diff --git a/.appveyor.yml b/.appveyor.yml deleted file mode 100644 index 0a25dceab43a46..00000000000000 --- a/.appveyor.yml +++ /dev/null @@ -1,133 +0,0 @@ ---- -version: '{build}' -init: - - git config --global user.name git - - git config --global user.email svn-admin@ruby-lang.org - - git config --global core.autocrlf false - - git config --global core.eol lf - - git config --global advice.detachedHead 0 -shallow_clone: true -clone_depth: 10 -platform: - - x64 -skip_commits: - message: /\[DOC\]/ - files: - - doc/* - - '**/*.md' - - '**/*.rdoc' - - '**/.document' - - '**/*.[1-8]' - - '**/*.ronn' -environment: - ruby_version: "25-%Platform%" - matrix: - # Test only the oldest supported version because AppVeyor is unstable, its concurrency - # is limited, and compatibility issues that happen only in newer versions are rare. - # You may test some other stuff on GitHub Actions instead. - - build: vs - vs: 120 # Visual Studio 2013 - ssl: OpenSSL-v111 - # The worker image name. This is NOT the Visual Studio version we're using here. - APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015 - GEMS_FOR_TEST: "" - RELINE_TEST_ENCODING: "UTF-8" -cache: - - c:\Tools\vcpkg\installed\ -for: -- - matrix: - only: - - build: vs - install: - - ver - - chcp - - SET BITS=%Platform:x86=32% - - SET BITS=%BITS:x=% - - SET OPENSSL_DIR=C:\%ssl%-Win%BITS% - - cd C:\Tools\vcpkg - - git pull -q - - .\bootstrap-vcpkg.bat - - cd %APPVEYOR_BUILD_FOLDER% - - vcpkg --triplet %Platform%-windows install --x-use-aria2 libffi libyaml readline zlib - - CALL SET vcvars=%%^VS%VS%COMNTOOLS^%%..\..\VC\vcvarsall.bat - - SET vcvars - - '"%vcvars%" %Platform:x64=amd64%' - - SET ruby_path=C:\Ruby%ruby_version:-x86=% - - SET PATH=\usr\local\bin;%ruby_path%\bin;%PATH%;C:\msys64\mingw64\bin;C:\msys64\usr\bin - - ruby --version - - 'cl' - - echo> Makefile srcdir=. - - echo>> Makefile MSC_VER=0 - - echo>> Makefile RT=none - - echo>> Makefile RT_VER=0 - - echo>> Makefile BUILTIN_ENCOBJS=nul - - type win32\Makefile.sub >> Makefile - - nmake %mflags% up VCSUP="echo Update OK" - - nmake %mflags% extract-extlibs - - del Makefile - - mkdir \usr\local\bin - - mkdir \usr\local\include - - mkdir \usr\local\lib - - for %%I in (%OPENSSL_DIR%\*.dll) do mklink /h \usr\local\bin\%%~nxI %%I - - for %%I in (c:\Tools\vcpkg\installed\%Platform%-windows\bin\*.dll) do ( - if not %%~nI == readline mklink \usr\local\bin\%%~nxI %%I - ) - - attrib +r /s /d - - mkdir %Platform%-mswin_%vs% - build_script: - - set HAVE_GIT=no - - cd %APPVEYOR_BUILD_FOLDER% - - cd %Platform%-mswin_%vs% - - >- - ..\win32\configure.bat - --with-opt-dir="/usr/local;c:/Tools/vcpkg/installed/%Platform%-windows" - --with-openssl-dir=%OPENSSL_DIR:\=/% - - nmake -l - - nmake install-nodoc - - \usr\bin\ruby -v -e "p :locale => Encoding.find('locale'), :filesystem => Encoding.find('filesystem')" - - if not "%GEMS_FOR_TEST%" == "" \usr\bin\gem install --no-document %GEMS_FOR_TEST% - - \usr\bin\ruby -ropenssl -e "puts 'Build ' + OpenSSL::OPENSSL_VERSION, 'Runtime ' + OpenSSL::OPENSSL_LIBRARY_VERSION" - test_script: - - set /a JOBS=%NUMBER_OF_PROCESSORS% - - nmake -l "TESTOPTS=-v -q" btest - - nmake -l "TESTOPTS=-v -q" test-basic - - >- - nmake -l "TESTOPTS=--timeout-scale=3.0 - --excludes=../test/.excludes/_appveyor -j%JOBS% - --exclude win32ole - --exclude test_bignum - --exclude test_syntax - --exclude test_open-uri - --exclude test_bundled_ca - " test-all - # separately execute tests without -j which may crash worker with -j. - - >- - nmake -l - "TESTOPTS=--timeout-scale=3.0 --excludes=../test/.excludes/_appveyor" - TESTS=" - ../test/win32ole - ../test/ruby/test_bignum.rb - ../test/ruby/test_syntax.rb - ../test/open-uri/test_open-uri.rb - ../test/rubygems/test_bundled_ca.rb - " test-all - - nmake -l test-spec # not using `-j` because sometimes `mspec -j` silently dies on Windows -notifications: - - provider: Webhook - method: POST - url: - secure: CcFlJNDJ/a6to7u3Z4Fnz6dScEPNx7hTha2GkSRlV+1U6dqmxY/7uBcLXYb9gR3jfQk6w+2o/HrjNAyXMNGU/JOka3s2WRI4VKitzM+lQ08owvJIh0R7LxrGH0J2e81U # ruby-lang slack: ruby/simpler-alerts-bot - body: >- - {{^isPullRequest}} - { - "ci": "AppVeyor CI", - "env": "Visual Studio 2013", - "url": "{{buildUrl}}", - "commit": "{{commitId}}", - "branch": "{{branch}}" - } - {{/isPullRequest}} - on_build_success: false - on_build_failure: true - on_build_status_changed: false diff --git a/.cirrus.yml b/.cirrus.yml deleted file mode 100644 index 7ea0932a16f9bf..00000000000000 --- a/.cirrus.yml +++ /dev/null @@ -1,109 +0,0 @@ -# This CI is used to test Arm cases. We can set the maximum 16 tasks. -# The entire testing design is inspired from .github/workflows/compilers.yml. - -# By default, Cirrus mounts an empty volume to `/tmp` -# which triggers all sorts of warnings like "system temporary path is world-writable: /tmp". -# Lets workaround it by specifying a custom volume mount point. -env: - CIRRUS_VOLUME: /cirrus-ci-volume - CIRRUS_CLONE_DEPTH: 50 - LANG: C.UTF-8 - optflags: '-O1' - debugflags: '-ggdb3' - RUBY_PREFIX: /tmp/ruby-prefix - RUBY_DEBUG: ci rgengc - RUBY_TESTOPTS: >- - -q - --color=always - --tty=no - RUST_BACKTRACE: 1 - INIT_ENV: - -config_template: &CONFIG_TEMPLATE - only_if: changesInclude('.cirrus.yml', 'yjit.{c,h,rb}', 'yjit/**.{mk,rs,toml}') - skip: >- - $CIRRUS_CHANGE_MESSAGE =~ '.*\[DOC\].*' || - $CIRRUS_PR_LABELS =~ '.*Documentation.*' || - changesIncludeOnly('doc/**', '**.{md,rdoc,ronn,[1-8]}', '.document') - arm_container: - # We use the arm64 images at https://github.com/ruby/ruby-ci-image/pkgs/container/ruby-ci-image . - image: ghcr.io/ruby/ruby-ci-image:$CC - # Define the used cpu core in each matrix task. We can use total 16 cpu - # cores in entire matrix. [cpu] = [total cpu: 16] / [number of tasks] - cpu: 8 - # We can request maximum 4 GB per cpu. - # [memory per task] = [memory per cpu: 4 GB] * [cpu] - memory: 32G - - id_script: id - info_script: | - nproc - free -h - set_env_script: - # Set `GNUMAKEFLAGS`, because the flags are GNU make specific. - - echo "GNUMAKEFLAGS=-s -j$((1 + $CIRRUS_CPU))" >> "$CIRRUS_ENV" - - '[ -z "$INIT_ENV" ] || printenv | sort | comm -13 - <(set -x; source $INIT_ENV && printenv | sort) | tee -a "$CIRRUS_ENV"' - - cat "$CIRRUS_ENV" - bundled_gems_cache: - folder: .downloaded-cache - fingerprint_script: - sed 's/ */ /g;s/ *#.*//;/^$/d;s/\([^ ]*\) \([^ ]*\)/\1-\2.gem/;s/ .*//' gems/bundled_gems - populate_script: | - sudo apt-get install --no-install-recommends -q -y wget - mkdir -p .downloaded-cache - sed 's/ */ /g;s/ *#.*//;/^$/d;s/\([^ ]*\) \([^ ]*\)/\1-\2.gem/;s/ .*//' gems/bundled_gems | - wget -nv -P .downloaded-cache -nd -B https://rubygems.org/downloads/ -i - - # Arm containers are executed in AWS's EKS, and it's not yet supporting IPv6 - # See https://github.com/aws/containers-roadmap/issues/835 - disable_ipv6_script: sudo ./tool/disable_ipv6.sh - autogen_script: ./autogen.sh - configure_script: >- - ./configure -C - --enable-debug-env - --disable-install-doc - --with-ext=-test-/cxxanyargs,+ - --prefix="$RUBY_PREFIX" - $configure - -task: - name: Arm64 Graviton2 / $CC - env: - matrix: - CC: gcc-11 - << : *CONFIG_TEMPLATE - make_extract-extlibs_script: make extract-extlibs - make_incs_script: make incs - make_script: make - make_test_script: make test - make_install_script: make install - install_gems_for_test_script: $RUBY_PREFIX/bin/gem install --no-doc timezone tzinfo - make_test-tool_script: make test-tool - make_test-all_script: make test-all - make_test-spec_script: make test-spec - -# The following is to test YJIT on ARM64 CPUs available on Cirrus CI -yjit_task: - name: Arm64 Graviton2 / $CC YJIT - env: - INIT_ENV: $HOME/.cargo/env - matrix: - - CC: gcc-11 - configure: --enable-yjit - << : *CONFIG_TEMPLATE - make_miniruby_script: make miniruby - make_bindgen_script: | - if [[ "$CC" = "clang-12" ]]; then - make yjit-bindgen - else - echo "only running bindgen on clang image" - fi - boot_miniruby_script: ./miniruby --yjit-call-threshold=1 -e0 - test_dump_insns_script: ./miniruby --yjit-call-threshold=1 --yjit-dump-insns -e0 - output_stats_script: ./miniruby --yjit-call-threshold=1 --yjit-stats -e0 - full_build_script: make - cargo_test_script: cd yjit && cargo test - make_test_script: make test RUN_OPTS="--yjit-call-threshold=1 --yjit-verify-ctx" - make_test_all_script: make test-all RUN_OPTS="--yjit-call-threshold=1 --yjit-verify-ctx" TESTOPTS="$RUBY_TESTOPTS" - make_test_spec_script: make test-spec RUN_OPTS="--yjit-call-threshold=1 --yjit-verify-ctx" - # Cirrus Rust environments don't have enough permission to run `rustup component add clippy`. - # clippy_script: cd yjit && rustup component add clippy && cargo clippy --all-targets --all-features diff --git a/.document b/.document index e875e42546727b..2345776518b087 100644 --- a/.document +++ b/.document @@ -15,10 +15,10 @@ array.rb ast.rb dir.rb gc.rb +hash.rb io.rb kernel.rb marshal.rb -rjit.rb numeric.rb nilclass.rb pack.rb @@ -30,6 +30,10 @@ thread_sync.rb trace_point.rb warning.rb yjit.rb +zjit.rb + +# Errno::* +known_errors.inc # the lib/ directory (which has its own .document file) lib diff --git a/.gdbinit b/.gdbinit index 7dd3336e286115..f624456d048352 100644 --- a/.gdbinit +++ b/.gdbinit @@ -1,23 +1,7 @@ -set startup-with-shell off - -define hook-run - set $color_type = 0 - set $color_highlite = 0 - set $color_end = 0 -end - define ruby_gdb_init - if !$color_type - set $color_type = "\033[31m" - end - if !$color_highlite - set $color_highlite = "\033[36m" - end - if !$color_end - set $color_end = "\033[m" - end - if ruby_dummy_gdb_enums.special_consts - end + init-if-undefined $color_type = "\033[31m" + init-if-undefined $color_highlite = "\033[36m" + init-if-undefined $color_end = "\033[m" end # set prompt \033[36m(gdb)\033[m\040 @@ -99,13 +83,11 @@ define rp set $regsrc = ((struct RRegexp*)($arg0))->src set $rsflags = ((struct RBasic*)$regsrc)->flags printf "%sT_REGEXP%s: ", $color_type, $color_end - set $len = ($rsflags & RUBY_FL_USER1) ? \ - ((struct RString*)$regsrc)->as.heap.len : \ - (($rsflags & (RUBY_FL_USER2|RUBY_FL_USER3|RUBY_FL_USER4|RUBY_FL_USER5|RUBY_FL_USER6)) >> RUBY_FL_USHIFT+2) + set $len = ((struct RString*)($arg0))->len set print address off output *(char *)(($rsflags & RUBY_FL_USER1) ? \ ((struct RString*)$regsrc)->as.heap.ptr : \ - ((struct RString*)$regsrc)->as.ary) @ $len + ((struct RString*)$regsrc)->as.embed.ary) @ $len set print address on printf " len:%ld ", $len if $flags & RUBY_FL_USER6 @@ -157,13 +139,15 @@ define rp if ($flags & RUBY_T_MASK) == RUBY_T_HASH printf "%sT_HASH%s: ", $color_type, $color_end, if (((struct RHash *)($arg0))->basic.flags & RHASH_ST_TABLE_FLAG) - printf "st len=%ld ", ((struct RHash *)($arg0))->as.st->num_entries + set $st = (struct st_table *)((uintptr_t)($arg0) + sizeof(struct RHash)) + printf "st len=%ld ", $st->num_entries + print $st else printf "li len=%ld bound=%ld ", \ ((((struct RHash *)($arg0))->basic.flags & RHASH_AR_TABLE_SIZE_MASK) >> RHASH_AR_TABLE_SIZE_SHIFT), \ ((((struct RHash *)($arg0))->basic.flags & RHASH_AR_TABLE_BOUND_MASK) >> RHASH_AR_TABLE_BOUND_SHIFT) + print (struct ar_table_struct *)((uintptr_t)($arg0) + sizeof(struct RHash)) end - print (struct RHash *)($arg0) else if ($flags & RUBY_T_MASK) == RUBY_T_STRUCT set $len = (($flags & (RUBY_FL_USER1|RUBY_FL_USER2)) ? \ @@ -201,8 +185,8 @@ define rp print (struct RBasic *)($arg0) else if ($flags & RUBY_T_MASK) == RUBY_T_DATA - if ((struct RTypedData *)($arg0))->typed_flag == 1 - printf "%sT_DATA%s(%s): ", $color_type, $color_end, ((struct RTypedData *)($arg0))->type->wrap_struct_name + if ((struct RTypedData *)($arg0))->type & 1 + printf "%sT_DATA%s(%s): ", $color_type, $color_end, ((const rb_data_type_t *)(((struct RTypedData *)($arg0))->type & ~1))->wrap_struct_name print (struct RTypedData *)($arg0) else printf "%sT_DATA%s: ", $color_type, $color_end @@ -440,13 +424,11 @@ end define output_string set $flags = ((struct RBasic*)($arg0))->flags - set $len = ($flags & RUBY_FL_USER1) ? \ - ((struct RString*)($arg0))->as.heap.len : \ - (($flags & (RUBY_FL_USER2|RUBY_FL_USER3|RUBY_FL_USER4|RUBY_FL_USER5|RUBY_FL_USER6)) >> RUBY_FL_USHIFT+2) + set $len = ((struct RString*)($arg0))->len if $len > 0 output *(char *)(($flags & RUBY_FL_USER1) ? \ ((struct RString*)($arg0))->as.heap.ptr : \ - ((struct RString*)($arg0))->as.ary) @ $len + ((struct RString*)($arg0))->as.embed.ary) @ $len else output "" end @@ -454,13 +436,11 @@ end define print_string set $flags = ((struct RBasic*)($arg0))->flags - set $len = ($flags & RUBY_FL_USER1) ? \ - ((struct RString*)($arg0))->as.heap.len : \ - (($flags & (RUBY_FL_USER2|RUBY_FL_USER3|RUBY_FL_USER4|RUBY_FL_USER5|RUBY_FL_USER6)) >> RUBY_FL_USHIFT+2) + set $len = ((struct RString*)($arg0))->len if $len > 0 printf "%s", *(char *)(($flags & RUBY_FL_USER1) ? \ ((struct RString*)($arg0))->as.heap.ptr : \ - ((struct RString*)($arg0))->as.ary) @ $len + ((struct RString*)($arg0))->as.embed.ary) @ $len end end @@ -543,14 +523,14 @@ document rp_bignum end define rp_class + set $class_and_classext = (struct RClass_and_rb_classext_t *)($arg0) printf "(struct RClass *) %p", (void*)$arg0 - if RCLASS_ORIGIN((struct RClass *)($arg0)) != $arg0 - printf " -> %p", RCLASS_ORIGIN((struct RClass *)($arg0)) + if $class_and_classext->classext->origin_ != (VALUE)$arg0 + printf " -> %p", $class_and_classext->classext->origin_ end printf "\n" rb_classname $arg0 - print/x *(struct RClass *)($arg0) - print *RCLASS_EXT((struct RClass *)($arg0)) + print/x *$class_and_classext end document rp_class Print the content of a Class/Module. @@ -916,10 +896,10 @@ document rb_method_entry end define rb_classname - # up to 128bit int - set $rb_classname = rb_mod_name($arg0) - if $rb_classname != RUBY_Qnil - rp $rb_classname + set $rb_classname = ((struct RClass_and_rb_classext_t*)$arg0)->classext->classpath + if $rb_classname != RUBY_Qfalse + print_string $rb_classname + printf "\n" else echo anonymous class/module\n end @@ -1126,7 +1106,7 @@ define rb_ps_thread set $ps_thread = (struct RTypedData*)$arg0 set $ps_thread_th = (rb_thread_t*)$ps_thread->data printf "* #\n", \ - $ps_thread, $ps_thread_th, $ps_thread_th->thread_id + $ps_thread, $ps_thread_th, $ps_thread_th->nt set $cfp = $ps_thread_th->ec->cfp set $cfpend = (rb_control_frame_t *)($ps_thread_th->ec->vm_stack + $ps_thread_th->ec->vm_stack_size)-1 while $cfp < $cfpend @@ -1311,13 +1291,12 @@ define dump_node set $flags = ((struct RBasic*)($str))->flags printf "%s", (char *)(($flags & RUBY_FL_USER1) ? \ ((struct RString*)$str)->as.heap.ptr : \ - ((struct RString*)$str)->as.ary) + ((struct RString*)$str)->as.embed.ary) end define print_flags printf "RUBY_FL_WB_PROTECTED: %s\n", ((struct RBasic*)($arg0))->flags & RUBY_FL_WB_PROTECTED ? "1" : "0" - printf "RUBY_FL_PROMOTED0 : %s\n", ((struct RBasic*)($arg0))->flags & RUBY_FL_PROMOTED0 ? "1" : "0" - printf "RUBY_FL_PROMOTED1 : %s\n", ((struct RBasic*)($arg0))->flags & RUBY_FL_PROMOTED1 ? "1" : "0" + printf "RUBY_FL_PROMOTED : %s\n", ((struct RBasic*)($arg0))->flags & RUBY_FL_PROMOTED ? "1" : "0" printf "RUBY_FL_FINALIZE : %s\n", ((struct RBasic*)($arg0))->flags & RUBY_FL_FINALIZE ? "1" : "0" printf "RUBY_FL_SHAREABLE : %s\n", ((struct RBasic*)($arg0))->flags & RUBY_FL_SHAREABLE ? "1" : "0" printf "RUBY_FL_EXIVAR : %s\n", ((struct RBasic*)($arg0))->flags & RUBY_FL_EXIVAR ? "1" : "0" @@ -1344,4 +1323,7 @@ define print_flags printf "RUBY_FL_USER18 : %s\n", ((struct RBasic*)($arg0))->flags & RUBY_FL_USER18 ? "1" : "0" end -source misc/gdb.py +source -s misc/gdb.py + +# Moved from beginning, since it fails on older gdbs +set startup-with-shell off diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs index 6c35dbcf831a92..5fb9ba5f7dd3ac 100644 --- a/.git-blame-ignore-revs +++ b/.git-blame-ignore-revs @@ -6,6 +6,10 @@ # Expand tabs 5b21e94bebed90180d8ff63dad03b8b948361089 c5e9af9c9d890578182a21e7b71b50334cd5579e +e63a2115f64433b21cb5dd67c5bf8b30f87ef293 +712ac99e4d0384a941c80a9f48f62943ba7d97c0 +d1474affa8e105bece209cc9d594bb0a989859e1 +2da92388b948821269b18d6b178a680f17e41750 # Enable Style/StringLiterals cop for RubyGems/Bundler d7ffd3fea402239b16833cc434404a7af82d44f3 @@ -22,3 +26,13 @@ f28287d34c03f472ffe90ea262bdde9affd4b965 # Make benchmark indentation consistent fc4acf8cae82e5196186d3278d831f2438479d91 + +# Make prism_compile.c indentation consistent +40b2c8e5e7e6e5f83cee9276dc9c1922a69292d6 +d2c5867357ed88eccc28c2b3bd4a46e206e7ff85 + +# Miss-and-revived commits +a0f7de814ae5c299d6ce99bed5fb308a05d50ba0 +d4e24021d39e1f80f0055b55d91f8d5f22e15084 +7a56c316418980b8a41fcbdc94067b2bda2ad112 +e90282be7ba1bc8e3119f6e1a2c80356ceb3f80a diff --git a/.gitattributes b/.gitattributes index d0c2d266b4a154..6ac6e6fcc3f579 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1,5 +1,6 @@ *.gemspec diff=ruby *.rb diff=ruby +*.inc.rs linguist-generated=true bin svn-properties=svn:ignore=ruby bin/* diff=ruby tool/update-deps diff=ruby diff --git a/.github/actions/compilers/action.yml b/.github/actions/compilers/action.yml new file mode 100644 index 00000000000000..30ccd25a12f487 --- /dev/null +++ b/.github/actions/compilers/action.yml @@ -0,0 +1,126 @@ +name: Compiles ruby in a container +description: >- + Makes ruby using a dedicated container + +inputs: + tag: + required: false + default: clang-18 + description: >- + container image tag to use in this run. + + with_gcc: + required: false + description: >- + override compiler path & flags. + + CFLAGS: + required: false + description: >- + C compiler flags to override. + + CXXFLAGS: + required: false + description: >- + C++ compiler flags to override. + + optflags: + required: false + # -O1 is faster than -O3 in our tests... Majority of time are consumed trying + # to optimize binaries. Also GitHub Actions run on relatively modern CPUs + # compared to, say, GCC 4 or Clang 3. We don't specify `-march=native` + # because compilers tend not understand what the CPU is. + default: '-O1' + description: >- + Compiler flags for optimisations. + + cppflags: + required: false + description: >- + Additional preprocessor flags. + + append_configure: + required: false + default: >- + --without-valgrind + --without-jemalloc + --without-gmp + description: >- + flags to append to configure. + + enable_shared: + required: false + default: true + description: >- + Whether to build libruby.so. + + check: + required: false + default: '' + description: >- + Whether to run `make check` + + mspecopt: + required: false + default: '' + description: >- + Additional options for mspec. + + static_exts: + required: false + description: >- + whitespace separated list of extensions that need be linked statically. + +runs: + using: composite + steps: + - shell: bash + run: docker pull --quiet 'ghcr.io/ruby/ruby-ci-image:${{ inputs.tag }}' + + - name: Enable Launchable conditionally + id: enable-launchable + run: echo "enable-launchable=true" >> $GITHUB_OUTPUT + shell: bash + if: >- + ${{ + github.repository == 'ruby/ruby' || + (github.repository != 'ruby/ruby' && env.LAUNCHABLE_TOKEN) + }} + + - name: compile + shell: bash + run: >- + docker run + --rm + --user=root + --volume '${{ github.workspace }}:/github/workspace:ro' + --workdir=/github/workspace + --entrypoint=/github/workspace/.github/actions/compilers/entrypoint.sh + --env CI + --env GITHUB_ACTION + --env INPUT_WITH_GCC='${{ inputs.with_gcc || inputs.tag }}' + --env INPUT_CFLAGS='${{ inputs.CFLAGS }}' + --env INPUT_CXXFLAGS='${{ inputs.CXXFLAGS }}' + --env INPUT_OPTFLAGS='${{ inputs.OPTFLAGS }}' + --env INPUT_CPPFLAGS='${{ inputs.cppflags }}' + --env INPUT_APPEND_CONFIGURE='${{ inputs.append_configure }}' + --env INPUT_CHECK='${{ inputs.check }}' + --env INPUT_MSPECOPT='${{ inputs.mspecopt }}' + --env INPUT_ENABLE_SHARED='${{ inputs.enable_shared }}' + --env INPUT_STATIC_EXTS='${{ inputs.static_exts }}' + --env LAUNCHABLE_ORGANIZATION='${{ github.repository_owner }}' + --env LAUNCHABLE_WORKSPACE='${{ github.event.repository.name }}' + --env LAUNCHABLE_ENABLED='${{ steps.enable-launchable.outputs.enable-launchable || false }}' + --env GITHUB_PR_HEAD_SHA='${{ github.event.pull_request.head.sha || github.sha }}' + --env GITHUB_PULL_REQUEST_URL='${{ github.event.pull_request.html_url }}' + --env GITHUB_REF='${{ github.ref }}' + --env GITHUB_ACTIONS + --env GITHUB_RUN_ID + --env GITHUB_REPOSITORY + --env GITHUB_WORKFLOW + --env GITHUB_RUN_NUMBER + --env GITHUB_EVENT_NAME + --env GITHUB_SHA + --env GITHUB_HEAD_REF + --env GITHUB_SERVER_URL + 'ghcr.io/ruby/ruby-ci-image:${{ inputs.tag }}' diff --git a/.github/actions/compilers/entrypoint.sh b/.github/actions/compilers/entrypoint.sh new file mode 100755 index 00000000000000..17f749d69ebf60 --- /dev/null +++ b/.github/actions/compilers/entrypoint.sh @@ -0,0 +1,94 @@ +#! /bin/bash + +# Copyright (c) 2024 Ruby developers. All rights reserved. +# +# This file is a part of the programming language Ruby. Permission is hereby +# granted, to either redistribute and/or modify this file, provided that the +# conditions mentioned in the file COPYING are met. Consult the file for +# details. + +grouped() +{ + echo "::group::${@}" + "${@}" + echo "::endgroup::" +} + +set -e +set -u +set -o pipefail + +srcdir="/github/workspace/src" +builddir="$(mktemp -dt)" + +export GITHUB_WORKFLOW='Compilations' +export CONFIGURE_TTY='never' +export RUBY_DEBUG='ci rgengc' +export RUBY_TESTOPTS='-q --color=always --tty=no' +export RUBY_DEBUG_COUNTER_DISABLE='1' +export GNUMAKEFLAGS="-j$((1 + $(nproc --all)))" + +case "x${INPUT_ENABLE_SHARED}" in +x | xno | xfalse ) + enable_shared='--disable-shared' + ;; +*) + enable_shared='--enable-shared' + ;; +esac + +pushd ${builddir} + +grouped git config --global --add safe.directory ${srcdir} + +grouped ${srcdir}/configure \ + -C \ + --with-gcc="${INPUT_WITH_GCC}" \ + --enable-debug-env \ + --disable-install-doc \ + --with-ext=-test-/cxxanyargs,+ \ + ${enable_shared} \ + ${INPUT_APPEND_CONFIGURE} \ + CFLAGS="${INPUT_CFLAGS}" \ + CXXFLAGS="${INPUT_CXXFLAGS}" \ + optflags="${INPUT_OPTFLAGS}" \ + cppflags="${INPUT_CPPFLAGS}" \ + debugflags='-ggdb3' # -g0 disables backtraces when SEGV. Do not set that. + +popd + +if [[ -n "${INPUT_STATIC_EXTS}" ]]; then + echo "::group::ext/Setup" + set -x + mkdir ${builddir}/ext + ( + for ext in ${INPUT_STATIC_EXTS}; do + echo "${ext}" + done + ) >> ${builddir}/ext/Setup + set +x + echo "::endgroup::" +fi + +btests='' +tests='' +spec_opts='' + +pushd ${builddir} + +grouped make showflags +grouped make all +grouped make test BTESTS="${btests}" + +[[ -z "${INPUT_CHECK}" ]] && exit 0 + +if [ "$INPUT_CHECK" = "true" ]; then + tests+=" -- ruby -ext-" +else + tests+=" -- $INPUT_CHECK" +fi + +# grouped make install +grouped make test-tool +grouped make test-all TESTS="$tests" +grouped env CHECK_LEAKS=true make test-spec MSPECOPT="$INPUT_MSPECOPT" SPECOPTS="${spec_opts}" diff --git a/.github/actions/launchable/setup/action.yml b/.github/actions/launchable/setup/action.yml new file mode 100644 index 00000000000000..3a939452a36bd1 --- /dev/null +++ b/.github/actions/launchable/setup/action.yml @@ -0,0 +1,289 @@ +name: Set up Launchable +description: >- + Install the required dependencies and execute the necessary Launchable commands for test recording + +inputs: + os: + required: true + description: The operating system that CI runs on. This value is used in Launchable flavor. + + test-opts: + default: none + required: false + description: >- + Test options that determine how tests are run. + This value is used in the Launchable flavor. + + launchable-token: + required: false + description: >- + Launchable token is needed if you want to run Launchable on your forked repository. + See https://github.com/ruby/ruby/wiki/CI-Servers#launchable-ci for details. + + builddir: + required: false + default: ${{ github.workspace }} + description: >- + Directory to create Launchable report file. + + srcdir: + required: false + default: ${{ github.workspace }} + description: >- + Directory to (re-)checkout source codes. Launchable retrieves the commit information + from the directory. + + test-task: + required: false + default: ${{ matrix.test_task }} + description: >- + Specifies a single test task to be executed. + This value is used in the Launchable flavor. + Either 'test-task' or 'multi-test-tasks' must be configured. + + test-tasks: + required: false + default: '[]' + description: >- + Specifies an array of multiple test tasks to be executed. + For example: '["test", "test-all"]'. + If you want to run a single test task, use the 'test-task' input instead. + + is-yjit: + required: false + default: 'false' + description: >- + Whether this workflow is executed on YJIT. + +outputs: + stdout_report_path: + value: ${{ steps.global.outputs.stdout_report_path }} + description: >- + Report file path for standard output. + + stderr_report_path: + value: ${{ steps.global.outputs.stderr_report_path }} + description: >- + Report file path for standard error. + +runs: + using: composite + + steps: + - name: Enable Launchable conditionally + id: enable-launchable + run: echo "enable-launchable=true" >> $GITHUB_OUTPUT + shell: bash + if: >- + ${{ + (github.repository == 'ruby/ruby' + || (github.repository != 'ruby/ruby' + && env.LAUNCHABLE_TOKEN)) + && (inputs.test-task == 'check' + || inputs.test-task == 'test-all' + || inputs.test-task == 'test' + || contains(fromJSON(inputs.test-tasks), 'test-all') + || contains(fromJSON(inputs.test-tasks), 'test')) + }} + + # Launchable CLI requires Python and Java. + # https://www.launchableinc.com/docs/resources/cli-reference/ + - name: Set up Python + uses: actions/setup-python@871daa956ca9ea99f3c3e30acb424b7960676734 # v5.0.0 + with: + python-version: "3.x" + if: steps.enable-launchable.outputs.enable-launchable + + - name: Set up Java + uses: actions/setup-java@7a445ee88d4e23b52c33fdc7601e40278616c7f8 # v4.0.0 + with: + distribution: 'temurin' + java-version: '17' + if: steps.enable-launchable.outputs.enable-launchable + + - name: Set global vars + id: global + shell: bash + run: | + test_all_enabled="${{ inputs.test-task == 'check' || inputs.test-task == 'test-all' || contains(fromJSON(inputs.test-tasks), 'test-all') }}" + btest_enabled="${{ inputs.test-task == 'check' || inputs.test-task == 'test' || contains(fromJSON(inputs.test-tasks), 'test') }}" + test_spec_enabled="${{ inputs.test-task == 'check' || inputs.test-task == 'test-spec' || contains(fromJSON(inputs.test-tasks), 'test-spec') }}" + echo test_all_enabled="${test_all_enabled}" >> $GITHUB_OUTPUT + echo btest_enabled="${btest_enabled}" >> $GITHUB_OUTPUT + echo test_spec_enabled="${test_spec_enabled}" >> $GITHUB_OUTPUT + echo test_all_report_file='launchable_test_all_report.json' >> $GITHUB_OUTPUT + echo btest_report_file='launchable_btest_report.json' >> $GITHUB_OUTPUT + echo test_spec_report_dir='launchable_test_spec_report' >> $GITHUB_OUTPUT + echo stdout_report_path="launchable_stdout.log" >> $GITHUB_OUTPUT + echo stderr_report_path="launchable_stderr.log" >> $GITHUB_OUTPUT + if: steps.enable-launchable.outputs.enable-launchable + + - name: Set environment variables for Launchable + shell: bash + run: | + : # GITHUB_PULL_REQUEST_URL are used for commenting test reports in Launchable Github App. + : # https://github.com/launchableinc/cli/blob/v1.80.1/launchable/utils/link.py#L42 + echo "GITHUB_PULL_REQUEST_URL=${{ github.event.pull_request.html_url }}" >> $GITHUB_ENV + : # The following envs are necessary in Launchable tokenless authentication. + : # https://github.com/launchableinc/cli/blob/v1.80.1/launchable/utils/authentication.py#L20 + echo "LAUNCHABLE_ORGANIZATION=${{ github.repository_owner }}" >> $GITHUB_ENV + echo "LAUNCHABLE_WORKSPACE=${{ github.event.repository.name }}" >> $GITHUB_ENV + : # https://github.com/launchableinc/cli/blob/v1.80.1/launchable/utils/authentication.py#L71 + echo "GITHUB_PR_HEAD_SHA=${{ github.event.pull_request.head.sha || github.sha }}" >> $GITHUB_ENV + echo "LAUNCHABLE_TOKEN=${{ inputs.launchable-token }}" >> $GITHUB_ENV + : # To prevent a slowdown in CI, disable request retries when the Launchable server is unstable. + echo "LAUNCHABLE_SKIP_TIMEOUT_RETRY=1" >> $GITHUB_ENV + echo "LAUNCHABLE_COMMIT_TIMEOUT=1" >> $GITHUB_ENV + if: steps.enable-launchable.outputs.enable-launchable + + - name: Set up path + shell: bash + working-directory: ${{ inputs.srcdir }} + # Since updated PATH variable will be available in only subsequent actions, we need to add the path beforehand. + # https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions#adding-a-system-path + run: echo "$(python -msite --user-base)/bin" >> $GITHUB_PATH + if: steps.enable-launchable.outputs.enable-launchable && startsWith(inputs.os, 'macos') + + - name: Set up Launchable + id: setup-launchable + shell: bash + working-directory: ${{ inputs.srcdir }} + run: | + set -x + pip install --user launchable + : # The build name cannot include a slash, so we replace the string here. + github_ref="${{ github.ref }}" + github_ref="${github_ref//\//_}" + : # With the --name option, we need to configure a unique identifier for this build. + : # To avoid setting the same build name as the CI which runs on other branches, we use the branch name here. + build_name="${github_ref}_${GITHUB_PR_HEAD_SHA}" + test_opts="${{ inputs.test-opts }}" + test_opts="${test_opts// /}" + test_opts="${test_opts//=/:}" + test_all_test_suite='test-all' + btest_test_suite='btest' + test_spec_test_suite='test-spec' + if [ "${{ inputs.is-yjit }}" = "true" ]; then + test_all_test_suite="yjit-${test_all_test_suite}" + btest_test_suite="yjit-${btest_test_suite}" + test_spec_test_suite="yjit-${test_spec_test_suite}" + fi + # launchable_setup target var -- refers ${target} prefixed variables + launchable_setup() { + local target=$1 session + eval [ "\${${target}_enabled}" = "true" ] || return + eval local suite=\${${target}_test_suite} + session=$(launchable record session \ + --build "${build_name}" \ + --observation \ + --flavor os="${{ inputs.os }}" \ + --flavor test_task="${{ inputs.test-task }}" \ + --flavor test_opts="${test_opts}" \ + --flavor workflow="${{ github.workflow }}" \ + --test-suite ${suite} \ + ) + launchable subset \ + --get-tests-from-previous-sessions \ + --non-blocking \ + --target 90% \ + --session "${session}" \ + raw > /dev/null + echo "${target}_session=${session}" >> $GITHUB_OUTPUT + } + + launchable record build --name "${build_name}" + if launchable_setup test_all; then + echo "TESTS=${TESTS:+$TESTS }--launchable-test-reports=${test_all_report_file}" >> $GITHUB_ENV + fi + if launchable_setup btest; then + echo "BTESTS=${BTESTS:+$BTESTS }--launchable-test-reports=${btest_report_file}" >> $GITHUB_ENV + fi + if launchable_setup test_spec; then + echo "SPECOPTS=${SPECOPTS:$SPECOPTS }--launchable-test-reports=${test_spec_report_dir}" >> $GITHUB_ENV + echo test_spec_enabled=true >> $GITHUB_OUTPUT + fi + + echo launchable_setup_dir=$(pwd) >> $GITHUB_OUTPUT + if: steps.enable-launchable.outputs.enable-launchable + env: + test_all_enabled: ${{ steps.global.outputs.test_all_enabled }} + btest_enabled: ${{ steps.global.outputs.btest_enabled }} + test_spec_enabled: ${{ steps.global.outputs.test_spec_enabled }} + test_all_report_file: ${{ steps.global.outputs.test_all_report_file }} + btest_report_file: ${{ steps.global.outputs.btest_report_file }} + test_spec_report_dir: ${{ steps.global.outputs.test_spec_report_dir }} + + - name: make test-spec report directory in build directory + shell: bash + working-directory: ${{ inputs.builddir }} + run: mkdir "${test_spec_report_dir}" + if: ${{ steps.setup-launchable.outputs.test_spec_enabled == 'true' }} + env: + test_spec_report_dir: ${{ steps.global.outputs.test_spec_report_dir }} + + - name: Clean up test results in Launchable + uses: gacts/run-and-post-run@674528335da98a7afc80915ff2b4b860a0b3553a # v1.4.0 + with: + shell: bash + working-directory: ${{ inputs.builddir }} + post: | + rm -f "${test_all_report_file}" + rm -f "${btest_report_file}" + rm -fr "${test_spec_report_dir}" + rm -f launchable_stdout.log + rm -f launchable_stderr.log + if: always() && steps.setup-launchable.outcome == 'success' + env: + test_all_report_file: ${{ steps.global.outputs.test_all_report_file }} + btest_report_file: ${{ steps.global.outputs.btest_report_file }} + test_spec_report_dir: ${{ steps.global.outputs.test_spec_report_dir }} + + - name: Record test results in Launchable + uses: gacts/run-and-post-run@674528335da98a7afc80915ff2b4b860a0b3553a # v1.4.0 + with: + shell: bash + working-directory: ${{ inputs.builddir }} + post: | + if [[ "${test_all_enabled}" = "true" ]]; then \ + launchable record attachment \ + --session "${test_all_session}" \ + "${stdout_report_path}" \ + "${stderr_report_path}"; \ + launchable record tests \ + --session "${test_all_session}" \ + raw "${test_all_report_file}" || true; \ + fi + + if [[ "${btest_enabled}" = "true" ]]; then \ + launchable record attachment \ + --session "${btest_session}" \ + "${stdout_report_path}" \ + "${stderr_report_path}"; \ + launchable record tests \ + --session "${btest_session}" \ + raw "${btest_report_file}" || true; \ + fi + + if [[ "${test_spec_enabled}" = "true" ]]; then \ + launchable record attachment \ + --session "${test_spec_session}" \ + "${stdout_report_path}" \ + "${stderr_report_path}"; \ + launchable record tests \ + --session "${test_spec_session}" \ + raw ${test_spec_report_dir}/* || true; \ + fi + if: ${{ always() && steps.setup-launchable.outcome == 'success' }} + env: + test_all_report_file: ${{ steps.global.outputs.test_all_report_file }} + btest_report_file: ${{ steps.global.outputs.btest_report_file }} + test_spec_report_dir: ${{ steps.global.outputs.test_spec_report_dir }} + test_all_enabled: ${{ steps.global.outputs.test_all_enabled }} + btest_enabled: ${{ steps.global.outputs.btest_enabled }} + test_spec_enabled: ${{ steps.global.outputs.test_spec_enabled }} + test_all_session: ${{ steps.setup-launchable.outputs.test_all_session }} + btest_session: ${{ steps.setup-launchable.outputs.btest_session }} + test_spec_session: ${{ steps.setup-launchable.outputs.test_spec_session }} + stdout_report_path: ${{ steps.global.outputs.stdout_report_path }} + stderr_report_path: ${{ steps.global.outputs.stderr_report_path }} + LAUNCHABLE_SETUP_DIR: ${{ steps.setup-launchable.outputs.launchable_setup_dir }} diff --git a/.github/actions/setup/directories/action.yml b/.github/actions/setup/directories/action.yml index ea5f2720ef343e..f16ce21e0ef66e 100644 --- a/.github/actions/setup/directories/action.yml +++ b/.github/actions/setup/directories/action.yml @@ -29,6 +29,33 @@ inputs: description: >- If set to true, additionally runs `make up`. + checkout: + required: false + type: boolean + default: true + description: >- + If set to '' (false), skip running actions/checkout. This is useful when + you don't want to overwrite a GitHub token that is already set up. + + dummy-files: + required: false + type: boolean + default: '' + description: >- + If set to true, creates dummy files in build dir. + + fetch-depth: + required: false + default: '1' + description: The depth of commit history fetched from the remote repository + + clean: + required: false + type: boolean + default: '' + description: >- + If set to true, clean build directory. + outputs: {} # nothing? runs: @@ -60,11 +87,13 @@ runs: git config --global advice.detachedHead 0 git config --global init.defaultBranch garbage - - uses: actions/checkout@c85c95e3d7251135ab7dc9ce3241c5835cc595a9 # v3.5.3 + - if: inputs.checkout + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: path: ${{ inputs.srcdir }} + fetch-depth: ${{ inputs.fetch-depth }} - - uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3.3.1 + - uses: actions/cache@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 with: path: ${{ inputs.srcdir }}/.downloaded-cache key: downloaded-cache @@ -72,7 +101,7 @@ runs: - if: steps.which.outputs.autoreconf shell: bash working-directory: ${{ inputs.srcdir }} - run: ./autogen.sh + run: ./autogen.sh --install # This is for MinGW. - if: runner.os == 'Windows' @@ -92,21 +121,67 @@ runs: shell: bash working-directory: ${{ inputs.srcdir }} run: | - touch config.status - touch .rbconfig.time - sed -f tool/prereq.status template/Makefile.in > Makefile - sed -f tool/prereq.status template/GNUmakefile.in > GNUmakefile + touch config.status .rbconfig.time + for mk in Makefile GNUmakefile; do + sed -f tool/prereq.status template/$mk.in > $mk + done make up # Cleanup, runs even on failure - if: always() && inputs.makeup shell: bash working-directory: ${{ inputs.srcdir }} - run: rm -f config.status Makefile rbconfig.rb .rbconfig.time + run: | + rm -f config.status .rbconfig.time \ + Makefile GNUmakefile uncommon.mk enc.mk noarch-fake.rb - if: steps.which.outputs.sudo shell: bash run: | sudo chmod -R go-w /usr/share chmod -v go-w $HOME $HOME/.config || : - sudo bash -c 'IFS=:; for d in '"$PATH"'; do chmod -v go-w $d; done' || : + declare -a dirs # -A is not supported by old bash, e.g. macos + SAVE_IFS="$IFS" IFS=:; set $PATH + for d do + while [ -d "$d" ]; do + case "$IFS${dirs[*]}$IFS" in *"$IFS$d$IFS"*) ;; *) dirs+=("$d");; esac + d="${d%/*}" + done + done + IFS="$SAVE_IFS" + sudo chmod -v go-w "${dirs[@]}" || : + + - if: inputs.dummy-files == 'true' + shell: bash + id: dummy-files + working-directory: ${{ inputs.builddir }} + run: | + : Create dummy files in build dir + set {{a..z},{A..Z},{0..9},foo,bar,test,zzz}.rb + for file; do \ + echo > $file "raise 'do not load $file'"; \ + done + # drop {a..z}.rb if case-insensitive filesystem + grep -F A.rb a.rb > /dev/null && set "${@:27}" + echo clean="cd ${{ inputs.builddir }} && rm $*" >> $GITHUB_OUTPUT + + - if: inputs.clean == 'true' + shell: bash + id: clean + run: | + echo distclean='make -C ${{ inputs.builddir }} distclean' >> $GITHUB_OUTPUT + echo remained-files='find ${{ inputs.builddir }} -ls' >> $GITHUB_OUTPUT + [ "${{ inputs.builddir }}" = "${{ inputs.srcdir }}" ] || + echo final='rmdir ${{ inputs.builddir }}' >> $GITHUB_OUTPUT + + - name: clean + uses: gacts/run-and-post-run@d803f6920adc9a47eeac4cb6c93dbc2e2890c684 # v1.4.2 + with: + working-directory: + post: | + ${{ steps.dummy-files.outputs.clean }} + ${{ steps.clean.outputs.distclean }} + ${{ steps.clean.outputs.remained-files }} + ${{ steps.clean.outputs.final }} + # rmdir randomly fails due to launchable files + continue-on-error: true diff --git a/.github/actions/setup/macos/action.yml b/.github/actions/setup/macos/action.yml index 3649a648760324..d0072ff82890c4 100644 --- a/.github/actions/setup/macos/action.yml +++ b/.github/actions/setup/macos/action.yml @@ -13,12 +13,17 @@ runs: - name: brew shell: bash run: | - brew install --quiet gmp libffi openssl@1.1 zlib autoconf automake libtool readline + brew install --quiet jemalloc gmp libffi openssl@3 zlib autoconf automake libtool - name: Set ENV shell: bash run: | - for lib in openssl@1.1 readline; do - CONFIGURE_ARGS="${CONFIGURE_ARGS:+$CONFIGURE_ARGS }--with-${lib%@*}-dir=$(brew --prefix $lib)" - done - echo CONFIGURE_ARGS="${CONFIGURE_ARGS}" >> $GITHUB_ENV + dir_config() { + local args=() lib var="$1"; shift + for lib in "$@"; do + args+=("--with-${lib%@*}-dir=$(brew --prefix $lib)") + done + echo "$var=${args[*]}" >> $GITHUB_ENV + } + dir_config ruby_configure_args gmp + dir_config CONFIGURE_ARGS openssl@3 diff --git a/.github/actions/slack/action.yml b/.github/actions/slack/action.yml index d1dd7f5def8105..98171efc5eed37 100644 --- a/.github/actions/slack/action.yml +++ b/.github/actions/slack/action.yml @@ -9,7 +9,7 @@ inputs: required: true description: >- The URL to post the payload. This is an input because it tends - to be stored in a secrets valut and a composite action cannot + to be stored in a secrets vault and a composite action cannot look into one. label: @@ -24,7 +24,7 @@ runs: using: composite steps: - - uses: ruby/action-slack@0bd85c72233cdbb6a0fe01d37aaeff1d21b5fce1 # v3.2.1 + - uses: ruby/action-slack@54175162371f1f7c8eb94d7c8644ee2479fcd375 # v3.2.2 with: payload: | { @@ -36,3 +36,4 @@ runs: } env: SLACK_WEBHOOK_URL: ${{ inputs.SLACK_WEBHOOK_URL }} + if: ${{github.event_name == 'push' && startsWith(github.repository, 'ruby/')}} diff --git a/.github/auto_request_review.yml b/.github/auto_request_review.yml index 8726df577d39eb..c4c94681f0e387 100644 --- a/.github/auto_request_review.yml +++ b/.github/auto_request_review.yml @@ -1,13 +1,19 @@ files: - 'yjit*': [team:yjit] - 'yjit/**/*': [team:yjit] + 'yjit*': [team:jit] + 'yjit/**/*': [team:jit] 'yjit/src/cruby_bindings.inc.rs': [] - 'doc/yjit/*': [team:yjit] - 'bootstraptest/test_yjit*': [team:yjit] - 'test/ruby/test_yjit*': [team:yjit] + 'doc/yjit/*': [team:jit] + 'bootstraptest/test_yjit*': [team:jit] + 'test/ruby/test_yjit*': [team:jit] + 'zjit*': [team:jit] + 'zjit/**/*': [team:jit] + 'zjit/src/cruby_bindings.inc.rs': [] + 'doc/zjit*': [team:jit] + 'test/ruby/test_zjit*': [team:jit] + 'defs/jit.mk': [team:jit] options: ignore_draft: true # This currently doesn't work as intended. We want to skip reviews when only # cruby_bingings.inc.rs is modified, but this skips reviews even when other - # yjit files are modified as well. To be enabled after fixing the behavior. + # files are modified as well. To be enabled after fixing the behavior. #last_files_match_only: true diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 6778b0493a160f..426893be2af281 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -4,3 +4,15 @@ updates: directory: '/' schedule: interval: 'daily' + - package-ecosystem: 'github-actions' + directory: '/.github/actions/slack' + schedule: + interval: 'daily' + - package-ecosystem: 'github-actions' + directory: '/.github/actions/setup/directories' + schedule: + interval: 'daily' + - package-ecosystem: 'cargo' + directory: '/yjit' + schedule: + interval: 'daily' diff --git a/.github/labeler.yml b/.github/labeler.yml new file mode 100644 index 00000000000000..e81aed8e986284 --- /dev/null +++ b/.github/labeler.yml @@ -0,0 +1,6 @@ +Documentation: +- changed-files: + - all-globs-to-all-files: doc/** + +Backport: +- base-branch: 'ruby_3_\d' diff --git a/.github/workflows/annocheck.yml b/.github/workflows/annocheck.yml index 2f5ece83280727..a890fc442f09fb 100644 --- a/.github/workflows/annocheck.yml +++ b/.github/workflows/annocheck.yml @@ -4,24 +4,20 @@ on: push: paths-ignore: - 'doc/**' - - '**/man' + - '**/man/*' - '**.md' - '**.rdoc' - '**/.document' + - '.*.yml' pull_request: paths-ignore: - 'doc/**' - - '**/man' + - '**/man/*' - '**.md' - '**.rdoc' - '**/.document' + - '.*.yml' merge_group: - paths-ignore: - - 'doc/**' - - '**/man' - - '**.md' - - '**.rdoc' - - '**/.document' concurrency: group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }} @@ -32,7 +28,7 @@ permissions: jobs: compile: - name: gcc-11 annocheck + name: test-annocheck runs-on: ubuntu-latest @@ -43,9 +39,11 @@ jobs: if: >- ${{!(false || contains(github.event.head_commit.message, '[DOC]') + || contains(github.event.head_commit.message, 'Document') || contains(github.event.pull_request.title, '[DOC]') + || contains(github.event.pull_request.title, 'Document') || contains(github.event.pull_request.labels.*.name, 'Documentation') - || (github.event_name == 'push' && github.actor == 'dependabot[bot]') + || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]') )}} env: @@ -65,7 +63,7 @@ jobs: - run: id working-directory: - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: sparse-checkout-cone-mode: false sparse-checkout: /.github @@ -76,6 +74,11 @@ jobs: builddir: build makeup: true + - uses: ruby/setup-ruby@a4effe49ee8ee5b8b5091268c473a4628afb5651 # v1.245.0 + with: + ruby-version: '3.1' + bundler: none + # Minimal flags to pass the check. # -g0 disables backtraces when SEGV. Do not set that. - name: Run configure @@ -97,26 +100,12 @@ jobs: - run: make - - run: make test - - - run: make install - - - run: make test-tool - - ### test-all doesn't work: https://github.com/ruby/ruby/actions/runs/4340112185/jobs/7578344307 - # - run: make test-all TESTS='-- ruby -ext-' - - ### test-spec doesn't work: https://github.com/ruby/ruby/actions/runs/4340193212/jobs/7578505652 - # - run: make test-spec - # env: - # CHECK_LEAKS: true - - run: make test-annocheck - uses: ./.github/actions/slack with: SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot - if: ${{ failure() && github.event_name == 'push' }} + if: ${{ failure() }} defaults: run: diff --git a/.github/workflows/auto_request_review.yml b/.github/workflows/auto_request_review.yml index d9eb774e3f41f2..207315a084cc59 100644 --- a/.github/workflows/auto_request_review.yml +++ b/.github/workflows/auto_request_review.yml @@ -2,6 +2,7 @@ name: Auto Request Review on: pull_request_target: types: [opened, ready_for_review, reopened] + branches: [master] permissions: contents: read @@ -10,10 +11,10 @@ jobs: auto-request-review: name: Auto Request Review runs-on: ubuntu-latest - if: ${{ github.repository == 'ruby/ruby' }} + if: ${{ github.repository == 'ruby/ruby' && github.base_ref == 'master' }} steps: - name: Request review based on files changes and/or groups the author belongs to - uses: necojackarc/auto-request-review@6a51cebffe2c084705d9a7b394abd802e0119633 # v0.12.0 + uses: necojackarc/auto-request-review@e89da1a8cd7c8c16d9de9c6e763290b6b0e3d424 # v0.13.0 with: # scope: public_repo - token: ${{ secrets.MATZBOT_GITHUB_TOKEN }} + token: ${{ secrets.MATZBOT_AUTO_REQUEST_REVIEW_TOKEN }} diff --git a/.github/workflows/baseruby.yml b/.github/workflows/baseruby.yml index 50176b3eb0d8bc..8b77b0188934f9 100644 --- a/.github/workflows/baseruby.yml +++ b/.github/workflows/baseruby.yml @@ -4,24 +4,20 @@ on: push: paths-ignore: - 'doc/**' - - '**/man' + - '**/man/*' - '**.md' - '**.rdoc' - '**/.document' + - '.*.yml' pull_request: paths-ignore: - 'doc/**' - - '**/man' + - '**/man/*' - '**.md' - '**.rdoc' - '**/.document' + - '.*.yml' merge_group: - paths-ignore: - - 'doc/**' - - '**/man' - - '**.md' - - '**.rdoc' - - '**/.document' concurrency: group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }} @@ -34,33 +30,32 @@ jobs: baseruby: name: BASERUBY - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 if: >- ${{!(false || contains(github.event.head_commit.message, '[DOC]') + || contains(github.event.head_commit.message, 'Document') || contains(github.event.pull_request.title, '[DOC]') + || contains(github.event.pull_request.title, 'Document') || contains(github.event.pull_request.labels.*.name, 'Documentation') - || (github.event_name == 'push' && github.actor == 'dependabot[bot]') + || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]') )}} strategy: matrix: ruby: - - ruby-2.5 -# - ruby-2.6 -# - ruby-2.7 - - ruby-3.0 - ruby-3.1 - ruby-3.2 + - ruby-3.3 steps: - - uses: ruby/setup-ruby@250fcd6a742febb1123a77a841497ccaa8b9e939 # v1.152.0 + - uses: ruby/setup-ruby@a4effe49ee8ee5b8b5091268c473a4628afb5651 # v1.245.0 with: ruby-version: ${{ matrix.ruby }} bundler: none - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/setup/ubuntu @@ -78,4 +73,4 @@ jobs: with: label: ${{ matrix.ruby }} SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot - if: ${{ failure() && github.event_name == 'push' }} + if: ${{ failure() }} diff --git a/.github/workflows/bundled_gems.yml b/.github/workflows/bundled_gems.yml index 8c78e3905b1fda..27ad55307bef76 100644 --- a/.github/workflows/bundled_gems.yml +++ b/.github/workflows/bundled_gems.yml @@ -12,10 +12,6 @@ on: - '.github/workflows/bundled_gems.yml' - 'gems/bundled_gems' merge_group: - branches: ['master'] - paths: - - '.github/workflows/bundled_gems.yml' - - 'gems/bundled_gems' schedule: - cron: '45 6 * * *' workflow_dispatch: @@ -35,9 +31,14 @@ jobs: runs-on: ubuntu-latest steps: - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + token: ${{ (github.repository == 'ruby/ruby' && !startsWith(github.event_name, 'pull')) && secrets.MATZBOT_AUTO_UPDATE_TOKEN || secrets.GITHUB_TOKEN }} - uses: ./.github/actions/setup/directories + with: + # Skip overwriting MATZBOT_AUTO_UPDATE_TOKEN + checkout: '' # false (ref: https://github.com/actions/runner/issues/2238) - name: Set ENV run: | @@ -45,14 +46,23 @@ jobs: - name: Download previous gems list run: | - data=bundled_gems.json mkdir -p .downloaded-cache - ln -s .downloaded-cache/$data . - curl -O -R -z ./$data https://stdgems.org/$data + for data in bundled_gems.json default_gems.json; do + ln -s .downloaded-cache/$data . + curl -O -R -z ./$data https://stdgems.org/$data + done - name: Update bundled gems list + id: bundled_gems + run: | + ruby -i~ tool/update-bundled_gems.rb gems/bundled_gems >> $GITHUB_OUTPUT + + - name: Update spec/bundler/support/builders.rb run: | - ruby -i~ tool/update-bundled_gems.rb gems/bundled_gems + #!ruby + rake_version = File.read("gems/bundled_gems")[/^rake\s+(\S+)/, 1] + print ARGF.read.sub(/^ *def rake_version\s*\K".*?"/) {rake_version.dump} + shell: ruby -i~ {0} spec/bundler/support/builders.rb - name: Maintain updated gems list in NEWS run: | @@ -61,59 +71,66 @@ jobs: - name: Check diffs id: diff run: | - git add -- NEWS.md - git diff --no-ext-diff --ignore-submodules --quiet -- gems/bundled_gems - continue-on-error: true + news= gems= + git diff --color --no-ext-diff --ignore-submodules --exit-code -- NEWS.md || + news=true + git diff --color --no-ext-diff --ignore-submodules --exit-code -- gems/bundled_gems || + gems=true + git add -- NEWS.md gems/bundled_gems + git add -- spec/bundler/support/builders.rb + echo news=$news >> $GITHUB_OUTPUT + echo gems=$gems >> $GITHUB_OUTPUT + echo update=${news:-$gems} >> $GITHUB_OUTPUT - name: Install libraries uses: ./.github/actions/setup/ubuntu - if: ${{ steps.diff.outcome == 'failure' }} + if: ${{ steps.diff.outputs.gems }} - name: Build run: | ./autogen.sh ./configure -C --disable-install-doc make - if: ${{ steps.diff.outcome == 'failure' }} + if: ${{ steps.diff.outputs.gems }} - name: Prepare bundled gems run: | make -s prepare-gems - if: ${{ steps.diff.outcome == 'failure' }} + if: ${{ steps.diff.outputs.gems }} - name: Test bundled gems run: | make -s test-bundled-gems - git add -- gems/bundled_gems timeout-minutes: 30 env: RUBY_TESTOPTS: '-q --tty=no' TEST_BUNDLED_GEMS_ALLOW_FAILURES: '' - if: ${{ steps.diff.outcome == 'failure' }} - - - name: Show diffs - id: show - run: | - git diff --cached --color --no-ext-diff --ignore-submodules --exit-code -- - continue-on-error: true + if: ${{ steps.diff.outputs.gems }} - name: Commit run: | git pull --ff-only origin ${GITHUB_REF#refs/heads/} - message="Update bundled gems list at " - if [ ${{ steps.diff.outcome }} = success ]; then - git commit --message="${message}${GITHUB_SHA:0:30} [ci skip]" + message="Update bundled gems list" + if [ -z "${gems}" ]; then + git commit --message="[DOC] ${message} at ${GITHUB_SHA:0:30}" else - git commit --message="${message}${TODAY}" + git commit --message="${message} as of ${TODAY}" fi git push origin ${GITHUB_REF#refs/heads/} env: + TODAY: ${{ steps.bundled_gems.outputs.latest_date || env.TODAY }} EMAIL: svn-admin@ruby-lang.org GIT_AUTHOR_NAME: git GIT_COMMITTER_NAME: git - if: ${{ github.repository == 'ruby/ruby' && !startsWith(github.event_name, 'pull') && steps.show.outcome == 'failure' }} + gems: ${{ steps.diff.outputs.gems }} + if: >- + ${{ + github.repository == 'ruby/ruby' && + !startsWith(github.event_name, 'pull') && + steps.diff.outputs.update + }} - uses: ./.github/actions/slack with: SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot - if: ${{ failure() && github.event_name == 'push' }} + if: ${{ failure() }} diff --git a/.github/workflows/check_dependencies.yml b/.github/workflows/check_dependencies.yml index ac065faaa0165c..22452a3b9e822e 100644 --- a/.github/workflows/check_dependencies.yml +++ b/.github/workflows/check_dependencies.yml @@ -3,24 +3,13 @@ on: push: paths-ignore: - 'doc/**' - - '**/man' + - '**/man/*' - '**.md' - '**.rdoc' - '**/.document' + - '.*.yml' pull_request: - paths-ignore: - - 'doc/**' - - '**/man' - - '**.md' - - '**.rdoc' - - '**/.document' merge_group: - paths-ignore: - - 'doc/**' - - '**/man' - - '**.md' - - '**.rdoc' - - '**/.document' concurrency: group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }} @@ -31,23 +20,17 @@ permissions: jobs: update-deps: + name: Dependency checks + strategy: matrix: - os: [ubuntu-20.04] + os: [ubuntu-latest] fail-fast: true runs-on: ${{ matrix.os }} - if: >- - ${{!(false - || contains(github.event.head_commit.message, '[DOC]') - || contains(github.event.pull_request.title, '[DOC]') - || contains(github.event.pull_request.labels.*.name, 'Documentation') - || (github.event_name == 'push' && github.actor == 'dependabot[bot]') - )}} - steps: - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - uses: ./.github/actions/setup/ubuntu if: ${{ contains(matrix.os, 'ubuntu') }} @@ -57,11 +40,18 @@ jobs: - uses: ./.github/actions/setup/directories + - uses: ruby/setup-ruby@a4effe49ee8ee5b8b5091268c473a4628afb5651 # v1.245.0 + with: + ruby-version: '3.1' + bundler: none + - name: Run configure run: ./configure -C --disable-install-doc --disable-rubygems --with-gcc 'optflags=-O0' 'debugflags=-save-temps=obj -g' - run: make all golf + - run: ./goruby -veh + - run: ruby tool/update-deps --fix - run: git diff --no-ext-diff --ignore-submodules --exit-code @@ -70,4 +60,4 @@ jobs: with: label: ${{ matrix.os }} / Dependencies need to update SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot - if: ${{ failure() && github.event_name == 'push' }} + if: ${{ failure() }} diff --git a/.github/workflows/check_misc.yml b/.github/workflows/check_misc.yml index e64a93189371bb..630ba3e4dca3de 100644 --- a/.github/workflows/check_misc.yml +++ b/.github/workflows/check_misc.yml @@ -1,4 +1,4 @@ -name: Miscellaneous checks +name: Misc on: [push, pull_request, merge_group] concurrency: @@ -10,26 +10,41 @@ permissions: jobs: checks: + name: Miscellaneous checks + permissions: contents: write # for Git to git push runs-on: ubuntu-latest steps: - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + token: ${{ (github.repository == 'ruby/ruby' && !startsWith(github.event_name, 'pull')) && secrets.MATZBOT_AUTO_UPDATE_TOKEN || secrets.GITHUB_TOKEN }} - uses: ./.github/actions/setup/directories with: makeup: true + # Skip overwriting MATZBOT_AUTO_UPDATE_TOKEN + checkout: '' # false (ref: https://github.com/actions/runner/issues/2238) - - name: Check if C-sources are US-ASCII + # Run this step first to make sure auto-style commits are pushed + - name: ${{ github.ref == 'refs/heads/master' && 'Auto-correct' || 'Check for' }} code styles run: | - grep -r -n '[^ -~]' -- *.[chy] include internal win32/*.[ch] && exit 1 || : + set -x + ruby tool/auto-style.rb "$GITHUB_OLD_SHA" "$GITHUB_NEW_SHA" "$PUSH_REF" + env: + EMAIL: svn-admin@ruby-lang.org + GIT_AUTHOR_NAME: git + GIT_COMMITTER_NAME: git + GITHUB_OLD_SHA: ${{ github.event.pull_request.base.sha }} + GITHUB_NEW_SHA: ${{ github.event.pull_request.merge_commit_sha }} + PUSH_REF: ${{ github.ref == 'refs/heads/master' && github.ref || '' }} + if: ${{ github.repository == 'ruby/ruby' && startsWith(github.event_name, 'pull') }} - - name: Check for trailing spaces + - name: Check if C-sources are US-ASCII run: | - git grep -I -n '[ ]$' -- '*.rb' '*.[chy]' '*.rs' && exit 1 || : - git grep -n '^[ ][ ]*$' -- '*.md' && exit 1 || : + grep -r -n --include='*.[chyS]' --include='*.asm' $'[^\t-~]' -- . && exit 1 || : - name: Check for bash specific substitution in configure.ac run: | @@ -46,61 +61,30 @@ jobs: exit $fail working-directory: include - - id: gems - run: true - if: ${{ github.ref == 'refs/heads/master' }} - - - name: Download previous gems list - run: | - data=default_gems.json - mkdir -p .downloaded-cache - ln -s .downloaded-cache/$data . - curl -O -R -z ./$data https://stdgems.org/$data - if: ${{ steps.gems.outcome == 'success' }} - - - name: Make default gems list + - name: Generate docs + id: docs run: | - #!ruby - require 'rubygems' - $:.unshift "lib" - rgver = File.foreach("lib/rubygems.rb") do |line| - break $1 if /^\s*VERSION\s*=\s*"([^"]+)"/ =~ line - end - gems = Dir.glob("{ext,lib}/**/*.gemspec").map do |f| - spec = Gem::Specification.load(f) - "#{spec.name} #{spec.version}" - end.sort - File.open("gems/default_gems", "w") do |f| - f.puts "RubyGems #{rgver}" - f.puts gems - end - shell: ruby --disable=gems {0} - if: ${{ steps.gems.outcome == 'success' }} - - - name: Maintain updated gems list in NEWS - run: | - ruby tool/update-NEWS-gemlist.rb default - if: ${{ steps.gems.outcome == 'success' }} - - - name: Check diffs - id: diff - run: | - git diff --color --no-ext-diff --ignore-submodules --exit-code NEWS.md - continue-on-error: true - if: ${{ steps.gems.outcome == 'success' }} - - - name: Commit - run: | - git pull --ff-only origin ${GITHUB_REF#refs/heads/} - git commit --message="Update default gems list at ${GITHUB_SHA:0:30} [ci skip]" NEWS.md - git push origin ${GITHUB_REF#refs/heads/} - env: - EMAIL: svn-admin@ruby-lang.org - GIT_AUTHOR_NAME: git - GIT_COMMITTER_NAME: git - if: ${{ github.repository == 'ruby/ruby' && !startsWith(github.event_name, 'pull') && steps.diff.outcome == 'failure' }} + ruby -W0 --disable-gems -I./lib tool/rdoc-srcdir -q --op html . + echo htmlout=ruby-html-${GITHUB_SHA:0:10} >> $GITHUB_OUTPUT + # Generate only when document commit/PR + if: >- + ${{false + || contains(github.event.head_commit.message, '[ruby/rdoc]') + || contains(github.event.head_commit.message, '[DOC]') + || contains(github.event.head_commit.message, 'Document') + || contains(github.event.pull_request.title, '[DOC]') + || contains(github.event.pull_request.title, 'Document') + || contains(github.event.pull_request.labels.*.name, 'Documentation') + }} + + - name: Upload docs + uses: actions/upload-artifact@v4 + with: + path: html + name: ${{ steps.docs.outputs.htmlout }} + if: ${{ steps.docs.outcome == 'success' }} - uses: ./.github/actions/slack with: SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot - if: ${{ failure() && github.event_name == 'push' }} + if: ${{ failure() }} diff --git a/.github/workflows/cirrus-notify.yml b/.github/workflows/cirrus-notify.yml deleted file mode 100644 index 295562ac638173..00000000000000 --- a/.github/workflows/cirrus-notify.yml +++ /dev/null @@ -1,52 +0,0 @@ -on: - check_suite: - types: ['completed'] -name: Cirrus CI failure notification - -permissions: - contents: read - -jobs: - cirrus-notify: - name: After Cirrus CI Failure - if: >- - github.event.check_suite.app.name == 'Cirrus CI' - && github.event.check_suite.conclusion != 'success' - && github.event.check_suite.conclusion != 'cancelled' - && github.event.check_suite.conclusion != 'neutral' - && github.event.check_suite.conclusion != 'skipped' - && github.event.check_suite.head_branch == 'master' - - runs-on: ubuntu-latest - - steps: - - uses: octokit/request-action@89697eb6635e52c6e1e5559f15b5c91ba5100cb0 # v2.1.9 - id: get_failed_check_run - with: - route: GET /repos/${{ github.repository }}/check-suites/${{ github.event.check_suite.id }}/check-runs?status=completed - mediaType: '{"previews": ["antiope"]}' - env: - GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Dump GitHub context - env: - GITHUB_CONTEXT: ${{ toJson(github) }} - run: echo "$GITHUB_CONTEXT" - - - name: Dump check_runs - env: - CHECK_RUNS: ${{ steps.get_failed_check_run.outputs.data }} - run: echo "$CHECK_RUNS" - - - uses: ruby/action-slack@0bd85c72233cdbb6a0fe01d37aaeff1d21b5fce1 # v3.2.1 - with: - payload: | - { - "ci": "Cirrus CI", - "env": "Cirrus CI", - "url": "${{ fromJson(steps.get_failed_check_run.outputs.data).check_runs[0].html_url }}", - "commit": "${{ github.event.check_suite.head_commit.id }}", - "branch": "${{ github.event.check_suite.head_branch }}" - } - env: - SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml index dcf3ee87062c54..0dfae7f045220b 100644 --- a/.github/workflows/codeql-analysis.yml +++ b/.github/workflows/codeql-analysis.yml @@ -5,17 +5,19 @@ on: branches: ['master'] paths-ignore: - 'doc/**' - - '**/man' + - '**/man/*' - '**.md' - '**.rdoc' - '**/.document' + - '.*.yml' pull_request: paths-ignore: - 'doc/**' - - '**/man' + - '**/man/*' - '**.md' - '**.rdoc' - '**/.document' + - '.*.yml' schedule: - cron: '0 12 * * *' workflow_dispatch: @@ -39,9 +41,11 @@ jobs: if: >- ${{!(false || contains(github.event.head_commit.message, '[DOC]') + || contains(github.event.head_commit.message, 'Document') || contains(github.event.pull_request.title, '[DOC]') + || contains(github.event.pull_request.title, 'Document') || contains(github.event.pull_request.labels.*.name, 'Documentation') - || (github.event_name == 'push' && github.actor == 'dependabot[bot]') + || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]') )}} env: @@ -50,38 +54,47 @@ jobs: strategy: fail-fast: false matrix: - language: ['cpp', 'ruby'] + include: + - language: cpp + - language: ruby steps: - name: Checkout repository - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - name: Install libraries + if: ${{ contains(matrix.os, 'macos') }} + uses: ./.github/actions/setup/macos + + - name: Install libraries + if : ${{ matrix.os == 'ubuntu-latest' }} uses: ./.github/actions/setup/ubuntu - uses: ./.github/actions/setup/directories - name: Remove an obsolete rubygems vendored file + if: ${{ matrix.os == 'ubuntu-latest' }} run: sudo rm /usr/lib/ruby/vendor_ruby/rubygems/defaults/operating_system.rb - name: Initialize CodeQL - uses: github/codeql-action/init@cdcdbb579706841c47f7063dda365e292e5cad7a # v2.13.4 + uses: github/codeql-action/init@df409f7d9260372bd5f19e5b04e83cb3c43714ae # v3.27.9 with: languages: ${{ matrix.language }} + trap-caching: false + debug: true - name: Autobuild - uses: github/codeql-action/autobuild@cdcdbb579706841c47f7063dda365e292e5cad7a # v2.13.4 + uses: github/codeql-action/autobuild@df409f7d9260372bd5f19e5b04e83cb3c43714ae # v3.27.9 - name: Perform CodeQL Analysis - uses: github/codeql-action/analyze@cdcdbb579706841c47f7063dda365e292e5cad7a # v2.13.4 + uses: github/codeql-action/analyze@df409f7d9260372bd5f19e5b04e83cb3c43714ae # v3.27.9 with: category: '/language:${{ matrix.language }}' upload: False output: sarif-results - ram: 8192 - name: filter-sarif - uses: advanced-security/filter-sarif@f3b8118a9349d88f7b1c0c488476411145b6270d # v1.0 + uses: advanced-security/filter-sarif@f3b8118a9349d88f7b1c0c488476411145b6270d # v1.0.1 with: patterns: | +**/*.rb @@ -101,8 +114,10 @@ jobs: input: sarif-results/${{ matrix.language }}.sarif output: sarif-results/${{ matrix.language }}.sarif if: ${{ matrix.language == 'ruby' }} + continue-on-error: true - name: Upload SARIF - uses: github/codeql-action/upload-sarif@cdcdbb579706841c47f7063dda365e292e5cad7a # v2.13.4 + uses: github/codeql-action/upload-sarif@df409f7d9260372bd5f19e5b04e83cb3c43714ae # v3.27.9 with: sarif_file: sarif-results/${{ matrix.language }}.sarif + continue-on-error: true diff --git a/.github/workflows/compilers.yml b/.github/workflows/compilers.yml index f39d3090cc22bc..d0be762ceeb7c2 100644 --- a/.github/workflows/compilers.yml +++ b/.github/workflows/compilers.yml @@ -1,292 +1,337 @@ +# Some tests depending on this name 'Compilations' via $GITHUB_WORKFLOW. Make sure to update such tests when renaming this workflow. name: Compilations on: push: paths-ignore: - 'doc/**' - - '**/man' + - '**/man/*' - '**.md' - '**.rdoc' - '**/.document' + - '.*.yml' pull_request: paths-ignore: - 'doc/**' - - '**/man' + - '**/man/*' - '**.md' - '**.rdoc' - '**/.document' + - '.*.yml' merge_group: - paths-ignore: - - 'doc/**' - - '**/man' - - '**.md' - - '**.rdoc' - - '**/.document' concurrency: group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }} cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }} -# GitHub actions does not support YAML anchors. This creative use of -# environment variables (plus the "echo $GITHUB_ENV" hack) is to reroute that -# restriction. -env: - default_cc: clang-17 - append_cc: '' - - # -O1 is faster than -O3 in our tests... Majority of time are consumed trying - # to optimize binaries. Also GitHub Actions run on relatively modern CPUs - # compared to, say, GCC 4 or Clang 3. We don't specify `-march=native` - # because compilers tend not understand what the CPU is. - optflags: '-O1' - - # -g0 disables backtraces when SEGV. Do not set that. - debugflags: '-ggdb3' - - default_configure: >- - --enable-debug-env - --disable-install-doc - --with-ext=-test-/cxxanyargs,+ - append_configure: >- - --without-valgrind - --without-jemalloc - --without-gmp - - CONFIGURE_TTY: never - GITPULLOPTIONS: --no-tags origin ${{ github.ref }} - RUBY_DEBUG: ci rgengc - RUBY_TESTOPTS: >- - -q - --color=always - --tty=no - permissions: contents: read +# Each job is split so that they roughly take 30min to run through. jobs: - compile: - strategy: - fail-fast: false - matrix: - env: - - {} - entry: - - { name: gcc-13, env: { default_cc: gcc-13 } } - - { name: gcc-12, env: { default_cc: gcc-12 } } - - { name: gcc-11, env: { default_cc: gcc-11 } } - - { name: gcc-10, env: { default_cc: gcc-10 } } - - { name: gcc-9, env: { default_cc: gcc-9 } } - - { name: gcc-8, env: { default_cc: gcc-8 } } - - { name: gcc-7, env: { default_cc: gcc-7 } } - - name: 'gcc-13 LTO' - container: gcc-13 - env: - default_cc: 'gcc-13 -flto=auto -ffat-lto-objects -Werror=lto-type-mismatch' - optflags: '-O2' - shared: disable - # check: true - - { name: clang-18, env: { default_cc: clang-18 } } - - { name: clang-17, env: { default_cc: clang-17 } } - - { name: clang-16, env: { default_cc: clang-16 } } - - { name: clang-15, env: { default_cc: clang-15 } } - - { name: clang-14, env: { default_cc: clang-14 } } - - { name: clang-13, env: { default_cc: clang-13 } } - - { name: clang-12, env: { default_cc: clang-12 } } - - { name: clang-11, env: { default_cc: clang-11 } } - - { name: clang-10, env: { default_cc: clang-10 } } - # llvm-objcopy<=9 doesn't have --wildcard. It compiles, but leaves Rust symbols in libyjit.o. - - { name: clang-9, env: { default_cc: clang-9, append_configure: '--disable-yjit' } } - - { name: clang-8, env: { default_cc: clang-8, append_configure: '--disable-yjit' } } - - { name: clang-7, env: { default_cc: clang-7, append_configure: '--disable-yjit' } } - - { name: clang-6.0, env: { default_cc: clang-6.0, append_configure: '--disable-yjit' } } - - name: 'clang-16 LTO' - container: clang-16 - env: - default_cc: 'clang-16 -flto=auto' - optflags: '-O2' - shared: disable - # check: true - - - { name: ext/Setup } - -# - { name: aarch64-linux-gnu, crosshost: aarch64-linux-gnu, container: crossbuild-essential-arm64 } -# - { name: arm-linux-gnueabi, crosshost: arm-linux-gnueabi } -# - { name: arm-linux-gnueabihf, crosshost: arm-linux-gnueabihf } -# - { name: i686-w64-mingw32, crosshost: i686-w64-mingw32 } -# - { name: powerpc-linux-gnu, crosshost: powerpc-linux-gnu } -# - { name: powerpc64le-linux-gnu, crosshost: powerpc64le-linux-gnu, container: crossbuild-essential-ppc64el } -# - { name: s390x-linux-gnu, crosshost: s390x-linux-gnu, container: crossbuild-essential-s390x } -# - { name: x86_64-w64-mingw32, crosshost: x86_64-w64-mingw32, container: mingw-w64 } - - # -Wno-strict-prototypes is necessary with current clang-15 since - # older autoconf generate functions without prototype and -pedantic - # now implies strict-prototypes. Disabling the error but leaving the - # warning generates a lot of noise from use of ANYARGS in - # rb_define_method() and friends. - # See: https://github.com/llvm/llvm-project/commit/11da1b53d8cd3507959022cd790d5a7ad4573d94 - - { name: c99, env: { CFLAGS: '-std=c99 -Werror=pedantic -pedantic-errors -Wno-strict-prototypes' } } -# - { name: c11, env: { CFLAGS: '-std=c11 -Werror=pedantic -pedantic-errors -Wno-strict-prototypes' } } -# - { name: c17, env: { CFLAGS: '-std=c17 -Werror=pedantic -pedantic-errors -Wno-strict-prototypes' } } - - { name: c23, env: { CFLAGS: '-std=c2x -Werror=pedantic -pedantic-errors -Wno-strict-prototypes' } } - - { name: c++98, env: { CXXFLAGS: '-std=c++98 -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' } } -# - { name: c++11, env: { CXXFLAGS: '-std=c++11 -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' } } -# - { name: c++14, env: { CXXFLAGS: '-std=c++14 -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' } } -# - { name: c++17, env: { CXXFLAGS: '-std=c++17 -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' } } -# - { name: c++20, env: { CXXFLAGS: '-std=c++20 -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' } } -# - { name: c++23, env: { CXXFLAGS: '-std=c++23 -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' } } - - { name: c++26, env: { CXXFLAGS: '-std=c++26 -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' } } - - - { name: '-O0', env: { optflags: '-O0 -march=x86-64 -mtune=generic' } } -# - { name: '-O3', env: { optflags: '-O3 -march=x86-64 -mtune=generic' }, check: true } - - - { name: gmp, env: { append_configure: '--with-gmp' } } - - { name: jemalloc, env: { append_configure: '--with-jemalloc' } } - - { name: valgrind, env: { append_configure: '--with-valgrind' } } - - { name: 'coroutine=ucontext', env: { append_configure: '--with-coroutine=ucontext' } } - - { name: 'coroutine=pthread', env: { append_configure: '--with-coroutine=pthread' } } - - { name: disable-jit-support, env: { append_configure: '--disable-jit-support' } } - - { name: disable-dln, env: { append_configure: '--disable-dln' } } - - { name: enable-mkmf-verbose, env: { append_configure: '--enable-mkmf-verbose' } } - - { name: disable-rubygems, env: { append_configure: '--disable-rubygems' } } - - { name: RUBY_DEVEL, env: { append_configure: '--enable-devel' } } - - - { name: OPT_THREADED_CODE=1, env: { cppflags: '-DOPT_THREADED_CODE=1' } } - - { name: OPT_THREADED_CODE=2, env: { cppflags: '-DOPT_THREADED_CODE=2' } } - - { name: OPT_THREADED_CODE=3, env: { cppflags: '-DOPT_THREADED_CODE=3' } } - - - { name: NDEBUG, env: { cppflags: '-DNDEBUG' } } - - { name: RUBY_DEBUG, env: { cppflags: '-DRUBY_DEBUG' } } -# - { name: ARRAY_DEBUG, env: { cppflags: '-DARRAY_DEBUG' } } -# - { name: BIGNUM_DEBUG, env: { cppflags: '-DBIGNUM_DEBUG' } } -# - { name: CCAN_LIST_DEBUG, env: { cppflags: '-DCCAN_LIST_DEBUG' } } -# - { name: CPDEBUG=-1, env: { cppflags: '-DCPDEBUG=-1' } } -# - { name: ENC_DEBUG, env: { cppflags: '-DENC_DEBUG' } } -# - { name: GC_DEBUG, env: { cppflags: '-DGC_DEBUG' } } -# - { name: HASH_DEBUG, env: { cppflags: '-DHASH_DEBUG' } } -# - { name: ID_TABLE_DEBUG, env: { cppflags: '-DID_TABLE_DEBUG' } } -# - { name: RGENGC_DEBUG=-1, env: { cppflags: '-DRGENGC_DEBUG=-1' } } -# - { name: SYMBOL_DEBUG, env: { cppflags: '-DSYMBOL_DEBUG' } } - -# - { name: RGENGC_CHECK_MODE, env: { cppflags: '-DRGENGC_CHECK_MODE' } } -# - { name: VM_CHECK_MODE, env: { cppflags: '-DVM_CHECK_MODE' } } - -# - { name: USE_EMBED_CI=0, env: { cppflags: '-DUSE_EMBED_CI=0' } } - - name: USE_FLONUM=0 - env: - cppflags: '-DUSE_FLONUM=0' - # yjit requires FLONUM for the pointer tagging scheme - append_configure: '--disable-yjit' -# - { name: USE_GC_MALLOC_OBJ_INFO_DETAILS, env: { cppflags: '-DUSE_GC_MALLOC_OBJ_INFO_DETAILS' } } -# - { name: USE_LAZY_LOAD, env: { cppflags: '-DUSE_LAZY_LOAD' } } -# - { name: USE_SYMBOL_GC=0, env: { cppflags: '-DUSE_SYMBOL_GC=0' } } -# - { name: USE_THREAD_CACHE=0, env: { cppflags: '-DUSE_THREAD_CACHE=0' } } - - { name: USE_RUBY_DEBUG_LOG=1, env: { cppflags: '-DUSE_RUBY_DEBUG_LOG=1' } } -# - { name: USE_DEBUG_COUNTER, env: { cppflags: '-DUSE_DEBUG_COUNTER=1', RUBY_DEBUG_COUNTER_DISABLE: '1' } } - - { name: SHARABLE_MIDDLE_SUBSTRING, env: { cppflags: '-DSHARABLE_MIDDLE_SUBSTRING=1' } } - -# - { name: DEBUG_FIND_TIME_NUMGUESS, env: { cppflags: '-DDEBUG_FIND_TIME_NUMGUESS' } } -# - { name: DEBUG_INTEGER_PACK, env: { cppflags: '-DDEBUG_INTEGER_PACK' } } -# - { name: ENABLE_PATH_CHECK, env: { cppflags: '-DENABLE_PATH_CHECK' } } - -# - { name: GC_DEBUG_STRESS_TO_CLASS, env: { cppflags: '-DGC_DEBUG_STRESS_TO_CLASS' } } -# - { name: GC_ENABLE_LAZY_SWEEP=0, env: { cppflags: '-DGC_ENABLE_LAZY_SWEEP=0' } } -# - { name: GC_PROFILE_DETAIL_MEMOTY, env: { cppflags: '-DGC_PROFILE_DETAIL_MEMOTY' } } -# - { name: GC_PROFILE_MORE_DETAIL, env: { cppflags: '-DGC_PROFILE_MORE_DETAIL' } } - -# - { name: CALC_EXACT_MALLOC_SIZE, env: { cppflags: '-DCALC_EXACT_MALLOC_SIZE' } } -# - { name: MALLOC_ALLOCATED_SIZE_CHECK, env: { cppflags: '-DMALLOC_ALLOCATED_SIZE_CHECK' } } - -# - { name: IBF_ISEQ_ENABLE_LOCAL_BUFFER, env: { cppflags: '-DIBF_ISEQ_ENABLE_LOCAL_BUFFER' } } - -# - { name: RGENGC_ESTIMATE_OLDMALLOC, env: { cppflags: '-DRGENGC_ESTIMATE_OLDMALLOC' } } -# - { name: RGENGC_FORCE_MAJOR_GC, env: { cppflags: '-DRGENGC_FORCE_MAJOR_GC' } } -# - { name: RGENGC_OBJ_INFO, env: { cppflags: '-DRGENGC_OBJ_INFO' } } -# - { name: RGENGC_PROFILE, env: { cppflags: '-DRGENGC_PROFILE' } } - -# - { name: VM_DEBUG_BP_CHECK, env: { cppflags: '-DVM_DEBUG_BP_CHECK' } } -# - { name: VM_DEBUG_VERIFY_METHOD_CACHE, env: { cppflags: '-DVM_DEBUG_VERIFY_METHOD_CACHE' } } - - - { name: enable-yjit, env: { append_configure: '--enable-yjit --disable-rjit' } } - - { name: enable-rjit, env: { append_configure: '--enable-rjit --disable-yjit' } } - - { name: YJIT_FORCE_ENABLE, env: { cppflags: '-DYJIT_FORCE_ENABLE' } } -# - { name: RJIT_FORCE_ENABLE, env: { cppflags: '-DRJIT_FORCE_ENABLE' } } - - { name: UNIVERSAL_PARSER, env: { cppflags: '-DUNIVERSAL_PARSER' } } - - name: ${{ matrix.entry.name }} - + compile-if: + name: 'omnibus compilations, trigger' runs-on: ubuntu-latest - - container: - image: ghcr.io/ruby/ruby-ci-image:${{ matrix.entry.container || matrix.entry.env.default_cc || 'clang-17' }} - options: --user root - if: >- ${{!(false || contains(github.event.head_commit.message, '[DOC]') + || contains(github.event.head_commit.message, 'Document') || contains(github.event.pull_request.title, '[DOC]') + || contains(github.event.pull_request.title, 'Document') || contains(github.event.pull_request.labels.*.name, 'Documentation') - || (github.event_name == 'push' && github.actor == 'dependabot[bot]') + || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]') )}} - - env: ${{ matrix.entry.env || matrix.env }} - steps: - - run: id + - run: true working-directory: - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + compile1: + name: 'omnibus compilations, #1' + runs-on: ubuntu-latest + needs: compile-if + if: ${{ needs.compile-if.result == 'success' }} + timeout-minutes: 60 + services: { docuum: { image: 'stephanmisc/docuum', options: '--init', volumes: [ '/root', '/var/run/docker.sock:/var/run/docker.sock' ] } } + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: { sparse-checkout-cone-mode: false, sparse-checkout: /.github } + # Set fetch-depth: 10 so that Launchable can receive commits information. + - { uses: './.github/actions/setup/directories', with: { srcdir: 'src', builddir: 'build', makeup: true, fetch-depth: 10 } } + - name: 'clang 18 LTO' + uses: './.github/actions/compilers' with: - sparse-checkout-cone-mode: false - sparse-checkout: /.github - - - uses: ./.github/actions/setup/directories + tag: clang-18 + with_gcc: 'clang-18 -flto=auto' + optflags: '-O2' + enable_shared: false + - { uses: './.github/actions/compilers', name: '-O0', with: { optflags: '-O0 -march=x86-64 -mtune=generic' } } + # - { uses: './.github/actions/compilers', name: '-O3', with: { optflags: '-O3 -march=x86-64 -mtune=generic', check: true } } + + compile2: + name: 'omnibus compilations, #2' + runs-on: ubuntu-latest + needs: compile-if + if: ${{ needs.compile-if.result == 'success' }} + timeout-minutes: 60 + services: { docuum: { image: 'stephanmisc/docuum', options: '--init', volumes: [ '/root', '/var/run/docker.sock:/var/run/docker.sock' ] } } + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: { sparse-checkout-cone-mode: false, sparse-checkout: /.github } + - { uses: './.github/actions/setup/directories', with: { srcdir: 'src', builddir: 'build', makeup: true, fetch-depth: 10 } } + - name: 'GCC 15 LTO' + uses: './.github/actions/compilers' with: - srcdir: src - builddir: build - makeup: true - - - name: Run configure - run: > - ../src/configure -C ${default_configure} ${append_configure} - --${{ - matrix.entry.crosshost && 'host' || 'with-gcc' - }}=${{ - matrix.entry.crosshost || '"${default_cc}${append_cc:+ $append_cc}"' - }} - --${{ matrix.entry.shared || 'enable' }}-shared - - - name: Add to ext/Setup # statically link just the etc extension - run: mkdir ext && echo etc >> ext/Setup - if: ${{ matrix.entry.name == 'ext/Setup' }} - - - run: make showflags - - - run: make - - - run: make test - - - run: make install - if: ${{ matrix.entry.check }} - - - run: make test-tool - if: ${{ matrix.entry.check }} - - - run: make test-all TESTS='-- ruby -ext-' - if: ${{ matrix.entry.check }} - - - run: make test-spec - env: - CHECK_LEAKS: true - if: ${{ matrix.entry.check }} - - - run: make test-annocheck - if: ${{ matrix.entry.check && endsWith(matrix.entry.name, 'annocheck') }} - + tag: gcc-15 + with_gcc: 'gcc-15 -flto=auto -ffat-lto-objects -Werror=lto-type-mismatch' + optflags: '-O2' + enable_shared: false + - { uses: './.github/actions/compilers', name: 'ext/Setup', with: { static_exts: 'etc json/* */escape' } } + - { uses: './.github/actions/compilers', name: 'GCC 15', with: { tag: 'gcc-15' } } + - { uses: './.github/actions/compilers', name: 'GCC 14', with: { tag: 'gcc-14' } } + - { uses: './.github/actions/compilers', name: 'GCC 13', with: { tag: 'gcc-13' } } + - { uses: './.github/actions/compilers', name: 'GCC 12', with: { tag: 'gcc-12' } } + - { uses: './.github/actions/compilers', name: 'GCC 11', with: { tag: 'gcc-11' } } + - { uses: './.github/actions/compilers', name: 'GCC 10', with: { tag: 'gcc-10' } } + - { uses: './.github/actions/compilers', name: 'GCC 9', with: { tag: 'gcc-9' } } + - { uses: './.github/actions/compilers', name: 'GCC 8', with: { tag: 'gcc-8' } } + - { uses: './.github/actions/compilers', name: 'GCC 7', with: { tag: 'gcc-7' } } + + compile3: + name: 'omnibus compilations, #3' + runs-on: ubuntu-latest + needs: compile-if + if: ${{ needs.compile-if.result == 'success' }} + timeout-minutes: 60 + services: { docuum: { image: 'stephanmisc/docuum', options: '--init', volumes: [ '/root', '/var/run/docker.sock:/var/run/docker.sock' ] } } + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: { sparse-checkout-cone-mode: false, sparse-checkout: /.github } + - { uses: './.github/actions/setup/directories', with: { srcdir: 'src', builddir: 'build', makeup: true, fetch-depth: 10 } } + - { uses: './.github/actions/compilers', name: 'clang 21', with: { tag: 'clang-21' } } + - { uses: './.github/actions/compilers', name: 'clang 20', with: { tag: 'clang-20' } } + - { uses: './.github/actions/compilers', name: 'clang 19', with: { tag: 'clang-19' } } + - { uses: './.github/actions/compilers', name: 'clang 18', with: { tag: 'clang-18' } } + - { uses: './.github/actions/compilers', name: 'clang 17', with: { tag: 'clang-17' } } + - { uses: './.github/actions/compilers', name: 'clang 16', with: { tag: 'clang-16' } } + - { uses: './.github/actions/compilers', name: 'clang 15', with: { tag: 'clang-15' } } + - { uses: './.github/actions/compilers', name: 'clang 14', with: { tag: 'clang-14' } } + + compile4: + name: 'omnibus compilations, #4' + runs-on: ubuntu-latest + needs: compile-if + if: ${{ needs.compile-if.result == 'success' }} + timeout-minutes: 60 + services: { docuum: { image: 'stephanmisc/docuum', options: '--init', volumes: [ '/root', '/var/run/docker.sock:/var/run/docker.sock' ] } } + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: { sparse-checkout-cone-mode: false, sparse-checkout: /.github } + - { uses: './.github/actions/setup/directories', with: { srcdir: 'src', builddir: 'build', makeup: true, fetch-depth: 10 } } + - { uses: './.github/actions/compilers', name: 'clang 13', with: { tag: 'clang-13' } } + - { uses: './.github/actions/compilers', name: 'clang 12', with: { tag: 'clang-12' } } + - { uses: './.github/actions/compilers', name: 'clang 11', with: { tag: 'clang-11' } } + - { uses: './.github/actions/compilers', name: 'clang 10', with: { tag: 'clang-10' } } + # llvm-objcopy<=9 doesn't have --wildcard. It compiles, but leaves Rust symbols in libyjit.o. + - { uses: './.github/actions/compilers', name: 'clang 9', with: { tag: 'clang-9', append_configure: '--disable-yjit' } } + - { uses: './.github/actions/compilers', name: 'clang 8', with: { tag: 'clang-8', append_configure: '--disable-yjit' } } + - { uses: './.github/actions/compilers', name: 'clang 7', with: { tag: 'clang-7', append_configure: '--disable-yjit' } } + - { uses: './.github/actions/compilers', name: 'clang 6', with: { tag: 'clang-6.0', append_configure: '--disable-yjit' } } + + compile5: + name: 'omnibus compilations, #5' + runs-on: ubuntu-latest + needs: compile-if + if: ${{ needs.compile-if.result == 'success' }} + timeout-minutes: 60 + services: { docuum: { image: 'stephanmisc/docuum', options: '--init', volumes: [ '/root', '/var/run/docker.sock:/var/run/docker.sock' ] } } + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: { sparse-checkout-cone-mode: false, sparse-checkout: /.github } + - { uses: './.github/actions/setup/directories', with: { srcdir: 'src', builddir: 'build', makeup: true, fetch-depth: 10 } } + # -Wno-strict-prototypes is necessary with current clang-15 since + # older autoconf generate functions without prototype and -pedantic + # now implies strict-prototypes. Disabling the error but leaving the + # warning generates a lot of noise from use of ANYARGS in + # rb_define_method() and friends. + # See: https://github.com/llvm/llvm-project/commit/11da1b53d8cd3507959022cd790d5a7ad4573d94 + - { uses: './.github/actions/compilers', name: 'C99', with: { CFLAGS: '-std=c99 -Werror=pedantic -pedantic-errors -Wno-strict-prototypes' } } + - { uses: './.github/actions/compilers', name: 'C11', with: { CFLAGS: '-std=c11 -Werror=pedantic -pedantic-errors -Wno-strict-prototypes' } } + - { uses: './.github/actions/compilers', name: 'C17', with: { CFLAGS: '-std=c17 -Werror=pedantic -pedantic-errors -Wno-strict-prototypes' } } + - { uses: './.github/actions/compilers', name: 'C23', with: { CFLAGS: '-std=c2x -Werror=pedantic -pedantic-errors -Wno-strict-prototypes' } } + - { uses: './.github/actions/compilers', name: 'C++98', with: { CXXFLAGS: '-std=c++98 -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' } } + - { uses: './.github/actions/compilers', name: 'C++11', with: { CXXFLAGS: '-std=c++11 -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' } } + - { uses: './.github/actions/compilers', name: 'C++14', with: { CXXFLAGS: '-std=c++14 -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' } } + - { uses: './.github/actions/compilers', name: 'C++17', with: { CXXFLAGS: '-std=c++17 -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' } } + + compile6: + name: 'omnibus compilations, #6' + runs-on: ubuntu-latest + needs: compile-if + if: ${{ needs.compile-if.result == 'success' }} + timeout-minutes: 60 + services: { docuum: { image: 'stephanmisc/docuum', options: '--init', volumes: [ '/root', '/var/run/docker.sock:/var/run/docker.sock' ] } } + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: { sparse-checkout-cone-mode: false, sparse-checkout: /.github } + - { uses: './.github/actions/setup/directories', with: { srcdir: 'src', builddir: 'build', makeup: true, fetch-depth: 10 } } + - { uses: './.github/actions/compilers', name: 'C++20', with: { CXXFLAGS: '-std=c++20 -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' } } + - { uses: './.github/actions/compilers', name: 'C++23', with: { CXXFLAGS: '-std=c++23 -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' } } + - { uses: './.github/actions/compilers', name: 'C++26', with: { CXXFLAGS: '-std=c++26 -Werror=pedantic -pedantic-errors -Wno-c++11-long-long' } } + - { uses: './.github/actions/compilers', name: 'gmp', with: { append_configure: '--with-gmp', check: 'ruby/test_bignum.rb', mspecopt: "/github/workspace/src/spec/ruby/core/integer" } } + - { uses: './.github/actions/compilers', name: 'jemalloc', with: { append_configure: '--with-jemalloc' } } + - { uses: './.github/actions/compilers', name: 'valgrind', with: { append_configure: '--with-valgrind' } } + - { uses: './.github/actions/compilers', name: 'coroutine=ucontext', with: { append_configure: '--with-coroutine=ucontext' } } + - { uses: './.github/actions/compilers', name: 'coroutine=pthread', with: { append_configure: '--with-coroutine=pthread' } } + + compile7: + name: 'omnibus compilations, #7' + runs-on: ubuntu-latest + needs: compile-if + if: ${{ needs.compile-if.result == 'success' }} + timeout-minutes: 60 + services: { docuum: { image: 'stephanmisc/docuum', options: '--init', volumes: [ '/root', '/var/run/docker.sock:/var/run/docker.sock' ] } } + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: { sparse-checkout-cone-mode: false, sparse-checkout: /.github } + - { uses: './.github/actions/setup/directories', with: { srcdir: 'src', builddir: 'build', makeup: true, fetch-depth: 10 } } + - { uses: './.github/actions/compilers', name: 'disable-jit', with: { append_configure: '--disable-yjit --disable-zjit' } } + - { uses: './.github/actions/compilers', name: 'disable-yjit', with: { append_configure: '--disable-yjit' } } + - { uses: './.github/actions/compilers', name: 'disable-zjit', with: { append_configure: '--disable-zjit' } } + - { uses: './.github/actions/compilers', name: 'disable-dln', with: { append_configure: '--disable-dln' } } + - { uses: './.github/actions/compilers', name: 'enable-mkmf-verbose', with: { append_configure: '--enable-mkmf-verbose' } } + - { uses: './.github/actions/compilers', name: 'disable-rubygems', with: { append_configure: '--disable-rubygems' } } + - { uses: './.github/actions/compilers', name: 'RUBY_DEVEL', with: { append_configure: '--enable-devel' } } + - { uses: './.github/actions/compilers', name: 'OPT_THREADED_CODE=0', with: { cppflags: '-DOPT_THREADED_CODE=0' } } + - { uses: './.github/actions/compilers', name: 'OPT_THREADED_CODE=1', with: { cppflags: '-DOPT_THREADED_CODE=1' } } + - { uses: './.github/actions/compilers', name: 'OPT_THREADED_CODE=2', with: { cppflags: '-DOPT_THREADED_CODE=2' } } + + compile8: + name: 'omnibus compilations, #8' + runs-on: ubuntu-latest + needs: compile-if + if: ${{ needs.compile-if.result == 'success' }} + timeout-minutes: 60 + services: { docuum: { image: 'stephanmisc/docuum', options: '--init', volumes: [ '/root', '/var/run/docker.sock:/var/run/docker.sock' ] } } + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: { sparse-checkout-cone-mode: false, sparse-checkout: /.github } + - { uses: './.github/actions/setup/directories', with: { srcdir: 'src', builddir: 'build', makeup: true, fetch-depth: 10 } } + - { uses: './.github/actions/compilers', name: 'NDEBUG', with: { cppflags: '-DNDEBUG' } } + - { uses: './.github/actions/compilers', name: 'RUBY_DEBUG', with: { cppflags: '-DRUBY_DEBUG' } } + - { uses: './.github/actions/compilers', name: 'ARRAY_DEBUG', with: { cppflags: '-DARRAY_DEBUG' } } + - { uses: './.github/actions/compilers', name: 'BIGNUM_DEBUG', with: { cppflags: '-DBIGNUM_DEBUG' } } + - { uses: './.github/actions/compilers', name: 'CCAN_LIST_DEBUG', with: { cppflags: '-DCCAN_LIST_DEBUG' } } + - { uses: './.github/actions/compilers', name: 'CPDEBUG=-1', with: { cppflags: '-DCPDEBUG=-1' } } + - { uses: './.github/actions/compilers', name: 'ENC_DEBUG', with: { cppflags: '-DENC_DEBUG' } } + - { uses: './.github/actions/compilers', name: 'GC_DEBUG', with: { cppflags: '-DGC_DEBUG' } } + + compile9: + name: 'omnibus compilations, #9' + runs-on: ubuntu-latest + needs: compile-if + if: ${{ needs.compile-if.result == 'success' }} + timeout-minutes: 60 + services: { docuum: { image: 'stephanmisc/docuum', options: '--init', volumes: [ '/root', '/var/run/docker.sock:/var/run/docker.sock' ] } } + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: { sparse-checkout-cone-mode: false, sparse-checkout: /.github } + - { uses: './.github/actions/setup/directories', with: { srcdir: 'src', builddir: 'build', makeup: true, fetch-depth: 10 } } + - { uses: './.github/actions/compilers', name: 'HASH_DEBUG', with: { cppflags: '-DHASH_DEBUG' } } + - { uses: './.github/actions/compilers', name: 'ID_TABLE_DEBUG', with: { cppflags: '-DID_TABLE_DEBUG' } } + - { uses: './.github/actions/compilers', name: 'RGENGC_DEBUG=-1', with: { cppflags: '-DRGENGC_DEBUG=-1' } } + - { uses: './.github/actions/compilers', name: 'SYMBOL_DEBUG', with: { cppflags: '-DSYMBOL_DEBUG' } } + - { uses: './.github/actions/compilers', name: 'RGENGC_CHECK_MODE', with: { cppflags: '-DRGENGC_CHECK_MODE' } } + - { uses: './.github/actions/compilers', name: 'VM_CHECK_MODE', with: { cppflags: '-DVM_CHECK_MODE' } } + - { uses: './.github/actions/compilers', name: 'USE_EMBED_CI=0', with: { cppflags: '-DUSE_EMBED_CI=0' } } + - { uses: './.github/actions/compilers', name: 'USE_FLONUM=0', with: { cppflags: '-DUSE_FLONUM=0', append_configure: '--disable-yjit' } } + + compileX: + name: 'omnibus compilations, #10' + runs-on: ubuntu-latest + needs: compile-if + if: ${{ needs.compile-if.result == 'success' }} + timeout-minutes: 60 + services: { docuum: { image: 'stephanmisc/docuum', options: '--init', volumes: [ '/root', '/var/run/docker.sock:/var/run/docker.sock' ] } } + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: { sparse-checkout-cone-mode: false, sparse-checkout: /.github } + - { uses: './.github/actions/setup/directories', with: { srcdir: 'src', builddir: 'build', makeup: true, fetch-depth: 10 } } + - { uses: './.github/actions/compilers', name: 'USE_LAZY_LOAD', with: { cppflags: '-DUSE_LAZY_LOAD' } } + - { uses: './.github/actions/compilers', name: 'USE_SYMBOL_GC=0', with: { cppflags: '-DUSE_SYMBOL_GC=0' } } + - { uses: './.github/actions/compilers', name: 'USE_THREAD_CACHE=0', with: { cppflags: '-DUSE_THREAD_CACHE=0' } } + - { uses: './.github/actions/compilers', name: 'USE_RUBY_DEBUG_LOG=1', with: { cppflags: '-DUSE_RUBY_DEBUG_LOG=1' } } + - { uses: './.github/actions/compilers', name: 'USE_DEBUG_COUNTER', with: { cppflags: '-DUSE_DEBUG_COUNTER=1' } } + - { uses: './.github/actions/compilers', name: 'SHARABLE_MIDDLE_SUBSTRING', with: { cppflags: '-DSHARABLE_MIDDLE_SUBSTRING=1' } } + - { uses: './.github/actions/compilers', name: 'DEBUG_FIND_TIME_NUMGUESS', with: { cppflags: '-DDEBUG_FIND_TIME_NUMGUESS' } } + - { uses: './.github/actions/compilers', name: 'DEBUG_INTEGER_PACK', with: { cppflags: '-DDEBUG_INTEGER_PACK' } } + + compileB: + name: 'omnibus compilations, #11' + runs-on: ubuntu-latest + needs: compile-if + if: ${{ needs.compile-if.result == 'success' }} + timeout-minutes: 60 + services: { docuum: { image: 'stephanmisc/docuum', options: '--init', volumes: [ '/root', '/var/run/docker.sock:/var/run/docker.sock' ] } } + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: { sparse-checkout-cone-mode: false, sparse-checkout: /.github } + - { uses: './.github/actions/setup/directories', with: { srcdir: 'src', builddir: 'build', makeup: true, fetch-depth: 10 } } + - { uses: './.github/actions/compilers', name: 'GC_DEBUG_STRESS_TO_CLASS', with: { cppflags: '-DGC_DEBUG_STRESS_TO_CLASS' } } + - { uses: './.github/actions/compilers', name: 'GC_ENABLE_LAZY_SWEEP=0', with: { cppflags: '-DGC_ENABLE_LAZY_SWEEP=0' } } + - { uses: './.github/actions/compilers', name: 'GC_PROFILE_DETAIL_MEMORY', with: { cppflags: '-DGC_PROFILE_DETAIL_MEMORY' } } + - { uses: './.github/actions/compilers', name: 'GC_PROFILE_MORE_DETAIL', with: { cppflags: '-DGC_PROFILE_MORE_DETAIL' } } + - { uses: './.github/actions/compilers', name: 'MALLOC_ALLOCATED_SIZE_CHECK', with: { cppflags: '-DMALLOC_ALLOCATED_SIZE_CHECK' } } + - { uses: './.github/actions/compilers', name: 'RGENGC_ESTIMATE_OLDMALLOC', with: { cppflags: '-DRGENGC_ESTIMATE_OLDMALLOC' } } + - { uses: './.github/actions/compilers', name: 'RGENGC_OBJ_INFO', with: { cppflags: '-DRGENGC_OBJ_INFO' } } + - { uses: './.github/actions/compilers', name: 'RGENGC_PROFILE', with: { cppflags: '-DRGENGC_PROFILE' } } + + compileC: + name: 'omnibus compilations, #12' + runs-on: ubuntu-latest + needs: compile-if + if: ${{ needs.compile-if.result == 'success' }} + timeout-minutes: 60 + services: { docuum: { image: 'stephanmisc/docuum', options: '--init', volumes: [ '/root', '/var/run/docker.sock:/var/run/docker.sock' ] } } + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: { sparse-checkout-cone-mode: false, sparse-checkout: /.github } + - { uses: './.github/actions/setup/directories', with: { srcdir: 'src', builddir: 'build', makeup: true, fetch-depth: 10 } } + - { uses: './.github/actions/compilers', name: 'VM_DEBUG_BP_CHECK', with: { cppflags: '-DVM_DEBUG_BP_CHECK' } } + - { uses: './.github/actions/compilers', name: 'VM_DEBUG_VERIFY_METHOD_CACHE', with: { cppflags: '-DVM_DEBUG_VERIFY_METHOD_CACHE' } } + - { uses: './.github/actions/compilers', name: 'enable-yjit', with: { append_configure: '--enable-yjit' } } + - { uses: './.github/actions/compilers', name: 'enable-{y,z}jit', with: { append_configure: '--enable-yjit --enable-zjit' } } + - { uses: './.github/actions/compilers', name: 'enable-{y,z}jit=dev', with: { append_configure: '--enable-yjit=dev --enable-zjit' } } + - { uses: './.github/actions/compilers', name: 'YJIT_FORCE_ENABLE', with: { cppflags: '-DYJIT_FORCE_ENABLE' } } + - { uses: './.github/actions/compilers', name: 'UNIVERSAL_PARSER', with: { cppflags: '-DUNIVERSAL_PARSER' } } + + compilemax: + name: 'omnibus compilations, result' + runs-on: ubuntu-latest + if: ${{ always() }} + needs: + - 'compile1' + - 'compile2' + - 'compile3' + - 'compile4' + - 'compile5' + - 'compile6' + - 'compile7' + - 'compile8' + - 'compile9' + - 'compileX' + - 'compileB' + - 'compileC' + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: { sparse-checkout-cone-mode: false, sparse-checkout: /.github } - uses: ./.github/actions/slack with: - label: ${{ matrix.entry.name }} + label: 'omnibus' SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot - if: ${{ failure() && github.event_name == 'push' }} + if: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }} + - run: false + working-directory: + if: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }} defaults: run: diff --git a/.github/workflows/cygwin.yml b/.github/workflows/cygwin.yml new file mode 100644 index 00000000000000..d822a2e9e217e3 --- /dev/null +++ b/.github/workflows/cygwin.yml @@ -0,0 +1,67 @@ +name: Cygwin +on: + push: + paths-ignore: + - 'doc/**' + - '**/man/*' + - '**.md' + - '**.rdoc' + - '**/.document' + - '.*.yml' + pull_request: + paths-ignore: + - 'doc/**' + - '**/man/*' + - '**.md' + - '**.rdoc' + - '**/.document' + - '.*.yml' + merge_group: + +concurrency: + group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }} + cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }} + +permissions: + contents: read + +jobs: + make: + runs-on: windows-2022 + + if: >- + ${{!(false + || contains(github.event.head_commit.message, '[DOC]') + || contains(github.event.head_commit.message, 'Document') + || contains(github.event.pull_request.title, '[DOC]') + || contains(github.event.pull_request.title, 'Document') + || contains(github.event.pull_request.labels.*.name, 'Documentation') + || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]') + )}} + + steps: + - run: git config --global core.autocrlf input + + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + + - name: Setup Cygwin + uses: cygwin/cygwin-install-action@master + with: + packages: ruby gcc-core make autoconf libtool libssl-devel libyaml-devel libffi-devel zlib-devel + + - name: configure + run: | + ./autogen.sh + ./configure --disable-install-doc + shell: C:\cygwin\bin\bash.EXE --noprofile --norc -e -o igncr -o pipefail {0} + + - name: Extract bundled gems + run: | + make ruby -j5 + make extract-gems + shell: C:\cygwin\bin\bash.EXE --noprofile --norc -e -o igncr -o pipefail {0} + + - name: make all + timeout-minutes: 30 + run: make -j4 V=1 + shell: C:\cygwin\bin\bash.EXE --noprofile --norc -e -o igncr -o pipefail {0} diff --git a/.github/workflows/default_gems.yml b/.github/workflows/default_gems.yml new file mode 100644 index 00000000000000..cd15e34229e593 --- /dev/null +++ b/.github/workflows/default_gems.yml @@ -0,0 +1,96 @@ +name: Update default gems list +on: [push, pull_request, merge_group] + +concurrency: + group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }} + cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }} + +permissions: + contents: read + +jobs: + update_default_gems: + name: Update default gems list + + permissions: + contents: write # for Git to git push + + runs-on: ubuntu-latest + + if: ${{ github.repository == 'ruby/ruby' }} + + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + token: ${{ (github.repository == 'ruby/ruby' && !startsWith(github.event_name, 'pull')) && secrets.MATZBOT_AUTO_UPDATE_TOKEN || secrets.GITHUB_TOKEN }} + + - id: gems + run: true + if: ${{ github.ref == 'refs/heads/master' }} + + - uses: ./.github/actions/setup/directories + with: + makeup: true + # Skip overwriting MATZBOT_AUTO_UPDATE_TOKEN + checkout: '' # false (ref: https://github.com/actions/runner/issues/2238) + if: ${{ steps.gems.outcome == 'success' }} + + - name: Download previous gems list + run: | + data=default_gems.json + mkdir -p .downloaded-cache + ln -s .downloaded-cache/$data . + curl -O -R -z ./$data https://stdgems.org/$data + if: ${{ steps.gems.outcome == 'success' }} + + - name: Make default gems list + run: | + #!ruby + require 'rubygems' + $:.unshift "lib" + rgver = File.foreach("lib/rubygems.rb") do |line| + break $1 if /^\s*VERSION\s*=\s*"([^"]+)"/ =~ line + end + gems = Dir.glob("{ext,lib}/**/*.gemspec").map do |f| + spec = Gem::Specification.load(f) + "#{spec.name} #{spec.version}" + end.sort + File.open("gems/default_gems", "w") do |f| + f.puts "RubyGems #{rgver}" + f.puts gems + end + shell: ruby --disable=gems {0} + if: ${{ steps.gems.outcome == 'success' }} + + - name: Maintain updated gems list in NEWS + run: | + ruby tool/update-NEWS-gemlist.rb default + if: ${{ steps.gems.outcome == 'success' }} + + - name: Check diffs + id: diff + run: | + git diff --color --no-ext-diff --ignore-submodules --exit-code NEWS.md || + echo update=true >> $GITHUB_OUTPUT + if: ${{ steps.gems.outcome == 'success' }} + + - name: Commit + run: | + git pull --ff-only origin ${GITHUB_REF#refs/heads/} + git commit --message="Update default gems list at ${GITHUB_SHA:0:30} [ci skip]" NEWS.md + git push origin ${GITHUB_REF#refs/heads/} + env: + EMAIL: svn-admin@ruby-lang.org + GIT_AUTHOR_NAME: git + GIT_COMMITTER_NAME: git + if: >- + ${{ + github.repository == 'ruby/ruby' && + !startsWith(github.event_name, 'pull') && + steps.diff.outputs.update + }} + + - uses: ./.github/actions/slack + with: + SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot + if: ${{ failure() }} diff --git a/.github/workflows/dependabot_automerge.yml b/.github/workflows/dependabot_automerge.yml index 6259199b113b64..09fdba7b2b66af 100644 --- a/.github/workflows/dependabot_automerge.yml +++ b/.github/workflows/dependabot_automerge.yml @@ -1,23 +1,25 @@ # from https://github.com/gofiber/swagger/blob/main/.github/workflows/dependabot_automerge.yml name: Dependabot auto-merge on: - pull_request_target: + pull_request: + +permissions: + contents: write + pull-requests: write jobs: automerge: runs-on: ubuntu-latest - - if: ${{ github.actor == 'dependabot[bot]' }} - + if: github.event.pull_request.user.login == 'dependabot[bot]' && github.repository == 'ruby/ruby' steps: - name: Dependabot metadata - uses: dependabot/fetch-metadata@c9c4182bf1b97f5224aee3906fd373f6b61b4526 # v1.6.0 + uses: dependabot/fetch-metadata@08eff52bf64351f401fb50d4972fa95b9f2c2d1b # v2.4.0 id: metadata - name: Wait for status checks - uses: lewagon/wait-on-check-action@e106e5c43e8ca1edea6383a39a01c5ca495fd812 # v1.3.1 + uses: lewagon/wait-on-check-action@ccfb013c15c8afb7bf2b7c028fb74dc5a068cccc # v1.3.4 with: - repo-token: ${{ secrets.MATZBOT_GITHUB_TOKEN }} + repo-token: ${{ secrets.GITHUB_TOKEN }} ref: ${{ github.event.pull_request.head.sha || github.sha }} check-regexp: 'make \(check, .*\)' wait-interval: 30 @@ -27,4 +29,4 @@ jobs: run: gh pr merge --auto --rebase "$PR_URL" env: PR_URL: ${{ github.event.pull_request.html_url }} - GITHUB_TOKEN: ${{ secrets.MATZBOT_GITHUB_TOKEN }} + GITHUB_TOKEN: ${{ secrets.MATZBOT_DEPENDABOT_MERGE_TOKEN }} diff --git a/.github/workflows/labeler.yml b/.github/workflows/labeler.yml new file mode 100644 index 00000000000000..e57cd86e2b3c7f --- /dev/null +++ b/.github/workflows/labeler.yml @@ -0,0 +1,12 @@ +name: "Pull Request Labeler" +on: +- pull_request_target + +jobs: + labeler: + permissions: + contents: read + pull-requests: write + runs-on: ubuntu-latest + steps: + - uses: actions/labeler@v5 diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 30c30e46265c4e..bf5f5cd413c112 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml @@ -3,24 +3,15 @@ on: push: paths-ignore: - 'doc/**' - - '**/man' + - '**/man/*' - '**.md' - '**.rdoc' - '**/.document' + - '.*.yml' pull_request: - paths-ignore: - - 'doc/**' - - '**/man' - - '**.md' - - '**.rdoc' - - '**/.document' + # Do not use paths-ignore for required status checks + # https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/collaborating-on-repositories-with-code-quality-features/troubleshooting-required-status-checks#handling-skipped-but-required-checks merge_group: - paths-ignore: - - 'doc/**' - - '**/man' - - '**.md' - - '**.rdoc' - - '**/.document' concurrency: group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }} @@ -33,13 +24,29 @@ jobs: make: strategy: matrix: - test_task: ['check'] # "test-bundler-parallel", "test-bundled-gems" - os: - - macos-11 - - macos-12 - configure: - - '' - - '--enable-shared' + include: + - test_task: check + os: macos-14 + - test_task: check + os: macos-14 + configure_args: '--with-gcc=gcc-14' + - test_task: check + os: macos-14 + configure_args: '--with-jemalloc --with-opt-dir=$(brew --prefix jemalloc)' + - test_task: check + os: macos-14 + configure_args: '--with-gmp' + - test_task: test-all + test_opts: --repeat-count=2 + os: macos-14 + - test_task: test-bundler-parallel + os: macos-14 + - test_task: test-bundled-gems + os: macos-14 + - test_task: check + os: macos-15 + - test_task: check + os: macos-13 fail-fast: false env: @@ -50,13 +57,15 @@ jobs: if: >- ${{!(false || contains(github.event.head_commit.message, '[DOC]') + || contains(github.event.head_commit.message, 'Document') || contains(github.event.pull_request.title, '[DOC]') + || contains(github.event.pull_request.title, 'Document') || contains(github.event.pull_request.labels.*.name, 'Documentation') - || (github.event_name == 'push' && github.actor == 'dependabot[bot]') + || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]') )}} steps: - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: sparse-checkout-cone-mode: false sparse-checkout: /.github @@ -69,41 +78,120 @@ jobs: srcdir: src builddir: build makeup: true + clean: true + dummy-files: ${{ matrix.test_task == 'check' }} + # Set fetch-depth: 0 so that Launchable can receive commits information. + fetch-depth: 10 + + - name: make sure that kern.coredump=1 + run: | + sysctl -n kern.coredump + sudo sysctl -w kern.coredump=1 + sudo chmod -R +rwx /cores/ + + - name: Delete unused SDKs + # To free up disk space to not run out during the run + run: | + sudo rm -rf ~/.dotnet + sudo rm -rf /Library/Android + sudo rm -rf /Library/Developer/CoreSimulator + continue-on-error: true - name: Run configure - run: ../src/configure -C --disable-install-doc ${{ matrix.configure }} + run: ../src/configure -C --disable-install-doc ${ruby_configure_args} ${{ matrix.configure_args }} - run: make prepare-gems if: ${{ matrix.test_task == 'test-bundled-gems' }} - run: make + - run: make hello + + - name: runirb + run: | + echo IRB::VERSION | make runirb RUNOPT="-- -f" + + - name: Set test options for skipped tests + run: | + set -x + TESTS="$(echo "${{ matrix.skipped_tests }}" | sed 's| |$$/ -n!/|g;s|^|-n!/|;s|$|$$/|')" + echo "TESTS=${TESTS}" >> $GITHUB_ENV + if: ${{ matrix.test_task == 'check' && matrix.skipped_tests }} + + - name: Set up Launchable + id: launchable + uses: ./.github/actions/launchable/setup + with: + os: ${{ matrix.os }} + test-opts: ${{ matrix.test_opts }} + launchable-token: ${{ secrets.LAUNCHABLE_TOKEN }} + builddir: build + srcdir: src + continue-on-error: true + timeout-minutes: 3 + + - name: Set extra test options + run: | + echo "TESTS=$TESTS ${{ matrix.test_opts }}" >> $GITHUB_ENV + echo "RUBY_TEST_TIMEOUT_SCALE=10" >> $GITHUB_ENV # With --repeat-count=2, flaky test by timeout occurs frequently for some reason + if: matrix.test_opts + - name: make ${{ matrix.test_task }} run: | - make -s ${{ matrix.test_task }} ${TESTS:+TESTS=`echo "$TESTS" | sed 's| |$$/ -n!/|g;s|^|-n!/|;s|$|$$/|'`} + test -n "${LAUNCHABLE_STDOUT}" && exec 1> >(tee "${LAUNCHABLE_STDOUT}") + test -n "${LAUNCHABLE_STDERR}" && exec 2> >(tee "${LAUNCHABLE_STDERR}") + + ulimit -c unlimited + make -s ${{ matrix.test_task }} ${TESTS:+TESTS="$TESTS"} timeout-minutes: 60 env: RUBY_TESTOPTS: '-q --tty=no' - TESTS: ${{ matrix.test_task == 'check' && matrix.skipped_tests || '' }} TEST_BUNDLED_GEMS_ALLOW_FAILURES: '' PRECHECK_BUNDLED_GEMS: 'no' + LAUNCHABLE_STDOUT: ${{ steps.launchable.outputs.stdout_report_path }} + LAUNCHABLE_STDERR: ${{ steps.launchable.outputs.stderr_report_path }} - name: make skipped tests run: | - make -s test-all TESTS=`echo "$TESTS" | sed 's| |$$/ -n/|g;s|^|-n/|;s|$|$$/|'` + make -s test-all TESTS="${TESTS//-n!\//-n/}" env: GNUMAKEFLAGS: '' RUBY_TESTOPTS: '-v --tty=no' - TESTS: ${{ matrix.skipped_tests }} PRECHECK_BUNDLED_GEMS: 'no' - if: ${{ matrix.test_task == 'check' && matrix.skipped_tests != '' }} + if: ${{ matrix.test_task == 'check' && matrix.skipped_tests }} continue-on-error: ${{ matrix.continue-on-skipped_tests || false }} - uses: ./.github/actions/slack with: - label: ${{ matrix.test_task }} + label: ${{ matrix.os }} / ${{ matrix.test_task }} SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot - if: ${{ failure() && github.event_name == 'push' }} + if: ${{ failure() }} + + - name: Resolve job ID + id: job_id + uses: actions/github-script@main + env: + matrix: ${{ toJson(matrix) }} + with: + script: | + const { data: workflow_run } = await github.rest.actions.listJobsForWorkflowRun({ + owner: context.repo.owner, + repo: context.repo.repo, + run_id: context.runId + }); + const matrix = JSON.parse(process.env.matrix); + const job_name = `${context.job}${matrix ? ` (${Object.values(matrix).join(", ")})` : ""}`; + return workflow_run.jobs.find((job) => job.name === job_name).id; + + result: + if: ${{ always() }} + name: ${{ github.workflow }} result + runs-on: macos-latest + needs: [make] + steps: + - run: exit 1 + working-directory: + if: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }} defaults: run: diff --git a/.github/workflows/mingw.yml b/.github/workflows/mingw.yml index df24ff394e0c51..72656fa7665f5c 100644 --- a/.github/workflows/mingw.yml +++ b/.github/workflows/mingw.yml @@ -3,24 +3,20 @@ on: push: paths-ignore: - 'doc/**' - - '**/man' + - '**/man/*' - '**.md' - '**.rdoc' - '**/.document' + - '.*.yml' pull_request: paths-ignore: - 'doc/**' - - '**/man' + - '**/man/*' - '**.md' - '**.rdoc' - '**/.document' + - '.*.yml' merge_group: - paths-ignore: - - 'doc/**' - - '**/man' - - '**.md' - - '**.rdoc' - - '**/.document' concurrency: group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }} @@ -52,8 +48,8 @@ jobs: matrix: include: # To mitigate flakiness of MinGW CI, we test only one runtime that newer MSYS2 uses. + # Ruby 3.2 is the first Windows Ruby to use OpenSSL 3.x - msystem: 'UCRT64' - base_ruby: head test_task: 'check' test-all-opts: '--name=!/TestObjSpace#test_reachable_objects_during_iteration/' fail-fast: false @@ -61,45 +57,43 @@ jobs: if: >- ${{!(false || contains(github.event.head_commit.message, '[DOC]') + || contains(github.event.head_commit.message, 'Document') || contains(github.event.pull_request.title, '[DOC]') + || contains(github.event.pull_request.title, 'Document') || contains(github.event.pull_request.labels.*.name, 'Documentation') - || (github.event_name == 'push' && github.actor == 'dependabot[bot]') + || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]') )}} steps: - name: Set up Ruby & MSYS2 - uses: ruby/setup-ruby@250fcd6a742febb1123a77a841497ccaa8b9e939 # v1.152.0 + uses: ruby/setup-ruby@d8d83c3960843afb664e821fed6be52f37da5267 # v1.231.0 with: - ruby-version: ${{ matrix.base_ruby }} + ruby-version: '3.2' - - name: where check + - name: Misc system & package info + working-directory: run: | # show where - mv /c/Windows/System32/libcrypto-1_1-x64.dll /c/Windows/System32/libcrypto-1_1-x64.dll_ - mv /c/Windows/System32/libssl-1_1-x64.dll /c/Windows/System32/libssl-1_1-x64.dll_ result=true - for e in gcc.exe ragel.exe make.exe libcrypto-1_1-x64.dll libssl-1_1-x64.dll; do + for e in gcc.exe ragel.exe make.exe libcrypto-3-x64.dll libssl-3-x64.dll; do echo ::group::$'\033[93m'$e$'\033[m' where $e || result=false echo ::endgroup:: done - $result - working-directory: - - - name: version check - run: | # show version - result=true for e in gcc ragel make "openssl version"; do case "$e" in *" "*) ;; *) e="$e --version";; esac echo ::group::$'\033[93m'$e$'\033[m' $e || result=false echo ::endgroup:: done + # show packages + echo ::group::$'\033[93m'Packages$'\033[m' + pacman -Qs mingw-w64-ucrt-x86_64-* | sed -n "s,local/mingw-w64-ucrt-x86_64-,,p" + echo ::endgroup:: $result - working-directory: - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: sparse-checkout-cone-mode: false sparse-checkout: /.github @@ -109,6 +103,8 @@ jobs: srcdir: src builddir: build makeup: true + # Set fetch-depth: 10 so that Launchable can receive commits information. + fetch-depth: 10 - name: configure run: > @@ -117,14 +113,26 @@ jobs: - name: make all timeout-minutes: 30 - run: make + run: make -j4 - name: make install run: make DESTDIR=../install install-nodoc + - name: Set up Launchable + uses: ./.github/actions/launchable/setup + with: + os: windows-2022 + launchable-token: ${{ secrets.LAUNCHABLE_TOKEN }} + builddir: build + srcdir: src + test-tasks: '["test", "test-all", "test-spec"]' + continue-on-error: true + timeout-minutes: 3 + - name: test timeout-minutes: 30 run: make test + shell: cmd env: GNUMAKEFLAGS: '' RUBY_TESTOPTS: '-v --tty=no' @@ -132,14 +140,14 @@ jobs: - name: test-all timeout-minutes: 45 + shell: cmd run: | - # Actions uses UTF8, causes test failures, similar to normal OS setup - chcp.com 437 make ${{ StartsWith(matrix.test_task, 'test/') && matrix.test_task || 'test-all' }} env: RUBY_TESTOPTS: >- - --retry --job-status=normal --show-skip --timeout-scale=1.5 + --retry --job-status=normal --show-skip --timeout-scale=1.5 -j4 ${{ matrix.test-all-opts }} + ${{ env.TESTS }} BUNDLER_VERSION: if: ${{ matrix.test_task == 'check' || matrix.test_task == 'test-all' || StartsWith(matrix.test_task, 'test/') }} @@ -147,13 +155,14 @@ jobs: timeout-minutes: 10 run: | make ${{ StartsWith(matrix.test_task, 'spec/') && matrix.test_task || 'test-spec' }} + shell: cmd if: ${{ matrix.test_task == 'check' || matrix.test_task == 'test-spec' || StartsWith(matrix.test_task, 'spec/') }} - uses: ./src/.github/actions/slack with: label: ${{ matrix.msystem }} / ${{ matrix.test_task }} SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot - if: ${{ failure() && github.event_name == 'push' }} + if: ${{ failure() }} defaults: run: diff --git a/.github/workflows/modgc.yml b/.github/workflows/modgc.yml new file mode 100644 index 00000000000000..815994b395b08e --- /dev/null +++ b/.github/workflows/modgc.yml @@ -0,0 +1,178 @@ +name: ModGC +on: + push: + paths-ignore: + - 'doc/**' + - '**/man/*' + - '**.md' + - '**.rdoc' + - '**/.document' + - '.*.yml' + pull_request: + # Do not use paths-ignore for required status checks + # https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/collaborating-on-repositories-with-code-quality-features/troubleshooting-required-status-checks#handling-skipped-but-required-checks + merge_group: + +concurrency: + group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }} + cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }} + +permissions: + contents: read + +jobs: + check: + strategy: + matrix: + gc: + - name: default + - name: mmtk + mmtk_build: release + os: [macos-latest, ubuntu-latest] + include: + - test_task: check + fail-fast: false + + env: + GITPULLOPTIONS: --no-tags origin ${{ github.ref }} + RUBY_DEBUG: ci + + runs-on: ${{ matrix.os }} + + if: >- + ${{!(false + || contains(github.event.head_commit.message, '[DOC]') + || contains(github.event.head_commit.message, 'Document') + || contains(github.event.pull_request.title, '[DOC]') + || contains(github.event.pull_request.title, 'Document') + || contains(github.event.pull_request.labels.*.name, 'Documentation') + || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]') + )}} + + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + sparse-checkout-cone-mode: false + sparse-checkout: /.github + + - name: Install libraries (macOS) + uses: ./.github/actions/setup/macos + if: ${{ contains(matrix.os, 'macos') }} + + - name: Install libraries (Ubuntu) + uses: ./.github/actions/setup/ubuntu + if: ${{ contains(matrix.os, 'ubuntu') }} + + - uses: ruby/setup-ruby@a4effe49ee8ee5b8b5091268c473a4628afb5651 # v1.245.0 + with: + ruby-version: '3.1' + bundler: none + if: ${{ contains(matrix.os, 'ubuntu') }} + + - uses: ./.github/actions/setup/directories + with: + srcdir: src + builddir: build + makeup: true + clean: true + dummy-files: false + # Set fetch-depth: 10 so that Launchable can receive commits information. + fetch-depth: 10 + + - name: make sure that kern.coredump=1 + run: | + sysctl -n kern.coredump + sudo sysctl -w kern.coredump=1 + sudo chmod -R +rwx /cores/ + if: ${{ contains(matrix.os, 'macos') }} + + - name: Delete unused SDKs + # To free up disk space to not run out during the run + run: | + sudo rm -rf ~/.dotnet + sudo rm -rf /Library/Android + sudo rm -rf /Library/Developer/CoreSimulator + continue-on-error: true + if: ${{ contains(matrix.os, 'macos') }} + + - name: Setup Ruby GC Directory + run: | + echo "MODULAR_GC_DIR=$HOME/ruby_gc" >> $GITHUB_ENV + + - name: Run configure + env: + arch: ${{ matrix.arch }} + run: >- + $SETARCH ../src/configure -C --disable-install-doc --with-modular-gc=${{ env.MODULAR_GC_DIR }} + ${arch:+--target=$arch-$OSTYPE --host=$arch-$OSTYPE} + + - uses: actions-rust-lang/setup-rust-toolchain@v1 + - name: Set MMTk environment variables + run: | + echo 'EXCLUDES=../src/test/.excludes-mmtk' >> $GITHUB_ENV + echo 'MSPECOPT=-B../src/spec/mmtk.mspec' >> $GITHUB_ENV + if: ${{ matrix.gc.name == 'mmtk' }} + + - run: $SETARCH make + + - name: Build Modular GC + run: | + echo "RUBY_GC_LIBRARY=${{ matrix.gc.name }}" >> $GITHUB_ENV + make install-modular-gc MODULAR_GC=${{ matrix.gc.name }} MMTK_BUILD=${{ matrix.gc.mmtk_build }} + make distclean-modular-gc MODULAR_GC=${{ matrix.gc.name }} + + - run: $SETARCH make hello + + - name: Set test options for skipped tests + run: | + set -x + TESTS="$(echo "${{ matrix.skipped_tests }}" | sed 's| |$$/ -n!/|g;s|^|-n!/|;s|$|$$/|')" + echo "TESTS=${TESTS}" >> $GITHUB_ENV + if: ${{ matrix.test_task == 'check' && matrix.skipped_tests }} + + - name: Set up Launchable + id: launchable + uses: ./.github/actions/launchable/setup + with: + os: ${{ matrix.os || 'ubuntu-22.04' }} + test-opts: ${{ matrix.configure }} + launchable-token: ${{ secrets.LAUNCHABLE_TOKEN }} + builddir: build + srcdir: src + continue-on-error: true + timeout-minutes: 3 + + - name: make ${{ matrix.test_task }} + run: | + test -n "${LAUNCHABLE_STDOUT}" && exec 1> >(tee "${LAUNCHABLE_STDOUT}") + test -n "${LAUNCHABLE_STDERR}" && exec 2> >(tee "${LAUNCHABLE_STDERR}") + + $SETARCH make -s ${{ matrix.test_task }} \ + ${TESTS:+TESTS="$TESTS"} \ + ${{ !contains(matrix.test_task, 'bundle') && 'RUBYOPT=-w' || '' }} + timeout-minutes: ${{ matrix.gc.timeout || 40 }} + env: + RUBY_TESTOPTS: '-q --tty=no' + TEST_BUNDLED_GEMS_ALLOW_FAILURES: '' + PRECHECK_BUNDLED_GEMS: 'no' + LAUNCHABLE_STDOUT: ${{ steps.launchable.outputs.stdout_report_path }} + LAUNCHABLE_STDERR: ${{ steps.launchable.outputs.stderr_report_path }} + + - name: make skipped tests + run: | + $SETARCH make -s test-all TESTS="${TESTS//-n!\//-n/}" + env: + GNUMAKEFLAGS: '' + RUBY_TESTOPTS: '-v --tty=no' + if: ${{ matrix.test_task == 'check' && matrix.skipped_tests }} + continue-on-error: ${{ matrix.continue-on-skipped_tests || false }} + + - uses: ./.github/actions/slack + with: + label: ${{ matrix.test_task }} ${{ matrix.configure }}${{ matrix.arch }} + SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot + if: ${{ failure() }} + +defaults: + run: + working-directory: build diff --git a/.github/workflows/parse_y.yml b/.github/workflows/parse_y.yml new file mode 100644 index 00000000000000..eb7c6c22026530 --- /dev/null +++ b/.github/workflows/parse_y.yml @@ -0,0 +1,100 @@ +name: parse.y +on: + push: + paths-ignore: + - 'doc/**' + - '**/man/*' + - '**.md' + - '**.rdoc' + - '**/.document' + - '.*.yml' + pull_request: + paths-ignore: + - 'doc/**' + - '**/man/*' + - '**.md' + - '**.rdoc' + - '**/.document' + - '.*.yml' + merge_group: + +concurrency: + group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }} + cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }} + +permissions: + contents: read + +jobs: + make: + strategy: + matrix: + include: + - test_task: check + - test_task: test-bundler-parallel + - test_task: test-bundled-gems + fail-fast: false + + env: + GITPULLOPTIONS: --no-tags origin ${{ github.ref }} + RUBY_DEBUG: ci + SETARCH: ${{ matrix.arch && format('setarch {0}', matrix.arch) }} + + runs-on: ubuntu-22.04 + + if: >- + ${{!(false + || contains(github.event.head_commit.message, '[DOC]') + || contains(github.event.head_commit.message, 'Document') + || contains(github.event.pull_request.title, '[DOC]') + || contains(github.event.pull_request.title, 'Document') + || contains(github.event.pull_request.labels.*.name, 'Documentation') + || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]') + )}} + + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + sparse-checkout-cone-mode: false + sparse-checkout: /.github + + - uses: ./.github/actions/setup/ubuntu + + - uses: ruby/setup-ruby@a4effe49ee8ee5b8b5091268c473a4628afb5651 # v1.245.0 + with: + ruby-version: '3.1' + bundler: none + + - uses: ./.github/actions/setup/directories + with: + srcdir: src + builddir: build + makeup: true + clean: true + dummy-files: ${{ matrix.test_task == 'check' }} + + - name: Run configure + run: ../src/configure -C --disable-install-doc cppflags=-DRUBY_DEBUG --with-parser=parse.y + + - run: make + + - run: make TESTRUN_SCRIPT='-e "exit !RUBY_DESCRIPTION.include?(%[+PRISM])"' run + + - name: make ${{ matrix.test_task }} + run: make -s ${{ matrix.test_task }} RUN_OPTS="$RUN_OPTS" SPECOPTS="$SPECOPTS" + env: + RUBY_TESTOPTS: ${{ matrix.testopts }} + EXCLUDES: '../src/test/.excludes-parsey' + RUN_OPTS: ${{ matrix.run_opts || '--parser=parse.y' }} + SPECOPTS: ${{ matrix.specopts || '-T --parser=parse.y' }} + TEST_BUNDLED_GEMS_ALLOW_FAILURES: '' + + - uses: ./.github/actions/slack + with: + label: ${{ matrix.run_opts }} + SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot + if: ${{ failure() }} + +defaults: + run: + working-directory: build diff --git a/.github/workflows/pr-playground.yml b/.github/workflows/pr-playground.yml new file mode 100644 index 00000000000000..cc060061421acd --- /dev/null +++ b/.github/workflows/pr-playground.yml @@ -0,0 +1,127 @@ +name: Post Playground link to PR +on: + pull_request_target: + types: [labeled] + workflow_run: + workflows: ["WebAssembly"] + types: [completed] + +jobs: + post-summary: + name: Post Playground link + runs-on: ubuntu-latest + permissions: + pull-requests: write + # Post a comment only if the PR status check is passed and the PR is labeled with `Playground`. + # Triggered twice: when the PR is labeled and when PR build is passed. + if: >- + ${{ false + || (true + && github.event_name == 'pull_request_target' + && contains(github.event.pull_request.labels.*.name, 'Playground')) + || (true + && github.event_name == 'workflow_run' + && github.event.workflow_run.conclusion == 'success' + && github.event.workflow_run.event == 'pull_request') + }} + steps: + - uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1 + with: + github-token: ${{ secrets.GITHUB_TOKEN }} + script: | + const fs = require('fs/promises'); + + const buildWorkflowPath = '.github/workflows/wasm.yml'; + const findSuccessfuBuildRun = async (pr) => { + const opts = github.rest.actions.listWorkflowRunsForRepo.endpoint.merge({ + owner: context.repo.owner, + repo: context.repo.repo, + status: 'success', + branch: pr.head.ref, + }); + const runs = await github.paginate(opts); + const buildRun = runs.find(run => run.path == buildWorkflowPath); + return buildRun; + } + + const postComment = async (body, pr) => { + const { data: comments } = await github.rest.issues.listComments({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: pr.number, + }); + + const commentOpts = { owner: context.repo.owner, repo: context.repo.repo, body: comment }; + + const existingComment = comments.find(comment => comment.body.startsWith(magicComment)); + if (existingComment) { + core.info(`Updating existing comment: ${existingComment.html_url}`); + await github.rest.issues.updateComment({ + ...commentOpts, comment_id: existingComment.id + }); + } else { + await github.rest.issues.createComment({ + ...commentOpts, issue_number: pr.number + }); + } + } + + const derivePRNumber = async () => { + if (context.payload.pull_request) { + return context.payload.pull_request.number; + } + // Workaround for https://github.com/orgs/community/discussions/25220 + + const { data: { artifacts } } = await github.rest.actions.listWorkflowRunArtifacts({ + owner: context.repo.owner, + repo: context.repo.repo, + run_id: context.payload.workflow_run.id, + }); + const artifact = artifacts.find(artifact => artifact.name == 'github-pr-info'); + if (!artifact) { + throw new Error('Cannot find github-pr-info.txt artifact'); + } + + const { data } = await github.rest.actions.downloadArtifact({ + owner: context.repo.owner, + repo: context.repo.repo, + artifact_id: artifact.id, + archive_format: 'zip', + }); + + await fs.writeFile('pr-info.zip', Buffer.from(data)); + await exec.exec('unzip', ['pr-info.zip']); + return await fs.readFile('github-pr-info.txt', 'utf8'); + } + + const prNumber = await derivePRNumber(); + + const { data: pr } = await github.rest.pulls.get({ + owner: context.repo.owner, + repo: context.repo.repo, + pull_number: prNumber, + }); + + core.info(`Checking if the PR ${prNumber} is labeled with Playground...`); + if (!pr.labels.some(label => label.name == 'Playground')) { + core.info(`The PR is not labeled with Playground.`); + return; + } + + core.info(`Checking if the build is successful for ${pr.head.ref} in ${pr.head.repo.owner.login}/${pr.head.repo.name}...`); + const buildRun = await findSuccessfuBuildRun(pr); + if (!buildRun) { + core.info(`No successful build run found for ${buildWorkflowPath} on ${pr.head.ref} yet.`); + return; + } + core.info(`Found a successful build run: ${buildRun.html_url}`); + + const runLink = `${process.env.GITHUB_SERVER_URL}/${process.env.GITHUB_REPOSITORY}/actions/runs/${process.env.GITHUB_RUN_ID}`; + const magicComment = ``; + const comment = `${magicComment} + **Try on Playground**: https://ruby.github.io/play-ruby?run=${buildRun.id} + This is an automated comment by [\`pr-playground.yml\`](${runLink}) workflow. + `; + core.info(`Comment: ${comment}`); + await postComment(comment, pr); + diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml new file mode 100644 index 00000000000000..5d4474d978f51a --- /dev/null +++ b/.github/workflows/publish.yml @@ -0,0 +1,18 @@ +name: Start release workflow +on: + push: + tags: + - '*' + +jobs: + notify: + runs-on: ubuntu-latest + steps: + - name: Build release package + run: | + curl -L -X POST \ + -H "Authorization: Bearer ${{ secrets.MATZBOT_GITHUB_WORKFLOW_TOKEN }}" \ + -H "Accept: application/vnd.github+json" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + https://api.github.com/repos/ruby/actions/dispatches \ + -d '{"event_type": "${{ github.ref }}"}' diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000000000..284e336a2942c2 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,107 @@ +name: Publish Ruby packages + +on: + repository_dispatch: + types: + - release + workflow_dispatch: + inputs: + version: + description: 'Version of the Ruby package to release' + required: true + default: '3.3.4' + +jobs: + release: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + + - uses: ruby/setup-ruby@v1 + with: + ruby-version: 3.3.4 + + - name: Store Ruby version + run: | + echo "RUBY_VERSION=${{ github.event.client_payload.version || github.event.inputs.version }}" >> $GITHUB_ENV + + - name: Store ABI version + run: echo "ABI_VERSION=$(echo ${{ env.RUBY_VERSION }} | cut -d '.' -f 1-2)" >> $GITHUB_ENV + + - name: Copy draft package `/tmp` to `/pub` directory + run: tool/release.sh ${{ env.RUBY_VERSION }} + env: + AWS_ACCESS_KEY_ID: ${{ secrets.FTP_R_L_O_AWS_ACCESS_KEY_ID }} + AWS_SECRET_ACCESS_KEY: ${{ secrets.FTP_R_L_O_AWS_SECRET_ACCESS_KEY }} + AWS_DEFAULT_REGION: us-west-2 + + - name: Purge URLs of release package + run: | + curl -X POST \ + -H "Fastly-Key: ${{ secrets.FASTLY_PURGE_TOKEN }}" \ + https://api.fastly.com/purge/cache.ruby-lang.org/pub/ruby/${{ env.ABI_VERSION }}/ruby-${{ env.RUBY_VERSION }}.tar.gz + curl -X POST \ + -H "Fastly-Key: ${{ secrets.FASTLY_PURGE_TOKEN }}" \ + https://api.fastly.com/purge/cache.ruby-lang.org/pub/ruby/${{ env.ABI_VERSION }}/ruby-${{ env.RUBY_VERSION }}.tar.xz + curl -X POST \ + -H "Fastly-Key: ${{ secrets.FASTLY_PURGE_TOKEN }}" \ + https://api.fastly.com/purge/cache.ruby-lang.org/pub/ruby/${{ env.ABI_VERSION }}/ruby-${{ env.RUBY_VERSION }}.zip + + - name: Create a release on GitHub + run: | + RELEASE_TAG=$(echo v${{ env.RUBY_VERSION }} | sed 's/\./_/g') + echo $RELEASE_TAG + PREVIOUS_RELEASE_TAG=$(echo $RELEASE_TAG | awk 'BEGIN {FS="_"; OFS="_"}{ $NF=$NF-1; print }') + echo $PREVIOUS_RELEASE_TAG + tool/gen-github-release.rb $PREVIOUS_RELEASE_TAG $RELEASE_TAG --no-dry-run + env: + GITHUB_TOKEN: ${{ secrets.MATZBOT_AUTO_UPDATE_TOKEN }} + + - name: Update versions index + run: | + curl -L -X POST \ + -H "Authorization: Bearer ${{ secrets.MATZBOT_GITHUB_WORKFLOW_TOKEN }}" \ + -H "Accept: application/vnd.github+json" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + https://api.github.com/repos/ruby/actions/dispatches \ + -d '{"event_type": "update_index"}' + + - name: Build and push Docker images + run: | + curl -L -X POST \ + -H "Authorization: Bearer ${{ secrets.MATZBOT_GITHUB_WORKFLOW_TOKEN }}" \ + -H "Accept: application/vnd.github+json" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + https://api.github.com/repos/ruby/docker-images/dispatches \ + -d '{"event_type": "build", "client_payload": {"ruby_version": "${{ env.RUBY_VERSION }}"}}' + + - name: Build snapcraft packages + run: | + curl -L -X POST \ + -H "Authorization: Bearer ${{ secrets.MATZBOT_GITHUB_WORKFLOW_TOKEN }}" \ + -H "Accept: application/vnd.github+json" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + https://api.github.com/repos/ruby/snap.ruby/dispatches \ + -d '{"event_type": "build", "client_payload": {"ruby_version": "${{ env.RUBY_VERSION }}"}}' + + - name: Store the latest LTS version of OpenSSL + run: | + echo "OPENSSL_VERSION=`curl -s https://api.github.com/repos/openssl/openssl/releases | jq -r '.[].tag_name | select(startswith("openssl-3.0"))' | sort -Vr | head -n1 | cut -d'-' -f2`" >> $GITHUB_ENV + + - name: Update ruby-build definition + run: | + curl -L -X POST \ + -H "Authorization: Bearer ${{ secrets.RUBY_BUILD_WORKFLOW_TOKEN }}" \ + -H "Accept: application/vnd.github+json" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + https://api.github.com/repos/rbenv/ruby-build/dispatches \ + -d '{"event_type": "update-ruby", "client_payload": {"ruby_version": "${{ env.RUBY_VERSION }}", "openssl_version": "${{ env.OPENSSL_VERSION }}"}}' + + - name: Update all-ruby definition + run: | + curl -L -X POST \ + -H "Authorization: Bearer ${{ secrets.MATZBOT_GITHUB_WORKFLOW_TOKEN }}" \ + -H "Accept: application/vnd.github+json" \ + -H "X-GitHub-Api-Version: 2022-11-28" \ + https://api.github.com/repos/ruby/all-ruby/dispatches \ + -d '{"event_type": "update"}' diff --git a/.github/workflows/rjit-bindgen.yml b/.github/workflows/rjit-bindgen.yml deleted file mode 100644 index 6a6769b92afc8d..00000000000000 --- a/.github/workflows/rjit-bindgen.yml +++ /dev/null @@ -1,88 +0,0 @@ -name: RJIT bindgen -on: - push: - paths-ignore: - - 'doc/**' - - '**/man' - - '**.md' - - '**.rdoc' - - '**/.document' - pull_request: - paths-ignore: - - 'doc/**' - - '**/man' - - '**.md' - - '**.rdoc' - - '**/.document' - merge_group: - paths-ignore: - - 'doc/**' - - '**/man' - - '**.md' - - '**.rdoc' - - '**/.document' - -concurrency: - group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }} - cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }} - -permissions: - contents: read - -jobs: - make: - strategy: - matrix: - include: - - task: rjit-bindgen - fail-fast: false - - runs-on: ubuntu-20.04 - - if: >- - ${{!(false - || contains(github.event.head_commit.message, '[DOC]') - || contains(github.event.pull_request.title, '[DOC]') - || contains(github.event.pull_request.labels.*.name, 'Documentation') - || (github.event_name == 'push' && github.actor == 'dependabot[bot]') - )}} - - steps: - - name: Set up Ruby - uses: ruby/setup-ruby@250fcd6a742febb1123a77a841497ccaa8b9e939 # v1.152.0 - with: - ruby-version: '3.1' - - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 - with: - sparse-checkout-cone-mode: false - sparse-checkout: /.github - - - uses: ./.github/actions/setup/ubuntu - - - uses: ./.github/actions/setup/directories - with: - srcdir: src - builddir: build - makeup: true - - - name: Run configure - run: ../src/configure -C --disable-install-doc --prefix=$(pwd)/install --enable-yjit=dev_nodebug - - - run: make - - - run: make install - - - run: make ${{ matrix.task }} - - - run: git diff --exit-code - working-directory: src - - - uses: ./.github/actions/slack - with: - SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot - if: ${{ failure() && github.event_name == 'push' }} - -defaults: - run: - working-directory: build diff --git a/.github/workflows/rjit.yml b/.github/workflows/rjit.yml deleted file mode 100644 index 66a6805abce2b1..00000000000000 --- a/.github/workflows/rjit.yml +++ /dev/null @@ -1,117 +0,0 @@ -name: RJIT -on: - push: - paths-ignore: - - 'doc/**' - - '**.md' - - '**.rdoc' - - '**/.document' - - '**.[1-8]' - - '**.ronn' - pull_request: - paths-ignore: - - 'doc/**' - - '**.md' - - '**.rdoc' - - '**/.document' - - '**.[1-8]' - - '**.ronn' - merge_group: - paths-ignore: - - 'doc/**' - - '**.md' - - '**.rdoc' - - '**/.document' - - '**.[1-8]' - - '**.ronn' - -concurrency: - group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }} - cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }} - -permissions: - contents: read - -jobs: - make: - strategy: - matrix: - # main variables included in the job name - test_task: [check] - run_opts: ['--rjit-call-threshold=1'] - arch: [''] - fail-fast: false - - env: - GITPULLOPTIONS: --no-tags origin ${{ github.ref }} - RUBY_DEBUG: ci - SETARCH: ${{ matrix.arch && format('setarch {0}', matrix.arch) }} - - runs-on: ubuntu-22.04 - - if: >- - ${{!(false - || contains(github.event.head_commit.message, '[DOC]') - || contains(github.event.pull_request.title, '[DOC]') - || contains(github.event.pull_request.labels.*.name, 'Documentation') - || (github.event_name == 'push' && github.actor == 'dependabot[bot]') - )}} - - steps: - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 - with: - sparse-checkout-cone-mode: false - sparse-checkout: /.github - - - uses: ./.github/actions/setup/ubuntu - - - uses: ./.github/actions/setup/directories - with: - srcdir: src - builddir: build - makeup: true - - - name: Run configure - env: - arch: ${{ matrix.arch }} - run: >- - $SETARCH ../src/configure -C --disable-install-doc cppflags=-DRUBY_DEBUG - ${arch:+--target=$arch-$OSTYPE --host=$arch-$OSTYPE} - - - run: $SETARCH make - - - name: make test - run: | - $SETARCH make -s test RUN_OPTS="$RUN_OPTS" - timeout-minutes: 30 - env: - GNUMAKEFLAGS: '' - RUBY_TESTOPTS: '-v --tty=no' - RUN_OPTS: ${{ matrix.run_opts }} - - - name: make test-all - run: | - $SETARCH make -s test-all RUN_OPTS="$RUN_OPTS" - timeout-minutes: 40 - env: - GNUMAKEFLAGS: '' - RUBY_TESTOPTS: '-q --tty=no' - RUN_OPTS: ${{ matrix.run_opts }} - - - name: make test-spec - run: | - $SETARCH make -s test-spec RUN_OPTS="$RUN_OPTS" - timeout-minutes: 10 - env: - GNUMAKEFLAGS: '' - RUN_OPTS: ${{ matrix.run_opts }} - - - uses: ./.github/actions/slack - with: - label: ${{ matrix.run_opts }} - SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot - if: ${{ failure() && github.event_name == 'push' }} - -defaults: - run: - working-directory: build diff --git a/.github/workflows/scorecards.yml b/.github/workflows/scorecards.yml index c6a4110af1b994..8cc7e00c47ec26 100644 --- a/.github/workflows/scorecards.yml +++ b/.github/workflows/scorecards.yml @@ -2,7 +2,7 @@ # by a third-party and are governed by separate terms of service, privacy # policy, and support documentation. -name: Scorecards supply-chain security +name: Scorecard supply-chain security on: # For Branch-Protection check. Only the default branch is supported. See # https://github.com/ossf/scorecard/blob/main/docs/checks.md#branch-protection @@ -10,7 +10,7 @@ on: # To guarantee Maintained check is occasionally updated. See # https://github.com/ossf/scorecard/blob/main/docs/checks.md#maintained schedule: - - cron: '22 4 * * 2' + - cron: '39 3 * * 5' # push: # branches: [ "master" ] @@ -19,8 +19,10 @@ permissions: read-all jobs: analysis: - name: Scorecards analysis + name: Scorecard analysis runs-on: ubuntu-latest + # `publish_results: true` only works when run from the default branch. conditional can be removed if disabled. + if: github.event.repository.default_branch == github.ref_name || github.event_name == 'pull_request' permissions: # Needed to upload the results to code-scanning dashboard. security-events: write @@ -31,21 +33,21 @@ jobs: # actions: read steps: - - name: 'Checkout code' - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + - name: "Checkout code" + uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: persist-credentials: false - - name: 'Run analysis' - uses: ossf/scorecard-action@08b4669551908b1024bb425080c797723083c031 # v2.2.0 + - name: "Run analysis" + uses: ossf/scorecard-action@05b42c624433fc40578a4040d5cf5e36ddca8cde # v2.4.2 with: results_file: results.sarif results_format: sarif - # (Optional) Read-only PAT token. Uncomment the `repo_token` line below if: + # (Optional) "write" PAT token. Uncomment the `repo_token` line below if: # - you want to enable the Branch-Protection check on a *public* repository, or - # - you are installing Scorecards on a *private* repository - # To create the PAT, follow the steps in https://github.com/ossf/scorecard-action#authentication-with-pat. - repo_token: ${{ secrets.SCORECARD_READ_TOKEN }} + # - you are installing Scorecard on a *private* repository + # To create the PAT, follow the steps in https://github.com/ossf/scorecard-action?tab=readme-ov-file#authentication-with-fine-grained-pat-optional. + # repo_token: ${{ secrets.SCORECARD_TOKEN }} # Public repositories: # - Publish results to OpenSSF REST API for easy access by consumers @@ -56,17 +58,21 @@ jobs: # of the value entered here. publish_results: true + # (Optional) Uncomment file_mode if you have a .gitattributes with files marked export-ignore + # file_mode: git + # Upload the results as artifacts (optional). Commenting out will disable uploads of run results in SARIF # format to the repository Actions tab. - # - name: "Upload artifact" - # uses: actions/upload-artifact@0b7f8abb1508181956e8e162db84b466c27e18ce # v3.1.2 - # with: - # name: SARIF file - # path: results.sarif - # retention-days: 5 + - name: "Upload artifact" + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + with: + name: SARIF file + path: results.sarif + retention-days: 5 - # Upload the results to GitHub's code scanning dashboard. - - name: 'Upload to code-scanning' - uses: github/codeql-action/upload-sarif@cdcdbb579706841c47f7063dda365e292e5cad7a # v2.1.27 + # Upload the results to GitHub's code scanning dashboard (optional). + # Commenting out will disable upload of results to your repo's Code Scanning dashboard + - name: "Upload to code-scanning" + uses: github/codeql-action/upload-sarif@v3 with: sarif_file: results.sarif diff --git a/.github/workflows/spec_guards.yml b/.github/workflows/spec_guards.yml index 77677c98596807..d723abde21ab69 100644 --- a/.github/workflows/spec_guards.yml +++ b/.github/workflows/spec_guards.yml @@ -3,16 +3,15 @@ name: Rubyspec Version Guards Check on: push: paths: + - '.github/workflows/spec_guards.yml' - 'spec/**' - '!spec/*.md' pull_request: - paths-ignore: + paths: + - '.github/workflows/spec_guards.yml' - 'spec/**' - '!spec/*.md' merge_group: - paths-ignore: - - 'spec/**' - - '!spec/*.md' concurrency: group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }} @@ -25,14 +24,16 @@ jobs: rubyspec: name: Rubyspec - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 if: >- ${{!(false || contains(github.event.head_commit.message, '[DOC]') + || contains(github.event.head_commit.message, 'Document') || contains(github.event.pull_request.title, '[DOC]') + || contains(github.event.pull_request.title, 'Document') || contains(github.event.pull_request.labels.*.name, 'Documentation') - || (github.event_name == 'push' && github.actor == 'dependabot[bot]') + || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]') )}} strategy: @@ -40,14 +41,14 @@ jobs: # Specs from ruby/spec should still run on all supported Ruby versions. # This also ensures the needed ruby_version_is guards are there, see spec/README.md. ruby: - - ruby-3.0 - - ruby-3.1 - ruby-3.2 + - ruby-3.3 + - ruby-3.4 steps: - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 - - uses: ruby/setup-ruby@250fcd6a742febb1123a77a841497ccaa8b9e939 # v1.152.0 + - uses: ruby/setup-ruby@a4effe49ee8ee5b8b5091268c473a4628afb5651 # v1.245.0 with: ruby-version: ${{ matrix.ruby }} bundler: none @@ -63,4 +64,4 @@ jobs: with: label: ${{ matrix.ruby }} SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot - if: ${{ failure() && github.event_name == 'push' }} + if: ${{ failure() }} diff --git a/.github/workflows/ubuntu.yml b/.github/workflows/ubuntu.yml index 66b0228102c023..3005809b08c475 100644 --- a/.github/workflows/ubuntu.yml +++ b/.github/workflows/ubuntu.yml @@ -3,24 +3,15 @@ on: push: paths-ignore: - 'doc/**' - - '**/man' + - '**/man/*' - '**.md' - '**.rdoc' - '**/.document' + - '.*.yml' pull_request: - paths-ignore: - - 'doc/**' - - '**/man' - - '**.md' - - '**.rdoc' - - '**/.document' + # Do not use paths-ignore for required status checks + # https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/collaborating-on-repositories-with-code-quality-features/troubleshooting-required-status-checks#handling-skipped-but-required-checks merge_group: - paths-ignore: - - 'doc/**' - - '**/man' - - '**.md' - - '**.rdoc' - - '**/.document' concurrency: group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }} @@ -33,38 +24,42 @@ jobs: make: strategy: matrix: - test_task: [check] - arch: [''] - configure: ['cppflags=-DVM_CHECK_MODE'] - # specifying everything else with `include` to avoid redundant tests include: + - test_task: check + configure: 'cppflags=-DVM_CHECK_MODE' - test_task: check arch: i686 + - test_task: check + configure: '--disable-yjit' - test_task: check configure: '--enable-shared --enable-load-relative' - - test_task: test-all TESTS=--repeat-count=2 - - test_task: test-all TESTS=--repeat-count=2 - configure: 'cppflags=-DUNIVERSAL_PARSER' - test_task: test-bundler-parallel + timeout: 50 - test_task: test-bundled-gems + - test_task: check + os: ubuntu-24.04 + - test_task: check + os: ubuntu-24.04-arm fail-fast: false env: GITPULLOPTIONS: --no-tags origin ${{ github.ref }} RUBY_DEBUG: ci - runs-on: ubuntu-20.04 + runs-on: ${{ matrix.os || 'ubuntu-22.04' }} if: >- ${{!(false || contains(github.event.head_commit.message, '[DOC]') + || contains(github.event.head_commit.message, 'Document') || contains(github.event.pull_request.title, '[DOC]') + || contains(github.event.pull_request.title, 'Document') || contains(github.event.pull_request.labels.*.name, 'Documentation') - || (github.event_name == 'push' && github.actor == 'dependabot[bot]') + || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]') )}} steps: - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: sparse-checkout-cone-mode: false sparse-checkout: /.github @@ -73,11 +68,21 @@ jobs: with: arch: ${{ matrix.arch }} + - uses: ruby/setup-ruby@a4effe49ee8ee5b8b5091268c473a4628afb5651 # v1.245.0 + with: + ruby-version: '3.1' + bundler: none + if: ${{ !endsWith(matrix.os, 'arm') }} + - uses: ./.github/actions/setup/directories with: srcdir: src builddir: build makeup: true + clean: true + dummy-files: ${{ matrix.test_task == 'check' }} + # Set fetch-depth: 10 so that Launchable can receive commits information. + fetch-depth: 10 - name: Run configure env: @@ -92,38 +97,71 @@ jobs: - run: $SETARCH make - - name: Create dummy files in build dir + - run: $SETARCH make hello + + - name: runirb run: | - $SETARCH ./miniruby -e '(("a".."z").to_a+("A".."Z").to_a+("0".."9").to_a+%w[foo bar test zzz]).each{|basename|File.write("#{basename}.rb", "raise %(do not load #{basename}.rb)")}' - if: ${{ matrix.test_task == 'check' }} + echo IRB::VERSION | $SETARCH make runirb RUNOPT="-- -f" + + - name: Set test options for skipped tests + run: | + set -x + TESTS="$(echo "${{ matrix.skipped_tests }}" | sed 's| |$$/ -n!/|g;s|^|-n!/|;s|$|$$/|')" + echo "TESTS=${TESTS}" >> $GITHUB_ENV + if: ${{ matrix.test_task == 'check' && matrix.skipped_tests }} + + - name: Set up Launchable + id: launchable + uses: ./.github/actions/launchable/setup + with: + os: ${{ matrix.os || 'ubuntu-22.04' }} + test-opts: ${{ matrix.configure }} + launchable-token: ${{ secrets.LAUNCHABLE_TOKEN }} + builddir: build + srcdir: src + continue-on-error: true + timeout-minutes: 3 - name: make ${{ matrix.test_task }} - run: >- - $SETARCH make -s ${{ matrix.test_task }} - ${TESTS:+TESTS=`echo "$TESTS" | sed 's| |$$/ -n!/|g;s|^|-n!/|;s|$|$$/|'`} - ${{ contains(matrix.test_task, 'bundle') && '' || 'RUBYOPT=-w' }} - timeout-minutes: 40 + run: | + test -n "${LAUNCHABLE_STDOUT}" && exec 1> >(tee "${LAUNCHABLE_STDOUT}") + test -n "${LAUNCHABLE_STDERR}" && exec 2> >(tee "${LAUNCHABLE_STDERR}") + + $SETARCH make -s ${{ matrix.test_task }} \ + ${TESTS:+TESTS="$TESTS"} \ + ${{ !contains(matrix.test_task, 'bundle') && 'RUBYOPT=-w' || '' }} + timeout-minutes: ${{ matrix.timeout || 40 }} env: RUBY_TESTOPTS: '-q --tty=no' - TESTS: ${{ matrix.test_task == 'check' && matrix.skipped_tests || '' }} TEST_BUNDLED_GEMS_ALLOW_FAILURES: '' PRECHECK_BUNDLED_GEMS: 'no' + LAUNCHABLE_STDOUT: ${{ steps.launchable.outputs.stdout_report_path }} + LAUNCHABLE_STDERR: ${{ steps.launchable.outputs.stderr_report_path }} - name: make skipped tests run: | - $SETARCH make -s test-all TESTS=`echo "$TESTS" | sed 's| |$$/ -n/|g;s|^|-n/|;s|$|$$/|'` + $SETARCH make -s test-all TESTS="${TESTS//-n!\//-n/}" env: GNUMAKEFLAGS: '' RUBY_TESTOPTS: '-v --tty=no' - TESTS: ${{ matrix.skipped_tests }} - if: ${{ matrix.test_task == 'check' && matrix.skipped_tests != '' }} + if: ${{ matrix.test_task == 'check' && matrix.skipped_tests }} continue-on-error: ${{ matrix.continue-on-skipped_tests || false }} - uses: ./.github/actions/slack with: label: ${{ matrix.test_task }} ${{ matrix.configure }}${{ matrix.arch }} SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot - if: ${{ failure() && github.event_name == 'push' }} + if: ${{ failure() }} + + result: + if: ${{ always() }} + name: ${{ github.workflow }} result + runs-on: ubuntu-latest + needs: [make] + steps: + - run: exit 1 + working-directory: + if: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }} defaults: run: diff --git a/.github/workflows/wasm.yml b/.github/workflows/wasm.yml index 3be9bf8d1ed380..2c49d990719637 100644 --- a/.github/workflows/wasm.yml +++ b/.github/workflows/wasm.yml @@ -3,24 +3,20 @@ on: push: paths-ignore: - 'doc/**' - - '**/man' + - '**/man/*' - '**.md' - '**.rdoc' - '**/.document' + - '.*.yml' pull_request: paths-ignore: - 'doc/**' - - '**/man' + - '**/man/*' - '**.md' - '**.rdoc' - '**/.document' + - '.*.yml' merge_group: - paths-ignore: - - 'doc/**' - - '**/man' - - '**.md' - - '**.rdoc' - - '**/.document' concurrency: group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }} @@ -47,23 +43,25 @@ jobs: env: RUBY_TESTOPTS: '-q --tty=no' GITPULLOPTIONS: --no-tags origin ${{ github.ref }} - WASI_SDK_VERSION_MAJOR: 14 + WASI_SDK_VERSION_MAJOR: 25 WASI_SDK_VERSION_MINOR: 0 - BINARYEN_VERSION: 109 - WASMTIME_VERSION: v0.33.0 + BINARYEN_VERSION: 113 + WASMTIME_VERSION: v15.0.0 - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 if: >- ${{!(false || contains(github.event.head_commit.message, '[DOC]') + || contains(github.event.head_commit.message, 'Document') || contains(github.event.pull_request.title, '[DOC]') + || contains(github.event.pull_request.title, 'Document') || contains(github.event.pull_request.labels.*.name, 'Documentation') - || (github.event_name == 'push' && github.actor == 'dependabot[bot]') + || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]') )}} steps: - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: sparse-checkout-cone-mode: false sparse-checkout: /.github @@ -80,7 +78,7 @@ jobs: sudo apt-get update -q || : sudo apt-get install --no-install-recommends -q -y ruby make autoconf git wget - wasi_sdk_deb="wasi-sdk_${WASI_SDK_VERSION_MAJOR}.${WASI_SDK_VERSION_MINOR}_amd64.deb" + wasi_sdk_deb="wasi-sdk-${WASI_SDK_VERSION_MAJOR}.${WASI_SDK_VERSION_MINOR}-x86_64-linux.deb" wget "https://github.com/WebAssembly/wasi-sdk/releases/download/wasi-sdk-${WASI_SDK_VERSION_MAJOR}/${wasi_sdk_deb}" sudo dpkg -i "$wasi_sdk_deb" rm -f "$wasi_sdk_deb" @@ -102,11 +100,33 @@ jobs: run: | echo "WASI_SDK_PATH=/opt/wasi-sdk" >> $GITHUB_ENV + - uses: ruby/setup-ruby@a4effe49ee8ee5b8b5091268c473a4628afb5651 # v1.245.0 + with: + ruby-version: '3.1' + bundler: none + + - name: Build baseruby + run: | + set -ex + mkdir ../baseruby + pushd ../baseruby + ../src/configure --prefix=$PWD/install + make + make install + + - name: Download config.guess with wasi version + run: | + rm tool/config.guess tool/config.sub + ruby tool/downloader.rb -d tool -e gnu config.guess config.sub + working-directory: src + - name: Run configure run: | ../src/configure \ --host wasm32-unknown-wasi \ + --with-baseruby=$PWD/../baseruby/install/bin/ruby \ --with-static-linked-ext \ + --with-ext=cgi/escape,continuation,coverage,date,digest/bubblebabble,digest,digest/md5,digest/rmd160,digest/sha1,digest/sha2,etc,fcntl,json,json/generator,json/parser,objspace,pathname,rbconfig/sizeof,ripper,stringio,strscan,monitor \ LDFLAGS=" \ -Xlinker --stack-first \ -Xlinker -z -Xlinker stack-size=16777216 \ @@ -118,6 +138,18 @@ jobs: # miniruby may not be built when cross-compling - run: make mini ruby + - run: make install DESTDIR=$PWD/../install + - run: tar cfz ../install.tar.gz -C ../install . + + - name: Upload artifacts + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + with: + name: ruby-wasm-install + path: ${{ github.workspace }}/install.tar.gz + - name: Show Playground URL to try the build + run: | + echo "Try on Playground: https://ruby.github.io/play-ruby?run=$GITHUB_RUN_ID" >> $GITHUB_STEP_SUMMARY + - name: Run basictest run: wasmtime run ./../build/miniruby --mapdir /::./ -- basictest/test.rb working-directory: src @@ -132,7 +164,17 @@ jobs: with: label: ${{ matrix.entry.name }} SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot - if: ${{ failure() && github.event_name == 'push' }} + if: ${{ failure() }} + + # Workaround for https://github.com/orgs/community/discussions/25220 + - name: Save Pull Request number + if: ${{ github.event_name == 'pull_request' }} + run: echo "${{ github.event.pull_request.number }}" >> ${{ github.workspace }}/github-pr-info.txt + - uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2 + if: ${{ github.event_name == 'pull_request' }} + with: + name: github-pr-info + path: ${{ github.workspace }}/github-pr-info.txt defaults: run: diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml index 71209a5c9c48a3..47e3f53241eafb 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml @@ -3,24 +3,15 @@ on: push: paths-ignore: - 'doc/**' - - '**/man' + - '**/man/*' - '**.md' - '**.rdoc' - '**/.document' + - '.*.yml' pull_request: - paths-ignore: - - 'doc/**' - - '**/man' - - '**.md' - - '**.rdoc' - - '**/.document' + # Do not use paths-ignore for required status checks + # https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/collaborating-on-repositories-with-code-quality-features/troubleshooting-required-status-checks#handling-skipped-but-required-checks merge_group: - paths-ignore: - - 'doc/**' - - '**/man' - - '**.md' - - '**.rdoc' - - '**/.document' concurrency: group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }} @@ -34,150 +25,193 @@ jobs: strategy: matrix: include: - - vs: 2019 - - vs: 2022 + - os: 2022 + vc: 2022 + test_task: check + - os: 2025 + vc: 2022 + test_task: check + - os: 11-arm + test_task: 'btest test-basic test-tool' # check and test-spec are broken yet. + target: arm64 + - os: 2025 + vc: 2022 + test_task: test-bundled-gems fail-fast: false - runs-on: windows-${{ matrix.vs < 2022 && '2019' || matrix.vs }} + runs-on: windows-${{ matrix.os < 2022 && '2019' || matrix.os }} if: >- ${{!(false || contains(github.event.head_commit.message, '[DOC]') + || contains(github.event.head_commit.message, 'Document') || contains(github.event.pull_request.title, '[DOC]') + || contains(github.event.pull_request.title, 'Document') || contains(github.event.pull_request.labels.*.name, 'Documentation') - || (github.event_name == 'push' && github.actor == 'dependabot[bot]') + || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]') )}} - name: VisualStudio ${{ matrix.vs }} + name: Windows ${{ matrix.os }}/Visual C++ ${{ matrix.vc }} (${{ matrix.test_task }}) env: GITPULLOPTIONS: --no-tags origin ${{ github.ref }} - OS_VER: windows-${{ matrix.vs < 2022 && '2019' || matrix.vs }} - # FIXME: This is a workaround for the vcpkg's issue present as of openssl 3.1.1 - # where OpenSSL's default modules directory is incorrectly set to C:\vcpkg\packages\openssl_x64-windows\bin - # cf. https://github.com/ruby/openssl/pull/635#issuecomment-1596833720 - OPENSSL_MODULES: C:\vcpkg\installed\x64-windows\bin + VCPKG_DEFAULT_TRIPLET: ${{ matrix.target || 'x64' }}-windows steps: - run: md build working-directory: - - name: find tools - id: find-tools - run: | - ::- find needed tools - set NEEDS= - for %%I in (patch.exe) do if "%%~$PATH:I" == "" ( - echo NEEDS=%NEEDS% %%I - ) else ( - echo %%I: %%~$PATH:I - ) - echo needs=%NEEDS% >> %GITHUB_OUTPUT% - - - uses: msys2/setup-msys2@d40200dc2db4c351366b048a9565ad82919e1c24 # v2 - id: setup-msys2 + - uses: ruby/setup-ruby@a4effe49ee8ee5b8b5091268c473a4628afb5651 # v1.245.0 with: - update: true - install: >- - ${{ steps.find-patch.outputs.needs }} - if: ${{ steps.find-patch.outputs.needs != '' }} + # windows-11-arm has only 3.4.1, 3.4.2, 3.4.3, head + ruby-version: ${{ !endsWith(matrix.os, 'arm') && '3.1' || '3.4' }} + bundler: none + windows-toolchain: none - - uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3.3.1 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: - path: C:\vcpkg\downloads - key: ${{ runner.os }}-vcpkg-download-${{ env.OS_VER }}-${{ github.sha }} - restore-keys: | - ${{ runner.os }}-vcpkg-download-${{ env.OS_VER }}- - ${{ runner.os }}-vcpkg-download- + sparse-checkout-cone-mode: false + sparse-checkout: /.github - - uses: actions/cache@88522ab9f39a2ea568f7027eddc7d8d8bc9d59c8 # v3.3.1 + - uses: ./.github/actions/setup/directories with: - path: C:\vcpkg\installed - key: ${{ runner.os }}-vcpkg-installed-${{ env.OS_VER }}-${{ github.sha }} - restore-keys: | - ${{ runner.os }}-vcpkg-installed-${{ env.OS_VER }}- - ${{ runner.os }}-vcpkg-installed- - - - name: Install libraries with vcpkg - run: | - vcpkg --triplet x64-windows install libffi libyaml openssl readline zlib + srcdir: src + builddir: build - - name: Install libraries with scoop + - name: Install tools with scoop run: | - iex "& {$(irm get.scoop.sh)} -RunAsAdmin" + Set-ExecutionPolicy -ExecutionPolicy RemoteSigned -Scope CurrentUser + iwr -useb get.scoop.sh | iex Join-Path (Resolve-Path ~).Path "scoop\shims" >> $Env:GITHUB_PATH + scoop install vcpkg uutils-coreutils cmake@3.31.6 shell: pwsh - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + - name: Restore vcpkg artifact + uses: actions/cache/restore@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 with: - sparse-checkout-cone-mode: false - sparse-checkout: /.github + path: src\vcpkg_installed + key: windows-${{ matrix.os }}-vcpkg-${{ hashFiles('src/vcpkg.json') }} - - uses: ./.github/actions/setup/directories + - name: Install libraries with vcpkg + run: | + vcpkg install --vcpkg-root=C:\Users\runneradmin\scoop\apps\vcpkg\current + working-directory: src + + - name: Save vcpkg artifact + uses: actions/cache/save@5a3ec84eff668545956fd18022155c47e93e2684 # v4.2.3 with: - srcdir: src - builddir: build + path: src\vcpkg_installed + key: windows-${{ matrix.os }}-vcpkg-${{ hashFiles('src/vcpkg.json') }} - name: setup env + # Available Ruby versions: https://github.com/actions/runner-images/blob/main/images/windows/Windows2019-Readme.md#ruby # %TEMP% is inconsistent with %TMP% and test-all expects they are consistent. # https://github.com/actions/virtual-environments/issues/712#issuecomment-613004302 run: | - set VS=${{ matrix.vs }} - set VCVARS=${{ matrix.vcvars || '' }} - if not "%VCVARS%" == "" goto :vcset - set VCVARS="C:\Program Files (x86)\Microsoft Visual Studio\%VS%\Enterprise\VC\Auxiliary\Build\vcvars64.bat" - if not exist %VCVARS% set VCVARS="C:\Program Files\Microsoft Visual Studio\%VS%\Enterprise\VC\Auxiliary\Build\vcvars64.bat" - :vcset - set | C:\msys64\usr\bin\sort > old.env - call %VCVARS% + ::- Set up VC ${{ matrix.vc }} + set | uutils sort > old.env + call ..\src\win32\vssetup.cmd ^ + -arch=${{ matrix.target || 'amd64' }} ^ + ${{ matrix.vcvars && '-vcvars_ver=' || '' }}${{ matrix.vcvars }} nmake -f nul set TMP=%USERPROFILE%\AppData\Local\Temp set TEMP=%USERPROFILE%\AppData\Local\Temp set MAKEFLAGS=l set /a TEST_JOBS=(15 * %NUMBER_OF_PROCESSORS% / 10) > nul - set | C:\msys64\usr\bin\sort > new.env - C:\msys64\usr\bin\comm -13 old.env new.env >> %GITHUB_ENV% + set RUBY_OPT_DIR=%GITHUB_WORKSPACE:\=/%/src/vcpkg_installed/%VCPKG_DEFAULT_TRIPLET% + set | uutils sort > new.env + uutils comm -13 old.env new.env >> %GITHUB_ENV% del *.env + - name: baseruby version + run: ruby -v + - name: compiler version run: cl - - name: link libraries - run: | - for %%I in (C:\vcpkg\installed\x64-windows\bin\*.dll) do ( - if not %%~nI == readline mklink %%~nxI %%I - ) - for %%I in (libcrypto-1_1-x64 libssl-1_1-x64) do ( - ren c:\Windows\System32\%%I.dll %%I.dll_ - ) + - name: volume info + run: Get-Volume + shell: pwsh + # TODO: We should use `../src` instead of `D:/a/ruby/ruby/src` - name: Configure run: >- ../src/win32/configure.bat --disable-install-doc - --with-opt-dir=C:/vcpkg/installed/x64-windows + --with-opt-dir=%RUBY_OPT_DIR% + --with-gmp + + - run: nmake prepare-vcpkg - run: nmake incs - run: nmake extract-extlibs - - run: nmake + # On all other platforms, test-spec depending on extract-gems (in common.mk) is enough. + # But not for this Visual Studio workflow. So here we extract gems before building. + - run: nmake extract-gems - - run: nmake test - timeout-minutes: 5 + # windows-11-arm runner cannot run `ruby tool/file2lastrev.rb --revision.h --output=revision.h` + - name: make revision.h + run: | + if not exist revision.h ( + for /f "tokens=1-3" %%I in ('git log -1 "--date=format-local:%%F %%T" "--format=%%H %%cd" @') do ( + set rev=%%I + set dt=%%J + set tm=%%K + ) + call set yy=%%dt:~0,4%% + call set /a mm=100%%dt:~5,2%% %%%% 100 + call set /a dd=100%%dt:~8,2%% %%%% 100 + call set branch=%%GITHUB_REF:refs/heads/=%% + ( + call echo #define RUBY_REVISION "%%rev:~,10%%" + call echo #define RUBY_FULL_REVISION "%%rev%%" + call echo #define RUBY_BRANCH_NAME "%%branch%%" + call echo #define RUBY_RELEASE_DATETIME "%%dt%%T%%tm%%" + call echo #define RUBY_RELEASE_YEAR %%yy%% + call echo #define RUBY_RELEASE_MONTH %%mm%% + call echo #define RUBY_RELEASE_DAY %%dd%% + ) > revision.h + copy /y NUL .revision.time + ) + type revision.h + env: + TZ: UTC - - run: nmake test-spec - timeout-minutes: 10 + - run: nmake - - run: nmake test-all + - name: Set up Launchable + uses: ./.github/actions/launchable/setup + with: + os: windows-${{ matrix.os < 2022 && '2019' || matrix.os }} + launchable-token: ${{ secrets.LAUNCHABLE_TOKEN }} + builddir: build + srcdir: src + test-task: ${{ matrix.test_task || 'check' }} + continue-on-error: true + if: ${{ matrix.test_task != 'test-bundled-gems' }} + timeout-minutes: 3 + + - run: nmake ${{ matrix.test_task || 'check' }} env: - RUBY_TESTOPTS: -j${{ env.TEST_JOBS || 4 }} --job-status=normal - timeout-minutes: 60 + RUBY_TESTOPTS: -j${{ env.TEST_JOBS || 4 }} + timeout-minutes: 70 - uses: ./.github/actions/slack with: - label: VS${{ matrix.vs }} / ${{ matrix.test_task || 'check' }} + label: Windows ${{ matrix.os }} / VC ${{ matrix.vc }} / ${{ matrix.test_task || 'check' }} SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot - if: ${{ failure() && github.event_name == 'push' }} + if: ${{ failure() }} + + result: + if: ${{ always() }} + name: ${{ github.workflow }} result + runs-on: windows-latest + needs: [make] + steps: + - run: exit 1 + working-directory: + if: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }} defaults: run: diff --git a/.github/workflows/wsl.yml b/.github/workflows/wsl.yml new file mode 100644 index 00000000000000..af490dffd74d1b --- /dev/null +++ b/.github/workflows/wsl.yml @@ -0,0 +1,72 @@ +name: Ubuntu on WSL + +on: + push: + paths-ignore: + - 'doc/**' + - '**/man/*' + - '**.md' + - '**.rdoc' + - '**/.document' + - '.*.yml' + pull_request: + # Do not use paths-ignore for required status checks + # https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/collaborating-on-repositories-with-code-quality-features/troubleshooting-required-status-checks#handling-skipped-but-required-checks + merge_group: + +jobs: + wsl: + runs-on: windows-2025 + + if: >- + ${{!(false + || contains(github.event.head_commit.message, '[DOC]') + || contains(github.event.head_commit.message, 'Document') + || contains(github.event.pull_request.title, '[DOC]') + || contains(github.event.pull_request.title, 'Document') + || contains(github.event.pull_request.labels.*.name, 'Documentation') + || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]') + )}} + + steps: + - name: Install or update WSL + uses: Ubuntu/WSL/.github/actions/wsl-install@main + with: + distro: Ubuntu-24.04 + + - name: Install dependencies + uses: Ubuntu/WSL/.github/actions/wsl-bash@main + with: + distro: Ubuntu-24.04 + working-dir: /tmp/github/ + exec: | + DEBIAN_FRONTEND=noninteractive sudo apt update + DEBIAN_FRONTEND=noninteractive sudo apt install -y ruby build-essential autoconf libssl-dev libyaml-dev zlib1g-dev libgmp-dev libffi-dev + + - name: Check out the repository + uses: Ubuntu/WSL/.github/actions/wsl-checkout@main + with: + distro: Ubuntu-24.04 + working-dir: /tmp/github/ + submodules: true + + - name: Build + uses: Ubuntu/WSL/.github/actions/wsl-bash@main + with: + distro: Ubuntu-24.04 + working-dir: /tmp/github/ + exec: | + ./autogen.sh + ./configure --disable-install-doc + make ruby -j4 + make extract-gems + make -j4 + + - name: Test + uses: Ubuntu/WSL/.github/actions/wsl-bash@main + with: + distro: Ubuntu-24.04 + working-dir: /tmp/github/ + exec: | + ./ruby -v + # make check TESTS="-j4" MSPECOPT="-j" diff --git a/.github/workflows/yjit-macos.yml b/.github/workflows/yjit-macos.yml new file mode 100644 index 00000000000000..60139257af306c --- /dev/null +++ b/.github/workflows/yjit-macos.yml @@ -0,0 +1,192 @@ +name: YJIT macOS Arm64 +on: + push: + branches: + - master + paths-ignore: + - 'doc/**' + - '**/man/*' + - '**.md' + - '**.rdoc' + - '**/.document' + - '.*.yml' + pull_request: + types: + - opened + - synchronize + - reopened + # Do not use paths-ignore for required status checks + # https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/collaborating-on-repositories-with-code-quality-features/troubleshooting-required-status-checks#handling-skipped-but-required-checks + merge_group: + +concurrency: + group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }} + cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }} + +permissions: + contents: read + +jobs: + cargo: + name: cargo test + + runs-on: macos-14 + + if: >- + ${{!(false + || contains(github.event.head_commit.message, '[DOC]') + || contains(github.event.head_commit.message, 'Document') + || contains(github.event.pull_request.title, '[DOC]') + || contains(github.event.pull_request.title, 'Document') + || contains(github.event.pull_request.labels.*.name, 'Documentation') + || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]') + )}} + + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + + - run: RUST_BACKTRACE=1 cargo test + working-directory: yjit + + # Also compile and test with all features enabled + - run: RUST_BACKTRACE=1 cargo test --all-features + working-directory: yjit + + # Check that we can build in release mode too + - run: cargo build --release + working-directory: yjit + + make: + strategy: + matrix: + include: + - test_task: 'check' + configure: '--enable-yjit' + yjit_opts: '--yjit' + - test_task: 'check' + configure: '--enable-yjit=dev' + yjit_opts: '--yjit-call-threshold=1 --yjit-verify-ctx --yjit-code-gc' + specopts: '-T --yjit-call-threshold=1 -T --yjit-verify-ctx -T --yjit-code-gc' + fail-fast: false + + env: + GITPULLOPTIONS: --no-tags origin ${{ github.ref }} + RUN_OPTS: ${{ matrix.yjit_opts }} + SPECOPTS: ${{ matrix.specopts }} + + runs-on: macos-14 + + if: >- + ${{!(false + || contains(github.event.head_commit.message, '[DOC]') + || contains(github.event.head_commit.message, 'Document') + || contains(github.event.pull_request.title, '[DOC]') + || contains(github.event.pull_request.title, 'Document') + || contains(github.event.pull_request.labels.*.name, 'Documentation') + || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]') + )}} + + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + sparse-checkout-cone-mode: false + sparse-checkout: /.github + + - name: Install libraries + uses: ./.github/actions/setup/macos + + - uses: ./.github/actions/setup/directories + with: + srcdir: src + builddir: build + makeup: true + dummy-files: ${{ matrix.test_task == 'check' }} + # Set fetch-depth: 10 so that Launchable can receive commits information. + fetch-depth: 10 + + - name: Run configure + run: ../src/configure -C --disable-install-doc ${{ matrix.configure }} + + - run: make prepare-gems + if: ${{ matrix.test_task == 'test-bundled-gems' }} + + - run: make + + - name: Verify that --yjit-dump-disasm works + run: | + ./miniruby --yjit-call-threshold=1 --yjit-dump-disasm -e0 | \ + wc -l | \ + ruby -ne 'raise "Disassembly seems broken in dev build (output has too few lines)" unless $_.to_i > 10' + if: ${{ contains(matrix.configure, 'jit=dev') }} + + - name: Enable YJIT through ENV + run: echo "RUBY_YJIT_ENABLE=1" >> $GITHUB_ENV + + - name: Set test options for skipped tests + run: | + set -x + TESTS="$(echo "${{ matrix.skipped_tests }}" | sed 's| |$$/ -n!/|g;s|^|-n!/|;s|$|$$/|')" + echo "TESTS=${TESTS}" >> $GITHUB_ENV + if: ${{ matrix.test_task == 'check' && matrix.skipped_tests }} + + - name: Set up Launchable + id: launchable + uses: ./.github/actions/launchable/setup + with: + os: macos-14 + test-opts: ${{ matrix.configure }} + launchable-token: ${{ secrets.LAUNCHABLE_TOKEN }} + builddir: build + srcdir: src + is-yjit: true + continue-on-error: true + timeout-minutes: 3 + + - name: make ${{ matrix.test_task }} + run: | + test -n "${LAUNCHABLE_STDOUT}" && exec 1> >(tee "${LAUNCHABLE_STDOUT}") + test -n "${LAUNCHABLE_STDERR}" && exec 2> >(tee "${LAUNCHABLE_STDERR}") + + make -s ${{ matrix.test_task }} ${TESTS:+TESTS="$TESTS"} \ + RUN_OPTS="$RUN_OPTS" \ + SPECOPTS="$SPECOPTS" + timeout-minutes: 60 + env: + RUBY_TESTOPTS: '-q --tty=no' + TEST_BUNDLED_GEMS_ALLOW_FAILURES: '' + SYNTAX_SUGGEST_TIMEOUT: '5' + PRECHECK_BUNDLED_GEMS: 'no' + LAUNCHABLE_STDOUT: ${{ steps.launchable.outputs.stdout_report_path }} + LAUNCHABLE_STDERR: ${{ steps.launchable.outputs.stderr_report_path }} + continue-on-error: ${{ matrix.continue-on-test_task || false }} + + - name: make skipped tests + run: | + make -s test-all TESTS="${TESTS//-n!\//-n/}" + env: + GNUMAKEFLAGS: '' + RUBY_TESTOPTS: '-v --tty=no' + PRECHECK_BUNDLED_GEMS: 'no' + if: ${{ matrix.test_task == 'check' && matrix.skipped_tests }} + continue-on-error: ${{ matrix.continue-on-skipped_tests || false }} + + - uses: ./.github/actions/slack + with: + label: ${{ matrix.test_task }} ${{ matrix.configure }} ${{ matrix.yjit_opts }} + SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot + if: ${{ failure() }} + + result: + if: ${{ always() }} + name: ${{ github.workflow }} result + runs-on: macos-14 + needs: [make] + steps: + - name: ${{ github.workflow }} jobs have failed + run: exit 1 + working-directory: + if: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }} + +defaults: + run: + working-directory: build diff --git a/.github/workflows/yjit-ubuntu.yml b/.github/workflows/yjit-ubuntu.yml index 45c7a224441356..d71c5df48a51b8 100644 --- a/.github/workflows/yjit-ubuntu.yml +++ b/.github/workflows/yjit-ubuntu.yml @@ -3,24 +3,15 @@ on: push: paths-ignore: - 'doc/**' - - '**/man' + - '**/man/*' - '**.md' - '**.rdoc' - '**/.document' + - '.*.yml' pull_request: - paths-ignore: - - 'doc/**' - - '**/man' - - '**.md' - - '**.rdoc' - - '**/.document' + # Do not use paths-ignore for required status checks + # https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/collaborating-on-repositories-with-code-quality-features/troubleshooting-required-status-checks#handling-skipped-but-required-checks merge_group: - paths-ignore: - - 'doc/**' - - '**/man' - - '**.md' - - '**.rdoc' - - '**/.document' concurrency: group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }} @@ -31,13 +22,21 @@ permissions: jobs: cargo: - name: Rust cargo test + name: cargo test # GitHub Action's image seems to already contain a Rust 1.58.0. - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 + + if: >- + ${{!(false + || contains(github.event.head_commit.message, '[DOC]') + || contains(github.event.pull_request.title, '[DOC]') + || contains(github.event.pull_request.labels.*.name, 'Documentation') + || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]') + )}} steps: - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 # For now we can't run cargo test --offline because it complains about the # capstone dependency, even though the dependency is optional @@ -55,13 +54,21 @@ jobs: working-directory: yjit lint: - name: Rust lint + name: cargo clippy # GitHub Action's image seems to already contain a Rust 1.58.0. - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 + + if: >- + ${{!(false + || contains(github.event.head_commit.message, '[DOC]') + || contains(github.event.pull_request.title, '[DOC]') + || contains(github.event.pull_request.labels.*.name, 'Documentation') + || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]') + )}} steps: - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 # Check that we don't have linting errors in release mode, too - run: cargo clippy --all-targets --all-features @@ -74,7 +81,8 @@ jobs: include: - test_task: 'yjit-bindgen' hint: 'To fix: use patch in logs' - configure: '--with-gcc=clang-12 --enable-yjit=dev' + configure: '--with-gcc=clang-14 --enable-yjit=dev' + libclang_path: '/usr/lib/llvm-14/lib/libclang.so.1' - test_task: 'check' # YJIT should be automatically built in release mode on x86-64 Linux with rustc present @@ -87,10 +95,8 @@ jobs: - test_task: 'check' configure: '--enable-yjit=dev' - yjit_opts: '--yjit-call-threshold=1 --yjit-verify-ctx' - - - test_task: 'test-all TESTS=--repeat-count=2' - configure: '--enable-yjit=dev' + yjit_opts: '--yjit-call-threshold=1 --yjit-verify-ctx --yjit-code-gc' + specopts: '-T --yjit-call-threshold=1 -T --yjit-verify-ctx -T --yjit-code-gc' - test_task: 'test-bundled-gems' configure: '--enable-yjit=dev' @@ -98,38 +104,50 @@ jobs: - test_task: 'yjit-bench' configure: '--enable-yjit=dev' yjit_bench_opts: '--yjit-stats' + continue-on-test_task: true env: GITPULLOPTIONS: --no-tags origin ${{ github.ref }} RUN_OPTS: ${{ matrix.yjit_opts }} YJIT_BENCH_OPTS: ${{ matrix.yjit_bench_opts }} + SPECOPTS: ${{ matrix.specopts }} RUBY_DEBUG: ci BUNDLE_JOBS: 8 # for yjit-bench RUST_BACKTRACE: 1 - runs-on: ubuntu-20.04 + runs-on: ubuntu-22.04 if: >- ${{!(false || contains(github.event.head_commit.message, '[DOC]') + || contains(github.event.head_commit.message, 'Document') || contains(github.event.pull_request.title, '[DOC]') + || contains(github.event.pull_request.title, 'Document') || contains(github.event.pull_request.labels.*.name, 'Documentation') - || (github.event_name == 'push' && github.actor == 'dependabot[bot]') + || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]') )}} steps: - - uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 with: sparse-checkout-cone-mode: false sparse-checkout: /.github - uses: ./.github/actions/setup/ubuntu + - uses: ruby/setup-ruby@a4effe49ee8ee5b8b5091268c473a4628afb5651 # v1.245.0 + with: + ruby-version: '3.1' + bundler: none + - uses: ./.github/actions/setup/directories with: srcdir: src builddir: build makeup: true + dummy-files: ${{ matrix.test_task == 'check' }} + # Set fetch-depth: 10 so that Launchable can receive commits information. + fetch-depth: 10 - name: Install Rust if: ${{ matrix.rust_version }} @@ -145,10 +163,12 @@ jobs: - run: make - - name: Create dummy files in build dir + - name: Verify that --yjit-dump-disasm works run: | - ./miniruby -e '(("a".."z").to_a+("A".."Z").to_a+("0".."9").to_a+%w[foo bar test zzz]).each{|basename|File.write("#{basename}.rb", "raise %(do not load #{basename}.rb)")}' - if: ${{ matrix.test_task == 'check' }} + ./miniruby --yjit-call-threshold=1 --yjit-dump-disasm -e0 | \ + wc -l | \ + ruby -ne 'raise "Disassembly seems broken in dev build (output has too few lines)" unless $_.to_i > 10' + if: ${{ contains(matrix.configure, 'jit=dev') }} - name: Enable YJIT through ENV run: echo "RUBY_YJIT_ENABLE=1" >> $GITHUB_ENV @@ -157,16 +177,38 @@ jobs: - name: Check YJIT enabled run: ./miniruby --yjit -v | grep "+YJIT" + - name: Set up Launchable + id: launchable + uses: ./.github/actions/launchable/setup + with: + os: ubuntu-22.04 + test-opts: ${{ matrix.configure }} + launchable-token: ${{ secrets.LAUNCHABLE_TOKEN }} + builddir: build + srcdir: src + is-yjit: true + continue-on-error: true + timeout-minutes: 3 + - name: make ${{ matrix.test_task }} - run: make -s -j ${{ matrix.test_task }} RUN_OPTS="$RUN_OPTS" YJIT_BENCH_OPTS="$YJIT_BENCH_OPTS" YJIT_BINDGEN_DIFF_OPTS="$YJIT_BINDGEN_DIFF_OPTS" - timeout-minutes: 60 + run: | + test -n "${LAUNCHABLE_STDOUT}" && exec 1> >(tee "${LAUNCHABLE_STDOUT}") + test -n "${LAUNCHABLE_STDERR}" && exec 2> >(tee "${LAUNCHABLE_STDERR}") + + make -s ${{ matrix.test_task }} ${TESTS:+TESTS="$TESTS"} \ + RUN_OPTS="$RUN_OPTS" MSPECOPT=--debug SPECOPTS="$SPECOPTS" \ + YJIT_BENCH_OPTS="$YJIT_BENCH_OPTS" YJIT_BINDGEN_DIFF_OPTS="$YJIT_BINDGEN_DIFF_OPTS" + timeout-minutes: 90 env: RUBY_TESTOPTS: '-q --tty=no' TEST_BUNDLED_GEMS_ALLOW_FAILURES: '' PRECHECK_BUNDLED_GEMS: 'no' SYNTAX_SUGGEST_TIMEOUT: '5' YJIT_BINDGEN_DIFF_OPTS: '--exit-code' - continue-on-error: ${{ matrix.test_task == 'yjit-bench' }} + LIBCLANG_PATH: ${{ matrix.libclang_path }} + LAUNCHABLE_STDOUT: ${{ steps.launchable.outputs.stdout_report_path }} + LAUNCHABLE_STDERR: ${{ steps.launchable.outputs.stderr_report_path }} + continue-on-error: ${{ matrix.continue-on-test_task || false }} - name: Show ${{ github.event.pull_request.base.ref }} GitHub URL for yjit-bench comparison run: echo "https://github.com/${BASE_REPO}/commit/${BASE_SHA}" @@ -179,7 +221,17 @@ jobs: with: label: ${{ matrix.test_task }} ${{ matrix.configure }} SLACK_WEBHOOK_URL: ${{ secrets.SIMPLER_ALERTS_URL }} # ruby-lang slack: ruby/simpler-alerts-bot - if: ${{ failure() && github.event_name == 'push' }} + if: ${{ failure() }} + + result: + if: ${{ always() }} + name: ${{ github.workflow }} result + runs-on: ubuntu-latest + needs: [make] + steps: + - run: exit 1 + working-directory: + if: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }} defaults: run: diff --git a/.github/workflows/zjit-macos.yml b/.github/workflows/zjit-macos.yml new file mode 100644 index 00000000000000..7a36b296f11afd --- /dev/null +++ b/.github/workflows/zjit-macos.yml @@ -0,0 +1,172 @@ +name: ZJIT macOS Arm64 +on: + push: + branches: + - master + paths-ignore: + - 'doc/**' + - '**/man/*' + - '**.md' + - '**.rdoc' + - '**/.document' + - '.*.yml' + pull_request: + types: + - opened + - synchronize + - reopened + # Do not use paths-ignore for required status checks + # https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/collaborating-on-repositories-with-code-quality-features/troubleshooting-required-status-checks#handling-skipped-but-required-checks + merge_group: + +concurrency: + group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }} + cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }} + +permissions: + contents: read + +jobs: + make: + strategy: + fail-fast: false + matrix: + include: + - test_task: 'zjit-test' + configure: '--enable-yjit=dev --enable-zjit' + + - test_task: 'ruby' # build test for combo build + configure: '--enable-yjit --enable-zjit' + + - test_task: 'test-all' + configure: '--enable-zjit=dev' + tests: '../src/test/ruby/test_zjit.rb' + + - test_task: 'btest' + configure: '--enable-zjit=dev' + + env: + GITPULLOPTIONS: --no-tags origin ${{ github.ref }} + RUN_OPTS: ${{ matrix.zjit_opts }} + SPECOPTS: ${{ matrix.specopts }} + + runs-on: macos-14 + + if: >- + ${{!(false + || contains(github.event.head_commit.message, '[DOC]') + || contains(github.event.head_commit.message, 'Document') + || contains(github.event.pull_request.title, '[DOC]') + || contains(github.event.pull_request.title, 'Document') + || contains(github.event.pull_request.labels.*.name, 'Documentation') + || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]') + )}} + + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + sparse-checkout-cone-mode: false + sparse-checkout: /.github + + - name: Install libraries + uses: ./.github/actions/setup/macos + + - uses: ./.github/actions/setup/directories + with: + srcdir: src + builddir: build + makeup: true + dummy-files: ${{ matrix.test_task == 'check' }} + # Set fetch-depth: 10 so that Launchable can receive commits information. + fetch-depth: 10 + + - uses: taiki-e/install-action@v2 + with: + tool: nextest@0.9 + if: ${{ matrix.test_task == 'zjit-test' }} + + - name: Install Rust # TODO(alan): remove when GitHub images catch up past 1.85.0 + run: rustup default 1.85.0 + + - name: Run configure + run: ../src/configure -C --disable-install-doc ${{ matrix.configure }} + + - run: make prepare-gems + if: ${{ matrix.test_task == 'test-bundled-gems' }} + + - run: make + + - name: Verify that --zjit-dump-disasm works + run: | + ./miniruby --zjit-call-threshold=1 --zjit-dump-disasm -e0 | \ + wc -l | \ + ruby -ne 'raise "Disassembly seems broken in dev build (output has too few lines)" unless $_.to_i > 10' + if: ${{ contains(matrix.configure, 'jit=dev') }} + + - name: btest + run: | + RUST_BACKTRACE=1 ruby --disable=gems ../src/bootstraptest/runner.rb --ruby="./miniruby -I../src/lib -I. -I.ext/common --zjit-call-threshold=1" \ + ../src/bootstraptest/test_attr.rb \ + ../src/bootstraptest/test_autoload.rb \ + ../src/bootstraptest/test_block.rb \ + ../src/bootstraptest/test_class.rb \ + ../src/bootstraptest/test_constant_cache.rb \ + ../src/bootstraptest/test_env.rb \ + ../src/bootstraptest/test_eval.rb \ + ../src/bootstraptest/test_exception.rb \ + ../src/bootstraptest/test_fiber.rb \ + ../src/bootstraptest/test_finalizer.rb \ + ../src/bootstraptest/test_flip.rb \ + ../src/bootstraptest/test_flow.rb \ + ../src/bootstraptest/test_fork.rb \ + ../src/bootstraptest/test_gc.rb \ + ../src/bootstraptest/test_insns.rb \ + ../src/bootstraptest/test_io.rb \ + ../src/bootstraptest/test_jump.rb \ + ../src/bootstraptest/test_literal.rb \ + ../src/bootstraptest/test_literal_suffix.rb \ + ../src/bootstraptest/test_load.rb \ + ../src/bootstraptest/test_marshal.rb \ + ../src/bootstraptest/test_massign.rb \ + ../src/bootstraptest/test_method.rb \ + ../src/bootstraptest/test_objectspace.rb \ + ../src/bootstraptest/test_proc.rb \ + ../src/bootstraptest/test_ractor.rb \ + ../src/bootstraptest/test_string.rb \ + ../src/bootstraptest/test_struct.rb \ + ../src/bootstraptest/test_syntax.rb \ + ../src/bootstraptest/test_thread.rb \ + ../src/bootstraptest/test_yjit_30k_ifelse.rb \ + ../src/bootstraptest/test_yjit_30k_methods.rb \ + ../src/bootstraptest/test_yjit_rust_port.rb + # ../src/bootstraptest/test_yjit.rb \ + if: ${{ matrix.test_task == 'btest' }} + + - name: make ${{ matrix.test_task }} + run: >- + make -s ${{ matrix.test_task }} ${TESTS:+TESTS="$TESTS"} + RUN_OPTS="$RUN_OPTS" + SPECOPTS="$SPECOPTS" + timeout-minutes: 60 + env: + RUBY_TESTOPTS: '-q --tty=no' + TEST_BUNDLED_GEMS_ALLOW_FAILURES: '' + SYNTAX_SUGGEST_TIMEOUT: '5' + PRECHECK_BUNDLED_GEMS: 'no' + TESTS: ${{ matrix.tests }} + continue-on-error: ${{ matrix.continue-on-test_task || false }} + if: ${{ matrix.test_task != 'btest' }} + + result: + if: ${{ always() }} + name: ${{ github.workflow }} result + runs-on: macos-14 + needs: [make] + steps: + - run: exit 1 + working-directory: + if: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }} + +defaults: + run: + working-directory: build diff --git a/.github/workflows/zjit-ubuntu.yml b/.github/workflows/zjit-ubuntu.yml new file mode 100644 index 00000000000000..91aa436b58bc24 --- /dev/null +++ b/.github/workflows/zjit-ubuntu.yml @@ -0,0 +1,197 @@ +name: ZJIT Ubuntu +on: + push: + branches: + - master + paths-ignore: + - 'doc/**' + - '**/man/*' + - '**.md' + - '**.rdoc' + - '**/.document' + - '.*.yml' + pull_request: + types: + - opened + - synchronize + - reopened + # Do not use paths-ignore for required status checks + # https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/collaborating-on-repositories-with-code-quality-features/troubleshooting-required-status-checks#handling-skipped-but-required-checks + merge_group: + +concurrency: + group: ${{ github.workflow }} / ${{ startsWith(github.event_name, 'pull') && github.ref_name || github.sha }} + cancel-in-progress: ${{ startsWith(github.event_name, 'pull') }} + +permissions: + contents: read + +jobs: + make: + strategy: + fail-fast: false + matrix: + include: + - test_task: 'zjit-bindgen' + hint: 'To fix: use patch in logs' + configure: '--enable-zjit=dev --with-gcc=clang-14' + libclang_path: '/usr/lib/llvm-14/lib/libclang.so.1' + + - test_task: 'zjit-test' + configure: '--enable-yjit --enable-zjit=dev' + + - test_task: 'test-all' + configure: '--enable-zjit=dev' + tests: '../src/test/ruby/test_zjit.rb' + + - test_task: 'btest' + configure: '--enable-zjit=dev' + + env: + GITPULLOPTIONS: --no-tags origin ${{ github.ref }} + RUN_OPTS: ${{ matrix.zjit_opts }} + YJIT_BENCH_OPTS: ${{ matrix.yjit_bench_opts }} + SPECOPTS: ${{ matrix.specopts }} + RUBY_DEBUG: ci + BUNDLE_JOBS: 8 # for yjit-bench + RUST_BACKTRACE: 1 + + runs-on: ubuntu-22.04 + + if: >- + ${{!(false + || contains(github.event.head_commit.message, '[DOC]') + || contains(github.event.head_commit.message, 'Document') + || contains(github.event.pull_request.title, '[DOC]') + || contains(github.event.pull_request.title, 'Document') + || contains(github.event.pull_request.labels.*.name, 'Documentation') + || (github.event_name == 'push' && github.event.pull_request.user.login == 'dependabot[bot]') + )}} + + steps: + - uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2 + with: + sparse-checkout-cone-mode: false + sparse-checkout: /.github + + - uses: ./.github/actions/setup/ubuntu + + - uses: ruby/setup-ruby@a4effe49ee8ee5b8b5091268c473a4628afb5651 # v1.245.0 + with: + ruby-version: '3.1' + bundler: none + + - uses: taiki-e/install-action@v2 + with: + tool: nextest@0.9 + if: ${{ matrix.test_task == 'zjit-test' }} + + + - uses: ./.github/actions/setup/directories + with: + srcdir: src + builddir: build + makeup: true + dummy-files: ${{ matrix.test_task == 'check' }} + # Set fetch-depth: 10 so that Launchable can receive commits information. + fetch-depth: 10 + + - name: Install Rust + run: rustup default 1.85.0 + + - name: Install rustfmt + if: ${{ matrix.test_task == 'zjit-bindgen' }} + run: rustup component add rustfmt + + - name: Run configure + run: ../src/configure -C --disable-install-doc --prefix=$(pwd)/install ${{ matrix.configure }} + + - run: make incs + + - run: make prepare-gems + if: ${{ matrix.test_task == 'test-bundled-gems' }} + + - run: make + + - name: Verify that --zjit-dump-disasm works + run: | + ./miniruby --zjit-call-threshold=1 --zjit-dump-disasm -e0 | \ + wc -l | \ + ruby -ne 'raise "Disassembly seems broken in dev build (output has too few lines)" unless $_.to_i > 10' + if: ${{ contains(matrix.configure, 'jit=dev') }} + + # Check that the binary was built with ZJIT + - name: Check ZJIT enabled + run: ./miniruby --zjit -v | grep "+ZJIT" + if: ${{ matrix.configure != '--disable-zjit' }} + + - name: btest + run: | + RUST_BACKTRACE=1 ruby --disable=gems ../src/bootstraptest/runner.rb --ruby="./miniruby -I../src/lib -I. -I.ext/common --zjit-call-threshold=1" \ + ../src/bootstraptest/test_attr.rb \ + ../src/bootstraptest/test_autoload.rb \ + ../src/bootstraptest/test_block.rb \ + ../src/bootstraptest/test_class.rb \ + ../src/bootstraptest/test_constant_cache.rb \ + ../src/bootstraptest/test_env.rb \ + ../src/bootstraptest/test_env.rb \ + ../src/bootstraptest/test_exception.rb \ + ../src/bootstraptest/test_fiber.rb \ + ../src/bootstraptest/test_finalizer.rb \ + ../src/bootstraptest/test_flip.rb \ + ../src/bootstraptest/test_flow.rb \ + ../src/bootstraptest/test_fork.rb \ + ../src/bootstraptest/test_gc.rb \ + ../src/bootstraptest/test_insns.rb \ + ../src/bootstraptest/test_io.rb \ + ../src/bootstraptest/test_jump.rb \ + ../src/bootstraptest/test_literal.rb \ + ../src/bootstraptest/test_literal_suffix.rb \ + ../src/bootstraptest/test_load.rb \ + ../src/bootstraptest/test_marshal.rb \ + ../src/bootstraptest/test_massign.rb \ + ../src/bootstraptest/test_method.rb \ + ../src/bootstraptest/test_objectspace.rb \ + ../src/bootstraptest/test_proc.rb \ + ../src/bootstraptest/test_ractor.rb \ + ../src/bootstraptest/test_string.rb \ + ../src/bootstraptest/test_struct.rb \ + ../src/bootstraptest/test_syntax.rb \ + ../src/bootstraptest/test_thread.rb \ + ../src/bootstraptest/test_yjit_30k_ifelse.rb \ + ../src/bootstraptest/test_yjit_30k_methods.rb \ + ../src/bootstraptest/test_yjit_rust_port.rb + # ../src/bootstraptest/test_yjit.rb \ + if: ${{ matrix.test_task == 'btest' }} + + - name: make ${{ matrix.test_task }} + run: >- + make -s ${{ matrix.test_task }} ${TESTS:+TESTS="$TESTS"} + RUN_OPTS="$RUN_OPTS" MSPECOPT=--debug SPECOPTS="$SPECOPTS" + ZJIT_BINDGEN_DIFF_OPTS="$ZJIT_BINDGEN_DIFF_OPTS" + timeout-minutes: 90 + env: + RUBY_TESTOPTS: '-q --tty=no' + TEST_BUNDLED_GEMS_ALLOW_FAILURES: '' + PRECHECK_BUNDLED_GEMS: 'no' + SYNTAX_SUGGEST_TIMEOUT: '5' + ZJIT_BINDGEN_DIFF_OPTS: '--exit-code' + LIBCLANG_PATH: ${{ matrix.libclang_path }} + TESTS: ${{ matrix.tests }} + continue-on-error: ${{ matrix.continue-on-test_task || false }} + if: ${{ matrix.test_task != 'btest' }} + + result: + if: ${{ always() }} + name: ${{ github.workflow }} result + runs-on: ubuntu-22.04 + needs: [make] + steps: + - name: ${{ github.workflow }} jobs have failed + run: exit 1 + working-directory: + if: ${{ contains(needs.*.result, 'failure') || contains(needs.*.result, 'cancelled') }} + +defaults: + run: + working-directory: build diff --git a/.gitignore b/.gitignore index 631a489eeff1f8..3e8d3310f555b4 100644 --- a/.gitignore +++ b/.gitignore @@ -138,12 +138,12 @@ lcov*.info /test.rb /test-coverage.dat /tmp +/vcpkg_installed /transdb.h /uncommon.mk /verconf.h /verconf.mk /web -/yasmdata.rb # /bin/ @@ -166,6 +166,7 @@ lcov*.info # /coroutine/ !/coroutine/**/*.s +!/coroutine/**/*.S # /enc/trans/ /enc/trans/*.c @@ -232,7 +233,6 @@ lcov*.info # for `make test-bundler` /.rspec_status -/tool/bundler/*.lock # /tool/ /tool/config.guess @@ -241,27 +241,38 @@ lcov*.info # /win32/ /win32/*.ico -# RJIT -/include/ruby-*/*/rb_rjit_min_header-*.h -/lib/ruby_vm/rjit/instruction.rb -/lib/ruby_vm/rjit/instruction.rb -/rjit_config.h -/rb_rjit_header.h* # YJIT /yjit-bench /yjit_exit_locations.dump +# Rust +/target + # /wasm/ /wasm/tests/*.wasm -# YARP -/lib/yarp/mutation_visitor.rb -/lib/yarp/node.rb -/lib/yarp/serialize.rb -/yarp/api_node.c -/yarp/ast.h -/yarp/node.c -/yarp/prettyprint.c -/yarp/serialize.c -/yarp/token_type.c +# prism +/lib/prism/compiler.rb +/lib/prism/dispatcher.rb +/lib/prism/dot_visitor.rb +/lib/prism/dsl.rb +/lib/prism/inspect_visitor.rb +/lib/prism/mutation_compiler.rb +/lib/prism/node.rb +/lib/prism/reflection.rb +/lib/prism/serialize.rb +/lib/prism/visitor.rb +/prism/api_node.c +/prism/ast.h +/prism/diagnostic.c +/prism/diagnostic.h +/prism/node.c +/prism/prettyprint.c +/prism/serialize.c +/prism/token_type.c + +# tool/update-NEWS-gemlist.rb +/bundled_gems.json +/default_gems.json +/gems/default_gems diff --git a/.mailmap b/.mailmap new file mode 100644 index 00000000000000..213a0f49164c0f --- /dev/null +++ b/.mailmap @@ -0,0 +1,431 @@ +git[bot] +git[bot] git +svn[bot] svn + +# a_matsuda +Akira Matsuda +Akira Matsuda + +# aamine +Minero Aoki +Minero Aoki + +# akira +akira yamada +## akira yamada +akira yamada +akira yamada + +# akiyoshi +AKIYOSHI, Masamichi +AKIYOSHI, Masamichi + +# akr +Tanaka Akira +Tanaka Akira + +# arai +Koji Arai +Koji Arai + +# arton +Akio Tajima +Akio Tajima + +# aycabta +aycabta +aycabta + +# ayumin +Ayumu AIZAWA +Ayumu AIZAWA + +# azav +Alexander Zavorine +Alexander Zavorine + +# charliesome +Charlie Somerville +Charlie Somerville + +# dave +Dave Thomas +Dave Thomas + +# davidflanagan +David Flanagan +David Flanagan +David Flanagan +David Flanagan + +# dblack +David A. Black +David A. Black +David A. Black +David A. Black + +# drbrain +Eric Hodel +Eric Hodel + +# duerst +Martin Dürst +Martin Dürst + +# eban +WATANABE Hirofumi +WATANABE Hirofumi + +# emboss +Martin Bosslet +Martin Bosslet +Martin Bosslet + +# eregon +Benoit Daloze +Benoit Daloze + +# evan +Evan Phoenix +Evan Phoenix +Evan Phoenix + +# glass +Masaki Matsushita +Masaki Matsushita + +# gogotanaka +Kazuki Tanaka +Kazuki Tanaka + +# gotoken +Kentaro Goto +Kentaro Goto + +# gotoyuzo +GOTOU Yuuzou +GOTOU Yuuzou + +# gsinclair +Gavin Sinclair +Gavin Sinclair + +# H_Konishi +KONISHI Hiromasa +KONISHI Hiromasa + +# headius +Charles Oliver Nutter +Charles Oliver Nutter + +# hone +Terence Lee +Terence Lee + +# hsbt +Hiroshi SHIBATA +Hiroshi SHIBATA + +# iwamatsu +Nobuhiro Iwamatsu +Nobuhiro Iwamatsu + +# jeg2 +James Edward Gray II +James Edward Gray II + +# jim +Jim Weirich +Jim Weirich + +# k0kubun +Takashi Kokubun +Takashi Kokubun + +# kanemoto +Yutaka Kanemoto +Yutaka Kanemoto + +# katsu +UENO Katsuhiro +UENO Katsuhiro + +# kazu +Kazuhiro NISHIYAMA +Kazuhiro NISHIYAMA + +# keiju +Keiju Ishitsuka +Keiju Ishitsuka + +# knu +Akinori MUSHA +Akinori MUSHA + +# ko1 +Koichi Sasada +Koichi Sasada + +# kosaki +KOSAKI Motohiro +KOSAKI Motohiro + +# kosako +K.Kosako +K.Kosako + +# kou +Sutou Kouhei +Sutou Kouhei +Sutou Kouhei + +# kouji +Kouji Takao +Kouji Takao +Kouji Takao + +# ksaito +Kazuo Saito +Kazuo Saito + +# ktsj +Kazuki Tsujimoto +Kazuki Tsujimoto + +# luislavena +Luis Lavena +Luis Lavena + +# mame +Yusuke Endoh +## Yusuke Endoh +Yusuke Endoh + +# marcandre +Marc-Andre Lafortune +Marc-Andre Lafortune +Marc-Andre Lafortune + +# matz +Yukihiro "Matz" Matsumoto +Yukihiro "Matz" Matsumoto +Yukihiro "Matz" Matsumoto + +# michal +Michal Rokos +Michal Rokos + +# mneumann +Michael Neumann +Michael Neumann + +# mrkn +Kenta Murata +Kenta Murata +Kenta Murata <3959+mrkn@users.noreply.github.com> +Kenta Murata + +# nagachika +nagachika +nagachika + +# nagai +Hidetoshi NAGAI +Hidetoshi NAGAI + +# nahi +Hiroshi Nakamura +Hiroshi Nakamura + +# nari +Narihiro Nakamura +Narihiro Nakamura + +# naruse +NARUSE, Yui +NARUSE, Yui +NARUSE, Yui + +# ngoto +Naohisa Goto +Naohisa Goto + +# nobu +Nobuyoshi Nakada +Nobuyoshi Nakada + +# normal +Eric Wong +Eric Wong +Eric Wong + +# ntalbott +Nathaniel Talbott +Nathaniel Talbott + +# ocean +Hirokazu Yamamoto +Hirokazu Yamamoto + +# odaira +Rei Odaira +Rei Odaira +Rei Odaira + +# okkez +okkez +okkez + +# rhe +Kazuki Yamaguchi +Kazuki Yamaguchi + +# ryan +Ryan Davis +Ryan Davis +Ryan Davis + +# samuel +Samuel Williams +Samuel Williams + +# seki +Masatoshi SEKI +Masatoshi SEKI + +# ser +Sean Russell +Sean Russell + +# shigek +Shigeo Kobayashi +Shigeo Kobayashi + +# shirosaki +Hiroshi Shirosaki +Hiroshi Shirosaki + +# sho-h +Sho Hashimoto +Sho Hashimoto +Sho Hashimoto +Sho Hashimoto + +# shugo +Shugo Maeda +Shugo Maeda + +# shyouhei +卜部昌平 +卜部昌平 + +# siena +Siena. +Siena. + +# sonots +sonots +sonots + +# sorah +Sorah Fukumori +Sorah Fukumori + +# stomar +Marcus Stollsteimer +Marcus Stollsteimer + +# suke +Masaki Suketa +Masaki Suketa + +# tadd +Tadashi Saito +Tadashi Saito + +# tadf +Tadayoshi Funaba +Tadayoshi Funaba + +# takano32 +TAKANO Mitsuhiro +TAKANO Mitsuhiro + +# tarui +Masaya Tarui +Masaya Tarui + +# technorama +Technorama Ltd. +Technorama Ltd. + +# tenderlove +Aaron Patterson +Aaron Patterson + +# tmm1 +Aman Gupta +Aman Gupta + +# ts +Guy Decoux +Guy Decoux + +# ttate +Takaaki Tateishi +## Takaaki Tateishi +Takaaki Tateishi + +# uema2 +Takaaki Uematsu +Takaaki Uematsu + +# usa +U.Nakamura +U.Nakamura +U.Nakamura + +# wakou +Wakou Aoyama +Wakou Aoyama + +# wanabe +wanabe +wanabe + +# watson1978 +Watson +Watson + +# wew +William Webber +William Webber + +# why +why the lucky stiff +why the lucky stiff + +# xibbar +Takeyuki FUJIOKA +Takeyuki FUJIOKA + +# yugui +Yuki Yugui Sonoda +Yuki Yugui Sonoda + +# yui-knk +yui-knk +yui-knk + +# yuki +Yuki Nishijima +Yuki Nishijima +Yuki Nishijima + +# zsombor +Dee Zsombor +Dee Zsombor + +# zzak +zzak +zzak diff --git a/.rdoc_options b/.rdoc_options index 760507c7a2d1c0..27d35e2f58b97f 100644 --- a/.rdoc_options +++ b/.rdoc_options @@ -1,4 +1,24 @@ --- page_dir: doc -main_page: README.md +charset: UTF-8 +encoding: UTF-8 +main_page: index.md title: Documentation for Ruby development version +visibility: :private +rdoc_include: +- doc + +exclude: +- \Alib/irb +- \.gemspec\z + +autolink_excluded_words: +- Class +- Method +- Module +- Process +- RDoc +- Ruby +- Set + +canonical_root: https://docs.ruby-lang.org/en/master diff --git a/.travis.yml b/.travis.yml index c6054ae6723a46..ca68ed20abd91f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,63 +6,46 @@ # conditions mentioned in the file COPYING are met. Consult the file for # details. -# We only manage non-amd64 free pipelines. -# https://docs.travis-ci.com/user/billing-overview/ +# When you see Travis CI issues, or you are interested in understanding how to +# manage, please check the link below. +# https://github.com/ruby/ruby/wiki/CI-Servers#travis-ci + +# We enable Travis on the specific branches or forked repositories here. +# https://docs.travis-ci.com/user/conditions-v1 +if: >- + (fork OR branch = master OR branch =~ /^ruby_\d_\d$/) + AND (commit_message !~ /(\[DOC\]|Document)/) + AND NOT (type = 'push' AND sender =~ /\[bot\]/) language: c os: linux -if: commit_message !~ /\[DOC\]/ - -dist: focal +dist: jammy git: quiet: true -cache: - ccache: true - directories: - - $HOME/config_2nd - - $HOME/.downloaded-cache - env: global: - # The tests skipped in `make test-all`. - - TEST_ALL_SKIPPED_TESTS= - # The tests executed separately by `make test-all`. - - TEST_ALL_SEPARATED_TESTS= - # Reset timestamps early - - _=$(touch NEWS && find . -type f -exec touch -r NEWS {} +) - - CONFIGURE_TTY=no - - CCACHE_COMPILERCHECK=none - - CCACHE_NOCOMPRESS=1 - - CCACHE_MAXSIZE=512Mi - - NPROC="`nproc`" - # JOBS and SETARCH are overridden when necessary; see below. - - JOBS=-j$((1+${NPROC})) - - SETARCH= - - RUBY_PREFIX=/tmp/ruby-prefix - - GEMS_FOR_TEST='timezone tzinfo' + - NPROC="$(nproc)" + - JOBS="-j${NPROC}" # https://github.com/travis-ci/travis-build/blob/e411371dda21430a60f61b8f3f57943d2fe4d344/lib/travis/build/bash/travis_apt_get_options.bash#L7 - travis_apt_get_options='--allow-downgrades --allow-remove-essential --allow-change-held-packages' - travis_apt_get_options="-yq --no-install-suggests --no-install-recommends $travis_apt_get_options" - # -O1 is faster than -O3 in our tests. - - optflags=-O1 - # -g0 disables backtraces when SEGV. Do not set that. + # -g0 disables backtraces when SEGV. Do not set that. - debugflags=-ggdb3 + - RUBY_TESTOPTS="$JOBS -q --tty=no" .org.ruby-lang.ci.matrix-definitions: - - - &gcc-10 - compiler: gcc-10 + - &gcc-11 + compiler: gcc-11 before_install: - tool/travis_retry.sh sudo bash -c "rm -rf '${TRAVIS_ROOT}/var/lib/apt/lists/'* && exec apt-get update -yq" - >- tool/travis_retry.sh sudo -E apt-get $travis_apt_get_options install - ccache - gcc-10 - g++-10 + gcc-11 + g++-11 libffi-dev libncurses-dev libncursesw5-dev @@ -71,165 +54,58 @@ env: libyaml-dev openssl zlib1g-dev - - # -------- - - - &arm64-linux - name: arm64-linux - arch: arm64 - <<: *gcc-10 - + - gcc-11 --version - &ppc64le-linux name: ppc64le-linux arch: ppc64le - <<: *gcc-10 - + <<: *gcc-11 - &s390x-linux name: s390x-linux arch: s390x - <<: *gcc-10 - - - &arm32-linux - name: arm32-linux - arch: arm64 - # https://packages.ubuntu.com/focal/crossbuild-essential-armhf - compiler: arm-linux-gnueabihf-gcc + <<: *gcc-11 env: - - SETARCH='setarch linux32 --verbose --32bit' - # The "TestReadline#test_interrupt_in_other_thread" started failing on arm32 - # from https://www.travis-ci.com/github/ruby/ruby/jobs/529005145 - - TEST_ALL_SKIPPED_TESTS=test_interrupt_in_other_thread - before_install: - - sudo dpkg --add-architecture armhf - - tool/travis_retry.sh sudo bash -c "rm -rf '${TRAVIS_ROOT}/var/lib/apt/lists/'* && exec apt-get update -yq" - - >- - tool/travis_retry.sh sudo -E apt-get $travis_apt_get_options install - ccache - crossbuild-essential-armhf - libc6:armhf - libstdc++-10-dev:armhf - libffi-dev:armhf - libncurses-dev:armhf - libncursesw5-dev:armhf - libreadline-dev:armhf - libssl-dev:armhf - libyaml-dev:armhf - linux-libc-dev:armhf - zlib1g-dev:armhf + # Avoid possible test failures with the zlib applying the following patch + # on s390x CPU architecture. + # https://github.com/madler/zlib/pull/410 + - DFLTCC=0 matrix: include: - # Build every commit (Allowed Failures): - - <<: *arm32-linux - # Comment out as the 2nd arm64 pipeline is unstable. - # - <<: *arm64-linux - <<: *ppc64le-linux - <<: *s390x-linux allow_failures: - # We see multiple errors indicating errors on the Travis environment itself in a short while: - # https://app.travis-ci.com/github/ruby/ruby/jobs/544382885 - # https://app.travis-ci.com/github/ruby/ruby/jobs/544361370 - # It's not a fault of Ruby's arm32 support but just Travis arm32 seems unsable. - - name: arm32-linux - # - name: arm64-linux - # We see "Some worker was crashed." in about 40% of recent ppc64le-linux jobs - # e.g. https://app.travis-ci.com/github/ruby/ruby/jobs/530959548 - name: ppc64le-linux - # Tentatively disable, because often hungs up **after** all tests - # have finished successfully and saving caches. - name: s390x-linux fast_finish: true before_script: - - . tool/ci_functions.sh - - |- - if [ -n "${TEST_ALL_SKIPPED_TESTS}" ]; then - TEST_ALL_OPTS="${TEST_ALL_OPTS} $(ci_to_excluded_test_opts "${TEST_ALL_SKIPPED_TESTS}")" - if [ -z "${TEST_ALL_SEPARATED_TESTS}" ]; then - TEST_ALL_SEPARATED_TESTS="${TEST_ALL_SKIPPED_TESTS}" - fi - fi - - |- - if [ -n "${TEST_ALL_SEPARATED_TESTS}" ]; then - TEST_ALL_OPTS_SEPARATED="$(ci_to_included_test_opts "${TEST_ALL_SEPARATED_TESTS}")" - fi - - echo TEST_ALL_OPTS="${TEST_ALL_OPTS}" TEST_ALL_OPTS_SEPARATED="${TEST_ALL_OPTS_SEPARATED}" - - rm -fr .ext autom4te.cache - - |- - [ -d ~/.downloaded-cache ] || - mkdir ~/.downloaded-cache - - ln -s ~/.downloaded-cache - - "> config.status" - - "> .rbconfig.time" - - sed -f tool/prereq.status template/Makefile.in common.mk > Makefile - - make -s $JOBS up - - make -s $JOBS srcs - - rm -f config.status Makefile rbconfig.rb .rbconfig.time - - |- - if [ -d ~/config_2nd ]; then - cp -pr ~/config_2nd build - else - mkdir build - fi - - mkdir config_1st config_2nd gems/src - - chmod -R a-w . - - chmod -R u+w build config_1st config_2nd gems/src .bundle + - lscpu + - ./autogen.sh + - mkdir build - cd build - - |- - case "$CC" in - gcc*) CC="ccache $CC${GCC_FLAGS:+ }$GCC_FLAGS -fno-diagnostics-color";; - clang*) CC="ccache $CC${GCC_FLAGS:+ }$GCC_FLAGS -fno-color-diagnostics";; - esac - - |- - [ ! -f config.cache ] || - [ "$CC" = "`sed -n s/^ac_cv_prog_CC=//p config.cache`" ] || - (set -x; exec rm config.cache) - - $SETARCH ../configure -C --disable-install-doc --prefix=$RUBY_PREFIX $CONFIG_FLAG - - cp -pr config.cache config.status .ext/include ../config_1st - - $SETARCH make reconfig - - cp -pr config.cache config.status .ext/include ../config_2nd - - (cd .. && exec diff -ru config_1st config_2nd) - - chmod u+w .. - - rm -rf ~/config_2nd - - mv ../config_2nd ~ - - chmod u-w .. - - $SETARCH make -s $JOBS - - make -s install - - |- - [ -z "${GEMS_FOR_TEST}" ] || - $RUBY_PREFIX/bin/gem install --no-document $GEMS_FOR_TEST - - echo "raise 'do not load ~/.irbrc in test'" > ~/.irbrc + - ../configure -C --disable-install-doc --prefix=$(pwd)/install + - make -s $JOBS + - make -s $JOBS install + # Useful info to report issues to the Ruby. + - $(pwd)/install/bin/ruby -v + # Useful info To report issues to the RubyGems. + - $(pwd)/install/bin/gem env script: - - $SETARCH make -s test -o showflags TESTOPTS="${TESTOPTS=$JOBS -q --tty=no}" - - ../tool/travis_wait.sh $SETARCH make -s test-all -o exts TESTOPTS="$JOBS -q --tty=no ${TEST_ALL_OPTS}" RUBYOPT="-w" - # Run the failing tests separately returning ok status to check if it works, - # visualize them. - - | - if [ -n "${TEST_ALL_OPTS_SEPARATED}" ]; then - $SETARCH make -s test-all -o exts TESTOPTS="$JOBS -v --tty=no ${TEST_ALL_OPTS_SEPARATED}" RUBYOPT="-w" || : - fi - - $SETARCH make -s test-spec # not using `-j` because sometimes `mspec -j` silently dies - - $SETARCH make -s -o showflags leaked-globals - -# We enable Travis on the specific branches or forked repositories here. -if: (repo = ruby/ruby AND (branch = master OR branch =~ /^ruby_\d_\d$/)) OR repo != ruby/ruby + - make -s test + - ../tool/travis_wait.sh make -s test-all RUBYOPT="-w" + - ../tool/travis_wait.sh make -s test-spec # We want to be notified when something happens. notifications: - irc: - channels: - - "chat.freenode.net#ruby-core" - on_success: change # [always|never|change] # default: always - on_failure: always # [always|never|change] # default: always - template: - - "%{message} by @%{author}: See %{build_url}" - webhooks: urls: - - secure: mRsoS/UbqDkKkW5p3AEqM27d4SZnV6Gsylo3bm8T/deltQzTsGzZwrm7OIBXZv0UFZdE68XmPlyHfZFLSP2V9QZ7apXMf9/vw0GtcSe1gchtnjpAPF6lYBn7nMCbVPPx9cS0dwL927fjdRM1vj7IKZ2bk4F0lAJ25R25S6teqdk= # ruby-lang slack: ruby/simpler-alerts-bot (travis) + # ruby-lang slack: ruby/simpler-alerts-bot (travis) + - secure: mRsoS/UbqDkKkW5p3AEqM27d4SZnV6Gsylo3bm8T/deltQzTsGzZwrm7OIBXZv0UFZdE68XmPlyHfZFLSP2V9QZ7apXMf9/vw0GtcSe1gchtnjpAPF6lYBn7nMCbVPPx9cS0dwL927fjdRM1vj7IKZ2bk4F0lAJ25R25S6teqdk= on_success: never on_failure: always - email: - - jaruga@ruby-lang.org + recipients: + - jun.aruga@gmail.com + on_success: never + on_failure: always diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 13df6087cad9b6..35e79dd3b9480f 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1 +1 @@ -See ["Contributing to Ruby"](https://docs.ruby-lang.org/en/master/contributing_md.html), which includes setup and build instructions. +See ["Contributing to Ruby"](https://docs.ruby-lang.org/en/master/contributing/contributing_md.html), which includes setup and build instructions. diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 00000000000000..65131406d32876 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,89 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "capstone" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "015ef5d5ca1743e3f94af9509ba6bd2886523cfee46e48d15c2ef5216fd4ac9a" +dependencies = [ + "capstone-sys", + "libc", +] + +[[package]] +name = "capstone-sys" +version = "0.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2267cb8d16a1e4197863ec4284ffd1aec26fe7e57c58af46b02590a0235809a0" +dependencies = [ + "cc", + "libc", +] + +[[package]] +name = "cc" +version = "1.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "525046617d8376e3db1deffb079e91cef90a89fc3ca5c185bbf8c9ecdd15cd5c" +dependencies = [ + "shlex", +] + +[[package]] +name = "dissimilar" +version = "1.0.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8975ffdaa0ef3661bfe02dbdcc06c9f829dfafe6a3c474de366a8d5e44276921" + +[[package]] +name = "expect-test" +version = "1.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63af43ff4431e848fb47472a920f14fa71c24de13255a5692e93d4e90302acb0" +dependencies = [ + "dissimilar", + "once_cell", +] + +[[package]] +name = "jit" +version = "0.0.0" +dependencies = [ + "yjit", + "zjit", +] + +[[package]] +name = "libc" +version = "0.2.171" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6" + +[[package]] +name = "once_cell" +version = "1.21.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" + +[[package]] +name = "shlex" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" + +[[package]] +name = "yjit" +version = "0.1.0" +dependencies = [ + "capstone", +] + +[[package]] +name = "zjit" +version = "0.0.1" +dependencies = [ + "capstone", + "expect-test", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 00000000000000..6ab7e3a45f7c7d --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,51 @@ +# Using Cargo's workspace feature to build all the Rust code in +# into a single package. +# TODO(alan) notes about rust version requirements. Undecided yet. + +[workspace] +members = ["zjit", "yjit"] + +[package] +name = "jit" +version = "0.0.0" +edition = "2024" +rust-version = "1.85.0" +publish = false # Don't publish to crates.io + +[dependencies] +yjit = { path = "yjit", optional = true } +zjit = { path = "zjit", optional = true } + +[lib] +crate-type = ["staticlib"] +path = "jit.rs" + +[features] +disasm = ["yjit?/disasm", "zjit?/disasm"] +runtime_checks = [] +yjit = [ "dep:yjit" ] +zjit = [ "dep:zjit" ] + +[profile.dev] +opt-level = 0 +debug = true +debug-assertions = true +overflow-checks = true + +[profile.dev_nodebug] +inherits = "dev" + +[profile.stats] +inherits = "release" + +[profile.release] +# NOTE: --enable-yjit and zjit builds use `rustc` without going through Cargo. You +# might want to update the `rustc` invocation if you change this profile. +opt-level = 3 +# The extra robustness that comes from checking for arithmetic overflow is +# worth the performance cost for the compiler. +overflow-checks = true +# Generate debug info +debug = true +# Use ThinLTO. Much smaller output for a small amount of build time increase. +lto = "thin" diff --git a/LEGAL b/LEGAL index e352c55ee50005..a05cd6eaa3b01b 100644 --- a/LEGAL +++ b/LEGAL @@ -58,12 +58,12 @@ mentioned below. [ccan/list/list.h] - This file is licensed under the {MIT License}[rdoc-label:label-MIT+License]. + This file is licensed under the {MIT License}[rdoc-ref:@MIT+License]. [coroutine] Unless otherwise specified, these files are licensed under the - {MIT License}[rdoc-label:label-MIT+License]. + {MIT License}[rdoc-ref:@MIT+License]. [include/ruby/onigmo.h] [include/ruby/oniguruma.h] @@ -546,7 +546,7 @@ mentioned below. [vsnprintf.c] - This file is under the {old-style BSD license}[rdoc-label:label-Old-style+BSD+license]. + This file is under the {old-style BSD license}[rdoc-ref:@Old-style+BSD+license]. >>> Copyright (c) 1990, 1993:: @@ -577,7 +577,7 @@ mentioned below. [missing/crypt.c] - This file is under the {old-style BSD license}[rdoc-label:label-Old-style+BSD+license]. + This file is under the {old-style BSD license}[rdoc-ref:@Old-style+BSD+license]. >>> Copyright (c) 1989, 1993:: @@ -588,7 +588,7 @@ mentioned below. [missing/setproctitle.c] - This file is under the {old-style BSD license}[rdoc-label:label-Old-style+BSD+license]. + This file is under the {old-style BSD license}[rdoc-ref:@Old-style+BSD+license]. >>> Copyright 2003:: Damien Miller @@ -702,48 +702,43 @@ mentioned below. OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -[ext/json/generator/generator.c] +[ext/json/vendor/fpconv.c] - The file contains the following copyright notice. + This file is under the Boost Software License. >>> - Copyright 2001-2004:: Unicode, Inc. - - Disclaimer:: - - This source code is provided as is by Unicode, Inc. No claims are - made as to fitness for any particular purpose. No warranties of any - kind are expressed or implied. The recipient agrees to determine - applicability of information provided. If this file has been - purchased on magnetic or optical media from Unicode, Inc., the - sole remedy for any claim will be exchange of defective media - within 90 days of receipt. - - Limitations on Rights to Redistribute This Code:: - - Unicode, Inc. hereby grants the right to freely use the information - supplied in this file in the creation of products supporting the - Unicode Standard, and to make copies of this file in any form - for internal or external distribution as long as this notice - remains attached. - -[ext/nkf/nkf-utf8/config.h] -[ext/nkf/nkf-utf8/nkf.c] -[ext/nkf/nkf-utf8/utf8tbl.c] + Boost Software License - Version 1.0 - August 17th, 2003 + + Permission is hereby granted, free of charge, to any person or organization + obtaining a copy of the software and accompanying documentation covered by + this license (the "Software") to use, reproduce, display, distribute, + execute, and transmit the Software, and to prepare derivative works of the + Software, and to permit third-parties to whom the Software is furnished to + do so, all subject to the following: + + The copyright notices in the Software and this entire statement, including + the above license grant, this restriction and the following disclaimer, + must be included in all copies of the Software, in whole or in part, and + all derivative works of the Software, unless such copies or derivative + works are solely in the form of machine-executable object code generated by + a source language processor. + + 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, TITLE AND NON-INFRINGEMENT. IN NO EVENT + SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE + FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, + ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + DEALINGS IN THE SOFTWARE. - These files are under the following license. So to speak, it is - copyrighted semi-public-domain software. +[ext/json/vendor/jeaiii-ltoa.h] >>> - Copyright (C) 1987:: Fujitsu LTD. (Itaru ICHIKAWA) + Copyright (c) 2024,2025 Enrico Thierbach - https://github.com/radiospiel + Copyright (c) 2022 James Edward Anhalt III - https://github.com/jeaiii/itoa - Everyone is permitted to do anything on this program - including copying, modifying, improving, - as long as you don't try to pretend that you wrote it. - i.e., the above copyright notice has to appear in all copies. - Binary distribution requires original version messages. - You don't have to ask before copying, redistribution or publishing. - THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE. + {MIT License}[rdoc-ref:@MIT+License] + [ext/psych] [test/psych] @@ -879,7 +874,7 @@ mentioned below. >>> RubyGems is copyrighted free software by Chad Fowler, Rich Kilmer, Jim Weirich and others. You can redistribute it and/or modify it under - either the terms of the {MIT license}[rdoc-label:label-MIT+License], or the conditions + either the terms of the {MIT license}[rdoc-ref:@MIT+License], or the conditions below: 1. You may make and give away verbatim copies of the source form of the @@ -941,7 +936,7 @@ mentioned below. Portions copyright (c) 2010:: Andre Arko Portions copyright (c) 2009:: Engine Yard - {MIT License}[rdoc-label:label-MIT+License] + {MIT License}[rdoc-ref:@MIT+License] [lib/bundler/vendor/thor] @@ -950,16 +945,16 @@ mentioned below. >>> Copyright (c) 2008 Yehuda Katz, Eric Hodel, et al. - {MIT License}[rdoc-label:label-MIT+License] + {MIT License}[rdoc-ref:@MIT+License] -[lib/rubygems/resolver/molinillo] +[lib/rubygems/vendor/molinillo] molinillo is under the following license. >>> Copyright (c) 2014 Samuel E. Giddins segiddins@segiddins.me - {MIT License}[rdoc-label:label-MIT+License] + {MIT License}[rdoc-ref:@MIT+License] [lib/bundler/vendor/pub_grub] @@ -968,7 +963,7 @@ mentioned below. >>> Copyright (c) 2018 John Hawthorn - {MIT License}[rdoc-label:label-MIT+License] + {MIT License}[rdoc-ref:@MIT+License] [lib/bundler/vendor/connection_pool] @@ -977,7 +972,7 @@ mentioned below. >>> Copyright (c) 2011 Mike Perham - {MIT License}[rdoc-label:label-MIT+License] + {MIT License}[rdoc-ref:@MIT+License] [lib/bundler/vendor/net-http-persistent] @@ -986,7 +981,7 @@ mentioned below. >>> Copyright (c) Eric Hodel, Aaron Patterson - {MIT License}[rdoc-label:label-MIT+License] + {MIT License}[rdoc-ref:@MIT+License] [lib/did_you_mean] [lib/did_you_mean.rb] @@ -997,7 +992,7 @@ mentioned below. >>> Copyright (c) 2014-2016 Yuki Nishijima - {MIT License}[rdoc-label:label-MIT+License] + {MIT License}[rdoc-ref:@MIT+License] [lib/error_highlight] [lib/error_highlight.rb] @@ -1008,7 +1003,7 @@ mentioned below. >>> Copyright (c) 2021 Yusuke Endoh - {MIT License}[rdoc-label:label-MIT+License] + {MIT License}[rdoc-ref:@MIT+License] [benchmark/so_ackermann.rb] [benchmark/so_array.rb] diff --git a/NEWS.md b/NEWS.md index f424808bf2d203..df9da1406eff0d 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,184 +1,235 @@ -# NEWS for Ruby 3.3.0 +# NEWS for Ruby 3.5.0 This document is a list of user-visible feature changes -since the **3.2.0** release, except for bug fixes. +since the **3.4.0** release, except for bug fixes. Note that each entry is kept to a minimum, see links for details. ## Language changes -## Command line options - -* A new `performance` warning category was introduced. - They are not displayed by default even in verbose mode. - Turn them on with `-W:performance` or `Warning[:performance] = true`. [[Feature #19538]] -* The `RUBY_GC_HEAP_INIT_SLOTS` environment variable has been deprecated and - removed. Environment variables `RUBY_GC_HEAP_%d_INIT_SLOTS` should be - used instead. [[Feature #19785]] +* `*nil` no longer calls `nil.to_a`, similar to how `**nil` does + not call `nil.to_hash`. [[Feature #21047]] ## Core classes updates Note: We're only listing outstanding class updates. -* Array +* Kernel - * Array#pack now raises ArgumentError for unknown directives. [[Bug #19150]] + * `Kernel#inspect` now checks for the existence of a `#instance_variables_to_inspect` method, + allowing control over which instance variables are displayed in the `#inspect` string: -* Dir + ```ruby + class DatabaseConfig + def initialize(host, user, password) + @host = host + @user = user + @password = password + end - * Dir.for_fd added for returning a Dir object for the directory specified - by the provided directory file descriptor. [[Feature #19347]] - * Dir.fchdir added for changing the directory to the directory specified - by the provided directory file descriptor. [[Feature #19347]] - * Dir#chdir added for changing the directory to the directory specified by - the provided `Dir` object. [[Feature #19347]] + private def instance_variables_to_inspect = [:@host, :@user] + end -* MatchData + conf = DatabaseConfig.new("localhost", "root", "hunter2") + conf.inspect #=> # + ``` - * MatchData#named_captures now accepts optional `symbolize_names` - keyword. [[Feature #19591]] + [[Feature #21219]] -* String +* Binding + + * `Binding#local_variables` does no longer include numbered parameters. + Also, `Binding#local_variable_get` and `Binding#local_variable_set` reject + to handle numbered parameters. [[Bug #21049]] + +* IO + + * `IO.select` accepts +Float::INFINITY+ as a timeout argument. + [[Feature #20610]] + +* Socket + + * `Socket.tcp` accepts `open_timeout` as a keyword argument to specify + the timeout for the initial connection. [[Feature #21347]] + +* Ractor - * String#unpack now raises ArgumentError for unknown directives. [[Bug #19150]] - * String#bytesplice now accepts new arguments index/length or range of the - source string to be copied. [[Feature #19314]] + * `Ractor::Port` class was added for a new synchronization mechanism + to communicate between Ractors. [[Feature #21262]] -* ObjectSpace::WeakKeyMap + ```ruby + port1 = Ractor::Port.new + port2 = Ractor::Port.new + Ractor.new port1, port2 do |port1, port2| + port1 << 1 + port2 << 11 + port1 << 2 + port2 << 12 + end + 2.times{ p port1.receive } #=> 1, 2 + 2.times{ p port2.receive } #=> 11, 12 + ``` - * New core class to build collections with weak references. - The class use equality semantic to lookup keys like a regular hash, - but it doesn't hold strong references on the keys. [[Feature #18498]] + `Ractor::Port` provides the following methods: -* Module + * `Ractor::Port#receive` + * `Ractor::Port#send` (or `Ractor::Port#<<`) + * `Ractor::Port#close` + * `Ractor::Port#closed?` - * Module#set_temporary_name added for setting a temporary name for a - module. [[Feature #19521]] + As result, `Ractor.yield` and `Ractor#take` were removed. -* Process.warmup + * `Ractor#join` and `Ractor#value` were added to wait for the + termination of a Ractor. These are similar to `Thread#join` + and `Thread#value`. + + * `Ractor#monitor` and `Ractor#unmonitor` were added as low-level + interfaces used internally to implement `Ractor#join`. + + * `Ractor.select` now only accepts Ractors and Ports. If Ractors are given, + it returns when a Ractor terminates. + + * `Ractor#default_port` was added. Each `Ractor` has a default port, + which is used by `Ractor.send`, `Ractor.receive`. + + * `Ractor#close_incoming` and `Ractor#close_outgoing` were removed. + +* Set + + * Set is now a core class, instead of an autoloaded stdlib class. + [[Feature #21216]] + +* String - * Notify the Ruby virtual machine that the boot sequence is finished, - and that now is a good time to optimize the application. This is useful - for long running applications. The actual optimizations performed are entirely - implementation specific and may change in the future without notice. [[Feature #18885]] + * Update Unicode to Version 16.0.0 and Emoji Version 16.0. + [[Feature #19908]][[Feature #20724]] (also applies to Regexp) -* Refinement +* Fiber::Scheduler - * Add Refinement#target as an alternative of Refinement#refined_class. - Refinement#refined_class is deprecated and will be removed in Ruby - 3.4. [[Feature #19714]] + * Introduce `Fiber::Scheduler#fiber_interrupt` to interrupt a fiber with a + given exception. The initial use case is to interrupt a fiber that is + waiting on a blocking IO operation when the IO operation is closed. + [[Feature #21166]] ## Stdlib updates -* RubyGems and Bundler warn if users require gem that is scheduled to become the bundled gems - in the future version of Ruby. [[Feature #19351]] [[Feature #19776]] [[Feature #19843]] +The following bundled gems are promoted from default gems. -* Random::Formatter#alphanumeric is extended to accept optional `chars` - keyword argument. [[Feature #18183]] +* ostruct 0.6.2 +* pstore 0.2.0 +* benchmark 0.4.1 +* logger 1.7.0 +* rdoc 6.14.2 +* win32ole 1.9.2 +* irb 1.15.2 +* reline 0.6.1 +* readline 0.0.4 +* fiddle 1.1.8 -The following default gems are updated. +We only list stdlib changes that are notable feature changes. -* RubyGems 3.5.0.dev -* bigdecimal 3.1.4 -* bundler 2.5.0.dev -* csv 3.2.8 -* erb 4.0.3 -* fiddle 1.1.2 -* fileutils 1.7.1 -* irb 1.8.1 -* nkf 0.1.3 -* optparse 0.4.0.pre.1 -* psych 5.1.0 -* reline 0.3.8 -* stringio 3.0.9 -* strscan 3.0.7 -* syntax_suggest 1.1.0 -* time 0.2.2 -* timeout 0.4.0 -* uri 0.12.2 -* yarp 0.10.0 +Other changes are listed in the following sections. We also listed release +history from the previous bundled version that is Ruby 3.3.0 if it has GitHub +releases. -The following bundled gems are updated. +The following default gem is added. + +* win32-registry 0.1.0 + +The following default gems are updated. + +* RubyGems 3.7.0.dev +* bundler 2.7.0.dev +* erb 5.0.1 +* json 2.12.2 +* optparse 0.7.0.dev.2 +* prism 1.4.0 +* psych 5.2.6 +* resolv 0.6.2 +* stringio 3.1.8.dev +* strscan 3.1.6.dev +* uri 1.0.3 +* weakref 0.1.4 -* minitest 5.19.0 -* test-unit 3.6.1 -* rexml 3.2.6 -* rss 0.3.0 -* net-imap 0.3.7 -* rbs 3.2.1 -* typeprof 0.21.8 -* debug 1.8.0 +The following bundled gems are added. -The following default gem is now bundled. -* racc 1.7.1 +The following bundled gems are updated. -See GitHub releases like [Logger](https://github.com/ruby/logger/releases) or -changelog for details of the default gems or bundled gems. +* minitest 5.25.5 +* rake 13.3.0 +* test-unit 3.7.0 +* rexml 3.4.1 +* net-imap 0.5.9 +* net-smtp 0.5.1 +* matrix 0.4.3 +* prime 0.1.4 +* rbs 3.9.4 +* debug 1.11.0 +* base64 0.3.0 +* bigdecimal 3.2.2 +* drb 2.2.3 +* syslog 0.3.0 +* csv 3.3.5 +* repl_type_completor 0.1.11 ## Supported platforms ## Compatibility issues +* The following methods were removed from Ractor due because of `Ractor::Port`: + + * `Ractor.yield` + * `Ractor#take` + * `Ractor#close_incoming` + * `Ractor#close_outgoging` + + [[Feature #21262]] + ## Stdlib compatibility issues -* `racc` is promoted bundled gems. - * You need to add `racc` to your `Gemfile` if you use `racc` under bundler environment. -* `ext/readline` is retired - * We have `reline` that is pure Ruby implementation compatible with `ext/readline` API. We rely on `reline` in the future. If you need to use `ext/readline`, you can install `ext/readline` via rubygems.org with `gem install readline-ext`. - * We no longer need to install libraries like `libreadline` or `libedit`. +* CGI library is removed from the default gems. Now we only provide `cgi/escape` for + the following methods: + + * `CGI.escape` and `CGI.unescape` + * `CGI.escapeHTML` and `CGI.unescapeHTML` + * `CGI.escapeURIComponent` and `CGI.unescapeURIComponent` + * `CGI.escapeElement` and `CGI.unescapeElement` + + [[Feature #21258]] + +* With the move of `Set` from stdlib to core class, `set/sorted_set.rb` has + been removed, and `SortedSet` is no longer an autoloaded constant. Please + install the `sorted_set` gem and `require 'sorted_set'` to use `SortedSet`. + [[Feature #21287]] ## C API updates +* IO + + * `rb_thread_fd_close` is deprecated and now a no-op. If you need to expose + file descriptors from C extensions to Ruby code, create an `IO` instance + using `RUBY_IO_MODE_EXTERNAL` and use `rb_io_close(io)` to close it (this + also interrupts and waits for all pending operations on the `IO` + instance). Directly closing file descriptors does not interrupt pending + operations, and may lead to undefined behaviour. In other words, if two + `IO` objects share the same file descriptor, closing one does not affect + the other. [[Feature #18455]] + ## Implementation improvements -* `defined?(@ivar)` is optimized with Object Shapes. - -### YJIT - -* Major performance improvements over 3.2 - * Support for splat and rest arguments has been improved. - * Registers are allocated for stack operations of the virtual machine. - * More calls with optional arguments are compiled. - * Exception handlers are also compiled. - * Instance variables no longer exit to the interpreter - with megamorphic Object Shapes. - * Unsupported call types no longer exit to the interpreter. - * Integer#!=, String#!=, Kernel#block_given?, Kernel#is_a?, - Kernel#instance_of?, Module#=== are specially optimized. - * Now more than 3x faster than the interpreter on optcarrot! -* Metadata for compiled code uses a lot less memory. -* Generate more compact code on ARM64 -* Option to start YJIT in paused mode and then later enable it manually - * `--yjit-pause` and RubyVM::YJIT.resume - * This can be used to enable YJIT only once your application is done booting -* `ratio_in_yjit` stat produced by `--yjit-stats` is now avaiable in release builds, - a special stats or dev build is no longer required. -* Exit tracing option now supports sampling - * `--trace-exits-sample-rate=N` -* `--yjit-stats=quiet` is added to avoid printing stats on exit. -* The default value for `--yjit-exec-mem-size` is changed from 64 to 128. -* More thorough testing and multiple bug fixes - -### RJIT - -* Introduced a pure-Ruby JIT compiler RJIT and replaced MJIT. - * RJIT supports only x86\_64 architecture on Unix platforms. - * Unlike MJIT, it doesn't require a C compiler at runtime. -* RJIT exists only for experimental purposes. - * You should keep using YJIT in production. - -[Feature #18183]: https://bugs.ruby-lang.org/issues/18183 -[Feature #18498]: https://bugs.ruby-lang.org/issues/18498 -[Feature #18885]: https://bugs.ruby-lang.org/issues/18885 -[Bug #19150]: https://bugs.ruby-lang.org/issues/19150 -[Feature #19314]: https://bugs.ruby-lang.org/issues/19314 -[Feature #19347]: https://bugs.ruby-lang.org/issues/19347 -[Feature #19351]: https://bugs.ruby-lang.org/issues/19351 -[Feature #19521]: https://bugs.ruby-lang.org/issues/19521 -[Feature #19538]: https://bugs.ruby-lang.org/issues/19538 -[Feature #19591]: https://bugs.ruby-lang.org/issues/19591 -[Feature #19714]: https://bugs.ruby-lang.org/issues/19714 -[Feature #19776]: https://bugs.ruby-lang.org/issues/19776 -[Feature #19785]: https://bugs.ruby-lang.org/issues/19785 -[Feature #19843]: https://bugs.ruby-lang.org/issues/19843 +## JIT + +[Feature #18455]: https://bugs.ruby-lang.org/issues/18455 +[Feature #19908]: https://bugs.ruby-lang.org/issues/19908 +[Feature #20610]: https://bugs.ruby-lang.org/issues/20610 +[Feature #20724]: https://bugs.ruby-lang.org/issues/20724 +[Feature #21047]: https://bugs.ruby-lang.org/issues/21047 +[Bug #21049]: https://bugs.ruby-lang.org/issues/21049 +[Feature #21166]: https://bugs.ruby-lang.org/issues/21166 +[Feature #21216]: https://bugs.ruby-lang.org/issues/21216 +[Feature #21219]: https://bugs.ruby-lang.org/issues/21219 +[Feature #21258]: https://bugs.ruby-lang.org/issues/21258 +[Feature #21262]: https://bugs.ruby-lang.org/issues/21262 +[Feature #21287]: https://bugs.ruby-lang.org/issues/21287 +[Feature #21347]: https://bugs.ruby-lang.org/issues/21347 diff --git a/README.ja.md b/README.ja.md index 0d2d309fb89522..278285dc83db3c 100644 --- a/README.ja.md +++ b/README.ja.md @@ -1,10 +1,8 @@ [![Actions Status: MinGW](https://github.com/ruby/ruby/workflows/MinGW/badge.svg)](https://github.com/ruby/ruby/actions?query=workflow%3A"MinGW") -[![Actions Status: RJIT](https://github.com/ruby/ruby/workflows/RJIT/badge.svg)](https://github.com/ruby/ruby/actions?query=workflow%3A"RJIT") [![Actions Status: Ubuntu](https://github.com/ruby/ruby/workflows/Ubuntu/badge.svg)](https://github.com/ruby/ruby/actions?query=workflow%3A"Ubuntu") [![Actions Status: Windows](https://github.com/ruby/ruby/workflows/Windows/badge.svg)](https://github.com/ruby/ruby/actions?query=workflow%3A"Windows") [![AppVeyor status](https://ci.appveyor.com/api/projects/status/0sy8rrxut4o0k960/branch/master?svg=true)](https://ci.appveyor.com/project/ruby/ruby/branch/master) [![Travis Status](https://app.travis-ci.com/ruby/ruby.svg?branch=master)](https://app.travis-ci.com/ruby/ruby) -[![Cirrus Status](https://api.cirrus-ci.com/github/ruby/ruby.svg)](https://cirrus-ci.com/github/ruby/ruby/master) # Rubyとは @@ -41,11 +39,15 @@ https://www.ruby-lang.org/ja/downloads/ ミラーをGitHubに公開しています. 以下のコマンドでリポジトリを取得できます. - $ git clone https://github.com/ruby/ruby.git +```console +$ git clone https://github.com/ruby/ruby.git +``` 他のブランチの一覧は次のコマンドで見られます. - $ git ls-remote https://github.com/ruby/ruby.git +```console +$ git ls-remote https://github.com/ruby/ruby.git +``` Rubyリポジトリの本来のmasterは https://git.ruby-lang.org/ruby.git にあります. コミッタはこちらを使います. diff --git a/README.md b/README.md index c0cbf05b7a519a..5ed312cca872a0 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,7 @@ [![Actions Status: MinGW](https://github.com/ruby/ruby/workflows/MinGW/badge.svg)](https://github.com/ruby/ruby/actions?query=workflow%3A"MinGW") -[![Actions Status: RJIT](https://github.com/ruby/ruby/workflows/RJIT/badge.svg)](https://github.com/ruby/ruby/actions?query=workflow%3A"RJIT") [![Actions Status: Ubuntu](https://github.com/ruby/ruby/workflows/Ubuntu/badge.svg)](https://github.com/ruby/ruby/actions?query=workflow%3A"Ubuntu") [![Actions Status: Windows](https://github.com/ruby/ruby/workflows/Windows/badge.svg)](https://github.com/ruby/ruby/actions?query=workflow%3A"Windows") -[![AppVeyor status](https://ci.appveyor.com/api/projects/status/0sy8rrxut4o0k960/branch/master?svg=true)](https://ci.appveyor.com/project/ruby/ruby/branch/master) [![Travis Status](https://app.travis-ci.com/ruby/ruby.svg?branch=master)](https://app.travis-ci.com/ruby/ruby) -[![Cirrus Status](https://api.cirrus-ci.com/github/ruby/ruby.svg)](https://cirrus-ci.com/github/ruby/ruby/master) # What is Ruby? @@ -88,7 +85,7 @@ Bugs should be reported at https://bugs.ruby-lang.org. Read ["Reporting Issues"] ## Contributing -See ["Contributing to Ruby"](https://docs.ruby-lang.org/en/master/contributing_md.html), which includes setup and build instructions. +See ["Contributing to Ruby"](https://docs.ruby-lang.org/en/master/contributing/contributing_md.html), which includes setup and build instructions. ## The Author diff --git a/addr2line.c b/addr2line.c index 358eccc5fc841f..745364cc0f78e8 100644 --- a/addr2line.c +++ b/addr2line.c @@ -56,11 +56,11 @@ # ifdef _AIX #pragma alloca # else -# ifndef alloca /* predefined by HP cc +Olibcalls */ +# ifndef alloca /* predefined by HP cc +Olibcalls */ void *alloca(); # endif # endif /* AIX */ -# endif /* HAVE_ALLOCA_H */ +# endif /* HAVE_ALLOCA_H */ # ifndef UNREACHABLE # define UNREACHABLE __builtin_unreachable() # endif @@ -144,7 +144,7 @@ void *alloca(); #define DW_LNE_define_file 0x03 #define DW_LNE_set_discriminator 0x04 /* DWARF4 */ -#define kprintf(...) fprintf(stderr, "" __VA_ARGS__) +#define kprintf(...) fprintf(errout, "" __VA_ARGS__) typedef struct line_info { const char *dirname; @@ -220,13 +220,13 @@ uleb128(const char **p) unsigned long r = 0; int s = 0; for (;;) { - unsigned char b = (unsigned char)*(*p)++; - if (b < 0x80) { - r += (unsigned long)b << s; - break; - } - r += (b & 0x7f) << s; - s += 7; + unsigned char b = (unsigned char)*(*p)++; + if (b < 0x80) { + r += (unsigned long)b << s; + break; + } + r += (b & 0x7f) << s; + s += 7; } return r; } @@ -237,44 +237,48 @@ sleb128(const char **p) long r = 0; int s = 0; for (;;) { - unsigned char b = (unsigned char)*(*p)++; - if (b < 0x80) { - if (b & 0x40) { - r -= (0x80 - b) << s; - } - else { - r += (b & 0x3f) << s; - } - break; - } - r += (b & 0x7f) << s; - s += 7; + unsigned char b = (unsigned char)*(*p)++; + if (b < 0x80) { + if (b & 0x40) { + r -= (0x80 - b) << s; + } + else { + r += (b & 0x3f) << s; + } + break; + } + r += (b & 0x7f) << s; + s += 7; } return r; } static const char * -get_nth_dirname(unsigned long dir, const char *p) +get_nth_dirname(unsigned long dir, const char *p, FILE *errout) { if (!dir--) { - return ""; + return ""; } while (dir--) { - while (*p) p++; - p++; - if (!*p) { - kprintf("Unexpected directory number %lu in %s\n", - dir, binary_filename); - return ""; - } + while (*p) p++; + p++; + if (!*p) { + kprintf("Unexpected directory number %lu in %s\n", + dir, binary_filename); + return ""; + } } return p; } -static const char *parse_ver5_debug_line_header(const char *p, int idx, uint8_t format, obj_info_t *obj, const char **out_path, uint64_t *out_directory_index); +static const char *parse_ver5_debug_line_header( + const char *p, int idx, uint8_t format, + obj_info_t *obj, const char **out_path, + uint64_t *out_directory_index, FILE *errout); static void -fill_filename(int file, uint8_t format, uint16_t version, const char *include_directories, const char *filenames, line_info_t *line, obj_info_t *obj) +fill_filename(int file, uint8_t format, uint16_t version, const char *include_directories, + const char *filenames, line_info_t *line, obj_info_t *obj, FILE *errout) { int i; const char *p = filenames; @@ -283,18 +287,20 @@ fill_filename(int file, uint8_t format, uint16_t version, const char *include_di if (version >= 5) { const char *path; uint64_t directory_index = -1; - parse_ver5_debug_line_header(filenames, file, format, obj, &path, &directory_index); + parse_ver5_debug_line_header(filenames, file, format, obj, &path, &directory_index, errout); line->filename = path; - parse_ver5_debug_line_header(include_directories, (int)directory_index, format, obj, &path, NULL); + parse_ver5_debug_line_header(include_directories, (int)directory_index, format, obj, &path, NULL, errout); line->dirname = path; } else { for (i = 1; i <= file; i++) { filename = p; if (!*p) { +#ifndef __APPLE__ /* Need to output binary file name? */ kprintf("Unexpected file number %d in %s at %tx\n", file, binary_filename, filenames - obj->mapped); +#endif return; } while (*p) p++; @@ -307,7 +313,7 @@ fill_filename(int file, uint8_t format, uint16_t version, const char *include_di if (i == file) { line->filename = filename; - line->dirname = get_nth_dirname(dir, include_directories); + line->dirname = get_nth_dirname(dir, include_directories, errout); } } } @@ -315,19 +321,19 @@ fill_filename(int file, uint8_t format, uint16_t version, const char *include_di static void fill_line(int num_traces, void **traces, uintptr_t addr, int file, int line, - uint8_t format, uint16_t version, const char *include_directories, const char *filenames, - obj_info_t *obj, line_info_t *lines, int offset) + uint8_t format, uint16_t version, const char *include_directories, const char *filenames, + obj_info_t *obj, line_info_t *lines, int offset, FILE *errout) { int i; addr += obj->base_addr - obj->vmaddr; for (i = offset; i < num_traces; i++) { - uintptr_t a = (uintptr_t)traces[i]; - /* We assume one line code doesn't result >100 bytes of native code. + uintptr_t a = (uintptr_t)traces[i]; + /* We assume one line code doesn't result >100 bytes of native code. We may want more reliable way eventually... */ - if (addr < a && a < addr + 100) { - fill_filename(file, format, version, include_directories, filenames, &lines[i], obj); - lines[i].line = line; - } + if (addr < a && a < addr + 100) { + fill_filename(file, format, version, include_directories, filenames, &lines[i], obj, errout); + lines[i].line = line; + } } } @@ -350,7 +356,7 @@ struct LineNumberProgramHeader { }; static int -parse_debug_line_header(obj_info_t *obj, const char **pp, struct LineNumberProgramHeader *header) +parse_debug_line_header(obj_info_t *obj, const char **pp, struct LineNumberProgramHeader *header, FILE *errout) { const char *p = *pp; header->unit_length = *(uint32_t *)p; @@ -358,8 +364,8 @@ parse_debug_line_header(obj_info_t *obj, const char **pp, struct LineNumberProgr header->format = 4; if (header->unit_length == 0xffffffff) { - header->unit_length = *(uint64_t *)p; - p += sizeof(uint64_t); + header->unit_length = *(uint64_t *)p; + p += sizeof(uint64_t); header->format = 8; } @@ -396,7 +402,7 @@ parse_debug_line_header(obj_info_t *obj, const char **pp, struct LineNumberProgr if (header->version >= 5) { header->include_directories = p; - p = parse_ver5_debug_line_header(p, -1, header->format, obj, NULL, NULL); + p = parse_ver5_debug_line_header(p, -1, header->format, obj, NULL, NULL, errout); header->filenames = p; } else { @@ -423,7 +429,7 @@ parse_debug_line_header(obj_info_t *obj, const char **pp, struct LineNumberProgr static int parse_debug_line_cu(int num_traces, void **traces, const char **debug_line, - obj_info_t *obj, line_info_t *lines, int offset) + obj_info_t *obj, line_info_t *lines, int offset, FILE *errout) { const char *p = (const char *)*debug_line; struct LineNumberProgramHeader header; @@ -440,109 +446,109 @@ parse_debug_line_cu(int num_traces, void **traces, const char **debug_line, /* int epilogue_begin = 0; */ /* unsigned int isa = 0; */ - if (parse_debug_line_header(obj, &p, &header)) + if (parse_debug_line_header(obj, &p, &header, errout)) return -1; is_stmt = header.default_is_stmt; -#define FILL_LINE() \ - do { \ - fill_line(num_traces, traces, addr, file, line, \ +#define FILL_LINE() \ + do { \ + fill_line(num_traces, traces, addr, file, line, \ header.format, \ header.version, \ header.include_directories, \ header.filenames, \ - obj, lines, offset); \ - /*basic_block = prologue_end = epilogue_begin = 0;*/ \ + obj, lines, offset, errout); \ + /*basic_block = prologue_end = epilogue_begin = 0;*/ \ } while (0) while (p < header.cu_end) { - unsigned long a; - unsigned char op = *p++; - switch (op) { - case DW_LNS_copy: - FILL_LINE(); - break; - case DW_LNS_advance_pc: - a = uleb128(&p) * header.minimum_instruction_length; - addr += a; - break; - case DW_LNS_advance_line: { - long a = sleb128(&p); - line += a; - break; - } - case DW_LNS_set_file: - file = (unsigned int)uleb128(&p); - break; - case DW_LNS_set_column: - /*column = (unsigned int)*/(void)uleb128(&p); - break; - case DW_LNS_negate_stmt: - is_stmt = !is_stmt; - break; - case DW_LNS_set_basic_block: - /*basic_block = 1; */ - break; - case DW_LNS_const_add_pc: - a = ((255UL - header.opcode_base) / header.line_range) * - header.minimum_instruction_length; - addr += a; - break; - case DW_LNS_fixed_advance_pc: - a = *(uint16_t *)p; - p += sizeof(uint16_t); - addr += a; - break; - case DW_LNS_set_prologue_end: - /* prologue_end = 1; */ - break; - case DW_LNS_set_epilogue_begin: - /* epilogue_begin = 1; */ - break; - case DW_LNS_set_isa: - /* isa = (unsigned int)*/(void)uleb128(&p); - break; - case 0: - a = uleb128(&p); - op = *p++; - switch (op) { - case DW_LNE_end_sequence: - /* end_sequence = 1; */ - FILL_LINE(); - addr = 0; - file = 1; - line = 1; - /* column = 0; */ - is_stmt = header.default_is_stmt; - /* end_sequence = 0; */ - /* isa = 0; */ - break; - case DW_LNE_set_address: - addr = *(unsigned long *)p; - p += sizeof(unsigned long); - break; - case DW_LNE_define_file: - kprintf("Unsupported operation in %s\n", - binary_filename); - break; - case DW_LNE_set_discriminator: - /* TODO:currently ignore */ - uleb128(&p); - break; - default: - kprintf("Unknown extended opcode: %d in %s\n", - op, binary_filename); - } - break; - default: { + unsigned long a; + unsigned char op = *p++; + switch (op) { + case DW_LNS_copy: + FILL_LINE(); + break; + case DW_LNS_advance_pc: + a = uleb128(&p) * header.minimum_instruction_length; + addr += a; + break; + case DW_LNS_advance_line: { + long a = sleb128(&p); + line += a; + break; + } + case DW_LNS_set_file: + file = (unsigned int)uleb128(&p); + break; + case DW_LNS_set_column: + /*column = (unsigned int)*/(void)uleb128(&p); + break; + case DW_LNS_negate_stmt: + is_stmt = !is_stmt; + break; + case DW_LNS_set_basic_block: + /*basic_block = 1; */ + break; + case DW_LNS_const_add_pc: + a = ((255UL - header.opcode_base) / header.line_range) * + header.minimum_instruction_length; + addr += a; + break; + case DW_LNS_fixed_advance_pc: + a = *(uint16_t *)p; + p += sizeof(uint16_t); + addr += a; + break; + case DW_LNS_set_prologue_end: + /* prologue_end = 1; */ + break; + case DW_LNS_set_epilogue_begin: + /* epilogue_begin = 1; */ + break; + case DW_LNS_set_isa: + /* isa = (unsigned int)*/(void)uleb128(&p); + break; + case 0: + a = uleb128(&p); + op = *p++; + switch (op) { + case DW_LNE_end_sequence: + /* end_sequence = 1; */ + FILL_LINE(); + addr = 0; + file = 1; + line = 1; + /* column = 0; */ + is_stmt = header.default_is_stmt; + /* end_sequence = 0; */ + /* isa = 0; */ + break; + case DW_LNE_set_address: + addr = *(unsigned long *)p; + p += sizeof(unsigned long); + break; + case DW_LNE_define_file: + kprintf("Unsupported operation in %s\n", + binary_filename); + break; + case DW_LNE_set_discriminator: + /* TODO:currently ignore */ + uleb128(&p); + break; + default: + kprintf("Unknown extended opcode: %d in %s\n", + op, binary_filename); + } + break; + default: { uint8_t adjusted_opcode = op - header.opcode_base; uint8_t operation_advance = adjusted_opcode / header.line_range; /* NOTE: this code doesn't support VLIW */ addr += operation_advance * header.minimum_instruction_length; line += header.line_base + (adjusted_opcode % header.line_range); - FILL_LINE(); - } - } + FILL_LINE(); + } + } } *debug_line = (char *)p; return 0; @@ -550,17 +556,17 @@ parse_debug_line_cu(int num_traces, void **traces, const char **debug_line, static int parse_debug_line(int num_traces, void **traces, - const char *debug_line, unsigned long size, - obj_info_t *obj, line_info_t *lines, int offset) + const char *debug_line, unsigned long size, + obj_info_t *obj, line_info_t *lines, int offset, FILE *errout) { const char *debug_line_end = debug_line + size; while (debug_line < debug_line_end) { - if (parse_debug_line_cu(num_traces, traces, &debug_line, obj, lines, offset)) - return -1; + if (parse_debug_line_cu(num_traces, traces, &debug_line, obj, lines, offset, errout)) + return -1; } if (debug_line != debug_line_end) { - kprintf("Unexpected size of .debug_line in %s\n", - binary_filename); + kprintf("Unexpected size of .debug_line in %s\n", + binary_filename); } return 0; } @@ -568,7 +574,7 @@ parse_debug_line(int num_traces, void **traces, /* read file and fill lines */ static uintptr_t fill_lines(int num_traces, void **traces, int check_debuglink, - obj_info_t **objp, line_info_t *lines, int offset); + obj_info_t **objp, line_info_t *lines, int offset, FILE *errout); static void append_obj(obj_info_t **objp) @@ -596,7 +602,7 @@ append_obj(obj_info_t **objp) // check the path pattern of "/usr/lib/debug/usr/bin/ruby.debug" static void follow_debuglink(const char *debuglink, int num_traces, void **traces, - obj_info_t **objp, line_info_t *lines, int offset) + obj_info_t **objp, line_info_t *lines, int offset, FILE *errout) { static const char global_debug_dir[] = "/usr/lib/debug"; const size_t global_debug_dir_len = sizeof(global_debug_dir) - 1; @@ -606,13 +612,13 @@ follow_debuglink(const char *debuglink, int num_traces, void **traces, p = strrchr(binary_filename, '/'); if (!p) { - return; + return; } p[1] = '\0'; len = strlen(binary_filename); if (len >= PATH_MAX - global_debug_dir_len) - len = PATH_MAX - global_debug_dir_len - 1; + len = PATH_MAX - global_debug_dir_len - 1; memmove(binary_filename + global_debug_dir_len, binary_filename, len); memcpy(binary_filename, global_debug_dir, global_debug_dir_len); len += global_debug_dir_len; @@ -622,13 +628,13 @@ follow_debuglink(const char *debuglink, int num_traces, void **traces, o2 = *objp; o2->base_addr = o1->base_addr; o2->path = o1->path; - fill_lines(num_traces, traces, 0, objp, lines, offset); + fill_lines(num_traces, traces, 0, objp, lines, offset, errout); } // check the path pattern of "/usr/lib/debug/.build-id/ab/cdef1234.debug" static void follow_debuglink_build_id(const char *build_id, size_t build_id_size, int num_traces, void **traces, - obj_info_t **objp, line_info_t *lines, int offset) + obj_info_t **objp, line_info_t *lines, int offset, FILE *errout) { static const char global_debug_dir[] = "/usr/lib/debug/.build-id/"; const size_t global_debug_dir_len = sizeof(global_debug_dir) - 1; @@ -653,7 +659,7 @@ follow_debuglink_build_id(const char *build_id, size_t build_id_size, int num_tr o2 = *objp; o2->base_addr = o1->base_addr; o2->path = o1->path; - fill_lines(num_traces, traces, 0, objp, lines, offset); + fill_lines(num_traces, traces, 0, objp, lines, offset, errout); } #endif @@ -1079,13 +1085,13 @@ di_read_debug_abbrev_cu(DebugInfoReader *reader) } static int -di_read_debug_line_cu(DebugInfoReader *reader) +di_read_debug_line_cu(DebugInfoReader *reader, FILE *errout) { const char *p; struct LineNumberProgramHeader header; p = (const char *)reader->debug_line_cu_end; - if (parse_debug_line_header(reader->obj, &p, &header)) + if (parse_debug_line_header(reader->obj, &p, &header, errout)) return -1; reader->debug_line_cu_end = (char *)header.cu_end; @@ -1186,7 +1192,7 @@ debug_info_reader_read_addr_value_member(DebugInfoReader *reader, DebugInfoValue static bool -debug_info_reader_read_value(DebugInfoReader *reader, uint64_t form, DebugInfoValue *v) +debug_info_reader_read_value(DebugInfoReader *reader, uint64_t form, DebugInfoValue *v, FILE *errout) { switch (form) { case DW_FORM_addr: @@ -1369,7 +1375,7 @@ debug_info_reader_read_value(DebugInfoReader *reader, uint64_t form, DebugInfoVa /* find abbrev in current compilation unit */ static const char * -di_find_abbrev(DebugInfoReader *reader, uint64_t abbrev_number) +di_find_abbrev(DebugInfoReader *reader, uint64_t abbrev_number, FILE *errout) { const char *p; if (abbrev_number < ABBREV_TABLE_SIZE) { @@ -1394,7 +1400,7 @@ di_find_abbrev(DebugInfoReader *reader, uint64_t abbrev_number) #if 0 static void -hexdump0(const unsigned char *p, size_t n) +hexdump0(const unsigned char *p, size_t n, FILE *errout) { size_t i; kprintf(" 0 1 2 3 4 5 6 7 8 9 A B C D E F\n"); @@ -1415,10 +1421,10 @@ hexdump0(const unsigned char *p, size_t n) kprintf("\n"); } } -#define hexdump(p,n) hexdump0((const unsigned char *)p, n) +#define hexdump(p,n,e) hexdump0((const unsigned char *)p, n, e) static void -div_inspect(DebugInfoValue *v) +div_inspect(DebugInfoValue *v, FILE *errout) { switch (v->type) { case VAL_uint: @@ -1432,14 +1438,14 @@ div_inspect(DebugInfoValue *v) break; case VAL_data: kprintf("%d: type:%d size:%" PRIxSIZE " v:\n",__LINE__,v->type,v->size); - hexdump(v->as.ptr, 16); + hexdump(v->as.ptr, 16, errout); break; } } #endif static DIE * -di_read_die(DebugInfoReader *reader, DIE *die) +di_read_die(DebugInfoReader *reader, DIE *die, FILE *errout) { uint64_t abbrev_number = uleb128(&reader->p); if (abbrev_number == 0) { @@ -1447,7 +1453,7 @@ di_read_die(DebugInfoReader *reader, DIE *die) return NULL; } - if (!(reader->q = di_find_abbrev(reader, abbrev_number))) return NULL; + if (!(reader->q = di_find_abbrev(reader, abbrev_number, errout))) return NULL; die->pos = reader->p - reader->obj->debug_info.ptr - 1; die->tag = (int)uleb128(&reader->q); /* tag */ @@ -1459,26 +1465,26 @@ di_read_die(DebugInfoReader *reader, DIE *die) } static DebugInfoValue * -di_read_record(DebugInfoReader *reader, DebugInfoValue *vp) +di_read_record(DebugInfoReader *reader, DebugInfoValue *vp, FILE *errout) { uint64_t at = uleb128(&reader->q); uint64_t form = uleb128(&reader->q); if (!at || !form) return NULL; vp->at = at; vp->form = form; - if (!debug_info_reader_read_value(reader, form, vp)) return NULL; + if (!debug_info_reader_read_value(reader, form, vp, errout)) return NULL; return vp; } static bool -di_skip_records(DebugInfoReader *reader) +di_skip_records(DebugInfoReader *reader, FILE *errout) { for (;;) { DebugInfoValue v = {{0}}; uint64_t at = uleb128(&reader->q); uint64_t form = uleb128(&reader->q); if (!at || !form) return true; - if (!debug_info_reader_read_value(reader, form, &v)) return false; + if (!debug_info_reader_read_value(reader, form, &v, errout)) return false; } } @@ -1491,12 +1497,13 @@ typedef struct addr_header { } addr_header_t; static bool -addr_header_init(obj_info_t *obj, addr_header_t *header) { +addr_header_init(obj_info_t *obj, addr_header_t *header, FILE *errout) +{ const char *p = obj->debug_addr.ptr; header->ptr = p; - if (!p) return false; + if (!p) return true; header->unit_length = *(uint32_t *)p; p += sizeof(uint32_t); @@ -1536,10 +1543,11 @@ typedef struct rnglists_header { } rnglists_header_t; static bool -rnglists_header_init(obj_info_t *obj, rnglists_header_t *header) { +rnglists_header_init(obj_info_t *obj, rnglists_header_t *header, FILE *errout) +{ const char *p = obj->debug_rnglists.ptr; - if (!p) return false; + if (!p) return true; header->unit_length = *(uint32_t *)p; p += sizeof(uint32_t); @@ -1603,7 +1611,7 @@ ranges_set(ranges_t *ptr, DebugInfoValue *v, addr_header_t *addr_header, uint64_ } static uint64_t -read_dw_form_addr(DebugInfoReader *reader, const char **ptr) +read_dw_form_addr(DebugInfoReader *reader, const char **ptr, FILE *errout) { const char *p = *ptr; *ptr = p + reader->address_size; @@ -1615,7 +1623,7 @@ read_dw_form_addr(DebugInfoReader *reader, const char **ptr) } static uintptr_t -ranges_include(DebugInfoReader *reader, ranges_t *ptr, uint64_t addr, rnglists_header_t *rnglists_header) +ranges_include(DebugInfoReader *reader, ranges_t *ptr, uint64_t addr, rnglists_header_t *rnglists_header, FILE *errout) { if (ptr->high_pc_set) { if (ptr->ranges_set || !ptr->low_pc_set) { @@ -1668,15 +1676,15 @@ ranges_include(DebugInfoReader *reader, ranges_t *ptr, uint64_t addr, rnglists_h to = (uintptr_t)base + uleb128(&p); break; case DW_RLE_base_address: - base = read_dw_form_addr(reader, &p); + base = read_dw_form_addr(reader, &p, errout); base_valid = true; break; case DW_RLE_start_end: - from = (uintptr_t)read_dw_form_addr(reader, &p); - to = (uintptr_t)read_dw_form_addr(reader, &p); + from = (uintptr_t)read_dw_form_addr(reader, &p, errout); + to = (uintptr_t)read_dw_form_addr(reader, &p, errout); break; case DW_RLE_start_length: - from = (uintptr_t)read_dw_form_addr(reader, &p); + from = (uintptr_t)read_dw_form_addr(reader, &p, errout); to = from + uleb128(&p); break; } @@ -1710,7 +1718,7 @@ ranges_include(DebugInfoReader *reader, ranges_t *ptr, uint64_t addr, rnglists_h #if 0 static void -ranges_inspect(DebugInfoReader *reader, ranges_t *ptr) +ranges_inspect(DebugInfoReader *reader, ranges_t *ptr, FILE *errout) { if (ptr->high_pc_set) { if (ptr->ranges_set || !ptr->low_pc_set) { @@ -1740,7 +1748,7 @@ ranges_inspect(DebugInfoReader *reader, ranges_t *ptr) #endif static int -di_read_cu(DebugInfoReader *reader) +di_read_cu(DebugInfoReader *reader, FILE *errout) { uint64_t unit_length; uint16_t version; @@ -1775,15 +1783,15 @@ di_read_cu(DebugInfoReader *reader) reader->level = 0; di_read_debug_abbrev_cu(reader); - if (di_read_debug_line_cu(reader)) return -1; + if (di_read_debug_line_cu(reader, errout)) return -1; do { DIE die; - if (!di_read_die(reader, &die)) continue; + if (!di_read_die(reader, &die, errout)) continue; if (die.tag != DW_TAG_compile_unit) { - if (!di_skip_records(reader)) return -1; + if (!di_skip_records(reader, errout)) return -1; break; } @@ -1795,7 +1803,7 @@ di_read_cu(DebugInfoReader *reader) /* enumerate abbrev */ for (;;) { DebugInfoValue v = {{0}}; - if (!di_read_record(reader, &v)) break; + if (!di_read_record(reader, &v, errout)) break; switch (v.at) { case DW_AT_low_pc: // clang may output DW_AT_addr_base after DW_AT_low_pc. @@ -1821,7 +1829,7 @@ di_read_cu(DebugInfoReader *reader) case VAL_addr: { addr_header_t header = {0}; - if (!addr_header_init(reader->obj, &header)) return -1; + if (!addr_header_init(reader->obj, &header, errout)) return -1; reader->current_low_pc = read_addr(&header, reader->current_addr_base, low_pc.as.addr_idx); } break; @@ -1832,7 +1840,7 @@ di_read_cu(DebugInfoReader *reader) } static void -read_abstract_origin(DebugInfoReader *reader, uint64_t form, uint64_t abstract_origin, line_info_t *line) +read_abstract_origin(DebugInfoReader *reader, uint64_t form, uint64_t abstract_origin, line_info_t *line, FILE *errout) { const char *p = reader->p; const char *q = reader->q; @@ -1857,12 +1865,12 @@ read_abstract_origin(DebugInfoReader *reader, uint64_t form, uint64_t abstract_o default: goto finish; } - if (!di_read_die(reader, &die)) goto finish; + if (!di_read_die(reader, &die, errout)) goto finish; /* enumerate abbrev */ for (;;) { DebugInfoValue v = {{0}}; - if (!di_read_record(reader, &v)) break; + if (!di_read_record(reader, &v, errout)) break; switch (v.at) { case DW_AT_name: line->sname = get_cstr_value(&v); @@ -1878,25 +1886,26 @@ read_abstract_origin(DebugInfoReader *reader, uint64_t form, uint64_t abstract_o static bool debug_info_read(DebugInfoReader *reader, int num_traces, void **traces, - line_info_t *lines, int offset) { + line_info_t *lines, int offset, FILE *errout) +{ addr_header_t addr_header = {0}; - if (!addr_header_init(reader->obj, &addr_header)) return false; + if (!addr_header_init(reader->obj, &addr_header, errout)) return false; rnglists_header_t rnglists_header = {0}; - if (!rnglists_header_init(reader->obj, &rnglists_header)) return false; + if (!rnglists_header_init(reader->obj, &rnglists_header, errout)) return false; while (reader->p < reader->cu_end) { DIE die; ranges_t ranges = {0}; line_info_t line = {0}; - if (!di_read_die(reader, &die)) continue; + if (!di_read_die(reader, &die, errout)) continue; /* kprintf("%d:%tx: <%d>\n",__LINE__,die.pos,reader->level,die.tag); */ if (die.tag != DW_TAG_subprogram && die.tag != DW_TAG_inlined_subroutine) { skip_die: - if (!di_skip_records(reader)) return false; + if (!di_skip_records(reader, errout)) return false; continue; } @@ -1904,15 +1913,15 @@ debug_info_read(DebugInfoReader *reader, int num_traces, void **traces, for (;;) { DebugInfoValue v = {{0}}; /* ptrdiff_t pos = reader->p - reader->p0; */ - if (!di_read_record(reader, &v)) break; + if (!di_read_record(reader, &v, errout)) break; /* kprintf("\n%d:%tx: AT:%lx FORM:%lx\n",__LINE__,pos,v.at,v.form); */ - /* div_inspect(&v); */ + /* div_inspect(&v, errout); */ switch (v.at) { case DW_AT_name: line.sname = get_cstr_value(&v); break; case DW_AT_call_file: - fill_filename((int)v.as.uint64, reader->debug_line_format, reader->debug_line_version, reader->debug_line_directories, reader->debug_line_files, &line, reader->obj); + fill_filename((int)v.as.uint64, reader->debug_line_format, reader->debug_line_version, reader->debug_line_directories, reader->debug_line_files, &line, reader->obj, errout); break; case DW_AT_call_line: line.line = (int)v.as.uint64; @@ -1928,16 +1937,16 @@ debug_info_read(DebugInfoReader *reader, int num_traces, void **traces, /* 1 or 3 */ break; /* goto skip_die; */ case DW_AT_abstract_origin: - read_abstract_origin(reader, v.form, v.as.uint64, &line); + read_abstract_origin(reader, v.form, v.as.uint64, &line, errout); break; /* goto skip_die; */ } } - /* ranges_inspect(reader, &ranges); */ + /* ranges_inspect(reader, &ranges, errout); */ /* kprintf("%d:%tx: %x ",__LINE__,diepos,die.tag); */ for (int i=offset; i < num_traces; i++) { uintptr_t addr = (uintptr_t)traces[i]; uintptr_t offset = addr - reader->obj->base_addr + reader->obj->vmaddr; - uintptr_t saddr = ranges_include(reader, &ranges, offset, &rnglists_header); + uintptr_t saddr = ranges_include(reader, &ranges, offset, &rnglists_header, errout); if (saddr == UINTPTR_MAX) return false; if (saddr) { /* kprintf("%d:%tx: %d %lx->%lx %x %s: %s/%s %d %s %s %s\n",__LINE__,die.pos, i,addr,offset, die.tag,line.sname,line.dirname,line.filename,line.line,reader->obj->path,line.sname,lines[i].sname); */ @@ -1976,7 +1985,10 @@ debug_info_read(DebugInfoReader *reader, int num_traces, void **traces, // // It records DW_LNCT_path and DW_LNCT_directory_index at the index "idx". static const char * -parse_ver5_debug_line_header(const char *p, int idx, uint8_t format, obj_info_t *obj, const char **out_path, uint64_t *out_directory_index) { +parse_ver5_debug_line_header(const char *p, int idx, uint8_t format, + obj_info_t *obj, const char **out_path, + uint64_t *out_directory_index, FILE *errout) +{ int i, j; int entry_format_count = *(uint8_t *)p++; const char *entry_format = p; @@ -1996,7 +2008,7 @@ parse_ver5_debug_line_header(const char *p, int idx, uint8_t format, obj_info_t DebugInfoValue v = {{0}}; unsigned long dw_lnct = uleb128(&format); unsigned long dw_form = uleb128(&format); - if (!debug_info_reader_read_value(&reader, dw_form, &v)) return 0; + if (!debug_info_reader_read_value(&reader, dw_form, &v, errout)) return 0; if (dw_lnct == 1 /* DW_LNCT_path */ && v.type == VAL_cstr && out_path) *out_path = v.as.ptr + v.off; if (dw_lnct == 2 /* DW_LNCT_directory_index */ && v.type == VAL_uint && out_directory_index) @@ -2019,14 +2031,14 @@ uncompress_debug_section(ElfW(Shdr) *shdr, char *file, char **ptr) int ret = 0; if (chdr->ch_type != ELFCOMPRESS_ZLIB) { - /* unsupported compression type */ - return 0; + /* unsupported compression type */ + return 0; } *ptr = malloc(destsize); if (!*ptr) return 0; ret = uncompress((Bytef *)*ptr, &destsize, - (const Bytef*)chdr + sizeof(ElfW(Chdr)), + (const Bytef*)chdr + sizeof(ElfW(Chdr)), shdr->sh_size - sizeof(ElfW(Chdr))); if (ret != Z_OK) goto fail; return destsize; @@ -2041,7 +2053,7 @@ uncompress_debug_section(ElfW(Shdr) *shdr, char *file, char **ptr) /* read file and fill lines */ static uintptr_t fill_lines(int num_traces, void **traces, int check_debuglink, - obj_info_t **objp, line_info_t *lines, int offset) + obj_info_t **objp, line_info_t *lines, int offset, FILE *errout) { int i, j; char *shstr; @@ -2059,40 +2071,40 @@ fill_lines(int num_traces, void **traces, int check_debuglink, fd = open(binary_filename, O_RDONLY); if (fd < 0) { - goto fail; + goto fail; } filesize = lseek(fd, 0, SEEK_END); if (filesize < 0) { - int e = errno; - close(fd); - kprintf("lseek: %s\n", strerror(e)); - goto fail; + int e = errno; + close(fd); + kprintf("lseek: %s\n", strerror(e)); + goto fail; } #if SIZEOF_OFF_T > SIZEOF_SIZE_T if (filesize > (off_t)SIZE_MAX) { - close(fd); - kprintf("Too large file %s\n", binary_filename); - goto fail; + close(fd); + kprintf("Too large file %s\n", binary_filename); + goto fail; } #endif lseek(fd, 0, SEEK_SET); /* async-signal unsafe */ file = (char *)mmap(NULL, (size_t)filesize, PROT_READ, MAP_SHARED, fd, 0); if (file == MAP_FAILED) { - int e = errno; - close(fd); - kprintf("mmap: %s\n", strerror(e)); - goto fail; + int e = errno; + close(fd); + kprintf("mmap: %s\n", strerror(e)); + goto fail; } close(fd); ehdr = (ElfW(Ehdr) *)file; if (memcmp(ehdr->e_ident, "\177ELF", 4) != 0) { - /* - * Huh? Maybe filename was overridden by setproctitle() and - * it match non-elf file. - */ - goto fail; + /* + * Huh? Maybe filename was overridden by setproctitle() and + * it match non-elf file. + */ + goto fail; } obj->mapped = file; obj->mapped_size = (size_t)filesize; @@ -2104,32 +2116,32 @@ fill_lines(int num_traces, void **traces, int check_debuglink, for (i = 0; i < ehdr->e_shnum; i++) { char *section_name = shstr + shdr[i].sh_name; - switch (shdr[i].sh_type) { - case SHT_STRTAB: - if (!strcmp(section_name, ".strtab")) { - strtab_shdr = shdr + i; - } - else if (!strcmp(section_name, ".dynstr")) { - dynstr_shdr = shdr + i; - } - break; - case SHT_SYMTAB: - /* if (!strcmp(section_name, ".symtab")) */ - symtab_shdr = shdr + i; - break; - case SHT_DYNSYM: - /* if (!strcmp(section_name, ".dynsym")) */ - dynsym_shdr = shdr + i; - break; + switch (shdr[i].sh_type) { + case SHT_STRTAB: + if (!strcmp(section_name, ".strtab")) { + strtab_shdr = shdr + i; + } + else if (!strcmp(section_name, ".dynstr")) { + dynstr_shdr = shdr + i; + } + break; + case SHT_SYMTAB: + /* if (!strcmp(section_name, ".symtab")) */ + symtab_shdr = shdr + i; + break; + case SHT_DYNSYM: + /* if (!strcmp(section_name, ".dynsym")) */ + dynsym_shdr = shdr + i; + break; case SHT_NOTE: if (!strcmp(section_name, ".note.gnu.build-id")) { note_gnu_build_id = shdr + i; } break; - case SHT_PROGBITS: - if (!strcmp(section_name, ".gnu_debuglink")) { - gnu_debuglink_shdr = shdr + i; - } + case SHT_PROGBITS: + if (!strcmp(section_name, ".gnu_debuglink")) { + gnu_debuglink_shdr = shdr + i; + } else { const char *debug_section_names[] = { ".debug_abbrev", @@ -2159,17 +2171,16 @@ fill_lines(int num_traces, void **traces, int check_debuglink, break; } } - break; - } + break; + } } - if (offset == -1) { - /* main executable */ - offset = 0; - if (dynsym_shdr && dynstr_shdr) { - char *strtab = file + dynstr_shdr->sh_offset; - ElfW(Sym) *symtab = (ElfW(Sym) *)(file + dynsym_shdr->sh_offset); - int symtab_count = (int)(dynsym_shdr->sh_size / sizeof(ElfW(Sym))); + if (offset == 0) { + /* main executable */ + if (dynsym_shdr && dynstr_shdr) { + char *strtab = file + dynstr_shdr->sh_offset; + ElfW(Sym) *symtab = (ElfW(Sym) *)(file + dynsym_shdr->sh_offset); + int symtab_count = (int)(dynsym_shdr->sh_size / sizeof(ElfW(Sym))); void *handle = dlopen(NULL, RTLD_NOW|RTLD_LOCAL); if (handle) { for (j = 0; j < symtab_count; j++) { @@ -2186,14 +2197,14 @@ fill_lines(int num_traces, void **traces, int check_debuglink, } dlclose(handle); } - if (ehdr->e_type == ET_EXEC) { - obj->base_addr = 0; - } - else { - /* PIE (position-independent executable) */ - obj->base_addr = dladdr_fbase; - } - } + if (ehdr->e_type == ET_EXEC) { + obj->base_addr = 0; + } + else { + /* PIE (position-independent executable) */ + obj->base_addr = dladdr_fbase; + } + } } if (obj->debug_info.ptr && obj->debug_abbrev.ptr) { @@ -2202,8 +2213,8 @@ fill_lines(int num_traces, void **traces, int check_debuglink, i = 0; while (reader.p < reader.pend) { /* kprintf("%d:%tx: CU[%d]\n", __LINE__, reader.p - reader.obj->debug_info.ptr, i++); */ - if (di_read_cu(&reader)) goto use_symtab; - if (!debug_info_read(&reader, num_traces, traces, lines, offset)) + if (di_read_cu(&reader, errout)) goto use_symtab; + if (!debug_info_read(&reader, num_traces, traces, lines, offset, errout)) goto use_symtab; } } @@ -2239,27 +2250,27 @@ fill_lines(int num_traces, void **traces, int check_debuglink, } if (!obj->debug_line.ptr) { - /* This file doesn't have .debug_line section, - let's check .gnu_debuglink section instead. */ - if (gnu_debuglink_shdr && check_debuglink) { - follow_debuglink(file + gnu_debuglink_shdr->sh_offset, - num_traces, traces, - objp, lines, offset); - } + /* This file doesn't have .debug_line section, + let's check .gnu_debuglink section instead. */ + if (gnu_debuglink_shdr && check_debuglink) { + follow_debuglink(file + gnu_debuglink_shdr->sh_offset, + num_traces, traces, + objp, lines, offset, errout); + } if (note_gnu_build_id && check_debuglink) { ElfW(Nhdr) *nhdr = (ElfW(Nhdr)*) (file + note_gnu_build_id->sh_offset); const char *build_id = (char *)(nhdr + 1) + nhdr->n_namesz; follow_debuglink_build_id(build_id, nhdr->n_descsz, - num_traces, traces, - objp, lines, offset); + num_traces, traces, + objp, lines, offset, errout); } - goto finish; + goto finish; } if (parse_debug_line(num_traces, traces, obj->debug_line.ptr, obj->debug_line.size, - obj, lines, offset) == -1) + obj, lines, offset, errout) == -1) goto fail; finish: @@ -2271,7 +2282,7 @@ fill_lines(int num_traces, void **traces, int check_debuglink, /* read file and fill lines */ static uintptr_t fill_lines(int num_traces, void **traces, int check_debuglink, - obj_info_t **objp, line_info_t *lines, int offset) + obj_info_t **objp, line_info_t *lines, int offset, FILE *errout) { # ifdef __LP64__ # define LP(x) x##_64 @@ -2374,13 +2385,14 @@ fill_lines(int num_traces, void **traces, int check_debuglink, goto fail; } else { - kprintf("'%s' is not a " # ifdef __LP64__ - "64" +# define bitsize "64" # else - "32" +# define bitsize "32" # endif + kprintf("'%s' is not a " bitsize "-bit Mach-O file!\n",binary_filename); +# undef bitsize close(fd); goto fail; } @@ -2415,7 +2427,17 @@ fill_lines(int num_traces, void **traces, int check_debuglink, for (int j=0; j < DWARF_SECTION_COUNT; j++) { struct dwarf_section *s = obj_dwarf_section_at(obj, j); - if (strcmp(sect->sectname, debug_section_names[j]) != 0) + if (strcmp(sect->sectname, debug_section_names[j]) != 0 +#ifdef __APPLE__ + /* macOS clang 16 generates DWARF5, which have Mach-O + * section names that are limited to 16 characters, + * which causes sections with long names to be truncated + * and not match above. + * See: https://wiki.dwarfstd.org/Best_Practices.md#Mach-2d-O + */ + && strncmp(sect->sectname, debug_section_names[j], 16) != 0 +#endif + ) continue; s->ptr = file + sect->offset; @@ -2472,8 +2494,8 @@ fill_lines(int num_traces, void **traces, int check_debuglink, DebugInfoReader reader; debug_info_reader_init(&reader, obj); while (reader.p < reader.pend) { - if (di_read_cu(&reader)) goto fail; - if (!debug_info_read(&reader, num_traces, traces, lines, offset)) + if (di_read_cu(&reader, errout)) goto fail; + if (!debug_info_read(&reader, num_traces, traces, lines, offset, errout)) goto fail; } } @@ -2481,7 +2503,7 @@ fill_lines(int num_traces, void **traces, int check_debuglink, if (parse_debug_line(num_traces, traces, obj->debug_line.ptr, obj->debug_line.size, - obj, lines, offset) == -1) + obj, lines, offset, errout) == -1) goto fail; return dladdr_fbase; @@ -2494,7 +2516,7 @@ fill_lines(int num_traces, void **traces, int check_debuglink, #if defined(__FreeBSD__) || defined(__DragonFly__) # include #endif -/* ssize_t main_exe_path(void) +/* ssize_t main_exe_path(FILE *errout) * * store the path of the main executable to `binary_filename`, * and returns strlen(binary_filename). @@ -2502,7 +2524,7 @@ fill_lines(int num_traces, void **traces, int check_debuglink, */ #if defined(__linux__) || defined(__NetBSD__) static ssize_t -main_exe_path(void) +main_exe_path(FILE *errout) { # if defined(__linux__) # define PROC_SELF_EXE "/proc/self/exe" @@ -2516,21 +2538,21 @@ main_exe_path(void) } #elif defined(__FreeBSD__) || defined(__DragonFly__) static ssize_t -main_exe_path(void) +main_exe_path(FILE *errout) { int mib[4] = {CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1}; size_t len = PATH_MAX; int err = sysctl(mib, 4, binary_filename, &len, NULL, 0); if (err) { - kprintf("Can't get the path of ruby"); - return -1; + kprintf("Can't get the path of ruby"); + return -1; } len--; /* sysctl sets strlen+1 */ return len; } #elif defined(HAVE_LIBPROC_H) static ssize_t -main_exe_path(void) +main_exe_path(FILE *errout) { int len = proc_pidpath(getpid(), binary_filename, PATH_MAX); if (len == 0) return 0; @@ -2542,7 +2564,7 @@ main_exe_path(void) #endif static void -print_line0(line_info_t *line, void *address) +print_line0(line_info_t *line, void *address, FILE *errout) { uintptr_t addr = (uintptr_t)address; uintptr_t d = addr - line->saddr; @@ -2583,16 +2605,16 @@ print_line0(line_info_t *line, void *address) } static void -print_line(line_info_t *line, void *address) +print_line(line_info_t *line, void *address, FILE *errout) { - print_line0(line, address); + print_line0(line, address, errout); if (line->next) { - print_line(line->next, NULL); + print_line(line->next, NULL, errout); } } void -rb_dump_backtrace_with_lines(int num_traces, void **traces) +rb_dump_backtrace_with_lines(int num_traces, void **traces, FILE *errout) { int i; /* async-signal unsafe */ @@ -2604,80 +2626,80 @@ rb_dump_backtrace_with_lines(int num_traces, void **traces) #ifdef HAVE_MAIN_EXE_PATH char *main_path = NULL; /* used on printing backtrace */ ssize_t len; - if ((len = main_exe_path()) > 0) { - main_path = (char *)alloca(len + 1); - if (main_path) { - uintptr_t addr; - memcpy(main_path, binary_filename, len+1); - append_obj(&obj); - obj->path = main_path; - addr = fill_lines(num_traces, traces, 1, &obj, lines, -1); - if (addr != (uintptr_t)-1) { - dladdr_fbases[0] = (void *)addr; - } - } + if ((len = main_exe_path(errout)) > 0) { + main_path = (char *)alloca(len + 1); + if (main_path) { + uintptr_t addr; + memcpy(main_path, binary_filename, len+1); + append_obj(&obj); + obj->path = main_path; + addr = fill_lines(num_traces, traces, 1, &obj, lines, 0, errout); + if (addr != (uintptr_t)-1) { + dladdr_fbases[0] = (void *)addr; + } + } } #endif /* fill source lines by reading dwarf */ for (i = 0; i < num_traces; i++) { - Dl_info info; - if (lines[i].line) continue; - if (dladdr(traces[i], &info)) { - const char *path; - void **p; - - /* skip symbols which is in already checked objects */ - /* if the binary is strip-ed, this may effect */ - for (p=dladdr_fbases; *p; p++) { - if (*p == info.dli_fbase) { - if (info.dli_fname) lines[i].path = info.dli_fname; - if (info.dli_sname) lines[i].sname = info.dli_sname; - goto next_line; - } - } - *p = info.dli_fbase; - - append_obj(&obj); - obj->base_addr = (uintptr_t)info.dli_fbase; - path = info.dli_fname; - obj->path = path; - if (path) lines[i].path = path; + Dl_info info; + if (lines[i].line) continue; + if (dladdr(traces[i], &info)) { + const char *path; + void **p; + + /* skip symbols which is in already checked objects */ + /* if the binary is strip-ed, this may effect */ + for (p=dladdr_fbases; *p; p++) { + if (*p == info.dli_fbase) { + if (info.dli_fname) lines[i].path = info.dli_fname; + if (info.dli_sname) lines[i].sname = info.dli_sname; + goto next_line; + } + } + *p = info.dli_fbase; + + append_obj(&obj); + obj->base_addr = (uintptr_t)info.dli_fbase; + path = info.dli_fname; + obj->path = path; + if (path) lines[i].path = path; if (info.dli_sname) { lines[i].sname = info.dli_sname; lines[i].saddr = (uintptr_t)info.dli_saddr; } - strlcpy(binary_filename, path, PATH_MAX); - if (fill_lines(num_traces, traces, 1, &obj, lines, i) == (uintptr_t)-1) - break; - } + strlcpy(binary_filename, path, PATH_MAX); + if (fill_lines(num_traces, traces, 1, &obj, lines, i, errout) == (uintptr_t)-1) + break; + } next_line: - continue; + continue; } /* output */ for (i = 0; i < num_traces; i++) { - print_line(&lines[i], traces[i]); + print_line(&lines[i], traces[i], errout); - /* FreeBSD's backtrace may show _start and so on */ - if (lines[i].sname && strcmp("main", lines[i].sname) == 0) - break; + /* FreeBSD's backtrace may show _start and so on */ + if (lines[i].sname && strcmp("main", lines[i].sname) == 0) + break; } /* free */ while (obj) { - obj_info_t *o = obj; + obj_info_t *o = obj; for (i=0; i < DWARF_SECTION_COUNT; i++) { struct dwarf_section *s = obj_dwarf_section_at(obj, i); if (s->flags & SHF_COMPRESSED) { free(s->ptr); } } - if (obj->mapped_size) { - munmap(obj->mapped, obj->mapped_size); - } - obj = o->next; - free(o); + if (obj->mapped_size) { + munmap(obj->mapped, obj->mapped_size); + } + obj = o->next; + free(o); } for (i = 0; i < num_traces; i++) { line_info_t *line = lines[i].next; diff --git a/addr2line.h b/addr2line.h index f09b6658001d1e..ff8e476b929f16 100644 --- a/addr2line.h +++ b/addr2line.h @@ -12,8 +12,10 @@ #if (defined(USE_ELF) || defined(HAVE_MACH_O_LOADER_H)) +#include + void -rb_dump_backtrace_with_lines(int num_traces, void **traces); +rb_dump_backtrace_with_lines(int num_traces, void **traces, FILE *errout); #endif /* USE_ELF */ diff --git a/array.c b/array.c index 103269630839a4..f485223e34bd21 100644 --- a/array.c +++ b/array.c @@ -27,7 +27,9 @@ #include "probes.h" #include "ruby/encoding.h" #include "ruby/st.h" +#include "ruby/thread.h" #include "ruby/util.h" +#include "vm_core.h" #include "builtin.h" #if !ARRAY_DEBUG @@ -37,15 +39,16 @@ #include "ruby_assert.h" VALUE rb_cArray; +VALUE rb_cArray_empty_frozen; /* Flags of RArray * + * 0: RARRAY_SHARED_FLAG (equal to ELTS_SHARED) + * The array is shared. The buffer this array points to is owned by + * another array (the shared root). * 1: RARRAY_EMBED_FLAG * The array is embedded (its contents follow the header, rather than * being on a separately allocated buffer). - * 2: RARRAY_SHARED_FLAG (equal to ELTS_SHARED) - * The array is shared. The buffer this array points to is owned by - * another array (the shared root). * 3-9: RARRAY_EMBED_LEN * The length of the array when RARRAY_EMBED_FLAG is set. * 12: RARRAY_SHARED_ROOT_FLAG @@ -76,47 +79,47 @@ should_be_T_ARRAY(VALUE ary) return RB_TYPE_P(ary, T_ARRAY); } -#define ARY_HEAP_PTR(a) (assert(!ARY_EMBED_P(a)), RARRAY(a)->as.heap.ptr) -#define ARY_HEAP_LEN(a) (assert(!ARY_EMBED_P(a)), RARRAY(a)->as.heap.len) -#define ARY_HEAP_CAPA(a) (assert(!ARY_EMBED_P(a)), assert(!ARY_SHARED_ROOT_P(a)), \ +#define ARY_HEAP_PTR(a) (RUBY_ASSERT(!ARY_EMBED_P(a)), RARRAY(a)->as.heap.ptr) +#define ARY_HEAP_LEN(a) (RUBY_ASSERT(!ARY_EMBED_P(a)), RARRAY(a)->as.heap.len) +#define ARY_HEAP_CAPA(a) (RUBY_ASSERT(!ARY_EMBED_P(a)), RUBY_ASSERT(!ARY_SHARED_ROOT_P(a)), \ RARRAY(a)->as.heap.aux.capa) -#define ARY_EMBED_PTR(a) (assert(ARY_EMBED_P(a)), RARRAY(a)->as.ary) +#define ARY_EMBED_PTR(a) (RUBY_ASSERT(ARY_EMBED_P(a)), RARRAY(a)->as.ary) #define ARY_EMBED_LEN(a) \ - (assert(ARY_EMBED_P(a)), \ + (RUBY_ASSERT(ARY_EMBED_P(a)), \ (long)((RBASIC(a)->flags >> RARRAY_EMBED_LEN_SHIFT) & \ (RARRAY_EMBED_LEN_MASK >> RARRAY_EMBED_LEN_SHIFT))) -#define ARY_HEAP_SIZE(a) (assert(!ARY_EMBED_P(a)), assert(ARY_OWNS_HEAP_P(a)), ARY_CAPA(a) * sizeof(VALUE)) +#define ARY_HEAP_SIZE(a) (RUBY_ASSERT(!ARY_EMBED_P(a)), RUBY_ASSERT(ARY_OWNS_HEAP_P(a)), ARY_CAPA(a) * sizeof(VALUE)) -#define ARY_OWNS_HEAP_P(a) (assert(should_be_T_ARRAY((VALUE)(a))), \ +#define ARY_OWNS_HEAP_P(a) (RUBY_ASSERT(should_be_T_ARRAY((VALUE)(a))), \ !FL_TEST_RAW((a), RARRAY_SHARED_FLAG|RARRAY_EMBED_FLAG)) #define FL_SET_EMBED(a) do { \ - assert(!ARY_SHARED_P(a)); \ + RUBY_ASSERT(!ARY_SHARED_P(a)); \ FL_SET((a), RARRAY_EMBED_FLAG); \ ary_verify(a); \ } while (0) #define FL_UNSET_EMBED(ary) FL_UNSET((ary), RARRAY_EMBED_FLAG|RARRAY_EMBED_LEN_MASK) #define FL_SET_SHARED(ary) do { \ - assert(!ARY_EMBED_P(ary)); \ + RUBY_ASSERT(!ARY_EMBED_P(ary)); \ FL_SET((ary), RARRAY_SHARED_FLAG); \ } while (0) #define FL_UNSET_SHARED(ary) FL_UNSET((ary), RARRAY_SHARED_FLAG) #define ARY_SET_PTR(ary, p) do { \ - assert(!ARY_EMBED_P(ary)); \ - assert(!OBJ_FROZEN(ary)); \ + RUBY_ASSERT(!ARY_EMBED_P(ary)); \ + RUBY_ASSERT(!OBJ_FROZEN(ary)); \ RARRAY(ary)->as.heap.ptr = (p); \ } while (0) #define ARY_SET_EMBED_LEN(ary, n) do { \ long tmp_n = (n); \ - assert(ARY_EMBED_P(ary)); \ + RUBY_ASSERT(ARY_EMBED_P(ary)); \ RBASIC(ary)->flags &= ~RARRAY_EMBED_LEN_MASK; \ RBASIC(ary)->flags |= (tmp_n) << RARRAY_EMBED_LEN_SHIFT; \ } while (0) #define ARY_SET_HEAP_LEN(ary, n) do { \ - assert(!ARY_EMBED_P(ary)); \ + RUBY_ASSERT(!ARY_EMBED_P(ary)); \ RARRAY(ary)->as.heap.len = (n); \ } while (0) #define ARY_SET_LEN(ary, n) do { \ @@ -126,15 +129,15 @@ should_be_T_ARRAY(VALUE ary) else { \ ARY_SET_HEAP_LEN((ary), (n)); \ } \ - assert(RARRAY_LEN(ary) == (n)); \ + RUBY_ASSERT(RARRAY_LEN(ary) == (n)); \ } while (0) #define ARY_INCREASE_PTR(ary, n) do { \ - assert(!ARY_EMBED_P(ary)); \ - assert(!OBJ_FROZEN(ary)); \ + RUBY_ASSERT(!ARY_EMBED_P(ary)); \ + RUBY_ASSERT(!OBJ_FROZEN(ary)); \ RARRAY(ary)->as.heap.ptr += (n); \ } while (0) #define ARY_INCREASE_LEN(ary, n) do { \ - assert(!OBJ_FROZEN(ary)); \ + RUBY_ASSERT(!OBJ_FROZEN(ary)); \ if (ARY_EMBED_P(ary)) { \ ARY_SET_EMBED_LEN((ary), RARRAY_LEN(ary)+(n)); \ } \ @@ -146,30 +149,30 @@ should_be_T_ARRAY(VALUE ary) #define ARY_CAPA(ary) (ARY_EMBED_P(ary) ? ary_embed_capa(ary) : \ ARY_SHARED_ROOT_P(ary) ? RARRAY_LEN(ary) : ARY_HEAP_CAPA(ary)) #define ARY_SET_CAPA(ary, n) do { \ - assert(!ARY_EMBED_P(ary)); \ - assert(!ARY_SHARED_P(ary)); \ - assert(!OBJ_FROZEN(ary)); \ + RUBY_ASSERT(!ARY_EMBED_P(ary)); \ + RUBY_ASSERT(!ARY_SHARED_P(ary)); \ + RUBY_ASSERT(!OBJ_FROZEN(ary)); \ RARRAY(ary)->as.heap.aux.capa = (n); \ } while (0) #define ARY_SHARED_ROOT_OCCUPIED(ary) (!OBJ_FROZEN(ary) && ARY_SHARED_ROOT_REFCNT(ary) == 1) #define ARY_SET_SHARED_ROOT_REFCNT(ary, value) do { \ - assert(ARY_SHARED_ROOT_P(ary)); \ - assert(!OBJ_FROZEN(ary)); \ - assert((value) >= 0); \ + RUBY_ASSERT(ARY_SHARED_ROOT_P(ary)); \ + RUBY_ASSERT(!OBJ_FROZEN(ary)); \ + RUBY_ASSERT((value) >= 0); \ RARRAY(ary)->as.heap.aux.capa = (value); \ } while (0) #define FL_SET_SHARED_ROOT(ary) do { \ - assert(!OBJ_FROZEN(ary)); \ - assert(!ARY_EMBED_P(ary)); \ + RUBY_ASSERT(!OBJ_FROZEN(ary)); \ + RUBY_ASSERT(!ARY_EMBED_P(ary)); \ FL_SET((ary), RARRAY_SHARED_ROOT_FLAG); \ } while (0) static inline void ARY_SET(VALUE a, long i, VALUE v) { - assert(!ARY_SHARED_P(a)); - assert(!OBJ_FROZEN(a)); + RUBY_ASSERT(!ARY_SHARED_P(a)); + RUBY_ASSERT(!OBJ_FROZEN(a)); RARRAY_ASET(a, i, v); } @@ -179,7 +182,7 @@ static long ary_embed_capa(VALUE ary) { size_t size = rb_gc_obj_slot_size(ary) - offsetof(struct RArray, as.ary); - assert(size % sizeof(VALUE) == 0); + RUBY_ASSERT(size % sizeof(VALUE) == 0); return size / sizeof(VALUE); } @@ -233,23 +236,22 @@ rb_ary_size_as_embedded(VALUE ary) static VALUE ary_verify_(VALUE ary, const char *file, int line) { - assert(RB_TYPE_P(ary, T_ARRAY)); + RUBY_ASSERT(RB_TYPE_P(ary, T_ARRAY)); if (ARY_SHARED_P(ary)) { VALUE root = ARY_SHARED_ROOT(ary); const VALUE *ptr = ARY_HEAP_PTR(ary); const VALUE *root_ptr = RARRAY_CONST_PTR(root); long len = ARY_HEAP_LEN(ary), root_len = RARRAY_LEN(root); - assert(ARY_SHARED_ROOT_P(root) || OBJ_FROZEN(root)); - assert(root_ptr <= ptr && ptr + len <= root_ptr + root_len); + RUBY_ASSERT(ARY_SHARED_ROOT_P(root) || OBJ_FROZEN(root)); + RUBY_ASSERT(root_ptr <= ptr && ptr + len <= root_ptr + root_len); ary_verify(root); } else if (ARY_EMBED_P(ary)) { - assert(!ARY_SHARED_P(ary)); - assert(RARRAY_LEN(ary) <= ary_embed_capa(ary)); + RUBY_ASSERT(!ARY_SHARED_P(ary)); + RUBY_ASSERT(RARRAY_LEN(ary) <= ary_embed_capa(ary)); } else { -#if 1 const VALUE *ptr = RARRAY_CONST_PTR(ary); long i, len = RARRAY_LEN(ary); volatile VALUE v; @@ -258,17 +260,10 @@ ary_verify_(VALUE ary, const char *file, int line) v = ptr[i]; /* access check */ } v = v; -#endif } return ary; } - -void -rb_ary_verify(VALUE ary) -{ - ary_verify(ary); -} #else #define ary_verify(ary) ((void)0) #endif @@ -326,7 +321,7 @@ ary_memfill(VALUE ary, long beg, long size, VALUE val) static void ary_memcpy0(VALUE ary, long beg, long argc, const VALUE *argv, VALUE buff_owner_ary) { - assert(!ARY_SHARED_P(buff_owner_ary)); + RUBY_ASSERT(!ARY_SHARED_P(buff_owner_ary)); if (argc > (int)(128/sizeof(VALUE)) /* is magic number (cache line size) */) { rb_gc_writebarrier_remember(buff_owner_ary); @@ -351,7 +346,7 @@ ary_memcpy(VALUE ary, long beg, long argc, const VALUE *argv) } static VALUE * -ary_heap_alloc(size_t capa) +ary_heap_alloc_buffer(size_t capa) { return ALLOC_N(VALUE, capa); } @@ -371,6 +366,7 @@ ary_heap_free(VALUE ary) static size_t ary_heap_realloc(VALUE ary, size_t new_capa) { + RUBY_ASSERT(!OBJ_FROZEN(ary)); SIZED_REALLOC_N(RARRAY(ary)->as.heap.ptr, VALUE, new_capa, ARY_HEAP_CAPA(ary)); ary_verify(ary); @@ -380,7 +376,7 @@ ary_heap_realloc(VALUE ary, size_t new_capa) void rb_ary_make_embedded(VALUE ary) { - assert(rb_ary_embeddable_p(ary)); + RUBY_ASSERT(rb_ary_embeddable_p(ary)); if (!ARY_EMBED_P(ary)) { const VALUE *buf = ARY_HEAP_PTR(ary); long len = ARY_HEAP_LEN(ary); @@ -397,15 +393,15 @@ rb_ary_make_embedded(VALUE ary) static void ary_resize_capa(VALUE ary, long capacity) { - assert(RARRAY_LEN(ary) <= capacity); - assert(!OBJ_FROZEN(ary)); - assert(!ARY_SHARED_P(ary)); + RUBY_ASSERT(RARRAY_LEN(ary) <= capacity); + RUBY_ASSERT(!OBJ_FROZEN(ary)); + RUBY_ASSERT(!ARY_SHARED_P(ary)); if (capacity > ary_embed_capa(ary)) { size_t new_capa = capacity; if (ARY_EMBED_P(ary)) { long len = ARY_EMBED_LEN(ary); - VALUE *ptr = ary_heap_alloc(capacity); + VALUE *ptr = ary_heap_alloc_buffer(capacity); MEMCPY(ptr, ARY_EMBED_PTR(ary), VALUE, len); FL_UNSET_EMBED(ary); @@ -440,9 +436,12 @@ ary_shrink_capa(VALUE ary) { long capacity = ARY_HEAP_LEN(ary); long old_capa = ARY_HEAP_CAPA(ary); - assert(!ARY_SHARED_P(ary)); - assert(old_capa >= capacity); - if (old_capa > capacity) ary_heap_realloc(ary, capacity); + RUBY_ASSERT(!ARY_SHARED_P(ary)); + RUBY_ASSERT(old_capa >= capacity); + if (old_capa > capacity) { + size_t new_capa = ary_heap_realloc(ary, capacity); + ARY_SET_CAPA(ary, new_capa); + } ary_verify(ary); } @@ -500,7 +499,7 @@ rb_ary_increment_share(VALUE shared_root) { if (!OBJ_FROZEN(shared_root)) { long num = ARY_SHARED_ROOT_REFCNT(shared_root); - assert(num >= 0); + RUBY_ASSERT(num >= 0); ARY_SET_SHARED_ROOT_REFCNT(shared_root, num + 1); } return shared_root; @@ -509,9 +508,9 @@ rb_ary_increment_share(VALUE shared_root) static void rb_ary_set_shared(VALUE ary, VALUE shared_root) { - assert(!ARY_EMBED_P(ary)); - assert(!OBJ_FROZEN(ary)); - assert(ARY_SHARED_ROOT_P(shared_root) || OBJ_FROZEN(shared_root)); + RUBY_ASSERT(!ARY_EMBED_P(ary)); + RUBY_ASSERT(!OBJ_FROZEN(ary)); + RUBY_ASSERT(ARY_SHARED_ROOT_P(shared_root) || OBJ_FROZEN(shared_root)); rb_ary_increment_share(shared_root); FL_SET_SHARED(ary); @@ -523,6 +522,8 @@ rb_ary_set_shared(VALUE ary, VALUE shared_root) static inline void rb_ary_modify_check(VALUE ary) { + RUBY_ASSERT(ruby_thread_has_gvl_p()); + rb_check_frozen(ary); ary_verify(ary); } @@ -556,7 +557,7 @@ rb_ary_cancel_sharing(VALUE ary) rb_ary_decrement_share(shared_root); } else { - VALUE *ptr = ary_heap_alloc(len); + VALUE *ptr = ary_heap_alloc_buffer(len); MEMCPY(ptr, ARY_HEAP_PTR(ary), VALUE, len); rb_ary_unshare(ary); ARY_SET_CAPA(ary, len); @@ -625,21 +626,32 @@ ary_ensure_room_for_push(VALUE ary, long add_len) /* * call-seq: - * array.freeze -> self + * freeze -> self * - * Freezes +self+; returns +self+: + * Freezes +self+ (if not already frozen); returns +self+: * * a = [] * a.frozen? # => false * a.freeze * a.frozen? # => true * - * An attempt to modify a frozen \Array raises FrozenError. + * No further changes may be made to +self+; + * raises FrozenError if a change is attempted. + * + * Related: Kernel#frozen?. */ VALUE rb_ary_freeze(VALUE ary) { + RUBY_ASSERT(RB_TYPE_P(ary, T_ARRAY)); + + if (OBJ_FROZEN(ary)) return ary; + + if (!ARY_EMBED_P(ary) && !ARY_SHARED_P(ary) && !ARY_SHARED_ROOT_P(ary)) { + ary_shrink_capa(ary); + } + return rb_obj_freeze(ary); } @@ -666,7 +678,7 @@ static VALUE ary_alloc_embed(VALUE klass, long capa) { size_t size = ary_embed_size(capa); - assert(rb_gc_size_allocatable_p(size)); + RUBY_ASSERT(rb_gc_size_allocatable_p(size)); NEWOBJ_OF(ary, struct RArray, klass, T_ARRAY | RARRAY_EMBED_FLAG | (RGENGC_WB_PROTECTED_ARRAY ? FL_WB_PROTECTED : 0), size, 0); @@ -696,6 +708,8 @@ empty_ary_alloc(VALUE klass) static VALUE ary_new(VALUE klass, long capa) { + RUBY_ASSERT(ruby_thread_has_gvl_p()); + VALUE ary; if (capa < 0) { @@ -713,9 +727,9 @@ ary_new(VALUE klass, long capa) else { ary = ary_alloc_heap(klass); ARY_SET_CAPA(ary, capa); - assert(!ARY_EMBED_P(ary)); + RUBY_ASSERT(!ARY_EMBED_P(ary)); - ARY_SET_PTR(ary, ary_heap_alloc(capa)); + ARY_SET_PTR(ary, ary_heap_alloc_buffer(capa)); ARY_SET_HEAP_LEN(ary, 0); } @@ -777,7 +791,7 @@ static VALUE ec_ary_alloc_embed(rb_execution_context_t *ec, VALUE klass, long capa) { size_t size = ary_embed_size(capa); - assert(rb_gc_size_allocatable_p(size)); + RUBY_ASSERT(rb_gc_size_allocatable_p(size)); NEWOBJ_OF(ary, struct RArray, klass, T_ARRAY | RARRAY_EMBED_FLAG | (RGENGC_WB_PROTECTED_ARRAY ? FL_WB_PROTECTED : 0), size, ec); @@ -817,9 +831,9 @@ ec_ary_new(rb_execution_context_t *ec, VALUE klass, long capa) else { ary = ec_ary_alloc_heap(ec, klass); ARY_SET_CAPA(ary, capa); - assert(!ARY_EMBED_P(ary)); + RUBY_ASSERT(!ARY_EMBED_P(ary)); - ARY_SET_PTR(ary, ary_heap_alloc(capa)); + ARY_SET_PTR(ary, ary_heap_alloc_buffer(capa)); ARY_SET_HEAP_LEN(ary, 0); } @@ -881,7 +895,32 @@ rb_ary_free(VALUE ary) } } -RUBY_FUNC_EXPORTED size_t +static VALUE fake_ary_flags; + +static VALUE +init_fake_ary_flags(void) +{ + struct RArray fake_ary = {0}; + fake_ary.basic.flags = T_ARRAY; + VALUE ary = (VALUE)&fake_ary; + rb_ary_freeze(ary); + return fake_ary.basic.flags; +} + +VALUE +rb_setup_fake_ary(struct RArray *fake_ary, const VALUE *list, long len) +{ + fake_ary->basic.flags = fake_ary_flags; + RBASIC_CLEAR_CLASS((VALUE)fake_ary); + + // bypass frozen checks + fake_ary->as.heap.ptr = list; + fake_ary->as.heap.len = len; + fake_ary->as.heap.aux.capa = len; + return (VALUE)fake_ary; +} + +size_t rb_ary_memsize(VALUE ary) { if (ARY_OWNS_HEAP_P(ary)) { @@ -904,9 +943,6 @@ ary_make_shared(VALUE ary) return ary; } else if (OBJ_FROZEN(ary)) { - if (!ARY_EMBED_P(ary)) { - ary_shrink_capa(ary); - } return ary; } else { @@ -919,7 +955,7 @@ ary_make_shared(VALUE ary) FL_SET_SHARED_ROOT(shared); if (ARY_EMBED_P(ary)) { - VALUE *ptr = ary_heap_alloc(capa); + VALUE *ptr = ary_heap_alloc_buffer(capa); ARY_SET_PTR(shared, ptr); ary_memcpy(shared, 0, len, RARRAY_CONST_PTR(ary)); @@ -949,7 +985,7 @@ ary_make_substitution(VALUE ary) if (ary_embeddable_p(len)) { VALUE subst = rb_ary_new_capa(len); - assert(ARY_EMBED_P(subst)); + RUBY_ASSERT(ARY_EMBED_P(subst)); ary_memcpy(subst, 0, len, RARRAY_CONST_PTR(ary)); ARY_SET_EMBED_LEN(subst, len); @@ -995,14 +1031,18 @@ rb_to_array(VALUE ary) * call-seq: * Array.try_convert(object) -> object, new_array, or nil * - * If +object+ is an \Array object, returns +object+. + * Attempts to return an array, based on the given +object+. * - * Otherwise if +object+ responds to :to_ary, - * calls object.to_ary and returns the result. + * If +object+ is an array, returns +object+. * - * Returns +nil+ if +object+ does not respond to :to_ary + * Otherwise if +object+ responds to :to_ary. + * calls object.to_ary: + * if the return value is an array or +nil+, returns that value; + * if not, raises TypeError. * - * Raises an exception unless object.to_ary returns an \Array object. + * Otherwise returns +nil+. + * + * Related: see {Methods for Creating an Array}[rdoc-ref:Array@Methods+for+Creating+an+Array]. */ static VALUE @@ -1039,48 +1079,51 @@ rb_ary_s_new(int argc, VALUE *argv, VALUE klass) * call-seq: * Array.new -> new_empty_array * Array.new(array) -> new_array - * Array.new(size) -> new_array - * Array.new(size, default_value) -> new_array - * Array.new(size) {|index| ... } -> new_array + * Array.new(size, default_value = nil) -> new_array + * Array.new(size = 0) {|index| ... } -> new_array * - * Returns a new \Array. + * Returns a new array. * - * With no block and no arguments, returns a new empty \Array object. + * With no block and no argument given, returns a new empty array: * - * With no block and a single \Array argument +array+, - * returns a new \Array formed from +array+: + * Array.new # => [] * - * a = Array.new([:foo, 'bar', 2]) - * a.class # => Array - * a # => [:foo, "bar", 2] + * With no block and array argument given, returns a new array with the same elements: + * + * Array.new([:foo, 'bar', 2]) # => [:foo, "bar", 2] + * + * With no block and integer argument given, returns a new array containing + * that many instances of the given +default_value+: * - * With no block and a single Integer argument +size+, - * returns a new \Array of the given size - * whose elements are all +nil+: + * Array.new(0) # => [] + * Array.new(3) # => [nil, nil, nil] + * Array.new(2, 3) # => [3, 3] * - * a = Array.new(3) - * a # => [nil, nil, nil] + * With a block given, returns an array of the given +size+; + * calls the block with each +index+ in the range (0...size); + * the element at that +index+ in the returned array is the blocks return value: * - * With no block and arguments +size+ and +default_value+, - * returns an \Array of the given size; - * each element is that same +default_value+: + * Array.new(3) {|index| "Element #{index}" } # => ["Element 0", "Element 1", "Element 2"] * - * a = Array.new(3, 'x') - * a # => ['x', 'x', 'x'] + * A common pitfall for new Rubyists is providing an expression as +default_value+: * - * With a block and argument +size+, - * returns an \Array of the given size; - * the block is called with each successive integer +index+; - * the element for that +index+ is the return value from the block: + * array = Array.new(2, {}) + * array # => [{}, {}] + * array[0][:a] = 1 + * array # => [{a: 1}, {a: 1}], as array[0] and array[1] are same object * - * a = Array.new(3) {|index| "Element #{index}" } - * a # => ["Element 0", "Element 1", "Element 2"] + * If you want the elements of the array to be distinct, you should pass a block: * - * Raises ArgumentError if +size+ is negative. + * array = Array.new(2) { {} } + * array # => [{}, {}] + * array[0][:a] = 1 + * array # => [{a: 1}, {}], as array[0] and array[1] are different objects * - * With a block and no argument, - * or a single argument +0+, - * ignores the block and returns a new empty \Array. + * Raises TypeError if the first argument is not either an array + * or an {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects]). + * Raises ArgumentError if the first argument is a negative integer. + * + * Related: see {Methods for Creating an Array}[rdoc-ref:Array@Methods+for+Creating+an+Array]. */ static VALUE @@ -1092,8 +1135,8 @@ rb_ary_initialize(int argc, VALUE *argv, VALUE ary) rb_ary_modify(ary); if (argc == 0) { rb_ary_reset(ary); - assert(ARY_EMBED_P(ary)); - assert(ARY_EMBED_LEN(ary) == 0); + RUBY_ASSERT(ARY_EMBED_P(ary)); + RUBY_ASSERT(ARY_EMBED_LEN(ary) == 0); if (rb_block_given_p()) { rb_warning("given block not used"); } @@ -1138,11 +1181,13 @@ rb_ary_initialize(int argc, VALUE *argv, VALUE ary) } /* - * Returns a new array populated with the given objects. + * Returns a new array, populated with the given objects: + * + * Array[1, 'a', /^A/] # => [1, "a", /^A/] + * Array[] # => [] + * Array.[](1, 'a', /^A/) # => [1, "a", /^A/] * - * Array.[]( 1, 'a', /^A/) # => [1, "a", /^A/] - * Array[ 1, 'a', /^A/ ] # => [1, "a", /^A/] - * [ 1, 'a', /^A/ ] # => [1, "a", /^A/] + * Related: see {Methods for Creating an Array}[rdoc-ref:Array@Methods+for+Creating+an+Array]. */ static VALUE @@ -1190,9 +1235,9 @@ rb_ary_store(VALUE ary, long idx, VALUE val) static VALUE ary_make_partial(VALUE ary, VALUE klass, long offset, long len) { - assert(offset >= 0); - assert(len >= 0); - assert(offset+len <= RARRAY_LEN(ary)); + RUBY_ASSERT(offset >= 0); + RUBY_ASSERT(len >= 0); + RUBY_ASSERT(offset+len <= RARRAY_LEN(ary)); VALUE result = ary_alloc_heap(klass); size_t embed_capa = ary_embed_capa(result); @@ -1204,7 +1249,10 @@ ary_make_partial(VALUE ary, VALUE klass, long offset, long len) else { VALUE shared = ary_make_shared(ary); - assert(!ARY_EMBED_P(result)); + /* The ary_make_shared call may allocate, which can trigger a GC + * compaction. This can cause the array to be embedded because it has + * a length of 0. */ + FL_UNSET_EMBED(result); ARY_SET_PTR(result, RARRAY_CONST_PTR(ary)); ARY_SET_LEN(result, RARRAY_LEN(ary)); @@ -1223,17 +1271,18 @@ ary_make_partial(VALUE ary, VALUE klass, long offset, long len) static VALUE ary_make_partial_step(VALUE ary, VALUE klass, long offset, long len, long step) { - assert(offset >= 0); - assert(len >= 0); - assert(offset+len <= RARRAY_LEN(ary)); - assert(step != 0); + RUBY_ASSERT(offset >= 0); + RUBY_ASSERT(len >= 0); + RUBY_ASSERT(offset+len <= RARRAY_LEN(ary)); + RUBY_ASSERT(step != 0); - const VALUE *values = RARRAY_CONST_PTR(ary); const long orig_len = len; if (step > 0 && step >= len) { VALUE result = ary_new(klass, 1); VALUE *ptr = (VALUE *)ARY_EMBED_PTR(result); + const VALUE *values = RARRAY_CONST_PTR(ary); + RB_OBJ_WRITE(result, ptr, values[offset]); ARY_SET_EMBED_LEN(result, 1); return result; @@ -1251,6 +1300,8 @@ ary_make_partial_step(VALUE ary, VALUE klass, long offset, long len, long step) VALUE result = ary_new(klass, len); if (ARY_EMBED_P(result)) { VALUE *ptr = (VALUE *)ARY_EMBED_PTR(result); + const VALUE *values = RARRAY_CONST_PTR(ary); + for (i = 0; i < len; ++i) { RB_OBJ_WRITE(result, ptr+i, values[j]); j += step; @@ -1258,6 +1309,8 @@ ary_make_partial_step(VALUE ary, VALUE klass, long offset, long len, long step) ARY_SET_EMBED_LEN(result, len); } else { + const VALUE *values = RARRAY_CONST_PTR(ary); + RARRAY_PTR_USE(result, ptr, { for (i = 0; i < len; ++i) { RB_OBJ_WRITE(result, ptr+i, values[j]); @@ -1313,19 +1366,17 @@ ary_take_first_or_last(int argc, const VALUE *argv, VALUE ary, enum ary_take_pos /* * call-seq: - * array << object -> self + * self << object -> self * - * Appends +object+ to +self+; returns +self+: + * Appends +object+ as the last element in +self+; returns +self+: * - * a = [:foo, 'bar', 2] - * a << :baz # => [:foo, "bar", 2, :baz] + * [:foo, 'bar', 2] << :baz # => [:foo, "bar", 2, :baz] * - * Appends +object+ as one element, even if it is another \Array: + * Appends +object+ as a single element, even if it is another array: * - * a = [:foo, 'bar', 2] - * a1 = a << [3, 4] - * a1 # => [:foo, "bar", 2, [3, 4]] + * [:foo, 'bar', 2] << [3, 4] # => [:foo, "bar", 2, [3, 4]] * + * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning]. */ VALUE @@ -1353,22 +1404,20 @@ rb_ary_cat(VALUE ary, const VALUE *argv, long len) /* * call-seq: - * array.push(*objects) -> self - * - * Appends trailing elements. + * push(*objects) -> self + * append(*objects) -> self * - * Appends each argument in +objects+ to +self+; returns +self+: + * Appends each argument in +objects+ to +self+; returns +self+: * - * a = [:foo, 'bar', 2] - * a.push(:baz, :bat) # => [:foo, "bar", 2, :baz, :bat] + * a = [:foo, 'bar', 2] # => [:foo, "bar", 2] + * a.push(:baz, :bat) # => [:foo, "bar", 2, :baz, :bat] * - * Appends each argument as one element, even if it is another \Array: + * Appends each argument as a single element, even if it is another array: * - * a = [:foo, 'bar', 2] - * a1 = a.push([:baz, :bat], [:bam, :bad]) - * a1 # => [:foo, "bar", 2, [:baz, :bat], [:bam, :bad]] + * a = [:foo, 'bar', 2] # => [:foo, "bar", 2] + a.push([:baz, :bat], [:bam, :bad]) # => [:foo, "bar", 2, [:baz, :bat], [:bam, :bad]] * - * Related: #pop, #shift, #unshift. + * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning]. */ static VALUE @@ -1398,33 +1447,32 @@ rb_ary_pop(VALUE ary) /* * call-seq: - * array.pop -> object or nil - * array.pop(n) -> new_array + * pop -> object or nil + * pop(count) -> new_array * - * Removes and returns trailing elements. + * Removes and returns trailing elements of +self+. * - * When no argument is given and +self+ is not empty, - * removes and returns the last element: + * With no argument given, removes and returns the last element, if available; + * otherwise returns +nil+: * * a = [:foo, 'bar', 2] - * a.pop # => 2 - * a # => [:foo, "bar"] + * a.pop # => 2 + * a # => [:foo, "bar"] + * [].pop # => nil * - * Returns +nil+ if the array is empty. + * With non-negative integer argument +count+ given, + * returns a new array containing the trailing +count+ elements of +self+, as available: * - * When a non-negative Integer argument +n+ is given and is in range, - * - * removes and returns the last +n+ elements in a new \Array: * a = [:foo, 'bar', 2] * a.pop(2) # => ["bar", 2] - * - * If +n+ is positive and out of range, - * removes and returns all elements: + * a # => [:foo] * * a = [:foo, 'bar', 2] * a.pop(50) # => [:foo, "bar", 2] + * a # => [] * - * Related: #push, #shift, #unshift. + * Related: Array#push; + * see also {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting]. */ static VALUE @@ -1463,35 +1511,40 @@ rb_ary_shift(VALUE ary) /* * call-seq: - * array.shift -> object or nil - * array.shift(n) -> new_array - * - * Removes and returns leading elements. + * shift -> object or nil + * shift(count) -> new_array or nil * - * When no argument is given, removes and returns the first element: - * - * a = [:foo, 'bar', 2] - * a.shift # => :foo - * a # => ['bar', 2] + * Removes and returns leading elements from +self+. * - * Returns +nil+ if +self+ is empty. + * With no argument, removes and returns one element, if available, + * or +nil+ otherwise: * - * When positive Integer argument +n+ is given, removes the first +n+ elements; - * returns those elements in a new \Array: + * a = [0, 1, 2, 3] + * a.shift # => 0 + * a # => [1, 2, 3] + * [].shift # => nil * - * a = [:foo, 'bar', 2] - * a.shift(2) # => [:foo, 'bar'] - * a # => [2] + * With non-negative numeric argument +count+ given, + * removes and returns the first +count+ elements: * - * If +n+ is as large as or larger than self.length, - * removes all elements; returns those elements in a new \Array: + * a = [0, 1, 2, 3] + * a.shift(2) # => [0, 1] + * a # => [2, 3] + * a.shift(1.1) # => [2] + * a # => [3] + * a.shift(0) # => [] + * a # => [3] + * + * If +count+ is large, + * removes and returns all elements: * - * a = [:foo, 'bar', 2] - * a.shift(3) # => [:foo, 'bar', 2] + * a = [0, 1, 2, 3] + * a.shift(50) # => [0, 1, 2, 3] + * a # => [] * - * If +n+ is zero, returns a new empty \Array; +self+ is unmodified. + * If +self+ is empty, returns a new empty array. * - * Related: #push, #pop, #unshift. + * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting]. */ static VALUE @@ -1556,7 +1609,7 @@ make_room_for_unshift(VALUE ary, const VALUE *head, VALUE *sharedp, int argc, lo head = sharedp + argc + room; } ARY_SET_PTR(ary, head - argc); - assert(ARY_SHARED_ROOT_OCCUPIED(ARY_SHARED_ROOT(ary))); + RUBY_ASSERT(ARY_SHARED_ROOT_OCCUPIED(ARY_SHARED_ROOT(ary))); ary_verify(ary); return ARY_SHARED_ROOT(ary); @@ -1632,14 +1685,16 @@ ary_ensure_room_for_unshift(VALUE ary, int argc) /* * call-seq: - * array.unshift(*objects) -> self + * unshift(*objects) -> self + * prepend(*objects) -> self * * Prepends the given +objects+ to +self+: * * a = [:foo, 'bar', 2] * a.unshift(:bam, :bat) # => [:bam, :bat, :foo, "bar", 2] * - * Related: #push, #pop, #shift. + * Related: Array#shift; + * see also {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning]. */ VALUE @@ -1715,25 +1770,42 @@ static VALUE rb_ary_aref2(VALUE ary, VALUE b, VALUE e); /* * call-seq: - * array[index] -> object or nil - * array[start, length] -> object or nil - * array[range] -> object or nil - * array[aseq] -> object or nil - * array.slice(index) -> object or nil - * array.slice(start, length) -> object or nil - * array.slice(range) -> object or nil - * array.slice(aseq) -> object or nil + * self[index] -> object or nil + * self[start, length] -> object or nil + * self[range] -> object or nil + * self[aseq] -> object or nil + * slice(index) -> object or nil + * slice(start, length) -> object or nil + * slice(range) -> object or nil + * slice(aseq) -> object or nil * * Returns elements from +self+; does not modify +self+. * - * When a single Integer argument +index+ is given, returns the element at offset +index+: + * In brief: + * + * a = [:foo, 'bar', 2] + * + * # Single argument index: returns one element. + * a[0] # => :foo # Zero-based index. + * a[-1] # => 2 # Negative index counts backwards from end. + * + * # Arguments start and length: returns an array. + * a[1, 2] # => ["bar", 2] + * a[-2, 2] # => ["bar", 2] # Negative start counts backwards from end. + * + * # Single argument range: returns an array. + * a[0..1] # => [:foo, "bar"] + * a[0..-2] # => [:foo, "bar"] # Negative range-begin counts backwards from end. + * a[-2..2] # => ["bar", 2] # Negative range-end counts backwards from end. + * + * When a single integer argument +index+ is given, returns the element at offset +index+: * * a = [:foo, 'bar', 2] * a[0] # => :foo * a[2] # => 2 * a # => [:foo, "bar", 2] * - * If +index+ is negative, counts relative to the end of +self+: + * If +index+ is negative, counts backwards from the end of +self+: * * a = [:foo, 'bar', 2] * a[-1] # => 2 @@ -1742,7 +1814,7 @@ static VALUE rb_ary_aref2(VALUE ary, VALUE b, VALUE e); * If +index+ is out of range, returns +nil+. * * When two Integer arguments +start+ and +length+ are given, - * returns a new \Array of size +length+ containing successive elements beginning at offset +start+: + * returns a new array of size +length+ containing successive elements beginning at offset +start+: * * a = [:foo, 'bar', 2] * a[0, 2] # => [:foo, "bar"] @@ -1757,7 +1829,7 @@ static VALUE rb_ary_aref2(VALUE ary, VALUE b, VALUE e); * a[2, 2] # => [2] * * If start == self.size and length >= 0, - * returns a new empty \Array. + * returns a new empty array. * * If +length+ is negative, returns +nil+. * @@ -1769,7 +1841,7 @@ static VALUE rb_ary_aref2(VALUE ary, VALUE b, VALUE e); * a[0..1] # => [:foo, "bar"] * a[1..2] # => ["bar", 2] * - * Special case: If range.start == a.size, returns a new empty \Array. + * Special case: If range.start == a.size, returns a new empty array. * * If range.end is negative, calculates the end index from the end: * @@ -1793,7 +1865,7 @@ static VALUE rb_ary_aref2(VALUE ary, VALUE b, VALUE e); * a[4..-1] # => nil * * When a single Enumerator::ArithmeticSequence argument +aseq+ is given, - * returns an \Array of elements corresponding to the indexes produced by + * returns an array of elements corresponding to the indexes produced by * the sequence. * * a = ['--', 'data1', '--', 'data2', '--', 'data3'] @@ -1815,6 +1887,7 @@ static VALUE rb_ary_aref2(VALUE ary, VALUE b, VALUE e); * # Raises TypeError (no implicit conversion of Symbol into Integer): * a[:foo] * + * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching]. */ VALUE @@ -1862,13 +1935,26 @@ rb_ary_aref1(VALUE ary, VALUE arg) /* * call-seq: - * array.at(index) -> object + * at(index) -> object or nil + * + * Returns the element of +self+ specified by the given +index+ + * or +nil+ if there is no such element; + * +index+ must be an + * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects]. + * + * For non-negative +index+, returns the element of +self+ at offset +index+: * - * Returns the element at Integer offset +index+; does not modify +self+. * a = [:foo, 'bar', 2] - * a.at(0) # => :foo - * a.at(2) # => 2 + * a.at(0) # => :foo + * a.at(2) # => 2 + * a.at(2.0) # => 2 + * + * For negative +index+, counts backwards from the end of +self+: + * + * a.at(-2) # => "bar" * + * Related: Array#[]; + * see also {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching]. */ VALUE @@ -1917,17 +2003,19 @@ rb_ary_last(int argc, const VALUE *argv, VALUE ary) // used by parse.y /* * call-seq: - * array.fetch(index) -> element - * array.fetch(index, default_value) -> element - * array.fetch(index) {|index| ... } -> element + * fetch(index) -> element + * fetch(index, default_value) -> element or default_value + * fetch(index) {|index| ... } -> element or block_return_value * - * Returns the element at offset +index+. + * Returns the element of +self+ at offset +index+ if +index+ is in range; +index+ must be an + * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects]. * - * With the single Integer argument +index+, + * With the single argument +index+ and no block, * returns the element at offset +index+: * * a = [:foo, 'bar', 2] - * a.fetch(1) # => "bar" + * a.fetch(1) # => "bar" + * a.fetch(1.1) # => "bar" * * If +index+ is negative, counts from the end of the array: * @@ -1935,12 +2023,12 @@ rb_ary_last(int argc, const VALUE *argv, VALUE ary) // used by parse.y * a.fetch(-1) # => 2 * a.fetch(-2) # => "bar" * - * With arguments +index+ and +default_value+, - * returns the element at offset +index+ if index is in range, - * otherwise returns +default_value+: + * With arguments +index+ and +default_value+ (which may be any object) and no block, + * returns +default_value+ if +index+ is out-of-range: * * a = [:foo, 'bar', 2] - * a.fetch(1, nil) # => "bar" + * a.fetch(1, nil) # => "bar" + * a.fetch(3, :foo) # => :foo * * With argument +index+ and a block, * returns the element at offset +index+ if index is in range @@ -1950,6 +2038,7 @@ rb_ary_last(int argc, const VALUE *argv, VALUE ary) // used by parse.y * a.fetch(1) {|index| raise 'Cannot happen' } # => "bar" * a.fetch(50) {|index| "Value for #{index}" } # => "Value for 50" * + * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching]. */ static VALUE @@ -1982,13 +2071,16 @@ rb_ary_fetch(int argc, VALUE *argv, VALUE ary) /* * call-seq: - * array.index(object) -> integer or nil - * array.index {|element| ... } -> integer or nil - * array.index -> new_enumerator + * find_index(object) -> integer or nil + * find_index {|element| ... } -> integer or nil + * find_index -> new_enumerator + * index(object) -> integer or nil + * index {|element| ... } -> integer or nil + * index -> new_enumerator * - * Returns the index of a specified element. + * Returns the zero-based integer index of a specified element, or +nil+. * - * When argument +object+ is given but no block, + * With only argument +object+ given, * returns the index of the first element +element+ * for which object == element: * @@ -1997,7 +2089,7 @@ rb_ary_fetch(int argc, VALUE *argv, VALUE ary) * * Returns +nil+ if no such element found. * - * When both argument +object+ and a block are given, + * With only a block given, * calls the block with each successive element; * returns the index of the first element for which the block returns a truthy value: * @@ -2006,14 +2098,9 @@ rb_ary_fetch(int argc, VALUE *argv, VALUE ary) * * Returns +nil+ if the block never returns a truthy value. * - * When neither an argument nor a block is given, returns a new Enumerator: + * With neither an argument nor a block given, returns a new Enumerator. * - * a = [:foo, 'bar', 2] - * e = a.index - * e # => # - * e.each {|element| element == 'bar' } # => 1 - * - * Related: #rindex. + * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying]. */ static VALUE @@ -2046,20 +2133,20 @@ rb_ary_index(int argc, VALUE *argv, VALUE ary) /* * call-seq: - * array.rindex(object) -> integer or nil - * array.rindex {|element| ... } -> integer or nil - * array.rindex -> new_enumerator + * rindex(object) -> integer or nil + * rindex {|element| ... } -> integer or nil + * rindex -> new_enumerator * * Returns the index of the last element for which object == element. * - * When argument +object+ is given but no block, returns the index of the last such element found: + * With argument +object+ given, returns the index of the last such element found: * * a = [:foo, 'bar', 2, 'bar'] * a.rindex('bar') # => 3 * * Returns +nil+ if no such object found. * - * When a block is given but no argument, calls the block with each successive element; + * With a block given, calls the block with each successive element; * returns the index of the last element for which the block returns a truthy value: * * a = [:foo, 'bar', 2, 'bar'] @@ -2067,14 +2154,9 @@ rb_ary_index(int argc, VALUE *argv, VALUE ary) * * Returns +nil+ if the block never returns a truthy value. * - * When neither an argument nor a block is given, returns a new Enumerator: - * - * a = [:foo, 'bar', 2, 'bar'] - * e = a.rindex - * e # => # - * e.each {|element| element == 'bar' } # => 3 + * When neither an argument nor a block is given, returns a new Enumerator. * - * Related: #index. + * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying]. */ static VALUE @@ -2221,7 +2303,7 @@ rb_ary_resize(VALUE ary, long len) rb_raise(rb_eIndexError, "index %ld too big", len); } if (len > olen) { - if (len >= ARY_CAPA(ary)) { + if (len > ARY_CAPA(ary)) { ary_double_capa(ary, len); } ary_mem_clear(ary, olen, len - olen); @@ -2271,11 +2353,39 @@ ary_aset_by_rb_ary_splice(VALUE ary, long beg, long len, VALUE val) /* * call-seq: - * array[index] = object -> object - * array[start, length] = object -> object - * array[range] = object -> object - * - * Assigns elements in +self+; returns the given +object+. + * self[index] = object -> object + * self[start, length] = object -> object + * self[range] = object -> object + * + * Assigns elements in +self+, based on the given +object+; returns +object+. + * + * In brief: + * + * a_orig = [:foo, 'bar', 2] + * + * # With argument index. + * a = a_orig.dup + * a[0] = 'foo' # => "foo" + * a # => ["foo", "bar", 2] + * a = a_orig.dup + * a[7] = 'foo' # => "foo" + * a # => [:foo, "bar", 2, nil, nil, nil, nil, "foo"] + * + * # With arguments start and length. + * a = a_orig.dup + * a[0, 2] = 'foo' # => "foo" + * a # => ["foo", 2] + * a = a_orig.dup + * a[6, 50] = 'foo' # => "foo" + * a # => [:foo, "bar", 2, nil, nil, nil, "foo"] + * + * # With argument range. + * a = a_orig.dup + * a[0..1] = 'foo' # => "foo" + * a # => ["foo", 2] + * a = a_orig.dup + * a[6..50] = 'foo' # => "foo" + * a # => [:foo, "bar", 2, nil, nil, nil, "foo"] * * When Integer argument +index+ is given, assigns +object+ to an element in +self+. * @@ -2297,7 +2407,7 @@ ary_aset_by_rb_ary_splice(VALUE ary, long beg, long len, VALUE val) * a[-1] = 'two' # => "two" * a # => [:foo, "bar", "two"] * - * When Integer arguments +start+ and +length+ are given and +object+ is not an \Array, + * When Integer arguments +start+ and +length+ are given and +object+ is not an array, * removes length - 1 elements beginning at offset +start+, * and assigns +object+ at offset +start+: * @@ -2332,7 +2442,7 @@ ary_aset_by_rb_ary_splice(VALUE ary, long beg, long len, VALUE val) * a[1, 5] = 'foo' # => "foo" * a # => [:foo, "foo"] * - * When Range argument +range+ is given and +object+ is an \Array, + * When Range argument +range+ is given and +object+ is not an array, * removes length - 1 elements beginning at offset +start+, * and assigns +object+ at offset +start+: * @@ -2347,7 +2457,8 @@ ary_aset_by_rb_ary_splice(VALUE ary, long beg, long len, VALUE val) * a # => [:foo, "foo"] * * If the array length is less than range.begin, - * assigns +object+ at offset range.begin, and ignores +length+: + * extends the array with +nil+, assigns +object+ at offset range.begin, + * and ignores +length+: * * a = [:foo, 'bar', 2] * a[6..50] = 'foo' # => "foo" @@ -2381,6 +2492,7 @@ ary_aset_by_rb_ary_splice(VALUE ary, long beg, long len, VALUE val) * a[1..5] = 'foo' # => "foo" * a # => [:foo, "foo"] * + * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning]. */ static VALUE @@ -2410,38 +2522,38 @@ rb_ary_aset(int argc, VALUE *argv, VALUE ary) /* * call-seq: - * array.insert(index, *objects) -> self + * insert(index, *objects) -> self * - * Inserts given +objects+ before or after the element at Integer index +offset+; + * Inserts the given +objects+ as elements of +self+; * returns +self+. * - * When +index+ is non-negative, inserts all given +objects+ - * before the element at offset +index+: + * When +index+ is non-negative, inserts +objects+ + * _before_ the element at offset +index+: * - * a = [:foo, 'bar', 2] - * a.insert(1, :bat, :bam) # => [:foo, :bat, :bam, "bar", 2] + * a = ['a', 'b', 'c'] # => ["a", "b", "c"] + * a.insert(1, :x, :y, :z) # => ["a", :x, :y, :z, "b", "c"] * * Extends the array if +index+ is beyond the array (index >= self.size): * - * a = [:foo, 'bar', 2] - * a.insert(5, :bat, :bam) - * a # => [:foo, "bar", 2, nil, nil, :bat, :bam] + * a = ['a', 'b', 'c'] # => ["a", "b", "c"] + * a.insert(5, :x, :y, :z) # => ["a", "b", "c", nil, nil, :x, :y, :z] * - * Does nothing if no objects given: + * When +index+ is negative, inserts +objects+ + * _after_ the element at offset index + self.size: * - * a = [:foo, 'bar', 2] - * a.insert(1) - * a.insert(50) - * a.insert(-50) - * a # => [:foo, "bar", 2] + * a = ['a', 'b', 'c'] # => ["a", "b", "c"] + * a.insert(-2, :x, :y, :z) # => ["a", "b", :x, :y, :z, "c"] * - * When +index+ is negative, inserts all given +objects+ - * _after_ the element at offset index+self.size: + * With no +objects+ given, does nothing: * - * a = [:foo, 'bar', 2] - * a.insert(-2, :bat, :bam) - * a # => [:foo, "bar", :bat, :bam, 2] + * a = ['a', 'b', 'c'] # => ["a", "b", "c"] + * a.insert(1) # => ["a", "b", "c"] + * a.insert(50) # => ["a", "b", "c"] + * a.insert(-50) # => ["a", "b", "c"] + * + * Raises IndexError if +objects+ are given and +index+ is negative and out of range. * + * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning]. */ static VALUE @@ -2477,14 +2589,27 @@ ary_enum_length(VALUE ary, VALUE args, VALUE eobj) return rb_ary_length(ary); } +// Primitive to avoid a race condition in Array#each. +// Return `true` and write `value` and `index` if the element exists. +static VALUE +ary_fetch_next(VALUE self, VALUE *index, VALUE *value) +{ + long i = NUM2LONG(*index); + if (i >= RARRAY_LEN(self)) { + return Qfalse; + } + *value = RARRAY_AREF(self, i); + *index = LONG2NUM(i + 1); + return Qtrue; +} + /* * call-seq: - * array.each {|element| ... } -> self - * array.each -> Enumerator - * - * Iterates over array elements. + * each {|element| ... } -> self + * each -> new_enumerator * - * When a block given, passes each successive array element to the block; + * With a block given, iterates over the elements of +self+, + * passing each element to the block; * returns +self+: * * a = [:foo, 'bar', 2] @@ -2506,20 +2631,9 @@ ary_enum_length(VALUE ary, VALUE args, VALUE eobj) * foo * bar * - * When no block given, returns a new Enumerator: - * a = [:foo, 'bar', 2] - * - * e = a.each - * e # => # - * a1 = e.each {|element| puts "#{element.class} #{element}" } - * - * Output: - * - * Symbol foo - * String bar - * Integer 2 + * With no block given, returns a new Enumerator. * - * Related: #each_index, #reverse_each. + * Related: see {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating]. */ VALUE @@ -2536,12 +2650,11 @@ rb_ary_each(VALUE ary) /* * call-seq: - * array.each_index {|index| ... } -> self - * array.each_index -> Enumerator + * each_index {|index| ... } -> self + * each_index -> new_enumerator * - * Iterates over array indexes. - * - * When a block given, passes each successive array index to the block; + * With a block given, iterates over the elements of +self+, + * passing each array index to the block; * returns +self+: * * a = [:foo, 'bar', 2] @@ -2557,26 +2670,16 @@ rb_ary_each(VALUE ary) * * a = [:foo, 'bar', 2] * a.each_index {|index| puts index; a.clear if index > 0 } + * a # => [] * * Output: * * 0 * 1 * - * When no block given, returns a new Enumerator: - * - * a = [:foo, 'bar', 2] - * e = a.each_index - * e # => # - * a1 = e.each {|index| puts "#{index} #{a[index]}"} - * - * Output: - * - * 0 foo - * 1 bar - * 2 2 + * With no block given, returns a new Enumerator. * - * Related: #each, #reverse_each. + * Related: see {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating]. */ static VALUE @@ -2593,47 +2696,26 @@ rb_ary_each_index(VALUE ary) /* * call-seq: - * array.reverse_each {|element| ... } -> self - * array.reverse_each -> Enumerator - * - * Iterates backwards over array elements. + * reverse_each {|element| ... } -> self + * reverse_each -> Enumerator * - * When a block given, passes, in reverse order, each element to the block; + * When a block given, iterates backwards over the elements of +self+, + * passing, in reverse order, each element to the block; * returns +self+: * - * a = [:foo, 'bar', 2] - * a.reverse_each {|element| puts "#{element.class} #{element}" } - * - * Output: - * - * Integer 2 - * String bar - * Symbol foo + * a = [] + * [0, 1, 2].reverse_each {|element| a.push(element) } + * a # => [2, 1, 0] * * Allows the array to be modified during iteration: * - * a = [:foo, 'bar', 2] - * a.reverse_each {|element| puts element; a.clear if element.to_s.start_with?('b') } - * - * Output: - * - * 2 - * bar - * - * When no block given, returns a new Enumerator: + * a = ['a', 'b', 'c'] + * a.reverse_each {|element| a.clear if element.start_with?('b') } + * a # => [] * - * a = [:foo, 'bar', 2] - * e = a.reverse_each - * e # => # - * a1 = e.each {|element| puts "#{element.class} #{element}" } - * - * Output: - * - * Integer 2 - * String bar - * Symbol foo + * When no block given, returns a new Enumerator. * - * Related: #each, #each_index. + * Related: see {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating]. */ static VALUE @@ -2656,9 +2738,15 @@ rb_ary_reverse_each(VALUE ary) /* * call-seq: - * array.length -> an_integer + * length -> integer + * size -> integer + * + * Returns the count of elements in +self+: * - * Returns the count of elements in +self+. + * [0, 1, 2].length # => 3 + * [].length # => 0 + * + * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying]. */ static VALUE @@ -2670,10 +2758,12 @@ rb_ary_length(VALUE ary) /* * call-seq: - * array.empty? -> true or false + * empty? -> true or false * * Returns +true+ if the count of elements in +self+ is zero, * +false+ otherwise. + * + * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying]. */ static VALUE @@ -2837,31 +2927,32 @@ rb_ary_join(VALUE ary, VALUE sep) /* * call-seq: - * array.join ->new_string - * array.join(separator = $,) -> new_string + * join(separator = $,) -> new_string * - * Returns the new String formed by joining the array elements after conversion. - * For each element +element+: + * Returns the new string formed by joining the converted elements of +self+; + * for each element +element+: * - * - Uses element.to_s if +element+ is not a kind_of?(Array). - * - Uses recursive element.join(separator) if +element+ is a kind_of?(Array). + * - Converts recursively using element.join(separator) + * if +element+ is a kind_of?(Array). + * - Otherwise, converts using element.to_s. * - * With no argument, joins using the output field separator, $,: + * With no argument given, joins using the output field separator, $,: * * a = [:foo, 'bar', 2] * $, # => nil * a.join # => "foobar2" * - * With \string argument +separator+, joins using that separator: + * With string argument +separator+ given, joins using that separator: * * a = [:foo, 'bar', 2] * a.join("\n") # => "foo\nbar\n2" * - * Joins recursively for nested Arrays: + * Joins recursively for nested arrays: * * a = [:foo, [:bar, [:baz, :bat]]] * a.join # => "foobarbazbat" * + * Related: see {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting]. */ static VALUE rb_ary_join_m(int argc, VALUE *argv, VALUE ary) @@ -2898,14 +2989,16 @@ inspect_ary(VALUE ary, VALUE dummy, int recur) /* * call-seq: - * array.inspect -> new_string + * inspect -> new_string + * to_s -> new_string * - * Returns the new String formed by calling method #inspect + * Returns the new string formed by calling method #inspect * on each array element: * * a = [:foo, 'bar', 2] * a.inspect # => "[:foo, \"bar\", 2]" * + * Related: see {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting]. */ static VALUE @@ -2925,21 +3018,17 @@ rb_ary_to_s(VALUE ary) * call-seq: * to_a -> self or new_array * - * When +self+ is an instance of \Array, returns +self+: - * - * a = [:foo, 'bar', 2] - * a.to_a # => [:foo, "bar", 2] + * When +self+ is an instance of \Array, returns +self+. * - * Otherwise, returns a new \Array containing the elements of +self+: + * Otherwise, returns a new array containing the elements of +self+: * * class MyArray < Array; end - * a = MyArray.new(['foo', 'bar', 'two']) - * a.instance_of?(Array) # => false - * a.kind_of?(Array) # => true - * a1 = a.to_a - * a1 # => ["foo", "bar", "two"] - * a1.class # => Array # Not MyArray + * my_a = MyArray.new(['foo', 'bar', 'two']) + * a = my_a.to_a + * a # => ["foo", "bar", "two"] + * a.class # => Array # Not MyArray. * + * Related: see {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting]. */ static VALUE @@ -2955,27 +3044,27 @@ rb_ary_to_a(VALUE ary) /* * call-seq: - * array.to_h -> new_hash - * array.to_h {|item| ... } -> new_hash + * to_h -> new_hash + * to_h {|element| ... } -> new_hash * - * Returns a new Hash formed from +self+. + * Returns a new hash formed from +self+. * - * When a block is given, calls the block with each array element; - * the block must return a 2-element \Array whose two elements - * form a key-value pair in the returned Hash: + * With no block given, each element of +self+ must be a 2-element sub-array; + * forms each sub-array into a key-value pair in the new hash: * - * a = ['foo', :bar, 1, [2, 3], {baz: 4}] - * h = a.to_h {|item| [item, item] } - * h # => {"foo"=>"foo", :bar=>:bar, 1=>1, [2, 3]=>[2, 3], {:baz=>4}=>{:baz=>4}} + * a = [['foo', 'zero'], ['bar', 'one'], ['baz', 'two']] + * a.to_h # => {"foo"=>"zero", "bar"=>"one", "baz"=>"two"} + * [].to_h # => {} * - * When no block is given, +self+ must be an \Array of 2-element sub-arrays, - * each sub-array is formed into a key-value pair in the new Hash: + * With a block given, the block must return a 2-element array; + * calls the block with each element of +self+; + * forms each returned array into a key-value pair in the returned hash: * - * [].to_h # => {} - * a = [['foo', 'zero'], ['bar', 'one'], ['baz', 'two']] - * h = a.to_h - * h # => {"foo"=>"zero", "bar"=>"one", "baz"=>"two"} + * a = ['foo', :bar, 1, [2, 3], {baz: 4}] + * a.to_h {|element| [element, element.class] } + * # => {"foo"=>String, :bar=>Symbol, 1=>Integer, [2, 3]=>Array, {:baz=>4}=>Hash} * + * Related: see {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting]. */ static VALUE @@ -3004,7 +3093,7 @@ rb_ary_to_h(VALUE ary) /* * call-seq: - * array.to_ary -> self + * to_ary -> self * * Returns +self+. */ @@ -3043,13 +3132,16 @@ rb_ary_reverse(VALUE ary) /* * call-seq: - * array.reverse! -> self + * reverse! -> self * - * Reverses +self+ in place: + * Reverses the order of the elements of +self+; + * returns +self+: * - * a = ['foo', 'bar', 'two'] - * a.reverse! # => ["two", "bar", "foo"] + * a = [0, 1, 2] + * a.reverse! # => [2, 1, 0] + * a # => [2, 1, 0] * + * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning]. */ static VALUE @@ -3060,14 +3152,13 @@ rb_ary_reverse_bang(VALUE ary) /* * call-seq: - * array.reverse -> new_array + * reverse -> new_array * - * Returns a new \Array with the elements of +self+ in reverse order: + * Returns a new array containing the elements of +self+ in reverse order: * - * a = ['foo', 'bar', 'two'] - * a1 = a.reverse - * a1 # => ["two", "bar", "foo"] + * [0, 1, 2].reverse # => [2, 1, 0] * + * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining]. */ static VALUE @@ -3129,48 +3220,34 @@ rb_ary_rotate(VALUE ary, long cnt) /* * call-seq: - * array.rotate! -> self - * array.rotate!(count) -> self + * rotate!(count = 1) -> self * * Rotates +self+ in place by moving elements from one end to the other; returns +self+. * - * When no argument given, rotates the first element to the last position: - * - * a = [:foo, 'bar', 2, 'bar'] - * a.rotate! # => ["bar", 2, "bar", :foo] - * - * When given a non-negative Integer +count+, + * With non-negative numeric +count+, * rotates +count+ elements from the beginning to the end: * - * a = [:foo, 'bar', 2] - * a.rotate!(2) - * a # => [2, :foo, "bar"] + * [0, 1, 2, 3].rotate!(2) # => [2, 3, 0, 1] + [0, 1, 2, 3].rotate!(2.1) # => [2, 3, 0, 1] * * If +count+ is large, uses count % array.size as the count: * - * a = [:foo, 'bar', 2] - * a.rotate!(20) - * a # => [2, :foo, "bar"] + * [0, 1, 2, 3].rotate!(21) # => [1, 2, 3, 0] * - * If +count+ is zero, returns +self+ unmodified: + * If +count+ is zero, rotates no elements: * - * a = [:foo, 'bar', 2] - * a.rotate!(0) - * a # => [:foo, "bar", 2] + * [0, 1, 2, 3].rotate!(0) # => [0, 1, 2, 3] * - * When given a negative Integer +count+, rotates in the opposite direction, + * With a negative numeric +count+, rotates in the opposite direction, * from end to beginning: * - * a = [:foo, 'bar', 2] - * a.rotate!(-2) - * a # => ["bar", 2, :foo] + * [0, 1, 2, 3].rotate!(-1) # => [3, 0, 1, 2] * * If +count+ is small (far from zero), uses count % array.size as the count: * - * a = [:foo, 'bar', 2] - * a.rotate!(-5) - * a # => ["bar", 2, :foo] + * [0, 1, 2, 3].rotate!(-21) # => [3, 0, 1, 2] * + * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning]. */ static VALUE @@ -3183,51 +3260,35 @@ rb_ary_rotate_bang(int argc, VALUE *argv, VALUE ary) /* * call-seq: - * array.rotate -> new_array - * array.rotate(count) -> new_array + * rotate(count = 1) -> new_array * - * Returns a new \Array formed from +self+ with elements + * Returns a new array formed from +self+ with elements * rotated from one end to the other. * - * When no argument given, returns a new \Array that is like +self+, - * except that the first element has been rotated to the last position: - * - * a = [:foo, 'bar', 2, 'bar'] - * a1 = a.rotate - * a1 # => ["bar", 2, "bar", :foo] - * - * When given a non-negative Integer +count+, - * returns a new \Array with +count+ elements rotated from the beginning to the end: + * With non-negative numeric +count+, + * rotates elements from the beginning to the end: * - * a = [:foo, 'bar', 2] - * a1 = a.rotate(2) - * a1 # => [2, :foo, "bar"] + * [0, 1, 2, 3].rotate(2) # => [2, 3, 0, 1] + * [0, 1, 2, 3].rotate(2.1) # => [2, 3, 0, 1] * * If +count+ is large, uses count % array.size as the count: * - * a = [:foo, 'bar', 2] - * a1 = a.rotate(20) - * a1 # => [2, :foo, "bar"] + * [0, 1, 2, 3].rotate(22) # => [2, 3, 0, 1] * - * If +count+ is zero, returns a copy of +self+, unmodified: + * With a +count+ of zero, rotates no elements: * - * a = [:foo, 'bar', 2] - * a1 = a.rotate(0) - * a1 # => [:foo, "bar", 2] + * [0, 1, 2, 3].rotate(0) # => [0, 1, 2, 3] * - * When given a negative Integer +count+, rotates in the opposite direction, - * from end to beginning: + * With negative numeric +count+, rotates in the opposite direction, + * from the end to the beginning: * - * a = [:foo, 'bar', 2] - * a1 = a.rotate(-2) - * a1 # => ["bar", 2, :foo] + * [0, 1, 2, 3].rotate(-1) # => [3, 0, 1, 2] * * If +count+ is small (far from zero), uses count % array.size as the count: * - * a = [:foo, 'bar', 2] - * a1 = a.rotate(-5) - * a1 # => ["bar", 2, :foo] + * [0, 1, 2, 3].rotate(-21) # => [3, 0, 1, 2] * + * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching]. */ static VALUE @@ -3320,50 +3381,19 @@ sort_2(const void *ap, const void *bp, void *dummy) /* * call-seq: - * array.sort! -> self - * array.sort! {|a, b| ... } -> self - * - * Returns +self+ with its elements sorted in place. - * - * With no block, compares elements using operator <=> - * (see Comparable): + * sort! -> self + * sort! {|a, b| ... } -> self * - * a = 'abcde'.split('').shuffle - * a # => ["e", "b", "d", "a", "c"] - * a.sort! - * a # => ["a", "b", "c", "d", "e"] - * - * With a block, calls the block with each element pair; - * for each element pair +a+ and +b+, the block should return an integer: - * - * - Negative when +b+ is to follow +a+. - * - Zero when +a+ and +b+ are equivalent. - * - Positive when +a+ is to follow +b+. - * - * Example: - * - * a = 'abcde'.split('').shuffle - * a # => ["e", "b", "d", "a", "c"] - * a.sort! {|a, b| a <=> b } - * a # => ["a", "b", "c", "d", "e"] - * a.sort! {|a, b| b <=> a } - * a # => ["e", "d", "c", "b", "a"] - * - * When the block returns zero, the order for +a+ and +b+ is indeterminate, - * and may be unstable: - * - * a = 'abcde'.split('').shuffle - * a # => ["e", "b", "d", "a", "c"] - * a.sort! {|a, b| 0 } - * a # => ["d", "e", "c", "a", "b"] + * Like Array#sort, but returns +self+ with its elements sorted in place. * + * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning]. */ VALUE rb_ary_sort_bang(VALUE ary) { rb_ary_modify(ary); - assert(!ARY_SHARED_P(ary)); + RUBY_ASSERT(!ARY_SHARED_P(ary)); if (RARRAY_LEN(ary) > 1) { VALUE tmp = ary_make_substitution(ary); /* only ary refers tmp */ struct ary_sort_data data; @@ -3381,6 +3411,9 @@ rb_ary_sort_bang(VALUE ary) rb_ary_unshare(ary); FL_SET_EMBED(ary); } + if (ARY_EMBED_LEN(tmp) > ARY_CAPA(ary)) { + ary_resize_capa(ary, ARY_EMBED_LEN(tmp)); + } ary_memcpy(ary, 0, ARY_EMBED_LEN(tmp), ARY_EMBED_PTR(tmp)); ARY_SET_LEN(ary, ARY_EMBED_LEN(tmp)); } @@ -3390,7 +3423,7 @@ rb_ary_sort_bang(VALUE ary) ARY_SET_CAPA(ary, RARRAY_LEN(tmp)); } else { - assert(!ARY_SHARED_P(tmp)); + RUBY_ASSERT(!ARY_SHARED_P(tmp)); if (ARY_EMBED_P(ary)) { FL_UNSET_EMBED(ary); } @@ -3406,10 +3439,9 @@ rb_ary_sort_bang(VALUE ary) ARY_SET_CAPA(ary, ARY_HEAP_LEN(tmp)); } /* tmp was lost ownership for the ptr */ - FL_UNSET(tmp, FL_FREEZE); FL_SET_EMBED(tmp); ARY_SET_EMBED_LEN(tmp, 0); - FL_SET(tmp, FL_FREEZE); + OBJ_FREEZE(tmp); } /* tmp will be GC'ed. */ RBASIC_SET_CLASS_RAW(tmp, rb_cArray); /* rb_cArray must be marked */ @@ -3420,21 +3452,18 @@ rb_ary_sort_bang(VALUE ary) /* * call-seq: - * array.sort -> new_array - * array.sort {|a, b| ... } -> new_array + * sort -> new_array + * sort {|a, b| ... } -> new_array * - * Returns a new \Array whose elements are those from +self+, sorted. + * Returns a new array containing the elements of +self+, sorted. * - * With no block, compares elements using operator <=> - * (see Comparable): + * With no block given, compares elements using operator #<=> + * (see Object#<=>): * - * a = 'abcde'.split('').shuffle - * a # => ["e", "b", "d", "a", "c"] - * a1 = a.sort - * a1 # => ["a", "b", "c", "d", "e"] + * [0, 2, 3, 1].sort # => [0, 1, 2, 3] * - * With a block, calls the block with each element pair; - * for each element pair +a+ and +b+, the block should return an integer: + * With a block given, calls the block with each combination of pairs of elements from +self+; + * for each pair +a+ and +b+, the block should return a numeric: * * - Negative when +b+ is to follow +a+. * - Zero when +a+ and +b+ are equivalent. @@ -3442,22 +3471,17 @@ rb_ary_sort_bang(VALUE ary) * * Example: * - * a = 'abcde'.split('').shuffle - * a # => ["e", "b", "d", "a", "c"] - * a1 = a.sort {|a, b| a <=> b } - * a1 # => ["a", "b", "c", "d", "e"] - * a2 = a.sort {|a, b| b <=> a } - * a2 # => ["e", "d", "c", "b", "a"] + * a = [3, 2, 0, 1] + * a.sort {|a, b| a <=> b } # => [0, 1, 2, 3] + * a.sort {|a, b| b <=> a } # => [3, 2, 1, 0] * * When the block returns zero, the order for +a+ and +b+ is indeterminate, - * and may be unstable: + * and may be unstable. * - * a = 'abcde'.split('').shuffle - * a # => ["e", "b", "d", "a", "c"] - * a1 = a.sort {|a, b| 0 } - * a1 # => ["c", "e", "b", "d", "a"] + * See an example in Numeric#nonzero? for the idiom to sort more + * complex structure. * - * Related: Enumerable#sort_by. + * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching]. */ VALUE @@ -3472,12 +3496,15 @@ static VALUE rb_ary_bsearch_index(VALUE ary); /* * call-seq: - * array.bsearch {|element| ... } -> object - * array.bsearch -> new_enumerator + * bsearch {|element| ... } -> found_element or nil + * bsearch -> new_enumerator * - * Returns an element from +self+ selected by a binary search. + * Returns the element from +self+ found by a binary search, + * or +nil+ if the search found no suitable element. * * See {Binary Searching}[rdoc-ref:bsearch.rdoc]. + * + * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching]. */ static VALUE @@ -3493,11 +3520,15 @@ rb_ary_bsearch(VALUE ary) /* * call-seq: - * array.bsearch_index {|element| ... } -> integer or nil - * array.bsearch_index -> new_enumerator + * bsearch_index {|element| ... } -> integer or nil + * bsearch_index -> new_enumerator + * + * Returns the integer index of the element from +self+ found by a binary search, + * or +nil+ if the search found no suitable element. + * + * See {Binary Searching}[rdoc-ref:bsearch.rdoc]. * - * Searches +self+ as described at method #bsearch, - * but returns the _index_ of the found element instead of the element itself. + * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching]. */ static VALUE @@ -3556,28 +3587,24 @@ sort_by_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, dummy)) /* * call-seq: - * array.sort_by! {|element| ... } -> self - * array.sort_by! -> new_enumerator + * sort_by! {|element| ... } -> self + * sort_by! -> new_enumerator * - * Sorts the elements of +self+ in place, - * using an ordering determined by the block; returns self. + * With a block given, sorts the elements of +self+ in place; + * returns self. * * Calls the block with each successive element; - * sorts elements based on the values returned from the block. - * - * For duplicates returned by the block, the ordering is indeterminate, and may be unstable. - * - * This example sorts strings based on their sizes: + * sorts elements based on the values returned from the block: * * a = ['aaaa', 'bbb', 'cc', 'd'] * a.sort_by! {|element| element.size } * a # => ["d", "cc", "bbb", "aaaa"] * - * Returns a new Enumerator if no block given: + * For duplicate values returned by the block, the ordering is indeterminate, and may be unstable. * - * a = ['aaaa', 'bbb', 'cc', 'd'] - * a.sort_by! # => # + * With no block given, returns a new Enumerator. * + * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning]. */ static VALUE @@ -3587,29 +3614,32 @@ rb_ary_sort_by_bang(VALUE ary) RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length); rb_ary_modify(ary); - sorted = rb_block_call(ary, rb_intern("sort_by"), 0, 0, sort_by_i, 0); - rb_ary_replace(ary, sorted); + if (RARRAY_LEN(ary) > 1) { + sorted = rb_block_call(ary, rb_intern("sort_by"), 0, 0, sort_by_i, 0); + rb_ary_replace(ary, sorted); + } return ary; } /* * call-seq: - * array.map {|element| ... } -> new_array - * array.map -> new_enumerator + * collect {|element| ... } -> new_array + * collect -> new_enumerator + * map {|element| ... } -> new_array + * map -> new_enumerator * - * Calls the block, if given, with each element of +self+; - * returns a new \Array whose elements are the return values from the block: + * With a block given, calls the block with each element of +self+; + * returns a new array whose elements are the return values from the block: * * a = [:foo, 'bar', 2] * a1 = a.map {|element| element.class } * a1 # => [Symbol, String, Integer] * - * Returns a new Enumerator if no block given: - * a = [:foo, 'bar', 2] - * a1 = a.map - * a1 # => # + * With no block given, returns a new Enumerator. * + * Related: #collect!; + * see also {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting]. */ static VALUE @@ -3629,21 +3659,22 @@ rb_ary_collect(VALUE ary) /* * call-seq: - * array.map! {|element| ... } -> self - * array.map! -> new_enumerator + * collect! {|element| ... } -> new_array + * collect! -> new_enumerator + * map! {|element| ... } -> new_array + * map! -> new_enumerator * - * Calls the block, if given, with each element; - * replaces the element with the block's return value: + * With a block given, calls the block with each element of +self+ + * and replaces the element with the block's return value; + * returns +self+: * * a = [:foo, 'bar', 2] * a.map! { |element| element.class } # => [Symbol, String, Integer] * - * Returns a new Enumerator if no block given: - * - * a = [:foo, 'bar', 2] - * a1 = a.map! - * a1 # => # + * With no block given, returns a new Enumerator. * + * Related: #collect; + * see also {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting]. */ static VALUE @@ -3715,45 +3746,108 @@ append_values_at_single(VALUE result, VALUE ary, long olen, VALUE idx) /* * call-seq: - * array.values_at(*indexes) -> new_array + * values_at(*specifiers) -> new_array * - * Returns a new \Array whose elements are the elements - * of +self+ at the given Integer or Range +indexes+. + * Returns elements from +self+ in a new array; does not modify +self+. * - * For each positive +index+, returns the element at offset +index+: + * The objects included in the returned array are the elements of +self+ + * selected by the given +specifiers+, + * each of which must be a numeric index or a Range. * - * a = [:foo, 'bar', 2] - * a.values_at(0, 2) # => [:foo, 2] - * a.values_at(0..1) # => [:foo, "bar"] + * In brief: * - * The given +indexes+ may be in any order, and may repeat: + * a = ['a', 'b', 'c', 'd'] * - * a = [:foo, 'bar', 2] - * a.values_at(2, 0, 1, 0, 2) # => [2, :foo, "bar", :foo, 2] - * a.values_at(1, 0..2) # => ["bar", :foo, "bar", 2] + * # Index specifiers. + * a.values_at(2, 0, 2, 0) # => ["c", "a", "c", "a"] # May repeat. + * a.values_at(-4, -3, -2, -1) # => ["a", "b", "c", "d"] # Counts backwards if negative. + * a.values_at(-50, 50) # => [nil, nil] # Outside of self. * - * Assigns +nil+ for an +index+ that is too large: + * # Range specifiers. + * a.values_at(1..3) # => ["b", "c", "d"] # From range.begin to range.end. + * a.values_at(1...3) # => ["b", "c"] # End excluded. + * a.values_at(3..1) # => [] # No such elements. * - * a = [:foo, 'bar', 2] - * a.values_at(0, 3, 1, 3) # => [:foo, nil, "bar", nil] + * a.values_at(-3..3) # => ["b", "c", "d"] # Negative range.begin counts backwards. + * a.values_at(-50..3) # Raises RangeError. * - * Returns a new empty \Array if no arguments given. + * a.values_at(1..-2) # => ["b", "c"] # Negative range.end counts backwards. + * a.values_at(1..-50) # => [] # No such elements. * - * For each negative +index+, counts backward from the end of the array: + * # Mixture of specifiers. + * a.values_at(2..3, 3, 0..1, 0) # => ["c", "d", "d", "a", "b", "a"] * - * a = [:foo, 'bar', 2] - * a.values_at(-1, -3) # => [2, :foo] + * With no +specifiers+ given, returns a new empty array: * - * Assigns +nil+ for an +index+ that is too small: + * a = ['a', 'b', 'c', 'd'] + * a.values_at # => [] * - * a = [:foo, 'bar', 2] - * a.values_at(0, -5, 1, -6, 2) # => [:foo, nil, "bar", nil, 2] + * For each numeric specifier +index+, includes an element: * - * The given +indexes+ may have a mixture of signs: + * - For each non-negative numeric specifier +index+ that is in-range (less than self.size), + * includes the element at offset +index+: * - * a = [:foo, 'bar', 2] - * a.values_at(0, -2, 1, -1) # => [:foo, "bar", "bar", 2] + * a.values_at(0, 2) # => ["a", "c"] + * a.values_at(0.1, 2.9) # => ["a", "c"] + * + * - For each negative numeric +index+ that is in-range (greater than or equal to - self.size), + * counts backwards from the end of +self+: + * + * a.values_at(-1, -4) # => ["d", "a"] + * + * The given indexes may be in any order, and may repeat: + * + * a.values_at(2, 0, 1, 0, 2) # => ["c", "a", "b", "a", "c"] + * + * For each +index+ that is out-of-range, includes +nil+: + * + * a.values_at(4, -5) # => [nil, nil] + * + * For each Range specifier +range+, includes elements + * according to range.begin and range.end: + * + * - If both range.begin and range.end + * are non-negative and in-range (less than self.size), + * includes elements from index range.begin + * through range.end - 1 (if range.exclude_end?), + * or through range.end (otherwise): + * + * a.values_at(1..2) # => ["b", "c"] + * a.values_at(1...2) # => ["b"] + * + * - If range.begin is negative and in-range (greater than or equal to - self.size), + * counts backwards from the end of +self+: + * + * a.values_at(-2..3) # => ["c", "d"] + * + * - If range.begin is negative and out-of-range, raises an exception: + * + * a.values_at(-5..3) # Raises RangeError. + * + * - If range.end is positive and out-of-range, + * extends the returned array with +nil+ elements: + * + * a.values_at(1..5) # => ["b", "c", "d", nil, nil] * + * - If range.end is negative and in-range, + * counts backwards from the end of +self+: + * + * a.values_at(1..-2) # => ["b", "c"] + * + * - If range.end is negative and out-of-range, + * returns an empty array: + * + * a.values_at(1..-5) # => [] + * + * The given ranges may be in any order and may repeat: + * + * a.values_at(2..3, 0..1, 2..3) # => ["c", "d", "a", "b", "c", "d"] + * + * The given specifiers may be any mixture of indexes and ranges: + * + * a.values_at(3, 1..2, 0, 2..3) # => ["d", "b", "c", "a", "c", "d"] + * + * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching]. */ static VALUE @@ -3771,22 +3865,22 @@ rb_ary_values_at(int argc, VALUE *argv, VALUE ary) /* * call-seq: - * array.select {|element| ... } -> new_array - * array.select -> new_enumerator + * select {|element| ... } -> new_array + * select -> new_enumerator + * filter {|element| ... } -> new_array + * filter -> new_enumerator * - * Calls the block, if given, with each element of +self+; - * returns a new \Array containing those elements of +self+ + * With a block given, calls the block with each element of +self+; + * returns a new array containing those elements of +self+ * for which the block returns a truthy value: * * a = [:foo, 'bar', 2, :bam] - * a1 = a.select {|element| element.to_s.start_with?('b') } - * a1 # => ["bar", :bam] + * a.select {|element| element.to_s.start_with?('b') } + * # => ["bar", :bam] * - * Returns a new Enumerator if no block given: - * - * a = [:foo, 'bar', 2, :bam] - * a.select # => # + * With no block given, returns a new Enumerator. * + * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching]. */ static VALUE @@ -3852,10 +3946,12 @@ select_bang_ensure(VALUE a) /* * call-seq: - * array.select! {|element| ... } -> self or nil - * array.select! -> new_enumerator + * select! {|element| ... } -> self or nil + * select! -> new_enumerator + * filter! {|element| ... } -> self or nil + * filter! -> new_enumerator * - * Calls the block, if given with each element of +self+; + * With a block given, calls the block with each element of +self+; * removes from +self+ those elements for which the block returns +false+ or +nil+. * * Returns +self+ if any elements were removed: @@ -3865,11 +3961,9 @@ select_bang_ensure(VALUE a) * * Returns +nil+ if no elements were removed. * - * Returns a new Enumerator if no block given: - * - * a = [:foo, 'bar', 2, :bam] - * a.select! # => # + * With no block given, returns a new Enumerator. * + * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting]. */ static VALUE @@ -3887,20 +3981,18 @@ rb_ary_select_bang(VALUE ary) /* * call-seq: - * array.keep_if {|element| ... } -> self - * array.keep_if -> new_enumeration + * keep_if {|element| ... } -> self + * keep_if -> new_enumerator * - * Retains those elements for which the block returns a truthy value; - * deletes all other elements; returns +self+: + * With a block given, calls the block with each element of +self+; + * removes the element from +self+ if the block does not return a truthy value: * * a = [:foo, 'bar', 2, :bam] * a.keep_if {|element| element.to_s.start_with?('b') } # => ["bar", :bam] * - * Returns a new Enumerator if no block given: - * - * a = [:foo, 'bar', 2, :bam] - * a.keep_if # => # + * With no block given, returns a new Enumerator. * + * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting]. */ static VALUE @@ -3926,38 +4018,39 @@ ary_resize_smaller(VALUE ary, long len) /* * call-seq: - * array.delete(obj) -> deleted_object - * array.delete(obj) {|nosuch| ... } -> deleted_object or block_return + * delete(object) -> last_removed_object + * delete(object) {|element| ... } -> last_removed_object or block_return * * Removes zero or more elements from +self+. * - * When no block is given, - * removes from +self+ each element +ele+ such that ele == obj; - * returns the last deleted element: + * With no block given, + * removes from +self+ each element +ele+ such that ele == object; + * returns the last removed element: * - * s1 = 'bar'; s2 = 'bar' - * a = [:foo, s1, 2, s2] - * a.delete('bar') # => "bar" - * a # => [:foo, 2] + * a = [0, 1, 2, 2.0] + * a.delete(2) # => 2.0 + * a # => [0, 1] * - * Returns +nil+ if no elements removed. + * Returns +nil+ if no elements removed: * - * When a block is given, - * removes from +self+ each element +ele+ such that ele == obj. + * a.delete(2) # => nil + * + * With a block given, + * removes from +self+ each element +ele+ such that ele == object. * * If any such elements are found, ignores the block - * and returns the last deleted element: + * and returns the last removed element: * - * s1 = 'bar'; s2 = 'bar' - * a = [:foo, s1, 2, s2] - * deleted_obj = a.delete('bar') {|obj| fail 'Cannot happen' } - * a # => [:foo, 2] + * a = [0, 1, 2, 2.0] + * a.delete(2) {|element| fail 'Cannot happen' } # => 2.0 + * a # => [0, 1] * - * If no such elements are found, returns the block's return value: + * If no such element is found, returns the block's return value: * - * a = [:foo, 'bar', 2] - * a.delete(:nosuch) {|obj| "#{obj} not found" } # => "nosuch not found" + * a.delete(2) {|element| "Element #{element} not found." } + * # => "Element 2 not found." * + * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting]. */ VALUE @@ -4038,9 +4131,10 @@ rb_ary_delete_at(VALUE ary, long pos) /* * call-seq: - * array.delete_at(index) -> deleted_object or nil + * delete_at(index) -> removed_object or nil * - * Deletes an element from +self+, per the given Integer +index+. + * Removes the element of +self+ at the given +index+, which must be an + * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects]. * * When +index+ is non-negative, deletes the element at offset +index+: * @@ -4048,15 +4142,19 @@ rb_ary_delete_at(VALUE ary, long pos) * a.delete_at(1) # => "bar" * a # => [:foo, 2] * - * If index is too large, returns +nil+. - * * When +index+ is negative, counts backward from the end of the array: * * a = [:foo, 'bar', 2] * a.delete_at(-2) # => "bar" * a # => [:foo, 2] * - * If +index+ is too small (far from zero), returns nil. + * When +index+ is out of range, returns +nil+. + * + * a = [:foo, 'bar', 2] + * a.delete_at(3) # => nil + * a.delete_at(-4) # => nil + * + * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting]. */ static VALUE @@ -4097,72 +4195,95 @@ ary_slice_bang_by_rb_ary_splice(VALUE ary, long pos, long len) /* * call-seq: - * array.slice!(n) -> object or nil - * array.slice!(start, length) -> new_array or nil - * array.slice!(range) -> new_array or nil + * slice!(index) -> object or nil + * slice!(start, length) -> new_array or nil + * slice!(range) -> new_array or nil * * Removes and returns elements from +self+. * - * When the only argument is an Integer +n+, - * removes and returns the _nth_ element in +self+: + * With numeric argument +index+ given, + * removes and returns the element at offset +index+: * - * a = [:foo, 'bar', 2] - * a.slice!(1) # => "bar" - * a # => [:foo, 2] + * a = ['a', 'b', 'c', 'd'] + * a.slice!(2) # => "c" + * a # => ["a", "b", "d"] + * a.slice!(2.1) # => "d" + * a # => ["a", "b"] * - * If +n+ is negative, counts backwards from the end of +self+: + * If +index+ is negative, counts backwards from the end of +self+: * - * a = [:foo, 'bar', 2] - * a.slice!(-1) # => 2 - * a # => [:foo, "bar"] + * a = ['a', 'b', 'c', 'd'] + * a.slice!(-2) # => "c" + * a # => ["a", "b", "d"] * - * If +n+ is out of range, returns +nil+. + * If +index+ is out of range, returns +nil+. * - * When the only arguments are Integers +start+ and +length+, - * removes +length+ elements from +self+ beginning at offset +start+; - * returns the deleted objects in a new \Array: + * With numeric arguments +start+ and +length+ given, + * removes +length+ elements from +self+ beginning at zero-based offset +start+; + * returns the removed objects in a new array: * - * a = [:foo, 'bar', 2] - * a.slice!(0, 2) # => [:foo, "bar"] - * a # => [2] + * a = ['a', 'b', 'c', 'd'] + * a.slice!(1, 2) # => ["b", "c"] + * a # => ["a", "d"] + * a.slice!(0.1, 1.1) # => ["a"] + * a # => ["d"] + * + * If +start+ is negative, counts backwards from the end of +self+: + * + * a = ['a', 'b', 'c', 'd'] + * a.slice!(-2, 1) # => ["c"] + * a # => ["a", "b", "d"] + * + * If +start+ is out-of-range, returns +nil+: + * + * a = ['a', 'b', 'c', 'd'] + * a.slice!(5, 1) # => nil + * a.slice!(-5, 1) # => nil * * If start + length exceeds the array size, * removes and returns all elements from offset +start+ to the end: * - * a = [:foo, 'bar', 2] - * a.slice!(1, 50) # => ["bar", 2] - * a # => [:foo] + * a = ['a', 'b', 'c', 'd'] + * a.slice!(2, 50) # => ["c", "d"] + * a # => ["a", "b"] * * If start == a.size and +length+ is non-negative, - * returns a new empty \Array. + * returns a new empty array. * * If +length+ is negative, returns +nil+. * - * When the only argument is a Range object +range+, - * treats range.min as +start+ above and range.size as +length+ above: + * With Range argument +range+ given, + * treats range.min as +start+ (as above) + * and range.size as +length+ (as above): * - * a = [:foo, 'bar', 2] - * a.slice!(1..2) # => ["bar", 2] - * a # => [:foo] + * a = ['a', 'b', 'c', 'd'] + * a.slice!(1..2) # => ["b", "c"] + * a # => ["a", "d"] * - * If range.start == a.size, returns a new empty \Array. + * If range.start == a.size, returns a new empty array: * - * If range.start is larger than the array size, returns +nil+. + * a = ['a', 'b', 'c', 'd'] + * a.slice!(4..5) # => [] * - * If range.end is negative, counts backwards from the end of the array: + * If range.start is larger than the array size, returns +nil+: * - * a = [:foo, 'bar', 2] - * a.slice!(0..-2) # => [:foo, "bar"] - * a # => [2] + * a = ['a', 'b', 'c', 'd'] + a.slice!(5..6) # => nil * * If range.start is negative, - * calculates the start index backwards from the end of the array: + * calculates the start index by counting backwards from the end of +self+: * - * a = [:foo, 'bar', 2] - * a.slice!(-2..2) # => ["bar", 2] - * a # => [:foo] + * a = ['a', 'b', 'c', 'd'] + * a.slice!(-2..2) # => ["c"] * - */ + * If range.end is negative, + * calculates the end index by counting backwards from the end of +self+: + * + * a = ['a', 'b', 'c', 'd'] + * a.slice!(0..-2) # => ["a", "b", "c"] + * + * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting]. + */ static VALUE rb_ary_slice_bang(int argc, VALUE *argv, VALUE ary) @@ -4242,10 +4363,11 @@ ary_reject_bang(VALUE ary) /* * call-seq: - * array.reject! {|element| ... } -> self or nil - * array.reject! -> new_enumerator + * reject! {|element| ... } -> self or nil + * reject! -> new_enumerator * - * Removes each element for which the block returns a truthy value. + * With a block given, calls the block with each element of +self+; + * removes each element for which the block returns a truthy value. * * Returns +self+ if any elements removed: * @@ -4254,11 +4376,9 @@ ary_reject_bang(VALUE ary) * * Returns +nil+ if no elements removed. * - * Returns a new Enumerator if no block given: - * - * a = [:foo, 'bar', 2] - * a.reject! # => # + * With no block given, returns a new Enumerator. * + * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting]. */ static VALUE @@ -4271,21 +4391,19 @@ rb_ary_reject_bang(VALUE ary) /* * call-seq: - * array.reject {|element| ... } -> new_array - * array.reject -> new_enumerator + * reject {|element| ... } -> new_array + * reject -> new_enumerator * - * Returns a new \Array whose elements are all those from +self+ + * With a block given, returns a new array whose elements are all those from +self+ * for which the block returns +false+ or +nil+: * * a = [:foo, 'bar', 2, 'bat'] * a1 = a.reject {|element| element.to_s.start_with?('b') } * a1 # => [:foo, 2] * - * Returns a new Enumerator if no block given: - * - * a = [:foo, 'bar', 2] - * a.reject # => # + * With no block given, returns a new Enumerator. * + * Related: {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching]. */ static VALUE @@ -4301,20 +4419,19 @@ rb_ary_reject(VALUE ary) /* * call-seq: - * array.delete_if {|element| ... } -> self - * array.delete_if -> Enumerator + * delete_if {|element| ... } -> self + * delete_if -> new_numerator * - * Removes each element in +self+ for which the block returns a truthy value; + * With a block given, calls the block with each element of +self+; + * removes the element if the block returns a truthy value; * returns +self+: * * a = [:foo, 'bar', 2, 'bat'] * a.delete_if {|element| element.to_s.start_with?('b') } # => [:foo, 2] * - * Returns a new Enumerator if no block given: - * - * a = [:foo, 'bar', 2] - * a.delete_if # => # + * With no block given, returns a new Enumerator. * + * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting]. */ static VALUE @@ -4355,58 +4472,95 @@ take_items(VALUE obj, long n) /* * call-seq: - * array.zip(*other_arrays) -> new_array - * array.zip(*other_arrays) {|other_array| ... } -> nil + * zip(*other_arrays) -> new_array + * zip(*other_arrays) {|sub_array| ... } -> nil * - * When no block given, returns a new \Array +new_array+ of size self.size - * whose elements are Arrays. + * With no block given, combines +self+ with the collection of +other_arrays+; + * returns a new array of sub-arrays: * - * Each nested array new_array[n] is of size other_arrays.size+1, - * and contains: + * [0, 1].zip(['zero', 'one'], [:zero, :one]) + * # => [[0, "zero", :zero], [1, "one", :one]] * - * - The _nth_ element of +self+. - * - The _nth_ element of each of the +other_arrays+. + * Returned: * - * If all +other_arrays+ and +self+ are the same size: + * - The outer array is of size self.size. + * - Each sub-array is of size other_arrays.size + 1. + * - The _nth_ sub-array contains (in order): + * + * - The _nth_ element of +self+. + * - The _nth_ element of each of the other arrays, as available. + * + * Example: + * + * a = [0, 1] + * zipped = a.zip(['zero', 'one'], [:zero, :one]) + * # => [[0, "zero", :zero], [1, "one", :one]] + * zipped.size # => 2 # Same size as a. + * zipped.first.size # => 3 # Size of other arrays plus 1. + * + * When the other arrays are all the same size as +self+, + * the returned sub-arrays are a rearrangement containing exactly elements of all the arrays + * (including +self+), with no omissions or additions: * * a = [:a0, :a1, :a2, :a3] * b = [:b0, :b1, :b2, :b3] * c = [:c0, :c1, :c2, :c3] * d = a.zip(b, c) - * d # => [[:a0, :b0, :c0], [:a1, :b1, :c1], [:a2, :b2, :c2], [:a3, :b3, :c3]] + * pp d + * # => + * [[:a0, :b0, :c0], + * [:a1, :b1, :c1], + * [:a2, :b2, :c2], + * [:a3, :b3, :c3]] * - * If any array in +other_arrays+ is smaller than +self+, - * fills to self.size with +nil+: + * When one of the other arrays is smaller than +self+, + * pads the corresponding sub-array with +nil+ elements: * * a = [:a0, :a1, :a2, :a3] * b = [:b0, :b1, :b2] * c = [:c0, :c1] * d = a.zip(b, c) - * d # => [[:a0, :b0, :c0], [:a1, :b1, :c1], [:a2, :b2, nil], [:a3, nil, nil]] + * pp d + * # => + * [[:a0, :b0, :c0], + * [:a1, :b1, :c1], + * [:a2, :b2, nil], + * [:a3, nil, nil]] * - * If any array in +other_arrays+ is larger than +self+, - * its trailing elements are ignored: + * When one of the other arrays is larger than +self+, + * _ignores_ its trailing elements: * * a = [:a0, :a1, :a2, :a3] * b = [:b0, :b1, :b2, :b3, :b4] * c = [:c0, :c1, :c2, :c3, :c4, :c5] * d = a.zip(b, c) - * d # => [[:a0, :b0, :c0], [:a1, :b1, :c1], [:a2, :b2, :c2], [:a3, :b3, :c3]] + * pp d + * # => + * [[:a0, :b0, :c0], + * [:a1, :b1, :c1], + * [:a2, :b2, :c2], + * [:a3, :b3, :c3]] * - * When a block is given, calls the block with each of the sub-arrays (formed as above); returns +nil+: + * With a block given, calls the block with each of the other arrays; + * returns +nil+: * + * d = [] * a = [:a0, :a1, :a2, :a3] * b = [:b0, :b1, :b2, :b3] * c = [:c0, :c1, :c2, :c3] - * a.zip(b, c) {|sub_array| p sub_array} # => nil - * - * Output: - * - * [:a0, :b0, :c0] - * [:a1, :b1, :c1] - * [:a2, :b2, :c2] - * [:a3, :b3, :c3] - * + * a.zip(b, c) {|sub_array| d.push(sub_array.reverse) } # => nil + * pp d + * # => + * [[:c0, :b0, :a0], + * [:c1, :b1, :a1], + * [:c2, :b2, :a2], + * [:c3, :b3, :a3]] + * + * For an *object* in *other_arrays* that is not actually an array, + * forms the the "other array" as object.to_ary, if defined, + * or as object.each.to_a otherwise. + * + * Related: see {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting]. */ static VALUE @@ -4469,14 +4623,17 @@ rb_ary_zip(int argc, VALUE *argv, VALUE ary) /* * call-seq: - * array.transpose -> new_array + * transpose -> new_array * - * Transposes the rows and columns in an \Array of Arrays; - * the nested Arrays must all be the same size: + * Returns a new array that is +self+ + * as a {transposed matrix}[https://en.wikipedia.org/wiki/Transpose]: * * a = [[:a0, :a1], [:b0, :b1], [:c0, :c1]] * a.transpose # => [[:a0, :b0, :c0], [:a1, :b1, :c1]] * + * The elements of +self+ must all be the same size. + * + * Related: see {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting]. */ static VALUE @@ -4509,13 +4666,17 @@ rb_ary_transpose(VALUE ary) /* * call-seq: - * array.replace(other_array) -> self + * initialize_copy(other_array) -> self + * replace(other_array) -> self * - * Replaces the content of +self+ with the content of +other_array+; returns +self+: + * Replaces the elements of +self+ with the elements of +other_array+, which must be an + * {array-convertible object}[rdoc-ref:implicit_conversion.rdoc@Array-Convertible+Objects]; + * returns +self+: * - * a = [:foo, 'bar', 2] - * a.replace(['foo', :bar, 3]) # => ["foo", :bar, 3] + * a = ['a', 'b', 'c'] # => ["a", "b", "c"] + * a.replace(['d', 'e']) # => ["d", "e"] * + * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning]. */ VALUE @@ -4529,7 +4690,7 @@ rb_ary_replace(VALUE copy, VALUE orig) /* orig has enough space to embed the contents of orig. */ if (RARRAY_LEN(orig) <= ary_embed_capa(copy)) { - assert(ARY_EMBED_P(copy)); + RUBY_ASSERT(ARY_EMBED_P(copy)); ary_memcpy(copy, 0, RARRAY_LEN(orig), RARRAY_CONST_PTR(orig)); ARY_SET_EMBED_LEN(copy, RARRAY_LEN(orig)); } @@ -4537,7 +4698,7 @@ rb_ary_replace(VALUE copy, VALUE orig) * contents of orig. */ else if (ARY_EMBED_P(orig)) { long len = ARY_EMBED_LEN(orig); - VALUE *ptr = ary_heap_alloc(len); + VALUE *ptr = ary_heap_alloc_buffer(len); FL_UNSET_EMBED(copy); ARY_SET_PTR(copy, ptr); @@ -4563,13 +4724,14 @@ rb_ary_replace(VALUE copy, VALUE orig) /* * call-seq: - * array.clear -> self + * clear -> self * - * Removes all elements from +self+: + * Removes all elements from +self+; returns +self+: * * a = [:foo, 'bar', 2] * a.clear # => [] * + * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting]. */ VALUE @@ -4577,11 +4739,9 @@ rb_ary_clear(VALUE ary) { rb_ary_modify_check(ary); if (ARY_SHARED_P(ary)) { - if (!ARY_EMBED_P(ary)) { - rb_ary_unshare(ary); - FL_SET_EMBED(ary); - ARY_SET_EMBED_LEN(ary, 0); - } + rb_ary_unshare(ary); + FL_SET_EMBED(ary); + ARY_SET_EMBED_LEN(ary, 0); } else { ARY_SET_LEN(ary, 0); @@ -4595,198 +4755,182 @@ rb_ary_clear(VALUE ary) /* * call-seq: - * array.fill(obj) -> self - * array.fill(obj, start) -> self - * array.fill(obj, start, length) -> self - * array.fill(obj, range) -> self - * array.fill {|index| ... } -> self - * array.fill(start) {|index| ... } -> self - * array.fill(start, length) {|index| ... } -> self - * array.fill(range) {|index| ... } -> self - * - * Replaces specified elements in +self+ with specified objects; returns +self+. - * - * With argument +obj+ and no block given, replaces all elements with that one object: - * - * a = ['a', 'b', 'c', 'd'] - * a # => ["a", "b", "c", "d"] - * a.fill(:X) # => [:X, :X, :X, :X] - * - * With arguments +obj+ and Integer +start+, and no block given, - * replaces elements based on the given start. - * - * If +start+ is in range (0 <= start < array.size), - * replaces all elements from offset +start+ through the end: - * - * a = ['a', 'b', 'c', 'd'] - * a.fill(:X, 2) # => ["a", "b", :X, :X] + * fill(object, start = nil, count = nil) -> new_array + * fill(object, range) -> new_array + * fill(start = nil, count = nil) {|element| ... } -> new_array + * fill(range) {|element| ... } -> new_array * - * If +start+ is too large (start >= array.size), does nothing: + * Replaces selected elements in +self+; + * may add elements to +self+; + * always returns +self+ (never a new array). * - * a = ['a', 'b', 'c', 'd'] - * a.fill(:X, 4) # => ["a", "b", "c", "d"] - * a = ['a', 'b', 'c', 'd'] - * a.fill(:X, 5) # => ["a", "b", "c", "d"] + * In brief: * - * If +start+ is negative, counts from the end (starting index is start + array.size): + * # Non-negative start. + * ['a', 'b', 'c', 'd'].fill('-', 1, 2) # => ["a", "-", "-", "d"] + * ['a', 'b', 'c', 'd'].fill(1, 2) {|e| e.to_s } # => ["a", "1", "2", "d"] * - * a = ['a', 'b', 'c', 'd'] - * a.fill(:X, -2) # => ["a", "b", :X, :X] + * # Extends with specified values if necessary. + * ['a', 'b', 'c', 'd'].fill('-', 3, 2) # => ["a", "b", "c", "-", "-"] + * ['a', 'b', 'c', 'd'].fill(3, 2) {|e| e.to_s } # => ["a", "b", "c", "3", "4"] * - * If +start+ is too small (less than and far from zero), replaces all elements: + * # Fills with nils if necessary. + * ['a', 'b', 'c', 'd'].fill('-', 6, 2) # => ["a", "b", "c", "d", nil, nil, "-", "-"] + * ['a', 'b', 'c', 'd'].fill(6, 2) {|e| e.to_s } # => ["a", "b", "c", "d", nil, nil, "6", "7"] * - * a = ['a', 'b', 'c', 'd'] - * a.fill(:X, -6) # => [:X, :X, :X, :X] - * a = ['a', 'b', 'c', 'd'] - * a.fill(:X, -50) # => [:X, :X, :X, :X] + * # For negative start, counts backwards from the end. + * ['a', 'b', 'c', 'd'].fill('-', -3, 3) # => ["a", "-", "-", "-"] + * ['a', 'b', 'c', 'd'].fill(-3, 3) {|e| e.to_s } # => ["a", "1", "2", "3"] * - * With arguments +obj+, Integer +start+, and Integer +length+, and no block given, - * replaces elements based on the given +start+ and +length+. + * # Range. + * ['a', 'b', 'c', 'd'].fill('-', 1..2) # => ["a", "-", "-", "d"] + * ['a', 'b', 'c', 'd'].fill(1..2) {|e| e.to_s } # => ["a", "1", "2", "d"] * - * If +start+ is in range, replaces +length+ elements beginning at offset +start+: + * When arguments +start+ and +count+ are given, + * they select the elements of +self+ to be replaced; + * each must be an + * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects] + * (or +nil+): * - * a = ['a', 'b', 'c', 'd'] - * a.fill(:X, 1, 1) # => ["a", :X, "c", "d"] + * - +start+ specifies the zero-based offset of the first element to be replaced; + * +nil+ means zero. + * - +count+ is the number of consecutive elements to be replaced; + * +nil+ means "all the rest." * - * If +start+ is negative, counts from the end: + * With argument +object+ given, + * that one object is used for all replacements: * - * a = ['a', 'b', 'c', 'd'] - * a.fill(:X, -2, 1) # => ["a", "b", :X, "d"] + * o = Object.new # => # + * a = ['a', 'b', 'c', 'd'] # => ["a", "b", "c", "d"] + * a.fill(o, 1, 2) + * # => ["a", #, #, "d"] * - * If +start+ is large (start >= array.size), extends +self+ with +nil+: + * With a block given, the block is called once for each element to be replaced; + * the value passed to the block is the _index_ of the element to be replaced + * (not the element itself); + * the block's return value replaces the element: * - * a = ['a', 'b', 'c', 'd'] - * a.fill(:X, 5, 0) # => ["a", "b", "c", "d", nil] - * a = ['a', 'b', 'c', 'd'] - * a.fill(:X, 5, 2) # => ["a", "b", "c", "d", nil, :X, :X] + * a = ['a', 'b', 'c', 'd'] # => ["a", "b", "c", "d"] + * a.fill(1, 2) {|element| element.to_s } # => ["a", "1", "2", "d"] * - * If +length+ is zero or negative, replaces no elements: + * For arguments +start+ and +count+: * - * a = ['a', 'b', 'c', 'd'] - * a.fill(:X, 1, 0) # => ["a", "b", "c", "d"] - * a.fill(:X, 1, -1) # => ["a", "b", "c", "d"] + * - If +start+ is non-negative, + * replaces +count+ elements beginning at offset +start+: * - * With arguments +obj+ and Range +range+, and no block given, - * replaces elements based on the given range. + * ['a', 'b', 'c', 'd'].fill('-', 0, 2) # => ["-", "-", "c", "d"] + * ['a', 'b', 'c', 'd'].fill('-', 1, 2) # => ["a", "-", "-", "d"] + * ['a', 'b', 'c', 'd'].fill('-', 2, 2) # => ["a", "b", "-", "-"] * - * If the range is positive and ascending (0 < range.begin <= range.end), - * replaces elements from range.begin to range.end: + * ['a', 'b', 'c', 'd'].fill(0, 2) {|e| e.to_s } # => ["0", "1", "c", "d"] + * ['a', 'b', 'c', 'd'].fill(1, 2) {|e| e.to_s } # => ["a", "1", "2", "d"] + * ['a', 'b', 'c', 'd'].fill(2, 2) {|e| e.to_s } # => ["a", "b", "2", "3"] * - * a = ['a', 'b', 'c', 'd'] - * a.fill(:X, (1..1)) # => ["a", :X, "c", "d"] + * Extends +self+ if necessary: * - * If range.first is negative, replaces no elements: + * ['a', 'b', 'c', 'd'].fill('-', 3, 2) # => ["a", "b", "c", "-", "-"] + * ['a', 'b', 'c', 'd'].fill('-', 4, 2) # => ["a", "b", "c", "d", "-", "-"] * - * a = ['a', 'b', 'c', 'd'] - * a.fill(:X, (-1..1)) # => ["a", "b", "c", "d"] + * ['a', 'b', 'c', 'd'].fill(3, 2) {|e| e.to_s } # => ["a", "b", "c", "3", "4"] + * ['a', 'b', 'c', 'd'].fill(4, 2) {|e| e.to_s } # => ["a", "b", "c", "d", "4", "5"] * - * If range.last is negative, counts from the end: + * Fills with +nil+ if necessary: * - * a = ['a', 'b', 'c', 'd'] - * a.fill(:X, (0..-2)) # => [:X, :X, :X, "d"] - * a = ['a', 'b', 'c', 'd'] - * a.fill(:X, (1..-2)) # => ["a", :X, :X, "d"] + * ['a', 'b', 'c', 'd'].fill('-', 5, 2) # => ["a", "b", "c", "d", nil, "-", "-"] + * ['a', 'b', 'c', 'd'].fill('-', 6, 2) # => ["a", "b", "c", "d", nil, nil, "-", "-"] * - * If range.last and range.last are both negative, - * both count from the end of the array: + * ['a', 'b', 'c', 'd'].fill(5, 2) {|e| e.to_s } # => ["a", "b", "c", "d", nil, "5", "6"] + * ['a', 'b', 'c', 'd'].fill(6, 2) {|e| e.to_s } # => ["a", "b", "c", "d", nil, nil, "6", "7"] * - * a = ['a', 'b', 'c', 'd'] - * a.fill(:X, (-1..-1)) # => ["a", "b", "c", :X] - * a = ['a', 'b', 'c', 'd'] - * a.fill(:X, (-2..-2)) # => ["a", "b", :X, "d"] + * Does nothing if +count+ is non-positive: * - * With no arguments and a block given, calls the block with each index; - * replaces the corresponding element with the block's return value: + * ['a', 'b', 'c', 'd'].fill('-', 2, 0) # => ["a", "b", "c", "d"] + * ['a', 'b', 'c', 'd'].fill('-', 2, -100) # => ["a", "b", "c", "d"] + * ['a', 'b', 'c', 'd'].fill('-', 6, -100) # => ["a", "b", "c", "d"] * - * a = ['a', 'b', 'c', 'd'] - * a.fill { |index| "new_#{index}" } # => ["new_0", "new_1", "new_2", "new_3"] + * ['a', 'b', 'c', 'd'].fill(2, 0) {|e| fail 'Cannot happen' } # => ["a", "b", "c", "d"] + * ['a', 'b', 'c', 'd'].fill(2, -100) {|e| fail 'Cannot happen' } # => ["a", "b", "c", "d"] + * ['a', 'b', 'c', 'd'].fill(6, -100) {|e| fail 'Cannot happen' } # => ["a", "b", "c", "d"] * - * With argument +start+ and a block given, calls the block with each index - * from offset +start+ to the end; replaces the corresponding element - * with the block's return value. + * - If +start+ is negative, counts backwards from the end of +self+: * - * If start is in range (0 <= start < array.size), - * replaces from offset +start+ to the end: + * ['a', 'b', 'c', 'd'].fill('-', -4, 3) # => ["-", "-", "-", "d"] + * ['a', 'b', 'c', 'd'].fill('-', -3, 3) # => ["a", "-", "-", "-"] * - * a = ['a', 'b', 'c', 'd'] - * a.fill(1) { |index| "new_#{index}" } # => ["a", "new_1", "new_2", "new_3"] + * ['a', 'b', 'c', 'd'].fill(-4, 3) {|e| e.to_s } # => ["0", "1", "2", "d"] + * ['a', 'b', 'c', 'd'].fill(-3, 3) {|e| e.to_s } # => ["a", "1", "2", "3"] * - * If +start+ is too large(start >= array.size), does nothing: + * Extends +self+ if necessary: * - * a = ['a', 'b', 'c', 'd'] - * a.fill(4) { |index| fail 'Cannot happen' } # => ["a", "b", "c", "d"] - * a = ['a', 'b', 'c', 'd'] - * a.fill(4) { |index| fail 'Cannot happen' } # => ["a", "b", "c", "d"] + * ['a', 'b', 'c', 'd'].fill('-', -2, 3) # => ["a", "b", "-", "-", "-"] + * ['a', 'b', 'c', 'd'].fill('-', -1, 3) # => ["a", "b", "c", "-", "-", "-"] * - * If +start+ is negative, counts from the end: + * ['a', 'b', 'c', 'd'].fill(-2, 3) {|e| e.to_s } # => ["a", "b", "2", "3", "4"] + * ['a', 'b', 'c', 'd'].fill(-1, 3) {|e| e.to_s } # => ["a", "b", "c", "3", "4", "5"] * - * a = ['a', 'b', 'c', 'd'] - * a.fill(-2) { |index| "new_#{index}" } # => ["a", "b", "new_2", "new_3"] + * Starts at the beginning of +self+ if +start+ is negative and out-of-range: * - * If start is too small (start <= -array.size, replaces all elements: + * ['a', 'b', 'c', 'd'].fill('-', -5, 2) # => ["-", "-", "c", "d"] + * ['a', 'b', 'c', 'd'].fill('-', -6, 2) # => ["-", "-", "c", "d"] * - * a = ['a', 'b', 'c', 'd'] - * a.fill(-6) { |index| "new_#{index}" } # => ["new_0", "new_1", "new_2", "new_3"] - * a = ['a', 'b', 'c', 'd'] - * a.fill(-50) { |index| "new_#{index}" } # => ["new_0", "new_1", "new_2", "new_3"] + * ['a', 'b', 'c', 'd'].fill(-5, 2) {|e| e.to_s } # => ["0", "1", "c", "d"] + * ['a', 'b', 'c', 'd'].fill(-6, 2) {|e| e.to_s } # => ["0", "1", "c", "d"] * - * With arguments +start+ and +length+, and a block given, - * calls the block for each index specified by start length; - * replaces the corresponding element with the block's return value. + * Does nothing if +count+ is non-positive: * - * If +start+ is in range, replaces +length+ elements beginning at offset +start+: + * ['a', 'b', 'c', 'd'].fill('-', -2, 0) # => ["a", "b", "c", "d"] + * ['a', 'b', 'c', 'd'].fill('-', -2, -1) # => ["a", "b", "c", "d"] * - * a = ['a', 'b', 'c', 'd'] - * a.fill(1, 1) { |index| "new_#{index}" } # => ["a", "new_1", "c", "d"] + * ['a', 'b', 'c', 'd'].fill(-2, 0) {|e| fail 'Cannot happen' } # => ["a", "b", "c", "d"] + * ['a', 'b', 'c', 'd'].fill(-2, -1) {|e| fail 'Cannot happen' } # => ["a", "b", "c", "d"] * - * If start is negative, counts from the end: + * When argument +range+ is given, + * it must be a Range object whose members are numeric; + * its +begin+ and +end+ values determine the elements of +self+ + * to be replaced: * - * a = ['a', 'b', 'c', 'd'] - * a.fill(-2, 1) { |index| "new_#{index}" } # => ["a", "b", "new_2", "d"] + * - If both +begin+ and +end+ are positive, they specify the first and last elements + * to be replaced: * - * If +start+ is large (start >= array.size), extends +self+ with +nil+: + * ['a', 'b', 'c', 'd'].fill('-', 1..2) # => ["a", "-", "-", "d"] + * ['a', 'b', 'c', 'd'].fill(1..2) {|e| e.to_s } # => ["a", "1", "2", "d"] * - * a = ['a', 'b', 'c', 'd'] - * a.fill(5, 0) { |index| "new_#{index}" } # => ["a", "b", "c", "d", nil] - * a = ['a', 'b', 'c', 'd'] - * a.fill(5, 2) { |index| "new_#{index}" } # => ["a", "b", "c", "d", nil, "new_5", "new_6"] + * If +end+ is smaller than +begin+, replaces no elements: * - * If +length+ is zero or less, replaces no elements: + * ['a', 'b', 'c', 'd'].fill('-', 2..1) # => ["a", "b", "c", "d"] + * ['a', 'b', 'c', 'd'].fill(2..1) {|e| e.to_s } # => ["a", "b", "c", "d"] * - * a = ['a', 'b', 'c', 'd'] - * a.fill(1, 0) { |index| "new_#{index}" } # => ["a", "b", "c", "d"] - * a.fill(1, -1) { |index| "new_#{index}" } # => ["a", "b", "c", "d"] + * - If either is negative (or both are negative), counts backwards from the end of +self+: * - * With arguments +obj+ and +range+, and a block given, - * calls the block with each index in the given range; - * replaces the corresponding element with the block's return value. + * ['a', 'b', 'c', 'd'].fill('-', -3..2) # => ["a", "-", "-", "d"] + * ['a', 'b', 'c', 'd'].fill('-', 1..-2) # => ["a", "-", "-", "d"] + * ['a', 'b', 'c', 'd'].fill('-', -3..-2) # => ["a", "-", "-", "d"] * - * If the range is positive and ascending (range 0 < range.begin <= range.end, - * replaces elements from range.begin to range.end: + * ['a', 'b', 'c', 'd'].fill(-3..2) {|e| e.to_s } # => ["a", "1", "2", "d"] + * ['a', 'b', 'c', 'd'].fill(1..-2) {|e| e.to_s } # => ["a", "1", "2", "d"] + * ['a', 'b', 'c', 'd'].fill(-3..-2) {|e| e.to_s } # => ["a", "1", "2", "d"] * - * a = ['a', 'b', 'c', 'd'] - * a.fill(1..1) { |index| "new_#{index}" } # => ["a", "new_1", "c", "d"] + * - If the +end+ value is excluded (see Range#exclude_end?), omits the last replacement: * - * If +range.first+ is negative, does nothing: + * ['a', 'b', 'c', 'd'].fill('-', 1...2) # => ["a", "-", "c", "d"] + * ['a', 'b', 'c', 'd'].fill('-', 1...-2) # => ["a", "-", "c", "d"] * - * a = ['a', 'b', 'c', 'd'] - * a.fill(-1..1) { |index| fail 'Cannot happen' } # => ["a", "b", "c", "d"] + * ['a', 'b', 'c', 'd'].fill(1...2) {|e| e.to_s } # => ["a", "1", "c", "d"] + * ['a', 'b', 'c', 'd'].fill(1...-2) {|e| e.to_s } # => ["a", "1", "c", "d"] * - * If range.last is negative, counts from the end: + * - If the range is endless (see {Endless Ranges}[rdoc-ref:Range@Endless+Ranges]), + * replaces elements to the end of +self+: * - * a = ['a', 'b', 'c', 'd'] - * a.fill(0..-2) { |index| "new_#{index}" } # => ["new_0", "new_1", "new_2", "d"] - * a = ['a', 'b', 'c', 'd'] - * a.fill(1..-2) { |index| "new_#{index}" } # => ["a", "new_1", "new_2", "d"] + * ['a', 'b', 'c', 'd'].fill('-', 1..) # => ["a", "-", "-", "-"] + * ['a', 'b', 'c', 'd'].fill(1..) {|e| e.to_s } # => ["a", "1", "2", "3"] * - * If range.first and range.last are both negative, - * both count from the end: + * - If the range is beginless (see {Beginless Ranges}[rdoc-ref:Range@Beginless+Ranges]), + * replaces elements from the beginning of +self+: * - * a = ['a', 'b', 'c', 'd'] - * a.fill(-1..-1) { |index| "new_#{index}" } # => ["a", "b", "c", "new_3"] - * a = ['a', 'b', 'c', 'd'] - * a.fill(-2..-2) { |index| "new_#{index}" } # => ["a", "b", "new_2", "d"] + * ['a', 'b', 'c', 'd'].fill('-', ..2) # => ["-", "-", "-", "d"] + * ['a', 'b', 'c', 'd'].fill(..2) {|e| e.to_s } # => ["0", "1", "2", "d"] * + * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning]. */ static VALUE @@ -4855,15 +4999,15 @@ rb_ary_fill(int argc, VALUE *argv, VALUE ary) /* * call-seq: - * array + other_array -> new_array + * self + other_array -> new_array * - * Returns a new \Array containing all elements of +array+ + * Returns a new array containing all elements of +self+ * followed by all elements of +other_array+: * * a = [0, 1] + [2, 3] * a # => [0, 1, 2, 3] * - * Related: #concat. + * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining]. */ VALUE @@ -4897,12 +5041,15 @@ ary_append(VALUE x, VALUE y) /* * call-seq: - * array.concat(*other_arrays) -> self + * concat(*other_arrays) -> self * - * Adds to +array+ all elements from each \Array in +other_arrays+; returns +self+: + * Adds to +self+ all elements from each array in +other_arrays+; returns +self+: * * a = [0, 1] - * a.concat([2, 3], [4, 5]) # => [0, 1, 2, 3, 4, 5] + * a.concat(['two', 'three'], [:four, :five], a) + * # => [0, 1, "two", "three", :four, :five, 0, 1] + * + * Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning]. */ static VALUE @@ -4934,19 +5081,19 @@ rb_ary_concat(VALUE x, VALUE y) /* * call-seq: - * array * n -> new_array - * array * string_separator -> new_string + * self * n -> new_array + * self * string_separator -> new_string * - * When non-negative argument Integer +n+ is given, - * returns a new \Array built by concatenating the +n+ copies of +self+: + * When non-negative integer argument +n+ is given, + * returns a new array built by concatenating +n+ copies of +self+: * * a = ['x', 'y'] * a * 3 # => ["x", "y", "x", "y", "x", "y"] * - * When String argument +string_separator+ is given, - * equivalent to array.join(string_separator): + * When string argument +string_separator+ is given, + * equivalent to self.join(string_separator): * - * [0, [0, 1], {foo: 0}] * ', ' # => "0, 0, 1, {:foo=>0}" + * [0, [0, 1], {foo: 0}] * ', ' # => "0, 0, 1, {foo: 0}" * */ @@ -4996,17 +5143,18 @@ rb_ary_times(VALUE ary, VALUE times) /* * call-seq: - * array.assoc(obj) -> found_array or nil + * assoc(object) -> found_array or nil * - * Returns the first element in +self+ that is an \Array - * whose first element == +obj+: + * Returns the first element +ele+ in +self+ such that +ele+ is an array + * and ele[0] == object: * * a = [{foo: 0}, [2, 4], [4, 5, 6], [4, 5]] * a.assoc(4) # => [4, 5, 6] * * Returns +nil+ if no such element is found. * - * Related: #rassoc. + * Related: Array#rassoc; + * see also {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching]. */ VALUE @@ -5026,17 +5174,19 @@ rb_ary_assoc(VALUE ary, VALUE key) /* * call-seq: - * array.rassoc(obj) -> found_array or nil + * rassoc(object) -> found_array or nil * - * Returns the first element in +self+ that is an \Array - * whose second element == +obj+: + * Returns the first element +ele+ in +self+ such that +ele+ is an array + * and ele[1] == object: * * a = [{foo: 0}, [2, 4], [4, 5, 6], [4, 5]] * a.rassoc(4) # => [2, 4] + * a.rassoc(5) # => [4, 5, 6] * * Returns +nil+ if no such element is found. * - * Related: #assoc. + * Related: Array#assoc; + * see also {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching]. */ VALUE @@ -5046,7 +5196,7 @@ rb_ary_rassoc(VALUE ary, VALUE value) VALUE v; for (i = 0; i < RARRAY_LEN(ary); ++i) { - v = RARRAY_AREF(ary, i); + v = rb_check_array_type(RARRAY_AREF(ary, i)); if (RB_TYPE_P(v, T_ARRAY) && RARRAY_LEN(v) > 1 && rb_equal(RARRAY_AREF(v, 1), value)) @@ -5091,20 +5241,26 @@ recursive_equal(VALUE ary1, VALUE ary2, int recur) /* * call-seq: - * array == other_array -> true or false + * self == other_array -> true or false * - * Returns +true+ if both array.size == other_array.size - * and for each index +i+ in +array+, array[i] == other_array[i]: + * Returns whether both: * - * a0 = [:foo, 'bar', 2] - * a1 = [:foo, 'bar', 2.0] - * a1 == a0 # => true - * [] == [] # => true + * - +self+ and +other_array+ are the same size. + * - Their corresponding elements are the same; + * that is, for each index +i+ in (0...self.size), + * self[i] == other_array[i]. * - * Otherwise, returns +false+. + * Examples: + * + * [:foo, 'bar', 2] == [:foo, 'bar', 2] # => true + * [:foo, 'bar', 2] == [:foo, 'bar', 2.0] # => true + * [:foo, 'bar', 2] == [:foo, 'bar'] # => false # Different sizes. + * [:foo, 'bar', 2] == [:foo, 'bar', 3] # => false # Different elements. * * This method is different from method Array#eql?, * which compares elements using Object#eql?. + * + * Related: see {Methods for Comparing}[rdoc-ref:Array@Methods+for+Comparing]. */ static VALUE @@ -5137,10 +5293,10 @@ recursive_eql(VALUE ary1, VALUE ary2, int recur) /* * call-seq: - * array.eql? other_array -> true or false + * eql?(other_array) -> true or false * * Returns +true+ if +self+ and +other_array+ are the same size, - * and if, for each index +i+ in +self+, self[i].eql? other_array[i]: + * and if, for each index +i+ in +self+, self[i].eql?(other_array[i]): * * a0 = [:foo, 'bar', 2] * a1 = [:foo, 'bar', 2] @@ -5150,6 +5306,8 @@ recursive_eql(VALUE ary1, VALUE ary2, int recur) * * This method is different from method Array#==, * which compares using method Object#==. + * + * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying]. */ static VALUE @@ -5162,8 +5320,8 @@ rb_ary_eql(VALUE ary1, VALUE ary2) return rb_exec_recursive_paired(recursive_eql, ary1, ary2, ary2); } -VALUE -rb_ary_hash_values(long len, const VALUE *elements) +static VALUE +ary_hash_values(long len, const VALUE *elements, const VALUE ary) { long i; st_index_t h; @@ -5174,39 +5332,55 @@ rb_ary_hash_values(long len, const VALUE *elements) for (i=0; i integer + * hash -> integer * * Returns the integer hash value for +self+. * - * Two arrays with the same content will have the same hash code (and will compare using eql?): + * Two arrays with the same content will have the same hash value + * (and will compare using eql?): * - * [0, 1, 2].hash == [0, 1, 2].hash # => true - * [0, 1, 2].hash == [0, 1, 3].hash # => false + * ['a', 'b'].hash == ['a', 'b'].hash # => true + * ['a', 'b'].hash == ['a', 'c'].hash # => false + * ['a', 'b'].hash == ['a'].hash # => false * */ static VALUE rb_ary_hash(VALUE ary) { - return rb_ary_hash_values(RARRAY_LEN(ary), RARRAY_CONST_PTR(ary)); + RBIMPL_ASSERT_OR_ASSUME(ary); + return ary_hash_values(RARRAY_LEN(ary), RARRAY_CONST_PTR(ary), ary); } /* * call-seq: - * array.include?(obj) -> true or false + * include?(object) -> true or false + * + * Returns whether for some element +element+ in +self+, + * object == element: * - * Returns +true+ if for some index +i+ in +self+, obj == self[i]; - * otherwise +false+: + * [0, 1, 2].include?(2) # => true + * [0, 1, 2].include?(2.0) # => true + * [0, 1, 2].include?(2.1) # => false * - * [0, 1, 2].include?(2) # => true - * [0, 1, 2].include?(3) # => false + * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying]. */ VALUE @@ -5261,33 +5435,40 @@ recursive_cmp(VALUE ary1, VALUE ary2, int recur) /* * call-seq: - * array <=> other_array -> -1, 0, or 1 - * - * Returns -1, 0, or 1 as +self+ is less than, equal to, or greater than +other_array+. - * For each index +i+ in +self+, evaluates result = self[i] <=> other_array[i]. + * self <=> other_array -> -1, 0, or 1 * - * Returns -1 if any result is -1: + * Returns -1, 0, or 1 as +self+ is determined + * to be less than, equal to, or greater than +other_array+. * - * [0, 1, 2] <=> [0, 1, 3] # => -1 + * Iterates over each index +i+ in (0...self.size): * - * Returns 1 if any result is 1: + * - Computes result[i] as self[i] <=> other_array[i]. + * - Immediately returns 1 if result[i] is 1: * - * [0, 1, 2] <=> [0, 1, 1] # => 1 + * [0, 1, 2] <=> [0, 0, 2] # => 1 * - * When all results are zero: + * - Immediately returns -1 if result[i] is -1: * - * - Returns -1 if +array+ is smaller than +other_array+: + * [0, 1, 2] <=> [0, 2, 2] # => -1 * - * [0, 1, 2] <=> [0, 1, 2, 3] # => -1 + * - Continues if result[i] is 0. * - * - Returns 1 if +array+ is larger than +other_array+: + * When every +result+ is 0, + * returns self.size <=> other_array.size + * (see Integer#<=>): * - * [0, 1, 2] <=> [0, 1] # => 1 + * [0, 1, 2] <=> [0, 1] # => 1 + * [0, 1, 2] <=> [0, 1, 2] # => 0 + * [0, 1, 2] <=> [0, 1, 2, 3] # => -1 * - * - Returns 0 if +array+ and +other_array+ are the same size: + * Note that when +other_array+ is larger than +self+, + * its trailing elements do not affect the result: * - * [0, 1, 2] <=> [0, 1, 2] # => 0 + * [0, 1, 2] <=> [0, 1, 2, -3] # => -1 + * [0, 1, 2] <=> [0, 1, 2, 0] # => -1 + * [0, 1, 2] <=> [0, 1, 2, 3] # => -1 * + * Related: see {Methods for Comparing}[rdoc-ref:Array@Methods+for+Comparing]. */ VALUE @@ -5357,18 +5538,20 @@ ary_make_hash_by(VALUE ary) /* * call-seq: - * array - other_array -> new_array + * self - other_array -> new_array * - * Returns a new \Array containing only those elements from +array+ - * that are not found in \Array +other_array+; - * items are compared using eql?; - * the order from +array+ is preserved: + * Returns a new array containing only those elements of +self+ + * that are not found in +other_array+; + * the order from +self+ is preserved: * - * [0, 1, 1, 2, 1, 1, 3, 1, 1] - [1] # => [0, 2, 3] - * [0, 1, 2, 3] - [3, 0] # => [1, 2] - * [0, 1, 2] - [4] # => [0, 1, 2] + * [0, 1, 1, 2, 1, 1, 3, 1, 1] - [1] # => [0, 2, 3] + * [0, 1, 1, 2, 1, 1, 3, 1, 1] - [3, 2, 0, :foo] # => [1, 1, 1, 1, 1, 1] + * [0, 1, 2] - [:foo] # => [0, 1, 2] * - * Related: Array#difference. + * Element are compared using method #eql? + * (as defined in each element of +self+). + * + * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining]. */ VALUE @@ -5402,19 +5585,21 @@ rb_ary_diff(VALUE ary1, VALUE ary2) /* * call-seq: - * array.difference(*other_arrays) -> new_array + * difference(*other_arrays = []) -> new_array * - * Returns a new \Array containing only those elements from +self+ - * that are not found in any of the Arrays +other_arrays+; + * Returns a new array containing only those elements from +self+ + * that are not found in any of the given +other_arrays+; * items are compared using eql?; order from +self+ is preserved: * * [0, 1, 1, 2, 1, 1, 3, 1, 1].difference([1]) # => [0, 2, 3] - * [0, 1, 2, 3].difference([3, 0], [1, 3]) # => [2] - * [0, 1, 2].difference([4]) # => [0, 1, 2] + * [0, 1, 2, 3].difference([3, 0], [1, 3]) # => [2] + * [0, 1, 2].difference([4]) # => [0, 1, 2] + * [0, 1, 2].difference # => [0, 1, 2] * - * Returns a copy of +self+ if no arguments given. + * Returns a copy of +self+ if no arguments are given. * - * Related: Array#-. + * Related: Array#-; + * see also {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining]. */ static VALUE @@ -5438,7 +5623,7 @@ rb_ary_difference_multi(int argc, VALUE *argv, VALUE ary) VALUE elt = rb_ary_elt(ary, i); for (j = 0; j < argc; j++) { if (is_hash[j]) { - if (rb_hash_stlike_lookup(argv[j], RARRAY_AREF(ary, i), NULL)) + if (rb_hash_stlike_lookup(argv[j], elt, NULL)) break; } else { @@ -5456,20 +5641,25 @@ rb_ary_difference_multi(int argc, VALUE *argv, VALUE ary) /* * call-seq: - * array & other_array -> new_array + * self & other_array -> new_array * - * Returns a new \Array containing each element found in both +array+ and \Array +other_array+; - * duplicates are omitted; items are compared using eql? - * (items must also implement +hash+ correctly): + * Returns a new array containing the _intersection_ of +self+ and +other_array+; + * that is, containing those elements found in both +self+ and +other_array+: * * [0, 1, 2, 3] & [1, 2] # => [1, 2] - * [0, 1, 0, 1] & [0, 1] # => [0, 1] * - * Preserves order from +array+: + * Omits duplicates: + * + * [0, 1, 1, 0] & [0, 1] # => [0, 1] + * + * Preserves order from +self+: * * [0, 1, 2] & [3, 2, 1, 0] # => [0, 1, 2] * - * Related: Array#intersection. + * Identifies common elements using method #eql? + * (as defined in each element of +self+). + * + * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining]. */ @@ -5509,23 +5699,23 @@ rb_ary_and(VALUE ary1, VALUE ary2) /* * call-seq: - * array.intersection(*other_arrays) -> new_array + * intersection(*other_arrays) -> new_array * - * Returns a new \Array containing each element found both in +self+ - * and in all of the given Arrays +other_arrays+; - * duplicates are omitted; items are compared using eql? - * (items must also implement +hash+ correctly): + * Returns a new array containing each element in +self+ that is +#eql?+ + * to at least one element in each of the given +other_arrays+; + * duplicates are omitted: * - * [0, 1, 2, 3].intersection([0, 1, 2], [0, 1, 3]) # => [0, 1] * [0, 0, 1, 1, 2, 3].intersection([0, 1, 2], [0, 1, 3]) # => [0, 1] * - * Preserves order from +self+: + * Each element must correctly implement method #hash. + * + * Order from +self+ is preserved: * * [0, 1, 2].intersection([2, 1, 0]) # => [0, 1, 2] * - * Returns a copy of +self+ if no arguments given. + * Returns a copy of +self+ if no arguments are given. * - * Related: Array#&. + * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining]. */ static VALUE @@ -5574,9 +5764,9 @@ rb_ary_union_hash(VALUE hash, VALUE ary2) /* * call-seq: - * array | other_array -> new_array + * self | other_array -> new_array * - * Returns the union of +array+ and \Array +other_array+; + * Returns the union of +self+ and +other_array+; * duplicates are removed; order is preserved; * items are compared using eql?: * @@ -5584,7 +5774,7 @@ rb_ary_union_hash(VALUE hash, VALUE ary2) * [0, 1, 1] | [2, 2, 3] # => [0, 1, 2, 3] * [0, 1, 2] | [3, 2, 1, 0] # => [0, 1, 2, 3] * - * Related: Array#union. + * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining]. */ static VALUE @@ -5608,18 +5798,25 @@ rb_ary_or(VALUE ary1, VALUE ary2) /* * call-seq: - * array.union(*other_arrays) -> new_array + * union(*other_arrays) -> new_array * - * Returns a new \Array that is the union of +self+ and all given Arrays +other_arrays+; - * duplicates are removed; order is preserved; items are compared using eql?: + * Returns a new array that is the union of the elements of +self+ + * and all given arrays +other_arrays+; + * items are compared using eql?: * * [0, 1, 2, 3].union([4, 5], [6, 7]) # => [0, 1, 2, 3, 4, 5, 6, 7] + * + * Removes duplicates (preserving the first found): + * * [0, 1, 1].union([2, 1], [3, 1]) # => [0, 1, 2, 3] - * [0, 1, 2, 3].union([3, 2], [1, 0]) # => [0, 1, 2, 3] * - * Returns a copy of +self+ if no arguments given. + * Preserves order (preserving the position of the first found): * - * Related: Array#|. + * [3, 2, 1, 0].union([5, 3], [4, 2]) # => [3, 2, 1, 0, 5, 4] + * + * With no arguments given, returns a copy of +self+. + * + * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining]. */ static VALUE @@ -5652,19 +5849,16 @@ rb_ary_union_multi(int argc, VALUE *argv, VALUE ary) /* * call-seq: - * ary.intersect?(other_ary) -> true or false + * intersect?(other_array) -> true or false * - * Returns +true+ if the array and +other_ary+ have at least one element in - * common, otherwise returns +false+: + * Returns whether +other_array+ has at least one element that is +#eql?+ to some element of +self+: * - * a = [ 1, 2, 3 ] - * b = [ 3, 4, 5 ] - * c = [ 5, 6, 7 ] - * a.intersect?(b) #=> true - * a.intersect?(c) #=> false + * [1, 2, 3].intersect?([3, 4, 5]) # => true + * [1, 2, 3].intersect?([4, 5, 6]) # => false * - * Array elements are compared using eql? - * (items must also implement +hash+ correctly). + * Each element must correctly implement method #hash. + * + * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying]. */ static VALUE @@ -5798,42 +5992,51 @@ ary_max_opt_string(VALUE ary, long i, VALUE vmax) /* * call-seq: - * array.max -> element - * array.max {|a, b| ... } -> element - * array.max(n) -> new_array - * array.max(n) {|a, b| ... } -> new_array + * max -> element + * max(count) -> new_array + * max {|a, b| ... } -> element + * max(count) {|a, b| ... } -> new_array * * Returns one of the following: * * - The maximum-valued element from +self+. - * - A new \Array of maximum-valued elements selected from +self+. + * - A new array of maximum-valued elements from +self+. + * + * Does not modify +self+. * - * When no block is given, each element in +self+ must respond to method <=> - * with an Integer. + * With no block given, each element in +self+ must respond to method #<=> + * with a numeric. * * With no argument and no block, returns the element in +self+ - * having the maximum value per method <=>: + * having the maximum value per method #<=>: * - * [0, 1, 2].max # => 2 + * [1, 0, 3, 2].max # => 3 * - * With an argument Integer +n+ and no block, returns a new \Array with at most +n+ elements, - * in descending order per method <=>: + * With non-negative numeric argument +count+ and no block, + * returns a new array with at most +count+ elements, + * in descending order, per method #<=>: * - * [0, 1, 2, 3].max(3) # => [3, 2, 1] - * [0, 1, 2, 3].max(6) # => [3, 2, 1, 0] + * [1, 0, 3, 2].max(3) # => [3, 2, 1] + * [1, 0, 3, 2].max(3.0) # => [3, 2, 1] + * [1, 0, 3, 2].max(9) # => [3, 2, 1, 0] + * [1, 0, 3, 2].max(0) # => [] * - * When a block is given, the block must return an Integer. + * With a block given, the block must return a numeric. * - * With a block and no argument, calls the block self.size-1 times to compare elements; + * With a block and no argument, calls the block self.size - 1 times to compare elements; * returns the element having the maximum value per the block: * - * ['0', '00', '000'].max {|a, b| a.size <=> b.size } # => "000" + * ['0', '', '000', '00'].max {|a, b| a.size <=> b.size } + * # => "000" * - * With an argument +n+ and a block, returns a new \Array with at most +n+ elements, - * in descending order per the block: + * With non-negative numeric argument +count+ and a block, + * returns a new array with at most +count+ elements, + * in descending order, per the block: * - * ['0', '00', '000'].max(2) {|a, b| a.size <=> b.size } # => ["000", "00"] + * ['0', '', '000', '00'].max(2) {|a, b| a.size <=> b.size } + * # => ["000", "00"] * + * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching]. */ static VALUE rb_ary_max(int argc, VALUE *argv, VALUE ary) @@ -5966,42 +6169,51 @@ ary_min_opt_string(VALUE ary, long i, VALUE vmin) /* * call-seq: - * array.min -> element - * array.min { |a, b| ... } -> element - * array.min(n) -> new_array - * array.min(n) { |a, b| ... } -> new_array + * min -> element + * min(count) -> new_array + * min {|a, b| ... } -> element + * min(count) {|a, b| ... } -> new_array * * Returns one of the following: * * - The minimum-valued element from +self+. - * - A new \Array of minimum-valued elements selected from +self+. + * - A new array of minimum-valued elements from +self+. * - * When no block is given, each element in +self+ must respond to method <=> - * with an Integer. + * Does not modify +self+. + * + * With no block given, each element in +self+ must respond to method #<=> + * with a numeric. * * With no argument and no block, returns the element in +self+ - * having the minimum value per method <=>: + * having the minimum value per method #<=>: * - * [0, 1, 2].min # => 0 + * [1, 0, 3, 2].min # => 0 * - * With Integer argument +n+ and no block, returns a new \Array with at most +n+ elements, - * in ascending order per method <=>: + * With non-negative numeric argument +count+ and no block, + * returns a new array with at most +count+ elements, + * in ascending order, per method #<=>: * - * [0, 1, 2, 3].min(3) # => [0, 1, 2] - * [0, 1, 2, 3].min(6) # => [0, 1, 2, 3] + * [1, 0, 3, 2].min(3) # => [0, 1, 2] + * [1, 0, 3, 2].min(3.0) # => [0, 1, 2] + * [1, 0, 3, 2].min(9) # => [0, 1, 2, 3] + * [1, 0, 3, 2].min(0) # => [] * - * When a block is given, the block must return an Integer. + * With a block given, the block must return a numeric. * - * With a block and no argument, calls the block self.size-1 times to compare elements; + * With a block and no argument, calls the block self.size - 1 times to compare elements; * returns the element having the minimum value per the block: * - * ['0', '00', '000'].min { |a, b| a.size <=> b.size } # => "0" + * ['0', '', '000', '00'].min {|a, b| a.size <=> b.size } + * # => "" * - * With an argument +n+ and a block, returns a new \Array with at most +n+ elements, - * in ascending order per the block: + * With non-negative numeric argument +count+ and a block, + * returns a new array with at most +count+ elements, + * in ascending order, per the block: * - * ['0', '00', '000'].min(2) {|a, b| a.size <=> b.size } # => ["0", "00"] + * ['0', '', '000', '00'].min(2) {|a, b| a.size <=> b.size } + * # => ["", "0"] * + * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching]. */ static VALUE rb_ary_min(int argc, VALUE *argv, VALUE ary) @@ -6045,26 +6257,25 @@ rb_ary_min(int argc, VALUE *argv, VALUE ary) /* * call-seq: - * array.minmax -> [min_val, max_val] - * array.minmax {|a, b| ... } -> [min_val, max_val] + * minmax -> array + * minmax {|a, b| ... } -> array * - * Returns a new 2-element \Array containing the minimum and maximum values - * from +self+, either per method <=> or per a given block:. + * Returns a 2-element array containing the minimum-valued and maximum-valued + * elements from +self+; + * does not modify +self+. * - * When no block is given, each element in +self+ must respond to method <=> - * with an Integer; - * returns a new 2-element \Array containing the minimum and maximum values - * from +self+, per method <=>: + * With no block given, the minimum and maximum values are determined using method #<=>: * - * [0, 1, 2].minmax # => [0, 2] + * [1, 0, 3, 2].minmax # => [0, 3] * - * When a block is given, the block must return an Integer; - * the block is called self.size-1 times to compare elements; - * returns a new 2-element \Array containing the minimum and maximum values - * from +self+, per the block: + * With a block given, the block must return a numeric; + * the block is called self.size - 1 times to compare elements; + * returns the elements having the minimum and maximum values per the block: * - * ['0', '00', '000'].minmax {|a, b| a.size <=> b.size } # => ["0", "000"] + * ['0', '', '000', '00'].minmax {|a, b| a.size <=> b.size } + * # => ["", "000"] * + * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching]. */ static VALUE rb_ary_minmax(VALUE ary) @@ -6084,32 +6295,30 @@ push_value(st_data_t key, st_data_t val, st_data_t ary) /* * call-seq: - * array.uniq! -> self or nil - * array.uniq! {|element| ... } -> self or nil + * uniq! -> self or nil + * uniq! {|element| ... } -> self or nil * * Removes duplicate elements from +self+, the first occurrence always being retained; * returns +self+ if any elements removed, +nil+ otherwise. * * With no block given, identifies and removes elements using method eql? - * to compare. - * - * Returns +self+ if any elements removed: + * to compare elements: * * a = [0, 0, 1, 1, 2, 2] * a.uniq! # => [0, 1, 2] - * - * Returns +nil+ if no elements removed. + * a.uniq! # => nil * * With a block given, calls the block for each element; - * identifies (using method eql?) and removes - * elements for which the block returns duplicate values. - * - * Returns +self+ if any elements removed: + * identifies and omits "duplicate" elements using method eql? + * to compare block return values; + * that is, an element is a duplicate if its block return value + * is the same as that of a previous element: * * a = ['a', 'aa', 'aaa', 'b', 'bb', 'bbb'] - * a.uniq! {|element| element.size } # => ['a', 'aa', 'aaa'] + * a.uniq! {|element| element.size } # => ["a", "aa", "aaa"] + * a.uniq! {|element| element.size } # => nil * - * Returns +nil+ if no elements removed. + * Related: see {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting]. */ static VALUE rb_ary_uniq_bang(VALUE ary) @@ -6131,7 +6340,7 @@ rb_ary_uniq_bang(VALUE ary) } rb_ary_modify_check(ary); ARY_SET_LEN(ary, 0); - if (ARY_SHARED_P(ary) && !ARY_EMBED_P(ary)) { + if (ARY_SHARED_P(ary)) { rb_ary_unshare(ary); FL_SET_EMBED(ary); } @@ -6143,25 +6352,28 @@ rb_ary_uniq_bang(VALUE ary) /* * call-seq: - * array.uniq -> new_array - * array.uniq {|element| ... } -> new_array + * uniq -> new_array + * uniq {|element| ... } -> new_array * - * Returns a new \Array containing those elements from +self+ that are not duplicates, + * Returns a new array containing those elements from +self+ that are not duplicates, * the first occurrence always being retained. * - * With no block given, identifies and omits duplicates using method eql? - * to compare: + * With no block given, identifies and omits duplicate elements using method eql? + * to compare elements: * * a = [0, 0, 1, 1, 2, 2] * a.uniq # => [0, 1, 2] * * With a block given, calls the block for each element; - * identifies (using method eql?) and omits duplicate values, - * that is, those elements for which the block returns the same value: + * identifies and omits "duplicate" elements using method eql? + * to compare block return values; + * that is, an element is a duplicate if its block return value + * is the same as that of a previous element: * * a = ['a', 'aa', 'aaa', 'b', 'bb', 'bbb'] * a.uniq {|element| element.size } # => ["a", "aa", "aaa"] * + * Related: {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching]. */ static VALUE @@ -6187,11 +6399,18 @@ rb_ary_uniq(VALUE ary) /* * call-seq: - * array.compact! -> self or nil + * compact! -> self or nil + * + * Removes all +nil+ elements from +self+; + * Returns +self+ if any elements are removed, +nil+ otherwise: * - * Removes all +nil+ elements from +self+. + * a = [nil, 0, nil, false, nil, '', nil, [], nil, {}] + * a.compact! # => [0, false, "", [], {}] + * a # => [0, false, "", [], {}] + * a.compact! # => nil * - * Returns +self+ if any elements removed, otherwise +nil+. + * Related: Array#compact; + * see also {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting]. */ static VALUE @@ -6219,12 +6438,16 @@ rb_ary_compact_bang(VALUE ary) /* * call-seq: - * array.compact -> new_array + * compact -> new_array + * + * Returns a new array containing only the non-+nil+ elements from +self+; + * element order is preserved: * - * Returns a new \Array containing all non-+nil+ elements from +self+: + * a = [nil, 0, nil, false, nil, '', nil, [], nil, {}] + * a.compact # => [0, false, "", [], {}] * - * a = [nil, 0, nil, 1, nil, 2, nil] - * a.compact # => [0, 1, 2] + * Related: Array#compact!; + * see also {Methods for Deleting}[rdoc-ref:Array@Methods+for+Deleting]. */ static VALUE @@ -6237,29 +6460,29 @@ rb_ary_compact(VALUE ary) /* * call-seq: - * array.count -> an_integer - * array.count(obj) -> an_integer - * array.count {|element| ... } -> an_integer + * count -> integer + * count(object) -> integer + * count {|element| ... } -> integer * * Returns a count of specified elements. * * With no argument and no block, returns the count of all elements: * - * [0, 1, 2].count # => 3 - * [].count # => 0 + * [0, :one, 'two', 3, 3.0].count # => 5 * - * With argument +obj+, returns the count of elements == to +obj+: + * With argument +object+ given, returns the count of elements == to +object+: * - * [0, 1, 2, 0.0].count(0) # => 2 - * [0, 1, 2].count(3) # => 0 + * [0, :one, 'two', 3, 3.0].count(3) # => 2 * * With no argument and a block given, calls the block with each element; * returns the count of elements for which the block returns a truthy value: * - * [0, 1, 2, 3].count {|element| element > 1} # => 2 + * [0, 1, 2, 3].count {|element| element > 1 } # => 2 * - * With argument +obj+ and a block given, issues a warning, ignores the block, - * and returns the count of elements == to +obj+. + * With argument +object+ and a block given, issues a warning, ignores the block, + * and returns the count of elements == to +object+. + * + * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying]. */ static VALUE @@ -6295,16 +6518,9 @@ rb_ary_count(int argc, VALUE *argv, VALUE ary) static VALUE flatten(VALUE ary, int level) { - static const rb_data_type_t flatten_memo_data_type = { - .wrap_struct_name = "array_flatten_memo_data_type", - .function = { NULL, (RUBY_DATA_FUNC)st_free_table }, - NULL, NULL, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED - }; - long i; - VALUE stack, result, tmp = 0, elt, vmemo; - st_table *memo = 0; - st_data_t id; + VALUE stack, result, tmp = 0, elt; + VALUE memo = Qfalse; for (i = 0; i < RARRAY_LEN(ary); i++) { elt = RARRAY_AREF(ary, i); @@ -6326,10 +6542,9 @@ flatten(VALUE ary, int level) rb_ary_push(stack, LONG2NUM(i + 1)); if (level < 0) { - memo = st_init_numtable(); - vmemo = TypedData_Wrap_Struct(0, &flatten_memo_data_type, memo); - st_insert(memo, (st_data_t)ary, (st_data_t)Qtrue); - st_insert(memo, (st_data_t)tmp, (st_data_t)Qtrue); + memo = rb_obj_hide(rb_ident_hash_new()); + rb_hash_aset(memo, ary, Qtrue); + rb_hash_aset(memo, tmp, Qtrue); } ary = tmp; @@ -6344,9 +6559,8 @@ flatten(VALUE ary, int level) } tmp = rb_check_array_type(elt); if (RBASIC(result)->klass) { - if (memo) { - RB_GC_GUARD(vmemo); - st_clear(memo); + if (RTEST(memo)) { + rb_hash_clear(memo); } rb_raise(rb_eRuntimeError, "flatten reentered"); } @@ -6355,12 +6569,11 @@ flatten(VALUE ary, int level) } else { if (memo) { - id = (st_data_t)tmp; - if (st_is_member(memo, id)) { - st_clear(memo); + if (rb_hash_aref(memo, tmp) == Qtrue) { + rb_hash_clear(memo); rb_raise(rb_eArgError, "tried to flatten recursive array"); } - st_insert(memo, id, (st_data_t)Qtrue); + rb_hash_aset(memo, tmp, Qtrue); } rb_ary_push(stack, ary); rb_ary_push(stack, LONG2NUM(i)); @@ -6372,8 +6585,7 @@ flatten(VALUE ary, int level) break; } if (memo) { - id = (st_data_t)ary; - st_delete(memo, &id, 0); + rb_hash_delete(memo, ary); } tmp = rb_ary_pop(stack); i = NUM2LONG(tmp); @@ -6381,7 +6593,7 @@ flatten(VALUE ary, int level) } if (memo) { - st_clear(memo); + rb_hash_clear(memo); } RBASIC_SET_CLASS(result, rb_cArray); @@ -6390,33 +6602,37 @@ flatten(VALUE ary, int level) /* * call-seq: - * array.flatten! -> self or nil - * array.flatten!(level) -> self or nil + * flatten!(depth = nil) -> self or nil + * + * Returns +self+ as a recursively flattening of +self+ to +depth+ levels of recursion; + * +depth+ must be an + * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects], + * or +nil+. + * At each level of recursion: * - * Replaces each nested \Array in +self+ with the elements from that \Array; - * returns +self+ if any changes, +nil+ otherwise. + * - Each element that is an array is "flattened" + * (that is, replaced by its individual array elements). + * - Each element that is not an array is unchanged + * (even if the element is an object that has instance method +flatten+). * - * With non-negative Integer argument +level+, flattens recursively through +level+ levels: + * Returns +nil+ if no elements were flattened. * - * a = [ 0, [ 1, [2, 3], 4 ], 5 ] - * a.flatten!(1) # => [0, 1, [2, 3], 4, 5] - * a = [ 0, [ 1, [2, 3], 4 ], 5 ] - * a.flatten!(2) # => [0, 1, 2, 3, 4, 5] - * a = [ 0, [ 1, [2, 3], 4 ], 5 ] - * a.flatten!(3) # => [0, 1, 2, 3, 4, 5] - * [0, 1, 2].flatten!(1) # => nil + * With non-negative integer argument +depth+, flattens recursively through +depth+ levels: * - * With no argument, a +nil+ argument, or with negative argument +level+, flattens all levels: + * a = [ 0, [ 1, [2, 3], 4 ], 5, {foo: 0}, Set.new([6, 7]) ] + * a # => [0, [1, [2, 3], 4], 5, {:foo=>0}, #] + * a.dup.flatten!(1) # => [0, 1, [2, 3], 4, 5, {:foo=>0}, #] + * a.dup.flatten!(1.1) # => [0, 1, [2, 3], 4, 5, {:foo=>0}, #] + * a.dup.flatten!(2) # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #] + * a.dup.flatten!(3) # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #] * - * a = [ 0, [ 1, [2, 3], 4 ], 5 ] - * a.flatten! # => [0, 1, 2, 3, 4, 5] - * [0, 1, 2].flatten! # => nil - * a = [ 0, [ 1, [2, 3], 4 ], 5 ] - * a.flatten!(-1) # => [0, 1, 2, 3, 4, 5] - * a = [ 0, [ 1, [2, 3], 4 ], 5 ] - * a.flatten!(-2) # => [0, 1, 2, 3, 4, 5] - * [0, 1, 2].flatten!(-1) # => nil + * With +nil+ or negative argument +depth+, flattens all levels: * + * a.dup.flatten! # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #] + * a.dup.flatten!(-1) # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #] + * + * Related: Array#flatten; + * see also {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning]. */ static VALUE @@ -6434,7 +6650,7 @@ rb_ary_flatten_bang(int argc, VALUE *argv, VALUE ary) if (result == ary) { return Qnil; } - if (!(mod = ARY_EMBED_P(result))) rb_obj_freeze(result); + if (!(mod = ARY_EMBED_P(result))) rb_ary_freeze(result); rb_ary_replace(ary, result); if (mod) ARY_SET_EMBED_LEN(result, 0); @@ -6443,35 +6659,37 @@ rb_ary_flatten_bang(int argc, VALUE *argv, VALUE ary) /* * call-seq: - * array.flatten -> new_array - * array.flatten(level) -> new_array - * - * Returns a new \Array that is a recursive flattening of +self+: - * - Each non-Array element is unchanged. - * - Each \Array is replaced by its individual elements. - * - * With non-negative Integer argument +level+, flattens recursively through +level+ levels: - * - * a = [ 0, [ 1, [2, 3], 4 ], 5 ] - * a.flatten(0) # => [0, [1, [2, 3], 4], 5] - * a = [ 0, [ 1, [2, 3], 4 ], 5 ] - * a.flatten(1) # => [0, 1, [2, 3], 4, 5] - * a = [ 0, [ 1, [2, 3], 4 ], 5 ] - * a.flatten(2) # => [0, 1, 2, 3, 4, 5] - * a = [ 0, [ 1, [2, 3], 4 ], 5 ] - * a.flatten(3) # => [0, 1, 2, 3, 4, 5] - * - * With no argument, a +nil+ argument, or with negative argument +level+, flattens all levels: - * - * a = [ 0, [ 1, [2, 3], 4 ], 5 ] - * a.flatten # => [0, 1, 2, 3, 4, 5] - * [0, 1, 2].flatten # => [0, 1, 2] - * a = [ 0, [ 1, [2, 3], 4 ], 5 ] - * a.flatten(-1) # => [0, 1, 2, 3, 4, 5] - * a = [ 0, [ 1, [2, 3], 4 ], 5 ] - * a.flatten(-2) # => [0, 1, 2, 3, 4, 5] - * [0, 1, 2].flatten(-1) # => [0, 1, 2] + * flatten(depth = nil) -> new_array + * + * Returns a new array that is a recursive flattening of +self+ + * to +depth+ levels of recursion; + * +depth+ must be an + * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects] + * or +nil+. + * At each level of recursion: * + * - Each element that is an array is "flattened" + * (that is, replaced by its individual array elements). + * - Each element that is not an array is unchanged + * (even if the element is an object that has instance method +flatten+). + * + * With non-negative integer argument +depth+, flattens recursively through +depth+ levels: + * + * a = [ 0, [ 1, [2, 3], 4 ], 5, {foo: 0}, Set.new([6, 7]) ] + * a # => [0, [1, [2, 3], 4], 5, {:foo=>0}, #] + * a.flatten(0) # => [0, [1, [2, 3], 4], 5, {:foo=>0}, #] + * a.flatten(1 ) # => [0, 1, [2, 3], 4, 5, {:foo=>0}, #] + * a.flatten(1.1) # => [0, 1, [2, 3], 4, 5, {:foo=>0}, #] + * a.flatten(2) # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #] + * a.flatten(3) # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #] + * + * With +nil+ or negative +depth+, flattens all levels. + * + * a.flatten # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #] + * a.flatten(-1) # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #] + * + * Related: Array#flatten!; + * see also {Methods for Converting}[rdoc-ref:Array@Methods+for+Converting]. */ static VALUE @@ -6503,7 +6721,7 @@ rb_ary_shuffle_bang(rb_execution_context_t *ec, VALUE ary, VALUE randgen) rb_ary_modify(ary); i = len = RARRAY_LEN(ary); RARRAY_PTR_USE(ary, ptr, { - while (i) { + while (i > 1) { long j = RAND_UPTO(i); VALUE tmp; if (len != RARRAY_LEN(ary) || ptr != RARRAY_CONST_PTR(ary)) { @@ -6525,6 +6743,14 @@ rb_ary_shuffle(rb_execution_context_t *ec, VALUE ary, VALUE randgen) return ary; } +static const rb_data_type_t ary_sample_memo_type = { + .wrap_struct_name = "ary_sample_memo", + .function = { + .dfree = (RUBY_DATA_FUNC)st_free_table, + }, + .flags = RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FREE_IMMEDIATELY +}; + static VALUE ary_sample(rb_execution_context_t *ec, VALUE ary, VALUE randgen, VALUE nv, VALUE to_array) { @@ -6606,11 +6832,9 @@ ary_sample(rb_execution_context_t *ec, VALUE ary, VALUE randgen, VALUE nv, VALUE } else if (n <= memo_threshold / 2) { long max_idx = 0; -#undef RUBY_UNTYPED_DATA_WARNING -#define RUBY_UNTYPED_DATA_WARNING 0 - VALUE vmemo = Data_Wrap_Struct(0, 0, st_free_table, 0); + VALUE vmemo = TypedData_Wrap_Struct(0, &ary_sample_memo_type, 0); st_table *memo = st_init_numtable_with_size(n); - DATA_PTR(vmemo) = memo; + RTYPEDDATA_DATA(vmemo) = memo; result = rb_ary_new_capa(n); RARRAY_PTR_USE(result, ptr_result, { for (i=0; i nil - * array.cycle(count) {|element| ... } -> nil - * array.cycle -> new_enumerator - * array.cycle(count) -> new_enumerator + * cycle(count = nil) {|element| ... } -> nil + * cycle(count = nil) -> new_enumerator * - * When called with positive Integer argument +count+ and a block, - * calls the block with each element, then does so again, + * With a block given, may call the block, depending on the value of argument +count+; + * +count+ must be an + * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects], + * or +nil+. + * + * When +count+ is positive, + * calls the block with each element, then does so repeatedly, * until it has done so +count+ times; returns +nil+: * * output = [] * [0, 1].cycle(2) {|element| output.push(element) } # => nil * output # => [0, 1, 0, 1] * - * If +count+ is zero or negative, does not call the block: + * When +count+ is zero or negative, does not call the block: * - * [0, 1].cycle(0) {|element| fail 'Cannot happen' } # => nil + * [0, 1].cycle(0) {|element| fail 'Cannot happen' } # => nil * [0, 1].cycle(-1) {|element| fail 'Cannot happen' } # => nil * - * When a block is given, and argument is omitted or +nil+, cycles forever: + * When +count+ is +nil+, cycles forever: * * # Prints 0 and 1 forever. * [0, 1].cycle {|element| puts element } * [0, 1].cycle(nil) {|element| puts element } * - * When no block is given, returns a new Enumerator: - * - * [0, 1].cycle(2) # => # - * [0, 1].cycle # => # => # - * [0, 1].cycle.first(5) # => [0, 1, 0, 1, 0] + * With no block given, returns a new Enumerator. * + * Related: see {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating]. */ static VALUE rb_ary_cycle(int argc, VALUE *argv, VALUE ary) @@ -6852,82 +7083,44 @@ rb_ary_permutation_size(VALUE ary, VALUE args, VALUE eobj) /* * call-seq: - * array.permutation {|element| ... } -> self - * array.permutation(n) {|element| ... } -> self - * array.permutation -> new_enumerator - * array.permutation(n) -> new_enumerator + * permutation(count = self.size) {|permutation| ... } -> self + * permutation(count = self.size) -> new_enumerator * - * When invoked with a block, yield all permutations of elements of +self+; returns +self+. - * The order of permutations is indeterminate. + * Iterates over permutations of the elements of +self+; + * the order of permutations is indeterminate. * - * When a block and an in-range positive Integer argument +n+ (0 < n <= self.size) - * are given, calls the block with all +n+-tuple permutations of +self+. - * - * Example: - * - * a = [0, 1, 2] - * a.permutation(2) {|permutation| p permutation } - * - * Output: - * - * [0, 1] - * [0, 2] - * [1, 0] - * [1, 2] - * [2, 0] - * [2, 1] - * - * Another example: + * With a block and an in-range positive integer argument +count+ (0 < count <= self.size) given, + * calls the block with each permutation of +self+ of size +count+; + * returns +self+: * * a = [0, 1, 2] - * a.permutation(3) {|permutation| p permutation } + * perms = [] + * a.permutation(1) {|perm| perms.push(perm) } + * perms # => [[0], [1], [2]] * - * Output: - * - * [0, 1, 2] - * [0, 2, 1] - * [1, 0, 2] - * [1, 2, 0] - * [2, 0, 1] - * [2, 1, 0] + * perms = [] + * a.permutation(2) {|perm| perms.push(perm) } + * perms # => [[0, 1], [0, 2], [1, 0], [1, 2], [2, 0], [2, 1]] * - * When +n+ is zero, calls the block once with a new empty \Array: - * - * a = [0, 1, 2] - * a.permutation(0) {|permutation| p permutation } + * perms = [] + * a.permutation(3) {|perm| perms.push(perm) } + * perms # => [[0, 1, 2], [0, 2, 1], [1, 0, 2], [1, 2, 0], [2, 0, 1], [2, 1, 0]] * - * Output: + * When +count+ is zero, calls the block once with a new empty array: * - * [] + * perms = [] + * a.permutation(0) {|perm| perms.push(perm) } + * perms # => [[]] * - * When +n+ is out of range (negative or larger than self.size), + * When +count+ is out of range (negative or larger than self.size), * does not call the block: * - * a = [0, 1, 2] * a.permutation(-1) {|permutation| fail 'Cannot happen' } * a.permutation(4) {|permutation| fail 'Cannot happen' } * - * When a block given but no argument, - * behaves the same as a.permutation(a.size): - * - * a = [0, 1, 2] - * a.permutation {|permutation| p permutation } - * - * Output: - * - * [0, 1, 2] - * [0, 2, 1] - * [1, 0, 2] - * [1, 2, 0] - * [2, 0, 1] - * [2, 1, 0] - * - * Returns a new Enumerator if no block given: - * - * a = [0, 1, 2] - * a.permutation # => # - * a.permutation(2) # => # + * With no block given, returns a new Enumerator. * + * Related: {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating]. */ static VALUE @@ -7000,56 +7193,46 @@ rb_ary_combination_size(VALUE ary, VALUE args, VALUE eobj) /* * call-seq: - * array.combination(n) {|element| ... } -> self - * array.combination(n) -> new_enumerator - * - * Calls the block, if given, with combinations of elements of +self+; - * returns +self+. The order of combinations is indeterminate. + * combination(count) {|element| ... } -> self + * combination(count) -> new_enumerator * - * When a block and an in-range positive Integer argument +n+ (0 < n <= self.size) - * are given, calls the block with all +n+-tuple combinations of +self+. - * - * Example: + * When a block and a positive + * {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects] + * argument +count+ (0 < count <= self.size) + * are given, calls the block with each combination of +self+ of size +count+; + * returns +self+: * - * a = [0, 1, 2] - * a.combination(2) {|combination| p combination } + * a = %w[a b c] # => ["a", "b", "c"] + * a.combination(2) {|combination| p combination } # => ["a", "b", "c"] * * Output: * - * [0, 1] - * [0, 2] - * [1, 2] + * ["a", "b"] + * ["a", "c"] + * ["b", "c"] * - * Another example: + * The order of the yielded combinations is not guaranteed. * - * a = [0, 1, 2] - * a.combination(3) {|combination| p combination } + * When +count+ is zero, calls the block once with a new empty array: * - * Output: - * - * [0, 1, 2] - * - * When +n+ is zero, calls the block once with a new empty \Array: - * - * a = [0, 1, 2] - * a1 = a.combination(0) {|combination| p combination } + * a.combination(0) {|combination| p combination } + * [].combination(0) {|combination| p combination } * * Output: * * [] + * [] * - * When +n+ is out of range (negative or larger than self.size), + * When +count+ is negative or larger than +self.size+ and +self+ is non-empty, * does not call the block: * - * a = [0, 1, 2] - * a.combination(-1) {|combination| fail 'Cannot happen' } - * a.combination(4) {|combination| fail 'Cannot happen' } - * - * Returns a new Enumerator if no block given: + * a.combination(-1) {|combination| fail 'Cannot happen' } # => ["a", "b", "c"] + * a.combination(4) {|combination| fail 'Cannot happen' } # => ["a", "b", "c"] * - * a = [0, 1, 2] - * a.combination(2) # => # + * With no block given, returns a new Enumerator. * + * Related: Array#permutation; + * see also {Methods for Iterating}[rdoc-ref:Array@Methods+for+Iterating]. */ static VALUE @@ -7136,68 +7319,41 @@ rb_ary_repeated_permutation_size(VALUE ary, VALUE args, VALUE eobj) /* * call-seq: - * array.repeated_permutation(n) {|permutation| ... } -> self - * array.repeated_permutation(n) -> new_enumerator + * repeated_permutation(size) {|permutation| ... } -> self + * repeated_permutation(size) -> new_enumerator * - * Calls the block with each repeated permutation of length +n+ of the elements of +self+; - * each permutation is an \Array; + * With a block given, calls the block with each repeated permutation of length +size+ + * of the elements of +self+; + * each permutation is an array; * returns +self+. The order of the permutations is indeterminate. * - * When a block and a positive Integer argument +n+ are given, calls the block with each - * +n+-tuple repeated permutation of the elements of +self+. - * The number of permutations is self.size**n. + * If a positive integer argument +size+ is given, + * calls the block with each +size+-tuple repeated permutation of the elements of +self+. + * The number of permutations is self.size**size. * - * +n+ = 1: - * - * a = [0, 1, 2] - * a.repeated_permutation(1) {|permutation| p permutation } - * - * Output: - * - * [0] - * [1] - * [2] - * - * +n+ = 2: - * - * a.repeated_permutation(2) {|permutation| p permutation } - * - * Output: + * Examples: * - * [0, 0] - * [0, 1] - * [0, 2] - * [1, 0] - * [1, 1] - * [1, 2] - * [2, 0] - * [2, 1] - * [2, 2] + * - +size+ is 1: * - * If +n+ is zero, calls the block once with an empty \Array. + * p = [] + * [0, 1, 2].repeated_permutation(1) {|permutation| p.push(permutation) } + * p # => [[0], [1], [2]] * - * If +n+ is negative, does not call the block: + * - +size+ is 2: * - * a.repeated_permutation(-1) {|permutation| fail 'Cannot happen' } + * p = [] + * [0, 1, 2].repeated_permutation(2) {|permutation| p.push(permutation) } + * p # => [[0, 0], [0, 1], [0, 2], [1, 0], [1, 1], [1, 2], [2, 0], [2, 1], [2, 2]] * - * Returns a new Enumerator if no block given: + * If +size+ is zero, calls the block once with an empty array. * - * a = [0, 1, 2] - * a.repeated_permutation(2) # => # + * If +size+ is negative, does not call the block: * - * Using Enumerators, it's convenient to show the permutations and counts - * for some values of +n+: + * [0, 1, 2].repeated_permutation(-1) {|permutation| fail 'Cannot happen' } * - * e = a.repeated_permutation(0) - * e.size # => 1 - * e.to_a # => [[]] - * e = a.repeated_permutation(1) - * e.size # => 3 - * e.to_a # => [[0], [1], [2]] - * e = a.repeated_permutation(2) - * e.size # => 9 - * e.to_a # => [[0, 0], [0, 1], [0, 2], [1, 0], [1, 1], [1, 2], [2, 0], [2, 1], [2, 2]] + * With no block given, returns a new Enumerator. * + * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining]. */ static VALUE rb_ary_repeated_permutation(VALUE ary, VALUE num) @@ -7268,65 +7424,41 @@ rb_ary_repeated_combination_size(VALUE ary, VALUE args, VALUE eobj) /* * call-seq: - * array.repeated_combination(n) {|combination| ... } -> self - * array.repeated_combination(n) -> new_enumerator + * repeated_combination(size) {|combination| ... } -> self + * repeated_combination(size) -> new_enumerator * - * Calls the block with each repeated combination of length +n+ of the elements of +self+; - * each combination is an \Array; + * With a block given, calls the block with each repeated combination of length +size+ + * of the elements of +self+; + * each combination is an array; * returns +self+. The order of the combinations is indeterminate. * - * When a block and a positive Integer argument +n+ are given, calls the block with each - * +n+-tuple repeated combination of the elements of +self+. - * The number of combinations is (n+1)(n+2)/2. - * - * +n+ = 1: - * - * a = [0, 1, 2] - * a.repeated_combination(1) {|combination| p combination } - * - * Output: - * - * [0] - * [1] - * [2] - * - * +n+ = 2: + * If a positive integer argument +size+ is given, + * calls the block with each +size+-tuple repeated combination of the elements of +self+. + * The number of combinations is (size+1)(size+2)/2. * - * a.repeated_combination(2) {|combination| p combination } + * Examples: * - * Output: + * - +size+ is 1: * - * [0, 0] - * [0, 1] - * [0, 2] - * [1, 1] - * [1, 2] - * [2, 2] + * c = [] + * [0, 1, 2].repeated_combination(1) {|combination| c.push(combination) } + * c # => [[0], [1], [2]] * - * If +n+ is zero, calls the block once with an empty \Array. + * - +size+ is 2: * - * If +n+ is negative, does not call the block: + * c = [] + * [0, 1, 2].repeated_combination(2) {|combination| c.push(combination) } + * c # => [[0, 0], [0, 1], [0, 2], [1, 1], [1, 2], [2, 2]] * - * a.repeated_combination(-1) {|combination| fail 'Cannot happen' } + * If +size+ is zero, calls the block once with an empty array. * - * Returns a new Enumerator if no block given: + * If +size+ is negative, does not call the block: * - * a = [0, 1, 2] - * a.repeated_combination(2) # => # + * [0, 1, 2].repeated_combination(-1) {|combination| fail 'Cannot happen' } * - * Using Enumerators, it's convenient to show the combinations and counts - * for some values of +n+: - * - * e = a.repeated_combination(0) - * e.size # => 1 - * e.to_a # => [[]] - * e = a.repeated_combination(1) - * e.size # => 3 - * e.to_a # => [[0], [1], [2]] - * e = a.repeated_combination(2) - * e.size # => 6 - * e.to_a # => [[0, 0], [0, 1], [0, 2], [1, 1], [1, 2], [2, 2]] + * With no block given, returns a new Enumerator. * + * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining]. */ static VALUE @@ -7366,62 +7498,55 @@ rb_ary_repeated_combination(VALUE ary, VALUE num) /* * call-seq: - * array.product(*other_arrays) -> new_array - * array.product(*other_arrays) {|combination| ... } -> self + * product(*other_arrays) -> new_array + * product(*other_arrays) {|combination| ... } -> self * - * Computes and returns or yields all combinations of elements from all the Arrays, + * Computes all combinations of elements from all the arrays, * including both +self+ and +other_arrays+: * * - The number of combinations is the product of the sizes of all the arrays, * including both +self+ and +other_arrays+. * - The order of the returned combinations is indeterminate. * - * When no block is given, returns the combinations as an \Array of Arrays: + * With no block given, returns the combinations as an array of arrays: * - * a = [0, 1, 2] - * a1 = [3, 4] - * a2 = [5, 6] - * p = a.product(a1) - * p.size # => 6 # a.size * a1.size - * p # => [[0, 3], [0, 4], [1, 3], [1, 4], [2, 3], [2, 4]] - * p = a.product(a1, a2) - * p.size # => 12 # a.size * a1.size * a2.size - * p # => [[0, 3, 5], [0, 3, 6], [0, 4, 5], [0, 4, 6], [1, 3, 5], [1, 3, 6], [1, 4, 5], [1, 4, 6], [2, 3, 5], [2, 3, 6], [2, 4, 5], [2, 4, 6]] - * - * If any argument is an empty \Array, returns an empty \Array. - * - * If no argument is given, returns an \Array of 1-element Arrays, - * each containing an element of +self+: - * - * a.product # => [[0], [1], [2]] + * p = [0, 1].product([2, 3]) + * # => [[0, 2], [0, 3], [1, 2], [1, 3]] + * p.size # => 4 + * p = [0, 1].product([2, 3], [4, 5]) + * # => [[0, 2, 4], [0, 2, 5], [0, 3, 4], [0, 3, 5], [1, 2, 4], [1, 2, 5], [1, 3, 4], [1, 3,... + * p.size # => 8 * - * When a block is given, yields each combination as an \Array; returns +self+: + * If +self+ or any argument is empty, returns an empty array: * - * a.product(a1) {|combination| p combination } + * [].product([2, 3], [4, 5]) # => [] + * [0, 1].product([2, 3], []) # => [] * - * Output: + * If no argument is given, returns an array of 1-element arrays, + * each containing an element of +self+: * - * [0, 3] - * [0, 4] - * [1, 3] - * [1, 4] - * [2, 3] - * [2, 4] + * a.product # => [[0], [1], [2]] * - * If any argument is an empty \Array, does not call the block: + * With a block given, calls the block with each combination; returns +self+: * - * a.product(a1, a2, []) {|combination| fail 'Cannot happen' } + * p = [] + * [0, 1].product([2, 3]) {|combination| p.push(combination) } + * p # => [[0, 2], [0, 3], [1, 2], [1, 3]] * - * If no argument is given, yields each element of +self+ as a 1-element \Array: + * If +self+ or any argument is empty, does not call the block: * - * a.product {|combination| p combination } + * [].product([2, 3], [4, 5]) {|combination| fail 'Cannot happen' } + * # => [] + * [0, 1].product([2, 3], []) {|combination| fail 'Cannot happen' } + * # => [0, 1] * - * Output: + * If no argument is given, calls the block with each element of +self+ as a 1-element array: * - * [0] - * [1] - * [2] + * p = [] + * [0, 1].product {|combination| p.push(combination) } + * p # => [[0], [1]] * + * Related: see {Methods for Combining}[rdoc-ref:Array@Methods+for+Combining]. */ static VALUE @@ -7514,20 +7639,20 @@ rb_ary_product(int argc, VALUE *argv, VALUE ary) /* * call-seq: - * array.take(n) -> new_array - * - * Returns a new \Array containing the first +n+ element of +self+, - * where +n+ is a non-negative Integer; - * does not modify +self+. + * take(count) -> new_array * - * Examples: + * Returns a new array containing the first +count+ element of +self+ + * (as available); + * +count+ must be a non-negative numeric; + * does not modify +self+: * - * a = [0, 1, 2, 3, 4, 5] - * a.take(1) # => [0] - * a.take(2) # => [0, 1] - * a.take(50) # => [0, 1, 2, 3, 4, 5] - * a # => [0, 1, 2, 3, 4, 5] + * a = ['a', 'b', 'c', 'd'] + * a.take(2) # => ["a", "b"] + * a.take(2.1) # => ["a", "b"] + * a.take(50) # => ["a", "b", "c", "d"] + * a.take(0) # => [] * + * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching]. */ static VALUE @@ -7542,25 +7667,23 @@ rb_ary_take(VALUE obj, VALUE n) /* * call-seq: - * array.take_while {|element| ... } -> new_array - * array.take_while -> new_enumerator - * - * Returns a new \Array containing zero or more leading elements of +self+; - * does not modify +self+. + * take_while {|element| ... } -> new_array + * take_while -> new_enumerator * * With a block given, calls the block with each successive element of +self+; - * stops if the block returns +false+ or +nil+; - * returns a new \Array containing those elements for which the block returned a truthy value: + * stops iterating if the block returns +false+ or +nil+; + * returns a new array containing those elements for which the block returned a truthy value: * * a = [0, 1, 2, 3, 4, 5] * a.take_while {|element| element < 3 } # => [0, 1, 2] - * a.take_while {|element| true } # => [0, 1, 2, 3, 4, 5] - * a # => [0, 1, 2, 3, 4, 5] + * a.take_while {|element| true } # => [0, 1, 2, 3, 4, 5] + * a.take_while {|element| false } # => [] * - * With no block given, returns a new Enumerator: + * With no block given, returns a new Enumerator. * - * [0, 1].take_while # => # + * Does not modify +self+. * + * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching]. */ static VALUE @@ -7577,10 +7700,10 @@ rb_ary_take_while(VALUE ary) /* * call-seq: - * array.drop(n) -> new_array + * drop(count) -> new_array * - * Returns a new \Array containing all but the first +n+ element of +self+, - * where +n+ is a non-negative Integer; + * Returns a new array containing all but the first +count+ element of +self+, + * where +count+ is a non-negative integer; * does not modify +self+. * * Examples: @@ -7589,7 +7712,9 @@ rb_ary_take_while(VALUE ary) * a.drop(0) # => [0, 1, 2, 3, 4, 5] * a.drop(1) # => [1, 2, 3, 4, 5] * a.drop(2) # => [2, 3, 4, 5] + * a.drop(9) # => [] * + * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching]. */ static VALUE @@ -7608,23 +7733,20 @@ rb_ary_drop(VALUE ary, VALUE n) /* * call-seq: - * array.drop_while {|element| ... } -> new_array - * array.drop_while -> new_enumerator - - * Returns a new \Array containing zero or more trailing elements of +self+; - * does not modify +self+. + * drop_while {|element| ... } -> new_array + * drop_while -> new_enumerator * * With a block given, calls the block with each successive element of +self+; * stops if the block returns +false+ or +nil+; - * returns a new \Array _omitting_ those elements for which the block returned a truthy value: + * returns a new array _omitting_ those elements for which the block returned a truthy value; + * does not modify +self+: * * a = [0, 1, 2, 3, 4, 5] * a.drop_while {|element| element < 3 } # => [3, 4, 5] * - * With no block given, returns a new Enumerator: - * - * [0, 1].drop_while # => # => # + * With no block given, returns a new Enumerator. * + * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching]. */ static VALUE @@ -7641,38 +7763,41 @@ rb_ary_drop_while(VALUE ary) /* * call-seq: - * array.any? -> true or false - * array.any? {|element| ... } -> true or false - * array.any?(obj) -> true or false + * any? -> true or false + * any?(object) -> true or false + * any? {|element| ... } -> true or false * - * Returns +true+ if any element of +self+ meets a given criterion. + * Returns whether for any element of +self+, a given criterion is satisfied. * - * If +self+ has no element, returns +false+ and argument or block - * are not used. + * With no block and no argument, returns whether any element of +self+ is truthy: * - * With no block given and no argument, returns +true+ if +self+ has any truthy element, - * +false+ otherwise: + * [nil, false, []].any? # => true # Array object is truthy. + * [nil, false, {}].any? # => true # Hash object is truthy. + * [nil, false, ''].any? # => true # String object is truthy. + * [nil, false].any? # => false # Nil and false are not truthy. * - * [nil, 0, false].any? # => true - * [nil, false].any? # => false - * [].any? # => false + * With argument +object+ given, + * returns whether object === ele for any element +ele+ in +self+: * - * With a block given and no argument, calls the block with each element in +self+; - * returns +true+ if the block returns any truthy value, +false+ otherwise: + * [nil, false, 0].any?(0) # => true + * [nil, false, 1].any?(0) # => false + * [nil, false, 'food'].any?(/foo/) # => true + * [nil, false, 'food'].any?(/bar/) # => false * - * [0, 1, 2].any? {|element| element > 1 } # => true - * [0, 1, 2].any? {|element| element > 2 } # => false + * With a block given, + * calls the block with each element in +self+; + * returns whether the block returns any truthy value: * - * If argument +obj+ is given, returns +true+ if +obj+.=== any element, - * +false+ otherwise: + * [0, 1, 2].any? {|ele| ele < 1 } # => true + * [0, 1, 2].any? {|ele| ele < 0 } # => false + * + * With both a block and argument +object+ given, + * ignores the block and uses +object+ as above. * - * ['food', 'drink'].any?(/foo/) # => true - * ['food', 'drink'].any?(/bar/) # => false - * [].any?(/foo/) # => false - * [0, 1, 2].any?(1) # => true - * [0, 1, 2].any?(3) # => false + * Special case: returns +false+ if +self+ is empty + * (regardless of any given argument or block). * - * Related: Enumerable#any? + * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying]. */ static VALUE @@ -7705,37 +7830,41 @@ rb_ary_any_p(int argc, VALUE *argv, VALUE ary) /* * call-seq: - * array.all? -> true or false - * array.all? {|element| ... } -> true or false - * array.all?(obj) -> true or false + * all? -> true or false + * all?(object) -> true or false + * all? {|element| ... } -> true or false * - * Returns +true+ if all elements of +self+ meet a given criterion. + * Returns whether for every element of +self+, + * a given criterion is satisfied. * - * If +self+ has no element, returns +true+ and argument or block - * are not used. + * With no block and no argument, + * returns whether every element of +self+ is truthy: * - * With no block given and no argument, returns +true+ if +self+ contains only truthy elements, - * +false+ otherwise: + * [[], {}, '', 0, 0.0, Object.new].all? # => true # All truthy objects. + * [[], {}, '', 0, 0.0, nil].all? # => false # nil is not truthy. + * [[], {}, '', 0, 0.0, false].all? # => false # false is not truthy. * - * [0, 1, :foo].all? # => true - * [0, nil, 2].all? # => false - * [].all? # => true + * With argument +object+ given, returns whether object === ele + * for every element +ele+ in +self+: * - * With a block given and no argument, calls the block with each element in +self+; - * returns +true+ if the block returns only truthy values, +false+ otherwise: + * [0, 0, 0].all?(0) # => true + * [0, 1, 2].all?(1) # => false + * ['food', 'fool', 'foot'].all?(/foo/) # => true + * ['food', 'drink'].all?(/foo/) # => false * - * [0, 1, 2].all? { |element| element < 3 } # => true - * [0, 1, 2].all? { |element| element < 2 } # => false + * With a block given, calls the block with each element in +self+; + * returns whether the block returns only truthy values: * - * If argument +obj+ is given, returns +true+ if obj.=== every element, +false+ otherwise: + * [0, 1, 2].all? { |ele| ele < 3 } # => true + * [0, 1, 2].all? { |ele| ele < 2 } # => false * - * ['food', 'fool', 'foot'].all?(/foo/) # => true - * ['food', 'drink'].all?(/bar/) # => false - * [].all?(/foo/) # => true - * [0, 0, 0].all?(0) # => true - * [0, 1, 2].all?(1) # => false + * With both a block and argument +object+ given, + * ignores the block and uses +object+ as above. * - * Related: Enumerable#all? + * Special case: returns +true+ if +self+ is empty + * (regardless of any given argument or block). + * + * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying]. */ static VALUE @@ -7768,34 +7897,35 @@ rb_ary_all_p(int argc, VALUE *argv, VALUE ary) /* * call-seq: - * array.none? -> true or false - * array.none? {|element| ... } -> true or false - * array.none?(obj) -> true or false + * none? -> true or false + * none?(object) -> true or false + * none? {|element| ... } -> true or false * - * Returns +true+ if no element of +self+ meet a given criterion. + * Returns +true+ if no element of +self+ meets a given criterion, +false+ otherwise. * * With no block given and no argument, returns +true+ if +self+ has no truthy elements, * +false+ otherwise: * - * [nil, false].none? # => true + * [nil, false].none? # => true * [nil, 0, false].none? # => false - * [].none? # => true + * [].none? # => true + * + * With argument +object+ given, returns +false+ if for any element +element+, + * object === element; +true+ otherwise: * - * With a block given and no argument, calls the block with each element in +self+; + * ['food', 'drink'].none?(/bar/) # => true + * ['food', 'drink'].none?(/foo/) # => false + * [].none?(/foo/) # => true + * [0, 1, 2].none?(3) # => true + * [0, 1, 2].none?(1) # => false + * + * With a block given, calls the block with each element in +self+; * returns +true+ if the block returns no truthy value, +false+ otherwise: * * [0, 1, 2].none? {|element| element > 3 } # => true * [0, 1, 2].none? {|element| element > 1 } # => false * - * If argument +obj+ is given, returns +true+ if obj.=== no element, +false+ otherwise: - * - * ['food', 'drink'].none?(/bar/) # => true - * ['food', 'drink'].none?(/foo/) # => false - * [].none?(/foo/) # => true - * [0, 1, 2].none?(3) # => true - * [0, 1, 2].none?(1) # => false - * - * Related: Enumerable#none? + * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying]. */ static VALUE @@ -7828,9 +7958,9 @@ rb_ary_none_p(int argc, VALUE *argv, VALUE ary) /* * call-seq: - * array.one? -> true or false - * array.one? {|element| ... } -> true or false - * array.one?(obj) -> true or false + * one? -> true or false + * one? {|element| ... } -> true or false + * one?(object) -> true or false * * Returns +true+ if exactly one element of +self+ meets a given criterion. * @@ -7842,14 +7972,14 @@ rb_ary_none_p(int argc, VALUE *argv, VALUE ary) * [nil, nil].one? # => false * [].one? # => false * - * With a block given and no argument, calls the block with each element in +self+; + * With a block given, calls the block with each element in +self+; * returns +true+ if the block a truthy value for exactly one element, +false+ otherwise: * * [0, 1, 2].one? {|element| element > 0 } # => false * [0, 1, 2].one? {|element| element > 1 } # => true * [0, 1, 2].one? {|element| element > 2 } # => false * - * If argument +obj+ is given, returns +true+ if obj.=== exactly one element, + * With argument +object+ given, returns +true+ if for exactly one element +element+, object === element; * +false+ otherwise: * * [0, 1, 2].one?(0) # => true @@ -7859,7 +7989,7 @@ rb_ary_none_p(int argc, VALUE *argv, VALUE ary) * ['food', 'drink'].one?(/foo/) # => true * [].one?(/foo/) # => false * - * Related: Enumerable#one? + * Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying]. */ static VALUE @@ -7902,11 +8032,11 @@ rb_ary_one_p(int argc, VALUE *argv, VALUE ary) /* * call-seq: - * array.dig(index, *identifiers) -> object + * dig(index, *identifiers) -> object * - * Finds and returns the object in nested objects - * that is specified by +index+ and +identifiers+. - * The nested objects may be instances of various classes. + * Finds and returns the object in nested object + * specified by +index+ and +identifiers+; + * the nested objects may be instances of various classes. * See {Dig Methods}[rdoc-ref:dig_methods.rdoc]. * * Examples: @@ -7917,6 +8047,7 @@ rb_ary_one_p(int argc, VALUE *argv, VALUE ary) * a.dig(1, 2, 0) # => :bat * a.dig(1, 2, 3) # => nil * + * Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching]. */ static VALUE @@ -7945,40 +8076,41 @@ finish_exact_sum(long n, VALUE r, VALUE v, int z) /* * call-seq: - * array.sum(init = 0) -> object - * array.sum(init = 0) {|element| ... } -> object + * sum(init = 0) -> object + * sum(init = 0) {|element| ... } -> object * - * When no block is given, returns the object equivalent to: + * With no block given, returns the sum of +init+ and all elements of +self+; + * for array +array+ and value +init+, equivalent to: * * sum = init * array.each {|element| sum += element } * sum * - * For example, [e1, e2, e3].sum returns init + e1 + e2 + e3. + * For example, [e0, e1, e2].sum returns init + e0 + e1 + e2. * * Examples: * - * a = [0, 1, 2, 3] - * a.sum # => 6 - * a.sum(100) # => 106 + * [0, 1, 2, 3].sum # => 6 + * [0, 1, 2, 3].sum(100) # => 106 + * ['abc', 'def', 'ghi'].sum('jkl') # => "jklabcdefghi" + * [[:foo, :bar], ['foo', 'bar']].sum([2, 3]) + * # => [2, 3, :foo, :bar, "foo", "bar"] * - * The elements need not be numeric, but must be +-compatible - * with each other and with +init+: + * The +init+ value and elements need not be numeric, but must all be +-compatible: * - * a = ['abc', 'def', 'ghi'] - * a.sum('jkl') # => "jklabcdefghi" + * # Raises TypeError: Array can't be coerced into Integer. + * [[:foo, :bar], ['foo', 'bar']].sum(2) * - * When a block is given, it is called with each element - * and the block's return value (instead of the element itself) is used as the addend: + * With a block given, calls the block with each element of +self+; + * the block's return value (instead of the element itself) is used as the addend: * - * a = ['zero', 1, :two] - * s = a.sum('Coerced and concatenated: ') {|element| element.to_s } - * s # => "Coerced and concatenated: zero1two" + * ['zero', 1, :two].sum('Coerced and concatenated: ') {|element| element.to_s } + * # => "Coerced and concatenated: zero1two" * * Notes: * * - Array#join and Array#flatten may be faster than Array#sum - * for an \Array of Strings or an \Array of Arrays. + * for an array of strings or an array of arrays. * - Array#sum method may not respect method redefinition of "+" methods such as Integer#+. * */ @@ -8100,6 +8232,7 @@ rb_ary_sum(int argc, VALUE *argv, VALUE ary) return v; } +/* :nodoc: */ static VALUE rb_ary_deconstruct(VALUE ary) { @@ -8107,15 +8240,37 @@ rb_ary_deconstruct(VALUE ary) } /* - * An \Array is an ordered, integer-indexed collection of objects, called _elements_. - * Any object (even another array) may be an array element, - * and an array can contain objects of different types. + * An \Array object is an ordered, integer-indexed collection of objects, + * called _elements_; + * the object represents + * an {array data structure}[https://en.wikipedia.org/wiki/Array_(data_structure)]. + * + * An element may be any object (even another array); + * elements may be any mixture of objects of different types. + * + * Important data structures that use arrays include: + * + * - {Coordinate vector}[https://en.wikipedia.org/wiki/Coordinate_vector]. + * - {Matrix}[https://en.wikipedia.org/wiki/Matrix_(mathematics)]. + * - {Heap}[https://en.wikipedia.org/wiki/Heap_(data_structure)]. + * - {Hash table}[https://en.wikipedia.org/wiki/Hash_table]. + * - {Deque (double-ended queue)}[https://en.wikipedia.org/wiki/Double-ended_queue]. + * - {Queue}[https://en.wikipedia.org/wiki/Queue_(abstract_data_type)]. + * - {Stack}[https://en.wikipedia.org/wiki/Stack_(abstract_data_type)]. + * + * There are also array-like data structures: + * + * - {Associative array}[https://en.wikipedia.org/wiki/Associative_array] (see Hash). + * - {Directory}[https://en.wikipedia.org/wiki/Directory_(computing)] (see Dir). + * - {Environment}[https://en.wikipedia.org/wiki/Environment_variable] (see ENV). + * - {Set}[https://en.wikipedia.org/wiki/Set_(abstract_data_type)] (see Set). + * - {String}[https://en.wikipedia.org/wiki/String_(computer_science)] (see String). * * == \Array Indexes * * \Array indexing starts at 0, as in C or Java. * - * A positive index is an offset from the first element: + * A non-negative index is an offset from the first element: * * - Index 0 indicates the first element. * - Index 1 indicates the second element. @@ -8127,6 +8282,9 @@ rb_ary_deconstruct(VALUE ary) * - Index -2 indicates the next-to-last element. * - ... * + * + * === In-Range and Out-of-Range Indexes + * * A non-negative index is in range if and only if it is smaller than * the size of the array. For a 3-element array: * @@ -8139,31 +8297,32 @@ rb_ary_deconstruct(VALUE ary) * - Indexes -1 through -3 are in range. * - Index -4 is out of range. * + * === Effective Index + * * Although the effective index into an array is always an integer, - * some methods (both within and outside of class \Array) + * some methods (both within class \Array and elsewhere) * accept one or more non-integer arguments that are * {integer-convertible objects}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects]. * - * * == Creating Arrays * * You can create an \Array object explicitly with: * - * - An {array literal}[rdoc-ref:literals.rdoc@Array+Literals]: + * - An {array literal}[rdoc-ref:syntax/literals.rdoc@Array+Literals]: * * [1, 'one', :one, [2, 'two', :two]] * - * - A {%w or %W: string-array Literal}[rdoc-ref:literals.rdoc@25w+and+-25W-3A+String-Array+Literals]: + * - A {%w or %W string-array Literal}[rdoc-ref:syntax/literals.rdoc@25w+and+-25W-3A+String-Array+Literals]: * * %w[foo bar baz] # => ["foo", "bar", "baz"] * %w[1 % *] # => ["1", "%", "*"] * - * - A {%i pr %I: symbol-array Literal}[rdoc-ref:literals.rdoc@25i+and+-25I-3A+Symbol-Array+Literals]: + * - A {%i or %I symbol-array Literal}[rdoc-ref:syntax/literals.rdoc@25i+and+-25I-3A+Symbol-Array+Literals]: * * %i[foo bar baz] # => [:foo, :bar, :baz] * %i[1 % *] # => [:"1", :%, :*] * - * - \Method Kernel#Array: + * - Method Kernel#Array: * * Array(["a", "b"]) # => ["a", "b"] * Array(1..5) # => [1, 2, 3, 4, 5] @@ -8172,7 +8331,7 @@ rb_ary_deconstruct(VALUE ary) * Array(1) # => [1] * Array({:a => "a", :b => "b"}) # => [[:a, "a"], [:b, "b"]] * - * - \Method Array.new: + * - Method Array.new: * * Array.new # => [] * Array.new(3) # => [nil, nil, nil] @@ -8227,8 +8386,8 @@ rb_ary_deconstruct(VALUE ary) * * == Example Usage * - * In addition to the methods it mixes in through the Enumerable module, the - * \Array class has proprietary methods for accessing, searching and otherwise + * In addition to the methods it mixes in through the Enumerable module, + * class \Array has proprietary methods for accessing, searching and otherwise * manipulating arrays. * * Some of the more common ones are illustrated below. @@ -8278,7 +8437,7 @@ rb_ary_deconstruct(VALUE ary) * * == Obtaining Information about an \Array * - * Arrays keep track of their own length at all times. To query an array + * An array keeps track of its own length at all times. To query an array * about the number of elements it contains, use #length, #count or #size. * * browsers = ['Chrome', 'Firefox', 'Safari', 'Opera', 'IE'] @@ -8293,7 +8452,7 @@ rb_ary_deconstruct(VALUE ary) * * browsers.include?('Konqueror') #=> false * - * == Adding Items to Arrays + * == Adding Items to an \Array * * Items can be added to the end of an array by using either #push or #<< * @@ -8354,11 +8513,11 @@ rb_ary_deconstruct(VALUE ary) * arr = [2, 5, 6, 556, 6, 6, 8, 9, 0, 123, 556] * arr.uniq #=> [2, 5, 6, 556, 8, 9, 0, 123] * - * == Iterating over Arrays + * == Iterating over an \Array * - * Like all classes that include the Enumerable module, \Array has an each + * Like all classes that include the Enumerable module, class \Array has an each * method, which defines what elements should be iterated over and how. In - * case of Array's #each, all elements in the \Array instance are yielded to + * case of Array#each, all elements in +self+ are yielded to * the supplied block in sequence. * * Note that this operation leaves the array unchanged. @@ -8418,7 +8577,7 @@ rb_ary_deconstruct(VALUE ary) * * == What's Here * - * First, what's elsewhere. \Class \Array: + * First, what's elsewhere. Class \Array: * * - Inherits from {class Object}[rdoc-ref:Object@What-27s+Here]. * - Includes {module Enumerable}[rdoc-ref:Enumerable@What-27s+Here], @@ -8443,148 +8602,132 @@ rb_ary_deconstruct(VALUE ary) * - ::new: Returns a new array. * - ::try_convert: Returns a new array created from a given object. * + * See also {Creating Arrays}[rdoc-ref:Array@Creating+Arrays]. + * * === Methods for Querying * - * - #length, #size: Returns the count of elements. - * - #include?: Returns whether any element == a given object. - * - #empty?: Returns whether there are no elements. * - #all?: Returns whether all elements meet a given criterion. * - #any?: Returns whether any element meets a given criterion. + * - #count: Returns the count of elements that meet a given criterion. + * - #empty?: Returns whether there are no elements. + * - #find_index (aliased as #index): Returns the index of the first element that meets a given criterion. + * - #hash: Returns the integer hash code. + * - #include?: Returns whether any element == a given object. + * - #length (aliased as #size): Returns the count of elements. * - #none?: Returns whether no element == a given object. * - #one?: Returns whether exactly one element == a given object. - * - #count: Returns the count of elements that meet a given criterion. - * - #find_index, #index: Returns the index of the first element that meets a given criterion. * - #rindex: Returns the index of the last element that meets a given criterion. - * - #hash: Returns the integer hash code. * * === Methods for Comparing * - * - #<=>: Returns -1, 0, or 1 * as +self+ is less than, equal to, or - * greater than a given object. - * - #==: Returns whether each element in +self+ is == to the corresponding element - * in a given object. - * - #eql?: Returns whether each element in +self+ is eql? to the corresponding - * element in a given object. + * - #<=>: Returns -1, 0, or 1, as +self+ is less than, equal to, or greater than a given object. + * - #==: Returns whether each element in +self+ is == to the corresponding element in a given object. + * - #eql?: Returns whether each element in +self+ is eql? to the corresponding element in a given object. * === Methods for Fetching * * These methods do not modify +self+. * - * - #[]: Returns one or more elements. - * - #fetch: Returns the element at a given offset. - * - #first: Returns one or more leading elements. - * - #last: Returns one or more trailing elements. - * - #max: Returns one or more maximum-valued elements, - * as determined by <=> or a given block. - * - #min: Returns one or more minimum-valued elements, - * as determined by <=> or a given block. - * - #minmax: Returns the minimum-valued and maximum-valued elements, - * as determined by <=> or a given block. - * - #assoc: Returns the first element that is an array - * whose first element == a given object. - * - #rassoc: Returns the first element that is an array - * whose second element == a given object. + * - #[] (aliased as #slice): Returns consecutive elements as determined by a given argument. + * - #assoc: Returns the first element that is an array whose first element == a given object. * - #at: Returns the element at a given offset. - * - #values_at: Returns the elements at given offsets. - * - #dig: Returns the object in nested objects - * that is specified by a given index and additional arguments. + * - #bsearch: Returns an element selected via a binary search as determined by a given block. + * - #bsearch_index: Returns the index of an element selected via a binary search as determined by a given block. + * - #compact: Returns an array containing all non-+nil+ elements. + * - #dig: Returns the object in nested objects that is specified by a given index and additional arguments. * - #drop: Returns trailing elements as determined by a given index. - * - #take: Returns leading elements as determined by a given index. * - #drop_while: Returns trailing elements as determined by a given block. - * - #take_while: Returns leading elements as determined by a given block. - * - #slice: Returns consecutive elements as determined by a given argument. - * - #sort: Returns all elements in an order determined by <=> or a given block. + * - #fetch: Returns the element at a given offset. + * - #fetch_values: Returns elements at given offsets. + * - #first: Returns one or more leading elements. + * - #last: Returns one or more trailing elements. + * - #max: Returns one or more maximum-valued elements, as determined by #<=> or a given block. + * - #min: Returns one or more minimum-valued elements, as determined by #<=> or a given block. + * - #minmax: Returns the minimum-valued and maximum-valued elements, as determined by #<=> or a given block. + * - #rassoc: Returns the first element that is an array whose second element == a given object. + * - #reject: Returns an array containing elements not rejected by a given block. * - #reverse: Returns all elements in reverse order. - * - #compact: Returns an array containing all non-+nil+ elements. - * - #select, #filter: Returns an array containing elements selected by a given block. - * - #uniq: Returns an array containing non-duplicate elements. * - #rotate: Returns all elements with some rotated from one end to the other. - * - #bsearch: Returns an element selected via a binary search - * as determined by a given block. - * - #bsearch_index: Returns the index of an element selected via a binary search - * as determined by a given block. * - #sample: Returns one or more random elements. + * - #select (aliased as #filter): Returns an array containing elements selected by a given block. * - #shuffle: Returns elements in a random order. + * - #sort: Returns all elements in an order determined by #<=> or a given block. + * - #take: Returns leading elements as determined by a given index. + * - #take_while: Returns leading elements as determined by a given block. + * - #uniq: Returns an array containing non-duplicate elements. + * - #values_at: Returns the elements at given offsets. * * === Methods for Assigning * * These methods add, replace, or reorder elements in +self+. * + * - #<<: Appends an element. * - #[]=: Assigns specified elements with a given object. - * - #push, #append, #<<: Appends trailing elements. - * - #unshift, #prepend: Prepends leading elements. - * - #insert: Inserts given objects at a given offset; does not replace elements. * - #concat: Appends all elements from given arrays. * - #fill: Replaces specified elements with specified objects. - * - #replace: Replaces the content of +self+ with the content of a given array. + * - #flatten!: Replaces each nested array in +self+ with the elements from that array. + * - #initialize_copy (aliased as #replace): Replaces the content of +self+ with the content of a given array. + * - #insert: Inserts given objects at a given offset; does not replace elements. + * - #push (aliased as #append): Appends elements. * - #reverse!: Replaces +self+ with its elements reversed. * - #rotate!: Replaces +self+ with its elements rotated. * - #shuffle!: Replaces +self+ with its elements in random order. - * - #sort!: Replaces +self+ with its elements sorted, - * as determined by <=> or a given block. + * - #sort!: Replaces +self+ with its elements sorted, as determined by #<=> or a given block. * - #sort_by!: Replaces +self+ with its elements sorted, as determined by a given block. + * - #unshift (aliased as #prepend): Prepends leading elements. * * === Methods for Deleting * * Each of these methods removes elements from +self+: * - * - #pop: Removes and returns the last element. - * - #shift: Removes and returns the first element. + * - #clear: Removes all elements. * - #compact!: Removes all +nil+ elements. * - #delete: Removes elements equal to a given object. * - #delete_at: Removes the element at a given offset. * - #delete_if: Removes elements specified by a given block. * - #keep_if: Removes elements not specified by a given block. + * - #pop: Removes and returns the last element. * - #reject!: Removes elements specified by a given block. - * - #select!, #filter!: Removes elements not specified by a given block. + * - #select! (aliased as #filter!): Removes elements not specified by a given block. + * - #shift: Removes and returns the first element. * - #slice!: Removes and returns a sequence of elements. * - #uniq!: Removes duplicates. * * === Methods for Combining * * - #&: Returns an array containing elements found both in +self+ and a given array. - * - #intersection: Returns an array containing elements found both in +self+ - * and in each given array. * - #+: Returns an array containing all elements of +self+ followed by all elements of a given array. * - #-: Returns an array containing all elements of +self+ that are not found in a given array. - * - #|: Returns an array containing all elements of +self+ and all elements of a given array, - * duplicates removed. - * - #union: Returns an array containing all elements of +self+ and all elements of given arrays, - * duplicates removed. - * - #difference: Returns an array containing all elements of +self+ that are not found - * in any of the given arrays.. + * - #|: Returns an array containing all element of +self+ and all elements of a given array, duplicates removed. + * - #difference: Returns an array containing all elements of +self+ that are not found in any of the given arrays.. + * - #intersection: Returns an array containing elements found both in +self+ and in each given array. * - #product: Returns or yields all combinations of elements from +self+ and given arrays. + * - #reverse: Returns an array containing all elements of +self+ in reverse order. + * - #union: Returns an array containing all elements of +self+ and all elements of given arrays, duplicates removed. * * === Methods for Iterating * + * - #combination: Calls a given block with combinations of elements of +self+; a combination does not use the same element more than once. + * - #cycle: Calls a given block with each element, then does so again, for a specified number of times, or forever. * - #each: Passes each element to a given block. - * - #reverse_each: Passes each element, in reverse order, to a given block. * - #each_index: Passes each element index to a given block. - * - #cycle: Calls a given block with each element, then does so again, - * for a specified number of times, or forever. - * - #combination: Calls a given block with combinations of elements of +self+; - * a combination does not use the same element more than once. - * - #permutation: Calls a given block with permutations of elements of +self+; - * a permutation does not use the same element more than once. - * - #repeated_combination: Calls a given block with combinations of elements of +self+; - * a combination may use the same element more than once. - * - #repeated_permutation: Calls a given block with permutations of elements of +self+; - * a permutation may use the same element more than once. + * - #permutation: Calls a given block with permutations of elements of +self+; a permutation does not use the same element more than once. + * - #repeated_combination: Calls a given block with combinations of elements of +self+; a combination may use the same element more than once. + * - #repeated_permutation: Calls a given block with permutations of elements of +self+; a permutation may use the same element more than once. + * - #reverse_each: Passes each element, in reverse order, to a given block. * * === Methods for Converting * - * - #map, #collect: Returns an array containing the block return-value for each element. - * - #map!, #collect!: Replaces each element with a block return-value. + * - #collect (aliased as #map): Returns an array containing the block return-value for each element. + * - #collect! (aliased as #map!): Replaces each element with a block return-value. * - #flatten: Returns an array that is a recursive flattening of +self+. - * - #flatten!: Replaces each nested array in +self+ with the elements from that array. - * - #inspect, #to_s: Returns a new String containing the elements. - * - #join: Returns a newsString containing the elements joined by the field separator. + * - #inspect (aliased as #to_s): Returns a new String containing the elements. + * - #join: Returns a new String containing the elements joined by the field separator. * - #to_a: Returns +self+ or a new array containing all elements. * - #to_ary: Returns +self+. * - #to_h: Returns a new hash formed from the elements. * - #transpose: Transposes +self+, which must be an array of arrays. - * - #zip: Returns a new array of arrays containing +self+ and given arrays; - * follow the link for details. + * - #zip: Returns a new array of arrays containing +self+ and given arrays. * * === Other Methods * @@ -8595,7 +8738,6 @@ rb_ary_deconstruct(VALUE ary) * - With string argument +field_separator+, a new string that is equivalent to * join(field_separator). * - * - #abbrev: Returns a hash of unambiguous abbreviations for elements. * - #pack: Packs the elements into a binary sequence. * - #sum: Returns a sum of elements according to either + or a given block. */ @@ -8603,6 +8745,8 @@ rb_ary_deconstruct(VALUE ary) void Init_Array(void) { + fake_ary_flags = init_fake_ary_flags(); + rb_cArray = rb_define_class("Array", rb_cObject); rb_include_module(rb_cArray, rb_mEnumerable); @@ -8723,8 +8867,12 @@ Init_Array(void) rb_define_method(rb_cArray, "one?", rb_ary_one_p, -1); rb_define_method(rb_cArray, "dig", rb_ary_dig, -1); rb_define_method(rb_cArray, "sum", rb_ary_sum, -1); + rb_define_method(rb_cArray, "freeze", rb_ary_freeze, 0); rb_define_method(rb_cArray, "deconstruct", rb_ary_deconstruct, 0); + + rb_cArray_empty_frozen = rb_ary_freeze(rb_ary_new()); + rb_vm_register_global_object(rb_cArray_empty_frozen); } #include "array.rbinc" diff --git a/array.rb b/array.rb index d17f3742357613..5f31693cabf2de 100644 --- a/array.rb +++ b/array.rb @@ -1,62 +1,97 @@ class Array # call-seq: - # array.shuffle!(random: Random) -> array + # shuffle!(random: Random) -> self # - # Shuffles the elements of +self+ in place. - # a = [1, 2, 3] #=> [1, 2, 3] - # a.shuffle! #=> [2, 3, 1] - # a #=> [2, 3, 1] + # Shuffles all elements in +self+ into a random order, + # as selected by the object given by the keyword argument +random+. + # Returns +self+: # - # The optional +random+ argument will be used as the random number generator: - # a.shuffle!(random: Random.new(1)) #=> [1, 3, 2] + # a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] + # a.shuffle! # => [5, 3, 8, 7, 6, 1, 9, 4, 2, 0] + # a.shuffle! # => [9, 4, 0, 6, 2, 8, 1, 5, 3, 7] + # + # Duplicate elements are included: + # + # a = [0, 1, 0, 1, 0, 1, 0, 1, 0, 1] + # a.shuffle! # => [1, 0, 0, 1, 1, 0, 1, 0, 0, 1] + # a.shuffle! # => [0, 1, 0, 1, 1, 0, 1, 0, 1, 0] + # + # The object given with the keyword argument +random+ is used as the random number generator. + # + # Related: see {Methods for Assigning}[rdoc-ref:Array@Methods+for+Assigning]. def shuffle!(random: Random) Primitive.rb_ary_shuffle_bang(random) end # call-seq: - # array.shuffle(random: Random) -> new_ary + # shuffle(random: Random) -> new_array + # + # Returns a new array containing all elements from +self+ in a random order, + # as selected by the object given by the keyword argument +random+: # - # Returns a new array with elements of +self+ shuffled. - # a = [1, 2, 3] #=> [1, 2, 3] - # a.shuffle #=> [2, 3, 1] - # a #=> [1, 2, 3] + # a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] + # a.shuffle # => [0, 8, 1, 9, 6, 3, 4, 7, 2, 5] + # a.shuffle # => [8, 9, 0, 5, 1, 2, 6, 4, 7, 3] # - # The optional +random+ argument will be used as the random number generator: - # a.shuffle(random: Random.new(1)) #=> [1, 3, 2] + # Duplicate elements are included: + # + # a = [0, 1, 0, 1, 0, 1, 0, 1, 0, 1] + # a.shuffle # => [1, 0, 1, 1, 0, 0, 1, 0, 0, 1] + # a.shuffle # => [1, 1, 0, 0, 0, 1, 1, 0, 0, 1] + # + # The object given with the keyword argument +random+ is used as the random number generator. + # + # Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching]. def shuffle(random: Random) Primitive.rb_ary_shuffle(random) end # call-seq: - # array.sample(random: Random) -> object - # array.sample(n, random: Random) -> new_ary + # sample(random: Random) -> object + # sample(count, random: Random) -> new_ary # - # Returns random elements from +self+. + # Returns random elements from +self+, + # as selected by the object given by the keyword argument +random+. # - # When no arguments are given, returns a random element from +self+: - # a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] - # a.sample # => 3 - # a.sample # => 8 - # If +self+ is empty, returns +nil+. + # With no argument +count+ given, returns one random element from +self+: + # + # a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] + # a.sample # => 3 + # a.sample # => 8 + # + # Returns +nil+ if +self+ is empty: + # + # [].sample # => nil + # + # With a non-negative numeric argument +count+ given, + # returns a new array containing +count+ random elements from +self+: + # + # a.sample(3) # => [8, 9, 2] + # a.sample(6) # => [9, 6, 0, 3, 1, 4] + # + # The order of the result array is unrelated to the order of +self+. + # + # Returns a new empty array if +self+ is empty: + # + # [].sample(4) # => [] + # + # May return duplicates in +self+: + # + # a = [1, 1, 1, 2, 2, 3] + # a.sample(a.size) # => [1, 1, 3, 2, 1, 2] # - # When argument +n+ is given, returns a new \Array containing +n+ random - # elements from +self+: - # a.sample(3) # => [8, 9, 2] - # a.sample(6) # => [9, 6, 10, 3, 1, 4] # Returns no more than a.size elements # (because no new duplicates are introduced): - # a.sample(a.size * 2) # => [6, 4, 1, 8, 5, 9, 10, 2, 3, 7] - # But +self+ may contain duplicates: - # a = [1, 1, 1, 2, 2, 3] - # a.sample(a.size * 2) # => [1, 1, 3, 2, 1, 2] - # The argument +n+ must be a non-negative numeric value. - # The order of the result array is unrelated to the order of +self+. - # Returns a new empty \Array if +self+ is empty. # - # The optional +random+ argument will be used as the random number generator: - # a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] - # a.sample(random: Random.new(1)) #=> 6 - # a.sample(4, random: Random.new(1)) #=> [6, 10, 9, 2] + # a.sample(50) # => [6, 4, 1, 8, 5, 9, 0, 2, 3, 7] + # + # The object given with the keyword argument +random+ is used as the random number generator: + # + # a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] + # a.sample(random: Random.new(1)) # => 6 + # a.sample(4, random: Random.new(1)) # => [6, 10, 9, 2] + # + # Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching]. def sample(n = (ary = false), random: Random) if Primitive.mandatory_only? # Primitive.cexpr! %{ rb_ary_sample(self, rb_cRandom, Qfalse, Qfalse) } @@ -68,12 +103,12 @@ def sample(n = (ary = false), random: Random) end # call-seq: - # array.first -> object or nil - # array.first(n) -> new_array + # first -> object or nil + # first(count) -> new_array # - # Returns elements from +self+; does not modify +self+. + # Returns elements from +self+, or +nil+; does not modify +self+. # - # When no argument is given, returns the first element: + # With no argument given, returns the first element (if available): # # a = [:foo, 'bar', 2] # a.first # => :foo @@ -81,23 +116,16 @@ def sample(n = (ary = false), random: Random) # # If +self+ is empty, returns +nil+. # - # When non-negative Integer argument +n+ is given, - # returns the first +n+ elements in a new \Array: - # - # a = [:foo, 'bar', 2] - # a.first(2) # => [:foo, "bar"] + # [].first # => nil # - # If n >= array.size, returns all elements: + # With a non-negative integer argument +count+ given, + # returns the first +count+ elements (as available) in a new array: # - # a = [:foo, 'bar', 2] + # a.first(0) # => [] + # a.first(2) # => [:foo, "bar"] # a.first(50) # => [:foo, "bar", 2] # - # If n == 0 returns an new empty \Array: - # - # a = [:foo, 'bar', 2] - # a.first(0) # [] - # - # Related: #last. + # Related: see {Methods for Querying}[rdoc-ref:Array@Methods+for+Querying]. def first n = unspecified = true if Primitive.mandatory_only? Primitive.attr! :leaf @@ -112,36 +140,29 @@ def first n = unspecified = true end # call-seq: - # array.last -> object or nil - # array.last(n) -> new_array + # last -> last_object or nil + # last(count) -> new_array # - # Returns elements from +self+; +self+ is not modified. + # Returns elements from +self+, or +nil+; +self+ is not modified. # - # When no argument is given, returns the last element: + # With no argument given, returns the last element, or +nil+ if +self+ is empty: # # a = [:foo, 'bar', 2] # a.last # => 2 # a # => [:foo, "bar", 2] + # [].last # => nil # - # If +self+ is empty, returns +nil+. # - # When non-negative Integer argument +n+ is given, - # returns the last +n+ elements in a new \Array: - # - # a = [:foo, 'bar', 2] - # a.last(2) # => ["bar", 2] - # - # If n >= array.size, returns all elements: + # With non-negative integer argument +count+ given, + # returns a new array containing the trailing +count+ elements of +self+, as available: # # a = [:foo, 'bar', 2] + # a.last(2) # => ["bar", 2] # a.last(50) # => [:foo, "bar", 2] + # a.last(0) # => [] + # [].last(3) # => [] # - # If n == 0, returns an new empty \Array: - # - # a = [:foo, 'bar', 2] - # a.last(0) # [] - # - # Related: #first. + # Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching]. def last n = unspecified = true if Primitive.mandatory_only? Primitive.attr! :leaf @@ -154,4 +175,110 @@ def last n = unspecified = true end end end + + # call-seq: + # fetch_values(*indexes) -> new_array + # fetch_values(*indexes) { |index| ... } -> new_array + # + # With no block given, returns a new array containing the elements of +self+ + # at the offsets specified by +indexes+. Each of the +indexes+ must be an + # {integer-convertible object}[rdoc-ref:implicit_conversion.rdoc@Integer-Convertible+Objects]: + # + # a = [:foo, :bar, :baz] + # a.fetch_values(2, 0) # => [:baz, :foo] + # a.fetch_values(2.1, 0) # => [:baz, :foo] + # a.fetch_values # => [] + # + # For a negative index, counts backwards from the end of the array: + # + # a.fetch_values(-2, -1) # [:bar, :baz] + # + # When no block is given, raises an exception if any index is out of range. + # + # With a block given, for each index: + # + # - If the index is in range, uses an element of +self+ (as above). + # - Otherwise, calls the block with the index and uses the block's return value. + # + # Example: + # + # a = [:foo, :bar, :baz] + # a.fetch_values(1, 0, 42, 777) { |index| index.to_s } + # # => [:bar, :foo, "42", "777"] + # + # Related: see {Methods for Fetching}[rdoc-ref:Array@Methods+for+Fetching]. + def fetch_values(*indexes, &block) + indexes.map! { |i| fetch(i, &block) } + indexes + end + + with_yjit do + if Primitive.rb_builtin_basic_definition_p(:each) + undef :each + + def each # :nodoc: + Primitive.attr! :inline_block, :c_trace + + unless defined?(yield) + return Primitive.cexpr! 'SIZED_ENUMERATOR(self, 0, 0, ary_enum_length)' + end + _i = 0 + value = nil + while Primitive.cexpr!(%q{ ary_fetch_next(self, LOCAL_PTR(_i), LOCAL_PTR(value)) }) + yield value + end + self + end + end + + if Primitive.rb_builtin_basic_definition_p(:map) + undef :map + + def map # :nodoc: + Primitive.attr! :inline_block, :c_trace + + unless defined?(yield) + return Primitive.cexpr! 'SIZED_ENUMERATOR(self, 0, 0, ary_enum_length)' + end + + _i = 0 + value = nil + result = Primitive.ary_sized_alloc + while Primitive.cexpr!(%q{ ary_fetch_next(self, LOCAL_PTR(_i), LOCAL_PTR(value)) }) + result << yield(value) + end + result + end + + if Primitive.rb_builtin_basic_definition_p(:collect) + undef :collect + alias collect map + end + end + + if Primitive.rb_builtin_basic_definition_p(:select) + undef :select + + def select # :nodoc: + Primitive.attr! :inline_block, :c_trace + + unless defined?(yield) + return Primitive.cexpr! 'SIZED_ENUMERATOR(self, 0, 0, ary_enum_length)' + end + + _i = 0 + value = nil + result = Primitive.ary_sized_alloc + while Primitive.cexpr!(%q{ ary_fetch_next(self, LOCAL_PTR(_i), LOCAL_PTR(value)) }) + result << value if yield value + end + result + end + + if Primitive.rb_builtin_basic_definition_p(:filter) + undef :filter + alias filter select + end + end + end end diff --git a/ast.c b/ast.c index 4bd3784fbae9ae..dde42e5921f3d5 100644 --- a/ast.c +++ b/ast.c @@ -14,9 +14,10 @@ static VALUE rb_mAST; static VALUE rb_cNode; +static VALUE rb_cLocation; struct ASTNodeData { - rb_ast_t *ast; + VALUE ast_value; const NODE *node; }; @@ -24,14 +25,16 @@ static void node_gc_mark(void *ptr) { struct ASTNodeData *data = (struct ASTNodeData *)ptr; - rb_gc_mark((VALUE)data->ast); + rb_gc_mark(data->ast_value); } static size_t node_memsize(const void *ptr) { struct ASTNodeData *data = (struct ASTNodeData *)ptr; - return rb_ast_memsize(data->ast); + rb_ast_t *ast = rb_ruby_ast_data_get(data->ast_value); + + return sizeof(struct ASTNodeData) + rb_ast_memsize(ast); } static const rb_data_type_t rb_node_type = { @@ -41,25 +44,51 @@ static const rb_data_type_t rb_node_type = { RUBY_TYPED_FREE_IMMEDIATELY, }; +struct ASTLocationData { + int first_lineno; + int first_column; + int last_lineno; + int last_column; +}; + +static void +location_gc_mark(void *ptr) +{ +} + +static size_t +location_memsize(const void *ptr) +{ + return sizeof(struct ASTLocationData); +} + +static const rb_data_type_t rb_location_type = { + "AST/location", + {location_gc_mark, RUBY_TYPED_DEFAULT_FREE, location_memsize,}, + 0, 0, + RUBY_TYPED_FREE_IMMEDIATELY, +}; + + static VALUE rb_ast_node_alloc(VALUE klass); static void -setup_node(VALUE obj, rb_ast_t *ast, const NODE *node) +setup_node(VALUE obj, VALUE ast_value, const NODE *node) { struct ASTNodeData *data; TypedData_Get_Struct(obj, struct ASTNodeData, &rb_node_type, data); - data->ast = ast; + data->ast_value = ast_value; data->node = node; } static VALUE -ast_new_internal(rb_ast_t *ast, const NODE *node) +ast_new_internal(VALUE ast_value, const NODE *node) { VALUE obj; obj = rb_ast_node_alloc(rb_cNode); - setup_node(obj, ast, node); + setup_node(obj, ast_value, node); return obj; } @@ -74,14 +103,26 @@ ast_parse_new(void) } static VALUE -ast_parse_done(rb_ast_t *ast) +ast_parse_done(VALUE ast_value) { + rb_ast_t *ast = rb_ruby_ast_data_get(ast_value); + if (!ast->body.root) { rb_ast_dispose(ast); rb_exc_raise(GET_EC()->errinfo); } - return ast_new_internal(ast, (NODE *)ast->body.root); + return ast_new_internal(ast_value, (NODE *)ast->body.root); +} + +static VALUE +setup_vparser(VALUE keep_script_lines, VALUE error_tolerant, VALUE keep_tokens) +{ + VALUE vparser = ast_parse_new(); + if (RTEST(keep_script_lines)) rb_parser_set_script_lines(vparser); + if (RTEST(error_tolerant)) rb_parser_error_tolerant(vparser); + if (RTEST(keep_tokens)) rb_parser_keep_tokens(vparser); + return vparser; } static VALUE @@ -93,15 +134,11 @@ ast_s_parse(rb_execution_context_t *ec, VALUE module, VALUE str, VALUE keep_scri static VALUE rb_ast_parse_str(VALUE str, VALUE keep_script_lines, VALUE error_tolerant, VALUE keep_tokens) { - rb_ast_t *ast = 0; - + VALUE ast_value = Qnil; StringValue(str); - VALUE vparser = ast_parse_new(); - if (RTEST(keep_script_lines)) rb_parser_set_script_lines(vparser, Qtrue); - if (RTEST(error_tolerant)) rb_parser_error_tolerant(vparser); - if (RTEST(keep_tokens)) rb_parser_keep_tokens(vparser); - ast = rb_parser_compile_string_path(vparser, Qnil, str, 1); - return ast_parse_done(ast); + VALUE vparser = setup_vparser(keep_script_lines, error_tolerant, keep_tokens); + ast_value = rb_parser_compile_string_path(vparser, Qnil, str, 1); + return ast_parse_done(ast_value); } static VALUE @@ -114,49 +151,29 @@ static VALUE rb_ast_parse_file(VALUE path, VALUE keep_script_lines, VALUE error_tolerant, VALUE keep_tokens) { VALUE f; - rb_ast_t *ast = 0; + VALUE ast_value = Qnil; rb_encoding *enc = rb_utf8_encoding(); - FilePathValue(path); f = rb_file_open_str(path, "r"); rb_funcall(f, rb_intern("set_encoding"), 2, rb_enc_from_encoding(enc), rb_str_new_cstr("-")); - VALUE vparser = ast_parse_new(); - if (RTEST(keep_script_lines)) rb_parser_set_script_lines(vparser, Qtrue); - if (RTEST(error_tolerant)) rb_parser_error_tolerant(vparser); - if (RTEST(keep_tokens)) rb_parser_keep_tokens(vparser); - ast = rb_parser_compile_file_path(vparser, Qnil, f, 1); + VALUE vparser = setup_vparser(keep_script_lines, error_tolerant, keep_tokens); + ast_value = rb_parser_compile_file_path(vparser, Qnil, f, 1); rb_io_close(f); - return ast_parse_done(ast); -} - -static VALUE -lex_array(VALUE array, int index) -{ - VALUE str = rb_ary_entry(array, index); - if (!NIL_P(str)) { - StringValue(str); - if (!rb_enc_asciicompat(rb_enc_get(str))) { - rb_raise(rb_eArgError, "invalid source encoding"); - } - } - return str; + return ast_parse_done(ast_value); } static VALUE rb_ast_parse_array(VALUE array, VALUE keep_script_lines, VALUE error_tolerant, VALUE keep_tokens) { - rb_ast_t *ast = 0; + VALUE ast_value = Qnil; array = rb_check_array_type(array); - VALUE vparser = ast_parse_new(); - if (RTEST(keep_script_lines)) rb_parser_set_script_lines(vparser, Qtrue); - if (RTEST(error_tolerant)) rb_parser_error_tolerant(vparser); - if (RTEST(keep_tokens)) rb_parser_keep_tokens(vparser); - ast = rb_parser_compile_generic(vparser, lex_array, Qnil, array, 1); - return ast_parse_done(ast); + VALUE vparser = setup_vparser(keep_script_lines, error_tolerant, keep_tokens); + ast_value = rb_parser_compile_array(vparser, Qnil, array, 1); + return ast_parse_done(ast_value); } -static VALUE node_children(rb_ast_t*, const NODE*); +static VALUE node_children(VALUE, const NODE*); static VALUE node_find(VALUE self, const int node_id) @@ -168,7 +185,7 @@ node_find(VALUE self, const int node_id) if (nd_node_id(data->node) == node_id) return self; - ary = node_children(data->ast, data->node); + ary = node_children(data->ast_value, data->node); for (i = 0; i < RARRAY_LEN(ary); i++) { VALUE child = RARRAY_AREF(ary, i); @@ -184,29 +201,6 @@ node_find(VALUE self, const int node_id) extern VALUE rb_e_script; -VALUE -rb_script_lines_for(VALUE path, bool add) -{ - VALUE hash, lines; - ID script_lines; - CONST_ID(script_lines, "SCRIPT_LINES__"); - if (!rb_const_defined_at(rb_cObject, script_lines)) return Qnil; - hash = rb_const_get_at(rb_cObject, script_lines); - if (!RB_TYPE_P(hash, T_HASH)) return Qnil; - if (add) { - rb_hash_aset(hash, path, lines = rb_ary_new()); - } - else if (!RB_TYPE_P((lines = rb_hash_lookup(hash, path)), T_ARRAY)) { - return Qnil; - } - return lines; -} -static VALUE -script_lines(VALUE path) -{ - return rb_script_lines_for(path, false); -} - static VALUE node_id_for_backtrace_location(rb_execution_context_t *ec, VALUE module, VALUE location) { @@ -254,6 +248,11 @@ ast_s_of(rb_execution_context_t *ec, VALUE module, VALUE body, VALUE keep_script if (!iseq) { return Qnil; } + + if (ISEQ_BODY(iseq)->prism) { + rb_raise(rb_eRuntimeError, "cannot get AST for ISEQ compiled by prism"); + } + lines = ISEQ_BODY(iseq)->variable.script_lines; VALUE path = rb_iseq_path(iseq); @@ -263,7 +262,7 @@ ast_s_of(rb_execution_context_t *ec, VALUE module, VALUE body, VALUE keep_script rb_raise(rb_eArgError, "cannot get AST for method defined in eval"); } - if (!NIL_P(lines) || !NIL_P(lines = script_lines(path))) { + if (!NIL_P(lines)) { node = rb_ast_parse_array(lines, keep_script_lines, error_tolerant, keep_tokens); } else if (e_option) { @@ -309,10 +308,10 @@ ast_node_node_id(rb_execution_context_t *ec, VALUE self) return INT2FIX(nd_node_id(data->node)); } -#define NEW_CHILD(ast, node) node ? ast_new_internal(ast, node) : Qnil +#define NEW_CHILD(ast_value, node) (node ? ast_new_internal(ast_value, node) : Qnil) static VALUE -rb_ary_new_from_node_args(rb_ast_t *ast, long n, ...) +rb_ary_new_from_node_args(VALUE ast_value, long n, ...) { va_list ar; VALUE ary; @@ -324,39 +323,57 @@ rb_ary_new_from_node_args(rb_ast_t *ast, long n, ...) for (i=0; ind_head)); + rb_ary_push(ary, NEW_CHILD(ast_value, node->nd_head)); } while (node->nd_next && nd_type_p(node->nd_next, NODE_BLOCK) && - (node = node->nd_next, 1)); + (node = RNODE_BLOCK(node->nd_next), 1)); if (node->nd_next) { - rb_ary_push(ary, NEW_CHILD(ast, node->nd_next)); + rb_ary_push(ary, NEW_CHILD(ast_value, node->nd_next)); } return ary; } static VALUE -dump_array(rb_ast_t *ast, const NODE *node) +dump_array(VALUE ast_value, const struct RNode_LIST *node) { VALUE ary = rb_ary_new(); - rb_ary_push(ary, NEW_CHILD(ast, node->nd_head)); + rb_ary_push(ary, NEW_CHILD(ast_value, node->nd_head)); while (node->nd_next && nd_type_p(node->nd_next, NODE_LIST)) { - node = node->nd_next; - rb_ary_push(ary, NEW_CHILD(ast, node->nd_head)); + node = RNODE_LIST(node->nd_next); + rb_ary_push(ary, NEW_CHILD(ast_value, node->nd_head)); + } + rb_ary_push(ary, NEW_CHILD(ast_value, node->nd_next)); + + return ary; +} + +static VALUE +dump_parser_array(VALUE ast_value, rb_parser_ary_t *p_ary) +{ + VALUE ary; + + if (p_ary->data_type != PARSER_ARY_DATA_NODE) { + rb_bug("unexpected rb_parser_ary_data_type: %d", p_ary->data_type); + } + + ary = rb_ary_new(); + + for (long i = 0; i < p_ary->len; i++) { + rb_ary_push(ary, NEW_CHILD(ast_value, p_ary->data[i])); } - rb_ary_push(ary, NEW_CHILD(ast, node->nd_next)); return ary; } @@ -378,307 +395,341 @@ no_name_rest(void) } static VALUE -rest_arg(rb_ast_t *ast, const NODE *rest_arg) +rest_arg(VALUE ast_value, const NODE *rest_arg) { - return NODE_NAMED_REST_P(rest_arg) ? NEW_CHILD(ast, rest_arg) : no_name_rest(); + return NODE_NAMED_REST_P(rest_arg) ? NEW_CHILD(ast_value, rest_arg) : no_name_rest(); } static VALUE -node_children(rb_ast_t *ast, const NODE *node) +node_children(VALUE ast_value, const NODE *node) { char name[sizeof("$") + DECIMAL_SIZE_OF(long)]; enum node_type type = nd_type(node); switch (type) { case NODE_BLOCK: - return dump_block(ast, node); + return dump_block(ast_value, RNODE_BLOCK(node)); case NODE_IF: - return rb_ary_new_from_node_args(ast, 3, node->nd_cond, node->nd_body, node->nd_else); + return rb_ary_new_from_node_args(ast_value, 3, RNODE_IF(node)->nd_cond, RNODE_IF(node)->nd_body, RNODE_IF(node)->nd_else); case NODE_UNLESS: - return rb_ary_new_from_node_args(ast, 3, node->nd_cond, node->nd_body, node->nd_else); + return rb_ary_new_from_node_args(ast_value, 3, RNODE_UNLESS(node)->nd_cond, RNODE_UNLESS(node)->nd_body, RNODE_UNLESS(node)->nd_else); case NODE_CASE: - return rb_ary_new_from_node_args(ast, 2, node->nd_head, node->nd_body); + return rb_ary_new_from_node_args(ast_value, 2, RNODE_CASE(node)->nd_head, RNODE_CASE(node)->nd_body); case NODE_CASE2: - return rb_ary_new_from_node_args(ast, 2, node->nd_head, node->nd_body); + return rb_ary_new_from_node_args(ast_value, 2, RNODE_CASE2(node)->nd_head, RNODE_CASE2(node)->nd_body); case NODE_CASE3: - return rb_ary_new_from_node_args(ast, 2, node->nd_head, node->nd_body); + return rb_ary_new_from_node_args(ast_value, 2, RNODE_CASE3(node)->nd_head, RNODE_CASE3(node)->nd_body); case NODE_WHEN: - return rb_ary_new_from_node_args(ast, 3, node->nd_head, node->nd_body, node->nd_next); + return rb_ary_new_from_node_args(ast_value, 3, RNODE_WHEN(node)->nd_head, RNODE_WHEN(node)->nd_body, RNODE_WHEN(node)->nd_next); case NODE_IN: - return rb_ary_new_from_node_args(ast, 3, node->nd_head, node->nd_body, node->nd_next); + return rb_ary_new_from_node_args(ast_value, 3, RNODE_IN(node)->nd_head, RNODE_IN(node)->nd_body, RNODE_IN(node)->nd_next); case NODE_WHILE: case NODE_UNTIL: - return rb_ary_push(rb_ary_new_from_node_args(ast, 2, node->nd_cond, node->nd_body), - RBOOL(node->nd_state)); + return rb_ary_push(rb_ary_new_from_node_args(ast_value, 2, RNODE_WHILE(node)->nd_cond, RNODE_WHILE(node)->nd_body), + RBOOL(RNODE_WHILE(node)->nd_state)); case NODE_ITER: case NODE_FOR: - return rb_ary_new_from_node_args(ast, 2, node->nd_iter, node->nd_body); + return rb_ary_new_from_node_args(ast_value, 2, RNODE_ITER(node)->nd_iter, RNODE_ITER(node)->nd_body); case NODE_FOR_MASGN: - return rb_ary_new_from_node_args(ast, 1, node->nd_var); + return rb_ary_new_from_node_args(ast_value, 1, RNODE_FOR_MASGN(node)->nd_var); case NODE_BREAK: + return rb_ary_new_from_node_args(ast_value, 1, RNODE_BREAK(node)->nd_stts); case NODE_NEXT: + return rb_ary_new_from_node_args(ast_value, 1, RNODE_NEXT(node)->nd_stts); case NODE_RETURN: - return rb_ary_new_from_node_args(ast, 1, node->nd_stts); + return rb_ary_new_from_node_args(ast_value, 1, RNODE_RETURN(node)->nd_stts); case NODE_REDO: - return rb_ary_new_from_node_args(ast, 0); + return rb_ary_new_from_node_args(ast_value, 0); case NODE_RETRY: - return rb_ary_new_from_node_args(ast, 0); + return rb_ary_new_from_node_args(ast_value, 0); case NODE_BEGIN: - return rb_ary_new_from_node_args(ast, 1, node->nd_body); + return rb_ary_new_from_node_args(ast_value, 1, RNODE_BEGIN(node)->nd_body); case NODE_RESCUE: - return rb_ary_new_from_node_args(ast, 3, node->nd_head, node->nd_resq, node->nd_else); + return rb_ary_new_from_node_args(ast_value, 3, RNODE_RESCUE(node)->nd_head, RNODE_RESCUE(node)->nd_resq, RNODE_RESCUE(node)->nd_else); case NODE_RESBODY: - return rb_ary_new_from_node_args(ast, 3, node->nd_args, node->nd_body, node->nd_head); + return rb_ary_new_from_node_args(ast_value, 4, RNODE_RESBODY(node)->nd_args, RNODE_RESBODY(node)->nd_exc_var, RNODE_RESBODY(node)->nd_body, RNODE_RESBODY(node)->nd_next); case NODE_ENSURE: - return rb_ary_new_from_node_args(ast, 2, node->nd_head, node->nd_ensr); + return rb_ary_new_from_node_args(ast_value, 2, RNODE_ENSURE(node)->nd_head, RNODE_ENSURE(node)->nd_ensr); case NODE_AND: case NODE_OR: { VALUE ary = rb_ary_new(); while (1) { - rb_ary_push(ary, NEW_CHILD(ast, node->nd_1st)); - if (!node->nd_2nd || !nd_type_p(node->nd_2nd, type)) + rb_ary_push(ary, NEW_CHILD(ast_value, RNODE_AND(node)->nd_1st)); + if (!RNODE_AND(node)->nd_2nd || !nd_type_p(RNODE_AND(node)->nd_2nd, type)) break; - node = node->nd_2nd; + node = RNODE_AND(node)->nd_2nd; } - rb_ary_push(ary, NEW_CHILD(ast, node->nd_2nd)); + rb_ary_push(ary, NEW_CHILD(ast_value, RNODE_AND(node)->nd_2nd)); return ary; } case NODE_MASGN: - if (NODE_NAMED_REST_P(node->nd_args)) { - return rb_ary_new_from_node_args(ast, 3, node->nd_value, node->nd_head, node->nd_args); + if (NODE_NAMED_REST_P(RNODE_MASGN(node)->nd_args)) { + return rb_ary_new_from_node_args(ast_value, 3, RNODE_MASGN(node)->nd_value, RNODE_MASGN(node)->nd_head, RNODE_MASGN(node)->nd_args); } else { - return rb_ary_new_from_args(3, NEW_CHILD(ast, node->nd_value), - NEW_CHILD(ast, node->nd_head), + return rb_ary_new_from_args(3, NEW_CHILD(ast_value, RNODE_MASGN(node)->nd_value), + NEW_CHILD(ast_value, RNODE_MASGN(node)->nd_head), no_name_rest()); } case NODE_LASGN: + if (NODE_REQUIRED_KEYWORD_P(RNODE_LASGN(node)->nd_value)) { + return rb_ary_new_from_args(2, var_name(RNODE_LASGN(node)->nd_vid), ID2SYM(rb_intern("NODE_SPECIAL_REQUIRED_KEYWORD"))); + } + return rb_ary_new_from_args(2, var_name(RNODE_LASGN(node)->nd_vid), NEW_CHILD(ast_value, RNODE_LASGN(node)->nd_value)); case NODE_DASGN: + if (NODE_REQUIRED_KEYWORD_P(RNODE_DASGN(node)->nd_value)) { + return rb_ary_new_from_args(2, var_name(RNODE_DASGN(node)->nd_vid), ID2SYM(rb_intern("NODE_SPECIAL_REQUIRED_KEYWORD"))); + } + return rb_ary_new_from_args(2, var_name(RNODE_DASGN(node)->nd_vid), NEW_CHILD(ast_value, RNODE_DASGN(node)->nd_value)); case NODE_IASGN: + return rb_ary_new_from_args(2, var_name(RNODE_IASGN(node)->nd_vid), NEW_CHILD(ast_value, RNODE_IASGN(node)->nd_value)); case NODE_CVASGN: + return rb_ary_new_from_args(2, var_name(RNODE_CVASGN(node)->nd_vid), NEW_CHILD(ast_value, RNODE_CVASGN(node)->nd_value)); case NODE_GASGN: - if (NODE_REQUIRED_KEYWORD_P(node)) { - return rb_ary_new_from_args(2, var_name(node->nd_vid), ID2SYM(rb_intern("NODE_SPECIAL_REQUIRED_KEYWORD"))); - } - return rb_ary_new_from_args(2, var_name(node->nd_vid), NEW_CHILD(ast, node->nd_value)); + return rb_ary_new_from_args(2, var_name(RNODE_GASGN(node)->nd_vid), NEW_CHILD(ast_value, RNODE_GASGN(node)->nd_value)); case NODE_CDECL: - if (node->nd_vid) { - return rb_ary_new_from_args(2, ID2SYM(node->nd_vid), NEW_CHILD(ast, node->nd_value)); + if (RNODE_CDECL(node)->nd_vid) { + return rb_ary_new_from_args(2, ID2SYM(RNODE_CDECL(node)->nd_vid), NEW_CHILD(ast_value, RNODE_CDECL(node)->nd_value)); } - return rb_ary_new_from_args(3, NEW_CHILD(ast, node->nd_else), ID2SYM(node->nd_else->nd_mid), NEW_CHILD(ast, node->nd_value)); + return rb_ary_new_from_args(3, NEW_CHILD(ast_value, RNODE_CDECL(node)->nd_else), ID2SYM(RNODE_COLON2(RNODE_CDECL(node)->nd_else)->nd_mid), NEW_CHILD(ast_value, RNODE_CDECL(node)->nd_value)); case NODE_OP_ASGN1: - return rb_ary_new_from_args(4, NEW_CHILD(ast, node->nd_recv), - ID2SYM(node->nd_mid), - NEW_CHILD(ast, node->nd_args->nd_head), - NEW_CHILD(ast, node->nd_args->nd_body)); + return rb_ary_new_from_args(4, NEW_CHILD(ast_value, RNODE_OP_ASGN1(node)->nd_recv), + ID2SYM(RNODE_OP_ASGN1(node)->nd_mid), + NEW_CHILD(ast_value, RNODE_OP_ASGN1(node)->nd_index), + NEW_CHILD(ast_value, RNODE_OP_ASGN1(node)->nd_rvalue)); case NODE_OP_ASGN2: - return rb_ary_new_from_args(5, NEW_CHILD(ast, node->nd_recv), - RBOOL(node->nd_next->nd_aid), - ID2SYM(node->nd_next->nd_vid), - ID2SYM(node->nd_next->nd_mid), - NEW_CHILD(ast, node->nd_value)); + return rb_ary_new_from_args(5, NEW_CHILD(ast_value, RNODE_OP_ASGN2(node)->nd_recv), + RBOOL(RNODE_OP_ASGN2(node)->nd_aid), + ID2SYM(RNODE_OP_ASGN2(node)->nd_vid), + ID2SYM(RNODE_OP_ASGN2(node)->nd_mid), + NEW_CHILD(ast_value, RNODE_OP_ASGN2(node)->nd_value)); case NODE_OP_ASGN_AND: - return rb_ary_new_from_args(3, NEW_CHILD(ast, node->nd_head), ID2SYM(idANDOP), - NEW_CHILD(ast, node->nd_value)); + return rb_ary_new_from_args(3, NEW_CHILD(ast_value, RNODE_OP_ASGN_AND(node)->nd_head), ID2SYM(idANDOP), + NEW_CHILD(ast_value, RNODE_OP_ASGN_AND(node)->nd_value)); case NODE_OP_ASGN_OR: - return rb_ary_new_from_args(3, NEW_CHILD(ast, node->nd_head), ID2SYM(idOROP), - NEW_CHILD(ast, node->nd_value)); + return rb_ary_new_from_args(3, NEW_CHILD(ast_value, RNODE_OP_ASGN_OR(node)->nd_head), ID2SYM(idOROP), + NEW_CHILD(ast_value, RNODE_OP_ASGN_OR(node)->nd_value)); case NODE_OP_CDECL: - return rb_ary_new_from_args(3, NEW_CHILD(ast, node->nd_head), - ID2SYM(node->nd_aid), - NEW_CHILD(ast, node->nd_value)); + return rb_ary_new_from_args(3, NEW_CHILD(ast_value, RNODE_OP_CDECL(node)->nd_head), + ID2SYM(RNODE_OP_CDECL(node)->nd_aid), + NEW_CHILD(ast_value, RNODE_OP_CDECL(node)->nd_value)); case NODE_CALL: + return rb_ary_new_from_args(3, NEW_CHILD(ast_value, RNODE_CALL(node)->nd_recv), + ID2SYM(RNODE_CALL(node)->nd_mid), + NEW_CHILD(ast_value, RNODE_CALL(node)->nd_args)); case NODE_OPCALL: + return rb_ary_new_from_args(3, NEW_CHILD(ast_value, RNODE_OPCALL(node)->nd_recv), + ID2SYM(RNODE_OPCALL(node)->nd_mid), + NEW_CHILD(ast_value, RNODE_OPCALL(node)->nd_args)); case NODE_QCALL: - return rb_ary_new_from_args(3, NEW_CHILD(ast, node->nd_recv), - ID2SYM(node->nd_mid), - NEW_CHILD(ast, node->nd_args)); + return rb_ary_new_from_args(3, NEW_CHILD(ast_value, RNODE_QCALL(node)->nd_recv), + ID2SYM(RNODE_QCALL(node)->nd_mid), + NEW_CHILD(ast_value, RNODE_QCALL(node)->nd_args)); case NODE_FCALL: - return rb_ary_new_from_args(2, ID2SYM(node->nd_mid), - NEW_CHILD(ast, node->nd_args)); + return rb_ary_new_from_args(2, ID2SYM(RNODE_FCALL(node)->nd_mid), + NEW_CHILD(ast_value, RNODE_FCALL(node)->nd_args)); case NODE_VCALL: - return rb_ary_new_from_args(1, ID2SYM(node->nd_mid)); + return rb_ary_new_from_args(1, ID2SYM(RNODE_VCALL(node)->nd_mid)); case NODE_SUPER: - return rb_ary_new_from_node_args(ast, 1, node->nd_args); + return rb_ary_new_from_node_args(ast_value, 1, RNODE_SUPER(node)->nd_args); case NODE_ZSUPER: - return rb_ary_new_from_node_args(ast, 0); + return rb_ary_new_from_node_args(ast_value, 0); case NODE_LIST: - case NODE_VALUES: - return dump_array(ast, node); + return dump_array(ast_value, RNODE_LIST(node)); case NODE_ZLIST: - return rb_ary_new_from_node_args(ast, 0); + return rb_ary_new_from_node_args(ast_value, 0); case NODE_HASH: - return rb_ary_new_from_node_args(ast, 1, node->nd_head); + return rb_ary_new_from_node_args(ast_value, 1, RNODE_HASH(node)->nd_head); case NODE_YIELD: - return rb_ary_new_from_node_args(ast, 1, node->nd_head); + return rb_ary_new_from_node_args(ast_value, 1, RNODE_YIELD(node)->nd_head); case NODE_LVAR: + return rb_ary_new_from_args(1, var_name(RNODE_LVAR(node)->nd_vid)); case NODE_DVAR: - return rb_ary_new_from_args(1, var_name(node->nd_vid)); + return rb_ary_new_from_args(1, var_name(RNODE_DVAR(node)->nd_vid)); case NODE_IVAR: + return rb_ary_new_from_args(1, ID2SYM(RNODE_IVAR(node)->nd_vid)); case NODE_CONST: + return rb_ary_new_from_args(1, ID2SYM(RNODE_CONST(node)->nd_vid)); case NODE_CVAR: + return rb_ary_new_from_args(1, ID2SYM(RNODE_CVAR(node)->nd_vid)); case NODE_GVAR: - return rb_ary_new_from_args(1, ID2SYM(node->nd_vid)); + return rb_ary_new_from_args(1, ID2SYM(RNODE_GVAR(node)->nd_vid)); case NODE_NTH_REF: - snprintf(name, sizeof(name), "$%ld", node->nd_nth); + snprintf(name, sizeof(name), "$%ld", RNODE_NTH_REF(node)->nd_nth); return rb_ary_new_from_args(1, ID2SYM(rb_intern(name))); case NODE_BACK_REF: name[0] = '$'; - name[1] = (char)node->nd_nth; + name[1] = (char)RNODE_BACK_REF(node)->nd_nth; name[2] = '\0'; return rb_ary_new_from_args(1, ID2SYM(rb_intern(name))); + case NODE_MATCH: + return rb_ary_new_from_args(1, rb_node_regx_string_val(node)); case NODE_MATCH2: - if (node->nd_args) { - return rb_ary_new_from_node_args(ast, 3, node->nd_recv, node->nd_value, node->nd_args); + if (RNODE_MATCH2(node)->nd_args) { + return rb_ary_new_from_node_args(ast_value, 3, RNODE_MATCH2(node)->nd_recv, RNODE_MATCH2(node)->nd_value, RNODE_MATCH2(node)->nd_args); } - return rb_ary_new_from_node_args(ast, 2, node->nd_recv, node->nd_value); + return rb_ary_new_from_node_args(ast_value, 2, RNODE_MATCH2(node)->nd_recv, RNODE_MATCH2(node)->nd_value); case NODE_MATCH3: - return rb_ary_new_from_node_args(ast, 2, node->nd_recv, node->nd_value); - case NODE_MATCH: - case NODE_LIT: + return rb_ary_new_from_node_args(ast_value, 2, RNODE_MATCH3(node)->nd_recv, RNODE_MATCH3(node)->nd_value); case NODE_STR: case NODE_XSTR: - return rb_ary_new_from_args(1, node->nd_lit); + return rb_ary_new_from_args(1, rb_node_str_string_val(node)); + case NODE_INTEGER: + return rb_ary_new_from_args(1, rb_node_integer_literal_val(node)); + case NODE_FLOAT: + return rb_ary_new_from_args(1, rb_node_float_literal_val(node)); + case NODE_RATIONAL: + return rb_ary_new_from_args(1, rb_node_rational_literal_val(node)); + case NODE_IMAGINARY: + return rb_ary_new_from_args(1, rb_node_imaginary_literal_val(node)); + case NODE_REGX: + return rb_ary_new_from_args(1, rb_node_regx_string_val(node)); case NODE_ONCE: - return rb_ary_new_from_node_args(ast, 1, node->nd_body); + return rb_ary_new_from_node_args(ast_value, 1, RNODE_ONCE(node)->nd_body); case NODE_DSTR: case NODE_DXSTR: case NODE_DREGX: case NODE_DSYM: { - NODE *n = node->nd_next; + struct RNode_LIST *n = RNODE_DSTR(node)->nd_next; VALUE head = Qnil, next = Qnil; if (n) { - head = NEW_CHILD(ast, n->nd_head); - next = NEW_CHILD(ast, n->nd_next); + head = NEW_CHILD(ast_value, n->nd_head); + next = NEW_CHILD(ast_value, n->nd_next); } - return rb_ary_new_from_args(3, node->nd_lit, head, next); + return rb_ary_new_from_args(3, rb_node_dstr_string_val(node), head, next); } + case NODE_SYM: + return rb_ary_new_from_args(1, rb_node_sym_string_val(node)); case NODE_EVSTR: - return rb_ary_new_from_node_args(ast, 1, node->nd_body); + return rb_ary_new_from_node_args(ast_value, 1, RNODE_EVSTR(node)->nd_body); case NODE_ARGSCAT: - return rb_ary_new_from_node_args(ast, 2, node->nd_head, node->nd_body); + return rb_ary_new_from_node_args(ast_value, 2, RNODE_ARGSCAT(node)->nd_head, RNODE_ARGSCAT(node)->nd_body); case NODE_ARGSPUSH: - return rb_ary_new_from_node_args(ast, 2, node->nd_head, node->nd_body); + return rb_ary_new_from_node_args(ast_value, 2, RNODE_ARGSPUSH(node)->nd_head, RNODE_ARGSPUSH(node)->nd_body); case NODE_SPLAT: - return rb_ary_new_from_node_args(ast, 1, node->nd_head); + return rb_ary_new_from_node_args(ast_value, 1, RNODE_SPLAT(node)->nd_head); case NODE_BLOCK_PASS: - return rb_ary_new_from_node_args(ast, 2, node->nd_head, node->nd_body); + return rb_ary_new_from_node_args(ast_value, 2, RNODE_BLOCK_PASS(node)->nd_head, RNODE_BLOCK_PASS(node)->nd_body); case NODE_DEFN: - return rb_ary_new_from_args(2, ID2SYM(node->nd_mid), NEW_CHILD(ast, node->nd_defn)); + return rb_ary_new_from_args(2, ID2SYM(RNODE_DEFN(node)->nd_mid), NEW_CHILD(ast_value, RNODE_DEFN(node)->nd_defn)); case NODE_DEFS: - return rb_ary_new_from_args(3, NEW_CHILD(ast, node->nd_recv), ID2SYM(node->nd_mid), NEW_CHILD(ast, node->nd_defn)); + return rb_ary_new_from_args(3, NEW_CHILD(ast_value, RNODE_DEFS(node)->nd_recv), ID2SYM(RNODE_DEFS(node)->nd_mid), NEW_CHILD(ast_value, RNODE_DEFS(node)->nd_defn)); case NODE_ALIAS: - return rb_ary_new_from_node_args(ast, 2, node->nd_1st, node->nd_2nd); + return rb_ary_new_from_node_args(ast_value, 2, RNODE_ALIAS(node)->nd_1st, RNODE_ALIAS(node)->nd_2nd); case NODE_VALIAS: - return rb_ary_new_from_args(2, ID2SYM(node->nd_alias), ID2SYM(node->nd_orig)); + return rb_ary_new_from_args(2, ID2SYM(RNODE_VALIAS(node)->nd_alias), ID2SYM(RNODE_VALIAS(node)->nd_orig)); case NODE_UNDEF: - return rb_ary_new_from_node_args(ast, 1, node->nd_undef); + return rb_ary_new_from_args(1, dump_parser_array(ast_value, RNODE_UNDEF(node)->nd_undefs)); case NODE_CLASS: - return rb_ary_new_from_node_args(ast, 3, node->nd_cpath, node->nd_super, node->nd_body); + return rb_ary_new_from_node_args(ast_value, 3, RNODE_CLASS(node)->nd_cpath, RNODE_CLASS(node)->nd_super, RNODE_CLASS(node)->nd_body); case NODE_MODULE: - return rb_ary_new_from_node_args(ast, 2, node->nd_cpath, node->nd_body); + return rb_ary_new_from_node_args(ast_value, 2, RNODE_MODULE(node)->nd_cpath, RNODE_MODULE(node)->nd_body); case NODE_SCLASS: - return rb_ary_new_from_node_args(ast, 2, node->nd_recv, node->nd_body); + return rb_ary_new_from_node_args(ast_value, 2, RNODE_SCLASS(node)->nd_recv, RNODE_SCLASS(node)->nd_body); case NODE_COLON2: - return rb_ary_new_from_args(2, NEW_CHILD(ast, node->nd_head), ID2SYM(node->nd_mid)); + return rb_ary_new_from_args(2, NEW_CHILD(ast_value, RNODE_COLON2(node)->nd_head), ID2SYM(RNODE_COLON2(node)->nd_mid)); case NODE_COLON3: - return rb_ary_new_from_args(1, ID2SYM(node->nd_mid)); + return rb_ary_new_from_args(1, ID2SYM(RNODE_COLON3(node)->nd_mid)); case NODE_DOT2: case NODE_DOT3: case NODE_FLIP2: case NODE_FLIP3: - return rb_ary_new_from_node_args(ast, 2, node->nd_beg, node->nd_end); + return rb_ary_new_from_node_args(ast_value, 2, RNODE_DOT2(node)->nd_beg, RNODE_DOT2(node)->nd_end); case NODE_SELF: - return rb_ary_new_from_node_args(ast, 0); + return rb_ary_new_from_node_args(ast_value, 0); case NODE_NIL: - return rb_ary_new_from_node_args(ast, 0); + return rb_ary_new_from_node_args(ast_value, 0); case NODE_TRUE: - return rb_ary_new_from_node_args(ast, 0); + return rb_ary_new_from_node_args(ast_value, 0); case NODE_FALSE: - return rb_ary_new_from_node_args(ast, 0); + return rb_ary_new_from_node_args(ast_value, 0); case NODE_ERRINFO: - return rb_ary_new_from_node_args(ast, 0); + return rb_ary_new_from_node_args(ast_value, 0); case NODE_DEFINED: - return rb_ary_new_from_node_args(ast, 1, node->nd_head); + return rb_ary_new_from_node_args(ast_value, 1, RNODE_DEFINED(node)->nd_head); case NODE_POSTEXE: - return rb_ary_new_from_node_args(ast, 1, node->nd_body); + return rb_ary_new_from_node_args(ast_value, 1, RNODE_POSTEXE(node)->nd_body); case NODE_ATTRASGN: - return rb_ary_new_from_args(3, NEW_CHILD(ast, node->nd_recv), ID2SYM(node->nd_mid), NEW_CHILD(ast, node->nd_args)); + return rb_ary_new_from_args(3, NEW_CHILD(ast_value, RNODE_ATTRASGN(node)->nd_recv), ID2SYM(RNODE_ATTRASGN(node)->nd_mid), NEW_CHILD(ast_value, RNODE_ATTRASGN(node)->nd_args)); case NODE_LAMBDA: - return rb_ary_new_from_node_args(ast, 1, node->nd_body); + return rb_ary_new_from_node_args(ast_value, 1, RNODE_LAMBDA(node)->nd_body); case NODE_OPT_ARG: - return rb_ary_new_from_node_args(ast, 2, node->nd_body, node->nd_next); + return rb_ary_new_from_node_args(ast_value, 2, RNODE_OPT_ARG(node)->nd_body, RNODE_OPT_ARG(node)->nd_next); case NODE_KW_ARG: - return rb_ary_new_from_node_args(ast, 2, node->nd_body, node->nd_next); + return rb_ary_new_from_node_args(ast_value, 2, RNODE_KW_ARG(node)->nd_body, RNODE_KW_ARG(node)->nd_next); case NODE_POSTARG: - if (NODE_NAMED_REST_P(node->nd_1st)) { - return rb_ary_new_from_node_args(ast, 2, node->nd_1st, node->nd_2nd); + if (NODE_NAMED_REST_P(RNODE_POSTARG(node)->nd_1st)) { + return rb_ary_new_from_node_args(ast_value, 2, RNODE_POSTARG(node)->nd_1st, RNODE_POSTARG(node)->nd_2nd); } return rb_ary_new_from_args(2, no_name_rest(), - NEW_CHILD(ast, node->nd_2nd)); + NEW_CHILD(ast_value, RNODE_POSTARG(node)->nd_2nd)); case NODE_ARGS: { - struct rb_args_info *ainfo = node->nd_ainfo; + struct rb_args_info *ainfo = &RNODE_ARGS(node)->nd_ainfo; return rb_ary_new_from_args(10, INT2NUM(ainfo->pre_args_num), - NEW_CHILD(ast, ainfo->pre_init), - NEW_CHILD(ast, ainfo->opt_args), + NEW_CHILD(ast_value, ainfo->pre_init), + NEW_CHILD(ast_value, (NODE *)ainfo->opt_args), var_name(ainfo->first_post_arg), INT2NUM(ainfo->post_args_num), - NEW_CHILD(ast, ainfo->post_init), + NEW_CHILD(ast_value, ainfo->post_init), (ainfo->rest_arg == NODE_SPECIAL_EXCESSIVE_COMMA ? ID2SYM(rb_intern("NODE_SPECIAL_EXCESSIVE_COMMA")) : var_name(ainfo->rest_arg)), - (ainfo->no_kwarg ? Qfalse : NEW_CHILD(ast, ainfo->kw_args)), - (ainfo->no_kwarg ? Qfalse : NEW_CHILD(ast, ainfo->kw_rest_arg)), + (ainfo->no_kwarg ? Qfalse : NEW_CHILD(ast_value, (NODE *)ainfo->kw_args)), + (ainfo->no_kwarg ? Qfalse : NEW_CHILD(ast_value, ainfo->kw_rest_arg)), var_name(ainfo->block_arg)); } case NODE_SCOPE: { - rb_ast_id_table_t *tbl = node->nd_tbl; + rb_ast_id_table_t *tbl = RNODE_SCOPE(node)->nd_tbl; int i, size = tbl ? tbl->size : 0; VALUE locals = rb_ary_new_capa(size); for (i = 0; i < size; i++) { rb_ary_push(locals, var_name(tbl->ids[i])); } - return rb_ary_new_from_args(3, locals, NEW_CHILD(ast, node->nd_args), NEW_CHILD(ast, node->nd_body)); + return rb_ary_new_from_args(3, locals, NEW_CHILD(ast_value, (NODE *)RNODE_SCOPE(node)->nd_args), NEW_CHILD(ast_value, RNODE_SCOPE(node)->nd_body)); } case NODE_ARYPTN: { - struct rb_ary_pattern_info *apinfo = node->nd_apinfo; - VALUE rest = rest_arg(ast, apinfo->rest_arg); + VALUE rest = rest_arg(ast_value, RNODE_ARYPTN(node)->rest_arg); return rb_ary_new_from_args(4, - NEW_CHILD(ast, node->nd_pconst), - NEW_CHILD(ast, apinfo->pre_args), + NEW_CHILD(ast_value, RNODE_ARYPTN(node)->nd_pconst), + NEW_CHILD(ast_value, RNODE_ARYPTN(node)->pre_args), rest, - NEW_CHILD(ast, apinfo->post_args)); + NEW_CHILD(ast_value, RNODE_ARYPTN(node)->post_args)); } case NODE_FNDPTN: { - struct rb_fnd_pattern_info *fpinfo = node->nd_fpinfo; - VALUE pre_rest = rest_arg(ast, fpinfo->pre_rest_arg); - VALUE post_rest = rest_arg(ast, fpinfo->post_rest_arg); + VALUE pre_rest = rest_arg(ast_value, RNODE_FNDPTN(node)->pre_rest_arg); + VALUE post_rest = rest_arg(ast_value, RNODE_FNDPTN(node)->post_rest_arg); return rb_ary_new_from_args(4, - NEW_CHILD(ast, node->nd_pconst), + NEW_CHILD(ast_value, RNODE_FNDPTN(node)->nd_pconst), pre_rest, - NEW_CHILD(ast, fpinfo->args), + NEW_CHILD(ast_value, RNODE_FNDPTN(node)->args), post_rest); } case NODE_HSHPTN: { - VALUE kwrest = node->nd_pkwrestarg == NODE_SPECIAL_NO_REST_KEYWORD ? ID2SYM(rb_intern("NODE_SPECIAL_NO_REST_KEYWORD")) : - NEW_CHILD(ast, node->nd_pkwrestarg); + VALUE kwrest = RNODE_HSHPTN(node)->nd_pkwrestarg == NODE_SPECIAL_NO_REST_KEYWORD ? ID2SYM(rb_intern("NODE_SPECIAL_NO_REST_KEYWORD")) : + NEW_CHILD(ast_value, RNODE_HSHPTN(node)->nd_pkwrestarg); return rb_ary_new_from_args(3, - NEW_CHILD(ast, node->nd_pconst), - NEW_CHILD(ast, node->nd_pkwargs), + NEW_CHILD(ast_value, RNODE_HSHPTN(node)->nd_pconst), + NEW_CHILD(ast_value, RNODE_HSHPTN(node)->nd_pkwargs), kwrest); } + case NODE_LINE: + return rb_ary_new_from_args(1, rb_node_line_lineno_val(node)); + case NODE_FILE: + return rb_ary_new_from_args(1, rb_node_file_path_val(node)); + case NODE_ENCODING: + return rb_ary_new_from_args(1, rb_node_encoding_val(node)); case NODE_ERROR: - return rb_ary_new_from_node_args(ast, 0); + return rb_ary_new_from_node_args(ast_value, 0); case NODE_ARGS_AUX: case NODE_LAST: break; @@ -693,7 +744,227 @@ ast_node_children(rb_execution_context_t *ec, VALUE self) struct ASTNodeData *data; TypedData_Get_Struct(self, struct ASTNodeData, &rb_node_type, data); - return node_children(data->ast, data->node); + return node_children(data->ast_value, data->node); +} + +static int +null_loc_p(rb_code_location_t *loc) +{ + return (loc->beg_pos.lineno == 0 && loc->beg_pos.column == -1 && loc->end_pos.lineno == 0 && loc->end_pos.column == -1); +} + +static VALUE +location_new(rb_code_location_t *loc) +{ + VALUE obj; + struct ASTLocationData *data; + + if (null_loc_p(loc)) return Qnil; + + obj = TypedData_Make_Struct(rb_cLocation, struct ASTLocationData, &rb_location_type, data); + data->first_lineno = loc->beg_pos.lineno; + data->first_column = loc->beg_pos.column; + data->last_lineno = loc->end_pos.lineno; + data->last_column = loc->end_pos.column; + + return obj; +} + +static VALUE +node_locations(VALUE ast_value, const NODE *node) +{ + enum node_type type = nd_type(node); + switch (type) { + case NODE_ALIAS: + return rb_ary_new_from_args(2, + location_new(nd_code_loc(node)), + location_new(&RNODE_ALIAS(node)->keyword_loc)); + case NODE_AND: + return rb_ary_new_from_args(2, + location_new(nd_code_loc(node)), + location_new(&RNODE_AND(node)->operator_loc)); + case NODE_BLOCK_PASS: + return rb_ary_new_from_args(2, + location_new(nd_code_loc(node)), + location_new(&RNODE_BLOCK_PASS(node)->operator_loc)); + case NODE_BREAK: + return rb_ary_new_from_args(2, + location_new(nd_code_loc(node)), + location_new(&RNODE_BREAK(node)->keyword_loc)); + case NODE_CASE: + return rb_ary_new_from_args(3, + location_new(nd_code_loc(node)), + location_new(&RNODE_CASE(node)->case_keyword_loc), + location_new(&RNODE_CASE(node)->end_keyword_loc)); + case NODE_CASE2: + return rb_ary_new_from_args(3, + location_new(nd_code_loc(node)), + location_new(&RNODE_CASE2(node)->case_keyword_loc), + location_new(&RNODE_CASE2(node)->end_keyword_loc)); + case NODE_CASE3: + return rb_ary_new_from_args(3, + location_new(nd_code_loc(node)), + location_new(&RNODE_CASE3(node)->case_keyword_loc), + location_new(&RNODE_CASE3(node)->end_keyword_loc)); + case NODE_CLASS: + return rb_ary_new_from_args(4, + location_new(nd_code_loc(node)), + location_new(&RNODE_CLASS(node)->class_keyword_loc), + location_new(&RNODE_CLASS(node)->inheritance_operator_loc), + location_new(&RNODE_CLASS(node)->end_keyword_loc)); + case NODE_COLON2: + return rb_ary_new_from_args(3, + location_new(nd_code_loc(node)), + location_new(&RNODE_COLON2(node)->delimiter_loc), + location_new(&RNODE_COLON2(node)->name_loc)); + case NODE_COLON3: + return rb_ary_new_from_args(3, + location_new(nd_code_loc(node)), + location_new(&RNODE_COLON3(node)->delimiter_loc), + location_new(&RNODE_COLON3(node)->name_loc)); + case NODE_DOT2: + return rb_ary_new_from_args(2, + location_new(nd_code_loc(node)), + location_new(&RNODE_DOT2(node)->operator_loc)); + case NODE_DOT3: + return rb_ary_new_from_args(2, + location_new(nd_code_loc(node)), + location_new(&RNODE_DOT3(node)->operator_loc)); + case NODE_EVSTR: + return rb_ary_new_from_args(3, + location_new(nd_code_loc(node)), + location_new(&RNODE_EVSTR(node)->opening_loc), + location_new(&RNODE_EVSTR(node)->closing_loc)); + case NODE_FLIP2: + return rb_ary_new_from_args(2, + location_new(nd_code_loc(node)), + location_new(&RNODE_FLIP2(node)->operator_loc)); + case NODE_FLIP3: + return rb_ary_new_from_args(2, + location_new(nd_code_loc(node)), + location_new(&RNODE_FLIP3(node)->operator_loc)); + case NODE_FOR: + return rb_ary_new_from_args(5, + location_new(nd_code_loc(node)), + location_new(&RNODE_FOR(node)->for_keyword_loc), + location_new(&RNODE_FOR(node)->in_keyword_loc), + location_new(&RNODE_FOR(node)->do_keyword_loc), + location_new(&RNODE_FOR(node)->end_keyword_loc)); + case NODE_LAMBDA: + return rb_ary_new_from_args(4, + location_new(nd_code_loc(node)), + location_new(&RNODE_LAMBDA(node)->operator_loc), + location_new(&RNODE_LAMBDA(node)->opening_loc), + location_new(&RNODE_LAMBDA(node)->closing_loc)); + case NODE_IF: + return rb_ary_new_from_args(4, + location_new(nd_code_loc(node)), + location_new(&RNODE_IF(node)->if_keyword_loc), + location_new(&RNODE_IF(node)->then_keyword_loc), + location_new(&RNODE_IF(node)->end_keyword_loc)); + case NODE_NEXT: + return rb_ary_new_from_args(2, + location_new(nd_code_loc(node)), + location_new(&RNODE_NEXT(node)->keyword_loc)); + case NODE_OR: + return rb_ary_new_from_args(2, + location_new(nd_code_loc(node)), + location_new(&RNODE_OR(node)->operator_loc)); + case NODE_OP_ASGN1: + return rb_ary_new_from_args(5, + location_new(nd_code_loc(node)), + location_new(&RNODE_OP_ASGN1(node)->call_operator_loc), + location_new(&RNODE_OP_ASGN1(node)->opening_loc), + location_new(&RNODE_OP_ASGN1(node)->closing_loc), + location_new(&RNODE_OP_ASGN1(node)->binary_operator_loc)); + case NODE_OP_ASGN2: + return rb_ary_new_from_args(4, + location_new(nd_code_loc(node)), + location_new(&RNODE_OP_ASGN2(node)->call_operator_loc), + location_new(&RNODE_OP_ASGN2(node)->message_loc), + location_new(&RNODE_OP_ASGN2(node)->binary_operator_loc)); + case NODE_POSTEXE: + return rb_ary_new_from_args(4, + location_new(nd_code_loc(node)), + location_new(&RNODE_POSTEXE(node)->keyword_loc), + location_new(&RNODE_POSTEXE(node)->opening_loc), + location_new(&RNODE_POSTEXE(node)->closing_loc)); + case NODE_REDO: + return rb_ary_new_from_args(2, + location_new(nd_code_loc(node)), + location_new(&RNODE_REDO(node)->keyword_loc)); + case NODE_REGX: + return rb_ary_new_from_args(4, + location_new(nd_code_loc(node)), + location_new(&RNODE_REGX(node)->opening_loc), + location_new(&RNODE_REGX(node)->content_loc), + location_new(&RNODE_REGX(node)->closing_loc)); + case NODE_RETURN: + return rb_ary_new_from_args(2, + location_new(nd_code_loc(node)), + location_new(&RNODE_RETURN(node)->keyword_loc)); + case NODE_SPLAT: + return rb_ary_new_from_args(2, + location_new(nd_code_loc(node)), + location_new(&RNODE_SPLAT(node)->operator_loc)); + case NODE_SUPER: + return rb_ary_new_from_args(4, + location_new(nd_code_loc(node)), + location_new(&RNODE_SUPER(node)->keyword_loc), + location_new(&RNODE_SUPER(node)->lparen_loc), + location_new(&RNODE_SUPER(node)->rparen_loc)); + case NODE_UNDEF: + return rb_ary_new_from_args(2, + location_new(nd_code_loc(node)), + location_new(&RNODE_UNDEF(node)->keyword_loc)); + case NODE_UNLESS: + return rb_ary_new_from_args(4, + location_new(nd_code_loc(node)), + location_new(&RNODE_UNLESS(node)->keyword_loc), + location_new(&RNODE_UNLESS(node)->then_keyword_loc), + location_new(&RNODE_UNLESS(node)->end_keyword_loc)); + case NODE_VALIAS: + return rb_ary_new_from_args(2, + location_new(nd_code_loc(node)), + location_new(&RNODE_VALIAS(node)->keyword_loc)); + case NODE_WHEN: + return rb_ary_new_from_args(3, + location_new(nd_code_loc(node)), + location_new(&RNODE_WHEN(node)->keyword_loc), + location_new(&RNODE_WHEN(node)->then_keyword_loc)); + case NODE_WHILE: + return rb_ary_new_from_args(3, + location_new(nd_code_loc(node)), + location_new(&RNODE_WHILE(node)->keyword_loc), + location_new(&RNODE_WHILE(node)->closing_loc)); + case NODE_UNTIL: + return rb_ary_new_from_args(3, + location_new(nd_code_loc(node)), + location_new(&RNODE_UNTIL(node)->keyword_loc), + location_new(&RNODE_UNTIL(node)->closing_loc)); + case NODE_YIELD: + return rb_ary_new_from_args(4, + location_new(nd_code_loc(node)), + location_new(&RNODE_YIELD(node)->keyword_loc), + location_new(&RNODE_YIELD(node)->lparen_loc), + location_new(&RNODE_YIELD(node)->rparen_loc)); + case NODE_ARGS_AUX: + case NODE_LAST: + break; + default: + return rb_ary_new_from_args(1, location_new(nd_code_loc(node))); + } + + rb_bug("node_locations: unknown node: %s", ruby_node_name(type)); +} + +static VALUE +ast_node_locations(rb_execution_context_t *ec, VALUE self) +{ + struct ASTNodeData *data; + TypedData_Get_Struct(self, struct ASTNodeData, &rb_node_type, data); + + return node_locations(data->ast_value, data->node); } static VALUE @@ -735,10 +1006,37 @@ ast_node_last_column(rb_execution_context_t *ec, VALUE self) static VALUE ast_node_all_tokens(rb_execution_context_t *ec, VALUE self) { + long i; struct ASTNodeData *data; + rb_ast_t *ast; + rb_parser_ary_t *parser_tokens; + rb_parser_ast_token_t *parser_token; + VALUE str, loc, token, all_tokens; + TypedData_Get_Struct(self, struct ASTNodeData, &rb_node_type, data); + ast = rb_ruby_ast_data_get(data->ast_value); - return rb_ast_tokens(data->ast); + parser_tokens = ast->node_buffer->tokens; + if (parser_tokens == NULL) { + return Qnil; + } + + all_tokens = rb_ary_new2(parser_tokens->len); + for (i = 0; i < parser_tokens->len; i++) { + parser_token = parser_tokens->data[i]; + str = rb_str_new(parser_token->str->ptr, parser_token->str->len); + loc = rb_ary_new_from_args(4, + INT2FIX(parser_token->loc.beg_pos.lineno), + INT2FIX(parser_token->loc.beg_pos.column), + INT2FIX(parser_token->loc.end_pos.lineno), + INT2FIX(parser_token->loc.end_pos.column) + ); + token = rb_ary_new_from_args(4, INT2FIX(parser_token->id), ID2SYM(rb_intern(parser_token->type_name)), str, loc); + rb_ary_push(all_tokens, token); + } + rb_ary_freeze(all_tokens); + + return all_tokens; } static VALUE @@ -765,10 +1063,66 @@ static VALUE ast_node_script_lines(rb_execution_context_t *ec, VALUE self) { struct ASTNodeData *data; + rb_ast_t *ast; TypedData_Get_Struct(self, struct ASTNodeData, &rb_node_type, data); - VALUE ret = data->ast->body.script_lines; - if (!RB_TYPE_P(ret, T_ARRAY)) return Qnil; - return ret; + ast = rb_ruby_ast_data_get(data->ast_value); + rb_parser_ary_t *ret = ast->body.script_lines; + return rb_parser_build_script_lines_from(ret); +} + +static VALUE +ast_location_first_lineno(rb_execution_context_t *ec, VALUE self) +{ + struct ASTLocationData *data; + TypedData_Get_Struct(self, struct ASTLocationData, &rb_location_type, data); + + return INT2NUM(data->first_lineno); +} + +static VALUE +ast_location_first_column(rb_execution_context_t *ec, VALUE self) +{ + struct ASTLocationData *data; + TypedData_Get_Struct(self, struct ASTLocationData, &rb_location_type, data); + + return INT2NUM(data->first_column); +} + +static VALUE +ast_location_last_lineno(rb_execution_context_t *ec, VALUE self) +{ + struct ASTLocationData *data; + TypedData_Get_Struct(self, struct ASTLocationData, &rb_location_type, data); + + return INT2NUM(data->last_lineno); +} + +static VALUE +ast_location_last_column(rb_execution_context_t *ec, VALUE self) +{ + struct ASTLocationData *data; + TypedData_Get_Struct(self, struct ASTLocationData, &rb_location_type, data); + + return INT2NUM(data->last_column); +} + +static VALUE +ast_location_inspect(rb_execution_context_t *ec, VALUE self) +{ + VALUE str; + VALUE cname; + struct ASTLocationData *data; + TypedData_Get_Struct(self, struct ASTLocationData, &rb_location_type, data); + + cname = rb_class_path(rb_obj_class(self)); + str = rb_str_new2("#<"); + + rb_str_append(str, cname); + rb_str_catf(str, ":@%d:%d-%d:%d>", + data->first_lineno, data->first_column, + data->last_lineno, data->last_column); + + return str; } #include "ast.rbinc" @@ -778,5 +1132,7 @@ Init_ast(void) { rb_mAST = rb_define_module_under(rb_cRubyVM, "AbstractSyntaxTree"); rb_cNode = rb_define_class_under(rb_mAST, "Node", rb_cObject); + rb_cLocation = rb_define_class_under(rb_mAST, "Location", rb_cObject); rb_undef_alloc_func(rb_cNode); + rb_undef_alloc_func(rb_cLocation); } diff --git a/ast.rb b/ast.rb index fa9b69507c3f43..6380621780a0bf 100644 --- a/ast.rb +++ b/ast.rb @@ -13,9 +13,8 @@ # access children nodes by name, etc. # # If you are looking for a stable API or an API working under multiple Ruby -# implementations, consider using the _parser_ gem or Ripper. If you would -# like to make RubyVM::AbstractSyntaxTree stable, please join the discussion -# at https://bugs.ruby-lang.org/issues/14844. +# implementations, consider using the _prism_ gem, which is the official +# Ruby API to parse Ruby code. # module RubyVM::AbstractSyntaxTree @@ -265,12 +264,69 @@ def source lines = script_lines if lines lines = lines[first_lineno - 1 .. last_lineno - 1] - lines[-1] = lines[-1][0...last_column] - lines[0] = lines[0][first_column..-1] + lines[-1] = lines[-1].byteslice(0...last_column) + lines[0] = lines[0].byteslice(first_column..-1) lines.join else nil end end + + # call-seq: + # node.locations -> array + # + # Returns location objects associated with the AST node. + # The returned array contains RubyVM::AbstractSyntaxTree::Location. + def locations + Primitive.ast_node_locations + end + end + + # RubyVM::AbstractSyntaxTree::Location instances are created by + # RubyVM::AbstractSyntaxTree::Node#locations. + # + # This class is MRI specific. + # + class Location + + # call-seq: + # location.first_lineno -> integer + # + # The line number in the source code where this AST's text began. + def first_lineno + Primitive.ast_location_first_lineno + end + + # call-seq: + # location.first_column -> integer + # + # The column number in the source code where this AST's text began. + def first_column + Primitive.ast_location_first_column + end + + # call-seq: + # location.last_lineno -> integer + # + # The line number in the source code where this AST's text ended. + def last_lineno + Primitive.ast_location_last_lineno + end + + # call-seq: + # location.last_column -> integer + # + # The column number in the source code where this AST's text ended. + def last_column + Primitive.ast_location_last_column + end + + # call-seq: + # location.inspect -> string + # + # Returns debugging information about this location as a string. + def inspect + Primitive.ast_location_inspect + end end end diff --git a/basictest/test.rb b/basictest/test.rb index 95875b52a6ef79..711e4f4ab32209 100755 --- a/basictest/test.rb +++ b/basictest/test.rb @@ -879,7 +879,7 @@ def r(val); a,b,*c = *yield(); test_ok([a,b,c] == val, 2); end test_ok($x == [7,5,3,2,1]) # split test -$x = "The Book of Mormon" +$x = +"The Book of Mormon" test_ok($x.split(//).reverse!.join == $x.reverse) test_ok($x.reverse == $x.reverse!) test_ok("1 byte string".split(//).reverse.join(":") == "g:n:i:r:t:s: :e:t:y:b: :1") @@ -1643,7 +1643,7 @@ def shift_test(a) test_ok(/(\s+\d+){2}/ =~ " 1 2" && $& == " 1 2") test_ok(/(?:\s+\d+){2}/ =~ " 1 2" && $& == " 1 2") -$x = < true } +benchmark: hash.key?(obj) +loop_count: 30000000 diff --git a/benchmark/hash_new.yml b/benchmark/hash_new.yml new file mode 100644 index 00000000000000..9d8e34187f6785 --- /dev/null +++ b/benchmark/hash_new.yml @@ -0,0 +1,16 @@ +prelude: | + has_hash_with_capa = Hash.instance_method(:initialize).parameters.include?([:key, :capacity]) + strings_1k = 1_000.times.map { |i| -i.to_s.freeze } + strings_100k = 100_000.times.map { |i| -i.to_s.freeze } +benchmark: + new: Hash.new + new_with_capa_1k: | + h = has_hash_with_capa ? Hash.new(capacity: strings_1k.size) : {} + strings_1k.each do |x| + h[x] = true + end + new_with_capa_100k: | + h = has_hash_with_capa ? Hash.new(capacity: strings_100k.size) : {} + strings_100k.each do |x| + h[x] = true + end diff --git a/benchmark/io_close.yml b/benchmark/io_close.yml new file mode 100644 index 00000000000000..a552872884b3ee --- /dev/null +++ b/benchmark/io_close.yml @@ -0,0 +1,13 @@ +prelude: | + ios = 1000.times.map do + 100.times.map{IO.pipe} + end +benchmark: + # Close IO + io_close: | + # Process each batch of ios per iteration of the benchmark. + ios.pop.each do |r, w| + r.close + w.close + end +loop_count: 100 diff --git a/benchmark/io_close_contended.yml b/benchmark/io_close_contended.yml new file mode 100644 index 00000000000000..1d9e4e0d0f8636 --- /dev/null +++ b/benchmark/io_close_contended.yml @@ -0,0 +1,21 @@ +prelude: | + ios = 100.times.map do + 10.times.map do + pipe = IO.pipe.tap do |r, w| + Thread.new do + r.read + rescue IOError + # Ignore + end + end + end + end +benchmark: + # Close IO + io_close_contended: | + # Process each batch of ios per iteration of the benchmark. + ios.pop.each do |r, w| + r.close + w.close + end +loop_count: 10 diff --git a/benchmark/lib/benchmark_driver/runner/ractor.rb b/benchmark/lib/benchmark_driver/runner/ractor.rb index c730b8e4a54bf2..fd9c2dd4db731d 100644 --- a/benchmark/lib/benchmark_driver/runner/ractor.rb +++ b/benchmark/lib/benchmark_driver/runner/ractor.rb @@ -87,7 +87,7 @@ def render(results:) <% end %> # Wait for all Ractors before executing code to write results -__bmdv_ractors.map!(&:take) +__bmdv_ractors.map!(&:value) <% results.each do |result| %> File.write(<%= result.dump %>, __bmdv_ractors.shift) diff --git a/benchmark/loop_each.yml b/benchmark/loop_each.yml new file mode 100644 index 00000000000000..1c757185a8a7e9 --- /dev/null +++ b/benchmark/loop_each.yml @@ -0,0 +1,4 @@ +prelude: | + arr = [nil] * 30_000_000 +benchmark: + loop_each: arr.each{|e|} diff --git a/benchmark/loop_times_megamorphic.yml b/benchmark/loop_times_megamorphic.yml new file mode 100644 index 00000000000000..f9343ba8973b79 --- /dev/null +++ b/benchmark/loop_times_megamorphic.yml @@ -0,0 +1,7 @@ +prelude: | + eval(<<~EOS) + def loop_times_megamorphic + #{"1.times {|i|};" * 1000} + end + EOS +benchmark: loop_times_megamorphic diff --git a/benchmark/module_eqq.yml b/benchmark/module_eqq.yml index a561fb86dc4b06..2f9c490d92cf7b 100644 --- a/benchmark/module_eqq.yml +++ b/benchmark/module_eqq.yml @@ -1,4 +1,5 @@ prelude: | + module SomeModule; end class SimpleClass; end class MediumClass 10.times { include Module.new } @@ -24,4 +25,8 @@ benchmark: SimpleClass === LargeObj simple_class_eqq_huge_obj: | SimpleClass === HugeObj -loop_count: 20000000 + simple_class_eqq_module: | + SimpleClass === HugeObj + module_eqq_module: | + SomeModule === HugeObj +loop_count: 10000000 diff --git a/benchmark/nilclass.yml b/benchmark/nilclass.yml index fba67a5f6a1764..66234c4cdfe05b 100644 --- a/benchmark/nilclass.yml +++ b/benchmark/nilclass.yml @@ -1,6 +1,16 @@ +prelude: | + def a = nil benchmark: + rationalize: + nil.rationalize + to_c: | + nil.to_c to_i: | nil.to_i to_f: | nil.to_f + to_r: | + nil.to_r + splat: | + a(*nil) loop_count: 100000 diff --git a/benchmark/object_allocate.yml b/benchmark/object_allocate.yml index 93ff463e415585..c6269923f07cc0 100644 --- a/benchmark/object_allocate.yml +++ b/benchmark/object_allocate.yml @@ -11,6 +11,26 @@ prelude: | class OneTwentyEight 128.times { include(Module.new) } end + class OnePositional + def initialize a; end + end + class TwoPositional + def initialize a, b; end + end + class ThreePositional + def initialize a, b, c; end + end + class FourPositional + def initialize a, b, c, d; end + end + class KWArg + def initialize a:, b:, c:, d: + end + end + class Mixed + def initialize a, b, c:, d: + end + end # Disable GC to see raw throughput: GC.disable benchmark: @@ -18,4 +38,12 @@ benchmark: allocate_32_deep: ThirtyTwo.new allocate_64_deep: SixtyFour.new allocate_128_deep: OneTwentyEight.new + allocate_1_positional_params: OnePositional.new(1) + allocate_2_positional_params: TwoPositional.new(1, 2) + allocate_3_positional_params: ThreePositional.new(1, 2, 3) + allocate_4_positional_params: FourPositional.new(1, 2, 3, 4) + allocate_kwarg_params: "KWArg.new(a: 1, b: 2, c: 3, d: 4)" + allocate_mixed_params: "Mixed.new(1, 2, c: 3, d: 4)" + allocate_no_params: "Object.new" + allocate_allocate: "Object.allocate" loop_count: 100000 diff --git a/benchmark/object_id.yml b/benchmark/object_id.yml new file mode 100644 index 00000000000000..2bd52b923fa100 --- /dev/null +++ b/benchmark/object_id.yml @@ -0,0 +1,4 @@ +benchmark: + baseline: "Object.new" + object_id: "Object.new.object_id" +# loop_count: 100000 diff --git a/benchmark/ractor_string_fstring.yml b/benchmark/ractor_string_fstring.yml new file mode 100644 index 00000000000000..14b92d8fd87f3a --- /dev/null +++ b/benchmark/ractor_string_fstring.yml @@ -0,0 +1,18 @@ +type: lib/benchmark_driver/runner/ractor +benchmark: + ractor_fstring_random: | + i = 0 + str = "same".dup + while i < 2000000 + -(i.to_s.freeze) + i += 1 + end + ractor_fstring_same: | + i = 0 + str = "same".dup + while i < 2000000 + -str + i += 1 + end +loop_count: 1 +ractor: 4 diff --git a/benchmark/range_bsearch_bignum.yml b/benchmark/range_bsearch_bignum.yml new file mode 100644 index 00000000000000..5730c93fcfb016 --- /dev/null +++ b/benchmark/range_bsearch_bignum.yml @@ -0,0 +1,10 @@ +prelude: | + first = 2**100 + last = 2**1000 + mid = (first + last) / 2 + r = first..last + +benchmark: + first: r.bsearch { |x| x >= first } + mid: r.bsearch { |x| x >= mid } + last: r.bsearch { |x| x >= last } diff --git a/benchmark/range_bsearch_endpointless.yml b/benchmark/range_bsearch_endpointless.yml new file mode 100644 index 00000000000000..8d7bedb662e007 --- /dev/null +++ b/benchmark/range_bsearch_endpointless.yml @@ -0,0 +1,21 @@ +prelude: | + re = (1..) + rb = (..0) + +benchmark: + 'endless 10**0': re.bsearch { |x| x >= 1 } + 'endless 10**1': re.bsearch { |x| x >= 10 } + 'endless 10**2': re.bsearch { |x| x >= 100 } + 'endless 10**3': re.bsearch { |x| x >= 1000 } + 'endless 10**4': re.bsearch { |x| x >= 10000 } + 'endless 10**5': re.bsearch { |x| x >= 100000 } + 'endless 10**10': re.bsearch { |x| x >= 10000000000 } + 'endless 10**100': re.bsearch { |x| x >= 10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 } + 'beginless -10**0': rb.bsearch { |x| x >= -1 } + 'beginless -10**1': rb.bsearch { |x| x >= -10 } + 'beginless -10**2': rb.bsearch { |x| x >= -100 } + 'beginless -10**3': rb.bsearch { |x| x >= -1000 } + 'beginless -10**4': rb.bsearch { |x| x >= -10000 } + 'beginless -10**5': rb.bsearch { |x| x >= -100000 } + 'beginless -10**10': rb.bsearch { |x| x >= -10000000000 } + 'beginless -10**100': rb.bsearch { |x| x >= -10000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 } diff --git a/benchmark/range_bsearch_fixnum.yml b/benchmark/range_bsearch_fixnum.yml new file mode 100644 index 00000000000000..59416531b9abd0 --- /dev/null +++ b/benchmark/range_bsearch_fixnum.yml @@ -0,0 +1,10 @@ +prelude: | + first = 1 + last = 10000 + mid = (first + last) / 2 + r = first..last + +benchmark: + first: r.bsearch { |x| x >= first } + mid: r.bsearch { |x| x >= mid } + last: r.bsearch { |x| x >= last } diff --git a/benchmark/range_count.yml b/benchmark/range_count.yml new file mode 100644 index 00000000000000..58f53a023613cc --- /dev/null +++ b/benchmark/range_count.yml @@ -0,0 +1,11 @@ +prelude: | + r_1 = 1..1 + r_1k = 1..1000 + r_1m = 1..1000000 + r_str = 'a'..'z' + +benchmark: + 'int 1': r_1.count + 'int 1K': r_1k.count + 'int 1M': r_1m.count + string: r_str.count diff --git a/benchmark/range_overlap.yml b/benchmark/range_overlap.yml new file mode 100644 index 00000000000000..700a00053c84aa --- /dev/null +++ b/benchmark/range_overlap.yml @@ -0,0 +1,19 @@ +prelude: | + class Range + unless method_defined?(:overlap?) + def overlap?(other) + other.begin == self.begin || cover?(other.begin) || other.cover?(self.begin) + end + end + end + +benchmark: + - (2..3).overlap?(1..1) + - (2..3).overlap?(2..4) + - (2..3).overlap?(4..5) + - (2..3).overlap?(2..1) + - (2..3).overlap?(0..1) + - (2..3).overlap?(...1) + - (2...3).overlap?(..2) + - (2...3).overlap?(3...) + - (2..3).overlap?('a'..'d') diff --git a/benchmark/range_reverse_each.yml b/benchmark/range_reverse_each.yml new file mode 100644 index 00000000000000..a32efeccc68e91 --- /dev/null +++ b/benchmark/range_reverse_each.yml @@ -0,0 +1,16 @@ +prelude: | + rf_1 = 0..1 + rf_1k = 0..1000 + rf_1m = 0..1000000 + big = 2**1000 + rb_1 = big..big+1 + rb_1k = big..big+1000 + rb_1m = big..big+1000000 + +benchmark: + "Fixnum 1": rf_1.reverse_each { _1 } + "Fixnum 1K": rf_1k.reverse_each { _1 } + "Fixnum 1M": rf_1m.reverse_each { _1 } + "Bignum 1": rb_1.reverse_each { _1 } + "Bignum 1K": rb_1k.reverse_each { _1 } + "Bignum 1M": rb_1m.reverse_each { _1 } diff --git a/benchmark/realpath.yml b/benchmark/realpath.yml index 90a029d5b982ba..6b6a4836b0df20 100644 --- a/benchmark/realpath.yml +++ b/benchmark/realpath.yml @@ -12,6 +12,9 @@ prelude: | relative_dir = 'b/c' absolute_dir = File.join(pwd, relative_dir) file_dir = 'c' +teardown: | + require 'fileutils' + FileUtils.rm_rf('b') benchmark: relative_nil: "f.realpath(relative, nil)" absolute_nil: "f.realpath(absolute, nil)" diff --git a/benchmark/scan.yaml b/benchmark/scan.yaml new file mode 100644 index 00000000000000..62ad1d6862df6d --- /dev/null +++ b/benchmark/scan.yaml @@ -0,0 +1,16 @@ +prelude: | + $LOAD_PATH.unshift(File.expand_path("lib")) + require "strscan" + str = "test string" + scanner = StringScanner.new(str) + str = "test" + reg = /test/ +benchmark: + check(reg): | + scanner.check(reg) + check(str): | + scanner.check(str) + match?(reg): | + scanner.match?(reg) + match?(str): | + scanner.match?(str) diff --git a/benchmark/search.yaml b/benchmark/search.yaml new file mode 100644 index 00000000000000..42a50c90e6c134 --- /dev/null +++ b/benchmark/search.yaml @@ -0,0 +1,16 @@ +prelude: | + $LOAD_PATH.unshift(File.expand_path("lib")) + require "strscan" + str = "test string" + scanner = StringScanner.new(str) + str = "string" + reg = /string/ +benchmark: + check_until(reg): | + scanner.check_until(reg) + check_until(str): | + scanner.check_until(str) + exist?(reg): | + scanner.exist?(reg) + exist?(str): | + scanner.exist?(str) diff --git a/benchmark/set.yml b/benchmark/set.yml new file mode 100644 index 00000000000000..43217036e25ba5 --- /dev/null +++ b/benchmark/set.yml @@ -0,0 +1,265 @@ +prelude: | + # First 1000 digits of pi + pi = <<~END.gsub(/\D/, '') + 31415926535897932384626433832795028841971693993751058209749445923078164062862089 + 98628034825342117067982148086513282306647093844609550582231725359408128481117450 + 28410270193852110555964462294895493038196442881097566593344612847564823378678316 + 52712019091456485669234603486104543266482133936072602491412737245870066063155881 + 74881520920962829254091715364367892590360011330530548820466521384146951941511609 + 43305727036575959195309218611738193261179310511854807446237996274956735188575272 + 48912279381830119491298336733624406566430860213949463952247371907021798609437027 + 70539217176293176752384674818467669405132000568127145263560827785771342757789609 + 17363717872146844090122495343014654958537105079227968925892354201995611212902196 + 08640344181598136297747713099605187072113499999983729780499510597317328160963185 + 95024459455346908302642522308253344685035261931188171010003137838752886587533208 + 38142061717766914730359825349042875546873115956286388235378759375195778185778053 + 21712268066130019278766111959092164201989380952572010654505906988788448549 + END + array1 = 10.times.flat_map do |i| + pi[i...].chars.each_slice(10).map(&:join) + end + array2 = array1.map(&:reverse) + array1.map!(&:to_i) + array2.map!(&:to_i) + a1 = array1[...10] + a2 = array1[...100] + a3 = array1 + oa1 = array2[...10] + oa2 = array2[...100] + oa3 = array2 + s0 = Set.new + s0 = Set.new + s1 = Set.new(a1) + s2 = Set.new(a2) + s3 = Set.new(a3) + o0 = Set.new + o1 = Set.new(array2[...10]) + o2 = Set.new(array2[...100]) + o3 = Set.new(array2) + d0 = s0.dup + d1 = s1.dup + d2 = s2.dup + d3 = s3.dup + ss1 = s1 - a1[-1..-1] + ss2 = s2 - a2[-1..-1] + ss3 = s3 - a3[-1..-1] + os1 = o1 - oa1[-1..-1] + os2 = o2 - oa2[-1..-1] + os3 = o3 - oa3[-1..-1] + member = a1.first + cbi = s0.dup.compare_by_identity + ns = Set[s3, o3, d3] + set_subclass = Class.new(Set) + +benchmark: + new_0: Set.new + new_10: Set.new(a1) + new_100: Set.new(a2) + new_1000: Set.new(a3) + aref_0: Set[] + aref_10: Set[*a1] + aref_100: Set[*a2] + aref_1000: Set[*a3] + amp_0: s0 & o0 + amp_10: s1 & o1 + amp_100: s2 & o2 + amp_1000: s3 & o3 + amp_same_0: s0 & d0 + amp_same_10: s1 & d1 + amp_same_100: s2 & d2 + amp_same_1000: s3 & d3 + minus_0: s0 - o0 + minus_10: s1 - o1 + minus_100: s2 - o2 + minus_1000: s3 - o3 + minus_same_0: s0 - d0 + minus_same_10: s1 - d1 + minus_same_100: s2 - d2 + minus_same_1000: s3 - d3 + spaceship_0: s0 <=> o0 + spaceship_diff_10: s1 <=> o1 + spaceship_diff_100: s2 <=> o2 + spaceship_diff_1000: s2 <=> o3 + spaceship_sub_10: s1 <=> ss1 + spaceship_sub_100: s2 <=> ss2 + spaceship_sub_1000: s2 <=> ss3 + spaceship_sup_10: ss1 <=> s1 + spaceship_sup_100: ss2 <=> s2 + spaceship_sup_1000: ss2 <=> s3 + eq_0: s0 == o0 + eq_10: s1 == o1 + eq_100: s2 == o2 + eq_1000: s3 == o3 + eq_same_0: s0 == d0 + eq_same_10: s1 == d1 + eq_same_100: s2 == d2 + eq_same_1000: s3 == d3 + xor_0: s0 ^ o0 + xor_10: s1 ^ o1 + xor_100: s2 ^ o2 + xor_1000: s3 ^ o3 + xor_same_0: s0 ^ d0 + xor_same_10: s1 ^ d1 + xor_same_100: s2 ^ d2 + xor_same_1000: s3 ^ d3 + pipe_0: s0 | o0 + pipe_10: s1 | o1 + pipe_100: s2 | o2 + pipe_1000: s3 | o3 + pipe_same_0: s0 | d0 + pipe_same_10: s1 | d1 + pipe_same_100: s2 | d2 + pipe_same_1000: s3 | d3 + add: a3.each { s0.add(it) } + add_exist: a3.each { s3.add(it) } + addq: a3.each { s0.add?(it) } + addq_exist: a3.each { s3.add?(it) } + classify_0: s0.classify { it } + classify_10: s1.classify { it & 2 } + classify_100: s2.classify { it & 8 } + classify_1000: s3.classify { it & 32 } + clear: s0.clear + collect_0: s0.collect! { it } + collect_10: s1.collect! { it } + collect_100: s2.collect! { it } + collect_1000: s3.collect! { it } + compare_by_identity_0: s0.dup.compare_by_identity + compare_by_identity_10: s1.dup.compare_by_identity + compare_by_identity_100: s2.dup.compare_by_identity + compare_by_identity_1000: s3.dup.compare_by_identity + compare_by_identityq_false: s0.compare_by_identity? + compare_by_identityq_true: cbi.compare_by_identity? + clone_0: s0.clone + clone_10: s1.clone + clone_100: s2.clone + clone_1000: s3.clone + delete: a3.each { s3.delete(it) } + delete_not_exist: a3.each { o3.delete(it) } + deleteq: a3.each { s3.delete?(it) } + deleteq_not_exist: a3.each { o3.delete?(it) } + delete_if_0: s0.delete_if { it } + delete_if_10: s1.delete_if { it & 2 == 0 } + delete_if_100: s2.delete_if { it & 2 == 0 } + delete_if_1000: s3.delete_if { it & 2 == 0 } + disjoint_0: s0.disjoint? o0 + disjoint_10: s1.disjoint? o1 + disjoint_100: s2.disjoint? o2 + disjoint_1000: s3.disjoint? o3 + disjoint_same_0: s0.disjoint? d0 + disjoint_same_10: s1.disjoint? d1 + disjoint_same_100: s2.disjoint? d2 + disjoint_same_1000: s3.disjoint? d3 + divide_1arity_0: s0.divide { true } + divide_1arity_10: s1.divide { it & 2 } + divide_1arity_100: s2.divide { it & 8 } + divide_1arity_1000: s3.divide { it & 32 } + divide_2arity_0: s0.divide { true } + divide_2arity_10: s1.divide { (_1 & 2) == (_2 & 2) } + divide_2arity_100: s2.divide { (_1 & 8) == (_2 & 8) } + divide_2arity_1000: s3.divide { (_1 & 32) == (_2 & 32) } + dup_0: s0.dup + dup_10: s1.dup + dup_100: s2.dup + dup_1000: s3.dup + each_0: s0.each { it } + each_10: s1.each { it } + each_100: s2.each { it } + each_1000: s3.each { it } + empty_true: s0.empty? + empty_false: s3.empty? + flatten: ns.flatten + flattenb: ns.flatten! + include_true_0: s0.include? member + include_true_10: s1.include? member + include_true_100: s2.include? member + include_true_1000: s3.include? member + include_false_0: s0.include?(-1) + include_false_10: s1.include?(-1) + include_false_100: s2.include?(-1) + include_false_1000: s3.include?(-1) + intersect_0: s0.intersect? o0 + intersect_10: s1.intersect? o1 + intersect_100: s2.intersect? o2 + intersect_1000: s3.intersect? o3 + intersect_same_0: s0.intersect? d0 + intersect_same_10: s1.intersect? d1 + intersect_same_100: s2.intersect? d2 + intersect_same_1000: s3.intersect? d3 + join_0: s0.join + join_10: s1.join + join_100: s2.join + join_1000: s3.join + join_arg_0: s0.join "" + join_arg_10: s1.join "" + join_arg_100: s2.join "" + join_arg_1000: s3.join "" + keep_if_0: s0.keep_if { it } + keep_if_10: s1.keep_if { it & 2 == 0 } + keep_if_100: s2.keep_if { it & 2 == 0 } + keep_if_1000: s3.keep_if { it & 2 == 0 } + merge_set: s0.dup.merge(s3, o3) + merge_enum: s0.dup.merge(array1, array2) + proper_subset_0: s0.proper_subset? s0 + proper_subset_10: s1.proper_subset? ss1 + proper_subset_100: s2.proper_subset? ss2 + proper_subset_1000: s3.proper_subset? ss3 + proper_subset_false_10: s1.proper_subset? os1 + proper_subset_false_100: s2.proper_subset? os2 + proper_subset_false_1000: s3.proper_subset? os3 + proper_superset_0: s0.proper_superset? s0 + proper_superset_10: ss1.proper_superset? s1 + proper_superset_100: ss2.proper_superset? s2 + proper_superset_1000: ss3.proper_superset? s3 + proper_superset_false_10: os1.proper_superset? s1 + proper_superset_false_100: os2.proper_superset? s2 + proper_superset_false_1000: os3.proper_superset? s3 + reject_0: s0.reject! { it } + reject_10: s1.reject! { it & 2 == 0 } + reject_100: s2.reject! { it & 2 == 0 } + reject_1000: s3.reject! { it & 2 == 0 } + replace_0: s = Set.new; array1.each { s.replace(s0) } + replace_10: s = Set.new; array1.each { s.replace(s1) } + replace_100: s = Set.new; array1.each { s.replace(s2) } + replace_1000: s = Set.new; array1.each { s.replace(s3) } + reset_0: s0.reset + reset_10: s1.reset + reset_100: s2.reset + reset_1000: s3.reset + select_0: s0.select! { it } + select_10: s1.select! { it & 2 == 0 } + select_100: s2.select! { it & 2 == 0 } + select_1000: s3.select! { it & 2 == 0 } + size_0: s0.size + size_10: s1.size + size_100: s2.size + size_1000: s3.size + subtract_set: s3.dup.subtract(os3) + subtract_enum: s3.dup.subtract(oa3) + subtract_same_set: s3.dup.subtract(s3) + subtract_same_enum: s3.dup.subtract(a3) + subset_0: s0.subset? s0 + subset_10: s1.subset? ss1 + subset_100: s2.subset? ss2 + subset_1000: s3.subset? ss3 + subset_false_10: s1.subset? os1 + subset_false_100: s2.subset? os2 + subset_false_1000: s3.subset? os3 + superset_0: s0.superset? s0 + superset_10: ss1.superset? s1 + superset_100: ss2.superset? s2 + superset_1000: ss3.superset? s3 + superset_false_10: os1.superset? s1 + superset_false_100: os2.superset? s2 + superset_false_1000: os3.superset? s3 + to_a_0: s0.to_a + to_a_10: s1.to_a + to_a_100: s2.to_a + to_a_1000: s3.to_a + to_set_0: s0.to_set + to_set_10: s1.to_set + to_set_100: s2.to_set + to_set_1000: s3.to_set + to_set_arg_0: s0.to_set set_subclass + to_set_arg_10: s1.to_set set_subclass + to_set_arg_100: s2.to_set set_subclass + to_set_arg_1000: s3.to_set set_subclass diff --git a/benchmark/so_count_words.yml b/benchmark/so_count_words.yml index 99683505f927ac..f7322a8541d8cb 100644 --- a/benchmark/so_count_words.yml +++ b/benchmark/so_count_words.yml @@ -15,13 +15,13 @@ prelude: | Newsgroups: rec.games.roguelike.nethack X-Mailer: Mozilla 1.1N (Macintosh; I; 68K) - Hello there, Izchak Miller was my father. When I was younger I spent - many a night, hunched over the keyboard with a cup of tea, playing - nethack with him and my brother. my dad was a philosopher with a strong - weakness for fantasy/sci fi. I remember when he started to get involved - with the Nethack team- my brother's Dungeons and Dragons monster book - found a regular place beside my dad's desk. it's nice to see him living - on in the game he loved so much :-). + Hello there, Izchak Miller was my father. When I was younger I spent + many a night, hunched over the keyboard with a cup of tea, playing + nethack with him and my brother. my dad was a philosopher with a strong + weakness for fantasy/sci fi. I remember when he started to get involved + with the Nethack team- my brother's Dungeons and Dragons monster book + found a regular place beside my dad's desk. it's nice to see him living + on in the game he loved so much :-). Tamar Miller The following is a really long word of 5000 characters: @@ -38,8 +38,9 @@ prelude: | 13.times{ data << data } - open(wcinput, 'w'){|f| f.write data} + File.write(wcinput, data) end + at_exit {File.unlink(wcinput) rescue nil} end prepare_wc_input(wc_input_base) @@ -49,16 +50,16 @@ benchmark: # $Id: wc-ruby.code,v 1.4 2004/11/13 07:43:32 bfulgham Exp $ # http://www.bagley.org/~doug/shootout/ # with help from Paul Brannan - input = open(File.join(File.dirname($0), 'wc.input'), 'rb') nl = nw = nc = 0 - while true - tmp = input.read(4096) or break - data = tmp << (input.gets || "") - nc += data.length - nl += data.count("\n") - ((data.strip! || data).tr!("\n", " ") || data).squeeze! - nw += data.count(" ") + 1 + File.open(File.join(File.dirname($0), 'wc.input'), 'rb') do |input| + while tmp = input.read(4096) + data = tmp << (input.gets || "") + nc += data.length + nl += data.count("\n") + ((data.strip! || data).tr!("\n", " ") || data).squeeze! + nw += data.count(" ") + 1 + end end # STDERR.puts "#{nl} #{nw} #{nc}" diff --git a/benchmark/string_concat.yml b/benchmark/string_concat.yml index da14692f5ecc2c..f11f95ee9a7891 100644 --- a/benchmark/string_concat.yml +++ b/benchmark/string_concat.yml @@ -45,7 +45,7 @@ benchmark: "#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}" \ "#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}" \ "#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}#{CHUNK}" - interpolation_same_size_pool: | + interpolation_same_heap: | buffer = "#{SHORT}#{SHORT}" - interpolation_switching_size_pools: | + interpolation_switching_heaps: | buffer = "#{SHORT}#{LONG}" diff --git a/benchmark/string_dup.yml b/benchmark/string_dup.yml new file mode 100644 index 00000000000000..90793f9f2a8975 --- /dev/null +++ b/benchmark/string_dup.yml @@ -0,0 +1,7 @@ +prelude: | + # frozen_string_literal: true +benchmark: + uplus: | + +"A" + dup: | + "A".dup diff --git a/benchmark/string_fstring.yml b/benchmark/string_fstring.yml new file mode 100644 index 00000000000000..cafef1f3fea360 --- /dev/null +++ b/benchmark/string_fstring.yml @@ -0,0 +1,16 @@ +benchmark: + fstring_random: | + i = 0 + str = "same".dup + while i < 5_000_000 + -(i.to_s.freeze) + i += 1 + end + fstring_same: | + i = 0 + str = "same".dup + while i < 10_000_000 + -str + i += 1 + end +loop_count: 1 diff --git a/benchmark/string_gsub.yml b/benchmark/string_gsub.yml new file mode 100644 index 00000000000000..0f964337dd9613 --- /dev/null +++ b/benchmark/string_gsub.yml @@ -0,0 +1,43 @@ +prelude: | + # frozen_string_literal: true + STR = ((("a" * 31) + "<") * 1000).freeze + STR_UNICODE = ((("a" * 30) + "\u2028") * 1000).freeze + ESCAPED_CHARS_BINARY = { + "\u2028".b => '\u2028'.b, + "\u2029".b => '\u2029'.b, + ">".b => '\u003e'.b.freeze, + "<".b => '\u003c'.b.freeze, + "&".b => '\u0026'.b.freeze, + } + BINARY_PATTERN = Regexp.union(ESCAPED_CHARS_BINARY.keys) + + ESCAPED_CHARS = { + "\u2028" => '\u2028', + "\u2029" => '\u2029', + ">" => '\u003e', + "<" => '\u003c', + "&" => '\u0026', + } + ESCAPE_PATTERN = Regexp.union(ESCAPED_CHARS.keys) + + +benchmark: + escape: | + str = STR.dup + str.gsub!(ESCAPE_PATTERN, ESCAPED_CHARS) + str + + escape_bin: | + str = STR.b + str.gsub!(BINARY_PATTERN, ESCAPED_CHARS_BINARY) + str.force_encoding(Encoding::UTF_8) + + escape_utf8: | + str = STR_UNICODE.dup + str.gsub!(ESCAPE_PATTERN, ESCAPED_CHARS) + str + + escape_utf8_bin: | + str = STR_UNICODE.b + str.gsub!(BINARY_PATTERN, ESCAPED_CHARS_BINARY) + str.force_encoding(Encoding::UTF_8) diff --git a/benchmark/struct_accessor.yml b/benchmark/struct_accessor.yml new file mode 100644 index 00000000000000..61176cfdd48d3a --- /dev/null +++ b/benchmark/struct_accessor.yml @@ -0,0 +1,25 @@ +prelude: | + C = Struct.new(:x) do + class_eval <<-END + def r + #{'x;'*256} + end + def w + #{'self.x = nil;'*256} + end + def rm + m = method(:x) + #{'m.call;'*256} + end + def wm + m = method(:x=) + #{'m.call(nil);'*256} + end + END + end + obj = C.new(nil) +benchmark: + member_reader: "obj.r" + member_writer: "obj.w" + member_reader_method: "obj.rm" + member_writer_method: "obj.wm" diff --git a/benchmark/time_strftime.yml b/benchmark/time_strftime.yml new file mode 100644 index 00000000000000..28f62aec87a20d --- /dev/null +++ b/benchmark/time_strftime.yml @@ -0,0 +1,7 @@ +prelude: | + # frozen_string_literal: true + time = Time.now +benchmark: + - time.strftime("%FT%T") # 19B + - time.strftime("%FT%T.%3N") # 23B + - time.strftime("%FT%T.%6N") # 26B diff --git a/benchmark/time_xmlschema.yml b/benchmark/time_xmlschema.yml new file mode 100644 index 00000000000000..654e5cfcbc3bcd --- /dev/null +++ b/benchmark/time_xmlschema.yml @@ -0,0 +1,27 @@ +prelude: | + # frozen_string_literal + unless Time.method_defined?(:xmlschema) + class Time + def xmlschema(fraction_digits=0) + fraction_digits = fraction_digits.to_i + s = strftime("%FT%T") + if fraction_digits > 0 + s << strftime(".%#{fraction_digits}N") + end + s << (utc? ? 'Z' : strftime("%:z")) + end + end + end + time = Time.now + utc_time = Time.now.utc + fraction_sec = Time.at(123456789.quo(9999999999)).getlocal("+09:00") + future_time = Time.utc(10000) +benchmark: + - time.xmlschema + - utc_time.xmlschema + - time.xmlschema(6) + - utc_time.xmlschema(6) + - time.xmlschema(9) + - utc_time.xmlschema(9) + - fraction_sec.xmlschema(10) + - future_time.xmlschema diff --git a/benchmark/vm_call_kw_and_kw_splat.yml b/benchmark/vm_call_kw_and_kw_splat.yml new file mode 100644 index 00000000000000..aa6e549e0c4224 --- /dev/null +++ b/benchmark/vm_call_kw_and_kw_splat.yml @@ -0,0 +1,25 @@ +prelude: | + h1, h10, h100, h1000 = [1, 10, 100, 1000].map do |n| + h = {kw: 1} + n.times{|i| h[i.to_s.to_sym] = i} + h + end + eh = {} + def kw(kw: nil, **kws) end +benchmark: + 1: | + kw(**h1) + 1_mutable: | + kw(**eh, **h1) + 10: | + kw(**h10) + 10_mutable: | + kw(**eh, **h10) + 100: | + kw(**h100) + 100_mutable: | + kw(**eh, **h100) + 1000: | + kw(**h1000) + 1000_mutable: | + kw(**eh, **h1000) diff --git a/benchmark/vm_ivar_ic_miss.yml b/benchmark/vm_ivar_ic_miss.yml new file mode 100644 index 00000000000000..944fb1a9e6d38e --- /dev/null +++ b/benchmark/vm_ivar_ic_miss.yml @@ -0,0 +1,20 @@ +prelude: | + class Foo + def initialize diverge + if diverge + @a = 1 + end + + @a0 = @a1 = @a2 = @a3 = @a4 = @a5 = @a6 = @a7 = @a8 = @a9 = @a10 = @a11 = @a12 = @a13 = @a14 = @a15 = @a16 = @a17 = @a18 = @a19 = @a20 = @a21 = @a22 = @a23 = @a24 = @a25 = @a26 = @a27 = @a28 = @a29 = @a30 = @a31 = @a32 = @a33 = @a34 = @a35 = @a36 = @a37 = @a38 = @a39 = @a40 = @a41 = @a42 = @a43 = @a44 = @a45 = @a46 = @a47 = @a48 = @a49 = @a50 = @a51 = @a52 = @a53 = @a54 = @a55 = @a56 = @a57 = @a58 = @a59 = @a60 = @a61 = @a62 = @a63 = @a64 = @a65 = @a66 = @a67 = @a68 = @a69 = @a70 = @a71 = @a72 = @a73 = @a74 = @b = 1 + end + + def b; @b; end + end + + a = Foo.new false + b = Foo.new true +benchmark: + vm_ivar_ic_miss: | + a.b + b.b +loop_count: 30000000 diff --git a/benchmark/vm_ivar_memoize.yml b/benchmark/vm_ivar_memoize.yml new file mode 100644 index 00000000000000..90f6b07f05de41 --- /dev/null +++ b/benchmark/vm_ivar_memoize.yml @@ -0,0 +1,85 @@ +prelude: | + IVARS = 60 + class Record + def initialize(offset = false) + @offset = 1 if offset + @first = 0 + IVARS.times do |i| + instance_variable_set("@ivar_#{i}", i) + end + end + + def first + @first + end + + def lazy_set + @lazy_set ||= 123 + end + + def undef + @undef + end + end + + Record.new # Need one alloc to right size + + BASE = Record.new + LAZY = Record.new + LAZY.lazy_set + + class Miss < Record + @first = 0 + IVARS.times do |i| + instance_variable_set("@i_#{i}", i) + end + end + + Miss.new # Need one alloc to right size + MISS = Miss.new + + DIVERGENT = Record.new(true) + +benchmark: + vm_ivar_stable_shape: | + BASE.first + BASE.first + BASE.first + BASE.first + BASE.first + BASE.first + vm_ivar_memoize_unstable_shape: | + BASE.first + LAZY.first + BASE.first + LAZY.first + BASE.first + LAZY.first + vm_ivar_memoize_unstable_shape_miss: | + BASE.first + MISS.first + BASE.first + MISS.first + BASE.first + MISS.first + vm_ivar_unstable_undef: | + BASE.undef + LAZY.undef + BASE.undef + LAZY.undef + BASE.undef + LAZY.undef + vm_ivar_divergent_shape: | + BASE.first + DIVERGENT.first + BASE.first + DIVERGENT.first + BASE.first + DIVERGENT.first + vm_ivar_divergent_shape_imbalanced: | + BASE.first + DIVERGENT.first + DIVERGENT.first + DIVERGENT.first + DIVERGENT.first + DIVERGENT.first diff --git a/benchmark/vm_method_splat_calls.yml b/benchmark/vm_method_splat_calls.yml new file mode 100644 index 00000000000000..f2f366e99ca8d3 --- /dev/null +++ b/benchmark/vm_method_splat_calls.yml @@ -0,0 +1,13 @@ +prelude: | + def f(x=0, y: 0) end + a = [1] + ea = [] + kw = {y: 1} + b = lambda{} +benchmark: + arg_splat: "f(1, *ea)" + arg_splat_block: "f(1, *ea, &b)" + splat_kw_splat: "f(*a, **kw)" + splat_kw_splat_block: "f(*a, **kw, &b)" + splat_kw: "f(*a, y: 1)" + splat_kw_block: "f(*a, y: 1, &b)" diff --git a/benchmark/vm_method_splat_calls2.yml b/benchmark/vm_method_splat_calls2.yml new file mode 100644 index 00000000000000..d33dcd7e8b91e1 --- /dev/null +++ b/benchmark/vm_method_splat_calls2.yml @@ -0,0 +1,27 @@ +prelude: | + def named_arg_splat(*a) end + def named_arg_kw_splat(*a, **kw) end + def anon_arg_splat(*) end + def anon_kw_splat(**) end + def anon_arg_kw_splat(*, **) end + def anon_fw_to_named(*, **) named_arg_kw_splat(*, **) end + def fw_to_named(...) named_arg_kw_splat(...) end + def fw_to_anon_to_named(...) anon_fw_to_named(...) end + def fw_no_kw(...) named_arg_splat(...) end + a = [1] + kw = {y: 1} +benchmark: + named_multi_arg_splat: "named_arg_splat(*a, *a)" + named_post_splat: "named_arg_splat(*a, a)" + anon_arg_splat: "anon_arg_splat(*a)" + anon_arg_kw_splat: "anon_arg_kw_splat(*a, **kw)" + anon_multi_arg_splat: "anon_arg_splat(*a, *a)" + anon_post_splat: "anon_arg_splat(*a, a)" + anon_kw_splat: "anon_kw_splat(**kw)" + anon_fw_to_named_splat: "anon_fw_to_named(*a, **kw)" + anon_fw_to_named_no_splat: "anon_fw_to_named(1, y: 1)" + fw_to_named_splat: "fw_to_named(*a, **kw)" + fw_to_named_no_splat: "fw_to_named(1, y: 1)" + fw_to_anon_to_named_splat: "fw_to_anon_to_named(*a, **kw)" + fw_to_anon_to_named_no_splat: "fw_to_anon_to_named(1, y: 1)" + fw_no_kw: "fw_no_kw(1, 2)" diff --git a/benchmark/vm_super_splat_calls.yml b/benchmark/vm_super_splat_calls.yml new file mode 100644 index 00000000000000..795e44e4da4c25 --- /dev/null +++ b/benchmark/vm_super_splat_calls.yml @@ -0,0 +1,25 @@ +prelude: | + @a = [1].freeze + @ea = [].freeze + @kw = {y: 1}.freeze + @b = lambda{} + extend(Module.new{def arg_splat(x=0, y: 0) end}) + extend(Module.new{def arg_splat_block(x=0, y: 0) end}) + extend(Module.new{def splat_kw_splat(x=0, y: 0) end}) + extend(Module.new{def splat_kw_splat_block(x=0, y: 0) end}) + extend(Module.new{def splat_kw(x=0, y: 0) end}) + extend(Module.new{def splat_kw_block(x=0, y: 0) end}) + + extend(Module.new{def arg_splat; super(1, *@ea) end}) + extend(Module.new{def arg_splat_block; super(1, *@ea, &@b) end}) + extend(Module.new{def splat_kw_splat; super(*@a, **@kw) end}) + extend(Module.new{def splat_kw_splat_block; super(*@a, **@kw, &@b) end}) + extend(Module.new{def splat_kw; super(*@a, y: 1) end}) + extend(Module.new{def splat_kw_block; super(*@a, y: 1, &@b) end}) +benchmark: + arg_splat: "arg_splat" + arg_splat_block: "arg_splat_block" + splat_kw_splat: "splat_kw_splat" + splat_kw_splat_block: "splat_kw_splat_block" + splat_kw: "splat_kw" + splat_kw_block: "splat_kw_block" diff --git a/benchmark/vm_zsuper_splat_calls.yml b/benchmark/vm_zsuper_splat_calls.yml new file mode 100644 index 00000000000000..82dc22349d4a24 --- /dev/null +++ b/benchmark/vm_zsuper_splat_calls.yml @@ -0,0 +1,28 @@ +prelude: | + a = [1].freeze + ea = [].freeze + kw = {y: 1}.freeze + b = lambda{} + extend(Module.new{def arg_splat(x=0, y: 0) end}) + extend(Module.new{def arg_splat_block(x=0, y: 0) end}) + extend(Module.new{def arg_splat_post(x=0, y: 0) end}) + extend(Module.new{def splat_kw_splat(x=0, y: 0) end}) + extend(Module.new{def splat_kw_splat_block(x=0, y: 0) end}) + extend(Module.new{def splat_kw(x=0, y: 0) end}) + extend(Module.new{def splat_kw_block(x=0, y: 0) end}) + + extend(Module.new{def arg_splat(x, *a) super end}) + extend(Module.new{def arg_splat_block(x, *a, &b) super end}) + extend(Module.new{def arg_splat_post(*a, x) super end}) + extend(Module.new{def splat_kw_splat(*a, **kw) super end}) + extend(Module.new{def splat_kw_splat_block(*a, **kw, &b) super end}) + extend(Module.new{def splat_kw(*a, y: 1) super end}) + extend(Module.new{def splat_kw_block(*a, y: 1, &b) super end}) +benchmark: + arg_splat: "arg_splat(1, *ea)" + arg_splat_block: "arg_splat_block(1, *ea, &b)" + arg_splat_post: "arg_splat_post(1, *ea, &b)" + splat_kw_splat: "splat_kw_splat(*a, **kw)" + splat_kw_splat_block: "splat_kw_splat_block(*a, **kw, &b)" + splat_kw: "splat_kw(*a, y: 1)" + splat_kw_block: "splat_kw_block(*a, y: 1, &b)" diff --git a/bignum.c b/bignum.c index e9bf37d2060ea7..fb4714307e6375 100644 --- a/bignum.c +++ b/bignum.c @@ -30,9 +30,6 @@ # define USE_GMP 0 #endif #endif -#if USE_GMP -# include -#endif #include "id.h" #include "internal.h" @@ -48,6 +45,15 @@ #include "ruby/util.h" #include "ruby_assert.h" +#if USE_GMP +RBIMPL_WARNING_PUSH() +# ifdef _MSC_VER +RBIMPL_WARNING_IGNORED(4146) /* for mpn_neg() */ +# endif +# include +RBIMPL_WARNING_POP() +#endif + static const bool debug_integer_pack = ( #ifdef DEBUG_INTEGER_PACK DEBUG_INTEGER_PACK+0 @@ -349,7 +355,7 @@ maxpow_in_bdigit_dbl(int base, int *exp_ret) BDIGIT_DBL maxpow; int exponent; - assert(2 <= base && base <= 36); + RUBY_ASSERT(2 <= base && base <= 36); { #if SIZEOF_BDIGIT_DBL == 2 @@ -381,7 +387,7 @@ maxpow_in_bdigit_dbl(int base, int *exp_ret) static inline BDIGIT_DBL bary2bdigitdbl(const BDIGIT *ds, size_t n) { - assert(n <= 2); + RUBY_ASSERT(n <= 2); if (n == 2) return ds[0] | BIGUP(ds[1]); @@ -393,7 +399,7 @@ bary2bdigitdbl(const BDIGIT *ds, size_t n) static inline void bdigitdbl2bary(BDIGIT *ds, size_t n, BDIGIT_DBL num) { - assert(n == 2); + RUBY_ASSERT(n == 2); ds[0] = BIGLO(num); ds[1] = (BDIGIT)BIGDN(num); @@ -424,7 +430,7 @@ bary_small_lshift(BDIGIT *zds, const BDIGIT *xds, size_t n, int shift) { size_t i; BDIGIT_DBL num = 0; - assert(0 <= shift && shift < BITSPERDIG); + RUBY_ASSERT(0 <= shift && shift < BITSPERDIG); for (i=0; i yn) { const BDIGIT *tds; @@ -1476,7 +1482,7 @@ bary_mul_single(BDIGIT *zds, size_t zn, BDIGIT x, BDIGIT y) { BDIGIT_DBL n; - assert(2 <= zn); + RUBY_ASSERT(2 <= zn); n = (BDIGIT_DBL)x * y; bdigitdbl2bary(zds, 2, n); @@ -1490,7 +1496,7 @@ bary_muladd_1xN(BDIGIT *zds, size_t zn, BDIGIT x, const BDIGIT *yds, size_t yn) BDIGIT_DBL dd; size_t j; - assert(zn > yn); + RUBY_ASSERT(zn > yn); if (x == 0) return 0; @@ -1525,7 +1531,7 @@ bigdivrem_mulsub(BDIGIT *zds, size_t zn, BDIGIT x, const BDIGIT *yds, size_t yn) BDIGIT_DBL t2; BDIGIT_DBL_SIGNED num; - assert(zn == yn + 1); + RUBY_ASSERT(zn == yn + 1); num = 0; t2 = 0; @@ -1550,7 +1556,7 @@ bary_mulsub_1xN(BDIGIT *zds, size_t zn, BDIGIT x, const BDIGIT *yds, size_t yn) { BDIGIT_DBL_SIGNED num; - assert(zn == yn + 1); + RUBY_ASSERT(zn == yn + 1); num = bigdivrem_mulsub(zds, zn, x, yds, yn); zds[yn] = BIGLO(num); @@ -1564,7 +1570,7 @@ bary_mul_normal(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const BDIG { size_t i; - assert(xn + yn <= zn); + RUBY_ASSERT(xn + yn <= zn); BDIGITS_ZERO(zds, zn); for (i = 0; i < xn; i++) { @@ -1595,7 +1601,7 @@ bary_sq_fast(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn) BDIGIT vl; int vh; - assert(xn * 2 <= zn); + RUBY_ASSERT(xn * 2 <= zn); BDIGITS_ZERO(zds, zn); @@ -1667,9 +1673,9 @@ bary_mul_balance_with_mulfunc(BDIGIT *const zds, const size_t zn, VALUE work = 0; size_t n; - assert(xn + yn <= zn); - assert(xn <= yn); - assert(!KARATSUBA_BALANCED(xn, yn) || !TOOM3_BALANCED(xn, yn)); + RUBY_ASSERT(xn + yn <= zn); + RUBY_ASSERT(xn <= yn); + RUBY_ASSERT(!KARATSUBA_BALANCED(xn, yn) || !TOOM3_BALANCED(xn, yn)); BDIGITS_ZERO(zds, xn); @@ -1751,9 +1757,9 @@ bary_mul_karatsuba(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const B const BDIGIT *xds0, *xds1, *yds0, *yds1; BDIGIT *zds0, *zds1, *zds2, *zds3; - assert(xn + yn <= zn); - assert(xn <= yn); - assert(yn < 2 * xn); + RUBY_ASSERT(xn + yn <= zn); + RUBY_ASSERT(xn <= yn); + RUBY_ASSERT(yn < 2 * xn); sq = xds == yds && xn == yn; @@ -1768,7 +1774,7 @@ bary_mul_karatsuba(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const B n = yn / 2; - assert(n < xn); + RUBY_ASSERT(n < xn); if (wn < n) { /* This function itself needs only n BDIGITs for work area. @@ -1889,7 +1895,7 @@ bary_mul_karatsuba(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const B for (x = 0, i = xn-1; 0 <= i; i--) { x <<= SIZEOF_BDIGIT*CHAR_BIT; x |= xds[i]; } for (y = 0, i = yn-1; 0 <= i; i--) { y <<= SIZEOF_BDIGIT*CHAR_BIT; y |= yds[i]; } for (z = 0, i = zn-1; 0 <= i; i--) { z <<= SIZEOF_BDIGIT*CHAR_BIT; z |= zds[i]; } - assert(z == x * y); + RUBY_ASSERT(z == x * y); } */ @@ -1957,11 +1963,11 @@ bary_mul_toom3(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const BDIGI int sq = xds == yds && xn == yn; - assert(xn <= yn); /* assume y >= x */ - assert(xn + yn <= zn); + RUBY_ASSERT(xn <= yn); /* assume y >= x */ + RUBY_ASSERT(xn + yn <= zn); n = (yn + 2) / 3; - assert(2*n < xn); + RUBY_ASSERT(2*n < xn); wnc = 0; @@ -2148,19 +2154,19 @@ bary_mul_toom3(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const BDIGI /* z(1) : t1 <- u1 * v1 */ bary_mul_toom3_start(t1ds, t1n, u1ds, u1n, v1ds, v1n, wds, wn); t1p = u1p == v1p; - assert(t1ds[t1n-1] == 0); + RUBY_ASSERT(t1ds[t1n-1] == 0); t1n--; /* z(-1) : t2 <- u2 * v2 */ bary_mul_toom3_start(t2ds, t2n, u2ds, u2n, v2ds, v2n, wds, wn); t2p = u2p == v2p; - assert(t2ds[t2n-1] == 0); + RUBY_ASSERT(t2ds[t2n-1] == 0); t2n--; /* z(-2) : t3 <- u3 * v3 */ bary_mul_toom3_start(t3ds, t3n, u3ds, u3n, v3ds, v3n, wds, wn); t3p = u3p == v3p; - assert(t3ds[t3n-1] == 0); + RUBY_ASSERT(t3ds[t3n-1] == 0); t3n--; /* z(inf) : t4 <- x2 * y2 */ @@ -2336,7 +2342,7 @@ bary_mul_gmp(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const BDIGIT mpz_t x, y, z; size_t count; - assert(xn + yn <= zn); + RUBY_ASSERT(xn + yn <= zn); mpz_init(x); mpz_init(y); @@ -2371,7 +2377,7 @@ rb_big_mul_gmp(VALUE x, VALUE y) static void bary_short_mul(BDIGIT *zds, size_t zn, const BDIGIT *xds, size_t xn, const BDIGIT *yds, size_t yn) { - assert(xn + yn <= zn); + RUBY_ASSERT(xn + yn <= zn); if (xn == 1 && yn == 1) { bary_mul_single(zds, zn, xds[0], yds[0]); @@ -2407,7 +2413,7 @@ bary_mul_precheck(BDIGIT **zdsp, size_t *znp, const BDIGIT **xdsp, size_t *xnp, const BDIGIT *yds = *ydsp; size_t yn = *ynp; - assert(xn + yn <= zn); + RUBY_ASSERT(xn + yn <= zn); nlsz = 0; @@ -2456,7 +2462,7 @@ bary_mul_precheck(BDIGIT **zdsp, size_t *znp, const BDIGIT **xdsp, size_t *xnp, tds = xds; xds = yds; yds = tds; tn = xn; xn = yn; yn = tn; } - assert(xn <= yn); + RUBY_ASSERT(xn <= yn); if (xn <= 1) { if (xn == 0) { @@ -2639,8 +2645,8 @@ rb_big_stop(void *ptr) static BDIGIT bigdivrem_single1(BDIGIT *qds, const BDIGIT *xds, size_t xn, BDIGIT x_higher_bdigit, BDIGIT y) { - assert(0 < xn); - assert(x_higher_bdigit < y); + RUBY_ASSERT(0 < xn); + RUBY_ASSERT(x_higher_bdigit < y); if (POW2_P(y)) { BDIGIT r; r = xds[0] & (y-1); @@ -2672,9 +2678,9 @@ bigdivrem_restoring(BDIGIT *zds, size_t zn, BDIGIT *yds, size_t yn) struct big_div_struct bds; size_t ynzero; - assert(yn < zn); - assert(BDIGIT_MSB(yds[yn-1])); - assert(zds[zn-1] < yds[yn-1]); + RUBY_ASSERT(yn < zn); + RUBY_ASSERT(BDIGIT_MSB(yds[yn-1])); + RUBY_ASSERT(zds[zn-1] < yds[yn-1]); for (ynzero = 0; !yds[ynzero]; ynzero++); @@ -2693,7 +2699,7 @@ bigdivrem_restoring(BDIGIT *zds, size_t zn, BDIGIT *yds, size_t yn) if (bds.zn > 10000 || bds.yn > 10000) { retry: bds.stop = Qfalse; - rb_nogvl(bigdivrem1, &bds, rb_big_stop, &bds, RB_NOGVL_UBF_ASYNC_SAFE); + rb_nogvl(bigdivrem1, &bds, rb_big_stop, &bds, RB_NOGVL_UBF_ASYNC_SAFE | RB_NOGVL_OFFLOAD_SAFE); if (bds.stop == Qtrue) { /* execute trap handler, but exception was not raised. */ @@ -2713,9 +2719,9 @@ bary_divmod_normal(BDIGIT *qds, size_t qn, BDIGIT *rds, size_t rn, const BDIGIT size_t zn; VALUE tmpyz = 0; - assert(yn < xn || (xn == yn && yds[yn - 1] <= xds[xn - 1])); - assert(qds ? (xn - yn + 1) <= qn : 1); - assert(rds ? yn <= rn : 1); + RUBY_ASSERT(yn < xn || (xn == yn && yds[yn - 1] <= xds[xn - 1])); + RUBY_ASSERT(qds ? (xn - yn + 1) <= qn : 1); + RUBY_ASSERT(rds ? yn <= rn : 1); zn = xn + BIGDIVREM_EXTRA_WORDS; @@ -2807,10 +2813,10 @@ bary_divmod_gmp(BDIGIT *qds, size_t qn, BDIGIT *rds, size_t rn, const BDIGIT *xd mpz_t x, y, q, r; size_t count; - assert(yn < xn || (xn == yn && yds[yn - 1] <= xds[xn - 1])); - assert(qds ? (xn - yn + 1) <= qn : 1); - assert(rds ? yn <= rn : 1); - assert(qds || rds); + RUBY_ASSERT(yn < xn || (xn == yn && yds[yn - 1] <= xds[xn - 1])); + RUBY_ASSERT(qds ? (xn - yn + 1) <= qn : 1); + RUBY_ASSERT(rds ? yn <= rn : 1); + RUBY_ASSERT(qds || rds); mpz_init(x); mpz_init(y); @@ -2896,8 +2902,8 @@ bary_divmod_branch(BDIGIT *qds, size_t qn, BDIGIT *rds, size_t rn, const BDIGIT static void bary_divmod(BDIGIT *qds, size_t qn, BDIGIT *rds, size_t rn, const BDIGIT *xds, size_t xn, const BDIGIT *yds, size_t yn) { - assert(xn <= qn); - assert(yn <= rn); + RUBY_ASSERT(xn <= qn); + RUBY_ASSERT(yn <= rn); BARY_TRUNC(yds, yn); if (yn == 0) @@ -3432,8 +3438,8 @@ rb_absint_numwords(VALUE val, size_t word_numbits, size_t *nlz_bits_ret) if (debug_integer_pack) { size_t numwords0, nlz_bits0; numwords0 = absint_numwords_generic(numbytes, nlz_bits_in_msbyte, word_numbits, &nlz_bits0); - assert(numwords0 == numwords); - assert(nlz_bits0 == nlz_bits); + RUBY_ASSERT(numwords0 == numwords); + RUBY_ASSERT(nlz_bits0 == nlz_bits); (void)numwords0; } } @@ -3848,7 +3854,7 @@ str2big_poweroftwo( if (numbits) { *dp++ = BIGLO(dd); } - assert((size_t)(dp - BDIGITS(z)) == num_bdigits); + RUBY_ASSERT((size_t)(dp - BDIGITS(z)) == num_bdigits); return z; } @@ -3891,7 +3897,7 @@ str2big_normal( } break; } - assert(blen <= num_bdigits); + RUBY_ASSERT(blen <= num_bdigits); } return z; @@ -3949,7 +3955,7 @@ str2big_karatsuba( current_base = 1; } } - assert(i == num_bdigits); + RUBY_ASSERT(i == num_bdigits); for (unit = 2; unit < num_bdigits; unit *= 2) { for (i = 0; i < num_bdigits; i += unit*2) { if (2*unit <= num_bdigits - i) { @@ -4094,8 +4100,8 @@ rb_int_parse_cstr(const char *str, ssize_t len, char **endp, size_t *ndigits, len -= (n); \ } while (0) #define ASSERT_LEN() do {\ - assert(len != 0); \ - if (len0 >= 0) assert(s + len0 == str + len); \ + RUBY_ASSERT(len != 0); \ + if (len0 >= 0) RUBY_ASSERT(s + len0 == str + len); \ } while (0) if (!str) { @@ -4640,8 +4646,8 @@ big_shift2(VALUE x, int lshift_p, VALUE y) size_t shift_numdigits; int shift_numbits; - assert(POW2_P(CHAR_BIT)); - assert(POW2_P(BITSPERDIG)); + RUBY_ASSERT(POW2_P(CHAR_BIT)); + RUBY_ASSERT(POW2_P(BITSPERDIG)); if (BIGZEROP(x)) return INT2FIX(0); @@ -4728,7 +4734,7 @@ power_cache_get_power(int base, int power_level, size_t *numdigits_ret) rb_obj_hide(power); base36_power_cache[base - 2][power_level] = power; base36_numdigits_cache[base - 2][power_level] = numdigits; - rb_gc_register_mark_object(power); + rb_vm_register_global_object(power); } if (numdigits_ret) *numdigits_ret = base36_numdigits_cache[base - 2][power_level]; @@ -4764,7 +4770,7 @@ big2str_2bdigits(struct big2str_struct *b2s, BDIGIT *xds, size_t xn, size_t tail int beginning = !b2s->ptr; size_t len = 0; - assert(xn <= 2); + RUBY_ASSERT(xn <= 2); num = bary2bdigitdbl(xds, xn); if (beginning) { @@ -4892,7 +4898,7 @@ big2str_karatsuba(struct big2str_struct *b2s, BDIGIT *xds, size_t xn, size_t wn, /* bigdivrem_restoring will modify y. * So use temporary buffer. */ tds = xds + qn; - assert(qn + bn <= xn + wn); + RUBY_ASSERT(qn + bn <= xn + wn); bary_small_lshift(tds, bds, bn, shift); xds[xn] = bary_small_lshift(xds, xds, xn, shift); } @@ -4910,7 +4916,7 @@ big2str_karatsuba(struct big2str_struct *b2s, BDIGIT *xds, size_t xn, size_t wn, } BARY_TRUNC(qds, qn); - assert(qn <= bn); + RUBY_ASSERT(qn <= bn); big2str_karatsuba(b2s, qds, qn, xn+wn - (rn+qn), lower_power_level, lower_numdigits+taillen); BARY_TRUNC(rds, rn); big2str_karatsuba(b2s, rds, rn, xn+wn - rn, lower_power_level, taillen); @@ -4975,7 +4981,7 @@ big2str_generic(VALUE x, int base) invalid_radix(base); if (xn >= LONG_MAX/BITSPERDIG) { - rb_raise(rb_eRangeError, "bignum too big to convert into `string'"); + rb_raise(rb_eRangeError, "bignum too big to convert into 'string'"); } power_level = 0; @@ -4985,7 +4991,7 @@ big2str_generic(VALUE x, int base) power_level++; power = power_cache_get_power(base, power_level, NULL); } - assert(power_level != MAX_BASE36_POWER_TABLE_ENTRIES); + RUBY_ASSERT(power_level != MAX_BASE36_POWER_TABLE_ENTRIES); if ((size_t)BIGNUM_LEN(power) <= xn) { /* @@ -5100,7 +5106,7 @@ rb_big2str1(VALUE x, int base) invalid_radix(base); if (xn >= LONG_MAX/BITSPERDIG) { - rb_raise(rb_eRangeError, "bignum too big to convert into `string'"); + rb_raise(rb_eRangeError, "bignum too big to convert into 'string'"); } if (POW2_P(base)) { @@ -5136,7 +5142,7 @@ big2ulong(VALUE x, const char *type) if (len == 0) return 0; if (BIGSIZE(x) > sizeof(long)) { - rb_raise(rb_eRangeError, "bignum too big to convert into `%s'", type); + rb_raise(rb_eRangeError, "bignum too big to convert into '%s'", type); } ds = BDIGITS(x); #if SIZEOF_LONG <= SIZEOF_BDIGIT @@ -5179,7 +5185,7 @@ rb_big2long(VALUE x) if (num <= 1+(unsigned long)(-(LONG_MIN+1))) return -(long)(num-1)-1; } - rb_raise(rb_eRangeError, "bignum too big to convert into `long'"); + rb_raise(rb_eRangeError, "bignum too big to convert into 'long'"); } #if HAVE_LONG_LONG @@ -5197,7 +5203,7 @@ big2ull(VALUE x, const char *type) if (len == 0) return 0; if (BIGSIZE(x) > SIZEOF_LONG_LONG) - rb_raise(rb_eRangeError, "bignum too big to convert into `%s'", type); + rb_raise(rb_eRangeError, "bignum too big to convert into '%s'", type); #if SIZEOF_LONG_LONG <= SIZEOF_BDIGIT num = (unsigned LONG_LONG)ds[0]; #else @@ -5238,7 +5244,7 @@ rb_big2ll(VALUE x) if (num <= 1+(unsigned LONG_LONG)(-(LLONG_MIN+1))) return -(LONG_LONG)(num-1)-1; } - rb_raise(rb_eRangeError, "bignum too big to convert into `long long'"); + rb_raise(rb_eRangeError, "bignum too big to convert into 'long long'"); } #endif /* HAVE_LONG_LONG */ @@ -5501,10 +5507,10 @@ big_op(VALUE x, VALUE y, enum big_op_t op) n = FIX2INT(rel); switch (op) { - case big_op_gt: return RBOOL(n > 0); - case big_op_ge: return RBOOL(n >= 0); - case big_op_lt: return RBOOL(n < 0); - case big_op_le: return RBOOL(n <= 0); + case big_op_gt: return RBOOL(n > 0); + case big_op_ge: return RBOOL(n >= 0); + case big_op_lt: return RBOOL(n < 0); + case big_op_le: return RBOOL(n <= 0); } return Qundef; } @@ -5660,7 +5666,7 @@ bigsub_int(VALUE x, long y0) zds = BDIGITS(z); #if SIZEOF_BDIGIT >= SIZEOF_LONG - assert(xn == zn); + RUBY_ASSERT(xn == zn); num = (BDIGIT_DBL_SIGNED)xds[0] - y; if (xn == 1 && num < 0) { BIGNUM_NEGATE(z); @@ -5723,7 +5729,7 @@ bigsub_int(VALUE x, long y0) goto finish; finish: - assert(num == 0 || num == -1); + RUBY_ASSERT(num == 0 || num == -1); if (num < 0) { get2comp(z); BIGNUM_NEGATE(z); @@ -5908,6 +5914,8 @@ bigsq(VALUE x) BDIGIT *xds, *zds; xn = BIGNUM_LEN(x); + if (MUL_OVERFLOW_LONG_P(2, xn)) + rb_raise(rb_eArgError, "square overflow"); zn = 2 * xn; z = bignew(zn, 1); @@ -5936,6 +5944,8 @@ bigmul0(VALUE x, VALUE y) xn = BIGNUM_LEN(x); yn = BIGNUM_LEN(y); + if (ADD_OVERFLOW_LONG_P(xn, yn)) + rb_raise(rb_eArgError, "multiplication overflow"); zn = xn + yn; z = bignew(zn, BIGNUM_SIGN(x)==BIGNUM_SIGN(y)); @@ -6281,8 +6291,7 @@ rb_big_pow(VALUE x, VALUE y) y = bignorm(y); if (FIXNUM_P(y)) goto again; - rb_warn("in a**b, b may be too big"); - d = rb_big2dbl(y); + rb_raise(rb_eArgError, "exponent is too large"); } else if (FIXNUM_P(y)) { yy = FIX2LONG(y); @@ -6298,13 +6307,17 @@ rb_big_pow(VALUE x, VALUE y) VALUE z = 0; SIGNED_VALUE mask; const size_t xbits = rb_absint_numwords(x, 1, NULL); - const size_t BIGLEN_LIMIT = 32*1024*1024; +#if SIZEOF_SIZE_T == 4 + const size_t BIGLEN_LIMIT = 1ULL << 31; // 2 GB +#else // SIZEOF_SIZE_T == 8 + const size_t BIGLEN_LIMIT = 1ULL << 34; // 16 GB +#endif if (xbits == (size_t)-1 || (xbits > BIGLEN_LIMIT) || + MUL_OVERFLOW_LONG_P(yy, xbits) || (xbits * yy > BIGLEN_LIMIT)) { - rb_warn("in a**b, b may be too big"); - d = (double)yy; + rb_raise(rb_eArgError, "exponent is too large"); } else { for (mask = FIXNUM_MAX + 1; mask; mask >>= 1) { @@ -6878,63 +6891,11 @@ BDIGIT rb_bdigit_dbl_isqrt(BDIGIT_DBL); # define BDIGIT_DBL_TO_DOUBLE(n) (double)(n) #endif -static BDIGIT * -estimate_initial_sqrt(VALUE *xp, const size_t xn, const BDIGIT *nds, size_t len) -{ - enum {dbl_per_bdig = roomof(DBL_MANT_DIG,BITSPERDIG)}; - const int zbits = nlz(nds[len-1]); - VALUE x = *xp = bignew_1(0, xn, 1); /* division may release the GVL */ - BDIGIT *xds = BDIGITS(x); - BDIGIT_DBL d = bary2bdigitdbl(nds+len-dbl_per_bdig, dbl_per_bdig); - BDIGIT lowbits = 1; - int rshift = (int)((BITSPERDIG*2-zbits+(len&BITSPERDIG&1) - DBL_MANT_DIG + 1) & ~1); - double f; - - if (rshift > 0) { - lowbits = (BDIGIT)d & ~(~(BDIGIT)1U << rshift); - d >>= rshift; - } - else if (rshift < 0) { - d <<= -rshift; - d |= nds[len-dbl_per_bdig-1] >> (BITSPERDIG+rshift); - } - f = sqrt(BDIGIT_DBL_TO_DOUBLE(d)); - d = (BDIGIT_DBL)ceil(f); - if (BDIGIT_DBL_TO_DOUBLE(d) == f) { - if (lowbits || (lowbits = !bary_zero_p(nds, len-dbl_per_bdig))) - ++d; - } - else { - lowbits = 1; - } - rshift /= 2; - rshift += (2-(len&1))*BITSPERDIG/2; - if (rshift >= 0) { - if (nlz((BDIGIT)d) + rshift >= BITSPERDIG) { - /* (d << rshift) does cause overflow. - * example: Integer.sqrt(0xffff_ffff_ffff_ffff ** 2) - */ - d = ~(BDIGIT_DBL)0; - } - else { - d <<= rshift; - } - } - BDIGITS_ZERO(xds, xn-2); - bdigitdbl2bary(&xds[xn-2], 2, d); - - if (!lowbits) return NULL; /* special case, exact result */ - return xds; -} - VALUE rb_big_isqrt(VALUE n) { BDIGIT *nds = BDIGITS(n); size_t len = BIGNUM_LEN(n); - size_t xn = (len+1) / 2; - VALUE x; - BDIGIT *xds; if (len <= 2) { BDIGIT sq = rb_bdigit_dbl_isqrt(bary2bdigitdbl(nds, len)); @@ -6944,25 +6905,19 @@ rb_big_isqrt(VALUE n) return ULONG2NUM(sq); #endif } - else if ((xds = estimate_initial_sqrt(&x, xn, nds, len)) != 0) { - size_t tn = xn + BIGDIVREM_EXTRA_WORDS; - VALUE t = bignew_1(0, tn, 1); - BDIGIT *tds = BDIGITS(t); - tn = BIGNUM_LEN(t); - - /* t = n/x */ - while (bary_divmod_branch(tds, tn, NULL, 0, nds, len, xds, xn), - bary_cmp(tds, tn, xds, xn) < 0) { - int carry; - BARY_TRUNC(tds, tn); - /* x = (x+t)/2 */ - carry = bary_add(xds, xn, xds, xn, tds, tn); - bary_small_rshift(xds, xds, xn, 1, carry); - tn = BIGNUM_LEN(t); + else { + size_t shift = FIX2LONG(rb_big_bit_length(n)) / 4; + VALUE n2 = rb_int_rshift(n, SIZET2NUM(2 * shift)); + VALUE x = FIXNUM_P(n2) ? LONG2FIX(rb_ulong_isqrt(FIX2ULONG(n2))) : rb_big_isqrt(n2); + /* x = (x+n/x)/2 */ + x = rb_int_plus(rb_int_lshift(x, SIZET2NUM(shift - 1)), rb_int_idiv(rb_int_rshift(n, SIZET2NUM(shift + 1)), x)); + VALUE xx = rb_int_mul(x, x); + while (rb_int_gt(xx, n)) { + xx = rb_int_minus(xx, rb_int_minus(rb_int_plus(x, x), INT2FIX(1))); + x = rb_int_minus(x, INT2FIX(1)); } + return x; } - RBASIC_SET_CLASS_RAW(x, rb_cInteger); - return x; } #if USE_GMP @@ -7001,7 +6956,7 @@ int_pow_tmp3(VALUE x, VALUE y, VALUE m, int nega_flg) if (FIXNUM_P(y)) { y = rb_int2big(FIX2LONG(y)); } - assert(RB_BIGNUM_TYPE_P(m)); + RUBY_ASSERT(RB_BIGNUM_TYPE_P(m)); xn = BIGNUM_LEN(x); yn = BIGNUM_LEN(y); mn = BIGNUM_LEN(m); diff --git a/bootstraptest/runner.rb b/bootstraptest/runner.rb index c8ba8244076986..a8e67f34968b58 100755 --- a/bootstraptest/runner.rb +++ b/bootstraptest/runner.rb @@ -6,7 +6,6 @@ # Never use optparse in this file. # Never use test/unit in this file. # Never use Ruby extensions in this file. -# Maintain Ruby 1.8 compatibility for now $start_time = Time.now @@ -77,6 +76,9 @@ def Dir.mktmpdir(prefix_suffix=nil, tmpdir=nil) :width, :indent, :platform, + :timeout, + :timeout_scale, + :launchable_test_reports ) BT = Class.new(bt) do def indent=(n) @@ -144,6 +146,10 @@ def wn=(wn) end super wn end + + def apply_timeout_scale(timeout) + timeout&.*(timeout_scale) + end end.new BT_STATE = Struct.new(:count, :error).new @@ -156,6 +162,12 @@ def main BT.color = nil BT.tty = nil BT.quiet = false + BT.timeout = 180 + BT.timeout_scale = 1 + if (ts = (ENV["RUBY_TEST_TIMEOUT_SCALE"] || ENV["RUBY_TEST_SUBPROCESS_TIMEOUT_SCALE"]).to_i) > 1 + BT.timeout_scale *= ts + end + # BT.wn = 1 dir = nil quiet = false @@ -186,14 +198,18 @@ def main warn "unknown --tty argument: #$3" if $3 BT.tty = !$1 || !$2 true - when /\A(-q|--q(uiet))\z/ + when /\A(-q|--q(uiet)?)\z/ quiet = true BT.quiet = true true when /\A-j(\d+)?/ BT.wn = $1.to_i true - when /\A(-v|--v(erbose))\z/ + when /\A--timeout=(\d+(?:_\d+)*(?:\.\d+(?:_\d+)*)?)(?::(\d+(?:_\d+)*(?:\.\d+(?:_\d+)*)?))?/ + BT.timeout = $1.to_f + BT.timeout_scale = $2.to_f if defined?($2) + true + when /\A(-v|--v(erbose)?)\z/ BT.verbose = true BT.quiet = false true @@ -205,6 +221,7 @@ def main default: /tmp/bootstraptestXXXXX.tmpwd --color[=WHEN] Colorize the output. WHEN defaults to 'always' or can be 'never' or 'auto'. + --timeout=TIMEOUT Default timeout in seconds. -s, --stress stress test. -v, --verbose Output test name before exec. -q, --quiet Don\'t print header message. @@ -213,6 +230,31 @@ def main exit true when /\A-j/ true + when /--launchable-test-reports=(.*)/ + if File.exist?($1) + # To protect files from overwritten, do nothing when the file exists. + return true + end + + begin + require_relative '../tool/lib/launchable' + rescue LoadError + # The following error sometimes happens, so we're going to skip writing Launchable report files in this case. + # + # ``` + # /tmp/tmp.bISss9CtXZ/.ext/common/json/ext.rb:15:in 'Kernel#require': + # /tmp/tmp.bISss9CtXZ/.ext/x86_64-linux/json/ext/parser.so: + # undefined symbol: ruby_abi_version - ruby_abi_version (LoadError) + # ``` + # + return true + end + BT.launchable_test_reports = writer = Launchable::JsonStreamWriter.new($1) + writer.write_array('testCases') + at_exit { + writer.close + } + true else false end @@ -222,7 +264,7 @@ def main end tests ||= ARGV tests = Dir.glob("#{File.dirname($0)}/test_*.rb").sort if tests.empty? - pathes = tests.map {|path| File.expand_path(path) } + paths = tests.map {|path| File.expand_path(path) } BT.progress = %w[- \\ | /] BT.progress_bs = "\b" * BT.progress[0].size @@ -266,7 +308,7 @@ def main end in_temporary_working_directory(dir) do - exec_test pathes + exec_test paths end end @@ -278,8 +320,8 @@ def erase(e = true) end end -def load_test pathes - pathes.each do |path| +def load_test paths + paths.each do |path| load File.expand_path(path) end end @@ -312,6 +354,7 @@ def concurrent_exec_test begin while BT.wn != term_wn if r = rq.pop + BT_STATE.count += 1 case when BT.quiet when BT.tty @@ -329,13 +372,66 @@ def concurrent_exec_test end end -def exec_test(pathes) +## +# Module for writing a test file for uploading test results into Launchable. +# In bootstraptest, we aggregate the test results based on file level. +module Launchable + @@last_test_name = nil + @@failure_log = '' + @@duration = 0 + + def show_progress(message = '') + faildesc, t = super + + if writer = BT.launchable_test_reports + if faildesc + @@failure_log += faildesc + end + repo_path = File.expand_path("#{__dir__}/../") + relative_path = File.join(__dir__, self.path).delete_prefix("#{repo_path}/") + if @@last_test_name != nil && @@last_test_name != relative_path + # The test path is a URL-encoded representation. + # https://github.com/launchableinc/cli/blob/v1.81.0/launchable/testpath.py#L18 + test_path = "#{encode_test_path_component("file")}=#{encode_test_path_component(@@last_test_name)}" + if @@failure_log.size > 0 + status = 'TEST_FAILED' + else + status = 'TEST_PASSED' + end + writer.write_object( + { + testPath: test_path, + status: status, + duration: t, + createdAt: Time.now.to_s, + stderr: @@failure_log, + stdout: nil, + data: { + lineNumber: self.lineno + } + } + ) + @@duration = 0 + @@failure_log = '' + end + @@last_test_name = relative_path + @@duration += t + end + end + + private + def encode_test_path_component component + component.to_s.gsub('%', '%25').gsub('=', '%3D').gsub('#', '%23').gsub('&', '%26') + end +end + +def exec_test(paths) # setup - load_test pathes + load_test paths BT_STATE.count = 0 BT_STATE.error = 0 BT.columns = 0 - BT.width = pathes.map {|path| File.basename(path).size}.max + 2 + BT.width = paths.map {|path| File.basename(path).size}.max + 2 # execute tests if BT.wn > 1 @@ -405,6 +501,7 @@ def target_platform end class Assertion < Struct.new(:src, :path, :lineno, :proc) + prepend Launchable @count = 0 @all = Hash.new{|h, k| h[k] = []} @errbuf = [] @@ -428,7 +525,7 @@ def add as def initialize(*args) super self.class.add self - @category = self.path.match(/test_(.+)\.rb/)[1] + @category = self.path[/\Atest_(.+)\.rb\z/, 1] end def call @@ -479,9 +576,9 @@ def show_progress(message = '') $stderr.print "#{BT.progress_bs}#{BT.progress[BT_STATE.count % BT.progress.size]}" end - t = Time.now if BT.verbose + t = Time.now if BT.verbose || BT.launchable_test_reports faildesc, errout = with_stderr {yield} - t = Time.now - t if BT.verbose + t = Time.now - t if BT.verbose || BT.launchable_test_reports if !faildesc # success @@ -508,6 +605,8 @@ def show_progress(message = '') $stderr.printf("%-*s%s", BT.width, path, BT.progress[BT_STATE.count % BT.progress.size]) end end + + [faildesc, t] rescue Interrupt $stderr.puts "\##{@id} #{path}:#{lineno}" raise @@ -526,14 +625,22 @@ def show_progress(message = '') end end - def get_result_string(opt = '', **argh) + class Timeout < StandardError; end + + def get_result_string(opt = '', timeout: BT.timeout, **argh) if BT.ruby + timeout = BT.apply_timeout_scale(timeout) filename = make_srcfile(**argh) begin kw = self.err ? {err: self.err} : {} out = IO.popen("#{BT.ruby} -W0 #{opt} #{filename}", **kw) pid = out.pid - out.read.tap{ Process.waitpid(pid); out.close } + th = Thread.new {out.read.tap {Process.waitpid(pid); out.close}} + if th.join(timeout) + th.value + else + Timeout.new("timed out after #{timeout} seconds") + end ensure raise Interrupt if $? and $?.signaled? && $?.termsig == Signal.list["INT"] @@ -551,9 +658,14 @@ def get_result_string(opt = '', **argh) def make_srcfile(frozen_string_literal: nil) filename = "bootstraptest.#{self.path}_#{self.lineno}_#{self.id}.rb" File.open(filename, 'w') {|f| - f.puts "#frozen_string_literal:true" if frozen_string_literal - f.puts "GC.stress = true" if $stress - f.puts "print(begin; #{self.src}; end)" + f.puts "#frozen_string_literal:#{frozen_string_literal}" unless frozen_string_literal.nil? + if $stress + f.puts "GC.stress = true" if $stress + else + f.puts "" + end + f.puts "class BT_Skip < Exception; end; def skip(msg) = raise(BT_Skip, msg.to_s)" + f.puts "print(begin; #{self.src}; rescue BT_Skip; $!.message; end)" } filename end @@ -567,9 +679,9 @@ def add_assertion src, pr Assertion.new(src, path, lineno, pr) end -def assert_equal(expected, testsrc, message = '', opt = '', **argh) +def assert_equal(expected, testsrc, message = '', opt = '', **kwargs) add_assertion testsrc, -> as do - as.assert_check(message, opt, **argh) {|result| + as.assert_check(message, opt, **kwargs) {|result| if expected == result nil else @@ -580,9 +692,9 @@ def assert_equal(expected, testsrc, message = '', opt = '', **argh) end end -def assert_match(expected_pattern, testsrc, message = '') +def assert_match(expected_pattern, testsrc, message = '', **argh) add_assertion testsrc, -> as do - as.assert_check(message) {|result| + as.assert_check(message, **argh) {|result| if expected_pattern =~ result nil else @@ -614,8 +726,9 @@ def assert_valid_syntax(testsrc, message = '') end end -def assert_normal_exit(testsrc, *rest, timeout: nil, **opt) +def assert_normal_exit(testsrc, *rest, timeout: BT.timeout, **opt) add_assertion testsrc, -> as do + timeout = BT.apply_timeout_scale(timeout) message, ignore_signals = rest message ||= '' as.show_progress(message) { @@ -624,23 +737,19 @@ def assert_normal_exit(testsrc, *rest, timeout: nil, **opt) timeout_signaled = false logfile = "assert_normal_exit.#{as.path}.#{as.lineno}.log" - begin - err = open(logfile, "w") - io = IO.popen("#{BT.ruby} -W0 #{filename}", err: err) - pid = io.pid - th = Thread.new { - io.read - io.close - $? - } - if !th.join(timeout) - Process.kill :KILL, pid - timeout_signaled = true - end - status = th.value - ensure - err.close + io = IO.popen("#{BT.ruby} -W0 #{filename}", err: logfile) + pid = io.pid + th = Thread.new { + io.read + io.close + $? + } + if !th.join(timeout) + Process.kill :KILL, pid + timeout_signaled = true end + status = th.value + if status && status.signaled? signo = status.termsig signame = Signal.list.invert[signo] @@ -669,9 +778,7 @@ def assert_normal_exit(testsrc, *rest, timeout: nil, **opt) def assert_finish(timeout_seconds, testsrc, message = '') add_assertion testsrc, -> as do - if defined?(RubyVM::RJIT) && RubyVM::RJIT.enabled? # for --jit-wait - timeout_seconds *= 3 - end + timeout_seconds = BT.apply_timeout_scale(timeout_seconds) as.show_progress(message) { faildesc = nil @@ -727,6 +834,8 @@ def show_limit(testsrc, opt = '', **argh) def pretty(src, desc, result) src = src.sub(/\A\s*\n/, '') + lines = src.lines + src = lines[0..20].join + "(...snip)\n" if lines.size > 20 (/\n/ =~ src ? "\n#{adjust_indent(src)}" : src) + " #=> #{desc}" end @@ -784,4 +893,12 @@ def check_coredump end end +def yjit_enabled? + ENV.key?('RUBY_YJIT_ENABLE') || ENV.fetch('RUN_OPTS', '').include?('yjit') || BT.ruby.include?('yjit') +end + +def zjit_enabled? + ENV.key?('RUBY_ZJIT_ENABLE') || ENV.fetch('RUN_OPTS', '').include?('zjit') || BT.ruby.include?('zjit') +end + exit main diff --git a/bootstraptest/test_autoload.rb b/bootstraptest/test_autoload.rb index 9e0850bc529720..de66f1f3ee15de 100644 --- a/bootstraptest/test_autoload.rb +++ b/bootstraptest/test_autoload.rb @@ -11,7 +11,7 @@ }, '[ruby-dev:43816]' assert_equal 'ok', %q{ - open('zzz2.rb', 'w') {|f| f.puts '' } + File.write('zzz2.rb', '') instance_eval do autoload :ZZZ, './zzz2.rb' begin @@ -23,7 +23,7 @@ }, '[ruby-dev:43816]' assert_equal 'ok', %q{ - open('zzz3.rb', 'w') {|f| f.puts 'class ZZZ; def self.ok;:ok;end;end'} + File.write('zzz3.rb', "class ZZZ; def self.ok;:ok;end;end\n") instance_eval do autoload :ZZZ, './zzz3.rb' ZZZ.ok @@ -31,20 +31,20 @@ }, '[ruby-dev:43816]' assert_equal 'ok', %q{ - open("zzz4.rb", "w") {|f| f.puts "class ZZZ; def self.ok;:ok;end;end"} + File.write("zzz4.rb", "class ZZZ; def self.ok;:ok;end;end\n") autoload :ZZZ, "./zzz4.rb" ZZZ.ok } assert_equal 'ok', %q{ - open("zzz5.rb", "w") {|f| f.puts "class ZZZ; def self.ok;:ok;end;end"} + File.write("zzz5.rb", "class ZZZ; def self.ok;:ok;end;end\n") autoload :ZZZ, "./zzz5.rb" require "./zzz5.rb" ZZZ.ok } assert_equal 'okok', %q{ - open("zzz6.rb", "w") {|f| f.puts "class ZZZ; def self.ok;:ok;end;end"} + File.write("zzz6.rb", "class ZZZ; def self.ok;:ok;end;end\n") autoload :ZZZ, "./zzz6.rb" t1 = Thread.new {ZZZ.ok} t2 = Thread.new {ZZZ.ok} @@ -60,7 +60,7 @@ }, '[ruby-core:21696]' assert_equal 'A::C', %q{ - open("zzz7.rb", "w") {} + File.write("zzz7.rb", "") class A autoload :C, "./zzz7" class C diff --git a/bootstraptest/test_eval.rb b/bootstraptest/test_eval.rb index a9f389c673412b..20bd9615f4561c 100644 --- a/bootstraptest/test_eval.rb +++ b/bootstraptest/test_eval.rb @@ -217,7 +217,7 @@ def initialize &b } %w[break next redo].each do |keyword| - assert_match %r"Can't escape from eval with #{keyword}\b", %{ + assert_match %r"Invalid #{keyword}\b", %{ $stderr = STDOUT begin eval "0 rescue #{keyword}" @@ -227,6 +227,16 @@ def initialize &b }, '[ruby-dev:31372]' end +assert_normal_exit %{ + $stderr = STDOUT + 5000.times do + begin + eval "0 rescue break" + rescue SyntaxError + end + end +} + assert_normal_exit %q{ $stderr = STDOUT class Foo @@ -354,3 +364,34 @@ def kaboom! end }, 'check escaping the internal value th->base_block' +assert_equal "false", <<~RUBY, "literal strings are mutable", "--disable-frozen-string-literal" + eval("'test'").frozen? +RUBY + +assert_equal "false", <<~RUBY, "literal strings are mutable", "--disable-frozen-string-literal", frozen_string_literal: true + eval("'test'").frozen? +RUBY + +assert_equal "true", <<~RUBY, "literal strings are frozen", "--enable-frozen-string-literal" + eval("'test'").frozen? +RUBY + +assert_equal "true", <<~RUBY, "literal strings are frozen", "--enable-frozen-string-literal", frozen_string_literal: false + eval("'test'").frozen? +RUBY + +assert_equal "false", <<~RUBY, "__FILE__ is mutable", "--disable-frozen-string-literal" + eval("__FILE__").frozen? +RUBY + +assert_equal "false", <<~RUBY, "__FILE__ is mutable", "--disable-frozen-string-literal", frozen_string_literal: true + eval("__FILE__").frozen? +RUBY + +assert_equal "true", <<~RUBY, "__FILE__ is frozen", "--enable-frozen-string-literal" + eval("__FILE__").frozen? +RUBY + +assert_equal "true", <<~RUBY, "__FILE__ is frozen", "--enable-frozen-string-literal", frozen_string_literal: false + eval("__FILE__").frozen? +RUBY diff --git a/bootstraptest/test_exception.rb b/bootstraptest/test_exception.rb index 0fb6f552b88d10..decfdc08a30895 100644 --- a/bootstraptest/test_exception.rb +++ b/bootstraptest/test_exception.rb @@ -370,7 +370,7 @@ def m } ## -assert_match /undefined method `foo\'/, %q{#` +assert_match /undefined method 'foo\'/, %q{#` STDERR.reopen(STDOUT) class C def inspect diff --git a/bootstraptest/test_fiber.rb b/bootstraptest/test_fiber.rb index 2614dd13bf1d6d..ae809a59366779 100644 --- a/bootstraptest/test_fiber.rb +++ b/bootstraptest/test_fiber.rb @@ -37,3 +37,8 @@ assert_normal_exit %q{ Fiber.new(&Object.method(:class_eval)).resume("foo") }, '[ruby-dev:34128]' + +# [Bug #21400] +assert_normal_exit %q{ + Thread.new { Fiber.current.kill }.join +} diff --git a/bootstraptest/test_finalizer.rb b/bootstraptest/test_finalizer.rb index 22a16b1220e784..ccfa0b55d613f2 100644 --- a/bootstraptest/test_finalizer.rb +++ b/bootstraptest/test_finalizer.rb @@ -6,3 +6,11 @@ ObjectSpace.define_finalizer(a2,proc{a1.inspect}) ObjectSpace.define_finalizer(a1,proc{}) }, '[ruby-dev:35778]' + +assert_equal 'true', %q{ + obj = Object.new + id = obj.object_id + + ObjectSpace.define_finalizer(obj, proc { |i| print(id == i) }) + nil +} diff --git a/bootstraptest/test_flow.rb b/bootstraptest/test_flow.rb index 35f19db5888f85..15528a42130fc1 100644 --- a/bootstraptest/test_flow.rb +++ b/bootstraptest/test_flow.rb @@ -363,7 +363,7 @@ class C ; $a << 8 ; rescue Exception; $a << 99; end; $a} assert_equal %q{[1, 2, 6, 3, 5, 7, 8]}, %q{$a = []; begin; ; $a << 1 - o = "test"; $a << 2 + o = "test".dup; $a << 2 def o.test(a); $a << 3 return a; $a << 4 ensure; $a << 5 diff --git a/bootstraptest/test_fork.rb b/bootstraptest/test_fork.rb index 83923dad97eff6..860ef285d033e2 100644 --- a/bootstraptest/test_fork.rb +++ b/bootstraptest/test_fork.rb @@ -75,3 +75,30 @@ end }, '[ruby-dev:44005] [Ruby 1.9 - Bug #4950]' +assert_equal 'ok', %q{ + def now = Process.clock_gettime(Process::CLOCK_MONOTONIC) + + Thread.new do + loop { sleep 0.0001 } + end + + 10.times do + pid = fork{ exit!(0) } + deadline = now + 10 + while true + _, status = Process.waitpid2(pid, Process::WNOHANG) + break if status + if now > deadline + Process.kill(:KILL, pid) + raise "failed" + end + sleep 0.001 + end + unless status.success? + raise "child exited with status #{status}" + end + rescue NotImplementedError + end + :ok +}, '[Bug #20670]' + diff --git a/bootstraptest/test_gc.rb b/bootstraptest/test_gc.rb index 9f17e1481405c8..eb68c9845e37c9 100644 --- a/bootstraptest/test_gc.rb +++ b/bootstraptest/test_gc.rb @@ -14,7 +14,7 @@ o.send(meth) end end -}, '[ruby-dev:39453]' unless ENV.fetch('RUN_OPTS', '').include?('rjit') # speed up RJIT CI +}, '[ruby-dev:39453]' assert_normal_exit %q{ a = [] diff --git a/bootstraptest/test_insns.rb b/bootstraptest/test_insns.rb index d2e799f855def9..8a6efae08985d5 100644 --- a/bootstraptest/test_insns.rb +++ b/bootstraptest/test_insns.rb @@ -92,7 +92,7 @@ def m&b [ 'intern', %q{ :"#{true}" }, ], [ 'newarray', %q{ ["true"][0] }, ], - [ 'newarraykwsplat', %q{ [**{x:'true'}][0][:x] }, ], + [ 'pushtoarraykwsplat', %q{ [**{x:'true'}][0][:x] }, ], [ 'duparray', %q{ [ true ][0] }, ], [ 'expandarray', %q{ y = [ true, false, nil ]; x, = y; x }, ], [ 'expandarray', %q{ y = [ true, false, nil ]; x, *z = y; x }, ], @@ -214,8 +214,21 @@ def freeze 'true'.freeze }, + [ 'opt_duparray_send', %q{ x = :a; [:a, :b].include?(x) }, ], + [ 'opt_duparray_send', <<-'},', ], # { + class Array + def include?(i) + i == 1 + end + end + x = 1 + [:a, :b].include?(x) + }, + [ 'opt_newarray_send', %q{ ![ ].hash.nil? }, ], + [ 'opt_newarray_send', %q{ v=2; [1, Object.new, 2].include?(v) }, ], + [ 'opt_newarray_send', %q{ [ ].max.nil? }, ], [ 'opt_newarray_send', %q{ [1, x = 2, 3].max == 3 }, ], [ 'opt_newarray_send', <<-'},', ], # { @@ -236,6 +249,48 @@ def min end [3, x = 2, 1].min }, + [ 'opt_newarray_send', %q{ v = 1.23; [v, v*2].pack("E*").unpack("E*") == [v, v*2] }, ], + [ 'opt_newarray_send', %q{ v = 4.56; b = +"x"; [v, v*2].pack("E*", buffer: b); b[1..].unpack("E*") == [v, v*2] }, ], + [ 'opt_newarray_send', <<-'},', ], # { + v = 7.89; + b = +"x"; + class Array + alias _pack pack + def pack(s, buffer: nil, prefix: "y") + buffer ||= +"b" + buffer << prefix + _pack(s, buffer: buffer) + end + end + tests = [] + + ret = [v].pack("E*", prefix: "z") + tests << (ret[0..1] == "bz") + tests << (ret[2..].unpack("E*") == [v]) + + ret = [v].pack("E*") + tests << (ret[0..1] == "by") + tests << (ret[2..].unpack("E*") == [v]) + + [v, v*2, v*3].pack("E*", buffer: b) + tests << (b[0..1] == "xy") + tests << (b[2..].unpack("E*") == [v, v*2, v*3]) + + class Array + def pack(_fmt, buffer:) = buffer + end + + b = nil + tests << [v].pack("E*", buffer: b).nil? + + class Array + def pack(_fmt, **kw) = kw.empty? + end + + tests << [v].pack("E*") == true + + tests.all? or puts tests + }, [ 'throw', %q{ false.tap { break true } }, ], [ 'branchif', %q{ x = nil; x ||= true }, ], @@ -354,7 +409,7 @@ class X; def != other; true; end; end [ 'opt_ge', %q{ +0.0.next_float >= 0.0 }, ], [ 'opt_ge', %q{ ?z >= ?a }, ], - [ 'opt_ltlt', %q{ '' << 'true' }, ], + [ 'opt_ltlt', %q{ +'' << 'true' }, ], [ 'opt_ltlt', %q{ ([] << 'true').join }, ], [ 'opt_ltlt', %q{ (1 << 31) == 2147483648 }, ], @@ -363,7 +418,7 @@ class X; def != other; true; end; end [ 'opt_aref', %q{ 'true'[0] == ?t }, ], [ 'opt_aset', %q{ [][0] = true }, ], [ 'opt_aset', %q{ {}[0] = true }, ], - [ 'opt_aset', %q{ x = 'frue'; x[0] = 't'; x }, ], + [ 'opt_aset', %q{ x = +'frue'; x[0] = 't'; x }, ], [ 'opt_aset', <<-'},', ], # { # opt_aref / opt_aset mixup situation class X; def x; {}; end; end diff --git a/bootstraptest/test_io.rb b/bootstraptest/test_io.rb index 666e5a011b63c7..4e5d6d59c9bd36 100644 --- a/bootstraptest/test_io.rb +++ b/bootstraptest/test_io.rb @@ -91,7 +91,7 @@ at_exit { p :foo } megacontent = "abc" * 12345678 - #File.open("megasrc", "w") {|f| f << megacontent } + #File.write("megasrc", megacontent) t0 = Thread.main Thread.new { sleep 0.001 until t0.stop?; Process.kill(:INT, $$) } diff --git a/bootstraptest/test_jump.rb b/bootstraptest/test_jump.rb index d07c47a56d7400..8751343b1f2d2a 100644 --- a/bootstraptest/test_jump.rb +++ b/bootstraptest/test_jump.rb @@ -292,7 +292,7 @@ class << self end end end - s = "foo" + s = +"foo" s.return_eigenclass == class << s; self; end }, '[ruby-core:21379]' diff --git a/bootstraptest/test_literal.rb b/bootstraptest/test_literal.rb index a0d4ee08c6b2e9..39e6527027a8f7 100644 --- a/bootstraptest/test_literal.rb +++ b/bootstraptest/test_literal.rb @@ -70,6 +70,7 @@ assert_equal "foo\n", %q(`echo foo`) assert_equal "foo\n", %q(s = "foo"; `echo #{s}`) end +assert_equal "ECHO FOO", %q(def `(s) s.upcase; end; `echo foo`) # regexp assert_equal '', '//.source' @@ -116,16 +117,16 @@ assert_equal 'true', 'a = [obj = Object.new]; a[0] == obj' assert_equal '5', 'a = [1,2,3]; a[1] = 5; a[1]' assert_equal 'bar', '[*:foo];:bar' -assert_equal '[1, 2]', 'def nil.to_a; [2]; end; [1, *nil]' -assert_equal '[1, 2]', 'def nil.to_a; [1, 2]; end; [*nil]' -assert_equal '[0, 1, {2=>3}]', '[0, *[1], 2=>3]', "[ruby-dev:31592]" +assert_equal '[]', 'def nil.to_a; [1, 2]; end; [*nil]' +assert_equal '[1]', 'def nil.to_a; [2]; end; [1, *nil]' +assert_equal '[0, 1, {2 => 3}]', '[0, *[1], 2=>3]', "[ruby-dev:31592]" # hash assert_equal 'Hash', '{}.class' assert_equal '{}', '{}.inspect' assert_equal 'Hash', '{1=>2}.class' -assert_equal '{1=>2}', '{1=>2}.inspect' +assert_equal '{1 => 2}', '{1=>2}.inspect' assert_equal '2', 'h = {1 => 2}; h[1]' assert_equal '0', 'h = {1 => 2}; h.delete(1); h.size' assert_equal '', 'h = {1 => 2}; h.delete(1); h[1]' diff --git a/bootstraptest/test_literal_suffix.rb b/bootstraptest/test_literal_suffix.rb index c36fa7078f950d..7a4d67d0fac3e3 100644 --- a/bootstraptest/test_literal_suffix.rb +++ b/bootstraptest/test_literal_suffix.rb @@ -46,9 +46,9 @@ assert_equal '10000000000000000001/10000000000000000000', '1.0000000000000000001r' -assert_equal 'syntax error, unexpected local variable or method, expecting end-of-input', - %q{begin eval('1ir', nil, '', 0); rescue SyntaxError => e; e.message[/\A:(?:\d+:)? (.*)/, 1] end} -assert_equal 'syntax error, unexpected local variable or method, expecting end-of-input', - %q{begin eval('1.2ir', nil, '', 0); rescue SyntaxError => e; e.message[/\A:(?:\d+:)? (.*)/, 1] end} -assert_equal 'syntax error, unexpected local variable or method, expecting end-of-input', - %q{begin eval('1e1r', nil, '', 0); rescue SyntaxError => e; e.message[/\A:(?:\d+:)? (.*)/, 1] end} +assert_equal 'unexpected local variable or method, expecting end-of-input', + %q{begin eval('1ir', nil, '', 0); rescue SyntaxError => e; e.message[/(?:\^~*|\A:(?:\d+:)? syntax error,) (.*)/, 1]; end} +assert_equal 'unexpected local variable or method, expecting end-of-input', + %q{begin eval('1.2ir', nil, '', 0); rescue SyntaxError => e; e.message[/(?:\^~*|\A:(?:\d+:)? syntax error,) (.*)/, 1]; end} +assert_equal 'unexpected local variable or method, expecting end-of-input', + %q{begin eval('1e1r', nil, '', 0); rescue SyntaxError => e; e.message[/(?:\^~*|\A:(?:\d+:)? syntax error,) (.*)/, 1]; end} diff --git a/bootstraptest/test_load.rb b/bootstraptest/test_load.rb index 3253582a324995..fa8d31c098c029 100644 --- a/bootstraptest/test_load.rb +++ b/bootstraptest/test_load.rb @@ -1,9 +1,9 @@ assert_equal 'ok', %q{ - open("require-lock-test.rb", "w") {|f| - f.puts "sleep 0.1" - f.puts "module M" - f.puts "end" - } + File.write("require-lock-test.rb", <<-END) + sleep 0.1 + module M + end + END $:.unshift Dir.pwd vs = (1..2).map {|i| Thread.start { @@ -12,11 +12,11 @@ } }.map {|t| t.value } vs[0] == M && vs[1] == M ? :ok : :ng -}, '[ruby-dev:32048]' unless ENV.fetch('RUN_OPTS', '').include?('rjit') # Thread seems to be switching during JIT. To be fixed later. +}, '[ruby-dev:32048]' assert_equal 'ok', %q{ %w[a a/foo b].each {|d| Dir.mkdir(d)} - open("b/foo", "w") {|f| f.puts "$ok = :ok"} + File.write("b/foo", "$ok = :ok\n") $:.replace(%w[a b]) begin load "foo" diff --git a/bootstraptest/test_method.rb b/bootstraptest/test_method.rb index 04c9eb2d11425e..997675200e4d73 100644 --- a/bootstraptest/test_method.rb +++ b/bootstraptest/test_method.rb @@ -340,24 +340,6 @@ def method_missing(mid, *args, &block) block end assert_equal '1', %q( class C; def m() 1 end; private :m end C.new.send(:m) ) -# with block -assert_equal '[[:ok1, :foo], [:ok2, :foo, :bar]]', -%q{ - class C - def [](a) - $ary << [yield, a] - end - def []=(a, b) - $ary << [yield, a, b] - end - end - - $ary = [] - C.new[:foo, &lambda{:ok1}] - C.new[:foo, &lambda{:ok2}] = :bar - $ary -} - # with assert_equal '[:ok1, [:ok2, 11]]', %q{ class C @@ -404,7 +386,6 @@ def m(*args, &b) # aset and splat assert_equal '4', %q{class Foo;def []=(a,b,c,d);end;end;Foo.new[1,*a=[2,3]]=4} -assert_equal '4', %q{class Foo;def []=(a,b,c,d);end;end;def m(&blk)Foo.new[1,*a=[2,3],&blk]=4;end;m{}} # post test assert_equal %q{[1, 2, :o1, :o2, [], 3, 4, NilClass, nil, nil]}, %q{ @@ -1107,10 +1088,6 @@ class C 'ok' end } -assert_equal 'ok', %q{ - [0][0, &proc{}] += 21 - 'ok' -}, '[ruby-core:30534]' # should not cache when splat assert_equal 'ok', %q{ @@ -1190,3 +1167,263 @@ def test2 o, args, block test2 o1, [], block $result.join } + +assert_equal 'ok', %q{ + def foo + binding + ["ok"].first + end + foo + foo +}, '[Bug #20178]' + +assert_equal 'ok', %q{ + def bar(x); x; end + def foo(...); bar(...); end + foo('ok') +} + +assert_equal 'ok', %q{ + def bar(x); x; end + def foo(z, ...); bar(...); end + foo(1, 'ok') +} + +assert_equal 'ok', %q{ + def bar(x, y); x; end + def foo(...); bar("ok", ...); end + foo(1) +} + +assert_equal 'ok', %q{ + def bar(x); x; end + def foo(...); 1.times { return bar(...) }; end + foo("ok") +} + +assert_equal 'ok', %q{ + def bar(x); x; end + def foo(...); x = nil; 1.times { x = bar(...) }; x; end + foo("ok") +} + +assert_equal 'ok', %q{ + def bar(x); yield; end + def foo(...); bar(...); end + foo(1) { "ok" } +} + +assert_equal 'ok', %q{ + def baz(x); x; end + def bar(...); baz(...); end + def foo(...); bar(...); end + foo("ok") +} + +assert_equal '[1, 2, 3, 4]', %q{ + def baz(a, b, c, d); [a, b, c, d]; end + def bar(...); baz(1, ...); end + def foo(...); bar(2, ...); end + foo(3, 4) +} + +assert_equal 'ok', %q{ + class Foo; def self.foo(x); x; end; end + class Bar < Foo; def self.foo(...); super; end; end + Bar.foo('ok') +} + +assert_equal 'ok', %q{ + class Foo; def self.foo(x); x; end; end + class Bar < Foo; def self.foo(...); super(...); end; end + Bar.foo('ok') +} + +assert_equal 'ok', %q{ + class Foo; def self.foo(x, y); x + y; end; end + class Bar < Foo; def self.foo(...); super("o", ...); end; end + Bar.foo('k') +} + +assert_equal 'ok', %q{ + def bar(a); a; end + def foo(...); lambda { bar(...) }; end + foo("ok").call +} + +assert_equal 'ok', %q{ + class Foo; def self.foo(x, y); x + y; end; end + class Bar < Foo; def self.y(&b); b; end; def self.foo(...); y { super("o", ...) }; end; end + Bar.foo('k').call +} + +assert_equal 'ok', %q{ + def baz(n); n; end + def foo(...); bar = baz(...); lambda { lambda { bar } }; end + foo("ok").call.call +} + +assert_equal 'ok', %q{ + class A; def self.foo(...); new(...); end; attr_reader :b; def initialize(a, b:"ng"); @a = a; @b = b; end end + A.foo(1).b + A.foo(1, b: "ok").b +} + +assert_equal 'ok', %q{ + class A; def initialize; @a = ["ok"]; end; def first(...); @a.first(...); end; end + def call x; x.first; end + def call1 x; x.first(1); end + call(A.new) + call1(A.new).first +} + +assert_equal 'ok', %q{ + class A; def foo; yield("o"); end; end + class B < A; def foo(...); super { |x| yield(x + "k") }; end; end + B.new.foo { |x| x } +} + +assert_equal "[1, 2, 3, 4]", %q{ + def foo(*b) = b + + def forward(...) + splat = [1,2,3] + foo(*splat, ...) + end + + forward(4) +} + +assert_equal "[1, 2, 3, 4]", %q{ +class A + def foo(*b) = b +end + +class B < A + def foo(...) + splat = [1,2,3] + super(*splat, ...) + end +end + +B.new.foo(4) +} + +assert_equal 'ok', %q{ + class A; attr_reader :iv; def initialize(...) = @iv = "ok"; end + A.new("foo", bar: []).iv +} + +assert_equal 'ok', %q{ + def foo(a, b) = a + b + def bar(...) = foo(...) + bar(1, 2) + bar(1, 2) + begin + bar(1, 2, 3) + "ng" + rescue ArgumentError + "ok" + end +} + +assert_equal 'ok', %q{ + class C + def foo(...) = :ok + def bar(...) = __send__(:foo, ...) + end + + C.new.bar +} + +assert_equal 'ok', %q{ + class C + def method_missing(...) = :ok + def foo(...) = xyzzy(...) + end + + C.new.foo +} + +assert_equal 'ok', %q{ + class C + def initialize(a) + end + end + + def foo(...) + C.new(...) + :ok + end + + foo(*["bar"]) + foo("baz") +} + +assert_equal 'ok', %q{ + class C + def foo(b:) + b + end + end + + def foo(...) + C.new.send(...) + end + + foo(:foo, b: :ok) + foo(*["foo"], b: :ok) +} + +assert_equal 'ok', %q{ + Thing = Struct.new(:value) + + Obj = Thing.new("ok") + + def delegate(...) + Obj.value(...) + end + + def no_args + delegate + end + + def splat_args(*args) + delegate(*args) + end + + no_args + splat_args +} + +assert_equal 'ok', %q{ + class A + private + def foo = "ng" + end + + class B + def initialize(o) + @o = o + end + + def foo(...) = @o.foo(...) + def internal_foo = foo + end + + b = B.new(A.new) + + begin + b.internal_foo + rescue NoMethodError + "ok" + end +} + +assert_equal 'ok', <<~RUBY + def test(*, kw: false) + "ok" + end + + test +RUBY diff --git a/bootstraptest/test_ractor.rb b/bootstraptest/test_ractor.rb index 7a71f6e0715094..1c2a4b0b8ec8bd 100644 --- a/bootstraptest/test_ractor.rb +++ b/bootstraptest/test_ractor.rb @@ -67,7 +67,7 @@ # Return id, loc, and status for no-name ractor assert_match /^#$/, %q{ r = Ractor.new { '' } - r.take + r.join sleep 0.1 until r.inspect =~ /terminated/ r.inspect } @@ -75,7 +75,7 @@ # Return id, name, loc, and status for named ractor assert_match /^#$/, %q{ r = Ractor.new(name: 'Test Ractor') { '' } - r.take + r.join sleep 0.1 until r.inspect =~ /terminated/ r.inspect } @@ -86,7 +86,7 @@ r = Ractor.new do 'ok' end - r.take + r.value } # Passed arguments to Ractor.new will be a block parameter @@ -96,7 +96,7 @@ r = Ractor.new 'ok' do |msg| msg end - r.take + r.value } # Pass multiple arguments to Ractor.new @@ -105,7 +105,7 @@ r = Ractor.new 'ping', 'pong' do |msg, msg2| [msg, msg2] end - 'ok' if r.take == ['ping', 'pong'] + 'ok' if r.value == ['ping', 'pong'] } # Ractor#send passes an object with copy to a Ractor @@ -115,65 +115,23 @@ msg = Ractor.receive end r.send 'ok' - r.take + r.value } # Ractor#receive_if can filter the message -assert_equal '[2, 3, 1]', %q{ - r = Ractor.new Ractor.current do |main| - main << 1 - main << 2 - main << 3 - end - a = [] - a << Ractor.receive_if{|msg| msg == 2} - a << Ractor.receive_if{|msg| msg == 3} - a << Ractor.receive -} +assert_equal '[1, 2, 3]', %q{ + ports = 3.times.map{Ractor::Port.new} -# Ractor#receive_if with break -assert_equal '[2, [1, :break], 3]', %q{ - r = Ractor.new Ractor.current do |main| - main << 1 - main << 2 - main << 3 + r = Ractor.new ports do |ports| + ports[0] << 3 + ports[1] << 1 + ports[2] << 2 end - - a = [] - a << Ractor.receive_if{|msg| msg == 2} - a << Ractor.receive_if{|msg| break [msg, :break]} - a << Ractor.receive -} - -# Ractor#receive_if can't be called recursively -assert_equal '[[:e1, 1], [:e2, 2]]', %q{ - r = Ractor.new Ractor.current do |main| - main << 1 - main << 2 - main << 3 - end - a = [] - - Ractor.receive_if do |msg| - begin - Ractor.receive - rescue Ractor::Error - a << [:e1, msg] - end - true # delete 1 from queue - end - - Ractor.receive_if do |msg| - begin - Ractor.receive_if{} - rescue Ractor::Error - a << [:e2, msg] - end - true # delete 2 from queue - end - - a # + a << ports[1].receive # 1 + a << ports[2].receive # 2 + a << ports[0].receive # 3 + a } # dtoa race condition @@ -184,7 +142,7 @@ 10_000.times{ rand.to_s } :ok } - }.map(&:take) + }.map(&:value) } # Ractor.make_shareable issue for locals in proc [Bug #18023] @@ -211,46 +169,39 @@ Ractor.make_shareable(closure).call } -# Now autoload in non-main Ractor is not supported -assert_equal 'ok', %q{ - autoload :Foo, 'foo.rb' - r = Ractor.new do - p Foo - rescue Ractor::UnsafeError - :ok - end - r.take -} - ### ### # Ractor still has several memory corruption so skip huge number of tests -if ENV['GITHUB_WORKFLOW'] && - ENV['GITHUB_WORKFLOW'] == 'Compilations' +if ENV['GITHUB_WORKFLOW'] == 'Compilations' # ignore the follow else -# Ractor.select(*ractors) receives a values from a ractors. -# It is similar to select(2) and Go's select syntax. -# The return value is [ch, received_value] +# Ractor.select with a Ractor argument assert_equal 'ok', %q{ # select 1 r1 = Ractor.new{'r1'} - r, obj = Ractor.select(r1) - 'ok' if r == r1 and obj == 'r1' + port, obj = Ractor.select(r1) + if port == r1 and obj == 'r1' + 'ok' + else + # failed + [port, obj].inspect + end } # Ractor.select from two ractors. assert_equal '["r1", "r2"]', %q{ # select 2 - r1 = Ractor.new{'r1'} - r2 = Ractor.new{'r2'} - rs = [r1, r2] + p1 = Ractor::Port.new + p2 = Ractor::Port.new + r1 = Ractor.new(p1){|p1| p1 << 'r1'} + r2 = Ractor.new(p2){|p2| p2 << 'r2'} + ps = [p1, p2] as = [] - r, obj = Ractor.select(*rs) - rs.delete(r) + port, obj = Ractor.select(*ps) + ps.delete(port) as << obj - r, obj = Ractor.select(*rs) + port, obj = Ractor.select(*ps) as << obj as.sort #=> ["r1", "r2"] } @@ -294,30 +245,12 @@ def test n end } -# Outgoing port of a ractor will be closed when the Ractor is terminated. -assert_equal 'ok', %q{ - r = Ractor.new do - 'finish' - end - - r.take - sleep 0.1 until r.inspect =~ /terminated/ - - begin - o = r.take - rescue Ractor::ClosedError - 'ok' - else - "ng: #{o}" - end -} - # Raise Ractor::ClosedError when try to send into a terminated ractor assert_equal 'ok', %q{ r = Ractor.new do end - r.take # closed + r.join # closed sleep 0.1 until r.inspect =~ /terminated/ begin @@ -329,47 +262,16 @@ def test n end } -# Raise Ractor::ClosedError when try to send into a closed actor -assert_equal 'ok', %q{ - r = Ractor.new { Ractor.receive } - r.close_incoming - - begin - r.send(1) - rescue Ractor::ClosedError - 'ok' - else - 'ng' - end -} - -# Raise Ractor::ClosedError when try to take from closed actor -assert_equal 'ok', %q{ - r = Ractor.new do - Ractor.yield 1 - Ractor.receive - end - - r.close_outgoing - begin - r.take - rescue Ractor::ClosedError - 'ok' - else - 'ng' - end -} - -# Can mix with Thread#interrupt and Ractor#take [Bug #17366] +# Can mix with Thread#interrupt and Ractor#join [Bug #17366] assert_equal 'err', %q{ - Ractor.new{ + Ractor.new do t = Thread.current begin Thread.new{ t.raise "err" }.join rescue => e e.message end - }.take + end.value } # Killed Ractor's thread yields nil @@ -377,34 +279,18 @@ def test n Ractor.new{ t = Thread.current Thread.new{ t.kill }.join - }.take.inspect #=> nil + }.value.inspect #=> nil } -# Ractor.yield raises Ractor::ClosedError when outgoing port is closed. +# Raise Ractor::ClosedError when try to send into a ractor with closed default port assert_equal 'ok', %q{ - r = Ractor.new Ractor.current do |main| + r = Ractor.new { + Ractor.current.close + Ractor.main << :ok Ractor.receive - main << true - Ractor.yield 1 - end - - r.close_outgoing - r << true - Ractor.receive - - begin - r.take - rescue Ractor::ClosedError - 'ok' - else - 'ng' - end -} + } -# Raise Ractor::ClosedError when try to send into a ractor with closed incoming port -assert_equal 'ok', %q{ - r = Ractor.new { Ractor.receive } - r.close_incoming + Ractor.receive # wait for ok begin r.send(1) @@ -415,154 +301,82 @@ def test n end } -# A ractor with closed incoming port still can send messages out -assert_equal '[1, 2]', %q{ - r = Ractor.new do - Ractor.yield 1 - 2 - end - r.close_incoming - - [r.take, r.take] -} - -# Raise Ractor::ClosedError when try to take from a ractor with closed outgoing port -assert_equal 'ok', %q{ - r = Ractor.new do - Ractor.yield 1 - Ractor.receive - end - - sleep 0.01 # wait for Ractor.yield in r - r.close_outgoing - begin - r.take - rescue Ractor::ClosedError - 'ok' - else - 'ng' - end -} - -# A ractor with closed outgoing port still can receive messages from incoming port -assert_equal 'ok', %q{ - r = Ractor.new do - Ractor.receive - end - - r.close_outgoing - begin - r.send(1) - rescue Ractor::ClosedError - 'ng' - else - 'ok' - end -} - # Ractor.main returns main ractor assert_equal 'true', %q{ Ractor.new{ Ractor.main - }.take == Ractor.current + }.value == Ractor.current } # a ractor with closed outgoing port should terminate assert_equal 'ok', %q{ Ractor.new do - close_outgoing + Ractor.current.close end true until Ractor.count == 1 :ok } -# multiple Ractors can receive (wait) from one Ractor -assert_equal '[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]', %q{ - pipe = Ractor.new do - loop do - Ractor.yield Ractor.receive - end +# an exception in a Ractor main thread will be re-raised at Ractor#receive +assert_equal '[RuntimeError, "ok", true]', %q{ + r = Ractor.new do + raise 'ok' # exception will be transferred receiver end - - RN = 10 - rs = RN.times.map{|i| - Ractor.new pipe, i do |pipe, i| - msg = pipe.take - msg # ping-pong - end - } - RN.times{|i| - pipe << i - } - RN.times.map{ - r, n = Ractor.select(*rs) - rs.delete r - n - }.sort -} unless /mswin/ =~ RUBY_PLATFORM # randomly hangs on mswin https://github.com/ruby/ruby/actions/runs/3753871445/jobs/6377551069#step:20:131 - -# Ractor.select also support multiple take, receive and yield -assert_equal '[true, true, true]', %q{ - RN = 10 - CR = Ractor.current - - rs = (1..RN).map{ - Ractor.new do - CR.send 'send' + CR.take #=> 'sendyield' - 'take' - end - } - received = [] - taken = [] - yielded = [] - until received.size == RN && taken.size == RN && yielded.size == RN - r, v = Ractor.select(CR, *rs, yield_value: 'yield') - case r - when :receive - received << v - when :yield - yielded << v - else - taken << v - rs.delete r - end + begin + r.join + rescue Ractor::RemoteError => e + [e.cause.class, #=> RuntimeError + e.cause.message, #=> 'ok' + e.ractor == r] #=> true end - r = [received == ['sendyield'] * RN, - yielded == [nil] * RN, - taken == ['take'] * RN, - ] - - STDERR.puts [received, yielded, taken].inspect - r } -# multiple Ractors can send to one Ractor -assert_equal '[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]', %q{ - pipe = Ractor.new do - loop do - Ractor.yield Ractor.receive - end +# an exception in a Ractor will be re-raised at Ractor#value +assert_equal '[RuntimeError, "ok", true]', %q{ + r = Ractor.new do + raise 'ok' # exception will be transferred receiver + end + begin + r.value + rescue Ractor::RemoteError => e + [e.cause.class, #=> RuntimeError + e.cause.message, #=> 'ok' + e.ractor == r] #=> true end +} - RN = 10 - RN.times.map{|i| - Ractor.new pipe, i do |pipe, i| - pipe << i +# an exception in a Ractor non-main thread will not be re-raised at Ractor#receive +assert_equal 'ok', %q{ + r = Ractor.new do + Thread.new do + raise 'ng' end - } - RN.times.map{ - pipe.take - }.sort + sleep 0.1 + 'ok' + end + r.value } -# an exception in a Ractor will be re-raised at Ractor#receive -assert_equal '[RuntimeError, "ok", true]', %q{ - r = Ractor.new do - raise 'ok' # exception will be transferred receiver +# SystemExit from a Ractor is re-raised +# [Bug #21505] +assert_equal '[SystemExit, "exit", true]', %q{ + r = Ractor.new { exit } + begin + r.value + rescue Ractor::RemoteError => e + [e.cause.class, #=> RuntimeError + e.cause.message, #=> 'ok' + e.ractor == r] #=> true end +} + +# SystemExit from a Thread inside a Ractor is re-raised +# [Bug #21505] +assert_equal '[SystemExit, "exit", true]', %q{ + r = Ractor.new { Thread.new { exit }.join } begin - r.take + r.value rescue Ractor::RemoteError => e [e.cause.class, #=> RuntimeError e.cause.message, #=> 'ok' @@ -571,7 +385,7 @@ def test n } # threads in a ractor will killed -assert_equal '{:ok=>3}', %q{ +assert_equal '{ok: 3}', %q{ Ractor.new Ractor.current do |main| q = Thread::Queue.new Thread.new do @@ -601,7 +415,7 @@ def test n end 3.times.map{Ractor.receive}.tally -} +} unless yjit_enabled? || zjit_enabled? # YJIT: `[BUG] Bus Error at 0x000000010b7002d0` in jit_exec(), ZJIT hangs # unshareable object are copied assert_equal 'false', %q{ @@ -610,7 +424,7 @@ def test n msg.object_id end - obj.object_id == r.take + obj.object_id == r.value } # To copy the object, now Marshal#dump is used @@ -628,11 +442,12 @@ def test n } # send shareable and unshareable objects -assert_equal "ok", %q{ - echo_ractor = Ractor.new do +assert_equal "ok", <<~'RUBY', frozen_string_literal: false + port = Ractor::Port.new + echo_ractor = Ractor.new port do |port| loop do v = Ractor.receive - Ractor.yield v + port << v end end @@ -680,13 +495,13 @@ module M; end shareable_objects.map{|o| echo_ractor << o - o2 = echo_ractor.take + o2 = port.receive results << "#{o} is copied" unless o.object_id == o2.object_id } unshareable_objects.map{|o| echo_ractor << o - o2 = echo_ractor.take + o2 = port.receive results << "#{o.inspect} is not copied" if o.object_id == o2.object_id } @@ -695,10 +510,10 @@ module M; end else results.inspect end -} +RUBY # frozen Objects are shareable -assert_equal [false, true, false].inspect, %q{ +assert_equal [false, true, false].inspect, <<~'RUBY', frozen_string_literal: false class C def initialize freeze @a = 1 @@ -712,7 +527,7 @@ def initialize freeze def check obj1 obj2 = Ractor.new obj1 do |obj| obj - end.take + end.value obj1.object_id == obj2.object_id end @@ -721,11 +536,11 @@ def check obj1 results << check(C.new(true)) # false results << check(C.new(true).freeze) # true results << check(C.new(false).freeze) # false -} +RUBY # move example2: String # touching moved object causes an error -assert_equal 'hello world', %q{ +assert_equal 'hello world', <<~'RUBY', frozen_string_literal: false # move r = Ractor.new do obj = Ractor.receive @@ -734,7 +549,7 @@ def check obj1 str = 'hello' r.send str, move: true - modified = r.take + modified = r.value begin str << ' exception' # raise Ractor::MovedError @@ -743,7 +558,7 @@ def check obj1 else raise 'unreachable' end -} +RUBY # move example2: Array assert_equal '[0, 1]', %q{ @@ -754,7 +569,7 @@ def check obj1 a1 = [0] r.send a1, move: true - a2 = r.take + a2 = r.value begin a1 << 2 # raise Ractor::MovedError rescue Ractor::MovedError @@ -762,46 +577,15 @@ def check obj1 end } -# move with yield -assert_equal 'hello', %q{ - r = Ractor.new do - Thread.current.report_on_exception = false - obj = 'hello' - Ractor.yield obj, move: true - obj << 'world' - end - - str = r.take - begin - r.take - rescue Ractor::RemoteError - str #=> "hello" - end -} - -# yield/move should not make moved object when the yield is not succeeded -assert_equal '"str"', %q{ - R = Ractor.new{} - M = Ractor.current - r = Ractor.new do - s = 'str' - selected_r, v = Ractor.select R, yield_value: s, move: true - raise if selected_r != R # taken from R - M.send s.inspect # s should not be a moved object - end - - Ractor.receive -} - -# yield/move can fail -assert_equal "allocator undefined for Thread", %q{ +# unshareable frozen objects should still be frozen in new ractor after move +assert_equal 'true', %q{ r = Ractor.new do - obj = Thread.new{} - Ractor.yield obj - rescue => e - e.message + obj = receive + { frozen: obj.frozen? } end - r.take + obj = [Object.new].freeze + r.send(obj, move: true) + r.value[:frozen] } # Access to global-variables are prohibited @@ -812,7 +596,7 @@ def check obj1 end begin - r.take + r.join rescue Ractor::RemoteError => e e.cause.message end @@ -825,7 +609,7 @@ def check obj1 end begin - r.take + r.join rescue Ractor::RemoteError => e e.cause.message end @@ -839,7 +623,7 @@ def check obj1 } end - [$stdin, $stdout, $stderr].zip(r.take){|io, (oid, fno)| + [$stdin, $stdout, $stderr].zip(r.value){|io, (oid, fno)| raise "should not be different object" if io.object_id == oid raise "fd should be same" unless io.fileno == fno } @@ -855,7 +639,7 @@ def check obj1 'ok' end - r.take + r.value } # $DEBUG, $VERBOSE are Ractor local @@ -913,7 +697,7 @@ def ractor_local_globals h = Ractor.new do ractor_local_globals - end.take + end.value ractor_local_globals == h #=> true } @@ -922,7 +706,8 @@ def ractor_local_globals r = Ractor.new do self.object_id end - r.take == self.object_id #=> false + ret = r.value + ret == self.object_id } # self is a Ractor instance @@ -930,7 +715,12 @@ def ractor_local_globals r = Ractor.new do self.object_id end - r.object_id == r.take #=> true + ret = r.value + if r.object_id == ret #=> true + true + else + raise [ret, r.object_id].inspect + end } # given block Proc will be isolated, so can not access outer variables. @@ -946,7 +736,7 @@ def ractor_local_globals } # ivar in shareable-objects are not allowed to access from non-main Ractor -assert_equal "can not get unshareable values from instance variables of classes/modules from non-main Ractors", %q{ +assert_equal "can not get unshareable values from instance variables of classes/modules from non-main Ractors", <<~'RUBY', frozen_string_literal: false class C @iv = 'str' end @@ -957,13 +747,12 @@ class C end end - begin - r.take + r.value rescue Ractor::RemoteError => e e.cause.message end -} +RUBY # ivar in shareable-objects are not allowed to access from non-main Ractor assert_equal 'can not access instance variables of shareable objects from non-main Ractors', %q{ @@ -975,7 +764,7 @@ class C end begin - r.take + r.value rescue Ractor::RemoteError => e e.cause.message end @@ -1001,7 +790,7 @@ def foo end begin - r.take + r.value rescue Ractor::RemoteError => e e.cause.message end @@ -1022,7 +811,7 @@ def setup end begin - r.take + r.value rescue Ractor::RemoteError => e e.cause.message end @@ -1036,7 +825,7 @@ def setup Ractor.new obj do |obj| obj.instance_variable_get('@a') - end.take.to_s + end.value.to_s }.join } @@ -1062,31 +851,66 @@ def self.str = @str def self.fstr = @fstr end - a = Ractor.new{ C.int }.take + a = Ractor.new{ C.int }.value b = Ractor.new do C.str.to_i rescue Ractor::IsolationError 10 - end.take + end.value c = Ractor.new do C.fstr.to_i - end.take + end.value - d = Ractor.new{ M.int }.take + d = Ractor.new{ M.int }.value e = Ractor.new do M.str.to_i rescue Ractor::IsolationError 20 - end.take + end.value f = Ractor.new do M.fstr.to_i - end.take + end.value # 1 + 10 + 100 + 2 + 20 + 200 a + b + c + d + e + f } +assert_equal '["instance-variable", "instance-variable", nil]', %q{ + class C + @iv1 = "" + @iv2 = 42 + def self.iv1 = defined?(@iv1) # "instance-variable" + def self.iv2 = defined?(@iv2) # "instance-variable" + def self.iv3 = defined?(@iv3) # nil + end + + Ractor.new{ + [C.iv1, C.iv2, C.iv3] + }.value +} + +# moved objects have their shape properly set to original object's shape +assert_equal '1234', %q{ + class Obj + attr_accessor :a, :b, :c, :d + def initialize + @a = 1 + @b = 2 + @c = 3 + end + end + r = Ractor.new do + obj = receive + obj.d = 4 + [obj.a, obj.b, obj.c, obj.d] + end + obj = Obj.new + r.send(obj, move: true) + values = r.value + values.join +} + # cvar in shareable-objects are not allowed to access from non-main Ractor assert_equal 'can not access class variables from non-main Ractors', %q{ class C @@ -1100,7 +924,7 @@ class C end begin - r.take + r.join rescue Ractor::RemoteError => e e.cause.message end @@ -1122,14 +946,14 @@ def self.cv end begin - r.take + r.join rescue Ractor::RemoteError => e e.cause.message end } # Getting non-shareable objects via constants by other Ractors is not allowed -assert_equal 'can not access non-shareable objects in constant C::CONST by non-main Ractor.', %q{ +assert_equal 'can not access non-shareable objects in constant C::CONST by non-main Ractor.', <<~'RUBY', frozen_string_literal: false class C CONST = 'str' end @@ -1137,44 +961,44 @@ class C C::CONST end begin - r.take + r.join rescue Ractor::RemoteError => e e.cause.message end -} + RUBY # Constant cache should care about non-sharable constants -assert_equal "can not access non-shareable objects in constant Object::STR by non-main Ractor.", %q{ +assert_equal "can not access non-shareable objects in constant Object::STR by non-main Ractor.", <<~'RUBY', frozen_string_literal: false STR = "hello" def str; STR; end s = str() # fill const cache begin - Ractor.new{ str() }.take + Ractor.new{ str() }.join rescue Ractor::RemoteError => e e.cause.message end -} +RUBY # Setting non-shareable objects into constants by other Ractors is not allowed -assert_equal 'can not set constants with non-shareable objects by non-main Ractors', %q{ +assert_equal 'can not set constants with non-shareable objects by non-main Ractors', <<~'RUBY', frozen_string_literal: false class C end r = Ractor.new do C::CONST = 'str' end begin - r.take + r.join rescue Ractor::RemoteError => e e.cause.message end -} +RUBY # define_method is not allowed assert_equal "defined with an un-shareable Proc in a different Ractor", %q{ str = "foo" define_method(:buggy){|i| str << "#{i}"} begin - Ractor.new{buggy(10)}.take + Ractor.new{buggy(10)}.join rescue => e e.cause.message end @@ -1185,7 +1009,7 @@ class C A = Array.new(1000).freeze # [nil, ...] H = {a: 1, b: 2, c: 3}.freeze - Ractor.new{ [A.size, H.size] }.take + Ractor.new{ [A.size, H.size] }.value } # Ractor.count @@ -1195,15 +1019,15 @@ class C ractors = (1..3).map { Ractor.new { Ractor.receive } } counts << Ractor.count - ractors[0].send('End 0').take + ractors[0].send('End 0').join sleep 0.1 until ractors[0].inspect =~ /terminated/ counts << Ractor.count - ractors[1].send('End 1').take + ractors[1].send('End 1').join sleep 0.1 until ractors[1].inspect =~ /terminated/ counts << Ractor.count - ractors[2].send('End 2').take + ractors[2].send('End 2').join sleep 0.1 until ractors[2].inspect =~ /terminated/ counts << Ractor.count @@ -1216,11 +1040,11 @@ class C n = 0 ObjectSpace.each_object{|o| n += 1 unless Ractor.shareable?(o)} n - }.take + }.value } # ObjectSpace._id2ref can not handle unshareable objects with Ractors -assert_equal 'ok', %q{ +assert_equal 'ok', <<~'RUBY', frozen_string_literal: false s = 'hello' Ractor.new s.object_id do |id ;s| @@ -1229,11 +1053,11 @@ class C rescue => e :ok end - end.take -} + end.value +RUBY # Ractor.make_shareable(obj) -assert_equal 'true', %q{ +assert_equal 'true', <<~'RUBY', frozen_string_literal: false class C def initialize @a = 'foo' @@ -1304,7 +1128,7 @@ def /(other) } Ractor.shareable?(a) -} +RUBY # Ractor.make_shareable(obj) doesn't freeze shareable objects assert_equal 'true', %q{ @@ -1328,6 +1152,28 @@ def /(other) Ractor.shareable?(pr) } +# Ractor.make_shareable(a_proc) makes inner structure shareable and freezes it +assert_equal 'true,true,true,true', %q{ + class Proc + attr_reader :obj + def initialize + @obj = Object.new + end + end + + pr = Ractor.current.instance_eval do + Proc.new {} + end + + results = [] + Ractor.make_shareable(pr) + results << Ractor.shareable?(pr) + results << pr.frozen? + results << Ractor.shareable?(pr.obj) + results << pr.obj.frozen? + results.map(&:to_s).join(',') +} + # Ractor.shareable?(recursive_objects) assert_equal '[false, false]', %q{ y = [] @@ -1356,6 +1202,21 @@ module M; end Ractor.make_shareable(ary = [C, M]) } +# Ractor.make_shareable with curried proc checks isolation of original proc +assert_equal 'isolation error', %q{ + a = Object.new + orig = proc { a } + curried = orig.curry + + begin + Ractor.make_shareable(curried) + rescue Ractor::IsolationError + 'isolation error' + else + 'no error' + end +} + # define_method() can invoke different Ractor's proc if the proc is shareable. assert_equal '1', %q{ class C @@ -1364,7 +1225,7 @@ class C a = 2 end - Ractor.new{ C.new.foo }.take + Ractor.new{ C.new.foo }.value } # Ractor.make_shareable(a_proc) makes a proc shareable. @@ -1401,14 +1262,14 @@ class C } # TracePoint with normal Proc should be Ractor local -assert_equal '[4, 8]', %q{ +assert_equal '[6, 10]', %q{ rs = [] TracePoint.new(:line){|tp| rs << tp.lineno if tp.path == __FILE__}.enable do - Ractor.new{ # line 4 + Ractor.new{ # line 5 a = 1 b = 2 - }.take - c = 3 # line 8 + }.value + c = 3 # line 9 end rs } @@ -1417,7 +1278,7 @@ class C assert_equal '[true, false]', %q{ Ractor.new([[]].freeze) { |ary| [ary.frozen?, ary.first.frozen? ] - }.take + }.value } # Ractor deep copies frozen objects (str) @@ -1425,7 +1286,7 @@ class C s = String.new.instance_eval { @x = []; freeze} Ractor.new(s) { |s| [s.frozen?, s.instance_variable_get(:@x).frozen?] - }.take + }.value } # Can not trap with not isolated Proc on non-main ractor @@ -1433,33 +1294,85 @@ class C a = [] Ractor.new{ trap(:INT){p :ok} - }.take + }.join a << :ok begin Ractor.new{ s = 'str' trap(:INT){p s} - }.take + }.join rescue => Ractor::RemoteError a << :ok end } +# Ractor.select is interruptible +assert_normal_exit %q{ + trap(:INT) do + exit + end + + r = Ractor.new do + loop do + sleep 1 + end + end + + Thread.new do + sleep 0.5 + Process.kill(:INT, Process.pid) + end + Ractor.select(r) +} + # Ractor-local storage assert_equal '[nil, "b", "a"]', %q{ ans = [] Ractor.current[:key] = 'a' r = Ractor.new{ - Ractor.yield self[:key] + Ractor.main << self[:key] self[:key] = 'b' self[:key] } - ans << r.take - ans << r.take + ans << Ractor.receive + ans << r.value ans << Ractor.current[:key] } +assert_equal '1', %q{ + N = 1_000 + Ractor.new{ + a = [] + 1_000.times.map{|i| + Thread.new(i){|i| + Thread.pass if i < N + a << Ractor.store_if_absent(:i){ i } + a << Ractor.current[:i] + } + }.each(&:join) + a.uniq.size + }.value +} + +# Ractor-local storage +assert_equal '2', %q{ + Ractor.new { + fails = 0 + begin + Ractor.main[:key] # cannot get ractor local storage from non-main ractor + rescue => e + fails += 1 if e.message =~ /Cannot get ractor local/ + end + begin + Ractor.main[:key] = 'val' + rescue => e + fails += 1 if e.message =~ /Cannot set ractor local/ + end + fails + }.value +} + ### ### Synchronization tests ### @@ -1473,23 +1386,38 @@ class C Ractor.new{ N.times{|i| -(i.to_s)} } - }.map{|r| r.take}.join + }.map{|r| r.value}.join +} + +assert_equal "ok", %Q{ + N = #{N} + a, b = 2.times.map{ + Ractor.new{ + N.times.map{|i| -(i.to_s)} + } + }.map{|r| r.value} + N.times do |i| + unless a[i].equal?(b[i]) + raise [a[i], b[i]].inspect + end + end + :ok } -# Generic ivtbl +# Generic fields_tbl n = N/2 assert_equal "#{n}#{n}", %Q{ 2.times.map{ Ractor.new do #{n}.times do - obj = '' + obj = +'' obj.instance_variable_set("@a", 1) obj.instance_variable_set("@b", 1) obj.instance_variable_set("@c", 1) obj.instance_variable_defined?("@a") end end - }.map{|r| r.take}.join + }.map{|r| r.value}.join } # NameError @@ -1521,18 +1449,19 @@ class C # Can yield back values while GC is sweeping [Bug #18117] assert_equal "ok", %q{ + port = Ractor::Port.new workers = (0...8).map do - Ractor.new do + Ractor.new port do |port| loop do 10_000.times.map { Object.new } - Ractor.yield Time.now + port << Time.now end end end - 1_000.times { idle_worker, tmp_reporter = Ractor.select(*workers) } + 1_000.times { port.receive } "ok" -} unless ENV['RUN_OPTS'] =~ /rjit/ # flaky +} if !yjit_enabled? && ENV['GITHUB_WORKFLOW'] != 'ModGC' # flaky assert_equal "ok", %q{ def foo(*); ->{ super }; end @@ -1633,26 +1562,48 @@ class C8; def self.foo = 17; end } n = CS.inject(1){|r, c| r * c.foo} * LN - rs.map{|r| r.take} == Array.new(RN){n} + rs.map{|r| r.value} == Array.new(RN){n} } # check experimental warning assert_match /\Atest_ractor\.rb:1:\s+warning:\s+Ractor is experimental/, %q{ Warning[:experimental] = $VERBOSE = true STDERR.reopen(STDOUT) - eval("Ractor.new{}.take", nil, "test_ractor.rb", 1) + eval("Ractor.new{}.value", nil, "test_ractor.rb", 1) +}, frozen_string_literal: false + +# check moved object +assert_equal 'ok', %q{ + r = Ractor.new do + Ractor.receive + GC.start + :ok + end + + obj = begin + raise + rescue => e + e = Marshal.load(Marshal.dump(e)) + end + + r.send obj, move: true + r.value } ## Ractor::Selector # Selector#empty? returns true assert_equal 'true', %q{ + skip true unless defined? Ractor::Selector + s = Ractor::Selector.new s.empty? } # Selector#empty? returns false if there is target ractors assert_equal 'false', %q{ + skip false unless defined? Ractor::Selector + s = Ractor::Selector.new s.add Ractor.new{} s.empty? @@ -1660,6 +1611,8 @@ class C8; def self.foo = 17; end # Selector#clear removes all ractors from the waiting list assert_equal 'true', %q{ + skip true unless defined? Ractor::Selector + s = Ractor::Selector.new s.add Ractor.new{10} s.add Ractor.new{20} @@ -1669,6 +1622,8 @@ class C8; def self.foo = 17; end # Selector#wait can wait multiple ractors assert_equal '[10, 20, true]', %q{ + skip [10, 20, true] unless defined? Ractor::Selector + s = Ractor::Selector.new s.add Ractor.new{10} s.add Ractor.new{20} @@ -1678,10 +1633,12 @@ class C8; def self.foo = 17; end r, v = s.wait vs << v [*vs.sort, s.empty?] -} +} if defined? Ractor::Selector # Selector#wait can wait multiple ractors with receiving. assert_equal '30', %q{ + skip 30 unless defined? Ractor::Selector + RN = 30 rs = RN.times.map{ Ractor.new{ :v } @@ -1698,17 +1655,19 @@ class C8; def self.foo = 17; end end results.size -} +} if defined? Ractor::Selector # Selector#wait can support dynamic addition -yjit_enabled = ENV.key?('RUBY_YJIT_ENABLE') || ENV.fetch('RUN_OPTS', '').include?('yjit') || BT.ruby.include?('yjit') assert_equal '600', %q{ + skip 600 unless defined? Ractor::Selector + RN = 100 s = Ractor::Selector.new + port = Ractor::Port.new rs = RN.times.map{ Ractor.new{ - Ractor.main << Ractor.new{ Ractor.yield :v3; :v4 } - Ractor.main << Ractor.new{ Ractor.yield :v5; :v6 } + Ractor.main << Ractor.new(port){|port| port << :v3; :v4 } + Ractor.main << Ractor.new(port){|port| port << :v5; :v6 } Ractor.yield :v1 :v2 } @@ -1728,10 +1687,12 @@ class C8; def self.foo = 17; end end h.sum{|k, v| v} -} unless yjit_enabled # http://ci.rvm.jp/results/trunk-yjit@ruby-sp2-docker/4466770 +} unless yjit_enabled? # http://ci.rvm.jp/results/trunk-yjit@ruby-sp2-docker/4466770 # Selector should be GCed (free'ed) without trouble assert_equal 'ok', %q{ + skip :ok unless defined? Ractor::Selector + RN = 30 rs = RN.times.map{ Ractor.new{ :v } @@ -1741,3 +1702,608 @@ class C8; def self.foo = 17; end } end # if !ENV['GITHUB_WORKFLOW'] + +# Chilled strings are not shareable +assert_equal 'false', %q{ + Ractor.shareable?("chilled") +} + +# Chilled strings can be made shareable +assert_equal 'true', %q{ + shareable = Ractor.make_shareable("chilled") + shareable == "chilled" && Ractor.shareable?(shareable) +} + +# require in Ractor +assert_equal 'true', %q{ + Module.new do + def require feature + return Ractor._require(feature) unless Ractor.main? + super + end + Object.prepend self + set_temporary_name 'Ractor#require' + end + + Ractor.new{ + begin + require 'tempfile' + Tempfile.new + rescue SystemStackError + # prism parser with -O0 build consumes a lot of machine stack + Data.define(:fileno).new(1) + end + }.value.fileno > 0 +} + +# require_relative in Ractor +assert_equal 'true', %q{ + dummyfile = File.join(__dir__, "dummy#{rand}.rb") + return true if File.exist?(dummyfile) + + begin + File.write dummyfile, '' + rescue Exception + # skip on any errors + return true + end + + begin + Ractor.new dummyfile do |f| + require_relative File.basename(f) + end.value + ensure + File.unlink dummyfile + end +} + +# require_relative in Ractor +assert_equal 'LoadError', %q{ + dummyfile = File.join(__dir__, "not_existed_dummy#{rand}.rb") + return true if File.exist?(dummyfile) + + Ractor.new dummyfile do |f| + begin + require_relative File.basename(f) + rescue LoadError => e + e.class + end + end.value +} + +# autolaod in Ractor +assert_equal 'true', %q{ + autoload :Tempfile, 'tempfile' + + r = Ractor.new do + begin + Tempfile.new + rescue SystemStackError + # prism parser with -O0 build consumes a lot of machine stack + Data.define(:fileno).new(1) + end + end + r.value.fileno > 0 +} + +# failed in autolaod in Ractor +assert_equal 'LoadError', %q{ + dummyfile = File.join(__dir__, "not_existed_dummy#{rand}.rb") + autoload :Tempfile, dummyfile + + r = Ractor.new do + begin + Tempfile.new + rescue LoadError => e + e.class + end + end + r.value +} + +# bind_call in Ractor [Bug #20934] +assert_equal 'ok', %q{ + 2.times.map do + Ractor.new do + 1000.times do + Object.instance_method(:itself).bind_call(self) + end + end + end.each(&:join) + GC.start + :ok.itself +} + +# moved objects being corrupted if embeded (String) +assert_equal 'ok', %q{ + ractor = Ractor.new { Ractor.receive } + obj = "foobarbazfoobarbazfoobarbazfoobarbaz" + ractor.send(obj.dup, move: true) + roundtripped_obj = ractor.value + roundtripped_obj == obj ? :ok : roundtripped_obj +} + +# moved objects being corrupted if embeded (Array) +assert_equal 'ok', %q{ + ractor = Ractor.new { Ractor.receive } + obj = Array.new(10, 42) + ractor.send(obj.dup, move: true) + roundtripped_obj = ractor.value + roundtripped_obj == obj ? :ok : roundtripped_obj +} + +# moved objects being corrupted if embeded (Hash) +assert_equal 'ok', %q{ + ractor = Ractor.new { Ractor.receive } + obj = { foo: 1, bar: 2 } + ractor.send(obj.dup, move: true) + roundtripped_obj = ractor.value + roundtripped_obj == obj ? :ok : roundtripped_obj +} + +# moved objects being corrupted if embeded (MatchData) +assert_equal 'ok', %q{ + ractor = Ractor.new { Ractor.receive } + obj = "foo".match(/o/) + ractor.send(obj.dup, move: true) + roundtripped_obj = ractor.value + roundtripped_obj == obj ? :ok : roundtripped_obj +} + +# moved objects being corrupted if embeded (Struct) +assert_equal 'ok', %q{ + ractor = Ractor.new { Ractor.receive } + obj = Struct.new(:a, :b, :c, :d, :e, :f).new(1, 2, 3, 4, 5, 6) + ractor.send(obj.dup, move: true) + roundtripped_obj = ractor.value + roundtripped_obj == obj ? :ok : roundtripped_obj +} + +# moved objects being corrupted if embeded (Object) +assert_equal 'ok', %q{ + ractor = Ractor.new { Ractor.receive } + class SomeObject + attr_reader :a, :b, :c, :d, :e, :f + def initialize + @a = @b = @c = @d = @e = @f = 1 + end + + def ==(o) + @a == o.a && + @b == o.b && + @c == o.c && + @d == o.d && + @e == o.e && + @f == o.f + end + end + + SomeObject.new # initial non-embeded + + obj = SomeObject.new + ractor.send(obj.dup, move: true) + roundtripped_obj = ractor.value + roundtripped_obj == obj ? :ok : roundtripped_obj +} + +# moved arrays can't be used +assert_equal 'ok', %q{ + ractor = Ractor.new { Ractor.receive } + obj = [1] + ractor.send(obj, move: true) + begin + [].concat(obj) + rescue TypeError + :ok + else + :fail + end +} + +# moved strings can't be used +assert_equal 'ok', %q{ + ractor = Ractor.new { Ractor.receive } + obj = "hello" + ractor.send(obj, move: true) + begin + "".replace(obj) + rescue TypeError + :ok + else + :fail + end +} + +# moved hashes can't be used +assert_equal 'ok', %q{ + ractor = Ractor.new { Ractor.receive } + obj = { a: 1 } + ractor.send(obj, move: true) + begin + {}.merge(obj) + rescue TypeError + :ok + else + :fail + end +} + +# move objects inside frozen containers +assert_equal 'ok', %q{ + ractor = Ractor.new { Ractor.receive } + obj = Array.new(10, 42) + original = obj.dup + ractor.send([obj].freeze, move: true) + roundtripped_obj = ractor.value[0] + roundtripped_obj == original ? :ok : roundtripped_obj +} + +# move object with generic ivar +assert_equal 'ok', %q{ + ractor = Ractor.new { Ractor.receive } + obj = Array.new(10, 42) + obj.instance_variable_set(:@array, [1]) + + ractor.send(obj, move: true) + roundtripped_obj = ractor.value + roundtripped_obj.instance_variable_get(:@array) == [1] ? :ok : roundtripped_obj +} + +# move object with many generic ivars +assert_equal 'ok', %q{ + ractor = Ractor.new { Ractor.receive } + obj = Array.new(10, 42) + 0.upto(300) do |i| + obj.instance_variable_set(:"@array#{i}", [i]) + end + + ractor.send(obj, move: true) + roundtripped_obj = ractor.value + roundtripped_obj.instance_variable_get(:@array1) == [1] ? :ok : roundtripped_obj +} + +# move object with complex generic ivars +assert_equal 'ok', %q{ + # Make Array too_complex + 30.times { |i| [].instance_variable_set(:"@complex#{i}", 1) } + + ractor = Ractor.new { Ractor.receive } + obj = Array.new(10, 42) + obj.instance_variable_set(:@array1, [1]) + + ractor.send(obj, move: true) + roundtripped_obj = ractor.value + roundtripped_obj.instance_variable_get(:@array1) == [1] ? :ok : roundtripped_obj +} + +# copy object with complex generic ivars +assert_equal 'ok', %q{ + # Make Array too_complex + 30.times { |i| [].instance_variable_set(:"@complex#{i}", 1) } + + ractor = Ractor.new { Ractor.receive } + obj = Array.new(10, 42) + obj.instance_variable_set(:@array1, [1]) + + ractor.send(obj) + roundtripped_obj = ractor.value + roundtripped_obj.instance_variable_get(:@array1) == [1] ? :ok : roundtripped_obj +} + +# copy object with many generic ivars +assert_equal 'ok', %q{ + ractor = Ractor.new { Ractor.receive } + obj = Array.new(10, 42) + 0.upto(300) do |i| + obj.instance_variable_set(:"@array#{i}", [i]) + end + + ractor.send(obj) + roundtripped_obj = ractor.value + roundtripped_obj.instance_variable_get(:@array1) == [1] ? :ok : roundtripped_obj +} + +# moved composite types move their non-shareable parts properly +assert_equal 'ok', %q{ + k, v = String.new("key"), String.new("value") + h = { k => v } + h.instance_variable_set("@b", String.new("b")) + a = [k,v] + o_singleton = Object.new + def o_singleton.a + @a + end + o_singleton.instance_variable_set("@a", String.new("a")) + class MyObject + attr_reader :a + def initialize(a) + @a = a + end + end + struct_class = Struct.new(:a) + struct = struct_class.new(String.new('a')) + o = MyObject.new(String.new('a')) + port = Ractor::Port.new + + r = Ractor.new port do |port| + loop do + obj = Ractor.receive + val = case obj + when Hash + obj['key'] == 'value' && obj.instance_variable_get("@b") == 'b' + when Array + obj[0] == 'key' + when Struct + obj.a == 'a' + when Object + obj.a == 'a' + end + port << val + end + end + + objs = [h, a, o_singleton, o, struct] + objs.each_with_index do |obj, i| + klass = obj.class + parts_moved = {} + case obj + when Hash + parts_moved[klass] = [obj['key'], obj.instance_variable_get("@b")] + when Array + parts_moved[klass] = obj.dup # the contents + when Struct, Object + parts_moved[klass] = [obj.a] + end + r.send(obj, move: true) + val = port.receive + if val != true + raise "bad val in ractor for obj at i:#{i}" + end + begin + p obj + rescue + else + raise "should be moved" + end + parts_moved.each do |klass, parts| + parts.each_with_index do |part, j| + case part + when Ractor::MovedObject + else + raise "part for class #{klass} at i:#{j} should be moved" + end + end + end + end + 'ok' +} + +# fork after creating Ractor +assert_equal 'ok', %q{ +begin + Ractor.new { Ractor.receive } + _, status = Process.waitpid2 fork { } + status.success? ? "ok" : status +rescue NotImplementedError + :ok +end +} + +# Ractors should be terminated after fork +assert_equal 'ok', %q{ +begin + r = Ractor.new { Ractor.receive } + _, status = Process.waitpid2 fork { + begin + raise if r.value != nil + end + } + r.send(123) + raise unless r.value == 123 + status.success? ? "ok" : status +rescue NotImplementedError + :ok +end +} + +# Ractors should be terminated after fork +assert_equal 'ok', %q{ +begin + r = Ractor.new { Ractor.receive } + _, status = Process.waitpid2 fork { + begin + r.send(123) + rescue Ractor::ClosedError + end + } + r.send(123) + raise unless r.value == 123 + status.success? ? "ok" : status +rescue NotImplementedError + :ok +end +} + +# Creating classes inside of Ractors +# [Bug #18119] +assert_equal 'ok', %q{ + port = Ractor::Port.new + workers = (0...8).map do + Ractor.new port do |port| + loop do + 100.times.map { Class.new } + port << nil + end + end + end + + 100.times { port.receive } + + 'ok' +} + +# Using Symbol#to_proc inside ractors +# [Bug #21354] +assert_equal 'ok', %q{ + :inspect.to_proc + Ractor.new do + # It should not use this cached proc, it should create a new one. If it used + # the cached proc, we would get a ractor_confirm_belonging error here. + :inspect.to_proc + end.join + 'ok' +} + +# take vm lock when deleting generic ivars from the global table +assert_equal 'ok', %q{ + Ractor.new do + a = [1, 2, 3] + a.object_id + a.dup # this deletes generic ivar on dupped object + 'ok' + end.value +} + +## Ractor#monitor + +# monitor port returns `:exited` when the monitering Ractor terminated. +assert_equal 'true', %q{ + r = Ractor.new do + Ractor.main << :ok1 + :ok2 + end + + r.monitor port = Ractor::Port.new + Ractor.receive # :ok1 + port.receive == :exited +} + +# monitor port returns `:exited` even if the monitoring Ractor was terminated. +assert_equal 'true', %q{ + r = Ractor.new do + :ok + end + + r.join # wait for r's terminateion + + r.monitor port = Ractor::Port.new + port.receive == :exited +} + +# monitor returns false if the monitoring Ractor was terminated. +assert_equal 'false', %q{ + r = Ractor.new do + :ok + end + + r.join # wait for r's terminateion + + r.monitor Ractor::Port.new +} + +# monitor port returns `:aborted` when the monitering Ractor is aborted. +assert_equal 'true', %q{ + r = Ractor.new do + Ractor.main << :ok1 + raise 'ok' + end + + r.monitor port = Ractor::Port.new + Ractor.receive # :ok1 + port.receive == :aborted +} + +# monitor port returns `:aborted` even if the monitoring Ractor was aborted. +assert_equal 'true', %q{ + r = Ractor.new do + raise 'ok' + end + + begin + r.join # wait for r's terminateion + rescue Ractor::RemoteError + # ignore + end + + r.monitor port = Ractor::Port.new + port.receive == :aborted +} + +## Ractor#join + +# Ractor#join returns self when the Ractor is terminated. +assert_equal 'true', %q{ + r = Ractor.new do + Ractor.receive + end + + r << :ok + r.join + r.inspect in /terminated/ +} if false # TODO + +# Ractor#join raises RemoteError when the remote Ractor aborted with an exception +assert_equal 'err', %q{ + r = Ractor.new do + raise 'err' + end + + begin + r.join + rescue Ractor::RemoteError => e + e.cause.message + end +} + +## Ractor#value + +# Ractor#value returns the last expression even if it is unshareable +assert_equal 'true', %q{ + r = Ractor.new do + obj = [1, 2] + obj << obj.object_id + end + + ret = r.value + ret == [1, 2, ret.object_id] +} + +# Only one Ractor can call Ractor#value +assert_equal '[["Only the successor ractor can take a value", 9], ["ok", 2]]', %q{ + r = Ractor.new do + 'ok' + end + + RN = 10 + + rs = RN.times.map do + Ractor.new r do |r| + begin + Ractor.main << r.value + Ractor.main << r.value # this ractor can get same result + rescue Ractor::Error => e + Ractor.main << e.message + end + end + end + + (RN+1).times.map{ + Ractor.receive + }.tally.sort +} + +# Ractor#take will warn for compatibility. +# This method will be removed after 2025/09/01 +assert_equal "2", %q{ + raise "remove Ractor#take and this test" if Time.now > Time.new(2025, 9, 2) + $VERBOSE = true + r = Ractor.new{42} + $msg = [] + def Warning.warn(msg) + $msg << msg + end + r.take + r.take + raise unless $msg.all?{/Ractor#take/ =~ it} + $msg.size +} diff --git a/bootstraptest/test_rjit.rb b/bootstraptest/test_rjit.rb deleted file mode 100644 index 464af7a6e6a65a..00000000000000 --- a/bootstraptest/test_rjit.rb +++ /dev/null @@ -1,44 +0,0 @@ -# VM_CALL_OPT_SEND + VM_METHOD_TYPE_ATTRSET -assert_equal '1', %q{ - class Foo - attr_writer :foo - - def bar - send(:foo=, 1) - end - end - - Foo.new.bar -} - -# VM_CALL_OPT_SEND + OPTIMIZED_METHOD_TYPE_CALL -assert_equal 'foo', %q{ - def bar(&foo) - foo.send(:call) - end - - bar { :foo } -} - -# VM_CALL_OPT_SEND + OPTIMIZED_METHOD_TYPE_STRUCT_AREF -assert_equal 'bar', %q{ - def bar(foo) - foo.send(:bar) - end - - bar(Struct.new(:bar).new(:bar)) -} - -# kwargs default w/ checkkeyword + locals (which shouldn't overwrite unspecified_bits) -assert_equal '1', %q{ - def foo(bar: 1.to_s) - _ = 1 - bar - end - - def entry - foo - end - - entry -} diff --git a/bootstraptest/test_syntax.rb b/bootstraptest/test_syntax.rb index 948e2d7809ee24..fbc9c6f62e377a 100644 --- a/bootstraptest/test_syntax.rb +++ b/bootstraptest/test_syntax.rb @@ -528,24 +528,24 @@ def lines i } def assert_syntax_error expected, code, message = '' - assert_equal "#{expected}", - "begin eval(%q{#{code}}, nil, '', 0)"'; rescue SyntaxError => e; e.message[/\A:(?:\d+:)? (.*)/, 1] end', message + assert_match /^#{Regexp.escape(expected)}/, + "begin eval(%q{#{code}}, nil, '', 0)"'; rescue SyntaxError => e; e.message[/(?:\^~*|\A:(?:\d+:)?(?! syntax errors? found)(?: syntax error,)?) (.*)/, 1] end', message end assert_syntax_error "unterminated string meets end of file", '().."', '[ruby-dev:29732]' assert_equal %q{[]}, %q{$&;[]}, '[ruby-dev:31068]' -assert_syntax_error "syntax error, unexpected *, expecting '}'", %q{{*0}}, '[ruby-dev:31072]' -assert_syntax_error "`@0' is not allowed as an instance variable name", %q{@0..0}, '[ruby-dev:31095]' -assert_syntax_error "identifier $00 is not valid to get", %q{$00..0}, '[ruby-dev:31100]' -assert_syntax_error "identifier $00 is not valid to set", %q{0..$00=1} +assert_syntax_error "unexpected *, expecting '}'", %q{{*0}}, '[ruby-dev:31072]' +assert_syntax_error "'@0' is not allowed as an instance variable name", %q{@0..0}, '[ruby-dev:31095]' +assert_syntax_error "'$00' is not allowed as a global variable name", %q{$00..0}, '[ruby-dev:31100]' +assert_syntax_error "'$00' is not allowed as a global variable name", %q{0..$00=1} assert_equal %q{0}, %q{[*0];0}, '[ruby-dev:31102]' -assert_syntax_error "syntax error, unexpected ')'", %q{v0,(*,v1,) = 0}, '[ruby-dev:31104]' +assert_syntax_error "unexpected ')'", %q{v0,(*,v1,) = 0}, '[ruby-dev:31104]' assert_equal %q{1}, %q{ class << (ary=[]); def []; 0; end; def []=(x); super(0,x);end;end; ary[]+=1 }, '[ruby-dev:31110]' assert_syntax_error "Can't set variable $1", %q{0..$1=1}, '[ruby-dev:31118]' assert_valid_syntax %q{1.times{1+(1&&next)}}, '[ruby-dev:31119]' assert_valid_syntax %q{x=-1;loop{x+=1&&redo if (x+=1).zero?}}, '[ruby-dev:31119]' -assert_syntax_error %q{syntax error, unexpected end-of-input}, %q{!}, '[ruby-dev:31243]' +assert_syntax_error %q{unexpected end-of-input}, %q{!}, '[ruby-dev:31243]' assert_equal %q{[nil]}, %q{[()]}, '[ruby-dev:31252]' assert_equal %q{true}, %q{!_=()}, '[ruby-dev:31263]' assert_equal 'ok', %q{while true; redo; end if 1 == 2; :ok}, '[ruby-dev:31360]' @@ -629,7 +629,7 @@ class << (ary=[]); def []; 0; end; def []=(x); super(0,x);end;end; ary[]+=1 assert_match /invalid multibyte char/, %q{ $stderr = STDOUT - eval("\"\xf0".force_encoding("utf-8")) + eval("\"\xf0".dup.force_encoding("utf-8")) }, '[ruby-dev:32429]' # method ! and != @@ -904,3 +904,35 @@ def foo(&block) Class end }, '[ruby-core:30293]' + +assert_equal "false", <<~RUBY, "literal strings are mutable", "--disable-frozen-string-literal" + 'test'.frozen? +RUBY + +assert_equal "true", <<~RUBY, "literal strings are frozen", "--disable-frozen-string-literal", frozen_string_literal: true + 'test'.frozen? +RUBY + +assert_equal "true", <<~RUBY, "literal strings are frozen", "--enable-frozen-string-literal" + 'test'.frozen? +RUBY + +assert_equal "false", <<~RUBY, "literal strings are mutable", "--enable-frozen-string-literal", frozen_string_literal: false + 'test'.frozen? +RUBY + +assert_equal "false", <<~RUBY, "__FILE__ is mutable", "--disable-frozen-string-literal" + __FILE__.frozen? +RUBY + +assert_equal "true", <<~RUBY, "__FILE__ is frozen", "--disable-frozen-string-literal", frozen_string_literal: true + __FILE__.frozen? +RUBY + +assert_equal "true", <<~RUBY, "__FILE__ is frozen", "--enable-frozen-string-literal" + __FILE__.frozen? +RUBY + +assert_equal "false", <<~RUBY, "__FILE__ is mutable", "--enable-frozen-string-literal", frozen_string_literal: false + __FILE__.frozen? +RUBY diff --git a/bootstraptest/test_thread.rb b/bootstraptest/test_thread.rb index 0c163d0db02dca..7ff5bb4a38fb59 100644 --- a/bootstraptest/test_thread.rb +++ b/bootstraptest/test_thread.rb @@ -242,9 +242,22 @@ end } +assert_equal 'true', %{ + Thread.new{}.join + begin + Process.waitpid2 fork{ + Thread.new{ + sleep 0.1 + }.join + } + true + rescue NotImplementedError + true + end +} + assert_equal 'ok', %{ - open("zzz_t1.rb", "w") do |f| - f.puts <<-END + File.write("zzz_t1.rb", <<-END) begin Thread.new { fork { GC.start } }.join pid, status = Process.wait2 @@ -253,7 +266,6 @@ $result = :ok end END - end require "./zzz_t1.rb" $result } @@ -279,7 +291,6 @@ exec "/" } -rjit_enabled = RUBY_DESCRIPTION.include?('+RJIT') assert_normal_exit %q{ (0..10).map { Thread.new { @@ -290,7 +301,7 @@ }.each {|t| t.join } -} unless rjit_enabled # flaky +} assert_equal 'ok', %q{ def m @@ -409,8 +420,7 @@ def m } assert_equal 'ok', %{ - open("zzz_t2.rb", "w") do |f| - f.puts <<-'end;' # do + File.write("zzz_t2.rb", <<-'end;') # do begin m = Thread::Mutex.new parent = Thread.current @@ -432,7 +442,6 @@ def m $result = :ok end end; - end require "./zzz_t2.rb" $result } @@ -484,7 +493,8 @@ def m [th1, th2].each {|t| t.join } GC.start f.call.source -} unless rjit_enabled # flaky +} + assert_normal_exit %q{ class C def inspect diff --git a/bootstraptest/test_yjit.rb b/bootstraptest/test_yjit.rb index 3c53641f91e2fb..d480369c759119 100644 --- a/bootstraptest/test_yjit.rb +++ b/bootstraptest/test_yjit.rb @@ -1,3 +1,181 @@ +# To run the tests in this file only, with YJIT enabled: +# make btest BTESTS=bootstraptest/test_yjit.rb RUN_OPTS="--yjit-call-threshold=1" + +# regression test for popping before side exit +assert_equal "ok", %q{ + def foo(a, *) = a + + def call(args, &) + foo(1) # spill at where the block arg will be + foo(*args, &) + end + + call([1, 2]) + + begin + call([]) + rescue ArgumentError + :ok + end +} + +# regression test for send processing before side exit +assert_equal "ok", %q{ + def foo(a, *) = :foo + + def call(args) + send(:foo, *args) + end + + call([1, 2]) + + begin + call([]) + rescue ArgumentError + :ok + end +} + +# test discarding extra yield arguments +assert_equal "22131300500015901015", %q{ + def splat_kw(ary) = yield *ary, a: 1 + + def splat(ary) = yield *ary + + def kw = yield 1, 2, a: 3 + + def kw_only = yield a: 0 + + def simple = yield 0, 1 + + def none = yield + + def calls + [ + splat([1, 1, 2]) { |x, y| x + y }, + splat([1, 1, 2]) { |y, opt = raise| opt + y}, + splat_kw([0, 1]) { |a:| a }, + kw { |a:| a }, + kw { |one| one }, + kw { |one, a:| a }, + kw_only { |a:| a }, + kw_only { |a: 1| a }, + simple { 5.itself }, + simple { |a| a }, + simple { |opt = raise| opt }, + simple { |*rest| rest }, + simple { |opt_kw: 5| opt_kw }, + none { |a: 9| a }, + # autosplat ineractions + [0, 1, 2].yield_self { |a, b| [a, b] }, + [0, 1, 2].yield_self { |a, opt = raise| [a, opt] }, + [1].yield_self { |a, opt = 4| a + opt }, + ] + end + + calls.join +} + +# test autosplat with empty splat +assert_equal "ok", %q{ + def m(pos, splat) = yield pos, *splat + + m([:ok], []) {|v0,| v0 } +} + +# regression test for send stack shifting +assert_normal_exit %q{ + def foo(a, b) + a.singleton_methods(b) + end + + def call_foo + [1, 1, 1, 1, 1, 1, send(:foo, 1, 1)] + end + + call_foo +} + +# regression test for keyword splat with yield +assert_equal 'nil', %q{ + def splat_kw(kwargs) = yield(**kwargs) + + splat_kw({}) { _1 }.inspect +} + +# regression test for arity check with splat +assert_equal '[:ae, :ae]', %q{ + def req_one(a_, b_ = 1) = raise + + def test(args) + req_one *args + rescue ArgumentError + :ae + end + + [test(Array.new 5), test([])] +} + +# regression test for arity check with splat and send +assert_equal '[:ae, :ae]', %q{ + def two_reqs(a, b_, _ = 1) = a.gsub(a, a) + + def test(name, args) + send(name, *args) + rescue ArgumentError + :ae + end + + [test(:two_reqs, ["g", nil, nil, nil]), test(:two_reqs, ["g"])] +} + +# regression test for GC marking stubs in invalidated code +assert_normal_exit %q{ + skip true unless GC.respond_to?(:compact) + garbage = Array.new(10_000) { [] } # create garbage to cause iseq movement + eval(<<~RUBY) + def foo(n, garbage) + if n == 2 + # 1.times.each to create a cfunc frame to preserve the JIT frame + # which will return to a stub housed in an invalidated block + return 1.times.each do + Object.define_method(:foo) {} + garbage.clear + GC.verify_compaction_references(toward: :empty, expand_heap: true) + end + end + + foo(n + 1, garbage) + end + RUBY + + foo(1, garbage) +} + +# regression test for callee block handler overlapping with arguments +assert_equal '3', %q{ + def foo(_req, *args) = args.last + + def call_foo = foo(0, 1, 2, 3, &->{}) + + call_foo +} + +# call leaf builtin with a block argument +assert_equal '0', "0.abs(&nil)" + +# regression test for invokeblock iseq guard +assert_equal 'ok', %q{ + skip :ok unless GC.respond_to?(:compact) + def foo = yield + 10.times do |i| + ret = eval("foo { #{i} }") + raise "failed at #{i}" unless ret == i + GC.compact + end + :ok +} + # regression test for overly generous guard elision assert_equal '[0, :sum, 0, :sum]', %q{ # In faulty versions, the following happens: @@ -16,7 +194,7 @@ def carray(iter) end def cstring(iter) - string = "" + string = "".dup string.sum(iter.times { def string.sum(_) = :sum }) end @@ -42,6 +220,15 @@ class Sub < String; end call(Sub.new('o')).class } +# String#dup with generic ivars +assert_equal '["str", "ivar"]', %q{ + def str_dup(str) = str.dup + str = "str" + str.instance_variable_set(:@ivar, "ivar") + str = str_dup(str) + [str, str.instance_variable_get(:@ivar)] +} + # test splat filling required and feeding rest assert_equal '[0, 1, 2, [3, 4]]', %q{ public def lead_rest(a, b, *rest) @@ -124,7 +311,7 @@ def extender # Used to crash due to GC run in rb_ensure_iv_list_size() # not marking the newly allocated [:ok]. RegressionTest.new.extender.itself -} unless RUBY_DESCRIPTION.include?('+RJIT') # Skip on RJIT since this uncovers a crash +} assert_equal 'true', %q{ # regression test for tracking type of locals for too long @@ -174,7 +361,7 @@ def call_graph_root } assert_normal_exit %q{ - # Test to ensure send on overriden c functions + # Test to ensure send on overridden c functions # doesn't corrupt the stack class Bar def bar(x) @@ -254,6 +441,33 @@ def foo Foo.new.foo } +# getinstancevariable with shape too complex +assert_normal_exit %q{ + class Foo + def initialize + @a = 1 + end + + def getter + @foobar + end + end + + # Initialize ivars in changing order, making the Foo + # class have shape too complex + 100.times do |x| + foo = Foo.new + foo.instance_variable_set(:"@a#{x}", 1) + foo.instance_variable_set(:"@foobar", 777) + + # The getter method eventually sees shape too complex + r = foo.getter + if r != 777 + raise "error" + end + end +} + assert_equal '0', %q{ # This is a regression test for incomplete invalidation from # opt_setinlinecache. This test might be brittle, so @@ -396,6 +610,8 @@ def foo # Check that exceptions work when getting global variable assert_equal 'rescued', %q{ + Warning[:deprecated] = true + module Warning def warn(message) raise @@ -1031,6 +1247,7 @@ def special.[](idx) # Test that object references in generated code get marked and moved assert_equal "good", %q{ + skip :good unless GC.respond_to?(:compact) def bar "good" end @@ -1054,7 +1271,7 @@ def foo # Test polymorphic getinstancevariable. T_OBJECT -> T_STRING assert_equal 'ok', %q{ @hello = @h1 = @h2 = @h3 = @h4 = 'ok' - str = "" + str = +"" str.instance_variable_set(:@hello, 'ok') public def get @@ -1199,7 +1416,7 @@ def index(obj, idx) } # Test default value block for Hash with opt_aref_with -assert_equal "false", %q{ +assert_equal "false", <<~RUBY, frozen_string_literal: false def index_with_string(h) h["foo"] end @@ -1208,7 +1425,7 @@ def index_with_string(h) index_with_string(h) index_with_string(h) -} +RUBY # A regression test for making sure cfp->sp is proper when # hitting stubs. See :stub-sp-flush: @@ -1598,7 +1815,7 @@ def build_hash } # test building hash with values -assert_equal '{:foo=>:bar}', %q{ +assert_equal '{foo: :bar}', %q{ def build_hash(val) { foo: val } end @@ -1708,7 +1925,7 @@ def make_str(foo) } # Test that String unary plus returns the same object ID for an unfrozen string. -assert_equal 'true', %q{ +assert_equal 'true', <<~RUBY, frozen_string_literal: false def jittable_method str = "bar" @@ -1718,7 +1935,7 @@ def jittable_method uplus_str.object_id == old_obj_id end jittable_method -} +RUBY # Test that String unary plus returns a different unfrozen string when given a frozen string assert_equal 'false', %q{ @@ -1832,6 +2049,85 @@ def jittable_method jittable_method } +# test getbyte on string class +assert_equal '[97, :nil, 97, :nil, :raised]', %q{ + def getbyte(s, i) + byte = begin + s.getbyte(i) + rescue TypeError + :raised + end + + byte || :nil + end + + getbyte("a", 0) + getbyte("a", 0) + + [getbyte("a", 0), getbyte("a", 1), getbyte("a", -1), getbyte("a", -2), getbyte("a", "a")] +} + +# Basic test for String#setbyte +assert_equal 'AoZ', %q{ + s = +"foo" + s.setbyte(0, 65) + s.setbyte(-1, 90) + s +} + +# String#setbyte IndexError +assert_equal 'String#setbyte', %q{ + def ccall = "".setbyte(1, 0) + begin + ccall + rescue => e + e.backtrace.first.split("'").last + end +} + +# String#setbyte TypeError +assert_equal 'String#setbyte', %q{ + def ccall = "".setbyte(nil, 0) + begin + ccall + rescue => e + e.backtrace.first.split("'").last + end +} + +# String#setbyte FrozenError +assert_equal 'String#setbyte', %q{ + def ccall = "a".freeze.setbyte(0, 0) + begin + ccall + rescue => e + e.backtrace.first.split("'").last + end +} + +# non-leaf String#setbyte +assert_equal 'String#setbyte', %q{ + def to_int + @caller = caller + 0 + end + + def ccall = "a".dup.setbyte(self, 98) + ccall + + @caller.first.split("'").last +} + +# non-leaf String#byteslice +assert_equal 'TypeError', %q{ + def ccall = "".byteslice(nil, nil) + begin + ccall + rescue => e + e.class + end +} + # Test << operator on string subclass assert_equal 'abab', %q{ class MyString < String; end @@ -1977,6 +2273,34 @@ def foo(foo, bar) foo(5,2) } +# regression test for argument registers with invalidation +assert_equal '[0, 1, 2]', %q{ + def test(n) + ret = n + binding + ret + end + + [0, 1, 2].map do |n| + test(n) + end +} + +# regression test for argument registers +assert_equal 'true', %q{ + class Foo + def ==(other) + other == nil + end + end + + def test + [Foo.new].include?(Foo.new) + end + + test +} + # test pattern matching assert_equal '[:ok, :ok]', %q{ class C @@ -2042,6 +2366,20 @@ def foo(obj) foo(Foo) } +# Test EP == BP invalidation with moving ISEQs +assert_equal 'ok', %q{ + skip :ok unless GC.respond_to?(:compact) + def entry + ok = proc { :ok } # set #entry as an EP-escaping ISEQ + [nil].reverse_each do # avoid exiting the JIT frame on the constant + GC.compact # move #entry ISEQ + end + ok # should be read off of escaped EP + end + + entry.call +} + # invokesuper edge case assert_equal '[:A, [:A, :B]]', %q{ class B @@ -2230,6 +2568,18 @@ def foo B.new.foo } +# invokesuper zsuper in a bmethod +assert_equal 'ok', %q{ + class Foo + define_method(:itself) { super } + end + begin + Foo.new.itself + rescue RuntimeError + :ok + end +} + # Call to fixnum assert_equal '[true, false]', %q{ def is_odd(obj) @@ -2270,6 +2620,16 @@ def is_odd(obj) [is_odd(123), is_odd(456), is_odd(bignum), is_odd(bignum+1)] } +# Flonum and Flonum +assert_equal '[2.0, 0.0, 1.0, 4.0]', %q{ + [1.0 + 1.0, 1.0 - 1.0, 1.0 * 1.0, 8.0 / 2.0] +} + +# Flonum and Fixnum +assert_equal '[2.0, 0.0, 1.0, 4.0]', %q{ + [1.0 + 1, 1.0 - 1, 1.0 * 1, 8.0 / 2] +} + # Call to static and dynamic symbol assert_equal 'bar', %q{ def to_string(obj) @@ -2310,6 +2670,30 @@ def splatarray splatarray } +# splatkw +assert_equal '[1, 2]', %q{ + def foo(a:) = [a, yield] + + def entry(&block) + a = { a: 1 } + foo(**a, &block) + end + + entry { 2 } +} +assert_equal '[1, 2]', %q{ + def foo(a:) = [a, yield] + + def entry(obj, &block) + foo(**obj, &block) + end + + entry({ a: 3 }) { 2 } + obj = Object.new + def obj.to_hash = { a: 1 } + entry(obj) { 2 } +} + assert_equal '[1, 1, 2, 1, 2, 3]', %q{ def expandarray arr = [1, 2, 3] @@ -2364,6 +2748,23 @@ def obj.to_ary expandarray_not_array(obj) } +assert_equal '[1, 2]', %q{ + class NilClass + private + def to_ary + [1, 2] + end + end + + def expandarray_redefined_nilclass + a, b = nil + [a, b] + end + + expandarray_redefined_nilclass + expandarray_redefined_nilclass +} + assert_equal '[1, 2, nil]', %q{ def expandarray_rhs_too_small a, b, c = [1, 2] @@ -2474,7 +2875,7 @@ def events.compiled(obj) events.compiled(events) events -} unless defined?(RubyVM::RJIT) && RubyVM::RJIT.enabled? # RJIT calls extra Ruby methods +} # test enabling a TracePoint that targets a particular line in a C method call assert_equal '[true]', %q{ @@ -2556,7 +2957,7 @@ def shouldnt_compile tp.enable { shouldnt_compile } events -} unless defined?(RubyVM::RJIT) && RubyVM::RJIT.enabled? # RJIT calls extra Ruby methods +} # test enabling c_return tracing before compiling assert_equal '[[:c_return, :itself, main]]', %q{ @@ -2571,7 +2972,7 @@ def shouldnt_compile tp.enable { shouldnt_compile } events -} unless defined?(RubyVM::RJIT) && RubyVM::RJIT.enabled? # RJIT calls extra Ruby methods +} # test c_call invalidation assert_equal '[[:c_call, :itself]]', %q{ @@ -2617,15 +3018,16 @@ def traced_method itself end - tracing_ractor = Ractor.new do + port = Ractor::Port.new + tracing_ractor = Ractor.new port do |port| # 1: start tracing events = [] tp = TracePoint.new(:c_call) { events << _1.method_id } tp.enable - Ractor.yield(nil) + port << nil # 3: run compiled method on tracing ractor - Ractor.yield(nil) + port << nil traced_method events @@ -2633,13 +3035,13 @@ def traced_method tp&.disable end - tracing_ractor.take + port.receive # 2: compile on non tracing ractor traced_method - tracing_ractor.take - tracing_ractor.take + port.receive + tracing_ractor.value } # Try to hit a lazy branch stub while another ractor enables tracing @@ -2653,17 +3055,18 @@ def compiled(arg) end end - ractor = Ractor.new do + port = Ractor::Port.new + ractor = Ractor.new port do |port| compiled(false) - Ractor.yield(nil) + port << nil compiled(41) end tp = TracePoint.new(:line) { itself } - ractor.take + port.receive tp.enable - ractor.take + ractor.value } # Test equality with changing types @@ -2739,7 +3142,7 @@ def self.foo A.foo A.foo - Ractor.new { A.foo }.take + Ractor.new { A.foo }.value } assert_equal '["plain", "special", "sub", "plain"]', %q{ @@ -2991,7 +3394,7 @@ def foo(required:, specified: 999, simple_default: 3, complex_default: "4".to_i) } # cfunc kwargs -assert_equal '{:foo=>123}', %q{ +assert_equal '{foo: 123}', %q{ def foo(bar) bar.store(:value, foo: 123) bar[:value] @@ -3002,7 +3405,7 @@ def foo(bar) } # cfunc kwargs -assert_equal '{:foo=>123}', %q{ +assert_equal '{foo: 123}', %q{ def foo(bar) bar.replace(foo: 123) end @@ -3012,7 +3415,7 @@ def foo(bar) } # cfunc kwargs -assert_equal '{:foo=>123, :bar=>456}', %q{ +assert_equal '{foo: 123, bar: 456}', %q{ def foo(bar) bar.replace(foo: 123, bar: 456) end @@ -3022,7 +3425,7 @@ def foo(bar) } # variadic cfunc kwargs -assert_equal '{:foo=>123}', %q{ +assert_equal '{foo: 123}', %q{ def foo(bar) bar.merge(foo: 123) end @@ -3146,7 +3549,7 @@ def initialize(title) } # duphash -assert_equal '{:foo=>123}', %q{ +assert_equal '{foo: 123}', %q{ def foo {foo: 123} end @@ -3156,7 +3559,7 @@ def foo } # newhash -assert_equal '{:foo=>2}', %q{ +assert_equal '{foo: 2}', %q{ def foo {foo: 1+1} end @@ -3266,6 +3669,74 @@ def foo test } +# Bug #21257 (infinite jmp) +assert_equal 'ok', %q{ + Good = :ok + + def first + second + end + + def second + ::Good + end + + # Make `second` side exit on its first instruction + trace = TracePoint.new(:line) { } + trace.enable(target: method(:second)) + + first + # Recompile now that the constant cache is populated, so we get a fallthrough from `first` to `second` + # (this is need to reproduce with --yjit-call-threshold=1) + RubyVM::YJIT.code_gc if defined?(RubyVM::YJIT) + first + + # Trigger a constant cache miss in rb_vm_opt_getconstant_path (in `second`) next time it's called + module InvalidateConstantCache + Good = nil + end + + RubyVM::YJIT.simulate_oom! if defined?(RubyVM::YJIT) + + first + first +} + +assert_equal 'ok', %q{ + # Multiple incoming branches into second + Good = :ok + + def incoming_one + second + end + + def incoming_two + second + end + + def second + ::Good + end + + # Make `second` side exit on its first instruction + trace = TracePoint.new(:line) { } + trace.enable(target: method(:second)) + + incoming_one + # Recompile now that the constant cache is populated, so we get a fallthrough from `incoming_one` to `second` + # (this is need to reproduce with --yjit-call-threshold=1) + RubyVM::YJIT.code_gc if defined?(RubyVM::YJIT) + incoming_one + incoming_two + + # Trigger a constant cache miss in rb_vm_opt_getconstant_path (in `second`) next time it's called + module InvalidateConstantCache + Good = nil + end + + incoming_one +} + assert_equal 'ok', %q{ # Try to compile new method while OOM def foo @@ -3390,36 +3861,6 @@ def pt_inspect(pt) pt_inspect(p) } -# Regression test for deadlock between branch_stub_hit and ractor_receive_if -assert_equal '10', %q{ - r = Ractor.new Ractor.current do |main| - main << 1 - main << 2 - main << 3 - main << 4 - main << 5 - main << 6 - main << 7 - main << 8 - main << 9 - main << 10 - end - - a = [] - a << Ractor.receive_if{|msg| msg == 10} - a << Ractor.receive_if{|msg| msg == 9} - a << Ractor.receive_if{|msg| msg == 8} - a << Ractor.receive_if{|msg| msg == 7} - a << Ractor.receive_if{|msg| msg == 6} - a << Ractor.receive_if{|msg| msg == 5} - a << Ractor.receive_if{|msg| msg == 4} - a << Ractor.receive_if{|msg| msg == 3} - a << Ractor.receive_if{|msg| msg == 2} - a << Ractor.receive_if{|msg| msg == 1} - - a.length -} - # checktype assert_equal 'false', %q{ def function() @@ -3829,7 +4270,7 @@ def foo assert_equal 'Hello World', %q{ def bar args = ["Hello "] - greeting = "World" + greeting = +"World" greeting.insert(0, *args) greeting end @@ -3965,7 +4406,7 @@ def literal_append(sql, v) # Rest with block # Simplified code from railsbench -assert_equal '[{"/a"=>"b", :as=>:c, :via=>:post}, [], nil]', %q{ +assert_equal '[{"/a" => "b", as: :c, via: :post}, [], nil]', %q{ def match(path, *rest, &block) [path, rest, block] end @@ -4065,7 +4506,7 @@ def calling_my_func calling_my_func } -# Regresssion test: rest and optional and splat +# Regression test: rest and optional and splat assert_equal 'true', %q{ def my_func(base=nil, *args) [base, args] @@ -4093,9 +4534,9 @@ def calling_func rescue ArgumentError true end -} unless defined?(RubyVM::RJIT) && RubyVM::RJIT.enabled? # Not yet working on RJIT +} -# Regresssion test: register allocator on expandarray +# Regression test: register allocator on expandarray assert_equal '[]', %q{ func = proc { [] } proc do @@ -4151,3 +4592,838 @@ def foo(a, b) [r1, r2, r3, r4, r5] } + +# Integer multiplication and overflow (minimized regression test from test-basic) +assert_equal '8515157028618240000', %q{2128789257154560000 * 4} + +# Inlined method calls +assert_equal 'nil', %q{ + def putnil = nil + def entry = putnil + entry.inspect +} +assert_equal '1', %q{ + def putobject_1 = 1 + def entry = putobject_1 + entry +} +assert_equal 'false', %q{ + def putobject(_unused_arg1) = false + def entry = putobject(nil) + entry +} +assert_equal 'true', %q{ + def entry = yield + entry { true } +} +assert_equal 'sym', %q{ + def entry = :sym.to_sym + entry +} + +assert_normal_exit %q{ + ivars = 1024.times.map { |i| "@iv_#{i} = #{i}\n" }.join + Foo = Class.new + Foo.class_eval "def initialize() #{ivars} end" + Foo.new +} + +assert_equal '0', %q{ + def spill + 1.to_i # not inlined + end + + def inline(_stack1, _stack2, _stack3, _stack4, _stack5) + 0 # inlined + end + + def entry + # RegTemps is 00111110 prior to the #inline call. + # Its return value goes to stack_idx=0, which conflicts with stack_idx=5. + inline(spill, 2, 3, 4, 5) + end + + entry +} + +# Integer succ and overflow +assert_equal '[2, 4611686018427387904]', %q{ + [1.succ, 4611686018427387903.succ] +} + +# Integer pred and overflow +assert_equal '[0, -4611686018427387905]', %q{ + [1.pred, -4611686018427387904.pred] +} + +# Integer right shift +assert_equal '[0, 1, -4]', %q{ + [0 >> 1, 2 >> 1, -7 >> 1] +} + +# Integer XOR +assert_equal '[0, 0, 4]', %q{ + [0 ^ 0, 1 ^ 1, 7 ^ 3] +} + +assert_equal '[nil, "yield"]', %q{ + def defined_yield = defined?(yield) + [defined_yield, defined_yield {}] +} + +# splat with ruby2_keywords into rest parameter +assert_equal '[[{a: 1}], {}]', %q{ + ruby2_keywords def foo(*args) = args + + def bar(*args, **kw) = [args, kw] + + def pass_bar(*args) = bar(*args) + + def body + args = foo(a: 1) + pass_bar(*args) + end + + body +} + +# concatarray +assert_equal '[1, 2]', %q{ + def foo(a, b) = [a, b] + arr = [2] + foo(*[1], *arr) +} + +# pushtoarray +assert_equal '[1, 2]', %q{ + def foo(a, b) = [a, b] + arr = [1] + foo(*arr, 2) +} + +# pop before fallback +assert_normal_exit %q{ + class Foo + attr_reader :foo + + def try = foo(0, &nil) + end + + Foo.new.try +} + +# a kwrest case +assert_equal '[1, 2, {complete: false}]', %q{ + def rest(foo: 1, bar: 2, **kwrest) + [foo, bar, kwrest] + end + + def callsite = rest(complete: false) + + callsite +} + +# splat+kw_splat+opt+rest +assert_equal '[1, []]', %q{ + def opt_rest(a = 0, *rest) = [a, rest] + + def call_site(args) = opt_rest(*args, **nil) + + call_site([1]) +} + +# splat and nil kw_splat +assert_equal 'ok', %q{ + def identity(x) = x + + def splat_nil_kw_splat(args) = identity(*args, **nil) + + splat_nil_kw_splat([:ok]) +} + +# empty splat and kwsplat into leaf builtins +assert_equal '[1, 1, 1]', %q{ + empty = [] + [1.abs(*empty), 1.abs(**nil), 1.bit_length(*empty, **nil)] +} + +# splat into C methods with -1 arity +assert_equal '[[1, 2, 3], [0, 2, 3], [1, 2, 3], [2, 2, 3], [], [], [{}]]', %q{ + class Foo < Array + def push(args) = super(1, *args) + end + + def test_cfunc_vargs_splat(sub_instance, array_class, empty_kw_hash) + splat = [2, 3] + kw_splat = [empty_kw_hash] + [ + sub_instance.push(splat), + array_class[0, *splat, **nil], + array_class[1, *splat, &nil], + array_class[2, *splat, **nil, &nil], + array_class.send(:[], *kw_splat), + # kw_splat disables keywords hash handling + array_class[*kw_splat], + array_class[*kw_splat, **nil], + ] + end + + test_cfunc_vargs_splat(Foo.new, Array, Hash.ruby2_keywords_hash({})) +} + +# Class#new (arity=-1), splat, and ruby2_keywords +assert_equal '[0, {1 => 1}]', %q{ + class KwInit + attr_reader :init_args + def initialize(x = 0, **kw) + @init_args = [x, kw] + end + end + + def test(klass, args) + klass.new(*args).init_args + end + + test(KwInit, [Hash.ruby2_keywords_hash({1 => 1})]) +} + +# Chilled string setivar trigger warning +assert_match(/literal string will be frozen in the future/, %q{ + Warning[:deprecated] = true + $VERBOSE = true + $warning = "no-warning" + module ::Warning + def self.warn(message) + $warning = message.split("warning: ").last.strip + end + end + + class String + def setivar! + @ivar = 42 + end + end + + def setivar!(str) + str.setivar! + end + + 10.times { setivar!("mutable".dup) } + 10.times do + setivar!("frozen".freeze) + rescue FrozenError + end + + setivar!("chilled") # Emit warning + $warning +}) + +# arity=-2 cfuncs +assert_equal '["", "1/2", [0, [:ok, 1]]]', %q{ + def test_cases(file, chain) + new_chain = chain.allocate # to call initialize directly + new_chain.send(:initialize, [0], ok: 1) + + [ + file.join, + file.join("1", "2"), + new_chain.to_a, + ] + end + + test_cases(File, Enumerator::Chain) +} + +# singleton class should invalidate Type::CString assumption +assert_equal 'foo', %q{ + def define_singleton(str, define) + if define + # Wrap a C method frame to avoid exiting JIT code on defineclass + [nil].reverse_each do + class << str + def +(_) + "foo" + end + end + end + end + "bar" + end + + def entry(define) + str = "" + # When `define` is false, #+ compiles to rb_str_plus() without a class guard. + # When the code is reused with `define` is true, the class of `str` is changed + # to a singleton class, so the block should be invalidated. + str + define_singleton(str, define) + end + + entry(false) + entry(true) +} + +assert_equal 'ok', %q{ + def ok + :ok + end + + def delegator(...) + ok(...) + end + + def caller + send(:delegator) + end + + caller +} + +# test inlining of simple iseqs +assert_equal '[:ok, :ok, :ok]', %q{ + def identity(x) = x + def foo(x, _) = x + def bar(_, _, _, _, x) = x + + def tests + [ + identity(:ok), + foo(:ok, 2), + bar(1, 2, 3, 4, :ok), + ] + end + + tests +} + +# test inlining of simple iseqs with kwargs +assert_equal '[:ok, :ok, :ok, :ok, :ok]', %q{ + def optional_unused(x, opt: :not_ok) = x + def optional_used(x, opt: :ok) = opt + def required_unused(x, req:) = x + def required_used(x, req:) = req + def unknown(x) = x + + def tests + [ + optional_unused(:ok), + optional_used(:not_ok), + required_unused(:ok, req: :not_ok), + required_used(:not_ok, req: :ok), + begin unknown(:not_ok, unknown_kwarg: :not_ok) rescue ArgumentError; :ok end, + ] + end + + tests +} + +# test simple iseqs not eligible for inlining +assert_equal '[:ok, :ok, :ok, :ok, :ok]', %q{ + def identity(x) = x + def arg_splat(x, *args) = x + def kwarg_splat(x, **kwargs) = x + def block_arg(x, &blk) = x + def block_iseq(x) = x + def call_forwarding(...) = identity(...) + + def tests + [ + arg_splat(:ok), + kwarg_splat(:ok), + block_arg(:ok, &proc { :not_ok }), + block_iseq(:ok) { :not_ok }, + call_forwarding(:ok), + ] + end + + tests +} + +# regression test for invalidating an empty block +assert_equal '0', %q{ + def foo = (* = 1).pred + + foo # compile it + + class Integer + def to_ary = [] # invalidate + end + + foo # try again +} + +# test integer left shift with constant rhs +assert_equal [0x80000000000, 'a+', :ok].inspect, %q{ + def shift(val) = val << 43 + + def tests + int = shift(1) + str = shift("a") + + Integer.define_method(:<<) { |_| :ok } + redef = shift(1) + + [int, str, redef] + end + + tests +} + +# test integer left shift fusion followed by opt_getconstant_path +assert_equal '33', %q{ + def test(a) + (a << 5) | (Object; a) + end + + test(1) +} + +# test String#stebyte with arguments that need conversion +assert_equal "abc", %q{ + str = +"a00" + def change_bytes(str, one, two) + str.setbyte(one, "b".ord) + str.setbyte(2, two) + end + + to_int_1 = Object.new + to_int_99 = Object.new + def to_int_1.to_int = 1 + def to_int_99.to_int = 99 + + change_bytes(str, to_int_1, to_int_99) + str +} + +# test --yjit-verify-ctx for arrays with a singleton class +assert_equal "ok", %q{ + class Array + def foo + self.singleton_class.define_method(:first) { :ok } + first + end + end + + def test = [].foo + + test +} + +assert_equal '["raised", "Module", "Object"]', %q{ + def foo(obj) + obj.superclass.name + end + + ret = [] + + begin + foo(Class.allocate) + rescue TypeError + ret << 'raised' + end + + ret += [foo(Class), foo(Class.new)] +} + +# test TrueClass#=== before and after redefining TrueClass#== +assert_equal '[[true, false, false], [true, true, false], [true, :error, :error]]', %q{ + def true_eqq(x) + true === x + rescue NoMethodError + :error + end + + def test + [ + # first one is always true because rb_equal does object comparison before calling #== + true_eqq(true), + # these will use TrueClass#== + true_eqq(false), + true_eqq(:truthy), + ] + end + + results = [test] + + class TrueClass + def ==(x) + !x + end + end + + results << test + + class TrueClass + undef_method :== + end + + results << test +} + +# test FalseClass#=== before and after redefining FalseClass#== +assert_equal '[[true, false, false], [true, false, true], [true, :error, :error]]', %q{ + def case_equal(x, y) + x === y + rescue NoMethodError + :error + end + + def test + [ + # first one is always true because rb_equal does object comparison before calling #== + case_equal(false, false), + # these will use #== + case_equal(false, true), + case_equal(false, nil), + ] + end + + results = [test] + + class FalseClass + def ==(x) + !x + end + end + + results << test + + class FalseClass + undef_method :== + end + + results << test +} + +# test NilClass#=== before and after redefining NilClass#== +assert_equal '[[true, false, false], [true, false, true], [true, :error, :error]]', %q{ + def case_equal(x, y) + x === y + rescue NoMethodError + :error + end + + def test + [ + # first one is always true because rb_equal does object comparison before calling #== + case_equal(nil, nil), + # these will use #== + case_equal(nil, true), + case_equal(nil, false), + ] + end + + results = [test] + + class NilClass + def ==(x) + !x + end + end + + results << test + + class NilClass + undef_method :== + end + + results << test +} + +# test struct accessors fire c_call events +assert_equal '[[:c_call, :x=], [:c_call, :x]]', %q{ + c = Struct.new(:x) + obj = c.new + + events = [] + TracePoint.new(:c_call) do + events << [_1.event, _1.method_id] + end.enable do + obj.x = 100 + obj.x + end + + events +} + +# regression test for splatting empty array +assert_equal '1', %q{ + def callee(foo) = foo + + def test_body(args) = callee(1, *args) + + test_body([]) + array = Array.new(100) + array.clear + test_body(array) +} + +# regression test for splatting empty array to cfunc +assert_normal_exit %q{ + def test_body(args) = Array(1, *args) + + test_body([]) + 0x100.times do + array = Array.new(100) + array.clear + test_body(array) + end +} + +# compiling code shouldn't emit warnings as it may call into more Ruby code +assert_equal 'ok', <<~'RUBY' + # [Bug #20522] + $VERBOSE = true + Warning[:performance] = true + + module StrictWarnings + def warn(msg, **) + raise msg + end + end + Warning.singleton_class.prepend(StrictWarnings) + + class A + def compiled_method(is_private) + @some_ivar = is_private + end + end + + shape_max_variations = 8 + if defined?(RubyVM::Shape::SHAPE_MAX_VARIATIONS) && RubyVM::Shape::SHAPE_MAX_VARIATIONS != shape_max_variations + raise "Expected SHAPE_MAX_VARIATIONS to be #{shape_max_variations}, got: #{RubyVM::Shape::SHAPE_MAX_VARIATIONS}" + end + + 100.times do |i| + klass = Class.new(A) + (shape_max_variations - 1).times do |j| + obj = klass.new + obj.instance_variable_set("@base_#{i}", 42) + obj.instance_variable_set("@ivar_#{j}", 42) + end + obj = klass.new + obj.instance_variable_set("@base_#{i}", 42) + begin + obj.compiled_method(true) + rescue + # expected + end + end + + :ok +RUBY + +assert_equal 'ok', <<~'RUBY' + class MyRelation + def callee(...) + :ok + end + + def uncached(...) + callee(...) + end + + def takes_block(&block) + # push blockhandler + uncached(&block) # CI1 + end + end + + relation = MyRelation.new + relation.takes_block { } +RUBY + +assert_equal 'ok', <<~'RUBY' + def _exec_scope(...) + instance_exec(...) + end + + def ok args, body + _exec_scope(*args, &body) + end + + ok([], -> { "ok" }) +RUBY + +assert_equal 'ok', <<~'RUBY' + def _exec_scope(...) + instance_exec(...) + end + + def ok args, body + _exec_scope(*args, &body) + end + + ok(["ok"], ->(x) { x }) +RUBY + +assert_equal 'ok', <<~'RUBY' +def baz(a, b) + a + b +end + +def bar(...) + baz(...) +end + +def foo(a, ...) + bar(a, ...) +end + +def test + foo("o", "k") +end + +test +RUBY + +# opt_newarray_send pack/buffer +assert_equal '[true, true]', <<~'RUBY' + def pack + v = 1.23 + [v, v*2, v*3].pack("E*").unpack("E*") == [v, v*2, v*3] + end + + def with_buffer + v = 4.56 + b = +"x" + [v, v*2, v*3].pack("E*", buffer: b) + b[1..].unpack("E*") == [v, v*2, v*3] + end + + [pack, with_buffer] +RUBY + +# String#[] / String#slice +assert_equal 'ok', <<~'RUBY' + def error(klass) + yield + rescue klass + true + end + + def test + str = "こんにちは" + substr = "にち" + failures = [] + + # Use many small statements to keep context for each slice call smaller than MAX_CTX_TEMPS + + str[1] == "ん" && str.slice(4) == "は" || failures << :index + str[5].nil? && str.slice(5).nil? || failures << :index_end + + str[1, 2] == "んに" && str.slice(2, 1) == "に" || failures << :beg_len + str[5, 1] == "" && str.slice(5, 1) == "" || failures << :beg_len_end + + str[1..2] == "んに" && str.slice(2..2) == "に" || failures << :range + + str[/に./] == "にち" && str.slice(/に./) == "にち" || failures << :regexp + + str[/に./, 0] == "にち" && str.slice(/に./, 0) == "にち" || failures << :regexp_cap0 + + str[/に(.)/, 1] == "ち" && str.slice(/に(.)/, 1) == "ち" || failures << :regexp_cap1 + + str[substr] == substr && str.slice(substr) == substr || failures << :substr + + error(TypeError) { str[Object.new] } && error(TypeError) { str.slice(Object.new, 1) } || failures << :type_error + error(RangeError) { str[Float::INFINITY] } && error(RangeError) { str.slice(Float::INFINITY) } || failures << :range_error + + return "ok" if failures.empty? + {failures: failures} + end + + test +RUBY + +# opt_duparray_send :include? +assert_equal '[true, false]', <<~'RUBY' + def test(x) + [:a, :b].include?(x) + end + + [ + test(:b), + test(:c), + ] +RUBY + +# opt_newarray_send :include? +assert_equal '[true, false]', <<~'RUBY' + def test(x) + [Object.new, :a, :b].include?(x.to_sym) + end + + [ + test("b"), + test("c"), + ] +RUBY + +# YARV: swap and opt_reverse +assert_equal '["x", "Y", "c", "A", "t", "A", "b", "C", "d"]', <<~'RUBY' + class Swap + def initialize(s) + @a, @b, @c, @d = s.split("") + end + + def swap + a, b = @a, @b + b = b.upcase + @a, @b = a, b + end + + def reverse_odd + a, b, c = @a, @b, @c + b = b.upcase + @a, @b, @c = a, b, c + end + + def reverse_even + a, b, c, d = @a, @b, @c, @d + a = a.upcase + c = c.upcase + @a, @b, @c, @d = a, b, c, d + end + end + + Swap.new("xy").swap + Swap.new("cat").reverse_odd + Swap.new("abcd").reverse_even +RUBY + +assert_normal_exit %{ + class Bug20997 + def foo(&) = self.class.name(&) + + new.foo + end +} + +# This used to trigger a "try to mark T_NONE" +# due to an uninitialized local in foo. +assert_normal_exit %{ + def foo(...) + _local_that_should_nil_on_call = GC.start + end + + def test_bug21021 + puts [], [], [], [], [], [] + foo [] + end + + GC.stress = true + test_bug21021 +} + +assert_equal 'nil', %{ + def foo(...) + _a = _b = _c = binding.local_variable_get(:_c) + + _c + end + + # [Bug #21021] + def test_local_fill_in_forwardable + puts [], [], [], [], [] + foo [] + end + + test_local_fill_in_forwardable.inspect +} diff --git a/bootstraptest/test_yjit_rust_port.rb b/bootstraptest/test_yjit_rust_port.rb index e399e0e49ef637..2dbcebc03a780d 100644 --- a/bootstraptest/test_yjit_rust_port.rb +++ b/bootstraptest/test_yjit_rust_port.rb @@ -374,7 +374,7 @@ def nimai(jita) r = Ractor.new do 'ok' end - r.take + r.value } # Passed arguments to Ractor.new will be a block parameter @@ -384,7 +384,7 @@ def nimai(jita) r = Ractor.new 'ok' do |msg| msg end - r.take + r.value } # Pass multiple arguments to Ractor.new @@ -393,7 +393,7 @@ def nimai(jita) r = Ractor.new 'ping', 'pong' do |msg, msg2| [msg, msg2] end - 'ok' if r.take == ['ping', 'pong'] + 'ok' if r.value == ['ping', 'pong'] } # Ractor#send passes an object with copy to a Ractor @@ -403,7 +403,7 @@ def nimai(jita) msg = Ractor.receive end r.send 'ok' - r.take + r.value } assert_equal '[1, 2, 3]', %q{ diff --git a/builtin.c b/builtin.c index aef5b2c2d44b30..3207704b28a096 100644 --- a/builtin.c +++ b/builtin.c @@ -3,15 +3,15 @@ #include "iseq.h" #include "builtin.h" -#ifdef CROSS_COMPILING +#include "builtin_binary.inc" + +#ifndef BUILTIN_BINARY_SIZE -#define INCLUDED_BY_BUILTIN_C 1 +#define BUILTIN_LOADED(feature_name, iseq) ((void)0) #include "mini_builtin.c" #else -#include "builtin_binary.inc" - static const unsigned char * bin4feature(const struct builtin_binary *bb, const char *feature, size_t *psize) { @@ -32,8 +32,8 @@ builtin_lookup(const char *feature, size_t *psize) return bin; } -void -rb_load_with_builtin_functions(const char *feature_name, const struct rb_builtin_function *table) +static void +load_with_builtin_functions(const char *feature_name, const struct rb_builtin_function *table) { // search binary size_t size; @@ -46,17 +46,37 @@ rb_load_with_builtin_functions(const char *feature_name, const struct rb_builtin rb_vm_t *vm = GET_VM(); if (vm->builtin_function_table != NULL) rb_bug("vm->builtin_function_table should be NULL."); vm->builtin_function_table = table; - vm->builtin_inline_index = 0; const rb_iseq_t *iseq = rb_iseq_ibf_load_bytes((const char *)bin, size); ASSUME(iseq); // otherwise an exception should have raised vm->builtin_function_table = NULL; + rb_namespace_enable_builtin(); + // exec - rb_iseq_eval(rb_iseq_check(iseq)); + if (rb_namespace_available() && rb_mNamespaceRefiner) { + rb_iseq_eval_with_refinement(rb_iseq_check(iseq), rb_mNamespaceRefiner); + } + else { + rb_iseq_eval(rb_iseq_check(iseq)); + } + + rb_namespace_disable_builtin(); +} + +void +rb_load_with_builtin_functions(const char *feature_name, const struct rb_builtin_function *table) +{ + load_with_builtin_functions(feature_name, table); } #endif +void +rb_free_loaded_builtin_table(void) +{ + // do nothing +} + void Init_builtin(void) { @@ -66,5 +86,5 @@ Init_builtin(void) void Init_builtin_features(void) { - rb_load_with_builtin_functions("gem_prelude", NULL); + load_with_builtin_functions("gem_prelude", NULL); } diff --git a/builtin.h b/builtin.h index 85fd1a009a24f5..fd1c4c307fc62b 100644 --- a/builtin.h +++ b/builtin.h @@ -15,7 +15,7 @@ struct rb_builtin_function { #define RB_BUILTIN_FUNCTION(_i, _name, _fname, _arity) {\ .name = _i < 0 ? NULL : #_name, \ - .func_ptr = (void *)_fname, \ + .func_ptr = (void *)(uintptr_t)_fname, \ .argc = _arity, \ .index = _i, \ } @@ -106,6 +106,14 @@ rb_vm_lvar(rb_execution_context_t *ec, int index) #endif } +static inline VALUE +rb_builtin_basic_definition_p(rb_execution_context_t *ec, VALUE klass, VALUE id_sym) +{ + return rb_method_basic_definition_p(klass, rb_sym2id(id_sym)) ? Qtrue : Qfalse; +} + +#define LOCAL_PTR(local) local ## __ptr + // dump/load struct builtin_binary { diff --git a/ccan/list/list.h b/ccan/list/list.h index 30b2af04e954ad..bf692a6937b8a2 100644 --- a/ccan/list/list.h +++ b/ccan/list/list.h @@ -635,14 +635,16 @@ static inline void ccan_list_prepend_list_(struct ccan_list_head *to, /* internal macros, do not use directly */ #define ccan_list_for_each_off_dir_(h, i, off, dir) \ - for (i = ccan_list_node_to_off_(ccan_list_debug(h, CCAN_LIST_LOC)->n.dir, \ + for (i = 0, \ + i = ccan_list_node_to_off_(ccan_list_debug(h, CCAN_LIST_LOC)->n.dir, \ (off)); \ ccan_list_node_from_off_((void *)i, (off)) != &(h)->n; \ i = ccan_list_node_to_off_(ccan_list_node_from_off_((void *)i, (off))->dir, \ (off))) #define ccan_list_for_each_safe_off_dir_(h, i, nxt, off, dir) \ - for (i = ccan_list_node_to_off_(ccan_list_debug(h, CCAN_LIST_LOC)->n.dir, \ + for (i = 0, \ + i = ccan_list_node_to_off_(ccan_list_debug(h, CCAN_LIST_LOC)->n.dir, \ (off)), \ nxt = ccan_list_node_to_off_(ccan_list_node_from_off_(i, (off))->dir, \ (off)); \ diff --git a/class.c b/class.c index e0222d47342571..bef54eae2f38c1 100644 --- a/class.c +++ b/class.c @@ -24,46 +24,53 @@ #include "internal/class.h" #include "internal/eval.h" #include "internal/hash.h" +#include "internal/namespace.h" #include "internal/object.h" #include "internal/string.h" #include "internal/variable.h" #include "ruby/st.h" #include "vm_core.h" +#include "yjit.h" /* Flags of T_CLASS * - * 2: RCLASS_SUPERCLASSES_INCLUDE_SELF - * The RCLASS_SUPERCLASSES contains the class as the last element. - * This means that this class owns the RCLASS_SUPERCLASSES list. - * if !SHAPE_IN_BASIC_FLAGS - * 4-19: SHAPE_FLAG_MASK - * Shape ID for the class. - * endif + * 0: RCLASS_IS_ROOT + * The class has been added to the VM roots. Will always be marked and pinned. + * This is done for classes defined from C to allow storing them in global variables. + * 1: RUBY_FL_SINGLETON + * This class is a singleton class. + * 2: RCLASS_PRIME_CLASSEXT_PRIME_WRITABLE + * This class's prime classext is the only classext and writable from any namespaces. + * If unset, the prime classext is writable only from the root namespace. + * 3: RCLASS_IS_INITIALIZED + * Class has been initialized. + * 4: RCLASS_NAMESPACEABLE + * Is a builtin class that may be namespaced. It larger than a normal class. */ /* Flags of T_ICLASS * - * 0: RICLASS_IS_ORIGIN - * 3: RICLASS_ORIGIN_SHARED_MTBL - * The T_ICLASS does not own the method table. - * if !SHAPE_IN_BASIC_FLAGS - * 4-19: SHAPE_FLAG_MASK - * Shape ID. This is set but not used. - * endif + * 2: RCLASS_PRIME_CLASSEXT_PRIME_WRITABLE + * This module's prime classext is the only classext and writable from any namespaces. + * If unset, the prime classext is writable only from the root namespace. + * 4: RCLASS_NAMESPACEABLE + * Is a builtin class that may be namespaced. It larger than a normal class. */ /* Flags of T_MODULE * - * 1: RMODULE_ALLOCATED_BUT_NOT_INITIALIZED - * Module has not been initialized. - * 2: RCLASS_SUPERCLASSES_INCLUDE_SELF - * See RCLASS_SUPERCLASSES_INCLUDE_SELF in T_CLASS. - * 3: RMODULE_IS_REFINEMENT + * 0: RCLASS_IS_ROOT + * The class has been added to the VM roots. Will always be marked and pinned. + * This is done for classes defined from C to allow storing them in global variables. + * 1: RMODULE_IS_REFINEMENT * Module is used for refinements. - * if !SHAPE_IN_BASIC_FLAGS - * 4-19: SHAPE_FLAG_MASK - * Shape ID for the module. - * endif + * 2: RCLASS_PRIME_CLASSEXT_PRIME_WRITABLE + * This module's prime classext is the only classext and writable from any namespaces. + * If unset, the prime classext is writable only from the root namespace. + * 3: RCLASS_IS_INITIALIZED + * Module has been initialized. + * 4: RCLASS_NAMESPACEABLE + * Is a builtin class that may be namespaced. It larger than a normal class. */ #define METACLASS_OF(k) RBASIC(k)->klass @@ -71,122 +78,527 @@ RUBY_EXTERN rb_serial_t ruby_vm_global_cvar_state; -static rb_subclass_entry_t * -push_subclass_entry_to_list(VALUE super, VALUE klass) +struct duplicate_id_tbl_data { + struct rb_id_table *tbl; + VALUE klass; +}; + +static enum rb_id_table_iterator_result +duplicate_classext_id_table_i(ID key, VALUE value, void *data) +{ + struct rb_id_table *tbl = (struct rb_id_table *)data; + rb_id_table_insert(tbl, key, value); + return ID_TABLE_CONTINUE; +} + +static enum rb_id_table_iterator_result +duplicate_classext_m_tbl_i(ID key, VALUE value, void *data) +{ + struct duplicate_id_tbl_data *arg = (struct duplicate_id_tbl_data *)data; + rb_method_entry_t *me = (rb_method_entry_t *)value; + rb_method_table_insert0(arg->klass, arg->tbl, key, me, false); + return ID_TABLE_CONTINUE; +} + +static struct rb_id_table * +duplicate_classext_m_tbl(struct rb_id_table *orig, VALUE klass, bool init_missing) +{ + struct rb_id_table *tbl; + if (!orig) { + if (init_missing) + return rb_id_table_create(0); + else + return NULL; + } + tbl = rb_id_table_create(rb_id_table_size(orig)); + struct duplicate_id_tbl_data data = { + .tbl = tbl, + .klass = klass, + }; + rb_id_table_foreach(orig, duplicate_classext_m_tbl_i, &data); + return tbl; +} + +static struct rb_id_table * +duplicate_classext_id_table(struct rb_id_table *orig, bool init_missing) +{ + struct rb_id_table *tbl; + + if (!orig) { + if (init_missing) + return rb_id_table_create(0); + else + return NULL; + } + tbl = rb_id_table_create(rb_id_table_size(orig)); + rb_id_table_foreach(orig, duplicate_classext_id_table_i, tbl); + return tbl; +} + +static rb_const_entry_t * +duplicate_classext_const_entry(rb_const_entry_t *src, VALUE klass) +{ + // See also: setup_const_entry (variable.c) + rb_const_entry_t *dst = ZALLOC(rb_const_entry_t); + + dst->flag = src->flag; + dst->line = src->line; + RB_OBJ_WRITE(klass, &dst->value, src->value); + RB_OBJ_WRITE(klass, &dst->file, src->file); + + return dst; +} + +static enum rb_id_table_iterator_result +duplicate_classext_const_tbl_i(ID key, VALUE value, void *data) +{ + struct duplicate_id_tbl_data *arg = (struct duplicate_id_tbl_data *)data; + rb_const_entry_t *entry = duplicate_classext_const_entry((rb_const_entry_t *)value, arg->klass); + + rb_id_table_insert(arg->tbl, key, (VALUE)entry); + + return ID_TABLE_CONTINUE; +} + +static struct rb_id_table * +duplicate_classext_const_tbl(struct rb_id_table *src, VALUE klass) +{ + struct rb_id_table *dst; + + if (!src) + return NULL; + + dst = rb_id_table_create(rb_id_table_size(src)); + + struct duplicate_id_tbl_data data = { + .tbl = dst, + .klass = klass, + }; + rb_id_table_foreach(src, duplicate_classext_const_tbl_i, (void *)&data); + + return dst; +} + +static VALUE +namespace_subclasses_tbl_key(const rb_namespace_t *ns) +{ + if (!ns){ + return 0; + } + return (VALUE)ns->ns_id; +} + +static void +duplicate_classext_subclasses(rb_classext_t *orig, rb_classext_t *copy) +{ + rb_subclass_anchor_t *anchor, *orig_anchor; + rb_subclass_entry_t *head, *cur, *cdr, *entry, *first = NULL; + rb_ns_subclasses_t *ns_subclasses; + struct st_table *tbl; + + if (RCLASSEXT_SUBCLASSES(orig)) { + orig_anchor = RCLASSEXT_SUBCLASSES(orig); + ns_subclasses = orig_anchor->ns_subclasses; + tbl = ((rb_ns_subclasses_t *)ns_subclasses)->tbl; + + anchor = ZALLOC(rb_subclass_anchor_t); + anchor->ns_subclasses = rb_ns_subclasses_ref_inc(ns_subclasses); + + head = ZALLOC(rb_subclass_entry_t); + anchor->head = head; + + RCLASSEXT_SUBCLASSES(copy) = anchor; + + cur = head; + entry = orig_anchor->head; + RUBY_ASSERT(!entry->klass); + // The head entry has NULL klass always. See rb_class_foreach_subclass(). + entry = entry->next; + while (entry) { + if (rb_objspace_garbage_object_p(entry->klass)) { + entry = entry->next; + continue; + } + cdr = ZALLOC(rb_subclass_entry_t); + cdr->klass = entry->klass; + cdr->prev = cur; + cur->next = cdr; + if (!first) { + VALUE ns_id = namespace_subclasses_tbl_key(RCLASSEXT_NS(copy)); + first = cdr; + st_insert(tbl, ns_id, (st_data_t)first); + } + cur = cdr; + entry = entry->next; + } + } + + if (RCLASSEXT_NS_SUPER_SUBCLASSES(orig)) + RCLASSEXT_NS_SUPER_SUBCLASSES(copy) = rb_ns_subclasses_ref_inc(RCLASSEXT_NS_SUPER_SUBCLASSES(orig)); + if (RCLASSEXT_NS_MODULE_SUBCLASSES(orig)) + RCLASSEXT_NS_MODULE_SUBCLASSES(copy) = rb_ns_subclasses_ref_inc(RCLASSEXT_NS_MODULE_SUBCLASSES(orig)); +} + +static void +class_duplicate_iclass_classext(VALUE iclass, rb_classext_t *mod_ext, const rb_namespace_t *ns) +{ + RUBY_ASSERT(RB_TYPE_P(iclass, T_ICLASS)); + + rb_classext_t *src = RCLASS_EXT_PRIME(iclass); + rb_classext_t *ext = RCLASS_EXT_TABLE_LOOKUP_INTERNAL(iclass, ns); + int first_set = 0; + + if (ext) { + // iclass classext for the ns is only for cc/callable_m_tbl if it's created earlier than module's one + rb_invalidate_method_caches(RCLASSEXT_CALLABLE_M_TBL(ext), RCLASSEXT_CC_TBL(ext)); + } + + ext = ZALLOC(rb_classext_t); + + RCLASSEXT_NS(ext) = ns; + + RCLASSEXT_SUPER(ext) = RCLASSEXT_SUPER(src); + + // See also: rb_include_class_new() + if (RCLASSEXT_ICLASS_IS_ORIGIN(src) && !RCLASSEXT_ICLASS_ORIGIN_SHARED_MTBL(src)) { + RCLASSEXT_M_TBL(ext) = duplicate_classext_m_tbl(RCLASSEXT_M_TBL(src), iclass, true); + } + else { + RCLASSEXT_M_TBL(ext) = RCLASSEXT_M_TBL(mod_ext); + } + + RCLASSEXT_CONST_TBL(ext) = RCLASSEXT_CONST_TBL(mod_ext); + RCLASSEXT_CVC_TBL(ext) = RCLASSEXT_CVC_TBL(mod_ext); + + // Those are cache and should be recreated when methods are called + // RCLASSEXT_CALLABLE_M_TBL(ext) = NULL; + // RCLASSEXT_CC_TBL(ext) = NULL; + + // subclasses, namespace_super_subclasses_tbl, namespace_module_subclasses_tbl + duplicate_classext_subclasses(src, ext); + + RCLASSEXT_SET_ORIGIN(ext, iclass, RCLASSEXT_ORIGIN(src)); + RCLASSEXT_ICLASS_IS_ORIGIN(ext) = RCLASSEXT_ICLASS_IS_ORIGIN(src); + RCLASSEXT_ICLASS_ORIGIN_SHARED_MTBL(ext) = RCLASSEXT_ICLASS_ORIGIN_SHARED_MTBL(src); + + RCLASSEXT_SET_INCLUDER(ext, iclass, RCLASSEXT_INCLUDER(src)); + + first_set = RCLASS_SET_NAMESPACE_CLASSEXT(iclass, ns, ext); + if (first_set) { + RCLASS_SET_PRIME_CLASSEXT_WRITABLE(iclass, false); + } +} + +rb_classext_t * +rb_class_duplicate_classext(rb_classext_t *orig, VALUE klass, const rb_namespace_t *ns) +{ + VM_ASSERT(RB_TYPE_P(klass, T_CLASS) || RB_TYPE_P(klass, T_MODULE) || RB_TYPE_P(klass, T_ICLASS)); + + rb_classext_t *ext = ZALLOC(rb_classext_t); + bool dup_iclass = RB_TYPE_P(klass, T_MODULE) ? true : false; + + RCLASSEXT_NS(ext) = ns; + + RCLASSEXT_SUPER(ext) = RCLASSEXT_SUPER(orig); + + RCLASSEXT_M_TBL(ext) = duplicate_classext_m_tbl(RCLASSEXT_M_TBL(orig), klass, dup_iclass); + + if (orig->fields_obj) { + RB_OBJ_WRITE(klass, &ext->fields_obj, rb_imemo_fields_clone(orig->fields_obj)); + } + + if (RCLASSEXT_SHARED_CONST_TBL(orig)) { + RCLASSEXT_CONST_TBL(ext) = RCLASSEXT_CONST_TBL(orig); + RCLASSEXT_SHARED_CONST_TBL(ext) = true; + } + else { + RCLASSEXT_CONST_TBL(ext) = duplicate_classext_const_tbl(RCLASSEXT_CONST_TBL(orig), klass); + RCLASSEXT_SHARED_CONST_TBL(ext) = false; + } + /* + * callable_m_tbl is for `super` chain, and entries will be created when the super chain is called. + * so initially, it can be NULL and let it be created lazily. + * RCLASSEXT_CALLABLE_M_TBL(ext) = NULL; + * + * cc_tbl is for method inline cache, and method calls from different namespaces never occur on + * the same code, so the copied classext should have a different cc_tbl from the prime one. + * RCLASSEXT_CC_TBL(copy) = NULL + */ + + RCLASSEXT_CVC_TBL(ext) = duplicate_classext_id_table(RCLASSEXT_CVC_TBL(orig), dup_iclass); + + // subclasses, subclasses_index + duplicate_classext_subclasses(orig, ext); + + RCLASSEXT_SET_ORIGIN(ext, klass, RCLASSEXT_ORIGIN(orig)); + /* + * Members not copied to namespace classext values + * * refined_class + * * as.class.allocator / as.singleton_class.attached_object + * * includer + * * max IV count + * * variation count + */ + RCLASSEXT_PERMANENT_CLASSPATH(ext) = RCLASSEXT_PERMANENT_CLASSPATH(orig); + RCLASSEXT_CLONED(ext) = RCLASSEXT_CLONED(orig); + RCLASSEXT_CLASSPATH(ext) = RCLASSEXT_CLASSPATH(orig); + + /* For the usual T_CLASS/T_MODULE, iclass flags are always false */ + + if (dup_iclass) { + VALUE iclass; + /* + * ICLASS has the same m_tbl/const_tbl/cvc_tbl with the included module. + * So the module's classext is copied, its tables should be also referred + * by the ICLASS's classext for the namespace. + */ + rb_subclass_anchor_t *anchor = RCLASSEXT_SUBCLASSES(ext); + rb_subclass_entry_t *subclass_entry = anchor->head; + while (subclass_entry) { + if (subclass_entry->klass && RB_TYPE_P(subclass_entry->klass, T_ICLASS)) { + iclass = subclass_entry->klass; + if (RBASIC_CLASS(iclass) == klass) { + // Is the subclass an ICLASS including this module into another class + // If so we need to re-associate it under our namespace with the new ext + class_duplicate_iclass_classext(iclass, ext, ns); + } + } + subclass_entry = subclass_entry->next; + } + } + + return ext; +} + +void +rb_class_ensure_writable(VALUE klass) +{ + VM_ASSERT(RB_TYPE_P(klass, T_CLASS) || RB_TYPE_P(klass, T_MODULE) || RB_TYPE_P(klass, T_ICLASS)); + RCLASS_EXT_WRITABLE(klass); +} + +struct class_classext_foreach_arg { + rb_class_classext_foreach_callback_func *func; + void * callback_arg; +}; + +static int +class_classext_foreach_i(st_data_t key, st_data_t value, st_data_t arg) +{ + struct class_classext_foreach_arg *foreach_arg = (struct class_classext_foreach_arg *)arg; + rb_class_classext_foreach_callback_func *func = foreach_arg->func; + func((rb_classext_t *)value, false, (VALUE)key, foreach_arg->callback_arg); + return ST_CONTINUE; +} + +void +rb_class_classext_foreach(VALUE klass, rb_class_classext_foreach_callback_func *func, void *arg) +{ + st_table *tbl = RCLASS_CLASSEXT_TBL(klass); + struct class_classext_foreach_arg foreach_arg; + if (tbl) { + foreach_arg.func = func; + foreach_arg.callback_arg = arg; + rb_st_foreach(tbl, class_classext_foreach_i, (st_data_t)&foreach_arg); + } + func(RCLASS_EXT_PRIME(klass), true, (VALUE)NULL, arg); +} + +VALUE +rb_class_super_of(VALUE klass) +{ + return RCLASS_SUPER(klass); +} + +VALUE +rb_class_singleton_p(VALUE klass) +{ + return RCLASS_SINGLETON_P(klass); +} + +unsigned char +rb_class_variation_count(VALUE klass) +{ + return RCLASS_VARIATION_COUNT(klass); +} + +static void +push_subclass_entry_to_list(VALUE super, VALUE klass, bool is_module) { rb_subclass_entry_t *entry, *head; + rb_subclass_anchor_t *anchor; + rb_ns_subclasses_t *ns_subclasses; + struct st_table *tbl; + const rb_namespace_t *ns = rb_current_namespace(); entry = ZALLOC(rb_subclass_entry_t); entry->klass = klass; - head = RCLASS_SUBCLASSES(super); - if (!head) { - head = ZALLOC(rb_subclass_entry_t); - RCLASS_SUBCLASSES(super) = head; - } - entry->next = head->next; - entry->prev = head; + RB_VM_LOCKING() { + anchor = RCLASS_WRITABLE_SUBCLASSES(super); + VM_ASSERT(anchor); + ns_subclasses = (rb_ns_subclasses_t *)anchor->ns_subclasses; + VM_ASSERT(ns_subclasses); + tbl = ns_subclasses->tbl; + VM_ASSERT(tbl); - if (head->next) { - head->next->prev = entry; + head = anchor->head; + if (head->next) { + head->next->prev = entry; + entry->next = head->next; + } + head->next = entry; + entry->prev = head; + st_insert(tbl, namespace_subclasses_tbl_key(ns), (st_data_t)entry); } - head->next = entry; - return entry; + if (is_module) { + RCLASS_WRITE_NS_MODULE_SUBCLASSES(klass, anchor->ns_subclasses); + } + else { + RCLASS_WRITE_NS_SUPER_SUBCLASSES(klass, anchor->ns_subclasses); + } } void rb_class_subclass_add(VALUE super, VALUE klass) { if (super && !UNDEF_P(super)) { - rb_subclass_entry_t *entry = push_subclass_entry_to_list(super, klass); - RCLASS_SUBCLASS_ENTRY(klass) = entry; + push_subclass_entry_to_list(super, klass, false); } } static void rb_module_add_to_subclasses_list(VALUE module, VALUE iclass) { - rb_subclass_entry_t *entry = push_subclass_entry_to_list(module, iclass); - RCLASS_MODULE_SUBCLASS_ENTRY(iclass) = entry; + if (module && !UNDEF_P(module)) { + push_subclass_entry_to_list(module, iclass, true); + } } void -rb_class_remove_subclass_head(VALUE klass) +rb_class_remove_subclass_head(VALUE klass) // TODO: check this is still used and required { - rb_subclass_entry_t *head = RCLASS_SUBCLASSES(klass); + rb_classext_t *ext = RCLASS_EXT_WRITABLE(klass); + rb_class_classext_free_subclasses(ext, klass); +} - if (head) { - if (head->next) { - head->next->prev = NULL; - } - RCLASS_SUBCLASSES(klass) = NULL; - xfree(head); +static struct rb_subclass_entry * +class_get_subclasses_for_ns(struct st_table *tbl, VALUE ns_id) +{ + st_data_t value; + if (st_lookup(tbl, (st_data_t)ns_id, &value)) { + return (struct rb_subclass_entry *)value; } + return NULL; } -void -rb_class_remove_from_super_subclasses(VALUE klass) +static void +remove_class_from_subclasses(struct st_table *tbl, VALUE ns_id, VALUE klass) { - rb_subclass_entry_t *entry = RCLASS_SUBCLASS_ENTRY(klass); + rb_subclass_entry_t *entry = class_get_subclasses_for_ns(tbl, ns_id); + bool first_entry = true; + while (entry) { + if (entry->klass == klass) { + rb_subclass_entry_t *prev = entry->prev, *next = entry->next; - if (entry) { - rb_subclass_entry_t *prev = entry->prev, *next = entry->next; + if (prev) { + prev->next = next; + } + if (next) { + next->prev = prev; + } + + xfree(entry); - if (prev) { - prev->next = next; + if (first_entry) { + if (next) { + st_insert(tbl, ns_id, (st_data_t)next); + } + else { + // no subclass entries in this ns + st_delete(tbl, &ns_id, NULL); + } + } + break; } - if (next) { - next->prev = prev; + else if (first_entry) { + first_entry = false; } - - xfree(entry); + entry = entry->next; } +} - RCLASS_SUBCLASS_ENTRY(klass) = NULL; +void +rb_class_remove_from_super_subclasses(VALUE klass) +{ + rb_classext_t *ext = RCLASS_EXT_WRITABLE(klass); + rb_ns_subclasses_t *ns_subclasses = RCLASSEXT_NS_SUPER_SUBCLASSES(ext); + + if (!ns_subclasses) return; + remove_class_from_subclasses(ns_subclasses->tbl, namespace_subclasses_tbl_key(RCLASSEXT_NS(ext)), klass); + rb_ns_subclasses_ref_dec(ns_subclasses); + RCLASSEXT_NS_SUPER_SUBCLASSES(ext) = 0; } void rb_class_remove_from_module_subclasses(VALUE klass) { - rb_subclass_entry_t *entry = RCLASS_MODULE_SUBCLASS_ENTRY(klass); + rb_classext_t *ext = RCLASS_EXT_WRITABLE(klass); + rb_ns_subclasses_t *ns_subclasses = RCLASSEXT_NS_MODULE_SUBCLASSES(ext); - if (entry) { - rb_subclass_entry_t *prev = entry->prev, *next = entry->next; + if (!ns_subclasses) return; + remove_class_from_subclasses(ns_subclasses->tbl, namespace_subclasses_tbl_key(RCLASSEXT_NS(ext)), klass); + rb_ns_subclasses_ref_dec(ns_subclasses); + RCLASSEXT_NS_MODULE_SUBCLASSES(ext) = 0; +} - if (prev) { - prev->next = next; - } - if (next) { - next->prev = prev; - } +void +rb_class_classext_free_subclasses(rb_classext_t *ext, VALUE klass) +{ + rb_subclass_anchor_t *anchor = RCLASSEXT_SUBCLASSES(ext); + struct st_table *tbl = anchor->ns_subclasses->tbl; + VALUE ns_id = namespace_subclasses_tbl_key(RCLASSEXT_NS(ext)); + rb_subclass_entry_t *next, *entry = anchor->head; + while (entry) { + next = entry->next; xfree(entry); + entry = next; } + VM_ASSERT( + rb_ns_subclasses_ref_count(anchor->ns_subclasses) > 0, + "ns_subclasses refcount (%p) %ld", anchor->ns_subclasses, rb_ns_subclasses_ref_count(anchor->ns_subclasses)); + st_delete(tbl, &ns_id, NULL); + rb_ns_subclasses_ref_dec(anchor->ns_subclasses); + xfree(anchor); - RCLASS_MODULE_SUBCLASS_ENTRY(klass) = NULL; + if (RCLASSEXT_NS_SUPER_SUBCLASSES(ext)) { + rb_ns_subclasses_t *ns_sub = RCLASSEXT_NS_SUPER_SUBCLASSES(ext); + remove_class_from_subclasses(ns_sub->tbl, ns_id, klass); + rb_ns_subclasses_ref_dec(ns_sub); + } + if (RCLASSEXT_NS_MODULE_SUBCLASSES(ext)) { + rb_ns_subclasses_t *ns_sub = RCLASSEXT_NS_MODULE_SUBCLASSES(ext); + remove_class_from_subclasses(ns_sub->tbl, ns_id, klass); + rb_ns_subclasses_ref_dec(ns_sub); + } } void rb_class_foreach_subclass(VALUE klass, void (*f)(VALUE, VALUE), VALUE arg) { - // RCLASS_SUBCLASSES should always point to our head element which has NULL klass - rb_subclass_entry_t *cur = RCLASS_SUBCLASSES(klass); - // if we have a subclasses list, then the head is a placeholder with no valid - // class. So ignore it and use the next element in the list (if one exists) - if (cur) { - RUBY_ASSERT(!cur->klass); - cur = cur->next; - } - + rb_subclass_entry_t *tmp; + rb_subclass_entry_t *cur = RCLASS_SUBCLASSES_FIRST(klass); /* do not be tempted to simplify this loop into a for loop, the order of operations is important here if `f` modifies the linked list */ while (cur) { VALUE curklass = cur->klass; - cur = cur->next; + tmp = cur->next; // do not trigger GC during f, otherwise the cur will become // a dangling pointer if the subclass is collected f(curklass, arg); + cur = tmp; } } @@ -214,75 +626,159 @@ rb_class_detach_module_subclasses(VALUE klass) rb_class_foreach_subclass(klass, class_detach_module_subclasses, Qnil); } +static void +class_switch_superclass(VALUE super, VALUE klass) +{ + class_detach_subclasses(klass, Qnil); + rb_class_subclass_add(super, klass); +} + /** - * Allocates a struct RClass for a new class. + * Allocates a struct RClass for a new class, iclass, or module. * - * \param flags initial value for basic.flags of the returned class. - * \param klass the class of the returned class. - * \return an uninitialized Class object. - * \pre \p klass must refer \c Class class or an ancestor of Class. - * \pre \code (flags | T_CLASS) != 0 \endcode - * \post the returned class can safely be \c #initialize 'd. + * @param type The type of the RClass (T_CLASS, T_ICLASS, or T_MODULE) + * @param klass value for basic.klass of the returned object. + * @return an uninitialized Class/IClass/Module object. + * @pre `klass` must refer to a class or module * - * \note this function is not Class#allocate. + * @note this function is not Class#allocate. */ static VALUE -class_alloc(VALUE flags, VALUE klass) +class_alloc0(enum ruby_value_type type, VALUE klass, bool namespaceable) { - size_t alloc_size = sizeof(struct RClass) + sizeof(rb_classext_t); + rb_ns_subclasses_t *ns_subclasses; + rb_subclass_anchor_t *anchor; + const rb_namespace_t *ns = rb_definition_namespace(); - flags &= T_MASK; + if (!ruby_namespace_init_done) { + namespaceable = true; + } + + size_t alloc_size = sizeof(struct RClass_and_rb_classext_t); + if (namespaceable) { + alloc_size = sizeof(struct RClass_namespaceable); + } + + // class_alloc is supposed to return a new object that is not promoted yet. + // So, we need to avoid GC after NEWOBJ_OF. + // To achieve that, we allocate subclass lists before NEWOBJ_OF. + // + // TODO: Note that this could cause memory leak. + // If NEWOBJ_OF fails with out of memory, these buffers will leak. + ns_subclasses = ZALLOC(rb_ns_subclasses_t); + ns_subclasses->refcount = 1; + ns_subclasses->tbl = st_init_numtable(); + anchor = ZALLOC(rb_subclass_anchor_t); + anchor->ns_subclasses = ns_subclasses; + anchor->head = ZALLOC(rb_subclass_entry_t); + + RUBY_ASSERT(type == T_CLASS || type == T_ICLASS || type == T_MODULE); + + VALUE flags = type; if (RGENGC_WB_PROTECTED_CLASS) flags |= FL_WB_PROTECTED; + if (namespaceable) flags |= RCLASS_NAMESPACEABLE; + NEWOBJ_OF(obj, struct RClass, klass, flags, alloc_size, 0); - memset(RCLASS_EXT(obj), 0, sizeof(rb_classext_t)); + memset(RCLASS_EXT_PRIME(obj), 0, sizeof(rb_classext_t)); /* ZALLOC RCLASS_CONST_TBL(obj) = 0; RCLASS_M_TBL(obj) = 0; - RCLASS_IV_INDEX_TBL(obj) = 0; + RCLASS_FIELDS(obj) = 0; RCLASS_SET_SUPER((VALUE)obj, 0); - RCLASS_SUBCLASSES(obj) = NULL; - RCLASS_PARENT_SUBCLASSES(obj) = NULL; - RCLASS_MODULE_SUBCLASSES(obj) = NULL; */ + + RCLASS_PRIME_NS((VALUE)obj) = ns; + // Classes/Modules defined in user namespaces are + // writable directly because it exists only in a namespace. + RCLASS_SET_PRIME_CLASSEXT_WRITABLE((VALUE)obj, !namespaceable || NAMESPACE_USER_P(ns)); + RCLASS_SET_ORIGIN((VALUE)obj, (VALUE)obj); - RB_OBJ_WRITE(obj, &RCLASS_REFINED_CLASS(obj), Qnil); - RCLASS_SET_ALLOCATOR((VALUE)obj, 0); + RCLASS_SET_REFINED_CLASS((VALUE)obj, Qnil); + + RCLASS_SET_SUBCLASSES((VALUE)obj, anchor); return (VALUE)obj; } +static VALUE +class_alloc(enum ruby_value_type type, VALUE klass) +{ + return class_alloc0(type, klass, false); +} + +static VALUE +class_associate_super(VALUE klass, VALUE super, bool init) +{ + if (super && !UNDEF_P(super)) { + class_switch_superclass(super, klass); + } + if (init) { + RCLASS_SET_SUPER(klass, super); + } + else { + RCLASS_WRITE_SUPER(klass, super); + } + rb_class_update_superclasses(klass); + return super; +} + +VALUE +rb_class_set_super(VALUE klass, VALUE super) +{ + return class_associate_super(klass, super, false); +} + static void -RCLASS_M_TBL_INIT(VALUE c) +class_initialize_method_table(VALUE c) { - RCLASS_M_TBL(c) = rb_id_table_create(0); + // initialize the prime classext m_tbl + RCLASS_SET_M_TBL_EVEN_WHEN_PROMOTED(c, rb_id_table_create(0)); } -/*! +static void +class_clear_method_table(VALUE c) +{ + RCLASS_WRITE_M_TBL_EVEN_WHEN_PROMOTED(c, rb_id_table_create(0)); +} + +static VALUE +class_boot_namespaceable(VALUE super, bool namespaceable) +{ + VALUE klass = class_alloc0(T_CLASS, rb_cClass, namespaceable); + + // initialize method table prior to class_associate_super() + // because class_associate_super() may cause GC and promote klass + class_initialize_method_table(klass); + + class_associate_super(klass, super, true); + if (super && !UNDEF_P(super)) { + rb_class_set_initialized(klass); + } + + return (VALUE)klass; +} + +/** * A utility function that wraps class_alloc. * * allocates a class and initializes safely. - * \param super a class from which the new class derives. - * \return a class object. - * \pre \a super must be a class. - * \post the metaclass of the new class is Class. + * @param super a class from which the new class derives. + * @return a class object. + * @pre `super` must be a class. + * @post the metaclass of the new class is Class. */ VALUE rb_class_boot(VALUE super) { - VALUE klass = class_alloc(T_CLASS, rb_cClass); - - RCLASS_SET_SUPER(klass, super); - RCLASS_M_TBL_INIT(klass); - - return (VALUE)klass; + return class_boot_namespaceable(super, false); } static VALUE * class_superclasses_including_self(VALUE klass) { - if (FL_TEST_RAW(klass, RCLASS_SUPERCLASSES_INCLUDE_SELF)) + if (RCLASS_SUPERCLASSES_WITH_SELF_P(klass)) return RCLASS_SUPERCLASSES(klass); size_t depth = RCLASS_SUPERCLASS_DEPTH(klass); @@ -291,14 +787,14 @@ class_superclasses_including_self(VALUE klass) memcpy(superclasses, RCLASS_SUPERCLASSES(klass), sizeof(VALUE) * depth); superclasses[depth] = klass; - RCLASS_SUPERCLASSES(klass) = superclasses; - FL_SET_RAW(klass, RCLASS_SUPERCLASSES_INCLUDE_SELF); return superclasses; } void rb_class_update_superclasses(VALUE klass) { + VALUE *superclasses; + size_t super_depth; VALUE super = RCLASS_SUPER(klass); if (!RB_TYPE_P(klass, T_CLASS)) return; @@ -327,8 +823,17 @@ rb_class_update_superclasses(VALUE klass) return; } - RCLASS_SUPERCLASSES(klass) = class_superclasses_including_self(super); - RCLASS_SUPERCLASS_DEPTH(klass) = RCLASS_SUPERCLASS_DEPTH(super) + 1; + super_depth = RCLASS_SUPERCLASS_DEPTH(super); + if (RCLASS_SUPERCLASSES_WITH_SELF_P(super)) { + superclasses = RCLASS_SUPERCLASSES(super); + } + else { + superclasses = class_superclasses_including_self(super); + RCLASS_WRITE_SUPERCLASSES(super, super_depth, superclasses, true); + } + + size_t depth = super_depth == RCLASS_MAX_SUPERCLASS_DEPTH ? super_depth : super_depth + 1; + RCLASS_WRITE_SUPERCLASSES(klass, depth, superclasses, false); } void @@ -338,7 +843,7 @@ rb_check_inheritable(VALUE super) rb_raise(rb_eTypeError, "superclass must be an instance of Class (given an instance of %"PRIsVALUE")", rb_obj_class(super)); } - if (RBASIC(super)->flags & FL_SINGLETON) { + if (RCLASS_SINGLETON_P(super)) { rb_raise(rb_eTypeError, "can't make subclass of singleton class"); } if (super == rb_cClass) { @@ -354,9 +859,11 @@ rb_class_new(VALUE super) VALUE klass = rb_class_boot(super); if (super != rb_cObject && super != rb_cBasicObject) { - RCLASS_EXT(klass)->max_iv_count = RCLASS_EXT(super)->max_iv_count; + RCLASS_SET_MAX_IV_COUNT(klass, RCLASS_MAX_IV_COUNT(super)); } + RUBY_ASSERT(getenv("RUBY_NAMESPACE") || RCLASS_PRIME_CLASSEXT_WRITABLE_P(klass)); + return klass; } @@ -370,8 +877,7 @@ static void clone_method(VALUE old_klass, VALUE new_klass, ID mid, const rb_method_entry_t *me) { if (me->def->type == VM_METHOD_TYPE_ISEQ) { - rb_cref_t *new_cref; - rb_vm_rewrite_cref(me->def->body.iseq.cref, old_klass, new_klass, &new_cref); + rb_cref_t *new_cref = rb_vm_rewrite_cref(me->def->body.iseq.cref, old_klass, new_klass); rb_add_method_iseq(new_klass, mid, me->def->body.iseq.iseqptr, new_cref, METHOD_ENTRY_VISI(me)); } else { @@ -421,10 +927,10 @@ class_init_copy_check(VALUE clone, VALUE orig) if (orig == rb_cBasicObject) { rb_raise(rb_eTypeError, "can't copy the root class"); } - if (RCLASS_SUPER(clone) != 0 || clone == rb_cBasicObject) { + if (RCLASS_INITIALIZED_P(clone)) { rb_raise(rb_eTypeError, "already initialized class"); } - if (FL_TEST(orig, FL_SINGLETON)) { + if (RCLASS_SINGLETON_P(orig)) { rb_raise(rb_eTypeError, "can't copy singleton class"); } } @@ -459,7 +965,7 @@ copy_tables(VALUE clone, VALUE orig) { if (RCLASS_CONST_TBL(clone)) { rb_free_const_table(RCLASS_CONST_TBL(clone)); - RCLASS_CONST_TBL(clone) = 0; + RCLASS_WRITE_CONST_TBL(clone, 0, false); } if (RCLASS_CVC_TBL(orig)) { struct rb_id_table *rb_cvc_tbl = RCLASS_CVC_TBL(orig); @@ -469,51 +975,38 @@ copy_tables(VALUE clone, VALUE orig) ctx.clone = clone; ctx.new_table = rb_cvc_tbl_dup; rb_id_table_foreach(rb_cvc_tbl, cvc_table_copy, &ctx); - RCLASS_CVC_TBL(clone) = rb_cvc_tbl_dup; + RCLASS_WRITE_CVC_TBL(clone, rb_cvc_tbl_dup); } - RCLASS_M_TBL(clone) = 0; + rb_id_table_free(RCLASS_M_TBL(clone)); + RCLASS_WRITE_M_TBL_EVEN_WHEN_PROMOTED(clone, 0); if (!RB_TYPE_P(clone, T_ICLASS)) { - st_data_t id; - - rb_iv_tbl_copy(clone, orig); - CONST_ID(id, "__tmp_classpath__"); - rb_attr_delete(clone, id); - CONST_ID(id, "__classpath__"); - rb_attr_delete(clone, id); + rb_fields_tbl_copy(clone, orig); } if (RCLASS_CONST_TBL(orig)) { struct clone_const_arg arg; - - arg.tbl = RCLASS_CONST_TBL(clone) = rb_id_table_create(0); + struct rb_id_table *const_tbl; + struct rb_id_table *orig_tbl = RCLASS_CONST_TBL(orig); + arg.tbl = const_tbl = rb_id_table_create(rb_id_table_size(orig_tbl)); arg.klass = clone; - rb_id_table_foreach(RCLASS_CONST_TBL(orig), clone_const_i, &arg); + rb_id_table_foreach(orig_tbl, clone_const_i, &arg); + RCLASS_WRITE_CONST_TBL(clone, const_tbl, false); } } static bool ensure_origin(VALUE klass); -/** - * If this flag is set, that module is allocated but not initialized yet. - */ -enum {RMODULE_ALLOCATED_BUT_NOT_INITIALIZED = RUBY_FL_USER1}; - -static inline bool -RMODULE_UNINITIALIZED(VALUE module) -{ - return FL_TEST_RAW(module, RMODULE_ALLOCATED_BUT_NOT_INITIALIZED); -} - void -rb_module_set_initialized(VALUE mod) +rb_class_set_initialized(VALUE klass) { - FL_UNSET_RAW(mod, RMODULE_ALLOCATED_BUT_NOT_INITIALIZED); + RUBY_ASSERT(RB_TYPE_P(klass, T_CLASS) || RB_TYPE_P(klass, T_MODULE)); + FL_SET_RAW(klass, RCLASS_IS_INITIALIZED); /* no more re-initialization */ } void rb_module_check_initializable(VALUE mod) { - if (!RMODULE_UNINITIALIZED(mod)) { + if (RCLASS_INITIALIZED_P(mod)) { rb_raise(rb_eTypeError, "already initialized module"); } } @@ -522,9 +1015,11 @@ rb_module_check_initializable(VALUE mod) VALUE rb_mod_init_copy(VALUE clone, VALUE orig) { + /* Only class or module is valid here, but other classes may enter here and + * only hit an exception on the OBJ_INIT_COPY checks + */ switch (BUILTIN_TYPE(clone)) { case T_CLASS: - case T_ICLASS: class_init_copy_check(clone, orig); break; case T_MODULE: @@ -535,28 +1030,37 @@ rb_mod_init_copy(VALUE clone, VALUE orig) } if (!OBJ_INIT_COPY(clone, orig)) return clone; + RUBY_ASSERT(RB_TYPE_P(orig, T_CLASS) || RB_TYPE_P(orig, T_MODULE)); + RUBY_ASSERT(BUILTIN_TYPE(clone) == BUILTIN_TYPE(orig)); + + rb_class_set_initialized(clone); + /* cloned flag is refer at constant inline cache * see vm_get_const_key_cref() in vm_insnhelper.c */ - RCLASS_EXT(clone)->cloned = true; - RCLASS_EXT(orig)->cloned = true; + RCLASS_SET_CLONED(clone, true); + RCLASS_SET_CLONED(orig, true); - if (!FL_TEST(CLASS_OF(clone), FL_SINGLETON)) { + if (!RCLASS_SINGLETON_P(CLASS_OF(clone))) { RBASIC_SET_CLASS(clone, rb_singleton_class_clone(orig)); rb_singleton_class_attached(METACLASS_OF(clone), (VALUE)clone); } - RCLASS_SET_ALLOCATOR(clone, RCLASS_ALLOCATOR(orig)); + if (BUILTIN_TYPE(clone) == T_CLASS) { + RCLASS_SET_ALLOCATOR(clone, RCLASS_ALLOCATOR(orig)); + } copy_tables(clone, orig); if (RCLASS_M_TBL(orig)) { struct clone_method_arg arg; arg.old_klass = orig; arg.new_klass = clone; - RCLASS_M_TBL_INIT(clone); + // TODO: use class_initialize_method_table() instead of RCLASS_SET_M_TBL_* + // after RCLASS_SET_M_TBL is protected by write barrier + RCLASS_SET_M_TBL_EVEN_WHEN_PROMOTED(clone, rb_id_table_create(0)); rb_id_table_foreach(RCLASS_M_TBL(orig), clone_method_i, &arg); } if (RCLASS_ORIGIN(orig) == orig) { - RCLASS_SET_SUPER(clone, RCLASS_SUPER(orig)); + rb_class_set_super(clone, RCLASS_SUPER(orig)); } else { VALUE p = RCLASS_SUPER(orig); @@ -576,12 +1080,14 @@ rb_mod_init_copy(VALUE clone, VALUE orig) if (BUILTIN_TYPE(p) != T_ICLASS) { rb_bug("non iclass between module/class and origin"); } - clone_p = class_alloc(RBASIC(p)->flags, METACLASS_OF(p)); - RCLASS_SET_SUPER(prev_clone_p, clone_p); + clone_p = class_alloc(T_ICLASS, METACLASS_OF(p)); + /* We should set the m_tbl right after allocation before anything + * that can trigger GC to avoid clone_p from becoming old and + * needing to fire write barriers. */ + RCLASS_SET_M_TBL(clone_p, RCLASS_M_TBL(p)); + rb_class_set_super(prev_clone_p, clone_p); prev_clone_p = clone_p; - RCLASS_M_TBL(clone_p) = RCLASS_M_TBL(p); - RCLASS_CONST_TBL(clone_p) = RCLASS_CONST_TBL(p); - RCLASS_SET_ALLOCATOR(clone_p, RCLASS_ALLOCATOR(p)); + RCLASS_SET_CONST_TBL(clone_p, RCLASS_CONST_TBL(p), false); if (RB_TYPE_P(clone, T_CLASS)) { RCLASS_SET_INCLUDER(clone_p, clone); } @@ -593,8 +1099,8 @@ rb_mod_init_copy(VALUE clone, VALUE orig) } else if ((origin_len = RARRAY_LEN(origin_stack)) > 1 && RARRAY_AREF(origin_stack, origin_len - 1) == p) { - RCLASS_SET_ORIGIN(RARRAY_AREF(origin_stack, (origin_len -= 2)), clone_p); - RICLASS_SET_ORIGIN_SHARED_MTBL(clone_p); + RCLASS_WRITE_ORIGIN(RARRAY_AREF(origin_stack, (origin_len -= 2)), clone_p); + RICLASS_WRITE_ORIGIN_SHARED_MTBL(clone_p); rb_ary_resize(origin_stack, origin_len); add_subclass = FALSE; } @@ -606,15 +1112,15 @@ rb_mod_init_copy(VALUE clone, VALUE orig) if (p == orig_origin) { if (clone_p) { - RCLASS_SET_SUPER(clone_p, clone_origin); - RCLASS_SET_SUPER(clone_origin, RCLASS_SUPER(orig_origin)); + rb_class_set_super(clone_p, clone_origin); + rb_class_set_super(clone_origin, RCLASS_SUPER(orig_origin)); } copy_tables(clone_origin, orig_origin); if (RCLASS_M_TBL(orig_origin)) { struct clone_method_arg arg; arg.old_klass = orig; arg.new_klass = clone; - RCLASS_M_TBL_INIT(clone_origin); + class_initialize_method_table(clone_origin); rb_id_table_foreach(RCLASS_M_TBL(orig_origin), clone_method_i, &arg); } } @@ -644,14 +1150,15 @@ rb_singleton_class_clone_and_attach(VALUE obj, VALUE attach) // attached to an object other than `obj`. In which case `obj` does not have // a material singleton class attached yet and there is no singleton class // to clone. - if (!(FL_TEST(klass, FL_SINGLETON) && RCLASS_ATTACHED_OBJECT(klass) == obj)) { + if (!(RCLASS_SINGLETON_P(klass) && RCLASS_ATTACHED_OBJECT(klass) == obj)) { // nothing to clone return klass; } else { /* copy singleton(unnamed) class */ bool klass_of_clone_is_new; - VALUE clone = class_alloc(RBASIC(klass)->flags, 0); + RUBY_ASSERT(RB_TYPE_P(klass, T_CLASS)); + VALUE clone = class_alloc(T_CLASS, 0); if (BUILTIN_TYPE(obj) == T_CLASS) { klass_of_clone_is_new = true; @@ -665,18 +1172,22 @@ rb_singleton_class_clone_and_attach(VALUE obj, VALUE attach) RBASIC_SET_CLASS(clone, klass_metaclass_clone); } - RCLASS_SET_SUPER(clone, RCLASS_SUPER(klass)); - rb_iv_tbl_copy(clone, klass); + // initialize method table before any GC chance + class_initialize_method_table(clone); + + rb_class_set_super(clone, RCLASS_SUPER(klass)); + rb_fields_tbl_copy(clone, klass); if (RCLASS_CONST_TBL(klass)) { struct clone_const_arg arg; - arg.tbl = RCLASS_CONST_TBL(clone) = rb_id_table_create(0); + struct rb_id_table *table; + arg.tbl = table = rb_id_table_create(0); arg.klass = clone; rb_id_table_foreach(RCLASS_CONST_TBL(klass), clone_const_i, &arg); + RCLASS_SET_CONST_TBL(clone, table, false); } if (!UNDEF_P(attach)) { rb_singleton_class_attached(clone, attach); } - RCLASS_M_TBL_INIT(clone); { struct clone_method_arg arg; arg.old_klass = klass; @@ -695,7 +1206,7 @@ rb_singleton_class_clone_and_attach(VALUE obj, VALUE attach) void rb_singleton_class_attached(VALUE klass, VALUE obj) { - if (FL_TEST(klass, FL_SINGLETON)) { + if (RCLASS_SINGLETON_P(klass)) { RCLASS_SET_ATTACHED_OBJECT(klass, obj); } } @@ -720,7 +1231,7 @@ rb_singleton_class_internal_p(VALUE sklass) !rb_singleton_class_has_metaclass_p(sklass)); } -/*! +/** * whether k has a metaclass * @retval 1 if \a k has a metaclass * @retval 0 otherwise @@ -729,31 +1240,31 @@ rb_singleton_class_internal_p(VALUE sklass) (FL_TEST(METACLASS_OF(k), FL_SINGLETON) && \ rb_singleton_class_has_metaclass_p(k)) -/*! - * ensures \a klass belongs to its own eigenclass. - * @return the eigenclass of \a klass - * @post \a klass belongs to the returned eigenclass. - * i.e. the attached object of the eigenclass is \a klass. +/** + * ensures `klass` belongs to its own eigenclass. + * @return the eigenclass of `klass` + * @post `klass` belongs to the returned eigenclass. + * i.e. the attached object of the eigenclass is `klass`. * @note this macro creates a new eigenclass if necessary. */ #define ENSURE_EIGENCLASS(klass) \ (HAVE_METACLASS_P(klass) ? METACLASS_OF(klass) : make_metaclass(klass)) -/*! - * Creates a metaclass of \a klass - * \param klass a class - * \return created metaclass for the class - * \pre \a klass is a Class object - * \pre \a klass has no singleton class. - * \post the class of \a klass is the returned class. - * \post the returned class is meta^(n+1)-class when \a klass is a meta^(n)-klass for n >= 0 +/** + * Creates a metaclass of `klass` + * @param klass a class + * @return created metaclass for the class + * @pre `klass` is a Class object + * @pre `klass` has no singleton class. + * @post the class of `klass` is the returned class. + * @post the returned class is meta^(n+1)-class when `klass` is a meta^(n)-klass for n >= 0 */ static inline VALUE make_metaclass(VALUE klass) { VALUE super; - VALUE metaclass = rb_class_boot(Qundef); + VALUE metaclass = class_boot_namespaceable(Qundef, FL_TEST_RAW(klass, RCLASS_NAMESPACEABLE)); FL_SET(metaclass, FL_SINGLETON); rb_singleton_class_attached(metaclass, klass); @@ -770,7 +1281,8 @@ make_metaclass(VALUE klass) super = RCLASS_SUPER(klass); while (RB_TYPE_P(super, T_ICLASS)) super = RCLASS_SUPER(super); - RCLASS_SET_SUPER(metaclass, super ? ENSURE_EIGENCLASS(super) : rb_cClass); + class_associate_super(metaclass, super ? ENSURE_EIGENCLASS(super) : rb_cClass, true); + rb_class_set_initialized(klass); // Full class ancestry may not have been filled until we reach here. rb_class_update_superclasses(METACLASS_OF(metaclass)); @@ -778,21 +1290,22 @@ make_metaclass(VALUE klass) return metaclass; } -/*! - * Creates a singleton class for \a obj. - * \pre \a obj must not a immediate nor a special const. - * \pre \a obj must not a Class object. - * \pre \a obj has no singleton class. +/** + * Creates a singleton class for `obj`. + * @pre `obj` must not be an immediate nor a special const. + * @pre `obj` must not be a Class object. + * @pre `obj` has no singleton class. */ static inline VALUE make_singleton_class(VALUE obj) { VALUE orig_class = METACLASS_OF(obj); - VALUE klass = rb_class_boot(orig_class); + VALUE klass = class_boot_namespaceable(orig_class, FL_TEST_RAW(orig_class, RCLASS_NAMESPACEABLE)); FL_SET(klass, FL_SINGLETON); RBASIC_SET_CLASS(obj, klass); rb_singleton_class_attached(klass, obj); + rb_yjit_invalidate_no_singleton_class(orig_class); SET_METACLASS_OF(klass, METACLASS_OF(rb_class_real(orig_class))); return klass; @@ -806,7 +1319,7 @@ boot_defclass(const char *name, VALUE super) ID id = rb_intern(name); rb_const_set((rb_cObject ? rb_cObject : obj), id, obj); - rb_vm_add_root_module(obj); + rb_vm_register_global_object(obj); return obj; } @@ -888,7 +1401,7 @@ Init_class_hierarchy(void) { rb_cBasicObject = boot_defclass("BasicObject", 0); rb_cObject = boot_defclass("Object", rb_cBasicObject); - rb_gc_register_mark_object(rb_cObject); + rb_vm_register_global_object(rb_cObject); /* resolve class name ASAP for order-independence */ rb_set_class_path_string(rb_cObject, rb_cObject, rb_fstring_lit("Object")); @@ -913,15 +1426,15 @@ Init_class_hierarchy(void) } -/*! - * \internal +/** + * @internal * Creates a new *singleton class* for an object. * - * \pre \a obj has no singleton class. - * \note DO NOT USE the function in an extension libraries. Use \ref rb_singleton_class. - * \param obj An object. - * \param unused ignored. - * \return The singleton class of the object. + * @pre `obj` has no singleton class. + * @note DO NOT USE the function in an extension libraries. Use @ref rb_singleton_class. + * @param obj An object. + * @param unused ignored. + * @return The singleton class of the object. */ VALUE rb_make_metaclass(VALUE obj, VALUE unused) @@ -947,13 +1460,13 @@ rb_define_class_id(ID id, VALUE super) } -/*! +/** * Calls Class#inherited. - * \param super A class which will be called #inherited. + * @param super A class which will be called #inherited. * NULL means Object class. - * \param klass A Class object which derived from \a super - * \return the value \c Class#inherited's returns - * \pre Each of \a super and \a klass must be a \c Class object. + * @param klass A Class object which derived from `super` + * @return the value `Class#inherited` returns + * @pre Each of `super` and `klass` must be a `Class` object. */ VALUE rb_class_inherited(VALUE super, VALUE klass) @@ -969,8 +1482,12 @@ rb_define_class(const char *name, VALUE super) { VALUE klass; ID id; + const rb_namespace_t *ns = rb_current_namespace(); id = rb_intern(name); + if (NAMESPACE_OPTIONAL_P(ns)) { + return rb_define_class_id_under(ns->ns_object, id, super); + } if (rb_const_defined(rb_cObject, id)) { klass = rb_const_get(rb_cObject, id); if (!RB_TYPE_P(klass, T_CLASS)) { @@ -982,14 +1499,14 @@ rb_define_class(const char *name, VALUE super) } /* Class may have been defined in Ruby and not pin-rooted */ - rb_vm_add_root_module(klass); + rb_vm_register_global_object(klass); return klass; } if (!super) { - rb_raise(rb_eArgError, "no super class for `%s'", name); + rb_raise(rb_eArgError, "no super class for '%s'", name); } klass = rb_define_class_id(id, super); - rb_vm_add_root_module(klass); + rb_vm_register_global_object(klass); rb_const_set(rb_cObject, id, klass); rb_class_inherited(super, klass); @@ -1003,7 +1520,7 @@ rb_define_class_under(VALUE outer, const char *name, VALUE super) } VALUE -rb_define_class_id_under(VALUE outer, ID id, VALUE super) +rb_define_class_id_under_no_pin(VALUE outer, ID id, VALUE super) { VALUE klass; @@ -1020,30 +1537,34 @@ rb_define_class_id_under(VALUE outer, ID id, VALUE super) " (%"PRIsVALUE" is given but was %"PRIsVALUE")", outer, rb_id2str(id), RCLASS_SUPER(klass), super); } - /* Class may have been defined in Ruby and not pin-rooted */ - rb_vm_add_root_module(klass); return klass; } if (!super) { - rb_raise(rb_eArgError, "no super class for `%"PRIsVALUE"::%"PRIsVALUE"'", + rb_raise(rb_eArgError, "no super class for '%"PRIsVALUE"::%"PRIsVALUE"'", rb_class_path(outer), rb_id2str(id)); } klass = rb_define_class_id(id, super); rb_set_class_path_string(klass, outer, rb_id2str(id)); rb_const_set(outer, id, klass); rb_class_inherited(super, klass); - rb_vm_add_root_module(klass); return klass; } +VALUE +rb_define_class_id_under(VALUE outer, ID id, VALUE super) +{ + VALUE klass = rb_define_class_id_under_no_pin(outer, id, super); + rb_vm_register_global_object(klass); + return klass; +} + VALUE rb_module_s_alloc(VALUE klass) { VALUE mod = class_alloc(T_MODULE, klass); - RCLASS_M_TBL_INIT(mod); - FL_SET(mod, RMODULE_ALLOCATED_BUT_NOT_INITIALIZED); + class_initialize_method_table(mod); return mod; } @@ -1051,7 +1572,7 @@ static inline VALUE module_new(VALUE klass) { VALUE mdl = class_alloc(T_MODULE, klass); - RCLASS_M_TBL_INIT(mdl); + class_initialize_method_table(mdl); return (VALUE)mdl; } @@ -1079,8 +1600,12 @@ rb_define_module(const char *name) { VALUE module; ID id; + const rb_namespace_t *ns = rb_current_namespace(); id = rb_intern(name); + if (NAMESPACE_OPTIONAL_P(ns)) { + return rb_define_module_id_under(ns->ns_object, id); + } if (rb_const_defined(rb_cObject, id)) { module = rb_const_get(rb_cObject, id); if (!RB_TYPE_P(module, T_MODULE)) { @@ -1088,11 +1613,11 @@ rb_define_module(const char *name) name, rb_obj_class(module)); } /* Module may have been defined in Ruby and not pin-rooted */ - rb_vm_add_root_module(module); + rb_vm_register_global_object(module); return module; } module = rb_module_new(); - rb_vm_add_root_module(module); + rb_vm_register_global_object(module); rb_const_set(rb_cObject, id, module); return module; @@ -1117,43 +1642,40 @@ rb_define_module_id_under(VALUE outer, ID id) outer, rb_id2str(id), rb_obj_class(module)); } /* Module may have been defined in Ruby and not pin-rooted */ - rb_gc_register_mark_object(module); + rb_vm_register_global_object(module); return module; } module = rb_module_new(); rb_const_set(outer, id, module); rb_set_class_path_string(module, outer, rb_id2str(id)); - rb_gc_register_mark_object(module); + rb_vm_register_global_object(module); return module; } -VALUE -rb_iclass_alloc(VALUE klass) -{ - return class_alloc(T_ICLASS, klass); -} - VALUE rb_include_class_new(VALUE module, VALUE super) { - VALUE klass = rb_iclass_alloc(rb_cClass); + VALUE klass = class_alloc(T_ICLASS, rb_cClass); - RCLASS_M_TBL(klass) = RCLASS_M_TBL(module); + RCLASS_SET_M_TBL(klass, RCLASS_WRITABLE_M_TBL(module)); RCLASS_SET_ORIGIN(klass, klass); if (BUILTIN_TYPE(module) == T_ICLASS) { module = METACLASS_OF(module); } RUBY_ASSERT(!RB_TYPE_P(module, T_ICLASS)); - if (!RCLASS_CONST_TBL(module)) { - RCLASS_CONST_TBL(module) = rb_id_table_create(0); + if (RCLASS_WRITABLE_CONST_TBL(module)) { + RCLASS_SET_CONST_TBL(klass, RCLASS_WRITABLE_CONST_TBL(module), true); + } + else { + RCLASS_WRITE_CONST_TBL(module, rb_id_table_create(0), false); + RCLASS_SET_CONST_TBL(klass, RCLASS_WRITABLE_CONST_TBL(module), true); } - RCLASS_CVC_TBL(klass) = RCLASS_CVC_TBL(module); - RCLASS_CONST_TBL(klass) = RCLASS_CONST_TBL(module); + RCLASS_SET_CVC_TBL(klass, RCLASS_WRITABLE_CVC_TBL(module)); - RCLASS_SET_SUPER(klass, super); + class_associate_super(klass, super, true); RBASIC_SET_CLASS(klass, module); return (VALUE)klass; @@ -1166,7 +1688,7 @@ ensure_includable(VALUE klass, VALUE module) { rb_class_modify_check(klass); Check_Type(module, T_MODULE); - rb_module_set_initialized(module); + rb_class_set_initialized(module); if (!NIL_P(rb_refinement_module_get_refined_class(module))) { rb_raise(rb_eArgError, "refinement module is not allowed"); } @@ -1184,15 +1706,9 @@ rb_include_module(VALUE klass, VALUE module) rb_raise(rb_eArgError, "cyclic include detected"); if (RB_TYPE_P(klass, T_MODULE)) { - rb_subclass_entry_t *iclass = RCLASS_SUBCLASSES(klass); - // skip the placeholder subclass entry at the head of the list - if (iclass) { - RUBY_ASSERT(!iclass->klass); - iclass = iclass->next; - } - - int do_include = 1; + rb_subclass_entry_t *iclass = RCLASS_SUBCLASSES_FIRST(klass); while (iclass) { + int do_include = 1; VALUE check_class = iclass->klass; /* During lazy sweeping, iclass->klass could be a dead object that * has not yet been swept. */ @@ -1259,7 +1775,7 @@ static int do_include_modules_at(const VALUE klass, VALUE c, VALUE module, int search_super, bool check_cyclic) { VALUE p, iclass, origin_stack = 0; - int method_changed = 0, add_subclass; + int method_changed = 0; long origin_len; VALUE klass_origin = RCLASS_ORIGIN(klass); VALUE original_klass = klass; @@ -1321,9 +1837,8 @@ do_include_modules_at(const VALUE klass, VALUE c, VALUE module, int search_super // setup T_ICLASS for the include/prepend module iclass = rb_include_class_new(module, super_class); - c = RCLASS_SET_SUPER(c, iclass); + c = rb_class_set_super(c, iclass); RCLASS_SET_INCLUDER(iclass, klass); - add_subclass = TRUE; if (module != RCLASS_ORIGIN(module)) { if (!origin_stack) origin_stack = rb_ary_hidden_new(2); VALUE origin[2] = {iclass, RCLASS_ORIGIN(module)}; @@ -1331,17 +1846,14 @@ do_include_modules_at(const VALUE klass, VALUE c, VALUE module, int search_super } else if (origin_stack && (origin_len = RARRAY_LEN(origin_stack)) > 1 && RARRAY_AREF(origin_stack, origin_len - 1) == module) { - RCLASS_SET_ORIGIN(RARRAY_AREF(origin_stack, (origin_len -= 2)), iclass); - RICLASS_SET_ORIGIN_SHARED_MTBL(iclass); + RCLASS_WRITE_ORIGIN(RARRAY_AREF(origin_stack, (origin_len -= 2)), iclass); + RICLASS_WRITE_ORIGIN_SHARED_MTBL(iclass); rb_ary_resize(origin_stack, origin_len); - add_subclass = FALSE; } - if (add_subclass) { - VALUE m = module; - if (BUILTIN_TYPE(m) == T_ICLASS) m = METACLASS_OF(m); - rb_module_add_to_subclasses_list(m, iclass); - } + VALUE m = module; + if (BUILTIN_TYPE(m) == T_ICLASS) m = METACLASS_OF(m); + rb_module_add_to_subclasses_list(m, iclass); if (BUILTIN_TYPE(klass) == T_MODULE && FL_TEST(klass, RMODULE_IS_REFINEMENT)) { VALUE refined_class = @@ -1374,7 +1886,7 @@ move_refined_method(ID key, VALUE value, void *data) if (me->def->type == VM_METHOD_TYPE_REFINED) { VALUE klass = (VALUE)data; - struct rb_id_table *tbl = RCLASS_M_TBL(klass); + struct rb_id_table *tbl = RCLASS_WRITABLE_M_TBL(klass); if (me->def->body.refined.orig_me) { const rb_method_entry_t *orig_me = me->def->body.refined.orig_me, *new_me; @@ -1414,12 +1926,12 @@ ensure_origin(VALUE klass) { VALUE origin = RCLASS_ORIGIN(klass); if (origin == klass) { - origin = rb_iclass_alloc(klass); - RCLASS_SET_SUPER(origin, RCLASS_SUPER(klass)); - RCLASS_SET_SUPER(klass, origin); - RCLASS_SET_ORIGIN(klass, origin); - RCLASS_M_TBL(origin) = RCLASS_M_TBL(klass); - RCLASS_M_TBL_INIT(klass); + origin = class_alloc(T_ICLASS, klass); + RCLASS_SET_M_TBL(origin, RCLASS_M_TBL(klass)); + rb_class_set_super(origin, RCLASS_SUPER(klass)); + rb_class_set_super(klass, origin); // writes origin into RCLASS_SUPER(klass) + RCLASS_WRITE_ORIGIN(klass, origin); + class_clear_method_table(klass); rb_id_table_foreach(RCLASS_M_TBL(origin), cache_clear_refined_method, (void *)klass); rb_id_table_foreach(RCLASS_M_TBL(origin), move_refined_method, (void *)klass); return true; @@ -1444,13 +1956,7 @@ rb_prepend_module(VALUE klass, VALUE module) rb_vm_check_redefinition_by_prepend(klass); } if (RB_TYPE_P(klass, T_MODULE)) { - rb_subclass_entry_t *iclass = RCLASS_SUBCLASSES(klass); - // skip the placeholder subclass entry at the head of the list if it exists - if (iclass) { - RUBY_ASSERT(!iclass->klass); - iclass = iclass->next; - } - + rb_subclass_entry_t *iclass = RCLASS_SUBCLASSES_FIRST(klass); VALUE klass_origin = RCLASS_ORIGIN(klass); struct rb_id_table *klass_m_tbl = RCLASS_M_TBL(klass); struct rb_id_table *klass_origin_m_tbl = RCLASS_M_TBL(klass_origin); @@ -1462,11 +1968,11 @@ rb_prepend_module(VALUE klass, VALUE module) if (klass_had_no_origin && klass_origin_m_tbl == RCLASS_M_TBL(subclass)) { // backfill an origin iclass to handle refinements and future prepends rb_id_table_foreach(RCLASS_M_TBL(subclass), clear_module_cache_i, (void *)subclass); - RCLASS_M_TBL(subclass) = klass_m_tbl; + RCLASS_WRITE_M_TBL_EVEN_WHEN_PROMOTED(subclass, klass_m_tbl); VALUE origin = rb_include_class_new(klass_origin, RCLASS_SUPER(subclass)); - RCLASS_SET_SUPER(subclass, origin); + rb_class_set_super(subclass, origin); RCLASS_SET_INCLUDER(origin, RCLASS_INCLUDER(subclass)); - RCLASS_SET_ORIGIN(subclass, origin); + RCLASS_WRITE_ORIGIN(subclass, origin); RICLASS_SET_ORIGIN_SHARED_MTBL(origin); } include_modules_at(subclass, subclass, module, FALSE); @@ -1542,7 +2048,7 @@ rb_mod_include_p(VALUE mod, VALUE mod2) Check_Type(mod2, T_MODULE); for (p = RCLASS_SUPER(mod); p; p = RCLASS_SUPER(p)) { - if (BUILTIN_TYPE(p) == T_ICLASS && !FL_TEST(p, RICLASS_IS_ORIGIN)) { + if (BUILTIN_TYPE(p) == T_ICLASS && !RICLASS_IS_ORIGIN_P(p)) { if (METACLASS_OF(p) == mod2) return Qtrue; } } @@ -1602,7 +2108,7 @@ class_descendants_recursive(VALUE klass, VALUE v) { struct subclass_traverse_data *data = (struct subclass_traverse_data *) v; - if (BUILTIN_TYPE(klass) == T_CLASS && !FL_TEST(klass, FL_SINGLETON)) { + if (BUILTIN_TYPE(klass) == T_CLASS && !RCLASS_SINGLETON_P(klass)) { if (data->buffer && data->count < data->maxcount && !rb_objspace_garbage_object_p(klass)) { // assumes that this does not cause GC as long as the length does not exceed the capacity rb_ary_push(data->buffer, klass); @@ -1707,8 +2213,8 @@ rb_class_subclasses(VALUE klass) VALUE rb_class_attached_object(VALUE klass) { - if (!FL_TEST(klass, FL_SINGLETON)) { - rb_raise(rb_eTypeError, "`%"PRIsVALUE"' is not a singleton class", klass); + if (!RCLASS_SINGLETON_P(klass)) { + rb_raise(rb_eTypeError, "'%"PRIsVALUE"' is not a singleton class", klass); } return RCLASS_ATTACHED_OBJECT(klass); @@ -1810,7 +2316,7 @@ static bool particular_class_p(VALUE mod) { if (!mod) return false; - if (FL_TEST(mod, FL_SINGLETON)) return true; + if (RCLASS_SINGLETON_P(mod)) return true; if (BUILTIN_TYPE(mod) == T_ICLASS) return true; return false; } @@ -2087,19 +2593,19 @@ rb_obj_singleton_methods(int argc, const VALUE *argv, VALUE obj) int recur = TRUE; if (rb_check_arity(argc, 0, 1)) recur = RTEST(argv[0]); - if (RB_TYPE_P(obj, T_CLASS) && FL_TEST(obj, FL_SINGLETON)) { + if (RCLASS_SINGLETON_P(obj)) { rb_singleton_class(obj); } klass = CLASS_OF(obj); origin = RCLASS_ORIGIN(klass); me_arg.list = st_init_numtable(); me_arg.recur = recur; - if (klass && FL_TEST(klass, FL_SINGLETON)) { + if (klass && RCLASS_SINGLETON_P(klass)) { if ((mtbl = RCLASS_M_TBL(origin)) != 0) rb_id_table_foreach(mtbl, method_entry_i, &me_arg); klass = RCLASS_SUPER(klass); } if (recur) { - while (klass && (FL_TEST(klass, FL_SINGLETON) || RB_TYPE_P(klass, T_ICLASS))) { + while (klass && (RCLASS_SINGLETON_P(klass) || RB_TYPE_P(klass, T_ICLASS))) { if (klass != origin && (mtbl = RCLASS_M_TBL(klass)) != 0) rb_id_table_foreach(mtbl, method_entry_i, &me_arg); klass = RCLASS_SUPER(klass); } @@ -2203,13 +2709,13 @@ rb_special_singleton_class(VALUE obj) return special_singleton_class_of(obj); } -/*! - * \internal - * Returns the singleton class of \a obj. Creates it if necessary. +/** + * @internal + * Returns the singleton class of `obj`. Creates it if necessary. * - * \note DO NOT expose the returned singleton class to + * @note DO NOT expose the returned singleton class to * outside of class.c. - * Use \ref rb_singleton_class instead for + * Use @ref rb_singleton_class instead for * consistency of the metaclass hierarchy. */ static VALUE @@ -2233,13 +2739,16 @@ singleton_class_of(VALUE obj) return klass; case T_STRING: - if (FL_TEST_RAW(obj, RSTRING_FSTR)) { + if (CHILLED_STRING_P(obj)) { + CHILLED_STRING_MUTATED(obj); + } + else if (FL_TEST_RAW(obj, RSTRING_FSTR)) { rb_raise(rb_eTypeError, "can't define singleton"); } } klass = METACLASS_OF(obj); - if (!(FL_TEST(klass, FL_SINGLETON) && + if (!(RCLASS_SINGLETON_P(klass) && RCLASS_ATTACHED_OBJECT(klass) == obj)) { klass = rb_make_metaclass(obj, klass); } @@ -2253,21 +2762,22 @@ void rb_freeze_singleton_class(VALUE x) { /* should not propagate to meta-meta-class, and so on */ - if (!(RBASIC(x)->flags & FL_SINGLETON)) { + if (!RCLASS_SINGLETON_P(x)) { VALUE klass = RBASIC_CLASS(x); if (klass && // no class when hidden from ObjectSpace - FL_TEST(klass, (FL_SINGLETON|FL_FREEZE)) == FL_SINGLETON) { - OBJ_FREEZE_RAW(klass); + FL_TEST_RAW(klass, FL_SINGLETON) && + !OBJ_FROZEN_RAW(klass)) { + OBJ_FREEZE(klass); } } } -/*! - * Returns the singleton class of \a obj, or nil if obj is not a +/** + * Returns the singleton class of `obj`, or nil if obj is not a * singleton object. * - * \param obj an arbitrary object. - * \return the singleton class or nil. + * @param obj an arbitrary object. + * @return the singleton class or nil. */ VALUE rb_singleton_class_get(VALUE obj) @@ -2278,7 +2788,7 @@ rb_singleton_class_get(VALUE obj) return rb_special_singleton_class(obj); } klass = METACLASS_OF(obj); - if (!FL_TEST(klass, FL_SINGLETON)) return Qnil; + if (!RCLASS_SINGLETON_P(klass)) return Qnil; if (RCLASS_ATTACHED_OBJECT(klass) != obj) return Qnil; return klass; } diff --git a/common.mk b/common.mk index d55d1788aa8e01..5a54cecb636c4f 100644 --- a/common.mk +++ b/common.mk @@ -6,7 +6,7 @@ bin: $(PROGRAM) $(WPROGRAM) lib: $(LIBRUBY) dll: $(LIBRUBY_SO) -.SUFFIXES: .rbinc .rb .inc .h .c .y .i .$(ASMEXT) .$(DTRACE_EXT) +.SUFFIXES: .rbinc .rbbin .rb .inc .h .c .y .i .$(ASMEXT) .$(DTRACE_EXT) # V=0 quiet, V=1 verbose. other values don't work. V = 0 @@ -18,9 +18,10 @@ ECHO = @$(ECHO0) mflags = $(MFLAGS) gnumake_recursive = +sequential = $(gnumake:yes=-sequential) enable_shared = $(ENABLE_SHARED:no=) -UNICODE_VERSION = 15.0.0 +UNICODE_VERSION = 16.0.0 UNICODE_EMOJI_VERSION_0 = $(UNICODE_VERSION)/// UNICODE_EMOJI_VERSION_1 = $(UNICODE_EMOJI_VERSION_0:.0///=) UNICODE_EMOJI_VERSION = $(UNICODE_EMOJI_VERSION_1:///=) @@ -45,8 +46,8 @@ RUN_OPTS = --disable-gems # GITPULLOPTIONS = --no-tags -YARP_SRCDIR = $(srcdir)/yarp -INCFLAGS = -I. -I$(arch_hdrdir) -I$(hdrdir) -I$(srcdir) -I$(YARP_SRCDIR) -I$(UNICODE_HDR_DIR) +PRISM_SRCDIR = $(srcdir)/prism +INCFLAGS = -I. -I$(arch_hdrdir) -I$(ext_hdrdir) -I$(hdrdir) -I$(srcdir) -I$(PRISM_SRCDIR) -I$(UNICODE_HDR_DIR) $(incflags) GEM_HOME = GEM_PATH = @@ -64,64 +65,61 @@ LIBRUBY_EXTS = ./.libruby-with-ext.time REVISION_H = ./.revision.time PLATFORM_D = $(TIMESTAMPDIR)/.$(PLATFORM_DIR).time ENC_TRANS_D = $(TIMESTAMPDIR)/.enc-trans.time -RDOC = $(XRUBY) "$(srcdir)/libexec/rdoc" --root "$(srcdir)" --encoding=UTF-8 --all +RDOC = $(XRUBY) "$(tooldir)/rdoc-srcdir" RDOCOUT = $(EXTOUT)/rdoc HTMLOUT = $(EXTOUT)/html CAPIOUT = doc/capi INSTALL_DOC_OPTS = --rdoc-output="$(RDOCOUT)" --html-output="$(HTMLOUT)" -RDOC_GEN_OPTS = --page-dir "$(srcdir)/doc" --no-force-update \ - --title "Documentation for Ruby $(RUBY_API_VERSION)" \ - --main README.md +RDOC_GEN_OPTS = --no-force-update \ + $(empty) INITOBJS = dmyext.$(OBJEXT) dmyenc.$(OBJEXT) NORMALMAINOBJ = main.$(OBJEXT) MAINOBJ = $(NORMALMAINOBJ) DLDOBJS = $(INITOBJS) EXTSOLIBS = -MINIOBJS = $(ARCHMINIOBJS) miniinit.$(OBJEXT) dmyext.$(OBJEXT) +MINIOBJS = $(ARCHMINIOBJS) miniinit.$(OBJEXT) ENC_MK = enc.mk MAKE_ENC = -f $(ENC_MK) V="$(V)" UNICODE_HDR_DIR="$(UNICODE_HDR_DIR)" \ RUBY="$(BOOTSTRAPRUBY)" MINIRUBY="$(BOOTSTRAPRUBY)" $(mflags) -YARP_FILES = yarp/api_node.$(OBJEXT) \ - yarp/api_pack.$(OBJEXT) \ - yarp/diagnostic.$(OBJEXT) \ - yarp/enc/yp_big5.$(OBJEXT) \ - yarp/enc/yp_euc_jp.$(OBJEXT) \ - yarp/enc/yp_gbk.$(OBJEXT) \ - yarp/enc/yp_shift_jis.$(OBJEXT) \ - yarp/enc/yp_tables.$(OBJEXT) \ - yarp/enc/yp_unicode.$(OBJEXT) \ - yarp/enc/yp_windows_31j.$(OBJEXT) \ - yarp/extension.$(OBJEXT) \ - yarp/node.$(OBJEXT) \ - yarp/pack.$(OBJEXT) \ - yarp/prettyprint.$(OBJEXT) \ - yarp/regexp.$(OBJEXT) \ - yarp/serialize.$(OBJEXT) \ - yarp/token_type.$(OBJEXT) \ - yarp/unescape.$(OBJEXT) \ - yarp/util/yp_buffer.$(OBJEXT) \ - yarp/util/yp_char.$(OBJEXT) \ - yarp/util/yp_constant_pool.$(OBJEXT) \ - yarp/util/yp_list.$(OBJEXT) \ - yarp/util/yp_memchr.$(OBJEXT) \ - yarp/util/yp_newline_list.$(OBJEXT) \ - yarp/util/yp_state_stack.$(OBJEXT) \ - yarp/util/yp_string.$(OBJEXT) \ - yarp/util/yp_string_list.$(OBJEXT) \ - yarp/util/yp_strncasecmp.$(OBJEXT) \ - yarp/util/yp_strpbrk.$(OBJEXT) \ - yarp/yarp.$(OBJEXT) \ - yarp/yarp_init.$(OBJEXT) - -COMMONOBJS = array.$(OBJEXT) \ +PRISM_BUILD_DIR = prism + +PRISM_FILES = prism/api_node.$(OBJEXT) \ + prism/api_pack.$(OBJEXT) \ + prism/diagnostic.$(OBJEXT) \ + prism/encoding.$(OBJEXT) \ + prism/extension.$(OBJEXT) \ + prism/node.$(OBJEXT) \ + prism/options.$(OBJEXT) \ + prism/pack.$(OBJEXT) \ + prism/prettyprint.$(OBJEXT) \ + prism/regexp.$(OBJEXT) \ + prism/serialize.$(OBJEXT) \ + prism/static_literals.$(OBJEXT) \ + prism/token_type.$(OBJEXT) \ + prism/util/pm_buffer.$(OBJEXT) \ + prism/util/pm_char.$(OBJEXT) \ + prism/util/pm_constant_pool.$(OBJEXT) \ + prism/util/pm_integer.$(OBJEXT) \ + prism/util/pm_list.$(OBJEXT) \ + prism/util/pm_memchr.$(OBJEXT) \ + prism/util/pm_newline_list.$(OBJEXT) \ + prism/util/pm_string.$(OBJEXT) \ + prism/util/pm_strncasecmp.$(OBJEXT) \ + prism/util/pm_strpbrk.$(OBJEXT) \ + prism/prism.$(OBJEXT) \ + prism_init.$(OBJEXT) + +COMMONOBJS = \ + array.$(OBJEXT) \ ast.$(OBJEXT) \ bignum.$(OBJEXT) \ class.$(OBJEXT) \ compar.$(OBJEXT) \ compile.$(OBJEXT) \ complex.$(OBJEXT) \ + concurrent_set.$(OBJEXT) \ cont.$(OBJEXT) \ debug.$(OBJEXT) \ debug_counter.$(OBJEXT) \ @@ -135,6 +133,7 @@ COMMONOBJS = array.$(OBJEXT) \ file.$(OBJEXT) \ gc.$(OBJEXT) \ hash.$(OBJEXT) \ + imemo.$(OBJEXT) \ inits.$(OBJEXT) \ io.$(OBJEXT) \ io_buffer.$(OBJEXT) \ @@ -143,8 +142,7 @@ COMMONOBJS = array.$(OBJEXT) \ marshal.$(OBJEXT) \ math.$(OBJEXT) \ memory_view.$(OBJEXT) \ - rjit.$(OBJEXT) \ - rjit_c.$(OBJEXT) \ + namespace.$(OBJEXT) \ node.$(OBJEXT) \ node_dump.$(OBJEXT) \ numeric.$(OBJEXT) \ @@ -168,6 +166,7 @@ COMMONOBJS = array.$(OBJEXT) \ ruby.$(OBJEXT) \ ruby_parser.$(OBJEXT) \ scheduler.$(OBJEXT) \ + set.$(OBJEXT) \ shape.$(OBJEXT) \ signal.$(OBJEXT) \ sprintf.$(OBJEXT) \ @@ -188,59 +187,99 @@ COMMONOBJS = array.$(OBJEXT) \ vm_sync.$(OBJEXT) \ vm_trace.$(OBJEXT) \ weakmap.$(OBJEXT) \ - $(YARP_FILES) \ + $(PRISM_FILES) \ $(YJIT_OBJ) \ - $(YJIT_LIBOBJ) \ + $(ZJIT_OBJ) \ + $(JIT_OBJ) \ + $(RUST_LIBOBJ) \ $(COROUTINE_OBJ) \ $(DTRACE_OBJ) \ $(BUILTIN_ENCOBJS) \ $(BUILTIN_TRANSOBJS) \ $(MISSING) -$(YARP_FILES): $(YARP_BUILD_DIR)/.time $(YARP_BUILD_DIR)/enc/.time $(YARP_BUILD_DIR)/util/.time +$(PRISM_FILES): $(PRISM_BUILD_DIR)/.time $(PRISM_BUILD_DIR)/util/.time -$(YARP_BUILD_DIR)/.time $(YARP_BUILD_DIR)/enc/.time $(YARP_BUILD_DIR)/util/.time: +$(PRISM_BUILD_DIR)/.time $(PRISM_BUILD_DIR)/util/.time: $(Q) $(MAKEDIRS) $(@D) @$(NULLCMD) > $@ -main: $(srcdir)/lib/yarp/mutation_visitor.rb -srcs: $(srcdir)/lib/yarp/mutation_visitor.rb -$(srcdir)/lib/yarp/mutation_visitor.rb: $(YARP_SRCDIR)/config.yml $(YARP_SRCDIR)/templates/template.rb $(YARP_SRCDIR)/templates/lib/yarp/mutation_visitor.rb.erb - $(Q) $(BASERUBY) $(YARP_SRCDIR)/templates/template.rb lib/yarp/mutation_visitor.rb $(srcdir)/lib/yarp/mutation_visitor.rb - -main: $(srcdir)/lib/yarp/node.rb -srcs: $(srcdir)/lib/yarp/node.rb -$(srcdir)/lib/yarp/node.rb: $(YARP_SRCDIR)/config.yml $(YARP_SRCDIR)/templates/template.rb $(YARP_SRCDIR)/templates/lib/yarp/node.rb.erb - $(Q) $(BASERUBY) $(YARP_SRCDIR)/templates/template.rb lib/yarp/node.rb $(srcdir)/lib/yarp/node.rb - -main: $(srcdir)/lib/yarp/serialize.rb -srcs: $(srcdir)/lib/yarp/serialize.rb -$(srcdir)/lib/yarp/serialize.rb: $(YARP_SRCDIR)/config.yml $(YARP_SRCDIR)/templates/template.rb $(YARP_SRCDIR)/templates/lib/yarp/serialize.rb.erb - $(Q) $(BASERUBY) $(YARP_SRCDIR)/templates/template.rb lib/yarp/serialize.rb $(srcdir)/lib/yarp/serialize.rb - -srcs: yarp/api_node.c -yarp/api_node.c: $(YARP_SRCDIR)/config.yml $(YARP_SRCDIR)/templates/template.rb $(YARP_SRCDIR)/templates/ext/yarp/api_node.c.erb - $(Q) $(BASERUBY) $(YARP_SRCDIR)/templates/template.rb ext/yarp/api_node.c $@ - -srcs: yarp/ast.h -yarp/ast.h: $(YARP_SRCDIR)/config.yml $(YARP_SRCDIR)/templates/template.rb $(YARP_SRCDIR)/templates/include/yarp/ast.h.erb - $(Q) $(BASERUBY) $(YARP_SRCDIR)/templates/template.rb include/yarp/ast.h $@ - -srcs: yarp/node.c -yarp/node.c: $(YARP_SRCDIR)/config.yml $(YARP_SRCDIR)/templates/template.rb $(YARP_SRCDIR)/templates/src/node.c.erb - $(Q) $(BASERUBY) $(YARP_SRCDIR)/templates/template.rb src/node.c $@ - -srcs: yarp/prettyprint.c -yarp/prettyprint.c: $(YARP_SRCDIR)/config.yml $(YARP_SRCDIR)/templates/template.rb $(YARP_SRCDIR)/templates/src/prettyprint.c.erb - $(Q) $(BASERUBY) $(YARP_SRCDIR)/templates/template.rb src/prettyprint.c $@ - -srcs: yarp/serialize.c -yarp/serialize.c: $(YARP_SRCDIR)/config.yml $(YARP_SRCDIR)/templates/template.rb $(YARP_SRCDIR)/templates/src/serialize.c.erb - $(Q) $(BASERUBY) $(YARP_SRCDIR)/templates/template.rb src/serialize.c $@ - -srcs: yarp/token_type.c -yarp/token_type.c: $(YARP_SRCDIR)/config.yml $(YARP_SRCDIR)/templates/template.rb $(YARP_SRCDIR)/templates/src/token_type.c.erb - $(Q) $(BASERUBY) $(YARP_SRCDIR)/templates/template.rb src/token_type.c $@ +main: $(srcdir)/lib/prism/compiler.rb +srcs: $(srcdir)/lib/prism/compiler.rb +$(srcdir)/lib/prism/compiler.rb: $(PRISM_SRCDIR)/config.yml $(PRISM_SRCDIR)/templates/template.rb $(PRISM_SRCDIR)/templates/lib/prism/compiler.rb.erb + $(Q) $(BASERUBY) $(PRISM_SRCDIR)/templates/template.rb lib/prism/compiler.rb $(srcdir)/lib/prism/compiler.rb + +main: $(srcdir)/lib/prism/dispatcher.rb +srcs: $(srcdir)/lib/prism/dispatcher.rb +$(srcdir)/lib/prism/dispatcher.rb: $(PRISM_SRCDIR)/config.yml $(PRISM_SRCDIR)/templates/template.rb $(PRISM_SRCDIR)/templates/lib/prism/dispatcher.rb.erb + $(Q) $(BASERUBY) $(PRISM_SRCDIR)/templates/template.rb lib/prism/dispatcher.rb $(srcdir)/lib/prism/dispatcher.rb + +main: $(srcdir)/lib/prism/dsl.rb +srcs: $(srcdir)/lib/prism/dsl.rb +$(srcdir)/lib/prism/dsl.rb: $(PRISM_SRCDIR)/config.yml $(PRISM_SRCDIR)/templates/template.rb $(PRISM_SRCDIR)/templates/lib/prism/dsl.rb.erb + $(Q) $(BASERUBY) $(PRISM_SRCDIR)/templates/template.rb lib/prism/dsl.rb $(srcdir)/lib/prism/dsl.rb + +main: $(srcdir)/lib/prism/inspect_visitor.rb +srcs: $(srcdir)/lib/prism/inspect_visitor.rb +$(srcdir)/lib/prism/inspect_visitor.rb: $(PRISM_SRCDIR)/config.yml $(PRISM_SRCDIR)/templates/template.rb $(PRISM_SRCDIR)/templates/lib/prism/inspect_visitor.rb.erb + $(Q) $(BASERUBY) $(PRISM_SRCDIR)/templates/template.rb lib/prism/inspect_visitor.rb $(srcdir)/lib/prism/inspect_visitor.rb + +main: $(srcdir)/lib/prism/mutation_compiler.rb +srcs: $(srcdir)/lib/prism/mutation_compiler.rb +$(srcdir)/lib/prism/mutation_compiler.rb: $(PRISM_SRCDIR)/config.yml $(PRISM_SRCDIR)/templates/template.rb $(PRISM_SRCDIR)/templates/lib/prism/mutation_compiler.rb.erb + $(Q) $(BASERUBY) $(PRISM_SRCDIR)/templates/template.rb lib/prism/mutation_compiler.rb $(srcdir)/lib/prism/mutation_compiler.rb + +main: $(srcdir)/lib/prism/node.rb +srcs: $(srcdir)/lib/prism/node.rb +$(srcdir)/lib/prism/node.rb: $(PRISM_SRCDIR)/config.yml $(PRISM_SRCDIR)/templates/template.rb $(PRISM_SRCDIR)/templates/lib/prism/node.rb.erb + $(Q) $(BASERUBY) $(PRISM_SRCDIR)/templates/template.rb lib/prism/node.rb $(srcdir)/lib/prism/node.rb + +main: $(srcdir)/lib/prism/reflection.rb +srcs: $(srcdir)/lib/prism/reflection.rb +$(srcdir)/lib/prism/reflection.rb: $(PRISM_SRCDIR)/config.yml $(PRISM_SRCDIR)/templates/template.rb $(PRISM_SRCDIR)/templates/lib/prism/reflection.rb.erb + $(Q) $(BASERUBY) $(PRISM_SRCDIR)/templates/template.rb lib/prism/reflection.rb $(srcdir)/lib/prism/reflection.rb + +main: $(srcdir)/lib/prism/serialize.rb +srcs: $(srcdir)/lib/prism/serialize.rb +$(srcdir)/lib/prism/serialize.rb: $(PRISM_SRCDIR)/config.yml $(PRISM_SRCDIR)/templates/template.rb $(PRISM_SRCDIR)/templates/lib/prism/serialize.rb.erb + $(Q) $(BASERUBY) $(PRISM_SRCDIR)/templates/template.rb lib/prism/serialize.rb $(srcdir)/lib/prism/serialize.rb + +main: $(srcdir)/lib/prism/visitor.rb +srcs: $(srcdir)/lib/prism/visitor.rb +$(srcdir)/lib/prism/visitor.rb: $(PRISM_SRCDIR)/config.yml $(PRISM_SRCDIR)/templates/template.rb $(PRISM_SRCDIR)/templates/lib/prism/visitor.rb.erb + $(Q) $(BASERUBY) $(PRISM_SRCDIR)/templates/template.rb lib/prism/visitor.rb $(srcdir)/lib/prism/visitor.rb + +srcs: prism/api_node.c +prism/api_node.c: $(PRISM_SRCDIR)/config.yml $(PRISM_SRCDIR)/templates/template.rb $(PRISM_SRCDIR)/templates/ext/prism/api_node.c.erb + $(Q) $(BASERUBY) $(PRISM_SRCDIR)/templates/template.rb ext/prism/api_node.c $@ + +srcs: prism/ast.h +prism/ast.h: $(PRISM_SRCDIR)/config.yml $(PRISM_SRCDIR)/templates/template.rb $(PRISM_SRCDIR)/templates/include/prism/ast.h.erb + $(Q) $(BASERUBY) $(PRISM_SRCDIR)/templates/template.rb include/prism/ast.h $@ + +srcs: prism/diagnostic.c +prism/diagnostic.c: $(PRISM_SRCDIR)/config.yml $(PRISM_SRCDIR)/templates/template.rb $(PRISM_SRCDIR)/templates/src/diagnostic.c.erb + $(Q) $(BASERUBY) $(PRISM_SRCDIR)/templates/template.rb src/diagnostic.c $@ + +srcs: prism/diagnostic.h +prism/diagnostic.h: $(PRISM_SRCDIR)/config.yml $(PRISM_SRCDIR)/templates/template.rb $(PRISM_SRCDIR)/templates/include/prism/diagnostic.h.erb + $(Q) $(BASERUBY) $(PRISM_SRCDIR)/templates/template.rb include/prism/diagnostic.h $@ + +srcs: prism/node.c +prism/node.c: $(PRISM_SRCDIR)/config.yml $(PRISM_SRCDIR)/templates/template.rb $(PRISM_SRCDIR)/templates/src/node.c.erb + $(Q) $(BASERUBY) $(PRISM_SRCDIR)/templates/template.rb src/node.c $@ + +srcs: prism/prettyprint.c +prism/prettyprint.c: $(PRISM_SRCDIR)/config.yml $(PRISM_SRCDIR)/templates/template.rb $(PRISM_SRCDIR)/templates/src/prettyprint.c.erb + $(Q) $(BASERUBY) $(PRISM_SRCDIR)/templates/template.rb src/prettyprint.c $@ + +srcs: prism/serialize.c +prism/serialize.c: $(PRISM_SRCDIR)/config.yml $(PRISM_SRCDIR)/templates/template.rb $(PRISM_SRCDIR)/templates/src/serialize.c.erb + $(Q) $(BASERUBY) $(PRISM_SRCDIR)/templates/template.rb src/serialize.c $@ + +srcs: prism/token_type.c +prism/token_type.c: $(PRISM_SRCDIR)/config.yml $(PRISM_SRCDIR)/templates/template.rb $(PRISM_SRCDIR)/templates/src/token_type.c.erb + $(Q) $(BASERUBY) $(PRISM_SRCDIR)/templates/template.rb src/token_type.c $@ EXPORTOBJS = $(DLNOBJ) \ localeinit.$(OBJEXT) \ @@ -248,7 +287,7 @@ EXPORTOBJS = $(DLNOBJ) \ $(COMMONOBJS) OBJS = $(EXPORTOBJS) builtin.$(OBJEXT) -ALLOBJS = $(NORMALMAINOBJ) $(MINIOBJS) $(COMMONOBJS) $(INITOBJS) +ALLOBJS = $(OBJS) $(MINIOBJS) $(INITOBJS) $(MAINOBJ) GOLFOBJS = goruby.$(OBJEXT) @@ -256,7 +295,7 @@ DEFAULT_PRELUDES = $(GEM_PRELUDE) PRELUDE_SCRIPTS = $(DEFAULT_PRELUDES) GEM_PRELUDE = PRELUDES = {$(srcdir)}miniprelude.c -GOLFPRELUDES = {$(srcdir)}golf_prelude.c +GOLFPRELUDES = golf_prelude.rbbin SCRIPT_ARGS = --dest-dir="$(DESTDIR)" \ --extout="$(EXTOUT)" \ @@ -308,23 +347,23 @@ YJIT_RUSTC_ARGS = --crate-name=yjit \ -C opt-level=3 \ -C overflow-checks=on \ '--out-dir=$(CARGO_TARGET_DIR)/release/' \ - $(top_srcdir)/yjit/src/lib.rs + '$(top_srcdir)/yjit/src/lib.rs' + +ZJIT_RUSTC_ARGS = --crate-name=zjit \ + --crate-type=staticlib \ + --edition=2024 \ + -g \ + -C lto=thin \ + -C opt-level=3 \ + -C overflow-checks=on \ + '--out-dir=$(CARGO_TARGET_DIR)/release/' \ + '$(top_srcdir)/zjit/src/lib.rs' -all: $(SHOWFLAGS) main docs +all: $(SHOWFLAGS) main main: $(SHOWFLAGS) exts $(ENCSTATIC:static=lib)encs @$(NULLCMD) -main: $(srcdir)/lib/ruby_vm/rjit/instruction.rb -srcs: $(srcdir)/lib/ruby_vm/rjit/instruction.rb -$(srcdir)/lib/ruby_vm/rjit/instruction.rb: $(tooldir)/insns2vm.rb $(tooldir)/ruby_vm/views/lib/ruby_vm/rjit/instruction.rb.erb $(srcdir)/insns.def - $(ECHO) generating $@ - $(Q) $(BASERUBY) -Ku $(tooldir)/insns2vm.rb --basedir="$(srcdir)" $(INSNS2VMOPT) $@ - -.PHONY: rjit-bindgen -rjit-bindgen: - $(Q) $(BASERUBY) -rrubygems -C $(srcdir)/tool/rjit bindgen.rb $(CURDIR) - .PHONY: showflags exts enc trans: $(SHOWFLAGS) showflags: @@ -344,6 +383,7 @@ showflags: " MFLAGS = $(MFLAGS)" \ " RUSTC = $(RUSTC)" \ " YJIT_RUSTC_ARGS = $(YJIT_RUSTC_ARGS)" \ + " ZJIT_RUSTC_ARGS = $(ZJIT_RUSTC_ARGS)" \ $(MESSAGE_END) -@$(CC_VERSION) @@ -380,7 +420,7 @@ configure-ext: $(EXTS_MK) build-ext: $(EXTS_MK) $(Q)$(MAKE) -f $(EXTS_MK) $(mflags) libdir="$(libdir)" LIBRUBY_EXTS=$(LIBRUBY_EXTS) \ EXTENCS="$(ENCOBJS)" BASERUBY="$(BASERUBY)" MINIRUBY="$(MINIRUBY)" \ - UPDATE_LIBRARIES=no $(EXTSTATIC) + $(EXTSTATIC) $(Q)$(MAKE) $(EXTS_NOTE) exts-note: $(EXTS_MK) @@ -396,7 +436,7 @@ programs: $(PROGRAM) $(WPROGRAM) $(arch)-fake.rb $(PREP): $(MKFILES) -miniruby$(EXEEXT): config.status $(ALLOBJS) $(ARCHFILE) +miniruby$(EXEEXT): config.status $(NORMALMAINOBJ) $(MINIOBJS) $(COMMONOBJS) $(ARCHFILE) objs: $(ALLOBJS) @@ -423,8 +463,8 @@ Doxyfile: $(srcdir)/template/Doxyfile.tmpl $(PREP) $(tooldir)/generic_erb.rb $(R $(Q) $(MINIRUBY) $(tooldir)/generic_erb.rb -o $@ $(srcdir)/template/Doxyfile.tmpl \ --srcdir="$(srcdir)" --miniruby="$(MINIRUBY)" -program: $(SHOWFLAGS) $(PROGRAM) -wprogram: $(SHOWFLAGS) $(WPROGRAM) +program: $(SHOWFLAGS) $(DOT_WAIT) $(PROGRAM) +wprogram: $(SHOWFLAGS) $(DOT_WAIT) $(WPROGRAM) mini: PHONY miniruby$(EXEEXT) $(PROGRAM) $(WPROGRAM): $(LIBRUBY) $(MAINOBJ) $(OBJS) $(EXTOBJS) $(SETUP) $(PREP) @@ -444,8 +484,6 @@ ruby.imp: $(COMMONOBJS) $(Q){ \ $(NM) -Pgp $(COMMONOBJS) | \ awk 'BEGIN{print "#!"}; $$2~/^[A-TV-Z]$$/&&$$1!~/^$(SYMBOL_PREFIX)(Init_|InitVM_|ruby_static_id_|.*_threadptr_|rb_ec_)|^\./{print $$1}'; \ - ($(CHDIR) $(srcdir) && \ - exec sed -n '/^RJIT_FUNC_EXPORTED/!d;N;s/.*\n\(rb_[a-zA-Z_0-9]*\).*/$(SYMBOL_PREFIX)\1/p' cont.c gc.c thread*c vm*.c) \ } | \ sort -u -o $@ @@ -454,17 +492,19 @@ docs: srcs-doc $(DOCTARGETS) pkgconfig-data: $(ruby_pc) $(ruby_pc): $(srcdir)/template/ruby.pc.in config.status -install-all: docs pre-install-all do-install-all post-install-all +INSTALL_ALL = all + +install-all: pre-install-all do-install-all post-install-all pre-install-all:: all pre-install-local pre-install-ext pre-install-gem pre-install-doc -do-install-all: pre-install-all - $(INSTRUBY) --make="$(MAKE)" $(INSTRUBY_ARGS) --install=all $(INSTALL_DOC_OPTS) +do-install-all: pre-install-all $(DOT_WAIT) docs + $(INSTRUBY) --make="$(MAKE)" $(INSTRUBY_ARGS) --install=$(INSTALL_ALL) $(INSTALL_DOC_OPTS) post-install-all:: post-install-local post-install-ext post-install-gem post-install-doc @$(NULLCMD) install-nodoc: pre-install-nodoc do-install-nodoc post-install-nodoc pre-install-nodoc:: pre-install-local pre-install-ext pre-install-gem do-install-nodoc: main pre-install-nodoc - $(INSTRUBY) --make="$(MAKE)" $(INSTRUBY_ARGS) --install=all --exclude=doc + $(INSTRUBY) --make="$(MAKE)" $(INSTRUBY_ARGS) --install=$(INSTALL_ALL) --exclude=doc post-install-nodoc:: post-install-local post-install-ext post-install-gem install-local: pre-install-local do-install-local post-install-local @@ -539,7 +579,7 @@ what-where-all: no-install-all no-install-all: pre-no-install-all dont-install-all post-no-install-all pre-no-install-all:: pre-no-install-local pre-no-install-ext pre-no-install-doc dont-install-all: $(PROGRAM) - $(INSTRUBY) -n --make="$(MAKE)" $(INSTRUBY_ARGS) --install=all $(INSTALL_DOC_OPTS) + $(INSTRUBY) -n --make="$(MAKE)" $(INSTRUBY_ARGS) --install=$(INSTALL_ALL) $(INSTALL_DOC_OPTS) post-no-install-all:: post-no-install-local post-no-install-ext post-no-install-doc @$(NULLCMD) @@ -644,18 +684,26 @@ do-install-dbg: $(PROGRAM) pre-install-dbg post-install-dbg:: @$(NULLCMD) +srcs-doc: prepare-gems + rdoc: PHONY main srcs-doc @echo Generating RDoc documentation - $(Q) $(RDOC) --ri --op "$(RDOCOUT)" $(RDOC_GEN_OPTS) $(RDOCFLAGS) "$(srcdir)" + $(Q) $(RDOC) --ri --op "$(RDOCOUT)" $(RDOC_GEN_OPTS) $(RDOCFLAGS) . html: PHONY main srcs-doc @echo Generating RDoc HTML files - $(Q) $(RDOC) --op "$(HTMLOUT)" $(RDOC_GEN_OPTS) $(RDOCFLAGS) "$(srcdir)" + $(Q) $(RDOC) --op "$(HTMLOUT)" $(RDOC_GEN_OPTS) $(RDOCFLAGS) . rdoc-coverage: PHONY main srcs-doc @echo Generating RDoc coverage report $(Q) $(RDOC) --quiet -C $(RDOCFLAGS) "$(srcdir)" +undocumented: PHONY main srcs-doc + $(Q) $(RDOC) --quiet -C $(RDOCFLAGS) "$(srcdir)" | \ + sed -n \ + -e '/^ *# in file /{' -e 's///;N;s/\n/: /p' -e '}' \ + -e 's/^ *\(.*[^ ]\) *# in file \(.*\)/\2: \1/p' | sort + RDOCBENCHOUT=/tmp/rdocbench GCBENCH_ITEM=null @@ -683,22 +731,27 @@ install-prereq: $(CLEAR_INSTALLED_LIST) yes-fake sudo-precheck PHONY clear-installed-list: PHONY @> $(INSTALLED_LIST) set MAKE="$(MAKE)" -clean: clean-ext clean-enc clean-golf clean-docs clean-extout clean-local clean-platform clean-spec +clean: clean-ext clean-enc clean-golf clean-docs clean-extout clean-modular-gc clean-local clean-platform clean-spec clean-local:: clean-runnable - $(Q)$(RM) $(OBJS) $(MINIOBJS) $(INITOBJS) $(MAINOBJ) $(LIBRUBY_A) $(LIBRUBY_SO) $(LIBRUBY) $(LIBRUBY_ALIASES) + $(Q)$(RM) $(ALLOBJS) $(LIBRUBY_A) $(LIBRUBY_SO) $(LIBRUBY) $(LIBRUBY_ALIASES) $(Q)$(RM) $(PROGRAM) $(WPROGRAM) miniruby$(EXEEXT) dmyext.$(OBJEXT) dmyenc.$(OBJEXT) $(ARCHFILE) .*.time $(Q)$(RM) y.tab.c y.output encdb.h transdb.h config.log rbconfig.rb $(ruby_pc) $(COROUTINE_H:/Context.h=/.time) $(Q)$(RM) probes.h probes.$(OBJEXT) probes.stamp ruby-glommed.$(OBJEXT) ruby.imp ChangeLog $(STATIC_RUBY)$(EXEEXT) $(Q)$(RM) GNUmakefile.old Makefile.old $(arch)-fake.rb bisect.sh $(ENC_TRANS_D) builtin_binary.inc - -$(Q)$(RMALL) yjit/target - -$(Q) $(RMDIR) enc/jis enc/trans enc $(COROUTINE_H:/Context.h=) coroutine yjit 2> $(NULL) || $(NULLCMD) + $(Q)$(RM) $(PRISM_BUILD_DIR)/.time $(PRISM_BUILD_DIR)/*/.time yjit_exit_locations.dump + -$(Q)$(RMALL) target + -$(Q) $(RMDIR) enc/jis enc/trans enc $(COROUTINE_H:/Context.h=) coroutine target \ + $(PRISM_BUILD_DIR)/*/ $(PRISM_BUILD_DIR) tmp \ + 2> $(NULL) || $(NULLCMD) bin/clean-runnable:: PHONY $(Q)$(CHDIR) bin 2>$(NULL) && $(RM) $(PROGRAM) $(WPROGRAM) $(GORUBY)$(EXEEXT) bin/*.$(DLEXT) 2>$(NULL) || $(NULLCMD) lib/clean-runnable:: PHONY - $(Q)$(CHDIR) lib 2>$(NULL) && $(RM) $(LIBRUBY_A) $(LIBRUBY) $(LIBRUBY_ALIASES) $(RUBY_BASE_NAME)/$(RUBY_PROGRAM_VERSION) $(RUBY_BASE_NAME)/vendor_ruby 2>$(NULL) || $(NULLCMD) + $(Q)$(CHDIR) lib 2>$(NULL) && $(RM) $(LIBRUBY_A) $(LIBRUBY) $(LIBRUBY_ALIASES) $(RUBY_BASE_NAME)/$(ruby_version) $(RUBY_BASE_NAME)/vendor_ruby 2>$(NULL) || $(NULLCMD) clean-runnable:: bin/clean-runnable lib/clean-runnable PHONY $(Q)$(RMDIR) lib/$(RUBY_BASE_NAME) lib bin 2>$(NULL) || $(NULLCMD) + -$(Q)$(RM) $(EXTOUT)/$(arch)/rbconfig.rb $(EXTOUT)/common/$(arch) + -$(Q)$(RMALL) exe/ clean-ext:: PHONY clean-golf: PHONY $(Q)$(RM) $(GORUBY)$(EXEEXT) $(GOLFOBJS) @@ -712,9 +765,9 @@ clean-docs: clean-rdoc clean-html clean-capi clean-spec: PHONY clean-rubyspec: clean-spec -distclean: distclean-ext distclean-enc distclean-golf distclean-docs distclean-extout distclean-local distclean-platform distclean-spec +distclean: distclean-ext distclean-enc distclean-golf distclean-docs distclean-extout distclean-modular-gc distclean-local distclean-platform distclean-spec distclean-local:: clean-local - $(Q)$(RM) $(MKFILES) yasmdata.rb *.inc $(PRELUDES) *.rbinc + $(Q)$(RM) $(MKFILES) *.inc $(PRELUDES) *.rbinc *.rbbin $(Q)$(RM) config.cache config.status config.status.lineno $(Q)$(RM) *~ *.bak *.stackdump core *.core gmon.out $(PREP) -$(Q)$(RMALL) $(srcdir)/autom4te.cache @@ -810,6 +863,12 @@ clean-platform distclean-platform realclean-platform: -$(Q) $(RMDIR) $(PLATFORM_DIR) 2> $(NULL) || $(NULLCMD) RUBYSPEC_CAPIEXT = spec/ruby/optional/capi/ext +RUBYSPEC_CAPIEXT_SRCDIR = $(srcdir)/$(RUBYSPEC_CAPIEXT) +RUBYSPEC_CAPIEXT_DEPS = $(RUBYSPEC_CAPIEXT_SRCDIR)/rubyspec.h $(RUBY_H_INCLUDES) $(LIBRUBY) + +rubyspec-capiext: build-ext $(DOT_WAIT) +# make-dependent rules should be included after this and built after build-ext. + clean-spec: PHONY -$(Q) $(RM) $(RUBYSPEC_CAPIEXT)/*.$(OBJEXT) $(RUBYSPEC_CAPIEXT)/*.$(DLEXT) -$(Q) $(RMDIRS) $(RUBYSPEC_CAPIEXT) 2> $(NULL) || $(NULLCMD) @@ -839,7 +898,8 @@ $(arch:noarch=ignore)-fake.rb: $(srcdir)/template/fake.rb.in $(tooldir)/generic_ $(ECHO) generating $@ $(Q) $(CPP) -DRUBY_EXPORT $(INCFLAGS) $(CPPFLAGS) "$(srcdir)/version.c" | \ $(BOOTSTRAPRUBY) "$(tooldir)/generic_erb.rb" -o $@ "$(srcdir)/template/fake.rb.in" \ - i=- srcdir="$(srcdir)" BASERUBY="$(BASERUBY)" + i=- srcdir="$(srcdir)" BASERUBY="$(BASERUBY)" \ + LIBPATHENV="$(LIBPATHENV)" PRELOADENV="$(PRELOADENV)" LIBRUBY_SO="$(LIBRUBY_SO)" noarch-fake.rb: # prerequisite of yes-fake $(Q) exit > $@ @@ -904,18 +964,28 @@ test-sample: test-basic # backward compatibility for mswin-build test-short: btest-ruby $(DOT_WAIT) test-knownbug $(DOT_WAIT) test-basic test: test-short -yes-test-all-precheck: programs encs exts PHONY $(DOT_WAIT) +# Separate to skip updating encs and exts by `make -o test-precheck` +# for GNU make. +test-precheck: $(ENCSTATIC:static=lib)encs exts PHONY $(DOT_WAIT) +yes-test-all-precheck: programs $(DOT_WAIT) test-precheck + +PRECHECK_TEST_ALL = yes-test-all-precheck # $ make test-all TESTOPTS="--help" displays more detail # for example, make test-all TESTOPTS="-j2 -v -n test-name -- test-file-name" test-all: $(TEST_RUNNABLE)-test-all -yes-test-all: yes-test-all-precheck +yes-test-all: $(PRECHECK_TEST_ALL) $(ACTIONS_GROUP) - $(gnumake_recursive)$(Q)$(exec) $(RUNRUBY) "$(TESTSDIR)/runner.rb" --ruby="$(RUNRUBY)" $(TEST_EXCLUDES) $(TESTOPTS) $(TESTS) + $(gnumake_recursive)$(Q)$(exec) $(RUNRUBY) -r$(tooldir)/lib/_tmpdir \ + "$(TESTSDIR)/runner.rb" --ruby="$(RUNRUBY)" \ + $(TEST_EXCLUDES) $(TESTOPTS) $(TESTS) $(ACTIONS_ENDGROUP) TESTS_BUILD = mkmf no-test-all: PHONY - $(gnumake_recursive)$(MINIRUBY) -I"$(srcdir)/lib" "$(TESTSDIR)/runner.rb" $(TESTOPTS) $(TESTS_BUILD) + $(ACTIONS_GROUP) + $(gnumake_recursive)$(MINIRUBY) -I"$(srcdir)/lib" -r$(tooldir)/lib/_tmpdir \ + "$(TESTSDIR)/runner.rb" $(TESTOPTS) $(TESTS_BUILD) + $(ACTIONS_ENDGROUP) test-almost: test-all yes-test-almost: yes-test-all @@ -957,7 +1027,7 @@ test-spec: $(TEST_RUNNABLE)-test-spec yes-test-spec: yes-test-spec-precheck $(ACTIONS_GROUP) $(gnumake_recursive)$(Q) \ - $(RUNRUBY) -r./$(arch)-fake -r$(tooldir)/rubyspec_temp \ + $(RUNRUBY) -r./$(arch)-fake -r$(tooldir)/lib/_tmpdir \ $(srcdir)/spec/mspec/bin/mspec run -B $(srcdir)/spec/default.mspec $(MSPECOPT) $(SPECOPTS) $(ACTIONS_ENDGROUP) no-test-spec: @@ -965,10 +1035,18 @@ no-test-spec: check: $(DOT_WAIT) test-spec RUNNABLE = $(LIBRUBY_RELATIVE:no=un)-runnable -runnable: $(RUNNABLE) prog $(tooldir)/mkrunnable.rb PHONY +runnable: $(RUNNABLE) +runnable-golf: golf +runnable $(enable_shared:yes=runnable-golf): prog $(tooldir)/mkrunnable.rb PHONY $(Q) $(MINIRUBY) $(tooldir)/mkrunnable.rb -v $(EXTOUT) yes-runnable: PHONY +hello: $(TEST_RUNNABLE)-hello +yes-hello: runnable-golf + ./$(enable_shared:yes=bin/)$(GORUBY) -veh +no-hello: runnable-golf + $(ECHO) Run ./$(enable_shared:yes=bin/)$(GORUBY) -veh + encs: enc trans libencs: libenc libtrans encs enc trans libencs libenc libtrans: $(SHOWFLAGS) $(ENC_MK) $(LIBRUBY) $(PREP) PHONY @@ -1008,12 +1086,13 @@ PHONY: {$(srcdir)}.y.c: $(ECHO) generating $@ $(Q)$(BASERUBY) $(tooldir)/id2token.rb $(SRC_FILE) | \ - $(YACC) -d $(YFLAGS) -o$@ -h$*.h - parse.y + $(LRAMA) $(YFLAGS) -o$@ -H$*.h - parse.y $(PLATFORM_D): $(Q) $(MAKEDIRS) $(PLATFORM_DIR) $(@D) @$(NULLCMD) > $@ +exe/$(PROGRAM): $(TIMESTAMPDIR)/$(arch)/.time exe/$(PROGRAM): ruby-runner.c ruby-runner.h exe/.time $(PREP) {$(VPATH)}config.h $(Q) $(CC) $(CFLAGS) $(INCFLAGS) $(CPPFLAGS) -DRUBY_INSTALL_NAME=$(@F) $(COUTFLAG)ruby-runner.$(OBJEXT) -c $(CSRCFLAG)$(srcdir)/ruby-runner.c $(Q) $(PURIFY) $(CC) $(CFLAGS) $(LDFLAGS) $(OUTFLAG)$@ ruby-runner.$(OBJEXT) $(LIBS) @@ -1026,6 +1105,8 @@ exe/$(PROGRAM): ruby-runner.c ruby-runner.h exe/.time $(PREP) {$(VPATH)}config.h -e ' File.symlink(prog, dest)' \ -e 'end' \ $(@F) $(@D) $(RUBY_INSTALL_NAME)$(EXEEXT) + $(Q) $(BOOTSTRAPRUBY) -r$(srcdir)/lib/fileutils \ + -e 'FileUtils::Verbose.ln_sr(*ARGV, force: true)' rbconfig.rb $(EXTOUT)/$(arch) exe/.time: $(Q) $(MAKEDIRS) $(@D) @@ -1127,10 +1208,11 @@ $(srcs_vpath)insns_info.inc: $(tooldir)/ruby_vm/views/insns_info.inc.erb $(inc_c $(tooldir)/ruby_vm/views/_insn_type_chars.erb $(tooldir)/ruby_vm/views/_insn_name_info.erb \ $(tooldir)/ruby_vm/views/_insn_len_info.erb $(tooldir)/ruby_vm/views/_insn_operand_info.erb \ $(tooldir)/ruby_vm/views/_attributes.erb $(tooldir)/ruby_vm/views/_comptime_insn_stack_increase.erb \ - $(tooldir)/ruby_vm/views/_insn_sp_pc_dependency.erb + $(tooldir)/ruby_vm/views/_zjit_helpers.erb $(srcs_vpath)vmtc.inc: $(tooldir)/ruby_vm/views/vmtc.inc.erb $(inc_common_headers) $(srcs_vpath)vm.inc: $(tooldir)/ruby_vm/views/vm.inc.erb $(inc_common_headers) \ - $(tooldir)/ruby_vm/views/_insn_entry.erb $(tooldir)/ruby_vm/views/_trace_instruction.erb + $(tooldir)/ruby_vm/views/_insn_entry.erb $(tooldir)/ruby_vm/views/_trace_instruction.erb \ + $(tooldir)/ruby_vm/views/_zjit_instruction.erb BUILTIN_RB_SRCS = \ $(srcdir)/ast.rb \ @@ -1139,12 +1221,11 @@ BUILTIN_RB_SRCS = \ $(srcdir)/numeric.rb \ $(srcdir)/io.rb \ $(srcdir)/marshal.rb \ - $(srcdir)/rjit.rb \ - $(srcdir)/rjit_c.rb \ $(srcdir)/pack.rb \ $(srcdir)/trace_point.rb \ $(srcdir)/warning.rb \ $(srcdir)/array.rb \ + $(srcdir)/hash.rb \ $(srcdir)/kernel.rb \ $(srcdir)/ractor.rb \ $(srcdir)/symbol.rb \ @@ -1154,6 +1235,8 @@ BUILTIN_RB_SRCS = \ $(srcdir)/prelude.rb \ $(srcdir)/gem_prelude.rb \ $(srcdir)/yjit.rb \ + $(srcdir)/yjit_hook.rb \ + $(srcdir)/zjit.rb \ $(empty) BUILTIN_RB_INCS = $(BUILTIN_RB_SRCS:.rb=.rbinc) @@ -1183,7 +1266,7 @@ srcs-ext: $(EXT_SRCS) realclean-srcs-ext:: $(Q)$(RM) $(EXT_SRCS) -EXTRA_SRCS = $(srcdir)/ext/json/parser/parser.c \ +EXTRA_SRCS = \ $(srcdir)/ext/date/zonetab.h \ $(empty) @@ -1199,11 +1282,12 @@ srcs-enc: $(ENC_MK) $(ECHO) making srcs under enc $(Q) $(MAKE) $(MAKE_ENC) srcs -all-incs: incs {$(VPATH)}encdb.h {$(VPATH)}transdb.h +all-incs: incs {$(VPATH)}encdb.h {$(VPATH)}transdb.h {$(VPATH)}probes.h incs: $(INSNS) {$(VPATH)}node_name.inc {$(VPATH)}known_errors.inc \ {$(VPATH)}vm_call_iseq_optimized.inc $(srcdir)/revision.h \ $(REVISION_H) \ $(UNICODE_DATA_HEADERS) $(ENC_HEADERS) \ + $(srcs_vpath)prism/ast.h $(srcs_vpath)prism/diagnostic.h \ {$(VPATH)}id.h {$(VPATH)}probes.dmyh insns: $(INSNS) @@ -1245,10 +1329,7 @@ $(MINIPRELUDE_C): $(COMPILE_PRELUDE) $(BUILTIN_RB_SRCS) $(Q) $(BASERUBY) $(tooldir)/generic_erb.rb -I$(srcdir) -o $@ \ $(srcdir)/template/prelude.c.tmpl $(BUILTIN_RB_SRCS) -$(GOLF_PRELUDE_C): $(COMPILE_PRELUDE) {$(srcdir)}golf_prelude.rb - $(ECHO) generating $@ - $(Q) $(BASERUBY) $(tooldir)/generic_erb.rb -I$(srcdir) -c -o $@ \ - $(srcdir)/template/prelude.c.tmpl golf_prelude.rb +golf_prelude.rbbin: {$(srcdir)}golf_prelude.rb $(tooldir)/mk_rbbin.rb $(PREP) MAINCPPFLAGS = $(ENABLE_DEBUG_ENV:yes=-DRUBY_DEBUG_ENV=1) @@ -1266,15 +1347,22 @@ probes.h: {$(VPATH)}probes.$(DTRACE_EXT) prereq: incs srcs preludes PHONY preludes: {$(VPATH)}miniprelude.c -preludes: {$(srcdir)}golf_prelude.c + +{$(srcdir)}.rb.rbbin: + $(ECHO) making $@ + $(Q) $(MINIRUBY) $(tooldir)/mk_rbbin.rb $< > $@ {$(srcdir)}.rb.rbinc: $(ECHO) making $@ $(Q) $(BASERUBY) $(tooldir)/mk_builtin_loader.rb $< -builtin_binary.inc: $(PREP) $(BUILTIN_RB_SRCS) $(srcdir)/template/builtin_binary.inc.tmpl +$(BUILTIN_BINARY:yes=built)in_binary.inc: $(PREP) $(BUILTIN_RB_SRCS) $(srcdir)/template/builtin_binary.inc.tmpl $(Q) $(MINIRUBY) $(tooldir)/generic_erb.rb -o $@ \ - $(srcdir)/template/builtin_binary.inc.tmpl -- --cross=$(CROSS_COMPILING) + $(srcdir)/template/builtin_binary.inc.tmpl + -$(Q) sha256sum $@ 2> $(NULL) || $(NULLCMD) + +$(BUILTIN_BINARY:no=builtin)_binary.inc: + $(Q) echo> $@ // empty $(@F) $(BUILTIN_RB_INCS): $(top_srcdir)/tool/mk_builtin_loader.rb @@ -1288,7 +1376,7 @@ $(REVISION_H)$(yes_baseruby:yes=~disabled~): # uncommon.mk: $(REVISION_H) # $(MKFILES): $(REVISION_H) -$(DOT_WAIT)ripper_srcs: $(RIPPER_SRCS) +ripper_srcs: $(RIPPER_SRCS) $(RIPPER_SRCS): $(srcdir)/parse.y $(srcdir)/defs/id.def $(RIPPER_SRCS): $(srcdir)/ext/ripper/tools/preproc.rb $(srcdir)/ext/ripper/tools/dsl.rb @@ -1300,11 +1388,6 @@ $(RIPPER_SRCS): $(srcdir)/ext/ripper/ripper_init.c.tmpl $(srcdir)/ext/ripper/eve Q=$(Q) ECHO=$(ECHO) RM="$(RM1)" top_srcdir=../.. srcdir=. VPATH=../.. \ RUBY="$(BASERUBY)" BASERUBY="$(BASERUBY)" PATH_SEPARATOR="$(PATH_SEPARATOR)" LANG=C -$(srcdir)/ext/json/parser/parser.c: $(srcdir)/ext/json/parser/parser.rl $(srcdir)/ext/json/parser/prereq.mk - $(ECHO) generating $@ - $(Q) $(CHDIR) $(@D) && $(exec) $(MAKE) -f prereq.mk $(mflags) \ - Q=$(Q) ECHO=$(ECHO) top_srcdir=../../.. srcdir=. VPATH=../../.. BASERUBY="$(BASERUBY)" - $(srcdir)/ext/date/zonetab.h: $(srcdir)/ext/date/zonetab.list $(srcdir)/ext/date/prereq.mk $(ECHO) generating $@ $(Q) $(CHDIR) $(@D) && $(exec) $(MAKE) -f prereq.mk $(mflags) \ @@ -1326,7 +1409,7 @@ $(srcdir)/ext/rbconfig/sizeof/limits.c: $(srcdir)/ext/rbconfig/sizeof/depend \ $(exec) $(MAKE) -f - $(mflags) \ Q=$(Q) ECHO=$(ECHO) top_srcdir=../../.. srcdir=. VPATH=../../.. RUBY="$(BASERUBY)" $(@F) -$(srcdir)/ext/socket/constdefs.c: $(srcdir)/ext/socket/depend +$(srcdir)/ext/socket/constdefs.c: $(srcdir)/ext/socket/depend $(srcdir)/ext/socket/mkconstants.rb $(Q) $(CHDIR) $(@D) && \ $(CAT_DEPEND) depend | \ $(exec) $(MAKE) -f - $(mflags) \ @@ -1346,8 +1429,8 @@ run: yes-fake miniruby$(EXEEXT) PHONY runruby: $(PROGRAM) PHONY RUBY_ON_BUG='gdb -x $(srcdir)/.gdbinit -p' $(RUNRUBY) $(RUNOPT0) $(TESTRUN_SCRIPT) $(RUNOPT) -runirb: $(PROGRAM) PHONY - RUBY_ON_BUG='gdb -x $(srcdir)/.gdbinit -p' $(RUNRUBY) $(RUNOPT0) -r irb -e 'IRB.start("make runirb")' $(RUNOPT) +runirb: $(PROGRAM) update-default-gemspecs + RUBY_ON_BUG='gdb -x $(srcdir)/.gdbinit -p' $(RUNRUBY) $(RUNOPT0) -rrubygems -r irb -e 'IRB.start("make runirb")' $(RUNOPT) parse: yes-fake miniruby$(EXEEXT) PHONY $(BTESTRUBY) --dump=parsetree_with_comment,insns $(TESTRUN_SCRIPT) @@ -1449,7 +1532,7 @@ refresh-gems: update-bundled_gems prepare-gems prepare-gems: $(HAVE_BASERUBY:yes=update-gems) $(HAVE_BASERUBY:yes=extract-gems) extract-gems: $(HAVE_BASERUBY:yes=update-gems) -update-gems$(gnumake:yes=-sequential): PHONY +update-gems$(sequential): PHONY $(ECHO) Downloading bundled gem files... $(Q) $(BASERUBY) -C "$(srcdir)" \ -I./tool -rdownloader -answ \ @@ -1463,7 +1546,7 @@ update-gems$(gnumake:yes=-sequential): PHONY -e 'FileUtils.rm_rf(old.map{'"|n|"'n.chomp(".gem")})' \ gems/bundled_gems -extract-gems$(gnumake:yes=-sequential): PHONY +extract-gems$(sequential): PHONY $(ECHO) Extracting bundled gem files... $(Q) $(BASERUBY) -C "$(srcdir)" \ -Itool/lib -rfileutils -rbundled_gem -answ \ @@ -1479,22 +1562,12 @@ extract-gems$(gnumake:yes=-sequential): PHONY -e 'end' \ gems/bundled_gems -extract-gems$(gnumake:yes=-sequential): $(HAVE_GIT:yes=clone-bundled-gems-src) - -clone-bundled-gems-src: PHONY - $(Q) $(BASERUBY) -C "$(srcdir)" \ - -Itool/lib -rbundled_gem -answ \ - -e 'BEGIN {git = $$git}' \ - -e 'gem, _, repo, rev = *$$F' \ - -e 'next if !rev or /^#/=~gem' \ - -e 'gemdir = "gems/src/#{gem}"' \ - -e 'BundledGem.checkout(gemdir, repo, rev, git: git)' \ - -e 'BundledGem.dummy_gemspec("#{gemdir}/#{gem}.gemspec")' \ - -- -git="$(GIT)" \ - gems/bundled_gems +extract-gems$(sequential): $(HAVE_GIT:yes=clone-bundled-gems-src) outdate-bundled-gems: PHONY - $(Q) $(BASERUBY) $(tooldir)/$@.rb --make="$(MAKE)" --mflags="$(MFLAGS)" "$(srcdir)" + $(Q) $(BASERUBY) $(tooldir)/$@.rb --make="$(MAKE)" --mflags="$(MFLAGS)" \ + --ruby-platform=$(arch) --ruby-version=$(ruby_version) \ + "$(srcdir)" update-bundled_gems: PHONY $(Q) $(RUNRUBY) -rrubygems \ @@ -1504,63 +1577,89 @@ update-bundled_gems: PHONY $(GIT) -C "$(srcdir)" diff --no-ext-diff --ignore-submodules --exit-code || \ $(GIT) -C "$(srcdir)" commit -m "Update bundled_gems" gems/bundled_gems -PRECHECK_BUNDLED_GEMS = test-bundled-gems-precheck +PRECHECK_BUNDLED_GEMS = yes test-bundled-gems-precheck: $(TEST_RUNNABLE)-test-bundled-gems-precheck -yes-test-bundled-gems-precheck: main +yes-test-bundled-gems-precheck: $(PRECHECK_BUNDLED_GEMS:yes=main) no-test-bundled-gems-precheck: +update-default-gemspecs: $(TEST_RUNNABLE)-update-default-gemspecs +no-update-default-gemspecs: +yes-update-default-gemspecs: $(PRECHECK_BUNDLED_GEMS:yes=main) + @$(MAKEDIRS) $(srcdir)/.bundle/specifications + @$(XRUBY) -W0 -C "$(srcdir)" -rrubygems \ + -e "destdir = ARGV.shift" \ + -e "ARGV.each do |basedir|" \ + -e "Dir.glob(basedir+'/**/*.gemspec') do |g|" \ + -e "dir, base = File.split(g)" \ + -e "spec = Dir.chdir(dir) {Gem::Specification.load(base)} ||" \ + -e "Gem::Specification.load(g)" \ + -e "unless spec" \ + -e "puts %[Ignoring #{g}]" \ + -e "next" \ + -e "end" \ + -e "spec.files.clear" \ + -e "spec.extensions.clear" \ + -e "File.binwrite(File.join(destdir, spec.full_name+'.gemspec'), spec.to_ruby)" \ + -e "end" \ + -e "end" \ + -- .bundle/specifications lib ext + +install-for-test-bundled-gems: $(TEST_RUNNABLE)-install-for-test-bundled-gems +no-install-for-test-bundled-gems: no-update-default-gemspecs +yes-install-for-test-bundled-gems: yes-update-default-gemspecs + $(XRUBY) -C "$(srcdir)" -r./tool/lib/gem_env.rb bin/gem \ + install --no-document --conservative \ + "hoe" "json-schema:5.1.0" "test-unit-rr" "simplecov" "simplecov-html" "simplecov-json" "rspec" "zeitwerk" \ + "sinatra" "rack" "tilt" "mustermann" "base64" "compact_index" "rack-test" "logger" "kpeg" "tracer" + test-bundled-gems-fetch: yes-test-bundled-gems-fetch -yes-test-bundled-gems-fetch: - $(ACTIONS_GROUP) - $(Q) $(BASERUBY) -C $(srcdir)/gems ../tool/fetch-bundled_gems.rb src bundled_gems - $(ACTIONS_ENDGROUP) +yes-test-bundled-gems-fetch: clone-bundled-gems-src +clone-bundled-gems-src: PHONY + $(Q) $(BASERUBY) -C $(srcdir)/gems ../tool/fetch-bundled_gems.rb BUNDLED_GEMS="$(BUNDLED_GEMS)" src bundled_gems no-test-bundled-gems-fetch: -test-bundled-gems-prepare: $(PRECHECK_BUNDLED_GEMS) test-bundled-gems-fetch test-bundled-gems-prepare: $(TEST_RUNNABLE)-test-bundled-gems-prepare -no-test-bundled-gems-prepare: no-test-bundled-gems-precheck -yes-test-bundled-gems-prepare: yes-test-bundled-gems-precheck +no-test-bundled-gems-prepare: no-test-bundled-gems-precheck no-test-bundled-gems-fetch +Preparing-test-bundled-gems: $(ACTIONS_GROUP) - $(XRUBY) -C "$(srcdir)" bin/gem install --no-document \ - --install-dir .bundle --conservative "hoe" "json-schema" "test-unit-rr" +yes-test-bundled-gems-prepare: Preparing-test-bundled-gems $(DOT_WAIT) $(ACTIONS_ENDGROUP) +yes-test-bundled-gems-prepare: yes-test-bundled-gems-precheck $(DOT_WAIT) +yes-test-bundled-gems-prepare: yes-install-for-test-bundled-gems $(DOT_WAIT) +yes-test-bundled-gems-prepare: yes-test-bundled-gems-fetch $(DOT_WAIT) +yes-test-bundled-gems-precheck: Preparing-test-bundled-gems +yes-install-for-test-bundled-gems: Preparing-test-bundled-gems +yes-test-bundled-gems-fetch: Preparing-test-bundled-gems PREPARE_BUNDLED_GEMS = test-bundled-gems-prepare -test-bundled-gems: $(TEST_RUNNABLE)-test-bundled-gems +test-bundled-gems: $(TEST_RUNNABLE)-test-bundled-gems $(DOT_WAIT) $(TEST_RUNNABLE)-test-bundled-gems-spec yes-test-bundled-gems: test-bundled-gems-run no-test-bundled-gems: +bundled_gems_spec-run: install-for-test-bundled-gems + $(XRUBY) -C $(srcdir) .bundle/bin/rspec spec/bundled_gems_spec.rb + # Override this to allow failure of specific gems on CI # TEST_BUNDLED_GEMS_ALLOW_FAILURES = BUNDLED_GEMS = -test-bundled-gems-run: $(PREPARE_BUNDLED_GEMS) +test-bundled-gems-run: $(TEST_RUNNABLE)-test-bundled-gems-run +yes-test-bundled-gems-run: $(PREPARE_BUNDLED_GEMS) $(gnumake_recursive)$(Q) $(XRUBY) $(tooldir)/test-bundled-gems.rb $(BUNDLED_GEMS) +no-test-bundled-gems-run: $(PREPARE_BUNDLED_GEMS) -test-syntax-suggest-precheck: $(TEST_RUNNABLE)-test-syntax-suggest-precheck -no-test-syntax-suggest-precheck: -yes-test-syntax-suggest-precheck: main - -test-syntax-suggest-prepare: $(TEST_RUNNABLE)-test-syntax-suggest-prepare -no-test-syntax-suggest-prepare: no-test-syntax-suggest-precheck -yes-test-syntax-suggest-prepare: yes-test-syntax-suggest-precheck +test-bundled-gems-spec: $(TEST_RUNNABLE)-test-bundled-gems-spec +yes-test-bundled-gems-spec: yes-test-spec-precheck $(PREPARE_BUNDLED_GEMS) $(ACTIONS_GROUP) - $(XRUBY) -C "$(srcdir)" bin/gem install --no-document \ - --install-dir .bundle --conservative "rspec:~> 3" + $(gnumake_recursive)$(Q) \ + $(RUNRUBY) -r./$(arch)-fake -r$(tooldir)/lib/_tmpdir \ + $(srcdir)/spec/mspec/bin/mspec run --env BUNDLED_GEMS=$(BUNDLED_GEMS) -B $(srcdir)/spec/bundled_gems.mspec \ + $(MSPECOPT) $(SPECOPTS) $(ACTIONS_ENDGROUP) +no-test-bundled-gems-spec: -RSPECOPTS = -SYNTAX_SUGGEST_SPECS = -PREPARE_SYNTAX_SUGGEST = $(TEST_RUNNABLE)-test-syntax-suggest-prepare -test-syntax-suggest: $(TEST_RUNNABLE)-test-syntax-suggest -yes-test-syntax-suggest: $(PREPARE_SYNTAX_SUGGEST) - $(ACTIONS_GROUP) - $(XRUBY) -C $(srcdir) -Ispec/syntax_suggest:spec/lib .bundle/bin/rspec \ - --require rspec/expectations \ - --require spec_helper --require formatter_overrides --require spec_coverage \ - $(RSPECOPTS) spec/syntax_suggest/$(SYNTAX_SUGGEST_SPECS) - $(ACTIONS_ENDGROUP) -no-test-syntax-suggest: + +test-syntax-suggest: check: $(DOT_WAIT) $(PREPARE_SYNTAX_SUGGEST) test-syntax-suggest @@ -1573,24 +1672,19 @@ test-bundler-prepare: $(TEST_RUNNABLE)-test-bundler-prepare no-test-bundler-prepare: no-test-bundler-precheck yes-test-bundler-prepare: yes-test-bundler-precheck $(ACTIONS_GROUP) - $(XRUBY) -C $(srcdir) -Ilib \ - -e 'ENV["GEM_HOME"] = File.expand_path(".bundle")' \ - -e 'ENV["BUNDLE_APP_CONFIG"] = File.expand_path(".bundle")' \ - -e 'ENV["BUNDLE_PATH__SYSTEM"] = "true"' \ - -e 'ENV["BUNDLE_WITHOUT"] = "lint doc"' \ - -e 'load "spec/bundler/support/bundle.rb"' -- install --quiet --gemfile=tool/bundler/dev_gems.rb + $(XRUBY) -C $(srcdir) -Ilib -r./tool/lib/bundle_env.rb \ + spec/bin/bundle install --quiet --gemfile=tool/bundler/dev_gems.rb $(ACTIONS_ENDGROUP) -RSPECOPTS = +RSPECOPTS = -r formatter_overrides BUNDLER_SPECS = PREPARE_BUNDLER = $(TEST_RUNNABLE)-test-bundler-prepare test-bundler: $(TEST_RUNNABLE)-test-bundler yes-test-bundler: $(PREPARE_BUNDLER) $(gnumake_recursive)$(XRUBY) \ -r./$(arch)-fake \ - -e "exec(*ARGV)" -- \ - $(XRUBY) -C $(srcdir) -Ispec/bundler:spec/lib .bundle/bin/rspec \ - --require spec_helper --require formatter_overrides $(RSPECOPTS) spec/bundler/$(BUNDLER_SPECS) + -C $(srcdir) -Ispec/bundler -Ispec/lib spec/bin/rspec \ + -r spec_helper $(RSPECOPTS) spec/bundler/$(BUNDLER_SPECS) no-test-bundler: PARALLELRSPECOPTS = --runtime-log $(srcdir)/tmp/parallel_runtime_rspec.log @@ -1598,22 +1692,21 @@ test-bundler-parallel: $(TEST_RUNNABLE)-test-bundler-parallel yes-test-bundler-parallel: $(PREPARE_BUNDLER) $(gnumake_recursive)$(XRUBY) \ -r./$(arch)-fake \ + -I$(srcdir)/spec/bundler \ + -e "ruby = ENV['RUBY']" \ -e "ARGV[-1] = File.expand_path(ARGV[-1])" \ - -e "exec(*ARGV)" -- \ - $(XRUBY) -I$(srcdir)/spec/bundler \ - -e "ENV['PARALLEL_TESTS_EXECUTABLE'] = ARGV.shift" \ + -e "ENV['RSPEC_EXECUTABLE'] = ruby + ARGV.shift" \ -e "load ARGV.shift" \ - "$(XRUBY) -C $(srcdir) -Ispec/bundler:spec/lib .bundle/bin/rspec" \ - $(srcdir)/.bundle/bin/parallel_rspec \ - -o "--require spec_helper --require formatter_overrides" \ + " -C $(srcdir) -Ispec/bundler -Ispec/lib .bundle/bin/rspec -r spec_helper" \ + $(srcdir)/spec/bin/parallel_rspec $(RSPECOPTS) \ $(PARALLELRSPECOPTS) $(srcdir)/spec/bundler/$(BUNDLER_SPECS) no-test-bundler-parallel: # The annocheck supports ELF format binaries compiled for any OS and for any # architecture. It is designed to be independent of the host OS and the # architecture. The test-annocheck.sh requires docker or podman. -test-annocheck: $(PROGRAM) - $(tooldir)/test-annocheck.sh $(PROGRAM) +test-annocheck: $(PROGRAM) $(LIBRUBY_SO) + $(tooldir)/test-annocheck.sh $(PROGRAM) $(LIBRUBY_SO) GEM = up sync-default-gems: @@ -1626,7 +1719,7 @@ UNICODE_FILES = $(UNICODE_SRC_DATA_DIR)/UnicodeData.txt \ $(UNICODE_SRC_DATA_DIR)/SpecialCasing.txt \ $(empty) -UNICODE_PROPERTY_FILES = \ +UNICODE_PROPERTY_FILES = \ $(UNICODE_SRC_DATA_DIR)/Blocks.txt \ $(UNICODE_SRC_DATA_DIR)/DerivedAge.txt \ $(UNICODE_SRC_DATA_DIR)/DerivedCoreProperties.txt \ @@ -1636,7 +1729,7 @@ UNICODE_PROPERTY_FILES = \ $(UNICODE_SRC_DATA_DIR)/Scripts.txt \ $(empty) -UNICODE_AUXILIARY_FILES = \ +UNICODE_AUXILIARY_FILES = \ $(UNICODE_SRC_DATA_DIR)/auxiliary/GraphemeBreakProperty.txt \ $(UNICODE_SRC_DATA_DIR)/auxiliary/GraphemeBreakTest.txt \ $(empty) @@ -1679,30 +1772,46 @@ UNICODE_EMOJI_DOWNLOAD = \ -d $(UNICODE_SRC_EMOJI_DATA_DIR) \ -p emoji/$(UNICODE_EMOJI_VERSION) -update-unicode-files: $(UNICODE_FILES) $(UNICODE_PROPERTY_FILES) -$(UNICODE_FILES) $(UNICODE_PROPERTY_FILES): +update-unicode-files: $(ECHO) Downloading Unicode $(UNICODE_VERSION) data and property files... $(Q) $(MAKEDIRS) "$(UNICODE_SRC_DATA_DIR)" $(Q) $(UNICODE_DOWNLOAD) $(UNICODE_FILES) $(UNICODE_PROPERTY_FILES) -update-unicode-auxiliary-files: $(UNICODE_AUXILIARY_FILES) -$(UNICODE_AUXILIARY_FILES): +update-unicode-auxiliary-files: $(ECHO) Downloading Unicode $(UNICODE_VERSION) auxiliary files... $(Q) $(MAKEDIRS) "$(UNICODE_SRC_DATA_DIR)/auxiliary" $(Q) $(UNICODE_AUXILIARY_DOWNLOAD) $(UNICODE_AUXILIARY_FILES) -update-unicode-ucd-emoji-files: $(UNICODE_UCD_EMOJI_FILES) -$(UNICODE_UCD_EMOJI_FILES): +update-unicode-ucd-emoji-files: $(ECHO) Downloading Unicode UCD emoji $(UNICODE_EMOJI_VERSION) files... $(Q) $(MAKEDIRS) "$(UNICODE_SRC_DATA_DIR)/emoji" $(Q) $(UNICODE_UCD_EMOJI_DOWNLOAD) $(UNICODE_UCD_EMOJI_FILES) -update-unicode-emoji-files: $(UNICODE_EMOJI_FILES) -$(UNICODE_EMOJI_FILES): +update-unicode-emoji-files: $(ECHO) Downloading Unicode emoji $(UNICODE_EMOJI_VERSION) files... $(Q) $(MAKEDIRS) "$(UNICODE_SRC_EMOJI_DATA_DIR)" $(Q) $(UNICODE_EMOJI_DOWNLOAD) $(UNICODE_EMOJI_FILES) +$(UNICODE_FILES) $(UNICODE_PROPERTY_FILES): + $(ECHO) Downloading Unicode $(UNICODE_VERSION) data and property files... + $(Q) $(MAKEDIRS) "$(UNICODE_SRC_DATA_DIR)" + $(Q) $(UNICODE_DOWNLOAD) $@ + +$(UNICODE_AUXILIARY_FILES): + $(ECHO) Downloading Unicode $(UNICODE_VERSION) auxiliary files... + $(Q) $(MAKEDIRS) "$(UNICODE_SRC_DATA_DIR)/auxiliary" + $(Q) $(UNICODE_AUXILIARY_DOWNLOAD) $@ + +$(UNICODE_UCD_EMOJI_FILES): + $(ECHO) Downloading Unicode UCD emoji $(UNICODE_EMOJI_VERSION) files... + $(Q) $(MAKEDIRS) "$(UNICODE_SRC_DATA_DIR)/emoji" + $(Q) $(UNICODE_UCD_EMOJI_DOWNLOAD) $@ + +$(UNICODE_EMOJI_FILES): + $(ECHO) Downloading Unicode emoji $(UNICODE_EMOJI_VERSION) files... + $(Q) $(MAKEDIRS) "$(UNICODE_SRC_EMOJI_DATA_DIR)" + $(Q) $(UNICODE_EMOJI_DOWNLOAD) $@ + $(srcdir)/lib/unicode_normalize/tables.rb: \ $(UNICODE_SRC_DATA_DIR)/$(HAVE_BASERUBY:yes=.unicode-tables.time) @@ -1808,6 +1917,7 @@ info-arch: PHONY exam: check exam: $(DOT_WAIT) test-bundler-parallel +exam: $(DOT_WAIT) bundled_gems_spec-run exam: $(DOT_WAIT) test-bundled-gems love: sudo-precheck up all test exam install @@ -1830,11 +1940,56 @@ update-man-date: PHONY ChangeLog: $(ECHO) Generating $@ -$(Q) $(BASERUBY) -I"$(tooldir)/lib" -rvcs \ - -e 'VCS.detect(ARGV[0]).export_changelog("@", nil, nil, ARGV[1])' \ + -e 'VCS.detect(ARGV[0]).export_changelog(path: ARGV[1])' \ "$(srcdir)" $@ +# CAUTION: If using GNU make 3 which does not support `.WAIT`, this +# recipe with multiple jobs makes build and `git reset` run +# simultaneously, and will cause inconsistent results. Run with `-j1` +# or update GNU make. +nightly: yesterday $(DOT_WAIT) install + $(NULLCMD) + +# Rewind to the last commit "yesterday". "Yesterday" means here the +# period where `RUBY_RELEASE_DATE` is the day before the date to be +# generated now. In short, the yesterday in JST-9 time zone. +yesterday: rewindable + +rewindable: + $(GIT) -C $(srcdir) status --porcelain + $(GIT) -C $(srcdir) diff --quiet + HELP_EXTRA_TASKS = "" +gc/Makefile: + $(MAKEDIRS) $(@D) + $(MESSAGE_BEGIN) \ + "all:" \ + " @echo You must specify MODULAR_GC with the GC to build" \ + " @exit 1" \ + $(MESSAGE_END) > $@ +gc/distclean gc/realclean:: + -$(Q) $(RM) gc/Makefile + +modular-gc-precheck: +modular-gc: probes.h gc/Makefile + $(Q) $(RUNRUBY) $(srcdir)/ext/extmk.rb \ + $(SCRIPT_ARGS) \ + --make='$(MAKE)' --make-flags="V=$(V) MINIRUBY='$(MINIRUBY)'" \ + --gnumake=$(gnumake) --extflags="$(EXTLDFLAGS)" \ + --ext-build-dir=gc --command-output=gc/$(MODULAR_GC)/exts.mk -- \ + configure gc/$(MODULAR_GC) + $(CHDIR) gc/$(MODULAR_GC) && $(exec) $(MAKE) TARGET_SO_DIR=./ +install-modular-gc: modular-gc modular-gc-precheck + $(Q) $(MAKEDIRS) $(modular_gc_dir) + $(CP) gc/$(MODULAR_GC)/librubygc.$(MODULAR_GC).$(DLEXT) $(modular_gc_dir) + +clean-modular-gc: gc/clean +distclean-modular-gc: gc/distclean +realclean-modular-gc: gc/realclean +distclean-modular-gc realclean-modular-gc: + -$(Q) $(RMDIR) gc + help: PHONY $(MESSAGE_BEGIN) \ " Makefile of Ruby" \ @@ -1955,11 +2110,14 @@ array.$(OBJEXT): $(top_srcdir)/internal/fixnum.h array.$(OBJEXT): $(top_srcdir)/internal/gc.h array.$(OBJEXT): $(top_srcdir)/internal/hash.h array.$(OBJEXT): $(top_srcdir)/internal/imemo.h +array.$(OBJEXT): $(top_srcdir)/internal/namespace.h array.$(OBJEXT): $(top_srcdir)/internal/numeric.h array.$(OBJEXT): $(top_srcdir)/internal/object.h array.$(OBJEXT): $(top_srcdir)/internal/proc.h array.$(OBJEXT): $(top_srcdir)/internal/rational.h +array.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h array.$(OBJEXT): $(top_srcdir)/internal/serial.h +array.$(OBJEXT): $(top_srcdir)/internal/set_table.h array.$(OBJEXT): $(top_srcdir)/internal/static_assert.h array.$(OBJEXT): $(top_srcdir)/internal/variable.h array.$(OBJEXT): $(top_srcdir)/internal/vm.h @@ -2110,6 +2268,7 @@ array.$(OBJEXT): {$(VPATH)}internal/intern/re.h array.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h array.$(OBJEXT): {$(VPATH)}internal/intern/select.h array.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +array.$(OBJEXT): {$(VPATH)}internal/intern/set.h array.$(OBJEXT): {$(VPATH)}internal/intern/signal.h array.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h array.$(OBJEXT): {$(VPATH)}internal/intern/string.h @@ -2129,6 +2288,7 @@ array.$(OBJEXT): {$(VPATH)}internal/special_consts.h array.$(OBJEXT): {$(VPATH)}internal/static_assert.h array.$(OBJEXT): {$(VPATH)}internal/stdalign.h array.$(OBJEXT): {$(VPATH)}internal/stdbool.h +array.$(OBJEXT): {$(VPATH)}internal/stdckdint.h array.$(OBJEXT): {$(VPATH)}internal/symbol.h array.$(OBJEXT): {$(VPATH)}internal/value.h array.$(OBJEXT): {$(VPATH)}internal/value_type.h @@ -2148,6 +2308,7 @@ array.$(OBJEXT): {$(VPATH)}rubyparser.h array.$(OBJEXT): {$(VPATH)}shape.h array.$(OBJEXT): {$(VPATH)}st.h array.$(OBJEXT): {$(VPATH)}subst.h +array.$(OBJEXT): {$(VPATH)}thread.h array.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h array.$(OBJEXT): {$(VPATH)}thread_native.h array.$(OBJEXT): {$(VPATH)}util.h @@ -2161,17 +2322,46 @@ ast.$(OBJEXT): $(hdrdir)/ruby.h ast.$(OBJEXT): $(hdrdir)/ruby/ruby.h ast.$(OBJEXT): $(top_srcdir)/internal/array.h ast.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h +ast.$(OBJEXT): $(top_srcdir)/internal/bignum.h +ast.$(OBJEXT): $(top_srcdir)/internal/bits.h ast.$(OBJEXT): $(top_srcdir)/internal/compilers.h +ast.$(OBJEXT): $(top_srcdir)/internal/complex.h +ast.$(OBJEXT): $(top_srcdir)/internal/fixnum.h ast.$(OBJEXT): $(top_srcdir)/internal/gc.h ast.$(OBJEXT): $(top_srcdir)/internal/imemo.h +ast.$(OBJEXT): $(top_srcdir)/internal/namespace.h +ast.$(OBJEXT): $(top_srcdir)/internal/numeric.h ast.$(OBJEXT): $(top_srcdir)/internal/parse.h +ast.$(OBJEXT): $(top_srcdir)/internal/rational.h ast.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h +ast.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h ast.$(OBJEXT): $(top_srcdir)/internal/serial.h +ast.$(OBJEXT): $(top_srcdir)/internal/set_table.h ast.$(OBJEXT): $(top_srcdir)/internal/static_assert.h ast.$(OBJEXT): $(top_srcdir)/internal/symbol.h ast.$(OBJEXT): $(top_srcdir)/internal/variable.h ast.$(OBJEXT): $(top_srcdir)/internal/vm.h ast.$(OBJEXT): $(top_srcdir)/internal/warnings.h +ast.$(OBJEXT): $(top_srcdir)/prism/defines.h +ast.$(OBJEXT): $(top_srcdir)/prism/encoding.h +ast.$(OBJEXT): $(top_srcdir)/prism/node.h +ast.$(OBJEXT): $(top_srcdir)/prism/options.h +ast.$(OBJEXT): $(top_srcdir)/prism/pack.h +ast.$(OBJEXT): $(top_srcdir)/prism/parser.h +ast.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h +ast.$(OBJEXT): $(top_srcdir)/prism/prism.h +ast.$(OBJEXT): $(top_srcdir)/prism/regexp.h +ast.$(OBJEXT): $(top_srcdir)/prism/static_literals.h +ast.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h +ast.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h +ast.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h +ast.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h +ast.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h +ast.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h +ast.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h +ast.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h +ast.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h +ast.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h ast.$(OBJEXT): {$(VPATH)}assert.h ast.$(OBJEXT): {$(VPATH)}ast.c ast.$(OBJEXT): {$(VPATH)}ast.rbinc @@ -2317,6 +2507,7 @@ ast.$(OBJEXT): {$(VPATH)}internal/intern/re.h ast.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h ast.$(OBJEXT): {$(VPATH)}internal/intern/select.h ast.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +ast.$(OBJEXT): {$(VPATH)}internal/intern/set.h ast.$(OBJEXT): {$(VPATH)}internal/intern/signal.h ast.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h ast.$(OBJEXT): {$(VPATH)}internal/intern/string.h @@ -2336,6 +2527,7 @@ ast.$(OBJEXT): {$(VPATH)}internal/special_consts.h ast.$(OBJEXT): {$(VPATH)}internal/static_assert.h ast.$(OBJEXT): {$(VPATH)}internal/stdalign.h ast.$(OBJEXT): {$(VPATH)}internal/stdbool.h +ast.$(OBJEXT): {$(VPATH)}internal/stdckdint.h ast.$(OBJEXT): {$(VPATH)}internal/symbol.h ast.$(OBJEXT): {$(VPATH)}internal/value.h ast.$(OBJEXT): {$(VPATH)}internal/value_type.h @@ -2348,6 +2540,10 @@ ast.$(OBJEXT): {$(VPATH)}missing.h ast.$(OBJEXT): {$(VPATH)}node.h ast.$(OBJEXT): {$(VPATH)}onigmo.h ast.$(OBJEXT): {$(VPATH)}oniguruma.h +ast.$(OBJEXT): {$(VPATH)}prism/ast.h +ast.$(OBJEXT): {$(VPATH)}prism/diagnostic.h +ast.$(OBJEXT): {$(VPATH)}prism/version.h +ast.$(OBJEXT): {$(VPATH)}prism_compile.h ast.$(OBJEXT): {$(VPATH)}ruby_assert.h ast.$(OBJEXT): {$(VPATH)}ruby_atomic.h ast.$(OBJEXT): {$(VPATH)}rubyparser.h @@ -2374,10 +2570,12 @@ bignum.$(OBJEXT): $(top_srcdir)/internal/complex.h bignum.$(OBJEXT): $(top_srcdir)/internal/fixnum.h bignum.$(OBJEXT): $(top_srcdir)/internal/gc.h bignum.$(OBJEXT): $(top_srcdir)/internal/imemo.h +bignum.$(OBJEXT): $(top_srcdir)/internal/namespace.h bignum.$(OBJEXT): $(top_srcdir)/internal/numeric.h bignum.$(OBJEXT): $(top_srcdir)/internal/object.h bignum.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h bignum.$(OBJEXT): $(top_srcdir)/internal/serial.h +bignum.$(OBJEXT): $(top_srcdir)/internal/set_table.h bignum.$(OBJEXT): $(top_srcdir)/internal/static_assert.h bignum.$(OBJEXT): $(top_srcdir)/internal/variable.h bignum.$(OBJEXT): $(top_srcdir)/internal/vm.h @@ -2525,6 +2723,7 @@ bignum.$(OBJEXT): {$(VPATH)}internal/intern/re.h bignum.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h bignum.$(OBJEXT): {$(VPATH)}internal/intern/select.h bignum.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +bignum.$(OBJEXT): {$(VPATH)}internal/intern/set.h bignum.$(OBJEXT): {$(VPATH)}internal/intern/signal.h bignum.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h bignum.$(OBJEXT): {$(VPATH)}internal/intern/string.h @@ -2544,6 +2743,7 @@ bignum.$(OBJEXT): {$(VPATH)}internal/special_consts.h bignum.$(OBJEXT): {$(VPATH)}internal/static_assert.h bignum.$(OBJEXT): {$(VPATH)}internal/stdalign.h bignum.$(OBJEXT): {$(VPATH)}internal/stdbool.h +bignum.$(OBJEXT): {$(VPATH)}internal/stdckdint.h bignum.$(OBJEXT): {$(VPATH)}internal/symbol.h bignum.$(OBJEXT): {$(VPATH)}internal/value.h bignum.$(OBJEXT): {$(VPATH)}internal/value_type.h @@ -2577,11 +2777,34 @@ builtin.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h builtin.$(OBJEXT): $(top_srcdir)/internal/compilers.h builtin.$(OBJEXT): $(top_srcdir)/internal/gc.h builtin.$(OBJEXT): $(top_srcdir)/internal/imemo.h +builtin.$(OBJEXT): $(top_srcdir)/internal/namespace.h +builtin.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h builtin.$(OBJEXT): $(top_srcdir)/internal/serial.h +builtin.$(OBJEXT): $(top_srcdir)/internal/set_table.h builtin.$(OBJEXT): $(top_srcdir)/internal/static_assert.h builtin.$(OBJEXT): $(top_srcdir)/internal/variable.h builtin.$(OBJEXT): $(top_srcdir)/internal/vm.h builtin.$(OBJEXT): $(top_srcdir)/internal/warnings.h +builtin.$(OBJEXT): $(top_srcdir)/prism/defines.h +builtin.$(OBJEXT): $(top_srcdir)/prism/encoding.h +builtin.$(OBJEXT): $(top_srcdir)/prism/node.h +builtin.$(OBJEXT): $(top_srcdir)/prism/options.h +builtin.$(OBJEXT): $(top_srcdir)/prism/pack.h +builtin.$(OBJEXT): $(top_srcdir)/prism/parser.h +builtin.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h +builtin.$(OBJEXT): $(top_srcdir)/prism/prism.h +builtin.$(OBJEXT): $(top_srcdir)/prism/regexp.h +builtin.$(OBJEXT): $(top_srcdir)/prism/static_literals.h +builtin.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h +builtin.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h +builtin.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h +builtin.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h +builtin.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h +builtin.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h +builtin.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h +builtin.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h +builtin.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h +builtin.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h builtin.$(OBJEXT): {$(VPATH)}assert.h builtin.$(OBJEXT): {$(VPATH)}atomic.h builtin.$(OBJEXT): {$(VPATH)}backward/2/assume.h @@ -2727,6 +2950,7 @@ builtin.$(OBJEXT): {$(VPATH)}internal/intern/re.h builtin.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h builtin.$(OBJEXT): {$(VPATH)}internal/intern/select.h builtin.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +builtin.$(OBJEXT): {$(VPATH)}internal/intern/set.h builtin.$(OBJEXT): {$(VPATH)}internal/intern/signal.h builtin.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h builtin.$(OBJEXT): {$(VPATH)}internal/intern/string.h @@ -2746,6 +2970,7 @@ builtin.$(OBJEXT): {$(VPATH)}internal/special_consts.h builtin.$(OBJEXT): {$(VPATH)}internal/static_assert.h builtin.$(OBJEXT): {$(VPATH)}internal/stdalign.h builtin.$(OBJEXT): {$(VPATH)}internal/stdbool.h +builtin.$(OBJEXT): {$(VPATH)}internal/stdckdint.h builtin.$(OBJEXT): {$(VPATH)}internal/symbol.h builtin.$(OBJEXT): {$(VPATH)}internal/value.h builtin.$(OBJEXT): {$(VPATH)}internal/value_type.h @@ -2758,6 +2983,10 @@ builtin.$(OBJEXT): {$(VPATH)}missing.h builtin.$(OBJEXT): {$(VPATH)}node.h builtin.$(OBJEXT): {$(VPATH)}onigmo.h builtin.$(OBJEXT): {$(VPATH)}oniguruma.h +builtin.$(OBJEXT): {$(VPATH)}prism/ast.h +builtin.$(OBJEXT): {$(VPATH)}prism/diagnostic.h +builtin.$(OBJEXT): {$(VPATH)}prism/version.h +builtin.$(OBJEXT): {$(VPATH)}prism_compile.h builtin.$(OBJEXT): {$(VPATH)}ruby_assert.h builtin.$(OBJEXT): {$(VPATH)}ruby_atomic.h builtin.$(OBJEXT): {$(VPATH)}rubyparser.h @@ -2781,8 +3010,11 @@ class.$(OBJEXT): $(top_srcdir)/internal/eval.h class.$(OBJEXT): $(top_srcdir)/internal/gc.h class.$(OBJEXT): $(top_srcdir)/internal/hash.h class.$(OBJEXT): $(top_srcdir)/internal/imemo.h +class.$(OBJEXT): $(top_srcdir)/internal/namespace.h class.$(OBJEXT): $(top_srcdir)/internal/object.h +class.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h class.$(OBJEXT): $(top_srcdir)/internal/serial.h +class.$(OBJEXT): $(top_srcdir)/internal/set_table.h class.$(OBJEXT): $(top_srcdir)/internal/static_assert.h class.$(OBJEXT): $(top_srcdir)/internal/string.h class.$(OBJEXT): $(top_srcdir)/internal/variable.h @@ -2932,6 +3164,7 @@ class.$(OBJEXT): {$(VPATH)}internal/intern/re.h class.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h class.$(OBJEXT): {$(VPATH)}internal/intern/select.h class.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +class.$(OBJEXT): {$(VPATH)}internal/intern/set.h class.$(OBJEXT): {$(VPATH)}internal/intern/signal.h class.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h class.$(OBJEXT): {$(VPATH)}internal/intern/string.h @@ -2951,6 +3184,7 @@ class.$(OBJEXT): {$(VPATH)}internal/special_consts.h class.$(OBJEXT): {$(VPATH)}internal/static_assert.h class.$(OBJEXT): {$(VPATH)}internal/stdalign.h class.$(OBJEXT): {$(VPATH)}internal/stdbool.h +class.$(OBJEXT): {$(VPATH)}internal/stdckdint.h class.$(OBJEXT): {$(VPATH)}internal/symbol.h class.$(OBJEXT): {$(VPATH)}internal/value.h class.$(OBJEXT): {$(VPATH)}internal/value_type.h @@ -2971,13 +3205,18 @@ class.$(OBJEXT): {$(VPATH)}subst.h class.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h class.$(OBJEXT): {$(VPATH)}thread_native.h class.$(OBJEXT): {$(VPATH)}vm_core.h +class.$(OBJEXT): {$(VPATH)}vm_debug.h class.$(OBJEXT): {$(VPATH)}vm_opts.h +class.$(OBJEXT): {$(VPATH)}vm_sync.h +class.$(OBJEXT): {$(VPATH)}yjit.h compar.$(OBJEXT): $(hdrdir)/ruby/ruby.h +compar.$(OBJEXT): $(hdrdir)/ruby/version.h compar.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h compar.$(OBJEXT): $(top_srcdir)/internal/compar.h compar.$(OBJEXT): $(top_srcdir)/internal/compilers.h compar.$(OBJEXT): $(top_srcdir)/internal/error.h compar.$(OBJEXT): $(top_srcdir)/internal/serial.h +compar.$(OBJEXT): $(top_srcdir)/internal/set_table.h compar.$(OBJEXT): $(top_srcdir)/internal/static_assert.h compar.$(OBJEXT): $(top_srcdir)/internal/string.h compar.$(OBJEXT): $(top_srcdir)/internal/vm.h @@ -3121,6 +3360,7 @@ compar.$(OBJEXT): {$(VPATH)}internal/intern/re.h compar.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h compar.$(OBJEXT): {$(VPATH)}internal/intern/select.h compar.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +compar.$(OBJEXT): {$(VPATH)}internal/intern/set.h compar.$(OBJEXT): {$(VPATH)}internal/intern/signal.h compar.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h compar.$(OBJEXT): {$(VPATH)}internal/intern/string.h @@ -3140,6 +3380,7 @@ compar.$(OBJEXT): {$(VPATH)}internal/special_consts.h compar.$(OBJEXT): {$(VPATH)}internal/static_assert.h compar.$(OBJEXT): {$(VPATH)}internal/stdalign.h compar.$(OBJEXT): {$(VPATH)}internal/stdbool.h +compar.$(OBJEXT): {$(VPATH)}internal/stdckdint.h compar.$(OBJEXT): {$(VPATH)}internal/symbol.h compar.$(OBJEXT): {$(VPATH)}internal/value.h compar.$(OBJEXT): {$(VPATH)}internal/value_type.h @@ -3156,6 +3397,7 @@ compile.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h compile.$(OBJEXT): $(CCAN_DIR)/list/list.h compile.$(OBJEXT): $(CCAN_DIR)/str/str.h compile.$(OBJEXT): $(hdrdir)/ruby/ruby.h +compile.$(OBJEXT): $(hdrdir)/ruby/version.h compile.$(OBJEXT): $(top_srcdir)/internal/array.h compile.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h compile.$(OBJEXT): $(top_srcdir)/internal/bignum.h @@ -3170,11 +3412,17 @@ compile.$(OBJEXT): $(top_srcdir)/internal/fixnum.h compile.$(OBJEXT): $(top_srcdir)/internal/gc.h compile.$(OBJEXT): $(top_srcdir)/internal/hash.h compile.$(OBJEXT): $(top_srcdir)/internal/imemo.h +compile.$(OBJEXT): $(top_srcdir)/internal/io.h +compile.$(OBJEXT): $(top_srcdir)/internal/namespace.h compile.$(OBJEXT): $(top_srcdir)/internal/numeric.h compile.$(OBJEXT): $(top_srcdir)/internal/object.h +compile.$(OBJEXT): $(top_srcdir)/internal/parse.h compile.$(OBJEXT): $(top_srcdir)/internal/rational.h compile.$(OBJEXT): $(top_srcdir)/internal/re.h +compile.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h +compile.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h compile.$(OBJEXT): $(top_srcdir)/internal/serial.h +compile.$(OBJEXT): $(top_srcdir)/internal/set_table.h compile.$(OBJEXT): $(top_srcdir)/internal/static_assert.h compile.$(OBJEXT): $(top_srcdir)/internal/string.h compile.$(OBJEXT): $(top_srcdir)/internal/symbol.h @@ -3182,26 +3430,27 @@ compile.$(OBJEXT): $(top_srcdir)/internal/thread.h compile.$(OBJEXT): $(top_srcdir)/internal/variable.h compile.$(OBJEXT): $(top_srcdir)/internal/vm.h compile.$(OBJEXT): $(top_srcdir)/internal/warnings.h -compile.$(OBJEXT): $(top_srcdir)/yarp/defines.h -compile.$(OBJEXT): $(top_srcdir)/yarp/diagnostic.h -compile.$(OBJEXT): $(top_srcdir)/yarp/enc/yp_encoding.h -compile.$(OBJEXT): $(top_srcdir)/yarp/node.h -compile.$(OBJEXT): $(top_srcdir)/yarp/pack.h -compile.$(OBJEXT): $(top_srcdir)/yarp/parser.h -compile.$(OBJEXT): $(top_srcdir)/yarp/regexp.h -compile.$(OBJEXT): $(top_srcdir)/yarp/unescape.h -compile.$(OBJEXT): $(top_srcdir)/yarp/util/yp_buffer.h -compile.$(OBJEXT): $(top_srcdir)/yarp/util/yp_char.h -compile.$(OBJEXT): $(top_srcdir)/yarp/util/yp_constant_pool.h -compile.$(OBJEXT): $(top_srcdir)/yarp/util/yp_list.h -compile.$(OBJEXT): $(top_srcdir)/yarp/util/yp_memchr.h -compile.$(OBJEXT): $(top_srcdir)/yarp/util/yp_newline_list.h -compile.$(OBJEXT): $(top_srcdir)/yarp/util/yp_state_stack.h -compile.$(OBJEXT): $(top_srcdir)/yarp/util/yp_string.h -compile.$(OBJEXT): $(top_srcdir)/yarp/util/yp_string_list.h -compile.$(OBJEXT): $(top_srcdir)/yarp/util/yp_strpbrk.h -compile.$(OBJEXT): $(top_srcdir)/yarp/yarp.h -compile.$(OBJEXT): $(top_srcdir)/yarp/yarp_compiler.c +compile.$(OBJEXT): $(top_srcdir)/prism/defines.h +compile.$(OBJEXT): $(top_srcdir)/prism/encoding.h +compile.$(OBJEXT): $(top_srcdir)/prism/node.h +compile.$(OBJEXT): $(top_srcdir)/prism/options.h +compile.$(OBJEXT): $(top_srcdir)/prism/pack.h +compile.$(OBJEXT): $(top_srcdir)/prism/parser.h +compile.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h +compile.$(OBJEXT): $(top_srcdir)/prism/prism.h +compile.$(OBJEXT): $(top_srcdir)/prism/regexp.h +compile.$(OBJEXT): $(top_srcdir)/prism/static_literals.h +compile.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h +compile.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h +compile.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h +compile.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h +compile.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h +compile.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h +compile.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h +compile.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h +compile.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h +compile.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h +compile.$(OBJEXT): $(top_srcdir)/prism_compile.c compile.$(OBJEXT): {$(VPATH)}assert.h compile.$(OBJEXT): {$(VPATH)}atomic.h compile.$(OBJEXT): {$(VPATH)}backward/2/assume.h @@ -3352,6 +3601,7 @@ compile.$(OBJEXT): {$(VPATH)}internal/intern/re.h compile.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h compile.$(OBJEXT): {$(VPATH)}internal/intern/select.h compile.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +compile.$(OBJEXT): {$(VPATH)}internal/intern/set.h compile.$(OBJEXT): {$(VPATH)}internal/intern/signal.h compile.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h compile.$(OBJEXT): {$(VPATH)}internal/intern/string.h @@ -3371,12 +3621,14 @@ compile.$(OBJEXT): {$(VPATH)}internal/special_consts.h compile.$(OBJEXT): {$(VPATH)}internal/static_assert.h compile.$(OBJEXT): {$(VPATH)}internal/stdalign.h compile.$(OBJEXT): {$(VPATH)}internal/stdbool.h +compile.$(OBJEXT): {$(VPATH)}internal/stdckdint.h compile.$(OBJEXT): {$(VPATH)}internal/symbol.h compile.$(OBJEXT): {$(VPATH)}internal/value.h compile.$(OBJEXT): {$(VPATH)}internal/value_type.h compile.$(OBJEXT): {$(VPATH)}internal/variable.h compile.$(OBJEXT): {$(VPATH)}internal/warning_push.h compile.$(OBJEXT): {$(VPATH)}internal/xmalloc.h +compile.$(OBJEXT): {$(VPATH)}io.h compile.$(OBJEXT): {$(VPATH)}iseq.h compile.$(OBJEXT): {$(VPATH)}method.h compile.$(OBJEXT): {$(VPATH)}missing.h @@ -3384,6 +3636,13 @@ compile.$(OBJEXT): {$(VPATH)}node.h compile.$(OBJEXT): {$(VPATH)}onigmo.h compile.$(OBJEXT): {$(VPATH)}oniguruma.h compile.$(OBJEXT): {$(VPATH)}optinsn.inc +compile.$(OBJEXT): {$(VPATH)}prism/ast.h +compile.$(OBJEXT): {$(VPATH)}prism/diagnostic.h +compile.$(OBJEXT): {$(VPATH)}prism/prism.h +compile.$(OBJEXT): {$(VPATH)}prism/version.h +compile.$(OBJEXT): {$(VPATH)}prism_compile.c +compile.$(OBJEXT): {$(VPATH)}prism_compile.h +compile.$(OBJEXT): {$(VPATH)}ractor.h compile.$(OBJEXT): {$(VPATH)}re.h compile.$(OBJEXT): {$(VPATH)}regex.h compile.$(OBJEXT): {$(VPATH)}ruby_assert.h @@ -3399,9 +3658,8 @@ compile.$(OBJEXT): {$(VPATH)}vm_callinfo.h compile.$(OBJEXT): {$(VPATH)}vm_core.h compile.$(OBJEXT): {$(VPATH)}vm_debug.h compile.$(OBJEXT): {$(VPATH)}vm_opts.h -compile.$(OBJEXT): {$(VPATH)}yarp/ast.h -compile.$(OBJEXT): {$(VPATH)}yarp/version.h -compile.$(OBJEXT): {$(VPATH)}yarp/yarp.h +compile.$(OBJEXT): {$(VPATH)}vm_sync.h +compile.$(OBJEXT): {$(VPATH)}yjit.h complex.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h complex.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h complex.$(OBJEXT): $(CCAN_DIR)/list/list.h @@ -3418,11 +3676,15 @@ complex.$(OBJEXT): $(top_srcdir)/internal/fixnum.h complex.$(OBJEXT): $(top_srcdir)/internal/gc.h complex.$(OBJEXT): $(top_srcdir)/internal/imemo.h complex.$(OBJEXT): $(top_srcdir)/internal/math.h +complex.$(OBJEXT): $(top_srcdir)/internal/namespace.h complex.$(OBJEXT): $(top_srcdir)/internal/numeric.h complex.$(OBJEXT): $(top_srcdir)/internal/object.h complex.$(OBJEXT): $(top_srcdir)/internal/rational.h +complex.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h complex.$(OBJEXT): $(top_srcdir)/internal/serial.h +complex.$(OBJEXT): $(top_srcdir)/internal/set_table.h complex.$(OBJEXT): $(top_srcdir)/internal/static_assert.h +complex.$(OBJEXT): $(top_srcdir)/internal/string.h complex.$(OBJEXT): $(top_srcdir)/internal/variable.h complex.$(OBJEXT): $(top_srcdir)/internal/vm.h complex.$(OBJEXT): $(top_srcdir)/internal/warnings.h @@ -3440,6 +3702,7 @@ complex.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h complex.$(OBJEXT): {$(VPATH)}complex.c complex.$(OBJEXT): {$(VPATH)}config.h complex.$(OBJEXT): {$(VPATH)}constant.h +complex.$(OBJEXT): {$(VPATH)}debug_counter.h complex.$(OBJEXT): {$(VPATH)}defines.h complex.$(OBJEXT): {$(VPATH)}encoding.h complex.$(OBJEXT): {$(VPATH)}id.h @@ -3569,6 +3832,7 @@ complex.$(OBJEXT): {$(VPATH)}internal/intern/re.h complex.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h complex.$(OBJEXT): {$(VPATH)}internal/intern/select.h complex.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +complex.$(OBJEXT): {$(VPATH)}internal/intern/set.h complex.$(OBJEXT): {$(VPATH)}internal/intern/signal.h complex.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h complex.$(OBJEXT): {$(VPATH)}internal/intern/string.h @@ -3588,6 +3852,7 @@ complex.$(OBJEXT): {$(VPATH)}internal/special_consts.h complex.$(OBJEXT): {$(VPATH)}internal/static_assert.h complex.$(OBJEXT): {$(VPATH)}internal/stdalign.h complex.$(OBJEXT): {$(VPATH)}internal/stdbool.h +complex.$(OBJEXT): {$(VPATH)}internal/stdckdint.h complex.$(OBJEXT): {$(VPATH)}internal/symbol.h complex.$(OBJEXT): {$(VPATH)}internal/value.h complex.$(OBJEXT): {$(VPATH)}internal/value_type.h @@ -3608,13 +3873,220 @@ complex.$(OBJEXT): {$(VPATH)}subst.h complex.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h complex.$(OBJEXT): {$(VPATH)}thread_native.h complex.$(OBJEXT): {$(VPATH)}vm_core.h +complex.$(OBJEXT): {$(VPATH)}vm_debug.h complex.$(OBJEXT): {$(VPATH)}vm_opts.h +complex.$(OBJEXT): {$(VPATH)}vm_sync.h +concurrent_set.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h +concurrent_set.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h +concurrent_set.$(OBJEXT): $(CCAN_DIR)/list/list.h +concurrent_set.$(OBJEXT): $(CCAN_DIR)/str/str.h +concurrent_set.$(OBJEXT): $(hdrdir)/ruby/ruby.h +concurrent_set.$(OBJEXT): $(top_srcdir)/internal/array.h +concurrent_set.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h +concurrent_set.$(OBJEXT): $(top_srcdir)/internal/compilers.h +concurrent_set.$(OBJEXT): $(top_srcdir)/internal/concurrent_set.h +concurrent_set.$(OBJEXT): $(top_srcdir)/internal/gc.h +concurrent_set.$(OBJEXT): $(top_srcdir)/internal/imemo.h +concurrent_set.$(OBJEXT): $(top_srcdir)/internal/namespace.h +concurrent_set.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h +concurrent_set.$(OBJEXT): $(top_srcdir)/internal/serial.h +concurrent_set.$(OBJEXT): $(top_srcdir)/internal/set_table.h +concurrent_set.$(OBJEXT): $(top_srcdir)/internal/static_assert.h +concurrent_set.$(OBJEXT): $(top_srcdir)/internal/vm.h +concurrent_set.$(OBJEXT): $(top_srcdir)/internal/warnings.h +concurrent_set.$(OBJEXT): {$(VPATH)}assert.h +concurrent_set.$(OBJEXT): {$(VPATH)}atomic.h +concurrent_set.$(OBJEXT): {$(VPATH)}backward/2/assume.h +concurrent_set.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +concurrent_set.$(OBJEXT): {$(VPATH)}backward/2/bool.h +concurrent_set.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h +concurrent_set.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +concurrent_set.$(OBJEXT): {$(VPATH)}backward/2/limits.h +concurrent_set.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +concurrent_set.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +concurrent_set.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h +concurrent_set.$(OBJEXT): {$(VPATH)}concurrent_set.c +concurrent_set.$(OBJEXT): {$(VPATH)}config.h +concurrent_set.$(OBJEXT): {$(VPATH)}debug_counter.h +concurrent_set.$(OBJEXT): {$(VPATH)}defines.h +concurrent_set.$(OBJEXT): {$(VPATH)}encoding.h +concurrent_set.$(OBJEXT): {$(VPATH)}id.h +concurrent_set.$(OBJEXT): {$(VPATH)}id_table.h +concurrent_set.$(OBJEXT): {$(VPATH)}intern.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/abi.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/anyargs.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/assume.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/attr/const.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/attr/error.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/attr/format.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/attr/packed_struct.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/cast.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/config.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/constant_p.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/core.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/core/robject.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/ctype.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/dllexport.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/dosish.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/encoding/re.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/encoding/string.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/error.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/eval.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/event.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/fl_type.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/gc.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/glob.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/globals.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/has/extension.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/has/feature.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/has/warning.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/intern/array.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/intern/class.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/intern/error.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/intern/file.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/intern/io.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/intern/load.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/intern/object.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/intern/process.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/intern/random.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/intern/range.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/intern/re.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/intern/select.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/intern/set.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/intern/signal.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/intern/string.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/intern/time.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/interpreter.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/iterator.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/memory.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/method.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/module.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/newobj.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/scan_args.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/special_consts.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/static_assert.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/stdalign.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/stdbool.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/stdckdint.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/symbol.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/value.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/value_type.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/variable.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/warning_push.h +concurrent_set.$(OBJEXT): {$(VPATH)}internal/xmalloc.h +concurrent_set.$(OBJEXT): {$(VPATH)}method.h +concurrent_set.$(OBJEXT): {$(VPATH)}missing.h +concurrent_set.$(OBJEXT): {$(VPATH)}node.h +concurrent_set.$(OBJEXT): {$(VPATH)}onigmo.h +concurrent_set.$(OBJEXT): {$(VPATH)}oniguruma.h +concurrent_set.$(OBJEXT): {$(VPATH)}ruby_assert.h +concurrent_set.$(OBJEXT): {$(VPATH)}ruby_atomic.h +concurrent_set.$(OBJEXT): {$(VPATH)}rubyparser.h +concurrent_set.$(OBJEXT): {$(VPATH)}st.h +concurrent_set.$(OBJEXT): {$(VPATH)}subst.h +concurrent_set.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h +concurrent_set.$(OBJEXT): {$(VPATH)}thread_native.h +concurrent_set.$(OBJEXT): {$(VPATH)}vm_core.h +concurrent_set.$(OBJEXT): {$(VPATH)}vm_debug.h +concurrent_set.$(OBJEXT): {$(VPATH)}vm_opts.h +concurrent_set.$(OBJEXT): {$(VPATH)}vm_sync.h cont.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h cont.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h cont.$(OBJEXT): $(CCAN_DIR)/list/list.h cont.$(OBJEXT): $(CCAN_DIR)/str/str.h cont.$(OBJEXT): $(hdrdir)/ruby.h cont.$(OBJEXT): $(hdrdir)/ruby/ruby.h +cont.$(OBJEXT): $(hdrdir)/ruby/version.h cont.$(OBJEXT): $(top_srcdir)/internal/array.h cont.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h cont.$(OBJEXT): $(top_srcdir)/internal/compilers.h @@ -3622,15 +4094,37 @@ cont.$(OBJEXT): $(top_srcdir)/internal/cont.h cont.$(OBJEXT): $(top_srcdir)/internal/error.h cont.$(OBJEXT): $(top_srcdir)/internal/gc.h cont.$(OBJEXT): $(top_srcdir)/internal/imemo.h +cont.$(OBJEXT): $(top_srcdir)/internal/namespace.h cont.$(OBJEXT): $(top_srcdir)/internal/proc.h cont.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h cont.$(OBJEXT): $(top_srcdir)/internal/serial.h +cont.$(OBJEXT): $(top_srcdir)/internal/set_table.h cont.$(OBJEXT): $(top_srcdir)/internal/static_assert.h cont.$(OBJEXT): $(top_srcdir)/internal/string.h cont.$(OBJEXT): $(top_srcdir)/internal/thread.h cont.$(OBJEXT): $(top_srcdir)/internal/variable.h cont.$(OBJEXT): $(top_srcdir)/internal/vm.h cont.$(OBJEXT): $(top_srcdir)/internal/warnings.h +cont.$(OBJEXT): $(top_srcdir)/prism/defines.h +cont.$(OBJEXT): $(top_srcdir)/prism/encoding.h +cont.$(OBJEXT): $(top_srcdir)/prism/node.h +cont.$(OBJEXT): $(top_srcdir)/prism/options.h +cont.$(OBJEXT): $(top_srcdir)/prism/pack.h +cont.$(OBJEXT): $(top_srcdir)/prism/parser.h +cont.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h +cont.$(OBJEXT): $(top_srcdir)/prism/prism.h +cont.$(OBJEXT): $(top_srcdir)/prism/regexp.h +cont.$(OBJEXT): $(top_srcdir)/prism/static_literals.h +cont.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h +cont.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h +cont.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h +cont.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h +cont.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h +cont.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h +cont.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h +cont.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h +cont.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h +cont.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h cont.$(OBJEXT): {$(VPATH)}$(COROUTINE_H) cont.$(OBJEXT): {$(VPATH)}assert.h cont.$(OBJEXT): {$(VPATH)}atomic.h @@ -3778,6 +4272,7 @@ cont.$(OBJEXT): {$(VPATH)}internal/intern/re.h cont.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h cont.$(OBJEXT): {$(VPATH)}internal/intern/select.h cont.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +cont.$(OBJEXT): {$(VPATH)}internal/intern/set.h cont.$(OBJEXT): {$(VPATH)}internal/intern/signal.h cont.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h cont.$(OBJEXT): {$(VPATH)}internal/intern/string.h @@ -3797,6 +4292,7 @@ cont.$(OBJEXT): {$(VPATH)}internal/special_consts.h cont.$(OBJEXT): {$(VPATH)}internal/static_assert.h cont.$(OBJEXT): {$(VPATH)}internal/stdalign.h cont.$(OBJEXT): {$(VPATH)}internal/stdbool.h +cont.$(OBJEXT): {$(VPATH)}internal/stdckdint.h cont.$(OBJEXT): {$(VPATH)}internal/symbol.h cont.$(OBJEXT): {$(VPATH)}internal/value.h cont.$(OBJEXT): {$(VPATH)}internal/value_type.h @@ -3809,9 +4305,12 @@ cont.$(OBJEXT): {$(VPATH)}missing.h cont.$(OBJEXT): {$(VPATH)}node.h cont.$(OBJEXT): {$(VPATH)}onigmo.h cont.$(OBJEXT): {$(VPATH)}oniguruma.h +cont.$(OBJEXT): {$(VPATH)}prism/ast.h +cont.$(OBJEXT): {$(VPATH)}prism/diagnostic.h +cont.$(OBJEXT): {$(VPATH)}prism/version.h +cont.$(OBJEXT): {$(VPATH)}prism_compile.h cont.$(OBJEXT): {$(VPATH)}ractor.h cont.$(OBJEXT): {$(VPATH)}ractor_core.h -cont.$(OBJEXT): {$(VPATH)}rjit.h cont.$(OBJEXT): {$(VPATH)}ruby_assert.h cont.$(OBJEXT): {$(VPATH)}ruby_atomic.h cont.$(OBJEXT): {$(VPATH)}rubyparser.h @@ -3836,7 +4335,10 @@ debug.$(OBJEXT): $(top_srcdir)/internal/class.h debug.$(OBJEXT): $(top_srcdir)/internal/compilers.h debug.$(OBJEXT): $(top_srcdir)/internal/gc.h debug.$(OBJEXT): $(top_srcdir)/internal/imemo.h +debug.$(OBJEXT): $(top_srcdir)/internal/namespace.h +debug.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h debug.$(OBJEXT): $(top_srcdir)/internal/serial.h +debug.$(OBJEXT): $(top_srcdir)/internal/set_table.h debug.$(OBJEXT): $(top_srcdir)/internal/signal.h debug.$(OBJEXT): $(top_srcdir)/internal/static_assert.h debug.$(OBJEXT): $(top_srcdir)/internal/variable.h @@ -3988,6 +4490,7 @@ debug.$(OBJEXT): {$(VPATH)}internal/intern/re.h debug.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h debug.$(OBJEXT): {$(VPATH)}internal/intern/select.h debug.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +debug.$(OBJEXT): {$(VPATH)}internal/intern/set.h debug.$(OBJEXT): {$(VPATH)}internal/intern/signal.h debug.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h debug.$(OBJEXT): {$(VPATH)}internal/intern/string.h @@ -4007,6 +4510,7 @@ debug.$(OBJEXT): {$(VPATH)}internal/special_consts.h debug.$(OBJEXT): {$(VPATH)}internal/static_assert.h debug.$(OBJEXT): {$(VPATH)}internal/stdalign.h debug.$(OBJEXT): {$(VPATH)}internal/stdbool.h +debug.$(OBJEXT): {$(VPATH)}internal/stdckdint.h debug.$(OBJEXT): {$(VPATH)}internal/symbol.h debug.$(OBJEXT): {$(VPATH)}internal/value.h debug.$(OBJEXT): {$(VPATH)}internal/value_type.h @@ -4035,6 +4539,7 @@ debug.$(OBJEXT): {$(VPATH)}vm_callinfo.h debug.$(OBJEXT): {$(VPATH)}vm_core.h debug.$(OBJEXT): {$(VPATH)}vm_debug.h debug.$(OBJEXT): {$(VPATH)}vm_opts.h +debug.$(OBJEXT): {$(VPATH)}vm_sync.h debug_counter.$(OBJEXT): $(hdrdir)/ruby/ruby.h debug_counter.$(OBJEXT): {$(VPATH)}assert.h debug_counter.$(OBJEXT): {$(VPATH)}backward/2/assume.h @@ -4165,6 +4670,7 @@ debug_counter.$(OBJEXT): {$(VPATH)}internal/intern/re.h debug_counter.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h debug_counter.$(OBJEXT): {$(VPATH)}internal/intern/select.h debug_counter.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/intern/set.h debug_counter.$(OBJEXT): {$(VPATH)}internal/intern/signal.h debug_counter.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h debug_counter.$(OBJEXT): {$(VPATH)}internal/intern/string.h @@ -4184,6 +4690,7 @@ debug_counter.$(OBJEXT): {$(VPATH)}internal/special_consts.h debug_counter.$(OBJEXT): {$(VPATH)}internal/static_assert.h debug_counter.$(OBJEXT): {$(VPATH)}internal/stdalign.h debug_counter.$(OBJEXT): {$(VPATH)}internal/stdbool.h +debug_counter.$(OBJEXT): {$(VPATH)}internal/stdckdint.h debug_counter.$(OBJEXT): {$(VPATH)}internal/symbol.h debug_counter.$(OBJEXT): {$(VPATH)}internal/value.h debug_counter.$(OBJEXT): {$(VPATH)}internal/value_type.h @@ -4199,6 +4706,7 @@ dir.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h dir.$(OBJEXT): $(CCAN_DIR)/list/list.h dir.$(OBJEXT): $(CCAN_DIR)/str/str.h dir.$(OBJEXT): $(hdrdir)/ruby/ruby.h +dir.$(OBJEXT): $(hdrdir)/ruby/version.h dir.$(OBJEXT): $(top_srcdir)/internal/array.h dir.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h dir.$(OBJEXT): $(top_srcdir)/internal/class.h @@ -4210,8 +4718,11 @@ dir.$(OBJEXT): $(top_srcdir)/internal/file.h dir.$(OBJEXT): $(top_srcdir)/internal/gc.h dir.$(OBJEXT): $(top_srcdir)/internal/imemo.h dir.$(OBJEXT): $(top_srcdir)/internal/io.h +dir.$(OBJEXT): $(top_srcdir)/internal/namespace.h dir.$(OBJEXT): $(top_srcdir)/internal/object.h +dir.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h dir.$(OBJEXT): $(top_srcdir)/internal/serial.h +dir.$(OBJEXT): $(top_srcdir)/internal/set_table.h dir.$(OBJEXT): $(top_srcdir)/internal/static_assert.h dir.$(OBJEXT): $(top_srcdir)/internal/string.h dir.$(OBJEXT): $(top_srcdir)/internal/variable.h @@ -4363,6 +4874,7 @@ dir.$(OBJEXT): {$(VPATH)}internal/intern/re.h dir.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h dir.$(OBJEXT): {$(VPATH)}internal/intern/select.h dir.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +dir.$(OBJEXT): {$(VPATH)}internal/intern/set.h dir.$(OBJEXT): {$(VPATH)}internal/intern/signal.h dir.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h dir.$(OBJEXT): {$(VPATH)}internal/intern/string.h @@ -4382,6 +4894,7 @@ dir.$(OBJEXT): {$(VPATH)}internal/special_consts.h dir.$(OBJEXT): {$(VPATH)}internal/static_assert.h dir.$(OBJEXT): {$(VPATH)}internal/stdalign.h dir.$(OBJEXT): {$(VPATH)}internal/stdbool.h +dir.$(OBJEXT): {$(VPATH)}internal/stdckdint.h dir.$(OBJEXT): {$(VPATH)}internal/symbol.h dir.$(OBJEXT): {$(VPATH)}internal/value.h dir.$(OBJEXT): {$(VPATH)}internal/value_type.h @@ -4408,6 +4921,7 @@ dir.$(OBJEXT): {$(VPATH)}vm_core.h dir.$(OBJEXT): {$(VPATH)}vm_opts.h dln.$(OBJEXT): $(hdrdir)/ruby/ruby.h dln.$(OBJEXT): $(top_srcdir)/internal/compilers.h +dln.$(OBJEXT): $(top_srcdir)/internal/namespace.h dln.$(OBJEXT): $(top_srcdir)/internal/warnings.h dln.$(OBJEXT): {$(VPATH)}assert.h dln.$(OBJEXT): {$(VPATH)}backward/2/assume.h @@ -4539,6 +5053,7 @@ dln.$(OBJEXT): {$(VPATH)}internal/intern/re.h dln.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h dln.$(OBJEXT): {$(VPATH)}internal/intern/select.h dln.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +dln.$(OBJEXT): {$(VPATH)}internal/intern/set.h dln.$(OBJEXT): {$(VPATH)}internal/intern/signal.h dln.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h dln.$(OBJEXT): {$(VPATH)}internal/intern/string.h @@ -4558,6 +5073,7 @@ dln.$(OBJEXT): {$(VPATH)}internal/special_consts.h dln.$(OBJEXT): {$(VPATH)}internal/static_assert.h dln.$(OBJEXT): {$(VPATH)}internal/stdalign.h dln.$(OBJEXT): {$(VPATH)}internal/stdbool.h +dln.$(OBJEXT): {$(VPATH)}internal/stdckdint.h dln.$(OBJEXT): {$(VPATH)}internal/symbol.h dln.$(OBJEXT): {$(VPATH)}internal/value.h dln.$(OBJEXT): {$(VPATH)}internal/value_type.h @@ -4696,6 +5212,7 @@ dln_find.$(OBJEXT): {$(VPATH)}internal/intern/re.h dln_find.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h dln_find.$(OBJEXT): {$(VPATH)}internal/intern/select.h dln_find.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +dln_find.$(OBJEXT): {$(VPATH)}internal/intern/set.h dln_find.$(OBJEXT): {$(VPATH)}internal/intern/signal.h dln_find.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h dln_find.$(OBJEXT): {$(VPATH)}internal/intern/string.h @@ -4715,6 +5232,7 @@ dln_find.$(OBJEXT): {$(VPATH)}internal/special_consts.h dln_find.$(OBJEXT): {$(VPATH)}internal/static_assert.h dln_find.$(OBJEXT): {$(VPATH)}internal/stdalign.h dln_find.$(OBJEXT): {$(VPATH)}internal/stdbool.h +dln_find.$(OBJEXT): {$(VPATH)}internal/stdckdint.h dln_find.$(OBJEXT): {$(VPATH)}internal/symbol.h dln_find.$(OBJEXT): {$(VPATH)}internal/value.h dln_find.$(OBJEXT): {$(VPATH)}internal/value_type.h @@ -4852,6 +5370,7 @@ dmydln.$(OBJEXT): {$(VPATH)}internal/intern/re.h dmydln.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h dmydln.$(OBJEXT): {$(VPATH)}internal/intern/select.h dmydln.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +dmydln.$(OBJEXT): {$(VPATH)}internal/intern/set.h dmydln.$(OBJEXT): {$(VPATH)}internal/intern/signal.h dmydln.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h dmydln.$(OBJEXT): {$(VPATH)}internal/intern/string.h @@ -4871,6 +5390,7 @@ dmydln.$(OBJEXT): {$(VPATH)}internal/special_consts.h dmydln.$(OBJEXT): {$(VPATH)}internal/static_assert.h dmydln.$(OBJEXT): {$(VPATH)}internal/stdalign.h dmydln.$(OBJEXT): {$(VPATH)}internal/stdbool.h +dmydln.$(OBJEXT): {$(VPATH)}internal/stdckdint.h dmydln.$(OBJEXT): {$(VPATH)}internal/symbol.h dmydln.$(OBJEXT): {$(VPATH)}internal/value.h dmydln.$(OBJEXT): {$(VPATH)}internal/value_type.h @@ -5700,24 +6220,34 @@ enc/utf_8.$(OBJEXT): {$(VPATH)}oniguruma.h enc/utf_8.$(OBJEXT): {$(VPATH)}regenc.h enc/utf_8.$(OBJEXT): {$(VPATH)}st.h enc/utf_8.$(OBJEXT): {$(VPATH)}subst.h +encoding.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h +encoding.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h +encoding.$(OBJEXT): $(CCAN_DIR)/list/list.h +encoding.$(OBJEXT): $(CCAN_DIR)/str/str.h encoding.$(OBJEXT): $(hdrdir)/ruby.h encoding.$(OBJEXT): $(hdrdir)/ruby/ruby.h +encoding.$(OBJEXT): $(hdrdir)/ruby/version.h +encoding.$(OBJEXT): $(top_srcdir)/internal/array.h +encoding.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h encoding.$(OBJEXT): $(top_srcdir)/internal/class.h encoding.$(OBJEXT): $(top_srcdir)/internal/compilers.h encoding.$(OBJEXT): $(top_srcdir)/internal/enc.h encoding.$(OBJEXT): $(top_srcdir)/internal/encoding.h encoding.$(OBJEXT): $(top_srcdir)/internal/error.h encoding.$(OBJEXT): $(top_srcdir)/internal/gc.h +encoding.$(OBJEXT): $(top_srcdir)/internal/imemo.h encoding.$(OBJEXT): $(top_srcdir)/internal/inits.h encoding.$(OBJEXT): $(top_srcdir)/internal/load.h encoding.$(OBJEXT): $(top_srcdir)/internal/object.h encoding.$(OBJEXT): $(top_srcdir)/internal/serial.h +encoding.$(OBJEXT): $(top_srcdir)/internal/set_table.h encoding.$(OBJEXT): $(top_srcdir)/internal/static_assert.h encoding.$(OBJEXT): $(top_srcdir)/internal/string.h encoding.$(OBJEXT): $(top_srcdir)/internal/variable.h encoding.$(OBJEXT): $(top_srcdir)/internal/vm.h encoding.$(OBJEXT): $(top_srcdir)/internal/warnings.h encoding.$(OBJEXT): {$(VPATH)}assert.h +encoding.$(OBJEXT): {$(VPATH)}atomic.h encoding.$(OBJEXT): {$(VPATH)}backward/2/assume.h encoding.$(OBJEXT): {$(VPATH)}backward/2/attributes.h encoding.$(OBJEXT): {$(VPATH)}backward/2/bool.h @@ -5734,6 +6264,7 @@ encoding.$(OBJEXT): {$(VPATH)}defines.h encoding.$(OBJEXT): {$(VPATH)}encindex.h encoding.$(OBJEXT): {$(VPATH)}encoding.c encoding.$(OBJEXT): {$(VPATH)}encoding.h +encoding.$(OBJEXT): {$(VPATH)}id.h encoding.$(OBJEXT): {$(VPATH)}id_table.h encoding.$(OBJEXT): {$(VPATH)}intern.h encoding.$(OBJEXT): {$(VPATH)}internal.h @@ -5860,6 +6391,7 @@ encoding.$(OBJEXT): {$(VPATH)}internal/intern/re.h encoding.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h encoding.$(OBJEXT): {$(VPATH)}internal/intern/select.h encoding.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +encoding.$(OBJEXT): {$(VPATH)}internal/intern/set.h encoding.$(OBJEXT): {$(VPATH)}internal/intern/signal.h encoding.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h encoding.$(OBJEXT): {$(VPATH)}internal/intern/string.h @@ -5879,22 +6411,31 @@ encoding.$(OBJEXT): {$(VPATH)}internal/special_consts.h encoding.$(OBJEXT): {$(VPATH)}internal/static_assert.h encoding.$(OBJEXT): {$(VPATH)}internal/stdalign.h encoding.$(OBJEXT): {$(VPATH)}internal/stdbool.h +encoding.$(OBJEXT): {$(VPATH)}internal/stdckdint.h encoding.$(OBJEXT): {$(VPATH)}internal/symbol.h encoding.$(OBJEXT): {$(VPATH)}internal/value.h encoding.$(OBJEXT): {$(VPATH)}internal/value_type.h encoding.$(OBJEXT): {$(VPATH)}internal/variable.h encoding.$(OBJEXT): {$(VPATH)}internal/warning_push.h encoding.$(OBJEXT): {$(VPATH)}internal/xmalloc.h +encoding.$(OBJEXT): {$(VPATH)}method.h encoding.$(OBJEXT): {$(VPATH)}missing.h +encoding.$(OBJEXT): {$(VPATH)}node.h encoding.$(OBJEXT): {$(VPATH)}onigmo.h encoding.$(OBJEXT): {$(VPATH)}oniguruma.h encoding.$(OBJEXT): {$(VPATH)}regenc.h encoding.$(OBJEXT): {$(VPATH)}ruby_assert.h +encoding.$(OBJEXT): {$(VPATH)}ruby_atomic.h +encoding.$(OBJEXT): {$(VPATH)}rubyparser.h encoding.$(OBJEXT): {$(VPATH)}shape.h encoding.$(OBJEXT): {$(VPATH)}st.h encoding.$(OBJEXT): {$(VPATH)}subst.h +encoding.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h +encoding.$(OBJEXT): {$(VPATH)}thread_native.h encoding.$(OBJEXT): {$(VPATH)}util.h +encoding.$(OBJEXT): {$(VPATH)}vm_core.h encoding.$(OBJEXT): {$(VPATH)}vm_debug.h +encoding.$(OBJEXT): {$(VPATH)}vm_opts.h encoding.$(OBJEXT): {$(VPATH)}vm_sync.h enum.$(OBJEXT): $(hdrdir)/ruby/ruby.h enum.$(OBJEXT): $(top_srcdir)/internal/array.h @@ -5915,6 +6456,7 @@ enum.$(OBJEXT): $(top_srcdir)/internal/proc.h enum.$(OBJEXT): $(top_srcdir)/internal/rational.h enum.$(OBJEXT): $(top_srcdir)/internal/re.h enum.$(OBJEXT): $(top_srcdir)/internal/serial.h +enum.$(OBJEXT): $(top_srcdir)/internal/set_table.h enum.$(OBJEXT): $(top_srcdir)/internal/static_assert.h enum.$(OBJEXT): $(top_srcdir)/internal/variable.h enum.$(OBJEXT): $(top_srcdir)/internal/vm.h @@ -6061,6 +6603,7 @@ enum.$(OBJEXT): {$(VPATH)}internal/intern/re.h enum.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h enum.$(OBJEXT): {$(VPATH)}internal/intern/select.h enum.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +enum.$(OBJEXT): {$(VPATH)}internal/intern/set.h enum.$(OBJEXT): {$(VPATH)}internal/intern/signal.h enum.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h enum.$(OBJEXT): {$(VPATH)}internal/intern/string.h @@ -6080,6 +6623,7 @@ enum.$(OBJEXT): {$(VPATH)}internal/special_consts.h enum.$(OBJEXT): {$(VPATH)}internal/static_assert.h enum.$(OBJEXT): {$(VPATH)}internal/stdalign.h enum.$(OBJEXT): {$(VPATH)}internal/stdbool.h +enum.$(OBJEXT): {$(VPATH)}internal/stdckdint.h enum.$(OBJEXT): {$(VPATH)}internal/symbol.h enum.$(OBJEXT): {$(VPATH)}internal/value.h enum.$(OBJEXT): {$(VPATH)}internal/value_type.h @@ -6100,6 +6644,7 @@ enumerator.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h enumerator.$(OBJEXT): $(CCAN_DIR)/list/list.h enumerator.$(OBJEXT): $(CCAN_DIR)/str/str.h enumerator.$(OBJEXT): $(hdrdir)/ruby/ruby.h +enumerator.$(OBJEXT): $(hdrdir)/ruby/version.h enumerator.$(OBJEXT): $(top_srcdir)/internal/array.h enumerator.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h enumerator.$(OBJEXT): $(top_srcdir)/internal/bignum.h @@ -6112,10 +6657,13 @@ enumerator.$(OBJEXT): $(top_srcdir)/internal/fixnum.h enumerator.$(OBJEXT): $(top_srcdir)/internal/gc.h enumerator.$(OBJEXT): $(top_srcdir)/internal/hash.h enumerator.$(OBJEXT): $(top_srcdir)/internal/imemo.h +enumerator.$(OBJEXT): $(top_srcdir)/internal/namespace.h enumerator.$(OBJEXT): $(top_srcdir)/internal/numeric.h enumerator.$(OBJEXT): $(top_srcdir)/internal/range.h enumerator.$(OBJEXT): $(top_srcdir)/internal/rational.h +enumerator.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h enumerator.$(OBJEXT): $(top_srcdir)/internal/serial.h +enumerator.$(OBJEXT): $(top_srcdir)/internal/set_table.h enumerator.$(OBJEXT): $(top_srcdir)/internal/static_assert.h enumerator.$(OBJEXT): $(top_srcdir)/internal/string.h enumerator.$(OBJEXT): $(top_srcdir)/internal/struct.h @@ -6135,6 +6683,7 @@ enumerator.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h enumerator.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h enumerator.$(OBJEXT): {$(VPATH)}config.h enumerator.$(OBJEXT): {$(VPATH)}constant.h +enumerator.$(OBJEXT): {$(VPATH)}debug_counter.h enumerator.$(OBJEXT): {$(VPATH)}defines.h enumerator.$(OBJEXT): {$(VPATH)}encoding.h enumerator.$(OBJEXT): {$(VPATH)}enumerator.c @@ -6265,6 +6814,7 @@ enumerator.$(OBJEXT): {$(VPATH)}internal/intern/re.h enumerator.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h enumerator.$(OBJEXT): {$(VPATH)}internal/intern/select.h enumerator.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +enumerator.$(OBJEXT): {$(VPATH)}internal/intern/set.h enumerator.$(OBJEXT): {$(VPATH)}internal/intern/signal.h enumerator.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h enumerator.$(OBJEXT): {$(VPATH)}internal/intern/string.h @@ -6284,6 +6834,7 @@ enumerator.$(OBJEXT): {$(VPATH)}internal/special_consts.h enumerator.$(OBJEXT): {$(VPATH)}internal/static_assert.h enumerator.$(OBJEXT): {$(VPATH)}internal/stdalign.h enumerator.$(OBJEXT): {$(VPATH)}internal/stdbool.h +enumerator.$(OBJEXT): {$(VPATH)}internal/stdckdint.h enumerator.$(OBJEXT): {$(VPATH)}internal/symbol.h enumerator.$(OBJEXT): {$(VPATH)}internal/value.h enumerator.$(OBJEXT): {$(VPATH)}internal/value_type.h @@ -6304,12 +6855,15 @@ enumerator.$(OBJEXT): {$(VPATH)}subst.h enumerator.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h enumerator.$(OBJEXT): {$(VPATH)}thread_native.h enumerator.$(OBJEXT): {$(VPATH)}vm_core.h +enumerator.$(OBJEXT): {$(VPATH)}vm_debug.h enumerator.$(OBJEXT): {$(VPATH)}vm_opts.h +enumerator.$(OBJEXT): {$(VPATH)}vm_sync.h error.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h error.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h error.$(OBJEXT): $(CCAN_DIR)/list/list.h error.$(OBJEXT): $(CCAN_DIR)/str/str.h error.$(OBJEXT): $(hdrdir)/ruby/ruby.h +error.$(OBJEXT): $(hdrdir)/ruby/version.h error.$(OBJEXT): $(top_srcdir)/internal/array.h error.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h error.$(OBJEXT): $(top_srcdir)/internal/class.h @@ -6321,8 +6875,12 @@ error.$(OBJEXT): $(top_srcdir)/internal/hash.h error.$(OBJEXT): $(top_srcdir)/internal/imemo.h error.$(OBJEXT): $(top_srcdir)/internal/io.h error.$(OBJEXT): $(top_srcdir)/internal/load.h +error.$(OBJEXT): $(top_srcdir)/internal/namespace.h error.$(OBJEXT): $(top_srcdir)/internal/object.h +error.$(OBJEXT): $(top_srcdir)/internal/process.h +error.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h error.$(OBJEXT): $(top_srcdir)/internal/serial.h +error.$(OBJEXT): $(top_srcdir)/internal/set_table.h error.$(OBJEXT): $(top_srcdir)/internal/static_assert.h error.$(OBJEXT): $(top_srcdir)/internal/string.h error.$(OBJEXT): $(top_srcdir)/internal/symbol.h @@ -6344,6 +6902,7 @@ error.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h error.$(OBJEXT): {$(VPATH)}builtin.h error.$(OBJEXT): {$(VPATH)}config.h error.$(OBJEXT): {$(VPATH)}constant.h +error.$(OBJEXT): {$(VPATH)}debug_counter.h error.$(OBJEXT): {$(VPATH)}defines.h error.$(OBJEXT): {$(VPATH)}encoding.h error.$(OBJEXT): {$(VPATH)}error.c @@ -6474,6 +7033,7 @@ error.$(OBJEXT): {$(VPATH)}internal/intern/re.h error.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h error.$(OBJEXT): {$(VPATH)}internal/intern/select.h error.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +error.$(OBJEXT): {$(VPATH)}internal/intern/set.h error.$(OBJEXT): {$(VPATH)}internal/intern/signal.h error.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h error.$(OBJEXT): {$(VPATH)}internal/intern/string.h @@ -6493,6 +7053,7 @@ error.$(OBJEXT): {$(VPATH)}internal/special_consts.h error.$(OBJEXT): {$(VPATH)}internal/static_assert.h error.$(OBJEXT): {$(VPATH)}internal/stdalign.h error.$(OBJEXT): {$(VPATH)}internal/stdbool.h +error.$(OBJEXT): {$(VPATH)}internal/stdckdint.h error.$(OBJEXT): {$(VPATH)}internal/symbol.h error.$(OBJEXT): {$(VPATH)}internal/value.h error.$(OBJEXT): {$(VPATH)}internal/value_type.h @@ -6514,15 +7075,20 @@ error.$(OBJEXT): {$(VPATH)}st.h error.$(OBJEXT): {$(VPATH)}subst.h error.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h error.$(OBJEXT): {$(VPATH)}thread_native.h +error.$(OBJEXT): {$(VPATH)}util.h error.$(OBJEXT): {$(VPATH)}vm_core.h +error.$(OBJEXT): {$(VPATH)}vm_debug.h error.$(OBJEXT): {$(VPATH)}vm_opts.h +error.$(OBJEXT): {$(VPATH)}vm_sync.h error.$(OBJEXT): {$(VPATH)}warning.rbinc +error.$(OBJEXT): {$(VPATH)}yjit.h eval.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h eval.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h eval.$(OBJEXT): $(CCAN_DIR)/list/list.h eval.$(OBJEXT): $(CCAN_DIR)/str/str.h eval.$(OBJEXT): $(hdrdir)/ruby.h eval.$(OBJEXT): $(hdrdir)/ruby/ruby.h +eval.$(OBJEXT): $(hdrdir)/ruby/version.h eval.$(OBJEXT): $(top_srcdir)/internal/array.h eval.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h eval.$(OBJEXT): $(top_srcdir)/internal/class.h @@ -6535,14 +7101,37 @@ eval.$(OBJEXT): $(top_srcdir)/internal/hash.h eval.$(OBJEXT): $(top_srcdir)/internal/imemo.h eval.$(OBJEXT): $(top_srcdir)/internal/inits.h eval.$(OBJEXT): $(top_srcdir)/internal/io.h +eval.$(OBJEXT): $(top_srcdir)/internal/namespace.h eval.$(OBJEXT): $(top_srcdir)/internal/object.h +eval.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h eval.$(OBJEXT): $(top_srcdir)/internal/serial.h +eval.$(OBJEXT): $(top_srcdir)/internal/set_table.h eval.$(OBJEXT): $(top_srcdir)/internal/static_assert.h eval.$(OBJEXT): $(top_srcdir)/internal/string.h eval.$(OBJEXT): $(top_srcdir)/internal/thread.h eval.$(OBJEXT): $(top_srcdir)/internal/variable.h eval.$(OBJEXT): $(top_srcdir)/internal/vm.h eval.$(OBJEXT): $(top_srcdir)/internal/warnings.h +eval.$(OBJEXT): $(top_srcdir)/prism/defines.h +eval.$(OBJEXT): $(top_srcdir)/prism/encoding.h +eval.$(OBJEXT): $(top_srcdir)/prism/node.h +eval.$(OBJEXT): $(top_srcdir)/prism/options.h +eval.$(OBJEXT): $(top_srcdir)/prism/pack.h +eval.$(OBJEXT): $(top_srcdir)/prism/parser.h +eval.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h +eval.$(OBJEXT): $(top_srcdir)/prism/prism.h +eval.$(OBJEXT): $(top_srcdir)/prism/regexp.h +eval.$(OBJEXT): $(top_srcdir)/prism/static_literals.h +eval.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h +eval.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h +eval.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h +eval.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h +eval.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h +eval.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h +eval.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h +eval.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h +eval.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h +eval.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h eval.$(OBJEXT): {$(VPATH)}assert.h eval.$(OBJEXT): {$(VPATH)}atomic.h eval.$(OBJEXT): {$(VPATH)}backward/2/assume.h @@ -6691,6 +7280,7 @@ eval.$(OBJEXT): {$(VPATH)}internal/intern/re.h eval.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h eval.$(OBJEXT): {$(VPATH)}internal/intern/select.h eval.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +eval.$(OBJEXT): {$(VPATH)}internal/intern/set.h eval.$(OBJEXT): {$(VPATH)}internal/intern/signal.h eval.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h eval.$(OBJEXT): {$(VPATH)}internal/intern/string.h @@ -6710,6 +7300,7 @@ eval.$(OBJEXT): {$(VPATH)}internal/special_consts.h eval.$(OBJEXT): {$(VPATH)}internal/static_assert.h eval.$(OBJEXT): {$(VPATH)}internal/stdalign.h eval.$(OBJEXT): {$(VPATH)}internal/stdbool.h +eval.$(OBJEXT): {$(VPATH)}internal/stdckdint.h eval.$(OBJEXT): {$(VPATH)}internal/symbol.h eval.$(OBJEXT): {$(VPATH)}internal/value.h eval.$(OBJEXT): {$(VPATH)}internal/value_type.h @@ -6723,12 +7314,15 @@ eval.$(OBJEXT): {$(VPATH)}missing.h eval.$(OBJEXT): {$(VPATH)}node.h eval.$(OBJEXT): {$(VPATH)}onigmo.h eval.$(OBJEXT): {$(VPATH)}oniguruma.h +eval.$(OBJEXT): {$(VPATH)}prism/ast.h +eval.$(OBJEXT): {$(VPATH)}prism/diagnostic.h +eval.$(OBJEXT): {$(VPATH)}prism/version.h +eval.$(OBJEXT): {$(VPATH)}prism_compile.h eval.$(OBJEXT): {$(VPATH)}probes.dmyh eval.$(OBJEXT): {$(VPATH)}probes.h eval.$(OBJEXT): {$(VPATH)}probes_helper.h eval.$(OBJEXT): {$(VPATH)}ractor.h eval.$(OBJEXT): {$(VPATH)}ractor_core.h -eval.$(OBJEXT): {$(VPATH)}rjit.h eval.$(OBJEXT): {$(VPATH)}ruby_assert.h eval.$(OBJEXT): {$(VPATH)}ruby_atomic.h eval.$(OBJEXT): {$(VPATH)}rubyparser.h @@ -6741,6 +7335,7 @@ eval.$(OBJEXT): {$(VPATH)}vm.h eval.$(OBJEXT): {$(VPATH)}vm_core.h eval.$(OBJEXT): {$(VPATH)}vm_debug.h eval.$(OBJEXT): {$(VPATH)}vm_opts.h +eval.$(OBJEXT): {$(VPATH)}vm_sync.h explicit_bzero.$(OBJEXT): {$(VPATH)}config.h explicit_bzero.$(OBJEXT): {$(VPATH)}explicit_bzero.c explicit_bzero.$(OBJEXT): {$(VPATH)}internal/attr/format.h @@ -6761,6 +7356,7 @@ file.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h file.$(OBJEXT): $(CCAN_DIR)/list/list.h file.$(OBJEXT): $(CCAN_DIR)/str/str.h file.$(OBJEXT): $(hdrdir)/ruby/ruby.h +file.$(OBJEXT): $(hdrdir)/ruby/version.h file.$(OBJEXT): $(top_srcdir)/internal/array.h file.$(OBJEXT): $(top_srcdir)/internal/class.h file.$(OBJEXT): $(top_srcdir)/internal/compilers.h @@ -6924,6 +7520,7 @@ file.$(OBJEXT): {$(VPATH)}internal/intern/re.h file.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h file.$(OBJEXT): {$(VPATH)}internal/intern/select.h file.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +file.$(OBJEXT): {$(VPATH)}internal/intern/set.h file.$(OBJEXT): {$(VPATH)}internal/intern/signal.h file.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h file.$(OBJEXT): {$(VPATH)}internal/intern/string.h @@ -6943,6 +7540,7 @@ file.$(OBJEXT): {$(VPATH)}internal/special_consts.h file.$(OBJEXT): {$(VPATH)}internal/static_assert.h file.$(OBJEXT): {$(VPATH)}internal/stdalign.h file.$(OBJEXT): {$(VPATH)}internal/stdbool.h +file.$(OBJEXT): {$(VPATH)}internal/stdckdint.h file.$(OBJEXT): {$(VPATH)}internal/symbol.h file.$(OBJEXT): {$(VPATH)}internal/value.h file.$(OBJEXT): {$(VPATH)}internal/value_type.h @@ -6965,6 +7563,10 @@ gc.$(OBJEXT): $(CCAN_DIR)/list/list.h gc.$(OBJEXT): $(CCAN_DIR)/str/str.h gc.$(OBJEXT): $(hdrdir)/ruby.h gc.$(OBJEXT): $(hdrdir)/ruby/ruby.h +gc.$(OBJEXT): $(hdrdir)/ruby/version.h +gc.$(OBJEXT): $(top_srcdir)/gc/default/default.c +gc.$(OBJEXT): $(top_srcdir)/gc/gc.h +gc.$(OBJEXT): $(top_srcdir)/gc/gc_impl.h gc.$(OBJEXT): $(top_srcdir)/internal/array.h gc.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h gc.$(OBJEXT): $(top_srcdir)/internal/bignum.h @@ -6981,12 +7583,14 @@ gc.$(OBJEXT): $(top_srcdir)/internal/gc.h gc.$(OBJEXT): $(top_srcdir)/internal/hash.h gc.$(OBJEXT): $(top_srcdir)/internal/imemo.h gc.$(OBJEXT): $(top_srcdir)/internal/io.h +gc.$(OBJEXT): $(top_srcdir)/internal/namespace.h gc.$(OBJEXT): $(top_srcdir)/internal/numeric.h gc.$(OBJEXT): $(top_srcdir)/internal/object.h gc.$(OBJEXT): $(top_srcdir)/internal/proc.h gc.$(OBJEXT): $(top_srcdir)/internal/rational.h gc.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h gc.$(OBJEXT): $(top_srcdir)/internal/serial.h +gc.$(OBJEXT): $(top_srcdir)/internal/set_table.h gc.$(OBJEXT): $(top_srcdir)/internal/static_assert.h gc.$(OBJEXT): $(top_srcdir)/internal/string.h gc.$(OBJEXT): $(top_srcdir)/internal/struct.h @@ -6995,6 +7599,26 @@ gc.$(OBJEXT): $(top_srcdir)/internal/thread.h gc.$(OBJEXT): $(top_srcdir)/internal/variable.h gc.$(OBJEXT): $(top_srcdir)/internal/vm.h gc.$(OBJEXT): $(top_srcdir)/internal/warnings.h +gc.$(OBJEXT): $(top_srcdir)/prism/defines.h +gc.$(OBJEXT): $(top_srcdir)/prism/encoding.h +gc.$(OBJEXT): $(top_srcdir)/prism/node.h +gc.$(OBJEXT): $(top_srcdir)/prism/options.h +gc.$(OBJEXT): $(top_srcdir)/prism/pack.h +gc.$(OBJEXT): $(top_srcdir)/prism/parser.h +gc.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h +gc.$(OBJEXT): $(top_srcdir)/prism/prism.h +gc.$(OBJEXT): $(top_srcdir)/prism/regexp.h +gc.$(OBJEXT): $(top_srcdir)/prism/static_literals.h +gc.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h +gc.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h +gc.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h +gc.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h +gc.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h +gc.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h +gc.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h +gc.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h +gc.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h +gc.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h gc.$(OBJEXT): {$(VPATH)}assert.h gc.$(OBJEXT): {$(VPATH)}atomic.h gc.$(OBJEXT): {$(VPATH)}backward/2/assume.h @@ -7145,6 +7769,7 @@ gc.$(OBJEXT): {$(VPATH)}internal/intern/re.h gc.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h gc.$(OBJEXT): {$(VPATH)}internal/intern/select.h gc.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +gc.$(OBJEXT): {$(VPATH)}internal/intern/set.h gc.$(OBJEXT): {$(VPATH)}internal/intern/signal.h gc.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h gc.$(OBJEXT): {$(VPATH)}internal/intern/string.h @@ -7164,6 +7789,7 @@ gc.$(OBJEXT): {$(VPATH)}internal/special_consts.h gc.$(OBJEXT): {$(VPATH)}internal/static_assert.h gc.$(OBJEXT): {$(VPATH)}internal/stdalign.h gc.$(OBJEXT): {$(VPATH)}internal/stdbool.h +gc.$(OBJEXT): {$(VPATH)}internal/stdckdint.h gc.$(OBJEXT): {$(VPATH)}internal/symbol.h gc.$(OBJEXT): {$(VPATH)}internal/value.h gc.$(OBJEXT): {$(VPATH)}internal/value_type.h @@ -7177,6 +7803,10 @@ gc.$(OBJEXT): {$(VPATH)}missing.h gc.$(OBJEXT): {$(VPATH)}node.h gc.$(OBJEXT): {$(VPATH)}onigmo.h gc.$(OBJEXT): {$(VPATH)}oniguruma.h +gc.$(OBJEXT): {$(VPATH)}prism/ast.h +gc.$(OBJEXT): {$(VPATH)}prism/diagnostic.h +gc.$(OBJEXT): {$(VPATH)}prism/version.h +gc.$(OBJEXT): {$(VPATH)}prism_compile.h gc.$(OBJEXT): {$(VPATH)}probes.dmyh gc.$(OBJEXT): {$(VPATH)}probes.h gc.$(OBJEXT): {$(VPATH)}ractor.h @@ -7185,7 +7815,6 @@ gc.$(OBJEXT): {$(VPATH)}re.h gc.$(OBJEXT): {$(VPATH)}regenc.h gc.$(OBJEXT): {$(VPATH)}regex.h gc.$(OBJEXT): {$(VPATH)}regint.h -gc.$(OBJEXT): {$(VPATH)}rjit.h gc.$(OBJEXT): {$(VPATH)}ruby_assert.h gc.$(OBJEXT): {$(VPATH)}ruby_atomic.h gc.$(OBJEXT): {$(VPATH)}rubyparser.h @@ -7197,11 +7826,14 @@ gc.$(OBJEXT): {$(VPATH)}thread.h gc.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h gc.$(OBJEXT): {$(VPATH)}thread_native.h gc.$(OBJEXT): {$(VPATH)}util.h +gc.$(OBJEXT): {$(VPATH)}variable.h +gc.$(OBJEXT): {$(VPATH)}vm.h gc.$(OBJEXT): {$(VPATH)}vm_callinfo.h gc.$(OBJEXT): {$(VPATH)}vm_core.h gc.$(OBJEXT): {$(VPATH)}vm_debug.h gc.$(OBJEXT): {$(VPATH)}vm_opts.h gc.$(OBJEXT): {$(VPATH)}vm_sync.h +gc.$(OBJEXT): {$(VPATH)}yjit.h goruby.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h goruby.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h goruby.$(OBJEXT): $(CCAN_DIR)/list/list.h @@ -7210,15 +7842,45 @@ goruby.$(OBJEXT): $(hdrdir)/ruby.h goruby.$(OBJEXT): $(hdrdir)/ruby/ruby.h goruby.$(OBJEXT): $(top_srcdir)/internal/array.h goruby.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h +goruby.$(OBJEXT): $(top_srcdir)/internal/bignum.h +goruby.$(OBJEXT): $(top_srcdir)/internal/bits.h goruby.$(OBJEXT): $(top_srcdir)/internal/compilers.h +goruby.$(OBJEXT): $(top_srcdir)/internal/complex.h +goruby.$(OBJEXT): $(top_srcdir)/internal/fixnum.h goruby.$(OBJEXT): $(top_srcdir)/internal/gc.h goruby.$(OBJEXT): $(top_srcdir)/internal/imemo.h +goruby.$(OBJEXT): $(top_srcdir)/internal/namespace.h +goruby.$(OBJEXT): $(top_srcdir)/internal/numeric.h +goruby.$(OBJEXT): $(top_srcdir)/internal/parse.h +goruby.$(OBJEXT): $(top_srcdir)/internal/rational.h goruby.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h +goruby.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h goruby.$(OBJEXT): $(top_srcdir)/internal/serial.h +goruby.$(OBJEXT): $(top_srcdir)/internal/set_table.h goruby.$(OBJEXT): $(top_srcdir)/internal/static_assert.h goruby.$(OBJEXT): $(top_srcdir)/internal/variable.h goruby.$(OBJEXT): $(top_srcdir)/internal/vm.h goruby.$(OBJEXT): $(top_srcdir)/internal/warnings.h +goruby.$(OBJEXT): $(top_srcdir)/prism/defines.h +goruby.$(OBJEXT): $(top_srcdir)/prism/encoding.h +goruby.$(OBJEXT): $(top_srcdir)/prism/node.h +goruby.$(OBJEXT): $(top_srcdir)/prism/options.h +goruby.$(OBJEXT): $(top_srcdir)/prism/pack.h +goruby.$(OBJEXT): $(top_srcdir)/prism/parser.h +goruby.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h +goruby.$(OBJEXT): $(top_srcdir)/prism/prism.h +goruby.$(OBJEXT): $(top_srcdir)/prism/regexp.h +goruby.$(OBJEXT): $(top_srcdir)/prism/static_literals.h +goruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h +goruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h +goruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h +goruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h +goruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h +goruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h +goruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h +goruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h +goruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h +goruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h goruby.$(OBJEXT): {$(VPATH)}assert.h goruby.$(OBJEXT): {$(VPATH)}atomic.h goruby.$(OBJEXT): {$(VPATH)}backward.h @@ -7235,7 +7897,7 @@ goruby.$(OBJEXT): {$(VPATH)}config.h goruby.$(OBJEXT): {$(VPATH)}constant.h goruby.$(OBJEXT): {$(VPATH)}defines.h goruby.$(OBJEXT): {$(VPATH)}encoding.h -goruby.$(OBJEXT): {$(VPATH)}golf_prelude.c +goruby.$(OBJEXT): {$(VPATH)}golf_prelude.rbbin goruby.$(OBJEXT): {$(VPATH)}goruby.c goruby.$(OBJEXT): {$(VPATH)}id.h goruby.$(OBJEXT): {$(VPATH)}id_table.h @@ -7364,6 +8026,7 @@ goruby.$(OBJEXT): {$(VPATH)}internal/intern/re.h goruby.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h goruby.$(OBJEXT): {$(VPATH)}internal/intern/select.h goruby.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +goruby.$(OBJEXT): {$(VPATH)}internal/intern/set.h goruby.$(OBJEXT): {$(VPATH)}internal/intern/signal.h goruby.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h goruby.$(OBJEXT): {$(VPATH)}internal/intern/string.h @@ -7383,6 +8046,7 @@ goruby.$(OBJEXT): {$(VPATH)}internal/special_consts.h goruby.$(OBJEXT): {$(VPATH)}internal/static_assert.h goruby.$(OBJEXT): {$(VPATH)}internal/stdalign.h goruby.$(OBJEXT): {$(VPATH)}internal/stdbool.h +goruby.$(OBJEXT): {$(VPATH)}internal/stdckdint.h goruby.$(OBJEXT): {$(VPATH)}internal/symbol.h goruby.$(OBJEXT): {$(VPATH)}internal/value.h goruby.$(OBJEXT): {$(VPATH)}internal/value_type.h @@ -7396,6 +8060,10 @@ goruby.$(OBJEXT): {$(VPATH)}missing.h goruby.$(OBJEXT): {$(VPATH)}node.h goruby.$(OBJEXT): {$(VPATH)}onigmo.h goruby.$(OBJEXT): {$(VPATH)}oniguruma.h +goruby.$(OBJEXT): {$(VPATH)}prism/ast.h +goruby.$(OBJEXT): {$(VPATH)}prism/diagnostic.h +goruby.$(OBJEXT): {$(VPATH)}prism/version.h +goruby.$(OBJEXT): {$(VPATH)}prism_compile.h goruby.$(OBJEXT): {$(VPATH)}ruby_assert.h goruby.$(OBJEXT): {$(VPATH)}ruby_atomic.h goruby.$(OBJEXT): {$(VPATH)}rubyparser.h @@ -7412,6 +8080,7 @@ hash.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h hash.$(OBJEXT): $(CCAN_DIR)/list/list.h hash.$(OBJEXT): $(CCAN_DIR)/str/str.h hash.$(OBJEXT): $(hdrdir)/ruby/ruby.h +hash.$(OBJEXT): $(hdrdir)/ruby/version.h hash.$(OBJEXT): $(top_srcdir)/internal/array.h hash.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h hash.$(OBJEXT): $(top_srcdir)/internal/bignum.h @@ -7423,9 +8092,13 @@ hash.$(OBJEXT): $(top_srcdir)/internal/error.h hash.$(OBJEXT): $(top_srcdir)/internal/gc.h hash.$(OBJEXT): $(top_srcdir)/internal/hash.h hash.$(OBJEXT): $(top_srcdir)/internal/imemo.h +hash.$(OBJEXT): $(top_srcdir)/internal/namespace.h hash.$(OBJEXT): $(top_srcdir)/internal/object.h hash.$(OBJEXT): $(top_srcdir)/internal/proc.h +hash.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h hash.$(OBJEXT): $(top_srcdir)/internal/serial.h +hash.$(OBJEXT): $(top_srcdir)/internal/set_table.h +hash.$(OBJEXT): $(top_srcdir)/internal/st.h hash.$(OBJEXT): $(top_srcdir)/internal/static_assert.h hash.$(OBJEXT): $(top_srcdir)/internal/string.h hash.$(OBJEXT): $(top_srcdir)/internal/symbol.h @@ -7434,6 +8107,26 @@ hash.$(OBJEXT): $(top_srcdir)/internal/time.h hash.$(OBJEXT): $(top_srcdir)/internal/variable.h hash.$(OBJEXT): $(top_srcdir)/internal/vm.h hash.$(OBJEXT): $(top_srcdir)/internal/warnings.h +hash.$(OBJEXT): $(top_srcdir)/prism/defines.h +hash.$(OBJEXT): $(top_srcdir)/prism/encoding.h +hash.$(OBJEXT): $(top_srcdir)/prism/node.h +hash.$(OBJEXT): $(top_srcdir)/prism/options.h +hash.$(OBJEXT): $(top_srcdir)/prism/pack.h +hash.$(OBJEXT): $(top_srcdir)/prism/parser.h +hash.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h +hash.$(OBJEXT): $(top_srcdir)/prism/prism.h +hash.$(OBJEXT): $(top_srcdir)/prism/regexp.h +hash.$(OBJEXT): $(top_srcdir)/prism/static_literals.h +hash.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h +hash.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h +hash.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h +hash.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h +hash.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h +hash.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h +hash.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h +hash.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h +hash.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h +hash.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h hash.$(OBJEXT): {$(VPATH)}assert.h hash.$(OBJEXT): {$(VPATH)}atomic.h hash.$(OBJEXT): {$(VPATH)}backward/2/assume.h @@ -7445,12 +8138,14 @@ hash.$(OBJEXT): {$(VPATH)}backward/2/limits.h hash.$(OBJEXT): {$(VPATH)}backward/2/long_long.h hash.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h hash.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h +hash.$(OBJEXT): {$(VPATH)}builtin.h hash.$(OBJEXT): {$(VPATH)}config.h hash.$(OBJEXT): {$(VPATH)}constant.h hash.$(OBJEXT): {$(VPATH)}debug_counter.h hash.$(OBJEXT): {$(VPATH)}defines.h hash.$(OBJEXT): {$(VPATH)}encoding.h hash.$(OBJEXT): {$(VPATH)}hash.c +hash.$(OBJEXT): {$(VPATH)}hash.rbinc hash.$(OBJEXT): {$(VPATH)}id.h hash.$(OBJEXT): {$(VPATH)}id_table.h hash.$(OBJEXT): {$(VPATH)}intern.h @@ -7578,6 +8273,7 @@ hash.$(OBJEXT): {$(VPATH)}internal/intern/re.h hash.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h hash.$(OBJEXT): {$(VPATH)}internal/intern/select.h hash.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +hash.$(OBJEXT): {$(VPATH)}internal/intern/set.h hash.$(OBJEXT): {$(VPATH)}internal/intern/signal.h hash.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h hash.$(OBJEXT): {$(VPATH)}internal/intern/string.h @@ -7594,9 +8290,11 @@ hash.$(OBJEXT): {$(VPATH)}internal/module.h hash.$(OBJEXT): {$(VPATH)}internal/newobj.h hash.$(OBJEXT): {$(VPATH)}internal/scan_args.h hash.$(OBJEXT): {$(VPATH)}internal/special_consts.h +hash.$(OBJEXT): {$(VPATH)}internal/st.h hash.$(OBJEXT): {$(VPATH)}internal/static_assert.h hash.$(OBJEXT): {$(VPATH)}internal/stdalign.h hash.$(OBJEXT): {$(VPATH)}internal/stdbool.h +hash.$(OBJEXT): {$(VPATH)}internal/stdckdint.h hash.$(OBJEXT): {$(VPATH)}internal/symbol.h hash.$(OBJEXT): {$(VPATH)}internal/value.h hash.$(OBJEXT): {$(VPATH)}internal/value_type.h @@ -7609,6 +8307,10 @@ hash.$(OBJEXT): {$(VPATH)}missing.h hash.$(OBJEXT): {$(VPATH)}node.h hash.$(OBJEXT): {$(VPATH)}onigmo.h hash.$(OBJEXT): {$(VPATH)}oniguruma.h +hash.$(OBJEXT): {$(VPATH)}prism/ast.h +hash.$(OBJEXT): {$(VPATH)}prism/diagnostic.h +hash.$(OBJEXT): {$(VPATH)}prism/version.h +hash.$(OBJEXT): {$(VPATH)}prism_compile.h hash.$(OBJEXT): {$(VPATH)}probes.dmyh hash.$(OBJEXT): {$(VPATH)}probes.h hash.$(OBJEXT): {$(VPATH)}ractor.h @@ -7626,6 +8328,215 @@ hash.$(OBJEXT): {$(VPATH)}vm_core.h hash.$(OBJEXT): {$(VPATH)}vm_debug.h hash.$(OBJEXT): {$(VPATH)}vm_opts.h hash.$(OBJEXT): {$(VPATH)}vm_sync.h +imemo.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h +imemo.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h +imemo.$(OBJEXT): $(CCAN_DIR)/list/list.h +imemo.$(OBJEXT): $(CCAN_DIR)/str/str.h +imemo.$(OBJEXT): $(hdrdir)/ruby/ruby.h +imemo.$(OBJEXT): $(top_srcdir)/internal/array.h +imemo.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h +imemo.$(OBJEXT): $(top_srcdir)/internal/class.h +imemo.$(OBJEXT): $(top_srcdir)/internal/compilers.h +imemo.$(OBJEXT): $(top_srcdir)/internal/gc.h +imemo.$(OBJEXT): $(top_srcdir)/internal/imemo.h +imemo.$(OBJEXT): $(top_srcdir)/internal/namespace.h +imemo.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h +imemo.$(OBJEXT): $(top_srcdir)/internal/serial.h +imemo.$(OBJEXT): $(top_srcdir)/internal/set_table.h +imemo.$(OBJEXT): $(top_srcdir)/internal/st.h +imemo.$(OBJEXT): $(top_srcdir)/internal/static_assert.h +imemo.$(OBJEXT): $(top_srcdir)/internal/variable.h +imemo.$(OBJEXT): $(top_srcdir)/internal/vm.h +imemo.$(OBJEXT): $(top_srcdir)/internal/warnings.h +imemo.$(OBJEXT): {$(VPATH)}assert.h +imemo.$(OBJEXT): {$(VPATH)}atomic.h +imemo.$(OBJEXT): {$(VPATH)}backward/2/assume.h +imemo.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +imemo.$(OBJEXT): {$(VPATH)}backward/2/bool.h +imemo.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h +imemo.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +imemo.$(OBJEXT): {$(VPATH)}backward/2/limits.h +imemo.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +imemo.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +imemo.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h +imemo.$(OBJEXT): {$(VPATH)}config.h +imemo.$(OBJEXT): {$(VPATH)}constant.h +imemo.$(OBJEXT): {$(VPATH)}debug_counter.h +imemo.$(OBJEXT): {$(VPATH)}defines.h +imemo.$(OBJEXT): {$(VPATH)}encoding.h +imemo.$(OBJEXT): {$(VPATH)}id.h +imemo.$(OBJEXT): {$(VPATH)}id_table.h +imemo.$(OBJEXT): {$(VPATH)}imemo.c +imemo.$(OBJEXT): {$(VPATH)}intern.h +imemo.$(OBJEXT): {$(VPATH)}internal.h +imemo.$(OBJEXT): {$(VPATH)}internal/abi.h +imemo.$(OBJEXT): {$(VPATH)}internal/anyargs.h +imemo.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +imemo.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +imemo.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +imemo.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +imemo.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +imemo.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +imemo.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +imemo.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +imemo.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +imemo.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +imemo.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +imemo.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +imemo.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +imemo.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +imemo.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +imemo.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +imemo.$(OBJEXT): {$(VPATH)}internal/assume.h +imemo.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +imemo.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +imemo.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +imemo.$(OBJEXT): {$(VPATH)}internal/attr/const.h +imemo.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +imemo.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +imemo.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +imemo.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +imemo.$(OBJEXT): {$(VPATH)}internal/attr/error.h +imemo.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +imemo.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +imemo.$(OBJEXT): {$(VPATH)}internal/attr/format.h +imemo.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +imemo.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +imemo.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +imemo.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +imemo.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +imemo.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +imemo.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +imemo.$(OBJEXT): {$(VPATH)}internal/attr/packed_struct.h +imemo.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +imemo.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +imemo.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +imemo.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +imemo.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +imemo.$(OBJEXT): {$(VPATH)}internal/cast.h +imemo.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +imemo.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +imemo.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +imemo.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +imemo.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +imemo.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +imemo.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +imemo.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +imemo.$(OBJEXT): {$(VPATH)}internal/config.h +imemo.$(OBJEXT): {$(VPATH)}internal/constant_p.h +imemo.$(OBJEXT): {$(VPATH)}internal/core.h +imemo.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +imemo.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +imemo.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +imemo.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +imemo.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +imemo.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +imemo.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +imemo.$(OBJEXT): {$(VPATH)}internal/core/robject.h +imemo.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +imemo.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +imemo.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +imemo.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +imemo.$(OBJEXT): {$(VPATH)}internal/ctype.h +imemo.$(OBJEXT): {$(VPATH)}internal/dllexport.h +imemo.$(OBJEXT): {$(VPATH)}internal/dosish.h +imemo.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h +imemo.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h +imemo.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h +imemo.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h +imemo.$(OBJEXT): {$(VPATH)}internal/encoding/re.h +imemo.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h +imemo.$(OBJEXT): {$(VPATH)}internal/encoding/string.h +imemo.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h +imemo.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h +imemo.$(OBJEXT): {$(VPATH)}internal/error.h +imemo.$(OBJEXT): {$(VPATH)}internal/eval.h +imemo.$(OBJEXT): {$(VPATH)}internal/event.h +imemo.$(OBJEXT): {$(VPATH)}internal/fl_type.h +imemo.$(OBJEXT): {$(VPATH)}internal/gc.h +imemo.$(OBJEXT): {$(VPATH)}internal/glob.h +imemo.$(OBJEXT): {$(VPATH)}internal/globals.h +imemo.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +imemo.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +imemo.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +imemo.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +imemo.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +imemo.$(OBJEXT): {$(VPATH)}internal/has/extension.h +imemo.$(OBJEXT): {$(VPATH)}internal/has/feature.h +imemo.$(OBJEXT): {$(VPATH)}internal/has/warning.h +imemo.$(OBJEXT): {$(VPATH)}internal/intern/array.h +imemo.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +imemo.$(OBJEXT): {$(VPATH)}internal/intern/class.h +imemo.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +imemo.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +imemo.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +imemo.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +imemo.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +imemo.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +imemo.$(OBJEXT): {$(VPATH)}internal/intern/error.h +imemo.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +imemo.$(OBJEXT): {$(VPATH)}internal/intern/file.h +imemo.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +imemo.$(OBJEXT): {$(VPATH)}internal/intern/io.h +imemo.$(OBJEXT): {$(VPATH)}internal/intern/load.h +imemo.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +imemo.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +imemo.$(OBJEXT): {$(VPATH)}internal/intern/object.h +imemo.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +imemo.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +imemo.$(OBJEXT): {$(VPATH)}internal/intern/process.h +imemo.$(OBJEXT): {$(VPATH)}internal/intern/random.h +imemo.$(OBJEXT): {$(VPATH)}internal/intern/range.h +imemo.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +imemo.$(OBJEXT): {$(VPATH)}internal/intern/re.h +imemo.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h +imemo.$(OBJEXT): {$(VPATH)}internal/intern/select.h +imemo.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +imemo.$(OBJEXT): {$(VPATH)}internal/intern/set.h +imemo.$(OBJEXT): {$(VPATH)}internal/intern/signal.h +imemo.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +imemo.$(OBJEXT): {$(VPATH)}internal/intern/string.h +imemo.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +imemo.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +imemo.$(OBJEXT): {$(VPATH)}internal/intern/time.h +imemo.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +imemo.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +imemo.$(OBJEXT): {$(VPATH)}internal/interpreter.h +imemo.$(OBJEXT): {$(VPATH)}internal/iterator.h +imemo.$(OBJEXT): {$(VPATH)}internal/memory.h +imemo.$(OBJEXT): {$(VPATH)}internal/method.h +imemo.$(OBJEXT): {$(VPATH)}internal/module.h +imemo.$(OBJEXT): {$(VPATH)}internal/newobj.h +imemo.$(OBJEXT): {$(VPATH)}internal/scan_args.h +imemo.$(OBJEXT): {$(VPATH)}internal/special_consts.h +imemo.$(OBJEXT): {$(VPATH)}internal/static_assert.h +imemo.$(OBJEXT): {$(VPATH)}internal/stdalign.h +imemo.$(OBJEXT): {$(VPATH)}internal/stdbool.h +imemo.$(OBJEXT): {$(VPATH)}internal/stdckdint.h +imemo.$(OBJEXT): {$(VPATH)}internal/symbol.h +imemo.$(OBJEXT): {$(VPATH)}internal/value.h +imemo.$(OBJEXT): {$(VPATH)}internal/value_type.h +imemo.$(OBJEXT): {$(VPATH)}internal/variable.h +imemo.$(OBJEXT): {$(VPATH)}internal/warning_push.h +imemo.$(OBJEXT): {$(VPATH)}internal/xmalloc.h +imemo.$(OBJEXT): {$(VPATH)}method.h +imemo.$(OBJEXT): {$(VPATH)}missing.h +imemo.$(OBJEXT): {$(VPATH)}node.h +imemo.$(OBJEXT): {$(VPATH)}onigmo.h +imemo.$(OBJEXT): {$(VPATH)}oniguruma.h +imemo.$(OBJEXT): {$(VPATH)}ruby_assert.h +imemo.$(OBJEXT): {$(VPATH)}ruby_atomic.h +imemo.$(OBJEXT): {$(VPATH)}rubyparser.h +imemo.$(OBJEXT): {$(VPATH)}shape.h +imemo.$(OBJEXT): {$(VPATH)}st.h +imemo.$(OBJEXT): {$(VPATH)}subst.h +imemo.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h +imemo.$(OBJEXT): {$(VPATH)}thread_native.h +imemo.$(OBJEXT): {$(VPATH)}vm_callinfo.h +imemo.$(OBJEXT): {$(VPATH)}vm_core.h +imemo.$(OBJEXT): {$(VPATH)}vm_debug.h +imemo.$(OBJEXT): {$(VPATH)}vm_opts.h +imemo.$(OBJEXT): {$(VPATH)}vm_sync.h inits.$(OBJEXT): $(hdrdir)/ruby.h inits.$(OBJEXT): $(hdrdir)/ruby/ruby.h inits.$(OBJEXT): $(top_srcdir)/internal/compilers.h @@ -7760,6 +8671,7 @@ inits.$(OBJEXT): {$(VPATH)}internal/intern/re.h inits.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h inits.$(OBJEXT): {$(VPATH)}internal/intern/select.h inits.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +inits.$(OBJEXT): {$(VPATH)}internal/intern/set.h inits.$(OBJEXT): {$(VPATH)}internal/intern/signal.h inits.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h inits.$(OBJEXT): {$(VPATH)}internal/intern/string.h @@ -7779,6 +8691,7 @@ inits.$(OBJEXT): {$(VPATH)}internal/special_consts.h inits.$(OBJEXT): {$(VPATH)}internal/static_assert.h inits.$(OBJEXT): {$(VPATH)}internal/stdalign.h inits.$(OBJEXT): {$(VPATH)}internal/stdbool.h +inits.$(OBJEXT): {$(VPATH)}internal/stdckdint.h inits.$(OBJEXT): {$(VPATH)}internal/symbol.h inits.$(OBJEXT): {$(VPATH)}internal/value.h inits.$(OBJEXT): {$(VPATH)}internal/value_type.h @@ -7794,6 +8707,7 @@ io.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h io.$(OBJEXT): $(CCAN_DIR)/list/list.h io.$(OBJEXT): $(CCAN_DIR)/str/str.h io.$(OBJEXT): $(hdrdir)/ruby/ruby.h +io.$(OBJEXT): $(hdrdir)/ruby/version.h io.$(OBJEXT): $(top_srcdir)/internal/array.h io.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h io.$(OBJEXT): $(top_srcdir)/internal/bignum.h @@ -7807,10 +8721,13 @@ io.$(OBJEXT): $(top_srcdir)/internal/gc.h io.$(OBJEXT): $(top_srcdir)/internal/imemo.h io.$(OBJEXT): $(top_srcdir)/internal/inits.h io.$(OBJEXT): $(top_srcdir)/internal/io.h +io.$(OBJEXT): $(top_srcdir)/internal/namespace.h io.$(OBJEXT): $(top_srcdir)/internal/numeric.h io.$(OBJEXT): $(top_srcdir)/internal/object.h io.$(OBJEXT): $(top_srcdir)/internal/process.h +io.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h io.$(OBJEXT): $(top_srcdir)/internal/serial.h +io.$(OBJEXT): $(top_srcdir)/internal/set_table.h io.$(OBJEXT): $(top_srcdir)/internal/static_assert.h io.$(OBJEXT): $(top_srcdir)/internal/string.h io.$(OBJEXT): $(top_srcdir)/internal/thread.h @@ -7832,6 +8749,7 @@ io.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h io.$(OBJEXT): {$(VPATH)}builtin.h io.$(OBJEXT): {$(VPATH)}config.h io.$(OBJEXT): {$(VPATH)}constant.h +io.$(OBJEXT): {$(VPATH)}debug_counter.h io.$(OBJEXT): {$(VPATH)}defines.h io.$(OBJEXT): {$(VPATH)}dln.h io.$(OBJEXT): {$(VPATH)}encindex.h @@ -7964,6 +8882,7 @@ io.$(OBJEXT): {$(VPATH)}internal/intern/re.h io.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h io.$(OBJEXT): {$(VPATH)}internal/intern/select.h io.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +io.$(OBJEXT): {$(VPATH)}internal/intern/set.h io.$(OBJEXT): {$(VPATH)}internal/intern/signal.h io.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h io.$(OBJEXT): {$(VPATH)}internal/intern/string.h @@ -7983,6 +8902,7 @@ io.$(OBJEXT): {$(VPATH)}internal/special_consts.h io.$(OBJEXT): {$(VPATH)}internal/static_assert.h io.$(OBJEXT): {$(VPATH)}internal/stdalign.h io.$(OBJEXT): {$(VPATH)}internal/stdbool.h +io.$(OBJEXT): {$(VPATH)}internal/stdckdint.h io.$(OBJEXT): {$(VPATH)}internal/symbol.h io.$(OBJEXT): {$(VPATH)}internal/value.h io.$(OBJEXT): {$(VPATH)}internal/value_type.h @@ -8010,25 +8930,37 @@ io.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h io.$(OBJEXT): {$(VPATH)}thread_native.h io.$(OBJEXT): {$(VPATH)}util.h io.$(OBJEXT): {$(VPATH)}vm_core.h +io.$(OBJEXT): {$(VPATH)}vm_debug.h io.$(OBJEXT): {$(VPATH)}vm_opts.h +io.$(OBJEXT): {$(VPATH)}vm_sync.h io_buffer.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h io_buffer.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h io_buffer.$(OBJEXT): $(CCAN_DIR)/list/list.h io_buffer.$(OBJEXT): $(CCAN_DIR)/str/str.h io_buffer.$(OBJEXT): $(hdrdir)/ruby/ruby.h +io_buffer.$(OBJEXT): $(hdrdir)/ruby/version.h io_buffer.$(OBJEXT): $(top_srcdir)/internal/array.h +io_buffer.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h io_buffer.$(OBJEXT): $(top_srcdir)/internal/bignum.h io_buffer.$(OBJEXT): $(top_srcdir)/internal/bits.h io_buffer.$(OBJEXT): $(top_srcdir)/internal/compilers.h io_buffer.$(OBJEXT): $(top_srcdir)/internal/error.h io_buffer.$(OBJEXT): $(top_srcdir)/internal/fixnum.h +io_buffer.$(OBJEXT): $(top_srcdir)/internal/gc.h +io_buffer.$(OBJEXT): $(top_srcdir)/internal/imemo.h +io_buffer.$(OBJEXT): $(top_srcdir)/internal/io.h +io_buffer.$(OBJEXT): $(top_srcdir)/internal/namespace.h io_buffer.$(OBJEXT): $(top_srcdir)/internal/numeric.h +io_buffer.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h io_buffer.$(OBJEXT): $(top_srcdir)/internal/serial.h +io_buffer.$(OBJEXT): $(top_srcdir)/internal/set_table.h io_buffer.$(OBJEXT): $(top_srcdir)/internal/static_assert.h io_buffer.$(OBJEXT): $(top_srcdir)/internal/string.h io_buffer.$(OBJEXT): $(top_srcdir)/internal/thread.h io_buffer.$(OBJEXT): $(top_srcdir)/internal/vm.h +io_buffer.$(OBJEXT): $(top_srcdir)/internal/warnings.h io_buffer.$(OBJEXT): {$(VPATH)}assert.h +io_buffer.$(OBJEXT): {$(VPATH)}atomic.h io_buffer.$(OBJEXT): {$(VPATH)}backward/2/assume.h io_buffer.$(OBJEXT): {$(VPATH)}backward/2/attributes.h io_buffer.$(OBJEXT): {$(VPATH)}backward/2/bool.h @@ -8042,6 +8974,8 @@ io_buffer.$(OBJEXT): {$(VPATH)}config.h io_buffer.$(OBJEXT): {$(VPATH)}defines.h io_buffer.$(OBJEXT): {$(VPATH)}encoding.h io_buffer.$(OBJEXT): {$(VPATH)}fiber/scheduler.h +io_buffer.$(OBJEXT): {$(VPATH)}id.h +io_buffer.$(OBJEXT): {$(VPATH)}id_table.h io_buffer.$(OBJEXT): {$(VPATH)}intern.h io_buffer.$(OBJEXT): {$(VPATH)}internal.h io_buffer.$(OBJEXT): {$(VPATH)}internal/abi.h @@ -8167,6 +9101,7 @@ io_buffer.$(OBJEXT): {$(VPATH)}internal/intern/re.h io_buffer.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h io_buffer.$(OBJEXT): {$(VPATH)}internal/intern/select.h io_buffer.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/intern/set.h io_buffer.$(OBJEXT): {$(VPATH)}internal/intern/signal.h io_buffer.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h io_buffer.$(OBJEXT): {$(VPATH)}internal/intern/string.h @@ -8186,6 +9121,7 @@ io_buffer.$(OBJEXT): {$(VPATH)}internal/special_consts.h io_buffer.$(OBJEXT): {$(VPATH)}internal/static_assert.h io_buffer.$(OBJEXT): {$(VPATH)}internal/stdalign.h io_buffer.$(OBJEXT): {$(VPATH)}internal/stdbool.h +io_buffer.$(OBJEXT): {$(VPATH)}internal/stdckdint.h io_buffer.$(OBJEXT): {$(VPATH)}internal/symbol.h io_buffer.$(OBJEXT): {$(VPATH)}internal/value.h io_buffer.$(OBJEXT): {$(VPATH)}internal/value_type.h @@ -8195,33 +9131,51 @@ io_buffer.$(OBJEXT): {$(VPATH)}internal/xmalloc.h io_buffer.$(OBJEXT): {$(VPATH)}io.h io_buffer.$(OBJEXT): {$(VPATH)}io/buffer.h io_buffer.$(OBJEXT): {$(VPATH)}io_buffer.c +io_buffer.$(OBJEXT): {$(VPATH)}method.h io_buffer.$(OBJEXT): {$(VPATH)}missing.h +io_buffer.$(OBJEXT): {$(VPATH)}node.h io_buffer.$(OBJEXT): {$(VPATH)}onigmo.h io_buffer.$(OBJEXT): {$(VPATH)}oniguruma.h +io_buffer.$(OBJEXT): {$(VPATH)}ruby_assert.h +io_buffer.$(OBJEXT): {$(VPATH)}ruby_atomic.h +io_buffer.$(OBJEXT): {$(VPATH)}rubyparser.h io_buffer.$(OBJEXT): {$(VPATH)}st.h io_buffer.$(OBJEXT): {$(VPATH)}subst.h +io_buffer.$(OBJEXT): {$(VPATH)}thread.h +io_buffer.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h io_buffer.$(OBJEXT): {$(VPATH)}thread_native.h +io_buffer.$(OBJEXT): {$(VPATH)}vm_core.h +io_buffer.$(OBJEXT): {$(VPATH)}vm_opts.h iseq.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h iseq.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h iseq.$(OBJEXT): $(CCAN_DIR)/list/list.h iseq.$(OBJEXT): $(CCAN_DIR)/str/str.h iseq.$(OBJEXT): $(hdrdir)/ruby.h iseq.$(OBJEXT): $(hdrdir)/ruby/ruby.h +iseq.$(OBJEXT): $(hdrdir)/ruby/version.h iseq.$(OBJEXT): $(top_srcdir)/internal/array.h iseq.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h +iseq.$(OBJEXT): $(top_srcdir)/internal/bignum.h iseq.$(OBJEXT): $(top_srcdir)/internal/bits.h iseq.$(OBJEXT): $(top_srcdir)/internal/class.h iseq.$(OBJEXT): $(top_srcdir)/internal/compile.h iseq.$(OBJEXT): $(top_srcdir)/internal/compilers.h +iseq.$(OBJEXT): $(top_srcdir)/internal/complex.h iseq.$(OBJEXT): $(top_srcdir)/internal/error.h iseq.$(OBJEXT): $(top_srcdir)/internal/file.h +iseq.$(OBJEXT): $(top_srcdir)/internal/fixnum.h iseq.$(OBJEXT): $(top_srcdir)/internal/gc.h iseq.$(OBJEXT): $(top_srcdir)/internal/hash.h iseq.$(OBJEXT): $(top_srcdir)/internal/imemo.h +iseq.$(OBJEXT): $(top_srcdir)/internal/io.h +iseq.$(OBJEXT): $(top_srcdir)/internal/namespace.h +iseq.$(OBJEXT): $(top_srcdir)/internal/numeric.h iseq.$(OBJEXT): $(top_srcdir)/internal/parse.h +iseq.$(OBJEXT): $(top_srcdir)/internal/rational.h iseq.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h iseq.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h iseq.$(OBJEXT): $(top_srcdir)/internal/serial.h +iseq.$(OBJEXT): $(top_srcdir)/internal/set_table.h iseq.$(OBJEXT): $(top_srcdir)/internal/static_assert.h iseq.$(OBJEXT): $(top_srcdir)/internal/string.h iseq.$(OBJEXT): $(top_srcdir)/internal/symbol.h @@ -8229,25 +9183,26 @@ iseq.$(OBJEXT): $(top_srcdir)/internal/thread.h iseq.$(OBJEXT): $(top_srcdir)/internal/variable.h iseq.$(OBJEXT): $(top_srcdir)/internal/vm.h iseq.$(OBJEXT): $(top_srcdir)/internal/warnings.h -iseq.$(OBJEXT): $(top_srcdir)/yarp/defines.h -iseq.$(OBJEXT): $(top_srcdir)/yarp/diagnostic.h -iseq.$(OBJEXT): $(top_srcdir)/yarp/enc/yp_encoding.h -iseq.$(OBJEXT): $(top_srcdir)/yarp/node.h -iseq.$(OBJEXT): $(top_srcdir)/yarp/pack.h -iseq.$(OBJEXT): $(top_srcdir)/yarp/parser.h -iseq.$(OBJEXT): $(top_srcdir)/yarp/regexp.h -iseq.$(OBJEXT): $(top_srcdir)/yarp/unescape.h -iseq.$(OBJEXT): $(top_srcdir)/yarp/util/yp_buffer.h -iseq.$(OBJEXT): $(top_srcdir)/yarp/util/yp_char.h -iseq.$(OBJEXT): $(top_srcdir)/yarp/util/yp_constant_pool.h -iseq.$(OBJEXT): $(top_srcdir)/yarp/util/yp_list.h -iseq.$(OBJEXT): $(top_srcdir)/yarp/util/yp_memchr.h -iseq.$(OBJEXT): $(top_srcdir)/yarp/util/yp_newline_list.h -iseq.$(OBJEXT): $(top_srcdir)/yarp/util/yp_state_stack.h -iseq.$(OBJEXT): $(top_srcdir)/yarp/util/yp_string.h -iseq.$(OBJEXT): $(top_srcdir)/yarp/util/yp_string_list.h -iseq.$(OBJEXT): $(top_srcdir)/yarp/util/yp_strpbrk.h -iseq.$(OBJEXT): $(top_srcdir)/yarp/yarp.h +iseq.$(OBJEXT): $(top_srcdir)/prism/defines.h +iseq.$(OBJEXT): $(top_srcdir)/prism/encoding.h +iseq.$(OBJEXT): $(top_srcdir)/prism/node.h +iseq.$(OBJEXT): $(top_srcdir)/prism/options.h +iseq.$(OBJEXT): $(top_srcdir)/prism/pack.h +iseq.$(OBJEXT): $(top_srcdir)/prism/parser.h +iseq.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h +iseq.$(OBJEXT): $(top_srcdir)/prism/prism.h +iseq.$(OBJEXT): $(top_srcdir)/prism/regexp.h +iseq.$(OBJEXT): $(top_srcdir)/prism/static_literals.h +iseq.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h +iseq.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h +iseq.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h +iseq.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h +iseq.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h +iseq.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h +iseq.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h +iseq.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h +iseq.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h +iseq.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h iseq.$(OBJEXT): {$(VPATH)}assert.h iseq.$(OBJEXT): {$(VPATH)}atomic.h iseq.$(OBJEXT): {$(VPATH)}backward/2/assume.h @@ -8396,6 +9351,7 @@ iseq.$(OBJEXT): {$(VPATH)}internal/intern/re.h iseq.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h iseq.$(OBJEXT): {$(VPATH)}internal/intern/select.h iseq.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +iseq.$(OBJEXT): {$(VPATH)}internal/intern/set.h iseq.$(OBJEXT): {$(VPATH)}internal/intern/signal.h iseq.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h iseq.$(OBJEXT): {$(VPATH)}internal/intern/string.h @@ -8415,12 +9371,14 @@ iseq.$(OBJEXT): {$(VPATH)}internal/special_consts.h iseq.$(OBJEXT): {$(VPATH)}internal/static_assert.h iseq.$(OBJEXT): {$(VPATH)}internal/stdalign.h iseq.$(OBJEXT): {$(VPATH)}internal/stdbool.h +iseq.$(OBJEXT): {$(VPATH)}internal/stdckdint.h iseq.$(OBJEXT): {$(VPATH)}internal/symbol.h iseq.$(OBJEXT): {$(VPATH)}internal/value.h iseq.$(OBJEXT): {$(VPATH)}internal/value_type.h iseq.$(OBJEXT): {$(VPATH)}internal/variable.h iseq.$(OBJEXT): {$(VPATH)}internal/warning_push.h iseq.$(OBJEXT): {$(VPATH)}internal/xmalloc.h +iseq.$(OBJEXT): {$(VPATH)}io.h iseq.$(OBJEXT): {$(VPATH)}iseq.c iseq.$(OBJEXT): {$(VPATH)}iseq.h iseq.$(OBJEXT): {$(VPATH)}method.h @@ -8428,8 +9386,12 @@ iseq.$(OBJEXT): {$(VPATH)}missing.h iseq.$(OBJEXT): {$(VPATH)}node.h iseq.$(OBJEXT): {$(VPATH)}onigmo.h iseq.$(OBJEXT): {$(VPATH)}oniguruma.h +iseq.$(OBJEXT): {$(VPATH)}prism/ast.h +iseq.$(OBJEXT): {$(VPATH)}prism/diagnostic.h +iseq.$(OBJEXT): {$(VPATH)}prism/prism.h +iseq.$(OBJEXT): {$(VPATH)}prism/version.h +iseq.$(OBJEXT): {$(VPATH)}prism_compile.h iseq.$(OBJEXT): {$(VPATH)}ractor.h -iseq.$(OBJEXT): {$(VPATH)}rjit.h iseq.$(OBJEXT): {$(VPATH)}ruby_assert.h iseq.$(OBJEXT): {$(VPATH)}ruby_atomic.h iseq.$(OBJEXT): {$(VPATH)}rubyparser.h @@ -8441,35 +9403,303 @@ iseq.$(OBJEXT): {$(VPATH)}thread_native.h iseq.$(OBJEXT): {$(VPATH)}util.h iseq.$(OBJEXT): {$(VPATH)}vm_callinfo.h iseq.$(OBJEXT): {$(VPATH)}vm_core.h +iseq.$(OBJEXT): {$(VPATH)}vm_debug.h iseq.$(OBJEXT): {$(VPATH)}vm_opts.h -iseq.$(OBJEXT): {$(VPATH)}yarp/ast.h -iseq.$(OBJEXT): {$(VPATH)}yarp/version.h -iseq.$(OBJEXT): {$(VPATH)}yarp/yarp.h +iseq.$(OBJEXT): {$(VPATH)}vm_sync.h iseq.$(OBJEXT): {$(VPATH)}yjit.h +iseq.$(OBJEXT): {$(VPATH)}zjit.h +jit.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h +jit.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h +jit.$(OBJEXT): $(CCAN_DIR)/list/list.h +jit.$(OBJEXT): $(CCAN_DIR)/str/str.h +jit.$(OBJEXT): $(hdrdir)/ruby/ruby.h +jit.$(OBJEXT): $(top_srcdir)/internal/array.h +jit.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h +jit.$(OBJEXT): $(top_srcdir)/internal/class.h +jit.$(OBJEXT): $(top_srcdir)/internal/compilers.h +jit.$(OBJEXT): $(top_srcdir)/internal/gc.h +jit.$(OBJEXT): $(top_srcdir)/internal/imemo.h +jit.$(OBJEXT): $(top_srcdir)/internal/namespace.h +jit.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h +jit.$(OBJEXT): $(top_srcdir)/internal/serial.h +jit.$(OBJEXT): $(top_srcdir)/internal/set_table.h +jit.$(OBJEXT): $(top_srcdir)/internal/static_assert.h +jit.$(OBJEXT): $(top_srcdir)/internal/variable.h +jit.$(OBJEXT): $(top_srcdir)/internal/vm.h +jit.$(OBJEXT): $(top_srcdir)/internal/warnings.h +jit.$(OBJEXT): $(top_srcdir)/prism/defines.h +jit.$(OBJEXT): $(top_srcdir)/prism/encoding.h +jit.$(OBJEXT): $(top_srcdir)/prism/node.h +jit.$(OBJEXT): $(top_srcdir)/prism/options.h +jit.$(OBJEXT): $(top_srcdir)/prism/pack.h +jit.$(OBJEXT): $(top_srcdir)/prism/parser.h +jit.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h +jit.$(OBJEXT): $(top_srcdir)/prism/prism.h +jit.$(OBJEXT): $(top_srcdir)/prism/regexp.h +jit.$(OBJEXT): $(top_srcdir)/prism/static_literals.h +jit.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h +jit.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h +jit.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h +jit.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h +jit.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h +jit.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h +jit.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h +jit.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h +jit.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h +jit.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h +jit.$(OBJEXT): {$(VPATH)}assert.h +jit.$(OBJEXT): {$(VPATH)}atomic.h +jit.$(OBJEXT): {$(VPATH)}backward/2/assume.h +jit.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +jit.$(OBJEXT): {$(VPATH)}backward/2/bool.h +jit.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h +jit.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +jit.$(OBJEXT): {$(VPATH)}backward/2/limits.h +jit.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +jit.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +jit.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h +jit.$(OBJEXT): {$(VPATH)}builtin.h +jit.$(OBJEXT): {$(VPATH)}config.h +jit.$(OBJEXT): {$(VPATH)}constant.h +jit.$(OBJEXT): {$(VPATH)}debug_counter.h +jit.$(OBJEXT): {$(VPATH)}defines.h +jit.$(OBJEXT): {$(VPATH)}encoding.h +jit.$(OBJEXT): {$(VPATH)}id.h +jit.$(OBJEXT): {$(VPATH)}id_table.h +jit.$(OBJEXT): {$(VPATH)}insns.def +jit.$(OBJEXT): {$(VPATH)}insns.inc +jit.$(OBJEXT): {$(VPATH)}insns_info.inc +jit.$(OBJEXT): {$(VPATH)}intern.h +jit.$(OBJEXT): {$(VPATH)}internal.h +jit.$(OBJEXT): {$(VPATH)}internal/abi.h +jit.$(OBJEXT): {$(VPATH)}internal/anyargs.h +jit.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +jit.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +jit.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +jit.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +jit.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +jit.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +jit.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +jit.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +jit.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +jit.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +jit.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +jit.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +jit.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +jit.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +jit.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +jit.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +jit.$(OBJEXT): {$(VPATH)}internal/assume.h +jit.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +jit.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +jit.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +jit.$(OBJEXT): {$(VPATH)}internal/attr/const.h +jit.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +jit.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +jit.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +jit.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +jit.$(OBJEXT): {$(VPATH)}internal/attr/error.h +jit.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +jit.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +jit.$(OBJEXT): {$(VPATH)}internal/attr/format.h +jit.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +jit.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +jit.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +jit.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +jit.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +jit.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +jit.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +jit.$(OBJEXT): {$(VPATH)}internal/attr/packed_struct.h +jit.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +jit.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +jit.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +jit.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +jit.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +jit.$(OBJEXT): {$(VPATH)}internal/cast.h +jit.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +jit.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +jit.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +jit.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +jit.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +jit.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +jit.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +jit.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +jit.$(OBJEXT): {$(VPATH)}internal/config.h +jit.$(OBJEXT): {$(VPATH)}internal/constant_p.h +jit.$(OBJEXT): {$(VPATH)}internal/core.h +jit.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +jit.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +jit.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +jit.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +jit.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +jit.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +jit.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +jit.$(OBJEXT): {$(VPATH)}internal/core/robject.h +jit.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +jit.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +jit.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +jit.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +jit.$(OBJEXT): {$(VPATH)}internal/ctype.h +jit.$(OBJEXT): {$(VPATH)}internal/dllexport.h +jit.$(OBJEXT): {$(VPATH)}internal/dosish.h +jit.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h +jit.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h +jit.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h +jit.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h +jit.$(OBJEXT): {$(VPATH)}internal/encoding/re.h +jit.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h +jit.$(OBJEXT): {$(VPATH)}internal/encoding/string.h +jit.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h +jit.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h +jit.$(OBJEXT): {$(VPATH)}internal/error.h +jit.$(OBJEXT): {$(VPATH)}internal/eval.h +jit.$(OBJEXT): {$(VPATH)}internal/event.h +jit.$(OBJEXT): {$(VPATH)}internal/fl_type.h +jit.$(OBJEXT): {$(VPATH)}internal/gc.h +jit.$(OBJEXT): {$(VPATH)}internal/glob.h +jit.$(OBJEXT): {$(VPATH)}internal/globals.h +jit.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +jit.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +jit.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +jit.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +jit.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +jit.$(OBJEXT): {$(VPATH)}internal/has/extension.h +jit.$(OBJEXT): {$(VPATH)}internal/has/feature.h +jit.$(OBJEXT): {$(VPATH)}internal/has/warning.h +jit.$(OBJEXT): {$(VPATH)}internal/intern/array.h +jit.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +jit.$(OBJEXT): {$(VPATH)}internal/intern/class.h +jit.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +jit.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +jit.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +jit.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +jit.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +jit.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +jit.$(OBJEXT): {$(VPATH)}internal/intern/error.h +jit.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +jit.$(OBJEXT): {$(VPATH)}internal/intern/file.h +jit.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +jit.$(OBJEXT): {$(VPATH)}internal/intern/io.h +jit.$(OBJEXT): {$(VPATH)}internal/intern/load.h +jit.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +jit.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +jit.$(OBJEXT): {$(VPATH)}internal/intern/object.h +jit.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +jit.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +jit.$(OBJEXT): {$(VPATH)}internal/intern/process.h +jit.$(OBJEXT): {$(VPATH)}internal/intern/random.h +jit.$(OBJEXT): {$(VPATH)}internal/intern/range.h +jit.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +jit.$(OBJEXT): {$(VPATH)}internal/intern/re.h +jit.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h +jit.$(OBJEXT): {$(VPATH)}internal/intern/select.h +jit.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +jit.$(OBJEXT): {$(VPATH)}internal/intern/set.h +jit.$(OBJEXT): {$(VPATH)}internal/intern/signal.h +jit.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +jit.$(OBJEXT): {$(VPATH)}internal/intern/string.h +jit.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +jit.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +jit.$(OBJEXT): {$(VPATH)}internal/intern/time.h +jit.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +jit.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +jit.$(OBJEXT): {$(VPATH)}internal/interpreter.h +jit.$(OBJEXT): {$(VPATH)}internal/iterator.h +jit.$(OBJEXT): {$(VPATH)}internal/memory.h +jit.$(OBJEXT): {$(VPATH)}internal/method.h +jit.$(OBJEXT): {$(VPATH)}internal/module.h +jit.$(OBJEXT): {$(VPATH)}internal/newobj.h +jit.$(OBJEXT): {$(VPATH)}internal/scan_args.h +jit.$(OBJEXT): {$(VPATH)}internal/special_consts.h +jit.$(OBJEXT): {$(VPATH)}internal/static_assert.h +jit.$(OBJEXT): {$(VPATH)}internal/stdalign.h +jit.$(OBJEXT): {$(VPATH)}internal/stdbool.h +jit.$(OBJEXT): {$(VPATH)}internal/stdckdint.h +jit.$(OBJEXT): {$(VPATH)}internal/symbol.h +jit.$(OBJEXT): {$(VPATH)}internal/value.h +jit.$(OBJEXT): {$(VPATH)}internal/value_type.h +jit.$(OBJEXT): {$(VPATH)}internal/variable.h +jit.$(OBJEXT): {$(VPATH)}internal/warning_push.h +jit.$(OBJEXT): {$(VPATH)}internal/xmalloc.h +jit.$(OBJEXT): {$(VPATH)}iseq.h +jit.$(OBJEXT): {$(VPATH)}jit.c +jit.$(OBJEXT): {$(VPATH)}method.h +jit.$(OBJEXT): {$(VPATH)}missing.h +jit.$(OBJEXT): {$(VPATH)}node.h +jit.$(OBJEXT): {$(VPATH)}onigmo.h +jit.$(OBJEXT): {$(VPATH)}oniguruma.h +jit.$(OBJEXT): {$(VPATH)}prism/ast.h +jit.$(OBJEXT): {$(VPATH)}prism/diagnostic.h +jit.$(OBJEXT): {$(VPATH)}prism/version.h +jit.$(OBJEXT): {$(VPATH)}prism_compile.h +jit.$(OBJEXT): {$(VPATH)}ruby_assert.h +jit.$(OBJEXT): {$(VPATH)}ruby_atomic.h +jit.$(OBJEXT): {$(VPATH)}rubyparser.h +jit.$(OBJEXT): {$(VPATH)}shape.h +jit.$(OBJEXT): {$(VPATH)}st.h +jit.$(OBJEXT): {$(VPATH)}subst.h +jit.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h +jit.$(OBJEXT): {$(VPATH)}thread_native.h +jit.$(OBJEXT): {$(VPATH)}vm_callinfo.h +jit.$(OBJEXT): {$(VPATH)}vm_core.h +jit.$(OBJEXT): {$(VPATH)}vm_debug.h +jit.$(OBJEXT): {$(VPATH)}vm_opts.h +jit.$(OBJEXT): {$(VPATH)}vm_sync.h load.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h load.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h load.$(OBJEXT): $(CCAN_DIR)/list/list.h load.$(OBJEXT): $(CCAN_DIR)/str/str.h load.$(OBJEXT): $(hdrdir)/ruby/ruby.h +load.$(OBJEXT): $(hdrdir)/ruby/version.h load.$(OBJEXT): $(top_srcdir)/internal/array.h load.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h +load.$(OBJEXT): $(top_srcdir)/internal/bignum.h load.$(OBJEXT): $(top_srcdir)/internal/bits.h load.$(OBJEXT): $(top_srcdir)/internal/compilers.h +load.$(OBJEXT): $(top_srcdir)/internal/complex.h load.$(OBJEXT): $(top_srcdir)/internal/dir.h load.$(OBJEXT): $(top_srcdir)/internal/error.h +load.$(OBJEXT): $(top_srcdir)/internal/eval.h load.$(OBJEXT): $(top_srcdir)/internal/file.h +load.$(OBJEXT): $(top_srcdir)/internal/fixnum.h load.$(OBJEXT): $(top_srcdir)/internal/gc.h +load.$(OBJEXT): $(top_srcdir)/internal/hash.h load.$(OBJEXT): $(top_srcdir)/internal/imemo.h load.$(OBJEXT): $(top_srcdir)/internal/load.h +load.$(OBJEXT): $(top_srcdir)/internal/namespace.h +load.$(OBJEXT): $(top_srcdir)/internal/numeric.h load.$(OBJEXT): $(top_srcdir)/internal/parse.h +load.$(OBJEXT): $(top_srcdir)/internal/rational.h load.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h +load.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h load.$(OBJEXT): $(top_srcdir)/internal/serial.h +load.$(OBJEXT): $(top_srcdir)/internal/set_table.h load.$(OBJEXT): $(top_srcdir)/internal/static_assert.h load.$(OBJEXT): $(top_srcdir)/internal/string.h load.$(OBJEXT): $(top_srcdir)/internal/thread.h load.$(OBJEXT): $(top_srcdir)/internal/variable.h load.$(OBJEXT): $(top_srcdir)/internal/vm.h load.$(OBJEXT): $(top_srcdir)/internal/warnings.h +load.$(OBJEXT): $(top_srcdir)/prism/defines.h +load.$(OBJEXT): $(top_srcdir)/prism/encoding.h +load.$(OBJEXT): $(top_srcdir)/prism/node.h +load.$(OBJEXT): $(top_srcdir)/prism/options.h +load.$(OBJEXT): $(top_srcdir)/prism/pack.h +load.$(OBJEXT): $(top_srcdir)/prism/parser.h +load.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h +load.$(OBJEXT): $(top_srcdir)/prism/prism.h +load.$(OBJEXT): $(top_srcdir)/prism/regexp.h +load.$(OBJEXT): $(top_srcdir)/prism/static_literals.h +load.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h +load.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h +load.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h +load.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h +load.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h +load.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h +load.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h +load.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h +load.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h +load.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h load.$(OBJEXT): {$(VPATH)}assert.h load.$(OBJEXT): {$(VPATH)}atomic.h load.$(OBJEXT): {$(VPATH)}backward/2/assume.h @@ -8615,6 +9845,7 @@ load.$(OBJEXT): {$(VPATH)}internal/intern/re.h load.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h load.$(OBJEXT): {$(VPATH)}internal/intern/select.h load.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +load.$(OBJEXT): {$(VPATH)}internal/intern/set.h load.$(OBJEXT): {$(VPATH)}internal/intern/signal.h load.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h load.$(OBJEXT): {$(VPATH)}internal/intern/string.h @@ -8634,6 +9865,7 @@ load.$(OBJEXT): {$(VPATH)}internal/special_consts.h load.$(OBJEXT): {$(VPATH)}internal/static_assert.h load.$(OBJEXT): {$(VPATH)}internal/stdalign.h load.$(OBJEXT): {$(VPATH)}internal/stdbool.h +load.$(OBJEXT): {$(VPATH)}internal/stdckdint.h load.$(OBJEXT): {$(VPATH)}internal/symbol.h load.$(OBJEXT): {$(VPATH)}internal/value.h load.$(OBJEXT): {$(VPATH)}internal/value_type.h @@ -8647,8 +9879,14 @@ load.$(OBJEXT): {$(VPATH)}missing.h load.$(OBJEXT): {$(VPATH)}node.h load.$(OBJEXT): {$(VPATH)}onigmo.h load.$(OBJEXT): {$(VPATH)}oniguruma.h +load.$(OBJEXT): {$(VPATH)}prism/ast.h +load.$(OBJEXT): {$(VPATH)}prism/diagnostic.h +load.$(OBJEXT): {$(VPATH)}prism/version.h +load.$(OBJEXT): {$(VPATH)}prism_compile.h load.$(OBJEXT): {$(VPATH)}probes.dmyh load.$(OBJEXT): {$(VPATH)}probes.h +load.$(OBJEXT): {$(VPATH)}ractor.h +load.$(OBJEXT): {$(VPATH)}ractor_core.h load.$(OBJEXT): {$(VPATH)}ruby_assert.h load.$(OBJEXT): {$(VPATH)}ruby_atomic.h load.$(OBJEXT): {$(VPATH)}rubyparser.h @@ -8659,6 +9897,7 @@ load.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h load.$(OBJEXT): {$(VPATH)}thread_native.h load.$(OBJEXT): {$(VPATH)}util.h load.$(OBJEXT): {$(VPATH)}vm_core.h +load.$(OBJEXT): {$(VPATH)}vm_debug.h load.$(OBJEXT): {$(VPATH)}vm_opts.h loadpath.$(OBJEXT): $(hdrdir)/ruby/ruby.h loadpath.$(OBJEXT): $(hdrdir)/ruby/version.h @@ -8789,6 +10028,7 @@ loadpath.$(OBJEXT): {$(VPATH)}internal/intern/re.h loadpath.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h loadpath.$(OBJEXT): {$(VPATH)}internal/intern/select.h loadpath.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +loadpath.$(OBJEXT): {$(VPATH)}internal/intern/set.h loadpath.$(OBJEXT): {$(VPATH)}internal/intern/signal.h loadpath.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h loadpath.$(OBJEXT): {$(VPATH)}internal/intern/string.h @@ -8808,6 +10048,7 @@ loadpath.$(OBJEXT): {$(VPATH)}internal/special_consts.h loadpath.$(OBJEXT): {$(VPATH)}internal/static_assert.h loadpath.$(OBJEXT): {$(VPATH)}internal/stdalign.h loadpath.$(OBJEXT): {$(VPATH)}internal/stdbool.h +loadpath.$(OBJEXT): {$(VPATH)}internal/stdckdint.h loadpath.$(OBJEXT): {$(VPATH)}internal/symbol.h loadpath.$(OBJEXT): {$(VPATH)}internal/value.h loadpath.$(OBJEXT): {$(VPATH)}internal/value_type.h @@ -8958,6 +10199,7 @@ localeinit.$(OBJEXT): {$(VPATH)}internal/intern/re.h localeinit.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h localeinit.$(OBJEXT): {$(VPATH)}internal/intern/select.h localeinit.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +localeinit.$(OBJEXT): {$(VPATH)}internal/intern/set.h localeinit.$(OBJEXT): {$(VPATH)}internal/intern/signal.h localeinit.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h localeinit.$(OBJEXT): {$(VPATH)}internal/intern/string.h @@ -8977,6 +10219,7 @@ localeinit.$(OBJEXT): {$(VPATH)}internal/special_consts.h localeinit.$(OBJEXT): {$(VPATH)}internal/static_assert.h localeinit.$(OBJEXT): {$(VPATH)}internal/stdalign.h localeinit.$(OBJEXT): {$(VPATH)}internal/stdbool.h +localeinit.$(OBJEXT): {$(VPATH)}internal/stdckdint.h localeinit.$(OBJEXT): {$(VPATH)}internal/symbol.h localeinit.$(OBJEXT): {$(VPATH)}internal/value.h localeinit.$(OBJEXT): {$(VPATH)}internal/value_type.h @@ -8991,11 +10234,15 @@ localeinit.$(OBJEXT): {$(VPATH)}st.h localeinit.$(OBJEXT): {$(VPATH)}subst.h main.$(OBJEXT): $(hdrdir)/ruby.h main.$(OBJEXT): $(hdrdir)/ruby/ruby.h +main.$(OBJEXT): $(top_srcdir)/internal/compilers.h +main.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h +main.$(OBJEXT): $(top_srcdir)/internal/warnings.h main.$(OBJEXT): {$(VPATH)}assert.h main.$(OBJEXT): {$(VPATH)}backward.h main.$(OBJEXT): {$(VPATH)}backward/2/assume.h main.$(OBJEXT): {$(VPATH)}backward/2/attributes.h main.$(OBJEXT): {$(VPATH)}backward/2/bool.h +main.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h main.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h main.$(OBJEXT): {$(VPATH)}backward/2/limits.h main.$(OBJEXT): {$(VPATH)}backward/2/long_long.h @@ -9118,6 +10365,7 @@ main.$(OBJEXT): {$(VPATH)}internal/intern/re.h main.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h main.$(OBJEXT): {$(VPATH)}internal/intern/select.h main.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +main.$(OBJEXT): {$(VPATH)}internal/intern/set.h main.$(OBJEXT): {$(VPATH)}internal/intern/signal.h main.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h main.$(OBJEXT): {$(VPATH)}internal/intern/string.h @@ -9137,6 +10385,7 @@ main.$(OBJEXT): {$(VPATH)}internal/special_consts.h main.$(OBJEXT): {$(VPATH)}internal/static_assert.h main.$(OBJEXT): {$(VPATH)}internal/stdalign.h main.$(OBJEXT): {$(VPATH)}internal/stdbool.h +main.$(OBJEXT): {$(VPATH)}internal/stdckdint.h main.$(OBJEXT): {$(VPATH)}internal/symbol.h main.$(OBJEXT): {$(VPATH)}internal/value.h main.$(OBJEXT): {$(VPATH)}internal/value_type.h @@ -9153,6 +10402,7 @@ marshal.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h marshal.$(OBJEXT): $(CCAN_DIR)/list/list.h marshal.$(OBJEXT): $(CCAN_DIR)/str/str.h marshal.$(OBJEXT): $(hdrdir)/ruby/ruby.h +marshal.$(OBJEXT): $(hdrdir)/ruby/version.h marshal.$(OBJEXT): $(top_srcdir)/internal/array.h marshal.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h marshal.$(OBJEXT): $(top_srcdir)/internal/bignum.h @@ -9165,9 +10415,12 @@ marshal.$(OBJEXT): $(top_srcdir)/internal/fixnum.h marshal.$(OBJEXT): $(top_srcdir)/internal/gc.h marshal.$(OBJEXT): $(top_srcdir)/internal/hash.h marshal.$(OBJEXT): $(top_srcdir)/internal/imemo.h +marshal.$(OBJEXT): $(top_srcdir)/internal/namespace.h marshal.$(OBJEXT): $(top_srcdir)/internal/numeric.h marshal.$(OBJEXT): $(top_srcdir)/internal/object.h +marshal.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h marshal.$(OBJEXT): $(top_srcdir)/internal/serial.h +marshal.$(OBJEXT): $(top_srcdir)/internal/set_table.h marshal.$(OBJEXT): $(top_srcdir)/internal/static_assert.h marshal.$(OBJEXT): $(top_srcdir)/internal/string.h marshal.$(OBJEXT): $(top_srcdir)/internal/struct.h @@ -9190,6 +10443,7 @@ marshal.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h marshal.$(OBJEXT): {$(VPATH)}builtin.h marshal.$(OBJEXT): {$(VPATH)}config.h marshal.$(OBJEXT): {$(VPATH)}constant.h +marshal.$(OBJEXT): {$(VPATH)}debug_counter.h marshal.$(OBJEXT): {$(VPATH)}defines.h marshal.$(OBJEXT): {$(VPATH)}encindex.h marshal.$(OBJEXT): {$(VPATH)}encoding.h @@ -9234,6 +10488,7 @@ marshal.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h marshal.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h marshal.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h marshal.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +marshal.$(OBJEXT): {$(VPATH)}internal/attr/nonstring.h marshal.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h marshal.$(OBJEXT): {$(VPATH)}internal/attr/packed_struct.h marshal.$(OBJEXT): {$(VPATH)}internal/attr/pure.h @@ -9320,6 +10575,7 @@ marshal.$(OBJEXT): {$(VPATH)}internal/intern/re.h marshal.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h marshal.$(OBJEXT): {$(VPATH)}internal/intern/select.h marshal.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +marshal.$(OBJEXT): {$(VPATH)}internal/intern/set.h marshal.$(OBJEXT): {$(VPATH)}internal/intern/signal.h marshal.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h marshal.$(OBJEXT): {$(VPATH)}internal/intern/string.h @@ -9339,6 +10595,7 @@ marshal.$(OBJEXT): {$(VPATH)}internal/special_consts.h marshal.$(OBJEXT): {$(VPATH)}internal/static_assert.h marshal.$(OBJEXT): {$(VPATH)}internal/stdalign.h marshal.$(OBJEXT): {$(VPATH)}internal/stdbool.h +marshal.$(OBJEXT): {$(VPATH)}internal/stdckdint.h marshal.$(OBJEXT): {$(VPATH)}internal/symbol.h marshal.$(OBJEXT): {$(VPATH)}internal/value.h marshal.$(OBJEXT): {$(VPATH)}internal/value_type.h @@ -9363,7 +10620,9 @@ marshal.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h marshal.$(OBJEXT): {$(VPATH)}thread_native.h marshal.$(OBJEXT): {$(VPATH)}util.h marshal.$(OBJEXT): {$(VPATH)}vm_core.h +marshal.$(OBJEXT): {$(VPATH)}vm_debug.h marshal.$(OBJEXT): {$(VPATH)}vm_opts.h +marshal.$(OBJEXT): {$(VPATH)}vm_sync.h math.$(OBJEXT): $(hdrdir)/ruby/ruby.h math.$(OBJEXT): $(top_srcdir)/internal/bignum.h math.$(OBJEXT): $(top_srcdir)/internal/class.h @@ -9507,6 +10766,7 @@ math.$(OBJEXT): {$(VPATH)}internal/intern/re.h math.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h math.$(OBJEXT): {$(VPATH)}internal/intern/select.h math.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +math.$(OBJEXT): {$(VPATH)}internal/intern/set.h math.$(OBJEXT): {$(VPATH)}internal/intern/signal.h math.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h math.$(OBJEXT): {$(VPATH)}internal/intern/string.h @@ -9526,6 +10786,7 @@ math.$(OBJEXT): {$(VPATH)}internal/special_consts.h math.$(OBJEXT): {$(VPATH)}internal/static_assert.h math.$(OBJEXT): {$(VPATH)}internal/stdalign.h math.$(OBJEXT): {$(VPATH)}internal/stdbool.h +math.$(OBJEXT): {$(VPATH)}internal/stdckdint.h math.$(OBJEXT): {$(VPATH)}internal/symbol.h math.$(OBJEXT): {$(VPATH)}internal/value.h math.$(OBJEXT): {$(VPATH)}internal/value_type.h @@ -9548,7 +10809,10 @@ memory_view.$(OBJEXT): $(top_srcdir)/internal/compilers.h memory_view.$(OBJEXT): $(top_srcdir)/internal/gc.h memory_view.$(OBJEXT): $(top_srcdir)/internal/hash.h memory_view.$(OBJEXT): $(top_srcdir)/internal/imemo.h +memory_view.$(OBJEXT): $(top_srcdir)/internal/namespace.h +memory_view.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h memory_view.$(OBJEXT): $(top_srcdir)/internal/serial.h +memory_view.$(OBJEXT): $(top_srcdir)/internal/set_table.h memory_view.$(OBJEXT): $(top_srcdir)/internal/static_assert.h memory_view.$(OBJEXT): $(top_srcdir)/internal/variable.h memory_view.$(OBJEXT): $(top_srcdir)/internal/vm.h @@ -9696,6 +10960,7 @@ memory_view.$(OBJEXT): {$(VPATH)}internal/intern/re.h memory_view.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h memory_view.$(OBJEXT): {$(VPATH)}internal/intern/select.h memory_view.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +memory_view.$(OBJEXT): {$(VPATH)}internal/intern/set.h memory_view.$(OBJEXT): {$(VPATH)}internal/intern/signal.h memory_view.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h memory_view.$(OBJEXT): {$(VPATH)}internal/intern/string.h @@ -9715,6 +10980,7 @@ memory_view.$(OBJEXT): {$(VPATH)}internal/special_consts.h memory_view.$(OBJEXT): {$(VPATH)}internal/static_assert.h memory_view.$(OBJEXT): {$(VPATH)}internal/stdalign.h memory_view.$(OBJEXT): {$(VPATH)}internal/stdbool.h +memory_view.$(OBJEXT): {$(VPATH)}internal/stdckdint.h memory_view.$(OBJEXT): {$(VPATH)}internal/symbol.h memory_view.$(OBJEXT): {$(VPATH)}internal/value.h memory_view.$(OBJEXT): {$(VPATH)}internal/value_type.h @@ -9746,18 +11012,48 @@ miniinit.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h miniinit.$(OBJEXT): $(CCAN_DIR)/list/list.h miniinit.$(OBJEXT): $(CCAN_DIR)/str/str.h miniinit.$(OBJEXT): $(hdrdir)/ruby/ruby.h -miniinit.$(OBJEXT): $(srcdir)/rjit_c.rb miniinit.$(OBJEXT): $(top_srcdir)/internal/array.h miniinit.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h +miniinit.$(OBJEXT): $(top_srcdir)/internal/bignum.h +miniinit.$(OBJEXT): $(top_srcdir)/internal/bits.h miniinit.$(OBJEXT): $(top_srcdir)/internal/compilers.h +miniinit.$(OBJEXT): $(top_srcdir)/internal/complex.h +miniinit.$(OBJEXT): $(top_srcdir)/internal/eval.h +miniinit.$(OBJEXT): $(top_srcdir)/internal/fixnum.h miniinit.$(OBJEXT): $(top_srcdir)/internal/gc.h miniinit.$(OBJEXT): $(top_srcdir)/internal/imemo.h +miniinit.$(OBJEXT): $(top_srcdir)/internal/namespace.h +miniinit.$(OBJEXT): $(top_srcdir)/internal/numeric.h +miniinit.$(OBJEXT): $(top_srcdir)/internal/parse.h +miniinit.$(OBJEXT): $(top_srcdir)/internal/rational.h miniinit.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h +miniinit.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h miniinit.$(OBJEXT): $(top_srcdir)/internal/serial.h +miniinit.$(OBJEXT): $(top_srcdir)/internal/set_table.h miniinit.$(OBJEXT): $(top_srcdir)/internal/static_assert.h miniinit.$(OBJEXT): $(top_srcdir)/internal/variable.h miniinit.$(OBJEXT): $(top_srcdir)/internal/vm.h miniinit.$(OBJEXT): $(top_srcdir)/internal/warnings.h +miniinit.$(OBJEXT): $(top_srcdir)/prism/defines.h +miniinit.$(OBJEXT): $(top_srcdir)/prism/encoding.h +miniinit.$(OBJEXT): $(top_srcdir)/prism/node.h +miniinit.$(OBJEXT): $(top_srcdir)/prism/options.h +miniinit.$(OBJEXT): $(top_srcdir)/prism/pack.h +miniinit.$(OBJEXT): $(top_srcdir)/prism/parser.h +miniinit.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h +miniinit.$(OBJEXT): $(top_srcdir)/prism/prism.h +miniinit.$(OBJEXT): $(top_srcdir)/prism/regexp.h +miniinit.$(OBJEXT): $(top_srcdir)/prism/static_literals.h +miniinit.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h +miniinit.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h +miniinit.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h +miniinit.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h +miniinit.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h +miniinit.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h +miniinit.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h +miniinit.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h +miniinit.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h +miniinit.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h miniinit.$(OBJEXT): {$(VPATH)}array.rb miniinit.$(OBJEXT): {$(VPATH)}assert.h miniinit.$(OBJEXT): {$(VPATH)}ast.rb @@ -9820,6 +11116,7 @@ miniinit.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h miniinit.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h miniinit.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h miniinit.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +miniinit.$(OBJEXT): {$(VPATH)}internal/attr/nonstring.h miniinit.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h miniinit.$(OBJEXT): {$(VPATH)}internal/attr/packed_struct.h miniinit.$(OBJEXT): {$(VPATH)}internal/attr/pure.h @@ -9906,6 +11203,7 @@ miniinit.$(OBJEXT): {$(VPATH)}internal/intern/re.h miniinit.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h miniinit.$(OBJEXT): {$(VPATH)}internal/intern/select.h miniinit.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +miniinit.$(OBJEXT): {$(VPATH)}internal/intern/set.h miniinit.$(OBJEXT): {$(VPATH)}internal/intern/signal.h miniinit.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h miniinit.$(OBJEXT): {$(VPATH)}internal/intern/string.h @@ -9925,6 +11223,7 @@ miniinit.$(OBJEXT): {$(VPATH)}internal/special_consts.h miniinit.$(OBJEXT): {$(VPATH)}internal/static_assert.h miniinit.$(OBJEXT): {$(VPATH)}internal/stdalign.h miniinit.$(OBJEXT): {$(VPATH)}internal/stdbool.h +miniinit.$(OBJEXT): {$(VPATH)}internal/stdckdint.h miniinit.$(OBJEXT): {$(VPATH)}internal/symbol.h miniinit.$(OBJEXT): {$(VPATH)}internal/value.h miniinit.$(OBJEXT): {$(VPATH)}internal/value_type.h @@ -9947,9 +11246,11 @@ miniinit.$(OBJEXT): {$(VPATH)}onigmo.h miniinit.$(OBJEXT): {$(VPATH)}oniguruma.h miniinit.$(OBJEXT): {$(VPATH)}pack.rb miniinit.$(OBJEXT): {$(VPATH)}prelude.rb +miniinit.$(OBJEXT): {$(VPATH)}prism/ast.h +miniinit.$(OBJEXT): {$(VPATH)}prism/diagnostic.h +miniinit.$(OBJEXT): {$(VPATH)}prism/version.h +miniinit.$(OBJEXT): {$(VPATH)}prism_compile.h miniinit.$(OBJEXT): {$(VPATH)}ractor.rb -miniinit.$(OBJEXT): {$(VPATH)}rjit.rb -miniinit.$(OBJEXT): {$(VPATH)}rjit_c.rb miniinit.$(OBJEXT): {$(VPATH)}ruby_assert.h miniinit.$(OBJEXT): {$(VPATH)}ruby_atomic.h miniinit.$(OBJEXT): {$(VPATH)}rubyparser.h @@ -9966,6 +11267,223 @@ miniinit.$(OBJEXT): {$(VPATH)}vm_core.h miniinit.$(OBJEXT): {$(VPATH)}vm_opts.h miniinit.$(OBJEXT): {$(VPATH)}warning.rb miniinit.$(OBJEXT): {$(VPATH)}yjit.rb +miniinit.$(OBJEXT): {$(VPATH)}yjit_hook.rb +miniinit.$(OBJEXT): {$(VPATH)}zjit.rb +namespace.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h +namespace.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h +namespace.$(OBJEXT): $(CCAN_DIR)/list/list.h +namespace.$(OBJEXT): $(CCAN_DIR)/str/str.h +namespace.$(OBJEXT): $(hdrdir)/ruby/ruby.h +namespace.$(OBJEXT): $(top_srcdir)/internal/array.h +namespace.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h +namespace.$(OBJEXT): $(top_srcdir)/internal/class.h +namespace.$(OBJEXT): $(top_srcdir)/internal/compilers.h +namespace.$(OBJEXT): $(top_srcdir)/internal/error.h +namespace.$(OBJEXT): $(top_srcdir)/internal/eval.h +namespace.$(OBJEXT): $(top_srcdir)/internal/file.h +namespace.$(OBJEXT): $(top_srcdir)/internal/gc.h +namespace.$(OBJEXT): $(top_srcdir)/internal/hash.h +namespace.$(OBJEXT): $(top_srcdir)/internal/imemo.h +namespace.$(OBJEXT): $(top_srcdir)/internal/load.h +namespace.$(OBJEXT): $(top_srcdir)/internal/namespace.h +namespace.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h +namespace.$(OBJEXT): $(top_srcdir)/internal/serial.h +namespace.$(OBJEXT): $(top_srcdir)/internal/set_table.h +namespace.$(OBJEXT): $(top_srcdir)/internal/st.h +namespace.$(OBJEXT): $(top_srcdir)/internal/static_assert.h +namespace.$(OBJEXT): $(top_srcdir)/internal/string.h +namespace.$(OBJEXT): $(top_srcdir)/internal/variable.h +namespace.$(OBJEXT): $(top_srcdir)/internal/vm.h +namespace.$(OBJEXT): $(top_srcdir)/internal/warnings.h +namespace.$(OBJEXT): {$(VPATH)}assert.h +namespace.$(OBJEXT): {$(VPATH)}atomic.h +namespace.$(OBJEXT): {$(VPATH)}backward/2/assume.h +namespace.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +namespace.$(OBJEXT): {$(VPATH)}backward/2/bool.h +namespace.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h +namespace.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +namespace.$(OBJEXT): {$(VPATH)}backward/2/limits.h +namespace.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +namespace.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +namespace.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h +namespace.$(OBJEXT): {$(VPATH)}config.h +namespace.$(OBJEXT): {$(VPATH)}constant.h +namespace.$(OBJEXT): {$(VPATH)}debug_counter.h +namespace.$(OBJEXT): {$(VPATH)}defines.h +namespace.$(OBJEXT): {$(VPATH)}encoding.h +namespace.$(OBJEXT): {$(VPATH)}id.h +namespace.$(OBJEXT): {$(VPATH)}id_table.h +namespace.$(OBJEXT): {$(VPATH)}intern.h +namespace.$(OBJEXT): {$(VPATH)}internal.h +namespace.$(OBJEXT): {$(VPATH)}internal/abi.h +namespace.$(OBJEXT): {$(VPATH)}internal/anyargs.h +namespace.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +namespace.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +namespace.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +namespace.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +namespace.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +namespace.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +namespace.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +namespace.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +namespace.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +namespace.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +namespace.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +namespace.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +namespace.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +namespace.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +namespace.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +namespace.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +namespace.$(OBJEXT): {$(VPATH)}internal/assume.h +namespace.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +namespace.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +namespace.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +namespace.$(OBJEXT): {$(VPATH)}internal/attr/const.h +namespace.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +namespace.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +namespace.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +namespace.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +namespace.$(OBJEXT): {$(VPATH)}internal/attr/error.h +namespace.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +namespace.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +namespace.$(OBJEXT): {$(VPATH)}internal/attr/format.h +namespace.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +namespace.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +namespace.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +namespace.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +namespace.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +namespace.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +namespace.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +namespace.$(OBJEXT): {$(VPATH)}internal/attr/packed_struct.h +namespace.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +namespace.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +namespace.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +namespace.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +namespace.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +namespace.$(OBJEXT): {$(VPATH)}internal/cast.h +namespace.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +namespace.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +namespace.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +namespace.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +namespace.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +namespace.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +namespace.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +namespace.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +namespace.$(OBJEXT): {$(VPATH)}internal/config.h +namespace.$(OBJEXT): {$(VPATH)}internal/constant_p.h +namespace.$(OBJEXT): {$(VPATH)}internal/core.h +namespace.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +namespace.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +namespace.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +namespace.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +namespace.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +namespace.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +namespace.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +namespace.$(OBJEXT): {$(VPATH)}internal/core/robject.h +namespace.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +namespace.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +namespace.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +namespace.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +namespace.$(OBJEXT): {$(VPATH)}internal/ctype.h +namespace.$(OBJEXT): {$(VPATH)}internal/dllexport.h +namespace.$(OBJEXT): {$(VPATH)}internal/dosish.h +namespace.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h +namespace.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h +namespace.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h +namespace.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h +namespace.$(OBJEXT): {$(VPATH)}internal/encoding/re.h +namespace.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h +namespace.$(OBJEXT): {$(VPATH)}internal/encoding/string.h +namespace.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h +namespace.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h +namespace.$(OBJEXT): {$(VPATH)}internal/error.h +namespace.$(OBJEXT): {$(VPATH)}internal/eval.h +namespace.$(OBJEXT): {$(VPATH)}internal/event.h +namespace.$(OBJEXT): {$(VPATH)}internal/fl_type.h +namespace.$(OBJEXT): {$(VPATH)}internal/gc.h +namespace.$(OBJEXT): {$(VPATH)}internal/glob.h +namespace.$(OBJEXT): {$(VPATH)}internal/globals.h +namespace.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +namespace.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +namespace.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +namespace.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +namespace.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +namespace.$(OBJEXT): {$(VPATH)}internal/has/extension.h +namespace.$(OBJEXT): {$(VPATH)}internal/has/feature.h +namespace.$(OBJEXT): {$(VPATH)}internal/has/warning.h +namespace.$(OBJEXT): {$(VPATH)}internal/intern/array.h +namespace.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +namespace.$(OBJEXT): {$(VPATH)}internal/intern/class.h +namespace.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +namespace.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +namespace.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +namespace.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +namespace.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +namespace.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +namespace.$(OBJEXT): {$(VPATH)}internal/intern/error.h +namespace.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +namespace.$(OBJEXT): {$(VPATH)}internal/intern/file.h +namespace.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +namespace.$(OBJEXT): {$(VPATH)}internal/intern/io.h +namespace.$(OBJEXT): {$(VPATH)}internal/intern/load.h +namespace.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +namespace.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +namespace.$(OBJEXT): {$(VPATH)}internal/intern/object.h +namespace.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +namespace.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +namespace.$(OBJEXT): {$(VPATH)}internal/intern/process.h +namespace.$(OBJEXT): {$(VPATH)}internal/intern/random.h +namespace.$(OBJEXT): {$(VPATH)}internal/intern/range.h +namespace.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +namespace.$(OBJEXT): {$(VPATH)}internal/intern/re.h +namespace.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h +namespace.$(OBJEXT): {$(VPATH)}internal/intern/select.h +namespace.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +namespace.$(OBJEXT): {$(VPATH)}internal/intern/set.h +namespace.$(OBJEXT): {$(VPATH)}internal/intern/signal.h +namespace.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +namespace.$(OBJEXT): {$(VPATH)}internal/intern/string.h +namespace.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +namespace.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +namespace.$(OBJEXT): {$(VPATH)}internal/intern/time.h +namespace.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +namespace.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +namespace.$(OBJEXT): {$(VPATH)}internal/interpreter.h +namespace.$(OBJEXT): {$(VPATH)}internal/iterator.h +namespace.$(OBJEXT): {$(VPATH)}internal/memory.h +namespace.$(OBJEXT): {$(VPATH)}internal/method.h +namespace.$(OBJEXT): {$(VPATH)}internal/module.h +namespace.$(OBJEXT): {$(VPATH)}internal/newobj.h +namespace.$(OBJEXT): {$(VPATH)}internal/scan_args.h +namespace.$(OBJEXT): {$(VPATH)}internal/special_consts.h +namespace.$(OBJEXT): {$(VPATH)}internal/static_assert.h +namespace.$(OBJEXT): {$(VPATH)}internal/stdalign.h +namespace.$(OBJEXT): {$(VPATH)}internal/stdbool.h +namespace.$(OBJEXT): {$(VPATH)}internal/stdckdint.h +namespace.$(OBJEXT): {$(VPATH)}internal/symbol.h +namespace.$(OBJEXT): {$(VPATH)}internal/value.h +namespace.$(OBJEXT): {$(VPATH)}internal/value_type.h +namespace.$(OBJEXT): {$(VPATH)}internal/variable.h +namespace.$(OBJEXT): {$(VPATH)}internal/warning_push.h +namespace.$(OBJEXT): {$(VPATH)}internal/xmalloc.h +namespace.$(OBJEXT): {$(VPATH)}method.h +namespace.$(OBJEXT): {$(VPATH)}missing.h +namespace.$(OBJEXT): {$(VPATH)}namespace.c +namespace.$(OBJEXT): {$(VPATH)}node.h +namespace.$(OBJEXT): {$(VPATH)}onigmo.h +namespace.$(OBJEXT): {$(VPATH)}oniguruma.h +namespace.$(OBJEXT): {$(VPATH)}ruby_assert.h +namespace.$(OBJEXT): {$(VPATH)}ruby_atomic.h +namespace.$(OBJEXT): {$(VPATH)}rubyparser.h +namespace.$(OBJEXT): {$(VPATH)}shape.h +namespace.$(OBJEXT): {$(VPATH)}st.h +namespace.$(OBJEXT): {$(VPATH)}subst.h +namespace.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h +namespace.$(OBJEXT): {$(VPATH)}thread_native.h +namespace.$(OBJEXT): {$(VPATH)}util.h +namespace.$(OBJEXT): {$(VPATH)}vm_core.h +namespace.$(OBJEXT): {$(VPATH)}vm_debug.h +namespace.$(OBJEXT): {$(VPATH)}vm_opts.h +namespace.$(OBJEXT): {$(VPATH)}vm_sync.h node.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h node.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h node.$(OBJEXT): $(CCAN_DIR)/list/list.h @@ -9977,7 +11495,10 @@ node.$(OBJEXT): $(top_srcdir)/internal/compilers.h node.$(OBJEXT): $(top_srcdir)/internal/gc.h node.$(OBJEXT): $(top_srcdir)/internal/hash.h node.$(OBJEXT): $(top_srcdir)/internal/imemo.h +node.$(OBJEXT): $(top_srcdir)/internal/namespace.h +node.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h node.$(OBJEXT): $(top_srcdir)/internal/serial.h +node.$(OBJEXT): $(top_srcdir)/internal/set_table.h node.$(OBJEXT): $(top_srcdir)/internal/static_assert.h node.$(OBJEXT): $(top_srcdir)/internal/variable.h node.$(OBJEXT): $(top_srcdir)/internal/vm.h @@ -10124,6 +11645,7 @@ node.$(OBJEXT): {$(VPATH)}internal/intern/re.h node.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h node.$(OBJEXT): {$(VPATH)}internal/intern/select.h node.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +node.$(OBJEXT): {$(VPATH)}internal/intern/set.h node.$(OBJEXT): {$(VPATH)}internal/intern/signal.h node.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h node.$(OBJEXT): {$(VPATH)}internal/intern/string.h @@ -10143,6 +11665,7 @@ node.$(OBJEXT): {$(VPATH)}internal/special_consts.h node.$(OBJEXT): {$(VPATH)}internal/static_assert.h node.$(OBJEXT): {$(VPATH)}internal/stdalign.h node.$(OBJEXT): {$(VPATH)}internal/stdbool.h +node.$(OBJEXT): {$(VPATH)}internal/stdckdint.h node.$(OBJEXT): {$(VPATH)}internal/symbol.h node.$(OBJEXT): {$(VPATH)}internal/value.h node.$(OBJEXT): {$(VPATH)}internal/value_type.h @@ -10173,11 +11696,23 @@ node_dump.$(OBJEXT): $(CCAN_DIR)/str/str.h node_dump.$(OBJEXT): $(hdrdir)/ruby/ruby.h node_dump.$(OBJEXT): $(top_srcdir)/internal/array.h node_dump.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h +node_dump.$(OBJEXT): $(top_srcdir)/internal/bignum.h +node_dump.$(OBJEXT): $(top_srcdir)/internal/bits.h +node_dump.$(OBJEXT): $(top_srcdir)/internal/class.h node_dump.$(OBJEXT): $(top_srcdir)/internal/compilers.h +node_dump.$(OBJEXT): $(top_srcdir)/internal/complex.h +node_dump.$(OBJEXT): $(top_srcdir)/internal/fixnum.h node_dump.$(OBJEXT): $(top_srcdir)/internal/gc.h node_dump.$(OBJEXT): $(top_srcdir)/internal/hash.h node_dump.$(OBJEXT): $(top_srcdir)/internal/imemo.h +node_dump.$(OBJEXT): $(top_srcdir)/internal/namespace.h +node_dump.$(OBJEXT): $(top_srcdir)/internal/numeric.h +node_dump.$(OBJEXT): $(top_srcdir)/internal/parse.h +node_dump.$(OBJEXT): $(top_srcdir)/internal/rational.h +node_dump.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h +node_dump.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h node_dump.$(OBJEXT): $(top_srcdir)/internal/serial.h +node_dump.$(OBJEXT): $(top_srcdir)/internal/set_table.h node_dump.$(OBJEXT): $(top_srcdir)/internal/static_assert.h node_dump.$(OBJEXT): $(top_srcdir)/internal/variable.h node_dump.$(OBJEXT): $(top_srcdir)/internal/vm.h @@ -10195,6 +11730,7 @@ node_dump.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h node_dump.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h node_dump.$(OBJEXT): {$(VPATH)}config.h node_dump.$(OBJEXT): {$(VPATH)}constant.h +node_dump.$(OBJEXT): {$(VPATH)}debug_counter.h node_dump.$(OBJEXT): {$(VPATH)}defines.h node_dump.$(OBJEXT): {$(VPATH)}encoding.h node_dump.$(OBJEXT): {$(VPATH)}id.h @@ -10324,6 +11860,7 @@ node_dump.$(OBJEXT): {$(VPATH)}internal/intern/re.h node_dump.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h node_dump.$(OBJEXT): {$(VPATH)}internal/intern/select.h node_dump.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +node_dump.$(OBJEXT): {$(VPATH)}internal/intern/set.h node_dump.$(OBJEXT): {$(VPATH)}internal/intern/signal.h node_dump.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h node_dump.$(OBJEXT): {$(VPATH)}internal/intern/string.h @@ -10343,6 +11880,7 @@ node_dump.$(OBJEXT): {$(VPATH)}internal/special_consts.h node_dump.$(OBJEXT): {$(VPATH)}internal/static_assert.h node_dump.$(OBJEXT): {$(VPATH)}internal/stdalign.h node_dump.$(OBJEXT): {$(VPATH)}internal/stdbool.h +node_dump.$(OBJEXT): {$(VPATH)}internal/stdckdint.h node_dump.$(OBJEXT): {$(VPATH)}internal/symbol.h node_dump.$(OBJEXT): {$(VPATH)}internal/value.h node_dump.$(OBJEXT): {$(VPATH)}internal/value_type.h @@ -10364,7 +11902,9 @@ node_dump.$(OBJEXT): {$(VPATH)}subst.h node_dump.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h node_dump.$(OBJEXT): {$(VPATH)}thread_native.h node_dump.$(OBJEXT): {$(VPATH)}vm_core.h +node_dump.$(OBJEXT): {$(VPATH)}vm_debug.h node_dump.$(OBJEXT): {$(VPATH)}vm_opts.h +node_dump.$(OBJEXT): {$(VPATH)}vm_sync.h numeric.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h numeric.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h numeric.$(OBJEXT): $(CCAN_DIR)/list/list.h @@ -10382,10 +11922,13 @@ numeric.$(OBJEXT): $(top_srcdir)/internal/fixnum.h numeric.$(OBJEXT): $(top_srcdir)/internal/gc.h numeric.$(OBJEXT): $(top_srcdir)/internal/hash.h numeric.$(OBJEXT): $(top_srcdir)/internal/imemo.h +numeric.$(OBJEXT): $(top_srcdir)/internal/namespace.h numeric.$(OBJEXT): $(top_srcdir)/internal/numeric.h numeric.$(OBJEXT): $(top_srcdir)/internal/object.h numeric.$(OBJEXT): $(top_srcdir)/internal/rational.h +numeric.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h numeric.$(OBJEXT): $(top_srcdir)/internal/serial.h +numeric.$(OBJEXT): $(top_srcdir)/internal/set_table.h numeric.$(OBJEXT): $(top_srcdir)/internal/static_assert.h numeric.$(OBJEXT): $(top_srcdir)/internal/string.h numeric.$(OBJEXT): $(top_srcdir)/internal/util.h @@ -10535,6 +12078,7 @@ numeric.$(OBJEXT): {$(VPATH)}internal/intern/re.h numeric.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h numeric.$(OBJEXT): {$(VPATH)}internal/intern/select.h numeric.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +numeric.$(OBJEXT): {$(VPATH)}internal/intern/set.h numeric.$(OBJEXT): {$(VPATH)}internal/intern/signal.h numeric.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h numeric.$(OBJEXT): {$(VPATH)}internal/intern/string.h @@ -10554,6 +12098,7 @@ numeric.$(OBJEXT): {$(VPATH)}internal/special_consts.h numeric.$(OBJEXT): {$(VPATH)}internal/static_assert.h numeric.$(OBJEXT): {$(VPATH)}internal/stdalign.h numeric.$(OBJEXT): {$(VPATH)}internal/stdbool.h +numeric.$(OBJEXT): {$(VPATH)}internal/stdckdint.h numeric.$(OBJEXT): {$(VPATH)}internal/symbol.h numeric.$(OBJEXT): {$(VPATH)}internal/value.h numeric.$(OBJEXT): {$(VPATH)}internal/value_type.h @@ -10583,6 +12128,7 @@ object.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h object.$(OBJEXT): $(CCAN_DIR)/list/list.h object.$(OBJEXT): $(CCAN_DIR)/str/str.h object.$(OBJEXT): $(hdrdir)/ruby/ruby.h +object.$(OBJEXT): $(hdrdir)/ruby/version.h object.$(OBJEXT): $(top_srcdir)/internal/array.h object.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h object.$(OBJEXT): $(top_srcdir)/internal/bignum.h @@ -10595,9 +12141,13 @@ object.$(OBJEXT): $(top_srcdir)/internal/fixnum.h object.$(OBJEXT): $(top_srcdir)/internal/gc.h object.$(OBJEXT): $(top_srcdir)/internal/imemo.h object.$(OBJEXT): $(top_srcdir)/internal/inits.h +object.$(OBJEXT): $(top_srcdir)/internal/namespace.h object.$(OBJEXT): $(top_srcdir)/internal/numeric.h object.$(OBJEXT): $(top_srcdir)/internal/object.h +object.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h object.$(OBJEXT): $(top_srcdir)/internal/serial.h +object.$(OBJEXT): $(top_srcdir)/internal/set_table.h +object.$(OBJEXT): $(top_srcdir)/internal/st.h object.$(OBJEXT): $(top_srcdir)/internal/static_assert.h object.$(OBJEXT): $(top_srcdir)/internal/string.h object.$(OBJEXT): $(top_srcdir)/internal/struct.h @@ -10619,6 +12169,7 @@ object.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h object.$(OBJEXT): {$(VPATH)}builtin.h object.$(OBJEXT): {$(VPATH)}config.h object.$(OBJEXT): {$(VPATH)}constant.h +object.$(OBJEXT): {$(VPATH)}debug_counter.h object.$(OBJEXT): {$(VPATH)}defines.h object.$(OBJEXT): {$(VPATH)}encoding.h object.$(OBJEXT): {$(VPATH)}id.h @@ -10748,6 +12299,7 @@ object.$(OBJEXT): {$(VPATH)}internal/intern/re.h object.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h object.$(OBJEXT): {$(VPATH)}internal/intern/select.h object.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +object.$(OBJEXT): {$(VPATH)}internal/intern/set.h object.$(OBJEXT): {$(VPATH)}internal/intern/signal.h object.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h object.$(OBJEXT): {$(VPATH)}internal/intern/string.h @@ -10764,9 +12316,11 @@ object.$(OBJEXT): {$(VPATH)}internal/module.h object.$(OBJEXT): {$(VPATH)}internal/newobj.h object.$(OBJEXT): {$(VPATH)}internal/scan_args.h object.$(OBJEXT): {$(VPATH)}internal/special_consts.h +object.$(OBJEXT): {$(VPATH)}internal/st.h object.$(OBJEXT): {$(VPATH)}internal/static_assert.h object.$(OBJEXT): {$(VPATH)}internal/stdalign.h object.$(OBJEXT): {$(VPATH)}internal/stdbool.h +object.$(OBJEXT): {$(VPATH)}internal/stdckdint.h object.$(OBJEXT): {$(VPATH)}internal/symbol.h object.$(OBJEXT): {$(VPATH)}internal/value.h object.$(OBJEXT): {$(VPATH)}internal/value_type.h @@ -10794,7 +12348,10 @@ object.$(OBJEXT): {$(VPATH)}thread_native.h object.$(OBJEXT): {$(VPATH)}util.h object.$(OBJEXT): {$(VPATH)}variable.h object.$(OBJEXT): {$(VPATH)}vm_core.h +object.$(OBJEXT): {$(VPATH)}vm_debug.h object.$(OBJEXT): {$(VPATH)}vm_opts.h +object.$(OBJEXT): {$(VPATH)}vm_sync.h +object.$(OBJEXT): {$(VPATH)}yjit.h pack.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h pack.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h pack.$(OBJEXT): $(CCAN_DIR)/list/list.h @@ -10806,7 +12363,10 @@ pack.$(OBJEXT): $(top_srcdir)/internal/bits.h pack.$(OBJEXT): $(top_srcdir)/internal/compilers.h pack.$(OBJEXT): $(top_srcdir)/internal/gc.h pack.$(OBJEXT): $(top_srcdir)/internal/imemo.h +pack.$(OBJEXT): $(top_srcdir)/internal/namespace.h +pack.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h pack.$(OBJEXT): $(top_srcdir)/internal/serial.h +pack.$(OBJEXT): $(top_srcdir)/internal/set_table.h pack.$(OBJEXT): $(top_srcdir)/internal/static_assert.h pack.$(OBJEXT): $(top_srcdir)/internal/string.h pack.$(OBJEXT): $(top_srcdir)/internal/symbol.h @@ -10956,6 +12516,7 @@ pack.$(OBJEXT): {$(VPATH)}internal/intern/re.h pack.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h pack.$(OBJEXT): {$(VPATH)}internal/intern/select.h pack.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +pack.$(OBJEXT): {$(VPATH)}internal/intern/set.h pack.$(OBJEXT): {$(VPATH)}internal/intern/signal.h pack.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h pack.$(OBJEXT): {$(VPATH)}internal/intern/string.h @@ -10975,6 +12536,7 @@ pack.$(OBJEXT): {$(VPATH)}internal/special_consts.h pack.$(OBJEXT): {$(VPATH)}internal/static_assert.h pack.$(OBJEXT): {$(VPATH)}internal/stdalign.h pack.$(OBJEXT): {$(VPATH)}internal/stdbool.h +pack.$(OBJEXT): {$(VPATH)}internal/stdckdint.h pack.$(OBJEXT): {$(VPATH)}internal/symbol.h pack.$(OBJEXT): {$(VPATH)}internal/value.h pack.$(OBJEXT): {$(VPATH)}internal/value_type.h @@ -11005,6 +12567,7 @@ parse.$(OBJEXT): $(CCAN_DIR)/list/list.h parse.$(OBJEXT): $(CCAN_DIR)/str/str.h parse.$(OBJEXT): $(hdrdir)/ruby.h parse.$(OBJEXT): $(hdrdir)/ruby/ruby.h +parse.$(OBJEXT): $(hdrdir)/ruby/version.h parse.$(OBJEXT): $(top_srcdir)/internal/array.h parse.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h parse.$(OBJEXT): $(top_srcdir)/internal/bignum.h @@ -11019,12 +12582,15 @@ parse.$(OBJEXT): $(top_srcdir)/internal/gc.h parse.$(OBJEXT): $(top_srcdir)/internal/hash.h parse.$(OBJEXT): $(top_srcdir)/internal/imemo.h parse.$(OBJEXT): $(top_srcdir)/internal/io.h +parse.$(OBJEXT): $(top_srcdir)/internal/namespace.h parse.$(OBJEXT): $(top_srcdir)/internal/numeric.h parse.$(OBJEXT): $(top_srcdir)/internal/parse.h parse.$(OBJEXT): $(top_srcdir)/internal/rational.h parse.$(OBJEXT): $(top_srcdir)/internal/re.h parse.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h +parse.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h parse.$(OBJEXT): $(top_srcdir)/internal/serial.h +parse.$(OBJEXT): $(top_srcdir)/internal/set_table.h parse.$(OBJEXT): $(top_srcdir)/internal/static_assert.h parse.$(OBJEXT): $(top_srcdir)/internal/string.h parse.$(OBJEXT): $(top_srcdir)/internal/symbol.h @@ -11175,6 +12741,7 @@ parse.$(OBJEXT): {$(VPATH)}internal/intern/re.h parse.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h parse.$(OBJEXT): {$(VPATH)}internal/intern/select.h parse.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +parse.$(OBJEXT): {$(VPATH)}internal/intern/set.h parse.$(OBJEXT): {$(VPATH)}internal/intern/signal.h parse.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h parse.$(OBJEXT): {$(VPATH)}internal/intern/string.h @@ -11194,6 +12761,7 @@ parse.$(OBJEXT): {$(VPATH)}internal/special_consts.h parse.$(OBJEXT): {$(VPATH)}internal/static_assert.h parse.$(OBJEXT): {$(VPATH)}internal/stdalign.h parse.$(OBJEXT): {$(VPATH)}internal/stdbool.h +parse.$(OBJEXT): {$(VPATH)}internal/stdckdint.h parse.$(OBJEXT): {$(VPATH)}internal/symbol.h parse.$(OBJEXT): {$(VPATH)}internal/value.h parse.$(OBJEXT): {$(VPATH)}internal/value_type.h @@ -11292,11 +12860,1003 @@ parser_st.$(OBJEXT): {$(VPATH)}parser_st.c parser_st.$(OBJEXT): {$(VPATH)}parser_st.h parser_st.$(OBJEXT): {$(VPATH)}parser_value.h parser_st.$(OBJEXT): {$(VPATH)}st.c +prism/api_node.$(OBJEXT): $(hdrdir)/ruby.h +prism/api_node.$(OBJEXT): $(hdrdir)/ruby/ruby.h +prism/api_node.$(OBJEXT): $(top_srcdir)/prism/defines.h +prism/api_node.$(OBJEXT): $(top_srcdir)/prism/encoding.h +prism/api_node.$(OBJEXT): $(top_srcdir)/prism/extension.h +prism/api_node.$(OBJEXT): $(top_srcdir)/prism/node.h +prism/api_node.$(OBJEXT): $(top_srcdir)/prism/options.h +prism/api_node.$(OBJEXT): $(top_srcdir)/prism/pack.h +prism/api_node.$(OBJEXT): $(top_srcdir)/prism/parser.h +prism/api_node.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h +prism/api_node.$(OBJEXT): $(top_srcdir)/prism/prism.h +prism/api_node.$(OBJEXT): $(top_srcdir)/prism/regexp.h +prism/api_node.$(OBJEXT): $(top_srcdir)/prism/static_literals.h +prism/api_node.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h +prism/api_node.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h +prism/api_node.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h +prism/api_node.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h +prism/api_node.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h +prism/api_node.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h +prism/api_node.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h +prism/api_node.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h +prism/api_node.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h +prism/api_node.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h +prism/api_node.$(OBJEXT): {$(VPATH)}assert.h +prism/api_node.$(OBJEXT): {$(VPATH)}backward/2/assume.h +prism/api_node.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +prism/api_node.$(OBJEXT): {$(VPATH)}backward/2/bool.h +prism/api_node.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +prism/api_node.$(OBJEXT): {$(VPATH)}backward/2/limits.h +prism/api_node.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +prism/api_node.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +prism/api_node.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h +prism/api_node.$(OBJEXT): {$(VPATH)}config.h +prism/api_node.$(OBJEXT): {$(VPATH)}defines.h +prism/api_node.$(OBJEXT): {$(VPATH)}encoding.h +prism/api_node.$(OBJEXT): {$(VPATH)}intern.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/abi.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/anyargs.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/assume.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/attr/const.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/attr/error.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/attr/format.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/attr/packed_struct.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/cast.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/config.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/constant_p.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/core.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/core/robject.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/ctype.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/dllexport.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/dosish.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/encoding/re.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/encoding/string.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/error.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/eval.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/event.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/fl_type.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/gc.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/glob.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/globals.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/has/extension.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/has/feature.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/has/warning.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/array.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/class.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/error.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/file.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/io.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/load.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/object.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/process.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/random.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/range.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/re.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/select.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/set.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/signal.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/string.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/time.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/interpreter.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/iterator.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/memory.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/method.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/module.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/newobj.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/scan_args.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/special_consts.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/static_assert.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/stdalign.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/stdbool.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/stdckdint.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/symbol.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/value.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/value_type.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/variable.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/warning_push.h +prism/api_node.$(OBJEXT): {$(VPATH)}internal/xmalloc.h +prism/api_node.$(OBJEXT): {$(VPATH)}missing.h +prism/api_node.$(OBJEXT): {$(VPATH)}onigmo.h +prism/api_node.$(OBJEXT): {$(VPATH)}oniguruma.h +prism/api_node.$(OBJEXT): {$(VPATH)}prism/api_node.c +prism/api_node.$(OBJEXT): {$(VPATH)}prism/ast.h +prism/api_node.$(OBJEXT): {$(VPATH)}prism/diagnostic.h +prism/api_node.$(OBJEXT): {$(VPATH)}prism/version.h +prism/api_node.$(OBJEXT): {$(VPATH)}st.h +prism/api_node.$(OBJEXT): {$(VPATH)}subst.h +prism/api_pack.$(OBJEXT): $(hdrdir)/ruby.h +prism/api_pack.$(OBJEXT): $(hdrdir)/ruby/ruby.h +prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/api_pack.c +prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/defines.h +prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/encoding.h +prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/extension.h +prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/node.h +prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/options.h +prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/pack.h +prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/parser.h +prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h +prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/prism.h +prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/regexp.h +prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/static_literals.h +prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h +prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h +prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h +prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h +prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h +prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h +prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h +prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h +prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h +prism/api_pack.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h +prism/api_pack.$(OBJEXT): {$(VPATH)}assert.h +prism/api_pack.$(OBJEXT): {$(VPATH)}backward/2/assume.h +prism/api_pack.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +prism/api_pack.$(OBJEXT): {$(VPATH)}backward/2/bool.h +prism/api_pack.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +prism/api_pack.$(OBJEXT): {$(VPATH)}backward/2/limits.h +prism/api_pack.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +prism/api_pack.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +prism/api_pack.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h +prism/api_pack.$(OBJEXT): {$(VPATH)}config.h +prism/api_pack.$(OBJEXT): {$(VPATH)}defines.h +prism/api_pack.$(OBJEXT): {$(VPATH)}encoding.h +prism/api_pack.$(OBJEXT): {$(VPATH)}intern.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/abi.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/anyargs.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/assume.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/const.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/error.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/format.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/packed_struct.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/cast.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/config.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/constant_p.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/core.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/core/robject.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/ctype.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/dllexport.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/dosish.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/encoding/re.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/encoding/string.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/error.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/eval.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/event.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/fl_type.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/gc.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/glob.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/globals.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/has/extension.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/has/feature.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/has/warning.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/array.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/class.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/error.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/file.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/io.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/load.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/object.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/process.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/random.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/range.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/re.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/select.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/set.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/signal.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/string.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/time.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/interpreter.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/iterator.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/memory.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/method.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/module.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/newobj.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/scan_args.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/special_consts.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/static_assert.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/stdalign.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/stdbool.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/stdckdint.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/symbol.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/value.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/value_type.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/variable.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/warning_push.h +prism/api_pack.$(OBJEXT): {$(VPATH)}internal/xmalloc.h +prism/api_pack.$(OBJEXT): {$(VPATH)}missing.h +prism/api_pack.$(OBJEXT): {$(VPATH)}onigmo.h +prism/api_pack.$(OBJEXT): {$(VPATH)}oniguruma.h +prism/api_pack.$(OBJEXT): {$(VPATH)}prism/ast.h +prism/api_pack.$(OBJEXT): {$(VPATH)}prism/diagnostic.h +prism/api_pack.$(OBJEXT): {$(VPATH)}prism/version.h +prism/api_pack.$(OBJEXT): {$(VPATH)}st.h +prism/api_pack.$(OBJEXT): {$(VPATH)}subst.h +prism/diagnostic.$(OBJEXT): $(top_srcdir)/prism/defines.h +prism/diagnostic.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h +prism/diagnostic.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h +prism/diagnostic.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h +prism/diagnostic.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h +prism/diagnostic.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h +prism/diagnostic.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h +prism/diagnostic.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h +prism/diagnostic.$(OBJEXT): {$(VPATH)}prism/ast.h +prism/diagnostic.$(OBJEXT): {$(VPATH)}prism/diagnostic.c +prism/diagnostic.$(OBJEXT): {$(VPATH)}prism/diagnostic.h +prism/encoding.$(OBJEXT): $(top_srcdir)/prism/defines.h +prism/encoding.$(OBJEXT): $(top_srcdir)/prism/encoding.c +prism/encoding.$(OBJEXT): $(top_srcdir)/prism/encoding.h +prism/encoding.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h +prism/extension.$(OBJEXT): $(hdrdir)/ruby.h +prism/extension.$(OBJEXT): $(hdrdir)/ruby/ruby.h +prism/extension.$(OBJEXT): $(top_srcdir)/prism/defines.h +prism/extension.$(OBJEXT): $(top_srcdir)/prism/encoding.h +prism/extension.$(OBJEXT): $(top_srcdir)/prism/extension.c +prism/extension.$(OBJEXT): $(top_srcdir)/prism/extension.h +prism/extension.$(OBJEXT): $(top_srcdir)/prism/node.h +prism/extension.$(OBJEXT): $(top_srcdir)/prism/options.h +prism/extension.$(OBJEXT): $(top_srcdir)/prism/pack.h +prism/extension.$(OBJEXT): $(top_srcdir)/prism/parser.h +prism/extension.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h +prism/extension.$(OBJEXT): $(top_srcdir)/prism/prism.h +prism/extension.$(OBJEXT): $(top_srcdir)/prism/regexp.h +prism/extension.$(OBJEXT): $(top_srcdir)/prism/static_literals.h +prism/extension.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h +prism/extension.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h +prism/extension.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h +prism/extension.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h +prism/extension.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h +prism/extension.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h +prism/extension.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h +prism/extension.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h +prism/extension.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h +prism/extension.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h +prism/extension.$(OBJEXT): {$(VPATH)}assert.h +prism/extension.$(OBJEXT): {$(VPATH)}backward/2/assume.h +prism/extension.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +prism/extension.$(OBJEXT): {$(VPATH)}backward/2/bool.h +prism/extension.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +prism/extension.$(OBJEXT): {$(VPATH)}backward/2/limits.h +prism/extension.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +prism/extension.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +prism/extension.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h +prism/extension.$(OBJEXT): {$(VPATH)}config.h +prism/extension.$(OBJEXT): {$(VPATH)}defines.h +prism/extension.$(OBJEXT): {$(VPATH)}encoding.h +prism/extension.$(OBJEXT): {$(VPATH)}intern.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/abi.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/anyargs.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/assume.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/attr/const.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/attr/error.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/attr/format.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/attr/packed_struct.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/cast.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/config.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/constant_p.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/core.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/core/robject.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/ctype.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/dllexport.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/dosish.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/encoding/re.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/encoding/string.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/error.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/eval.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/event.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/fl_type.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/gc.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/glob.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/globals.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/has/extension.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/has/feature.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/has/warning.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/array.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/class.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/error.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/file.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/io.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/load.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/object.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/process.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/random.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/range.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/re.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/select.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/set.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/signal.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/string.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/time.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/interpreter.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/iterator.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/memory.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/method.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/module.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/newobj.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/scan_args.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/special_consts.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/static_assert.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/stdalign.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/stdbool.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/stdckdint.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/symbol.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/value.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/value_type.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/variable.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/warning_push.h +prism/extension.$(OBJEXT): {$(VPATH)}internal/xmalloc.h +prism/extension.$(OBJEXT): {$(VPATH)}missing.h +prism/extension.$(OBJEXT): {$(VPATH)}onigmo.h +prism/extension.$(OBJEXT): {$(VPATH)}oniguruma.h +prism/extension.$(OBJEXT): {$(VPATH)}prism/ast.h +prism/extension.$(OBJEXT): {$(VPATH)}prism/diagnostic.h +prism/extension.$(OBJEXT): {$(VPATH)}prism/version.h +prism/extension.$(OBJEXT): {$(VPATH)}st.h +prism/extension.$(OBJEXT): {$(VPATH)}subst.h +prism/node.$(OBJEXT): $(top_srcdir)/prism/defines.h +prism/node.$(OBJEXT): $(top_srcdir)/prism/encoding.h +prism/node.$(OBJEXT): $(top_srcdir)/prism/node.h +prism/node.$(OBJEXT): $(top_srcdir)/prism/options.h +prism/node.$(OBJEXT): $(top_srcdir)/prism/pack.h +prism/node.$(OBJEXT): $(top_srcdir)/prism/parser.h +prism/node.$(OBJEXT): $(top_srcdir)/prism/prism.h +prism/node.$(OBJEXT): $(top_srcdir)/prism/regexp.h +prism/node.$(OBJEXT): $(top_srcdir)/prism/static_literals.h +prism/node.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h +prism/node.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h +prism/node.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h +prism/node.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h +prism/node.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h +prism/node.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h +prism/node.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h +prism/node.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h +prism/node.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h +prism/node.$(OBJEXT): {$(VPATH)}prism/ast.h +prism/node.$(OBJEXT): {$(VPATH)}prism/diagnostic.h +prism/node.$(OBJEXT): {$(VPATH)}prism/node.c +prism/options.$(OBJEXT): $(top_srcdir)/prism/defines.h +prism/options.$(OBJEXT): $(top_srcdir)/prism/options.c +prism/options.$(OBJEXT): $(top_srcdir)/prism/options.h +prism/options.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h +prism/options.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h +prism/options.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h +prism/pack.$(OBJEXT): $(top_srcdir)/prism/defines.h +prism/pack.$(OBJEXT): $(top_srcdir)/prism/pack.c +prism/pack.$(OBJEXT): $(top_srcdir)/prism/pack.h +prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/defines.h +prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/encoding.h +prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/options.h +prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/parser.h +prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h +prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/static_literals.h +prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h +prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h +prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h +prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h +prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h +prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h +prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h +prism/prettyprint.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h +prism/prettyprint.$(OBJEXT): {$(VPATH)}prism/ast.h +prism/prettyprint.$(OBJEXT): {$(VPATH)}prism/prettyprint.c +prism/prism.$(OBJEXT): $(top_srcdir)/prism/defines.h +prism/prism.$(OBJEXT): $(top_srcdir)/prism/encoding.h +prism/prism.$(OBJEXT): $(top_srcdir)/prism/node.h +prism/prism.$(OBJEXT): $(top_srcdir)/prism/options.h +prism/prism.$(OBJEXT): $(top_srcdir)/prism/pack.h +prism/prism.$(OBJEXT): $(top_srcdir)/prism/parser.h +prism/prism.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h +prism/prism.$(OBJEXT): $(top_srcdir)/prism/prism.c +prism/prism.$(OBJEXT): $(top_srcdir)/prism/prism.h +prism/prism.$(OBJEXT): $(top_srcdir)/prism/regexp.h +prism/prism.$(OBJEXT): $(top_srcdir)/prism/static_literals.h +prism/prism.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h +prism/prism.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h +prism/prism.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h +prism/prism.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h +prism/prism.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h +prism/prism.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h +prism/prism.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h +prism/prism.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h +prism/prism.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h +prism/prism.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h +prism/prism.$(OBJEXT): $(top_srcdir)/prism/version.h +prism/prism.$(OBJEXT): {$(VPATH)}prism/ast.h +prism/prism.$(OBJEXT): {$(VPATH)}prism/diagnostic.h +prism/prism.$(OBJEXT): {$(VPATH)}prism/version.h +prism/regexp.$(OBJEXT): $(top_srcdir)/prism/defines.h +prism/regexp.$(OBJEXT): $(top_srcdir)/prism/encoding.h +prism/regexp.$(OBJEXT): $(top_srcdir)/prism/options.h +prism/regexp.$(OBJEXT): $(top_srcdir)/prism/parser.h +prism/regexp.$(OBJEXT): $(top_srcdir)/prism/regexp.c +prism/regexp.$(OBJEXT): $(top_srcdir)/prism/regexp.h +prism/regexp.$(OBJEXT): $(top_srcdir)/prism/static_literals.h +prism/regexp.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h +prism/regexp.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h +prism/regexp.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h +prism/regexp.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h +prism/regexp.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h +prism/regexp.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h +prism/regexp.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h +prism/regexp.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h +prism/regexp.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h +prism/regexp.$(OBJEXT): {$(VPATH)}prism/ast.h +prism/serialize.$(OBJEXT): $(top_srcdir)/prism/defines.h +prism/serialize.$(OBJEXT): $(top_srcdir)/prism/encoding.h +prism/serialize.$(OBJEXT): $(top_srcdir)/prism/node.h +prism/serialize.$(OBJEXT): $(top_srcdir)/prism/options.h +prism/serialize.$(OBJEXT): $(top_srcdir)/prism/pack.h +prism/serialize.$(OBJEXT): $(top_srcdir)/prism/parser.h +prism/serialize.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h +prism/serialize.$(OBJEXT): $(top_srcdir)/prism/prism.h +prism/serialize.$(OBJEXT): $(top_srcdir)/prism/regexp.h +prism/serialize.$(OBJEXT): $(top_srcdir)/prism/static_literals.h +prism/serialize.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h +prism/serialize.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h +prism/serialize.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h +prism/serialize.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h +prism/serialize.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h +prism/serialize.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h +prism/serialize.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h +prism/serialize.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h +prism/serialize.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h +prism/serialize.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h +prism/serialize.$(OBJEXT): {$(VPATH)}prism/ast.h +prism/serialize.$(OBJEXT): {$(VPATH)}prism/diagnostic.h +prism/serialize.$(OBJEXT): {$(VPATH)}prism/serialize.c +prism/serialize.$(OBJEXT): {$(VPATH)}prism/version.h +prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/defines.h +prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/encoding.h +prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/node.h +prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/options.h +prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/parser.h +prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/static_literals.c +prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/static_literals.h +prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h +prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h +prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h +prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h +prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h +prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h +prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h +prism/static_literals.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h +prism/static_literals.$(OBJEXT): {$(VPATH)}prism/ast.h +prism/token_type.$(OBJEXT): $(top_srcdir)/prism/defines.h +prism/token_type.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h +prism/token_type.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h +prism/token_type.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h +prism/token_type.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h +prism/token_type.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h +prism/token_type.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h +prism/token_type.$(OBJEXT): {$(VPATH)}prism/ast.h +prism/token_type.$(OBJEXT): {$(VPATH)}prism/token_type.c +prism/util/pm_buffer.$(OBJEXT): $(top_srcdir)/prism/defines.h +prism/util/pm_buffer.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.c +prism/util/pm_buffer.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h +prism/util/pm_buffer.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h +prism/util/pm_buffer.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h +prism/util/pm_char.$(OBJEXT): $(top_srcdir)/prism/defines.h +prism/util/pm_char.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.c +prism/util/pm_char.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h +prism/util/pm_char.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h +prism/util/pm_constant_pool.$(OBJEXT): $(top_srcdir)/prism/defines.h +prism/util/pm_constant_pool.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.c +prism/util/pm_constant_pool.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h +prism/util/pm_integer.$(OBJEXT): $(top_srcdir)/prism/defines.h +prism/util/pm_integer.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h +prism/util/pm_integer.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h +prism/util/pm_integer.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.c +prism/util/pm_integer.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h +prism/util/pm_integer.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h +prism/util/pm_list.$(OBJEXT): $(top_srcdir)/prism/defines.h +prism/util/pm_list.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.c +prism/util/pm_list.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h +prism/util/pm_memchr.$(OBJEXT): $(top_srcdir)/prism/defines.h +prism/util/pm_memchr.$(OBJEXT): $(top_srcdir)/prism/encoding.h +prism/util/pm_memchr.$(OBJEXT): $(top_srcdir)/prism/parser.h +prism/util/pm_memchr.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h +prism/util/pm_memchr.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h +prism/util/pm_memchr.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.c +prism/util/pm_memchr.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h +prism/util/pm_memchr.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h +prism/util/pm_memchr.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h +prism/util/pm_memchr.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h +prism/util/pm_memchr.$(OBJEXT): {$(VPATH)}prism/ast.h +prism/util/pm_newline_list.$(OBJEXT): $(top_srcdir)/prism/defines.h +prism/util/pm_newline_list.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.c +prism/util/pm_newline_list.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h +prism/util/pm_string.$(OBJEXT): $(top_srcdir)/prism/defines.h +prism/util/pm_string.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.c +prism/util/pm_string.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h +prism/util/pm_strncasecmp.$(OBJEXT): $(top_srcdir)/prism/defines.h +prism/util/pm_strncasecmp.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.c +prism/util/pm_strncasecmp.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h +prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/defines.h +prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/encoding.h +prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/options.h +prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/parser.h +prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/static_literals.h +prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h +prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h +prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h +prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h +prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h +prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h +prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h +prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h +prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.c +prism/util/pm_strpbrk.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h +prism/util/pm_strpbrk.$(OBJEXT): {$(VPATH)}prism/ast.h +prism/util/pm_strpbrk.$(OBJEXT): {$(VPATH)}prism/diagnostic.h +prism_init.$(OBJEXT): $(hdrdir)/ruby.h +prism_init.$(OBJEXT): $(hdrdir)/ruby/ruby.h +prism_init.$(OBJEXT): $(top_srcdir)/prism/defines.h +prism_init.$(OBJEXT): $(top_srcdir)/prism/encoding.h +prism_init.$(OBJEXT): $(top_srcdir)/prism/extension.h +prism_init.$(OBJEXT): $(top_srcdir)/prism/node.h +prism_init.$(OBJEXT): $(top_srcdir)/prism/options.h +prism_init.$(OBJEXT): $(top_srcdir)/prism/pack.h +prism_init.$(OBJEXT): $(top_srcdir)/prism/parser.h +prism_init.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h +prism_init.$(OBJEXT): $(top_srcdir)/prism/prism.h +prism_init.$(OBJEXT): $(top_srcdir)/prism/regexp.h +prism_init.$(OBJEXT): $(top_srcdir)/prism/static_literals.h +prism_init.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h +prism_init.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h +prism_init.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h +prism_init.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h +prism_init.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h +prism_init.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h +prism_init.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h +prism_init.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h +prism_init.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h +prism_init.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h +prism_init.$(OBJEXT): $(top_srcdir)/prism_init.c +prism_init.$(OBJEXT): {$(VPATH)}assert.h +prism_init.$(OBJEXT): {$(VPATH)}backward/2/assume.h +prism_init.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +prism_init.$(OBJEXT): {$(VPATH)}backward/2/bool.h +prism_init.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +prism_init.$(OBJEXT): {$(VPATH)}backward/2/limits.h +prism_init.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +prism_init.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +prism_init.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h +prism_init.$(OBJEXT): {$(VPATH)}config.h +prism_init.$(OBJEXT): {$(VPATH)}defines.h +prism_init.$(OBJEXT): {$(VPATH)}encoding.h +prism_init.$(OBJEXT): {$(VPATH)}intern.h +prism_init.$(OBJEXT): {$(VPATH)}internal/abi.h +prism_init.$(OBJEXT): {$(VPATH)}internal/anyargs.h +prism_init.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +prism_init.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +prism_init.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +prism_init.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +prism_init.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +prism_init.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +prism_init.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +prism_init.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +prism_init.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +prism_init.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +prism_init.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +prism_init.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +prism_init.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +prism_init.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +prism_init.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +prism_init.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +prism_init.$(OBJEXT): {$(VPATH)}internal/assume.h +prism_init.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +prism_init.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +prism_init.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +prism_init.$(OBJEXT): {$(VPATH)}internal/attr/const.h +prism_init.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +prism_init.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +prism_init.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +prism_init.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +prism_init.$(OBJEXT): {$(VPATH)}internal/attr/error.h +prism_init.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +prism_init.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +prism_init.$(OBJEXT): {$(VPATH)}internal/attr/format.h +prism_init.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +prism_init.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +prism_init.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +prism_init.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +prism_init.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +prism_init.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +prism_init.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +prism_init.$(OBJEXT): {$(VPATH)}internal/attr/packed_struct.h +prism_init.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +prism_init.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +prism_init.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +prism_init.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +prism_init.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +prism_init.$(OBJEXT): {$(VPATH)}internal/cast.h +prism_init.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +prism_init.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +prism_init.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +prism_init.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +prism_init.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +prism_init.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +prism_init.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +prism_init.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +prism_init.$(OBJEXT): {$(VPATH)}internal/config.h +prism_init.$(OBJEXT): {$(VPATH)}internal/constant_p.h +prism_init.$(OBJEXT): {$(VPATH)}internal/core.h +prism_init.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +prism_init.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +prism_init.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +prism_init.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +prism_init.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +prism_init.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +prism_init.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +prism_init.$(OBJEXT): {$(VPATH)}internal/core/robject.h +prism_init.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +prism_init.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +prism_init.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +prism_init.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +prism_init.$(OBJEXT): {$(VPATH)}internal/ctype.h +prism_init.$(OBJEXT): {$(VPATH)}internal/dllexport.h +prism_init.$(OBJEXT): {$(VPATH)}internal/dosish.h +prism_init.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h +prism_init.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h +prism_init.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h +prism_init.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h +prism_init.$(OBJEXT): {$(VPATH)}internal/encoding/re.h +prism_init.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h +prism_init.$(OBJEXT): {$(VPATH)}internal/encoding/string.h +prism_init.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h +prism_init.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h +prism_init.$(OBJEXT): {$(VPATH)}internal/error.h +prism_init.$(OBJEXT): {$(VPATH)}internal/eval.h +prism_init.$(OBJEXT): {$(VPATH)}internal/event.h +prism_init.$(OBJEXT): {$(VPATH)}internal/fl_type.h +prism_init.$(OBJEXT): {$(VPATH)}internal/gc.h +prism_init.$(OBJEXT): {$(VPATH)}internal/glob.h +prism_init.$(OBJEXT): {$(VPATH)}internal/globals.h +prism_init.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +prism_init.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +prism_init.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +prism_init.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +prism_init.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +prism_init.$(OBJEXT): {$(VPATH)}internal/has/extension.h +prism_init.$(OBJEXT): {$(VPATH)}internal/has/feature.h +prism_init.$(OBJEXT): {$(VPATH)}internal/has/warning.h +prism_init.$(OBJEXT): {$(VPATH)}internal/intern/array.h +prism_init.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +prism_init.$(OBJEXT): {$(VPATH)}internal/intern/class.h +prism_init.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +prism_init.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +prism_init.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +prism_init.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +prism_init.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +prism_init.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +prism_init.$(OBJEXT): {$(VPATH)}internal/intern/error.h +prism_init.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +prism_init.$(OBJEXT): {$(VPATH)}internal/intern/file.h +prism_init.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +prism_init.$(OBJEXT): {$(VPATH)}internal/intern/io.h +prism_init.$(OBJEXT): {$(VPATH)}internal/intern/load.h +prism_init.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +prism_init.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +prism_init.$(OBJEXT): {$(VPATH)}internal/intern/object.h +prism_init.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +prism_init.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +prism_init.$(OBJEXT): {$(VPATH)}internal/intern/process.h +prism_init.$(OBJEXT): {$(VPATH)}internal/intern/random.h +prism_init.$(OBJEXT): {$(VPATH)}internal/intern/range.h +prism_init.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +prism_init.$(OBJEXT): {$(VPATH)}internal/intern/re.h +prism_init.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h +prism_init.$(OBJEXT): {$(VPATH)}internal/intern/select.h +prism_init.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +prism_init.$(OBJEXT): {$(VPATH)}internal/intern/set.h +prism_init.$(OBJEXT): {$(VPATH)}internal/intern/signal.h +prism_init.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +prism_init.$(OBJEXT): {$(VPATH)}internal/intern/string.h +prism_init.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +prism_init.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +prism_init.$(OBJEXT): {$(VPATH)}internal/intern/time.h +prism_init.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +prism_init.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +prism_init.$(OBJEXT): {$(VPATH)}internal/interpreter.h +prism_init.$(OBJEXT): {$(VPATH)}internal/iterator.h +prism_init.$(OBJEXT): {$(VPATH)}internal/memory.h +prism_init.$(OBJEXT): {$(VPATH)}internal/method.h +prism_init.$(OBJEXT): {$(VPATH)}internal/module.h +prism_init.$(OBJEXT): {$(VPATH)}internal/newobj.h +prism_init.$(OBJEXT): {$(VPATH)}internal/scan_args.h +prism_init.$(OBJEXT): {$(VPATH)}internal/special_consts.h +prism_init.$(OBJEXT): {$(VPATH)}internal/static_assert.h +prism_init.$(OBJEXT): {$(VPATH)}internal/stdalign.h +prism_init.$(OBJEXT): {$(VPATH)}internal/stdbool.h +prism_init.$(OBJEXT): {$(VPATH)}internal/stdckdint.h +prism_init.$(OBJEXT): {$(VPATH)}internal/symbol.h +prism_init.$(OBJEXT): {$(VPATH)}internal/value.h +prism_init.$(OBJEXT): {$(VPATH)}internal/value_type.h +prism_init.$(OBJEXT): {$(VPATH)}internal/variable.h +prism_init.$(OBJEXT): {$(VPATH)}internal/warning_push.h +prism_init.$(OBJEXT): {$(VPATH)}internal/xmalloc.h +prism_init.$(OBJEXT): {$(VPATH)}missing.h +prism_init.$(OBJEXT): {$(VPATH)}onigmo.h +prism_init.$(OBJEXT): {$(VPATH)}oniguruma.h +prism_init.$(OBJEXT): {$(VPATH)}prism/ast.h +prism_init.$(OBJEXT): {$(VPATH)}prism/diagnostic.h +prism_init.$(OBJEXT): {$(VPATH)}prism/version.h +prism_init.$(OBJEXT): {$(VPATH)}prism_init.c +prism_init.$(OBJEXT): {$(VPATH)}st.h +prism_init.$(OBJEXT): {$(VPATH)}subst.h proc.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h proc.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h proc.$(OBJEXT): $(CCAN_DIR)/list/list.h proc.$(OBJEXT): $(CCAN_DIR)/str/str.h proc.$(OBJEXT): $(hdrdir)/ruby/ruby.h +proc.$(OBJEXT): $(hdrdir)/ruby/version.h proc.$(OBJEXT): $(top_srcdir)/internal/array.h proc.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h proc.$(OBJEXT): $(top_srcdir)/internal/class.h @@ -11304,16 +13864,40 @@ proc.$(OBJEXT): $(top_srcdir)/internal/compilers.h proc.$(OBJEXT): $(top_srcdir)/internal/error.h proc.$(OBJEXT): $(top_srcdir)/internal/eval.h proc.$(OBJEXT): $(top_srcdir)/internal/gc.h +proc.$(OBJEXT): $(top_srcdir)/internal/hash.h proc.$(OBJEXT): $(top_srcdir)/internal/imemo.h +proc.$(OBJEXT): $(top_srcdir)/internal/namespace.h proc.$(OBJEXT): $(top_srcdir)/internal/object.h proc.$(OBJEXT): $(top_srcdir)/internal/proc.h +proc.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h proc.$(OBJEXT): $(top_srcdir)/internal/serial.h +proc.$(OBJEXT): $(top_srcdir)/internal/set_table.h proc.$(OBJEXT): $(top_srcdir)/internal/static_assert.h proc.$(OBJEXT): $(top_srcdir)/internal/string.h proc.$(OBJEXT): $(top_srcdir)/internal/symbol.h proc.$(OBJEXT): $(top_srcdir)/internal/variable.h proc.$(OBJEXT): $(top_srcdir)/internal/vm.h proc.$(OBJEXT): $(top_srcdir)/internal/warnings.h +proc.$(OBJEXT): $(top_srcdir)/prism/defines.h +proc.$(OBJEXT): $(top_srcdir)/prism/encoding.h +proc.$(OBJEXT): $(top_srcdir)/prism/node.h +proc.$(OBJEXT): $(top_srcdir)/prism/options.h +proc.$(OBJEXT): $(top_srcdir)/prism/pack.h +proc.$(OBJEXT): $(top_srcdir)/prism/parser.h +proc.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h +proc.$(OBJEXT): $(top_srcdir)/prism/prism.h +proc.$(OBJEXT): $(top_srcdir)/prism/regexp.h +proc.$(OBJEXT): $(top_srcdir)/prism/static_literals.h +proc.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h +proc.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h +proc.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h +proc.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h +proc.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h +proc.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h +proc.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h +proc.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h +proc.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h +proc.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h proc.$(OBJEXT): {$(VPATH)}assert.h proc.$(OBJEXT): {$(VPATH)}atomic.h proc.$(OBJEXT): {$(VPATH)}backward/2/assume.h @@ -11327,6 +13911,7 @@ proc.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h proc.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h proc.$(OBJEXT): {$(VPATH)}config.h proc.$(OBJEXT): {$(VPATH)}constant.h +proc.$(OBJEXT): {$(VPATH)}debug_counter.h proc.$(OBJEXT): {$(VPATH)}defines.h proc.$(OBJEXT): {$(VPATH)}encoding.h proc.$(OBJEXT): {$(VPATH)}eval_intern.h @@ -11457,6 +14042,7 @@ proc.$(OBJEXT): {$(VPATH)}internal/intern/re.h proc.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h proc.$(OBJEXT): {$(VPATH)}internal/intern/select.h proc.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +proc.$(OBJEXT): {$(VPATH)}internal/intern/set.h proc.$(OBJEXT): {$(VPATH)}internal/intern/signal.h proc.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h proc.$(OBJEXT): {$(VPATH)}internal/intern/string.h @@ -11476,6 +14062,7 @@ proc.$(OBJEXT): {$(VPATH)}internal/special_consts.h proc.$(OBJEXT): {$(VPATH)}internal/static_assert.h proc.$(OBJEXT): {$(VPATH)}internal/stdalign.h proc.$(OBJEXT): {$(VPATH)}internal/stdbool.h +proc.$(OBJEXT): {$(VPATH)}internal/stdckdint.h proc.$(OBJEXT): {$(VPATH)}internal/symbol.h proc.$(OBJEXT): {$(VPATH)}internal/value.h proc.$(OBJEXT): {$(VPATH)}internal/value_type.h @@ -11488,7 +14075,13 @@ proc.$(OBJEXT): {$(VPATH)}missing.h proc.$(OBJEXT): {$(VPATH)}node.h proc.$(OBJEXT): {$(VPATH)}onigmo.h proc.$(OBJEXT): {$(VPATH)}oniguruma.h +proc.$(OBJEXT): {$(VPATH)}prism/ast.h +proc.$(OBJEXT): {$(VPATH)}prism/diagnostic.h +proc.$(OBJEXT): {$(VPATH)}prism/version.h +proc.$(OBJEXT): {$(VPATH)}prism_compile.h proc.$(OBJEXT): {$(VPATH)}proc.c +proc.$(OBJEXT): {$(VPATH)}ractor.h +proc.$(OBJEXT): {$(VPATH)}ractor_core.h proc.$(OBJEXT): {$(VPATH)}ruby_assert.h proc.$(OBJEXT): {$(VPATH)}ruby_atomic.h proc.$(OBJEXT): {$(VPATH)}rubyparser.h @@ -11498,7 +14091,9 @@ proc.$(OBJEXT): {$(VPATH)}subst.h proc.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h proc.$(OBJEXT): {$(VPATH)}thread_native.h proc.$(OBJEXT): {$(VPATH)}vm_core.h +proc.$(OBJEXT): {$(VPATH)}vm_debug.h proc.$(OBJEXT): {$(VPATH)}vm_opts.h +proc.$(OBJEXT): {$(VPATH)}vm_sync.h proc.$(OBJEXT): {$(VPATH)}yjit.h process.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h process.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h @@ -11506,6 +14101,7 @@ process.$(OBJEXT): $(CCAN_DIR)/list/list.h process.$(OBJEXT): $(CCAN_DIR)/str/str.h process.$(OBJEXT): $(hdrdir)/ruby.h process.$(OBJEXT): $(hdrdir)/ruby/ruby.h +process.$(OBJEXT): $(hdrdir)/ruby/version.h process.$(OBJEXT): $(top_srcdir)/internal/array.h process.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h process.$(OBJEXT): $(top_srcdir)/internal/bignum.h @@ -11520,10 +14116,13 @@ process.$(OBJEXT): $(top_srcdir)/internal/gc.h process.$(OBJEXT): $(top_srcdir)/internal/hash.h process.$(OBJEXT): $(top_srcdir)/internal/imemo.h process.$(OBJEXT): $(top_srcdir)/internal/io.h +process.$(OBJEXT): $(top_srcdir)/internal/namespace.h process.$(OBJEXT): $(top_srcdir)/internal/numeric.h process.$(OBJEXT): $(top_srcdir)/internal/object.h process.$(OBJEXT): $(top_srcdir)/internal/process.h +process.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h process.$(OBJEXT): $(top_srcdir)/internal/serial.h +process.$(OBJEXT): $(top_srcdir)/internal/set_table.h process.$(OBJEXT): $(top_srcdir)/internal/static_assert.h process.$(OBJEXT): $(top_srcdir)/internal/string.h process.$(OBJEXT): $(top_srcdir)/internal/thread.h @@ -11677,6 +14276,7 @@ process.$(OBJEXT): {$(VPATH)}internal/intern/re.h process.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h process.$(OBJEXT): {$(VPATH)}internal/intern/select.h process.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +process.$(OBJEXT): {$(VPATH)}internal/intern/set.h process.$(OBJEXT): {$(VPATH)}internal/intern/signal.h process.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h process.$(OBJEXT): {$(VPATH)}internal/intern/string.h @@ -11696,6 +14296,7 @@ process.$(OBJEXT): {$(VPATH)}internal/special_consts.h process.$(OBJEXT): {$(VPATH)}internal/static_assert.h process.$(OBJEXT): {$(VPATH)}internal/stdalign.h process.$(OBJEXT): {$(VPATH)}internal/stdbool.h +process.$(OBJEXT): {$(VPATH)}internal/stdckdint.h process.$(OBJEXT): {$(VPATH)}internal/symbol.h process.$(OBJEXT): {$(VPATH)}internal/value.h process.$(OBJEXT): {$(VPATH)}internal/value_type.h @@ -11710,7 +14311,7 @@ process.$(OBJEXT): {$(VPATH)}onigmo.h process.$(OBJEXT): {$(VPATH)}oniguruma.h process.$(OBJEXT): {$(VPATH)}process.c process.$(OBJEXT): {$(VPATH)}ractor.h -process.$(OBJEXT): {$(VPATH)}rjit.h +process.$(OBJEXT): {$(VPATH)}ractor_core.h process.$(OBJEXT): {$(VPATH)}ruby_assert.h process.$(OBJEXT): {$(VPATH)}ruby_atomic.h process.$(OBJEXT): {$(VPATH)}rubyparser.h @@ -11731,6 +14332,7 @@ ractor.$(OBJEXT): $(CCAN_DIR)/list/list.h ractor.$(OBJEXT): $(CCAN_DIR)/str/str.h ractor.$(OBJEXT): $(hdrdir)/ruby.h ractor.$(OBJEXT): $(hdrdir)/ruby/ruby.h +ractor.$(OBJEXT): $(hdrdir)/ruby/version.h ractor.$(OBJEXT): $(top_srcdir)/internal/array.h ractor.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h ractor.$(OBJEXT): $(top_srcdir)/internal/bignum.h @@ -11742,9 +14344,14 @@ ractor.$(OBJEXT): $(top_srcdir)/internal/fixnum.h ractor.$(OBJEXT): $(top_srcdir)/internal/gc.h ractor.$(OBJEXT): $(top_srcdir)/internal/hash.h ractor.$(OBJEXT): $(top_srcdir)/internal/imemo.h +ractor.$(OBJEXT): $(top_srcdir)/internal/namespace.h ractor.$(OBJEXT): $(top_srcdir)/internal/numeric.h +ractor.$(OBJEXT): $(top_srcdir)/internal/object.h +ractor.$(OBJEXT): $(top_srcdir)/internal/ractor.h ractor.$(OBJEXT): $(top_srcdir)/internal/rational.h +ractor.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h ractor.$(OBJEXT): $(top_srcdir)/internal/serial.h +ractor.$(OBJEXT): $(top_srcdir)/internal/set_table.h ractor.$(OBJEXT): $(top_srcdir)/internal/static_assert.h ractor.$(OBJEXT): $(top_srcdir)/internal/string.h ractor.$(OBJEXT): $(top_srcdir)/internal/struct.h @@ -11897,6 +14504,7 @@ ractor.$(OBJEXT): {$(VPATH)}internal/intern/re.h ractor.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h ractor.$(OBJEXT): {$(VPATH)}internal/intern/select.h ractor.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +ractor.$(OBJEXT): {$(VPATH)}internal/intern/set.h ractor.$(OBJEXT): {$(VPATH)}internal/intern/signal.h ractor.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h ractor.$(OBJEXT): {$(VPATH)}internal/intern/string.h @@ -11916,6 +14524,7 @@ ractor.$(OBJEXT): {$(VPATH)}internal/special_consts.h ractor.$(OBJEXT): {$(VPATH)}internal/static_assert.h ractor.$(OBJEXT): {$(VPATH)}internal/stdalign.h ractor.$(OBJEXT): {$(VPATH)}internal/stdbool.h +ractor.$(OBJEXT): {$(VPATH)}internal/stdckdint.h ractor.$(OBJEXT): {$(VPATH)}internal/symbol.h ractor.$(OBJEXT): {$(VPATH)}internal/value.h ractor.$(OBJEXT): {$(VPATH)}internal/value_type.h @@ -11931,7 +14540,7 @@ ractor.$(OBJEXT): {$(VPATH)}ractor.c ractor.$(OBJEXT): {$(VPATH)}ractor.h ractor.$(OBJEXT): {$(VPATH)}ractor.rbinc ractor.$(OBJEXT): {$(VPATH)}ractor_core.h -ractor.$(OBJEXT): {$(VPATH)}rjit.h +ractor.$(OBJEXT): {$(VPATH)}ractor_sync.c ractor.$(OBJEXT): {$(VPATH)}ruby_assert.h ractor.$(OBJEXT): {$(VPATH)}ruby_atomic.h ractor.$(OBJEXT): {$(VPATH)}rubyparser.h @@ -11960,10 +14569,12 @@ random.$(OBJEXT): $(top_srcdir)/internal/compilers.h random.$(OBJEXT): $(top_srcdir)/internal/fixnum.h random.$(OBJEXT): $(top_srcdir)/internal/gc.h random.$(OBJEXT): $(top_srcdir)/internal/imemo.h +random.$(OBJEXT): $(top_srcdir)/internal/namespace.h random.$(OBJEXT): $(top_srcdir)/internal/numeric.h random.$(OBJEXT): $(top_srcdir)/internal/random.h random.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h random.$(OBJEXT): $(top_srcdir)/internal/serial.h +random.$(OBJEXT): $(top_srcdir)/internal/set_table.h random.$(OBJEXT): $(top_srcdir)/internal/static_assert.h random.$(OBJEXT): $(top_srcdir)/internal/variable.h random.$(OBJEXT): $(top_srcdir)/internal/vm.h @@ -12110,6 +14721,7 @@ random.$(OBJEXT): {$(VPATH)}internal/intern/re.h random.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h random.$(OBJEXT): {$(VPATH)}internal/intern/select.h random.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +random.$(OBJEXT): {$(VPATH)}internal/intern/set.h random.$(OBJEXT): {$(VPATH)}internal/intern/signal.h random.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h random.$(OBJEXT): {$(VPATH)}internal/intern/string.h @@ -12129,6 +14741,7 @@ random.$(OBJEXT): {$(VPATH)}internal/special_consts.h random.$(OBJEXT): {$(VPATH)}internal/static_assert.h random.$(OBJEXT): {$(VPATH)}internal/stdalign.h random.$(OBJEXT): {$(VPATH)}internal/stdbool.h +random.$(OBJEXT): {$(VPATH)}internal/stdckdint.h random.$(OBJEXT): {$(VPATH)}internal/symbol.h random.$(OBJEXT): {$(VPATH)}internal/value.h random.$(OBJEXT): {$(VPATH)}internal/value_type.h @@ -12157,6 +14770,7 @@ random.$(OBJEXT): {$(VPATH)}thread_native.h random.$(OBJEXT): {$(VPATH)}vm_core.h random.$(OBJEXT): {$(VPATH)}vm_opts.h range.$(OBJEXT): $(hdrdir)/ruby/ruby.h +range.$(OBJEXT): $(hdrdir)/ruby/version.h range.$(OBJEXT): $(top_srcdir)/internal/array.h range.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h range.$(OBJEXT): $(top_srcdir)/internal/bignum.h @@ -12315,6 +14929,7 @@ range.$(OBJEXT): {$(VPATH)}internal/intern/re.h range.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h range.$(OBJEXT): {$(VPATH)}internal/intern/select.h range.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +range.$(OBJEXT): {$(VPATH)}internal/intern/set.h range.$(OBJEXT): {$(VPATH)}internal/intern/signal.h range.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h range.$(OBJEXT): {$(VPATH)}internal/intern/string.h @@ -12334,6 +14949,7 @@ range.$(OBJEXT): {$(VPATH)}internal/special_consts.h range.$(OBJEXT): {$(VPATH)}internal/static_assert.h range.$(OBJEXT): {$(VPATH)}internal/stdalign.h range.$(OBJEXT): {$(VPATH)}internal/stdbool.h +range.$(OBJEXT): {$(VPATH)}internal/stdckdint.h range.$(OBJEXT): {$(VPATH)}internal/symbol.h range.$(OBJEXT): {$(VPATH)}internal/value.h range.$(OBJEXT): {$(VPATH)}internal/value_type.h @@ -12362,10 +14978,13 @@ rational.$(OBJEXT): $(top_srcdir)/internal/complex.h rational.$(OBJEXT): $(top_srcdir)/internal/fixnum.h rational.$(OBJEXT): $(top_srcdir)/internal/gc.h rational.$(OBJEXT): $(top_srcdir)/internal/imemo.h +rational.$(OBJEXT): $(top_srcdir)/internal/namespace.h rational.$(OBJEXT): $(top_srcdir)/internal/numeric.h rational.$(OBJEXT): $(top_srcdir)/internal/object.h rational.$(OBJEXT): $(top_srcdir)/internal/rational.h +rational.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h rational.$(OBJEXT): $(top_srcdir)/internal/serial.h +rational.$(OBJEXT): $(top_srcdir)/internal/set_table.h rational.$(OBJEXT): $(top_srcdir)/internal/static_assert.h rational.$(OBJEXT): $(top_srcdir)/internal/variable.h rational.$(OBJEXT): $(top_srcdir)/internal/vm.h @@ -12512,6 +15131,7 @@ rational.$(OBJEXT): {$(VPATH)}internal/intern/re.h rational.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h rational.$(OBJEXT): {$(VPATH)}internal/intern/select.h rational.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +rational.$(OBJEXT): {$(VPATH)}internal/intern/set.h rational.$(OBJEXT): {$(VPATH)}internal/intern/signal.h rational.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h rational.$(OBJEXT): {$(VPATH)}internal/intern/string.h @@ -12531,6 +15151,7 @@ rational.$(OBJEXT): {$(VPATH)}internal/special_consts.h rational.$(OBJEXT): {$(VPATH)}internal/static_assert.h rational.$(OBJEXT): {$(VPATH)}internal/stdalign.h rational.$(OBJEXT): {$(VPATH)}internal/stdbool.h +rational.$(OBJEXT): {$(VPATH)}internal/stdckdint.h rational.$(OBJEXT): {$(VPATH)}internal/symbol.h rational.$(OBJEXT): {$(VPATH)}internal/value.h rational.$(OBJEXT): {$(VPATH)}internal/value_type.h @@ -12568,10 +15189,13 @@ re.$(OBJEXT): $(top_srcdir)/internal/encoding.h re.$(OBJEXT): $(top_srcdir)/internal/gc.h re.$(OBJEXT): $(top_srcdir)/internal/hash.h re.$(OBJEXT): $(top_srcdir)/internal/imemo.h +re.$(OBJEXT): $(top_srcdir)/internal/namespace.h re.$(OBJEXT): $(top_srcdir)/internal/object.h re.$(OBJEXT): $(top_srcdir)/internal/ractor.h re.$(OBJEXT): $(top_srcdir)/internal/re.h +re.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h re.$(OBJEXT): $(top_srcdir)/internal/serial.h +re.$(OBJEXT): $(top_srcdir)/internal/set_table.h re.$(OBJEXT): $(top_srcdir)/internal/static_assert.h re.$(OBJEXT): $(top_srcdir)/internal/string.h re.$(OBJEXT): $(top_srcdir)/internal/time.h @@ -12723,6 +15347,7 @@ re.$(OBJEXT): {$(VPATH)}internal/intern/re.h re.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h re.$(OBJEXT): {$(VPATH)}internal/intern/select.h re.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +re.$(OBJEXT): {$(VPATH)}internal/intern/set.h re.$(OBJEXT): {$(VPATH)}internal/intern/signal.h re.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h re.$(OBJEXT): {$(VPATH)}internal/intern/string.h @@ -12742,6 +15367,7 @@ re.$(OBJEXT): {$(VPATH)}internal/special_consts.h re.$(OBJEXT): {$(VPATH)}internal/static_assert.h re.$(OBJEXT): {$(VPATH)}internal/stdalign.h re.$(OBJEXT): {$(VPATH)}internal/stdbool.h +re.$(OBJEXT): {$(VPATH)}internal/stdckdint.h re.$(OBJEXT): {$(VPATH)}internal/symbol.h re.$(OBJEXT): {$(VPATH)}internal/value.h re.$(OBJEXT): {$(VPATH)}internal/value_type.h @@ -12753,6 +15379,8 @@ re.$(OBJEXT): {$(VPATH)}missing.h re.$(OBJEXT): {$(VPATH)}node.h re.$(OBJEXT): {$(VPATH)}onigmo.h re.$(OBJEXT): {$(VPATH)}oniguruma.h +re.$(OBJEXT): {$(VPATH)}ractor.h +re.$(OBJEXT): {$(VPATH)}ractor_core.h re.$(OBJEXT): {$(VPATH)}re.c re.$(OBJEXT): {$(VPATH)}re.h re.$(OBJEXT): {$(VPATH)}regenc.h @@ -12768,6 +15396,7 @@ re.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h re.$(OBJEXT): {$(VPATH)}thread_native.h re.$(OBJEXT): {$(VPATH)}util.h re.$(OBJEXT): {$(VPATH)}vm_core.h +re.$(OBJEXT): {$(VPATH)}vm_debug.h re.$(OBJEXT): {$(VPATH)}vm_opts.h regcomp.$(OBJEXT): $(hdrdir)/ruby.h regcomp.$(OBJEXT): $(hdrdir)/ruby/ruby.h @@ -12897,6 +15526,7 @@ regcomp.$(OBJEXT): {$(VPATH)}internal/intern/re.h regcomp.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h regcomp.$(OBJEXT): {$(VPATH)}internal/intern/select.h regcomp.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +regcomp.$(OBJEXT): {$(VPATH)}internal/intern/set.h regcomp.$(OBJEXT): {$(VPATH)}internal/intern/signal.h regcomp.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h regcomp.$(OBJEXT): {$(VPATH)}internal/intern/string.h @@ -12916,6 +15546,7 @@ regcomp.$(OBJEXT): {$(VPATH)}internal/special_consts.h regcomp.$(OBJEXT): {$(VPATH)}internal/static_assert.h regcomp.$(OBJEXT): {$(VPATH)}internal/stdalign.h regcomp.$(OBJEXT): {$(VPATH)}internal/stdbool.h +regcomp.$(OBJEXT): {$(VPATH)}internal/stdckdint.h regcomp.$(OBJEXT): {$(VPATH)}internal/symbol.h regcomp.$(OBJEXT): {$(VPATH)}internal/value.h regcomp.$(OBJEXT): {$(VPATH)}internal/value_type.h @@ -13058,6 +15689,7 @@ regenc.$(OBJEXT): {$(VPATH)}internal/intern/re.h regenc.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h regenc.$(OBJEXT): {$(VPATH)}internal/intern/select.h regenc.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +regenc.$(OBJEXT): {$(VPATH)}internal/intern/set.h regenc.$(OBJEXT): {$(VPATH)}internal/intern/signal.h regenc.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h regenc.$(OBJEXT): {$(VPATH)}internal/intern/string.h @@ -13077,6 +15709,7 @@ regenc.$(OBJEXT): {$(VPATH)}internal/special_consts.h regenc.$(OBJEXT): {$(VPATH)}internal/static_assert.h regenc.$(OBJEXT): {$(VPATH)}internal/stdalign.h regenc.$(OBJEXT): {$(VPATH)}internal/stdbool.h +regenc.$(OBJEXT): {$(VPATH)}internal/stdckdint.h regenc.$(OBJEXT): {$(VPATH)}internal/symbol.h regenc.$(OBJEXT): {$(VPATH)}internal/value.h regenc.$(OBJEXT): {$(VPATH)}internal/value_type.h @@ -13218,6 +15851,7 @@ regerror.$(OBJEXT): {$(VPATH)}internal/intern/re.h regerror.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h regerror.$(OBJEXT): {$(VPATH)}internal/intern/select.h regerror.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +regerror.$(OBJEXT): {$(VPATH)}internal/intern/set.h regerror.$(OBJEXT): {$(VPATH)}internal/intern/signal.h regerror.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h regerror.$(OBJEXT): {$(VPATH)}internal/intern/string.h @@ -13237,6 +15871,7 @@ regerror.$(OBJEXT): {$(VPATH)}internal/special_consts.h regerror.$(OBJEXT): {$(VPATH)}internal/static_assert.h regerror.$(OBJEXT): {$(VPATH)}internal/stdalign.h regerror.$(OBJEXT): {$(VPATH)}internal/stdbool.h +regerror.$(OBJEXT): {$(VPATH)}internal/stdckdint.h regerror.$(OBJEXT): {$(VPATH)}internal/symbol.h regerror.$(OBJEXT): {$(VPATH)}internal/value.h regerror.$(OBJEXT): {$(VPATH)}internal/value_type.h @@ -13378,6 +16013,7 @@ regexec.$(OBJEXT): {$(VPATH)}internal/intern/re.h regexec.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h regexec.$(OBJEXT): {$(VPATH)}internal/intern/select.h regexec.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +regexec.$(OBJEXT): {$(VPATH)}internal/intern/set.h regexec.$(OBJEXT): {$(VPATH)}internal/intern/signal.h regexec.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h regexec.$(OBJEXT): {$(VPATH)}internal/intern/string.h @@ -13397,6 +16033,7 @@ regexec.$(OBJEXT): {$(VPATH)}internal/special_consts.h regexec.$(OBJEXT): {$(VPATH)}internal/static_assert.h regexec.$(OBJEXT): {$(VPATH)}internal/stdalign.h regexec.$(OBJEXT): {$(VPATH)}internal/stdbool.h +regexec.$(OBJEXT): {$(VPATH)}internal/stdckdint.h regexec.$(OBJEXT): {$(VPATH)}internal/symbol.h regexec.$(OBJEXT): {$(VPATH)}internal/value.h regexec.$(OBJEXT): {$(VPATH)}internal/value_type.h @@ -13542,6 +16179,7 @@ regparse.$(OBJEXT): {$(VPATH)}internal/intern/re.h regparse.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h regparse.$(OBJEXT): {$(VPATH)}internal/intern/select.h regparse.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +regparse.$(OBJEXT): {$(VPATH)}internal/intern/set.h regparse.$(OBJEXT): {$(VPATH)}internal/intern/signal.h regparse.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h regparse.$(OBJEXT): {$(VPATH)}internal/intern/string.h @@ -13561,6 +16199,7 @@ regparse.$(OBJEXT): {$(VPATH)}internal/special_consts.h regparse.$(OBJEXT): {$(VPATH)}internal/static_assert.h regparse.$(OBJEXT): {$(VPATH)}internal/stdalign.h regparse.$(OBJEXT): {$(VPATH)}internal/stdbool.h +regparse.$(OBJEXT): {$(VPATH)}internal/stdckdint.h regparse.$(OBJEXT): {$(VPATH)}internal/symbol.h regparse.$(OBJEXT): {$(VPATH)}internal/value.h regparse.$(OBJEXT): {$(VPATH)}internal/value_type.h @@ -13703,6 +16342,7 @@ regsyntax.$(OBJEXT): {$(VPATH)}internal/intern/re.h regsyntax.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h regsyntax.$(OBJEXT): {$(VPATH)}internal/intern/select.h regsyntax.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/intern/set.h regsyntax.$(OBJEXT): {$(VPATH)}internal/intern/signal.h regsyntax.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h regsyntax.$(OBJEXT): {$(VPATH)}internal/intern/string.h @@ -13722,6 +16362,7 @@ regsyntax.$(OBJEXT): {$(VPATH)}internal/special_consts.h regsyntax.$(OBJEXT): {$(VPATH)}internal/static_assert.h regsyntax.$(OBJEXT): {$(VPATH)}internal/stdalign.h regsyntax.$(OBJEXT): {$(VPATH)}internal/stdbool.h +regsyntax.$(OBJEXT): {$(VPATH)}internal/stdckdint.h regsyntax.$(OBJEXT): {$(VPATH)}internal/symbol.h regsyntax.$(OBJEXT): {$(VPATH)}internal/value.h regsyntax.$(OBJEXT): {$(VPATH)}internal/value_type.h @@ -13735,461 +16376,6 @@ regsyntax.$(OBJEXT): {$(VPATH)}regint.h regsyntax.$(OBJEXT): {$(VPATH)}regsyntax.c regsyntax.$(OBJEXT): {$(VPATH)}st.h regsyntax.$(OBJEXT): {$(VPATH)}subst.h -rjit.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h -rjit.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h -rjit.$(OBJEXT): $(CCAN_DIR)/list/list.h -rjit.$(OBJEXT): $(CCAN_DIR)/str/str.h -rjit.$(OBJEXT): $(hdrdir)/ruby.h -rjit.$(OBJEXT): $(hdrdir)/ruby/ruby.h -rjit.$(OBJEXT): $(hdrdir)/ruby/version.h -rjit.$(OBJEXT): $(top_srcdir)/internal/array.h -rjit.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h -rjit.$(OBJEXT): $(top_srcdir)/internal/class.h -rjit.$(OBJEXT): $(top_srcdir)/internal/cmdlineopt.h -rjit.$(OBJEXT): $(top_srcdir)/internal/compile.h -rjit.$(OBJEXT): $(top_srcdir)/internal/compilers.h -rjit.$(OBJEXT): $(top_srcdir)/internal/cont.h -rjit.$(OBJEXT): $(top_srcdir)/internal/file.h -rjit.$(OBJEXT): $(top_srcdir)/internal/gc.h -rjit.$(OBJEXT): $(top_srcdir)/internal/hash.h -rjit.$(OBJEXT): $(top_srcdir)/internal/imemo.h -rjit.$(OBJEXT): $(top_srcdir)/internal/process.h -rjit.$(OBJEXT): $(top_srcdir)/internal/serial.h -rjit.$(OBJEXT): $(top_srcdir)/internal/static_assert.h -rjit.$(OBJEXT): $(top_srcdir)/internal/string.h -rjit.$(OBJEXT): $(top_srcdir)/internal/struct.h -rjit.$(OBJEXT): $(top_srcdir)/internal/variable.h -rjit.$(OBJEXT): $(top_srcdir)/internal/vm.h -rjit.$(OBJEXT): $(top_srcdir)/internal/warnings.h -rjit.$(OBJEXT): {$(VPATH)}assert.h -rjit.$(OBJEXT): {$(VPATH)}atomic.h -rjit.$(OBJEXT): {$(VPATH)}backward/2/assume.h -rjit.$(OBJEXT): {$(VPATH)}backward/2/attributes.h -rjit.$(OBJEXT): {$(VPATH)}backward/2/bool.h -rjit.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h -rjit.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h -rjit.$(OBJEXT): {$(VPATH)}backward/2/limits.h -rjit.$(OBJEXT): {$(VPATH)}backward/2/long_long.h -rjit.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h -rjit.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h -rjit.$(OBJEXT): {$(VPATH)}builtin.h -rjit.$(OBJEXT): {$(VPATH)}config.h -rjit.$(OBJEXT): {$(VPATH)}constant.h -rjit.$(OBJEXT): {$(VPATH)}debug.h -rjit.$(OBJEXT): {$(VPATH)}debug_counter.h -rjit.$(OBJEXT): {$(VPATH)}defines.h -rjit.$(OBJEXT): {$(VPATH)}dln.h -rjit.$(OBJEXT): {$(VPATH)}encoding.h -rjit.$(OBJEXT): {$(VPATH)}id.h -rjit.$(OBJEXT): {$(VPATH)}id_table.h -rjit.$(OBJEXT): {$(VPATH)}insns.def -rjit.$(OBJEXT): {$(VPATH)}insns.inc -rjit.$(OBJEXT): {$(VPATH)}insns_info.inc -rjit.$(OBJEXT): {$(VPATH)}intern.h -rjit.$(OBJEXT): {$(VPATH)}internal.h -rjit.$(OBJEXT): {$(VPATH)}internal/abi.h -rjit.$(OBJEXT): {$(VPATH)}internal/anyargs.h -rjit.$(OBJEXT): {$(VPATH)}internal/arithmetic.h -rjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h -rjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h -rjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h -rjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h -rjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h -rjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h -rjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h -rjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h -rjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h -rjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h -rjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h -rjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h -rjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h -rjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h -rjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h -rjit.$(OBJEXT): {$(VPATH)}internal/assume.h -rjit.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h -rjit.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h -rjit.$(OBJEXT): {$(VPATH)}internal/attr/cold.h -rjit.$(OBJEXT): {$(VPATH)}internal/attr/const.h -rjit.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h -rjit.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h -rjit.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h -rjit.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h -rjit.$(OBJEXT): {$(VPATH)}internal/attr/error.h -rjit.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h -rjit.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h -rjit.$(OBJEXT): {$(VPATH)}internal/attr/format.h -rjit.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h -rjit.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h -rjit.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h -rjit.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h -rjit.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h -rjit.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h -rjit.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h -rjit.$(OBJEXT): {$(VPATH)}internal/attr/packed_struct.h -rjit.$(OBJEXT): {$(VPATH)}internal/attr/pure.h -rjit.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h -rjit.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h -rjit.$(OBJEXT): {$(VPATH)}internal/attr/warning.h -rjit.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h -rjit.$(OBJEXT): {$(VPATH)}internal/cast.h -rjit.$(OBJEXT): {$(VPATH)}internal/compiler_is.h -rjit.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h -rjit.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h -rjit.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h -rjit.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h -rjit.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h -rjit.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h -rjit.$(OBJEXT): {$(VPATH)}internal/compiler_since.h -rjit.$(OBJEXT): {$(VPATH)}internal/config.h -rjit.$(OBJEXT): {$(VPATH)}internal/constant_p.h -rjit.$(OBJEXT): {$(VPATH)}internal/core.h -rjit.$(OBJEXT): {$(VPATH)}internal/core/rarray.h -rjit.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h -rjit.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h -rjit.$(OBJEXT): {$(VPATH)}internal/core/rclass.h -rjit.$(OBJEXT): {$(VPATH)}internal/core/rdata.h -rjit.$(OBJEXT): {$(VPATH)}internal/core/rfile.h -rjit.$(OBJEXT): {$(VPATH)}internal/core/rhash.h -rjit.$(OBJEXT): {$(VPATH)}internal/core/robject.h -rjit.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h -rjit.$(OBJEXT): {$(VPATH)}internal/core/rstring.h -rjit.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h -rjit.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h -rjit.$(OBJEXT): {$(VPATH)}internal/ctype.h -rjit.$(OBJEXT): {$(VPATH)}internal/dllexport.h -rjit.$(OBJEXT): {$(VPATH)}internal/dosish.h -rjit.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h -rjit.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h -rjit.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h -rjit.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h -rjit.$(OBJEXT): {$(VPATH)}internal/encoding/re.h -rjit.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h -rjit.$(OBJEXT): {$(VPATH)}internal/encoding/string.h -rjit.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h -rjit.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h -rjit.$(OBJEXT): {$(VPATH)}internal/error.h -rjit.$(OBJEXT): {$(VPATH)}internal/eval.h -rjit.$(OBJEXT): {$(VPATH)}internal/event.h -rjit.$(OBJEXT): {$(VPATH)}internal/fl_type.h -rjit.$(OBJEXT): {$(VPATH)}internal/gc.h -rjit.$(OBJEXT): {$(VPATH)}internal/glob.h -rjit.$(OBJEXT): {$(VPATH)}internal/globals.h -rjit.$(OBJEXT): {$(VPATH)}internal/has/attribute.h -rjit.$(OBJEXT): {$(VPATH)}internal/has/builtin.h -rjit.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h -rjit.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h -rjit.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h -rjit.$(OBJEXT): {$(VPATH)}internal/has/extension.h -rjit.$(OBJEXT): {$(VPATH)}internal/has/feature.h -rjit.$(OBJEXT): {$(VPATH)}internal/has/warning.h -rjit.$(OBJEXT): {$(VPATH)}internal/intern/array.h -rjit.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h -rjit.$(OBJEXT): {$(VPATH)}internal/intern/class.h -rjit.$(OBJEXT): {$(VPATH)}internal/intern/compar.h -rjit.$(OBJEXT): {$(VPATH)}internal/intern/complex.h -rjit.$(OBJEXT): {$(VPATH)}internal/intern/cont.h -rjit.$(OBJEXT): {$(VPATH)}internal/intern/dir.h -rjit.$(OBJEXT): {$(VPATH)}internal/intern/enum.h -rjit.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h -rjit.$(OBJEXT): {$(VPATH)}internal/intern/error.h -rjit.$(OBJEXT): {$(VPATH)}internal/intern/eval.h -rjit.$(OBJEXT): {$(VPATH)}internal/intern/file.h -rjit.$(OBJEXT): {$(VPATH)}internal/intern/hash.h -rjit.$(OBJEXT): {$(VPATH)}internal/intern/io.h -rjit.$(OBJEXT): {$(VPATH)}internal/intern/load.h -rjit.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h -rjit.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h -rjit.$(OBJEXT): {$(VPATH)}internal/intern/object.h -rjit.$(OBJEXT): {$(VPATH)}internal/intern/parse.h -rjit.$(OBJEXT): {$(VPATH)}internal/intern/proc.h -rjit.$(OBJEXT): {$(VPATH)}internal/intern/process.h -rjit.$(OBJEXT): {$(VPATH)}internal/intern/random.h -rjit.$(OBJEXT): {$(VPATH)}internal/intern/range.h -rjit.$(OBJEXT): {$(VPATH)}internal/intern/rational.h -rjit.$(OBJEXT): {$(VPATH)}internal/intern/re.h -rjit.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h -rjit.$(OBJEXT): {$(VPATH)}internal/intern/select.h -rjit.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h -rjit.$(OBJEXT): {$(VPATH)}internal/intern/signal.h -rjit.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h -rjit.$(OBJEXT): {$(VPATH)}internal/intern/string.h -rjit.$(OBJEXT): {$(VPATH)}internal/intern/struct.h -rjit.$(OBJEXT): {$(VPATH)}internal/intern/thread.h -rjit.$(OBJEXT): {$(VPATH)}internal/intern/time.h -rjit.$(OBJEXT): {$(VPATH)}internal/intern/variable.h -rjit.$(OBJEXT): {$(VPATH)}internal/intern/vm.h -rjit.$(OBJEXT): {$(VPATH)}internal/interpreter.h -rjit.$(OBJEXT): {$(VPATH)}internal/iterator.h -rjit.$(OBJEXT): {$(VPATH)}internal/memory.h -rjit.$(OBJEXT): {$(VPATH)}internal/method.h -rjit.$(OBJEXT): {$(VPATH)}internal/module.h -rjit.$(OBJEXT): {$(VPATH)}internal/newobj.h -rjit.$(OBJEXT): {$(VPATH)}internal/scan_args.h -rjit.$(OBJEXT): {$(VPATH)}internal/special_consts.h -rjit.$(OBJEXT): {$(VPATH)}internal/static_assert.h -rjit.$(OBJEXT): {$(VPATH)}internal/stdalign.h -rjit.$(OBJEXT): {$(VPATH)}internal/stdbool.h -rjit.$(OBJEXT): {$(VPATH)}internal/symbol.h -rjit.$(OBJEXT): {$(VPATH)}internal/value.h -rjit.$(OBJEXT): {$(VPATH)}internal/value_type.h -rjit.$(OBJEXT): {$(VPATH)}internal/variable.h -rjit.$(OBJEXT): {$(VPATH)}internal/warning_push.h -rjit.$(OBJEXT): {$(VPATH)}internal/xmalloc.h -rjit.$(OBJEXT): {$(VPATH)}iseq.h -rjit.$(OBJEXT): {$(VPATH)}method.h -rjit.$(OBJEXT): {$(VPATH)}missing.h -rjit.$(OBJEXT): {$(VPATH)}node.h -rjit.$(OBJEXT): {$(VPATH)}onigmo.h -rjit.$(OBJEXT): {$(VPATH)}oniguruma.h -rjit.$(OBJEXT): {$(VPATH)}ractor.h -rjit.$(OBJEXT): {$(VPATH)}ractor_core.h -rjit.$(OBJEXT): {$(VPATH)}rjit.c -rjit.$(OBJEXT): {$(VPATH)}rjit.h -rjit.$(OBJEXT): {$(VPATH)}rjit.rbinc -rjit.$(OBJEXT): {$(VPATH)}rjit_c.h -rjit.$(OBJEXT): {$(VPATH)}ruby_assert.h -rjit.$(OBJEXT): {$(VPATH)}ruby_atomic.h -rjit.$(OBJEXT): {$(VPATH)}rubyparser.h -rjit.$(OBJEXT): {$(VPATH)}shape.h -rjit.$(OBJEXT): {$(VPATH)}st.h -rjit.$(OBJEXT): {$(VPATH)}subst.h -rjit.$(OBJEXT): {$(VPATH)}thread.h -rjit.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h -rjit.$(OBJEXT): {$(VPATH)}thread_native.h -rjit.$(OBJEXT): {$(VPATH)}util.h -rjit.$(OBJEXT): {$(VPATH)}vm_callinfo.h -rjit.$(OBJEXT): {$(VPATH)}vm_core.h -rjit.$(OBJEXT): {$(VPATH)}vm_debug.h -rjit.$(OBJEXT): {$(VPATH)}vm_opts.h -rjit.$(OBJEXT): {$(VPATH)}vm_sync.h -rjit.$(OBJEXT): {$(VPATH)}yjit.h -rjit_c.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h -rjit_c.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h -rjit_c.$(OBJEXT): $(CCAN_DIR)/list/list.h -rjit_c.$(OBJEXT): $(CCAN_DIR)/str/str.h -rjit_c.$(OBJEXT): $(hdrdir)/ruby.h -rjit_c.$(OBJEXT): $(hdrdir)/ruby/ruby.h -rjit_c.$(OBJEXT): $(srcdir)/rjit_c.rb -rjit_c.$(OBJEXT): $(top_srcdir)/internal/array.h -rjit_c.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h -rjit_c.$(OBJEXT): $(top_srcdir)/internal/class.h -rjit_c.$(OBJEXT): $(top_srcdir)/internal/compile.h -rjit_c.$(OBJEXT): $(top_srcdir)/internal/compilers.h -rjit_c.$(OBJEXT): $(top_srcdir)/internal/fixnum.h -rjit_c.$(OBJEXT): $(top_srcdir)/internal/gc.h -rjit_c.$(OBJEXT): $(top_srcdir)/internal/hash.h -rjit_c.$(OBJEXT): $(top_srcdir)/internal/imemo.h -rjit_c.$(OBJEXT): $(top_srcdir)/internal/object.h -rjit_c.$(OBJEXT): $(top_srcdir)/internal/proc.h -rjit_c.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h -rjit_c.$(OBJEXT): $(top_srcdir)/internal/serial.h -rjit_c.$(OBJEXT): $(top_srcdir)/internal/static_assert.h -rjit_c.$(OBJEXT): $(top_srcdir)/internal/string.h -rjit_c.$(OBJEXT): $(top_srcdir)/internal/struct.h -rjit_c.$(OBJEXT): $(top_srcdir)/internal/variable.h -rjit_c.$(OBJEXT): $(top_srcdir)/internal/vm.h -rjit_c.$(OBJEXT): $(top_srcdir)/internal/warnings.h -rjit_c.$(OBJEXT): {$(VPATH)}assert.h -rjit_c.$(OBJEXT): {$(VPATH)}atomic.h -rjit_c.$(OBJEXT): {$(VPATH)}backward/2/assume.h -rjit_c.$(OBJEXT): {$(VPATH)}backward/2/attributes.h -rjit_c.$(OBJEXT): {$(VPATH)}backward/2/bool.h -rjit_c.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h -rjit_c.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h -rjit_c.$(OBJEXT): {$(VPATH)}backward/2/limits.h -rjit_c.$(OBJEXT): {$(VPATH)}backward/2/long_long.h -rjit_c.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h -rjit_c.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h -rjit_c.$(OBJEXT): {$(VPATH)}builtin.h -rjit_c.$(OBJEXT): {$(VPATH)}config.h -rjit_c.$(OBJEXT): {$(VPATH)}constant.h -rjit_c.$(OBJEXT): {$(VPATH)}debug.h -rjit_c.$(OBJEXT): {$(VPATH)}debug_counter.h -rjit_c.$(OBJEXT): {$(VPATH)}defines.h -rjit_c.$(OBJEXT): {$(VPATH)}encoding.h -rjit_c.$(OBJEXT): {$(VPATH)}id.h -rjit_c.$(OBJEXT): {$(VPATH)}id_table.h -rjit_c.$(OBJEXT): {$(VPATH)}insns.def -rjit_c.$(OBJEXT): {$(VPATH)}insns.inc -rjit_c.$(OBJEXT): {$(VPATH)}insns_info.inc -rjit_c.$(OBJEXT): {$(VPATH)}intern.h -rjit_c.$(OBJEXT): {$(VPATH)}internal.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/abi.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/anyargs.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/arithmetic.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/assume.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/attr/cold.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/attr/const.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/attr/error.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/attr/format.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/attr/packed_struct.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/attr/pure.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/attr/warning.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/cast.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/compiler_is.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/compiler_since.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/config.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/constant_p.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/core.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/core/rarray.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/core/rclass.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/core/rdata.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/core/rfile.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/core/rhash.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/core/robject.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/core/rstring.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/ctype.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/dllexport.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/dosish.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/encoding/re.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/encoding/string.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/error.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/eval.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/event.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/fl_type.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/gc.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/glob.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/globals.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/has/attribute.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/has/builtin.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/has/extension.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/has/feature.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/has/warning.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/intern/array.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/intern/class.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/intern/compar.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/intern/complex.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/intern/cont.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/intern/dir.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/intern/enum.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/intern/error.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/intern/eval.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/intern/file.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/intern/hash.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/intern/io.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/intern/load.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/intern/object.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/intern/parse.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/intern/proc.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/intern/process.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/intern/random.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/intern/range.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/intern/rational.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/intern/re.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/intern/select.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/intern/signal.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/intern/string.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/intern/struct.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/intern/thread.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/intern/time.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/intern/variable.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/intern/vm.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/interpreter.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/iterator.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/memory.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/method.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/module.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/newobj.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/scan_args.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/special_consts.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/static_assert.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/stdalign.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/stdbool.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/symbol.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/value.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/value_type.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/variable.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/warning_push.h -rjit_c.$(OBJEXT): {$(VPATH)}internal/xmalloc.h -rjit_c.$(OBJEXT): {$(VPATH)}iseq.h -rjit_c.$(OBJEXT): {$(VPATH)}method.h -rjit_c.$(OBJEXT): {$(VPATH)}missing.h -rjit_c.$(OBJEXT): {$(VPATH)}node.h -rjit_c.$(OBJEXT): {$(VPATH)}onigmo.h -rjit_c.$(OBJEXT): {$(VPATH)}oniguruma.h -rjit_c.$(OBJEXT): {$(VPATH)}probes.dmyh -rjit_c.$(OBJEXT): {$(VPATH)}probes.h -rjit_c.$(OBJEXT): {$(VPATH)}probes_helper.h -rjit_c.$(OBJEXT): {$(VPATH)}rjit.h -rjit_c.$(OBJEXT): {$(VPATH)}rjit_c.c -rjit_c.$(OBJEXT): {$(VPATH)}rjit_c.h -rjit_c.$(OBJEXT): {$(VPATH)}rjit_c.rb -rjit_c.$(OBJEXT): {$(VPATH)}rjit_c.rbinc -rjit_c.$(OBJEXT): {$(VPATH)}ruby_assert.h -rjit_c.$(OBJEXT): {$(VPATH)}ruby_atomic.h -rjit_c.$(OBJEXT): {$(VPATH)}rubyparser.h -rjit_c.$(OBJEXT): {$(VPATH)}shape.h -rjit_c.$(OBJEXT): {$(VPATH)}st.h -rjit_c.$(OBJEXT): {$(VPATH)}subst.h -rjit_c.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h -rjit_c.$(OBJEXT): {$(VPATH)}thread_native.h -rjit_c.$(OBJEXT): {$(VPATH)}vm_callinfo.h -rjit_c.$(OBJEXT): {$(VPATH)}vm_core.h -rjit_c.$(OBJEXT): {$(VPATH)}vm_exec.h -rjit_c.$(OBJEXT): {$(VPATH)}vm_insnhelper.h -rjit_c.$(OBJEXT): {$(VPATH)}vm_opts.h -rjit_c.$(OBJEXT): {$(VPATH)}yjit.h ruby-runner.$(OBJEXT): {$(VPATH)}config.h ruby-runner.$(OBJEXT): {$(VPATH)}internal/compiler_is.h ruby-runner.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h @@ -14211,12 +16397,16 @@ ruby.$(OBJEXT): $(hdrdir)/ruby/ruby.h ruby.$(OBJEXT): $(hdrdir)/ruby/version.h ruby.$(OBJEXT): $(top_srcdir)/internal/array.h ruby.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h +ruby.$(OBJEXT): $(top_srcdir)/internal/bignum.h +ruby.$(OBJEXT): $(top_srcdir)/internal/bits.h ruby.$(OBJEXT): $(top_srcdir)/internal/class.h ruby.$(OBJEXT): $(top_srcdir)/internal/cmdlineopt.h ruby.$(OBJEXT): $(top_srcdir)/internal/compilers.h +ruby.$(OBJEXT): $(top_srcdir)/internal/complex.h ruby.$(OBJEXT): $(top_srcdir)/internal/cont.h ruby.$(OBJEXT): $(top_srcdir)/internal/error.h ruby.$(OBJEXT): $(top_srcdir)/internal/file.h +ruby.$(OBJEXT): $(top_srcdir)/internal/fixnum.h ruby.$(OBJEXT): $(top_srcdir)/internal/gc.h ruby.$(OBJEXT): $(top_srcdir)/internal/imemo.h ruby.$(OBJEXT): $(top_srcdir)/internal/inits.h @@ -14224,15 +16414,41 @@ ruby.$(OBJEXT): $(top_srcdir)/internal/io.h ruby.$(OBJEXT): $(top_srcdir)/internal/load.h ruby.$(OBJEXT): $(top_srcdir)/internal/loadpath.h ruby.$(OBJEXT): $(top_srcdir)/internal/missing.h +ruby.$(OBJEXT): $(top_srcdir)/internal/namespace.h +ruby.$(OBJEXT): $(top_srcdir)/internal/numeric.h ruby.$(OBJEXT): $(top_srcdir)/internal/object.h ruby.$(OBJEXT): $(top_srcdir)/internal/parse.h +ruby.$(OBJEXT): $(top_srcdir)/internal/rational.h ruby.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h +ruby.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h ruby.$(OBJEXT): $(top_srcdir)/internal/serial.h +ruby.$(OBJEXT): $(top_srcdir)/internal/set_table.h ruby.$(OBJEXT): $(top_srcdir)/internal/static_assert.h ruby.$(OBJEXT): $(top_srcdir)/internal/string.h +ruby.$(OBJEXT): $(top_srcdir)/internal/thread.h ruby.$(OBJEXT): $(top_srcdir)/internal/variable.h ruby.$(OBJEXT): $(top_srcdir)/internal/vm.h ruby.$(OBJEXT): $(top_srcdir)/internal/warnings.h +ruby.$(OBJEXT): $(top_srcdir)/prism/defines.h +ruby.$(OBJEXT): $(top_srcdir)/prism/encoding.h +ruby.$(OBJEXT): $(top_srcdir)/prism/node.h +ruby.$(OBJEXT): $(top_srcdir)/prism/options.h +ruby.$(OBJEXT): $(top_srcdir)/prism/pack.h +ruby.$(OBJEXT): $(top_srcdir)/prism/parser.h +ruby.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h +ruby.$(OBJEXT): $(top_srcdir)/prism/prism.h +ruby.$(OBJEXT): $(top_srcdir)/prism/regexp.h +ruby.$(OBJEXT): $(top_srcdir)/prism/static_literals.h +ruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h +ruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h +ruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h +ruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h +ruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h +ruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h +ruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h +ruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h +ruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h +ruby.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h ruby.$(OBJEXT): {$(VPATH)}assert.h ruby.$(OBJEXT): {$(VPATH)}atomic.h ruby.$(OBJEXT): {$(VPATH)}backward/2/assume.h @@ -14378,6 +16594,7 @@ ruby.$(OBJEXT): {$(VPATH)}internal/intern/re.h ruby.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h ruby.$(OBJEXT): {$(VPATH)}internal/intern/select.h ruby.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +ruby.$(OBJEXT): {$(VPATH)}internal/intern/set.h ruby.$(OBJEXT): {$(VPATH)}internal/intern/signal.h ruby.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h ruby.$(OBJEXT): {$(VPATH)}internal/intern/string.h @@ -14397,6 +16614,7 @@ ruby.$(OBJEXT): {$(VPATH)}internal/special_consts.h ruby.$(OBJEXT): {$(VPATH)}internal/static_assert.h ruby.$(OBJEXT): {$(VPATH)}internal/stdalign.h ruby.$(OBJEXT): {$(VPATH)}internal/stdbool.h +ruby.$(OBJEXT): {$(VPATH)}internal/stdckdint.h ruby.$(OBJEXT): {$(VPATH)}internal/symbol.h ruby.$(OBJEXT): {$(VPATH)}internal/value.h ruby.$(OBJEXT): {$(VPATH)}internal/value_type.h @@ -14410,7 +16628,10 @@ ruby.$(OBJEXT): {$(VPATH)}missing.h ruby.$(OBJEXT): {$(VPATH)}node.h ruby.$(OBJEXT): {$(VPATH)}onigmo.h ruby.$(OBJEXT): {$(VPATH)}oniguruma.h -ruby.$(OBJEXT): {$(VPATH)}rjit.h +ruby.$(OBJEXT): {$(VPATH)}prism/ast.h +ruby.$(OBJEXT): {$(VPATH)}prism/diagnostic.h +ruby.$(OBJEXT): {$(VPATH)}prism/version.h +ruby.$(OBJEXT): {$(VPATH)}prism_compile.h ruby.$(OBJEXT): {$(VPATH)}ruby.c ruby.$(OBJEXT): {$(VPATH)}ruby_assert.h ruby.$(OBJEXT): {$(VPATH)}ruby_atomic.h @@ -14425,7 +16646,198 @@ ruby.$(OBJEXT): {$(VPATH)}util.h ruby.$(OBJEXT): {$(VPATH)}vm_core.h ruby.$(OBJEXT): {$(VPATH)}vm_opts.h ruby.$(OBJEXT): {$(VPATH)}yjit.h +ruby_parser.$(OBJEXT): $(hdrdir)/ruby/ruby.h +ruby_parser.$(OBJEXT): $(top_srcdir)/internal/array.h +ruby_parser.$(OBJEXT): $(top_srcdir)/internal/bignum.h +ruby_parser.$(OBJEXT): $(top_srcdir)/internal/bits.h +ruby_parser.$(OBJEXT): $(top_srcdir)/internal/compilers.h +ruby_parser.$(OBJEXT): $(top_srcdir)/internal/complex.h +ruby_parser.$(OBJEXT): $(top_srcdir)/internal/error.h +ruby_parser.$(OBJEXT): $(top_srcdir)/internal/fixnum.h +ruby_parser.$(OBJEXT): $(top_srcdir)/internal/imemo.h +ruby_parser.$(OBJEXT): $(top_srcdir)/internal/numeric.h +ruby_parser.$(OBJEXT): $(top_srcdir)/internal/parse.h +ruby_parser.$(OBJEXT): $(top_srcdir)/internal/rational.h +ruby_parser.$(OBJEXT): $(top_srcdir)/internal/re.h +ruby_parser.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h +ruby_parser.$(OBJEXT): $(top_srcdir)/internal/serial.h +ruby_parser.$(OBJEXT): $(top_srcdir)/internal/static_assert.h +ruby_parser.$(OBJEXT): $(top_srcdir)/internal/string.h +ruby_parser.$(OBJEXT): $(top_srcdir)/internal/vm.h +ruby_parser.$(OBJEXT): {$(VPATH)}assert.h +ruby_parser.$(OBJEXT): {$(VPATH)}backward/2/assume.h +ruby_parser.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +ruby_parser.$(OBJEXT): {$(VPATH)}backward/2/bool.h +ruby_parser.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h +ruby_parser.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +ruby_parser.$(OBJEXT): {$(VPATH)}backward/2/limits.h +ruby_parser.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +ruby_parser.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +ruby_parser.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h +ruby_parser.$(OBJEXT): {$(VPATH)}config.h +ruby_parser.$(OBJEXT): {$(VPATH)}defines.h +ruby_parser.$(OBJEXT): {$(VPATH)}encoding.h +ruby_parser.$(OBJEXT): {$(VPATH)}intern.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/abi.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/anyargs.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/assume.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/const.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/error.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/format.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/packed_struct.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/cast.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/config.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/constant_p.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/core.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/core/robject.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/ctype.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/dllexport.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/dosish.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/encoding/re.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/encoding/string.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/error.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/eval.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/event.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/fl_type.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/gc.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/glob.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/globals.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/has/extension.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/has/feature.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/has/warning.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/array.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/class.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/error.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/file.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/io.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/load.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/object.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/process.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/random.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/range.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/re.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/select.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/set.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/signal.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/string.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/time.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/interpreter.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/iterator.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/memory.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/method.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/module.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/newobj.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/scan_args.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/special_consts.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/static_assert.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/stdalign.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/stdbool.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/stdckdint.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/symbol.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/value.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/value_type.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/variable.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/warning_push.h +ruby_parser.$(OBJEXT): {$(VPATH)}internal/xmalloc.h +ruby_parser.$(OBJEXT): {$(VPATH)}missing.h +ruby_parser.$(OBJEXT): {$(VPATH)}node.h +ruby_parser.$(OBJEXT): {$(VPATH)}onigmo.h +ruby_parser.$(OBJEXT): {$(VPATH)}oniguruma.h +ruby_parser.$(OBJEXT): {$(VPATH)}ruby_assert.h ruby_parser.$(OBJEXT): {$(VPATH)}ruby_parser.c +ruby_parser.$(OBJEXT): {$(VPATH)}rubyparser.h +ruby_parser.$(OBJEXT): {$(VPATH)}st.h +ruby_parser.$(OBJEXT): {$(VPATH)}subst.h scheduler.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h scheduler.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h scheduler.$(OBJEXT): $(CCAN_DIR)/list/list.h @@ -14436,7 +16848,10 @@ scheduler.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h scheduler.$(OBJEXT): $(top_srcdir)/internal/compilers.h scheduler.$(OBJEXT): $(top_srcdir)/internal/gc.h scheduler.$(OBJEXT): $(top_srcdir)/internal/imemo.h +scheduler.$(OBJEXT): $(top_srcdir)/internal/namespace.h +scheduler.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h scheduler.$(OBJEXT): $(top_srcdir)/internal/serial.h +scheduler.$(OBJEXT): $(top_srcdir)/internal/set_table.h scheduler.$(OBJEXT): $(top_srcdir)/internal/static_assert.h scheduler.$(OBJEXT): $(top_srcdir)/internal/thread.h scheduler.$(OBJEXT): $(top_srcdir)/internal/variable.h @@ -14585,6 +17000,7 @@ scheduler.$(OBJEXT): {$(VPATH)}internal/intern/re.h scheduler.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h scheduler.$(OBJEXT): {$(VPATH)}internal/intern/select.h scheduler.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +scheduler.$(OBJEXT): {$(VPATH)}internal/intern/set.h scheduler.$(OBJEXT): {$(VPATH)}internal/intern/signal.h scheduler.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h scheduler.$(OBJEXT): {$(VPATH)}internal/intern/string.h @@ -14604,6 +17020,7 @@ scheduler.$(OBJEXT): {$(VPATH)}internal/special_consts.h scheduler.$(OBJEXT): {$(VPATH)}internal/static_assert.h scheduler.$(OBJEXT): {$(VPATH)}internal/stdalign.h scheduler.$(OBJEXT): {$(VPATH)}internal/stdbool.h +scheduler.$(OBJEXT): {$(VPATH)}internal/stdckdint.h scheduler.$(OBJEXT): {$(VPATH)}internal/symbol.h scheduler.$(OBJEXT): {$(VPATH)}internal/value.h scheduler.$(OBJEXT): {$(VPATH)}internal/value_type.h @@ -14624,10 +17041,221 @@ scheduler.$(OBJEXT): {$(VPATH)}scheduler.c scheduler.$(OBJEXT): {$(VPATH)}shape.h scheduler.$(OBJEXT): {$(VPATH)}st.h scheduler.$(OBJEXT): {$(VPATH)}subst.h +scheduler.$(OBJEXT): {$(VPATH)}thread.h scheduler.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h scheduler.$(OBJEXT): {$(VPATH)}thread_native.h scheduler.$(OBJEXT): {$(VPATH)}vm_core.h scheduler.$(OBJEXT): {$(VPATH)}vm_opts.h +set.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h +set.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h +set.$(OBJEXT): $(CCAN_DIR)/list/list.h +set.$(OBJEXT): $(CCAN_DIR)/str/str.h +set.$(OBJEXT): $(hdrdir)/ruby/ruby.h +set.$(OBJEXT): $(top_srcdir)/internal/array.h +set.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h +set.$(OBJEXT): $(top_srcdir)/internal/bits.h +set.$(OBJEXT): $(top_srcdir)/internal/compilers.h +set.$(OBJEXT): $(top_srcdir)/internal/error.h +set.$(OBJEXT): $(top_srcdir)/internal/gc.h +set.$(OBJEXT): $(top_srcdir)/internal/hash.h +set.$(OBJEXT): $(top_srcdir)/internal/imemo.h +set.$(OBJEXT): $(top_srcdir)/internal/namespace.h +set.$(OBJEXT): $(top_srcdir)/internal/proc.h +set.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h +set.$(OBJEXT): $(top_srcdir)/internal/serial.h +set.$(OBJEXT): $(top_srcdir)/internal/set_table.h +set.$(OBJEXT): $(top_srcdir)/internal/static_assert.h +set.$(OBJEXT): $(top_srcdir)/internal/string.h +set.$(OBJEXT): $(top_srcdir)/internal/symbol.h +set.$(OBJEXT): $(top_srcdir)/internal/variable.h +set.$(OBJEXT): $(top_srcdir)/internal/vm.h +set.$(OBJEXT): $(top_srcdir)/internal/warnings.h +set.$(OBJEXT): {$(VPATH)}assert.h +set.$(OBJEXT): {$(VPATH)}atomic.h +set.$(OBJEXT): {$(VPATH)}backward/2/assume.h +set.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +set.$(OBJEXT): {$(VPATH)}backward/2/bool.h +set.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h +set.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +set.$(OBJEXT): {$(VPATH)}backward/2/limits.h +set.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +set.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +set.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h +set.$(OBJEXT): {$(VPATH)}config.h +set.$(OBJEXT): {$(VPATH)}constant.h +set.$(OBJEXT): {$(VPATH)}defines.h +set.$(OBJEXT): {$(VPATH)}encoding.h +set.$(OBJEXT): {$(VPATH)}id.h +set.$(OBJEXT): {$(VPATH)}id_table.h +set.$(OBJEXT): {$(VPATH)}intern.h +set.$(OBJEXT): {$(VPATH)}internal.h +set.$(OBJEXT): {$(VPATH)}internal/abi.h +set.$(OBJEXT): {$(VPATH)}internal/anyargs.h +set.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +set.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +set.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +set.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +set.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +set.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +set.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +set.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +set.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +set.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +set.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +set.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +set.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +set.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +set.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +set.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +set.$(OBJEXT): {$(VPATH)}internal/assume.h +set.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +set.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +set.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +set.$(OBJEXT): {$(VPATH)}internal/attr/const.h +set.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +set.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +set.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +set.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +set.$(OBJEXT): {$(VPATH)}internal/attr/error.h +set.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +set.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +set.$(OBJEXT): {$(VPATH)}internal/attr/format.h +set.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +set.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +set.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +set.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +set.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +set.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +set.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +set.$(OBJEXT): {$(VPATH)}internal/attr/packed_struct.h +set.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +set.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +set.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +set.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +set.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +set.$(OBJEXT): {$(VPATH)}internal/cast.h +set.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +set.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +set.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +set.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +set.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +set.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +set.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +set.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +set.$(OBJEXT): {$(VPATH)}internal/config.h +set.$(OBJEXT): {$(VPATH)}internal/constant_p.h +set.$(OBJEXT): {$(VPATH)}internal/core.h +set.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +set.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +set.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +set.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +set.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +set.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +set.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +set.$(OBJEXT): {$(VPATH)}internal/core/robject.h +set.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +set.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +set.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +set.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +set.$(OBJEXT): {$(VPATH)}internal/ctype.h +set.$(OBJEXT): {$(VPATH)}internal/dllexport.h +set.$(OBJEXT): {$(VPATH)}internal/dosish.h +set.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h +set.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h +set.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h +set.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h +set.$(OBJEXT): {$(VPATH)}internal/encoding/re.h +set.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h +set.$(OBJEXT): {$(VPATH)}internal/encoding/string.h +set.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h +set.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h +set.$(OBJEXT): {$(VPATH)}internal/error.h +set.$(OBJEXT): {$(VPATH)}internal/eval.h +set.$(OBJEXT): {$(VPATH)}internal/event.h +set.$(OBJEXT): {$(VPATH)}internal/fl_type.h +set.$(OBJEXT): {$(VPATH)}internal/gc.h +set.$(OBJEXT): {$(VPATH)}internal/glob.h +set.$(OBJEXT): {$(VPATH)}internal/globals.h +set.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +set.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +set.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +set.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +set.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +set.$(OBJEXT): {$(VPATH)}internal/has/extension.h +set.$(OBJEXT): {$(VPATH)}internal/has/feature.h +set.$(OBJEXT): {$(VPATH)}internal/has/warning.h +set.$(OBJEXT): {$(VPATH)}internal/intern/array.h +set.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +set.$(OBJEXT): {$(VPATH)}internal/intern/class.h +set.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +set.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +set.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +set.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +set.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +set.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +set.$(OBJEXT): {$(VPATH)}internal/intern/error.h +set.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +set.$(OBJEXT): {$(VPATH)}internal/intern/file.h +set.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +set.$(OBJEXT): {$(VPATH)}internal/intern/io.h +set.$(OBJEXT): {$(VPATH)}internal/intern/load.h +set.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +set.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +set.$(OBJEXT): {$(VPATH)}internal/intern/object.h +set.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +set.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +set.$(OBJEXT): {$(VPATH)}internal/intern/process.h +set.$(OBJEXT): {$(VPATH)}internal/intern/random.h +set.$(OBJEXT): {$(VPATH)}internal/intern/range.h +set.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +set.$(OBJEXT): {$(VPATH)}internal/intern/re.h +set.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h +set.$(OBJEXT): {$(VPATH)}internal/intern/select.h +set.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +set.$(OBJEXT): {$(VPATH)}internal/intern/set.h +set.$(OBJEXT): {$(VPATH)}internal/intern/signal.h +set.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +set.$(OBJEXT): {$(VPATH)}internal/intern/string.h +set.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +set.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +set.$(OBJEXT): {$(VPATH)}internal/intern/time.h +set.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +set.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +set.$(OBJEXT): {$(VPATH)}internal/interpreter.h +set.$(OBJEXT): {$(VPATH)}internal/iterator.h +set.$(OBJEXT): {$(VPATH)}internal/memory.h +set.$(OBJEXT): {$(VPATH)}internal/method.h +set.$(OBJEXT): {$(VPATH)}internal/module.h +set.$(OBJEXT): {$(VPATH)}internal/newobj.h +set.$(OBJEXT): {$(VPATH)}internal/scan_args.h +set.$(OBJEXT): {$(VPATH)}internal/set_table.h +set.$(OBJEXT): {$(VPATH)}internal/special_consts.h +set.$(OBJEXT): {$(VPATH)}internal/static_assert.h +set.$(OBJEXT): {$(VPATH)}internal/stdalign.h +set.$(OBJEXT): {$(VPATH)}internal/stdbool.h +set.$(OBJEXT): {$(VPATH)}internal/stdckdint.h +set.$(OBJEXT): {$(VPATH)}internal/symbol.h +set.$(OBJEXT): {$(VPATH)}internal/value.h +set.$(OBJEXT): {$(VPATH)}internal/value_type.h +set.$(OBJEXT): {$(VPATH)}internal/variable.h +set.$(OBJEXT): {$(VPATH)}internal/warning_push.h +set.$(OBJEXT): {$(VPATH)}internal/xmalloc.h +set.$(OBJEXT): {$(VPATH)}method.h +set.$(OBJEXT): {$(VPATH)}missing.h +set.$(OBJEXT): {$(VPATH)}node.h +set.$(OBJEXT): {$(VPATH)}onigmo.h +set.$(OBJEXT): {$(VPATH)}oniguruma.h +set.$(OBJEXT): {$(VPATH)}ruby_assert.h +set.$(OBJEXT): {$(VPATH)}ruby_atomic.h +set.$(OBJEXT): {$(VPATH)}rubyparser.h +set.$(OBJEXT): {$(VPATH)}set.c +set.$(OBJEXT): {$(VPATH)}shape.h +set.$(OBJEXT): {$(VPATH)}st.h +set.$(OBJEXT): {$(VPATH)}subst.h +set.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h +set.$(OBJEXT): {$(VPATH)}thread_native.h +set.$(OBJEXT): {$(VPATH)}vm_core.h +set.$(OBJEXT): {$(VPATH)}vm_opts.h setproctitle.$(OBJEXT): $(hdrdir)/ruby.h setproctitle.$(OBJEXT): $(hdrdir)/ruby/ruby.h setproctitle.$(OBJEXT): {$(VPATH)}assert.h @@ -14756,6 +17384,7 @@ setproctitle.$(OBJEXT): {$(VPATH)}internal/intern/re.h setproctitle.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h setproctitle.$(OBJEXT): {$(VPATH)}internal/intern/select.h setproctitle.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/intern/set.h setproctitle.$(OBJEXT): {$(VPATH)}internal/intern/signal.h setproctitle.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h setproctitle.$(OBJEXT): {$(VPATH)}internal/intern/string.h @@ -14775,6 +17404,7 @@ setproctitle.$(OBJEXT): {$(VPATH)}internal/special_consts.h setproctitle.$(OBJEXT): {$(VPATH)}internal/static_assert.h setproctitle.$(OBJEXT): {$(VPATH)}internal/stdalign.h setproctitle.$(OBJEXT): {$(VPATH)}internal/stdbool.h +setproctitle.$(OBJEXT): {$(VPATH)}internal/stdckdint.h setproctitle.$(OBJEXT): {$(VPATH)}internal/symbol.h setproctitle.$(OBJEXT): {$(VPATH)}internal/value.h setproctitle.$(OBJEXT): {$(VPATH)}internal/value_type.h @@ -14791,6 +17421,7 @@ shape.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h shape.$(OBJEXT): $(CCAN_DIR)/list/list.h shape.$(OBJEXT): $(CCAN_DIR)/str/str.h shape.$(OBJEXT): $(hdrdir)/ruby/ruby.h +shape.$(OBJEXT): $(hdrdir)/ruby/version.h shape.$(OBJEXT): $(top_srcdir)/internal/array.h shape.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h shape.$(OBJEXT): $(top_srcdir)/internal/class.h @@ -14798,7 +17429,11 @@ shape.$(OBJEXT): $(top_srcdir)/internal/compilers.h shape.$(OBJEXT): $(top_srcdir)/internal/error.h shape.$(OBJEXT): $(top_srcdir)/internal/gc.h shape.$(OBJEXT): $(top_srcdir)/internal/imemo.h +shape.$(OBJEXT): $(top_srcdir)/internal/namespace.h +shape.$(OBJEXT): $(top_srcdir)/internal/object.h +shape.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h shape.$(OBJEXT): $(top_srcdir)/internal/serial.h +shape.$(OBJEXT): $(top_srcdir)/internal/set_table.h shape.$(OBJEXT): $(top_srcdir)/internal/static_assert.h shape.$(OBJEXT): $(top_srcdir)/internal/string.h shape.$(OBJEXT): $(top_srcdir)/internal/symbol.h @@ -14948,6 +17583,7 @@ shape.$(OBJEXT): {$(VPATH)}internal/intern/re.h shape.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h shape.$(OBJEXT): {$(VPATH)}internal/intern/select.h shape.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +shape.$(OBJEXT): {$(VPATH)}internal/intern/set.h shape.$(OBJEXT): {$(VPATH)}internal/intern/signal.h shape.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h shape.$(OBJEXT): {$(VPATH)}internal/intern/string.h @@ -14967,6 +17603,7 @@ shape.$(OBJEXT): {$(VPATH)}internal/special_consts.h shape.$(OBJEXT): {$(VPATH)}internal/static_assert.h shape.$(OBJEXT): {$(VPATH)}internal/stdalign.h shape.$(OBJEXT): {$(VPATH)}internal/stdbool.h +shape.$(OBJEXT): {$(VPATH)}internal/stdckdint.h shape.$(OBJEXT): {$(VPATH)}internal/symbol.h shape.$(OBJEXT): {$(VPATH)}internal/value.h shape.$(OBJEXT): {$(VPATH)}internal/value_type.h @@ -14998,6 +17635,7 @@ signal.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h signal.$(OBJEXT): $(CCAN_DIR)/list/list.h signal.$(OBJEXT): $(CCAN_DIR)/str/str.h signal.$(OBJEXT): $(hdrdir)/ruby/ruby.h +signal.$(OBJEXT): $(hdrdir)/ruby/version.h signal.$(OBJEXT): $(top_srcdir)/internal/array.h signal.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h signal.$(OBJEXT): $(top_srcdir)/internal/compilers.h @@ -15005,8 +17643,10 @@ signal.$(OBJEXT): $(top_srcdir)/internal/error.h signal.$(OBJEXT): $(top_srcdir)/internal/eval.h signal.$(OBJEXT): $(top_srcdir)/internal/gc.h signal.$(OBJEXT): $(top_srcdir)/internal/imemo.h +signal.$(OBJEXT): $(top_srcdir)/internal/namespace.h signal.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h signal.$(OBJEXT): $(top_srcdir)/internal/serial.h +signal.$(OBJEXT): $(top_srcdir)/internal/set_table.h signal.$(OBJEXT): $(top_srcdir)/internal/signal.h signal.$(OBJEXT): $(top_srcdir)/internal/static_assert.h signal.$(OBJEXT): $(top_srcdir)/internal/string.h @@ -15072,6 +17712,7 @@ signal.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h signal.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h signal.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h signal.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +signal.$(OBJEXT): {$(VPATH)}internal/attr/nonstring.h signal.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h signal.$(OBJEXT): {$(VPATH)}internal/attr/packed_struct.h signal.$(OBJEXT): {$(VPATH)}internal/attr/pure.h @@ -15158,6 +17799,7 @@ signal.$(OBJEXT): {$(VPATH)}internal/intern/re.h signal.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h signal.$(OBJEXT): {$(VPATH)}internal/intern/select.h signal.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +signal.$(OBJEXT): {$(VPATH)}internal/intern/set.h signal.$(OBJEXT): {$(VPATH)}internal/intern/signal.h signal.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h signal.$(OBJEXT): {$(VPATH)}internal/intern/string.h @@ -15177,6 +17819,7 @@ signal.$(OBJEXT): {$(VPATH)}internal/special_consts.h signal.$(OBJEXT): {$(VPATH)}internal/static_assert.h signal.$(OBJEXT): {$(VPATH)}internal/stdalign.h signal.$(OBJEXT): {$(VPATH)}internal/stdbool.h +signal.$(OBJEXT): {$(VPATH)}internal/stdckdint.h signal.$(OBJEXT): {$(VPATH)}internal/symbol.h signal.$(OBJEXT): {$(VPATH)}internal/value.h signal.$(OBJEXT): {$(VPATH)}internal/value_type.h @@ -15203,6 +17846,7 @@ signal.$(OBJEXT): {$(VPATH)}vm_core.h signal.$(OBJEXT): {$(VPATH)}vm_debug.h signal.$(OBJEXT): {$(VPATH)}vm_opts.h sprintf.$(OBJEXT): $(hdrdir)/ruby/ruby.h +sprintf.$(OBJEXT): $(hdrdir)/ruby/version.h sprintf.$(OBJEXT): $(top_srcdir)/internal/bignum.h sprintf.$(OBJEXT): $(top_srcdir)/internal/bits.h sprintf.$(OBJEXT): $(top_srcdir)/internal/class.h @@ -15363,6 +18007,7 @@ sprintf.$(OBJEXT): {$(VPATH)}internal/intern/re.h sprintf.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h sprintf.$(OBJEXT): {$(VPATH)}internal/intern/select.h sprintf.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +sprintf.$(OBJEXT): {$(VPATH)}internal/intern/set.h sprintf.$(OBJEXT): {$(VPATH)}internal/intern/signal.h sprintf.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h sprintf.$(OBJEXT): {$(VPATH)}internal/intern/string.h @@ -15382,6 +18027,7 @@ sprintf.$(OBJEXT): {$(VPATH)}internal/special_consts.h sprintf.$(OBJEXT): {$(VPATH)}internal/static_assert.h sprintf.$(OBJEXT): {$(VPATH)}internal/stdalign.h sprintf.$(OBJEXT): {$(VPATH)}internal/stdbool.h +sprintf.$(OBJEXT): {$(VPATH)}internal/stdckdint.h sprintf.$(OBJEXT): {$(VPATH)}internal/symbol.h sprintf.$(OBJEXT): {$(VPATH)}internal/value.h sprintf.$(OBJEXT): {$(VPATH)}internal/value_type.h @@ -15404,6 +18050,8 @@ st.$(OBJEXT): $(top_srcdir)/internal/bits.h st.$(OBJEXT): $(top_srcdir)/internal/compilers.h st.$(OBJEXT): $(top_srcdir)/internal/hash.h st.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h +st.$(OBJEXT): $(top_srcdir)/internal/set_table.h +st.$(OBJEXT): $(top_srcdir)/internal/st.h st.$(OBJEXT): $(top_srcdir)/internal/static_assert.h st.$(OBJEXT): $(top_srcdir)/internal/warnings.h st.$(OBJEXT): {$(VPATH)}assert.h @@ -15534,6 +18182,7 @@ st.$(OBJEXT): {$(VPATH)}internal/intern/re.h st.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h st.$(OBJEXT): {$(VPATH)}internal/intern/select.h st.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +st.$(OBJEXT): {$(VPATH)}internal/intern/set.h st.$(OBJEXT): {$(VPATH)}internal/intern/signal.h st.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h st.$(OBJEXT): {$(VPATH)}internal/intern/string.h @@ -15550,9 +18199,11 @@ st.$(OBJEXT): {$(VPATH)}internal/module.h st.$(OBJEXT): {$(VPATH)}internal/newobj.h st.$(OBJEXT): {$(VPATH)}internal/scan_args.h st.$(OBJEXT): {$(VPATH)}internal/special_consts.h +st.$(OBJEXT): {$(VPATH)}internal/st.h st.$(OBJEXT): {$(VPATH)}internal/static_assert.h st.$(OBJEXT): {$(VPATH)}internal/stdalign.h st.$(OBJEXT): {$(VPATH)}internal/stdbool.h +st.$(OBJEXT): {$(VPATH)}internal/stdckdint.h st.$(OBJEXT): {$(VPATH)}internal/symbol.h st.$(OBJEXT): {$(VPATH)}internal/value.h st.$(OBJEXT): {$(VPATH)}internal/value_type.h @@ -15560,6 +18211,7 @@ st.$(OBJEXT): {$(VPATH)}internal/variable.h st.$(OBJEXT): {$(VPATH)}internal/warning_push.h st.$(OBJEXT): {$(VPATH)}internal/xmalloc.h st.$(OBJEXT): {$(VPATH)}missing.h +st.$(OBJEXT): {$(VPATH)}ruby_assert.h st.$(OBJEXT): {$(VPATH)}st.c st.$(OBJEXT): {$(VPATH)}st.h st.$(OBJEXT): {$(VPATH)}subst.h @@ -15708,6 +18360,7 @@ strftime.$(OBJEXT): {$(VPATH)}internal/intern/re.h strftime.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h strftime.$(OBJEXT): {$(VPATH)}internal/intern/select.h strftime.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +strftime.$(OBJEXT): {$(VPATH)}internal/intern/set.h strftime.$(OBJEXT): {$(VPATH)}internal/intern/signal.h strftime.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h strftime.$(OBJEXT): {$(VPATH)}internal/intern/string.h @@ -15727,6 +18380,7 @@ strftime.$(OBJEXT): {$(VPATH)}internal/special_consts.h strftime.$(OBJEXT): {$(VPATH)}internal/static_assert.h strftime.$(OBJEXT): {$(VPATH)}internal/stdalign.h strftime.$(OBJEXT): {$(VPATH)}internal/stdbool.h +strftime.$(OBJEXT): {$(VPATH)}internal/stdckdint.h strftime.$(OBJEXT): {$(VPATH)}internal/symbol.h strftime.$(OBJEXT): {$(VPATH)}internal/value.h strftime.$(OBJEXT): {$(VPATH)}internal/value_type.h @@ -15746,6 +18400,7 @@ string.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h string.$(OBJEXT): $(CCAN_DIR)/list/list.h string.$(OBJEXT): $(CCAN_DIR)/str/str.h string.$(OBJEXT): $(hdrdir)/ruby/ruby.h +string.$(OBJEXT): $(hdrdir)/ruby/version.h string.$(OBJEXT): $(top_srcdir)/internal/array.h string.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h string.$(OBJEXT): $(top_srcdir)/internal/bignum.h @@ -15753,17 +18408,21 @@ string.$(OBJEXT): $(top_srcdir)/internal/bits.h string.$(OBJEXT): $(top_srcdir)/internal/class.h string.$(OBJEXT): $(top_srcdir)/internal/compar.h string.$(OBJEXT): $(top_srcdir)/internal/compilers.h +string.$(OBJEXT): $(top_srcdir)/internal/concurrent_set.h string.$(OBJEXT): $(top_srcdir)/internal/encoding.h string.$(OBJEXT): $(top_srcdir)/internal/error.h string.$(OBJEXT): $(top_srcdir)/internal/fixnum.h string.$(OBJEXT): $(top_srcdir)/internal/gc.h +string.$(OBJEXT): $(top_srcdir)/internal/hash.h string.$(OBJEXT): $(top_srcdir)/internal/imemo.h +string.$(OBJEXT): $(top_srcdir)/internal/namespace.h string.$(OBJEXT): $(top_srcdir)/internal/numeric.h string.$(OBJEXT): $(top_srcdir)/internal/object.h string.$(OBJEXT): $(top_srcdir)/internal/proc.h string.$(OBJEXT): $(top_srcdir)/internal/re.h string.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h string.$(OBJEXT): $(top_srcdir)/internal/serial.h +string.$(OBJEXT): $(top_srcdir)/internal/set_table.h string.$(OBJEXT): $(top_srcdir)/internal/static_assert.h string.$(OBJEXT): $(top_srcdir)/internal/string.h string.$(OBJEXT): $(top_srcdir)/internal/transcode.h @@ -15828,6 +18487,7 @@ string.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h string.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h string.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h string.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +string.$(OBJEXT): {$(VPATH)}internal/attr/nonstring.h string.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h string.$(OBJEXT): {$(VPATH)}internal/attr/packed_struct.h string.$(OBJEXT): {$(VPATH)}internal/attr/pure.h @@ -15915,6 +18575,7 @@ string.$(OBJEXT): {$(VPATH)}internal/intern/re.h string.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h string.$(OBJEXT): {$(VPATH)}internal/intern/select.h string.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +string.$(OBJEXT): {$(VPATH)}internal/intern/set.h string.$(OBJEXT): {$(VPATH)}internal/intern/signal.h string.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h string.$(OBJEXT): {$(VPATH)}internal/intern/string.h @@ -15934,6 +18595,7 @@ string.$(OBJEXT): {$(VPATH)}internal/special_consts.h string.$(OBJEXT): {$(VPATH)}internal/static_assert.h string.$(OBJEXT): {$(VPATH)}internal/stdalign.h string.$(OBJEXT): {$(VPATH)}internal/stdbool.h +string.$(OBJEXT): {$(VPATH)}internal/stdckdint.h string.$(OBJEXT): {$(VPATH)}internal/symbol.h string.$(OBJEXT): {$(VPATH)}internal/value.h string.$(OBJEXT): {$(VPATH)}internal/value_type.h @@ -15956,6 +18618,7 @@ string.$(OBJEXT): {$(VPATH)}shape.h string.$(OBJEXT): {$(VPATH)}st.h string.$(OBJEXT): {$(VPATH)}string.c string.$(OBJEXT): {$(VPATH)}subst.h +string.$(OBJEXT): {$(VPATH)}thread.h string.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h string.$(OBJEXT): {$(VPATH)}thread_native.h string.$(OBJEXT): {$(VPATH)}util.h @@ -15998,6 +18661,7 @@ struct.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h struct.$(OBJEXT): $(CCAN_DIR)/list/list.h struct.$(OBJEXT): $(CCAN_DIR)/str/str.h struct.$(OBJEXT): $(hdrdir)/ruby/ruby.h +struct.$(OBJEXT): $(hdrdir)/ruby/version.h struct.$(OBJEXT): $(top_srcdir)/internal/array.h struct.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h struct.$(OBJEXT): $(top_srcdir)/internal/class.h @@ -16006,9 +18670,12 @@ struct.$(OBJEXT): $(top_srcdir)/internal/error.h struct.$(OBJEXT): $(top_srcdir)/internal/gc.h struct.$(OBJEXT): $(top_srcdir)/internal/hash.h struct.$(OBJEXT): $(top_srcdir)/internal/imemo.h +struct.$(OBJEXT): $(top_srcdir)/internal/namespace.h struct.$(OBJEXT): $(top_srcdir)/internal/object.h struct.$(OBJEXT): $(top_srcdir)/internal/proc.h +struct.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h struct.$(OBJEXT): $(top_srcdir)/internal/serial.h +struct.$(OBJEXT): $(top_srcdir)/internal/set_table.h struct.$(OBJEXT): $(top_srcdir)/internal/static_assert.h struct.$(OBJEXT): $(top_srcdir)/internal/string.h struct.$(OBJEXT): $(top_srcdir)/internal/struct.h @@ -16030,6 +18697,7 @@ struct.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h struct.$(OBJEXT): {$(VPATH)}builtin.h struct.$(OBJEXT): {$(VPATH)}config.h struct.$(OBJEXT): {$(VPATH)}constant.h +struct.$(OBJEXT): {$(VPATH)}debug_counter.h struct.$(OBJEXT): {$(VPATH)}defines.h struct.$(OBJEXT): {$(VPATH)}encoding.h struct.$(OBJEXT): {$(VPATH)}id.h @@ -16159,6 +18827,7 @@ struct.$(OBJEXT): {$(VPATH)}internal/intern/re.h struct.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h struct.$(OBJEXT): {$(VPATH)}internal/intern/select.h struct.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +struct.$(OBJEXT): {$(VPATH)}internal/intern/set.h struct.$(OBJEXT): {$(VPATH)}internal/intern/signal.h struct.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h struct.$(OBJEXT): {$(VPATH)}internal/intern/string.h @@ -16178,6 +18847,7 @@ struct.$(OBJEXT): {$(VPATH)}internal/special_consts.h struct.$(OBJEXT): {$(VPATH)}internal/static_assert.h struct.$(OBJEXT): {$(VPATH)}internal/stdalign.h struct.$(OBJEXT): {$(VPATH)}internal/stdbool.h +struct.$(OBJEXT): {$(VPATH)}internal/stdckdint.h struct.$(OBJEXT): {$(VPATH)}internal/symbol.h struct.$(OBJEXT): {$(VPATH)}internal/value.h struct.$(OBJEXT): {$(VPATH)}internal/value_type.h @@ -16199,12 +18869,15 @@ struct.$(OBJEXT): {$(VPATH)}subst.h struct.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h struct.$(OBJEXT): {$(VPATH)}thread_native.h struct.$(OBJEXT): {$(VPATH)}vm_core.h +struct.$(OBJEXT): {$(VPATH)}vm_debug.h struct.$(OBJEXT): {$(VPATH)}vm_opts.h +struct.$(OBJEXT): {$(VPATH)}vm_sync.h symbol.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h symbol.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h symbol.$(OBJEXT): $(CCAN_DIR)/list/list.h symbol.$(OBJEXT): $(CCAN_DIR)/str/str.h symbol.$(OBJEXT): $(hdrdir)/ruby/ruby.h +symbol.$(OBJEXT): $(hdrdir)/ruby/version.h symbol.$(OBJEXT): $(top_srcdir)/internal/array.h symbol.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h symbol.$(OBJEXT): $(top_srcdir)/internal/class.h @@ -16213,8 +18886,11 @@ symbol.$(OBJEXT): $(top_srcdir)/internal/error.h symbol.$(OBJEXT): $(top_srcdir)/internal/gc.h symbol.$(OBJEXT): $(top_srcdir)/internal/hash.h symbol.$(OBJEXT): $(top_srcdir)/internal/imemo.h +symbol.$(OBJEXT): $(top_srcdir)/internal/namespace.h symbol.$(OBJEXT): $(top_srcdir)/internal/object.h +symbol.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h symbol.$(OBJEXT): $(top_srcdir)/internal/serial.h +symbol.$(OBJEXT): $(top_srcdir)/internal/set_table.h symbol.$(OBJEXT): $(top_srcdir)/internal/static_assert.h symbol.$(OBJEXT): $(top_srcdir)/internal/string.h symbol.$(OBJEXT): $(top_srcdir)/internal/symbol.h @@ -16281,6 +18957,7 @@ symbol.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h symbol.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h symbol.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h symbol.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +symbol.$(OBJEXT): {$(VPATH)}internal/attr/nonstring.h symbol.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h symbol.$(OBJEXT): {$(VPATH)}internal/attr/packed_struct.h symbol.$(OBJEXT): {$(VPATH)}internal/attr/pure.h @@ -16367,6 +19044,7 @@ symbol.$(OBJEXT): {$(VPATH)}internal/intern/re.h symbol.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h symbol.$(OBJEXT): {$(VPATH)}internal/intern/select.h symbol.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +symbol.$(OBJEXT): {$(VPATH)}internal/intern/set.h symbol.$(OBJEXT): {$(VPATH)}internal/intern/signal.h symbol.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h symbol.$(OBJEXT): {$(VPATH)}internal/intern/string.h @@ -16386,6 +19064,7 @@ symbol.$(OBJEXT): {$(VPATH)}internal/special_consts.h symbol.$(OBJEXT): {$(VPATH)}internal/static_assert.h symbol.$(OBJEXT): {$(VPATH)}internal/stdalign.h symbol.$(OBJEXT): {$(VPATH)}internal/stdbool.h +symbol.$(OBJEXT): {$(VPATH)}internal/stdckdint.h symbol.$(OBJEXT): {$(VPATH)}internal/symbol.h symbol.$(OBJEXT): {$(VPATH)}internal/value.h symbol.$(OBJEXT): {$(VPATH)}internal/value_type.h @@ -16421,6 +19100,7 @@ thread.$(OBJEXT): $(CCAN_DIR)/list/list.h thread.$(OBJEXT): $(CCAN_DIR)/str/str.h thread.$(OBJEXT): $(hdrdir)/ruby.h thread.$(OBJEXT): $(hdrdir)/ruby/ruby.h +thread.$(OBJEXT): $(hdrdir)/ruby/version.h thread.$(OBJEXT): $(top_srcdir)/internal/array.h thread.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h thread.$(OBJEXT): $(top_srcdir)/internal/bits.h @@ -16432,9 +19112,12 @@ thread.$(OBJEXT): $(top_srcdir)/internal/gc.h thread.$(OBJEXT): $(top_srcdir)/internal/hash.h thread.$(OBJEXT): $(top_srcdir)/internal/imemo.h thread.$(OBJEXT): $(top_srcdir)/internal/io.h +thread.$(OBJEXT): $(top_srcdir)/internal/namespace.h thread.$(OBJEXT): $(top_srcdir)/internal/object.h thread.$(OBJEXT): $(top_srcdir)/internal/proc.h +thread.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h thread.$(OBJEXT): $(top_srcdir)/internal/serial.h +thread.$(OBJEXT): $(top_srcdir)/internal/set_table.h thread.$(OBJEXT): $(top_srcdir)/internal/signal.h thread.$(OBJEXT): $(top_srcdir)/internal/static_assert.h thread.$(OBJEXT): $(top_srcdir)/internal/string.h @@ -16443,6 +19126,27 @@ thread.$(OBJEXT): $(top_srcdir)/internal/time.h thread.$(OBJEXT): $(top_srcdir)/internal/variable.h thread.$(OBJEXT): $(top_srcdir)/internal/vm.h thread.$(OBJEXT): $(top_srcdir)/internal/warnings.h +thread.$(OBJEXT): $(top_srcdir)/prism/defines.h +thread.$(OBJEXT): $(top_srcdir)/prism/encoding.h +thread.$(OBJEXT): $(top_srcdir)/prism/node.h +thread.$(OBJEXT): $(top_srcdir)/prism/options.h +thread.$(OBJEXT): $(top_srcdir)/prism/pack.h +thread.$(OBJEXT): $(top_srcdir)/prism/parser.h +thread.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h +thread.$(OBJEXT): $(top_srcdir)/prism/prism.h +thread.$(OBJEXT): $(top_srcdir)/prism/regexp.h +thread.$(OBJEXT): $(top_srcdir)/prism/static_literals.h +thread.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h +thread.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h +thread.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h +thread.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h +thread.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h +thread.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h +thread.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h +thread.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h +thread.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h +thread.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h +thread.$(OBJEXT): {$(VPATH)}$(COROUTINE_H) thread.$(OBJEXT): {$(VPATH)}assert.h thread.$(OBJEXT): {$(VPATH)}atomic.h thread.$(OBJEXT): {$(VPATH)}backward/2/assume.h @@ -16591,6 +19295,7 @@ thread.$(OBJEXT): {$(VPATH)}internal/intern/re.h thread.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h thread.$(OBJEXT): {$(VPATH)}internal/intern/select.h thread.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +thread.$(OBJEXT): {$(VPATH)}internal/intern/set.h thread.$(OBJEXT): {$(VPATH)}internal/intern/signal.h thread.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h thread.$(OBJEXT): {$(VPATH)}internal/intern/string.h @@ -16610,6 +19315,7 @@ thread.$(OBJEXT): {$(VPATH)}internal/special_consts.h thread.$(OBJEXT): {$(VPATH)}internal/static_assert.h thread.$(OBJEXT): {$(VPATH)}internal/stdalign.h thread.$(OBJEXT): {$(VPATH)}internal/stdbool.h +thread.$(OBJEXT): {$(VPATH)}internal/stdckdint.h thread.$(OBJEXT): {$(VPATH)}internal/symbol.h thread.$(OBJEXT): {$(VPATH)}internal/value.h thread.$(OBJEXT): {$(VPATH)}internal/value_type.h @@ -16623,9 +19329,12 @@ thread.$(OBJEXT): {$(VPATH)}missing.h thread.$(OBJEXT): {$(VPATH)}node.h thread.$(OBJEXT): {$(VPATH)}onigmo.h thread.$(OBJEXT): {$(VPATH)}oniguruma.h +thread.$(OBJEXT): {$(VPATH)}prism/ast.h +thread.$(OBJEXT): {$(VPATH)}prism/diagnostic.h +thread.$(OBJEXT): {$(VPATH)}prism/version.h +thread.$(OBJEXT): {$(VPATH)}prism_compile.h thread.$(OBJEXT): {$(VPATH)}ractor.h thread.$(OBJEXT): {$(VPATH)}ractor_core.h -thread.$(OBJEXT): {$(VPATH)}rjit.h thread.$(OBJEXT): {$(VPATH)}ruby_assert.h thread.$(OBJEXT): {$(VPATH)}ruby_atomic.h thread.$(OBJEXT): {$(VPATH)}rubyparser.h @@ -16637,6 +19346,7 @@ thread.$(OBJEXT): {$(VPATH)}thread.h thread.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).c thread.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h thread.$(OBJEXT): {$(VPATH)}thread_native.h +thread.$(OBJEXT): {$(VPATH)}thread_pthread_mn.c thread.$(OBJEXT): {$(VPATH)}thread_sync.c thread.$(OBJEXT): {$(VPATH)}thread_sync.rbinc thread.$(OBJEXT): {$(VPATH)}timev.h @@ -16659,9 +19369,12 @@ time.$(OBJEXT): $(top_srcdir)/internal/fixnum.h time.$(OBJEXT): $(top_srcdir)/internal/gc.h time.$(OBJEXT): $(top_srcdir)/internal/hash.h time.$(OBJEXT): $(top_srcdir)/internal/imemo.h +time.$(OBJEXT): $(top_srcdir)/internal/namespace.h time.$(OBJEXT): $(top_srcdir)/internal/numeric.h time.$(OBJEXT): $(top_srcdir)/internal/rational.h +time.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h time.$(OBJEXT): $(top_srcdir)/internal/serial.h +time.$(OBJEXT): $(top_srcdir)/internal/set_table.h time.$(OBJEXT): $(top_srcdir)/internal/static_assert.h time.$(OBJEXT): $(top_srcdir)/internal/string.h time.$(OBJEXT): $(top_srcdir)/internal/time.h @@ -16811,6 +19524,7 @@ time.$(OBJEXT): {$(VPATH)}internal/intern/re.h time.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h time.$(OBJEXT): {$(VPATH)}internal/intern/select.h time.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +time.$(OBJEXT): {$(VPATH)}internal/intern/set.h time.$(OBJEXT): {$(VPATH)}internal/intern/signal.h time.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h time.$(OBJEXT): {$(VPATH)}internal/intern/string.h @@ -16830,6 +19544,7 @@ time.$(OBJEXT): {$(VPATH)}internal/special_consts.h time.$(OBJEXT): {$(VPATH)}internal/static_assert.h time.$(OBJEXT): {$(VPATH)}internal/stdalign.h time.$(OBJEXT): {$(VPATH)}internal/stdbool.h +time.$(OBJEXT): {$(VPATH)}internal/stdckdint.h time.$(OBJEXT): {$(VPATH)}internal/symbol.h time.$(OBJEXT): {$(VPATH)}internal/value.h time.$(OBJEXT): {$(VPATH)}internal/value_type.h @@ -16852,6 +19567,7 @@ time.$(OBJEXT): {$(VPATH)}thread_native.h time.$(OBJEXT): {$(VPATH)}time.c time.$(OBJEXT): {$(VPATH)}timev.h time.$(OBJEXT): {$(VPATH)}timev.rbinc +time.$(OBJEXT): {$(VPATH)}util.h time.$(OBJEXT): {$(VPATH)}vm_core.h time.$(OBJEXT): {$(VPATH)}vm_opts.h transcode.$(OBJEXT): $(hdrdir)/ruby/ruby.h @@ -16879,6 +19595,7 @@ transcode.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h transcode.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h transcode.$(OBJEXT): {$(VPATH)}config.h transcode.$(OBJEXT): {$(VPATH)}constant.h +transcode.$(OBJEXT): {$(VPATH)}debug_counter.h transcode.$(OBJEXT): {$(VPATH)}defines.h transcode.$(OBJEXT): {$(VPATH)}encoding.h transcode.$(OBJEXT): {$(VPATH)}id.h @@ -17008,6 +19725,7 @@ transcode.$(OBJEXT): {$(VPATH)}internal/intern/re.h transcode.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h transcode.$(OBJEXT): {$(VPATH)}internal/intern/select.h transcode.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +transcode.$(OBJEXT): {$(VPATH)}internal/intern/set.h transcode.$(OBJEXT): {$(VPATH)}internal/intern/signal.h transcode.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h transcode.$(OBJEXT): {$(VPATH)}internal/intern/string.h @@ -17027,6 +19745,7 @@ transcode.$(OBJEXT): {$(VPATH)}internal/special_consts.h transcode.$(OBJEXT): {$(VPATH)}internal/static_assert.h transcode.$(OBJEXT): {$(VPATH)}internal/stdalign.h transcode.$(OBJEXT): {$(VPATH)}internal/stdbool.h +transcode.$(OBJEXT): {$(VPATH)}internal/stdckdint.h transcode.$(OBJEXT): {$(VPATH)}internal/symbol.h transcode.$(OBJEXT): {$(VPATH)}internal/value.h transcode.$(OBJEXT): {$(VPATH)}internal/value_type.h @@ -17041,9 +19760,14 @@ transcode.$(OBJEXT): {$(VPATH)}st.h transcode.$(OBJEXT): {$(VPATH)}subst.h transcode.$(OBJEXT): {$(VPATH)}transcode.c transcode.$(OBJEXT): {$(VPATH)}transcode_data.h +transcode.$(OBJEXT): {$(VPATH)}vm_debug.h +transcode.$(OBJEXT): {$(VPATH)}vm_sync.h util.$(OBJEXT): $(hdrdir)/ruby/ruby.h +util.$(OBJEXT): $(top_srcdir)/internal/array.h util.$(OBJEXT): $(top_srcdir)/internal/compilers.h +util.$(OBJEXT): $(top_srcdir)/internal/imemo.h util.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h +util.$(OBJEXT): $(top_srcdir)/internal/static_assert.h util.$(OBJEXT): $(top_srcdir)/internal/util.h util.$(OBJEXT): $(top_srcdir)/internal/warnings.h util.$(OBJEXT): {$(VPATH)}assert.h @@ -17060,6 +19784,7 @@ util.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h util.$(OBJEXT): {$(VPATH)}config.h util.$(OBJEXT): {$(VPATH)}defines.h util.$(OBJEXT): {$(VPATH)}dtoa.c +util.$(OBJEXT): {$(VPATH)}id_table.h util.$(OBJEXT): {$(VPATH)}intern.h util.$(OBJEXT): {$(VPATH)}internal.h util.$(OBJEXT): {$(VPATH)}internal/abi.h @@ -17176,6 +19901,7 @@ util.$(OBJEXT): {$(VPATH)}internal/intern/re.h util.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h util.$(OBJEXT): {$(VPATH)}internal/intern/select.h util.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +util.$(OBJEXT): {$(VPATH)}internal/intern/set.h util.$(OBJEXT): {$(VPATH)}internal/intern/signal.h util.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h util.$(OBJEXT): {$(VPATH)}internal/intern/string.h @@ -17195,6 +19921,7 @@ util.$(OBJEXT): {$(VPATH)}internal/special_consts.h util.$(OBJEXT): {$(VPATH)}internal/static_assert.h util.$(OBJEXT): {$(VPATH)}internal/stdalign.h util.$(OBJEXT): {$(VPATH)}internal/stdbool.h +util.$(OBJEXT): {$(VPATH)}internal/stdckdint.h util.$(OBJEXT): {$(VPATH)}internal/symbol.h util.$(OBJEXT): {$(VPATH)}internal/value.h util.$(OBJEXT): {$(VPATH)}internal/value_type.h @@ -17212,6 +19939,7 @@ variable.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h variable.$(OBJEXT): $(CCAN_DIR)/list/list.h variable.$(OBJEXT): $(CCAN_DIR)/str/str.h variable.$(OBJEXT): $(hdrdir)/ruby/ruby.h +variable.$(OBJEXT): $(hdrdir)/ruby/version.h variable.$(OBJEXT): $(top_srcdir)/internal/array.h variable.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h variable.$(OBJEXT): $(top_srcdir)/internal/class.h @@ -17221,9 +19949,12 @@ variable.$(OBJEXT): $(top_srcdir)/internal/eval.h variable.$(OBJEXT): $(top_srcdir)/internal/gc.h variable.$(OBJEXT): $(top_srcdir)/internal/hash.h variable.$(OBJEXT): $(top_srcdir)/internal/imemo.h +variable.$(OBJEXT): $(top_srcdir)/internal/namespace.h variable.$(OBJEXT): $(top_srcdir)/internal/object.h variable.$(OBJEXT): $(top_srcdir)/internal/re.h +variable.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h variable.$(OBJEXT): $(top_srcdir)/internal/serial.h +variable.$(OBJEXT): $(top_srcdir)/internal/set_table.h variable.$(OBJEXT): $(top_srcdir)/internal/static_assert.h variable.$(OBJEXT): $(top_srcdir)/internal/string.h variable.$(OBJEXT): $(top_srcdir)/internal/symbol.h @@ -17374,6 +20105,7 @@ variable.$(OBJEXT): {$(VPATH)}internal/intern/re.h variable.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h variable.$(OBJEXT): {$(VPATH)}internal/intern/select.h variable.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +variable.$(OBJEXT): {$(VPATH)}internal/intern/set.h variable.$(OBJEXT): {$(VPATH)}internal/intern/signal.h variable.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h variable.$(OBJEXT): {$(VPATH)}internal/intern/string.h @@ -17393,6 +20125,7 @@ variable.$(OBJEXT): {$(VPATH)}internal/special_consts.h variable.$(OBJEXT): {$(VPATH)}internal/static_assert.h variable.$(OBJEXT): {$(VPATH)}internal/stdalign.h variable.$(OBJEXT): {$(VPATH)}internal/stdbool.h +variable.$(OBJEXT): {$(VPATH)}internal/stdckdint.h variable.$(OBJEXT): {$(VPATH)}internal/symbol.h variable.$(OBJEXT): {$(VPATH)}internal/value.h variable.$(OBJEXT): {$(VPATH)}internal/value_type.h @@ -17435,7 +20168,11 @@ version.$(OBJEXT): $(top_srcdir)/internal/cmdlineopt.h version.$(OBJEXT): $(top_srcdir)/internal/compilers.h version.$(OBJEXT): $(top_srcdir)/internal/gc.h version.$(OBJEXT): $(top_srcdir)/internal/imemo.h +version.$(OBJEXT): $(top_srcdir)/internal/namespace.h +version.$(OBJEXT): $(top_srcdir)/internal/parse.h +version.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h version.$(OBJEXT): $(top_srcdir)/internal/serial.h +version.$(OBJEXT): $(top_srcdir)/internal/set_table.h version.$(OBJEXT): $(top_srcdir)/internal/static_assert.h version.$(OBJEXT): $(top_srcdir)/internal/variable.h version.$(OBJEXT): $(top_srcdir)/internal/vm.h @@ -17584,6 +20321,7 @@ version.$(OBJEXT): {$(VPATH)}internal/intern/re.h version.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h version.$(OBJEXT): {$(VPATH)}internal/intern/select.h version.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +version.$(OBJEXT): {$(VPATH)}internal/intern/set.h version.$(OBJEXT): {$(VPATH)}internal/intern/signal.h version.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h version.$(OBJEXT): {$(VPATH)}internal/intern/string.h @@ -17603,6 +20341,7 @@ version.$(OBJEXT): {$(VPATH)}internal/special_consts.h version.$(OBJEXT): {$(VPATH)}internal/static_assert.h version.$(OBJEXT): {$(VPATH)}internal/stdalign.h version.$(OBJEXT): {$(VPATH)}internal/stdbool.h +version.$(OBJEXT): {$(VPATH)}internal/stdckdint.h version.$(OBJEXT): {$(VPATH)}internal/symbol.h version.$(OBJEXT): {$(VPATH)}internal/value.h version.$(OBJEXT): {$(VPATH)}internal/value_type.h @@ -17615,7 +20354,6 @@ version.$(OBJEXT): {$(VPATH)}node.h version.$(OBJEXT): {$(VPATH)}onigmo.h version.$(OBJEXT): {$(VPATH)}oniguruma.h version.$(OBJEXT): {$(VPATH)}revision.h -version.$(OBJEXT): {$(VPATH)}rjit.h version.$(OBJEXT): {$(VPATH)}ruby_assert.h version.$(OBJEXT): {$(VPATH)}ruby_atomic.h version.$(OBJEXT): {$(VPATH)}rubyparser.h @@ -17634,6 +20372,7 @@ vm.$(OBJEXT): $(CCAN_DIR)/list/list.h vm.$(OBJEXT): $(CCAN_DIR)/str/str.h vm.$(OBJEXT): $(hdrdir)/ruby.h vm.$(OBJEXT): $(hdrdir)/ruby/ruby.h +vm.$(OBJEXT): $(hdrdir)/ruby/version.h vm.$(OBJEXT): $(top_srcdir)/internal/array.h vm.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h vm.$(OBJEXT): $(top_srcdir)/internal/bignum.h @@ -17642,7 +20381,9 @@ vm.$(OBJEXT): $(top_srcdir)/internal/class.h vm.$(OBJEXT): $(top_srcdir)/internal/compar.h vm.$(OBJEXT): $(top_srcdir)/internal/compile.h vm.$(OBJEXT): $(top_srcdir)/internal/compilers.h +vm.$(OBJEXT): $(top_srcdir)/internal/complex.h vm.$(OBJEXT): $(top_srcdir)/internal/cont.h +vm.$(OBJEXT): $(top_srcdir)/internal/encoding.h vm.$(OBJEXT): $(top_srcdir)/internal/error.h vm.$(OBJEXT): $(top_srcdir)/internal/eval.h vm.$(OBJEXT): $(top_srcdir)/internal/fixnum.h @@ -17650,23 +20391,48 @@ vm.$(OBJEXT): $(top_srcdir)/internal/gc.h vm.$(OBJEXT): $(top_srcdir)/internal/hash.h vm.$(OBJEXT): $(top_srcdir)/internal/imemo.h vm.$(OBJEXT): $(top_srcdir)/internal/inits.h +vm.$(OBJEXT): $(top_srcdir)/internal/missing.h +vm.$(OBJEXT): $(top_srcdir)/internal/namespace.h vm.$(OBJEXT): $(top_srcdir)/internal/numeric.h vm.$(OBJEXT): $(top_srcdir)/internal/object.h vm.$(OBJEXT): $(top_srcdir)/internal/parse.h vm.$(OBJEXT): $(top_srcdir)/internal/proc.h vm.$(OBJEXT): $(top_srcdir)/internal/random.h +vm.$(OBJEXT): $(top_srcdir)/internal/rational.h vm.$(OBJEXT): $(top_srcdir)/internal/re.h vm.$(OBJEXT): $(top_srcdir)/internal/ruby_parser.h vm.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h vm.$(OBJEXT): $(top_srcdir)/internal/serial.h +vm.$(OBJEXT): $(top_srcdir)/internal/set_table.h vm.$(OBJEXT): $(top_srcdir)/internal/static_assert.h vm.$(OBJEXT): $(top_srcdir)/internal/string.h vm.$(OBJEXT): $(top_srcdir)/internal/struct.h vm.$(OBJEXT): $(top_srcdir)/internal/symbol.h vm.$(OBJEXT): $(top_srcdir)/internal/thread.h +vm.$(OBJEXT): $(top_srcdir)/internal/transcode.h vm.$(OBJEXT): $(top_srcdir)/internal/variable.h vm.$(OBJEXT): $(top_srcdir)/internal/vm.h vm.$(OBJEXT): $(top_srcdir)/internal/warnings.h +vm.$(OBJEXT): $(top_srcdir)/prism/defines.h +vm.$(OBJEXT): $(top_srcdir)/prism/encoding.h +vm.$(OBJEXT): $(top_srcdir)/prism/node.h +vm.$(OBJEXT): $(top_srcdir)/prism/options.h +vm.$(OBJEXT): $(top_srcdir)/prism/pack.h +vm.$(OBJEXT): $(top_srcdir)/prism/parser.h +vm.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h +vm.$(OBJEXT): $(top_srcdir)/prism/prism.h +vm.$(OBJEXT): $(top_srcdir)/prism/regexp.h +vm.$(OBJEXT): $(top_srcdir)/prism/static_literals.h +vm.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h +vm.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h +vm.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h +vm.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h +vm.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h +vm.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h +vm.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h +vm.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h +vm.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h +vm.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h vm.$(OBJEXT): {$(VPATH)}assert.h vm.$(OBJEXT): {$(VPATH)}atomic.h vm.$(OBJEXT): {$(VPATH)}backward/2/assume.h @@ -17816,6 +20582,7 @@ vm.$(OBJEXT): {$(VPATH)}internal/intern/re.h vm.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h vm.$(OBJEXT): {$(VPATH)}internal/intern/select.h vm.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +vm.$(OBJEXT): {$(VPATH)}internal/intern/set.h vm.$(OBJEXT): {$(VPATH)}internal/intern/signal.h vm.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h vm.$(OBJEXT): {$(VPATH)}internal/intern/string.h @@ -17835,6 +20602,7 @@ vm.$(OBJEXT): {$(VPATH)}internal/special_consts.h vm.$(OBJEXT): {$(VPATH)}internal/static_assert.h vm.$(OBJEXT): {$(VPATH)}internal/stdalign.h vm.$(OBJEXT): {$(VPATH)}internal/stdbool.h +vm.$(OBJEXT): {$(VPATH)}internal/stdckdint.h vm.$(OBJEXT): {$(VPATH)}internal/symbol.h vm.$(OBJEXT): {$(VPATH)}internal/value.h vm.$(OBJEXT): {$(VPATH)}internal/value_type.h @@ -17847,18 +20615,22 @@ vm.$(OBJEXT): {$(VPATH)}missing.h vm.$(OBJEXT): {$(VPATH)}node.h vm.$(OBJEXT): {$(VPATH)}onigmo.h vm.$(OBJEXT): {$(VPATH)}oniguruma.h +vm.$(OBJEXT): {$(VPATH)}prism/ast.h +vm.$(OBJEXT): {$(VPATH)}prism/diagnostic.h +vm.$(OBJEXT): {$(VPATH)}prism/version.h +vm.$(OBJEXT): {$(VPATH)}prism_compile.h vm.$(OBJEXT): {$(VPATH)}probes.dmyh vm.$(OBJEXT): {$(VPATH)}probes.h vm.$(OBJEXT): {$(VPATH)}probes_helper.h vm.$(OBJEXT): {$(VPATH)}ractor.h vm.$(OBJEXT): {$(VPATH)}ractor_core.h -vm.$(OBJEXT): {$(VPATH)}rjit.h vm.$(OBJEXT): {$(VPATH)}ruby_assert.h vm.$(OBJEXT): {$(VPATH)}ruby_atomic.h vm.$(OBJEXT): {$(VPATH)}rubyparser.h vm.$(OBJEXT): {$(VPATH)}shape.h vm.$(OBJEXT): {$(VPATH)}st.h vm.$(OBJEXT): {$(VPATH)}subst.h +vm.$(OBJEXT): {$(VPATH)}symbol.h vm.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h vm.$(OBJEXT): {$(VPATH)}thread_native.h vm.$(OBJEXT): {$(VPATH)}variable.h @@ -17880,11 +20652,14 @@ vm.$(OBJEXT): {$(VPATH)}vm_opts.h vm.$(OBJEXT): {$(VPATH)}vm_sync.h vm.$(OBJEXT): {$(VPATH)}vmtc.inc vm.$(OBJEXT): {$(VPATH)}yjit.h +vm.$(OBJEXT): {$(VPATH)}yjit_hook.rbinc +vm.$(OBJEXT): {$(VPATH)}zjit.h vm_backtrace.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h vm_backtrace.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h vm_backtrace.$(OBJEXT): $(CCAN_DIR)/list/list.h vm_backtrace.$(OBJEXT): $(CCAN_DIR)/str/str.h vm_backtrace.$(OBJEXT): $(hdrdir)/ruby/ruby.h +vm_backtrace.$(OBJEXT): $(hdrdir)/ruby/version.h vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/array.h vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/class.h @@ -17892,12 +20667,35 @@ vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/compilers.h vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/error.h vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/gc.h vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/imemo.h +vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/namespace.h +vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/serial.h +vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/set_table.h vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/static_assert.h vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/string.h vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/variable.h vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/vm.h vm_backtrace.$(OBJEXT): $(top_srcdir)/internal/warnings.h +vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/defines.h +vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/encoding.h +vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/node.h +vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/options.h +vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/pack.h +vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/parser.h +vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h +vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/prism.h +vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/regexp.h +vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/static_literals.h +vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h +vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h +vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h +vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h +vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h +vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h +vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h +vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h +vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h +vm_backtrace.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h vm_backtrace.$(OBJEXT): {$(VPATH)}assert.h vm_backtrace.$(OBJEXT): {$(VPATH)}atomic.h vm_backtrace.$(OBJEXT): {$(VPATH)}backward/2/assume.h @@ -17912,6 +20710,7 @@ vm_backtrace.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h vm_backtrace.$(OBJEXT): {$(VPATH)}config.h vm_backtrace.$(OBJEXT): {$(VPATH)}constant.h vm_backtrace.$(OBJEXT): {$(VPATH)}debug.h +vm_backtrace.$(OBJEXT): {$(VPATH)}debug_counter.h vm_backtrace.$(OBJEXT): {$(VPATH)}defines.h vm_backtrace.$(OBJEXT): {$(VPATH)}encoding.h vm_backtrace.$(OBJEXT): {$(VPATH)}eval_intern.h @@ -18042,6 +20841,7 @@ vm_backtrace.$(OBJEXT): {$(VPATH)}internal/intern/re.h vm_backtrace.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h vm_backtrace.$(OBJEXT): {$(VPATH)}internal/intern/select.h vm_backtrace.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/intern/set.h vm_backtrace.$(OBJEXT): {$(VPATH)}internal/intern/signal.h vm_backtrace.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h vm_backtrace.$(OBJEXT): {$(VPATH)}internal/intern/string.h @@ -18061,6 +20861,7 @@ vm_backtrace.$(OBJEXT): {$(VPATH)}internal/special_consts.h vm_backtrace.$(OBJEXT): {$(VPATH)}internal/static_assert.h vm_backtrace.$(OBJEXT): {$(VPATH)}internal/stdalign.h vm_backtrace.$(OBJEXT): {$(VPATH)}internal/stdbool.h +vm_backtrace.$(OBJEXT): {$(VPATH)}internal/stdckdint.h vm_backtrace.$(OBJEXT): {$(VPATH)}internal/symbol.h vm_backtrace.$(OBJEXT): {$(VPATH)}internal/value.h vm_backtrace.$(OBJEXT): {$(VPATH)}internal/value_type.h @@ -18073,6 +20874,10 @@ vm_backtrace.$(OBJEXT): {$(VPATH)}missing.h vm_backtrace.$(OBJEXT): {$(VPATH)}node.h vm_backtrace.$(OBJEXT): {$(VPATH)}onigmo.h vm_backtrace.$(OBJEXT): {$(VPATH)}oniguruma.h +vm_backtrace.$(OBJEXT): {$(VPATH)}prism/ast.h +vm_backtrace.$(OBJEXT): {$(VPATH)}prism/diagnostic.h +vm_backtrace.$(OBJEXT): {$(VPATH)}prism/version.h +vm_backtrace.$(OBJEXT): {$(VPATH)}prism_compile.h vm_backtrace.$(OBJEXT): {$(VPATH)}ruby_assert.h vm_backtrace.$(OBJEXT): {$(VPATH)}ruby_atomic.h vm_backtrace.$(OBJEXT): {$(VPATH)}rubyparser.h @@ -18083,7 +20888,9 @@ vm_backtrace.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h vm_backtrace.$(OBJEXT): {$(VPATH)}thread_native.h vm_backtrace.$(OBJEXT): {$(VPATH)}vm_backtrace.c vm_backtrace.$(OBJEXT): {$(VPATH)}vm_core.h +vm_backtrace.$(OBJEXT): {$(VPATH)}vm_debug.h vm_backtrace.$(OBJEXT): {$(VPATH)}vm_opts.h +vm_backtrace.$(OBJEXT): {$(VPATH)}vm_sync.h vm_dump.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h vm_dump.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h vm_dump.$(OBJEXT): $(CCAN_DIR)/list/list.h @@ -18094,11 +20901,34 @@ vm_dump.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h vm_dump.$(OBJEXT): $(top_srcdir)/internal/compilers.h vm_dump.$(OBJEXT): $(top_srcdir)/internal/gc.h vm_dump.$(OBJEXT): $(top_srcdir)/internal/imemo.h +vm_dump.$(OBJEXT): $(top_srcdir)/internal/namespace.h +vm_dump.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h vm_dump.$(OBJEXT): $(top_srcdir)/internal/serial.h +vm_dump.$(OBJEXT): $(top_srcdir)/internal/set_table.h vm_dump.$(OBJEXT): $(top_srcdir)/internal/static_assert.h vm_dump.$(OBJEXT): $(top_srcdir)/internal/variable.h vm_dump.$(OBJEXT): $(top_srcdir)/internal/vm.h vm_dump.$(OBJEXT): $(top_srcdir)/internal/warnings.h +vm_dump.$(OBJEXT): $(top_srcdir)/prism/defines.h +vm_dump.$(OBJEXT): $(top_srcdir)/prism/encoding.h +vm_dump.$(OBJEXT): $(top_srcdir)/prism/node.h +vm_dump.$(OBJEXT): $(top_srcdir)/prism/options.h +vm_dump.$(OBJEXT): $(top_srcdir)/prism/pack.h +vm_dump.$(OBJEXT): $(top_srcdir)/prism/parser.h +vm_dump.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h +vm_dump.$(OBJEXT): $(top_srcdir)/prism/prism.h +vm_dump.$(OBJEXT): $(top_srcdir)/prism/regexp.h +vm_dump.$(OBJEXT): $(top_srcdir)/prism/static_literals.h +vm_dump.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h +vm_dump.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h +vm_dump.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h +vm_dump.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h +vm_dump.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h +vm_dump.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h +vm_dump.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h +vm_dump.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h +vm_dump.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h +vm_dump.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h vm_dump.$(OBJEXT): {$(VPATH)}addr2line.h vm_dump.$(OBJEXT): {$(VPATH)}assert.h vm_dump.$(OBJEXT): {$(VPATH)}atomic.h @@ -18115,6 +20945,7 @@ vm_dump.$(OBJEXT): {$(VPATH)}config.h vm_dump.$(OBJEXT): {$(VPATH)}constant.h vm_dump.$(OBJEXT): {$(VPATH)}defines.h vm_dump.$(OBJEXT): {$(VPATH)}encoding.h +vm_dump.$(OBJEXT): {$(VPATH)}fiber/scheduler.h vm_dump.$(OBJEXT): {$(VPATH)}id.h vm_dump.$(OBJEXT): {$(VPATH)}id_table.h vm_dump.$(OBJEXT): {$(VPATH)}intern.h @@ -18242,6 +21073,7 @@ vm_dump.$(OBJEXT): {$(VPATH)}internal/intern/re.h vm_dump.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h vm_dump.$(OBJEXT): {$(VPATH)}internal/intern/select.h vm_dump.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/intern/set.h vm_dump.$(OBJEXT): {$(VPATH)}internal/intern/signal.h vm_dump.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h vm_dump.$(OBJEXT): {$(VPATH)}internal/intern/string.h @@ -18261,6 +21093,7 @@ vm_dump.$(OBJEXT): {$(VPATH)}internal/special_consts.h vm_dump.$(OBJEXT): {$(VPATH)}internal/static_assert.h vm_dump.$(OBJEXT): {$(VPATH)}internal/stdalign.h vm_dump.$(OBJEXT): {$(VPATH)}internal/stdbool.h +vm_dump.$(OBJEXT): {$(VPATH)}internal/stdckdint.h vm_dump.$(OBJEXT): {$(VPATH)}internal/symbol.h vm_dump.$(OBJEXT): {$(VPATH)}internal/value.h vm_dump.$(OBJEXT): {$(VPATH)}internal/value_type.h @@ -18273,6 +21106,10 @@ vm_dump.$(OBJEXT): {$(VPATH)}missing.h vm_dump.$(OBJEXT): {$(VPATH)}node.h vm_dump.$(OBJEXT): {$(VPATH)}onigmo.h vm_dump.$(OBJEXT): {$(VPATH)}oniguruma.h +vm_dump.$(OBJEXT): {$(VPATH)}prism/ast.h +vm_dump.$(OBJEXT): {$(VPATH)}prism/diagnostic.h +vm_dump.$(OBJEXT): {$(VPATH)}prism/version.h +vm_dump.$(OBJEXT): {$(VPATH)}prism_compile.h vm_dump.$(OBJEXT): {$(VPATH)}procstat_vm.c vm_dump.$(OBJEXT): {$(VPATH)}ractor.h vm_dump.$(OBJEXT): {$(VPATH)}ractor_core.h @@ -18298,7 +21135,10 @@ vm_sync.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h vm_sync.$(OBJEXT): $(top_srcdir)/internal/compilers.h vm_sync.$(OBJEXT): $(top_srcdir)/internal/gc.h vm_sync.$(OBJEXT): $(top_srcdir)/internal/imemo.h +vm_sync.$(OBJEXT): $(top_srcdir)/internal/namespace.h +vm_sync.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h vm_sync.$(OBJEXT): $(top_srcdir)/internal/serial.h +vm_sync.$(OBJEXT): $(top_srcdir)/internal/set_table.h vm_sync.$(OBJEXT): $(top_srcdir)/internal/static_assert.h vm_sync.$(OBJEXT): $(top_srcdir)/internal/thread.h vm_sync.$(OBJEXT): $(top_srcdir)/internal/variable.h @@ -18447,6 +21287,7 @@ vm_sync.$(OBJEXT): {$(VPATH)}internal/intern/re.h vm_sync.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h vm_sync.$(OBJEXT): {$(VPATH)}internal/intern/select.h vm_sync.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/intern/set.h vm_sync.$(OBJEXT): {$(VPATH)}internal/intern/signal.h vm_sync.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h vm_sync.$(OBJEXT): {$(VPATH)}internal/intern/string.h @@ -18466,6 +21307,7 @@ vm_sync.$(OBJEXT): {$(VPATH)}internal/special_consts.h vm_sync.$(OBJEXT): {$(VPATH)}internal/static_assert.h vm_sync.$(OBJEXT): {$(VPATH)}internal/stdalign.h vm_sync.$(OBJEXT): {$(VPATH)}internal/stdbool.h +vm_sync.$(OBJEXT): {$(VPATH)}internal/stdckdint.h vm_sync.$(OBJEXT): {$(VPATH)}internal/symbol.h vm_sync.$(OBJEXT): {$(VPATH)}internal/value.h vm_sync.$(OBJEXT): {$(VPATH)}internal/value_type.h @@ -18500,17 +21342,42 @@ vm_trace.$(OBJEXT): $(hdrdir)/ruby.h vm_trace.$(OBJEXT): $(hdrdir)/ruby/ruby.h vm_trace.$(OBJEXT): $(top_srcdir)/internal/array.h vm_trace.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h +vm_trace.$(OBJEXT): $(top_srcdir)/internal/bits.h vm_trace.$(OBJEXT): $(top_srcdir)/internal/class.h vm_trace.$(OBJEXT): $(top_srcdir)/internal/compilers.h vm_trace.$(OBJEXT): $(top_srcdir)/internal/gc.h vm_trace.$(OBJEXT): $(top_srcdir)/internal/hash.h vm_trace.$(OBJEXT): $(top_srcdir)/internal/imemo.h +vm_trace.$(OBJEXT): $(top_srcdir)/internal/namespace.h +vm_trace.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h vm_trace.$(OBJEXT): $(top_srcdir)/internal/serial.h +vm_trace.$(OBJEXT): $(top_srcdir)/internal/set_table.h vm_trace.$(OBJEXT): $(top_srcdir)/internal/static_assert.h vm_trace.$(OBJEXT): $(top_srcdir)/internal/symbol.h +vm_trace.$(OBJEXT): $(top_srcdir)/internal/thread.h vm_trace.$(OBJEXT): $(top_srcdir)/internal/variable.h vm_trace.$(OBJEXT): $(top_srcdir)/internal/vm.h vm_trace.$(OBJEXT): $(top_srcdir)/internal/warnings.h +vm_trace.$(OBJEXT): $(top_srcdir)/prism/defines.h +vm_trace.$(OBJEXT): $(top_srcdir)/prism/encoding.h +vm_trace.$(OBJEXT): $(top_srcdir)/prism/node.h +vm_trace.$(OBJEXT): $(top_srcdir)/prism/options.h +vm_trace.$(OBJEXT): $(top_srcdir)/prism/pack.h +vm_trace.$(OBJEXT): $(top_srcdir)/prism/parser.h +vm_trace.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h +vm_trace.$(OBJEXT): $(top_srcdir)/prism/prism.h +vm_trace.$(OBJEXT): $(top_srcdir)/prism/regexp.h +vm_trace.$(OBJEXT): $(top_srcdir)/prism/static_literals.h +vm_trace.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h +vm_trace.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h +vm_trace.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h +vm_trace.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h +vm_trace.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h +vm_trace.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h +vm_trace.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h +vm_trace.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h +vm_trace.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h +vm_trace.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h vm_trace.$(OBJEXT): {$(VPATH)}assert.h vm_trace.$(OBJEXT): {$(VPATH)}atomic.h vm_trace.$(OBJEXT): {$(VPATH)}backward/2/assume.h @@ -18657,6 +21524,7 @@ vm_trace.$(OBJEXT): {$(VPATH)}internal/intern/re.h vm_trace.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h vm_trace.$(OBJEXT): {$(VPATH)}internal/intern/select.h vm_trace.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/intern/set.h vm_trace.$(OBJEXT): {$(VPATH)}internal/intern/signal.h vm_trace.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h vm_trace.$(OBJEXT): {$(VPATH)}internal/intern/string.h @@ -18676,6 +21544,7 @@ vm_trace.$(OBJEXT): {$(VPATH)}internal/special_consts.h vm_trace.$(OBJEXT): {$(VPATH)}internal/static_assert.h vm_trace.$(OBJEXT): {$(VPATH)}internal/stdalign.h vm_trace.$(OBJEXT): {$(VPATH)}internal/stdbool.h +vm_trace.$(OBJEXT): {$(VPATH)}internal/stdckdint.h vm_trace.$(OBJEXT): {$(VPATH)}internal/symbol.h vm_trace.$(OBJEXT): {$(VPATH)}internal/value.h vm_trace.$(OBJEXT): {$(VPATH)}internal/value_type.h @@ -18688,8 +21557,11 @@ vm_trace.$(OBJEXT): {$(VPATH)}missing.h vm_trace.$(OBJEXT): {$(VPATH)}node.h vm_trace.$(OBJEXT): {$(VPATH)}onigmo.h vm_trace.$(OBJEXT): {$(VPATH)}oniguruma.h +vm_trace.$(OBJEXT): {$(VPATH)}prism/ast.h +vm_trace.$(OBJEXT): {$(VPATH)}prism/diagnostic.h +vm_trace.$(OBJEXT): {$(VPATH)}prism/version.h +vm_trace.$(OBJEXT): {$(VPATH)}prism_compile.h vm_trace.$(OBJEXT): {$(VPATH)}ractor.h -vm_trace.$(OBJEXT): {$(VPATH)}rjit.h vm_trace.$(OBJEXT): {$(VPATH)}ruby_assert.h vm_trace.$(OBJEXT): {$(VPATH)}ruby_atomic.h vm_trace.$(OBJEXT): {$(VPATH)}rubyparser.h @@ -18700,7 +21572,9 @@ vm_trace.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h vm_trace.$(OBJEXT): {$(VPATH)}thread_native.h vm_trace.$(OBJEXT): {$(VPATH)}trace_point.rbinc vm_trace.$(OBJEXT): {$(VPATH)}vm_core.h +vm_trace.$(OBJEXT): {$(VPATH)}vm_debug.h vm_trace.$(OBJEXT): {$(VPATH)}vm_opts.h +vm_trace.$(OBJEXT): {$(VPATH)}vm_sync.h vm_trace.$(OBJEXT): {$(VPATH)}vm_trace.c vm_trace.$(OBJEXT): {$(VPATH)}yjit.h weakmap.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h @@ -18714,9 +21588,11 @@ weakmap.$(OBJEXT): $(top_srcdir)/internal/compilers.h weakmap.$(OBJEXT): $(top_srcdir)/internal/gc.h weakmap.$(OBJEXT): $(top_srcdir)/internal/hash.h weakmap.$(OBJEXT): $(top_srcdir)/internal/imemo.h +weakmap.$(OBJEXT): $(top_srcdir)/internal/namespace.h weakmap.$(OBJEXT): $(top_srcdir)/internal/proc.h weakmap.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h weakmap.$(OBJEXT): $(top_srcdir)/internal/serial.h +weakmap.$(OBJEXT): $(top_srcdir)/internal/set_table.h weakmap.$(OBJEXT): $(top_srcdir)/internal/static_assert.h weakmap.$(OBJEXT): $(top_srcdir)/internal/vm.h weakmap.$(OBJEXT): $(top_srcdir)/internal/warnings.h @@ -18735,6 +21611,7 @@ weakmap.$(OBJEXT): {$(VPATH)}config.h weakmap.$(OBJEXT): {$(VPATH)}defines.h weakmap.$(OBJEXT): {$(VPATH)}encoding.h weakmap.$(OBJEXT): {$(VPATH)}id.h +weakmap.$(OBJEXT): {$(VPATH)}id_table.h weakmap.$(OBJEXT): {$(VPATH)}intern.h weakmap.$(OBJEXT): {$(VPATH)}internal.h weakmap.$(OBJEXT): {$(VPATH)}internal/abi.h @@ -18860,6 +21737,7 @@ weakmap.$(OBJEXT): {$(VPATH)}internal/intern/re.h weakmap.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h weakmap.$(OBJEXT): {$(VPATH)}internal/intern/select.h weakmap.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +weakmap.$(OBJEXT): {$(VPATH)}internal/intern/set.h weakmap.$(OBJEXT): {$(VPATH)}internal/intern/signal.h weakmap.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h weakmap.$(OBJEXT): {$(VPATH)}internal/intern/string.h @@ -18879,6 +21757,7 @@ weakmap.$(OBJEXT): {$(VPATH)}internal/special_consts.h weakmap.$(OBJEXT): {$(VPATH)}internal/static_assert.h weakmap.$(OBJEXT): {$(VPATH)}internal/stdalign.h weakmap.$(OBJEXT): {$(VPATH)}internal/stdbool.h +weakmap.$(OBJEXT): {$(VPATH)}internal/stdckdint.h weakmap.$(OBJEXT): {$(VPATH)}internal/symbol.h weakmap.$(OBJEXT): {$(VPATH)}internal/value.h weakmap.$(OBJEXT): {$(VPATH)}internal/value_type.h @@ -18900,1070 +21779,6 @@ weakmap.$(OBJEXT): {$(VPATH)}thread_native.h weakmap.$(OBJEXT): {$(VPATH)}vm_core.h weakmap.$(OBJEXT): {$(VPATH)}vm_opts.h weakmap.$(OBJEXT): {$(VPATH)}weakmap.c -yarp/api_node.$(OBJEXT): $(hdrdir)/ruby.h -yarp/api_node.$(OBJEXT): $(hdrdir)/ruby/ruby.h -yarp/api_node.$(OBJEXT): $(top_srcdir)/yarp/defines.h -yarp/api_node.$(OBJEXT): $(top_srcdir)/yarp/diagnostic.h -yarp/api_node.$(OBJEXT): $(top_srcdir)/yarp/enc/yp_encoding.h -yarp/api_node.$(OBJEXT): $(top_srcdir)/yarp/extension.h -yarp/api_node.$(OBJEXT): $(top_srcdir)/yarp/node.h -yarp/api_node.$(OBJEXT): $(top_srcdir)/yarp/pack.h -yarp/api_node.$(OBJEXT): $(top_srcdir)/yarp/parser.h -yarp/api_node.$(OBJEXT): $(top_srcdir)/yarp/regexp.h -yarp/api_node.$(OBJEXT): $(top_srcdir)/yarp/unescape.h -yarp/api_node.$(OBJEXT): $(top_srcdir)/yarp/util/yp_buffer.h -yarp/api_node.$(OBJEXT): $(top_srcdir)/yarp/util/yp_char.h -yarp/api_node.$(OBJEXT): $(top_srcdir)/yarp/util/yp_constant_pool.h -yarp/api_node.$(OBJEXT): $(top_srcdir)/yarp/util/yp_list.h -yarp/api_node.$(OBJEXT): $(top_srcdir)/yarp/util/yp_memchr.h -yarp/api_node.$(OBJEXT): $(top_srcdir)/yarp/util/yp_newline_list.h -yarp/api_node.$(OBJEXT): $(top_srcdir)/yarp/util/yp_state_stack.h -yarp/api_node.$(OBJEXT): $(top_srcdir)/yarp/util/yp_string.h -yarp/api_node.$(OBJEXT): $(top_srcdir)/yarp/util/yp_string_list.h -yarp/api_node.$(OBJEXT): $(top_srcdir)/yarp/util/yp_strpbrk.h -yarp/api_node.$(OBJEXT): $(top_srcdir)/yarp/yarp.h -yarp/api_node.$(OBJEXT): {$(VPATH)}assert.h -yarp/api_node.$(OBJEXT): {$(VPATH)}backward/2/assume.h -yarp/api_node.$(OBJEXT): {$(VPATH)}backward/2/attributes.h -yarp/api_node.$(OBJEXT): {$(VPATH)}backward/2/bool.h -yarp/api_node.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h -yarp/api_node.$(OBJEXT): {$(VPATH)}backward/2/limits.h -yarp/api_node.$(OBJEXT): {$(VPATH)}backward/2/long_long.h -yarp/api_node.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h -yarp/api_node.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h -yarp/api_node.$(OBJEXT): {$(VPATH)}config.h -yarp/api_node.$(OBJEXT): {$(VPATH)}defines.h -yarp/api_node.$(OBJEXT): {$(VPATH)}encoding.h -yarp/api_node.$(OBJEXT): {$(VPATH)}intern.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/abi.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/anyargs.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/arithmetic.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/assume.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/attr/cold.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/attr/const.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/attr/error.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/attr/format.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/attr/packed_struct.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/attr/pure.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/attr/warning.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/cast.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/compiler_is.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/compiler_since.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/config.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/constant_p.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/core.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/core/rarray.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/core/rclass.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/core/rdata.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/core/rfile.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/core/rhash.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/core/robject.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/core/rstring.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/ctype.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/dllexport.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/dosish.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/encoding/re.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/encoding/string.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/error.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/eval.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/event.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/fl_type.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/gc.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/glob.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/globals.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/has/attribute.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/has/builtin.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/has/extension.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/has/feature.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/has/warning.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/intern/array.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/intern/class.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/intern/compar.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/intern/complex.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/intern/cont.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/intern/dir.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/intern/enum.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/intern/error.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/intern/eval.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/intern/file.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/intern/hash.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/intern/io.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/intern/load.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/intern/object.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/intern/parse.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/intern/proc.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/intern/process.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/intern/random.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/intern/range.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/intern/rational.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/intern/re.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/intern/select.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/intern/signal.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/intern/string.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/intern/struct.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/intern/thread.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/intern/time.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/intern/variable.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/intern/vm.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/interpreter.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/iterator.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/memory.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/method.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/module.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/newobj.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/scan_args.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/special_consts.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/static_assert.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/stdalign.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/stdbool.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/symbol.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/value.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/value_type.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/variable.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/warning_push.h -yarp/api_node.$(OBJEXT): {$(VPATH)}internal/xmalloc.h -yarp/api_node.$(OBJEXT): {$(VPATH)}missing.h -yarp/api_node.$(OBJEXT): {$(VPATH)}onigmo.h -yarp/api_node.$(OBJEXT): {$(VPATH)}oniguruma.h -yarp/api_node.$(OBJEXT): {$(VPATH)}st.h -yarp/api_node.$(OBJEXT): {$(VPATH)}subst.h -yarp/api_node.$(OBJEXT): {$(VPATH)}yarp/api_node.c -yarp/api_node.$(OBJEXT): {$(VPATH)}yarp/ast.h -yarp/api_node.$(OBJEXT): {$(VPATH)}yarp/version.h -yarp/api_pack.$(OBJEXT): $(hdrdir)/ruby.h -yarp/api_pack.$(OBJEXT): $(hdrdir)/ruby/ruby.h -yarp/api_pack.$(OBJEXT): $(top_srcdir)/yarp/api_pack.c -yarp/api_pack.$(OBJEXT): $(top_srcdir)/yarp/defines.h -yarp/api_pack.$(OBJEXT): $(top_srcdir)/yarp/diagnostic.h -yarp/api_pack.$(OBJEXT): $(top_srcdir)/yarp/enc/yp_encoding.h -yarp/api_pack.$(OBJEXT): $(top_srcdir)/yarp/extension.h -yarp/api_pack.$(OBJEXT): $(top_srcdir)/yarp/node.h -yarp/api_pack.$(OBJEXT): $(top_srcdir)/yarp/pack.h -yarp/api_pack.$(OBJEXT): $(top_srcdir)/yarp/parser.h -yarp/api_pack.$(OBJEXT): $(top_srcdir)/yarp/regexp.h -yarp/api_pack.$(OBJEXT): $(top_srcdir)/yarp/unescape.h -yarp/api_pack.$(OBJEXT): $(top_srcdir)/yarp/util/yp_buffer.h -yarp/api_pack.$(OBJEXT): $(top_srcdir)/yarp/util/yp_char.h -yarp/api_pack.$(OBJEXT): $(top_srcdir)/yarp/util/yp_constant_pool.h -yarp/api_pack.$(OBJEXT): $(top_srcdir)/yarp/util/yp_list.h -yarp/api_pack.$(OBJEXT): $(top_srcdir)/yarp/util/yp_memchr.h -yarp/api_pack.$(OBJEXT): $(top_srcdir)/yarp/util/yp_newline_list.h -yarp/api_pack.$(OBJEXT): $(top_srcdir)/yarp/util/yp_state_stack.h -yarp/api_pack.$(OBJEXT): $(top_srcdir)/yarp/util/yp_string.h -yarp/api_pack.$(OBJEXT): $(top_srcdir)/yarp/util/yp_string_list.h -yarp/api_pack.$(OBJEXT): $(top_srcdir)/yarp/util/yp_strpbrk.h -yarp/api_pack.$(OBJEXT): $(top_srcdir)/yarp/yarp.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}assert.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}backward/2/assume.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}backward/2/attributes.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}backward/2/bool.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}backward/2/limits.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}backward/2/long_long.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}config.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}defines.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}encoding.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}intern.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/abi.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/anyargs.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/arithmetic.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/assume.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/cold.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/const.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/error.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/format.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/packed_struct.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/pure.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/warning.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/cast.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/compiler_is.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/compiler_since.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/config.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/constant_p.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/core.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/core/rarray.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/core/rclass.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/core/rdata.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/core/rfile.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/core/rhash.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/core/robject.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/core/rstring.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/ctype.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/dllexport.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/dosish.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/encoding/re.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/encoding/string.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/error.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/eval.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/event.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/fl_type.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/gc.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/glob.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/globals.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/has/attribute.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/has/builtin.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/has/extension.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/has/feature.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/has/warning.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/array.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/class.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/compar.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/complex.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/cont.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/dir.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/enum.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/error.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/eval.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/file.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/hash.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/io.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/load.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/object.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/parse.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/proc.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/process.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/random.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/range.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/rational.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/re.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/select.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/signal.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/string.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/struct.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/thread.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/time.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/variable.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/intern/vm.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/interpreter.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/iterator.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/memory.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/method.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/module.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/newobj.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/scan_args.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/special_consts.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/static_assert.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/stdalign.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/stdbool.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/symbol.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/value.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/value_type.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/variable.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/warning_push.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}internal/xmalloc.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}missing.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}onigmo.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}oniguruma.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}st.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}subst.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}yarp/ast.h -yarp/api_pack.$(OBJEXT): {$(VPATH)}yarp/version.h -yarp/diagnostic.$(OBJEXT): $(top_srcdir)/yarp/defines.h -yarp/diagnostic.$(OBJEXT): $(top_srcdir)/yarp/diagnostic.c -yarp/diagnostic.$(OBJEXT): $(top_srcdir)/yarp/diagnostic.h -yarp/diagnostic.$(OBJEXT): $(top_srcdir)/yarp/util/yp_list.h -yarp/diagnostic.$(OBJEXT): {$(VPATH)}config.h -yarp/enc/yp_ascii.$(OBJEXT): $(top_srcdir)/yarp/defines.h -yarp/enc/yp_ascii.$(OBJEXT): $(top_srcdir)/yarp/enc/yp_ascii.c -yarp/enc/yp_ascii.$(OBJEXT): $(top_srcdir)/yarp/enc/yp_encoding.h -yarp/enc/yp_ascii.$(OBJEXT): {$(VPATH)}config.h -yarp/enc/yp_big5.$(OBJEXT): $(top_srcdir)/yarp/defines.h -yarp/enc/yp_big5.$(OBJEXT): $(top_srcdir)/yarp/enc/yp_big5.c -yarp/enc/yp_big5.$(OBJEXT): $(top_srcdir)/yarp/enc/yp_encoding.h -yarp/enc/yp_big5.$(OBJEXT): {$(VPATH)}config.h -yarp/enc/yp_euc_jp.$(OBJEXT): $(top_srcdir)/yarp/defines.h -yarp/enc/yp_euc_jp.$(OBJEXT): $(top_srcdir)/yarp/enc/yp_encoding.h -yarp/enc/yp_euc_jp.$(OBJEXT): $(top_srcdir)/yarp/enc/yp_euc_jp.c -yarp/enc/yp_euc_jp.$(OBJEXT): {$(VPATH)}config.h -yarp/enc/yp_gbk.$(OBJEXT): $(top_srcdir)/yarp/defines.h -yarp/enc/yp_gbk.$(OBJEXT): $(top_srcdir)/yarp/enc/yp_encoding.h -yarp/enc/yp_gbk.$(OBJEXT): $(top_srcdir)/yarp/enc/yp_gbk.c -yarp/enc/yp_gbk.$(OBJEXT): {$(VPATH)}config.h -yarp/enc/yp_iso_8859_1.$(OBJEXT): $(top_srcdir)/yarp/defines.h -yarp/enc/yp_iso_8859_1.$(OBJEXT): $(top_srcdir)/yarp/enc/yp_encoding.h -yarp/enc/yp_iso_8859_1.$(OBJEXT): $(top_srcdir)/yarp/enc/yp_iso_8859_1.c -yarp/enc/yp_iso_8859_1.$(OBJEXT): {$(VPATH)}config.h -yarp/enc/yp_iso_8859_10.$(OBJEXT): $(top_srcdir)/yarp/defines.h -yarp/enc/yp_iso_8859_10.$(OBJEXT): $(top_srcdir)/yarp/enc/yp_encoding.h -yarp/enc/yp_iso_8859_10.$(OBJEXT): $(top_srcdir)/yarp/enc/yp_iso_8859_10.c -yarp/enc/yp_iso_8859_10.$(OBJEXT): {$(VPATH)}config.h -yarp/enc/yp_iso_8859_11.$(OBJEXT): $(top_srcdir)/yarp/defines.h -yarp/enc/yp_iso_8859_11.$(OBJEXT): $(top_srcdir)/yarp/enc/yp_encoding.h -yarp/enc/yp_iso_8859_11.$(OBJEXT): $(top_srcdir)/yarp/enc/yp_iso_8859_11.c -yarp/enc/yp_iso_8859_11.$(OBJEXT): {$(VPATH)}config.h -yarp/enc/yp_iso_8859_13.$(OBJEXT): $(top_srcdir)/yarp/defines.h -yarp/enc/yp_iso_8859_13.$(OBJEXT): $(top_srcdir)/yarp/enc/yp_encoding.h -yarp/enc/yp_iso_8859_13.$(OBJEXT): $(top_srcdir)/yarp/enc/yp_iso_8859_13.c -yarp/enc/yp_iso_8859_13.$(OBJEXT): {$(VPATH)}config.h -yarp/enc/yp_iso_8859_14.$(OBJEXT): $(top_srcdir)/yarp/defines.h -yarp/enc/yp_iso_8859_14.$(OBJEXT): $(top_srcdir)/yarp/enc/yp_encoding.h -yarp/enc/yp_iso_8859_14.$(OBJEXT): $(top_srcdir)/yarp/enc/yp_iso_8859_14.c -yarp/enc/yp_iso_8859_14.$(OBJEXT): {$(VPATH)}config.h -yarp/enc/yp_iso_8859_15.$(OBJEXT): $(top_srcdir)/yarp/defines.h -yarp/enc/yp_iso_8859_15.$(OBJEXT): $(top_srcdir)/yarp/enc/yp_encoding.h -yarp/enc/yp_iso_8859_15.$(OBJEXT): $(top_srcdir)/yarp/enc/yp_iso_8859_15.c -yarp/enc/yp_iso_8859_15.$(OBJEXT): {$(VPATH)}config.h -yarp/enc/yp_iso_8859_16.$(OBJEXT): $(top_srcdir)/yarp/defines.h -yarp/enc/yp_iso_8859_16.$(OBJEXT): $(top_srcdir)/yarp/enc/yp_encoding.h -yarp/enc/yp_iso_8859_16.$(OBJEXT): $(top_srcdir)/yarp/enc/yp_iso_8859_16.c -yarp/enc/yp_iso_8859_16.$(OBJEXT): {$(VPATH)}config.h -yarp/enc/yp_iso_8859_2.$(OBJEXT): $(top_srcdir)/yarp/defines.h -yarp/enc/yp_iso_8859_2.$(OBJEXT): $(top_srcdir)/yarp/enc/yp_encoding.h -yarp/enc/yp_iso_8859_2.$(OBJEXT): $(top_srcdir)/yarp/enc/yp_iso_8859_2.c -yarp/enc/yp_iso_8859_2.$(OBJEXT): {$(VPATH)}config.h -yarp/enc/yp_iso_8859_3.$(OBJEXT): $(top_srcdir)/yarp/defines.h -yarp/enc/yp_iso_8859_3.$(OBJEXT): $(top_srcdir)/yarp/enc/yp_encoding.h -yarp/enc/yp_iso_8859_3.$(OBJEXT): $(top_srcdir)/yarp/enc/yp_iso_8859_3.c -yarp/enc/yp_iso_8859_3.$(OBJEXT): {$(VPATH)}config.h -yarp/enc/yp_iso_8859_4.$(OBJEXT): $(top_srcdir)/yarp/defines.h -yarp/enc/yp_iso_8859_4.$(OBJEXT): $(top_srcdir)/yarp/enc/yp_encoding.h -yarp/enc/yp_iso_8859_4.$(OBJEXT): $(top_srcdir)/yarp/enc/yp_iso_8859_4.c -yarp/enc/yp_iso_8859_4.$(OBJEXT): {$(VPATH)}config.h -yarp/enc/yp_iso_8859_5.$(OBJEXT): $(top_srcdir)/yarp/defines.h -yarp/enc/yp_iso_8859_5.$(OBJEXT): $(top_srcdir)/yarp/enc/yp_encoding.h -yarp/enc/yp_iso_8859_5.$(OBJEXT): $(top_srcdir)/yarp/enc/yp_iso_8859_5.c -yarp/enc/yp_iso_8859_5.$(OBJEXT): {$(VPATH)}config.h -yarp/enc/yp_iso_8859_6.$(OBJEXT): $(top_srcdir)/yarp/defines.h -yarp/enc/yp_iso_8859_6.$(OBJEXT): $(top_srcdir)/yarp/enc/yp_encoding.h -yarp/enc/yp_iso_8859_6.$(OBJEXT): $(top_srcdir)/yarp/enc/yp_iso_8859_6.c -yarp/enc/yp_iso_8859_6.$(OBJEXT): {$(VPATH)}config.h -yarp/enc/yp_iso_8859_7.$(OBJEXT): $(top_srcdir)/yarp/defines.h -yarp/enc/yp_iso_8859_7.$(OBJEXT): $(top_srcdir)/yarp/enc/yp_encoding.h -yarp/enc/yp_iso_8859_7.$(OBJEXT): $(top_srcdir)/yarp/enc/yp_iso_8859_7.c -yarp/enc/yp_iso_8859_7.$(OBJEXT): {$(VPATH)}config.h -yarp/enc/yp_iso_8859_8.$(OBJEXT): $(top_srcdir)/yarp/defines.h -yarp/enc/yp_iso_8859_8.$(OBJEXT): $(top_srcdir)/yarp/enc/yp_encoding.h -yarp/enc/yp_iso_8859_8.$(OBJEXT): $(top_srcdir)/yarp/enc/yp_iso_8859_8.c -yarp/enc/yp_iso_8859_8.$(OBJEXT): {$(VPATH)}config.h -yarp/enc/yp_iso_8859_9.$(OBJEXT): $(top_srcdir)/yarp/defines.h -yarp/enc/yp_iso_8859_9.$(OBJEXT): $(top_srcdir)/yarp/enc/yp_encoding.h -yarp/enc/yp_iso_8859_9.$(OBJEXT): $(top_srcdir)/yarp/enc/yp_iso_8859_9.c -yarp/enc/yp_iso_8859_9.$(OBJEXT): {$(VPATH)}config.h -yarp/enc/yp_koi8_r.$(OBJEXT): $(top_srcdir)/yarp/defines.h -yarp/enc/yp_koi8_r.$(OBJEXT): $(top_srcdir)/yarp/enc/yp_encoding.h -yarp/enc/yp_koi8_r.$(OBJEXT): $(top_srcdir)/yarp/enc/yp_koi8_r.c -yarp/enc/yp_koi8_r.$(OBJEXT): {$(VPATH)}config.h -yarp/enc/yp_shared.$(OBJEXT): $(top_srcdir)/yarp/defines.h -yarp/enc/yp_shared.$(OBJEXT): $(top_srcdir)/yarp/enc/yp_encoding.h -yarp/enc/yp_shared.$(OBJEXT): $(top_srcdir)/yarp/enc/yp_shared.c -yarp/enc/yp_shared.$(OBJEXT): {$(VPATH)}config.h -yarp/enc/yp_shift_jis.$(OBJEXT): $(top_srcdir)/yarp/defines.h -yarp/enc/yp_shift_jis.$(OBJEXT): $(top_srcdir)/yarp/enc/yp_encoding.h -yarp/enc/yp_shift_jis.$(OBJEXT): $(top_srcdir)/yarp/enc/yp_shift_jis.c -yarp/enc/yp_shift_jis.$(OBJEXT): {$(VPATH)}config.h -yarp/enc/yp_tables.$(OBJEXT): $(top_srcdir)/yarp/defines.h -yarp/enc/yp_tables.$(OBJEXT): $(top_srcdir)/yarp/enc/yp_encoding.h -yarp/enc/yp_tables.$(OBJEXT): $(top_srcdir)/yarp/enc/yp_tables.c -yarp/enc/yp_tables.$(OBJEXT): {$(VPATH)}config.h -yarp/enc/yp_unicode.$(OBJEXT): $(top_srcdir)/yarp/defines.h -yarp/enc/yp_unicode.$(OBJEXT): $(top_srcdir)/yarp/enc/yp_encoding.h -yarp/enc/yp_unicode.$(OBJEXT): $(top_srcdir)/yarp/enc/yp_unicode.c -yarp/enc/yp_unicode.$(OBJEXT): {$(VPATH)}config.h -yarp/enc/yp_windows_1251.$(OBJEXT): $(top_srcdir)/yarp/defines.h -yarp/enc/yp_windows_1251.$(OBJEXT): $(top_srcdir)/yarp/enc/yp_encoding.h -yarp/enc/yp_windows_1251.$(OBJEXT): $(top_srcdir)/yarp/enc/yp_windows_1251.c -yarp/enc/yp_windows_1251.$(OBJEXT): {$(VPATH)}config.h -yarp/enc/yp_windows_1252.$(OBJEXT): $(top_srcdir)/yarp/defines.h -yarp/enc/yp_windows_1252.$(OBJEXT): $(top_srcdir)/yarp/enc/yp_encoding.h -yarp/enc/yp_windows_1252.$(OBJEXT): $(top_srcdir)/yarp/enc/yp_windows_1252.c -yarp/enc/yp_windows_1252.$(OBJEXT): {$(VPATH)}config.h -yarp/enc/yp_windows_31j.$(OBJEXT): $(top_srcdir)/yarp/defines.h -yarp/enc/yp_windows_31j.$(OBJEXT): $(top_srcdir)/yarp/enc/yp_encoding.h -yarp/enc/yp_windows_31j.$(OBJEXT): $(top_srcdir)/yarp/enc/yp_windows_31j.c -yarp/enc/yp_windows_31j.$(OBJEXT): {$(VPATH)}config.h -yarp/extension.$(OBJEXT): $(hdrdir)/ruby.h -yarp/extension.$(OBJEXT): $(hdrdir)/ruby/ruby.h -yarp/extension.$(OBJEXT): $(top_srcdir)/yarp/defines.h -yarp/extension.$(OBJEXT): $(top_srcdir)/yarp/diagnostic.h -yarp/extension.$(OBJEXT): $(top_srcdir)/yarp/enc/yp_encoding.h -yarp/extension.$(OBJEXT): $(top_srcdir)/yarp/extension.c -yarp/extension.$(OBJEXT): $(top_srcdir)/yarp/extension.h -yarp/extension.$(OBJEXT): $(top_srcdir)/yarp/node.h -yarp/extension.$(OBJEXT): $(top_srcdir)/yarp/pack.h -yarp/extension.$(OBJEXT): $(top_srcdir)/yarp/parser.h -yarp/extension.$(OBJEXT): $(top_srcdir)/yarp/regexp.h -yarp/extension.$(OBJEXT): $(top_srcdir)/yarp/unescape.h -yarp/extension.$(OBJEXT): $(top_srcdir)/yarp/util/yp_buffer.h -yarp/extension.$(OBJEXT): $(top_srcdir)/yarp/util/yp_char.h -yarp/extension.$(OBJEXT): $(top_srcdir)/yarp/util/yp_constant_pool.h -yarp/extension.$(OBJEXT): $(top_srcdir)/yarp/util/yp_list.h -yarp/extension.$(OBJEXT): $(top_srcdir)/yarp/util/yp_memchr.h -yarp/extension.$(OBJEXT): $(top_srcdir)/yarp/util/yp_newline_list.h -yarp/extension.$(OBJEXT): $(top_srcdir)/yarp/util/yp_state_stack.h -yarp/extension.$(OBJEXT): $(top_srcdir)/yarp/util/yp_string.h -yarp/extension.$(OBJEXT): $(top_srcdir)/yarp/util/yp_string_list.h -yarp/extension.$(OBJEXT): $(top_srcdir)/yarp/util/yp_strpbrk.h -yarp/extension.$(OBJEXT): $(top_srcdir)/yarp/yarp.h -yarp/extension.$(OBJEXT): {$(VPATH)}assert.h -yarp/extension.$(OBJEXT): {$(VPATH)}backward/2/assume.h -yarp/extension.$(OBJEXT): {$(VPATH)}backward/2/attributes.h -yarp/extension.$(OBJEXT): {$(VPATH)}backward/2/bool.h -yarp/extension.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h -yarp/extension.$(OBJEXT): {$(VPATH)}backward/2/limits.h -yarp/extension.$(OBJEXT): {$(VPATH)}backward/2/long_long.h -yarp/extension.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h -yarp/extension.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h -yarp/extension.$(OBJEXT): {$(VPATH)}config.h -yarp/extension.$(OBJEXT): {$(VPATH)}defines.h -yarp/extension.$(OBJEXT): {$(VPATH)}encoding.h -yarp/extension.$(OBJEXT): {$(VPATH)}intern.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/abi.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/anyargs.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/arithmetic.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/assume.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/attr/cold.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/attr/const.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/attr/error.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/attr/format.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/attr/packed_struct.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/attr/pure.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/attr/warning.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/cast.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/compiler_is.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/compiler_since.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/config.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/constant_p.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/core.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/core/rarray.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/core/rclass.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/core/rdata.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/core/rfile.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/core/rhash.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/core/robject.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/core/rstring.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/ctype.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/dllexport.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/dosish.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/encoding/re.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/encoding/string.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/error.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/eval.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/event.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/fl_type.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/gc.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/glob.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/globals.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/has/attribute.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/has/builtin.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/has/extension.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/has/feature.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/has/warning.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/intern/array.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/intern/class.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/intern/compar.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/intern/complex.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/intern/cont.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/intern/dir.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/intern/enum.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/intern/error.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/intern/eval.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/intern/file.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/intern/hash.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/intern/io.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/intern/load.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/intern/object.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/intern/parse.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/intern/proc.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/intern/process.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/intern/random.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/intern/range.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/intern/rational.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/intern/re.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/intern/select.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/intern/signal.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/intern/string.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/intern/struct.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/intern/thread.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/intern/time.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/intern/variable.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/intern/vm.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/interpreter.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/iterator.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/memory.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/method.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/module.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/newobj.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/scan_args.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/special_consts.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/static_assert.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/stdalign.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/stdbool.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/symbol.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/value.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/value_type.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/variable.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/warning_push.h -yarp/extension.$(OBJEXT): {$(VPATH)}internal/xmalloc.h -yarp/extension.$(OBJEXT): {$(VPATH)}missing.h -yarp/extension.$(OBJEXT): {$(VPATH)}onigmo.h -yarp/extension.$(OBJEXT): {$(VPATH)}oniguruma.h -yarp/extension.$(OBJEXT): {$(VPATH)}st.h -yarp/extension.$(OBJEXT): {$(VPATH)}subst.h -yarp/extension.$(OBJEXT): {$(VPATH)}yarp/ast.h -yarp/extension.$(OBJEXT): {$(VPATH)}yarp/version.h -yarp/node.$(OBJEXT): $(top_srcdir)/yarp/defines.h -yarp/node.$(OBJEXT): $(top_srcdir)/yarp/diagnostic.h -yarp/node.$(OBJEXT): $(top_srcdir)/yarp/enc/yp_encoding.h -yarp/node.$(OBJEXT): $(top_srcdir)/yarp/node.h -yarp/node.$(OBJEXT): $(top_srcdir)/yarp/pack.h -yarp/node.$(OBJEXT): $(top_srcdir)/yarp/parser.h -yarp/node.$(OBJEXT): $(top_srcdir)/yarp/regexp.h -yarp/node.$(OBJEXT): $(top_srcdir)/yarp/unescape.h -yarp/node.$(OBJEXT): $(top_srcdir)/yarp/util/yp_buffer.h -yarp/node.$(OBJEXT): $(top_srcdir)/yarp/util/yp_char.h -yarp/node.$(OBJEXT): $(top_srcdir)/yarp/util/yp_constant_pool.h -yarp/node.$(OBJEXT): $(top_srcdir)/yarp/util/yp_list.h -yarp/node.$(OBJEXT): $(top_srcdir)/yarp/util/yp_newline_list.h -yarp/node.$(OBJEXT): $(top_srcdir)/yarp/util/yp_state_stack.h -yarp/node.$(OBJEXT): $(top_srcdir)/yarp/util/yp_string.h -yarp/node.$(OBJEXT): $(top_srcdir)/yarp/util/yp_string_list.h -yarp/node.$(OBJEXT): $(top_srcdir)/yarp/util/yp_strpbrk.h -yarp/node.$(OBJEXT): $(top_srcdir)/yarp/yarp.h -yarp/node.$(OBJEXT): {$(VPATH)}config.h -yarp/node.$(OBJEXT): {$(VPATH)}yarp/ast.h -yarp/node.$(OBJEXT): {$(VPATH)}yarp/node.c -yarp/pack.$(OBJEXT): $(top_srcdir)/yarp/defines.h -yarp/pack.$(OBJEXT): $(top_srcdir)/yarp/pack.c -yarp/pack.$(OBJEXT): $(top_srcdir)/yarp/pack.h -yarp/pack.$(OBJEXT): {$(VPATH)}config.h -yarp/prettyprint.$(OBJEXT): $(top_srcdir)/yarp/defines.h -yarp/prettyprint.$(OBJEXT): $(top_srcdir)/yarp/enc/yp_encoding.h -yarp/prettyprint.$(OBJEXT): $(top_srcdir)/yarp/parser.h -yarp/prettyprint.$(OBJEXT): $(top_srcdir)/yarp/util/yp_buffer.h -yarp/prettyprint.$(OBJEXT): $(top_srcdir)/yarp/util/yp_constant_pool.h -yarp/prettyprint.$(OBJEXT): $(top_srcdir)/yarp/util/yp_list.h -yarp/prettyprint.$(OBJEXT): $(top_srcdir)/yarp/util/yp_newline_list.h -yarp/prettyprint.$(OBJEXT): $(top_srcdir)/yarp/util/yp_state_stack.h -yarp/prettyprint.$(OBJEXT): $(top_srcdir)/yarp/util/yp_string.h -yarp/prettyprint.$(OBJEXT): {$(VPATH)}config.h -yarp/prettyprint.$(OBJEXT): {$(VPATH)}yarp/ast.h -yarp/prettyprint.$(OBJEXT): {$(VPATH)}yarp/prettyprint.c -yarp/regexp.$(OBJEXT): $(top_srcdir)/yarp/defines.h -yarp/regexp.$(OBJEXT): $(top_srcdir)/yarp/enc/yp_encoding.h -yarp/regexp.$(OBJEXT): $(top_srcdir)/yarp/parser.h -yarp/regexp.$(OBJEXT): $(top_srcdir)/yarp/regexp.c -yarp/regexp.$(OBJEXT): $(top_srcdir)/yarp/regexp.h -yarp/regexp.$(OBJEXT): $(top_srcdir)/yarp/util/yp_constant_pool.h -yarp/regexp.$(OBJEXT): $(top_srcdir)/yarp/util/yp_list.h -yarp/regexp.$(OBJEXT): $(top_srcdir)/yarp/util/yp_memchr.h -yarp/regexp.$(OBJEXT): $(top_srcdir)/yarp/util/yp_newline_list.h -yarp/regexp.$(OBJEXT): $(top_srcdir)/yarp/util/yp_state_stack.h -yarp/regexp.$(OBJEXT): $(top_srcdir)/yarp/util/yp_string.h -yarp/regexp.$(OBJEXT): $(top_srcdir)/yarp/util/yp_string_list.h -yarp/regexp.$(OBJEXT): {$(VPATH)}config.h -yarp/regexp.$(OBJEXT): {$(VPATH)}yarp/ast.h -yarp/serialize.$(OBJEXT): $(top_srcdir)/yarp/defines.h -yarp/serialize.$(OBJEXT): $(top_srcdir)/yarp/diagnostic.h -yarp/serialize.$(OBJEXT): $(top_srcdir)/yarp/enc/yp_encoding.h -yarp/serialize.$(OBJEXT): $(top_srcdir)/yarp/node.h -yarp/serialize.$(OBJEXT): $(top_srcdir)/yarp/pack.h -yarp/serialize.$(OBJEXT): $(top_srcdir)/yarp/parser.h -yarp/serialize.$(OBJEXT): $(top_srcdir)/yarp/regexp.h -yarp/serialize.$(OBJEXT): $(top_srcdir)/yarp/unescape.h -yarp/serialize.$(OBJEXT): $(top_srcdir)/yarp/util/yp_buffer.h -yarp/serialize.$(OBJEXT): $(top_srcdir)/yarp/util/yp_char.h -yarp/serialize.$(OBJEXT): $(top_srcdir)/yarp/util/yp_constant_pool.h -yarp/serialize.$(OBJEXT): $(top_srcdir)/yarp/util/yp_list.h -yarp/serialize.$(OBJEXT): $(top_srcdir)/yarp/util/yp_memchr.h -yarp/serialize.$(OBJEXT): $(top_srcdir)/yarp/util/yp_newline_list.h -yarp/serialize.$(OBJEXT): $(top_srcdir)/yarp/util/yp_state_stack.h -yarp/serialize.$(OBJEXT): $(top_srcdir)/yarp/util/yp_string.h -yarp/serialize.$(OBJEXT): $(top_srcdir)/yarp/util/yp_string_list.h -yarp/serialize.$(OBJEXT): $(top_srcdir)/yarp/util/yp_strpbrk.h -yarp/serialize.$(OBJEXT): $(top_srcdir)/yarp/yarp.h -yarp/serialize.$(OBJEXT): {$(VPATH)}config.h -yarp/serialize.$(OBJEXT): {$(VPATH)}yarp/ast.h -yarp/serialize.$(OBJEXT): {$(VPATH)}yarp/serialize.c -yarp/serialize.$(OBJEXT): {$(VPATH)}yarp/version.h -yarp/token_type.$(OBJEXT): $(top_srcdir)/yarp/defines.h -yarp/token_type.$(OBJEXT): $(top_srcdir)/yarp/util/yp_constant_pool.h -yarp/token_type.$(OBJEXT): $(top_srcdir)/yarp/util/yp_string.h -yarp/token_type.$(OBJEXT): {$(VPATH)}config.h -yarp/token_type.$(OBJEXT): {$(VPATH)}yarp/ast.h -yarp/token_type.$(OBJEXT): {$(VPATH)}yarp/token_type.c -yarp/unescape.$(OBJEXT): $(top_srcdir)/yarp/defines.h -yarp/unescape.$(OBJEXT): $(top_srcdir)/yarp/diagnostic.h -yarp/unescape.$(OBJEXT): $(top_srcdir)/yarp/enc/yp_encoding.h -yarp/unescape.$(OBJEXT): $(top_srcdir)/yarp/node.h -yarp/unescape.$(OBJEXT): $(top_srcdir)/yarp/pack.h -yarp/unescape.$(OBJEXT): $(top_srcdir)/yarp/parser.h -yarp/unescape.$(OBJEXT): $(top_srcdir)/yarp/regexp.h -yarp/unescape.$(OBJEXT): $(top_srcdir)/yarp/unescape.c -yarp/unescape.$(OBJEXT): $(top_srcdir)/yarp/unescape.h -yarp/unescape.$(OBJEXT): $(top_srcdir)/yarp/util/yp_buffer.h -yarp/unescape.$(OBJEXT): $(top_srcdir)/yarp/util/yp_char.h -yarp/unescape.$(OBJEXT): $(top_srcdir)/yarp/util/yp_constant_pool.h -yarp/unescape.$(OBJEXT): $(top_srcdir)/yarp/util/yp_list.h -yarp/unescape.$(OBJEXT): $(top_srcdir)/yarp/util/yp_memchr.h -yarp/unescape.$(OBJEXT): $(top_srcdir)/yarp/util/yp_newline_list.h -yarp/unescape.$(OBJEXT): $(top_srcdir)/yarp/util/yp_state_stack.h -yarp/unescape.$(OBJEXT): $(top_srcdir)/yarp/util/yp_string.h -yarp/unescape.$(OBJEXT): $(top_srcdir)/yarp/util/yp_string_list.h -yarp/unescape.$(OBJEXT): $(top_srcdir)/yarp/util/yp_strpbrk.h -yarp/unescape.$(OBJEXT): $(top_srcdir)/yarp/yarp.h -yarp/unescape.$(OBJEXT): {$(VPATH)}config.h -yarp/unescape.$(OBJEXT): {$(VPATH)}yarp/ast.h -yarp/unescape.$(OBJEXT): {$(VPATH)}yarp/version.h -yarp/util/yp_buffer.$(OBJEXT): $(top_srcdir)/yarp/defines.h -yarp/util/yp_buffer.$(OBJEXT): $(top_srcdir)/yarp/util/yp_buffer.c -yarp/util/yp_buffer.$(OBJEXT): $(top_srcdir)/yarp/util/yp_buffer.h -yarp/util/yp_buffer.$(OBJEXT): {$(VPATH)}config.h -yarp/util/yp_char.$(OBJEXT): $(top_srcdir)/yarp/defines.h -yarp/util/yp_char.$(OBJEXT): $(top_srcdir)/yarp/util/yp_char.c -yarp/util/yp_char.$(OBJEXT): $(top_srcdir)/yarp/util/yp_char.h -yarp/util/yp_char.$(OBJEXT): $(top_srcdir)/yarp/util/yp_newline_list.h -yarp/util/yp_char.$(OBJEXT): {$(VPATH)}config.h -yarp/util/yp_constant_pool.$(OBJEXT): $(top_srcdir)/yarp/defines.h -yarp/util/yp_constant_pool.$(OBJEXT): $(top_srcdir)/yarp/util/yp_constant_pool.c -yarp/util/yp_constant_pool.$(OBJEXT): $(top_srcdir)/yarp/util/yp_constant_pool.h -yarp/util/yp_constant_pool.$(OBJEXT): {$(VPATH)}config.h -yarp/util/yp_list.$(OBJEXT): $(top_srcdir)/yarp/defines.h -yarp/util/yp_list.$(OBJEXT): $(top_srcdir)/yarp/util/yp_list.c -yarp/util/yp_list.$(OBJEXT): $(top_srcdir)/yarp/util/yp_list.h -yarp/util/yp_list.$(OBJEXT): {$(VPATH)}config.h -yarp/util/yp_memchr.$(OBJEXT): $(top_srcdir)/yarp/defines.h -yarp/util/yp_memchr.$(OBJEXT): $(top_srcdir)/yarp/enc/yp_encoding.h -yarp/util/yp_memchr.$(OBJEXT): $(top_srcdir)/yarp/parser.h -yarp/util/yp_memchr.$(OBJEXT): $(top_srcdir)/yarp/util/yp_constant_pool.h -yarp/util/yp_memchr.$(OBJEXT): $(top_srcdir)/yarp/util/yp_list.h -yarp/util/yp_memchr.$(OBJEXT): $(top_srcdir)/yarp/util/yp_memchr.c -yarp/util/yp_memchr.$(OBJEXT): $(top_srcdir)/yarp/util/yp_memchr.h -yarp/util/yp_memchr.$(OBJEXT): $(top_srcdir)/yarp/util/yp_newline_list.h -yarp/util/yp_memchr.$(OBJEXT): $(top_srcdir)/yarp/util/yp_state_stack.h -yarp/util/yp_memchr.$(OBJEXT): $(top_srcdir)/yarp/util/yp_string.h -yarp/util/yp_memchr.$(OBJEXT): {$(VPATH)}config.h -yarp/util/yp_memchr.$(OBJEXT): {$(VPATH)}yarp/ast.h -yarp/util/yp_newline_list.$(OBJEXT): $(top_srcdir)/yarp/defines.h -yarp/util/yp_newline_list.$(OBJEXT): $(top_srcdir)/yarp/util/yp_newline_list.c -yarp/util/yp_newline_list.$(OBJEXT): $(top_srcdir)/yarp/util/yp_newline_list.h -yarp/util/yp_newline_list.$(OBJEXT): {$(VPATH)}config.h -yarp/util/yp_state_stack.$(OBJEXT): $(top_srcdir)/yarp/defines.h -yarp/util/yp_state_stack.$(OBJEXT): $(top_srcdir)/yarp/util/yp_state_stack.c -yarp/util/yp_state_stack.$(OBJEXT): $(top_srcdir)/yarp/util/yp_state_stack.h -yarp/util/yp_state_stack.$(OBJEXT): {$(VPATH)}config.h -yarp/util/yp_string.$(OBJEXT): $(top_srcdir)/yarp/defines.h -yarp/util/yp_string.$(OBJEXT): $(top_srcdir)/yarp/util/yp_string.c -yarp/util/yp_string.$(OBJEXT): $(top_srcdir)/yarp/util/yp_string.h -yarp/util/yp_string.$(OBJEXT): {$(VPATH)}config.h -yarp/util/yp_string_list.$(OBJEXT): $(top_srcdir)/yarp/defines.h -yarp/util/yp_string_list.$(OBJEXT): $(top_srcdir)/yarp/util/yp_string.h -yarp/util/yp_string_list.$(OBJEXT): $(top_srcdir)/yarp/util/yp_string_list.c -yarp/util/yp_string_list.$(OBJEXT): $(top_srcdir)/yarp/util/yp_string_list.h -yarp/util/yp_string_list.$(OBJEXT): {$(VPATH)}config.h -yarp/util/yp_strncasecmp.$(OBJEXT): $(top_srcdir)/yarp/defines.h -yarp/util/yp_strncasecmp.$(OBJEXT): $(top_srcdir)/yarp/util/yp_strncasecmp.c -yarp/util/yp_strpbrk.$(OBJEXT): $(top_srcdir)/yarp/defines.h -yarp/util/yp_strpbrk.$(OBJEXT): $(top_srcdir)/yarp/enc/yp_encoding.h -yarp/util/yp_strpbrk.$(OBJEXT): $(top_srcdir)/yarp/parser.h -yarp/util/yp_strpbrk.$(OBJEXT): $(top_srcdir)/yarp/util/yp_constant_pool.h -yarp/util/yp_strpbrk.$(OBJEXT): $(top_srcdir)/yarp/util/yp_list.h -yarp/util/yp_strpbrk.$(OBJEXT): $(top_srcdir)/yarp/util/yp_newline_list.h -yarp/util/yp_strpbrk.$(OBJEXT): $(top_srcdir)/yarp/util/yp_state_stack.h -yarp/util/yp_strpbrk.$(OBJEXT): $(top_srcdir)/yarp/util/yp_string.h -yarp/util/yp_strpbrk.$(OBJEXT): $(top_srcdir)/yarp/util/yp_strpbrk.c -yarp/util/yp_strpbrk.$(OBJEXT): $(top_srcdir)/yarp/util/yp_strpbrk.h -yarp/util/yp_strpbrk.$(OBJEXT): {$(VPATH)}config.h -yarp/util/yp_strpbrk.$(OBJEXT): {$(VPATH)}yarp/ast.h -yarp/yarp.$(OBJEXT): $(top_srcdir)/yarp/defines.h -yarp/yarp.$(OBJEXT): $(top_srcdir)/yarp/diagnostic.h -yarp/yarp.$(OBJEXT): $(top_srcdir)/yarp/enc/yp_encoding.h -yarp/yarp.$(OBJEXT): $(top_srcdir)/yarp/node.h -yarp/yarp.$(OBJEXT): $(top_srcdir)/yarp/pack.h -yarp/yarp.$(OBJEXT): $(top_srcdir)/yarp/parser.h -yarp/yarp.$(OBJEXT): $(top_srcdir)/yarp/regexp.h -yarp/yarp.$(OBJEXT): $(top_srcdir)/yarp/unescape.h -yarp/yarp.$(OBJEXT): $(top_srcdir)/yarp/util/yp_buffer.h -yarp/yarp.$(OBJEXT): $(top_srcdir)/yarp/util/yp_char.h -yarp/yarp.$(OBJEXT): $(top_srcdir)/yarp/util/yp_constant_pool.h -yarp/yarp.$(OBJEXT): $(top_srcdir)/yarp/util/yp_list.h -yarp/yarp.$(OBJEXT): $(top_srcdir)/yarp/util/yp_memchr.h -yarp/yarp.$(OBJEXT): $(top_srcdir)/yarp/util/yp_newline_list.h -yarp/yarp.$(OBJEXT): $(top_srcdir)/yarp/util/yp_state_stack.h -yarp/yarp.$(OBJEXT): $(top_srcdir)/yarp/util/yp_string.h -yarp/yarp.$(OBJEXT): $(top_srcdir)/yarp/util/yp_string_list.h -yarp/yarp.$(OBJEXT): $(top_srcdir)/yarp/util/yp_strpbrk.h -yarp/yarp.$(OBJEXT): $(top_srcdir)/yarp/version.h -yarp/yarp.$(OBJEXT): $(top_srcdir)/yarp/yarp.c -yarp/yarp.$(OBJEXT): $(top_srcdir)/yarp/yarp.h -yarp/yarp.$(OBJEXT): {$(VPATH)}config.h -yarp/yarp.$(OBJEXT): {$(VPATH)}yarp/ast.h -yarp/yarp.$(OBJEXT): {$(VPATH)}yarp/version.h -yarp/yarp_init.$(OBJEXT): $(hdrdir)/ruby.h -yarp/yarp_init.$(OBJEXT): $(hdrdir)/ruby/ruby.h -yarp/yarp_init.$(OBJEXT): $(top_srcdir)/yarp/defines.h -yarp/yarp_init.$(OBJEXT): $(top_srcdir)/yarp/diagnostic.h -yarp/yarp_init.$(OBJEXT): $(top_srcdir)/yarp/enc/yp_encoding.h -yarp/yarp_init.$(OBJEXT): $(top_srcdir)/yarp/extension.h -yarp/yarp_init.$(OBJEXT): $(top_srcdir)/yarp/node.h -yarp/yarp_init.$(OBJEXT): $(top_srcdir)/yarp/pack.h -yarp/yarp_init.$(OBJEXT): $(top_srcdir)/yarp/parser.h -yarp/yarp_init.$(OBJEXT): $(top_srcdir)/yarp/regexp.h -yarp/yarp_init.$(OBJEXT): $(top_srcdir)/yarp/unescape.h -yarp/yarp_init.$(OBJEXT): $(top_srcdir)/yarp/util/yp_buffer.h -yarp/yarp_init.$(OBJEXT): $(top_srcdir)/yarp/util/yp_char.h -yarp/yarp_init.$(OBJEXT): $(top_srcdir)/yarp/util/yp_constant_pool.h -yarp/yarp_init.$(OBJEXT): $(top_srcdir)/yarp/util/yp_list.h -yarp/yarp_init.$(OBJEXT): $(top_srcdir)/yarp/util/yp_memchr.h -yarp/yarp_init.$(OBJEXT): $(top_srcdir)/yarp/util/yp_newline_list.h -yarp/yarp_init.$(OBJEXT): $(top_srcdir)/yarp/util/yp_state_stack.h -yarp/yarp_init.$(OBJEXT): $(top_srcdir)/yarp/util/yp_string.h -yarp/yarp_init.$(OBJEXT): $(top_srcdir)/yarp/util/yp_string_list.h -yarp/yarp_init.$(OBJEXT): $(top_srcdir)/yarp/util/yp_strpbrk.h -yarp/yarp_init.$(OBJEXT): $(top_srcdir)/yarp/yarp.h -yarp/yarp_init.$(OBJEXT): $(top_srcdir)/yarp/yarp_init.c -yarp/yarp_init.$(OBJEXT): {$(VPATH)}assert.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}backward/2/assume.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}backward/2/attributes.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}backward/2/bool.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}backward/2/limits.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}backward/2/long_long.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}config.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}defines.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}encoding.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}intern.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/abi.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/anyargs.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/arithmetic.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/assume.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/attr/cold.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/attr/const.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/attr/error.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/attr/format.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/attr/packed_struct.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/attr/pure.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/attr/warning.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/cast.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/compiler_is.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/compiler_since.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/config.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/constant_p.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/core.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/core/rarray.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/core/rclass.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/core/rdata.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/core/rfile.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/core/rhash.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/core/robject.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/core/rstring.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/ctype.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/dllexport.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/dosish.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/encoding/re.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/encoding/string.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/error.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/eval.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/event.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/fl_type.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/gc.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/glob.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/globals.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/has/attribute.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/has/builtin.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/has/extension.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/has/feature.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/has/warning.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/intern/array.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/intern/class.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/intern/compar.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/intern/complex.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/intern/cont.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/intern/dir.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/intern/enum.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/intern/error.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/intern/eval.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/intern/file.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/intern/hash.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/intern/io.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/intern/load.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/intern/object.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/intern/parse.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/intern/proc.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/intern/process.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/intern/random.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/intern/range.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/intern/rational.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/intern/re.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/intern/select.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/intern/signal.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/intern/string.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/intern/struct.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/intern/thread.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/intern/time.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/intern/variable.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/intern/vm.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/interpreter.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/iterator.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/memory.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/method.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/module.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/newobj.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/scan_args.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/special_consts.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/static_assert.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/stdalign.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/stdbool.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/symbol.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/value.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/value_type.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/variable.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/warning_push.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}internal/xmalloc.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}missing.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}onigmo.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}oniguruma.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}st.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}subst.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}yarp/ast.h -yarp/yarp_init.$(OBJEXT): {$(VPATH)}yarp/version.h yjit.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h yjit.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h yjit.$(OBJEXT): $(CCAN_DIR)/list/list.h @@ -19981,14 +21796,36 @@ yjit.$(OBJEXT): $(top_srcdir)/internal/fixnum.h yjit.$(OBJEXT): $(top_srcdir)/internal/gc.h yjit.$(OBJEXT): $(top_srcdir)/internal/hash.h yjit.$(OBJEXT): $(top_srcdir)/internal/imemo.h +yjit.$(OBJEXT): $(top_srcdir)/internal/namespace.h yjit.$(OBJEXT): $(top_srcdir)/internal/numeric.h yjit.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h yjit.$(OBJEXT): $(top_srcdir)/internal/serial.h +yjit.$(OBJEXT): $(top_srcdir)/internal/set_table.h yjit.$(OBJEXT): $(top_srcdir)/internal/static_assert.h yjit.$(OBJEXT): $(top_srcdir)/internal/string.h yjit.$(OBJEXT): $(top_srcdir)/internal/variable.h yjit.$(OBJEXT): $(top_srcdir)/internal/vm.h yjit.$(OBJEXT): $(top_srcdir)/internal/warnings.h +yjit.$(OBJEXT): $(top_srcdir)/prism/defines.h +yjit.$(OBJEXT): $(top_srcdir)/prism/encoding.h +yjit.$(OBJEXT): $(top_srcdir)/prism/node.h +yjit.$(OBJEXT): $(top_srcdir)/prism/options.h +yjit.$(OBJEXT): $(top_srcdir)/prism/pack.h +yjit.$(OBJEXT): $(top_srcdir)/prism/parser.h +yjit.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h +yjit.$(OBJEXT): $(top_srcdir)/prism/prism.h +yjit.$(OBJEXT): $(top_srcdir)/prism/regexp.h +yjit.$(OBJEXT): $(top_srcdir)/prism/static_literals.h +yjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h +yjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h +yjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h +yjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h +yjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h +yjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h +yjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h +yjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h +yjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h +yjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h yjit.$(OBJEXT): {$(VPATH)}assert.h yjit.$(OBJEXT): {$(VPATH)}atomic.h yjit.$(OBJEXT): {$(VPATH)}backward/2/assume.h @@ -20137,6 +21974,7 @@ yjit.$(OBJEXT): {$(VPATH)}internal/intern/re.h yjit.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h yjit.$(OBJEXT): {$(VPATH)}internal/intern/select.h yjit.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +yjit.$(OBJEXT): {$(VPATH)}internal/intern/set.h yjit.$(OBJEXT): {$(VPATH)}internal/intern/signal.h yjit.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h yjit.$(OBJEXT): {$(VPATH)}internal/intern/string.h @@ -20157,6 +21995,7 @@ yjit.$(OBJEXT): {$(VPATH)}internal/special_consts.h yjit.$(OBJEXT): {$(VPATH)}internal/static_assert.h yjit.$(OBJEXT): {$(VPATH)}internal/stdalign.h yjit.$(OBJEXT): {$(VPATH)}internal/stdbool.h +yjit.$(OBJEXT): {$(VPATH)}internal/stdckdint.h yjit.$(OBJEXT): {$(VPATH)}internal/symbol.h yjit.$(OBJEXT): {$(VPATH)}internal/value.h yjit.$(OBJEXT): {$(VPATH)}internal/value_type.h @@ -20169,6 +22008,10 @@ yjit.$(OBJEXT): {$(VPATH)}missing.h yjit.$(OBJEXT): {$(VPATH)}node.h yjit.$(OBJEXT): {$(VPATH)}onigmo.h yjit.$(OBJEXT): {$(VPATH)}oniguruma.h +yjit.$(OBJEXT): {$(VPATH)}prism/ast.h +yjit.$(OBJEXT): {$(VPATH)}prism/diagnostic.h +yjit.$(OBJEXT): {$(VPATH)}prism/version.h +yjit.$(OBJEXT): {$(VPATH)}prism_compile.h yjit.$(OBJEXT): {$(VPATH)}probes.dmyh yjit.$(OBJEXT): {$(VPATH)}probes.h yjit.$(OBJEXT): {$(VPATH)}probes_helper.h @@ -20189,4 +22032,255 @@ yjit.$(OBJEXT): {$(VPATH)}vm_sync.h yjit.$(OBJEXT): {$(VPATH)}yjit.c yjit.$(OBJEXT): {$(VPATH)}yjit.h yjit.$(OBJEXT): {$(VPATH)}yjit.rbinc +yjit.$(OBJEXT): {$(VPATH)}zjit.h +zjit.$(OBJEXT): $(CCAN_DIR)/check_type/check_type.h +zjit.$(OBJEXT): $(CCAN_DIR)/container_of/container_of.h +zjit.$(OBJEXT): $(CCAN_DIR)/list/list.h +zjit.$(OBJEXT): $(CCAN_DIR)/str/str.h +zjit.$(OBJEXT): $(hdrdir)/ruby/ruby.h +zjit.$(OBJEXT): $(top_srcdir)/internal/array.h +zjit.$(OBJEXT): $(top_srcdir)/internal/basic_operators.h +zjit.$(OBJEXT): $(top_srcdir)/internal/bignum.h +zjit.$(OBJEXT): $(top_srcdir)/internal/bits.h +zjit.$(OBJEXT): $(top_srcdir)/internal/class.h +zjit.$(OBJEXT): $(top_srcdir)/internal/compile.h +zjit.$(OBJEXT): $(top_srcdir)/internal/compilers.h +zjit.$(OBJEXT): $(top_srcdir)/internal/cont.h +zjit.$(OBJEXT): $(top_srcdir)/internal/fixnum.h +zjit.$(OBJEXT): $(top_srcdir)/internal/gc.h +zjit.$(OBJEXT): $(top_srcdir)/internal/hash.h +zjit.$(OBJEXT): $(top_srcdir)/internal/imemo.h +zjit.$(OBJEXT): $(top_srcdir)/internal/numeric.h +zjit.$(OBJEXT): $(top_srcdir)/internal/sanitizers.h +zjit.$(OBJEXT): $(top_srcdir)/internal/serial.h +zjit.$(OBJEXT): $(top_srcdir)/internal/static_assert.h +zjit.$(OBJEXT): $(top_srcdir)/internal/string.h +zjit.$(OBJEXT): $(top_srcdir)/internal/variable.h +zjit.$(OBJEXT): $(top_srcdir)/internal/vm.h +zjit.$(OBJEXT): $(top_srcdir)/internal/warnings.h +zjit.$(OBJEXT): $(top_srcdir)/prism/defines.h +zjit.$(OBJEXT): $(top_srcdir)/prism/encoding.h +zjit.$(OBJEXT): $(top_srcdir)/prism/node.h +zjit.$(OBJEXT): $(top_srcdir)/prism/options.h +zjit.$(OBJEXT): $(top_srcdir)/prism/pack.h +zjit.$(OBJEXT): $(top_srcdir)/prism/parser.h +zjit.$(OBJEXT): $(top_srcdir)/prism/prettyprint.h +zjit.$(OBJEXT): $(top_srcdir)/prism/prism.h +zjit.$(OBJEXT): $(top_srcdir)/prism/regexp.h +zjit.$(OBJEXT): $(top_srcdir)/prism/static_literals.h +zjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_buffer.h +zjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_char.h +zjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_constant_pool.h +zjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_integer.h +zjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_list.h +zjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_memchr.h +zjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_newline_list.h +zjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_string.h +zjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_strncasecmp.h +zjit.$(OBJEXT): $(top_srcdir)/prism/util/pm_strpbrk.h +zjit.$(OBJEXT): {$(VPATH)}assert.h +zjit.$(OBJEXT): {$(VPATH)}atomic.h +zjit.$(OBJEXT): {$(VPATH)}backward/2/assume.h +zjit.$(OBJEXT): {$(VPATH)}backward/2/attributes.h +zjit.$(OBJEXT): {$(VPATH)}backward/2/bool.h +zjit.$(OBJEXT): {$(VPATH)}backward/2/gcc_version_since.h +zjit.$(OBJEXT): {$(VPATH)}backward/2/inttypes.h +zjit.$(OBJEXT): {$(VPATH)}backward/2/limits.h +zjit.$(OBJEXT): {$(VPATH)}backward/2/long_long.h +zjit.$(OBJEXT): {$(VPATH)}backward/2/stdalign.h +zjit.$(OBJEXT): {$(VPATH)}backward/2/stdarg.h +zjit.$(OBJEXT): {$(VPATH)}builtin.h +zjit.$(OBJEXT): {$(VPATH)}config.h +zjit.$(OBJEXT): {$(VPATH)}constant.h +zjit.$(OBJEXT): {$(VPATH)}debug.h +zjit.$(OBJEXT): {$(VPATH)}debug_counter.h +zjit.$(OBJEXT): {$(VPATH)}defines.h +zjit.$(OBJEXT): {$(VPATH)}encoding.h +zjit.$(OBJEXT): {$(VPATH)}id.h +zjit.$(OBJEXT): {$(VPATH)}id_table.h +zjit.$(OBJEXT): {$(VPATH)}insns.def +zjit.$(OBJEXT): {$(VPATH)}insns.inc +zjit.$(OBJEXT): {$(VPATH)}insns_info.inc +zjit.$(OBJEXT): {$(VPATH)}intern.h +zjit.$(OBJEXT): {$(VPATH)}internal.h +zjit.$(OBJEXT): {$(VPATH)}internal/abi.h +zjit.$(OBJEXT): {$(VPATH)}internal/anyargs.h +zjit.$(OBJEXT): {$(VPATH)}internal/arithmetic.h +zjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/char.h +zjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/double.h +zjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/fixnum.h +zjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/gid_t.h +zjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/int.h +zjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/intptr_t.h +zjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/long.h +zjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/long_long.h +zjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/mode_t.h +zjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/off_t.h +zjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/pid_t.h +zjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/short.h +zjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/size_t.h +zjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/st_data_t.h +zjit.$(OBJEXT): {$(VPATH)}internal/arithmetic/uid_t.h +zjit.$(OBJEXT): {$(VPATH)}internal/assume.h +zjit.$(OBJEXT): {$(VPATH)}internal/attr/alloc_size.h +zjit.$(OBJEXT): {$(VPATH)}internal/attr/artificial.h +zjit.$(OBJEXT): {$(VPATH)}internal/attr/cold.h +zjit.$(OBJEXT): {$(VPATH)}internal/attr/const.h +zjit.$(OBJEXT): {$(VPATH)}internal/attr/constexpr.h +zjit.$(OBJEXT): {$(VPATH)}internal/attr/deprecated.h +zjit.$(OBJEXT): {$(VPATH)}internal/attr/diagnose_if.h +zjit.$(OBJEXT): {$(VPATH)}internal/attr/enum_extensibility.h +zjit.$(OBJEXT): {$(VPATH)}internal/attr/error.h +zjit.$(OBJEXT): {$(VPATH)}internal/attr/flag_enum.h +zjit.$(OBJEXT): {$(VPATH)}internal/attr/forceinline.h +zjit.$(OBJEXT): {$(VPATH)}internal/attr/format.h +zjit.$(OBJEXT): {$(VPATH)}internal/attr/maybe_unused.h +zjit.$(OBJEXT): {$(VPATH)}internal/attr/noalias.h +zjit.$(OBJEXT): {$(VPATH)}internal/attr/nodiscard.h +zjit.$(OBJEXT): {$(VPATH)}internal/attr/noexcept.h +zjit.$(OBJEXT): {$(VPATH)}internal/attr/noinline.h +zjit.$(OBJEXT): {$(VPATH)}internal/attr/nonnull.h +zjit.$(OBJEXT): {$(VPATH)}internal/attr/noreturn.h +zjit.$(OBJEXT): {$(VPATH)}internal/attr/packed_struct.h +zjit.$(OBJEXT): {$(VPATH)}internal/attr/pure.h +zjit.$(OBJEXT): {$(VPATH)}internal/attr/restrict.h +zjit.$(OBJEXT): {$(VPATH)}internal/attr/returns_nonnull.h +zjit.$(OBJEXT): {$(VPATH)}internal/attr/warning.h +zjit.$(OBJEXT): {$(VPATH)}internal/attr/weakref.h +zjit.$(OBJEXT): {$(VPATH)}internal/cast.h +zjit.$(OBJEXT): {$(VPATH)}internal/compiler_is.h +zjit.$(OBJEXT): {$(VPATH)}internal/compiler_is/apple.h +zjit.$(OBJEXT): {$(VPATH)}internal/compiler_is/clang.h +zjit.$(OBJEXT): {$(VPATH)}internal/compiler_is/gcc.h +zjit.$(OBJEXT): {$(VPATH)}internal/compiler_is/intel.h +zjit.$(OBJEXT): {$(VPATH)}internal/compiler_is/msvc.h +zjit.$(OBJEXT): {$(VPATH)}internal/compiler_is/sunpro.h +zjit.$(OBJEXT): {$(VPATH)}internal/compiler_since.h +zjit.$(OBJEXT): {$(VPATH)}internal/config.h +zjit.$(OBJEXT): {$(VPATH)}internal/constant_p.h +zjit.$(OBJEXT): {$(VPATH)}internal/core.h +zjit.$(OBJEXT): {$(VPATH)}internal/core/rarray.h +zjit.$(OBJEXT): {$(VPATH)}internal/core/rbasic.h +zjit.$(OBJEXT): {$(VPATH)}internal/core/rbignum.h +zjit.$(OBJEXT): {$(VPATH)}internal/core/rclass.h +zjit.$(OBJEXT): {$(VPATH)}internal/core/rdata.h +zjit.$(OBJEXT): {$(VPATH)}internal/core/rfile.h +zjit.$(OBJEXT): {$(VPATH)}internal/core/rhash.h +zjit.$(OBJEXT): {$(VPATH)}internal/core/robject.h +zjit.$(OBJEXT): {$(VPATH)}internal/core/rregexp.h +zjit.$(OBJEXT): {$(VPATH)}internal/core/rstring.h +zjit.$(OBJEXT): {$(VPATH)}internal/core/rstruct.h +zjit.$(OBJEXT): {$(VPATH)}internal/core/rtypeddata.h +zjit.$(OBJEXT): {$(VPATH)}internal/ctype.h +zjit.$(OBJEXT): {$(VPATH)}internal/dllexport.h +zjit.$(OBJEXT): {$(VPATH)}internal/dosish.h +zjit.$(OBJEXT): {$(VPATH)}internal/encoding/coderange.h +zjit.$(OBJEXT): {$(VPATH)}internal/encoding/ctype.h +zjit.$(OBJEXT): {$(VPATH)}internal/encoding/encoding.h +zjit.$(OBJEXT): {$(VPATH)}internal/encoding/pathname.h +zjit.$(OBJEXT): {$(VPATH)}internal/encoding/re.h +zjit.$(OBJEXT): {$(VPATH)}internal/encoding/sprintf.h +zjit.$(OBJEXT): {$(VPATH)}internal/encoding/string.h +zjit.$(OBJEXT): {$(VPATH)}internal/encoding/symbol.h +zjit.$(OBJEXT): {$(VPATH)}internal/encoding/transcode.h +zjit.$(OBJEXT): {$(VPATH)}internal/error.h +zjit.$(OBJEXT): {$(VPATH)}internal/eval.h +zjit.$(OBJEXT): {$(VPATH)}internal/event.h +zjit.$(OBJEXT): {$(VPATH)}internal/fl_type.h +zjit.$(OBJEXT): {$(VPATH)}internal/gc.h +zjit.$(OBJEXT): {$(VPATH)}internal/glob.h +zjit.$(OBJEXT): {$(VPATH)}internal/globals.h +zjit.$(OBJEXT): {$(VPATH)}internal/has/attribute.h +zjit.$(OBJEXT): {$(VPATH)}internal/has/builtin.h +zjit.$(OBJEXT): {$(VPATH)}internal/has/c_attribute.h +zjit.$(OBJEXT): {$(VPATH)}internal/has/cpp_attribute.h +zjit.$(OBJEXT): {$(VPATH)}internal/has/declspec_attribute.h +zjit.$(OBJEXT): {$(VPATH)}internal/has/extension.h +zjit.$(OBJEXT): {$(VPATH)}internal/has/feature.h +zjit.$(OBJEXT): {$(VPATH)}internal/has/warning.h +zjit.$(OBJEXT): {$(VPATH)}internal/intern/array.h +zjit.$(OBJEXT): {$(VPATH)}internal/intern/bignum.h +zjit.$(OBJEXT): {$(VPATH)}internal/intern/class.h +zjit.$(OBJEXT): {$(VPATH)}internal/intern/compar.h +zjit.$(OBJEXT): {$(VPATH)}internal/intern/complex.h +zjit.$(OBJEXT): {$(VPATH)}internal/intern/cont.h +zjit.$(OBJEXT): {$(VPATH)}internal/intern/dir.h +zjit.$(OBJEXT): {$(VPATH)}internal/intern/enum.h +zjit.$(OBJEXT): {$(VPATH)}internal/intern/enumerator.h +zjit.$(OBJEXT): {$(VPATH)}internal/intern/error.h +zjit.$(OBJEXT): {$(VPATH)}internal/intern/eval.h +zjit.$(OBJEXT): {$(VPATH)}internal/intern/file.h +zjit.$(OBJEXT): {$(VPATH)}internal/intern/hash.h +zjit.$(OBJEXT): {$(VPATH)}internal/intern/io.h +zjit.$(OBJEXT): {$(VPATH)}internal/intern/load.h +zjit.$(OBJEXT): {$(VPATH)}internal/intern/marshal.h +zjit.$(OBJEXT): {$(VPATH)}internal/intern/numeric.h +zjit.$(OBJEXT): {$(VPATH)}internal/intern/object.h +zjit.$(OBJEXT): {$(VPATH)}internal/intern/parse.h +zjit.$(OBJEXT): {$(VPATH)}internal/intern/proc.h +zjit.$(OBJEXT): {$(VPATH)}internal/intern/process.h +zjit.$(OBJEXT): {$(VPATH)}internal/intern/random.h +zjit.$(OBJEXT): {$(VPATH)}internal/intern/range.h +zjit.$(OBJEXT): {$(VPATH)}internal/intern/rational.h +zjit.$(OBJEXT): {$(VPATH)}internal/intern/re.h +zjit.$(OBJEXT): {$(VPATH)}internal/intern/ruby.h +zjit.$(OBJEXT): {$(VPATH)}internal/intern/select.h +zjit.$(OBJEXT): {$(VPATH)}internal/intern/select/largesize.h +zjit.$(OBJEXT): {$(VPATH)}internal/intern/signal.h +zjit.$(OBJEXT): {$(VPATH)}internal/intern/sprintf.h +zjit.$(OBJEXT): {$(VPATH)}internal/intern/string.h +zjit.$(OBJEXT): {$(VPATH)}internal/intern/struct.h +zjit.$(OBJEXT): {$(VPATH)}internal/intern/thread.h +zjit.$(OBJEXT): {$(VPATH)}internal/intern/time.h +zjit.$(OBJEXT): {$(VPATH)}internal/intern/variable.h +zjit.$(OBJEXT): {$(VPATH)}internal/intern/vm.h +zjit.$(OBJEXT): {$(VPATH)}internal/interpreter.h +zjit.$(OBJEXT): {$(VPATH)}internal/iterator.h +zjit.$(OBJEXT): {$(VPATH)}internal/memory.h +zjit.$(OBJEXT): {$(VPATH)}internal/method.h +zjit.$(OBJEXT): {$(VPATH)}internal/module.h +zjit.$(OBJEXT): {$(VPATH)}internal/newobj.h +zjit.$(OBJEXT): {$(VPATH)}internal/numeric.h +zjit.$(OBJEXT): {$(VPATH)}internal/scan_args.h +zjit.$(OBJEXT): {$(VPATH)}internal/special_consts.h +zjit.$(OBJEXT): {$(VPATH)}internal/static_assert.h +zjit.$(OBJEXT): {$(VPATH)}internal/stdalign.h +zjit.$(OBJEXT): {$(VPATH)}internal/stdbool.h +zjit.$(OBJEXT): {$(VPATH)}internal/stdckdint.h +zjit.$(OBJEXT): {$(VPATH)}internal/symbol.h +zjit.$(OBJEXT): {$(VPATH)}internal/value.h +zjit.$(OBJEXT): {$(VPATH)}internal/value_type.h +zjit.$(OBJEXT): {$(VPATH)}internal/variable.h +zjit.$(OBJEXT): {$(VPATH)}internal/warning_push.h +zjit.$(OBJEXT): {$(VPATH)}internal/xmalloc.h +zjit.$(OBJEXT): {$(VPATH)}iseq.h +zjit.$(OBJEXT): {$(VPATH)}method.h +zjit.$(OBJEXT): {$(VPATH)}missing.h +zjit.$(OBJEXT): {$(VPATH)}node.h +zjit.$(OBJEXT): {$(VPATH)}onigmo.h +zjit.$(OBJEXT): {$(VPATH)}oniguruma.h +zjit.$(OBJEXT): {$(VPATH)}prism/ast.h +zjit.$(OBJEXT): {$(VPATH)}prism/diagnostic.h +zjit.$(OBJEXT): {$(VPATH)}prism/version.h +zjit.$(OBJEXT): {$(VPATH)}prism_compile.h +zjit.$(OBJEXT): {$(VPATH)}probes.dmyh +zjit.$(OBJEXT): {$(VPATH)}probes.h +zjit.$(OBJEXT): {$(VPATH)}probes_helper.h +zjit.$(OBJEXT): {$(VPATH)}ruby_assert.h +zjit.$(OBJEXT): {$(VPATH)}ruby_atomic.h +zjit.$(OBJEXT): {$(VPATH)}rubyparser.h +zjit.$(OBJEXT): {$(VPATH)}shape.h +zjit.$(OBJEXT): {$(VPATH)}st.h +zjit.$(OBJEXT): {$(VPATH)}subst.h +zjit.$(OBJEXT): {$(VPATH)}thread_$(THREAD_MODEL).h +zjit.$(OBJEXT): {$(VPATH)}thread_native.h +zjit.$(OBJEXT): {$(VPATH)}vm_callinfo.h +zjit.$(OBJEXT): {$(VPATH)}vm_core.h +zjit.$(OBJEXT): {$(VPATH)}vm_debug.h +zjit.$(OBJEXT): {$(VPATH)}vm_insnhelper.h +zjit.$(OBJEXT): {$(VPATH)}vm_opts.h +zjit.$(OBJEXT): {$(VPATH)}vm_sync.h +zjit.$(OBJEXT): {$(VPATH)}zjit.c +zjit.$(OBJEXT): {$(VPATH)}zjit.h +zjit.$(OBJEXT): {$(VPATH)}zjit.rbinc # AUTOGENERATED DEPENDENCIES END diff --git a/compar.c b/compar.c index 2b34ebb062c499..f5da6178cf4358 100644 --- a/compar.c +++ b/compar.c @@ -187,6 +187,12 @@ cmp_between(VALUE x, VALUE min, VALUE max) * 'd'.clamp('a', 'f') #=> 'd' * 'z'.clamp('a', 'f') #=> 'f' * + * If _min_ is +nil+, it is considered smaller than _obj_, + * and if _max_ is +nil+, it is considered greater than _obj_. + * + * -20.clamp(0, nil) #=> 0 + * 523.clamp(nil, 100) #=> 100 + * * In (range) form, returns _range.begin_ if _obj_ * <=> _range.begin_ is less than zero, _range.end_ * if _obj_ <=> _range.end_ is greater than zero, and @@ -257,25 +263,28 @@ cmp_clamp(int argc, VALUE *argv, VALUE x) * ==, >=, and >) and the * method between?. * - * class SizeMatters + * class StringSorter * include Comparable + * * attr :str * def <=>(other) * str.size <=> other.str.size * end + * * def initialize(str) * @str = str * end + * * def inspect * @str * end * end * - * s1 = SizeMatters.new("Z") - * s2 = SizeMatters.new("YY") - * s3 = SizeMatters.new("XXX") - * s4 = SizeMatters.new("WWWW") - * s5 = SizeMatters.new("VVVVV") + * s1 = StringSorter.new("Z") + * s2 = StringSorter.new("YY") + * s3 = StringSorter.new("XXX") + * s4 = StringSorter.new("WWWW") + * s5 = StringSorter.new("VVVVV") * * s1 < s2 #=> true * s4.between?(s1, s3) #=> false @@ -284,7 +293,7 @@ cmp_clamp(int argc, VALUE *argv, VALUE x) * * == What's Here * - * \Module \Comparable provides these methods, all of which use method <=>: + * Module \Comparable provides these methods, all of which use method #<=>: * * - #<: Returns whether +self+ is less than the given object. * - #<=: Returns whether +self+ is less than or equal to the given object. diff --git a/compile.c b/compile.c index a165690597938a..8d5cb45904c6e7 100644 --- a/compile.c +++ b/compile.c @@ -26,30 +26,29 @@ #include "internal/error.h" #include "internal/gc.h" #include "internal/hash.h" +#include "internal/io.h" #include "internal/numeric.h" #include "internal/object.h" #include "internal/rational.h" #include "internal/re.h" +#include "internal/ruby_parser.h" #include "internal/symbol.h" #include "internal/thread.h" #include "internal/variable.h" #include "iseq.h" +#include "ruby/ractor.h" #include "ruby/re.h" #include "ruby/util.h" #include "vm_core.h" #include "vm_callinfo.h" #include "vm_debug.h" +#include "yjit.h" #include "builtin.h" #include "insns.inc" #include "insns_info.inc" -#include "yarp/yarp.h" - -#undef RUBY_UNTYPED_DATA_WARNING -#define RUBY_UNTYPED_DATA_WARNING 0 #define FIXNUM_INC(n, i) ((n)+(INT2FIX(i)&~FIXNUM_FLAG)) -#define FIXNUM_OR(n, i) ((n)|INT2FIX(i)) typedef struct iseq_link_element { enum { @@ -119,7 +118,7 @@ struct ensure_range { }; struct iseq_compile_data_ensure_node_stack { - const NODE *ensure_node; + const void *ensure_node; struct iseq_compile_data_ensure_node_stack *prev; struct ensure_range *erange; }; @@ -214,36 +213,43 @@ const ID rb_iseq_shared_exc_local_tbl[] = {idERROR_INFO}; #define NEW_CHILD_ISEQ(node, name, type, line_no) \ new_child_iseq(iseq, (node), rb_fstring(name), iseq, (type), (line_no)) +#define NEW_CHILD_ISEQ_WITH_CALLBACK(callback_func, name, type, line_no) \ + new_child_iseq_with_callback(iseq, (callback_func), (name), iseq, (type), (line_no)) + /* add instructions */ #define ADD_SEQ(seq1, seq2) \ APPEND_LIST((seq1), (seq2)) /* add an instruction */ #define ADD_INSN(seq, line_node, insn) \ - ADD_ELEM((seq), (LINK_ELEMENT *) new_insn_body(iseq, (line_node), BIN(insn), 0)) + ADD_ELEM((seq), (LINK_ELEMENT *) new_insn_body(iseq, nd_line(line_node), nd_node_id(line_node), BIN(insn), 0)) + +/* add an instruction with the given line number and node id */ +#define ADD_SYNTHETIC_INSN(seq, line_no, node_id, insn) \ + ADD_ELEM((seq), (LINK_ELEMENT *) new_insn_body(iseq, (line_no), (node_id), BIN(insn), 0)) /* insert an instruction before next */ -#define INSERT_BEFORE_INSN(next, line_node, insn) \ - ELEM_INSERT_PREV(&(next)->link, (LINK_ELEMENT *) new_insn_body(iseq, (line_node), BIN(insn), 0)) +#define INSERT_BEFORE_INSN(next, line_no, node_id, insn) \ + ELEM_INSERT_PREV(&(next)->link, (LINK_ELEMENT *) new_insn_body(iseq, line_no, node_id, BIN(insn), 0)) /* insert an instruction after prev */ -#define INSERT_AFTER_INSN(prev, line_node, insn) \ - ELEM_INSERT_NEXT(&(prev)->link, (LINK_ELEMENT *) new_insn_body(iseq, (line_node), BIN(insn), 0)) +#define INSERT_AFTER_INSN(prev, line_no, node_id, insn) \ + ELEM_INSERT_NEXT(&(prev)->link, (LINK_ELEMENT *) new_insn_body(iseq, line_no, node_id, BIN(insn), 0)) /* add an instruction with some operands (1, 2, 3, 5) */ #define ADD_INSN1(seq, line_node, insn, op1) \ ADD_ELEM((seq), (LINK_ELEMENT *) \ - new_insn_body(iseq, (line_node), BIN(insn), 1, (VALUE)(op1))) + new_insn_body(iseq, nd_line(line_node), nd_node_id(line_node), BIN(insn), 1, (VALUE)(op1))) /* insert an instruction with some operands (1, 2, 3, 5) before next */ -#define INSERT_BEFORE_INSN1(next, line_node, insn, op1) \ +#define INSERT_BEFORE_INSN1(next, line_no, node_id, insn, op1) \ ELEM_INSERT_PREV(&(next)->link, (LINK_ELEMENT *) \ - new_insn_body(iseq, (line_node), BIN(insn), 1, (VALUE)(op1))) + new_insn_body(iseq, line_no, node_id, BIN(insn), 1, (VALUE)(op1))) /* insert an instruction with some operands (1, 2, 3, 5) after prev */ -#define INSERT_AFTER_INSN1(prev, line_node, insn, op1) \ +#define INSERT_AFTER_INSN1(prev, line_no, node_id, insn, op1) \ ELEM_INSERT_NEXT(&(prev)->link, (LINK_ELEMENT *) \ - new_insn_body(iseq, (line_node), BIN(insn), 1, (VALUE)(op1))) + new_insn_body(iseq, line_no, node_id, BIN(insn), 1, (VALUE)(op1))) #define LABEL_REF(label) ((label)->refcnt++) @@ -252,11 +258,11 @@ const ID rb_iseq_shared_exc_local_tbl[] = {idERROR_INFO}; #define ADD_INSN2(seq, line_node, insn, op1, op2) \ ADD_ELEM((seq), (LINK_ELEMENT *) \ - new_insn_body(iseq, (line_node), BIN(insn), 2, (VALUE)(op1), (VALUE)(op2))) + new_insn_body(iseq, nd_line(line_node), nd_node_id(line_node), BIN(insn), 2, (VALUE)(op1), (VALUE)(op2))) #define ADD_INSN3(seq, line_node, insn, op1, op2, op3) \ ADD_ELEM((seq), (LINK_ELEMENT *) \ - new_insn_body(iseq, (line_node), BIN(insn), 3, (VALUE)(op1), (VALUE)(op2), (VALUE)(op3))) + new_insn_body(iseq, nd_line(line_node), nd_node_id(line_node), BIN(insn), 3, (VALUE)(op1), (VALUE)(op2), (VALUE)(op3))) /* Specific Insn factory */ #define ADD_SEND(seq, line_node, id, argc) \ @@ -278,7 +284,7 @@ const ID rb_iseq_shared_exc_local_tbl[] = {idERROR_INFO}; ADD_SEND_R((seq), (line_node), (id), (argc), (block), (VALUE)INT2FIX(VM_CALL_FCALL), NULL) #define ADD_SEND_R(seq, line_node, id, argc, block, flag, keywords) \ - ADD_ELEM((seq), (LINK_ELEMENT *) new_insn_send(iseq, (line_node), (id), (VALUE)(argc), (block), (VALUE)(flag), (keywords))) + ADD_ELEM((seq), (LINK_ELEMENT *) new_insn_send(iseq, nd_line(line_node), nd_node_id(line_node), (id), (VALUE)(argc), (block), (VALUE)(flag), (keywords))) #define ADD_TRACE(seq, event) \ ADD_ELEM((seq), (LINK_ELEMENT *)new_trace_body(iseq, (event), 0)) @@ -333,10 +339,10 @@ static void iseq_add_setlocal(rb_iseq_t *iseq, LINK_ANCHOR *const seq, const NOD (debug_compile("== " desc "\n", \ iseq_compile_each(iseq, (anchor), (node), (popped)))) -#define COMPILE_RECV(anchor, desc, node) \ +#define COMPILE_RECV(anchor, desc, node, recv) \ (private_recv_p(node) ? \ (ADD_INSN(anchor, node, putself), VM_CALL_FCALL) : \ - COMPILE(anchor, desc, node->nd_recv) ? 0 : -1) + COMPILE(anchor, desc, recv) ? 0 : -1) #define OPERAND_AT(insn, idx) \ (((INSN*)(insn))->operands[(idx)]) @@ -432,12 +438,10 @@ do { \ #define NO_CHECK(sub) (void)(sub) #define BEFORE_RETURN -/* leave name uninitialized so that compiler warn if INIT_ANCHOR is - * missing */ #define DECL_ANCHOR(name) \ - LINK_ANCHOR name[1] = {{{ISEQ_ELEMENT_ANCHOR,},}} + LINK_ANCHOR name[1] = {{{ISEQ_ELEMENT_ANCHOR,},&name[0].anchor}} #define INIT_ANCHOR(name) \ - (name->last = &name->anchor) + ((name->last = &name->anchor)->next = NULL) /* re-initialize */ static inline VALUE freeze_hide_obj(VALUE obj) @@ -471,7 +475,7 @@ static void dump_disasm_list(const LINK_ELEMENT *elem); static int insn_data_length(INSN *iobj); static int calc_sp_depth(int depth, INSN *iobj); -static INSN *new_insn_body(rb_iseq_t *iseq, const NODE *const line_node, enum ruby_vminsn_type insn_id, int argc, ...); +static INSN *new_insn_body(rb_iseq_t *iseq, int line_no, int node_id, enum ruby_vminsn_type insn_id, int argc, ...); static LABEL *new_label_body(rb_iseq_t *iseq, long line); static ADJUST *new_adjust_body(rb_iseq_t *iseq, LABEL *label, int line); static TRACE *new_trace_body(rb_iseq_t *iseq, rb_event_flag_t event, long data); @@ -483,7 +487,7 @@ static int iseq_setup_insn(rb_iseq_t *iseq, LINK_ANCHOR *const anchor); static int iseq_optimize(rb_iseq_t *iseq, LINK_ANCHOR *const anchor); static int iseq_insns_unification(rb_iseq_t *iseq, LINK_ANCHOR *const anchor); -static int iseq_set_local_table(rb_iseq_t *iseq, const rb_ast_id_table_t *tbl); +static int iseq_set_local_table(rb_iseq_t *iseq, const rb_ast_id_table_t *tbl, const NODE *const node_args); static int iseq_set_exception_local_table(rb_iseq_t *iseq); static int iseq_set_arguments(rb_iseq_t *iseq, LINK_ANCHOR *const anchor, const NODE *const node); @@ -491,7 +495,7 @@ static int iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *const anchor); static int iseq_set_exception_table(rb_iseq_t *iseq); static int iseq_set_optargs_table(rb_iseq_t *iseq); -static int compile_defined_expr(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, VALUE needstr); +static int compile_defined_expr(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, VALUE needstr, bool ignore); static int compile_hash(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int method_call_keywords, int popped); /* @@ -605,13 +609,28 @@ branch_coverage_valid_p(rb_iseq_t *iseq, int first_line) return 1; } +#define PTR2NUM(x) (rb_int2inum((intptr_t)(void *)(x))) + static VALUE -decl_branch_base(rb_iseq_t *iseq, const NODE *node, const char *type) +setup_branch(const rb_code_location_t *loc, const char *type, VALUE structure, VALUE key) { - const int first_lineno = nd_first_lineno(node), first_column = nd_first_column(node); - const int last_lineno = nd_last_lineno(node), last_column = nd_last_column(node); + const int first_lineno = loc->beg_pos.lineno, first_column = loc->beg_pos.column; + const int last_lineno = loc->end_pos.lineno, last_column = loc->end_pos.column; + VALUE branch = rb_ary_hidden_new(6); - if (!branch_coverage_valid_p(iseq, first_lineno)) return Qundef; + rb_hash_aset(structure, key, branch); + rb_ary_push(branch, ID2SYM(rb_intern(type))); + rb_ary_push(branch, INT2FIX(first_lineno)); + rb_ary_push(branch, INT2FIX(first_column)); + rb_ary_push(branch, INT2FIX(last_lineno)); + rb_ary_push(branch, INT2FIX(last_column)); + return branch; +} + +static VALUE +decl_branch_base(rb_iseq_t *iseq, VALUE key, const rb_code_location_t *loc, const char *type) +{ + if (!branch_coverage_valid_p(iseq, loc->beg_pos.lineno)) return Qundef; /* * if !structure[node] @@ -622,18 +641,11 @@ decl_branch_base(rb_iseq_t *iseq, const NODE *node, const char *type) */ VALUE structure = RARRAY_AREF(ISEQ_BRANCH_COVERAGE(iseq), 0); - VALUE key = (VALUE)node | 1; // FIXNUM for hash key VALUE branch_base = rb_hash_aref(structure, key); VALUE branches; if (NIL_P(branch_base)) { - branch_base = rb_ary_hidden_new(6); - rb_hash_aset(structure, key, branch_base); - rb_ary_push(branch_base, ID2SYM(rb_intern(type))); - rb_ary_push(branch_base, INT2FIX(first_lineno)); - rb_ary_push(branch_base, INT2FIX(first_column)); - rb_ary_push(branch_base, INT2FIX(last_lineno)); - rb_ary_push(branch_base, INT2FIX(last_column)); + branch_base = setup_branch(loc, type, structure, key); branches = rb_hash_new(); rb_obj_hide(branches); rb_ary_push(branch_base, branches); @@ -655,12 +667,9 @@ generate_dummy_line_node(int lineno, int node_id) } static void -add_trace_branch_coverage(rb_iseq_t *iseq, LINK_ANCHOR *const seq, const NODE *node, int branch_id, const char *type, VALUE branches) +add_trace_branch_coverage(rb_iseq_t *iseq, LINK_ANCHOR *const seq, const rb_code_location_t *loc, int node_id, int branch_id, const char *type, VALUE branches) { - const int first_lineno = nd_first_lineno(node), first_column = nd_first_column(node); - const int last_lineno = nd_last_lineno(node), last_column = nd_last_column(node); - - if (!branch_coverage_valid_p(iseq, first_lineno)) return; + if (!branch_coverage_valid_p(iseq, loc->beg_pos.lineno)) return; /* * if !branches[branch_id] @@ -675,13 +684,7 @@ add_trace_branch_coverage(rb_iseq_t *iseq, LINK_ANCHOR *const seq, const NODE *n long counter_idx; if (NIL_P(branch)) { - branch = rb_ary_hidden_new(6); - rb_hash_aset(branches, key, branch); - rb_ary_push(branch, ID2SYM(rb_intern(type))); - rb_ary_push(branch, INT2FIX(first_lineno)); - rb_ary_push(branch, INT2FIX(first_column)); - rb_ary_push(branch, INT2FIX(last_lineno)); - rb_ary_push(branch, INT2FIX(last_column)); + branch = setup_branch(loc, type, branches, key); VALUE counters = RARRAY_AREF(ISEQ_BRANCH_COVERAGE(iseq), 1); counter_idx = RARRAY_LEN(counters); rb_ary_push(branch, LONG2FIX(counter_idx)); @@ -692,9 +695,7 @@ add_trace_branch_coverage(rb_iseq_t *iseq, LINK_ANCHOR *const seq, const NODE *n } ADD_TRACE_WITH_DATA(seq, RUBY_EVENT_COVERAGE_BRANCH, counter_idx); - - NODE dummy_line_node = generate_dummy_line_node(last_lineno, nd_node_id(node)); - ADD_INSN(seq, &dummy_line_node, nop); + ADD_SYNTHETIC_INSN(seq, loc->end_pos.lineno, node_id, nop); } #define ISEQ_LAST_LINE(iseq) (ISEQ_COMPILE_DATA(iseq)->last_line) @@ -721,6 +722,129 @@ validate_labels(rb_iseq_t *iseq, st_table *labels_table) st_free_table(labels_table); } +static NODE * +get_nd_recv(const NODE *node) +{ + switch (nd_type(node)) { + case NODE_CALL: + return RNODE_CALL(node)->nd_recv; + case NODE_OPCALL: + return RNODE_OPCALL(node)->nd_recv; + case NODE_FCALL: + return 0; + case NODE_QCALL: + return RNODE_QCALL(node)->nd_recv; + case NODE_VCALL: + return 0; + case NODE_ATTRASGN: + return RNODE_ATTRASGN(node)->nd_recv; + case NODE_OP_ASGN1: + return RNODE_OP_ASGN1(node)->nd_recv; + case NODE_OP_ASGN2: + return RNODE_OP_ASGN2(node)->nd_recv; + default: + rb_bug("unexpected node: %s", ruby_node_name(nd_type(node))); + } +} + +static ID +get_node_call_nd_mid(const NODE *node) +{ + switch (nd_type(node)) { + case NODE_CALL: + return RNODE_CALL(node)->nd_mid; + case NODE_OPCALL: + return RNODE_OPCALL(node)->nd_mid; + case NODE_FCALL: + return RNODE_FCALL(node)->nd_mid; + case NODE_QCALL: + return RNODE_QCALL(node)->nd_mid; + case NODE_VCALL: + return RNODE_VCALL(node)->nd_mid; + case NODE_ATTRASGN: + return RNODE_ATTRASGN(node)->nd_mid; + default: + rb_bug("unexpected node: %s", ruby_node_name(nd_type(node))); + } +} + +static NODE * +get_nd_args(const NODE *node) +{ + switch (nd_type(node)) { + case NODE_CALL: + return RNODE_CALL(node)->nd_args; + case NODE_OPCALL: + return RNODE_OPCALL(node)->nd_args; + case NODE_FCALL: + return RNODE_FCALL(node)->nd_args; + case NODE_QCALL: + return RNODE_QCALL(node)->nd_args; + case NODE_VCALL: + return 0; + case NODE_ATTRASGN: + return RNODE_ATTRASGN(node)->nd_args; + default: + rb_bug("unexpected node: %s", ruby_node_name(nd_type(node))); + } +} + +static ID +get_node_colon_nd_mid(const NODE *node) +{ + switch (nd_type(node)) { + case NODE_COLON2: + return RNODE_COLON2(node)->nd_mid; + case NODE_COLON3: + return RNODE_COLON3(node)->nd_mid; + default: + rb_bug("unexpected node: %s", ruby_node_name(nd_type(node))); + } +} + +static ID +get_nd_vid(const NODE *node) +{ + switch (nd_type(node)) { + case NODE_LASGN: + return RNODE_LASGN(node)->nd_vid; + case NODE_DASGN: + return RNODE_DASGN(node)->nd_vid; + case NODE_IASGN: + return RNODE_IASGN(node)->nd_vid; + case NODE_CVASGN: + return RNODE_CVASGN(node)->nd_vid; + default: + rb_bug("unexpected node: %s", ruby_node_name(nd_type(node))); + } +} + +static NODE * +get_nd_value(const NODE *node) +{ + switch (nd_type(node)) { + case NODE_LASGN: + return RNODE_LASGN(node)->nd_value; + case NODE_DASGN: + return RNODE_DASGN(node)->nd_value; + default: + rb_bug("unexpected node: %s", ruby_node_name(nd_type(node))); + } +} + +static VALUE +get_string_value(const NODE *node) +{ + switch (nd_type(node)) { + case NODE_STR: + return rb_node_str_string_val(node); + case NODE_FILE: + return rb_node_file_path_val(node); + default: + rb_bug("unexpected node: %s", ruby_node_name(nd_type(node))); + } +} + VALUE rb_iseq_compile_callback(rb_iseq_t *iseq, const struct rb_iseq_new_with_callback_callback_func * ifunc) { @@ -729,32 +853,29 @@ rb_iseq_compile_callback(rb_iseq_t *iseq, const struct rb_iseq_new_with_callback (*ifunc->func)(iseq, ret, ifunc->data); - NODE dummy_line_node = generate_dummy_line_node(ISEQ_COMPILE_DATA(iseq)->last_line, -1); - ADD_INSN(ret, &dummy_line_node, leave); + ADD_SYNTHETIC_INSN(ret, ISEQ_COMPILE_DATA(iseq)->last_line, -1, leave); CHECK(iseq_setup_insn(iseq, ret)); return iseq_setup(iseq, ret); } +static bool drop_unreachable_return(LINK_ANCHOR *ret); + VALUE rb_iseq_compile_node(rb_iseq_t *iseq, const NODE *node) { DECL_ANCHOR(ret); INIT_ANCHOR(ret); - if (IMEMO_TYPE_P(node, imemo_ifunc)) { - rb_raise(rb_eArgError, "unexpected imemo_ifunc"); - } - if (node == 0) { NO_CHECK(COMPILE(ret, "nil", node)); - iseq_set_local_table(iseq, 0); + iseq_set_local_table(iseq, 0, 0); } /* assume node is T_NODE */ else if (nd_type_p(node, NODE_SCOPE)) { /* iseq type of top, method, class, block */ - iseq_set_local_table(iseq, node->nd_tbl); - iseq_set_arguments(iseq, ret, node->nd_args); + iseq_set_local_table(iseq, RNODE_SCOPE(node)->nd_tbl, (NODE *)RNODE_SCOPE(node)->nd_args); + iseq_set_arguments(iseq, ret, (NODE *)RNODE_SCOPE(node)->nd_args); switch (ISEQ_BODY(iseq)->type) { case ISEQ_TYPE_BLOCK: @@ -766,10 +887,9 @@ rb_iseq_compile_node(rb_iseq_t *iseq, const NODE *node) end->rescued = LABEL_RESCUE_END; ADD_TRACE(ret, RUBY_EVENT_B_CALL); - NODE dummy_line_node = generate_dummy_line_node(ISEQ_BODY(iseq)->location.first_lineno, -1); - ADD_INSN (ret, &dummy_line_node, nop); + ADD_SYNTHETIC_INSN(ret, ISEQ_BODY(iseq)->location.first_lineno, -1, nop); ADD_LABEL(ret, start); - CHECK(COMPILE(ret, "block body", node->nd_body)); + CHECK(COMPILE(ret, "block body", RNODE_SCOPE(node)->nd_body)); ADD_LABEL(ret, end); ADD_TRACE(ret, RUBY_EVENT_B_RETURN); ISEQ_COMPILE_DATA(iseq)->last_line = ISEQ_BODY(iseq)->location.code_location.end_pos.lineno; @@ -782,23 +902,23 @@ rb_iseq_compile_node(rb_iseq_t *iseq, const NODE *node) case ISEQ_TYPE_CLASS: { ADD_TRACE(ret, RUBY_EVENT_CLASS); - CHECK(COMPILE(ret, "scoped node", node->nd_body)); + CHECK(COMPILE(ret, "scoped node", RNODE_SCOPE(node)->nd_body)); ADD_TRACE(ret, RUBY_EVENT_END); ISEQ_COMPILE_DATA(iseq)->last_line = nd_line(node); break; } case ISEQ_TYPE_METHOD: { - ISEQ_COMPILE_DATA(iseq)->root_node = node->nd_body; + ISEQ_COMPILE_DATA(iseq)->root_node = RNODE_SCOPE(node)->nd_body; ADD_TRACE(ret, RUBY_EVENT_CALL); - CHECK(COMPILE(ret, "scoped node", node->nd_body)); - ISEQ_COMPILE_DATA(iseq)->root_node = node->nd_body; + CHECK(COMPILE(ret, "scoped node", RNODE_SCOPE(node)->nd_body)); + ISEQ_COMPILE_DATA(iseq)->root_node = RNODE_SCOPE(node)->nd_body; ADD_TRACE(ret, RUBY_EVENT_RETURN); ISEQ_COMPILE_DATA(iseq)->last_line = nd_line(node); break; } default: { - CHECK(COMPILE(ret, "scoped node", node->nd_body)); + CHECK(COMPILE(ret, "scoped node", RNODE_SCOPE(node)->nd_body)); break; } } @@ -840,9 +960,8 @@ rb_iseq_compile_node(rb_iseq_t *iseq, const NODE *node) ADD_GETLOCAL(ret, &dummy_line_node, LVAR_ERRINFO, 0); ADD_INSN1(ret, &dummy_line_node, throw, INT2FIX(0) /* continue throw */ ); } - else { - NODE dummy_line_node = generate_dummy_line_node(ISEQ_COMPILE_DATA(iseq)->last_line, -1); - ADD_INSN(ret, &dummy_line_node, leave); + else if (!drop_unreachable_return(ret)) { + ADD_SYNTHETIC_INSN(ret, ISEQ_COMPILE_DATA(iseq)->last_line, -1, leave); } #if OPT_SUPPORT_JOKE @@ -856,45 +975,6 @@ rb_iseq_compile_node(rb_iseq_t *iseq, const NODE *node) return iseq_setup(iseq, ret); } -typedef struct yp_compile_context { - yp_parser_t *parser; - struct yp_compile_context *previous; - ID *constants; - st_table *index_lookup_table; -} yp_compile_context_t; - -static VALUE rb_translate_yarp(rb_iseq_t *iseq, const yp_node_t *node, LINK_ANCHOR *const ret, yp_compile_context_t *compile_context); - -VALUE -rb_iseq_compile_yarp_node(rb_iseq_t * iseq, const yp_node_t *yarp_pointer, yp_parser_t *parser) -{ - DECL_ANCHOR(ret); - INIT_ANCHOR(ret); - - ID *constants = calloc(parser->constant_pool.size, sizeof(ID)); - rb_encoding *encoding = rb_enc_find(parser->encoding.name); - - for (size_t index = 0; index < parser->constant_pool.capacity; index++) { - yp_constant_t constant = parser->constant_pool.constants[index]; - - if (constant.id != 0) { - constants[constant.id - 1] = rb_intern3((const char *) constant.start, constant.length, encoding); - } - } - - yp_compile_context_t compile_context = { - .parser = parser, - .previous = NULL, - .constants = constants - }; - - CHECK(rb_translate_yarp(iseq, yarp_pointer, ret, &compile_context)); - free(constants); - - CHECK(iseq_setup_insn(iseq, ret)); - return iseq_setup(iseq, ret); -} - static int rb_iseq_translate_threaded_code(rb_iseq_t *iseq) { @@ -911,6 +991,12 @@ rb_iseq_translate_threaded_code(rb_iseq_t *iseq) } FL_SET((VALUE)iseq, ISEQ_TRANSLATED); #endif + +#if USE_YJIT + rb_yjit_live_iseq_count++; + rb_yjit_iseq_alloc_count++; +#endif + return COMPILE_OK; } @@ -1204,10 +1290,15 @@ static void APPEND_LIST(ISEQ_ARG_DECLARE LINK_ANCHOR *const anc1, LINK_ANCHOR *const anc2) { if (anc2->anchor.next) { + /* LINK_ANCHOR must not loop */ + RUBY_ASSERT(anc2->last != &anc2->anchor); anc1->last->next = anc2->anchor.next; anc2->anchor.next->prev = anc1->last; anc1->last = anc2->last; } + else { + RUBY_ASSERT(anc2->last == &anc2->anchor); + } verify_list("append", anc1); } #if CPDEBUG < 0 @@ -1267,6 +1358,7 @@ new_label_body(rb_iseq_t *iseq, long line) labelobj->set = 0; labelobj->rescued = LABEL_RESCUE_NONE; labelobj->unremovable = 0; + labelobj->position = -1; return labelobj; } @@ -1303,14 +1395,13 @@ iseq_insn_each_markable_object(INSN *insn, void (*func)(VALUE *, VALUE), VALUE d } static void -iseq_insn_each_object_write_barrier(VALUE *obj_ptr, VALUE iseq) +iseq_insn_each_object_write_barrier(VALUE * obj, VALUE iseq) { - RB_OBJ_WRITTEN(iseq, Qundef, *obj_ptr); + RB_OBJ_WRITTEN(iseq, Qundef, *obj); } static INSN * -new_insn_core(rb_iseq_t *iseq, const NODE *line_node, - int insn_id, int argc, VALUE *argv) +new_insn_core(rb_iseq_t *iseq, int line_no, int node_id, int insn_id, int argc, VALUE *argv) { INSN *iobj = compile_data_alloc_insn(iseq); @@ -1319,8 +1410,8 @@ new_insn_core(rb_iseq_t *iseq, const NODE *line_node, iobj->link.type = ISEQ_ELEMENT_INSN; iobj->link.next = 0; iobj->insn_id = insn_id; - iobj->insn_info.line_no = nd_line(line_node); - iobj->insn_info.node_id = nd_node_id(line_node); + iobj->insn_info.line_no = line_no; + iobj->insn_info.node_id = node_id; iobj->insn_info.events = 0; iobj->operands = argv; iobj->operand_size = argc; @@ -1332,7 +1423,7 @@ new_insn_core(rb_iseq_t *iseq, const NODE *line_node, } static INSN * -new_insn_body(rb_iseq_t *iseq, const NODE *const line_node, enum ruby_vminsn_type insn_id, int argc, ...) +new_insn_body(rb_iseq_t *iseq, int line_no, int node_id, enum ruby_vminsn_type insn_id, int argc, ...) { VALUE *operands = 0; va_list argv; @@ -1346,7 +1437,7 @@ new_insn_body(rb_iseq_t *iseq, const NODE *const line_node, enum ruby_vminsn_typ } va_end(argv); } - return new_insn_core(iseq, line_node, insn_id, argc, operands); + return new_insn_core(iseq, line_no, node_id, insn_id, argc, operands); } static const struct rb_callinfo * @@ -1354,16 +1445,16 @@ new_callinfo(rb_iseq_t *iseq, ID mid, int argc, unsigned int flag, struct rb_cal { VM_ASSERT(argc >= 0); - if (!(flag & (VM_CALL_ARGS_SPLAT | VM_CALL_ARGS_BLOCKARG | VM_CALL_KW_SPLAT)) && - kw_arg == NULL && !has_blockiseq) { - flag |= VM_CALL_ARGS_SIMPLE; - } - if (kw_arg) { flag |= VM_CALL_KWARG; argc += kw_arg->keyword_len; } + if (!(flag & (VM_CALL_ARGS_SPLAT | VM_CALL_ARGS_BLOCKARG | VM_CALL_KWARG | VM_CALL_KW_SPLAT | VM_CALL_FORWARDING)) + && !has_blockiseq) { + flag |= VM_CALL_ARGS_SIMPLE; + } + ISEQ_BODY(iseq)->ci_size++; const struct rb_callinfo *ci = vm_ci_new(mid, flag, argc, kw_arg); RB_OBJ_WRITTEN(iseq, Qundef, ci); @@ -1371,7 +1462,7 @@ new_callinfo(rb_iseq_t *iseq, ID mid, int argc, unsigned int flag, struct rb_cal } static INSN * -new_insn_send(rb_iseq_t *iseq, const NODE *const line_node, ID id, VALUE argc, const rb_iseq_t *blockiseq, VALUE flag, struct rb_callinfo_kwarg *keywords) +new_insn_send(rb_iseq_t *iseq, int line_no, int node_id, ID id, VALUE argc, const rb_iseq_t *blockiseq, VALUE flag, struct rb_callinfo_kwarg *keywords) { VALUE *operands = compile_data_calloc2(iseq, sizeof(VALUE), 2); VALUE ci = (VALUE)new_callinfo(iseq, id, FIX2INT(argc), FIX2INT(flag), keywords, blockiseq != NULL); @@ -1380,7 +1471,16 @@ new_insn_send(rb_iseq_t *iseq, const NODE *const line_node, ID id, VALUE argc, c if (blockiseq) { RB_OBJ_WRITTEN(iseq, Qundef, blockiseq); } - INSN *insn = new_insn_core(iseq, line_node, BIN(send), 2, operands); + + INSN *insn; + + if (vm_ci_flag((struct rb_callinfo *)ci) & VM_CALL_FORWARDING) { + insn = new_insn_core(iseq, line_no, node_id, BIN(sendforward), 2, operands); + } + else { + insn = new_insn_core(iseq, line_no, node_id, BIN(send), 2, operands); + } + RB_OBJ_WRITTEN(iseq, Qundef, ci); RB_GC_GUARD(ci); return insn; @@ -1391,20 +1491,16 @@ new_child_iseq(rb_iseq_t *iseq, const NODE *const node, VALUE name, const rb_iseq_t *parent, enum rb_iseq_type type, int line_no) { rb_iseq_t *ret_iseq; - rb_ast_body_t ast; - - ast.root = node; - ast.frozen_string_literal = -1; - ast.coverage_enabled = -1; - ast.script_lines = ISEQ_BODY(iseq)->variable.script_lines; + VALUE ast_value = rb_ruby_ast_new(node); debugs("[new_child_iseq]> ---------------------------------------\n"); int isolated_depth = ISEQ_COMPILE_DATA(iseq)->isolated_depth; - ret_iseq = rb_iseq_new_with_opt(&ast, name, + ret_iseq = rb_iseq_new_with_opt(ast_value, name, rb_iseq_path(iseq), rb_iseq_realpath(iseq), line_no, parent, isolated_depth ? isolated_depth + 1 : 0, - type, ISEQ_COMPILE_DATA(iseq)->option); + type, ISEQ_COMPILE_DATA(iseq)->option, + ISEQ_BODY(iseq)->variable.script_lines); debugs("[new_child_iseq]< ---------------------------------------\n"); return ret_iseq; } @@ -1499,14 +1595,15 @@ iseq_insert_nop_between_end_and_cont(rb_iseq_t *iseq) for (e = end; e && (IS_LABEL(e) || IS_TRACE(e)); e = e->next) { if (e == cont) { - NODE dummy_line_node = generate_dummy_line_node(0, -1); - INSN *nop = new_insn_core(iseq, &dummy_line_node, BIN(nop), 0, 0); + INSN *nop = new_insn_core(iseq, 0, -1, BIN(nop), 0, 0); ELEM_INSERT_NEXT(end, &nop->link); break; } } } } + + RB_GC_GUARD(catch_table_ary); } static int @@ -1703,7 +1800,7 @@ access_outer_variables(const rb_iseq_t *iseq, int level, ID id, bool write) COMPILE_ERROR(iseq, ISEQ_LAST_LINE(iseq), "can not yield from isolated Proc"); } else { - COMPILE_ERROR(iseq, ISEQ_LAST_LINE(iseq), "can not access variable `%s' from isolated Proc", rb_id2name(id)); + COMPILE_ERROR(iseq, ISEQ_LAST_LINE(iseq), "can not access variable '%s' from isolated Proc", rb_id2name(id)); } } @@ -1808,7 +1905,7 @@ static int iseq_set_arguments_keywords(rb_iseq_t *iseq, LINK_ANCHOR *const optargs, const struct rb_args_info *args, int arg_size) { - const NODE *node = args->kw_args; + const rb_node_kw_arg_t *node = args->kw_args; struct rb_iseq_constant_body *const body = ISEQ_BODY(iseq); struct rb_iseq_param_keyword *keyword; const VALUE default_values = rb_ary_hidden_new(1); @@ -1827,7 +1924,7 @@ iseq_set_arguments_keywords(rb_iseq_t *iseq, LINK_ANCHOR *const optargs, node = args->kw_args; while (node) { - const NODE *val_node = node->nd_body->nd_value; + const NODE *val_node = get_nd_value(node->nd_body); VALUE dv; if (val_node == NODE_SPECIAL_REQUIRED_KEYWORD) { @@ -1835,8 +1932,29 @@ iseq_set_arguments_keywords(rb_iseq_t *iseq, LINK_ANCHOR *const optargs, } else { switch (nd_type(val_node)) { - case NODE_LIT: - dv = val_node->nd_lit; + case NODE_SYM: + dv = rb_node_sym_string_val(val_node); + break; + case NODE_REGX: + dv = rb_node_regx_string_val(val_node); + break; + case NODE_LINE: + dv = rb_node_line_lineno_val(val_node); + break; + case NODE_INTEGER: + dv = rb_node_integer_literal_val(val_node); + break; + case NODE_FLOAT: + dv = rb_node_float_literal_val(val_node); + break; + case NODE_RATIONAL: + dv = rb_node_rational_literal_val(val_node); + break; + case NODE_IMAGINARY: + dv = rb_node_imaginary_literal_val(val_node); + break; + case NODE_ENCODING: + dv = rb_node_encoding_val(val_node); break; case NODE_NIL: dv = Qnil; @@ -1848,7 +1966,7 @@ iseq_set_arguments_keywords(rb_iseq_t *iseq, LINK_ANCHOR *const optargs, dv = Qfalse; break; default: - NO_CHECK(COMPILE_POPPED(optargs, "kwarg", node)); /* nd_type_p(node, NODE_KW_ARG) */ + NO_CHECK(COMPILE_POPPED(optargs, "kwarg", RNODE(node))); /* nd_type_p(node, NODE_KW_ARG) */ dv = complex_mark; } @@ -1861,23 +1979,23 @@ iseq_set_arguments_keywords(rb_iseq_t *iseq, LINK_ANCHOR *const optargs, keyword->num = kw; - if (args->kw_rest_arg->nd_vid != 0) { + if (RNODE_DVAR(args->kw_rest_arg)->nd_vid != 0) { + ID kw_id = ISEQ_BODY(iseq)->local_table[arg_size]; keyword->rest_start = arg_size++; body->param.flags.has_kwrest = TRUE; + + if (kw_id == idPow) body->param.flags.anon_kwrest = TRUE; } keyword->required_num = rkw; keyword->table = &body->local_table[keyword->bits_start - keyword->num]; - { + if (RARRAY_LEN(default_values)) { VALUE *dvs = ALLOC_N(VALUE, RARRAY_LEN(default_values)); for (i = 0; i < RARRAY_LEN(default_values); i++) { VALUE dv = RARRAY_AREF(default_values, i); if (dv == complex_mark) dv = Qundef; - if (!SPECIAL_CONST_P(dv)) { - RB_OBJ_WRITTEN(iseq, Qundef, dv); - } - dvs[i] = dv; + RB_OBJ_WRITE(iseq, &dvs[i], dv); } keyword->default_values = dvs; @@ -1885,6 +2003,22 @@ iseq_set_arguments_keywords(rb_iseq_t *iseq, LINK_ANCHOR *const optargs, return arg_size; } +static void +iseq_set_use_block(rb_iseq_t *iseq) +{ + struct rb_iseq_constant_body *const body = ISEQ_BODY(iseq); + if (!body->param.flags.use_block) { + body->param.flags.use_block = 1; + + rb_vm_t *vm = GET_VM(); + + if (!rb_warning_category_enabled_p(RB_WARN_CATEGORY_STRICT_UNUSED_BLOCK)) { + st_data_t key = (st_data_t)rb_intern_str(body->location.label); // String -> ID + set_insert(vm->unused_block_warning_table, key); + } + } +} + static int iseq_set_arguments(rb_iseq_t *iseq, LINK_ANCHOR *const optargs, const NODE *const node_args) { @@ -1892,7 +2026,7 @@ iseq_set_arguments(rb_iseq_t *iseq, LINK_ANCHOR *const optargs, const NODE *cons if (node_args) { struct rb_iseq_constant_body *const body = ISEQ_BODY(iseq); - struct rb_args_info *args = node_args->nd_ainfo; + struct rb_args_info *args = &RNODE_ARGS(node_args)->nd_ainfo; ID rest_id = 0; int last_comma = 0; ID block_id = 0; @@ -1912,15 +2046,22 @@ iseq_set_arguments(rb_iseq_t *iseq, LINK_ANCHOR *const optargs, const NODE *cons } block_id = args->block_arg; + bool optimized_forward = (args->forwarding && args->pre_args_num == 0 && !args->opt_args); + + if (optimized_forward) { + rest_id = 0; + block_id = 0; + } + if (args->opt_args) { - const NODE *node = args->opt_args; + const rb_node_opt_arg_t *node = args->opt_args; LABEL *label; VALUE labels = rb_ary_hidden_new(1); VALUE *opt_table; int i = 0, j; while (node) { - label = NEW_LABEL(nd_line(node)); + label = NEW_LABEL(nd_line(RNODE(node))); rb_ary_push(labels, (VALUE)label | 1); ADD_LABEL(optargs, label); NO_CHECK(COMPILE_POPPED(optargs, "optarg", node->nd_body)); @@ -1950,7 +2091,8 @@ iseq_set_arguments(rb_iseq_t *iseq, LINK_ANCHOR *const optargs, const NODE *cons if (rest_id) { body->param.rest_start = arg_size++; body->param.flags.has_rest = TRUE; - assert(body->param.rest_start != -1); + if (rest_id == '*') body->param.flags.anon_rest = TRUE; + RUBY_ASSERT(body->param.rest_start != -1); } if (args->first_post_arg) { @@ -1967,11 +2109,16 @@ iseq_set_arguments(rb_iseq_t *iseq, LINK_ANCHOR *const optargs, const NODE *cons if (args->kw_args) { arg_size = iseq_set_arguments_keywords(iseq, optargs, args, arg_size); } - else if (args->kw_rest_arg) { + else if (args->kw_rest_arg && !optimized_forward) { + ID kw_id = ISEQ_BODY(iseq)->local_table[arg_size]; struct rb_iseq_param_keyword *keyword = ZALLOC_N(struct rb_iseq_param_keyword, 1); keyword->rest_start = arg_size++; body->param.keyword = keyword; body->param.flags.has_kwrest = TRUE; + + static ID anon_kwrest = 0; + if (!anon_kwrest) anon_kwrest = rb_intern("**"); + if (kw_id == anon_kwrest) body->param.flags.anon_kwrest = TRUE; } else if (args->no_kwarg) { body->param.flags.accepts_no_kwarg = TRUE; @@ -1980,6 +2127,14 @@ iseq_set_arguments(rb_iseq_t *iseq, LINK_ANCHOR *const optargs, const NODE *cons if (block_id) { body->param.block_start = arg_size++; body->param.flags.has_block = TRUE; + iseq_set_use_block(iseq); + } + + // Only optimize specifically methods like this: `foo(...)` + if (optimized_forward) { + body->param.flags.use_block = 1; + body->param.flags.forwardable = TRUE; + arg_size = 1; } iseq_calc_param_size(iseq); @@ -2011,13 +2166,27 @@ iseq_set_arguments(rb_iseq_t *iseq, LINK_ANCHOR *const optargs, const NODE *cons } static int -iseq_set_local_table(rb_iseq_t *iseq, const rb_ast_id_table_t *tbl) +iseq_set_local_table(rb_iseq_t *iseq, const rb_ast_id_table_t *tbl, const NODE *const node_args) { unsigned int size = tbl ? tbl->size : 0; + unsigned int offset = 0; + + if (node_args) { + struct rb_args_info *args = &RNODE_ARGS(node_args)->nd_ainfo; + + // If we have a function that only has `...` as the parameter, + // then its local table should only be `...` + // FIXME: I think this should be fixed in the AST rather than special case here. + if (args->forwarding && args->pre_args_num == 0 && !args->opt_args) { + CHECK(size >= 3); + size -= 3; + offset += 3; + } + } if (size > 0) { - ID *ids = (ID *)ALLOC_N(ID, size); - MEMCPY(ids, tbl->ids, ID, size); + ID *ids = ALLOC_N(ID, size); + MEMCPY(ids, tbl->ids + offset, ID, size); ISEQ_BODY(iseq)->local_table = ids; } ISEQ_BODY(iseq)->local_table_size = size; @@ -2301,6 +2470,7 @@ add_adjust_info(struct iseq_insn_info_entry *insns_info, unsigned int *positions int insns_info_index, int code_index, const ADJUST *adjust) { insns_info[insns_info_index].line_no = adjust->line_no; + insns_info[insns_info_index].node_id = -1; insns_info[insns_info_index].events = 0; positions[insns_info_index] = code_index; return TRUE; @@ -2312,7 +2482,7 @@ array_to_idlist(VALUE arr) RUBY_ASSERT(RB_TYPE_P(arr, T_ARRAY)); long size = RARRAY_LEN(arr); ID *ids = (ID *)ALLOC_N(ID, size + 1); - for (int i = 0; i < size; i++) { + for (long i = 0; i < size; i++) { VALUE sym = RARRAY_AREF(arr, i); ids[i] = SYM2ID(sym); } @@ -2421,8 +2591,19 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *const anchor) generated_iseq = ALLOC_N(VALUE, code_index); insns_info = ALLOC_N(struct iseq_insn_info_entry, insn_num); positions = ALLOC_N(unsigned int, insn_num); - body->is_entries = ZALLOC_N(union iseq_inline_storage_entry, ISEQ_IS_SIZE(body)); - body->call_data = ZALLOC_N(struct rb_call_data, body->ci_size); + if (ISEQ_IS_SIZE(body)) { + body->is_entries = ZALLOC_N(union iseq_inline_storage_entry, ISEQ_IS_SIZE(body)); + } + else { + body->is_entries = NULL; + } + + if (body->ci_size) { + body->call_data = ZALLOC_N(struct rb_call_data, body->ci_size); + } + else { + body->call_data = NULL; + } ISEQ_COMPILE_DATA(iseq)->ci_index = 0; // Calculate the bitmask buffer size. @@ -2433,16 +2614,21 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *const anchor) iseq_bits_t * mark_offset_bits; int code_size = code_index; - iseq_bits_t tmp[1] = {0}; bool needs_bitmap = false; if (ISEQ_MBITS_BUFLEN(code_index) == 1) { - mark_offset_bits = tmp; + mark_offset_bits = &ISEQ_COMPILE_DATA(iseq)->mark_bits.single; + ISEQ_COMPILE_DATA(iseq)->is_single_mark_bit = true; } else { mark_offset_bits = ZALLOC_N(iseq_bits_t, ISEQ_MBITS_BUFLEN(code_index)); + ISEQ_COMPILE_DATA(iseq)->mark_bits.list = mark_offset_bits; + ISEQ_COMPILE_DATA(iseq)->is_single_mark_bit = false; } + ISEQ_COMPILE_DATA(iseq)->iseq_encoded = (void *)generated_iseq; + ISEQ_COMPILE_DATA(iseq)->iseq_size = code_index; + list = FIRST_ELEMENT(anchor); insns_info_index = code_index = sp = 0; @@ -2557,11 +2743,11 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *const anchor) break; } - case TS_CALLDATA: + case TS_CALLDATA: { const struct rb_callinfo *source_ci = (const struct rb_callinfo *)operands[j]; + RUBY_ASSERT(ISEQ_COMPILE_DATA(iseq)->ci_index <= body->ci_size); struct rb_call_data *cd = &body->call_data[ISEQ_COMPILE_DATA(iseq)->ci_index++]; - assert(ISEQ_COMPILE_DATA(iseq)->ci_index <= body->ci_size); cd->ci = source_ci; cd->cc = vm_cc_empty(); generated_iseq[code_index + 1 + j] = (VALUE)cd; @@ -2653,15 +2839,16 @@ iseq_set_sequence(rb_iseq_t *iseq, LINK_ANCHOR *const anchor) body->iseq_size = code_index; body->stack_max = stack_max; - if (ISEQ_MBITS_BUFLEN(body->iseq_size) == 1) { - body->mark_bits.single = mark_offset_bits[0]; + if (ISEQ_COMPILE_DATA(iseq)->is_single_mark_bit) { + body->mark_bits.single = ISEQ_COMPILE_DATA(iseq)->mark_bits.single; } else { if (needs_bitmap) { body->mark_bits.list = mark_offset_bits; } else { - body->mark_bits.list = 0; + body->mark_bits.list = NULL; + ISEQ_COMPILE_DATA(iseq)->mark_bits.list = NULL; ruby_xfree(mark_offset_bits); } } @@ -2699,20 +2886,27 @@ iseq_set_exception_table(rb_iseq_t *iseq) struct iseq_catch_table_entry *entry; ISEQ_BODY(iseq)->catch_table = NULL; - if (NIL_P(ISEQ_COMPILE_DATA(iseq)->catch_table_ary)) return COMPILE_OK; - tlen = (int)RARRAY_LEN(ISEQ_COMPILE_DATA(iseq)->catch_table_ary); - tptr = RARRAY_CONST_PTR(ISEQ_COMPILE_DATA(iseq)->catch_table_ary); + + VALUE catch_table_ary = ISEQ_COMPILE_DATA(iseq)->catch_table_ary; + if (NIL_P(catch_table_ary)) return COMPILE_OK; + tlen = (int)RARRAY_LEN(catch_table_ary); + tptr = RARRAY_CONST_PTR(catch_table_ary); if (tlen > 0) { struct iseq_catch_table *table = xmalloc(iseq_catch_table_bytes(tlen)); table->size = tlen; for (i = 0; i < table->size; i++) { + int pos; ptr = RARRAY_CONST_PTR(tptr[i]); entry = UNALIGNED_MEMBER_PTR(table, entries[i]); entry->type = (enum rb_catch_type)(ptr[0] & 0xffff); - entry->start = label_get_position((LABEL *)(ptr[1] & ~1)); - entry->end = label_get_position((LABEL *)(ptr[2] & ~1)); + pos = label_get_position((LABEL *)(ptr[1] & ~1)); + RUBY_ASSERT(pos >= 0); + entry->start = (unsigned int)pos; + pos = label_get_position((LABEL *)(ptr[2] & ~1)); + RUBY_ASSERT(pos >= 0); + entry->end = (unsigned int)pos; entry->iseq = (rb_iseq_t *)ptr[3]; RB_OBJ_WRITTEN(iseq, Qundef, entry->iseq); @@ -2726,6 +2920,7 @@ iseq_set_exception_table(rb_iseq_t *iseq) if (entry->type == CATCH_TYPE_RESCUE || entry->type == CATCH_TYPE_BREAK || entry->type == CATCH_TYPE_NEXT) { + RUBY_ASSERT(entry->sp > 0); entry->sp--; } } @@ -2737,6 +2932,8 @@ iseq_set_exception_table(rb_iseq_t *iseq) RB_OBJ_WRITE(iseq, &ISEQ_COMPILE_DATA(iseq)->catch_table_ary, 0); /* free */ } + RB_GC_GUARD(catch_table_ary); + return COMPILE_OK; } @@ -2833,16 +3030,18 @@ unref_destination(INSN *iobj, int pos) if (!lobj->refcnt) ELEM_REMOVE(&lobj->link); } -static void +static bool replace_destination(INSN *dobj, INSN *nobj) { VALUE n = OPERAND_AT(nobj, 0); LABEL *dl = (LABEL *)OPERAND_AT(dobj, 0); LABEL *nl = (LABEL *)n; + if (dl == nl) return false; --dl->refcnt; ++nl->refcnt; OPERAND_AT(dobj, 0) = n; if (!dl->refcnt) ELEM_REMOVE(&dl->link); + return true; } static LABEL* @@ -2875,7 +3074,6 @@ remove_unreachable_chunk(rb_iseq_t *iseq, LINK_ELEMENT *i) break; } else if ((lab = find_destination((INSN *)i)) != 0) { - if (lab->unremovable) break; unref_counts[lab->label_no]++; } } @@ -2892,8 +3090,7 @@ remove_unreachable_chunk(rb_iseq_t *iseq, LINK_ELEMENT *i) /* do nothing */ } else if (IS_ADJUST(i)) { - LABEL *dest = ((ADJUST *)i)->label; - if (dest && dest->unremovable) return 0; + return 0; } end = i; } while ((i = i->next) != 0); @@ -2938,7 +3135,7 @@ iseq_pop_newarray(rb_iseq_t *iseq, INSN *iobj) static int is_frozen_putstring(INSN *insn, VALUE *op) { - if (IS_INSN_ID(insn, putstring)) { + if (IS_INSN_ID(insn, putstring) || IS_INSN_ID(insn, putchilledstring)) { *op = OPERAND_AT(insn, 0); return 1; } @@ -2980,6 +3177,7 @@ optimize_checktype(rb_iseq_t *iseq, INSN *iobj) switch (INSN_OF(iobj)) { case BIN(putstring): + case BIN(putchilledstring): type = INT2FIX(T_STRING); break; case BIN(putnil): @@ -3020,7 +3218,6 @@ optimize_checktype(rb_iseq_t *iseq, INSN *iobj) } line = ciobj->insn_info.line_no; node_id = ciobj->insn_info.node_id; - NODE dummy_line_node = generate_dummy_line_node(line, node_id); if (!dest) { if (niobj->link.next && IS_LABEL(niobj->link.next)) { dest = (LABEL *)niobj->link.next; /* reuse label */ @@ -3030,9 +3227,9 @@ optimize_checktype(rb_iseq_t *iseq, INSN *iobj) ELEM_INSERT_NEXT(&niobj->link, &dest->link); } } - INSERT_AFTER_INSN1(iobj, &dummy_line_node, jump, dest); + INSERT_AFTER_INSN1(iobj, line, node_id, jump, dest); LABEL_REF(dest); - if (!dup) INSERT_AFTER_INSN(iobj, &dummy_line_node, pop); + if (!dup) INSERT_AFTER_INSN(iobj, line, node_id, pop); return TRUE; } @@ -3058,6 +3255,8 @@ ci_argc_set(const rb_iseq_t *iseq, const struct rb_callinfo *ci, int argc) return nci; } +#define vm_ci_simple(ci) (vm_ci_flag(ci) & VM_CALL_ARGS_SIMPLE) + static int iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcallopt) { @@ -3096,9 +3295,10 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal * => in this case, first jump instruction should jump to * LABEL2 directly */ - replace_destination(iobj, diobj); - remove_unreachable_chunk(iseq, iobj->link.next); - goto again; + if (replace_destination(iobj, diobj)) { + remove_unreachable_chunk(iseq, iobj->link.next); + goto again; + } } else if (IS_INSN_ID(diobj, leave)) { /* @@ -3143,8 +3343,7 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal */ piobj->insn_id = (IS_INSN_ID(piobj, branchif)) ? BIN(branchunless) : BIN(branchif); - replace_destination(piobj, iobj); - if (refcnt <= 1) { + if (replace_destination(piobj, iobj) && refcnt <= 1) { ELEM_REMOVE(&iobj->link); } else { @@ -3166,8 +3365,7 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal * pop * jump L1 */ - NODE dummy_line_node = generate_dummy_line_node(iobj->insn_info.line_no, iobj->insn_info.node_id); - INSN *popiobj = new_insn_core(iseq, &dummy_line_node, BIN(pop), 0, 0); + INSN *popiobj = new_insn_core(iseq, iobj->insn_info.line_no, iobj->insn_info.node_id, BIN(pop), 0, 0); ELEM_REPLACE(&piobj->link, &popiobj->link); } } @@ -3212,19 +3410,117 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal /* * ... * duparray [...] - * concatarray + * concatarray | concattoarray * => * ... * putobject [...] - * concatarray + * concatarray | concattoarray */ if (IS_INSN_ID(iobj, duparray)) { LINK_ELEMENT *next = iobj->link.next; - if (IS_INSN(next) && IS_INSN_ID(next, concatarray)) { + if (IS_INSN(next) && (IS_INSN_ID(next, concatarray) || IS_INSN_ID(next, concattoarray))) { iobj->insn_id = BIN(putobject); } } + /* + * duparray [...] + * send , nil + * => + * opt_ary_freeze [...], + */ + if (IS_INSN_ID(iobj, duparray)) { + LINK_ELEMENT *next = iobj->link.next; + if (IS_INSN(next) && (IS_INSN_ID(next, send))) { + const struct rb_callinfo *ci = (struct rb_callinfo *)OPERAND_AT(next, 0); + const rb_iseq_t *blockiseq = (rb_iseq_t *)OPERAND_AT(next, 1); + + if (vm_ci_simple(ci) && vm_ci_argc(ci) == 0 && blockiseq == NULL && vm_ci_mid(ci) == idFreeze) { + VALUE ary = iobj->operands[0]; + rb_obj_reveal(ary, rb_cArray); + + iobj->insn_id = BIN(opt_ary_freeze); + iobj->operand_size = 2; + iobj->operands = compile_data_calloc2(iseq, iobj->operand_size, sizeof(VALUE)); + iobj->operands[0] = ary; + iobj->operands[1] = (VALUE)ci; + ELEM_REMOVE(next); + } + } + } + + /* + * duphash {...} + * send , nil + * => + * opt_hash_freeze {...}, + */ + if (IS_INSN_ID(iobj, duphash)) { + LINK_ELEMENT *next = iobj->link.next; + if (IS_INSN(next) && (IS_INSN_ID(next, send))) { + const struct rb_callinfo *ci = (struct rb_callinfo *)OPERAND_AT(next, 0); + const rb_iseq_t *blockiseq = (rb_iseq_t *)OPERAND_AT(next, 1); + + if (vm_ci_simple(ci) && vm_ci_argc(ci) == 0 && blockiseq == NULL && vm_ci_mid(ci) == idFreeze) { + VALUE hash = iobj->operands[0]; + rb_obj_reveal(hash, rb_cHash); + + iobj->insn_id = BIN(opt_hash_freeze); + iobj->operand_size = 2; + iobj->operands = compile_data_calloc2(iseq, iobj->operand_size, sizeof(VALUE)); + iobj->operands[0] = hash; + iobj->operands[1] = (VALUE)ci; + ELEM_REMOVE(next); + } + } + } + + /* + * newarray 0 + * send , nil + * => + * opt_ary_freeze [], + */ + if (IS_INSN_ID(iobj, newarray) && iobj->operands[0] == INT2FIX(0)) { + LINK_ELEMENT *next = iobj->link.next; + if (IS_INSN(next) && (IS_INSN_ID(next, send))) { + const struct rb_callinfo *ci = (struct rb_callinfo *)OPERAND_AT(next, 0); + const rb_iseq_t *blockiseq = (rb_iseq_t *)OPERAND_AT(next, 1); + + if (vm_ci_simple(ci) && vm_ci_argc(ci) == 0 && blockiseq == NULL && vm_ci_mid(ci) == idFreeze) { + iobj->insn_id = BIN(opt_ary_freeze); + iobj->operand_size = 2; + iobj->operands = compile_data_calloc2(iseq, iobj->operand_size, sizeof(VALUE)); + RB_OBJ_WRITE(iseq, &iobj->operands[0], rb_cArray_empty_frozen); + iobj->operands[1] = (VALUE)ci; + ELEM_REMOVE(next); + } + } + } + + /* + * newhash 0 + * send , nil + * => + * opt_hash_freeze {}, + */ + if (IS_INSN_ID(iobj, newhash) && iobj->operands[0] == INT2FIX(0)) { + LINK_ELEMENT *next = iobj->link.next; + if (IS_INSN(next) && (IS_INSN_ID(next, send))) { + const struct rb_callinfo *ci = (struct rb_callinfo *)OPERAND_AT(next, 0); + const rb_iseq_t *blockiseq = (rb_iseq_t *)OPERAND_AT(next, 1); + + if (vm_ci_simple(ci) && vm_ci_argc(ci) == 0 && blockiseq == NULL && vm_ci_mid(ci) == idFreeze) { + iobj->insn_id = BIN(opt_hash_freeze); + iobj->operand_size = 2; + iobj->operands = compile_data_calloc2(iseq, iobj->operand_size, sizeof(VALUE)); + RB_OBJ_WRITE(iseq, &iobj->operands[0], rb_cHash_empty_frozen); + iobj->operands[1] = (VALUE)ci; + ELEM_REMOVE(next); + } + } + } + if (IS_INSN_ID(iobj, branchif) || IS_INSN_ID(iobj, branchnil) || IS_INSN_ID(iobj, branchunless)) { @@ -3274,7 +3570,7 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal for (;;) { if (IS_INSN(&nobj->link) && IS_INSN_ID(nobj, jump)) { - replace_destination(iobj, nobj); + if (!replace_destination(iobj, nobj)) break; } else if (prev_dup && IS_INSN_ID(nobj, dup) && !!(nobj = (INSN *)nobj->link.next) && @@ -3295,7 +3591,7 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal * dup * if L2 */ - replace_destination(iobj, nobj); + if (!replace_destination(iobj, nobj)) break; } else if (pobj) { /* @@ -3346,14 +3642,12 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal ELEM_REMOVE(iobj->link.prev); } else if (!iseq_pop_newarray(iseq, pobj)) { - NODE dummy_line_node = generate_dummy_line_node(pobj->insn_info.line_no, pobj->insn_info.node_id); - pobj = new_insn_core(iseq, &dummy_line_node, BIN(pop), 0, NULL); + pobj = new_insn_core(iseq, pobj->insn_info.line_no, pobj->insn_info.node_id, BIN(pop), 0, NULL); ELEM_INSERT_PREV(&iobj->link, &pobj->link); } if (cond) { if (prev_dup) { - NODE dummy_line_node = generate_dummy_line_node(pobj->insn_info.line_no, pobj->insn_info.node_id); - pobj = new_insn_core(iseq, &dummy_line_node, BIN(putnil), 0, NULL); + pobj = new_insn_core(iseq, pobj->insn_info.line_no, pobj->insn_info.node_id, BIN(putnil), 0, NULL); ELEM_INSERT_NEXT(&iobj->link, &pobj->link); } iobj->insn_id = BIN(jump); @@ -3383,6 +3677,7 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal enum ruby_vminsn_type previ = ((INSN *)prev)->insn_id; if (previ == BIN(putobject) || previ == BIN(putnil) || previ == BIN(putself) || previ == BIN(putstring) || + previ == BIN(putchilledstring) || previ == BIN(dup) || previ == BIN(getlocal) || previ == BIN(getblockparam) || @@ -3399,8 +3694,7 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal } else if (previ == BIN(concatarray)) { INSN *piobj = (INSN *)prev; - NODE dummy_line_node = generate_dummy_line_node(piobj->insn_info.line_no, piobj->insn_info.node_id); - INSERT_BEFORE_INSN1(piobj, &dummy_line_node, splatarray, Qfalse); + INSERT_BEFORE_INSN1(piobj, piobj->insn_info.line_no, piobj->insn_info.node_id, splatarray, Qfalse); INSN_OF(piobj) = BIN(pop); } else if (previ == BIN(concatstrings)) { @@ -3417,7 +3711,6 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal if (IS_INSN_ID(iobj, newarray) || IS_INSN_ID(iobj, duparray) || - IS_INSN_ID(iobj, expandarray) || IS_INSN_ID(iobj, concatarray) || IS_INSN_ID(iobj, splatarray) || 0) { @@ -3466,7 +3759,6 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal } } else { - NODE dummy_line_node = generate_dummy_line_node(iobj->insn_info.line_no, iobj->insn_info.node_id); long diff = FIX2LONG(op1) - FIX2LONG(op2); INSN_OF(iobj) = BIN(opt_reverse); OPERAND_AT(iobj, 0) = OPERAND_AT(next, 0); @@ -3480,7 +3772,7 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal * opt_reverse Y */ for (; diff > 0; diff--) { - INSERT_BEFORE_INSN(iobj, &dummy_line_node, pop); + INSERT_BEFORE_INSN(iobj, iobj->insn_info.line_no, iobj->insn_info.node_id, pop); } } else { /* (op1 < op2) */ @@ -3492,7 +3784,7 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal * opt_reverse Y */ for (; diff < 0; diff++) { - INSERT_BEFORE_INSN(iobj, &dummy_line_node, putnil); + INSERT_BEFORE_INSN(iobj, iobj->insn_info.line_no, iobj->insn_info.node_id, putnil); } } } @@ -3527,7 +3819,7 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal } } - if (IS_INSN_ID(iobj, putstring) || + if (IS_INSN_ID(iobj, putstring) || IS_INSN_ID(iobj, putchilledstring) || (IS_INSN_ID(iobj, putobject) && RB_TYPE_P(OPERAND_AT(iobj, 0), T_STRING))) { /* * putstring "" @@ -3543,6 +3835,24 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal } ELEM_REMOVE(&iobj->link); } + if (IS_NEXT_INSN_ID(&iobj->link, toregexp)) { + INSN *next = (INSN *)iobj->link.next; + if (OPERAND_AT(next, 1) == INT2FIX(1)) { + VALUE src = OPERAND_AT(iobj, 0); + int opt = (int)FIX2LONG(OPERAND_AT(next, 0)); + VALUE path = rb_iseq_path(iseq); + int line = iobj->insn_info.line_no; + VALUE errinfo = rb_errinfo(); + VALUE re = rb_reg_compile(src, opt, RSTRING_PTR(path), line); + if (NIL_P(re)) { + VALUE message = rb_attr_get(rb_errinfo(), idMesg); + rb_set_errinfo(errinfo); + COMPILE_ERROR(iseq, line, "%" PRIsVALUE, message); + } + RB_OBJ_WRITE(iseq, &OPERAND_AT(iobj, 0), re); + ELEM_REMOVE(iobj->link.next); + } + } } if (IS_INSN_ID(iobj, concatstrings)) { @@ -3715,8 +4025,8 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal if (IS_NEXT_INSN_ID(iobj->link.next, leave)) { iobj->insn_id = BIN(opt_invokebuiltin_delegate_leave); const struct rb_builtin_function *bf = (const struct rb_builtin_function *)iobj->operands[0]; - if (iobj == (INSN *)list && bf->argc == 0 && (iseq->body->builtin_attrs & BUILTIN_ATTR_LEAF)) { - iseq->body->builtin_attrs |= BUILTIN_ATTR_SINGLE_NOARG_INLINE; + if (iobj == (INSN *)list && bf->argc == 0 && (ISEQ_BODY(iseq)->builtin_attrs & BUILTIN_ATTR_LEAF)) { + ISEQ_BODY(iseq)->builtin_attrs |= BUILTIN_ATTR_SINGLE_NOARG_LEAF; } } } @@ -3735,6 +4045,64 @@ iseq_peephole_optimize(rb_iseq_t *iseq, LINK_ELEMENT *list, const int do_tailcal } } + if (IS_INSN_ID(iobj, splatarray) && OPERAND_AT(iobj, 0) == false) { + LINK_ELEMENT *niobj = &iobj->link; + if (IS_NEXT_INSN_ID(niobj, duphash)) { + niobj = niobj->next; + LINK_ELEMENT *siobj; + unsigned int set_flags = 0, unset_flags = 0; + + /* + * Eliminate hash allocation for f(*a, kw: 1) + * + * splatarray false + * duphash + * send ARGS_SPLAT|KW_SPLAT|KW_SPLAT_MUT and not ARGS_BLOCKARG + * => + * splatarray false + * putobject + * send ARGS_SPLAT|KW_SPLAT + */ + if (IS_NEXT_INSN_ID(niobj, send)) { + siobj = niobj->next; + set_flags = VM_CALL_ARGS_SPLAT|VM_CALL_KW_SPLAT|VM_CALL_KW_SPLAT_MUT; + unset_flags = VM_CALL_ARGS_BLOCKARG; + } + /* + * Eliminate hash allocation for f(*a, kw: 1, &{arg,lvar,@iv}) + * + * splatarray false + * duphash + * getlocal / getinstancevariable / getblockparamproxy + * send ARGS_SPLAT|KW_SPLAT|KW_SPLAT_MUT|ARGS_BLOCKARG + * => + * splatarray false + * putobject + * getlocal / getinstancevariable / getblockparamproxy + * send ARGS_SPLAT|KW_SPLAT|ARGS_BLOCKARG + */ + else if ((IS_NEXT_INSN_ID(niobj, getlocal) || IS_NEXT_INSN_ID(niobj, getinstancevariable) || + IS_NEXT_INSN_ID(niobj, getblockparamproxy)) && (IS_NEXT_INSN_ID(niobj->next, send))) { + siobj = niobj->next->next; + set_flags = VM_CALL_ARGS_SPLAT|VM_CALL_KW_SPLAT|VM_CALL_KW_SPLAT_MUT|VM_CALL_ARGS_BLOCKARG; + } + + if (set_flags) { + const struct rb_callinfo *ci = (const struct rb_callinfo *)OPERAND_AT(siobj, 0); + unsigned int flags = vm_ci_flag(ci); + if ((flags & set_flags) == set_flags && !(flags & unset_flags)) { + ((INSN*)niobj)->insn_id = BIN(putobject); + RB_OBJ_WRITE(iseq, &OPERAND_AT(niobj, 0), rb_hash_freeze(rb_hash_resurrect(OPERAND_AT(niobj, 0)))); + + const struct rb_callinfo *nci = vm_ci_new(vm_ci_mid(ci), + flags & ~VM_CALL_KW_SPLAT_MUT, vm_ci_argc(ci), vm_ci_kwarg(ci)); + RB_OBJ_WRITTEN(iseq, ci, nci); + OPERAND_AT(siobj, 0) = (VALUE)nci; + } + } + } + } + return COMPILE_OK; } @@ -3762,37 +4130,169 @@ iseq_specialized_instruction(rb_iseq_t *iseq, INSN *iobj) if (IS_INSN_ID(iobj, newarray) && iobj->link.next && IS_INSN(iobj->link.next)) { /* - * [a, b, ...].max/min -> a, b, c, opt_newarray_max/min + * [a, b, ...].max/min -> a, b, c, opt_newarray_send max/min */ INSN *niobj = (INSN *)iobj->link.next; if (IS_INSN_ID(niobj, send)) { const struct rb_callinfo *ci = (struct rb_callinfo *)OPERAND_AT(niobj, 0); - if ((vm_ci_flag(ci) & VM_CALL_ARGS_SIMPLE) && vm_ci_argc(ci) == 0) { + if (vm_ci_simple(ci) && vm_ci_argc(ci) == 0) { + VALUE method = INT2FIX(0); switch (vm_ci_mid(ci)) { case idMax: + method = INT2FIX(VM_OPT_NEWARRAY_SEND_MAX); + break; case idMin: + method = INT2FIX(VM_OPT_NEWARRAY_SEND_MIN); + break; case idHash: - { - rb_num_t num = (rb_num_t)iobj->operands[0]; - iobj->insn_id = BIN(opt_newarray_send); - iobj->operands = compile_data_calloc2(iseq, insn_len(iobj->insn_id) - 1, sizeof(VALUE)); - iobj->operands[0] = (VALUE)num; - iobj->operands[1] = (VALUE)rb_id2sym(vm_ci_mid(ci)); - iobj->operand_size = insn_len(iobj->insn_id) - 1; - ELEM_REMOVE(&niobj->link); - return COMPILE_OK; - } + method = INT2FIX(VM_OPT_NEWARRAY_SEND_HASH); + break; + } + + if (method != INT2FIX(0)) { + VALUE num = iobj->operands[0]; + int operand_len = insn_len(BIN(opt_newarray_send)) - 1; + iobj->insn_id = BIN(opt_newarray_send); + iobj->operands = compile_data_calloc2(iseq, operand_len, sizeof(VALUE)); + iobj->operands[0] = num; + iobj->operands[1] = method; + iobj->operand_size = operand_len; + ELEM_REMOVE(&niobj->link); + return COMPILE_OK; } } } - } + else if ((IS_INSN_ID(niobj, putstring) || IS_INSN_ID(niobj, putchilledstring) || + (IS_INSN_ID(niobj, putobject) && RB_TYPE_P(OPERAND_AT(niobj, 0), T_STRING))) && + IS_NEXT_INSN_ID(&niobj->link, send)) { + const struct rb_callinfo *ci = (struct rb_callinfo *)OPERAND_AT((INSN *)niobj->link.next, 0); + if (vm_ci_simple(ci) && vm_ci_argc(ci) == 1 && vm_ci_mid(ci) == idPack) { + VALUE num = iobj->operands[0]; + int operand_len = insn_len(BIN(opt_newarray_send)) - 1; + iobj->insn_id = BIN(opt_newarray_send); + iobj->operands = compile_data_calloc2(iseq, operand_len, sizeof(VALUE)); + iobj->operands[0] = FIXNUM_INC(num, 1); + iobj->operands[1] = INT2FIX(VM_OPT_NEWARRAY_SEND_PACK); + iobj->operand_size = operand_len; + ELEM_REMOVE(&iobj->link); + ELEM_REMOVE(niobj->link.next); + ELEM_INSERT_NEXT(&niobj->link, &iobj->link); + return COMPILE_OK; + } + } + // newarray n, putchilledstring "E", getlocal b, send :pack with {buffer: b} + // -> putchilledstring "E", getlocal b, opt_newarray_send n+2, :pack, :buffer + else if ((IS_INSN_ID(niobj, putstring) || IS_INSN_ID(niobj, putchilledstring) || + (IS_INSN_ID(niobj, putobject) && RB_TYPE_P(OPERAND_AT(niobj, 0), T_STRING))) && + IS_NEXT_INSN_ID(&niobj->link, getlocal) && + (niobj->link.next && IS_NEXT_INSN_ID(niobj->link.next, send))) { + const struct rb_callinfo *ci = (struct rb_callinfo *)OPERAND_AT((INSN *)(niobj->link.next)->next, 0); + const struct rb_callinfo_kwarg *kwarg = vm_ci_kwarg(ci); + if (vm_ci_mid(ci) == idPack && vm_ci_argc(ci) == 2 && + (kwarg && kwarg->keyword_len == 1 && kwarg->keywords[0] == rb_id2sym(idBuffer))) { + VALUE num = iobj->operands[0]; + int operand_len = insn_len(BIN(opt_newarray_send)) - 1; + iobj->insn_id = BIN(opt_newarray_send); + iobj->operands = compile_data_calloc2(iseq, operand_len, sizeof(VALUE)); + iobj->operands[0] = FIXNUM_INC(num, 2); + iobj->operands[1] = INT2FIX(VM_OPT_NEWARRAY_SEND_PACK_BUFFER); + iobj->operand_size = operand_len; + // Remove the "send" insn. + ELEM_REMOVE((niobj->link.next)->next); + // Remove the modified insn from its original "newarray" position... + ELEM_REMOVE(&iobj->link); + // and insert it after the buffer insn. + ELEM_INSERT_NEXT(niobj->link.next, &iobj->link); + return COMPILE_OK; + } + } - if (IS_INSN_ID(iobj, send)) { - const struct rb_callinfo *ci = (struct rb_callinfo *)OPERAND_AT(iobj, 0); - const rb_iseq_t *blockiseq = (rb_iseq_t *)OPERAND_AT(iobj, 1); + // Break the "else if" chain since some prior checks abort after sub-ifs. + // We already found "newarray". To match `[...].include?(arg)` we look for + // the instruction(s) representing the argument followed by a "send". + if ((IS_INSN_ID(niobj, putstring) || IS_INSN_ID(niobj, putchilledstring) || + IS_INSN_ID(niobj, putobject) || + IS_INSN_ID(niobj, putself) || + IS_INSN_ID(niobj, getlocal) || + IS_INSN_ID(niobj, getinstancevariable)) && + IS_NEXT_INSN_ID(&niobj->link, send)) { -#define SP_INSN(opt) insn_set_specialized_instruction(iseq, iobj, BIN(opt_##opt)) - if (vm_ci_flag(ci) & VM_CALL_ARGS_SIMPLE) { + LINK_ELEMENT *sendobj = &(niobj->link); // Below we call ->next; + const struct rb_callinfo *ci; + // Allow any number (0 or more) of simple method calls on the argument + // (as in `[...].include?(arg.method1.method2)`. + do { + sendobj = sendobj->next; + ci = (struct rb_callinfo *)OPERAND_AT(sendobj, 0); + } while (vm_ci_simple(ci) && vm_ci_argc(ci) == 0 && IS_NEXT_INSN_ID(sendobj, send)); + + // If this send is for .include? with one arg we can do our opt. + if (vm_ci_simple(ci) && vm_ci_argc(ci) == 1 && vm_ci_mid(ci) == idIncludeP) { + VALUE num = iobj->operands[0]; + INSN *sendins = (INSN *)sendobj; + sendins->insn_id = BIN(opt_newarray_send); + sendins->operand_size = insn_len(sendins->insn_id) - 1; + sendins->operands = compile_data_calloc2(iseq, sendins->operand_size, sizeof(VALUE)); + sendins->operands[0] = FIXNUM_INC(num, 1); + sendins->operands[1] = INT2FIX(VM_OPT_NEWARRAY_SEND_INCLUDE_P); + // Remove the original "newarray" insn. + ELEM_REMOVE(&iobj->link); + return COMPILE_OK; + } + } + } + + /* + * duparray [...] + * some insn for the arg... + * send , nil + * => + * arg insn... + * opt_duparray_send [...], :include?, 1 + */ + if (IS_INSN_ID(iobj, duparray) && iobj->link.next && IS_INSN(iobj->link.next)) { + INSN *niobj = (INSN *)iobj->link.next; + if ((IS_INSN_ID(niobj, getlocal) || + IS_INSN_ID(niobj, getinstancevariable) || + IS_INSN_ID(niobj, putself)) && + IS_NEXT_INSN_ID(&niobj->link, send)) { + + LINK_ELEMENT *sendobj = &(niobj->link); // Below we call ->next; + const struct rb_callinfo *ci; + // Allow any number (0 or more) of simple method calls on the argument + // (as in `[...].include?(arg.method1.method2)`. + do { + sendobj = sendobj->next; + ci = (struct rb_callinfo *)OPERAND_AT(sendobj, 0); + } while (vm_ci_simple(ci) && vm_ci_argc(ci) == 0 && IS_NEXT_INSN_ID(sendobj, send)); + + if (vm_ci_simple(ci) && vm_ci_argc(ci) == 1 && vm_ci_mid(ci) == idIncludeP) { + // Move the array arg from duparray to opt_duparray_send. + VALUE ary = iobj->operands[0]; + rb_obj_reveal(ary, rb_cArray); + + INSN *sendins = (INSN *)sendobj; + sendins->insn_id = BIN(opt_duparray_send); + sendins->operand_size = insn_len(sendins->insn_id) - 1;; + sendins->operands = compile_data_calloc2(iseq, sendins->operand_size, sizeof(VALUE)); + sendins->operands[0] = ary; + sendins->operands[1] = rb_id2sym(idIncludeP); + sendins->operands[2] = INT2FIX(1); + + // Remove the duparray insn. + ELEM_REMOVE(&iobj->link); + return COMPILE_OK; + } + } + } + + + if (IS_INSN_ID(iobj, send)) { + const struct rb_callinfo *ci = (struct rb_callinfo *)OPERAND_AT(iobj, 0); + const rb_iseq_t *blockiseq = (rb_iseq_t *)OPERAND_AT(iobj, 1); + +#define SP_INSN(opt) insn_set_specialized_instruction(iseq, iobj, BIN(opt_##opt)) + if (vm_ci_simple(ci)) { switch (vm_ci_argc(ci)) { case 0: switch (vm_ci_mid(ci)) { @@ -3832,7 +4332,7 @@ iseq_specialized_instruction(rb_iseq_t *iseq, INSN *iobj) } } - if ((vm_ci_flag(ci) & VM_CALL_ARGS_BLOCKARG) == 0 && blockiseq == NULL) { + if ((vm_ci_flag(ci) & (VM_CALL_ARGS_BLOCKARG | VM_CALL_FORWARDING)) == 0 && blockiseq == NULL) { iobj->insn_id = BIN(opt_send_without_block); iobj->operand_size = insn_len(iobj->insn_id) - 1; } @@ -3874,9 +4374,18 @@ iseq_optimize(rb_iseq_t *iseq, LINK_ANCHOR *const anchor) list = FIRST_ELEMENT(anchor); int do_block_optimization = 0; + LABEL * block_loop_label = NULL; - if (ISEQ_BODY(iseq)->type == ISEQ_TYPE_BLOCK && !ISEQ_COMPILE_DATA(iseq)->catch_except_p) { + // If we're optimizing a block + if (ISEQ_BODY(iseq)->type == ISEQ_TYPE_BLOCK) { do_block_optimization = 1; + + // If the block starts with a nop and a label, + // record the label so we can detect if it's a jump target + LINK_ELEMENT * le = FIRST_ELEMENT(anchor)->next; + if (IS_INSN(le) && IS_INSN_ID((INSN *)le, nop) && IS_LABEL(le->next)) { + block_loop_label = (LABEL *)le->next; + } } while (list) { @@ -3893,9 +4402,27 @@ iseq_optimize(rb_iseq_t *iseq, LINK_ANCHOR *const anchor) if (do_block_optimization) { INSN * item = (INSN *)list; - if (IS_INSN_ID(item, jump)) { + // Give up if there is a throw + if (IS_INSN_ID(item, throw)) { do_block_optimization = 0; } + else { + // If the instruction has a jump target, check if the + // jump target is the block loop label + const char *types = insn_op_types(item->insn_id); + for (int j = 0; types[j]; j++) { + if (types[j] == TS_OFFSET) { + // If the jump target is equal to the block loop + // label, then we can't do the optimization because + // the leading `nop` instruction fires the block + // entry tracepoint + LABEL * target = (LABEL *)OPERAND_AT(item, j); + if (target == block_loop_label) { + do_block_optimization = 0; + } + } + } + } } } if (IS_LABEL(list)) { @@ -3952,8 +4479,7 @@ new_unified_insn(rb_iseq_t *iseq, list = list->next; } - NODE dummy_line_node = generate_dummy_line_node(iobj->insn_info.line_no, iobj->insn_info.node_id); - return new_insn_core(iseq, &dummy_line_node, insn_id, argc, operands); + return new_insn_core(iseq, iobj->insn_info.line_no, iobj->insn_info.node_id, insn_id, argc, operands); } #endif @@ -4018,65 +4544,109 @@ all_string_result_p(const NODE *node) { if (!node) return FALSE; switch (nd_type(node)) { - case NODE_STR: case NODE_DSTR: + case NODE_STR: case NODE_DSTR: case NODE_FILE: return TRUE; case NODE_IF: case NODE_UNLESS: - if (!node->nd_body || !node->nd_else) return FALSE; - if (all_string_result_p(node->nd_body)) - return all_string_result_p(node->nd_else); + if (!RNODE_IF(node)->nd_body || !RNODE_IF(node)->nd_else) return FALSE; + if (all_string_result_p(RNODE_IF(node)->nd_body)) + return all_string_result_p(RNODE_IF(node)->nd_else); return FALSE; case NODE_AND: case NODE_OR: - if (!node->nd_2nd) - return all_string_result_p(node->nd_1st); - if (!all_string_result_p(node->nd_1st)) + if (!RNODE_AND(node)->nd_2nd) + return all_string_result_p(RNODE_AND(node)->nd_1st); + if (!all_string_result_p(RNODE_AND(node)->nd_1st)) return FALSE; - return all_string_result_p(node->nd_2nd); + return all_string_result_p(RNODE_AND(node)->nd_2nd); default: return FALSE; } } +struct dstr_ctxt { + rb_iseq_t *const iseq; + LINK_ANCHOR *const ret; + VALUE lit; + const NODE *lit_node; + int cnt; + int dregx; +}; + static int -compile_dstr_fragments(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int *cntp) +append_dstr_fragment(struct dstr_ctxt *args, const NODE *const node, rb_parser_string_t *str) { - const NODE *list = node->nd_next; - VALUE lit = node->nd_lit; - LINK_ELEMENT *first_lit = 0; - int cnt = 0; - - debugp_param("nd_lit", lit); - if (!NIL_P(lit)) { - cnt++; - if (!RB_TYPE_P(lit, T_STRING)) { - COMPILE_ERROR(ERROR_ARGS "dstr: must be string: %s", - rb_builtin_type_name(TYPE(lit))); + VALUE s = rb_str_new_mutable_parser_string(str); + if (args->dregx) { + VALUE error = rb_reg_check_preprocess(s); + if (!NIL_P(error)) { + COMPILE_ERROR(args->iseq, nd_line(node), "%" PRIsVALUE, error); return COMPILE_NG; } + } + if (NIL_P(args->lit)) { + args->lit = s; + args->lit_node = node; + } + else { + rb_str_buf_append(args->lit, s); + } + return COMPILE_OK; +} + +static void +flush_dstr_fragment(struct dstr_ctxt *args) +{ + if (!NIL_P(args->lit)) { + rb_iseq_t *iseq = args->iseq; + VALUE lit = args->lit; + args->lit = Qnil; lit = rb_fstring(lit); - ADD_INSN1(ret, node, putobject, lit); - RB_OBJ_WRITTEN(iseq, Qundef, lit); - if (RSTRING_LEN(lit) == 0) first_lit = LAST_ELEMENT(ret); + ADD_INSN1(args->ret, args->lit_node, putobject, lit); + RB_OBJ_WRITTEN(args->iseq, Qundef, lit); + args->cnt++; + } +} + +static int +compile_dstr_fragments_0(struct dstr_ctxt *args, const NODE *const node) +{ + const struct RNode_LIST *list = RNODE_DSTR(node)->nd_next; + rb_parser_string_t *str = RNODE_DSTR(node)->string; + + if (str) { + CHECK(append_dstr_fragment(args, node, str)); } while (list) { const NODE *const head = list->nd_head; if (nd_type_p(head, NODE_STR)) { - lit = rb_fstring(head->nd_lit); - ADD_INSN1(ret, head, putobject, lit); - RB_OBJ_WRITTEN(iseq, Qundef, lit); - lit = Qnil; + CHECK(append_dstr_fragment(args, node, RNODE_STR(head)->string)); + } + else if (nd_type_p(head, NODE_DSTR)) { + CHECK(compile_dstr_fragments_0(args, head)); } else { - CHECK(COMPILE(ret, "each string", head)); + flush_dstr_fragment(args); + rb_iseq_t *iseq = args->iseq; + CHECK(COMPILE(args->ret, "each string", head)); + args->cnt++; } - cnt++; - list = list->nd_next; - } - if (NIL_P(lit) && first_lit) { - ELEM_REMOVE(first_lit); - --cnt; + list = (struct RNode_LIST *)list->nd_next; } - *cntp = cnt; + return COMPILE_OK; +} + +static int +compile_dstr_fragments(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int *cntp, int dregx) +{ + struct dstr_ctxt args = { + .iseq = iseq, .ret = ret, + .lit = Qnil, .lit_node = NULL, + .cnt = 0, .dregx = dregx, + }; + CHECK(compile_dstr_fragments_0(&args, node)); + flush_dstr_fragment(&args); + + *cntp = args.cnt; return COMPILE_OK; } @@ -4085,12 +4655,12 @@ static int compile_block(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int popped) { while (node && nd_type_p(node, NODE_BLOCK)) { - CHECK(COMPILE_(ret, "BLOCK body", node->nd_head, - (node->nd_next ? 1 : popped))); - node = node->nd_next; + CHECK(COMPILE_(ret, "BLOCK body", RNODE_BLOCK(node)->nd_head, + (RNODE_BLOCK(node)->nd_next ? 1 : popped))); + node = RNODE_BLOCK(node)->nd_next; } if (node) { - CHECK(COMPILE_(ret, "BLOCK next", node->nd_next, popped)); + CHECK(COMPILE_(ret, "BLOCK next", RNODE_BLOCK(node)->nd_next, popped)); } return COMPILE_OK; } @@ -4099,24 +4669,41 @@ static int compile_dstr(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node) { int cnt; - if (!node->nd_next) { - VALUE lit = rb_fstring(node->nd_lit); + if (!RNODE_DSTR(node)->nd_next) { + VALUE lit = rb_node_dstr_string_val(node); ADD_INSN1(ret, node, putstring, lit); RB_OBJ_WRITTEN(iseq, Qundef, lit); } else { - CHECK(compile_dstr_fragments(iseq, ret, node, &cnt)); + CHECK(compile_dstr_fragments(iseq, ret, node, &cnt, FALSE)); ADD_INSN1(ret, node, concatstrings, INT2FIX(cnt)); } return COMPILE_OK; } static int -compile_dregx(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node) +compile_dregx(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int popped) { int cnt; - CHECK(compile_dstr_fragments(iseq, ret, node, &cnt)); - ADD_INSN2(ret, node, toregexp, INT2FIX(node->nd_cflag), INT2FIX(cnt)); + int cflag = (int)RNODE_DREGX(node)->as.nd_cflag; + + if (!RNODE_DREGX(node)->nd_next) { + if (!popped) { + VALUE src = rb_node_dregx_string_val(node); + VALUE match = rb_reg_compile(src, cflag, NULL, 0); + ADD_INSN1(ret, node, putobject, match); + RB_OBJ_WRITTEN(iseq, Qundef, match); + } + return COMPILE_OK; + } + + CHECK(compile_dstr_fragments(iseq, ret, node, &cnt, TRUE)); + ADD_INSN2(ret, node, toregexp, INT2FIX(cflag), INT2FIX(cnt)); + + if (popped) { + ADD_INSN(ret, node, pop); + } + return COMPILE_OK; } @@ -4134,7 +4721,7 @@ compile_flip_flop(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const nod ADD_INSNL(ret, node, branchif, lend); /* *flip == 0 */ - CHECK(COMPILE(ret, "flip2 beg", node->nd_beg)); + CHECK(COMPILE(ret, "flip2 beg", RNODE_FLIP2(node)->nd_beg)); ADD_INSNL(ret, node, branchunless, else_label); ADD_INSN1(ret, node, putobject, Qtrue); ADD_INSN1(ret, node, setspecial, key); @@ -4144,7 +4731,7 @@ compile_flip_flop(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const nod /* *flip == 1 */ ADD_LABEL(ret, lend); - CHECK(COMPILE(ret, "flip2 end", node->nd_end)); + CHECK(COMPILE(ret, "flip2 end", RNODE_FLIP2(node)->nd_end)); ADD_INSNL(ret, node, branchunless, then_label); ADD_INSN1(ret, node, putobject, Qfalse); ADD_INSN1(ret, node, setspecial, key); @@ -4154,9 +4741,10 @@ compile_flip_flop(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const nod } static int -compile_branch_condition(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *cond, +compile_branch_condition(rb_iseq_t *iseq, LINK_ANCHOR *ret, const NODE *cond, LABEL *then_label, LABEL *else_label); +#define COMPILE_SINGLE 2 static int compile_logical(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *cond, LABEL *then_label, LABEL *else_label) @@ -4175,32 +4763,51 @@ compile_logical(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *cond, return COMPILE_OK; } if (!label->refcnt) { - ADD_INSN(seq, cond, putnil); - } - else { - ADD_LABEL(seq, label); + return COMPILE_SINGLE; } + ADD_LABEL(seq, label); ADD_SEQ(ret, seq); return COMPILE_OK; } static int -compile_branch_condition(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *cond, +compile_branch_condition(rb_iseq_t *iseq, LINK_ANCHOR *ret, const NODE *cond, LABEL *then_label, LABEL *else_label) { + int ok; + DECL_ANCHOR(ignore); + again: switch (nd_type(cond)) { case NODE_AND: - CHECK(compile_logical(iseq, ret, cond->nd_1st, NULL, else_label)); - cond = cond->nd_2nd; + CHECK(ok = compile_logical(iseq, ret, RNODE_AND(cond)->nd_1st, NULL, else_label)); + cond = RNODE_AND(cond)->nd_2nd; + if (ok == COMPILE_SINGLE) { + INIT_ANCHOR(ignore); + ret = ignore; + then_label = NEW_LABEL(nd_line(cond)); + } goto again; case NODE_OR: - CHECK(compile_logical(iseq, ret, cond->nd_1st, then_label, NULL)); - cond = cond->nd_2nd; + CHECK(ok = compile_logical(iseq, ret, RNODE_OR(cond)->nd_1st, then_label, NULL)); + cond = RNODE_OR(cond)->nd_2nd; + if (ok == COMPILE_SINGLE) { + INIT_ANCHOR(ignore); + ret = ignore; + else_label = NEW_LABEL(nd_line(cond)); + } goto again; - case NODE_LIT: /* NODE_LIT is always true */ + case NODE_SYM: + case NODE_LINE: + case NODE_FILE: + case NODE_ENCODING: + case NODE_INTEGER: /* NODE_INTEGER is always true */ + case NODE_FLOAT: /* NODE_FLOAT is always true */ + case NODE_RATIONAL: /* NODE_RATIONAL is always true */ + case NODE_IMAGINARY: /* NODE_IMAGINARY is always true */ case NODE_TRUE: case NODE_STR: + case NODE_REGX: case NODE_ZLIST: case NODE_LAMBDA: /* printf("useless condition eliminate (%s)\n", ruby_node_name(nd_type(cond))); */ @@ -4225,7 +4832,7 @@ compile_branch_condition(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *co CHECK(compile_flip_flop(iseq, ret, cond, FALSE, then_label, else_label)); return COMPILE_OK; case NODE_DEFINED: - CHECK(compile_defined_expr(iseq, ret, cond, Qfalse)); + CHECK(compile_defined_expr(iseq, ret, cond, Qfalse, ret == ignore)); break; default: { @@ -4263,7 +4870,40 @@ compile_branch_condition(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *co static int keyword_node_p(const NODE *const node) { - return nd_type_p(node, NODE_HASH) && (node->nd_brace & HASH_BRACE) != HASH_BRACE; + return nd_type_p(node, NODE_HASH) && (RNODE_HASH(node)->nd_brace & HASH_BRACE) != HASH_BRACE; +} + +static VALUE +get_symbol_value(rb_iseq_t *iseq, const NODE *node) +{ + switch (nd_type(node)) { + case NODE_SYM: + return rb_node_sym_string_val(node); + default: + UNKNOWN_NODE("get_symbol_value", node, Qnil); + } +} + +static VALUE +node_hash_unique_key_index(rb_iseq_t *iseq, rb_node_hash_t *node_hash, int *count_ptr) +{ + NODE *node = node_hash->nd_head; + VALUE hash = rb_hash_new(); + VALUE ary = rb_ary_new(); + + for (int i = 0; node != NULL; i++, node = RNODE_LIST(RNODE_LIST(node)->nd_next)->nd_next) { + VALUE key = get_symbol_value(iseq, RNODE_LIST(node)->nd_head); + VALUE idx = rb_hash_aref(hash, key); + if (!NIL_P(idx)) { + rb_ary_store(ary, FIX2INT(idx), Qfalse); + (*count_ptr)--; + } + rb_hash_aset(hash, key, INT2FIX(i)); + rb_ary_store(ary, i, Qtrue); + (*count_ptr)++; + } + + return ary; } static int @@ -4276,22 +4916,22 @@ compile_keyword_arg(rb_iseq_t *iseq, LINK_ANCHOR *const ret, RUBY_ASSERT(kw_arg_ptr != NULL); RUBY_ASSERT(flag != NULL); - if (root_node->nd_head && nd_type_p(root_node->nd_head, NODE_LIST)) { - const NODE *node = root_node->nd_head; + if (RNODE_HASH(root_node)->nd_head && nd_type_p(RNODE_HASH(root_node)->nd_head, NODE_LIST)) { + const NODE *node = RNODE_HASH(root_node)->nd_head; int seen_nodes = 0; while (node) { - const NODE *key_node = node->nd_head; + const NODE *key_node = RNODE_LIST(node)->nd_head; seen_nodes++; - assert(nd_type_p(node, NODE_LIST)); - if (key_node && nd_type_p(key_node, NODE_LIT) && SYMBOL_P(key_node->nd_lit)) { + RUBY_ASSERT(nd_type_p(node, NODE_LIST)); + if (key_node && nd_type_p(key_node, NODE_SYM)) { /* can be keywords */ } else { if (flag) { *flag |= VM_CALL_KW_SPLAT; - if (seen_nodes > 1 || node->nd_next->nd_next) { + if (seen_nodes > 1 || RNODE_LIST(RNODE_LIST(node)->nd_next)->nd_next) { /* A new hash will be created for the keyword arguments * in this case, so mark the method as passing mutable * keyword splat. @@ -4301,29 +4941,37 @@ compile_keyword_arg(rb_iseq_t *iseq, LINK_ANCHOR *const ret, } return FALSE; } - node = node->nd_next; /* skip value node */ - node = node->nd_next; + node = RNODE_LIST(node)->nd_next; /* skip value node */ + node = RNODE_LIST(node)->nd_next; } /* may be keywords */ - node = root_node->nd_head; + node = RNODE_HASH(root_node)->nd_head; { - int len = (int)node->nd_alen / 2; + int len = 0; + VALUE key_index = node_hash_unique_key_index(iseq, RNODE_HASH(root_node), &len); struct rb_callinfo_kwarg *kw_arg = rb_xmalloc_mul_add(len, sizeof(VALUE), sizeof(struct rb_callinfo_kwarg)); VALUE *keywords = kw_arg->keywords; int i = 0; + int j = 0; + kw_arg->references = 0; kw_arg->keyword_len = len; *kw_arg_ptr = kw_arg; - for (i=0; node != NULL; i++, node = node->nd_next->nd_next) { - const NODE *key_node = node->nd_head; - const NODE *val_node = node->nd_next->nd_head; - keywords[i] = key_node->nd_lit; - NO_CHECK(COMPILE(ret, "keyword values", val_node)); + for (i=0; node != NULL; i++, node = RNODE_LIST(RNODE_LIST(node)->nd_next)->nd_next) { + const NODE *key_node = RNODE_LIST(node)->nd_head; + const NODE *val_node = RNODE_LIST(RNODE_LIST(node)->nd_next)->nd_head; + int popped = TRUE; + if (rb_ary_entry(key_index, i)) { + keywords[j] = get_symbol_value(iseq, key_node); + j++; + popped = FALSE; + } + NO_CHECK(COMPILE_(ret, "keyword values", val_node, popped)); } - assert(i == len); + RUBY_ASSERT(j == len); return TRUE; } } @@ -4335,34 +4983,48 @@ compile_args(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, NODE **k { int len = 0; - for (; node; len++, node = node->nd_next) { + for (; node; len++, node = RNODE_LIST(node)->nd_next) { if (CPDEBUG > 0) { EXPECT_NODE("compile_args", node, NODE_LIST, -1); } - if (node->nd_next == NULL && keyword_node_p(node->nd_head)) { /* last node is kwnode */ - *kwnode_ptr = node->nd_head; + if (RNODE_LIST(node)->nd_next == NULL && keyword_node_p(RNODE_LIST(node)->nd_head)) { /* last node is kwnode */ + *kwnode_ptr = RNODE_LIST(node)->nd_head; } else { - RUBY_ASSERT(!keyword_node_p(node->nd_head)); - NO_CHECK(COMPILE_(ret, "array element", node->nd_head, FALSE)); + RUBY_ASSERT(!keyword_node_p(RNODE_LIST(node)->nd_head)); + NO_CHECK(COMPILE_(ret, "array element", RNODE_LIST(node)->nd_head, FALSE)); } } return len; } -static inline int -static_literal_node_p(const NODE *node, const rb_iseq_t *iseq) +static inline bool +frozen_string_literal_p(const rb_iseq_t *iseq) +{ + return ISEQ_COMPILE_DATA(iseq)->option->frozen_string_literal > 0; +} + +static inline bool +static_literal_node_p(const NODE *node, const rb_iseq_t *iseq, bool hash_key) { switch (nd_type(node)) { - case NODE_LIT: + case NODE_SYM: + case NODE_REGX: + case NODE_LINE: + case NODE_ENCODING: + case NODE_INTEGER: + case NODE_FLOAT: + case NODE_RATIONAL: + case NODE_IMAGINARY: case NODE_NIL: case NODE_TRUE: case NODE_FALSE: return TRUE; case NODE_STR: - return ISEQ_COMPILE_DATA(iseq)->option->frozen_string_literal; + case NODE_FILE: + return hash_key || frozen_string_literal_p(iseq); default: return FALSE; } @@ -4372,30 +5034,44 @@ static inline VALUE static_literal_value(const NODE *node, rb_iseq_t *iseq) { switch (nd_type(node)) { + case NODE_INTEGER: + return rb_node_integer_literal_val(node); + case NODE_FLOAT: + return rb_node_float_literal_val(node); + case NODE_RATIONAL: + return rb_node_rational_literal_val(node); + case NODE_IMAGINARY: + return rb_node_imaginary_literal_val(node); case NODE_NIL: return Qnil; case NODE_TRUE: return Qtrue; case NODE_FALSE: return Qfalse; + case NODE_SYM: + return rb_node_sym_string_val(node); + case NODE_REGX: + return rb_node_regx_string_val(node); + case NODE_LINE: + return rb_node_line_lineno_val(node); + case NODE_ENCODING: + return rb_node_encoding_val(node); + case NODE_FILE: case NODE_STR: if (ISEQ_COMPILE_DATA(iseq)->option->debug_frozen_string_literal || RTEST(ruby_debug)) { - VALUE lit; - VALUE debug_info = rb_ary_new_from_args(2, rb_iseq_path(iseq), INT2FIX((int)nd_line(node))); - lit = rb_str_dup(node->nd_lit); - rb_ivar_set(lit, id_debug_created_info, rb_obj_freeze(debug_info)); - return rb_str_freeze(lit); + VALUE lit = get_string_value(node); + return rb_str_with_debug_created_info(lit, rb_iseq_path(iseq), (int)nd_line(node)); } else { - return rb_fstring(node->nd_lit); + return get_string_value(node); } default: - return node->nd_lit; + rb_bug("unexpected node: %s", ruby_node_name(nd_type(node))); } } static int -compile_array(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int popped) +compile_array(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int popped, bool first_chunk) { const NODE *line_node = node; @@ -4409,8 +5085,8 @@ compile_array(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int pop EXPECT_NODE("compile_array", node, NODE_LIST, -1); if (popped) { - for (; node; node = node->nd_next) { - NO_CHECK(COMPILE_(ret, "array element", node->nd_head, popped)); + for (; node; node = RNODE_LIST(node)->nd_next) { + NO_CHECK(COMPILE_(ret, "array element", RNODE_LIST(node)->nd_head, popped)); } return 1; } @@ -4430,8 +5106,8 @@ compile_array(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int pop * * [x1,x2,...,x10000] => * push x1 ; push x2 ; ...; push x256; newarray 256; - * push x257; push x258; ...; push x512; newarray 256; concatarray; - * push x513; push x514; ...; push x768; newarray 256; concatarray; + * push x257; push x258; ...; push x512; pushtoarray 256; + * push x513; push x514; ...; push x768; pushtoarray 256; * ... * * - Long subarray can be optimized by pre-allocating a hidden array. @@ -4441,38 +5117,38 @@ compile_array(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int pop * * [x, 1,2,3,...,100, z] => * push x; newarray 1; - * putobject [1,2,3,...,100] (<- hidden array); concatarray; - * push z; newarray 1; concatarray + * putobject [1,2,3,...,100] (<- hidden array); concattoarray; + * push z; pushtoarray 1; * - * - If the last element is a keyword, newarraykwsplat should be emitted - * to check and remove empty keyword arguments hash from array. + * - If the last element is a keyword, pushtoarraykwsplat should be emitted + * to only push it onto the array if it is not empty * (Note: a keyword is NODE_HASH which is not static_literal_node_p.) * * [1,2,3,**kw] => - * putobject 1; putobject 2; putobject 3; push kw; newarraykwsplat + * putobject 1; putobject 2; putobject 3; newarray 3; ...; pushtoarraykwsplat kw */ const int max_stack_len = 0x100; const int min_tmp_ary_len = 0x40; int stack_len = 0; - int first_chunk = 1; - /* Convert pushed elements to an array, and concatarray if needed */ -#define FLUSH_CHUNK(newarrayinsn) \ + /* Either create a new array, or push to the existing array */ +#define FLUSH_CHUNK \ if (stack_len) { \ - ADD_INSN1(ret, line_node, newarrayinsn, INT2FIX(stack_len)); \ - if (!first_chunk) ADD_INSN(ret, line_node, concatarray); \ - first_chunk = stack_len = 0; \ + if (first_chunk) ADD_INSN1(ret, line_node, newarray, INT2FIX(stack_len)); \ + else ADD_INSN1(ret, line_node, pushtoarray, INT2FIX(stack_len)); \ + first_chunk = FALSE; \ + stack_len = 0; \ } while (node) { int count = 1; /* pre-allocation check (this branch can be omittable) */ - if (static_literal_node_p(node->nd_head, iseq)) { + if (static_literal_node_p(RNODE_LIST(node)->nd_head, iseq, false)) { /* count the elements that are optimizable */ - const NODE *node_tmp = node->nd_next; - for (; node_tmp && static_literal_node_p(node_tmp->nd_head, iseq); node_tmp = node_tmp->nd_next) + const NODE *node_tmp = RNODE_LIST(node)->nd_next; + for (; node_tmp && static_literal_node_p(RNODE_LIST(node_tmp)->nd_head, iseq, false); node_tmp = RNODE_LIST(node_tmp)->nd_next) count++; if ((first_chunk && stack_len == 0 && !node_tmp) || count >= min_tmp_ary_len) { @@ -4480,72 +5156,61 @@ compile_array(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int pop VALUE ary = rb_ary_hidden_new(count); /* Create a hidden array */ - for (; count; count--, node = node->nd_next) - rb_ary_push(ary, static_literal_value(node->nd_head, iseq)); + for (; count; count--, node = RNODE_LIST(node)->nd_next) + rb_ary_push(ary, static_literal_value(RNODE_LIST(node)->nd_head, iseq)); OBJ_FREEZE(ary); /* Emit optimized code */ - FLUSH_CHUNK(newarray); + FLUSH_CHUNK; if (first_chunk) { ADD_INSN1(ret, line_node, duparray, ary); - first_chunk = 0; + first_chunk = FALSE; } else { ADD_INSN1(ret, line_node, putobject, ary); - ADD_INSN(ret, line_node, concatarray); + ADD_INSN(ret, line_node, concattoarray); } RB_OBJ_WRITTEN(iseq, Qundef, ary); } } /* Base case: Compile "count" elements */ - for (; count; count--, node = node->nd_next) { + for (; count; count--, node = RNODE_LIST(node)->nd_next) { if (CPDEBUG > 0) { EXPECT_NODE("compile_array", node, NODE_LIST, -1); } - NO_CHECK(COMPILE_(ret, "array element", node->nd_head, 0)); - stack_len++; - - if (!node->nd_next && keyword_node_p(node->nd_head)) { - /* Reached the end, and the last element is a keyword */ - FLUSH_CHUNK(newarraykwsplat); + if (!RNODE_LIST(node)->nd_next && keyword_node_p(RNODE_LIST(node)->nd_head)) { + /* Create array or push existing non-keyword elements onto array */ + if (stack_len == 0 && first_chunk) { + ADD_INSN1(ret, line_node, newarray, INT2FIX(0)); + } + else { + FLUSH_CHUNK; + } + NO_CHECK(COMPILE_(ret, "array element", RNODE_LIST(node)->nd_head, 0)); + ADD_INSN(ret, line_node, pushtoarraykwsplat); return 1; } + else { + NO_CHECK(COMPILE_(ret, "array element", RNODE_LIST(node)->nd_head, 0)); + stack_len++; + } /* If there are many pushed elements, flush them to avoid stack overflow */ - if (stack_len >= max_stack_len) FLUSH_CHUNK(newarray); + if (stack_len >= max_stack_len) FLUSH_CHUNK; } } - FLUSH_CHUNK(newarray); + FLUSH_CHUNK; #undef FLUSH_CHUNK return 1; } -/* Compile an array containing the single element represented by node */ -static int -compile_array_1(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node) -{ - if (static_literal_node_p(node, iseq)) { - VALUE ary = rb_ary_hidden_new(1); - rb_ary_push(ary, static_literal_value(node, iseq)); - OBJ_FREEZE(ary); - - ADD_INSN1(ret, node, duparray, ary); - } - else { - CHECK(COMPILE_(ret, "array element", node, FALSE)); - ADD_INSN1(ret, node, newarray, INT2FIX(1)); - } - - return 1; -} - static inline int static_literal_node_pair_p(const NODE *node, const rb_iseq_t *iseq) { - return node->nd_head && static_literal_node_p(node->nd_head, iseq) && static_literal_node_p(node->nd_next->nd_head, iseq); + return RNODE_LIST(node)->nd_head && static_literal_node_p(RNODE_LIST(node)->nd_head, iseq, true) && static_literal_node_p(RNODE_LIST(RNODE_LIST(node)->nd_next)->nd_head, iseq, false); } static int @@ -4553,7 +5218,7 @@ compile_hash(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int meth { const NODE *line_node = node; - node = node->nd_head; + node = RNODE_HASH(node)->nd_head; if (!node || nd_type_p(node, NODE_ZLIST)) { if (!popped) { @@ -4565,8 +5230,8 @@ compile_hash(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int meth EXPECT_NODE("compile_hash", node, NODE_LIST, -1); if (popped) { - for (; node; node = node->nd_next) { - NO_CHECK(COMPILE_(ret, "hash element", node->nd_head, popped)); + for (; node; node = RNODE_LIST(node)->nd_next) { + NO_CHECK(COMPILE_(ret, "hash element", RNODE_LIST(node)->nd_head, popped)); } return 1; } @@ -4619,8 +5284,8 @@ compile_hash(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int meth /* pre-allocation check (this branch can be omittable) */ if (static_literal_node_pair_p(node, iseq)) { /* count the elements that are optimizable */ - const NODE *node_tmp = node->nd_next->nd_next; - for (; node_tmp && static_literal_node_pair_p(node_tmp, iseq); node_tmp = node_tmp->nd_next->nd_next) + const NODE *node_tmp = RNODE_LIST(RNODE_LIST(node)->nd_next)->nd_next; + for (; node_tmp && static_literal_node_pair_p(node_tmp, iseq); node_tmp = RNODE_LIST(RNODE_LIST(node_tmp)->nd_next)->nd_next) count++; if ((first_chunk && stack_len == 0 && !node_tmp) || count >= min_tmp_hash_len) { @@ -4628,10 +5293,10 @@ compile_hash(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int meth VALUE ary = rb_ary_hidden_new(count); /* Create a hidden hash */ - for (; count; count--, node = node->nd_next->nd_next) { + for (; count; count--, node = RNODE_LIST(RNODE_LIST(node)->nd_next)->nd_next) { VALUE elem[2]; - elem[0] = static_literal_value(node->nd_head, iseq); - elem[1] = static_literal_value(node->nd_next->nd_head, iseq); + elem[0] = static_literal_value(RNODE_LIST(node)->nd_head, iseq); + elem[1] = static_literal_value(RNODE_LIST(RNODE_LIST(node)->nd_next)->nd_head, iseq); rb_ary_cat(ary, elem, 2); } VALUE hash = rb_hash_new_with_size(RARRAY_LEN(ary) / 2); @@ -4658,16 +5323,16 @@ compile_hash(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int meth } /* Base case: Compile "count" elements */ - for (; count; count--, node = node->nd_next->nd_next) { + for (; count; count--, node = RNODE_LIST(RNODE_LIST(node)->nd_next)->nd_next) { if (CPDEBUG > 0) { EXPECT_NODE("compile_hash", node, NODE_LIST, -1); } - if (node->nd_head) { + if (RNODE_LIST(node)->nd_head) { /* Normal key-value pair */ - NO_CHECK(COMPILE_(anchor, "hash key element", node->nd_head, 0)); - NO_CHECK(COMPILE_(anchor, "hash value element", node->nd_next->nd_head, 0)); + NO_CHECK(COMPILE_(anchor, "hash key element", RNODE_LIST(node)->nd_head, 0)); + NO_CHECK(COMPILE_(anchor, "hash value element", RNODE_LIST(RNODE_LIST(node)->nd_next)->nd_head, 0)); stack_len += 2; /* If there are many pushed elements, flush them to avoid stack overflow */ @@ -4677,12 +5342,13 @@ compile_hash(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, int meth /* kwsplat case: foo(..., **kw, ...) */ FLUSH_CHUNK(); - const NODE *kw = node->nd_next->nd_head; - int empty_kw = nd_type_p(kw, NODE_LIT) && RB_TYPE_P(kw->nd_lit, T_HASH); /* foo( ..., **{}, ...) */ + const NODE *kw = RNODE_LIST(RNODE_LIST(node)->nd_next)->nd_head; + int empty_kw = nd_type_p(kw, NODE_HASH) && (!RNODE_HASH(kw)->nd_head); /* foo( ..., **{}, ...) */ int first_kw = first_chunk && stack_len == 0; /* foo(1,2,3, **kw, ...) */ - int last_kw = !node->nd_next->nd_next; /* foo( ..., **kw) */ + int last_kw = !RNODE_LIST(RNODE_LIST(node)->nd_next)->nd_next; /* foo( ..., **kw) */ int only_kw = last_kw && first_kw; /* foo(1,2,3, **kw) */ + empty_kw = empty_kw || nd_type_p(kw, NODE_NIL); /* foo( ..., **nil, ...) */ if (empty_kw) { if (only_kw && method_call_keywords) { /* **{} appears at the only keyword argument in method call, @@ -4742,29 +5408,34 @@ VALUE rb_node_case_when_optimizable_literal(const NODE *const node) { switch (nd_type(node)) { - case NODE_LIT: { - VALUE v = node->nd_lit; + case NODE_INTEGER: + return rb_node_integer_literal_val(node); + case NODE_FLOAT: { + VALUE v = rb_node_float_literal_val(node); double ival; - if (RB_FLOAT_TYPE_P(v) && - modf(RFLOAT_VALUE(v), &ival) == 0.0) { + + if (modf(RFLOAT_VALUE(v), &ival) == 0.0) { return FIXABLE(ival) ? LONG2FIX((long)ival) : rb_dbl2big(ival); } - if (RB_TYPE_P(v, T_RATIONAL) || RB_TYPE_P(v, T_COMPLEX)) { - return Qundef; - } - if (SYMBOL_P(v) || rb_obj_is_kind_of(v, rb_cNumeric)) { - return v; - } - break; + return v; } + case NODE_RATIONAL: + case NODE_IMAGINARY: + return Qundef; case NODE_NIL: return Qnil; case NODE_TRUE: return Qtrue; case NODE_FALSE: return Qfalse; + case NODE_SYM: + return rb_node_sym_string_val(node); + case NODE_LINE: + return rb_node_line_lineno_val(node); case NODE_STR: - return rb_fstring(node->nd_lit); + return rb_node_str_string_val(node); + case NODE_FILE: + return rb_node_file_path_val(node); } return Qundef; } @@ -4774,7 +5445,7 @@ when_vals(rb_iseq_t *iseq, LINK_ANCHOR *const cond_seq, const NODE *vals, LABEL *l1, int only_special_literals, VALUE literals) { while (vals) { - const NODE *val = vals->nd_head; + const NODE *val = RNODE_LIST(vals)->nd_head; VALUE lit = rb_node_case_when_optimizable_literal(val); if (UNDEF_P(lit)) { @@ -4784,9 +5455,9 @@ when_vals(rb_iseq_t *iseq, LINK_ANCHOR *const cond_seq, const NODE *vals, rb_hash_aset(literals, lit, (VALUE)(l1) | 1); } - if (nd_type_p(val, NODE_STR)) { - debugp_param("nd_lit", val->nd_lit); - lit = rb_fstring(val->nd_lit); + if (nd_type_p(val, NODE_STR) || nd_type_p(val, NODE_FILE)) { + debugp_param("nd_lit", get_string_value(val)); + lit = get_string_value(val); ADD_INSN1(cond_seq, val, putobject, lit); RB_OBJ_WRITTEN(iseq, Qundef, lit); } @@ -4798,7 +5469,7 @@ when_vals(rb_iseq_t *iseq, LINK_ANCHOR *const cond_seq, const NODE *vals, ADD_INSN1(cond_seq, vals, topn, INT2FIX(1)); ADD_CALL(cond_seq, vals, idEqq, INT2FIX(1)); ADD_INSNL(cond_seq, val, branchif, l1); - vals = vals->nd_next; + vals = RNODE_LIST(vals)->nd_next; } return only_special_literals; } @@ -4816,19 +5487,19 @@ when_splat_vals(rb_iseq_t *iseq, LINK_ANCHOR *const cond_seq, const NODE *vals, break; case NODE_SPLAT: ADD_INSN (cond_seq, line_node, dup); - CHECK(COMPILE(cond_seq, "when splat", vals->nd_head)); + CHECK(COMPILE(cond_seq, "when splat", RNODE_SPLAT(vals)->nd_head)); ADD_INSN1(cond_seq, line_node, splatarray, Qfalse); ADD_INSN1(cond_seq, line_node, checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_CASE | VM_CHECKMATCH_ARRAY)); ADD_INSNL(cond_seq, line_node, branchif, l1); break; case NODE_ARGSCAT: - CHECK(when_splat_vals(iseq, cond_seq, vals->nd_head, l1, only_special_literals, literals)); - CHECK(when_splat_vals(iseq, cond_seq, vals->nd_body, l1, only_special_literals, literals)); + CHECK(when_splat_vals(iseq, cond_seq, RNODE_ARGSCAT(vals)->nd_head, l1, only_special_literals, literals)); + CHECK(when_splat_vals(iseq, cond_seq, RNODE_ARGSCAT(vals)->nd_body, l1, only_special_literals, literals)); break; case NODE_ARGSPUSH: - CHECK(when_splat_vals(iseq, cond_seq, vals->nd_head, l1, only_special_literals, literals)); + CHECK(when_splat_vals(iseq, cond_seq, RNODE_ARGSPUSH(vals)->nd_head, l1, only_special_literals, literals)); ADD_INSN (cond_seq, line_node, dup); - CHECK(COMPILE(cond_seq, "when argspush body", vals->nd_body)); + CHECK(COMPILE(cond_seq, "when argspush body", RNODE_ARGSPUSH(vals)->nd_body)); ADD_INSN1(cond_seq, line_node, checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_CASE)); ADD_INSNL(cond_seq, line_node, branchif, l1); break; @@ -4987,12 +5658,17 @@ compile_massign_lhs(rb_iseq_t *iseq, LINK_ANCHOR *const pre, LINK_ANCHOR *const CHECK(COMPILE_POPPED(pre, "masgn lhs (NODE_ATTRASGN)", node)); + bool safenav_call = false; LINK_ELEMENT *insn_element = LAST_ELEMENT(pre); iobj = (INSN *)get_prev_insn((INSN *)insn_element); /* send insn */ ASSUME(iobj); - ELEM_REMOVE(LAST_ELEMENT(pre)); - ELEM_REMOVE((LINK_ELEMENT *)iobj); - pre->last = iobj->link.prev; + ELEM_REMOVE(insn_element); + if (!IS_INSN_ID(iobj, send)) { + safenav_call = true; + iobj = (INSN *)get_prev_insn(iobj); + ELEM_INSERT_NEXT(&iobj->link, insn_element); + } + (pre->last = iobj->link.prev)->next = 0; const struct rb_callinfo *ci = (struct rb_callinfo *)OPERAND_AT(iobj, 0); int argc = vm_ci_argc(ci) + 1; @@ -5011,18 +5687,46 @@ compile_massign_lhs(rb_iseq_t *iseq, LINK_ANCHOR *const pre, LINK_ANCHOR *const return COMPILE_NG; } - ADD_ELEM(lhs, (LINK_ELEMENT *)iobj); + iobj->link.prev = lhs->last; + lhs->last->next = &iobj->link; + for (lhs->last = &iobj->link; lhs->last->next; lhs->last = lhs->last->next); if (vm_ci_flag(ci) & VM_CALL_ARGS_SPLAT) { int argc = vm_ci_argc(ci); + bool dupsplat = false; ci = ci_argc_set(iseq, ci, argc - 1); + if (!(vm_ci_flag(ci) & VM_CALL_ARGS_SPLAT_MUT)) { + /* Given h[*a], _ = ary + * setup_args sets VM_CALL_ARGS_SPLAT and not VM_CALL_ARGS_SPLAT_MUT + * `a` must be dupped, because it will be appended with ary[0] + * Since you are dupping `a`, you can set VM_CALL_ARGS_SPLAT_MUT + */ + dupsplat = true; + ci = ci_flag_set(iseq, ci, VM_CALL_ARGS_SPLAT_MUT); + } OPERAND_AT(iobj, 0) = (VALUE)ci; RB_OBJ_WRITTEN(iseq, Qundef, iobj); - INSERT_BEFORE_INSN1(iobj, line_node, newarray, INT2FIX(1)); - INSERT_BEFORE_INSN(iobj, line_node, concatarray); + + /* Given: h[*a], h[*b, 1] = ary + * h[*a] uses splatarray false and does not set VM_CALL_ARGS_SPLAT_MUT, + * so this uses splatarray true on a to dup it before using pushtoarray + * h[*b, 1] uses splatarray true and sets VM_CALL_ARGS_SPLAT_MUT, + * so you can use pushtoarray directly + */ + int line_no = nd_line(line_node); + int node_id = nd_node_id(line_node); + + if (dupsplat) { + INSERT_BEFORE_INSN(iobj, line_no, node_id, swap); + INSERT_BEFORE_INSN1(iobj, line_no, node_id, splatarray, Qtrue); + INSERT_BEFORE_INSN(iobj, line_no, node_id, swap); + } + INSERT_BEFORE_INSN1(iobj, line_no, node_id, pushtoarray, INT2FIX(1)); } - ADD_INSN(lhs, line_node, pop); - if (argc != 1) { + if (!safenav_call) { ADD_INSN(lhs, line_node, pop); + if (argc != 1) { + ADD_INSN(lhs, line_node, pop); + } } for (int i=0; i < argc; i++) { ADD_INSN(post, line_node, pop); @@ -5048,7 +5752,7 @@ compile_massign_lhs(rb_iseq_t *iseq, LINK_ANCHOR *const pre, LINK_ANCHOR *const break; } case NODE_CDECL: - if (!node->nd_vid) { + if (!RNODE_CDECL(node)->nd_vid) { /* Special handling only needed for expr::C, not for C */ INSN *iobj; @@ -5086,8 +5790,8 @@ static int compile_massign_opt_lhs(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *lhsn) { if (lhsn) { - CHECK(compile_massign_opt_lhs(iseq, ret, lhsn->nd_next)); - CHECK(compile_massign_lhs(iseq, ret, ret, ret, ret, lhsn->nd_head, NULL, 0)); + CHECK(compile_massign_opt_lhs(iseq, ret, RNODE_LIST(lhsn)->nd_next)); + CHECK(compile_massign_lhs(iseq, ret, ret, ret, ret, RNODE_LIST(lhsn)->nd_head, NULL, 0)); } return COMPILE_OK; } @@ -5117,31 +5821,29 @@ compile_massign_opt(rb_iseq_t *iseq, LINK_ANCHOR *const ret, } while (lhsn) { - const NODE *ln = lhsn->nd_head; + const NODE *ln = RNODE_LIST(lhsn)->nd_head; switch (nd_type(ln)) { case NODE_LASGN: - MEMORY(ln->nd_vid); - break; case NODE_DASGN: case NODE_IASGN: case NODE_CVASGN: - MEMORY(ln->nd_vid); + MEMORY(get_nd_vid(ln)); break; default: return 0; } - lhsn = lhsn->nd_next; + lhsn = RNODE_LIST(lhsn)->nd_next; llen++; } while (rhsn) { if (llen <= rlen) { - NO_CHECK(COMPILE_POPPED(ret, "masgn val (popped)", rhsn->nd_head)); + NO_CHECK(COMPILE_POPPED(ret, "masgn val (popped)", RNODE_LIST(rhsn)->nd_head)); } else { - NO_CHECK(COMPILE(ret, "masgn val", rhsn->nd_head)); + NO_CHECK(COMPILE(ret, "masgn val", RNODE_LIST(rhsn)->nd_head)); } - rhsn = rhsn->nd_next; + rhsn = RNODE_LIST(rhsn)->nd_next; rlen++; } @@ -5158,32 +5860,31 @@ compile_massign_opt(rb_iseq_t *iseq, LINK_ANCHOR *const ret, static int compile_massign0(rb_iseq_t *iseq, LINK_ANCHOR *const pre, LINK_ANCHOR *const rhs, LINK_ANCHOR *const lhs, LINK_ANCHOR *const post, const NODE *const node, struct masgn_state *state, int popped) { - const NODE *rhsn = node->nd_value; - const NODE *splatn = node->nd_args; - const NODE *lhsn = node->nd_head; + const NODE *rhsn = RNODE_MASGN(node)->nd_value; + const NODE *splatn = RNODE_MASGN(node)->nd_args; + const NODE *lhsn = RNODE_MASGN(node)->nd_head; const NODE *lhsn_count = lhsn; int lhs_splat = (splatn && NODE_NAMED_REST_P(splatn)) ? 1 : 0; int llen = 0; int lpos = 0; - int expand = 1; while (lhsn_count) { llen++; - lhsn_count = lhsn_count->nd_next; + lhsn_count = RNODE_LIST(lhsn_count)->nd_next; } while (lhsn) { - CHECK(compile_massign_lhs(iseq, pre, rhs, lhs, post, lhsn->nd_head, state, (llen - lpos) + lhs_splat + state->lhs_level)); + CHECK(compile_massign_lhs(iseq, pre, rhs, lhs, post, RNODE_LIST(lhsn)->nd_head, state, (llen - lpos) + lhs_splat + state->lhs_level)); lpos++; - lhsn = lhsn->nd_next; + lhsn = RNODE_LIST(lhsn)->nd_next; } if (lhs_splat) { if (nd_type_p(splatn, NODE_POSTARG)) { /*a, b, *r, p1, p2 */ - const NODE *postn = splatn->nd_2nd; - const NODE *restn = splatn->nd_1st; - int plen = (int)postn->nd_alen; + const NODE *postn = RNODE_POSTARG(splatn)->nd_2nd; + const NODE *restn = RNODE_POSTARG(splatn)->nd_1st; + int plen = (int)RNODE_LIST(postn)->as.nd_alen; int ppos = 0; int flag = 0x02 | (NODE_NAMED_REST_P(restn) ? 0x01 : 0x00); @@ -5193,9 +5894,9 @@ compile_massign0(rb_iseq_t *iseq, LINK_ANCHOR *const pre, LINK_ANCHOR *const rhs CHECK(compile_massign_lhs(iseq, pre, rhs, lhs, post, restn, state, 1 + plen + state->lhs_level)); } while (postn) { - CHECK(compile_massign_lhs(iseq, pre, rhs, lhs, post, postn->nd_head, state, (plen - ppos) + state->lhs_level)); + CHECK(compile_massign_lhs(iseq, pre, rhs, lhs, post, RNODE_LIST(postn)->nd_head, state, (plen - ppos) + state->lhs_level)); ppos++; - postn = postn->nd_next; + postn = RNODE_LIST(postn)->nd_next; } } else { @@ -5204,7 +5905,6 @@ compile_massign0(rb_iseq_t *iseq, LINK_ANCHOR *const pre, LINK_ANCHOR *const rhs } } - if (!state->nested) { NO_CHECK(COMPILE(rhs, "normal masgn rhs", rhsn)); } @@ -5212,16 +5912,14 @@ compile_massign0(rb_iseq_t *iseq, LINK_ANCHOR *const pre, LINK_ANCHOR *const rhs if (!popped) { ADD_INSN(rhs, node, dup); } - if (expand) { - ADD_INSN2(rhs, node, expandarray, INT2FIX(llen), INT2FIX(lhs_splat)); - } + ADD_INSN2(rhs, node, expandarray, INT2FIX(llen), INT2FIX(lhs_splat)); return COMPILE_OK; } static int compile_massign(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int popped) { - if (!popped || node->nd_args || !compile_massign_opt(iseq, ret, node->nd_value, node->nd_head)) { + if (!popped || RNODE_MASGN(node)->nd_args || !compile_massign_opt(iseq, ret, RNODE_MASGN(node)->nd_value, RNODE_MASGN(node)->nd_head)) { struct masgn_state state; state.lhs_level = popped ? 0 : 1; state.nested = 0; @@ -5243,7 +5941,7 @@ compile_massign(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, while (memo) { VALUE topn_arg = INT2FIX((state.num_args - memo->argn) + memo->lhs_pos); for (int i = 0; i < memo->num_args; i++) { - INSERT_BEFORE_INSN1(memo->before_insn, memo->line_node, topn, topn_arg); + INSERT_BEFORE_INSN1(memo->before_insn, nd_line(memo->line_node), nd_node_id(memo->line_node), topn, topn_arg); } tmp_memo = memo->next; free(memo); @@ -5270,15 +5968,15 @@ collect_const_segments(rb_iseq_t *iseq, const NODE *node) for (;;) { switch (nd_type(node)) { case NODE_CONST: - rb_ary_unshift(arr, ID2SYM(node->nd_vid)); + rb_ary_unshift(arr, ID2SYM(RNODE_CONST(node)->nd_vid)); return arr; case NODE_COLON3: - rb_ary_unshift(arr, ID2SYM(node->nd_mid)); + rb_ary_unshift(arr, ID2SYM(RNODE_COLON3(node)->nd_mid)); rb_ary_unshift(arr, ID2SYM(idNULL)); return arr; case NODE_COLON2: - rb_ary_unshift(arr, ID2SYM(node->nd_mid)); - node = node->nd_head; + rb_ary_unshift(arr, ID2SYM(RNODE_COLON2(node)->nd_mid)); + node = RNODE_COLON2(node)->nd_head; break; default: return Qfalse; @@ -5292,22 +5990,22 @@ compile_const_prefix(rb_iseq_t *iseq, const NODE *const node, { switch (nd_type(node)) { case NODE_CONST: - debugi("compile_const_prefix - colon", node->nd_vid); + debugi("compile_const_prefix - colon", RNODE_CONST(node)->nd_vid); ADD_INSN1(body, node, putobject, Qtrue); - ADD_INSN1(body, node, getconstant, ID2SYM(node->nd_vid)); + ADD_INSN1(body, node, getconstant, ID2SYM(RNODE_CONST(node)->nd_vid)); break; case NODE_COLON3: - debugi("compile_const_prefix - colon3", node->nd_mid); + debugi("compile_const_prefix - colon3", RNODE_COLON3(node)->nd_mid); ADD_INSN(body, node, pop); ADD_INSN1(body, node, putobject, rb_cObject); ADD_INSN1(body, node, putobject, Qtrue); - ADD_INSN1(body, node, getconstant, ID2SYM(node->nd_mid)); + ADD_INSN1(body, node, getconstant, ID2SYM(RNODE_COLON3(node)->nd_mid)); break; case NODE_COLON2: - CHECK(compile_const_prefix(iseq, node->nd_head, pref, body)); - debugi("compile_const_prefix - colon2", node->nd_mid); + CHECK(compile_const_prefix(iseq, RNODE_COLON2(node)->nd_head, pref, body)); + debugi("compile_const_prefix - colon2", RNODE_COLON2(node)->nd_mid); ADD_INSN1(body, node, putobject, Qfalse); - ADD_INSN1(body, node, getconstant, ID2SYM(node->nd_mid)); + ADD_INSN1(body, node, getconstant, ID2SYM(RNODE_COLON2(node)->nd_mid)); break; default: CHECK(COMPILE(pref, "const colon2 prefix", node)); @@ -5324,9 +6022,9 @@ compile_cpath(LINK_ANCHOR *const ret, rb_iseq_t *iseq, const NODE *cpath) ADD_INSN1(ret, cpath, putobject, rb_cObject); return VM_DEFINECLASS_FLAG_SCOPED; } - else if (cpath->nd_head) { + else if (nd_type_p(cpath, NODE_COLON2) && RNODE_COLON2(cpath)->nd_head) { /* Bar::Foo */ - NO_CHECK(COMPILE(ret, "nd_else->nd_head", cpath->nd_head)); + NO_CHECK(COMPILE(ret, "nd_else->nd_head", RNODE_COLON2(cpath)->nd_head)); return VM_DEFINECLASS_FLAG_SCOPED; } else { @@ -5340,16 +6038,16 @@ compile_cpath(LINK_ANCHOR *const ret, rb_iseq_t *iseq, const NODE *cpath) static inline int private_recv_p(const NODE *node) { - if (nd_type_p(node->nd_recv, NODE_SELF)) { - NODE *self = node->nd_recv; - return self->nd_state != 0; + NODE *recv = get_nd_recv(node); + if (recv && nd_type_p(recv, NODE_SELF)) { + return RNODE_SELF(recv)->nd_state != 0; } return 0; } static void defined_expr(rb_iseq_t *iseq, LINK_ANCHOR *const ret, - const NODE *const node, LABEL **lfinish, VALUE needstr); + const NODE *const node, LABEL **lfinish, VALUE needstr, bool ignore); static int compile_call(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, const enum node_type type, const NODE *const line_node, int popped, bool assume_receiver); @@ -5380,21 +6078,34 @@ defined_expr0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, expr_type = DEFINED_FALSE; break; + case NODE_HASH: case NODE_LIST:{ - const NODE *vals = node; + const NODE *vals = (nd_type(node) == NODE_HASH) ? RNODE_HASH(node)->nd_head : node; - do { - defined_expr0(iseq, ret, vals->nd_head, lfinish, Qfalse, false); + if (vals) { + do { + if (RNODE_LIST(vals)->nd_head) { + defined_expr0(iseq, ret, RNODE_LIST(vals)->nd_head, lfinish, Qfalse, false); - if (!lfinish[1]) { - lfinish[1] = NEW_LABEL(line); - } - ADD_INSNL(ret, line_node, branchunless, lfinish[1]); - } while ((vals = vals->nd_next) != NULL); + if (!lfinish[1]) { + lfinish[1] = NEW_LABEL(line); + } + ADD_INSNL(ret, line_node, branchunless, lfinish[1]); + } + } while ((vals = RNODE_LIST(vals)->nd_next) != NULL); + } } /* fall through */ case NODE_STR: - case NODE_LIT: + case NODE_SYM: + case NODE_REGX: + case NODE_LINE: + case NODE_FILE: + case NODE_ENCODING: + case NODE_INTEGER: + case NODE_FLOAT: + case NODE_RATIONAL: + case NODE_IMAGINARY: case NODE_ZLIST: case NODE_AND: case NODE_OR: @@ -5402,6 +6113,15 @@ defined_expr0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, expr_type = DEFINED_EXPR; break; + case NODE_SPLAT: + defined_expr0(iseq, ret, RNODE_LIST(node)->nd_head, lfinish, Qfalse, false); + if (!lfinish[1]) { + lfinish[1] = NEW_LABEL(line); + } + ADD_INSNL(ret, line_node, branchunless, lfinish[1]); + expr_type = DEFINED_EXPR; + break; + /* variables */ case NODE_LVAR: case NODE_DVAR: @@ -5411,47 +6131,47 @@ defined_expr0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, #define PUSH_VAL(type) (needstr == Qfalse ? Qtrue : rb_iseq_defined_string(type)) case NODE_IVAR: ADD_INSN3(ret, line_node, definedivar, - ID2SYM(node->nd_vid), get_ivar_ic_value(iseq,node->nd_vid), PUSH_VAL(DEFINED_IVAR)); + ID2SYM(RNODE_IVAR(node)->nd_vid), get_ivar_ic_value(iseq,RNODE_IVAR(node)->nd_vid), PUSH_VAL(DEFINED_IVAR)); return; case NODE_GVAR: ADD_INSN(ret, line_node, putnil); ADD_INSN3(ret, line_node, defined, INT2FIX(DEFINED_GVAR), - ID2SYM(node->nd_vid), PUSH_VAL(DEFINED_GVAR)); + ID2SYM(RNODE_GVAR(node)->nd_vid), PUSH_VAL(DEFINED_GVAR)); return; case NODE_CVAR: ADD_INSN(ret, line_node, putnil); ADD_INSN3(ret, line_node, defined, INT2FIX(DEFINED_CVAR), - ID2SYM(node->nd_vid), PUSH_VAL(DEFINED_CVAR)); + ID2SYM(RNODE_CVAR(node)->nd_vid), PUSH_VAL(DEFINED_CVAR)); return; case NODE_CONST: ADD_INSN(ret, line_node, putnil); ADD_INSN3(ret, line_node, defined, INT2FIX(DEFINED_CONST), - ID2SYM(node->nd_vid), PUSH_VAL(DEFINED_CONST)); + ID2SYM(RNODE_CONST(node)->nd_vid), PUSH_VAL(DEFINED_CONST)); return; case NODE_COLON2: if (!lfinish[1]) { lfinish[1] = NEW_LABEL(line); } - defined_expr0(iseq, ret, node->nd_head, lfinish, Qfalse, false); + defined_expr0(iseq, ret, RNODE_COLON2(node)->nd_head, lfinish, Qfalse, false); ADD_INSNL(ret, line_node, branchunless, lfinish[1]); - NO_CHECK(COMPILE(ret, "defined/colon2#nd_head", node->nd_head)); + NO_CHECK(COMPILE(ret, "defined/colon2#nd_head", RNODE_COLON2(node)->nd_head)); - if (rb_is_const_id(node->nd_mid)) { + if (rb_is_const_id(RNODE_COLON2(node)->nd_mid)) { ADD_INSN3(ret, line_node, defined, INT2FIX(DEFINED_CONST_FROM), - ID2SYM(node->nd_mid), PUSH_VAL(DEFINED_CONST)); + ID2SYM(RNODE_COLON2(node)->nd_mid), PUSH_VAL(DEFINED_CONST)); } else { ADD_INSN3(ret, line_node, defined, INT2FIX(DEFINED_METHOD), - ID2SYM(node->nd_mid), PUSH_VAL(DEFINED_METHOD)); + ID2SYM(RNODE_COLON2(node)->nd_mid), PUSH_VAL(DEFINED_METHOD)); } return; case NODE_COLON3: ADD_INSN1(ret, line_node, putobject, rb_cObject); ADD_INSN3(ret, line_node, defined, - INT2FIX(DEFINED_CONST_FROM), ID2SYM(node->nd_mid), PUSH_VAL(DEFINED_CONST)); + INT2FIX(DEFINED_CONST_FROM), ID2SYM(RNODE_COLON3(node)->nd_mid), PUSH_VAL(DEFINED_CONST)); return; /* method dispatch */ @@ -5464,7 +6184,7 @@ defined_expr0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, (type == NODE_CALL || type == NODE_OPCALL || (type == NODE_ATTRASGN && !private_recv_p(node))); - if (node->nd_args || explicit_receiver) { + if (get_nd_args(node) || explicit_receiver) { if (!lfinish[1]) { lfinish[1] = NEW_LABEL(line); } @@ -5472,31 +6192,31 @@ defined_expr0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, lfinish[2] = NEW_LABEL(line); } } - if (node->nd_args) { - defined_expr0(iseq, ret, node->nd_args, lfinish, Qfalse, false); + if (get_nd_args(node)) { + defined_expr0(iseq, ret, get_nd_args(node), lfinish, Qfalse, false); ADD_INSNL(ret, line_node, branchunless, lfinish[1]); } if (explicit_receiver) { - defined_expr0(iseq, ret, node->nd_recv, lfinish, Qfalse, true); - switch (nd_type(node->nd_recv)) { + defined_expr0(iseq, ret, get_nd_recv(node), lfinish, Qfalse, true); + switch (nd_type(get_nd_recv(node))) { case NODE_CALL: case NODE_OPCALL: case NODE_VCALL: case NODE_FCALL: case NODE_ATTRASGN: ADD_INSNL(ret, line_node, branchunless, lfinish[2]); - compile_call(iseq, ret, node->nd_recv, nd_type(node->nd_recv), line_node, 0, true); + compile_call(iseq, ret, get_nd_recv(node), nd_type(get_nd_recv(node)), line_node, 0, true); break; default: ADD_INSNL(ret, line_node, branchunless, lfinish[1]); - NO_CHECK(COMPILE(ret, "defined/recv", node->nd_recv)); + NO_CHECK(COMPILE(ret, "defined/recv", get_nd_recv(node))); break; } if (keep_result) { ADD_INSN(ret, line_node, dup); } ADD_INSN3(ret, line_node, defined, INT2FIX(DEFINED_METHOD), - ID2SYM(node->nd_mid), PUSH_VAL(DEFINED_METHOD)); + ID2SYM(get_node_call_nd_mid(node)), PUSH_VAL(DEFINED_METHOD)); } else { ADD_INSN(ret, line_node, putself); @@ -5504,7 +6224,7 @@ defined_expr0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, ADD_INSN(ret, line_node, dup); } ADD_INSN3(ret, line_node, defined, INT2FIX(DEFINED_FUNC), - ID2SYM(node->nd_mid), PUSH_VAL(DEFINED_METHOD)); + ID2SYM(get_node_call_nd_mid(node)), PUSH_VAL(DEFINED_METHOD)); } return; } @@ -5513,13 +6233,14 @@ defined_expr0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, ADD_INSN(ret, line_node, putnil); ADD_INSN3(ret, line_node, defined, INT2FIX(DEFINED_YIELD), 0, PUSH_VAL(DEFINED_YIELD)); + iseq_set_use_block(ISEQ_BODY(iseq)->local_iseq); return; case NODE_BACK_REF: case NODE_NTH_REF: ADD_INSN(ret, line_node, putnil); ADD_INSN3(ret, line_node, defined, INT2FIX(DEFINED_REF), - INT2FIX((node->nd_nth << 1) | (type == NODE_BACK_REF)), + INT2FIX((RNODE_BACK_REF(node)->nd_nth << 1) | (type == NODE_BACK_REF)), PUSH_VAL(DEFINED_GVAR)); return; @@ -5542,11 +6263,12 @@ defined_expr0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, case NODE_IASGN: case NODE_CDECL: case NODE_CVASGN: + case NODE_OP_CDECL: expr_type = DEFINED_ASGN; break; } - assert(expr_type != DEFINED_NOT_DEFINED); + RUBY_ASSERT(expr_type != DEFINED_NOT_DEFINED); if (needstr != Qfalse) { VALUE str = rb_iseq_defined_string(expr_type); @@ -5560,14 +6282,13 @@ defined_expr0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, static void build_defined_rescue_iseq(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const void *unused) { - NODE dummy_line_node = generate_dummy_line_node(0, -1); - ADD_INSN(ret, &dummy_line_node, putnil); + ADD_SYNTHETIC_INSN(ret, 0, -1, putnil); iseq_set_exception_local_table(iseq); } static void defined_expr(rb_iseq_t *iseq, LINK_ANCHOR *const ret, - const NODE *const node, LABEL **lfinish, VALUE needstr) + const NODE *const node, LABEL **lfinish, VALUE needstr, bool ignore) { LINK_ELEMENT *lcur = ret->last; defined_expr0(iseq, ret, node, lfinish, needstr, false); @@ -5578,24 +6299,26 @@ defined_expr(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const rb_iseq_t *rescue; struct rb_iseq_new_with_callback_callback_func *ifunc = rb_iseq_new_with_callback_new_callback(build_defined_rescue_iseq, NULL); - rescue = new_child_iseq_with_callback(iseq, ifunc, + rescue = NEW_CHILD_ISEQ_WITH_CALLBACK(ifunc, rb_str_concat(rb_str_new2("defined guard in "), ISEQ_BODY(iseq)->location.label), - iseq, ISEQ_TYPE_RESCUE, 0); + ISEQ_TYPE_RESCUE, 0); lstart->rescued = LABEL_RESCUE_BEG; lend->rescued = LABEL_RESCUE_END; APPEND_LABEL(ret, lcur, lstart); ADD_LABEL(ret, lend); - ADD_CATCH_ENTRY(CATCH_TYPE_RESCUE, lstart, lend, rescue, lfinish[1]); + if (!ignore) { + ADD_CATCH_ENTRY(CATCH_TYPE_RESCUE, lstart, lend, rescue, lfinish[1]); + } } } static int -compile_defined_expr(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, VALUE needstr) +compile_defined_expr(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, VALUE needstr, bool ignore) { const int line = nd_line(node); const NODE *line_node = node; - if (!node->nd_head) { + if (!RNODE_DEFINED(node)->nd_head) { VALUE str = rb_iseq_defined_string(DEFINED_NIL); ADD_INSN1(ret, line_node, putobject, str); } @@ -5605,9 +6328,9 @@ compile_defined_expr(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const lfinish[0] = NEW_LABEL(line); lfinish[1] = 0; lfinish[2] = 0; - defined_expr(iseq, ret, node->nd_head, lfinish, needstr); + defined_expr(iseq, ret, RNODE_DEFINED(node)->nd_head, lfinish, needstr, ignore); if (lfinish[1]) { - ELEM_INSERT_NEXT(last, &new_insn_body(iseq, line_node, BIN(putnil), 0)->link); + ELEM_INSERT_NEXT(last, &new_insn_body(iseq, nd_line(line_node), nd_node_id(line_node), BIN(putnil), 0)->link); ADD_INSN(ret, line_node, swap); if (lfinish[2]) { ADD_LABEL(ret, lfinish[2]); @@ -5646,7 +6369,7 @@ make_name_for_block(const rb_iseq_t *orig_iseq) static void push_ensure_entry(rb_iseq_t *iseq, struct iseq_compile_data_ensure_node_stack *enl, - struct ensure_range *er, const NODE *const node) + struct ensure_range *er, const void *const node) { enl->ensure_node = node; enl->prev = ISEQ_COMPILE_DATA(iseq)->ensure_node_stack; /* prev */ @@ -5688,7 +6411,7 @@ can_add_ensure_iseq(const rb_iseq_t *iseq) static void add_ensure_iseq(LINK_ANCHOR *const ret, rb_iseq_t *iseq, int is_return) { - assert(can_add_ensure_iseq(iseq)); + RUBY_ASSERT(can_add_ensure_iseq(iseq)); struct iseq_compile_data_ensure_node_stack *enlp = ISEQ_COMPILE_DATA(iseq)->ensure_node_stack; @@ -5729,10 +6452,10 @@ check_keyword(const NODE *node) /* This check is essentially a code clone of compile_keyword_arg. */ if (nd_type_p(node, NODE_LIST)) { - while (node->nd_next) { - node = node->nd_next; + while (RNODE_LIST(node)->nd_next) { + node = RNODE_LIST(node)->nd_next; } - node = node->nd_head; + node = RNODE_LIST(node)->nd_head; } return keyword_node_p(node); @@ -5744,14 +6467,29 @@ keyword_node_single_splat_p(NODE *kwnode) { RUBY_ASSERT(keyword_node_p(kwnode)); - NODE *node = kwnode->nd_head; - return node->nd_head == NULL && - node->nd_next->nd_next == NULL; + NODE *node = RNODE_HASH(kwnode)->nd_head; + return RNODE_LIST(node)->nd_head == NULL && + RNODE_LIST(RNODE_LIST(node)->nd_next)->nd_next == NULL; +} + +static void +compile_single_keyword_splat_mutable(rb_iseq_t *iseq, LINK_ANCHOR *const args, const NODE *argn, + NODE *kwnode, unsigned int *flag_ptr) +{ + *flag_ptr |= VM_CALL_KW_SPLAT_MUT; + ADD_INSN1(args, argn, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); + ADD_INSN1(args, argn, newhash, INT2FIX(0)); + compile_hash(iseq, args, kwnode, TRUE, FALSE); + ADD_SEND(args, argn, id_core_hash_merge_kwd, INT2FIX(2)); } +#define SPLATARRAY_FALSE 0 +#define SPLATARRAY_TRUE 1 +#define DUP_SINGLE_KW_SPLAT 2 + static int setup_args_core(rb_iseq_t *iseq, LINK_ANCHOR *const args, const NODE *argn, - int dup_rest, unsigned int *flag_ptr, struct rb_callinfo_kwarg **kwarg_ptr) + unsigned int *dup_rest, unsigned int *flag_ptr, struct rb_callinfo_kwarg **kwarg_ptr) { if (!argn) return 0; @@ -5759,132 +6497,273 @@ setup_args_core(rb_iseq_t *iseq, LINK_ANCHOR *const args, const NODE *argn, switch (nd_type(argn)) { case NODE_LIST: { - // f(x, y, z) - int len = compile_args(iseq, args, argn, &kwnode); - RUBY_ASSERT(flag_ptr == NULL || (*flag_ptr & VM_CALL_ARGS_SPLAT) == 0); + // f(x, y, z) + int len = compile_args(iseq, args, argn, &kwnode); + RUBY_ASSERT(flag_ptr == NULL || (*flag_ptr & VM_CALL_ARGS_SPLAT) == 0); - if (kwnode) { - if (compile_keyword_arg(iseq, args, kwnode, kwarg_ptr, flag_ptr)) { - len -= 1; - } - else { - compile_hash(iseq, args, kwnode, TRUE, FALSE); - } - } + if (kwnode) { + if (compile_keyword_arg(iseq, args, kwnode, kwarg_ptr, flag_ptr)) { + len -= 1; + } + else { + if (keyword_node_single_splat_p(kwnode) && (*dup_rest & DUP_SINGLE_KW_SPLAT)) { + compile_single_keyword_splat_mutable(iseq, args, argn, kwnode, flag_ptr); + } + else { + compile_hash(iseq, args, kwnode, TRUE, FALSE); + } + } + } - return len; + return len; } case NODE_SPLAT: { - // f(*a) - NO_CHECK(COMPILE(args, "args (splat)", argn->nd_head)); - ADD_INSN1(args, argn, splatarray, RBOOL(dup_rest)); - if (flag_ptr) *flag_ptr |= VM_CALL_ARGS_SPLAT; - RUBY_ASSERT(flag_ptr == NULL || (*flag_ptr & VM_CALL_KW_SPLAT) == 0); - return 1; + // f(*a) + NO_CHECK(COMPILE(args, "args (splat)", RNODE_SPLAT(argn)->nd_head)); + ADD_INSN1(args, argn, splatarray, RBOOL(*dup_rest & SPLATARRAY_TRUE)); + if (*dup_rest & SPLATARRAY_TRUE) *dup_rest &= ~SPLATARRAY_TRUE; + if (flag_ptr) *flag_ptr |= VM_CALL_ARGS_SPLAT; + RUBY_ASSERT(flag_ptr == NULL || (*flag_ptr & VM_CALL_KW_SPLAT) == 0); + return 1; } case NODE_ARGSCAT: { - if (flag_ptr) *flag_ptr |= VM_CALL_ARGS_SPLAT; - int argc = setup_args_core(iseq, args, argn->nd_head, 1, NULL, NULL); + if (flag_ptr) *flag_ptr |= VM_CALL_ARGS_SPLAT; + int argc = setup_args_core(iseq, args, RNODE_ARGSCAT(argn)->nd_head, dup_rest, NULL, NULL); + bool args_pushed = false; - if (nd_type_p(argn->nd_body, NODE_LIST)) { - int rest_len = compile_args(iseq, args, argn->nd_body, &kwnode); - if (kwnode) rest_len--; - ADD_INSN1(args, argn, newarray, INT2FIX(rest_len)); - } - else { - RUBY_ASSERT(!check_keyword(argn->nd_body)); - NO_CHECK(COMPILE(args, "args (cat: splat)", argn->nd_body)); - } + if (nd_type_p(RNODE_ARGSCAT(argn)->nd_body, NODE_LIST)) { + int rest_len = compile_args(iseq, args, RNODE_ARGSCAT(argn)->nd_body, &kwnode); + if (kwnode) rest_len--; + ADD_INSN1(args, argn, pushtoarray, INT2FIX(rest_len)); + args_pushed = true; + } + else { + RUBY_ASSERT(!check_keyword(RNODE_ARGSCAT(argn)->nd_body)); + NO_CHECK(COMPILE(args, "args (cat: splat)", RNODE_ARGSCAT(argn)->nd_body)); + } - if (nd_type_p(argn->nd_head, NODE_LIST)) { - ADD_INSN1(args, argn, splatarray, Qtrue); - argc += 1; - } - else { - ADD_INSN1(args, argn, splatarray, Qfalse); - ADD_INSN(args, argn, concatarray); - } + if (nd_type_p(RNODE_ARGSCAT(argn)->nd_head, NODE_LIST)) { + ADD_INSN1(args, argn, splatarray, RBOOL(*dup_rest & SPLATARRAY_TRUE)); + if (*dup_rest & SPLATARRAY_TRUE) *dup_rest &= ~SPLATARRAY_TRUE; + argc += 1; + } + else if (!args_pushed) { + ADD_INSN(args, argn, concattoarray); + } - // f(..., *a, ..., k1:1, ...) #=> f(..., *[*a, ...], **{k1:1, ...}) - if (kwnode) { - // kwsplat - *flag_ptr |= VM_CALL_KW_SPLAT; - *flag_ptr |= VM_CALL_KW_SPLAT_MUT; - compile_hash(iseq, args, kwnode, TRUE, FALSE); - argc += 1; - } + // f(..., *a, ..., k1:1, ...) #=> f(..., *[*a, ...], **{k1:1, ...}) + if (kwnode) { + // kwsplat + *flag_ptr |= VM_CALL_KW_SPLAT; + compile_hash(iseq, args, kwnode, TRUE, FALSE); + argc += 1; + } - return argc; + return argc; } case NODE_ARGSPUSH: { - if (flag_ptr) *flag_ptr |= VM_CALL_ARGS_SPLAT; - int argc = setup_args_core(iseq, args, argn->nd_head, 1, NULL, NULL); - - if (nd_type_p(argn->nd_body, NODE_LIST)) { - int rest_len = compile_args(iseq, args, argn->nd_body, &kwnode); - if (kwnode) rest_len--; - ADD_INSN1(args, argn, newarray, INT2FIX(rest_len)); - ADD_INSN1(args, argn, newarray, INT2FIX(1)); - ADD_INSN(args, argn, concatarray); - } - else { - if (keyword_node_p(argn->nd_body)) { - kwnode = argn->nd_body; - } - else { - NO_CHECK(COMPILE(args, "args (cat: splat)", argn->nd_body)); - ADD_INSN1(args, argn, newarray, INT2FIX(1)); - ADD_INSN(args, argn, concatarray); - } - } + if (flag_ptr) *flag_ptr |= VM_CALL_ARGS_SPLAT; + int argc = setup_args_core(iseq, args, RNODE_ARGSPUSH(argn)->nd_head, dup_rest, NULL, NULL); - if (kwnode) { - // f(*a, k:1) - *flag_ptr |= VM_CALL_KW_SPLAT; - if (!keyword_node_single_splat_p(kwnode)) { - *flag_ptr |= VM_CALL_KW_SPLAT_MUT; - } - compile_hash(iseq, args, kwnode, TRUE, FALSE); - argc += 1; - } + if (nd_type_p(RNODE_ARGSPUSH(argn)->nd_body, NODE_LIST)) { + int rest_len = compile_args(iseq, args, RNODE_ARGSPUSH(argn)->nd_body, &kwnode); + if (kwnode) rest_len--; + ADD_INSN1(args, argn, newarray, INT2FIX(rest_len)); + ADD_INSN1(args, argn, pushtoarray, INT2FIX(1)); + } + else { + if (keyword_node_p(RNODE_ARGSPUSH(argn)->nd_body)) { + kwnode = RNODE_ARGSPUSH(argn)->nd_body; + } + else { + NO_CHECK(COMPILE(args, "args (cat: splat)", RNODE_ARGSPUSH(argn)->nd_body)); + ADD_INSN1(args, argn, pushtoarray, INT2FIX(1)); + } + } + + if (kwnode) { + // f(*a, k:1) + *flag_ptr |= VM_CALL_KW_SPLAT; + if (!keyword_node_single_splat_p(kwnode)) { + *flag_ptr |= VM_CALL_KW_SPLAT_MUT; + compile_hash(iseq, args, kwnode, TRUE, FALSE); + } + else if (*dup_rest & DUP_SINGLE_KW_SPLAT) { + compile_single_keyword_splat_mutable(iseq, args, argn, kwnode, flag_ptr); + } + else { + compile_hash(iseq, args, kwnode, TRUE, FALSE); + } + argc += 1; + } - return argc; + return argc; } default: { - UNKNOWN_NODE("setup_arg", argn, Qnil); + UNKNOWN_NODE("setup_arg", argn, Qnil); } } } +static void +setup_args_splat_mut(unsigned int *flag, int dup_rest, int initial_dup_rest) +{ + if ((*flag & VM_CALL_ARGS_SPLAT) && dup_rest != initial_dup_rest) { + *flag |= VM_CALL_ARGS_SPLAT_MUT; + } +} + +static bool +setup_args_dup_rest_p(const NODE *argn) +{ + switch(nd_type(argn)) { + case NODE_LVAR: + case NODE_DVAR: + case NODE_GVAR: + case NODE_IVAR: + case NODE_CVAR: + case NODE_CONST: + case NODE_COLON3: + case NODE_INTEGER: + case NODE_FLOAT: + case NODE_RATIONAL: + case NODE_IMAGINARY: + case NODE_STR: + case NODE_SYM: + case NODE_REGX: + case NODE_SELF: + case NODE_NIL: + case NODE_TRUE: + case NODE_FALSE: + case NODE_LAMBDA: + case NODE_NTH_REF: + case NODE_BACK_REF: + return false; + case NODE_COLON2: + return setup_args_dup_rest_p(RNODE_COLON2(argn)->nd_head); + case NODE_LIST: + while (argn) { + if (setup_args_dup_rest_p(RNODE_LIST(argn)->nd_head)) { + return true; + } + argn = RNODE_LIST(argn)->nd_next; + } + return false; + default: + return true; + } +} + static VALUE setup_args(rb_iseq_t *iseq, LINK_ANCHOR *const args, const NODE *argn, unsigned int *flag, struct rb_callinfo_kwarg **keywords) { VALUE ret; - if (argn && nd_type_p(argn, NODE_BLOCK_PASS)) { - unsigned int dup_rest = 1; - DECL_ANCHOR(arg_block); - INIT_ANCHOR(arg_block); - NO_CHECK(COMPILE(arg_block, "block", argn->nd_body)); + unsigned int dup_rest = SPLATARRAY_TRUE, initial_dup_rest; - *flag |= VM_CALL_ARGS_BLOCKARG; + if (argn) { + const NODE *check_arg = nd_type_p(argn, NODE_BLOCK_PASS) ? + RNODE_BLOCK_PASS(argn)->nd_head : argn; - if (LIST_INSN_SIZE_ONE(arg_block)) { - LINK_ELEMENT *elem = FIRST_ELEMENT(arg_block); - if (IS_INSN(elem)) { - INSN *iobj = (INSN *)elem; - if (iobj->insn_id == BIN(getblockparam)) { - iobj->insn_id = BIN(getblockparamproxy); + if (check_arg) { + switch(nd_type(check_arg)) { + case(NODE_SPLAT): + // avoid caller side array allocation for f(*arg) + dup_rest = SPLATARRAY_FALSE; + break; + case(NODE_ARGSCAT): + // avoid caller side array allocation for f(1, *arg) + dup_rest = !nd_type_p(RNODE_ARGSCAT(check_arg)->nd_head, NODE_LIST); + break; + case(NODE_ARGSPUSH): + // avoid caller side array allocation for f(*arg, **hash) and f(1, *arg, **hash) + dup_rest = !((nd_type_p(RNODE_ARGSPUSH(check_arg)->nd_head, NODE_SPLAT) || + (nd_type_p(RNODE_ARGSPUSH(check_arg)->nd_head, NODE_ARGSCAT) && + nd_type_p(RNODE_ARGSCAT(RNODE_ARGSPUSH(check_arg)->nd_head)->nd_head, NODE_LIST))) && + nd_type_p(RNODE_ARGSPUSH(check_arg)->nd_body, NODE_HASH) && + !RNODE_HASH(RNODE_ARGSPUSH(check_arg)->nd_body)->nd_brace); + + if (dup_rest == SPLATARRAY_FALSE) { + // require allocation for keyword key/value/splat that may modify splatted argument + NODE *node = RNODE_HASH(RNODE_ARGSPUSH(check_arg)->nd_body)->nd_head; + while (node) { + NODE *key_node = RNODE_LIST(node)->nd_head; + if (key_node && setup_args_dup_rest_p(key_node)) { + dup_rest = SPLATARRAY_TRUE; + break; + } + + node = RNODE_LIST(node)->nd_next; + NODE *value_node = RNODE_LIST(node)->nd_head; + if (setup_args_dup_rest_p(value_node)) { + dup_rest = SPLATARRAY_TRUE; + break; + } + + node = RNODE_LIST(node)->nd_next; + } } - dup_rest = 0; + break; + default: + break; } } - ret = INT2FIX(setup_args_core(iseq, args, argn->nd_head, dup_rest, flag, keywords)); - ADD_SEQ(args, arg_block); - } - else { - ret = INT2FIX(setup_args_core(iseq, args, argn, 0, flag, keywords)); + + if (check_arg != argn && setup_args_dup_rest_p(RNODE_BLOCK_PASS(argn)->nd_body)) { + // for block pass that may modify splatted argument, dup rest and kwrest if given + dup_rest = SPLATARRAY_TRUE | DUP_SINGLE_KW_SPLAT; + } } + initial_dup_rest = dup_rest; + + if (argn && nd_type_p(argn, NODE_BLOCK_PASS)) { + DECL_ANCHOR(arg_block); + INIT_ANCHOR(arg_block); + + if (RNODE_BLOCK_PASS(argn)->forwarding && ISEQ_BODY(ISEQ_BODY(iseq)->local_iseq)->param.flags.forwardable) { + int idx = ISEQ_BODY(ISEQ_BODY(iseq)->local_iseq)->local_table_size;// - get_local_var_idx(iseq, idDot3); + + RUBY_ASSERT(nd_type_p(RNODE_BLOCK_PASS(argn)->nd_head, NODE_ARGSPUSH)); + const NODE * arg_node = + RNODE_ARGSPUSH(RNODE_BLOCK_PASS(argn)->nd_head)->nd_head; + + int argc = 0; + + // Only compile leading args: + // foo(x, y, ...) + // ^^^^ + if (nd_type_p(arg_node, NODE_ARGSCAT)) { + argc += setup_args_core(iseq, args, RNODE_ARGSCAT(arg_node)->nd_head, &dup_rest, flag, keywords); + } + + *flag |= VM_CALL_FORWARDING; + + ADD_GETLOCAL(args, argn, idx, get_lvar_level(iseq)); + setup_args_splat_mut(flag, dup_rest, initial_dup_rest); + return INT2FIX(argc); + } + else { + *flag |= VM_CALL_ARGS_BLOCKARG; + + NO_CHECK(COMPILE(arg_block, "block", RNODE_BLOCK_PASS(argn)->nd_body)); + } + + if (LIST_INSN_SIZE_ONE(arg_block)) { + LINK_ELEMENT *elem = FIRST_ELEMENT(arg_block); + if (IS_INSN(elem)) { + INSN *iobj = (INSN *)elem; + if (iobj->insn_id == BIN(getblockparam)) { + iobj->insn_id = BIN(getblockparamproxy); + } + } + } + ret = INT2FIX(setup_args_core(iseq, args, RNODE_BLOCK_PASS(argn)->nd_head, &dup_rest, flag, keywords)); + ADD_SEQ(args, arg_block); + } + else { + ret = INT2FIX(setup_args_core(iseq, args, argn, &dup_rest, flag, keywords)); + } + setup_args_splat_mut(flag, dup_rest, initial_dup_rest); return ret; } @@ -5899,7 +6778,7 @@ build_postexe_iseq(rb_iseq_t *iseq, LINK_ANCHOR *ret, const void *ptr) ADD_INSN1(ret, body, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); ADD_CALL_WITH_BLOCK(ret, body, id_core_set_postexe, argc, block); RB_OBJ_WRITTEN(iseq, Qundef, (VALUE)block); - iseq_set_local_table(iseq, 0); + iseq_set_local_table(iseq, 0, 0); } static void @@ -5919,19 +6798,19 @@ compile_named_capture_assign(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE ADD_INSN(ret, line_node, dup); ADD_INSNL(ret, line_node, branchunless, fail_label); - for (vars = node; vars; vars = vars->nd_next) { + for (vars = node; vars; vars = RNODE_BLOCK(vars)->nd_next) { INSN *cap; - if (vars->nd_next) { + if (RNODE_BLOCK(vars)->nd_next) { ADD_INSN(ret, line_node, dup); } last = ret->last; - NO_CHECK(COMPILE_POPPED(ret, "capture", vars->nd_head)); + NO_CHECK(COMPILE_POPPED(ret, "capture", RNODE_BLOCK(vars)->nd_head)); last = last->next; /* putobject :var */ - cap = new_insn_send(iseq, line_node, idAREF, INT2FIX(1), + cap = new_insn_send(iseq, nd_line(line_node), nd_node_id(line_node), idAREF, INT2FIX(1), NULL, INT2FIX(0), NULL); ELEM_INSERT_PREV(last->next, (LINK_ELEMENT *)cap); #if !defined(NAMED_CAPTURE_SINGLE_OPT) || NAMED_CAPTURE_SINGLE_OPT-0 - if (!vars->nd_next && vars == node) { + if (!RNODE_BLOCK(vars)->nd_next && vars == node) { /* only one name */ DECL_ANCHOR(nom); @@ -5952,9 +6831,9 @@ compile_named_capture_assign(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE ADD_INSNL(ret, line_node, jump, end_label); ADD_LABEL(ret, fail_label); ADD_INSN(ret, line_node, pop); - for (vars = node; vars; vars = vars->nd_next) { + for (vars = node; vars; vars = RNODE_BLOCK(vars)->nd_next) { last = ret->last; - NO_CHECK(COMPILE_POPPED(ret, "capture", vars->nd_head)); + NO_CHECK(COMPILE_POPPED(ret, "capture", RNODE_BLOCK(vars)->nd_head)); last = last->next; /* putobject :var */ ((INSN*)last)->insn_id = BIN(putnil); ((INSN*)last)->operand_size = 0; @@ -5967,8 +6846,10 @@ optimizable_range_item_p(const NODE *n) { if (!n) return FALSE; switch (nd_type(n)) { - case NODE_LIT: - return RB_INTEGER_TYPE_P(n->nd_lit); + case NODE_LINE: + return TRUE; + case NODE_INTEGER: + return TRUE; case NODE_NIL: return TRUE; default: @@ -5976,11 +6857,32 @@ optimizable_range_item_p(const NODE *n) } } +static VALUE +optimized_range_item(const NODE *n) +{ + switch (nd_type(n)) { + case NODE_LINE: + return rb_node_line_lineno_val(n); + case NODE_INTEGER: + return rb_node_integer_literal_val(n); + case NODE_FLOAT: + return rb_node_float_literal_val(n); + case NODE_RATIONAL: + return rb_node_rational_literal_val(n); + case NODE_IMAGINARY: + return rb_node_imaginary_literal_val(n); + case NODE_NIL: + return Qnil; + default: + rb_bug("unexpected node: %s", ruby_node_name(nd_type(n))); + } +} + static int compile_if(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int popped, const enum node_type type) { - const NODE *const node_body = type == NODE_IF ? node->nd_body : node->nd_else; - const NODE *const node_else = type == NODE_IF ? node->nd_else : node->nd_body; + const NODE *const node_body = type == NODE_IF ? RNODE_IF(node)->nd_body : RNODE_UNLESS(node)->nd_else; + const NODE *const node_else = type == NODE_IF ? RNODE_IF(node)->nd_else : RNODE_UNLESS(node)->nd_body; const int line = nd_line(node); const NODE *line_node = node; @@ -5993,11 +6895,16 @@ compile_if(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int else_label = NEW_LABEL(line); end_label = 0; - compile_branch_condition(iseq, cond_seq, node->nd_cond, then_label, else_label); + NODE *cond = RNODE_IF(node)->nd_cond; + if (nd_type(cond) == NODE_BLOCK) { + cond = RNODE_BLOCK(cond)->nd_head; + } + + CHECK(compile_branch_condition(iseq, cond_seq, cond, then_label, else_label)); ADD_SEQ(ret, cond_seq); if (then_label->refcnt && else_label->refcnt) { - branches = decl_branch_base(iseq, node, type == NODE_IF ? "if" : "unless"); + branches = decl_branch_base(iseq, PTR2NUM(node), nd_code_loc(node), type == NODE_IF ? "if" : "unless"); } if (then_label->refcnt) { @@ -6008,10 +6915,12 @@ compile_if(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int CHECK(COMPILE_(then_seq, "then", node_body, popped)); if (else_label->refcnt) { + const NODE *const coverage_node = node_body ? node_body : node; add_trace_branch_coverage( iseq, ret, - node_body ? node_body : node, + nd_code_loc(coverage_node), + nd_node_id(coverage_node), 0, type == NODE_IF ? "then" : "else", branches); @@ -6032,10 +6941,12 @@ compile_if(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int CHECK(COMPILE_(else_seq, "else", node_else, popped)); if (then_label->refcnt) { + const NODE *const coverage_node = node_else ? node_else : node; add_trace_branch_coverage( iseq, ret, - node_else ? node_else : node, + nd_code_loc(coverage_node), + nd_node_id(coverage_node), 1, type == NODE_IF ? "else" : "then", branches); @@ -6073,11 +6984,11 @@ compile_case(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_nod RHASH_TBL_RAW(literals)->type = &cdhash_type; - CHECK(COMPILE(head, "case base", node->nd_head)); + CHECK(COMPILE(head, "case base", RNODE_CASE(node)->nd_head)); - branches = decl_branch_base(iseq, node, "case"); + branches = decl_branch_base(iseq, PTR2NUM(node), nd_code_loc(node), "case"); - node = node->nd_body; + node = RNODE_CASE(node)->nd_body; EXPECT_NODE("NODE_CASE", node, NODE_WHEN, COMPILE_NG); type = nd_type(node); line = nd_line(node); @@ -6094,17 +7005,21 @@ compile_case(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_nod l1 = NEW_LABEL(line); ADD_LABEL(body_seq, l1); ADD_INSN(body_seq, line_node, pop); + + const NODE *const coverage_node = RNODE_WHEN(node)->nd_body ? RNODE_WHEN(node)->nd_body : node; add_trace_branch_coverage( iseq, body_seq, - node->nd_body ? node->nd_body : node, + nd_code_loc(coverage_node), + nd_node_id(coverage_node), branch_id++, "when", branches); - CHECK(COMPILE_(body_seq, "when body", node->nd_body, popped)); + + CHECK(COMPILE_(body_seq, "when body", RNODE_WHEN(node)->nd_body, popped)); ADD_INSNL(body_seq, line_node, jump, endlabel); - vals = node->nd_head; + vals = RNODE_WHEN(node)->nd_head; if (vals) { switch (nd_type(vals)) { case NODE_LIST: @@ -6125,7 +7040,7 @@ compile_case(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_nod EXPECT_NODE_NONULL("NODE_CASE", node, NODE_LIST, COMPILE_NG); } - node = node->nd_next; + node = RNODE_WHEN(node)->nd_next; if (!node) { break; } @@ -6137,7 +7052,7 @@ compile_case(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_nod if (node) { ADD_LABEL(cond_seq, elselabel); ADD_INSN(cond_seq, line_node, pop); - add_trace_branch_coverage(iseq, cond_seq, node, branch_id, "else", branches); + add_trace_branch_coverage(iseq, cond_seq, nd_code_loc(node), nd_node_id(node), branch_id, "else", branches); CHECK(COMPILE_(cond_seq, "else", node, popped)); ADD_INSNL(cond_seq, line_node, jump, endlabel); } @@ -6145,7 +7060,7 @@ compile_case(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_nod debugs("== else (implicit)\n"); ADD_LABEL(cond_seq, elselabel); ADD_INSN(cond_seq, orig_node, pop); - add_trace_branch_coverage(iseq, cond_seq, orig_node, branch_id, "else", branches); + add_trace_branch_coverage(iseq, cond_seq, nd_code_loc(orig_node), nd_node_id(orig_node), branch_id, "else", branches); if (!popped) { ADD_INSN(cond_seq, orig_node, putnil); } @@ -6170,13 +7085,13 @@ compile_case2(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_no { const NODE *vals; const NODE *val; - const NODE *node = orig_node->nd_body; + const NODE *node = RNODE_CASE2(orig_node)->nd_body; LABEL *endlabel; DECL_ANCHOR(body_seq); VALUE branches = Qfalse; int branch_id = 0; - branches = decl_branch_base(iseq, orig_node, "case"); + branches = decl_branch_base(iseq, PTR2NUM(orig_node), nd_code_loc(orig_node), "case"); INIT_ANCHOR(body_seq); endlabel = NEW_LABEL(nd_line(node)); @@ -6185,17 +7100,21 @@ compile_case2(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_no const int line = nd_line(node); LABEL *l1 = NEW_LABEL(line); ADD_LABEL(body_seq, l1); + + const NODE *const coverage_node = RNODE_WHEN(node)->nd_body ? RNODE_WHEN(node)->nd_body : node; add_trace_branch_coverage( iseq, body_seq, - node->nd_body ? node->nd_body : node, + nd_code_loc(coverage_node), + nd_node_id(coverage_node), branch_id++, "when", branches); - CHECK(COMPILE_(body_seq, "when", node->nd_body, popped)); + + CHECK(COMPILE_(body_seq, "when", RNODE_WHEN(node)->nd_body, popped)); ADD_INSNL(body_seq, node, jump, endlabel); - vals = node->nd_head; + vals = RNODE_WHEN(node)->nd_head; if (!vals) { EXPECT_NODE_NONULL("NODE_WHEN", node, NODE_LIST, COMPILE_NG); } @@ -6203,12 +7122,12 @@ compile_case2(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_no case NODE_LIST: while (vals) { LABEL *lnext; - val = vals->nd_head; + val = RNODE_LIST(vals)->nd_head; lnext = NEW_LABEL(nd_line(val)); debug_compile("== when2\n", (void)0); CHECK(compile_branch_condition(iseq, ret, val, l1, lnext)); ADD_LABEL(ret, lnext); - vals = vals->nd_next; + vals = RNODE_LIST(vals)->nd_next; } break; case NODE_SPLAT: @@ -6222,13 +7141,15 @@ compile_case2(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_no default: UNKNOWN_NODE("NODE_WHEN", vals, COMPILE_NG); } - node = node->nd_next; + node = RNODE_WHEN(node)->nd_next; } /* else */ + const NODE *const coverage_node = node ? node : orig_node; add_trace_branch_coverage( iseq, ret, - node ? node : orig_node, + nd_code_loc(coverage_node), + nd_node_id(coverage_node), branch_id, "else", branches); @@ -6314,14 +7235,13 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c * match_failed: * goto unmatched */ - struct rb_ary_pattern_info *apinfo = node->nd_apinfo; - const NODE *args = apinfo->pre_args; - const int pre_args_num = apinfo->pre_args ? rb_long2int(apinfo->pre_args->nd_alen) : 0; - const int post_args_num = apinfo->post_args ? rb_long2int(apinfo->post_args->nd_alen) : 0; + const NODE *args = RNODE_ARYPTN(node)->pre_args; + const int pre_args_num = RNODE_ARYPTN(node)->pre_args ? rb_long2int(RNODE_LIST(RNODE_ARYPTN(node)->pre_args)->as.nd_alen) : 0; + const int post_args_num = RNODE_ARYPTN(node)->post_args ? rb_long2int(RNODE_LIST(RNODE_ARYPTN(node)->post_args)->as.nd_alen) : 0; const int min_argc = pre_args_num + post_args_num; - const int use_rest_num = apinfo->rest_arg && (NODE_NAMED_REST_P(apinfo->rest_arg) || - (!NODE_NAMED_REST_P(apinfo->rest_arg) && post_args_num > 0)); + const int use_rest_num = RNODE_ARYPTN(node)->rest_arg && (NODE_NAMED_REST_P(RNODE_ARYPTN(node)->rest_arg) || + (!NODE_NAMED_REST_P(RNODE_ARYPTN(node)->rest_arg) && post_args_num > 0)); LABEL *match_failed, *type_error, *deconstruct, *deconstructed; int i; @@ -6345,10 +7265,10 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c ADD_INSN(ret, line_node, dup); ADD_SEND(ret, line_node, idLength, INT2FIX(0)); ADD_INSN1(ret, line_node, putobject, INT2FIX(min_argc)); - ADD_SEND(ret, line_node, apinfo->rest_arg ? idGE : idEq, INT2FIX(1)); // (1) + ADD_SEND(ret, line_node, RNODE_ARYPTN(node)->rest_arg ? idGE : idEq, INT2FIX(1)); // (1) if (in_single_pattern) { CHECK(iseq_compile_pattern_set_length_errmsg(iseq, ret, node, - apinfo->rest_arg ? rb_fstring_lit("%p length mismatch (given %p, expected %p+)") : + RNODE_ARYPTN(node)->rest_arg ? rb_fstring_lit("%p length mismatch (given %p, expected %p+)") : rb_fstring_lit("%p length mismatch (given %p, expected %p)"), INT2FIX(min_argc), base_index + 1 /* (1) */)); } @@ -6358,12 +7278,12 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c ADD_INSN(ret, line_node, dup); ADD_INSN1(ret, line_node, putobject, INT2FIX(i)); ADD_SEND(ret, line_node, idAREF, INT2FIX(1)); // (2) - CHECK(iseq_compile_pattern_match(iseq, ret, args->nd_head, match_failed, in_single_pattern, in_alt_pattern, base_index + 1 /* (2) */, false)); - args = args->nd_next; + CHECK(iseq_compile_pattern_match(iseq, ret, RNODE_LIST(args)->nd_head, match_failed, in_single_pattern, in_alt_pattern, base_index + 1 /* (2) */, false)); + args = RNODE_LIST(args)->nd_next; } - if (apinfo->rest_arg) { - if (NODE_NAMED_REST_P(apinfo->rest_arg)) { + if (RNODE_ARYPTN(node)->rest_arg) { + if (NODE_NAMED_REST_P(RNODE_ARYPTN(node)->rest_arg)) { ADD_INSN(ret, line_node, dup); ADD_INSN1(ret, line_node, putobject, INT2FIX(pre_args_num)); ADD_INSN1(ret, line_node, topn, INT2FIX(1)); @@ -6373,7 +7293,7 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c ADD_INSN1(ret, line_node, setn, INT2FIX(4)); ADD_SEND(ret, line_node, idAREF, INT2FIX(2)); // (3) - CHECK(iseq_compile_pattern_match(iseq, ret, apinfo->rest_arg, match_failed, in_single_pattern, in_alt_pattern, base_index + 1 /* (3) */, false)); + CHECK(iseq_compile_pattern_match(iseq, ret, RNODE_ARYPTN(node)->rest_arg, match_failed, in_single_pattern, in_alt_pattern, base_index + 1 /* (3) */, false)); } else { if (post_args_num > 0) { @@ -6387,7 +7307,7 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c } } - args = apinfo->post_args; + args = RNODE_ARYPTN(node)->post_args; for (i = 0; i < post_args_num; i++) { ADD_INSN(ret, line_node, dup); @@ -6396,8 +7316,8 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c ADD_SEND(ret, line_node, idPLUS, INT2FIX(1)); ADD_SEND(ret, line_node, idAREF, INT2FIX(1)); // (4) - CHECK(iseq_compile_pattern_match(iseq, ret, args->nd_head, match_failed, in_single_pattern, in_alt_pattern, base_index + 1 /* (4) */, false)); - args = args->nd_next; + CHECK(iseq_compile_pattern_match(iseq, ret, RNODE_LIST(args)->nd_head, match_failed, in_single_pattern, in_alt_pattern, base_index + 1 /* (4) */, false)); + args = RNODE_LIST(args)->nd_next; } ADD_INSN(ret, line_node, pop); @@ -6475,9 +7395,8 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c * match_failed: * goto unmatched */ - struct rb_fnd_pattern_info *fpinfo = node->nd_fpinfo; - const NODE *args = fpinfo->args; - const int args_num = fpinfo->args ? rb_long2int(fpinfo->args->nd_alen) : 0; + const NODE *args = RNODE_FNDPTN(node)->args; + const int args_num = RNODE_FNDPTN(node)->args ? rb_long2int(RNODE_LIST(RNODE_FNDPTN(node)->args)->as.nd_alen) : 0; LABEL *match_failed, *type_error, *deconstruct, *deconstructed; match_failed = NEW_LABEL(line); @@ -6530,25 +7449,25 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c } ADD_SEND(ret, line_node, idAREF, INT2FIX(1)); // (5) - CHECK(iseq_compile_pattern_match(iseq, ret, args->nd_head, next_loop, in_single_pattern, in_alt_pattern, base_index + 4 /* (2), (3), (4), (5) */, false)); - args = args->nd_next; + CHECK(iseq_compile_pattern_match(iseq, ret, RNODE_LIST(args)->nd_head, next_loop, in_single_pattern, in_alt_pattern, base_index + 4 /* (2), (3), (4), (5) */, false)); + args = RNODE_LIST(args)->nd_next; } - if (NODE_NAMED_REST_P(fpinfo->pre_rest_arg)) { + if (NODE_NAMED_REST_P(RNODE_FNDPTN(node)->pre_rest_arg)) { ADD_INSN1(ret, line_node, topn, INT2FIX(3)); ADD_INSN1(ret, line_node, putobject, INT2FIX(0)); ADD_INSN1(ret, line_node, topn, INT2FIX(2)); ADD_SEND(ret, line_node, idAREF, INT2FIX(2)); // (6) - CHECK(iseq_compile_pattern_match(iseq, ret, fpinfo->pre_rest_arg, find_failed, in_single_pattern, in_alt_pattern, base_index + 4 /* (2), (3), (4), (6) */, false)); + CHECK(iseq_compile_pattern_match(iseq, ret, RNODE_FNDPTN(node)->pre_rest_arg, find_failed, in_single_pattern, in_alt_pattern, base_index + 4 /* (2), (3), (4), (6) */, false)); } - if (NODE_NAMED_REST_P(fpinfo->post_rest_arg)) { + if (NODE_NAMED_REST_P(RNODE_FNDPTN(node)->post_rest_arg)) { ADD_INSN1(ret, line_node, topn, INT2FIX(3)); ADD_INSN1(ret, line_node, topn, INT2FIX(1)); ADD_INSN1(ret, line_node, putobject, INT2FIX(args_num)); ADD_SEND(ret, line_node, idPLUS, INT2FIX(1)); ADD_INSN1(ret, line_node, topn, INT2FIX(3)); ADD_SEND(ret, line_node, idAREF, INT2FIX(2)); // (7) - CHECK(iseq_compile_pattern_match(iseq, ret, fpinfo->post_rest_arg, find_failed, in_single_pattern, in_alt_pattern, base_index + 4 /* (2), (3),(4), (7) */, false)); + CHECK(iseq_compile_pattern_match(iseq, ret, RNODE_FNDPTN(node)->post_rest_arg, find_failed, in_single_pattern, in_alt_pattern, base_index + 4 /* (2), (3),(4), (7) */, false)); } ADD_INSNL(ret, line_node, jump, find_succeeded); @@ -6662,12 +7581,12 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c match_failed = NEW_LABEL(line); type_error = NEW_LABEL(line); - if (node->nd_pkwargs && !node->nd_pkwrestarg) { - const NODE *kw_args = node->nd_pkwargs->nd_head; - keys = rb_ary_new_capa(kw_args ? kw_args->nd_alen/2 : 0); + if (RNODE_HSHPTN(node)->nd_pkwargs && !RNODE_HSHPTN(node)->nd_pkwrestarg) { + const NODE *kw_args = RNODE_HASH(RNODE_HSHPTN(node)->nd_pkwargs)->nd_head; + keys = rb_ary_new_capa(kw_args ? RNODE_LIST(kw_args)->as.nd_alen/2 : 0); while (kw_args) { - rb_ary_push(keys, kw_args->nd_head->nd_lit); - kw_args = kw_args->nd_next->nd_next; + rb_ary_push(keys, get_symbol_value(iseq, RNODE_LIST(kw_args)->nd_head)); + kw_args = RNODE_LIST(RNODE_LIST(kw_args)->nd_next)->nd_next; } } @@ -6694,28 +7613,23 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c ADD_INSN1(ret, line_node, checktype, INT2FIX(T_HASH)); ADD_INSNL(ret, line_node, branchunless, type_error); - if (node->nd_pkwrestarg) { + if (RNODE_HSHPTN(node)->nd_pkwrestarg) { ADD_SEND(ret, line_node, rb_intern("dup"), INT2FIX(0)); } - if (node->nd_pkwargs) { + if (RNODE_HSHPTN(node)->nd_pkwargs) { int i; int keys_num; const NODE *args; - args = node->nd_pkwargs->nd_head; + args = RNODE_HASH(RNODE_HSHPTN(node)->nd_pkwargs)->nd_head; if (args) { DECL_ANCHOR(match_values); INIT_ANCHOR(match_values); - keys_num = rb_long2int(args->nd_alen) / 2; + keys_num = rb_long2int(RNODE_LIST(args)->as.nd_alen) / 2; for (i = 0; i < keys_num; i++) { - NODE *key_node = args->nd_head; - NODE *value_node = args->nd_next->nd_head; - VALUE key; - - if (!nd_type_p(key_node, NODE_LIT)) { - UNKNOWN_NODE("NODE_IN", key_node, COMPILE_NG); - } - key = key_node->nd_lit; + NODE *key_node = RNODE_LIST(args)->nd_head; + NODE *value_node = RNODE_LIST(RNODE_LIST(args)->nd_next)->nd_head; + VALUE key = get_symbol_value(iseq, key_node); ADD_INSN(ret, line_node, dup); ADD_INSN1(ret, line_node, putobject, key); @@ -6744,9 +7658,9 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c ADD_INSN(match_values, line_node, dup); ADD_INSN1(match_values, line_node, putobject, key); - ADD_SEND(match_values, line_node, node->nd_pkwrestarg ? rb_intern("delete") : idAREF, INT2FIX(1)); // (8) + ADD_SEND(match_values, line_node, RNODE_HSHPTN(node)->nd_pkwrestarg ? rb_intern("delete") : idAREF, INT2FIX(1)); // (8) CHECK(iseq_compile_pattern_match(iseq, match_values, value_node, match_failed, in_single_pattern, in_alt_pattern, base_index + 1 /* (8) */, false)); - args = args->nd_next->nd_next; + args = RNODE_LIST(RNODE_LIST(args)->nd_next)->nd_next; } ADD_SEQ(ret, match_values); } @@ -6760,8 +7674,8 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c ADD_INSNL(ret, line_node, branchunless, match_failed); } - if (node->nd_pkwrestarg) { - if (node->nd_pkwrestarg == NODE_SPECIAL_NO_REST_KEYWORD) { + if (RNODE_HSHPTN(node)->nd_pkwrestarg) { + if (RNODE_HSHPTN(node)->nd_pkwrestarg == NODE_SPECIAL_NO_REST_KEYWORD) { ADD_INSN(ret, line_node, dup); ADD_SEND(ret, line_node, idEmptyP, INT2FIX(0)); // (10) if (in_single_pattern) { @@ -6771,7 +7685,7 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c } else { ADD_INSN(ret, line_node, dup); // (11) - CHECK(iseq_compile_pattern_match(iseq, ret, node->nd_pkwrestarg, match_failed, in_single_pattern, in_alt_pattern, base_index + 1 /* (11) */, false)); + CHECK(iseq_compile_pattern_match(iseq, ret, RNODE_HSHPTN(node)->nd_pkwrestarg, match_failed, in_single_pattern, in_alt_pattern, base_index + 1 /* (11) */, false)); } } @@ -6791,7 +7705,15 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c ADD_INSNL(ret, line_node, jump, unmatched); break; } - case NODE_LIT: + case NODE_SYM: + case NODE_REGX: + case NODE_LINE: + case NODE_INTEGER: + case NODE_FLOAT: + case NODE_RATIONAL: + case NODE_IMAGINARY: + case NODE_FILE: + case NODE_ENCODING: case NODE_STR: case NODE_XSTR: case NODE_DSTR: @@ -6815,6 +7737,8 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c case NODE_COLON2: case NODE_COLON3: case NODE_BEGIN: + case NODE_BLOCK: + case NODE_ONCE: CHECK(COMPILE(ret, "case in literal", node)); // (1) if (in_single_pattern) { ADD_INSN1(ret, line_node, dupn, INT2FIX(2)); @@ -6828,7 +7752,7 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c break; case NODE_LASGN: { struct rb_iseq_constant_body *const body = ISEQ_BODY(iseq); - ID id = node->nd_vid; + ID id = RNODE_LASGN(node)->nd_vid; int idx = ISEQ_BODY(body->local_iseq)->local_table_size - get_local_var_idx(iseq, id); if (in_alt_pattern) { @@ -6846,7 +7770,7 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c } case NODE_DASGN: { int idx, lv, ls; - ID id = node->nd_vid; + ID id = RNODE_DASGN(node)->nd_vid; idx = get_dyna_var_idx(iseq, id, &lv, &ls); @@ -6872,8 +7796,8 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c case NODE_UNLESS: { LABEL *match_failed; match_failed = unmatched; - CHECK(iseq_compile_pattern_match(iseq, ret, node->nd_body, unmatched, in_single_pattern, in_alt_pattern, base_index, use_deconstructed_cache)); - CHECK(COMPILE(ret, "case in if", node->nd_cond)); + CHECK(iseq_compile_pattern_match(iseq, ret, RNODE_IF(node)->nd_body, unmatched, in_single_pattern, in_alt_pattern, base_index, use_deconstructed_cache)); + CHECK(COMPILE(ret, "case in if", RNODE_IF(node)->nd_cond)); if (in_single_pattern) { LABEL *match_succeeded; match_succeeded = NEW_LABEL(line); @@ -6910,15 +7834,15 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c LABEL *match_failed; match_failed = NEW_LABEL(line); - n = node->nd_head; - if (! (nd_type_p(n, NODE_LIST) && n->nd_alen == 2)) { + n = RNODE_HASH(node)->nd_head; + if (! (nd_type_p(n, NODE_LIST) && RNODE_LIST(n)->as.nd_alen == 2)) { COMPILE_ERROR(ERROR_ARGS "unexpected node"); return COMPILE_NG; } ADD_INSN(ret, line_node, dup); // (1) - CHECK(iseq_compile_pattern_match(iseq, ret, n->nd_head, match_failed, in_single_pattern, in_alt_pattern, base_index + 1 /* (1) */, use_deconstructed_cache)); - CHECK(iseq_compile_pattern_each(iseq, ret, n->nd_next->nd_head, matched, match_failed, in_single_pattern, in_alt_pattern, base_index, false)); + CHECK(iseq_compile_pattern_match(iseq, ret, RNODE_LIST(n)->nd_head, match_failed, in_single_pattern, in_alt_pattern, base_index + 1 /* (1) */, use_deconstructed_cache)); + CHECK(iseq_compile_pattern_each(iseq, ret, RNODE_LIST(RNODE_LIST(n)->nd_next)->nd_head, matched, match_failed, in_single_pattern, in_alt_pattern, base_index, false)); ADD_INSN(ret, line_node, putnil); ADD_LABEL(ret, match_failed); @@ -6932,13 +7856,13 @@ iseq_compile_pattern_each(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *c fin = NEW_LABEL(line); ADD_INSN(ret, line_node, dup); // (1) - CHECK(iseq_compile_pattern_each(iseq, ret, node->nd_1st, match_succeeded, fin, in_single_pattern, true, base_index + 1 /* (1) */, use_deconstructed_cache)); + CHECK(iseq_compile_pattern_each(iseq, ret, RNODE_OR(node)->nd_1st, match_succeeded, fin, in_single_pattern, true, base_index + 1 /* (1) */, use_deconstructed_cache)); ADD_LABEL(ret, match_succeeded); ADD_INSN(ret, line_node, pop); ADD_INSNL(ret, line_node, jump, matched); ADD_INSN(ret, line_node, putnil); ADD_LABEL(ret, fin); - CHECK(iseq_compile_pattern_each(iseq, ret, node->nd_2nd, matched, unmatched, in_single_pattern, true, base_index, use_deconstructed_cache)); + CHECK(iseq_compile_pattern_each(iseq, ret, RNODE_OR(node)->nd_2nd, matched, unmatched, in_single_pattern, true, base_index, use_deconstructed_cache)); break; } default: @@ -6961,9 +7885,9 @@ iseq_compile_pattern_constant(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NOD { const NODE *line_node = node; - if (node->nd_pconst) { + if (RNODE_ARYPTN(node)->nd_pconst) { ADD_INSN(ret, line_node, dup); // (1) - CHECK(COMPILE(ret, "constant", node->nd_pconst)); // (2) + CHECK(COMPILE(ret, "constant", RNODE_ARYPTN(node)->nd_pconst)); // (2) if (in_single_pattern) { ADD_INSN1(ret, line_node, dupn, INT2FIX(2)); } @@ -7164,14 +8088,14 @@ compile_case3(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_no INIT_ANCHOR(body_seq); INIT_ANCHOR(cond_seq); - branches = decl_branch_base(iseq, node, "case"); + branches = decl_branch_base(iseq, PTR2NUM(node), nd_code_loc(node), "case"); - node = node->nd_body; + node = RNODE_CASE3(node)->nd_body; EXPECT_NODE("NODE_CASE3", node, NODE_IN, COMPILE_NG); type = nd_type(node); line = nd_line(node); line_node = node; - single_pattern = !node->nd_next; + single_pattern = !RNODE_IN(node)->nd_next; endlabel = NEW_LABEL(line); elselabel = NEW_LABEL(line); @@ -7185,7 +8109,7 @@ compile_case3(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_no } ADD_INSN(head, line_node, putnil); /* allocate stack for cached #deconstruct value */ - CHECK(COMPILE(head, "case base", orig_node->nd_head)); + CHECK(COMPILE(head, "case base", RNODE_CASE3(orig_node)->nd_head)); ADD_SEQ(ret, head); /* case VAL */ @@ -7198,17 +8122,21 @@ compile_case3(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_no l1 = NEW_LABEL(line); ADD_LABEL(body_seq, l1); ADD_INSN1(body_seq, line_node, adjuststack, INT2FIX(single_pattern ? 6 : 2)); + + const NODE *const coverage_node = RNODE_IN(node)->nd_body ? RNODE_IN(node)->nd_body : node; add_trace_branch_coverage( iseq, body_seq, - node->nd_body ? node->nd_body : node, + nd_code_loc(coverage_node), + nd_node_id(coverage_node), branch_id++, "in", branches); - CHECK(COMPILE_(body_seq, "in body", node->nd_body, popped)); + + CHECK(COMPILE_(body_seq, "in body", RNODE_IN(node)->nd_body, popped)); ADD_INSNL(body_seq, line_node, jump, endlabel); - pattern = node->nd_head; + pattern = RNODE_IN(node)->nd_head; if (pattern) { int pat_line = nd_line(pattern); LABEL *next_pat = NEW_LABEL(pat_line); @@ -7223,7 +8151,7 @@ compile_case3(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_no return COMPILE_NG; } - node = node->nd_next; + node = RNODE_IN(node)->nd_next; if (!node) { break; } @@ -7236,7 +8164,7 @@ compile_case3(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_no ADD_LABEL(cond_seq, elselabel); ADD_INSN(cond_seq, line_node, pop); ADD_INSN(cond_seq, line_node, pop); /* discard cached #deconstruct value */ - add_trace_branch_coverage(iseq, cond_seq, node, branch_id, "else", branches); + add_trace_branch_coverage(iseq, cond_seq, nd_code_loc(node), nd_node_id(node), branch_id, "else", branches); CHECK(COMPILE_(cond_seq, "else", node, popped)); ADD_INSNL(cond_seq, line_node, jump, endlabel); ADD_INSN(cond_seq, line_node, putnil); @@ -7247,7 +8175,7 @@ compile_case3(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_no else { debugs("== else (implicit)\n"); ADD_LABEL(cond_seq, elselabel); - add_trace_branch_coverage(iseq, cond_seq, orig_node, branch_id, "else", branches); + add_trace_branch_coverage(iseq, cond_seq, nd_code_loc(orig_node), nd_node_id(orig_node), branch_id, "else", branches); ADD_INSN1(cond_seq, orig_node, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); if (single_pattern) { @@ -7265,6 +8193,7 @@ compile_case3(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const orig_no fin = NEW_LABEL(line); kw_arg = rb_xmalloc_mul_add(2, sizeof(VALUE), sizeof(struct rb_callinfo_kwarg)); + kw_arg->references = 0; kw_arg->keyword_len = 2; kw_arg->keywords[0] = ID2SYM(rb_intern("matchee")); kw_arg->keywords[1] = ID2SYM(rb_intern("key")); @@ -7348,7 +8277,7 @@ compile_loop(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, in ISEQ_COMPILE_DATA(iseq)->loopval_popped = 0; push_ensure_entry(iseq, &enl, NULL, NULL); - if (node->nd_state == 1) { + if (RNODE_WHILE(node)->nd_state == 1) { ADD_INSNL(ret, line_node, jump, next_label); } else { @@ -7363,31 +8292,35 @@ compile_loop(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, in if (tmp_label) ADD_LABEL(ret, tmp_label); ADD_LABEL(ret, redo_label); - branches = decl_branch_base(iseq, node, type == NODE_WHILE ? "while" : "until"); + branches = decl_branch_base(iseq, PTR2NUM(node), nd_code_loc(node), type == NODE_WHILE ? "while" : "until"); + + const NODE *const coverage_node = RNODE_WHILE(node)->nd_body ? RNODE_WHILE(node)->nd_body : node; add_trace_branch_coverage( iseq, ret, - node->nd_body ? node->nd_body : node, + nd_code_loc(coverage_node), + nd_node_id(coverage_node), 0, "body", branches); - CHECK(COMPILE_POPPED(ret, "while body", node->nd_body)); + + CHECK(COMPILE_POPPED(ret, "while body", RNODE_WHILE(node)->nd_body)); ADD_LABEL(ret, next_label); /* next */ if (type == NODE_WHILE) { - compile_branch_condition(iseq, ret, node->nd_cond, - redo_label, end_label); + CHECK(compile_branch_condition(iseq, ret, RNODE_WHILE(node)->nd_cond, + redo_label, end_label)); } else { /* until */ - compile_branch_condition(iseq, ret, node->nd_cond, - end_label, redo_label); + CHECK(compile_branch_condition(iseq, ret, RNODE_WHILE(node)->nd_cond, + end_label, redo_label)); } ADD_LABEL(ret, end_label); ADD_ADJUST_RESTORE(ret, adjust_label); - if (UNDEF_P(node->nd_state)) { + if (UNDEF_P(RNODE_WHILE(node)->nd_state)) { /* ADD_INSN(ret, line_node, putundef); */ COMPILE_ERROR(ERROR_ARGS "unsupported: putundef"); return COMPILE_NG; @@ -7429,18 +8362,18 @@ compile_iter(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, in ADD_LABEL(ret, retry_label); if (nd_type_p(node, NODE_FOR)) { - CHECK(COMPILE(ret, "iter caller (for)", node->nd_iter)); + CHECK(COMPILE(ret, "iter caller (for)", RNODE_FOR(node)->nd_iter)); ISEQ_COMPILE_DATA(iseq)->current_block = child_iseq = - NEW_CHILD_ISEQ(node->nd_body, make_name_for_block(iseq), + NEW_CHILD_ISEQ(RNODE_FOR(node)->nd_body, make_name_for_block(iseq), ISEQ_TYPE_BLOCK, line); ADD_SEND_WITH_BLOCK(ret, line_node, idEach, INT2FIX(0), child_iseq); } else { ISEQ_COMPILE_DATA(iseq)->current_block = child_iseq = - NEW_CHILD_ISEQ(node->nd_body, make_name_for_block(iseq), + NEW_CHILD_ISEQ(RNODE_ITER(node)->nd_body, make_name_for_block(iseq), ISEQ_TYPE_BLOCK, line); - CHECK(COMPILE(ret, "iter caller", node->nd_iter)); + CHECK(COMPILE(ret, "iter caller", RNODE_ITER(node)->nd_iter)); } { @@ -7451,11 +8384,11 @@ compile_iter(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, in // Normally, "send" instruction is at the last. // However, qcall under branch coverage measurement adds some instructions after the "send". // - // Note that "invokesuper" appears instead of "send". + // Note that "invokesuper", "invokesuperforward" appears instead of "send". INSN *iobj; LINK_ELEMENT *last_elem = LAST_ELEMENT(ret); iobj = IS_INSN(last_elem) ? (INSN*) last_elem : (INSN*) get_prev_insn((INSN*) last_elem); - while (INSN_OF(iobj) != BIN(send) && INSN_OF(iobj) != BIN(invokesuper)) { + while (!IS_INSN_ID(iobj, send) && !IS_INSN_ID(iobj, invokesuper) && !IS_INSN_ID(iobj, sendforward) && !IS_INSN_ID(iobj, invokesuperforward)) { iobj = (INSN*) get_prev_insn(iobj); } ELEM_INSERT_NEXT(&iobj->link, (LINK_ELEMENT*) retry_end_l); @@ -7484,7 +8417,7 @@ compile_for_masgn(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const nod * (args.length == 1 && Array.try_convert(args[0])) || args */ const NODE *line_node = node; - const NODE *var = node->nd_var; + const NODE *var = RNODE_FOR_MASGN(node)->nd_var; LABEL *not_single = NEW_LABEL(nd_line(var)); LABEL *not_ary = NEW_LABEL(nd_line(var)); CHECK(COMPILE(ret, "for var", var)); @@ -7519,7 +8452,7 @@ compile_break(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, i LABEL *splabel = NEW_LABEL(0); ADD_LABEL(ret, splabel); ADD_ADJUST(ret, line_node, ISEQ_COMPILE_DATA(iseq)->redo_label); - CHECK(COMPILE_(ret, "break val (while/until)", node->nd_stts, + CHECK(COMPILE_(ret, "break val (while/until)", RNODE_BREAK(node)->nd_stts, ISEQ_COMPILE_DATA(iseq)->loopval_popped)); add_ensure_iseq(ret, iseq, 0); ADD_INSNL(ret, line_node, jump, ISEQ_COMPILE_DATA(iseq)->end_label); @@ -7554,7 +8487,7 @@ compile_break(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, i } /* escape from block */ - CHECK(COMPILE(ret, "break val (block)", node->nd_stts)); + CHECK(COMPILE(ret, "break val (block)", RNODE_BREAK(node)->nd_stts)); ADD_INSN1(ret, line_node, throw, INT2FIX(throw_flag | TAG_BREAK)); if (popped) { ADD_INSN(ret, line_node, pop); @@ -7577,7 +8510,7 @@ compile_next(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, in LABEL *splabel = NEW_LABEL(0); debugs("next in while loop\n"); ADD_LABEL(ret, splabel); - CHECK(COMPILE(ret, "next val/valid syntax?", node->nd_stts)); + CHECK(COMPILE(ret, "next val/valid syntax?", RNODE_NEXT(node)->nd_stts)); add_ensure_iseq(ret, iseq, 0); ADD_ADJUST(ret, line_node, ISEQ_COMPILE_DATA(iseq)->redo_label); ADD_INSNL(ret, line_node, jump, ISEQ_COMPILE_DATA(iseq)->start_label); @@ -7591,11 +8524,10 @@ compile_next(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, in debugs("next in block\n"); ADD_LABEL(ret, splabel); ADD_ADJUST(ret, line_node, ISEQ_COMPILE_DATA(iseq)->start_label); - CHECK(COMPILE(ret, "next val", node->nd_stts)); + CHECK(COMPILE(ret, "next val", RNODE_NEXT(node)->nd_stts)); add_ensure_iseq(ret, iseq, 0); ADD_INSNL(ret, line_node, jump, ISEQ_COMPILE_DATA(iseq)->end_label); ADD_ADJUST_RESTORE(ret, splabel); - splabel->unremovable = FALSE; if (!popped) { ADD_INSN(ret, line_node, putnil); @@ -7626,7 +8558,7 @@ compile_next(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, in ip = ISEQ_BODY(ip)->parent_iseq; } if (ip != 0) { - CHECK(COMPILE(ret, "next val", node->nd_stts)); + CHECK(COMPILE(ret, "next val", RNODE_NEXT(node)->nd_stts)); ADD_INSN1(ret, line_node, throw, INT2FIX(throw_flag | TAG_NEXT)); if (popped) { @@ -7738,7 +8670,7 @@ compile_rescue(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, LABEL *lstart = NEW_LABEL(line); LABEL *lend = NEW_LABEL(line); LABEL *lcont = NEW_LABEL(line); - const rb_iseq_t *rescue = NEW_CHILD_ISEQ(node->nd_resq, + const rb_iseq_t *rescue = NEW_CHILD_ISEQ(RNODE_RESCUE(node)->nd_resq, rb_str_concat(rb_str_new2("rescue in "), ISEQ_BODY(iseq)->location.label), ISEQ_TYPE_RESCUE, line); @@ -7750,14 +8682,14 @@ compile_rescue(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, bool prev_in_rescue = ISEQ_COMPILE_DATA(iseq)->in_rescue; ISEQ_COMPILE_DATA(iseq)->in_rescue = true; { - CHECK(COMPILE(ret, "rescue head", node->nd_head)); + CHECK(COMPILE(ret, "rescue head", RNODE_RESCUE(node)->nd_head)); } ISEQ_COMPILE_DATA(iseq)->in_rescue = prev_in_rescue; ADD_LABEL(ret, lend); - if (node->nd_else) { + if (RNODE_RESCUE(node)->nd_else) { ADD_INSN(ret, line_node, pop); - CHECK(COMPILE(ret, "rescue else", node->nd_else)); + CHECK(COMPILE(ret, "rescue else", RNODE_RESCUE(node)->nd_else)); } ADD_INSN(ret, line_node, nop); ADD_LABEL(ret, lcont); @@ -7785,16 +8717,16 @@ compile_resbody(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, label_miss = NEW_LABEL(line); label_hit = NEW_LABEL(line); - narg = resq->nd_args; + narg = RNODE_RESBODY(resq)->nd_args; if (narg) { switch (nd_type(narg)) { case NODE_LIST: while (narg) { ADD_GETLOCAL(ret, line_node, LVAR_ERRINFO, 0); - CHECK(COMPILE(ret, "rescue arg", narg->nd_head)); + CHECK(COMPILE(ret, "rescue arg", RNODE_LIST(narg)->nd_head)); ADD_INSN1(ret, line_node, checkmatch, INT2FIX(VM_CHECKMATCH_TYPE_RESCUE)); ADD_INSNL(ret, line_node, branchif, label_hit); - narg = narg->nd_next; + narg = RNODE_LIST(narg)->nd_next; } break; case NODE_SPLAT: @@ -7819,14 +8751,16 @@ compile_resbody(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, ADD_LABEL(ret, label_hit); ADD_TRACE(ret, RUBY_EVENT_RESCUE); - if (nd_type(resq->nd_body) == NODE_BEGIN && resq->nd_body->nd_body == NULL) { + if (RNODE_RESBODY(resq)->nd_exc_var) { + CHECK(COMPILE_POPPED(ret, "resbody exc_var", RNODE_RESBODY(resq)->nd_exc_var)); + } + + if (nd_type(RNODE_RESBODY(resq)->nd_body) == NODE_BEGIN && RNODE_BEGIN(RNODE_RESBODY(resq)->nd_body)->nd_body == NULL && !RNODE_RESBODY(resq)->nd_exc_var) { // empty body - int lineno = nd_line(resq->nd_body); - NODE dummy_line_node = generate_dummy_line_node(lineno, -1); - ADD_INSN(ret, &dummy_line_node, putnil); + ADD_SYNTHETIC_INSN(ret, nd_line(RNODE_RESBODY(resq)->nd_body), -1, putnil); } else { - CHECK(COMPILE(ret, "resbody body", resq->nd_body)); + CHECK(COMPILE(ret, "resbody body", RNODE_RESBODY(resq)->nd_body)); } if (ISEQ_COMPILE_DATA(iseq)->option->tailcall_optimization) { @@ -7834,7 +8768,7 @@ compile_resbody(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, } ADD_INSN(ret, line_node, leave); ADD_LABEL(ret, label_miss); - resq = resq->nd_head; + resq = RNODE_RESBODY(resq)->nd_next; } return COMPILE_OK; } @@ -7842,10 +8776,10 @@ compile_resbody(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, static int compile_ensure(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int popped) { - const int line = nd_line(node); + const int line = nd_line(RNODE_ENSURE(node)->nd_ensr); const NODE *line_node = node; DECL_ANCHOR(ensr); - const rb_iseq_t *ensure = NEW_CHILD_ISEQ(node->nd_ensr, + const rb_iseq_t *ensure = NEW_CHILD_ISEQ(RNODE_ENSURE(node)->nd_ensr, rb_str_concat(rb_str_new2 ("ensure in "), ISEQ_BODY(iseq)->location.label), ISEQ_TYPE_ENSURE, line); LABEL *lstart = NEW_LABEL(line); @@ -7858,17 +8792,17 @@ compile_ensure(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, struct ensure_range *erange; INIT_ANCHOR(ensr); - CHECK(COMPILE_POPPED(ensr, "ensure ensr", node->nd_ensr)); + CHECK(COMPILE_POPPED(ensr, "ensure ensr", RNODE_ENSURE(node)->nd_ensr)); last = ensr->last; last_leave = last && IS_INSN(last) && IS_INSN_ID(last, leave); er.begin = lstart; er.end = lend; er.next = 0; - push_ensure_entry(iseq, &enl, &er, node->nd_ensr); + push_ensure_entry(iseq, &enl, &er, RNODE_ENSURE(node)->nd_ensr); ADD_LABEL(ret, lstart); - CHECK(COMPILE_(ret, "ensure head", node->nd_head, (popped | last_leave))); + CHECK(COMPILE_(ret, "ensure head", RNODE_ENSURE(node)->nd_head, (popped | last_leave))); ADD_LABEL(ret, lend); ADD_SEQ(ret, ensr); if (!popped && last_leave) ADD_INSN(ret, line_node, putnil); @@ -7897,7 +8831,7 @@ compile_return(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, enum rb_iseq_type type = ISEQ_BODY(iseq)->type; const rb_iseq_t *is = iseq; enum rb_iseq_type t = type; - const NODE *retval = node->nd_stts; + const NODE *retval = RNODE_RETURN(node)->nd_stts; LABEL *splabel = 0; while (t == ISEQ_TYPE_RESCUE || t == ISEQ_TYPE_ENSURE) { @@ -7947,6 +8881,27 @@ compile_return(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, return COMPILE_OK; } +static bool +drop_unreachable_return(LINK_ANCHOR *ret) +{ + LINK_ELEMENT *i = ret->last, *last; + if (!i) return false; + if (IS_TRACE(i)) i = i->prev; + if (!IS_INSN(i) || !IS_INSN_ID(i, putnil)) return false; + last = i = i->prev; + if (IS_ADJUST(i)) i = i->prev; + if (!IS_INSN(i)) return false; + switch (INSN_OF(i)) { + case BIN(leave): + case BIN(jump): + break; + default: + return false; + } + (ret->last = last->prev)->next = NULL; + return true; +} + static int compile_evstr(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int popped) { @@ -7980,11 +8935,11 @@ qcall_branch_start(rb_iseq_t *iseq, LINK_ANCHOR *const recv, VALUE *branches, co LABEL *else_label = NEW_LABEL(nd_line(line_node)); VALUE br = 0; - br = decl_branch_base(iseq, node, "&."); + br = decl_branch_base(iseq, PTR2NUM(node), nd_code_loc(node), "&."); *branches = br; ADD_INSN(recv, line_node, dup); ADD_INSNL(recv, line_node, branchnil, else_label); - add_trace_branch_coverage(iseq, recv, node, 0, "then", br); + add_trace_branch_coverage(iseq, recv, nd_code_loc(node), nd_node_id(node), 0, "then", br); return else_label; } @@ -7996,7 +8951,7 @@ qcall_branch_end(rb_iseq_t *iseq, LINK_ANCHOR *const ret, LABEL *else_label, VAL end_label = NEW_LABEL(nd_line(line_node)); ADD_INSNL(ret, line_node, jump, end_label); ADD_LABEL(ret, else_label); - add_trace_branch_coverage(iseq, ret, node, 1, "else", branches); + add_trace_branch_coverage(iseq, ret, nd_code_loc(node), nd_node_id(node), 1, "else", branches); ADD_LABEL(ret, end_label); } @@ -8006,13 +8961,14 @@ compile_call_precheck_freeze(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE /* optimization shortcut * "literal".freeze -> opt_str_freeze("literal") */ - if (node->nd_recv && nd_type_p(node->nd_recv, NODE_STR) && - (node->nd_mid == idFreeze || node->nd_mid == idUMinus) && - node->nd_args == NULL && + if (get_nd_recv(node) && + (nd_type_p(get_nd_recv(node), NODE_STR) || nd_type_p(get_nd_recv(node), NODE_FILE)) && + (get_node_call_nd_mid(node) == idFreeze || get_node_call_nd_mid(node) == idUMinus) && + get_nd_args(node) == NULL && ISEQ_COMPILE_DATA(iseq)->current_block == NULL && ISEQ_COMPILE_DATA(iseq)->option->specialized_instruction) { - VALUE str = rb_fstring(node->nd_recv->nd_lit); - if (node->nd_mid == idUMinus) { + VALUE str = get_string_value(get_nd_recv(node)); + if (get_node_call_nd_mid(node) == idUMinus) { ADD_INSN2(ret, line_node, opt_str_uminus, str, new_callinfo(iseq, idUMinus, 0, 0, NULL, FALSE)); } @@ -8029,14 +8985,14 @@ compile_call_precheck_freeze(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE /* optimization shortcut * obj["literal"] -> opt_aref_with(obj, "literal") */ - if (node->nd_mid == idAREF && !private_recv_p(node) && node->nd_args && - nd_type_p(node->nd_args, NODE_LIST) && node->nd_args->nd_alen == 1 && - nd_type_p(node->nd_args->nd_head, NODE_STR) && + if (get_node_call_nd_mid(node) == idAREF && !private_recv_p(node) && get_nd_args(node) && + nd_type_p(get_nd_args(node), NODE_LIST) && RNODE_LIST(get_nd_args(node))->as.nd_alen == 1 && + (nd_type_p(RNODE_LIST(get_nd_args(node))->nd_head, NODE_STR) || nd_type_p(RNODE_LIST(get_nd_args(node))->nd_head, NODE_FILE)) && ISEQ_COMPILE_DATA(iseq)->current_block == NULL && - !ISEQ_COMPILE_DATA(iseq)->option->frozen_string_literal && + !frozen_string_literal_p(iseq) && ISEQ_COMPILE_DATA(iseq)->option->specialized_instruction) { - VALUE str = rb_fstring(node->nd_args->nd_head->nd_lit); - CHECK(COMPILE(ret, "recv", node->nd_recv)); + VALUE str = get_string_value(RNODE_LIST(get_nd_args(node))->nd_head); + CHECK(COMPILE(ret, "recv", get_nd_recv(node))); ADD_INSN2(ret, line_node, opt_aref_with, str, new_callinfo(iseq, idAREF, 1, 0, NULL, FALSE)); RB_OBJ_WRITTEN(iseq, Qundef, str); @@ -8079,12 +9035,12 @@ iseq_builtin_function_name(const enum node_type type, const NODE *recv, ID mid) if (recv) { switch (nd_type(recv)) { case NODE_VCALL: - if (recv->nd_mid == rb_intern("__builtin")) { + if (RNODE_VCALL(recv)->nd_mid == rb_intern("__builtin")) { return name; } break; case NODE_CONST: - if (recv->nd_vid == rb_intern("Primitive")) { + if (RNODE_CONST(recv)->nd_vid == rb_intern("Primitive")) { return name; } break; @@ -8174,21 +9130,33 @@ compile_builtin_attr(rb_iseq_t *iseq, const NODE *node) if (!node) goto no_arg; while (node) { if (!nd_type_p(node, NODE_LIST)) goto bad_arg; - const NODE *next = node->nd_next; + const NODE *next = RNODE_LIST(node)->nd_next; - node = node->nd_head; + node = RNODE_LIST(node)->nd_head; if (!node) goto no_arg; - if (!nd_type_p(node, NODE_LIT)) goto bad_arg; + switch (nd_type(node)) { + case NODE_SYM: + symbol = rb_node_sym_string_val(node); + break; + default: + goto bad_arg; + } - symbol = node->nd_lit; if (!SYMBOL_P(symbol)) goto non_symbol_arg; - string = rb_sym_to_s(symbol); + string = rb_sym2str(symbol); if (strcmp(RSTRING_PTR(string), "leaf") == 0) { ISEQ_BODY(iseq)->builtin_attrs |= BUILTIN_ATTR_LEAF; } - else if (strcmp(RSTRING_PTR(string), "no_gc") == 0) { - ISEQ_BODY(iseq)->builtin_attrs |= BUILTIN_ATTR_NO_GC; + else if (strcmp(RSTRING_PTR(string), "inline_block") == 0) { + ISEQ_BODY(iseq)->builtin_attrs |= BUILTIN_ATTR_INLINE_BLOCK; + } + else if (strcmp(RSTRING_PTR(string), "use_block") == 0) { + iseq_set_use_block(iseq); + } + else if (strcmp(RSTRING_PTR(string), "c_trace") == 0) { + // Let the iseq act like a C method in backtraces + ISEQ_BODY(iseq)->builtin_attrs |= BUILTIN_ATTR_C_TRACE; } else { goto unknown_arg; @@ -8212,13 +9180,20 @@ compile_builtin_attr(rb_iseq_t *iseq, const NODE *node) static int compile_builtin_arg(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *node, const NODE *line_node, int popped) { + VALUE name; + if (!node) goto no_arg; if (!nd_type_p(node, NODE_LIST)) goto bad_arg; - if (node->nd_next) goto too_many_arg; - node = node->nd_head; + if (RNODE_LIST(node)->nd_next) goto too_many_arg; + node = RNODE_LIST(node)->nd_head; if (!node) goto no_arg; - if (!nd_type_p(node, NODE_LIT)) goto bad_arg; - VALUE name = node->nd_lit; + switch (nd_type(node)) { + case NODE_SYM: + name = rb_node_sym_string_val(node); + break; + default: + goto bad_arg; + } if (!SYMBOL_P(name)) goto non_symbol_arg; if (!popped) { compile_lvar(iseq, ret, line_node, SYM2ID(name)); @@ -8242,8 +9217,8 @@ static NODE * mandatory_node(const rb_iseq_t *iseq, const NODE *cond_node) { const NODE *node = ISEQ_COMPILE_DATA(iseq)->root_node; - if (nd_type(node) == NODE_IF && node->nd_cond == cond_node) { - return node->nd_body; + if (nd_type(node) == NODE_IF && RNODE_IF(node)->nd_cond == cond_node) { + return RNODE_IF(node)->nd_body; } else { rb_bug("mandatory_node: can't find mandatory node"); @@ -8257,8 +9232,9 @@ compile_builtin_mandatory_only_method(rb_iseq_t *iseq, const NODE *node, const N struct rb_args_info args = { .pre_args_num = ISEQ_BODY(iseq)->param.lead_num, }; - NODE args_node; - rb_node_init(&args_node, NODE_ARGS, 0, 0, (VALUE)&args); + rb_node_args_t args_node; + rb_node_init(RNODE(&args_node), NODE_ARGS); + args_node.nd_ainfo = args; // local table without non-mandatory parameters const int skip_local_size = ISEQ_BODY(iseq)->param.size - ISEQ_BODY(iseq)->param.lead_num; @@ -8279,21 +9255,21 @@ compile_builtin_mandatory_only_method(rb_iseq_t *iseq, const NODE *node, const N tbl->ids[i] = ISEQ_BODY(iseq)->local_table[i + skip_local_size]; } - NODE scope_node; - rb_node_init(&scope_node, NODE_SCOPE, (VALUE)tbl, (VALUE)mandatory_node(iseq, node), (VALUE)&args_node); + rb_node_scope_t scope_node; + rb_node_init(RNODE(&scope_node), NODE_SCOPE); + scope_node.nd_tbl = tbl; + scope_node.nd_body = mandatory_node(iseq, node); + scope_node.nd_args = &args_node; - rb_ast_body_t ast = { - .root = &scope_node, - .frozen_string_literal = -1, - .coverage_enabled = -1, - .script_lines = ISEQ_BODY(iseq)->variable.script_lines, - }; + VALUE ast_value = rb_ruby_ast_new(RNODE(&scope_node)); - ISEQ_BODY(iseq)->mandatory_only_iseq = - rb_iseq_new_with_opt(&ast, rb_iseq_base_label(iseq), + const rb_iseq_t *mandatory_only_iseq = + rb_iseq_new_with_opt(ast_value, rb_iseq_base_label(iseq), rb_iseq_path(iseq), rb_iseq_realpath(iseq), nd_line(line_node), NULL, 0, - ISEQ_TYPE_METHOD, ISEQ_COMPILE_DATA(iseq)->option); + ISEQ_TYPE_METHOD, ISEQ_COMPILE_DATA(iseq)->option, + ISEQ_BODY(iseq)->variable.script_lines); + RB_OBJ_WRITE(iseq, &ISEQ_BODY(iseq)->mandatory_only_iseq, (VALUE)mandatory_only_iseq); ALLOCV_END(idtmp); return COMPILE_OK; @@ -8303,7 +9279,7 @@ static int compile_builtin_function_call(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, const NODE *line_node, int popped, const rb_iseq_t *parent_block, LINK_ANCHOR *args, const char *builtin_func) { - NODE *args_node = node->nd_args; + NODE *args_node = get_nd_args(node); if (parent_block != NULL) { COMPILE_ERROR(ERROR_ARGS_AT(line_node) "should not call builtins here."); @@ -8326,7 +9302,6 @@ compile_builtin_function_call(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NOD } else if (strcmp("cinit!", builtin_func) == 0) { // ignore - GET_VM()->builtin_inline_index++; return COMPILE_OK; } else if (strcmp("attr!", builtin_func) == 0) { @@ -8354,10 +9329,7 @@ compile_builtin_function_call(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NOD return COMPILE_NG; } - if (GET_VM()->builtin_inline_index == INT_MAX) { - rb_bug("builtin inline function index overflow:%s", builtin_func); - } - int inline_index = GET_VM()->builtin_inline_index++; + int inline_index = nd_line(node); snprintf(inline_func, sizeof(inline_func), BUILTIN_INLINE_PREFIX "%d", inline_index); builtin_func = inline_func; args_node = NULL; @@ -8366,7 +9338,7 @@ compile_builtin_function_call(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NOD if (cconst) { typedef VALUE(*builtin_func0)(void *, VALUE); - VALUE const_val = (*(builtin_func0)bf->func_ptr)(NULL, Qnil); + VALUE const_val = (*(builtin_func0)(uintptr_t)bf->func_ptr)(NULL, Qnil); ADD_INSN1(ret, line_node, putobject, const_val); return COMPILE_OK; } @@ -8406,7 +9378,7 @@ compile_call(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, co */ DECL_ANCHOR(recv); DECL_ANCHOR(args); - ID mid = node->nd_mid; + ID mid = get_node_call_nd_mid(node); VALUE argc; unsigned int flag = 0; struct rb_callinfo_kwarg *keywords = NULL; @@ -8418,6 +9390,7 @@ compile_call(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, co INIT_ANCHOR(recv); INIT_ANCHOR(args); + #if OPT_SUPPORT_JOKE if (nd_type_p(node, NODE_VCALL)) { ID id_bitblt; @@ -8454,20 +9427,7 @@ compile_call(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, co labels_table = st_init_numtable(); ISEQ_COMPILE_DATA(iseq)->labels_table = labels_table; } - if (nd_type_p(node->nd_args->nd_head, NODE_LIT) && - SYMBOL_P(node->nd_args->nd_head->nd_lit)) { - - label_name = node->nd_args->nd_head->nd_lit; - if (!st_lookup(labels_table, (st_data_t)label_name, &data)) { - label = NEW_LABEL(nd_line(line_node)); - label->position = nd_line(line_node); - st_insert(labels_table, (st_data_t)label_name, (st_data_t)label); - } - else { - label = (LABEL *)data; - } - } - else { + { COMPILE_ERROR(ERROR_ARGS "invalid goto/label format"); return COMPILE_NG; } @@ -8485,7 +9445,7 @@ compile_call(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, co const char *builtin_func; if (UNLIKELY(iseq_has_builtin_function_table(iseq)) && - (builtin_func = iseq_builtin_function_name(type, node->nd_recv, mid)) != NULL) { + (builtin_func = iseq_builtin_function_name(type, get_nd_recv(node), mid)) != NULL) { return compile_builtin_function_call(iseq, ret, node, line_node, popped, parent_block, args, builtin_func); } @@ -8495,16 +9455,16 @@ compile_call(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, co int idx, level; if (mid == idCall && - nd_type_p(node->nd_recv, NODE_LVAR) && - iseq_block_param_id_p(iseq, node->nd_recv->nd_vid, &idx, &level)) { - ADD_INSN2(recv, node->nd_recv, getblockparamproxy, INT2FIX(idx + VM_ENV_DATA_SIZE - 1), INT2FIX(level)); + nd_type_p(get_nd_recv(node), NODE_LVAR) && + iseq_block_param_id_p(iseq, RNODE_LVAR(get_nd_recv(node))->nd_vid, &idx, &level)) { + ADD_INSN2(recv, get_nd_recv(node), getblockparamproxy, INT2FIX(idx + VM_ENV_DATA_SIZE - 1), INT2FIX(level)); } else if (private_recv_p(node)) { ADD_INSN(recv, node, putself); flag |= VM_CALL_FCALL; } else { - CHECK(COMPILE(recv, "recv", node->nd_recv)); + CHECK(COMPILE(recv, "recv", get_nd_recv(node))); } if (type == NODE_QCALL) { @@ -8518,7 +9478,7 @@ compile_call(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, co /* args */ if (type != NODE_VCALL) { - argc = setup_args(iseq, args, node->nd_args, &flag, &keywords); + argc = setup_args(iseq, args, get_nd_args(node), &flag, &keywords); CHECK(!NIL_P(argc)); } else { @@ -8526,6 +9486,17 @@ compile_call(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, co } ADD_SEQ(ret, recv); + + bool inline_new = ISEQ_COMPILE_DATA(iseq)->option->specialized_instruction && + mid == rb_intern("new") && + parent_block == NULL && + !(flag & VM_CALL_ARGS_BLOCKARG); + + if (inline_new) { + ADD_INSN(ret, node, putnil); + ADD_INSN(ret, node, swap); + } + ADD_SEQ(ret, args); debugp_param("call args argc", argc); @@ -8539,7 +9510,40 @@ compile_call(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, co flag |= VM_CALL_FCALL; } - ADD_SEND_R(ret, line_node, mid, argc, parent_block, INT2FIX(flag), keywords); + if ((flag & VM_CALL_ARGS_BLOCKARG) && (flag & VM_CALL_KW_SPLAT) && !(flag & VM_CALL_KW_SPLAT_MUT)) { + ADD_INSN(ret, line_node, splatkw); + } + + LABEL *not_basic_new = NEW_LABEL(nd_line(node)); + LABEL *not_basic_new_finish = NEW_LABEL(nd_line(node)); + + if (inline_new) { + // Jump unless the receiver uses the "basic" implementation of "new" + VALUE ci; + if (flag & VM_CALL_FORWARDING) { + ci = (VALUE)new_callinfo(iseq, mid, NUM2INT(argc) + 1, flag, keywords, 0); + } + else { + ci = (VALUE)new_callinfo(iseq, mid, NUM2INT(argc), flag, keywords, 0); + } + ADD_INSN2(ret, node, opt_new, ci, not_basic_new); + LABEL_REF(not_basic_new); + + // optimized path + ADD_SEND_R(ret, line_node, rb_intern("initialize"), argc, parent_block, INT2FIX(flag | VM_CALL_FCALL), keywords); + ADD_INSNL(ret, line_node, jump, not_basic_new_finish); + + ADD_LABEL(ret, not_basic_new); + // Fall back to normal send + ADD_SEND_R(ret, line_node, mid, argc, parent_block, INT2FIX(flag), keywords); + ADD_INSN(ret, line_node, swap); + + ADD_LABEL(ret, not_basic_new_finish); + ADD_INSN(ret, line_node, pop); + } + else { + ADD_SEND_R(ret, line_node, mid, argc, parent_block, INT2FIX(flag), keywords); + } qcall_branch_end(iseq, ret, else_label, branches, node, line_node); if (popped) { @@ -8555,8 +9559,7 @@ compile_op_asgn1(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node VALUE argc; unsigned int flag = 0; int asgnflag = 0; - ID id = node->nd_mid; - int boff = 0; + ID id = RNODE_OP_ASGN1(node)->nd_mid; /* * a[x] (op)= y @@ -8584,22 +9587,20 @@ compile_op_asgn1(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node if (!popped) { ADD_INSN(ret, node, putnil); } - asgnflag = COMPILE_RECV(ret, "NODE_OP_ASGN1 recv", node); + asgnflag = COMPILE_RECV(ret, "NODE_OP_ASGN1 recv", node, RNODE_OP_ASGN1(node)->nd_recv); CHECK(asgnflag != -1); - switch (nd_type(node->nd_args->nd_head)) { + switch (nd_type(RNODE_OP_ASGN1(node)->nd_index)) { case NODE_ZLIST: argc = INT2FIX(0); break; - case NODE_BLOCK_PASS: - boff = 1; - /* fall through */ default: - argc = setup_args(iseq, ret, node->nd_args->nd_head, &flag, NULL); + argc = setup_args(iseq, ret, RNODE_OP_ASGN1(node)->nd_index, &flag, NULL); CHECK(!NIL_P(argc)); } - ADD_INSN1(ret, node, dupn, FIXNUM_INC(argc, 1 + boff)); + int dup_argn = FIX2INT(argc) + 1; + ADD_INSN1(ret, node, dupn, INT2FIX(dup_argn)); flag |= asgnflag; - ADD_SEND_WITH_FLAG(ret, node, idAREF, argc, INT2FIX(flag)); + ADD_SEND_R(ret, node, idAREF, argc, NULL, INT2FIX(flag & ~VM_CALL_ARGS_SPLAT_MUT), NULL); if (id == idOROP || id == idANDOP) { /* a[x] ||= y or a[x] &&= y @@ -8622,64 +9623,63 @@ compile_op_asgn1(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node } ADD_INSN(ret, node, pop); - CHECK(COMPILE(ret, "NODE_OP_ASGN1 args->body: ", node->nd_args->nd_body)); + CHECK(COMPILE(ret, "NODE_OP_ASGN1 nd_rvalue: ", RNODE_OP_ASGN1(node)->nd_rvalue)); if (!popped) { - ADD_INSN1(ret, node, setn, FIXNUM_INC(argc, 2+boff)); + ADD_INSN1(ret, node, setn, INT2FIX(dup_argn+1)); } if (flag & VM_CALL_ARGS_SPLAT) { - ADD_INSN1(ret, node, newarray, INT2FIX(1)); - if (boff > 0) { - ADD_INSN1(ret, node, dupn, INT2FIX(3)); + if (!(flag & VM_CALL_ARGS_SPLAT_MUT)) { ADD_INSN(ret, node, swap); - ADD_INSN(ret, node, pop); - } - ADD_INSN(ret, node, concatarray); - if (boff > 0) { - ADD_INSN1(ret, node, setn, INT2FIX(3)); - ADD_INSN(ret, node, pop); - ADD_INSN(ret, node, pop); + ADD_INSN1(ret, node, splatarray, Qtrue); + ADD_INSN(ret, node, swap); + flag |= VM_CALL_ARGS_SPLAT_MUT; } - ADD_SEND_WITH_FLAG(ret, node, idASET, argc, INT2FIX(flag)); + ADD_INSN1(ret, node, pushtoarray, INT2FIX(1)); + ADD_SEND_R(ret, node, idASET, argc, NULL, INT2FIX(flag), NULL); } else { - if (boff > 0) - ADD_INSN(ret, node, swap); - ADD_SEND_WITH_FLAG(ret, node, idASET, FIXNUM_INC(argc, 1), INT2FIX(flag)); + ADD_SEND_R(ret, node, idASET, FIXNUM_INC(argc, 1), NULL, INT2FIX(flag), NULL); } ADD_INSN(ret, node, pop); ADD_INSNL(ret, node, jump, lfin); ADD_LABEL(ret, label); if (!popped) { - ADD_INSN1(ret, node, setn, FIXNUM_INC(argc, 2+boff)); + ADD_INSN1(ret, node, setn, INT2FIX(dup_argn+1)); } - ADD_INSN1(ret, node, adjuststack, FIXNUM_INC(argc, 2+boff)); + ADD_INSN1(ret, node, adjuststack, INT2FIX(dup_argn+1)); ADD_LABEL(ret, lfin); } else { - CHECK(COMPILE(ret, "NODE_OP_ASGN1 args->body: ", node->nd_args->nd_body)); + CHECK(COMPILE(ret, "NODE_OP_ASGN1 nd_rvalue: ", RNODE_OP_ASGN1(node)->nd_rvalue)); ADD_SEND(ret, node, id, INT2FIX(1)); if (!popped) { - ADD_INSN1(ret, node, setn, FIXNUM_INC(argc, 2+boff)); + ADD_INSN1(ret, node, setn, INT2FIX(dup_argn+1)); } if (flag & VM_CALL_ARGS_SPLAT) { - ADD_INSN1(ret, node, newarray, INT2FIX(1)); - if (boff > 0) { - ADD_INSN1(ret, node, dupn, INT2FIX(3)); + if (flag & VM_CALL_KW_SPLAT) { + ADD_INSN1(ret, node, topn, INT2FIX(2)); + if (!(flag & VM_CALL_ARGS_SPLAT_MUT)) { + ADD_INSN1(ret, node, splatarray, Qtrue); + flag |= VM_CALL_ARGS_SPLAT_MUT; + } ADD_INSN(ret, node, swap); + ADD_INSN1(ret, node, pushtoarray, INT2FIX(1)); + ADD_INSN1(ret, node, setn, INT2FIX(2)); ADD_INSN(ret, node, pop); } - ADD_INSN(ret, node, concatarray); - if (boff > 0) { - ADD_INSN1(ret, node, setn, INT2FIX(3)); - ADD_INSN(ret, node, pop); - ADD_INSN(ret, node, pop); + else { + if (!(flag & VM_CALL_ARGS_SPLAT_MUT)) { + ADD_INSN(ret, node, swap); + ADD_INSN1(ret, node, splatarray, Qtrue); + ADD_INSN(ret, node, swap); + flag |= VM_CALL_ARGS_SPLAT_MUT; + } + ADD_INSN1(ret, node, pushtoarray, INT2FIX(1)); } - ADD_SEND_WITH_FLAG(ret, node, idASET, argc, INT2FIX(flag)); + ADD_SEND_R(ret, node, idASET, argc, NULL, INT2FIX(flag), NULL); } else { - if (boff > 0) - ADD_INSN(ret, node, swap); - ADD_SEND_WITH_FLAG(ret, node, idASET, FIXNUM_INC(argc, 1), INT2FIX(flag)); + ADD_SEND_R(ret, node, idASET, FIXNUM_INC(argc, 1), NULL, INT2FIX(flag), NULL); } ADD_INSN(ret, node, pop); } @@ -8690,8 +9690,8 @@ static int compile_op_asgn2(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int popped) { const int line = nd_line(node); - ID atype = node->nd_next->nd_mid; - ID vid = node->nd_next->nd_vid, aid = rb_id_attrset(vid); + ID atype = RNODE_OP_ASGN2(node)->nd_mid; + ID vid = RNODE_OP_ASGN2(node)->nd_vid, aid = rb_id_attrset(vid); int asgnflag; LABEL *lfin = NEW_LABEL(line); LABEL *lcfin = NEW_LABEL(line); @@ -8749,9 +9749,9 @@ compile_op_asgn2(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node */ - asgnflag = COMPILE_RECV(ret, "NODE_OP_ASGN2#recv", node); + asgnflag = COMPILE_RECV(ret, "NODE_OP_ASGN2#recv", node, RNODE_OP_ASGN2(node)->nd_recv); CHECK(asgnflag != -1); - if (node->nd_next->nd_aid) { + if (RNODE_OP_ASGN2(node)->nd_aid) { lskip = NEW_LABEL(line); ADD_INSN(ret, node, dup); ADD_INSNL(ret, node, branchnil, lskip); @@ -8772,7 +9772,7 @@ compile_op_asgn2(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node if (!popped) { ADD_INSN(ret, node, pop); } - CHECK(COMPILE(ret, "NODE_OP_ASGN2 val", node->nd_value)); + CHECK(COMPILE(ret, "NODE_OP_ASGN2 val", RNODE_OP_ASGN2(node)->nd_value)); if (!popped) { ADD_INSN(ret, node, swap); ADD_INSN1(ret, node, topn, INT2FIX(1)); @@ -8788,7 +9788,7 @@ compile_op_asgn2(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node ADD_LABEL(ret, lfin); } else { - CHECK(COMPILE(ret, "NODE_OP_ASGN2 val", node->nd_value)); + CHECK(COMPILE(ret, "NODE_OP_ASGN2 val", RNODE_OP_ASGN2(node)->nd_value)); ADD_SEND(ret, node, atype, INT2FIX(1)); if (!popped) { ADD_INSN(ret, node, swap); @@ -8806,6 +9806,8 @@ compile_op_asgn2(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node return COMPILE_OK; } +static int compile_shareable_constant_value(rb_iseq_t *iseq, LINK_ANCHOR *ret, enum rb_parser_shareability shareable, const NODE *lhs, const NODE *value); + static int compile_op_cdecl(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int popped) { @@ -8814,21 +9816,21 @@ compile_op_cdecl(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node LABEL *lassign = 0; ID mid; - switch (nd_type(node->nd_head)) { + switch (nd_type(RNODE_OP_CDECL(node)->nd_head)) { case NODE_COLON3: ADD_INSN1(ret, node, putobject, rb_cObject); break; case NODE_COLON2: - CHECK(COMPILE(ret, "NODE_OP_CDECL/colon2#nd_head", node->nd_head->nd_head)); + CHECK(COMPILE(ret, "NODE_OP_CDECL/colon2#nd_head", RNODE_COLON2(RNODE_OP_CDECL(node)->nd_head)->nd_head)); break; default: COMPILE_ERROR(ERROR_ARGS "%s: invalid node in NODE_OP_CDECL", - ruby_node_name(nd_type(node->nd_head))); + ruby_node_name(nd_type(RNODE_OP_CDECL(node)->nd_head))); return COMPILE_NG; } - mid = node->nd_head->nd_mid; + mid = get_node_colon_nd_mid(RNODE_OP_CDECL(node)->nd_head); /* cref */ - if (node->nd_aid == idOROP) { + if (RNODE_OP_CDECL(node)->nd_aid == idOROP) { lassign = NEW_LABEL(line); ADD_INSN(ret, node, dup); /* cref cref */ ADD_INSN3(ret, node, defined, INT2FIX(DEFINED_CONST_FROM), @@ -8839,17 +9841,17 @@ compile_op_cdecl(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node ADD_INSN1(ret, node, putobject, Qtrue); ADD_INSN1(ret, node, getconstant, ID2SYM(mid)); /* cref obj */ - if (node->nd_aid == idOROP || node->nd_aid == idANDOP) { + if (RNODE_OP_CDECL(node)->nd_aid == idOROP || RNODE_OP_CDECL(node)->nd_aid == idANDOP) { lfin = NEW_LABEL(line); if (!popped) ADD_INSN(ret, node, dup); /* cref [obj] obj */ - if (node->nd_aid == idOROP) + if (RNODE_OP_CDECL(node)->nd_aid == idOROP) ADD_INSNL(ret, node, branchif, lfin); else /* idANDOP */ ADD_INSNL(ret, node, branchunless, lfin); /* cref [obj] */ if (!popped) ADD_INSN(ret, node, pop); /* cref */ if (lassign) ADD_LABEL(ret, lassign); - CHECK(COMPILE(ret, "NODE_OP_CDECL#nd_value", node->nd_value)); + CHECK(compile_shareable_constant_value(iseq, ret, RNODE_OP_CDECL(node)->shareability, RNODE_OP_CDECL(node)->nd_head, RNODE_OP_CDECL(node)->nd_value)); /* cref value */ if (popped) ADD_INSN1(ret, node, topn, INT2FIX(1)); /* cref value cref */ @@ -8863,9 +9865,9 @@ compile_op_cdecl(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node ADD_INSN(ret, node, pop); /* [value] */ } else { - CHECK(COMPILE(ret, "NODE_OP_CDECL#nd_value", node->nd_value)); + CHECK(compile_shareable_constant_value(iseq, ret, RNODE_OP_CDECL(node)->shareability, RNODE_OP_CDECL(node)->nd_head, RNODE_OP_CDECL(node)->nd_value)); /* cref obj value */ - ADD_CALL(ret, node, node->nd_aid, INT2FIX(1)); + ADD_CALL(ret, node, RNODE_OP_CDECL(node)->nd_aid, INT2FIX(1)); /* cref value */ ADD_INSN(ret, node, swap); /* value cref */ if (!popped) { @@ -8884,11 +9886,11 @@ compile_op_log(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, LABEL *lfin = NEW_LABEL(line); LABEL *lassign; - if (type == NODE_OP_ASGN_OR && !nd_type_p(node->nd_head, NODE_IVAR)) { + if (type == NODE_OP_ASGN_OR && !nd_type_p(RNODE_OP_ASGN_OR(node)->nd_head, NODE_IVAR)) { LABEL *lfinish[2]; lfinish[0] = lfin; lfinish[1] = 0; - defined_expr(iseq, ret, node->nd_head, lfinish, Qfalse); + defined_expr(iseq, ret, RNODE_OP_ASGN_OR(node)->nd_head, lfinish, Qfalse, false); lassign = lfinish[1]; if (!lassign) { lassign = NEW_LABEL(line); @@ -8899,7 +9901,7 @@ compile_op_log(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, lassign = NEW_LABEL(line); } - CHECK(COMPILE(ret, "NODE_OP_ASGN_AND/OR#nd_head", node->nd_head)); + CHECK(COMPILE(ret, "NODE_OP_ASGN_AND/OR#nd_head", RNODE_OP_ASGN_OR(node)->nd_head)); if (!popped) { ADD_INSN(ret, node, dup); @@ -8917,7 +9919,7 @@ compile_op_log(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, } ADD_LABEL(ret, lassign); - CHECK(COMPILE_(ret, "NODE_OP_ASGN_AND/OR#nd_value", node->nd_value, popped)); + CHECK(COMPILE_(ret, "NODE_OP_ASGN_AND/OR#nd_value", RNODE_OP_ASGN_OR(node)->nd_value, popped)); ADD_LABEL(ret, lfin); return COMPILE_OK; } @@ -8931,13 +9933,22 @@ compile_super(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, i unsigned int flag = 0; struct rb_callinfo_kwarg *keywords = NULL; const rb_iseq_t *parent_block = ISEQ_COMPILE_DATA(iseq)->current_block; + int use_block = 1; INIT_ANCHOR(args); ISEQ_COMPILE_DATA(iseq)->current_block = NULL; + if (type == NODE_SUPER) { - VALUE vargc = setup_args(iseq, args, node->nd_args, &flag, &keywords); + VALUE vargc = setup_args(iseq, args, RNODE_SUPER(node)->nd_args, &flag, &keywords); CHECK(!NIL_P(vargc)); argc = FIX2INT(vargc); + if ((flag & VM_CALL_ARGS_BLOCKARG) && (flag & VM_CALL_KW_SPLAT) && !(flag & VM_CALL_KW_SPLAT_MUT)) { + ADD_INSN(args, node, splatkw); + } + + if (flag & VM_CALL_ARGS_BLOCKARG) { + use_block = 0; + } } else { /* NODE_ZSUPER */ @@ -8955,6 +9966,13 @@ compile_super(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, i ADD_GETLOCAL(args, node, idx, lvar_level); } + /* forward ... */ + if (local_body->param.flags.forwardable) { + flag |= VM_CALL_FORWARDING; + int idx = local_body->local_table_size - get_local_var_idx(liseq, idDot3); + ADD_GETLOCAL(args, node, idx, lvar_level); + } + if (local_body->param.flags.has_opt) { /* optional arguments */ int j; @@ -8969,7 +9987,7 @@ compile_super(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, i /* rest argument */ int idx = local_body->local_table_size - local_body->param.rest_start; ADD_GETLOCAL(args, node, idx, lvar_level); - ADD_INSN1(args, node, splatarray, Qfalse); + ADD_INSN1(args, node, splatarray, RBOOL(local_body->param.flags.has_post)); argc = local_body->param.rest_start + 1; flag |= VM_CALL_ARGS_SPLAT; @@ -8985,8 +10003,8 @@ compile_super(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, i int idx = local_body->local_table_size - (post_start + j); ADD_GETLOCAL(args, node, idx, lvar_level); } - ADD_INSN1(args, node, newarray, INT2FIX(j)); - ADD_INSN (args, node, concatarray); + ADD_INSN1(args, node, pushtoarray, INT2FIX(j)); + flag |= VM_CALL_ARGS_SPLAT_MUT; /* argc is settled at above */ } else { @@ -9008,14 +10026,11 @@ compile_super(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, i if (local_body->param.flags.has_kwrest) { int idx = local_body->local_table_size - local_kwd->rest_start; ADD_GETLOCAL(args, node, idx, lvar_level); - if (local_kwd->num > 0) { - ADD_SEND (args, node, rb_intern("dup"), INT2FIX(0)); - flag |= VM_CALL_KW_SPLAT_MUT; - } + RUBY_ASSERT(local_kwd->num > 0); + ADD_SEND (args, node, rb_intern("dup"), INT2FIX(0)); } else { ADD_INSN1(args, node, newhash, INT2FIX(0)); - flag |= VM_CALL_KW_SPLAT_MUT; } for (i = 0; i < local_kwd->num; ++i) { ID id = local_kwd->table[i]; @@ -9024,23 +10039,33 @@ compile_super(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, i ADD_GETLOCAL(args, node, idx, lvar_level); } ADD_SEND(args, node, id_core_hash_merge_ptr, INT2FIX(i * 2 + 1)); - flag |= VM_CALL_KW_SPLAT; + flag |= VM_CALL_KW_SPLAT| VM_CALL_KW_SPLAT_MUT; } else if (local_body->param.flags.has_kwrest) { int idx = local_body->local_table_size - local_kwd->rest_start; ADD_GETLOCAL(args, node, idx, lvar_level); argc++; - flag |= VM_CALL_KW_SPLAT | VM_CALL_KW_SPLAT_MUT; + flag |= VM_CALL_KW_SPLAT; } } + if (use_block && parent_block == NULL) { + iseq_set_use_block(ISEQ_BODY(iseq)->local_iseq); + } + flag |= VM_CALL_SUPER | VM_CALL_FCALL; if (type == NODE_ZSUPER) flag |= VM_CALL_ZSUPER; ADD_INSN(ret, node, putself); ADD_SEQ(ret, args); - ADD_INSN2(ret, node, invokesuper, - new_callinfo(iseq, 0, argc, flag, keywords, parent_block != NULL), - parent_block); + + const struct rb_callinfo * ci = new_callinfo(iseq, 0, argc, flag, keywords, parent_block != NULL); + + if (vm_ci_flag(ci) & VM_CALL_FORWARDING) { + ADD_INSN2(ret, node, invokesuperforward, ci, parent_block); + } + else { + ADD_INSN2(ret, node, invokesuper, ci, parent_block); + } if (popped) { ADD_INSN(ret, node, pop); @@ -9067,8 +10092,8 @@ compile_yield(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, i default: /* valid */; } - if (node->nd_head) { - argc = setup_args(iseq, args, node->nd_head, &flag, &keywords); + if (RNODE_YIELD(node)->nd_head) { + argc = setup_args(iseq, args, RNODE_YIELD(node)->nd_head, &flag, &keywords); CHECK(!NIL_P(argc)); } else { @@ -9077,6 +10102,7 @@ compile_yield(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, i ADD_SEQ(ret, args); ADD_INSN1(ret, node, invokeblock, new_callinfo(iseq, 0, FIX2INT(argc), flag, keywords, FALSE)); + iseq_set_use_block(ISEQ_BODY(iseq)->local_iseq); if (popped) { ADD_INSN(ret, node, pop); @@ -9102,17 +10128,17 @@ compile_match(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, i INIT_ANCHOR(val); switch ((int)type) { case NODE_MATCH: - ADD_INSN1(recv, node, putobject, node->nd_lit); + ADD_INSN1(recv, node, putobject, rb_node_regx_string_val(node)); ADD_INSN2(val, node, getspecial, INT2FIX(0), INT2FIX(0)); break; case NODE_MATCH2: - CHECK(COMPILE(recv, "receiver", node->nd_recv)); - CHECK(COMPILE(val, "value", node->nd_value)); + CHECK(COMPILE(recv, "receiver", RNODE_MATCH2(node)->nd_recv)); + CHECK(COMPILE(val, "value", RNODE_MATCH2(node)->nd_value)); break; case NODE_MATCH3: - CHECK(COMPILE(recv, "receiver", node->nd_value)); - CHECK(COMPILE(val, "value", node->nd_recv)); + CHECK(COMPILE(recv, "receiver", RNODE_MATCH3(node)->nd_value)); + CHECK(COMPILE(val, "value", RNODE_MATCH3(node)->nd_recv)); break; } @@ -9120,8 +10146,8 @@ compile_match(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, i ADD_SEQ(ret, val); ADD_SEND(ret, node, idEqTilde, INT2FIX(1)); - if (node->nd_args) { - compile_named_capture_assign(iseq, ret, node->nd_args); + if (nd_type_p(node, NODE_MATCH2) && RNODE_MATCH2(node)->nd_args) { + compile_named_capture_assign(iseq, ret, RNODE_MATCH2(node)->nd_args); } if (popped) { @@ -9133,7 +10159,7 @@ compile_match(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, i static int compile_colon2(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int popped) { - if (rb_is_const_id(node->nd_mid)) { + if (rb_is_const_id(RNODE_COLON2(node)->nd_mid)) { /* constant */ VALUE segments; if (ISEQ_COMPILE_DATA(iseq)->option->inline_const_cache && @@ -9163,8 +10189,8 @@ compile_colon2(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, else { /* function call */ ADD_CALL_RECEIVER(ret, node); - CHECK(COMPILE(ret, "colon2#nd_head", node->nd_head)); - ADD_CALL(ret, node, node->nd_mid, INT2FIX(1)); + CHECK(COMPILE(ret, "colon2#nd_head", RNODE_COLON2(node)->nd_head)); + ADD_CALL(ret, node, RNODE_COLON2(node)->nd_mid, INT2FIX(1)); } if (popped) { ADD_INSN(ret, node, pop); @@ -9175,19 +10201,19 @@ compile_colon2(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, static int compile_colon3(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int popped) { - debugi("colon3#nd_mid", node->nd_mid); + debugi("colon3#nd_mid", RNODE_COLON3(node)->nd_mid); /* add cache insn */ if (ISEQ_COMPILE_DATA(iseq)->option->inline_const_cache) { ISEQ_BODY(iseq)->ic_size++; - VALUE segments = rb_ary_new_from_args(2, ID2SYM(idNULL), ID2SYM(node->nd_mid)); + VALUE segments = rb_ary_new_from_args(2, ID2SYM(idNULL), ID2SYM(RNODE_COLON3(node)->nd_mid)); ADD_INSN1(ret, node, opt_getconstant_path, segments); RB_OBJ_WRITTEN(iseq, Qundef, segments); } else { ADD_INSN1(ret, node, putobject, rb_cObject); ADD_INSN1(ret, node, putobject, Qtrue); - ADD_INSN1(ret, node, getconstant, ID2SYM(node->nd_mid)); + ADD_INSN1(ret, node, getconstant, ID2SYM(RNODE_COLON3(node)->nd_mid)); } if (popped) { @@ -9200,13 +10226,13 @@ static int compile_dots(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int popped, const int excl) { VALUE flag = INT2FIX(excl); - const NODE *b = node->nd_beg; - const NODE *e = node->nd_end; + const NODE *b = RNODE_DOT2(node)->nd_beg; + const NODE *e = RNODE_DOT2(node)->nd_end; if (optimizable_range_item_p(b) && optimizable_range_item_p(e)) { if (!popped) { - VALUE bv = nd_type_p(b, NODE_LIT) ? b->nd_lit : Qnil; - VALUE ev = nd_type_p(e, NODE_LIT) ? e->nd_lit : Qnil; + VALUE bv = optimized_range_item(b); + VALUE ev = optimized_range_item(e); VALUE val = rb_range_new(bv, ev, excl); ADD_INSN1(ret, node, putobject, val); RB_OBJ_WRITTEN(iseq, Qundef, val); @@ -9236,140 +10262,503 @@ compile_errinfo(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, if (ISEQ_BODY(ip)->type == ISEQ_TYPE_RESCUE) { break; } - ip = ISEQ_BODY(ip)->parent_iseq; - level++; + ip = ISEQ_BODY(ip)->parent_iseq; + level++; + } + if (ip) { + ADD_GETLOCAL(ret, node, LVAR_ERRINFO, level); + } + else { + ADD_INSN(ret, node, putnil); + } + } + } + return COMPILE_OK; +} + +static int +compile_kw_arg(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int popped) +{ + struct rb_iseq_constant_body *const body = ISEQ_BODY(iseq); + LABEL *end_label = NEW_LABEL(nd_line(node)); + const NODE *default_value = get_nd_value(RNODE_KW_ARG(node)->nd_body); + + if (default_value == NODE_SPECIAL_REQUIRED_KEYWORD) { + /* required argument. do nothing */ + COMPILE_ERROR(ERROR_ARGS "unreachable"); + return COMPILE_NG; + } + else if (nd_type_p(default_value, NODE_SYM) || + nd_type_p(default_value, NODE_REGX) || + nd_type_p(default_value, NODE_LINE) || + nd_type_p(default_value, NODE_INTEGER) || + nd_type_p(default_value, NODE_FLOAT) || + nd_type_p(default_value, NODE_RATIONAL) || + nd_type_p(default_value, NODE_IMAGINARY) || + nd_type_p(default_value, NODE_NIL) || + nd_type_p(default_value, NODE_TRUE) || + nd_type_p(default_value, NODE_FALSE)) { + COMPILE_ERROR(ERROR_ARGS "unreachable"); + return COMPILE_NG; + } + else { + /* if keywordcheck(_kw_bits, nth_keyword) + * kw = default_value + * end + */ + int kw_bits_idx = body->local_table_size - body->param.keyword->bits_start; + int keyword_idx = body->param.keyword->num; + + ADD_INSN2(ret, node, checkkeyword, INT2FIX(kw_bits_idx + VM_ENV_DATA_SIZE - 1), INT2FIX(keyword_idx)); + ADD_INSNL(ret, node, branchif, end_label); + CHECK(COMPILE_POPPED(ret, "keyword default argument", RNODE_KW_ARG(node)->nd_body)); + ADD_LABEL(ret, end_label); + } + return COMPILE_OK; +} + +static int +compile_attrasgn(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int popped) +{ + DECL_ANCHOR(recv); + DECL_ANCHOR(args); + unsigned int flag = 0; + ID mid = RNODE_ATTRASGN(node)->nd_mid; + VALUE argc; + LABEL *else_label = NULL; + VALUE branches = Qfalse; + + /* optimization shortcut + * obj["literal"] = value -> opt_aset_with(obj, "literal", value) + */ + if (!ISEQ_COMPILE_DATA(iseq)->in_masgn && + mid == idASET && !private_recv_p(node) && RNODE_ATTRASGN(node)->nd_args && + nd_type_p(RNODE_ATTRASGN(node)->nd_args, NODE_LIST) && RNODE_LIST(RNODE_ATTRASGN(node)->nd_args)->as.nd_alen == 2 && + (nd_type_p(RNODE_LIST(RNODE_ATTRASGN(node)->nd_args)->nd_head, NODE_STR) || nd_type_p(RNODE_LIST(RNODE_ATTRASGN(node)->nd_args)->nd_head, NODE_FILE)) && + ISEQ_COMPILE_DATA(iseq)->current_block == NULL && + !frozen_string_literal_p(iseq) && + ISEQ_COMPILE_DATA(iseq)->option->specialized_instruction) + { + VALUE str = get_string_value(RNODE_LIST(RNODE_ATTRASGN(node)->nd_args)->nd_head); + CHECK(COMPILE(ret, "recv", RNODE_ATTRASGN(node)->nd_recv)); + CHECK(COMPILE(ret, "value", RNODE_LIST(RNODE_LIST(RNODE_ATTRASGN(node)->nd_args)->nd_next)->nd_head)); + if (!popped) { + ADD_INSN(ret, node, swap); + ADD_INSN1(ret, node, topn, INT2FIX(1)); + } + ADD_INSN2(ret, node, opt_aset_with, str, + new_callinfo(iseq, idASET, 2, 0, NULL, FALSE)); + RB_OBJ_WRITTEN(iseq, Qundef, str); + ADD_INSN(ret, node, pop); + return COMPILE_OK; + } + + INIT_ANCHOR(recv); + INIT_ANCHOR(args); + argc = setup_args(iseq, args, RNODE_ATTRASGN(node)->nd_args, &flag, NULL); + CHECK(!NIL_P(argc)); + + int asgnflag = COMPILE_RECV(recv, "recv", node, RNODE_ATTRASGN(node)->nd_recv); + CHECK(asgnflag != -1); + flag |= (unsigned int)asgnflag; + + debugp_param("argc", argc); + debugp_param("nd_mid", ID2SYM(mid)); + + if (!rb_is_attrset_id(mid)) { + /* safe nav attr */ + mid = rb_id_attrset(mid); + else_label = qcall_branch_start(iseq, recv, &branches, node, node); + } + if (!popped) { + ADD_INSN(ret, node, putnil); + ADD_SEQ(ret, recv); + ADD_SEQ(ret, args); + + if (flag & VM_CALL_ARGS_SPLAT) { + ADD_INSN(ret, node, dup); + ADD_INSN1(ret, node, putobject, INT2FIX(-1)); + ADD_SEND_WITH_FLAG(ret, node, idAREF, INT2FIX(1), INT2FIX(asgnflag)); + ADD_INSN1(ret, node, setn, FIXNUM_INC(argc, 2)); + ADD_INSN (ret, node, pop); + } + else { + ADD_INSN1(ret, node, setn, FIXNUM_INC(argc, 1)); + } + } + else { + ADD_SEQ(ret, recv); + ADD_SEQ(ret, args); + } + ADD_SEND_WITH_FLAG(ret, node, mid, argc, INT2FIX(flag)); + qcall_branch_end(iseq, ret, else_label, branches, node, node); + ADD_INSN(ret, node, pop); + return COMPILE_OK; +} + +static int +compile_make_shareable_node(rb_iseq_t *iseq, LINK_ANCHOR *ret, LINK_ANCHOR *sub, const NODE *value, bool copy) +{ + ADD_INSN1(ret, value, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); + ADD_SEQ(ret, sub); + + if (copy) { + /* + * NEW_CALL(fcore, rb_intern("make_shareable_copy"), + * NEW_LIST(value, loc), loc); + */ + ADD_SEND_WITH_FLAG(ret, value, rb_intern("make_shareable_copy"), INT2FIX(1), INT2FIX(VM_CALL_ARGS_SIMPLE)); + } + else { + /* + * NEW_CALL(fcore, rb_intern("make_shareable"), + * NEW_LIST(value, loc), loc); + */ + ADD_SEND_WITH_FLAG(ret, value, rb_intern("make_shareable"), INT2FIX(1), INT2FIX(VM_CALL_ARGS_SIMPLE)); + } + + return COMPILE_OK; +} + +static VALUE +node_const_decl_val(const NODE *node) +{ + VALUE path; + switch (nd_type(node)) { + case NODE_CDECL: + if (RNODE_CDECL(node)->nd_vid) { + path = rb_id2str(RNODE_CDECL(node)->nd_vid); + goto end; + } + else { + node = RNODE_CDECL(node)->nd_else; + } + break; + case NODE_COLON2: + break; + case NODE_COLON3: + // ::Const + path = rb_str_new_cstr("::"); + rb_str_append(path, rb_id2str(RNODE_COLON3(node)->nd_mid)); + goto end; + default: + rb_bug("unexpected node: %s", ruby_node_name(nd_type(node))); + UNREACHABLE_RETURN(0); + } + + path = rb_ary_new(); + if (node) { + for (; node && nd_type_p(node, NODE_COLON2); node = RNODE_COLON2(node)->nd_head) { + rb_ary_push(path, rb_id2str(RNODE_COLON2(node)->nd_mid)); + } + if (node && nd_type_p(node, NODE_CONST)) { + // Const::Name + rb_ary_push(path, rb_id2str(RNODE_CONST(node)->nd_vid)); + } + else if (node && nd_type_p(node, NODE_COLON3)) { + // ::Const::Name + rb_ary_push(path, rb_id2str(RNODE_COLON3(node)->nd_mid)); + rb_ary_push(path, rb_str_new(0, 0)); + } + else { + // expression::Name + rb_ary_push(path, rb_str_new_cstr("...")); + } + path = rb_ary_join(rb_ary_reverse(path), rb_str_new_cstr("::")); + } + end: + path = rb_fstring(path); + return path; +} + +static VALUE +const_decl_path(NODE *dest) +{ + VALUE path = Qnil; + if (!nd_type_p(dest, NODE_CALL)) { + path = node_const_decl_val(dest); + } + return path; +} + +static int +compile_ensure_shareable_node(rb_iseq_t *iseq, LINK_ANCHOR *ret, NODE *dest, const NODE *value) +{ + /* + *. RubyVM::FrozenCore.ensure_shareable(value, const_decl_path(dest)) + */ + VALUE path = const_decl_path(dest); + ADD_INSN1(ret, value, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); + CHECK(COMPILE(ret, "compile_ensure_shareable_node", value)); + ADD_INSN1(ret, value, putobject, path); + RB_OBJ_WRITTEN(iseq, Qundef, path); + ADD_SEND_WITH_FLAG(ret, value, rb_intern("ensure_shareable"), INT2FIX(2), INT2FIX(VM_CALL_ARGS_SIMPLE)); + + return COMPILE_OK; +} + +#ifndef SHAREABLE_BARE_EXPRESSION +#define SHAREABLE_BARE_EXPRESSION 1 +#endif + +static int +compile_shareable_literal_constant(rb_iseq_t *iseq, LINK_ANCHOR *ret, enum rb_parser_shareability shareable, NODE *dest, const NODE *node, size_t level, VALUE *value_p, int *shareable_literal_p) +{ +# define compile_shareable_literal_constant_next(node, anchor, value_p, shareable_literal_p) \ + compile_shareable_literal_constant(iseq, anchor, shareable, dest, node, level+1, value_p, shareable_literal_p) + VALUE lit = Qnil; + DECL_ANCHOR(anchor); + + enum node_type type = node ? nd_type(node) : NODE_NIL; + switch (type) { + case NODE_TRUE: + *value_p = Qtrue; + goto compile; + case NODE_FALSE: + *value_p = Qfalse; + goto compile; + case NODE_NIL: + *value_p = Qnil; + goto compile; + case NODE_SYM: + *value_p = rb_node_sym_string_val(node); + goto compile; + case NODE_REGX: + *value_p = rb_node_regx_string_val(node); + goto compile; + case NODE_LINE: + *value_p = rb_node_line_lineno_val(node); + goto compile; + case NODE_INTEGER: + *value_p = rb_node_integer_literal_val(node); + goto compile; + case NODE_FLOAT: + *value_p = rb_node_float_literal_val(node); + goto compile; + case NODE_RATIONAL: + *value_p = rb_node_rational_literal_val(node); + goto compile; + case NODE_IMAGINARY: + *value_p = rb_node_imaginary_literal_val(node); + goto compile; + case NODE_ENCODING: + *value_p = rb_node_encoding_val(node); + + compile: + CHECK(COMPILE(ret, "shareable_literal_constant", node)); + *shareable_literal_p = 1; + return COMPILE_OK; + + case NODE_DSTR: + CHECK(COMPILE(ret, "shareable_literal_constant", node)); + if (shareable == rb_parser_shareable_literal) { + /* + * NEW_CALL(node, idUMinus, 0, loc); + * + * -"#{var}" + */ + ADD_SEND_WITH_FLAG(ret, node, idUMinus, INT2FIX(0), INT2FIX(VM_CALL_ARGS_SIMPLE)); + } + *value_p = Qundef; + *shareable_literal_p = 1; + return COMPILE_OK; + + case NODE_STR:{ + VALUE lit = rb_node_str_string_val(node); + ADD_INSN1(ret, node, putobject, lit); + RB_OBJ_WRITTEN(iseq, Qundef, lit); + *value_p = lit; + *shareable_literal_p = 1; + + return COMPILE_OK; + } + + case NODE_FILE:{ + VALUE lit = rb_node_file_path_val(node); + ADD_INSN1(ret, node, putobject, lit); + RB_OBJ_WRITTEN(iseq, Qundef, lit); + *value_p = lit; + *shareable_literal_p = 1; + + return COMPILE_OK; + } + + case NODE_ZLIST:{ + VALUE lit = rb_ary_new(); + OBJ_FREEZE(lit); + ADD_INSN1(ret, node, putobject, lit); + RB_OBJ_WRITTEN(iseq, Qundef, lit); + *value_p = lit; + *shareable_literal_p = 1; + + return COMPILE_OK; + } + + case NODE_LIST:{ + INIT_ANCHOR(anchor); + lit = rb_ary_new(); + for (NODE *n = (NODE *)node; n; n = RNODE_LIST(n)->nd_next) { + VALUE val; + int shareable_literal_p2; + NODE *elt = RNODE_LIST(n)->nd_head; + if (elt) { + CHECK(compile_shareable_literal_constant_next(elt, anchor, &val, &shareable_literal_p2)); + if (shareable_literal_p2) { + /* noop */ + } + else if (RTEST(lit)) { + rb_ary_clear(lit); + lit = Qfalse; + } + } + if (RTEST(lit)) { + if (!UNDEF_P(val)) { + rb_ary_push(lit, val); + } + else { + rb_ary_clear(lit); + lit = Qnil; /* make shareable at runtime */ + } } - if (ip) { - ADD_GETLOCAL(ret, node, LVAR_ERRINFO, level); + } + break; + } + case NODE_HASH:{ + if (!RNODE_HASH(node)->nd_brace) { + *value_p = Qundef; + *shareable_literal_p = 0; + return COMPILE_OK; + } + for (NODE *n = RNODE_HASH(node)->nd_head; n; n = RNODE_LIST(RNODE_LIST(n)->nd_next)->nd_next) { + if (!RNODE_LIST(n)->nd_head) { + // If the hash node have a keyword splat, fall back to the default case. + goto compile_shareable; } - else { - ADD_INSN(ret, node, putnil); + } + + INIT_ANCHOR(anchor); + lit = rb_hash_new(); + for (NODE *n = RNODE_HASH(node)->nd_head; n; n = RNODE_LIST(RNODE_LIST(n)->nd_next)->nd_next) { + VALUE key_val = 0; + VALUE value_val = 0; + int shareable_literal_p2; + NODE *key = RNODE_LIST(n)->nd_head; + NODE *val = RNODE_LIST(RNODE_LIST(n)->nd_next)->nd_head; + CHECK(compile_shareable_literal_constant_next(key, anchor, &key_val, &shareable_literal_p2)); + if (shareable_literal_p2) { + /* noop */ + } + else if (RTEST(lit)) { + rb_hash_clear(lit); + lit = Qfalse; + } + CHECK(compile_shareable_literal_constant_next(val, anchor, &value_val, &shareable_literal_p2)); + if (shareable_literal_p2) { + /* noop */ + } + else if (RTEST(lit)) { + rb_hash_clear(lit); + lit = Qfalse; + } + if (RTEST(lit)) { + if (!UNDEF_P(key_val) && !UNDEF_P(value_val)) { + rb_hash_aset(lit, key_val, value_val); + } + else { + rb_hash_clear(lit); + lit = Qnil; /* make shareable at runtime */ + } } } - } - return COMPILE_OK; -} + break; + } -static int -compile_kw_arg(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int popped) -{ - struct rb_iseq_constant_body *const body = ISEQ_BODY(iseq); - LABEL *end_label = NEW_LABEL(nd_line(node)); - const NODE *default_value = node->nd_body->nd_value; + default: - if (default_value == NODE_SPECIAL_REQUIRED_KEYWORD) { - /* required argument. do nothing */ - COMPILE_ERROR(ERROR_ARGS "unreachable"); - return COMPILE_NG; + compile_shareable: + if (shareable == rb_parser_shareable_literal && + (SHAREABLE_BARE_EXPRESSION || level > 0)) { + CHECK(compile_ensure_shareable_node(iseq, ret, dest, node)); + *value_p = Qundef; + *shareable_literal_p = 1; + return COMPILE_OK; + } + CHECK(COMPILE(ret, "shareable_literal_constant", node)); + *value_p = Qundef; + *shareable_literal_p = 0; + return COMPILE_OK; } - else if (nd_type_p(default_value, NODE_LIT) || - nd_type_p(default_value, NODE_NIL) || - nd_type_p(default_value, NODE_TRUE) || - nd_type_p(default_value, NODE_FALSE)) { - COMPILE_ERROR(ERROR_ARGS "unreachable"); - return COMPILE_NG; + + /* Array or Hash that does not have keyword splat */ + if (!lit) { + if (nd_type(node) == NODE_LIST) { + ADD_INSN1(anchor, node, newarray, INT2FIX(RNODE_LIST(node)->as.nd_alen)); + } + else if (nd_type(node) == NODE_HASH) { + int len = (int)RNODE_LIST(RNODE_HASH(node)->nd_head)->as.nd_alen; + ADD_INSN1(anchor, node, newhash, INT2FIX(len)); + } + *value_p = Qundef; + *shareable_literal_p = 0; + ADD_SEQ(ret, anchor); + return COMPILE_OK; + } + if (NIL_P(lit)) { + // if shareable_literal, all elements should have been ensured + // as shareable + if (nd_type(node) == NODE_LIST) { + ADD_INSN1(anchor, node, newarray, INT2FIX(RNODE_LIST(node)->as.nd_alen)); + } + else if (nd_type(node) == NODE_HASH) { + int len = (int)RNODE_LIST(RNODE_HASH(node)->nd_head)->as.nd_alen; + ADD_INSN1(anchor, node, newhash, INT2FIX(len)); + } + CHECK(compile_make_shareable_node(iseq, ret, anchor, node, false)); + *value_p = Qundef; + *shareable_literal_p = 1; } else { - /* if keywordcheck(_kw_bits, nth_keyword) - * kw = default_value - * end - */ - int kw_bits_idx = body->local_table_size - body->param.keyword->bits_start; - int keyword_idx = body->param.keyword->num; - - ADD_INSN2(ret, node, checkkeyword, INT2FIX(kw_bits_idx + VM_ENV_DATA_SIZE - 1), INT2FIX(keyword_idx)); - ADD_INSNL(ret, node, branchif, end_label); - CHECK(COMPILE_POPPED(ret, "keyword default argument", node->nd_body)); - ADD_LABEL(ret, end_label); + VALUE val = rb_ractor_make_shareable(lit); + ADD_INSN1(ret, node, putobject, val); + RB_OBJ_WRITTEN(iseq, Qundef, val); + *value_p = val; + *shareable_literal_p = 1; } + return COMPILE_OK; } static int -compile_attrasgn(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int popped) +compile_shareable_constant_value(rb_iseq_t *iseq, LINK_ANCHOR *ret, enum rb_parser_shareability shareable, const NODE *lhs, const NODE *value) { - DECL_ANCHOR(recv); - DECL_ANCHOR(args); - unsigned int flag = 0; - ID mid = node->nd_mid; - VALUE argc; - LABEL *else_label = NULL; - VALUE branches = Qfalse; + int literal_p = 0; + VALUE val; + DECL_ANCHOR(anchor); + INIT_ANCHOR(anchor); - /* optimization shortcut - * obj["literal"] = value -> opt_aset_with(obj, "literal", value) - */ - if (mid == idASET && !private_recv_p(node) && node->nd_args && - nd_type_p(node->nd_args, NODE_LIST) && node->nd_args->nd_alen == 2 && - nd_type_p(node->nd_args->nd_head, NODE_STR) && - ISEQ_COMPILE_DATA(iseq)->current_block == NULL && - !ISEQ_COMPILE_DATA(iseq)->option->frozen_string_literal && - ISEQ_COMPILE_DATA(iseq)->option->specialized_instruction) - { - VALUE str = rb_fstring(node->nd_args->nd_head->nd_lit); - CHECK(COMPILE(ret, "recv", node->nd_recv)); - CHECK(COMPILE(ret, "value", node->nd_args->nd_next->nd_head)); - if (!popped) { - ADD_INSN(ret, node, swap); - ADD_INSN1(ret, node, topn, INT2FIX(1)); - } - ADD_INSN2(ret, node, opt_aset_with, str, - new_callinfo(iseq, idASET, 2, 0, NULL, FALSE)); - RB_OBJ_WRITTEN(iseq, Qundef, str); - ADD_INSN(ret, node, pop); + switch (shareable) { + case rb_parser_shareable_none: + CHECK(COMPILE(ret, "compile_shareable_constant_value", value)); return COMPILE_OK; - } - - INIT_ANCHOR(recv); - INIT_ANCHOR(args); - argc = setup_args(iseq, args, node->nd_args, &flag, NULL); - CHECK(!NIL_P(argc)); - - int asgnflag = COMPILE_RECV(recv, "recv", node); - CHECK(asgnflag != -1); - flag |= (unsigned int)asgnflag; - - debugp_param("argc", argc); - debugp_param("nd_mid", ID2SYM(mid)); - if (!rb_is_attrset_id(mid)) { - /* safe nav attr */ - mid = rb_id_attrset(mid); - else_label = qcall_branch_start(iseq, recv, &branches, node, node); - } - if (!popped) { - ADD_INSN(ret, node, putnil); - ADD_SEQ(ret, recv); - ADD_SEQ(ret, args); + case rb_parser_shareable_literal: + CHECK(compile_shareable_literal_constant(iseq, anchor, shareable, (NODE *)lhs, value, 0, &val, &literal_p)); + ADD_SEQ(ret, anchor); + return COMPILE_OK; - if (flag & VM_CALL_ARGS_BLOCKARG) { - ADD_INSN1(ret, node, topn, INT2FIX(1)); - if (flag & VM_CALL_ARGS_SPLAT) { - ADD_INSN1(ret, node, putobject, INT2FIX(-1)); - ADD_SEND_WITH_FLAG(ret, node, idAREF, INT2FIX(1), INT2FIX(asgnflag)); - } - ADD_INSN1(ret, node, setn, FIXNUM_INC(argc, 3)); - ADD_INSN (ret, node, pop); - } - else if (flag & VM_CALL_ARGS_SPLAT) { - ADD_INSN(ret, node, dup); - ADD_INSN1(ret, node, putobject, INT2FIX(-1)); - ADD_SEND_WITH_FLAG(ret, node, idAREF, INT2FIX(1), INT2FIX(asgnflag)); - ADD_INSN1(ret, node, setn, FIXNUM_INC(argc, 2)); - ADD_INSN (ret, node, pop); + case rb_parser_shareable_copy: + case rb_parser_shareable_everything: + CHECK(compile_shareable_literal_constant(iseq, anchor, shareable, (NODE *)lhs, value, 0, &val, &literal_p)); + if (!literal_p) { + CHECK(compile_make_shareable_node(iseq, ret, anchor, value, shareable == rb_parser_shareable_copy)); } else { - ADD_INSN1(ret, node, setn, FIXNUM_INC(argc, 1)); + ADD_SEQ(ret, anchor); } + return COMPILE_OK; + default: + rb_bug("unexpected rb_parser_shareability: %d", shareable); } - else { - ADD_SEQ(ret, recv); - ADD_SEQ(ret, args); - } - ADD_SEND_WITH_FLAG(ret, node, mid, argc, INT2FIX(flag)); - qcall_branch_end(iseq, ret, else_label, branches, node, node); - ADD_INSN(ret, node, pop); - return COMPILE_OK; } static int iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const node, int popped); @@ -9388,8 +10777,7 @@ iseq_compile_each(rb_iseq_t *iseq, LINK_ANCHOR *ret, const NODE *node, int poppe int lineno = ISEQ_COMPILE_DATA(iseq)->last_line; if (lineno == 0) lineno = FIX2INT(rb_iseq_first_lineno(iseq)); debugs("node: NODE_NIL(implicit)\n"); - NODE dummy_line_node = generate_dummy_line_node(lineno, -1); - ADD_INSN(ret, &dummy_line_node, putnil); + ADD_SYNTHETIC_INSN(ret, lineno, -1, putnil); } return COMPILE_OK; } @@ -9407,10 +10795,10 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no /* ignore */ } else { - if (node->flags & NODE_FL_NEWLINE) { + if (nd_fl_newline(node)) { int event = RUBY_EVENT_LINE; ISEQ_COMPILE_DATA(iseq)->last_line = line; - if (ISEQ_COVERAGE(iseq) && ISEQ_LINE_COVERAGE(iseq)) { + if (line > 0 && ISEQ_COVERAGE(iseq) && ISEQ_LINE_COVERAGE(iseq)) { event |= RUBY_EVENT_COVERAGE_LINE; } ADD_TRACE(ret, event); @@ -9462,7 +10850,7 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no CHECK(compile_retry(iseq, ret, node, popped)); break; case NODE_BEGIN:{ - CHECK(COMPILE_(ret, "NODE_BEGIN", node->nd_body, popped)); + CHECK(COMPILE_(ret, "NODE_BEGIN", RNODE_BEGIN(node)->nd_body, popped)); break; } case NODE_RESCUE: @@ -9478,7 +10866,7 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no case NODE_AND: case NODE_OR:{ LABEL *end_label = NEW_LABEL(line); - CHECK(COMPILE(ret, "nd_1st", node->nd_1st)); + CHECK(COMPILE(ret, "nd_1st", RNODE_OR(node)->nd_1st)); if (!popped) { ADD_INSN(ret, node, dup); } @@ -9491,22 +10879,25 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no if (!popped) { ADD_INSN(ret, node, pop); } - CHECK(COMPILE_(ret, "nd_2nd", node->nd_2nd, popped)); + CHECK(COMPILE_(ret, "nd_2nd", RNODE_OR(node)->nd_2nd, popped)); ADD_LABEL(ret, end_label); break; } case NODE_MASGN:{ + bool prev_in_masgn = ISEQ_COMPILE_DATA(iseq)->in_masgn; + ISEQ_COMPILE_DATA(iseq)->in_masgn = true; compile_massign(iseq, ret, node, popped); + ISEQ_COMPILE_DATA(iseq)->in_masgn = prev_in_masgn; break; } case NODE_LASGN:{ - ID id = node->nd_vid; + ID id = RNODE_LASGN(node)->nd_vid; int idx = ISEQ_BODY(body->local_iseq)->local_table_size - get_local_var_idx(iseq, id); debugs("lvar: %s idx: %d\n", rb_id2name(id), idx); - CHECK(COMPILE(ret, "rvalue", node->nd_value)); + CHECK(COMPILE(ret, "rvalue", RNODE_LASGN(node)->nd_value)); if (!popped) { ADD_INSN(ret, node, dup); @@ -9516,8 +10907,8 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no } case NODE_DASGN: { int idx, lv, ls; - ID id = node->nd_vid; - CHECK(COMPILE(ret, "dvalue", node->nd_value)); + ID id = RNODE_DASGN(node)->nd_vid; + CHECK(COMPILE(ret, "dvalue", RNODE_DASGN(node)->nd_value)); debugi("dassn id", rb_id2str(id) ? id : '*'); if (!popped) { @@ -9535,27 +10926,27 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no break; } case NODE_GASGN:{ - CHECK(COMPILE(ret, "lvalue", node->nd_value)); + CHECK(COMPILE(ret, "lvalue", RNODE_GASGN(node)->nd_value)); if (!popped) { ADD_INSN(ret, node, dup); } - ADD_INSN1(ret, node, setglobal, ID2SYM(node->nd_vid)); + ADD_INSN1(ret, node, setglobal, ID2SYM(RNODE_GASGN(node)->nd_vid)); break; } case NODE_IASGN:{ - CHECK(COMPILE(ret, "lvalue", node->nd_value)); + CHECK(COMPILE(ret, "lvalue", RNODE_IASGN(node)->nd_value)); if (!popped) { ADD_INSN(ret, node, dup); } ADD_INSN2(ret, node, setinstancevariable, - ID2SYM(node->nd_vid), - get_ivar_ic_value(iseq,node->nd_vid)); + ID2SYM(RNODE_IASGN(node)->nd_vid), + get_ivar_ic_value(iseq,RNODE_IASGN(node)->nd_vid)); break; } case NODE_CDECL:{ - if (node->nd_vid) { - CHECK(COMPILE(ret, "lvalue", node->nd_value)); + if (RNODE_CDECL(node)->nd_vid) { + CHECK(compile_shareable_constant_value(iseq, ret, RNODE_CDECL(node)->shareability, node, RNODE_CDECL(node)->nd_value)); if (!popped) { ADD_INSN(ret, node, dup); @@ -9563,11 +10954,11 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no ADD_INSN1(ret, node, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_CONST_BASE)); - ADD_INSN1(ret, node, setconstant, ID2SYM(node->nd_vid)); + ADD_INSN1(ret, node, setconstant, ID2SYM(RNODE_CDECL(node)->nd_vid)); } else { - compile_cpath(ret, iseq, node->nd_else); - CHECK(COMPILE(ret, "lvalue", node->nd_value)); + compile_cpath(ret, iseq, RNODE_CDECL(node)->nd_else); + CHECK(compile_shareable_constant_value(iseq, ret, RNODE_CDECL(node)->shareability, node, RNODE_CDECL(node)->nd_value)); ADD_INSN(ret, node, swap); if (!popped) { @@ -9575,18 +10966,18 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no ADD_INSN(ret, node, swap); } - ADD_INSN1(ret, node, setconstant, ID2SYM(node->nd_else->nd_mid)); + ADD_INSN1(ret, node, setconstant, ID2SYM(get_node_colon_nd_mid(RNODE_CDECL(node)->nd_else))); } break; } case NODE_CVASGN:{ - CHECK(COMPILE(ret, "cvasgn val", node->nd_value)); + CHECK(COMPILE(ret, "cvasgn val", RNODE_CVASGN(node)->nd_value)); if (!popped) { ADD_INSN(ret, node, dup); } ADD_INSN2(ret, node, setclassvariable, - ID2SYM(node->nd_vid), - get_cvar_ic_value(iseq,node->nd_vid)); + ID2SYM(RNODE_CVASGN(node)->nd_vid), + get_cvar_ic_value(iseq, RNODE_CVASGN(node)->nd_vid)); break; } case NODE_OP_ASGN1: @@ -9619,7 +11010,7 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no CHECK(compile_super(iseq, ret, node, popped, type)); break; case NODE_LIST:{ - CHECK(compile_array(iseq, ret, node, popped) >= 0); + CHECK(compile_array(iseq, ret, node, popped, TRUE) >= 0); break; } case NODE_ZLIST:{ @@ -9628,18 +11019,6 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no } break; } - case NODE_VALUES:{ - const NODE *n = node; - if (popped) { - COMPILE_ERROR(ERROR_ARGS "NODE_VALUES: must not be popped"); - } - while (n) { - CHECK(COMPILE(ret, "values item", n->nd_head)); - n = n->nd_next; - } - ADD_INSN1(ret, node, newarray, INT2FIX(node->nd_alen)); - break; - } case NODE_HASH: CHECK(compile_hash(iseq, ret, node, FALSE, popped) >= 0); break; @@ -9651,18 +11030,18 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no break; case NODE_LVAR:{ if (!popped) { - compile_lvar(iseq, ret, node, node->nd_vid); + compile_lvar(iseq, ret, node, RNODE_LVAR(node)->nd_vid); } break; } case NODE_DVAR:{ int lv, idx, ls; - debugi("nd_vid", node->nd_vid); + debugi("nd_vid", RNODE_DVAR(node)->nd_vid); if (!popped) { - idx = get_dyna_var_idx(iseq, node->nd_vid, &lv, &ls); + idx = get_dyna_var_idx(iseq, RNODE_DVAR(node)->nd_vid, &lv, &ls); if (idx < 0) { COMPILE_ERROR(ERROR_ARGS "unknown dvar (%"PRIsVALUE")", - rb_id2str(node->nd_vid)); + rb_id2str(RNODE_DVAR(node)->nd_vid)); goto ng; } ADD_GETLOCAL(ret, node, ls - idx, lv); @@ -9670,34 +11049,34 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no break; } case NODE_GVAR:{ - ADD_INSN1(ret, node, getglobal, ID2SYM(node->nd_vid)); + ADD_INSN1(ret, node, getglobal, ID2SYM(RNODE_GVAR(node)->nd_vid)); if (popped) { ADD_INSN(ret, node, pop); } break; } case NODE_IVAR:{ - debugi("nd_vid", node->nd_vid); + debugi("nd_vid", RNODE_IVAR(node)->nd_vid); if (!popped) { ADD_INSN2(ret, node, getinstancevariable, - ID2SYM(node->nd_vid), - get_ivar_ic_value(iseq,node->nd_vid)); + ID2SYM(RNODE_IVAR(node)->nd_vid), + get_ivar_ic_value(iseq, RNODE_IVAR(node)->nd_vid)); } break; } case NODE_CONST:{ - debugi("nd_vid", node->nd_vid); + debugi("nd_vid", RNODE_CONST(node)->nd_vid); if (ISEQ_COMPILE_DATA(iseq)->option->inline_const_cache) { body->ic_size++; - VALUE segments = rb_ary_new_from_args(1, ID2SYM(node->nd_vid)); + VALUE segments = rb_ary_new_from_args(1, ID2SYM(RNODE_CONST(node)->nd_vid)); ADD_INSN1(ret, node, opt_getconstant_path, segments); RB_OBJ_WRITTEN(iseq, Qundef, segments); } else { ADD_INSN(ret, node, putnil); ADD_INSN1(ret, node, putobject, Qtrue); - ADD_INSN1(ret, node, getconstant, ID2SYM(node->nd_vid)); + ADD_INSN1(ret, node, getconstant, ID2SYM(RNODE_CONST(node)->nd_vid)); } if (popped) { @@ -9708,26 +11087,26 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no case NODE_CVAR:{ if (!popped) { ADD_INSN2(ret, node, getclassvariable, - ID2SYM(node->nd_vid), - get_cvar_ic_value(iseq,node->nd_vid)); + ID2SYM(RNODE_CVAR(node)->nd_vid), + get_cvar_ic_value(iseq, RNODE_CVAR(node)->nd_vid)); } break; } case NODE_NTH_REF:{ if (!popped) { - if (!node->nd_nth) { + if (!RNODE_NTH_REF(node)->nd_nth) { ADD_INSN(ret, node, putnil); break; } ADD_INSN2(ret, node, getspecial, INT2FIX(1) /* '~' */, - INT2FIX(node->nd_nth << 1)); + INT2FIX(RNODE_NTH_REF(node)->nd_nth << 1)); } break; } case NODE_BACK_REF:{ if (!popped) { ADD_INSN2(ret, node, getspecial, INT2FIX(1) /* '~' */, - INT2FIX(0x01 | (node->nd_nth << 1))); + INT2FIX(0x01 | (RNODE_BACK_REF(node)->nd_nth << 1))); } break; } @@ -9736,36 +11115,84 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no case NODE_MATCH3: CHECK(compile_match(iseq, ret, node, popped, type)); break; - case NODE_LIT:{ - debugp_param("lit", node->nd_lit); + case NODE_SYM:{ + if (!popped) { + ADD_INSN1(ret, node, putobject, rb_node_sym_string_val(node)); + } + break; + } + case NODE_LINE:{ + if (!popped) { + ADD_INSN1(ret, node, putobject, rb_node_line_lineno_val(node)); + } + break; + } + case NODE_ENCODING:{ + if (!popped) { + ADD_INSN1(ret, node, putobject, rb_node_encoding_val(node)); + } + break; + } + case NODE_INTEGER:{ + VALUE lit = rb_node_integer_literal_val(node); + debugp_param("integer", lit); + if (!popped) { + ADD_INSN1(ret, node, putobject, lit); + RB_OBJ_WRITTEN(iseq, Qundef, lit); + } + break; + } + case NODE_FLOAT:{ + VALUE lit = rb_node_float_literal_val(node); + debugp_param("float", lit); + if (!popped) { + ADD_INSN1(ret, node, putobject, lit); + RB_OBJ_WRITTEN(iseq, Qundef, lit); + } + break; + } + case NODE_RATIONAL:{ + VALUE lit = rb_node_rational_literal_val(node); + debugp_param("rational", lit); + if (!popped) { + ADD_INSN1(ret, node, putobject, lit); + RB_OBJ_WRITTEN(iseq, Qundef, lit); + } + break; + } + case NODE_IMAGINARY:{ + VALUE lit = rb_node_imaginary_literal_val(node); + debugp_param("imaginary", lit); if (!popped) { - ADD_INSN1(ret, node, putobject, node->nd_lit); - RB_OBJ_WRITTEN(iseq, Qundef, node->nd_lit); + ADD_INSN1(ret, node, putobject, lit); + RB_OBJ_WRITTEN(iseq, Qundef, lit); } break; } + case NODE_FILE: case NODE_STR:{ - debugp_param("nd_lit", node->nd_lit); + debugp_param("nd_lit", get_string_value(node)); if (!popped) { - VALUE lit = node->nd_lit; - if (!ISEQ_COMPILE_DATA(iseq)->option->frozen_string_literal) { - lit = rb_fstring(lit); + VALUE lit = get_string_value(node); + const rb_compile_option_t *option = ISEQ_COMPILE_DATA(iseq)->option; + if ((option->debug_frozen_string_literal || RTEST(ruby_debug)) && + option->frozen_string_literal != ISEQ_FROZEN_STRING_LITERAL_DISABLED) { + lit = rb_str_with_debug_created_info(lit, rb_iseq_path(iseq), line); + } + switch (option->frozen_string_literal) { + case ISEQ_FROZEN_STRING_LITERAL_UNSET: + ADD_INSN1(ret, node, putchilledstring, lit); + break; + case ISEQ_FROZEN_STRING_LITERAL_DISABLED: ADD_INSN1(ret, node, putstring, lit); - RB_OBJ_WRITTEN(iseq, Qundef, lit); - } - else { - if (ISEQ_COMPILE_DATA(iseq)->option->debug_frozen_string_literal || RTEST(ruby_debug)) { - VALUE debug_info = rb_ary_new_from_args(2, rb_iseq_path(iseq), INT2FIX(line)); - lit = rb_str_dup(lit); - rb_ivar_set(lit, id_debug_created_info, rb_obj_freeze(debug_info)); - lit = rb_str_freeze(lit); - } - else { - lit = rb_fstring(lit); - } + break; + case ISEQ_FROZEN_STRING_LITERAL_ENABLED: ADD_INSN1(ret, node, putobject, lit); - RB_OBJ_WRITTEN(iseq, Qundef, lit); + break; + default: + rb_bug("invalid frozen_string_literal"); } + RB_OBJ_WRITTEN(iseq, Qundef, lit); } break; } @@ -9779,7 +11206,7 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no } case NODE_XSTR:{ ADD_CALL_RECEIVER(ret, node); - VALUE str = rb_fstring(node->nd_lit); + VALUE str = rb_node_str_string_val(node); ADD_INSN1(ret, node, putobject, str); RB_OBJ_WRITTEN(iseq, Qundef, str); ADD_CALL(ret, node, idBackquote, INT2FIX(1)); @@ -9800,20 +11227,23 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no break; } case NODE_EVSTR: - CHECK(compile_evstr(iseq, ret, node->nd_body, popped)); + CHECK(compile_evstr(iseq, ret, RNODE_EVSTR(node)->nd_body, popped)); break; - case NODE_DREGX:{ - compile_dregx(iseq, ret, node); - - if (popped) { - ADD_INSN(ret, node, pop); + case NODE_REGX:{ + if (!popped) { + VALUE lit = rb_node_regx_string_val(node); + ADD_INSN1(ret, node, putobject, lit); + RB_OBJ_WRITTEN(iseq, Qundef, lit); } break; } + case NODE_DREGX: + compile_dregx(iseq, ret, node, popped); + break; case NODE_ONCE:{ int ic_index = body->ise_size++; const rb_iseq_t *block_iseq; - block_iseq = NEW_CHILD_ISEQ(node->nd_body, make_name_for_block(iseq), ISEQ_TYPE_PLAIN, line); + block_iseq = NEW_CHILD_ISEQ(RNODE_ONCE(node)->nd_body, make_name_for_block(iseq), ISEQ_TYPE_PLAIN, line); ADD_INSN2(ret, node, once, block_iseq, INT2FIX(ic_index)); RB_OBJ_WRITTEN(iseq, Qundef, (VALUE)block_iseq); @@ -9825,36 +11255,53 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no } case NODE_ARGSCAT:{ if (popped) { - CHECK(COMPILE(ret, "argscat head", node->nd_head)); + CHECK(COMPILE(ret, "argscat head", RNODE_ARGSCAT(node)->nd_head)); ADD_INSN1(ret, node, splatarray, Qfalse); ADD_INSN(ret, node, pop); - CHECK(COMPILE(ret, "argscat body", node->nd_body)); + CHECK(COMPILE(ret, "argscat body", RNODE_ARGSCAT(node)->nd_body)); ADD_INSN1(ret, node, splatarray, Qfalse); ADD_INSN(ret, node, pop); } else { - CHECK(COMPILE(ret, "argscat head", node->nd_head)); - CHECK(COMPILE(ret, "argscat body", node->nd_body)); - ADD_INSN(ret, node, concatarray); + CHECK(COMPILE(ret, "argscat head", RNODE_ARGSCAT(node)->nd_head)); + const NODE *body_node = RNODE_ARGSCAT(node)->nd_body; + if (nd_type_p(body_node, NODE_LIST)) { + CHECK(compile_array(iseq, ret, body_node, popped, FALSE) >= 0); + } + else { + CHECK(COMPILE(ret, "argscat body", body_node)); + ADD_INSN(ret, node, concattoarray); + } } break; } case NODE_ARGSPUSH:{ if (popped) { - CHECK(COMPILE(ret, "argspush head", node->nd_head)); + CHECK(COMPILE(ret, "argspush head", RNODE_ARGSPUSH(node)->nd_head)); ADD_INSN1(ret, node, splatarray, Qfalse); ADD_INSN(ret, node, pop); - CHECK(COMPILE_(ret, "argspush body", node->nd_body, popped)); + CHECK(COMPILE_(ret, "argspush body", RNODE_ARGSPUSH(node)->nd_body, popped)); } else { - CHECK(COMPILE(ret, "argspush head", node->nd_head)); - CHECK(compile_array_1(iseq, ret, node->nd_body)); - ADD_INSN(ret, node, concatarray); + CHECK(COMPILE(ret, "argspush head", RNODE_ARGSPUSH(node)->nd_head)); + const NODE *body_node = RNODE_ARGSPUSH(node)->nd_body; + if (keyword_node_p(body_node)) { + CHECK(COMPILE_(ret, "array element", body_node, FALSE)); + ADD_INSN(ret, node, pushtoarraykwsplat); + } + else if (static_literal_node_p(body_node, iseq, false)) { + ADD_INSN1(ret, body_node, putobject, static_literal_value(body_node, iseq)); + ADD_INSN1(ret, node, pushtoarray, INT2FIX(1)); + } + else { + CHECK(COMPILE_(ret, "array element", body_node, FALSE)); + ADD_INSN1(ret, node, pushtoarray, INT2FIX(1)); + } } break; } case NODE_SPLAT:{ - CHECK(COMPILE(ret, "splat", node->nd_head)); + CHECK(COMPILE(ret, "splat", RNODE_SPLAT(node)->nd_head)); ADD_INSN1(ret, node, splatarray, Qtrue); if (popped) { @@ -9863,8 +11310,8 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no break; } case NODE_DEFN:{ - ID mid = node->nd_mid; - const rb_iseq_t *method_iseq = NEW_ISEQ(node->nd_defn, + ID mid = RNODE_DEFN(node)->nd_mid; + const rb_iseq_t *method_iseq = NEW_ISEQ(RNODE_DEFN(node)->nd_defn, rb_id2str(mid), ISEQ_TYPE_METHOD, line); @@ -9879,13 +11326,13 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no break; } case NODE_DEFS:{ - ID mid = node->nd_mid; - const rb_iseq_t * singleton_method_iseq = NEW_ISEQ(node->nd_defn, + ID mid = RNODE_DEFS(node)->nd_mid; + const rb_iseq_t * singleton_method_iseq = NEW_ISEQ(RNODE_DEFS(node)->nd_defn, rb_id2str(mid), ISEQ_TYPE_METHOD, line); debugp_param("defs/iseq", rb_iseqw_new(singleton_method_iseq)); - CHECK(COMPILE(ret, "defs: recv", node->nd_recv)); + CHECK(COMPILE(ret, "defs: recv", RNODE_DEFS(node)->nd_recv)); ADD_INSN2(ret, node, definesmethod, ID2SYM(mid), singleton_method_iseq); RB_OBJ_WRITTEN(iseq, Qundef, (VALUE)singleton_method_iseq); @@ -9897,8 +11344,8 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no case NODE_ALIAS:{ ADD_INSN1(ret, node, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); ADD_INSN1(ret, node, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_CBASE)); - CHECK(COMPILE(ret, "alias arg1", node->nd_1st)); - CHECK(COMPILE(ret, "alias arg2", node->nd_2nd)); + CHECK(COMPILE(ret, "alias arg1", RNODE_ALIAS(node)->nd_1st)); + CHECK(COMPILE(ret, "alias arg2", RNODE_ALIAS(node)->nd_2nd)); ADD_SEND(ret, node, id_core_set_method_alias, INT2FIX(3)); if (popped) { @@ -9908,8 +11355,8 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no } case NODE_VALIAS:{ ADD_INSN1(ret, node, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); - ADD_INSN1(ret, node, putobject, ID2SYM(node->nd_alias)); - ADD_INSN1(ret, node, putobject, ID2SYM(node->nd_orig)); + ADD_INSN1(ret, node, putobject, ID2SYM(RNODE_VALIAS(node)->nd_alias)); + ADD_INSN1(ret, node, putobject, ID2SYM(RNODE_VALIAS(node)->nd_orig)); ADD_SEND(ret, node, id_core_set_variable_alias, INT2FIX(2)); if (popped) { @@ -9918,10 +11365,18 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no break; } case NODE_UNDEF:{ - ADD_INSN1(ret, node, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); - ADD_INSN1(ret, node, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_CBASE)); - CHECK(COMPILE(ret, "undef arg", node->nd_undef)); - ADD_SEND(ret, node, id_core_undef_method, INT2FIX(2)); + const rb_parser_ary_t *ary = RNODE_UNDEF(node)->nd_undefs; + + for (long i = 0; i < ary->len; i++) { + ADD_INSN1(ret, node, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); + ADD_INSN1(ret, node, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_CBASE)); + CHECK(COMPILE(ret, "undef arg", ary->data[i])); + ADD_SEND(ret, node, id_core_undef_method, INT2FIX(2)); + + if (i < ary->len - 1) { + ADD_INSN(ret, node, pop); + } + } if (popped) { ADD_INSN(ret, node, pop); @@ -9929,15 +11384,15 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no break; } case NODE_CLASS:{ - const rb_iseq_t *class_iseq = NEW_CHILD_ISEQ(node->nd_body, - rb_str_freeze(rb_sprintf("", rb_id2str(node->nd_cpath->nd_mid))), + const rb_iseq_t *class_iseq = NEW_CHILD_ISEQ(RNODE_CLASS(node)->nd_body, + rb_str_freeze(rb_sprintf("", rb_id2str(get_node_colon_nd_mid(RNODE_CLASS(node)->nd_cpath)))), ISEQ_TYPE_CLASS, line); const int flags = VM_DEFINECLASS_TYPE_CLASS | - (node->nd_super ? VM_DEFINECLASS_FLAG_HAS_SUPERCLASS : 0) | - compile_cpath(ret, iseq, node->nd_cpath); + (RNODE_CLASS(node)->nd_super ? VM_DEFINECLASS_FLAG_HAS_SUPERCLASS : 0) | + compile_cpath(ret, iseq, RNODE_CLASS(node)->nd_cpath); - CHECK(COMPILE(ret, "super", node->nd_super)); - ADD_INSN3(ret, node, defineclass, ID2SYM(node->nd_cpath->nd_mid), class_iseq, INT2FIX(flags)); + CHECK(COMPILE(ret, "super", RNODE_CLASS(node)->nd_super)); + ADD_INSN3(ret, node, defineclass, ID2SYM(get_node_colon_nd_mid(RNODE_CLASS(node)->nd_cpath)), class_iseq, INT2FIX(flags)); RB_OBJ_WRITTEN(iseq, Qundef, (VALUE)class_iseq); if (popped) { @@ -9946,14 +11401,14 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no break; } case NODE_MODULE:{ - const rb_iseq_t *module_iseq = NEW_CHILD_ISEQ(node->nd_body, - rb_str_freeze(rb_sprintf("", rb_id2str(node->nd_cpath->nd_mid))), + const rb_iseq_t *module_iseq = NEW_CHILD_ISEQ(RNODE_MODULE(node)->nd_body, + rb_str_freeze(rb_sprintf("", rb_id2str(get_node_colon_nd_mid(RNODE_MODULE(node)->nd_cpath)))), ISEQ_TYPE_CLASS, line); const int flags = VM_DEFINECLASS_TYPE_MODULE | - compile_cpath(ret, iseq, node->nd_cpath); + compile_cpath(ret, iseq, RNODE_MODULE(node)->nd_cpath); ADD_INSN (ret, node, putnil); /* dummy */ - ADD_INSN3(ret, node, defineclass, ID2SYM(node->nd_cpath->nd_mid), module_iseq, INT2FIX(flags)); + ADD_INSN3(ret, node, defineclass, ID2SYM(get_node_colon_nd_mid(RNODE_MODULE(node)->nd_cpath)), module_iseq, INT2FIX(flags)); RB_OBJ_WRITTEN(iseq, Qundef, (VALUE)module_iseq); if (popped) { @@ -9963,10 +11418,10 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no } case NODE_SCLASS:{ ID singletonclass; - const rb_iseq_t *singleton_class = NEW_ISEQ(node->nd_body, rb_fstring_lit("singleton class"), + const rb_iseq_t *singleton_class = NEW_ISEQ(RNODE_SCLASS(node)->nd_body, rb_fstring_lit("singleton class"), ISEQ_TYPE_CLASS, line); - CHECK(COMPILE(ret, "sclass#recv", node->nd_recv)); + CHECK(COMPILE(ret, "sclass#recv", RNODE_SCLASS(node)->nd_recv)); ADD_INSN (ret, node, putnil); CONST_ID(singletonclass, "singletonclass"); ADD_INSN3(ret, node, defineclass, @@ -10035,7 +11490,7 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no break; case NODE_DEFINED: if (!popped) { - CHECK(compile_defined_expr(iseq, ret, node, Qtrue)); + CHECK(compile_defined_expr(iseq, ret, node, Qtrue, false)); } break; case NODE_POSTEXE:{ @@ -10044,10 +11499,9 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no */ int is_index = body->ise_size++; struct rb_iseq_new_with_callback_callback_func *ifunc = - rb_iseq_new_with_callback_new_callback(build_postexe_iseq, node->nd_body); + rb_iseq_new_with_callback_new_callback(build_postexe_iseq, RNODE_POSTEXE(node)->nd_body); const rb_iseq_t *once_iseq = - new_child_iseq_with_callback(iseq, ifunc, - rb_fstring(make_name_for_block(iseq)), iseq, ISEQ_TYPE_BLOCK, line); + NEW_CHILD_ISEQ_WITH_CALLBACK(ifunc, rb_fstring(make_name_for_block(iseq)), ISEQ_TYPE_BLOCK, line); ADD_INSN2(ret, node, once, once_iseq, INT2FIX(is_index)); RB_OBJ_WRITTEN(iseq, Qundef, (VALUE)once_iseq); @@ -10075,7 +11529,7 @@ iseq_compile_each0(rb_iseq_t *iseq, LINK_ANCHOR *const ret, const NODE *const no break; case NODE_LAMBDA:{ /* compile same as lambda{...} */ - const rb_iseq_t *block = NEW_CHILD_ISEQ(node->nd_body, make_name_for_block(iseq), ISEQ_TYPE_BLOCK, line); + const rb_iseq_t *block = NEW_CHILD_ISEQ(RNODE_LAMBDA(node)->nd_body, make_name_for_block(iseq), ISEQ_TYPE_BLOCK, line); VALUE argc = INT2FIX(0); ADD_INSN1(ret, node, putspecialobject, INT2FIX(VM_SPECIAL_OBJECT_VMCORE)); @@ -10260,7 +11714,7 @@ dump_disasm_list_with_cursor(const LINK_ELEMENT *link, const LINK_ELEMENT *curr, case ISEQ_ELEMENT_LABEL: { lobj = (LABEL *)link; - printf(LABEL_FORMAT" [sp: %d]%s\n", lobj->label_no, lobj->sp, + printf(LABEL_FORMAT" [sp: %d, unremovable: %d, refcnt: %d]%s\n", lobj->label_no, lobj->sp, lobj->unremovable, lobj->refcnt, dest == lobj ? " <---" : ""); break; } @@ -10278,7 +11732,7 @@ dump_disasm_list_with_cursor(const LINK_ELEMENT *link, const LINK_ELEMENT *curr, } default: /* ignore */ - rb_raise(rb_eSyntaxError, "dump_disasm_list error: %ld\n", FIX2LONG(link->type)); + rb_raise(rb_eSyntaxError, "dump_disasm_list error: %d\n", (int)link->type); } link = link->next; } @@ -10306,7 +11760,7 @@ rb_insns_name_array(void) for (i = 0; i < VM_INSTRUCTION_SIZE; i++) { rb_ary_push(ary, rb_fstring_cstr(insn_name(i))); } - return rb_obj_freeze(ary); + return rb_ary_freeze(ary); } static LABEL * @@ -10455,6 +11909,7 @@ iseq_build_callinfo_from_hash(rb_iseq_t *iseq, VALUE op) size_t n = rb_callinfo_kwarg_bytes(len); kw_arg = xmalloc(n); + kw_arg->references = 0; kw_arg->keyword_len = len; for (i = 0; i < len; i++) { VALUE kw = RARRAY_AREF(vkw_arg, i); @@ -10491,7 +11946,7 @@ iseq_build_from_ary_body(rb_iseq_t *iseq, LINK_ANCHOR *const anchor, { /* TODO: body should be frozen */ long i, len = RARRAY_LEN(body); - struct st_table *labels_table = DATA_PTR(labels_wrapper); + struct st_table *labels_table = RTYPEDDATA_DATA(labels_wrapper); int j; int line_no = 0, node_id = -1, insn_idx = 0; int ret = COMPILE_OK; @@ -10551,9 +12006,8 @@ iseq_build_from_ary_body(rb_iseq_t *iseq, LINK_ANCHOR *const anchor, argv = compile_data_calloc2(iseq, sizeof(VALUE), argc); // add element before operand setup to make GC root - NODE dummy_line_node = generate_dummy_line_node(line_no, node_id); ADD_ELEM(anchor, - (LINK_ELEMENT*)new_insn_core(iseq, &dummy_line_node, + (LINK_ELEMENT*)new_insn_core(iseq, line_no, node_id, (enum ruby_vminsn_type)insn_id, argc, argv)); for (j=0; jtable = ids; @@ -10765,9 +12219,9 @@ iseq_build_kw(rb_iseq_t *iseq, VALUE params, VALUE keywords) } static void -iseq_insn_each_object_mark_and_move(VALUE *obj_ptr, VALUE _) +iseq_insn_each_object_mark_and_move(VALUE * obj, VALUE _) { - rb_gc_mark_and_move(obj_ptr); + rb_gc_mark_and_move(obj); } void @@ -10803,6 +12257,15 @@ rb_iseq_mark_and_move_insn_storage(struct iseq_compile_data_storage *storage) } } +static const rb_data_type_t labels_wrapper_type = { + .wrap_struct_name = "compiler/labels_wrapper", + .function = { + .dmark = (RUBY_DATA_FUNC)rb_mark_set, + .dfree = (RUBY_DATA_FUNC)st_free_table, + }, + .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED, +}; + void rb_iseq_build_from_ary(rb_iseq_t *iseq, VALUE misc, VALUE locals, VALUE params, VALUE exception, VALUE body) @@ -10812,7 +12275,7 @@ rb_iseq_build_from_ary(rb_iseq_t *iseq, VALUE misc, VALUE locals, VALUE params, unsigned int arg_size, local_size, stack_max; ID *tbl; struct st_table *labels_table = st_init_numtable(); - VALUE labels_wrapper = Data_Wrap_Struct(0, rb_mark_set, st_free_table, labels_table); + VALUE labels_wrapper = TypedData_Wrap_Struct(0, &labels_wrapper_type, labels_table); VALUE arg_opt_labels = rb_hash_aref(params, SYM(opt)); VALUE keywords = rb_hash_aref(params, SYM(keyword)); VALUE sym_arg_rest = ID2SYM(rb_intern_const("#arg_rest")); @@ -10894,6 +12357,10 @@ rb_iseq_build_from_ary(rb_iseq_t *iseq, VALUE misc, VALUE locals, VALUE params, ISEQ_BODY(iseq)->param.flags.ambiguous_param0 = TRUE; } + if (Qtrue == rb_hash_aref(params, SYM(use_block))) { + ISEQ_BODY(iseq)->param.flags.use_block = TRUE; + } + if (int_param(&i, params, SYM(kwrest))) { struct rb_iseq_param_keyword *keyword = (struct rb_iseq_param_keyword *)ISEQ_BODY(iseq)->param.keyword; if (keyword == NULL) { @@ -10969,7 +12436,7 @@ rb_local_defined(ID id, const rb_iseq_t *iseq) #define IBF_ISEQ_ENABLE_LOCAL_BUFFER 0 #endif -typedef unsigned int ibf_offset_t; +typedef uint32_t ibf_offset_t; #define IBF_OFFSET(ptr) ((ibf_offset_t)(VALUE)(ptr)) #define IBF_MAJOR_VERSION ISEQ_MAJOR_VERSION @@ -10980,17 +12447,27 @@ typedef unsigned int ibf_offset_t; #define IBF_MINOR_VERSION ISEQ_MINOR_VERSION #endif +static const char IBF_ENDIAN_MARK = +#ifdef WORDS_BIGENDIAN + 'b' +#else + 'l' +#endif + ; + struct ibf_header { char magic[4]; /* YARB */ - unsigned int major_version; - unsigned int minor_version; - unsigned int size; - unsigned int extra_size; + uint32_t major_version; + uint32_t minor_version; + uint32_t size; + uint32_t extra_size; - unsigned int iseq_list_size; - unsigned int global_object_list_size; + uint32_t iseq_list_size; + uint32_t global_object_list_size; ibf_offset_t iseq_list_offset; ibf_offset_t global_object_list_offset; + uint8_t endian; + uint8_t wordsize; /* assume no 2048-bit CPU */ }; struct ibf_dump_buffer { @@ -11025,7 +12502,7 @@ struct ibf_load { struct pinned_list { long size; - VALUE * buffer; + VALUE buffer[1]; }; static void @@ -11040,25 +12517,14 @@ pinned_list_mark(void *ptr) } } -static void -pinned_list_free(void *ptr) -{ - struct pinned_list *list = (struct pinned_list *)ptr; - xfree(list->buffer); - xfree(ptr); -} - -static size_t -pinned_list_memsize(const void *ptr) -{ - struct pinned_list *list = (struct pinned_list *)ptr; - return sizeof(struct pinned_list) + (list->size * sizeof(VALUE *)); -} - static const rb_data_type_t pinned_list_type = { "pinned_list", - {pinned_list_mark, pinned_list_free, pinned_list_memsize,}, - 0, 0, RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FREE_IMMEDIATELY + { + pinned_list_mark, + RUBY_DEFAULT_FREE, + NULL, // No external memory to report, + }, + 0, 0, RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_EMBEDDABLE }; static VALUE @@ -11092,13 +12558,10 @@ pinned_list_store(VALUE list, long offset, VALUE object) static VALUE pinned_list_new(long size) { - struct pinned_list * ptr; - VALUE obj_list = - TypedData_Make_Struct(0, struct pinned_list, &pinned_list_type, ptr); - - ptr->buffer = xcalloc(size, sizeof(VALUE)); + size_t memsize = offsetof(struct pinned_list, buffer) + size * sizeof(VALUE); + VALUE obj_list = rb_data_typed_object_zalloc(0, memsize, &pinned_list_type); + struct pinned_list * ptr = RTYPEDDATA_GET_DATA(obj_list); ptr->size = size; - return obj_list; } @@ -11137,8 +12600,13 @@ static ibf_offset_t ibf_dump_write(struct ibf_dump *dump, const void *buff, unsigned long size) { ibf_offset_t pos = ibf_dump_pos(dump); +#if SIZEOF_LONG > SIZEOF_INT + /* ensure the resulting dump does not exceed UINT_MAX */ + if (size >= UINT_MAX || pos + size >= UINT_MAX) { + rb_raise(rb_eRuntimeError, "dump size exceeds"); + } +#endif rb_str_cat(dump->current_buffer->str, (const char *)buff, size); - /* TODO: overflow check */ return pos; } @@ -11247,6 +12715,10 @@ ibf_load_id(const struct ibf_load *load, const ID id_index) return 0; } VALUE sym = ibf_load_object(load, id_index); + if (rb_integer_type_p(sym)) { + /* Load hidden local variables as indexes */ + return NUM2ULONG(sym); + } return rb_sym2id(sym); } @@ -11446,7 +12918,7 @@ ibf_dump_code(struct ibf_dump *dump, const rb_iseq_t *iseq) ibf_dump_write_small_value(dump, wv); skip_wv:; } - assert(insn_len(insn) == op_index+1); + RUBY_ASSERT(insn_len(insn) == op_index+1); } return offset; @@ -11611,8 +13083,8 @@ ibf_load_code(const struct ibf_load *load, rb_iseq_t *iseq, ibf_offset_t bytecod } } - assert(code_index == iseq_size); - assert(reading_pos == bytecode_offset + bytecode_size); + RUBY_ASSERT(code_index == iseq_size); + RUBY_ASSERT(reading_pos == bytecode_offset + bytecode_size); return code; } @@ -11673,19 +13145,17 @@ ibf_load_param_keyword(const struct ibf_load *load, ibf_offset_t param_keyword_o { if (param_keyword_offset) { struct rb_iseq_param_keyword *kw = IBF_R(param_keyword_offset, struct rb_iseq_param_keyword, 1); - ID *ids = IBF_R(kw->table, ID, kw->num); int dv_num = kw->num - kw->required_num; - VALUE *dvs = IBF_R(kw->default_values, VALUE, dv_num); - int i; + VALUE *dvs = dv_num ? IBF_R(kw->default_values, VALUE, dv_num) : NULL; - for (i=0; inum; i++) { - ids[i] = ibf_load_id(load, ids[i]); - } + int i; for (i=0; itable = ids; + // Will be set once the local table is loaded. + kw->table = NULL; + kw->default_values = dvs; return kw; } @@ -11770,7 +13240,12 @@ ibf_dump_local_table(struct ibf_dump *dump, const rb_iseq_t *iseq) int i; for (i=0; ilocal_table[i]); + VALUE v = ibf_dump_id(dump, body->local_table[i]); + if (v == 0) { + /* Dump hidden local variables as indexes, so load_from_binary will work with them */ + v = ibf_dump_object(dump, ULONG2NUM(body->local_table[i])); + } + table[i] = v; } IBF_W_ALIGN(ID); @@ -11824,12 +13299,13 @@ ibf_dump_catch_table(struct ibf_dump *dump, const rb_iseq_t *iseq) } } -static struct iseq_catch_table * -ibf_load_catch_table(const struct ibf_load *load, ibf_offset_t catch_table_offset, unsigned int size) +static void +ibf_load_catch_table(const struct ibf_load *load, ibf_offset_t catch_table_offset, unsigned int size, const rb_iseq_t *parent_iseq) { if (size) { - struct iseq_catch_table *table = ruby_xmalloc(iseq_catch_table_bytes(size)); + struct iseq_catch_table *table = ruby_xcalloc(1, iseq_catch_table_bytes(size)); table->size = size; + ISEQ_BODY(parent_iseq)->catch_table = table; ibf_offset_t reading_pos = catch_table_offset; @@ -11842,12 +13318,12 @@ ibf_load_catch_table(const struct ibf_load *load, ibf_offset_t catch_table_offse table->entries[i].cont = (unsigned int)ibf_load_small_value(load, &reading_pos); table->entries[i].sp = (unsigned int)ibf_load_small_value(load, &reading_pos); - table->entries[i].iseq = ibf_load_iseq(load, (const rb_iseq_t *)(VALUE)iseq_index); + rb_iseq_t *catch_iseq = (rb_iseq_t *)ibf_load_iseq(load, (const rb_iseq_t *)(VALUE)iseq_index); + RB_OBJ_WRITE(parent_iseq, UNALIGNED_MEMBER_PTR(&table->entries[i], iseq), catch_iseq); } - return table; } else { - return NULL; + ISEQ_BODY(parent_iseq)->catch_table = NULL; } } @@ -11891,15 +13367,44 @@ ibf_dump_ci_entries(struct ibf_dump *dump, const rb_iseq_t *iseq) return offset; } +struct outer_variable_pair { + ID id; + VALUE name; + VALUE val; +}; + +struct outer_variable_list { + size_t num; + struct outer_variable_pair pairs[1]; +}; + static enum rb_id_table_iterator_result -dump_outer_variable(ID id, VALUE val, void *dump) +store_outer_variable(ID id, VALUE val, void *dump) { - ibf_dump_write_small_value(dump, ibf_dump_id(dump, id)); - ibf_dump_write_small_value(dump, val); - + struct outer_variable_list *ovlist = dump; + struct outer_variable_pair *pair = &ovlist->pairs[ovlist->num++]; + pair->id = id; + pair->name = rb_id2str(id); + pair->val = val; return ID_TABLE_CONTINUE; } +static int +outer_variable_cmp(const void *a, const void *b, void *arg) +{ + const struct outer_variable_pair *ap = (const struct outer_variable_pair *)a; + const struct outer_variable_pair *bp = (const struct outer_variable_pair *)b; + + if (!ap->name) { + return -1; + } + else if (!bp->name) { + return 1; + } + + return rb_str_cmp(ap->name, bp->name); +} + static ibf_offset_t ibf_dump_outer_variables(struct ibf_dump *dump, const rb_iseq_t *iseq) { @@ -11907,12 +13412,24 @@ ibf_dump_outer_variables(struct ibf_dump *dump, const rb_iseq_t *iseq) ibf_offset_t offset = ibf_dump_pos(dump); - if (ovs) { - ibf_dump_write_small_value(dump, (VALUE)rb_id_table_size(ovs)); - rb_id_table_foreach(ovs, dump_outer_variable, (void *)dump); - } - else { - ibf_dump_write_small_value(dump, (VALUE)0); + size_t size = ovs ? rb_id_table_size(ovs) : 0; + ibf_dump_write_small_value(dump, (VALUE)size); + if (size > 0) { + VALUE buff; + size_t buffsize = + rb_size_mul_add_or_raise(sizeof(struct outer_variable_pair), size, + offsetof(struct outer_variable_list, pairs), + rb_eArgError); + struct outer_variable_list *ovlist = RB_ALLOCV(buff, buffsize); + ovlist->num = 0; + rb_id_table_foreach(ovs, store_outer_variable, ovlist); + ruby_qsort(ovlist->pairs, size, sizeof(struct outer_variable_pair), outer_variable_cmp, NULL); + for (size_t i = 0; i < size; ++i) { + ID id = ovlist->pairs[i].id; + ID val = ovlist->pairs[i].val; + ibf_dump_write_small_value(dump, ibf_dump_id(dump, id)); + ibf_dump_write_small_value(dump, val); + } } return offset; @@ -11925,6 +13442,11 @@ ibf_load_ci_entries(const struct ibf_load *load, unsigned int ci_size, struct rb_call_data **cd_ptr) { + if (!ci_size) { + *cd_ptr = NULL; + return; + } + ibf_offset_t reading_pos = ci_entries_offset; unsigned int i; @@ -11943,6 +13465,7 @@ ibf_load_ci_entries(const struct ibf_load *load, int kwlen = (int)ibf_load_small_value(load, &reading_pos); if (kwlen > 0) { kwarg = rb_xmalloc_mul_add(kwlen, sizeof(VALUE), sizeof(struct rb_callinfo_kwarg)); + kwarg->references = 0; kwarg->keyword_len = kwlen; for (int j=0; jcurrent_buffer == &dump->global_buffer); + RUBY_ASSERT(dump->current_buffer == &dump->global_buffer); unsigned int *positions; @@ -12047,7 +13570,11 @@ ibf_dump_iseq_each(struct ibf_dump *dump, const rb_iseq_t *iseq) (body->param.flags.has_block << 6) | (body->param.flags.ambiguous_param0 << 7) | (body->param.flags.accepts_no_kwarg << 8) | - (body->param.flags.ruby2_keywords << 9); + (body->param.flags.ruby2_keywords << 9) | + (body->param.flags.anon_rest << 10) | + (body->param.flags.anon_kwrest << 11) | + (body->param.flags.use_block << 12) | + (body->param.flags.forwardable << 13) ; #if IBF_ISEQ_ENABLE_LOCAL_BUFFER # define IBF_BODY_OFFSET(x) (x) @@ -12098,6 +13625,7 @@ ibf_dump_iseq_each(struct ibf_dump *dump, const rb_iseq_t *iseq) ibf_dump_write_small_value(dump, body->ci_size); ibf_dump_write_small_value(dump, body->stack_max); ibf_dump_write_small_value(dump, body->builtin_attrs); + ibf_dump_write_small_value(dump, body->prism ? 1 : 0); #undef IBF_BODY_OFFSET @@ -12210,6 +13738,7 @@ ibf_load_iseq_each(struct ibf_load *load, rb_iseq_t *iseq, ibf_offset_t offset) const unsigned int ci_size = (unsigned int)ibf_load_small_value(load, &reading_pos); const unsigned int stack_max = (unsigned int)ibf_load_small_value(load, &reading_pos); const unsigned int builtin_attrs = (unsigned int)ibf_load_small_value(load, &reading_pos); + const bool prism = (bool)ibf_load_small_value(load, &reading_pos); // setup fname and dummy frame VALUE path = ibf_load_object(load, location_pathobj_index); @@ -12259,6 +13788,10 @@ ibf_load_iseq_each(struct ibf_load *load, rb_iseq_t *iseq, ibf_offset_t offset) load_body->param.flags.ambiguous_param0 = (param_flags >> 7) & 1; load_body->param.flags.accepts_no_kwarg = (param_flags >> 8) & 1; load_body->param.flags.ruby2_keywords = (param_flags >> 9) & 1; + load_body->param.flags.anon_rest = (param_flags >> 10) & 1; + load_body->param.flags.anon_kwrest = (param_flags >> 11) & 1; + load_body->param.flags.use_block = (param_flags >> 12) & 1; + load_body->param.flags.forwardable = (param_flags >> 13) & 1; load_body->param.size = param_size; load_body->param.lead_num = param_lead_num; load_body->param.opt_num = param_opt_num; @@ -12282,12 +13815,19 @@ ibf_load_iseq_each(struct ibf_load *load, rb_iseq_t *iseq, ibf_offset_t offset) load_body->location.code_location.end_pos.lineno = location_code_location_end_pos_lineno; load_body->location.code_location.end_pos.column = location_code_location_end_pos_column; load_body->builtin_attrs = builtin_attrs; + load_body->prism = prism; load_body->ivc_size = ivc_size; load_body->icvarc_size = icvarc_size; load_body->ise_size = ise_size; load_body->ic_size = ic_size; - load_body->is_entries = ZALLOC_N(union iseq_inline_storage_entry, ISEQ_IS_SIZE(load_body)); + + if (ISEQ_IS_SIZE(load_body)) { + load_body->is_entries = ZALLOC_N(union iseq_inline_storage_entry, ISEQ_IS_SIZE(load_body)); + } + else { + load_body->is_entries = NULL; + } ibf_load_ci_entries(load, ci_entries_offset, ci_size, &load_body->call_data); load_body->outer_variables = ibf_load_outer_variables(load, outer_variables_offset); load_body->param.opt_table = ibf_load_param_opt_table(load, param_opt_table_offset, param_opt_num); @@ -12296,10 +13836,22 @@ ibf_load_iseq_each(struct ibf_load *load, rb_iseq_t *iseq, ibf_offset_t offset) load_body->insns_info.body = ibf_load_insns_info_body(load, insns_info_body_offset, insns_info_size); load_body->insns_info.positions = ibf_load_insns_info_positions(load, insns_info_positions_offset, insns_info_size); load_body->local_table = ibf_load_local_table(load, local_table_offset, local_table_size); - load_body->catch_table = ibf_load_catch_table(load, catch_table_offset, catch_table_size); - load_body->parent_iseq = ibf_load_iseq(load, (const rb_iseq_t *)(VALUE)parent_iseq_index); - load_body->local_iseq = ibf_load_iseq(load, (const rb_iseq_t *)(VALUE)local_iseq_index); - load_body->mandatory_only_iseq = ibf_load_iseq(load, (const rb_iseq_t *)(VALUE)mandatory_only_iseq_index); + ibf_load_catch_table(load, catch_table_offset, catch_table_size, iseq); + + const rb_iseq_t *parent_iseq = ibf_load_iseq(load, (const rb_iseq_t *)(VALUE)parent_iseq_index); + const rb_iseq_t *local_iseq = ibf_load_iseq(load, (const rb_iseq_t *)(VALUE)local_iseq_index); + const rb_iseq_t *mandatory_only_iseq = ibf_load_iseq(load, (const rb_iseq_t *)(VALUE)mandatory_only_iseq_index); + + RB_OBJ_WRITE(iseq, &load_body->parent_iseq, parent_iseq); + RB_OBJ_WRITE(iseq, &load_body->local_iseq, local_iseq); + RB_OBJ_WRITE(iseq, &load_body->mandatory_only_iseq, mandatory_only_iseq); + + // This must be done after the local table is loaded. + if (load_body->param.keyword != NULL) { + RUBY_ASSERT(load_body->local_table); + struct rb_iseq_param_keyword *keyword = (struct rb_iseq_param_keyword *) load_body->param.keyword; + keyword->table = &load_body->local_table[keyword->bits_start - keyword->num]; + } ibf_load_code(load, iseq, bytecode_offset, bytecode_size, iseq_size); #if VM_INSN_INFO_TABLE_IMPL == 2 @@ -12560,7 +14112,7 @@ ibf_load_object_string(const struct ibf_load *load, const struct ibf_object_head VALUE str; if (header->frozen && !header->internal) { - str = rb_enc_interned_str(ptr, len, rb_enc_from_index(encindex)); + str = rb_enc_literal_str(ptr, len, rb_enc_from_index(encindex)); } else { str = rb_enc_str_new(ptr, len, rb_enc_from_index(encindex)); @@ -12625,7 +14177,7 @@ ibf_load_object_array(const struct ibf_load *load, const struct ibf_object_heade rb_ary_push(ary, ibf_load_object(load, index)); } - if (header->frozen) rb_obj_freeze(ary); + if (header->frozen) rb_ary_freeze(ary); return ary; } @@ -12727,8 +14279,12 @@ ibf_load_object_bignum(const struct ibf_load *load, const struct ibf_object_head const struct ibf_object_bignum *bignum = IBF_OBJBODY(struct ibf_object_bignum, offset); int sign = bignum->slen > 0; ssize_t len = sign > 0 ? bignum->slen : -1 * bignum->slen; - VALUE obj = rb_integer_unpack(bignum->digits, len * 2, 2, 0, - INTEGER_PACK_LITTLE_ENDIAN | (sign == 0 ? INTEGER_PACK_NEGATIVE : 0)); + const int big_unpack_flags = /* c.f. rb_big_unpack() */ + INTEGER_PACK_LSWORD_FIRST | + INTEGER_PACK_NATIVE_BYTE_ORDER; + VALUE obj = rb_integer_unpack(bignum->digits, len, sizeof(BDIGIT), 0, + big_unpack_flags | + (sign == 0 ? INTEGER_PACK_NEGATIVE : 0)); if (header->internal) rb_obj_hide(obj); if (header->frozen) rb_obj_freeze(obj); return obj; @@ -12904,7 +14460,7 @@ ibf_dump_object_object(struct ibf_dump *dump, VALUE obj) else { obj_header.internal = SPECIAL_CONST_P(obj) ? FALSE : (RBASIC_CLASS(obj) == 0) ? TRUE : FALSE; obj_header.special_const = FALSE; - obj_header.frozen = FL_TEST(obj, FL_FREEZE) ? TRUE : FALSE; + obj_header.frozen = OBJ_FROZEN(obj) ? TRUE : FALSE; ibf_dump_object_object_header(dump, obj_header); (*dump_object_functions[obj_header.type])(dump, obj); } @@ -13056,14 +14612,13 @@ ibf_dump_free(void *ptr) st_free_table(dump->iseq_table); dump->iseq_table = 0; } - ruby_xfree(dump); } static size_t ibf_dump_memsize(const void *ptr) { struct ibf_dump *dump = (struct ibf_dump *)ptr; - size_t size = sizeof(*dump); + size_t size = 0; if (dump->iseq_table) size += st_memsize(dump->iseq_table); if (dump->global_buffer.obj_table) size += st_memsize(dump->global_buffer.obj_table); return size; @@ -13072,7 +14627,7 @@ ibf_dump_memsize(const void *ptr) static const rb_data_type_t ibf_dump_type = { "ibf_dump", {ibf_dump_mark, ibf_dump_free, ibf_dump_memsize,}, - 0, 0, RUBY_TYPED_FREE_IMMEDIATELY + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_EMBEDDABLE }; static void @@ -13108,7 +14663,6 @@ rb_iseq_ibf_dump(const rb_iseq_t *iseq, VALUE opt) ibf_dump_setup(dump, dump_obj); ibf_dump_write(dump, &header, sizeof(header)); - ibf_dump_write(dump, RUBY_PLATFORM, strlen(RUBY_PLATFORM) + 1); ibf_dump_iseq(dump, iseq); header.magic[0] = 'Y'; /* YARB */ @@ -13117,6 +14671,8 @@ rb_iseq_ibf_dump(const rb_iseq_t *iseq, VALUE opt) header.magic[3] = 'B'; header.major_version = IBF_MAJOR_VERSION; header.minor_version = IBF_MINOR_VERSION; + header.endian = IBF_ENDIAN_MARK; + header.wordsize = (uint8_t)SIZEOF_VALUE; ibf_dump_iseq_list(dump, &header); ibf_dump_object_list(dump, &header.global_object_list_offset, &header.global_object_list_size); header.size = ibf_dump_pos(dump); @@ -13134,8 +14690,6 @@ rb_iseq_ibf_dump(const rb_iseq_t *iseq, VALUE opt) ibf_dump_overwrite(dump, &header, sizeof(header), 0); str = dump->global_buffer.str; - ibf_dump_free(dump); - DATA_PTR(dump_obj) = NULL; RB_GC_GUARD(dump_obj); return str; } @@ -13228,35 +14782,39 @@ ibf_load_iseq(const struct ibf_load *load, const rb_iseq_t *index_iseq) static void ibf_load_setup_bytes(struct ibf_load *load, VALUE loader_obj, const char *bytes, size_t size) { + struct ibf_header *header = (struct ibf_header *)bytes; load->loader_obj = loader_obj; load->global_buffer.buff = bytes; - load->header = (struct ibf_header *)load->global_buffer.buff; - load->global_buffer.size = load->header->size; - load->global_buffer.obj_list_offset = load->header->global_object_list_offset; - load->global_buffer.obj_list_size = load->header->global_object_list_size; - RB_OBJ_WRITE(loader_obj, &load->iseq_list, pinned_list_new(load->header->iseq_list_size)); + load->header = header; + load->global_buffer.size = header->size; + load->global_buffer.obj_list_offset = header->global_object_list_offset; + load->global_buffer.obj_list_size = header->global_object_list_size; + RB_OBJ_WRITE(loader_obj, &load->iseq_list, pinned_list_new(header->iseq_list_size)); RB_OBJ_WRITE(loader_obj, &load->global_buffer.obj_list, pinned_list_new(load->global_buffer.obj_list_size)); load->iseq = NULL; load->current_buffer = &load->global_buffer; - if (size < load->header->size) { + if (size < header->size) { rb_raise(rb_eRuntimeError, "broken binary format"); } - if (strncmp(load->header->magic, "YARB", 4) != 0) { + if (strncmp(header->magic, "YARB", 4) != 0) { rb_raise(rb_eRuntimeError, "unknown binary format"); } - if (load->header->major_version != IBF_MAJOR_VERSION || - load->header->minor_version != IBF_MINOR_VERSION) { + if (header->major_version != IBF_MAJOR_VERSION || + header->minor_version != IBF_MINOR_VERSION) { rb_raise(rb_eRuntimeError, "unmatched version file (%u.%u for %u.%u)", - load->header->major_version, load->header->minor_version, IBF_MAJOR_VERSION, IBF_MINOR_VERSION); + header->major_version, header->minor_version, IBF_MAJOR_VERSION, IBF_MINOR_VERSION); } - if (strcmp(load->global_buffer.buff + sizeof(struct ibf_header), RUBY_PLATFORM) != 0) { - rb_raise(rb_eRuntimeError, "unmatched platform"); + if (header->endian != IBF_ENDIAN_MARK) { + rb_raise(rb_eRuntimeError, "unmatched endian: %c", header->endian); } - if (load->header->iseq_list_offset % RUBY_ALIGNOF(ibf_offset_t)) { + if (header->wordsize != SIZEOF_VALUE) { + rb_raise(rb_eRuntimeError, "unmatched word size: %d", header->wordsize); + } + if (header->iseq_list_offset % RUBY_ALIGNOF(ibf_offset_t)) { rb_raise(rb_eArgError, "unaligned iseq list offset: %u", - load->header->iseq_list_offset); + header->iseq_list_offset); } if (load->global_buffer.obj_list_offset % RUBY_ALIGNOF(ibf_offset_t)) { rb_raise(rb_eArgError, "unaligned object list offset: %u", @@ -13267,6 +14825,8 @@ ibf_load_setup_bytes(struct ibf_load *load, VALUE loader_obj, const char *bytes, static void ibf_load_setup(struct ibf_load *load, VALUE loader_obj, VALUE str) { + StringValue(str); + if (RSTRING_LENINT(str) < (int)sizeof(struct ibf_header)) { rb_raise(rb_eRuntimeError, "broken binary format"); } @@ -13275,7 +14835,7 @@ ibf_load_setup(struct ibf_load *load, VALUE loader_obj, VALUE str) str = rb_str_new(RSTRING_PTR(str), RSTRING_LEN(str)); } - ibf_load_setup_bytes(load, loader_obj, StringValuePtr(str), RSTRING_LEN(str)); + ibf_load_setup_bytes(load, loader_obj, RSTRING_PTR(str), RSTRING_LEN(str)); RB_OBJ_WRITE(loader_obj, &load->str, str); } @@ -13348,4 +14908,4 @@ rb_iseq_ibf_load_extra_data(VALUE str) return extra_str; } -#include "yarp/yarp_compiler.c" +#include "prism_compile.c" diff --git a/complex.c b/complex.c index c9272778bbee65..d6daee307cc170 100644 --- a/complex.c +++ b/complex.c @@ -24,6 +24,7 @@ #include "internal/numeric.h" #include "internal/object.h" #include "internal/rational.h" +#include "internal/string.h" #include "ruby_assert.h" #define ZERO INT2FIX(0) @@ -396,7 +397,7 @@ nucomp_s_new_internal(VALUE klass, VALUE real, VALUE imag) RCOMPLEX_SET_REAL(obj, real); RCOMPLEX_SET_IMAG(obj, imag); - OBJ_FREEZE_RAW((VALUE)obj); + OBJ_FREEZE((VALUE)obj); return (VALUE)obj; } @@ -410,15 +411,15 @@ nucomp_s_alloc(VALUE klass) inline static VALUE f_complex_new_bang1(VALUE klass, VALUE x) { - assert(!RB_TYPE_P(x, T_COMPLEX)); + RUBY_ASSERT(!RB_TYPE_P(x, T_COMPLEX)); return nucomp_s_new_internal(klass, x, ZERO); } inline static VALUE f_complex_new_bang2(VALUE klass, VALUE x, VALUE y) { - assert(!RB_TYPE_P(x, T_COMPLEX)); - assert(!RB_TYPE_P(y, T_COMPLEX)); + RUBY_ASSERT(!RB_TYPE_P(x, T_COMPLEX)); + RUBY_ASSERT(!RB_TYPE_P(y, T_COMPLEX)); return nucomp_s_new_internal(klass, x, y); } @@ -431,7 +432,7 @@ nucomp_real_check(VALUE num) !RB_TYPE_P(num, T_RATIONAL)) { if (RB_TYPE_P(num, T_COMPLEX) && nucomp_real_p(num)) { VALUE real = RCOMPLEX(num)->real; - assert(!RB_TYPE_P(real, T_COMPLEX)); + RUBY_ASSERT(!RB_TYPE_P(real, T_COMPLEX)); return real; } if (!k_numeric_p(num) || !f_real_p(num)) @@ -474,12 +475,19 @@ nucomp_s_canonicalize_internal(VALUE klass, VALUE real, VALUE imag) /* * call-seq: - * Complex.rect(real[, imag]) -> complex - * Complex.rectangular(real[, imag]) -> complex + * Complex.rect(real, imag = 0) -> complex * - * Returns a complex object which denotes the given rectangular form. + * Returns a new \Complex object formed from the arguments, + * each of which must be an instance of Numeric, + * or an instance of one of its subclasses: + * \Complex, Float, Integer, Rational; + * see {Rectangular Coordinates}[rdoc-ref:Complex@Rectangular+Coordinates]: * - * Complex.rectangular(1, 2) #=> (1+2i) + * Complex.rect(3) # => (3+0i) + * Complex.rect(3, Math::PI) # => (3+3.141592653589793i) + * Complex.rect(-3, -Math::PI) # => (-3-3.141592653589793i) + * + * \Complex.rectangular is an alias for \Complex.rect. */ static VALUE nucomp_s_new(int argc, VALUE *argv, VALUE klass) @@ -516,39 +524,54 @@ static VALUE nucomp_s_convert(int argc, VALUE *argv, VALUE klass); /* * call-seq: - * Complex(x[, y], exception: true) -> numeric or nil - * - * Returns x+i*y; - * - * Complex(1, 2) #=> (1+2i) - * Complex('1+2i') #=> (1+2i) - * Complex(nil) #=> TypeError - * Complex(1, nil) #=> TypeError - * - * Complex(1, nil, exception: false) #=> nil - * Complex('1+2', exception: false) #=> nil - * - * Syntax of string form: - * - * string form = extra spaces , complex , extra spaces ; - * complex = real part | [ sign ] , imaginary part - * | real part , sign , imaginary part - * | rational , "@" , rational ; - * real part = rational ; - * imaginary part = imaginary unit | unsigned rational , imaginary unit ; - * rational = [ sign ] , unsigned rational ; - * unsigned rational = numerator | numerator , "/" , denominator ; - * numerator = integer part | fractional part | integer part , fractional part ; - * denominator = digits ; - * integer part = digits ; - * fractional part = "." , digits , [ ( "e" | "E" ) , [ sign ] , digits ] ; - * imaginary unit = "i" | "I" | "j" | "J" ; - * sign = "-" | "+" ; - * digits = digit , { digit | "_" , digit }; - * digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ; - * extra spaces = ? \s* ? ; - * - * See String#to_c. + * Complex(real, imag = 0, exception: true) -> complex or nil + * Complex(s, exception: true) -> complex or nil + * + * Returns a new \Complex object if the arguments are valid; + * otherwise raises an exception if +exception+ is +true+; + * otherwise returns +nil+. + * + * With Numeric arguments +real+ and +imag+, + * returns Complex.rect(real, imag) if the arguments are valid. + * + * With string argument +s+, returns a new \Complex object if the argument is valid; + * the string may have: + * + * - One or two numeric substrings, + * each of which specifies a Complex, Float, Integer, Numeric, or Rational value, + * specifying {rectangular coordinates}[rdoc-ref:Complex@Rectangular+Coordinates]: + * + * - Sign-separated real and imaginary numeric substrings + * (with trailing character 'i'): + * + * Complex('1+2i') # => (1+2i) + * Complex('+1+2i') # => (1+2i) + * Complex('+1-2i') # => (1-2i) + * Complex('-1+2i') # => (-1+2i) + * Complex('-1-2i') # => (-1-2i) + * + * - Real-only numeric string (without trailing character 'i'): + * + * Complex('1') # => (1+0i) + * Complex('+1') # => (1+0i) + * Complex('-1') # => (-1+0i) + * + * - Imaginary-only numeric string (with trailing character 'i'): + * + * Complex('1i') # => (0+1i) + * Complex('+1i') # => (0+1i) + * Complex('-1i') # => (0-1i) + * + * - At-sign separated real and imaginary rational substrings, + * each of which specifies a Rational value, + * specifying {polar coordinates}[rdoc-ref:Complex@Polar+Coordinates]: + * + * Complex('1/2@3/4') # => (0.36584443443691045+0.34081938001166706i) + * Complex('+1/2@+3/4') # => (0.36584443443691045+0.34081938001166706i) + * Complex('+1/2@-3/4') # => (0.36584443443691045-0.34081938001166706i) + * Complex('-1/2@+3/4') # => (-0.36584443443691045-0.34081938001166706i) + * Complex('-1/2@-3/4') # => (-0.36584443443691045+0.34081938001166706i) + * */ static VALUE nucomp_f_complex(int argc, VALUE *argv, VALUE klass) @@ -698,14 +721,19 @@ rb_dbl_complex_new_polar_pi(double abs, double ang) /* * call-seq: - * Complex.polar(abs[, arg]) -> complex + * Complex.polar(abs, arg = 0) -> complex + * + * Returns a new \Complex object formed from the arguments, + * each of which must be an instance of Numeric, + * or an instance of one of its subclasses: + * \Complex, Float, Integer, Rational. + * Argument +arg+ is given in radians; + * see {Polar Coordinates}[rdoc-ref:Complex@Polar+Coordinates]: * - * Returns a complex object which denotes the given polar form. + * Complex.polar(3) # => (3+0i) + * Complex.polar(3, 2.0) # => (-1.2484405096414273+2.727892280477045i) + * Complex.polar(-3, -2.0) # => (1.2484405096414273+2.727892280477045i) * - * Complex.polar(3, 0) #=> (3.0+0.0i) - * Complex.polar(3, Math::PI/2) #=> (1.836909530733566e-16+3.0i) - * Complex.polar(3, Math::PI) #=> (-3.0+3.673819061467132e-16i) - * Complex.polar(3, -Math::PI/2) #=> (1.836909530733566e-16-3.0i) */ static VALUE nucomp_s_polar(int argc, VALUE *argv, VALUE klass) @@ -725,12 +753,19 @@ nucomp_s_polar(int argc, VALUE *argv, VALUE klass) /* * call-seq: - * cmp.real -> real + * real -> numeric * - * Returns the real part. + * Returns the real value for +self+: + * + * Complex.rect(7).real # => 7 + * Complex.rect(9, -4).real # => 9 + * + * If +self+ was created with + * {polar coordinates}[rdoc-ref:Complex@Polar+Coordinates], the returned value + * is computed, and may be inexact: + * + * Complex.polar(1, Math::PI/4).real # => 0.7071067811865476 # Square root of 2. * - * Complex(7).real #=> 7 - * Complex(9, -4).real #=> 9 */ VALUE rb_complex_real(VALUE self) @@ -741,13 +776,19 @@ rb_complex_real(VALUE self) /* * call-seq: - * cmp.imag -> real - * cmp.imaginary -> real + * imag -> numeric + * + * Returns the imaginary value for +self+: + * + * Complex.rect(7).imag # => 0 + * Complex.rect(9, -4).imag # => -4 * - * Returns the imaginary part. + * If +self+ was created with + * {polar coordinates}[rdoc-ref:Complex@Polar+Coordinates], the returned value + * is computed, and may be inexact: + * + * Complex.polar(1, Math::PI/4).imag # => 0.7071067811865476 # Square root of 2. * - * Complex(7).imaginary #=> 0 - * Complex(9, -4).imaginary #=> -4 */ VALUE rb_complex_imag(VALUE self) @@ -758,11 +799,13 @@ rb_complex_imag(VALUE self) /* * call-seq: - * -cmp -> complex + * -complex -> new_complex + * + * Returns the negation of +self+, which is the negation of each of its parts: * - * Returns negation of the value. + * -Complex.rect(1, 2) # => (-1-2i) + * -Complex.rect(-1, -2) # => (1+2i) * - * -Complex(1, 2) #=> (-1-2i) */ VALUE rb_complex_uminus(VALUE self) @@ -774,15 +817,16 @@ rb_complex_uminus(VALUE self) /* * call-seq: - * cmp + numeric -> complex + * complex + numeric -> new_complex + * + * Returns the sum of +self+ and +numeric+: * - * Performs addition. + * Complex.rect(2, 3) + Complex.rect(2, 3) # => (4+6i) + * Complex.rect(900) + Complex.rect(1) # => (901+0i) + * Complex.rect(-2, 9) + Complex.rect(-9, 2) # => (-11+11i) + * Complex.rect(9, 8) + 4 # => (13+8i) + * Complex.rect(20, 9) + 9.8 # => (29.8+9i) * - * Complex(2, 3) + Complex(2, 3) #=> (4+6i) - * Complex(900) + Complex(1) #=> (901+0i) - * Complex(-2, 9) + Complex(-9, 2) #=> (-11+11i) - * Complex(9, 8) + 4 #=> (13+8i) - * Complex(20, 9) + 9.8 #=> (29.8+9i) */ VALUE rb_complex_plus(VALUE self, VALUE other) @@ -808,15 +852,16 @@ rb_complex_plus(VALUE self, VALUE other) /* * call-seq: - * cmp - numeric -> complex + * complex - numeric -> new_complex * - * Performs subtraction. + * Returns the difference of +self+ and +numeric+: + * + * Complex.rect(2, 3) - Complex.rect(2, 3) # => (0+0i) + * Complex.rect(900) - Complex.rect(1) # => (899+0i) + * Complex.rect(-2, 9) - Complex.rect(-9, 2) # => (7+7i) + * Complex.rect(9, 8) - 4 # => (5+8i) + * Complex.rect(20, 9) - 9.8 # => (10.2+9i) * - * Complex(2, 3) - Complex(2, 3) #=> (0+0i) - * Complex(900) - Complex(1) #=> (899+0i) - * Complex(-2, 9) - Complex(-9, 2) #=> (7+7i) - * Complex(9, 8) - 4 #=> (5+8i) - * Complex(20, 9) - 9.8 #=> (10.2+9i) */ VALUE rb_complex_minus(VALUE self, VALUE other) @@ -868,15 +913,16 @@ comp_mul(VALUE areal, VALUE aimag, VALUE breal, VALUE bimag, VALUE *real, VALUE /* * call-seq: - * cmp * numeric -> complex + * complex * numeric -> new_complex + * + * Returns the product of +self+ and +numeric+: * - * Performs multiplication. + * Complex.rect(2, 3) * Complex.rect(2, 3) # => (-5+12i) + * Complex.rect(900) * Complex.rect(1) # => (900+0i) + * Complex.rect(-2, 9) * Complex.rect(-9, 2) # => (0-85i) + * Complex.rect(9, 8) * 4 # => (36+32i) + * Complex.rect(20, 9) * 9.8 # => (196.0+88.2i) * - * Complex(2, 3) * Complex(2, 3) #=> (-5+12i) - * Complex(900) * Complex(1) #=> (900+0i) - * Complex(-2, 9) * Complex(-9, 2) #=> (0-85i) - * Complex(9, 8) * 4 #=> (36+32i) - * Complex(20, 9) * 9.8 #=> (196.0+88.2i) */ VALUE rb_complex_mul(VALUE self, VALUE other) @@ -943,16 +989,16 @@ f_divide(VALUE self, VALUE other, /* * call-seq: - * cmp / numeric -> complex - * cmp.quo(numeric) -> complex + * complex / numeric -> new_complex + * + * Returns the quotient of +self+ and +numeric+: * - * Performs division. + * Complex.rect(2, 3) / Complex.rect(2, 3) # => (1+0i) + * Complex.rect(900) / Complex.rect(1) # => (900+0i) + * Complex.rect(-2, 9) / Complex.rect(-9, 2) # => ((36/85)-(77/85)*i) + * Complex.rect(9, 8) / 4 # => ((9/4)+2i) + * Complex.rect(20, 9) / 9.8 # => (2.0408163265306123+0.9183673469387754i) * - * Complex(2, 3) / Complex(2, 3) #=> ((1/1)+(0/1)*i) - * Complex(900) / Complex(1) #=> ((900/1)+(0/1)*i) - * Complex(-2, 9) / Complex(-9, 2) #=> ((36/85)-(77/85)*i) - * Complex(9, 8) / 4 #=> ((9/4)+(2/1)*i) - * Complex(20, 9) / 9.8 #=> (2.0408163265306123+0.9183673469387754i) */ VALUE rb_complex_div(VALUE self, VALUE other) @@ -964,11 +1010,12 @@ rb_complex_div(VALUE self, VALUE other) /* * call-seq: - * cmp.fdiv(numeric) -> complex + * fdiv(numeric) -> new_complex * - * Performs division as each part is a float, never returns a float. + * Returns Complex.rect(self.real/numeric, self.imag/numeric): + * + * Complex.rect(11, 22).fdiv(3) # => (3.6666666666666665+7.333333333333333i) * - * Complex(11, 22).fdiv(3) #=> (3.6666666666666665+7.333333333333333i) */ static VALUE nucomp_fdiv(VALUE self, VALUE other) @@ -982,14 +1029,96 @@ f_reciprocal(VALUE x) return f_quo(ONE, x); } +static VALUE +zero_for(VALUE x) +{ + if (RB_FLOAT_TYPE_P(x)) + return DBL2NUM(0); + if (RB_TYPE_P(x, T_RATIONAL)) + return rb_rational_new(INT2FIX(0), INT2FIX(1)); + + return INT2FIX(0); +} + +static VALUE +complex_pow_for_special_angle(VALUE self, VALUE other) +{ + if (!rb_integer_type_p(other)) { + return Qundef; + } + + get_dat1(self); + VALUE x = Qundef; + int dir; + if (f_zero_p(dat->imag)) { + x = dat->real; + dir = 0; + } + else if (f_zero_p(dat->real)) { + x = dat->imag; + dir = 2; + } + else if (f_eqeq_p(dat->real, dat->imag)) { + x = dat->real; + dir = 1; + } + else if (f_eqeq_p(dat->real, f_negate(dat->imag))) { + x = dat->imag; + dir = 3; + } + else { + dir = 0; + } + + if (UNDEF_P(x)) return x; + + if (f_negative_p(x)) { + x = f_negate(x); + dir += 4; + } + + VALUE zx; + if (dir % 2 == 0) { + zx = rb_num_pow(x, other); + } + else { + zx = rb_num_pow( + rb_funcall(rb_int_mul(TWO, x), '*', 1, x), + rb_int_div(other, TWO) + ); + if (rb_int_odd_p(other)) { + zx = rb_funcall(zx, '*', 1, x); + } + } + static const int dirs[][2] = { + {1, 0}, {1, 1}, {0, 1}, {-1, 1}, {-1, 0}, {-1, -1}, {0, -1}, {1, -1} + }; + int z_dir = FIX2INT(rb_int_modulo(rb_int_mul(INT2FIX(dir), other), INT2FIX(8))); + + VALUE zr = Qfalse, zi = Qfalse; + switch (dirs[z_dir][0]) { + case 0: zr = zero_for(zx); break; + case 1: zr = zx; break; + case -1: zr = f_negate(zx); break; + } + switch (dirs[z_dir][1]) { + case 0: zi = zero_for(zx); break; + case 1: zi = zx; break; + case -1: zi = f_negate(zx); break; + } + return nucomp_s_new_internal(CLASS_OF(self), zr, zi); +} + + /* * call-seq: - * cmp ** numeric -> complex + * complex ** numeric -> new_complex * - * Performs exponentiation. + * Returns +self+ raised to power +numeric+: + * + * Complex.rect(0, 1) ** 2 # => (-1+0i) + * Complex.rect(-8) ** Rational(1, 3) # => (1.0000000000000002+1.7320508075688772i) * - * Complex('i') ** 2 #=> (-1+0i) - * Complex(-8) ** Rational(1, 3) #=> (1.0000000000000002+1.7320508075688772i) */ VALUE rb_complex_pow(VALUE self, VALUE other) @@ -1007,6 +1136,14 @@ rb_complex_pow(VALUE self, VALUE other) other = dat->real; /* c14n */ } + if (other == ONE) { + get_dat1(self); + return nucomp_s_new_internal(CLASS_OF(self), dat->real, dat->imag); + } + + VALUE result = complex_pow_for_special_angle(self, other); + if (!UNDEF_P(result)) return result; + if (RB_TYPE_P(other, T_COMPLEX)) { VALUE r, theta, nr, ntheta; @@ -1079,15 +1216,13 @@ rb_complex_pow(VALUE self, VALUE other) /* * call-seq: - * cmp == object -> true or false + * complex == object -> true or false * - * Returns true if cmp equals object numerically. + * Returns +true+ if self.real == object.real + * and self.imag == object.imag: + * + * Complex.rect(2, 3) == Complex.rect(2.0, 3.0) # => true * - * Complex(2, 3) == Complex(2, 3) #=> true - * Complex(5) == 5 #=> true - * Complex(0) == 0.0 #=> true - * Complex('1/3') == 0.33 #=> false - * Complex('1/2') == '1/2' #=> false */ static VALUE nucomp_eqeq_p(VALUE self, VALUE other) @@ -1115,17 +1250,26 @@ nucomp_real_p(VALUE self) /* * call-seq: - * cmp <=> object -> 0, 1, -1, or nil + * complex <=> object -> -1, 0, 1, or nil + * + * Returns: + * + * - self.real <=> object.real if both of the following are true: + * + * - self.imag == 0. + * - object.imag == 0. # Always true if object is numeric but not complex. + * + * - +nil+ otherwise. * - * If +cmp+'s imaginary part is zero, and +object+ is also a - * real number (or a Complex number where the imaginary part is zero), - * compare the real part of +cmp+ to object. Otherwise, return nil. + * Examples: + * + * Complex.rect(2) <=> 3 # => -1 + * Complex.rect(2) <=> 2 # => 0 + * Complex.rect(2) <=> 1 # => 1 + * Complex.rect(2, 1) <=> 1 # => nil # self.imag not zero. + * Complex.rect(1) <=> Complex.rect(1, 1) # => nil # object.imag not zero. + * Complex.rect(1) <=> 'Foo' # => nil # object.imag not defined. * - * Complex(2, 3) <=> Complex(2, 3) #=> nil - * Complex(2, 3) <=> 1 #=> nil - * Complex(2) <=> 1 #=> 1 - * Complex(2) <=> 2 #=> 0 - * Complex(2) <=> 3 #=> -1 */ static VALUE nucomp_cmp(VALUE self, VALUE other) @@ -1170,13 +1314,19 @@ nucomp_coerce(VALUE self, VALUE other) /* * call-seq: - * cmp.abs -> real - * cmp.magnitude -> real + * abs -> float + * + * Returns the absolute value (magnitude) for +self+; + * see {polar coordinates}[rdoc-ref:Complex@Polar+Coordinates]: + * + * Complex.polar(-1, 0).abs # => 1.0 * - * Returns the absolute part of its polar form. + * If +self+ was created with + * {rectangular coordinates}[rdoc-ref:Complex@Rectangular+Coordinates], the returned value + * is computed, and may be inexact: + * + * Complex.rectangular(1, 1).abs # => 1.4142135623730951 # The square root of 2. * - * Complex(-1).abs #=> 1 - * Complex(3.0, -4.0).abs #=> 5.0 */ VALUE rb_complex_abs(VALUE self) @@ -1200,12 +1350,19 @@ rb_complex_abs(VALUE self) /* * call-seq: - * cmp.abs2 -> real + * abs2 -> float + * + * Returns square of the absolute value (magnitude) for +self+; + * see {polar coordinates}[rdoc-ref:Complex@Polar+Coordinates]: * - * Returns square of the absolute value. + * Complex.polar(2, 2).abs2 # => 4.0 + * + * If +self+ was created with + * {rectangular coordinates}[rdoc-ref:Complex@Rectangular+Coordinates], the returned value + * is computed, and may be inexact: + * + * Complex.rectangular(1.0/3, 1.0/3).abs2 # => 0.2222222222222222 * - * Complex(-1).abs2 #=> 1 - * Complex(3.0, -4.0).abs2 #=> 25.0 */ static VALUE nucomp_abs2(VALUE self) @@ -1217,13 +1374,19 @@ nucomp_abs2(VALUE self) /* * call-seq: - * cmp.arg -> float - * cmp.angle -> float - * cmp.phase -> float + * arg -> float + * + * Returns the argument (angle) for +self+ in radians; + * see {polar coordinates}[rdoc-ref:Complex@Polar+Coordinates]: + * + * Complex.polar(3, Math::PI/2).arg # => 1.57079632679489660 + * + * If +self+ was created with + * {rectangular coordinates}[rdoc-ref:Complex@Rectangular+Coordinates], the returned value + * is computed, and may be inexact: * - * Returns the angle part of its polar form. + * Complex.polar(1, 1.0/3).arg # => 0.33333333333333326 * - * Complex.polar(3, Math::PI/2).arg #=> 1.5707963267948966 */ VALUE rb_complex_arg(VALUE self) @@ -1234,12 +1397,22 @@ rb_complex_arg(VALUE self) /* * call-seq: - * cmp.rect -> array - * cmp.rectangular -> array + * rect -> array * - * Returns an array; [cmp.real, cmp.imag]. + * Returns the array [self.real, self.imag]: * - * Complex(1, 2).rectangular #=> [1, 2] + * Complex.rect(1, 2).rect # => [1, 2] + * + * See {Rectangular Coordinates}[rdoc-ref:Complex@Rectangular+Coordinates]. + * + * If +self+ was created with + * {polar coordinates}[rdoc-ref:Complex@Polar+Coordinates], the returned value + * is computed, and may be inexact: + * + * Complex.polar(1.0, 1.0).rect # => [0.5403023058681398, 0.8414709848078965] + * + * + * Complex#rectangular is an alias for Complex#rect. */ static VALUE nucomp_rect(VALUE self) @@ -1250,11 +1423,20 @@ nucomp_rect(VALUE self) /* * call-seq: - * cmp.polar -> array + * polar -> array + * + * Returns the array [self.abs, self.arg]: * - * Returns an array; [cmp.abs, cmp.arg]. + * Complex.polar(1, 2).polar # => [1.0, 2.0] + * + * See {Polar Coordinates}[rdoc-ref:Complex@Polar+Coordinates]. + * + * If +self+ was created with + * {rectangular coordinates}[rdoc-ref:Complex@Rectangular+Coordinates], the returned value + * is computed, and may be inexact: + * + * Complex.rect(1, 1).polar # => [1.4142135623730951, 0.7853981633974483] * - * Complex(1, 2).polar #=> [2.23606797749979, 1.1071487177940904] */ static VALUE nucomp_polar(VALUE self) @@ -1264,12 +1446,12 @@ nucomp_polar(VALUE self) /* * call-seq: - * cmp.conj -> complex - * cmp.conjugate -> complex + * conj -> complex * - * Returns the complex conjugate. + * Returns the conjugate of +self+, Complex.rect(self.imag, self.real): + * + * Complex.rect(1, 2).conj # => (1-2i) * - * Complex(1, 2).conjugate #=> (1-2i) */ VALUE rb_complex_conjugate(VALUE self) @@ -1280,10 +1462,9 @@ rb_complex_conjugate(VALUE self) /* * call-seq: - * Complex(1).real? -> false - * Complex(1, 2).real? -> false + * real? -> false * - * Returns false, even if the complex number has no imaginary part. + * Returns +false+; for compatibility with Numeric#real?. */ static VALUE nucomp_real_p_m(VALUE self) @@ -1293,11 +1474,17 @@ nucomp_real_p_m(VALUE self) /* * call-seq: - * cmp.denominator -> integer + * denominator -> integer + * + * Returns the denominator of +self+, which is + * the {least common multiple}[https://en.wikipedia.org/wiki/Least_common_multiple] + * of self.real.denominator and self.imag.denominator: * - * Returns the denominator (lcm of both denominator - real and imag). + * Complex.rect(Rational(1, 2), Rational(2, 3)).denominator # => 6 * - * See numerator. + * Note that n.denominator of a non-rational numeric is +1+. + * + * Related: Complex#numerator. */ static VALUE nucomp_denominator(VALUE self) @@ -1308,21 +1495,23 @@ nucomp_denominator(VALUE self) /* * call-seq: - * cmp.numerator -> numeric + * numerator -> new_complex + * + * Returns the \Complex object created from the numerators + * of the real and imaginary parts of +self+, + * after converting each part to the + * {lowest common denominator}[https://en.wikipedia.org/wiki/Lowest_common_denominator] + * of the two: * - * Returns the numerator. + * c = Complex.rect(Rational(2, 3), Rational(3, 4)) # => ((2/3)+(3/4)*i) + * c.numerator # => (8+9i) * - * 1 2 3+4i <- numerator - * - + -i -> ---- - * 2 3 6 <- denominator + * In this example, the lowest common denominator of the two parts is 12; + * the two converted parts may be thought of as \Rational(8, 12) and \Rational(9, 12), + * whose numerators, respectively, are 8 and 9; + * so the returned value of c.numerator is Complex.rect(8, 9). * - * c = Complex('1/2+2/3i') #=> ((1/2)+(2/3)*i) - * n = c.numerator #=> (3+4i) - * d = c.denominator #=> 6 - * n / d #=> ((1/2)+(2/3)*i) - * Complex(Rational(n.real, d), Rational(n.imag, d)) - * #=> ((1/2)+(2/3)*i) - * See denominator. + * Related: Complex#denominator. */ static VALUE nucomp_numerator(VALUE self) @@ -1355,6 +1544,18 @@ rb_complex_hash(VALUE self) return v; } +/* + * :call-seq: + * hash -> integer + * + * Returns the integer hash value for +self+. + * + * Two \Complex objects created from the same values will have the same hash value + * (and will compare using #eql?): + * + * Complex.rect(1, 2).hash == Complex.rect(1, 2).hash # => true + * + */ static VALUE nucomp_hash(VALUE self) { @@ -1393,16 +1594,15 @@ f_tpositive_p(VALUE x) } static VALUE -f_format(VALUE self, VALUE (*func)(VALUE)) +f_format(VALUE self, VALUE s, VALUE (*func)(VALUE)) { - VALUE s; int impos; get_dat1(self); impos = f_tpositive_p(dat->imag); - s = (*func)(dat->real); + rb_str_concat(s, (*func)(dat->real)); rb_str_cat2(s, !impos ? "-" : "+"); rb_str_concat(s, (*func)(f_abs(dat->imag))); @@ -1415,33 +1615,35 @@ f_format(VALUE self, VALUE (*func)(VALUE)) /* * call-seq: - * cmp.to_s -> string + * to_s -> string + * + * Returns a string representation of +self+: * - * Returns the value as a string. + * Complex.rect(2).to_s # => "2+0i" + * Complex.rect(-8, 6).to_s # => "-8+6i" + * Complex.rect(0, Rational(1, 2)).to_s # => "0+1/2i" + * Complex.rect(0, Float::INFINITY).to_s # => "0+Infinity*i" + * Complex.rect(Float::NAN, Float::NAN).to_s # => "NaN+NaN*i" * - * Complex(2).to_s #=> "2+0i" - * Complex('-8/6').to_s #=> "-4/3+0i" - * Complex('1/2i').to_s #=> "0+1/2i" - * Complex(0, Float::INFINITY).to_s #=> "0+Infinity*i" - * Complex(Float::NAN, Float::NAN).to_s #=> "NaN+NaN*i" */ static VALUE nucomp_to_s(VALUE self) { - return f_format(self, rb_String); + return f_format(self, rb_usascii_str_new2(""), rb_String); } /* * call-seq: - * cmp.inspect -> string + * inspect -> string * - * Returns the value as a string for inspection. + * Returns a string representation of +self+: + * + * Complex.rect(2).inspect # => "(2+0i)" + * Complex.rect(-8, 6).inspect # => "(-8+6i)" + * Complex.rect(0, Rational(1, 2)).inspect # => "(0+(1/2)*i)" + * Complex.rect(0, Float::INFINITY).inspect # => "(0+Infinity*i)" + * Complex.rect(Float::NAN, Float::NAN).inspect # => "(NaN+NaN*i)" * - * Complex(2).inspect #=> "(2+0i)" - * Complex('-8/6').inspect #=> "((-4/3)+0i)" - * Complex('1/2i').inspect #=> "(0+(1/2)*i)" - * Complex(0, Float::INFINITY).inspect #=> "(0+Infinity*i)" - * Complex(Float::NAN, Float::NAN).inspect #=> "(NaN+NaN*i)" */ static VALUE nucomp_inspect(VALUE self) @@ -1449,7 +1651,7 @@ nucomp_inspect(VALUE self) VALUE s; s = rb_usascii_str_new2("("); - rb_str_concat(s, f_format(self, rb_inspect)); + f_format(self, s, rb_inspect); rb_str_cat2(s, ")"); return s; @@ -1459,10 +1661,15 @@ nucomp_inspect(VALUE self) /* * call-seq: - * cmp.finite? -> true or false + * finite? -> true or false + * + * Returns +true+ if both self.real.finite? and self.imag.finite? + * are true, +false+ otherwise: + * + * Complex.rect(1, 1).finite? # => true + * Complex.rect(Float::INFINITY, 0).finite? # => false * - * Returns +true+ if +cmp+'s real and imaginary parts are both finite numbers, - * otherwise returns +false+. + * Related: Numeric#finite?, Float#finite?. */ static VALUE rb_complex_finite_p(VALUE self) @@ -1474,15 +1681,15 @@ rb_complex_finite_p(VALUE self) /* * call-seq: - * cmp.infinite? -> nil or 1 + * infinite? -> 1 or nil * - * Returns +1+ if +cmp+'s real or imaginary part is an infinite number, - * otherwise returns +nil+. + * Returns +1+ if either self.real.infinite? or self.imag.infinite? + * is true, +nil+ otherwise: * - * For example: + * Complex.rect(Float::INFINITY, 0).infinite? # => 1 + * Complex.rect(1, 1).infinite? # => nil * - * (1+1i).infinite? #=> nil - * (Float::INFINITY + 1i).infinite? #=> 1 + * Related: Numeric#infinite?, Float#infinite?. */ static VALUE rb_complex_infinite_p(VALUE self) @@ -1510,7 +1717,7 @@ nucomp_loader(VALUE self, VALUE a) RCOMPLEX_SET_REAL(dat, rb_ivar_get(a, id_i_real)); RCOMPLEX_SET_IMAG(dat, rb_ivar_get(a, id_i_imag)); - OBJ_FREEZE_RAW(self); + OBJ_FREEZE(self); return self; } @@ -1580,14 +1787,15 @@ rb_dbl_complex_new(double real, double imag) /* * call-seq: - * cmp.to_i -> integer + * to_i -> integer + * + * Returns the value of self.real as an Integer, if possible: * - * Returns the value as an integer if possible (the imaginary part - * should be exactly zero). + * Complex.rect(1, 0).to_i # => 1 + * Complex.rect(1, Rational(0, 1)).to_i # => 1 * - * Complex(1, 0).to_i #=> 1 - * Complex(1, 0.0).to_i # RangeError - * Complex(1, 2).to_i # RangeError + * Raises RangeError if self.imag is not exactly zero + * (either Integer(0) or Rational(0, _n_)). */ static VALUE nucomp_to_i(VALUE self) @@ -1603,14 +1811,15 @@ nucomp_to_i(VALUE self) /* * call-seq: - * cmp.to_f -> float + * to_f -> float * - * Returns the value as a float if possible (the imaginary part should - * be exactly zero). + * Returns the value of self.real as a Float, if possible: * - * Complex(1, 0).to_f #=> 1.0 - * Complex(1, 0.0).to_f # RangeError - * Complex(1, 2).to_f # RangeError + * Complex.rect(1, 0).to_f # => 1.0 + * Complex.rect(1, Rational(0, 1)).to_f # => 1.0 + * + * Raises RangeError if self.imag is not exactly zero + * (either Integer(0) or Rational(0, _n_)). */ static VALUE nucomp_to_f(VALUE self) @@ -1626,41 +1835,69 @@ nucomp_to_f(VALUE self) /* * call-seq: - * cmp.to_r -> rational + * to_r -> rational + * + * Returns the value of self.real as a Rational, if possible: * - * Returns the value as a rational if possible (the imaginary part - * should be exactly zero). + * Complex.rect(1, 0).to_r # => (1/1) + * Complex.rect(1, Rational(0, 1)).to_r # => (1/1) + * Complex.rect(1, 0.0).to_r # => (1/1) * - * Complex(1, 0).to_r #=> (1/1) - * Complex(1, 0.0).to_r # RangeError - * Complex(1, 2).to_r # RangeError + * Raises RangeError if self.imag is not exactly zero + * (either Integer(0) or Rational(0, _n_)) + * and self.imag.to_r is not exactly zero. * - * See rationalize. + * Related: Complex#rationalize. */ static VALUE nucomp_to_r(VALUE self) { get_dat1(self); - if (!k_exact_zero_p(dat->imag)) { - rb_raise(rb_eRangeError, "can't convert %"PRIsVALUE" into Rational", - self); + if (RB_FLOAT_TYPE_P(dat->imag) && FLOAT_ZERO_P(dat->imag)) { + /* Do nothing here */ + } + else if (!k_exact_zero_p(dat->imag)) { + VALUE imag = rb_check_convert_type_with_id(dat->imag, T_RATIONAL, "Rational", idTo_r); + if (NIL_P(imag) || !k_exact_zero_p(imag)) { + rb_raise(rb_eRangeError, "can't convert %"PRIsVALUE" into Rational", + self); + } } return f_to_r(dat->real); } /* * call-seq: - * cmp.rationalize([eps]) -> rational - * - * Returns the value as a rational if possible (the imaginary part - * should be exactly zero). - * - * Complex(1.0/3, 0).rationalize #=> (1/3) - * Complex(1, 0.0).rationalize # RangeError - * Complex(1, 2).rationalize # RangeError - * - * See to_r. + * rationalize(epsilon = nil) -> rational + * + * Returns a Rational object whose value is exactly or approximately + * equivalent to that of self.real. + * + * With no argument +epsilon+ given, returns a \Rational object + * whose value is exactly equal to that of self.real.rationalize: + * + * Complex.rect(1, 0).rationalize # => (1/1) + * Complex.rect(1, Rational(0, 1)).rationalize # => (1/1) + * Complex.rect(3.14159, 0).rationalize # => (314159/100000) + * + * With argument +epsilon+ given, returns a \Rational object + * whose value is exactly or approximately equal to that of self.real + * to the given precision: + * + * Complex.rect(3.14159, 0).rationalize(0.1) # => (16/5) + * Complex.rect(3.14159, 0).rationalize(0.01) # => (22/7) + * Complex.rect(3.14159, 0).rationalize(0.001) # => (201/64) + * Complex.rect(3.14159, 0).rationalize(0.0001) # => (333/106) + * Complex.rect(3.14159, 0).rationalize(0.00001) # => (355/113) + * Complex.rect(3.14159, 0).rationalize(0.000001) # => (7433/2366) + * Complex.rect(3.14159, 0).rationalize(0.0000001) # => (9208/2931) + * Complex.rect(3.14159, 0).rationalize(0.00000001) # => (47460/15107) + * Complex.rect(3.14159, 0).rationalize(0.000000001) # => (76149/24239) + * Complex.rect(3.14159, 0).rationalize(0.0000000001) # => (314159/100000) + * Complex.rect(3.14159, 0).rationalize(0.0) # => (3537115888337719/1125899906842624) + * + * Related: Complex#to_r. */ static VALUE nucomp_rationalize(int argc, VALUE *argv, VALUE self) @@ -1678,12 +1915,9 @@ nucomp_rationalize(int argc, VALUE *argv, VALUE self) /* * call-seq: - * complex.to_c -> self - * - * Returns self. + * to_c -> self * - * Complex(2).to_c #=> (2+0i) - * Complex(-8, 6).to_c #=> (-8+6i) + * Returns +self+. */ static VALUE nucomp_to_c(VALUE self) @@ -1693,24 +1927,9 @@ nucomp_to_c(VALUE self) /* * call-seq: - * to_c -> (0+0i) - * - * Returns zero as a Complex: - * - * nil.to_c # => (0+0i) - * - */ -static VALUE -nilclass_to_c(VALUE self) -{ - return rb_complex_new1(INT2FIX(0)); -} - -/* - * call-seq: - * num.to_c -> complex + * to_c -> complex * - * Returns the value as a complex. + * Returns +self+ as a Complex object. */ static VALUE numeric_to_c(VALUE self) @@ -1990,23 +2209,14 @@ string_to_c_strict(VALUE self, int raise) rb_must_asciicompat(self); - s = RSTRING_PTR(self); - - if (!s || memchr(s, '\0', RSTRING_LEN(self))) { - if (!raise) return Qnil; - rb_raise(rb_eArgError, "string contains null byte"); + if (raise) { + s = StringValueCStr(self); } - - if (s && s[RSTRING_LEN(self)]) { - rb_str_modify(self); - s = RSTRING_PTR(self); - s[RSTRING_LEN(self)] = '\0'; + else if (!(s = rb_str_to_cstr(self))) { + return Qnil; } - if (!s) - s = (char *)""; - - if (!parse_comp(s, 1, &num)) { + if (!parse_comp(s, TRUE, &num)) { if (!raise) return Qnil; rb_raise(rb_eArgError, "invalid value for convert(): %+"PRIsVALUE, self); @@ -2017,53 +2227,39 @@ string_to_c_strict(VALUE self, int raise) /* * call-seq: - * str.to_c -> complex - * - * Returns a complex which denotes the string form. The parser - * ignores leading whitespaces and trailing garbage. Any digit - * sequences can be separated by an underscore. Returns zero for null - * or garbage string. - * - * '9'.to_c #=> (9+0i) - * '2.5'.to_c #=> (2.5+0i) - * '2.5/1'.to_c #=> ((5/2)+0i) - * '-3/2'.to_c #=> ((-3/2)+0i) - * '-i'.to_c #=> (0-1i) - * '45i'.to_c #=> (0+45i) - * '3-4i'.to_c #=> (3-4i) - * '-4e2-4e-2i'.to_c #=> (-400.0-0.04i) - * '-0.0-0.0i'.to_c #=> (-0.0-0.0i) - * '1/2+3/4i'.to_c #=> ((1/2)+(3/4)*i) - * 'ruby'.to_c #=> (0+0i) - * - * Polar form: - * include Math - * "1.0@0".to_c #=> (1+0.0i) - * "1.0@#{PI/2}".to_c #=> (0.0+1i) - * "1.0@#{PI}".to_c #=> (-1+0.0i) - * - * See Kernel.Complex. + * to_c -> complex + * + * Returns +self+ interpreted as a Complex object; + * leading whitespace and trailing garbage are ignored: + * + * '9'.to_c # => (9+0i) + * '2.5'.to_c # => (2.5+0i) + * '2.5/1'.to_c # => ((5/2)+0i) + * '-3/2'.to_c # => ((-3/2)+0i) + * '-i'.to_c # => (0-1i) + * '45i'.to_c # => (0+45i) + * '3-4i'.to_c # => (3-4i) + * '-4e2-4e-2i'.to_c # => (-400.0-0.04i) + * '-0.0-0.0i'.to_c # => (-0.0-0.0i) + * '1/2+3/4i'.to_c # => ((1/2)+(3/4)*i) + * '1.0@0'.to_c # => (1+0.0i) + * "1.0@#{Math::PI/2}".to_c # => (0.0+1i) + * "1.0@#{Math::PI}".to_c # => (-1+0.0i) + * + * Returns \Complex zero if the string cannot be converted: + * + * 'ruby'.to_c # => (0+0i) + * + * See Kernel#Complex. */ static VALUE string_to_c(VALUE self) { - char *s; VALUE num; rb_must_asciicompat(self); - s = RSTRING_PTR(self); - - if (s && s[RSTRING_LEN(self)]) { - rb_str_modify(self); - s = RSTRING_PTR(self); - s[RSTRING_LEN(self)] = '\0'; - } - - if (!s) - s = (char *)""; - - (void)parse_comp(s, 0, &num); + (void)parse_comp(rb_str_fill_terminator(self, 1), FALSE, &num); return num; } @@ -2120,8 +2316,11 @@ nucomp_convert(VALUE klass, VALUE a1, VALUE a2, int raise) return a1; /* should raise exception for consistency */ if (!k_numeric_p(a1)) { - if (!raise) - return rb_protect(to_complex, a1, NULL); + if (!raise) { + a1 = rb_protect(to_complex, a1, NULL); + rb_set_errinfo(Qnil); + return a1; + } return to_complex(a1); } } @@ -2165,9 +2364,9 @@ nucomp_s_convert(int argc, VALUE *argv, VALUE klass) /* * call-seq: - * num.abs2 -> real + * abs2 -> real * - * Returns square of self. + * Returns the square of +self+. */ static VALUE numeric_abs2(VALUE self) @@ -2177,11 +2376,9 @@ numeric_abs2(VALUE self) /* * call-seq: - * num.arg -> 0 or float - * num.angle -> 0 or float - * num.phase -> 0 or float + * arg -> 0 or Math::PI * - * Returns 0 if the value is positive, pi otherwise. + * Returns zero if +self+ is positive, Math::PI otherwise. */ static VALUE numeric_arg(VALUE self) @@ -2193,10 +2390,9 @@ numeric_arg(VALUE self) /* * call-seq: - * num.rect -> array - * num.rectangular -> array + * rect -> array * - * Returns an array; [num, 0]. + * Returns array [self, 0]. */ static VALUE numeric_rect(VALUE self) @@ -2206,9 +2402,9 @@ numeric_rect(VALUE self) /* * call-seq: - * num.polar -> array + * polar -> array * - * Returns an array; [num.abs, num.arg]. + * Returns array [self.abs, self.arg]. */ static VALUE numeric_polar(VALUE self) @@ -2236,11 +2432,9 @@ numeric_polar(VALUE self) /* * call-seq: - * flo.arg -> 0 or float - * flo.angle -> 0 or float - * flo.phase -> 0 or float + * arg -> 0 or Math::PI * - * Returns 0 if the value is positive, pi otherwise. + * Returns 0 if +self+ is positive, Math::PI otherwise. */ static VALUE float_arg(VALUE self) @@ -2253,45 +2447,137 @@ float_arg(VALUE self) } /* - * A complex number can be represented as a paired real number with - * imaginary unit; a+bi. Where a is real part, b is imaginary part - * and i is imaginary unit. Real a equals complex a+0i - * mathematically. + * A \Complex object houses a pair of values, + * given when the object is created as either rectangular coordinates + * or polar coordinates. * - * You can create a \Complex object explicitly with: + * == Rectangular Coordinates + * + * The rectangular coordinates of a complex number + * are called the _real_ and _imaginary_ parts; + * see {Complex number definition}[https://en.wikipedia.org/wiki/Complex_number#Definition_and_basic_operations]. + * + * You can create a \Complex object from rectangular coordinates with: * * - A {complex literal}[rdoc-ref:syntax/literals.rdoc@Complex+Literals]. + * - Method Complex.rect. + * - Method Kernel#Complex, either with numeric arguments or with certain string arguments. + * - Method String#to_c, for certain strings. + * + * Note that each of the stored parts may be a an instance one of the classes + * Complex, Float, Integer, or Rational; + * they may be retrieved: + * + * - Separately, with methods Complex#real and Complex#imaginary. + * - Together, with method Complex#rect. + * + * The corresponding (computed) polar values may be retrieved: + * + * - Separately, with methods Complex#abs and Complex#arg. + * - Together, with method Complex#polar. + * + * == Polar Coordinates + * + * The polar coordinates of a complex number + * are called the _absolute_ and _argument_ parts; + * see {Complex polar plane}[https://en.wikipedia.org/wiki/Complex_number#Polar_form]. + * + * In this class, the argument part + * in expressed {radians}[https://en.wikipedia.org/wiki/Radian] + * (not {degrees}[https://en.wikipedia.org/wiki/Degree_(angle)]). + * + * You can create a \Complex object from polar coordinates with: + * + * - Method Complex.polar. + * - Method Kernel#Complex, with certain string arguments. + * - Method String#to_c, for certain strings. + * + * Note that each of the stored parts may be a an instance one of the classes + * Complex, Float, Integer, or Rational; + * they may be retrieved: + * + * - Separately, with methods Complex#abs and Complex#arg. + * - Together, with method Complex#polar. + * + * The corresponding (computed) rectangular values may be retrieved: + * + * - Separately, with methods Complex#real and Complex#imag. + * - Together, with method Complex#rect. + * + * == What's Here + * + * First, what's elsewhere: + * + * - Class \Complex inherits (directly or indirectly) + * from classes {Numeric}[rdoc-ref:Numeric@What-27s+Here] + * and {Object}[rdoc-ref:Object@What-27s+Here]. + * - Includes (indirectly) module {Comparable}[rdoc-ref:Comparable@What-27s+Here]. + * + * Here, class \Complex has methods for: + * + * === Creating \Complex Objects + * + * - ::polar: Returns a new \Complex object based on given polar coordinates. + * - ::rect (and its alias ::rectangular): + * Returns a new \Complex object based on given rectangular coordinates. + * + * === Querying + * + * - #abs (and its alias #magnitude): Returns the absolute value for +self+. + * - #arg (and its aliases #angle and #phase): + * Returns the argument (angle) for +self+ in radians. + * - #denominator: Returns the denominator of +self+. + * - #finite?: Returns whether both +self.real+ and +self.image+ are finite. + * - #hash: Returns the integer hash value for +self+. + * - #imag (and its alias #imaginary): Returns the imaginary value for +self+. + * - #infinite?: Returns whether +self.real+ or +self.image+ is infinite. + * - #numerator: Returns the numerator of +self+. + * - #polar: Returns the array [self.abs, self.arg]. + * - #inspect: Returns a string representation of +self+. + * - #real: Returns the real value for +self+. + * - #real?: Returns +false+; for compatibility with Numeric#real?. + * - #rect (and its alias #rectangular): + * Returns the array [self.real, self.imag]. + * + * === Comparing + * + * - #<=>: Returns whether +self+ is less than, equal to, or greater than the given argument. + * - #==: Returns whether +self+ is equal to the given argument. * - * You can convert certain objects to \Complex objects with: + * === Converting * - * - \Method #Complex. + * - #rationalize: Returns a Rational object whose value is exactly + * or approximately equivalent to that of self.real. + * - #to_c: Returns +self+. + * - #to_d: Returns the value as a BigDecimal object. + * - #to_f: Returns the value of self.real as a Float, if possible. + * - #to_i: Returns the value of self.real as an Integer, if possible. + * - #to_r: Returns the value of self.real as a Rational, if possible. + * - #to_s: Returns a string representation of +self+. * - * Complex object can be created as literal, and also by using - * Kernel#Complex, Complex::rect, Complex::polar or to_c method. + * === Performing Complex Arithmetic * - * 2+1i #=> (2+1i) - * Complex(1) #=> (1+0i) - * Complex(2, 3) #=> (2+3i) - * Complex.polar(2, 3) #=> (-1.9799849932008908+0.2822400161197344i) - * 3.to_c #=> (3+0i) + * - #*: Returns the product of +self+ and the given numeric. + * - #**: Returns +self+ raised to power of the given numeric. + * - #+: Returns the sum of +self+ and the given numeric. + * - #-: Returns the difference of +self+ and the given numeric. + * - #-@: Returns the negation of +self+. + * - #/: Returns the quotient of +self+ and the given numeric. + * - #abs2: Returns square of the absolute value (magnitude) for +self+. + * - #conj (and its alias #conjugate): Returns the conjugate of +self+. + * - #fdiv: Returns Complex.rect(self.real/numeric, self.imag/numeric). * - * You can also create complex object from floating-point numbers or - * strings. + * === Working with JSON * - * Complex(0.3) #=> (0.3+0i) - * Complex('0.3-0.5i') #=> (0.3-0.5i) - * Complex('2/3+3/4i') #=> ((2/3)+(3/4)*i) - * Complex('1@2') #=> (-0.4161468365471424+0.9092974268256817i) + * - ::json_create: Returns a new \Complex object, + * deserialized from the given serialized hash. + * - #as_json: Returns a serialized hash constructed from +self+. + * - #to_json: Returns a JSON string representing +self+. * - * 0.3.to_c #=> (0.3+0i) - * '0.3-0.5i'.to_c #=> (0.3-0.5i) - * '2/3+3/4i'.to_c #=> ((2/3)+(3/4)*i) - * '1@2'.to_c #=> (-0.4161468365471424+0.9092974268256817i) + * These methods are provided by the {JSON gem}[https://github.com/ruby/json]. To make these methods available: * - * A complex object is either an exact or an inexact number. + * require 'json/add/complex' * - * Complex(1, 1) / 2 #=> ((1/2)+(1/2)*i) - * Complex(1, 1) / 2.0 #=> (0.5+0.5i) */ void Init_Complex(void) @@ -2392,7 +2678,6 @@ Init_Complex(void) rb_define_method(rb_cComplex, "to_r", nucomp_to_r, 0); rb_define_method(rb_cComplex, "rationalize", nucomp_rationalize, -1); rb_define_method(rb_cComplex, "to_c", nucomp_to_c, 0); - rb_define_method(rb_cNilClass, "to_c", nilclass_to_c, 0); rb_define_method(rb_cNumeric, "to_c", numeric_to_c, 0); rb_define_method(rb_cString, "to_c", string_to_c, 0); @@ -2412,13 +2697,17 @@ Init_Complex(void) rb_define_method(rb_cFloat, "phase", float_arg, 0); /* - * The imaginary unit. + * Equivalent + * to Complex.rect(0, 1): + * + * Complex::I # => (0+1i) + * */ rb_define_const(rb_cComplex, "I", f_complex_new_bang2(rb_cComplex, ZERO, ONE)); #if !USE_FLONUM - rb_gc_register_mark_object(RFLOAT_0 = DBL2NUM(0.0)); + rb_vm_register_global_object(RFLOAT_0 = DBL2NUM(0.0)); #endif rb_provide("complex.so"); /* for backward compatibility */ diff --git a/concurrent_set.c b/concurrent_set.c new file mode 100644 index 00000000000000..dac6e9ce397ae5 --- /dev/null +++ b/concurrent_set.c @@ -0,0 +1,325 @@ +#include "internal.h" +#include "internal/gc.h" +#include "internal/concurrent_set.h" +#include "ruby_atomic.h" +#include "ruby/atomic.h" +#include "vm_sync.h" + +enum concurrent_set_special_values { + CONCURRENT_SET_EMPTY, + CONCURRENT_SET_DELETED, + CONCURRENT_SET_MOVED, + CONCURRENT_SET_SPECIAL_VALUE_COUNT +}; + +struct concurrent_set_entry { + VALUE hash; + VALUE key; +}; + +struct concurrent_set { + rb_atomic_t size; + unsigned int capacity; + unsigned int deleted_entries; + struct rb_concurrent_set_funcs *funcs; + struct concurrent_set_entry *entries; +}; + +static void +concurrent_set_free(void *ptr) +{ + struct concurrent_set *set = ptr; + xfree(set->entries); +} + +static size_t +concurrent_set_size(const void *ptr) +{ + const struct concurrent_set *set = ptr; + return sizeof(struct concurrent_set) + + (set->capacity * sizeof(struct concurrent_set_entry)); +} + +static const rb_data_type_t concurrent_set_type = { + .wrap_struct_name = "VM/concurrent_set", + .function = { + .dmark = NULL, + .dfree = concurrent_set_free, + .dsize = concurrent_set_size, + }, + .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_EMBEDDABLE +}; + +VALUE +rb_concurrent_set_new(struct rb_concurrent_set_funcs *funcs, int capacity) +{ + struct concurrent_set *set; + VALUE obj = TypedData_Make_Struct(0, struct concurrent_set, &concurrent_set_type, set); + set->funcs = funcs; + set->entries = ZALLOC_N(struct concurrent_set_entry, capacity); + set->capacity = capacity; + return obj; +} + +struct concurrent_set_probe { + int idx; + int d; + int mask; +}; + +static int +concurrent_set_probe_start(struct concurrent_set_probe *probe, struct concurrent_set *set, VALUE hash) +{ + RUBY_ASSERT((set->capacity & (set->capacity - 1)) == 0); + probe->d = 0; + probe->mask = set->capacity - 1; + probe->idx = hash & probe->mask; + return probe->idx; +} + +static int +concurrent_set_probe_next(struct concurrent_set_probe *probe) +{ + probe->d++; + probe->idx = (probe->idx + probe->d) & probe->mask; + return probe->idx; +} + +static void +concurrent_set_try_resize_without_locking(VALUE old_set_obj, VALUE *set_obj_ptr) +{ + // Check if another thread has already resized. + if (RUBY_ATOMIC_VALUE_LOAD(*set_obj_ptr) != old_set_obj) { + return; + } + + struct concurrent_set *old_set = RTYPEDDATA_GET_DATA(old_set_obj); + + // This may overcount by up to the number of threads concurrently attempting to insert + // GC may also happen between now and the set being rebuilt + int expected_size = RUBY_ATOMIC_LOAD(old_set->size) - old_set->deleted_entries; + + struct concurrent_set_entry *old_entries = old_set->entries; + int old_capacity = old_set->capacity; + int new_capacity = old_capacity * 2; + if (new_capacity > expected_size * 8) { + new_capacity = old_capacity / 2; + } + else if (new_capacity > expected_size * 4) { + new_capacity = old_capacity; + } + + // May cause GC and therefore deletes, so must hapen first. + VALUE new_set_obj = rb_concurrent_set_new(old_set->funcs, new_capacity); + struct concurrent_set *new_set = RTYPEDDATA_GET_DATA(new_set_obj); + + for (int i = 0; i < old_capacity; i++) { + struct concurrent_set_entry *entry = &old_entries[i]; + VALUE key = RUBY_ATOMIC_VALUE_EXCHANGE(entry->key, CONCURRENT_SET_MOVED); + RUBY_ASSERT(key != CONCURRENT_SET_MOVED); + + if (key < CONCURRENT_SET_SPECIAL_VALUE_COUNT) continue; + if (rb_objspace_garbage_object_p(key)) continue; + + VALUE hash = RUBY_ATOMIC_VALUE_LOAD(entry->hash); + if (hash == 0) { + // Either in-progress insert or extremely unlikely 0 hash. + // Re-calculate the hash. + hash = old_set->funcs->hash(key); + } + RUBY_ASSERT(hash == old_set->funcs->hash(key)); + + // Insert key into new_set. + struct concurrent_set_probe probe; + int idx = concurrent_set_probe_start(&probe, new_set, hash); + + while (true) { + struct concurrent_set_entry *entry = &new_set->entries[idx]; + + if (entry->key == CONCURRENT_SET_EMPTY) { + new_set->size++; + + RUBY_ASSERT(new_set->size < new_set->capacity / 2); + RUBY_ASSERT(entry->hash == 0); + + entry->key = key; + entry->hash = hash; + break; + } + else { + RUBY_ASSERT(entry->key >= CONCURRENT_SET_SPECIAL_VALUE_COUNT); + } + + idx = concurrent_set_probe_next(&probe); + } + } + + RUBY_ATOMIC_VALUE_SET(*set_obj_ptr, new_set_obj); + + RB_GC_GUARD(old_set_obj); +} + +static void +concurrent_set_try_resize(VALUE old_set_obj, VALUE *set_obj_ptr) +{ + RB_VM_LOCKING() { + concurrent_set_try_resize_without_locking(old_set_obj, set_obj_ptr); + } +} + +VALUE +rb_concurrent_set_find_or_insert(VALUE *set_obj_ptr, VALUE key, void *data) +{ + RUBY_ASSERT(key >= CONCURRENT_SET_SPECIAL_VALUE_COUNT); + + bool inserting = false; + VALUE set_obj; + + retry: + set_obj = RUBY_ATOMIC_VALUE_LOAD(*set_obj_ptr); + RUBY_ASSERT(set_obj); + struct concurrent_set *set = RTYPEDDATA_GET_DATA(set_obj); + + struct concurrent_set_probe probe; + VALUE hash = set->funcs->hash(key); + int idx = concurrent_set_probe_start(&probe, set, hash); + + while (true) { + struct concurrent_set_entry *entry = &set->entries[idx]; + VALUE curr_key = RUBY_ATOMIC_VALUE_LOAD(entry->key); + + switch (curr_key) { + case CONCURRENT_SET_EMPTY: { + // Not in set + if (!inserting) { + key = set->funcs->create(key, data); + RUBY_ASSERT(hash == set->funcs->hash(key)); + inserting = true; + } + + rb_atomic_t prev_size = RUBY_ATOMIC_FETCH_ADD(set->size, 1); + + if (UNLIKELY(prev_size > set->capacity / 2)) { + concurrent_set_try_resize(set_obj, set_obj_ptr); + + goto retry; + } + + curr_key = RUBY_ATOMIC_VALUE_CAS(entry->key, CONCURRENT_SET_EMPTY, key); + if (curr_key == CONCURRENT_SET_EMPTY) { + RUBY_ATOMIC_VALUE_SET(entry->hash, hash); + + RB_GC_GUARD(set_obj); + return key; + } + else { + // Entry was not inserted. + RUBY_ATOMIC_DEC(set->size); + + // Another thread won the race, try again at the same location. + continue; + } + } + case CONCURRENT_SET_DELETED: + break; + case CONCURRENT_SET_MOVED: + // Wait + RB_VM_LOCKING(); + + goto retry; + default: { + VALUE curr_hash = RUBY_ATOMIC_VALUE_LOAD(entry->hash); + if ((curr_hash == hash || curr_hash == 0) && set->funcs->cmp(key, curr_key)) { + // We've found a match. + if (UNLIKELY(rb_objspace_garbage_object_p(curr_key))) { + // This is a weakref set, so after marking but before sweeping is complete we may find a matching garbage object. + // Skip it and mark it as deleted. + RUBY_ATOMIC_VALUE_CAS(entry->key, curr_key, CONCURRENT_SET_DELETED); + + // Fall through and continue our search. + } + else { + RB_GC_GUARD(set_obj); + return curr_key; + } + } + + break; + } + } + + idx = concurrent_set_probe_next(&probe); + } +} + +VALUE +rb_concurrent_set_delete_by_identity(VALUE set_obj, VALUE key) +{ + // Assume locking and barrier (which there is no assert for). + ASSERT_vm_locking(); + + struct concurrent_set *set = RTYPEDDATA_GET_DATA(set_obj); + + VALUE hash = set->funcs->hash(key); + + struct concurrent_set_probe probe; + int idx = concurrent_set_probe_start(&probe, set, hash); + + while (true) { + struct concurrent_set_entry *entry = &set->entries[idx]; + VALUE curr_key = RUBY_ATOMIC_VALUE_LOAD(entry->key); + + switch (curr_key) { + case CONCURRENT_SET_EMPTY: + // We didn't find our entry to delete. + return 0; + case CONCURRENT_SET_DELETED: + break; + case CONCURRENT_SET_MOVED: + rb_bug("rb_concurrent_set_delete_by_identity: moved entry"); + break; + default: + if (key == curr_key) { + entry->key = CONCURRENT_SET_DELETED; + set->deleted_entries++; + return curr_key; + } + break; + } + + idx = concurrent_set_probe_next(&probe); + } +} + +void +rb_concurrent_set_foreach_with_replace(VALUE set_obj, int (*callback)(VALUE *key, void *data), void *data) +{ + // Assume locking and barrier (which there is no assert for). + ASSERT_vm_locking(); + + struct concurrent_set *set = RTYPEDDATA_GET_DATA(set_obj); + + for (unsigned int i = 0; i < set->capacity; i++) { + VALUE key = set->entries[i].key; + + switch (key) { + case CONCURRENT_SET_EMPTY: + case CONCURRENT_SET_DELETED: + continue; + case CONCURRENT_SET_MOVED: + rb_bug("rb_concurrent_set_foreach_with_replace: moved entry"); + break; + default: { + int ret = callback(&set->entries[i].key, data); + switch (ret) { + case ST_STOP: + return; + case ST_DELETE: + set->entries[i].key = CONCURRENT_SET_DELETED; + break; + } + break; + } + } + } +} diff --git a/configure.ac b/configure.ac index 122e0617929999..7270bd5e8b9cbe 100644 --- a/configure.ac +++ b/configure.ac @@ -9,43 +9,51 @@ tooldir="$srcdir/tool" AC_DISABLE_OPTION_CHECKING -m4_include([tool/m4/_colorize_result_prepare.m4])dnl -m4_include([tool/m4/ac_msg_result.m4])dnl -m4_include([tool/m4/colorize_result.m4])dnl -m4_include([tool/m4/ruby_append_option.m4])dnl -m4_include([tool/m4/ruby_append_options.m4])dnl -m4_include([tool/m4/ruby_check_builtin_func.m4])dnl -m4_include([tool/m4/ruby_check_builtin_setjmp.m4])dnl -m4_include([tool/m4/ruby_check_printf_prefix.m4])dnl -m4_include([tool/m4/ruby_check_setjmp.m4])dnl -m4_include([tool/m4/ruby_check_signedness.m4])dnl -m4_include([tool/m4/ruby_check_sizeof.m4])dnl -m4_include([tool/m4/ruby_check_sysconf.m4])dnl -m4_include([tool/m4/ruby_cppoutfile.m4])dnl -m4_include([tool/m4/ruby_decl_attribute.m4])dnl -m4_include([tool/m4/ruby_default_arch.m4])dnl -m4_include([tool/m4/ruby_define_if.m4])dnl -m4_include([tool/m4/ruby_defint.m4])dnl -m4_include([tool/m4/ruby_dtrace_available.m4])dnl -m4_include([tool/m4/ruby_dtrace_postprocess.m4])dnl -m4_include([tool/m4/ruby_func_attribute.m4])dnl -m4_include([tool/m4/ruby_mingw32.m4])dnl -m4_include([tool/m4/ruby_prepend_option.m4])dnl -m4_include([tool/m4/ruby_prog_gnu_ld.m4])dnl -m4_include([tool/m4/ruby_prog_makedirs.m4])dnl -m4_include([tool/m4/ruby_replace_funcs.m4])dnl -m4_include([tool/m4/ruby_replace_type.m4])dnl -m4_include([tool/m4/ruby_require_funcs.m4])dnl -m4_include([tool/m4/ruby_rm_recursive.m4])dnl -m4_include([tool/m4/ruby_setjmp_type.m4])dnl -m4_include([tool/m4/ruby_stack_grow_direction.m4])dnl -m4_include([tool/m4/ruby_thread.m4])dnl -m4_include([tool/m4/ruby_try_cflags.m4])dnl -m4_include([tool/m4/ruby_try_cxxflags.m4])dnl -m4_include([tool/m4/ruby_try_ldflags.m4])dnl -m4_include([tool/m4/ruby_universal_arch.m4])dnl -m4_include([tool/m4/ruby_wasm_tools.m4])dnl -m4_include([tool/m4/ruby_werror_flag.m4])dnl +m4_define([RUBY_M4_INCLUDED], [])dnl +AC_DEFUN([RUBY_M4_INCLUDE], [m4_include([tool/m4/$1])dnl + m4_append([RUBY_M4_INCLUDED], [ \ + $(tooldir)/m4/$1])dnl +]) +RUBY_M4_INCLUDE([_colorize_result_prepare.m4])dnl +RUBY_M4_INCLUDE([ac_msg_result.m4])dnl +RUBY_M4_INCLUDE([colorize_result.m4])dnl +RUBY_M4_INCLUDE([ruby_append_option.m4])dnl +RUBY_M4_INCLUDE([ruby_append_options.m4])dnl +RUBY_M4_INCLUDE([ruby_check_builtin_func.m4])dnl +RUBY_M4_INCLUDE([ruby_check_builtin_overflow.m4])dnl +RUBY_M4_INCLUDE([ruby_check_builtin_setjmp.m4])dnl +RUBY_M4_INCLUDE([ruby_check_header.m4])dnl +RUBY_M4_INCLUDE([ruby_check_printf_prefix.m4])dnl +RUBY_M4_INCLUDE([ruby_check_setjmp.m4])dnl +RUBY_M4_INCLUDE([ruby_check_signedness.m4])dnl +RUBY_M4_INCLUDE([ruby_check_sizeof.m4])dnl +RUBY_M4_INCLUDE([ruby_check_sysconf.m4])dnl +RUBY_M4_INCLUDE([ruby_cppoutfile.m4])dnl +RUBY_M4_INCLUDE([ruby_decl_attribute.m4])dnl +RUBY_M4_INCLUDE([ruby_default_arch.m4])dnl +RUBY_M4_INCLUDE([ruby_define_if.m4])dnl +RUBY_M4_INCLUDE([ruby_defint.m4])dnl +RUBY_M4_INCLUDE([ruby_dtrace_available.m4])dnl +RUBY_M4_INCLUDE([ruby_dtrace_postprocess.m4])dnl +RUBY_M4_INCLUDE([ruby_func_attribute.m4])dnl +RUBY_M4_INCLUDE([ruby_mingw32.m4])dnl +RUBY_M4_INCLUDE([ruby_prepend_option.m4])dnl +RUBY_M4_INCLUDE([ruby_prog_gnu_ld.m4])dnl +RUBY_M4_INCLUDE([ruby_prog_makedirs.m4])dnl +RUBY_M4_INCLUDE([ruby_replace_funcs.m4])dnl +RUBY_M4_INCLUDE([ruby_replace_type.m4])dnl +RUBY_M4_INCLUDE([ruby_require_funcs.m4])dnl +RUBY_M4_INCLUDE([ruby_rm_recursive.m4])dnl +RUBY_M4_INCLUDE([ruby_setjmp_type.m4])dnl +RUBY_M4_INCLUDE([ruby_modular_gc.m4])dnl +RUBY_M4_INCLUDE([ruby_stack_grow_direction.m4])dnl +RUBY_M4_INCLUDE([ruby_thread.m4])dnl +RUBY_M4_INCLUDE([ruby_try_cflags.m4])dnl +RUBY_M4_INCLUDE([ruby_try_cxxflags.m4])dnl +RUBY_M4_INCLUDE([ruby_try_ldflags.m4])dnl +RUBY_M4_INCLUDE([ruby_universal_arch.m4])dnl +RUBY_M4_INCLUDE([ruby_wasm_tools.m4])dnl +RUBY_M4_INCLUDE([ruby_werror_flag.m4])dnl AS_IF([test "x${GITHUB_ACTIONS}" = xtrue], [AC_REQUIRE([_COLORIZE_RESULT_PREPARE])dnl @@ -75,8 +83,10 @@ AC_ARG_WITH(baseruby, [ AC_PATH_PROG([BASERUBY], [ruby], [false]) ]) -# BASERUBY must be >= 2.5.0. Note that `"2.5.0" > "2.5"` is true. -AS_IF([test "$HAVE_BASERUBY" != no -a "`RUBYOPT=- $BASERUBY --disable=gems -e 'print 42 if RUBY_VERSION > "2.5"' 2>/dev/null`" = 42], [ +AS_IF([test "$HAVE_BASERUBY" != no], [ + RUBYOPT=- $BASERUBY --disable=gems -rerb -rfileutils -rtempfile "${tooldir}/missing-baseruby.bat" || HAVE_BASERUBY=no +]) +AS_IF([test "${HAVE_BASERUBY:=no}" != no], [ AS_CASE(["$build_os"], [mingw*], [ # Can MSys shell run a command with a drive letter? RUBYOPT=- `cygpath -ma "$BASERUBY"` --disable=gems -e exit 2>/dev/null || HAVE_BASERUBY=no @@ -84,12 +94,10 @@ AS_IF([test "$HAVE_BASERUBY" != no -a "`RUBYOPT=- $BASERUBY --disable=gems -e 'p RUBY_APPEND_OPTION(BASERUBY, "--disable=gems") BASERUBY_VERSION=`$BASERUBY -v` $BASERUBY -C "$srcdir" tool/downloader.rb -d tool -e gnu config.guess config.sub >&AS_MESSAGE_FD -], [ - HAVE_BASERUBY=no ]) AS_IF([test "$HAVE_BASERUBY" = no], [ AS_IF([test "$cross_compiling" = yes], [AC_MSG_ERROR([executable host ruby is required for cross-compiling])]) - BASERUBY="echo executable host ruby is required. use --with-baseruby option.; false" + BASERUBY=${tooldir}/missing-baseruby.bat ]) AC_SUBST(BASERUBY) AC_SUBST(HAVE_BASERUBY) @@ -141,6 +149,7 @@ dnl checks for alternative programs AC_CANONICAL_BUILD AC_CANONICAL_HOST AC_CANONICAL_TARGET +AC_SUBST(config_target, $target) AS_CASE(["$target_cpu-$target_os"], [aarch64-darwin*], [ target_cpu=arm64 @@ -199,7 +208,7 @@ AC_ARG_VAR([STRIP], [Strip command]) set rb_dummy ${CC} rb_CC=$2 AC_DEFUN([RUBY_CHECK_PROG_FOR_CC], [ - rb_prog=`echo "${rb_CC}" | sed "$2"` + rb_prog=`echo "${rb_CC}" | sed ["s:$2\([^/]*\)$:$3\1:"]` AC_CHECK_PROG([$1], [$rb_prog], [$rb_prog]) ]) AS_CASE(["/${rb_CC} "], @@ -210,30 +219,38 @@ AS_CASE(["/${rb_CC} "], [*icc*], [ # Intel C++ has interprocedural optimizations. It tends to come with its # own linker etc. - RUBY_CHECK_PROG_FOR_CC([AR], [s/icc/xiar/]) - RUBY_CHECK_PROG_FOR_CC([CXX], [s/icc/icpc/]) - RUBY_CHECK_PROG_FOR_CC([LD], [s/icc/xild/]) + RUBY_CHECK_PROG_FOR_CC([AR], [icc], [xiar]) + RUBY_CHECK_PROG_FOR_CC([CXX], [icc], [icpc]) + RUBY_CHECK_PROG_FOR_CC([LD], [icc], [xild]) ], [*gcc*], [ # Ditto for GCC. - RUBY_CHECK_PROG_FOR_CC([LD], [s/gcc/ld/]) - RUBY_CHECK_PROG_FOR_CC([AR], [s/gcc/gcc-ar/]) - RUBY_CHECK_PROG_FOR_CC([CXX], [s/gcc/g++/]) - RUBY_CHECK_PROG_FOR_CC([NM], [s/gcc/gcc-nm/]) - RUBY_CHECK_PROG_FOR_CC([RANLIB], [s/gcc/gcc-ranlib/]) + RUBY_CHECK_PROG_FOR_CC([LD], [gcc], [ld]) + RUBY_CHECK_PROG_FOR_CC([AR], [gcc], [gcc-ar]) + RUBY_CHECK_PROG_FOR_CC([CXX], [gcc], [g++]) + RUBY_CHECK_PROG_FOR_CC([NM], [gcc], [gcc-nm]) + RUBY_CHECK_PROG_FOR_CC([RANLIB], [gcc], [gcc-ranlib]) ], [*clang*], [ # Ditto for LLVM. Note however that llvm-as is a LLVM-IR to LLVM bitcode # assembler that does not target your machine native binary. - RUBY_CHECK_PROG_FOR_CC([LD], [s/clang/ld/]) # ... maybe try lld ? - RUBY_CHECK_PROG_FOR_CC([AR], [s/clang/llvm-ar/]) -# RUBY_CHECK_PROG_FOR_CC([AS], [s/clang/llvm-as/]) - RUBY_CHECK_PROG_FOR_CC([CXX], [s/clang/clang++/]) - RUBY_CHECK_PROG_FOR_CC([NM], [s/clang/llvm-nm/]) - RUBY_CHECK_PROG_FOR_CC([OBJCOPY], [s/clang/llvm-objcopy/]) - RUBY_CHECK_PROG_FOR_CC([OBJDUMP], [s/clang/llvm-objdump/]) - RUBY_CHECK_PROG_FOR_CC([RANLIB], [s/clang/llvm-ranlib/]) - RUBY_CHECK_PROG_FOR_CC([STRIP], [s/clang/llvm-strip/]) + + # Xcode has its own version tools that may be incompatible with + # genuine LLVM tools, use the tools in the same directory. + + AS_IF([$rb_CC -E -dM -xc - < /dev/null | grep -F __apple_build_version__ > /dev/null], + [llvm_prefix=], [llvm_prefix=llvm-]) + # AC_PREPROC_IFELSE cannot be used before AC_USE_SYSTEM_EXTENSIONS + + RUBY_CHECK_PROG_FOR_CC([LD], [clang], [ld]) # ... maybe try lld ? + RUBY_CHECK_PROG_FOR_CC([AR], [clang], [${llvm_prefix}ar]) +# RUBY_CHECK_PROG_FOR_CC([AS], [clang], [${llvm_prefix}as]) + RUBY_CHECK_PROG_FOR_CC([CXX], [clang], [clang++]) + RUBY_CHECK_PROG_FOR_CC([NM], [clang], [${llvm_prefix}nm]) + RUBY_CHECK_PROG_FOR_CC([OBJCOPY], [clang], [${llvm_prefix}objcopy]) + RUBY_CHECK_PROG_FOR_CC([OBJDUMP], [clang], [${llvm_prefix}objdump]) + RUBY_CHECK_PROG_FOR_CC([RANLIB], [clang], [${llvm_prefix}ranlib]) + RUBY_CHECK_PROG_FOR_CC([STRIP], [clang], [${llvm_prefix}strip]) ]) AS_UNSET(rb_CC) AS_UNSET(rb_dummy) @@ -244,12 +261,6 @@ AS_CASE(["${build_os}"], ], [aix*], [ AC_PATH_TOOL([NM], [nm], [/usr/ccs/bin/nm], [/usr/ccs/bin:$PATH]) -], -[darwin*], [ - # For Apple clang version 14.0.3 (clang-1403.0.22.14.1) - ac_cv_prog_ac_ct_AR=`$CC -print-prog-name=ar` - ac_cv_prog_ac_ct_LD=`$CC -print-prog-name=ld` - ac_cv_prog_ac_ct_NM=`$CC -print-prog-name=nm` ]) AS_CASE(["${target_os}"], [cygwin*|msys*|mingw*|darwin*], [ @@ -277,7 +288,7 @@ AC_CHECK_TOOLS([STRIP], [gstrip strip], [:]) # nm errors with Rust's LLVM bitcode when Rust uses a newer LLVM version than nm. # In case we're working with llvm-nm, tell it to not worry about the bitcode. -AS_IF([${NM} --help | grep -q 'llvm-bc'], [NM="$NM --no-llvm-bc"]) +AS_IF([${NM} --help 2>&1 | grep -q 'llvm-bc'], [NM="$NM --no-llvm-bc"]) AS_IF([test ! $rb_test_CFLAGS], [AS_UNSET(CFLAGS)]); AS_UNSET(rb_test_CFLAGS) AS_IF([test ! $rb_test_CXXFLAGS], [AS_UNSET(CXXFLAGS)]); AS_UNSET(rb_save_CXXFLAGS) @@ -351,7 +362,7 @@ test -z "$warnflags" || AS_IF([test -z "${CFLAGS+set}"], [ cflags=`echo " $cflags " | sed "$cflagspat;s/^ *//;s/ *$//"` orig_cflags="$cflags" - cflags="$cflags "'${optflags} ${debugflags} ${warnflags}' + cflags='${hardenflags} '"$cflags "'${optflags} ${debugflags} ${warnflags}' ]) dnl AS_IF([test -z "${CXXFLAGS+set}"], [ dnl cxxflags=`echo " $cxxflags " | sed "$cflagspat;s/^ *//;s/ *$//"` @@ -421,17 +432,25 @@ AC_SUBST(COUTFLAG) AC_SUBST(CSRCFLAG) AS_CASE(["$build_os"], - [darwin1*.*], [ + [darwin*], [ + # gcc 13 warns duplicate -l options, which are added by the + # default spec. # Xcode linker warns for deprecated architecture and wrongly # installed TBD files. - CC_WRAPPER="" + AC_MSG_CHECKING(for $CC linker warning) + suppress_ld_waring=no echo 'int main(void) {return 0;}' > conftest.c AS_IF([$CC -framework Foundation -o conftest conftest.c 2>&1 | - grep '^ld: warning: text-based stub file' >/dev/null], [ - CC_WRAPPER=`cd -P "${tooldir}" && pwd`/darwin-cc - CC="$CC_WRAPPER $CC" + grep \ + -e '^ld: warning: ignoring duplicate libraries:' \ + -e '^ld: warning: text-based stub file' \ + -e '^ld: warning: -multiply_defined is obsolete' \ + >/dev/null], [ + suppress_ld_waring=yes ]) rm -fr conftest* + test $suppress_ld_waring = yes && warnflags="${warnflags:+${warnflags} }-Wl,-w" + AC_MSG_RESULT($suppress_ld_waring) ]) AS_CASE(["$target_os"], [wasi*], [ @@ -458,8 +477,8 @@ AC_SUBST(CC_VERSION_MESSAGE, $cc_version_message) : ${DLDFLAGS="$LDFLAGS"} RUBY_UNIVERSAL_ARCH -AS_IF([test "$target_cpu" != "$host_cpu" -a "$GCC" = yes -a "$cross_compiling" = no -a "${universal_binary:-no}" = no], [ - RUBY_DEFAULT_ARCH("$target_cpu") +AS_IF([test "$target_cpu" != "$host_cpu" -a "$GCC" = yes -a "${universal_binary:-no}" = no], [ + RUBY_DEFAULT_ARCH($target_cpu) ]) host_os=$target_os host_vendor=$target_vendor @@ -472,7 +491,6 @@ AC_CACHE_CHECK([for $AR flags], [rb_cv_arflags], [ [rb_cv_arflags=rcD], [rb_cv_arflags=rcu]) ]) AC_SUBST(ARFLAGS, ["$rb_cv_arflags "]) -AC_SUBST(ASFLAGS) AS_CASE(["$target_os"], [cygwin*|msys*|mingw*], [ @@ -503,10 +521,10 @@ AS_CASE(["$target_os"], ]) rb_cv_binary_elf=no : ${enable_shared=yes} + AS_IF([$WINDRES --version | grep LLVM > /dev/null], [USE_LLVM_WINDRES=yes], [USE_LLVM_WINDRES=no]) ], [hiuxmpp*], [AC_DEFINE(__HIUX_MPP__)]) # by TOYODA Eizi - AC_PROG_LN_S AC_PROG_MAKE_SET AC_PROG_INSTALL @@ -646,9 +664,9 @@ RUBY_WERROR_FLAG([ [enable_rpath=$enableval], [enable_rpath="$rb_cv_binary_elf"]) AS_IF([test "$enable_rpath:${RPATHFLAG}" = yes:], [ - RPATHFLAG="${rpathflag:+ ${rpathflag}%1\$-s}" + RPATHFLAG="${rpathflag:+${rpathflag}%1\$-s}" ]) - AS_CASE([${RPATHFLAG}],[*'%1$'*],[: ${LIBPATHFLAG=' -L%1$-s'}],[: ${LIBPATHFLAG=' -L%s'}]) + AS_CASE([${RPATHFLAG}],[*'%1$'*],[: ${LIBPATHFLAG='-L%1$-s'}],[: ${LIBPATHFLAG='-L%s'}]) } RUBY_TRY_LDFLAGS(-fdeclspec, [fdeclspec=yes], [fdeclspec=no]) @@ -796,7 +814,7 @@ AS_IF([test "$GCC" = yes], [ [fortify_source=$enableval]) AS_IF([test "x$fortify_source" != xno], [ RUBY_TRY_CFLAGS([$optflags -D_FORTIFY_SOURCE=2], - [RUBY_APPEND_OPTION(XCFLAGS, -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2)], [], + [RUBY_PREPEND_OPTION(hardenflags, -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2)], [], [@%:@include ]) ]) @@ -817,18 +835,45 @@ AS_IF([test "$GCC" = yes], [ AC_MSG_CHECKING([for -fstack-protector]) AC_MSG_RESULT(["$stack_protector"]) AS_CASE(["$stack_protector"], [-*], [ - RUBY_APPEND_OPTION(XCFLAGS, $stack_protector) - RUBY_APPEND_OPTION(XLDFLAGS, $stack_protector) - RUBY_APPEND_OPTION(LDFLAGS, $stack_protector) + RUBY_PREPEND_OPTION(hardenflags, $stack_protector) + RUBY_APPEND_OPTION(XLDFLAGS, $stack_protector) + RUBY_APPEND_OPTION(LDFLAGS, $stack_protector) ]) # aarch64 branch protection - AS_CASE(["$target_cpu"], [aarch64], [ - AS_FOR(option, opt, [-mbranch-protection=pac-ret -msign-return-address=all], [ - RUBY_TRY_CFLAGS(option, [branch_protection=yes], [branch_protection=no]) - AS_IF([test "x$branch_protection" = xyes], [ - RUBY_APPEND_OPTION(XCFLAGS, option) - break + AS_CASE(["$target_cpu"], [aarch64|arm64], [ + # LLVM libunwind is not actually capable of unwinding code compiled with pointer + # authentication unless it's built without LIBUNWIND_ENABLE_CROSS_UNWINDING (see + # https://github.com/llvm/llvm-project/blob/8e35c86977ce5529a9387657321ac9fefcdae5b5/libunwind/src/DwarfInstructions.hpp#L294) + # It seems that macOS ships LLVM compiled this way. + # Detect this and disable automatic insertion of pac-ret flags in that case, since we assume + # that reliable backtraces are more important than hardening flags. + AC_MSG_CHECKING([for a broken LLVM libunwind that cannot unwind code with RA signing]) + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[ + @%:@include + int foo = UNW_ECROSSRASIGNING; + ]])], + # If compilation succeeds, that means we a) had libunwind, and b) it was NOT native only + [rb_cv_libunwind_broken_ra_signing=yes], + # if compilation fails, that means we either a) do not have libunwind, or b) have it in + # native only mode (which is good!) + [rb_cv_libunwind_broken_ra_signing=no] + ) + AC_MSG_RESULT(["$rb_cv_libunwind_broken_ra_signing"]) + AS_IF([test "x$rb_cv_libunwind_broken_ra_signing" = "xno"], [ + AS_FOR(option, opt, [-mbranch-protection=pac-ret -msign-return-address=all], [ + # Try these flags in the _prepended_ position - i.e. we want to try building a program + # with CFLAGS="-mbranch-protection=pac-ret $CFLAGS". If the builder has provided different + # branch protection flags in CFLAGS, we don't want to overwrite those. We just want to + # find some branch protection flags which work if none were provided. + RUBY_TRY_CFLAGS_PREPEND(option, [branch_protection=yes], [branch_protection=no]) + AS_IF([test "x$branch_protection" = xyes], [ + # _prepend_ the options to CFLAGS, so that user-provided flags will overwrite them. + # These CFLAGS are used during the configure script to compile further test programs; + # however, $harden_flags is prepended separately to CFLAGS at the end of the script. + RUBY_PREPEND_OPTION(hardenflags, $opt) + break + ]) ]) ]) ]) @@ -884,9 +929,9 @@ AS_IF([test "$GCC" = yes], [ # suppress annoying -Wstrict-overflow warnings RUBY_TRY_CFLAGS(-fno-strict-overflow, [RUBY_APPEND_OPTION(XCFLAGS, -fno-strict-overflow)]) - test "${debugflags+set}" || {RUBY_TRY_CFLAGS(-ggdb3, [debugflags=-ggdb3])} - test "${debugflags+set}" || {RUBY_TRY_CFLAGS(-ggdb, [debugflags=-ggdb])} - test "${debugflags+set}" || {RUBY_TRY_CFLAGS(-g3, [debugflags=-g3])} + test "${debugflags+set}" || {RUBY_TRY_LDFLAGS(-ggdb3, [debugflags=-ggdb3])} + test "${debugflags+set}" || {RUBY_TRY_LDFLAGS(-ggdb, [debugflags=-ggdb])} + test "${debugflags+set}" || {RUBY_TRY_LDFLAGS(-g3, [debugflags=-g3])} ]) test $ac_cv_prog_cc_g = yes && : ${debugflags=-g} @@ -958,22 +1003,31 @@ AC_ARG_WITH(opt-dir, [OPT_DIR="${OPT_DIR:+$OPT_DIR$PATH_SEPARATOR}$withval"], []) AS_IF([test "x$OPT_DIR" != x], [ + save_IFS="$IFS" IFS="$PATH_SEPARATOR" val= PWD= + for dir in $OPT_DIR; do + test -z "$dir" && continue + dir=`eval $CHDIR '"$dir"' 2>/dev/null && pwd` || continue + val="${val:+$val$PATH_SEPARATOR}$dir" + done + IFS="$save_IFS" OPT_DIR="$val" + unset PWD + unset save_IFS val=`IFS="$PATH_SEPARATOR" for dir in $OPT_DIR; do - test -z "$dir" && continue echo x ${LIBPATHFLAG} ${RPATHFLAG} | sed "s/^x *//;s${IFS}"'%1\\$-s'"${IFS}${dir}/lib${IFS}g;s${IFS}%s${IFS}${dir}/lib${IFS}g" done | tr '\012' ' ' | sed 's/ *$//'` LDFLAGS="${LDFLAGS:+$LDFLAGS }$val" DLDFLAGS="${DLDFLAGS:+$DLDFLAGS }$val" LDFLAGS_OPTDIR="$val" - CPPFLAGS="${CPPFLAGS:+$CPPFLAGS }"`echo "$OPT_DIR" | tr "${PATH_SEPARATOR}" '\012' | + INCFLAGS="${INCFLAGS:+$INCFLAGS }"`echo "$OPT_DIR" | tr "${PATH_SEPARATOR}" '\012' | sed '/^$/d;s|^|-I|;s|$|/include|' | tr '\012' ' ' | sed 's/ *$//'` ]) +AC_SUBST(incflags, "$INCFLAGS") test -z "${ac_env_CFLAGS_set}" -a -n "${cflags+set}" && eval CFLAGS="\"$cflags $ARCH_FLAG\"" test -z "${ac_env_CXXFLAGS_set}" -a -n "${cxxflags+set}" && eval CXXFLAGS="\"$cxxflags $ARCH_FLAG\"" -} + AC_CACHE_CHECK([whether compiler has statement and declarations in expressions], rb_cv_have_stmt_and_decl_in_expr, @@ -983,6 +1037,7 @@ AC_CACHE_CHECK([whether compiler has statement and declarations in expressions], AS_IF([test "$rb_cv_have_stmt_and_decl_in_expr" = yes], [ AC_DEFINE(HAVE_STMT_AND_DECL_IN_EXPR) ]) +} [begin]_group "header and library section" && { AC_ARG_WITH(winnt-ver, @@ -1039,7 +1094,6 @@ AS_CASE(["$target_os"], AS_IF([test $gcc_major -eq 4 -a $gcc_minor -lt 3], [ ac_cv_func___builtin_setjmp=no ]) - with_setjmp_type=sigsetjmp # to hijack SIGCHLD handler AC_CACHE_CHECK(for broken crypt with 8bit chars, rb_cv_broken_crypt, [AC_RUN_IFELSE([AC_LANG_SOURCE([[ #include @@ -1087,21 +1141,23 @@ main() ]) POSTLINK="" AC_CHECK_PROGS(codesign, codesign) - AC_CHECK_PROGS(dsymutil, dsymutil) + dsymutils= + AS_CASE("$CC_NO_WRAPPER", [gcc*-1[[3-9]]], [ + dsymutils=${CC_NO_WRAPPER@%:@gcc} + dsymutils=dsymutil${dsymutils%-1*} + dsymutils="$dsymutils-19 $dsymutils-18 $dsymutils-17" + ]) + AC_CHECK_PROGS(dsymutil, $dsymutils dsymutil) AS_IF([test -n "$codesign"], [ - POSTLINK="{ test -z '\$(RUBY_CODESIGN)' || $codesign -s '\$(RUBY_CODESIGN)' -f \$@; }${POSTLINK:+; $POSTLINK}" + POSTLINK="{ test -z '\$(RUBY_CODESIGN)' || $codesign -s '\$(RUBY_CODESIGN)' \$@; }${POSTLINK:+; $POSTLINK}" ]) AS_IF([test -n "$dsymutil"], [ - POSTLINK="$dsymutil \$@${POSTLINK:+; $POSTLINK}" - ]) - AS_IF([test -n "${POSTLINK}"], [ - LINK_SO="$LINK_SO -\$(POSTLINK)" + POSTLINK="$dsymutil \$@ 2>/dev/null${POSTLINK:+; $POSTLINK}" ]) AC_CHECK_HEADERS(crt_externs.h, [], [], [ #include ]) - cleanlibs='$(TARGET_SO).dSYM' + cleanlibs='$(TARGET_SO:=.dSYM)' ], [solaris*], [ LIBS="-lm $LIBS" ac_cv_func_vfork=no @@ -1194,8 +1250,6 @@ main() ac_cv_func_gmtime_r=yes rb_cv_large_fd_select=yes ac_cv_type_struct_timeval=yes - ac_cv_func_clock_gettime=yes - ac_cv_func_clock_getres=yes ac_cv_func_malloc_usable_size=no ac_cv_type_off_t=yes ac_cv_sizeof_off_t=8 @@ -1206,7 +1260,8 @@ main() ac_cv_func_tgamma=no AC_CHECK_TYPE([NET_LUID], [], [], [@%:@include - @%:@include ]) + @%:@include + @%:@include ]) AS_IF([test x"$ac_cv_type_NET_LUID" = xyes], [ AC_DEFINE(HAVE_TYPE_NET_LUID, 1) ]) @@ -1236,12 +1291,8 @@ main() # __builtin_longjmp in ppc64* Linux does not restore # the TOC register (r2), which is problematic # when a global exit happens from JITted .so code. - AS_CASE(["$target_cpu"], [powerpc64*], [ - ac_cv_func___builtin_setjmp=no - ]) - # With gcc-8's -fcf-protection, RJIT's __builtin_longjmp fails. - AS_CASE(["$CC $CFLAGS "], [*" -fcf-protection "*], [cf_protection=yes], [cf_protection=no]) - AS_IF([test "$cf_protection" = yes], [ + # __builtin_setjmp can have issues on arm64 linux (see [Bug #14480]). + AS_CASE(["$target_cpu"], [powerpc64*|arm64|aarch64], [ ac_cv_func___builtin_setjmp=no ]) ], @@ -1254,7 +1305,7 @@ main() [wasi*],[ LIBS="-lm -lwasi-emulated-mman -lwasi-emulated-signal -lwasi-emulated-getpid -lwasi-emulated-process-clocks $LIBS" RUBY_APPEND_OPTIONS(CFLAGS, -D_WASI_EMULATED_SIGNAL -D_WASI_EMULATED_MMAN -D_WASI_EMULATED_GETPID -D_WASI_EMULATED_PROCESS_CLOCKS) RUBY_APPEND_OPTIONS(CPPFLAGS, -D_WASI_EMULATED_SIGNAL -D_WASI_EMULATED_MMAN -D_WASI_EMULATED_GETPID -D_WASI_EMULATED_PROCESS_CLOCKS) - POSTLINK="\$(WASMOPT) --asyncify \$(wasmoptflags) --pass-arg=asyncify-ignore-imports -o \$@ \$@${POSTLINK:+; $POSTLINK}" + POSTLINK="\$(WASMOPT) --asyncify \$(wasmoptflags) -o \$@ \$@${POSTLINK:+; $POSTLINK}" # wasi-libc's sys/socket.h is not compatible with -std=gnu99, # so re-declare shutdown in include/ruby/missing.h ac_cv_func_shutdown=no @@ -1262,6 +1313,13 @@ main() [ LIBS="-lm $LIBS"]) : ${ORIG_LIBS=$LIBS} +AS_IF([test -n "${POSTLINK}"], [ + # NOTE: A (part of) link commands used link shared extension libraries. If + # the first line of the value is empty, mkmf prepends default link steps. + LINK_SO="$LINK_SO +\$(POSTLINK)" +]) + AS_IF([test -n "${rb_there_is_in_fact_no_gplusplus_but_autoconf_is_cheating_us}"], [ AC_MSG_NOTICE([Test skipped due to lack of a C++ compiler.]) ], @@ -1341,13 +1399,18 @@ AC_CHECK_HEADERS(syscall.h) AC_CHECK_HEADERS(time.h) AC_CHECK_HEADERS(ucontext.h) AC_CHECK_HEADERS(utime.h) -AS_CASE("$target_cpu", [x64|x86_64|i[3-6]86*], [ +AC_CHECK_HEADERS(sys/epoll.h) +AC_CHECK_HEADERS(sys/event.h) +AC_CHECK_HEADERS(stdckdint.h) +AC_CHECK_HEADERS(stdatomic.h) + +AS_CASE("$target_cpu", [x64|x86_64|[i[3-6]86*]], [ AC_CHECK_HEADERS(x86intrin.h) ]) RUBY_UNIVERSAL_CHECK_HEADER([x86_64, i386], x86intrin.h) AS_IF([test "x$with_gmp" != xno], - [AC_CHECK_HEADERS(gmp.h) + [RUBY_CHECK_HEADER(gmp.h) AS_IF([test "x$ac_cv_header_gmp_h" != xno], AC_SEARCH_LIBS([__gmpz_init], [gmp], [AC_DEFINE(HAVE_LIBGMP, 1)]))]) @@ -1357,6 +1420,8 @@ AC_ARG_WITH([jemalloc], [with_jemalloc=$withval], [with_jemalloc=no]) AS_IF([test "x$with_jemalloc" != xno],[ # find jemalloc header first + save_CPPFLAGS="${CPPFLAGS}" + CPPFLAGS="${INCFLAGS} ${CPPFLAGS}" malloc_header= AC_CHECK_HEADER(jemalloc/jemalloc.h, [malloc_header=jemalloc/jemalloc.h], [ AC_CHECK_HEADER(jemalloc.h, [malloc_header=jemalloc.h]) @@ -1388,6 +1453,8 @@ AS_IF([test "x$with_jemalloc" != xno],[ done done ]) + CPPFLAGS="${save_CPPFLAGS}" + unset save_CPPFLAGS with_jemalloc=${rb_cv_jemalloc_library} AS_CASE(["$with_jemalloc"], [no], @@ -1413,7 +1480,7 @@ AC_SYS_LARGEFILE # which is not added by AC_SYS_LARGEFILE. AS_IF([test x"$enable_largefile" != xno], [ AS_CASE(["$target_os"], [solaris*], [ - AC_MSG_CHECKING([wheather _LARGEFILE_SOURCE should be defined]) + AC_MSG_CHECKING([whether _LARGEFILE_SOURCE should be defined]) AS_CASE(["${ac_cv_sys_file_offset_bits}:${ac_cv_sys_large_files}"], ["64:"|"64:no"|"64:unknown"], [ # insert _LARGEFILE_SOURCE before _FILE_OFFSET_BITS line @@ -1474,6 +1541,25 @@ RUBY_CHECK_SIZEOF(float) RUBY_CHECK_SIZEOF(double) RUBY_CHECK_SIZEOF(time_t, [long "long long"], [], [@%:@include ]) RUBY_CHECK_SIZEOF(clock_t, [], [], [@%:@include ]) +AC_SUBST(X_BUILTIN_BINARY, yes) +AS_IF([test "$cross_compiling" = yes], +[dnl miniruby cannot run if cross compiling + X_BUILTIN_BINARY=no +], +[ + AS_CASE([ac_cv_sizeof_voidp], + [[1-9]*], [dnl fixed value + ], + [ + AC_CACHE_CHECK([word size], [rb_cv_word_size], + [for w in 4 8; do + AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[@%:@if SIZEOF_VOIDP != ${w} + @%:@error SIZEOF_VOIDP + @%:@endif]])], [rb_cv_word_size=${w}; break]) + done]) + AS_IF([test -z $rb_cv_word_size], [X_BUILTIN_BINARY=no]) + ]) +]) AC_CACHE_CHECK(packed struct attribute, rb_cv_packed_struct, [rb_cv_packed_struct=no @@ -1593,7 +1679,7 @@ AS_IF([test "$rb_cv_func_weak" != x], [ AC_DEFINE(HAVE_FUNC_WEAK) ]) -AC_CACHE_CHECK([for __attribute__((__depreacted__(msg))) in C++], +AC_CACHE_CHECK([for __attribute__((__deprecated__(msg))) in C++], rb_cv_CentOS6_CXX_workaround, RUBY_WERROR_FLAG([ AC_LANG_PUSH([C++]) @@ -1657,6 +1743,18 @@ AS_IF([test "$GCC" = yes], [ [rb_cv_gcc_atomic_builtins=no])]) AS_IF([test "$rb_cv_gcc_atomic_builtins" = yes], [ AC_DEFINE(HAVE_GCC_ATOMIC_BUILTINS) + AC_CACHE_CHECK([for 64bit __atomic builtins], [rb_cv_gcc_atomic_builtins_64], [ + AC_LINK_IFELSE([AC_LANG_PROGRAM([[@%:@include + uint64_t atomic_var;]], + [[ + __atomic_load_n(&atomic_var, __ATOMIC_RELAXED); + __atomic_store_n(&atomic_var, 0, __ATOMIC_RELAXED); + ]])], + [rb_cv_gcc_atomic_builtins_64=yes], + [rb_cv_gcc_atomic_builtins_64=no])]) + AS_IF([test "$rb_cv_gcc_atomic_builtins_64" = yes], [ + AC_DEFINE(HAVE_GCC_ATOMIC_BUILTINS_64) + ]) ]) AC_CACHE_CHECK([for __sync builtins], [rb_cv_gcc_sync_builtins], [ @@ -1703,7 +1801,7 @@ AS_IF([test "$GCC" = yes], [ AC_CACHE_CHECK(for exported function attribute, rb_cv_func_exported, [ rb_cv_func_exported=no RUBY_WERROR_FLAG([ -for mac in '__attribute__ ((__visibility__("default")))' '__declspec(dllexport)'; do +for mac in '__declspec(dllexport)' '__attribute__ ((__visibility__("default")))'; do AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[@%:@define RUBY_FUNC_EXPORTED $mac extern RUBY_FUNC_EXPORTED void conftest_attribute_check(void);]], [[]])], [rb_cv_func_exported="$mac"; break]) @@ -1729,7 +1827,7 @@ AC_CACHE_CHECK(for function name string predefined identifier, [AS_CASE(["$target_os"],[openbsd*],[ rb_cv_function_name_string=__func__ ],[ - rb_cv_function_name_string=no + rb_cv_function_name_string=no RUBY_WERROR_FLAG([ for func in __func__ __FUNCTION__; do AC_LINK_IFELSE([AC_LANG_PROGRAM([[@%:@include ]], @@ -1737,7 +1835,8 @@ AC_CACHE_CHECK(for function name string predefined identifier, [rb_cv_function_name_string=$func break]) done - ])])] + ]) + ])] ) AS_IF([test "$rb_cv_function_name_string" != no], [ AC_DEFINE_UNQUOTED(RUBY_FUNCTION_NAME_STRING, [$rb_cv_function_name_string]) @@ -1997,6 +2096,7 @@ AC_CHECK_FUNCS(_longjmp) # used for AC_ARG_WITH(setjmp-type) test x$ac_cv_func__longjmp = xno && ac_cv_func__setjmp=no AC_CHECK_FUNCS(arc4random_buf) AC_CHECK_FUNCS(atan2l atan2f) +AC_CHECK_DECLS(atomic_signal_fence, [], [], [@%:@include ]) AC_CHECK_FUNCS(chmod) AC_CHECK_FUNCS(chown) AC_CHECK_FUNCS(chroot) @@ -2061,7 +2161,6 @@ AC_CHECK_FUNCS(gettimeofday) # for making ac_cv_func_gettimeofday AC_CHECK_FUNCS(getuid) AC_CHECK_FUNCS(getuidx) AC_CHECK_FUNCS(gmtime_r) -AC_CHECK_FUNCS(grantpt) AC_CHECK_FUNCS(initgroups) AC_CHECK_FUNCS(ioctl) AC_CHECK_FUNCS(isfinite) @@ -2078,6 +2177,7 @@ AC_CHECK_FUNCS(lstat) AC_CHECK_FUNCS(lutimes) AC_CHECK_FUNCS(malloc_usable_size) AC_CHECK_FUNCS(malloc_size) +AC_CHECK_FUNCS(malloc_trim) AC_CHECK_FUNCS(mblen) AC_CHECK_FUNCS(memalign) AC_CHECK_FUNCS(memset_s) @@ -2205,10 +2305,6 @@ RUBY_CHECK_BUILTIN_FUNC(__builtin_clzl, [__builtin_clzl(0)]) RUBY_CHECK_BUILTIN_FUNC(__builtin_clzll, [__builtin_clzll(0)]) RUBY_CHECK_BUILTIN_FUNC(__builtin_ctz, [__builtin_ctz(0)]) RUBY_CHECK_BUILTIN_FUNC(__builtin_ctzll, [__builtin_ctzll(0)]) -RUBY_CHECK_BUILTIN_FUNC(__builtin_add_overflow, [int x;__builtin_add_overflow(0,0,&x)]) -RUBY_CHECK_BUILTIN_FUNC(__builtin_sub_overflow, [int x;__builtin_sub_overflow(0,0,&x)]) -RUBY_CHECK_BUILTIN_FUNC(__builtin_mul_overflow, [int x;__builtin_mul_overflow(0,0,&x)]) -RUBY_CHECK_BUILTIN_FUNC(__builtin_mul_overflow_p, [__builtin_mul_overflow_p(0,0,(int)0)]) RUBY_CHECK_BUILTIN_FUNC(__builtin_constant_p, [__builtin_constant_p(0)]) RUBY_CHECK_BUILTIN_FUNC(__builtin_choose_expr, [ [int x[__extension__(__builtin_choose_expr(1, 1, -1))]]; @@ -2224,26 +2320,9 @@ RUBY_CHECK_BUILTIN_FUNC(__builtin_types_compatible_p, [__builtin_types_compatibl RUBY_CHECK_BUILTIN_FUNC(__builtin_trap, [__builtin_trap()]) RUBY_CHECK_BUILTIN_FUNC(__builtin_expect, [__builtin_expect(0, 0)]) -AS_IF([test "$rb_cv_builtin___builtin_mul_overflow" != no], [ - AC_CACHE_CHECK(for __builtin_mul_overflow with long long arguments, rb_cv_use___builtin_mul_overflow_long_long, [ - AC_LINK_IFELSE([AC_LANG_SOURCE([[ -#pragma clang optimize off - -int -main(void) -{ - long long x = 0, y; - __builtin_mul_overflow(x, x, &y); - - return 0; -} -]])], - rb_cv_use___builtin_mul_overflow_long_long=yes, - rb_cv_use___builtin_mul_overflow_long_long=no)]) -]) -AS_IF([test "$rb_cv_use___builtin_mul_overflow_long_long" = yes], [ - AC_DEFINE(USE___BUILTIN_MUL_OVERFLOW_LONG_LONG, 1) -]) +RUBY_CHECK_BUILTIN_OVERFLOW(add) +RUBY_CHECK_BUILTIN_OVERFLOW(sub) +RUBY_CHECK_BUILTIN_OVERFLOW(mul) AS_IF([test "$ac_cv_func_qsort_r" != no], [ AC_CACHE_CHECK(whether qsort_r is GNU version, rb_cv_gnu_qsort_r, @@ -2632,6 +2711,9 @@ AS_CASE([$coroutine_type], [yes|''], [ [*86-mingw*], [ coroutine_type=win32 ], + [aarch64-mingw*], [ + coroutine_type=arm64 + ], [arm*-linux*], [ coroutine_type=arm32 ], @@ -2656,6 +2738,12 @@ AS_CASE([$coroutine_type], [yes|''], [ [aarch64-freebsd*], [ coroutine_type=arm64 ], + [powerpc64-freebsd*], [ + coroutine_type=ppc64le + ], + [powerpc64le-freebsd*], [ + coroutine_type=ppc64le + ], [x86_64-netbsd*], [ coroutine_type=amd64 ], @@ -2674,6 +2762,9 @@ AS_CASE([$coroutine_type], [yes|''], [ [aarch64-openbsd*], [ coroutine_type=arm64 ], + [riscv64-openbsd*], [ + coroutine_type=riscv64 + ], [*-openbsd*], [ coroutine_type=pthread ], @@ -2772,7 +2863,7 @@ AS_IF([test "$THREAD_MODEL" = pthread], [ ]) ]) - AC_CACHE_CHECK([for thread-local storage sepcifier], [rb_cv_tls_specifier], + AC_CACHE_CHECK([for thread-local storage specifier], [rb_cv_tls_specifier], rb_cv_tls_specifier=none RUBY_WERROR_FLAG([ for attr in \ @@ -2931,7 +3022,7 @@ AS_IF([test "x$ac_cv_func_ioctl" = xyes], [ } [begin]_group "runtime section" && { -dnl wheather use dln_a_out or not +dnl whether use dln_a_out or not AC_ARG_WITH(dln-a-out, AS_HELP_STRING([--with-dln-a-out], [dln_a_out is deprecated]), [ @@ -3079,7 +3170,7 @@ AC_SUBST(EXTOBJS) [darwin*], [ : ${LDSHARED='$(CC) -dynamic -bundle'} : ${DLDSHARED='$(CC) -dynamiclib'} : ${LDFLAGS=""} - : ${LIBPATHENV=DYLD_FALLBACK_LIBRARY_PATH} + : ${LIBPATHENV=DYLD_LIBRARY_PATH} : ${PRELOADENV=DYLD_INSERT_LIBRARIES} AS_IF([test x"$enable_shared" = xyes], [ # Resolve symbols from libruby.dylib in $(LIBS) when --enable-shared @@ -3118,6 +3209,7 @@ AC_SUBST(EXTOBJS) [hiuxmpp], [ : ${LDSHARED='$(LD) -r'}], [atheos*], [ : ${LDSHARED='$(CC) -shared'} rb_cv_dlopen=yes], + [wasi*], [ : ${LDSHARED='$(LD) -shared -Xlinker --export-dynamic'}], [ : ${LDSHARED='$(LD)'}]) AC_MSG_RESULT($rb_cv_dlopen) } @@ -3282,7 +3374,6 @@ AS_IF([test x$with_valgrind != xno], DLEXT=so]) : ${SOEXT="${DLEXT}"} AC_SUBST(SOEXT) -} AS_IF([test "$rb_cv_dlopen:$load_relative" = yes:yes], [ AS_IF([test "$ac_cv_func_dladdr" = yes], [ @@ -3301,6 +3392,9 @@ AC_DEFINE_UNQUOTED(DLEXT_MAXLEN, `expr $len + 1`) test ".$DLEXT" = "." || AC_DEFINE_UNQUOTED(DLEXT, ".$DLEXT") AC_SUBST(DLEXT) +AC_DEFINE_UNQUOTED(SOEXT, ".$SOEXT") +} + : "strip" && { AC_MSG_CHECKING([for $STRIP flags]) AC_LINK_IFELSE([AC_LANG_PROGRAM], [AS_IF( @@ -3373,7 +3467,7 @@ done BTESTRUBY='$(MINIRUBY)' AS_IF([test x"$cross_compiling" = xyes], [ - test x"$MINIRUBY" = x && MINIRUBY="${RUBY-$BASERUBY} -I`$CHDIR .; pwd` "-r'$(arch)-fake' + test x"$MINIRUBY" = x && MINIRUBY="${RUBY-$BASERUBY} -I${ac_abs_builddir-.} "-r'$(arch)-fake' XRUBY_LIBDIR=`${RUBY-$BASERUBY} -rrbconfig -e ['puts RbConfig::CONFIG["libdir"]']` XRUBY_RUBYLIBDIR=`${RUBY-$BASERUBY} -rrbconfig -e ['puts RbConfig::CONFIG["rubylibdir"]']` XRUBY_RUBYHDRDIR=`${RUBY-$BASERUBY} -rrbconfig -e ['puts RbConfig::CONFIG["rubyhdrdir"]']` @@ -3451,7 +3545,7 @@ AC_ARG_WITH(soname, ], [mingw*], [ RUBY_SO_NAME="${rb_cv_msvcrt}"'-$(RUBY_BASE_NAME)$(MAJOR)$(MINOR)0' - AS_IF([test x"${target_cpu}" != xi386], [ + AS_IF([test x"${target_cpu}" != xi386 || test x"${rb_cv_msvcrt}" != xmsvcrt], [ RUBY_SO_NAME="${target_cpu}-${RUBY_SO_NAME}" ]) ], @@ -3508,6 +3602,7 @@ AS_CASE("$enable_shared", [yes], [ ]) ]) + relative_libprefix="/../${multiarch+../}${libdir_basename}" AS_CASE(["$target_os"], [sunos4*], [ LIBRUBY_ALIASES='$(LIBRUBY_SONAME) lib$(RUBY_SO_NAME).$(SOEXT)' @@ -3516,7 +3611,7 @@ AS_CASE("$enable_shared", [yes], [ RUBY_APPEND_OPTIONS(LIBRUBY_DLDFLAGS, ['-Wl,-soname,$(LIBRUBY_SONAME)' "$LDFLAGS_OPTDIR"]) LIBRUBY_ALIASES='$(LIBRUBY_SONAME) lib$(RUBY_SO_NAME).$(SOEXT)' AS_IF([test "$load_relative" = yes], [ - libprefix="'\$\${ORIGIN}/../${libdir_basename}'" + libprefix="'\$\${ORIGIN}${relative_libprefix}'" LIBRUBY_RPATHFLAGS="-Wl,-rpath,${libprefix}" LIBRUBY_RELATIVE=yes ]) @@ -3528,7 +3623,7 @@ AS_CASE("$enable_shared", [yes], [ LIBRUBY_SO="$LIBRUBY_SO.\$(TEENY)" LIBRUBY_ALIASES='' ], [test "$load_relative" = yes], [ - libprefix="'\$\$ORIGIN/../${libdir_basename}'" + libprefix="'\$\$ORIGIN${relative_libprefix}'" LIBRUBY_RPATHFLAGS="-Wl,-rpath,${libprefix}" LIBRUBY_RELATIVE=yes ]) @@ -3552,7 +3647,7 @@ AS_CASE("$enable_shared", [yes], [ LIBRUBY_ALIASES='$(LIBRUBY_SONAME) lib$(RUBY_SO_NAME).$(SOEXT)' RUBY_APPEND_OPTIONS(LIBRUBY_DLDFLAGS, ["${linker_flag}-h${linker_flag:+,}"'$(@F)']) AS_IF([test "$load_relative" = yes], [ - libprefix="'\$\$ORIGIN/../${libdir_basename}'" + libprefix="'\$\$ORIGIN${relative_libprefix}'" LIBRUBY_RPATHFLAGS="-R${libprefix}" LIBRUBY_RELATIVE=yes ], [ @@ -3569,7 +3664,7 @@ AS_CASE("$enable_shared", [yes], [ LIBRUBY_SONAME='$(LIBRUBY_SO)' LIBRUBY_ALIASES='lib$(RUBY_INSTALL_NAME).$(SOEXT)' AS_IF([test "$load_relative" = yes], [ - libprefix="@executable_path/../${libdir_basename}" + libprefix="@executable_path${relative_libprefix}" LIBRUBY_RELATIVE=yes ]) LIBRUBY_DLDFLAGS="$LIBRUBY_DLDFLAGS -install_name ${libprefix}"'/$(LIBRUBY_SONAME)' @@ -3617,16 +3712,16 @@ AS_CASE("$enable_shared", [yes], [ ]) ]) AS_IF([test "$enable_rpath" = yes], [ - test -z "$LIBRUBY_RPATHFLAGS" || LIBRUBY_RPATHFLAGS="$LIBRUBY_RPATHFLAGS " - rpathflag="${RPATHFLAG}" - AS_CASE(["${cross_compiling}${load_relative}"], [*yes*], [], [rpathflag="$RPATHFLAG$LIBPATHFLAG"]) + AS_CASE(["${cross_compiling}${load_relative}"], + [*yes*], [rpathflag="${RPATHFLAG}"], + [rpathflag="$RPATHFLAG${LIBPATHFLAG:+${RPATHFLAG:+ }$LIBPATHFLAG}"]) rpathflag=`IFS="$PATH_SEPARATOR" echo x "$rpathflag" | sed "s/^x *//;s${IFS}"'%1\\$-s'"${IFS}${libprefix}${IFS}g;s${IFS}%s${IFS}${libprefix}${IFS}g" ` - LIBRUBY_RPATHFLAGS="$LIBRUBY_RPATHFLAGS${rpathflag}" - LIBRUBYARG_SHARED="$LIBRUBY_RPATHFLAGS $LIBRUBYARG_SHARED" - LIBRUBYARG_STATIC="$LIBRUBY_RPATHFLAGS $LIBRUBYARG_STATIC" + LIBRUBY_RPATHFLAGS="${LIBRUBY_RPATHFLAGS:+$LIBRUBY_RPATHFLAGS }${rpathflag}" + LIBRUBYARG_SHARED="${LIBRUBY_RPATHFLAGS:+$LIBRUBY_RPATHFLAGS }$LIBRUBYARG_SHARED" + LIBRUBYARG_STATIC="${LIBRUBY_RPATHFLAGS:+$LIBRUBY_RPATHFLAGS }$LIBRUBYARG_STATIC" ]) AC_SUBST(LIBRUBY_RELATIVE) @@ -3703,11 +3798,12 @@ AC_ARG_ENABLE(gcov, AS_HELP_STRING([--enable-gcov], [enable coverage measurement by gcov]), [gcov=yes]) AS_IF([test x"$gcov" = xyes], [ - CFLAGS="$CFLAGS -coverage" + CFLAGS="$CFLAGS -coverage -fprofile-update=atomic" LDFLAGS="$LDFLAGS -coverage" ]) RUBY_SETJMP_TYPE +RUBY_MODULAR_GC } [begin]_group "installation section" && { @@ -3773,51 +3869,64 @@ AC_SUBST(INSTALL_STATIC_LIBRARY) [begin]_group "JIT section" && { AC_CHECK_PROG(RUSTC, [rustc], [rustc], [no]) dnl no ac_tool_prefix -dnl check if rustc is recent enough to build YJIT (rustc >= 1.58.0) -YJIT_RUSTC_OK=no +dnl check if rustc is recent enough to build YJIT/ZJIT (rustc >= 1.58.0) +JIT_RUSTC_OK=no AS_IF([test "$RUSTC" != "no"], - AC_MSG_CHECKING([whether ${RUSTC} works for YJIT]) - YJIT_TARGET_ARCH= + AC_MSG_CHECKING([whether ${RUSTC} works for YJIT/ZJIT]) + JIT_TARGET_ARCH= AS_CASE(["$target_cpu"], - [arm64|aarch64], [YJIT_TARGET_ARCH=aarch64], - [x86_64], [YJIT_TARGET_ARCH=x86_64], + [arm64|aarch64], [JIT_TARGET_ARCH=aarch64], + [x86_64], [JIT_TARGET_ARCH=x86_64], ) dnl Fails in case rustc target doesn't match ruby target. dnl Can happen on Rosetta, for example. - AS_IF([echo "#[cfg(target_arch = \"$YJIT_TARGET_ARCH\")] fn main() { let x = 1; format!(\"{x}\"); }" | + AS_IF([echo "#[cfg(target_arch = \"$JIT_TARGET_ARCH\")] fn main() { let x = 1; format!(\"{x}\"); }" | $RUSTC - --emit asm=/dev/null 2>/dev/null], - [YJIT_RUSTC_OK=yes] + [JIT_RUSTC_OK=yes] ) - AC_MSG_RESULT($YJIT_RUSTC_OK) + AC_MSG_RESULT($JIT_RUSTC_OK) ) -dnl check if we can build YJIT on this target platform +dnl check if we can build YJIT/ZJIT on this target platform dnl we can't easily cross-compile with rustc so we don't support that -YJIT_TARGET_OK=no +JIT_TARGET_OK=no AS_IF([test "$cross_compiling" = no], AS_CASE(["$target_cpu-$target_os"], [*android*], [ - YJIT_TARGET_OK=no + JIT_TARGET_OK=no ], [arm64-darwin*|aarch64-darwin*|x86_64-darwin*], [ - YJIT_TARGET_OK=yes + JIT_TARGET_OK=yes ], [arm64-*linux*|aarch64-*linux*|x86_64-*linux*], [ - YJIT_TARGET_OK=yes + JIT_TARGET_OK=yes ], [arm64-*bsd*|aarch64-*bsd*|x86_64-*bsd*], [ - YJIT_TARGET_OK=yes + JIT_TARGET_OK=yes ] ) ) +dnl build ZJIT in release mode if rustc >= 1.58.0 is present and we are on a supported platform +AC_ARG_ENABLE(zjit, + AS_HELP_STRING([--enable-zjit], + [enable in-process JIT compiler that requires Rust build tools. enabled by default on supported platforms if rustc 1.58.0+ is available]), + [ZJIT_SUPPORT=$enableval], + [AS_CASE(["$JIT_TARGET_OK:$JIT_RUSTC_OK:$YJIT_SUPPORT"], + [yes:yes:no], [ + ZJIT_SUPPORT=yes + ], + [ZJIT_SUPPORT=no] + )] +) + dnl build YJIT in release mode if rustc >= 1.58.0 is present and we are on a supported platform AC_ARG_ENABLE(yjit, AS_HELP_STRING([--enable-yjit], [enable in-process JIT compiler that requires Rust build tools. enabled by default on supported platforms if rustc 1.58.0+ is available]), [YJIT_SUPPORT=$enableval], - [AS_CASE(["$YJIT_TARGET_OK:$YJIT_RUSTC_OK"], - [yes:yes], [ + [AS_CASE(["$JIT_TARGET_OK:$JIT_RUSTC_OK:$ZJIT_SUPPORT"], + [yes:yes:no], [ YJIT_SUPPORT=yes ], [YJIT_SUPPORT=no] @@ -3827,6 +3936,7 @@ AC_ARG_ENABLE(yjit, CARGO= CARGO_BUILD_ARGS= YJIT_LIBS= +JIT_CARGO_SUPPORT=no AS_CASE(["${YJIT_SUPPORT}"], [yes|dev|stats|dev_nodebug], [ AS_IF([test x"$RUSTC" = "xno"], @@ -3835,36 +3945,26 @@ AS_CASE(["${YJIT_SUPPORT}"], AS_CASE(["${YJIT_SUPPORT}"], [yes], [ - rb_rust_target_subdir=release ], [dev], [ - rb_rust_target_subdir=debug - CARGO_BUILD_ARGS='--features stats,disasm' + rb_cargo_features='disasm,runtime_checks' + JIT_CARGO_SUPPORT=dev AC_DEFINE(RUBY_DEBUG, 1) ], [dev_nodebug], [ - rb_rust_target_subdir=dev_nodebug - CARGO_BUILD_ARGS='--profile dev_nodebug --features stats,disasm' + rb_cargo_features='disasm' + JIT_CARGO_SUPPORT=dev_nodebug AC_DEFINE(YJIT_STATS, 1) ], [stats], [ - rb_rust_target_subdir=stats - CARGO_BUILD_ARGS='--profile stats --features stats' + JIT_CARGO_SUPPORT=stats AC_DEFINE(YJIT_STATS, 1) ]) - AS_IF([test -n "${CARGO_BUILD_ARGS}"], [ - AC_CHECK_TOOL(CARGO, [cargo], [no]) - AS_IF([test x"$CARGO" = "xno"], - AC_MSG_ERROR([cargo is required. Installation instructions available at https://www.rust-lang.org/tools/install]) - ])) - - YJIT_LIBS="yjit/target/${rb_rust_target_subdir}/libyjit.a" - AS_CASE(["$target_os"],[openbsd*],[ - # Link libc++abi (which requires libpthread) for _Unwind_* functions needed by yjit - LDFLAGS="$LDFLAGS -lpthread -lc++abi" - ]) + YJIT_LIBS="target/release/libyjit.a" + RUST_LIB='$(YJIT_LIBS)' YJIT_OBJ='yjit.$(OBJEXT)' + JIT_OBJ='jit.$(OBJEXT)' AS_IF([test x"$YJIT_SUPPORT" != "xyes" ], [ AC_DEFINE_UNQUOTED(YJIT_SUPPORT, [$YJIT_SUPPORT]) ]) @@ -3873,65 +3973,89 @@ AS_CASE(["${YJIT_SUPPORT}"], AC_DEFINE(USE_YJIT, 0) ]) -dnl These variables end up in ::RbConfig::CONFIG -AC_SUBST(YJIT_SUPPORT)dnl what flavor of YJIT the Ruby build includes -AC_SUBST(RUSTC)dnl Rust compiler command -AC_SUBST(CARGO)dnl Cargo command for Rust builds -AC_SUBST(CARGO_BUILD_ARGS)dnl for selecting Rust build profiles -AC_SUBST(YJIT_LIBS)dnl for optionally building the Rust parts of YJIT -AC_SUBST(YJIT_OBJ)dnl for optionally building the C parts of YJIT - -dnl Currently, RJIT only supports Unix x86_64 platforms. -RJIT_TARGET_OK=no -AS_IF([test "$cross_compiling" = no], - AS_CASE(["$target_cpu-$target_os"], - [*android*], [ - RJIT_TARGET_OK=no - ], - [x86_64-darwin*], [ - RJIT_TARGET_OK=yes - ], - [x86_64-*linux*], [ - RJIT_TARGET_OK=yes - ], - [x86_64-*bsd*], [ - RJIT_TARGET_OK=yes - ] +ZJIT_LIBS= +AS_CASE(["${ZJIT_SUPPORT}"], +[yes|dev|dev_nodebug], [ + AS_IF([test x"$RUSTC" = "xno"], + AC_MSG_ERROR([rustc is required. Installation instructions available at https://www.rust-lang.org/tools/install]) ) -) - -dnl Build RJIT on Unix x86_64 platforms or if --enable-rjit is specified. -AC_ARG_ENABLE(rjit, - AS_HELP_STRING([--enable-rjit], - [enable pure-Ruby JIT compiler. enabled by default on Unix x86_64 platforms]), - [RJIT_SUPPORT=$enableval], - [AS_CASE(["$YJIT_TARGET_OK"], - [yes], [RJIT_SUPPORT=yes], - [RJIT_SUPPORT=no] - )] -) -AS_CASE(["$RJIT_SUPPORT"], -[yes|dev|disasm], [ - AS_CASE(["$RJIT_SUPPORT"], + AS_CASE(["${ZJIT_SUPPORT}"], + [yes], [ + ], [dev], [ - # Link libcapstone for --rjit-dump-disasm - AC_CHECK_LIB([capstone], [cs_disasm]) - - # Enable extra stats (vm_insns_count, ratio_in_rjit) - AC_DEFINE(RJIT_STATS, 1) + rb_cargo_features="$rb_cargo_features,disasm" + JIT_CARGO_SUPPORT=dev + AC_DEFINE(RUBY_DEBUG, 1) ], - [disasm], [ - # Link libcapstone for --rjit-dump-disasm - AC_CHECK_LIB([capstone], [cs_disasm]) + [dev_nodebug], [ + rb_cargo_features="$rb_cargo_features,disasm" + JIT_CARGO_SUPPORT=dev_nodebug ]) - AC_DEFINE(USE_RJIT, 1) + ZJIT_LIBS="target/release/libzjit.a" + RUST_LIB='$(ZJIT_LIBS)' + ZJIT_OBJ='zjit.$(OBJEXT)' + JIT_OBJ='jit.$(OBJEXT)' + AS_IF([test x"$ZJIT_SUPPORT" != "xyes" ], [ + AC_DEFINE_UNQUOTED(ZJIT_SUPPORT, [$ZJIT_SUPPORT]) + ]) + AC_DEFINE(USE_ZJIT, 1) ], [ - AC_DEFINE(USE_RJIT, 0) + AC_DEFINE(USE_ZJIT, 0) ]) -AC_SUBST(RJIT_SUPPORT) +# if YJIT+ZJIT release build, or any build that requires Cargo +AS_IF([test x"$JIT_CARGO_SUPPORT" != "xno" -o \( x"$YJIT_SUPPORT" != "xno" -a x"$ZJIT_SUPPORT" != "xno" \)], [ + AC_CHECK_TOOL(CARGO, [cargo], [no]) + AS_IF([test x"$CARGO" = "xno"], + AC_MSG_ERROR([cargo is required. Installation instructions available at https://www.rust-lang.org/tools/install])) + + YJIT_LIBS= + ZJIT_LIBS= + + AS_IF([test x"${YJIT_SUPPORT}" != x"no"], [ + rb_cargo_features="$rb_cargo_features,yjit" + ]) + AS_IF([test x"${ZJIT_SUPPORT}" != x"no"], [ + rb_cargo_features="$rb_cargo_features,zjit" + ]) + # if YJIT and ZJIT release mode + AS_IF([test "${YJIT_SUPPORT}:${ZJIT_SUPPORT}" = "yes:yes"], [ + JIT_CARGO_SUPPORT=release + ]) + CARGO_BUILD_ARGS="--profile ${JIT_CARGO_SUPPORT} --features ${rb_cargo_features}" + AS_IF([test "${JIT_CARGO_SUPPORT}" = "dev"], [ + RUST_LIB="target/debug/libjit.a" + ], [ + RUST_LIB="target/${JIT_CARGO_SUPPORT}/libjit.a" + ]) +]) + +# In case either we're linking rust code +AS_IF([test -n "$RUST_LIB"], [ + AS_CASE(["$target_os"],[openbsd*],[ + # Link libc++abi (which requires libpthread) for _Unwind_* functions needed by rust stdlib + LDFLAGS="$LDFLAGS -lpthread -lc++abi" + ]) + + # absolute path to stop the "target" dir in src dir from interfering through VPATH + RUST_LIB="$(pwd)/${RUST_LIB}" +]) + +dnl These variables end up in ::RbConfig::CONFIG +AC_SUBST(RUSTC)dnl Rust compiler command +AC_SUBST(CARGO)dnl Cargo command for Rust builds +AC_SUBST(CARGO_BUILD_ARGS)dnl for selecting Rust build profiles +AC_SUBST(YJIT_SUPPORT)dnl what flavor of YJIT the Ruby build includes +AC_SUBST(YJIT_LIBS)dnl the .a library of YJIT +AC_SUBST(YJIT_OBJ)dnl for optionally building the C parts of YJIT +AC_SUBST(ZJIT_SUPPORT)dnl what flavor of ZJIT the Ruby build includes +AC_SUBST(ZJIT_LIBS)dnl path to the .a library of ZJIT +AC_SUBST(ZJIT_OBJ)dnl for optionally building the C parts of ZJIT +AC_SUBST(JIT_OBJ)dnl for optionally building C glue code for Rust FFI +AC_SUBST(RUST_LIB)dnl path to the rust .a library that contains either or both JITs +AC_SUBST(JIT_CARGO_SUPPORT)dnl "no" or the cargo profile of the rust code } [begin]_group "build section" && { @@ -3945,6 +4069,25 @@ AC_CACHE_CHECK([for prefix of external symbols], rb_cv_symbol_prefix, [ ]) SYMBOL_PREFIX="$rb_cv_symbol_prefix" test "x$SYMBOL_PREFIX" = xNONE && SYMBOL_PREFIX='' + +AS_IF([test x"$SOEXT" = xdll], [ + # DLL on Windows is managed by win32/mkexports.rb +], [test x"$enable_shared" = xyes], [ + AC_CACHE_CHECK([for default symbols in empty shared library], rb_cv_symbols_in_emptylib, [ + save_CC="$CC" + eval CC=\"`printf "%s" "${DLDSHARED}" | sed ['s/\$(CC)/${CC}/']`\" + AC_LINK_IFELSE([AC_LANG_PROGRAM()],[ + rb_cv_symbols_in_emptylib=`$NM -Pgp conftest$ac_exeext | + sed ["/ [A-TV-Z] .*/!d;s///;s/^${SYMBOL_PREFIX}//;/^main$/d"]` + ]) + set dummy ${rb_cv_symbols_in_emptylib} + shift + rb_cv_symbols_in_emptylib="$*" + CC="$save_CC" + ]) +]) +AC_SUBST(XSYMBOLS_IN_EMPTYLIB, "${rb_cv_symbols_in_emptylib}") + DLNOBJ=dln.o AC_ARG_ENABLE(dln, AS_HELP_STRING([--disable-dln], [disable dynamic link feature]), @@ -3959,7 +4102,8 @@ AS_CASE(["$target_os"], RUBY_APPEND_OPTION(CFLAGS, -pipe) ], [darwin*], [ - RUBY_APPEND_OPTION(CFLAGS, -pipe) + RUBY_TRY_CFLAGS(-pipe, [pipe_opt=yes], [pipe_opt=no]) + AS_IF([test $pipe_opt = yes], [RUBY_APPEND_OPTION(CFLAGS, -pipe)]) AC_MSG_CHECKING([whether Security framework is needed]) AC_COMPILE_IFELSE([ AC_LANG_BOOL_COMPILE_TRY([ @@ -4012,6 +4156,7 @@ enum { [mingw*], [ AS_IF([test x"$enable_shared" = xyes], [ LIBRUBY_SO='$(RUBY_SO_NAME)'.dll + LIBRUBY_SONAME='' LIBRUBY_DLDFLAGS="${LIBRUBY_DLDFLAGS}"' $(RUBYDEF)' ]) EXPORT_PREFIX=' ' @@ -4152,12 +4297,13 @@ AS_IF([test "${ARCH_FLAG}"], [ rb_cv_warnflags=`echo "$rb_cv_warnflags" | sed 's/^ *//;s/ *$//'` warnflags="$rb_cv_warnflags" AC_SUBST(cppflags)dnl -AC_SUBST(cflags, ["${orig_cflags:+$orig_cflags }"'${optflags} ${debugflags} ${warnflags}'])dnl +AC_SUBST(cflags, ['${hardenflags} '"${orig_cflags:+$orig_cflags }"' ${optflags} ${debugflags} ${warnflags}'])dnl AC_SUBST(cxxflags)dnl AC_SUBST(optflags)dnl AC_SUBST(debugflags)dnl AC_SUBST(warnflags)dnl AC_SUBST(strict_warnflags)dnl +AC_SUBST(hardenflags)dnl AC_SUBST(XCFLAGS)dnl AC_SUBST(XLDFLAGS)dnl AC_SUBST(EXTLDFLAGS)dnl @@ -4190,6 +4336,7 @@ AC_SUBST(MINIOBJS) AC_SUBST(THREAD_MODEL) AC_SUBST(COROUTINE_TYPE, ${coroutine_type}) AC_SUBST(PLATFORM_DIR) +AC_SUBST(USE_LLVM_WINDRES) firstmf=`echo $FIRSTMAKEFILE | sed 's/:.*//'` firsttmpl=`echo $FIRSTMAKEFILE | sed 's/.*://'` @@ -4341,6 +4488,10 @@ AS_IF([test "${universal_binary-no}" = yes ], [ arch="${target_cpu}-${target_os}" ]) AC_DEFINE_UNQUOTED(RUBY_PLATFORM, "$arch") + + AS_IF([test "$arch" = "s390x-linux"], [ + AC_DEFINE_UNQUOTED(USE_MN_THREADS, 0) + ]) ]) unset sitearch @@ -4438,6 +4589,17 @@ AS_IF([test x"$enable_rubygems" = xno], [ ]) AC_SUBST(USE_RUBYGEMS) +m4_define(available_parsers, [parse.y, prism]) +AC_ARG_WITH(parser, + AS_HELP_STRING([--with-parser=PARSER], + [specify default parser; PARSER is one of ]m4_join([, ],available_parsers)), + [], [with_parser=prism]) +AS_CASE([$with_parser], +m4_foreach(parser, [available_parsers], + parser[,][AC_DEFINE_UNQUOTED(RB_DEFAULT_PARSER, RB_DEFAULT_PARSER_[]AS_TR_CPP(parser)),]) + [AC_MSG_ERROR([Unknown parser: $with_parser])] +) + arch_hdrdir="${EXTOUT}/include/${arch}/ruby" AS_MKDIR_P("${arch_hdrdir}") config_h="${arch_hdrdir}/config.h" @@ -4445,7 +4607,7 @@ guard=INCLUDE_RUBY_CONFIG_H { echo "#ifndef $guard" echo "#define $guard 1" - grep -v "^#define PACKAGE_" confdefs.h + sed "/^@%:@define PACKAGE_/d;s/ *$//" confdefs.h echo "#endif /* $guard */" } | tr -d '\015' | ( @@ -4533,6 +4695,9 @@ AC_CONFIG_FILES(Makefile:template/Makefile.in, [ ], [ echo 'distclean-local::; @$(RM) GNUmakefile uncommon.mk' ]) + + echo; echo '$(srcdir)/$(CONFIGURE):RUBY_M4_INCLUDED \ + $(empty)' } > $tmpmk && AS_IF([! grep '^ruby:' $tmpmk > /dev/null], [ AS_IF([test "${gnumake}" = yes], [ tmpgmk=confgmk$$.tmp @@ -4599,6 +4764,7 @@ config_summary "target OS" "$target_os" config_summary "compiler" "$CC" config_summary "with thread" "$THREAD_MODEL" config_summary "with coroutine" "$coroutine_type" +config_summary "with modular GC" "$modular_gc_summary" config_summary "enable shared libs" "$ENABLE_SHARED" config_summary "dynamic library ext" "$DLEXT" config_summary "CFLAGS" "$cflags" @@ -4608,10 +4774,11 @@ config_summary "DLDFLAGS" "$DLDFLAGS" config_summary "optflags" "$optflags" config_summary "debugflags" "$debugflags" config_summary "warnflags" "$warnflags" +config_summary "hardenflags" "$hardenflags" config_summary "strip command" "$STRIP" config_summary "install doc" "$DOCTARGETS" config_summary "YJIT support" "$YJIT_SUPPORT" -config_summary "RJIT support" "$RJIT_SUPPORT" +config_summary "ZJIT support" "$ZJIT_SUPPORT" config_summary "man page type" "$MANTYPE" config_summary "search path" "$search_path" config_summary "static-linked-ext" ${EXTSTATIC:+"yes"} diff --git a/cont.c b/cont.c index db8508e724bebf..c40ed6715cbfe7 100644 --- a/cont.c +++ b/cont.c @@ -35,7 +35,6 @@ extern int madvise(caddr_t, size_t, int); #include "internal/sanitizers.h" #include "internal/warnings.h" #include "ruby/fiber/scheduler.h" -#include "rjit.h" #include "yjit.h" #include "vm_core.h" #include "vm_sync.h" @@ -71,8 +70,6 @@ static VALUE rb_cFiberPool; #define FIBER_POOL_ALLOCATION_FREE #endif -#define jit_cont_enabled (rb_rjit_enabled || rb_yjit_enabled_p()) - enum context_type { CONTINUATION_CONTEXT = 0, FIBER_CONTEXT = 1 @@ -228,7 +225,6 @@ typedef struct rb_context_struct { } machine; rb_execution_context_t saved_ec; rb_jmpbuf_t jmpbuf; - rb_ensure_entry_t *ensure_array; struct rb_jit_cont *jit_cont; // Continuation contexts for JITs } rb_context_t; @@ -277,6 +273,17 @@ struct rb_fiber_struct { static struct fiber_pool shared_fiber_pool = {NULL, NULL, 0, 0, 0, 0}; +void +rb_free_shared_fiber_pool(void) +{ + struct fiber_pool_allocation *allocations = shared_fiber_pool.allocations; + while (allocations) { + struct fiber_pool_allocation *next = allocations->next; + xfree(allocations); + allocations = next; + } +} + static ID fiber_initialize_keywords[3] = {0}; /* @@ -472,18 +479,20 @@ fiber_pool_allocate_memory(size_t * count, size_t stride) } #else errno = 0; - void * base = mmap(NULL, (*count)*stride, PROT_READ | PROT_WRITE, FIBER_STACK_FLAGS, -1, 0); + size_t mmap_size = (*count)*stride; + void * base = mmap(NULL, mmap_size, PROT_READ | PROT_WRITE, FIBER_STACK_FLAGS, -1, 0); if (base == MAP_FAILED) { // If the allocation fails, count = count / 2, and try again. *count = (*count) >> 1; } else { + ruby_annotate_mmap(base, mmap_size, "Ruby:fiber_pool_allocate_memory"); #if defined(MADV_FREE_REUSE) // On Mac MADV_FREE_REUSE is necessary for the task_info api // to keep the accounting accurate as possible when a page is marked as reusable // it can possibly not occurring at first call thus re-iterating if necessary. - while (madvise(base, (*count)*stride, MADV_FREE_REUSE) == -1 && errno == EAGAIN); + while (madvise(base, mmap_size, MADV_FREE_REUSE) == -1 && errno == EAGAIN); #endif return base; } @@ -500,80 +509,87 @@ fiber_pool_allocate_memory(size_t * count, size_t stride) static struct fiber_pool_allocation * fiber_pool_expand(struct fiber_pool * fiber_pool, size_t count) { - STACK_GROW_DIR_DETECTION; + struct fiber_pool_allocation * allocation; + RB_VM_LOCK_ENTER(); + { + STACK_GROW_DIR_DETECTION; - size_t size = fiber_pool->size; - size_t stride = size + RB_PAGE_SIZE; + size_t size = fiber_pool->size; + size_t stride = size + RB_PAGE_SIZE; - // Allocate the memory required for the stacks: - void * base = fiber_pool_allocate_memory(&count, stride); + // Allocate the memory required for the stacks: + void * base = fiber_pool_allocate_memory(&count, stride); - if (base == NULL) { - rb_raise(rb_eFiberError, "can't alloc machine stack to fiber (%"PRIuSIZE" x %"PRIuSIZE" bytes): %s", count, size, ERRNOMSG); - } + if (base == NULL) { + rb_raise(rb_eFiberError, "can't alloc machine stack to fiber (%"PRIuSIZE" x %"PRIuSIZE" bytes): %s", count, size, ERRNOMSG); + } - struct fiber_pool_vacancy * vacancies = fiber_pool->vacancies; - struct fiber_pool_allocation * allocation = RB_ALLOC(struct fiber_pool_allocation); + struct fiber_pool_vacancy * vacancies = fiber_pool->vacancies; + allocation = RB_ALLOC(struct fiber_pool_allocation); - // Initialize fiber pool allocation: - allocation->base = base; - allocation->size = size; - allocation->stride = stride; - allocation->count = count; + // Initialize fiber pool allocation: + allocation->base = base; + allocation->size = size; + allocation->stride = stride; + allocation->count = count; #ifdef FIBER_POOL_ALLOCATION_FREE - allocation->used = 0; + allocation->used = 0; #endif - allocation->pool = fiber_pool; - - if (DEBUG) { - fprintf(stderr, "fiber_pool_expand(%"PRIuSIZE"): %p, %"PRIuSIZE"/%"PRIuSIZE" x [%"PRIuSIZE":%"PRIuSIZE"]\n", - count, (void*)fiber_pool, fiber_pool->used, fiber_pool->count, size, fiber_pool->vm_stack_size); - } + allocation->pool = fiber_pool; - // Iterate over all stacks, initializing the vacancy list: - for (size_t i = 0; i < count; i += 1) { - void * base = (char*)allocation->base + (stride * i); - void * page = (char*)base + STACK_DIR_UPPER(size, 0); + if (DEBUG) { + fprintf(stderr, "fiber_pool_expand(%"PRIuSIZE"): %p, %"PRIuSIZE"/%"PRIuSIZE" x [%"PRIuSIZE":%"PRIuSIZE"]\n", + count, (void*)fiber_pool, fiber_pool->used, fiber_pool->count, size, fiber_pool->vm_stack_size); + } + // Iterate over all stacks, initializing the vacancy list: + for (size_t i = 0; i < count; i += 1) { + void * base = (char*)allocation->base + (stride * i); + void * page = (char*)base + STACK_DIR_UPPER(size, 0); #if defined(_WIN32) - DWORD old_protect; + DWORD old_protect; - if (!VirtualProtect(page, RB_PAGE_SIZE, PAGE_READWRITE | PAGE_GUARD, &old_protect)) { - VirtualFree(allocation->base, 0, MEM_RELEASE); - rb_raise(rb_eFiberError, "can't set a guard page: %s", ERRNOMSG); - } + if (!VirtualProtect(page, RB_PAGE_SIZE, PAGE_READWRITE | PAGE_GUARD, &old_protect)) { + VirtualFree(allocation->base, 0, MEM_RELEASE); + rb_raise(rb_eFiberError, "can't set a guard page: %s", ERRNOMSG); + } +#elif defined(__wasi__) + // wasi-libc's mprotect emulation doesn't support PROT_NONE. + (void)page; #else - if (mprotect(page, RB_PAGE_SIZE, PROT_NONE) < 0) { - munmap(allocation->base, count*stride); - rb_raise(rb_eFiberError, "can't set a guard page: %s", ERRNOMSG); - } + if (mprotect(page, RB_PAGE_SIZE, PROT_NONE) < 0) { + munmap(allocation->base, count*stride); + rb_raise(rb_eFiberError, "can't set a guard page: %s", ERRNOMSG); + } #endif - vacancies = fiber_pool_vacancy_initialize( - fiber_pool, vacancies, - (char*)base + STACK_DIR_UPPER(0, RB_PAGE_SIZE), - size - ); + vacancies = fiber_pool_vacancy_initialize( + fiber_pool, vacancies, + (char*)base + STACK_DIR_UPPER(0, RB_PAGE_SIZE), + size + ); #ifdef FIBER_POOL_ALLOCATION_FREE - vacancies->stack.allocation = allocation; + vacancies->stack.allocation = allocation; #endif - } + } - // Insert the allocation into the head of the pool: - allocation->next = fiber_pool->allocations; + // Insert the allocation into the head of the pool: + allocation->next = fiber_pool->allocations; #ifdef FIBER_POOL_ALLOCATION_FREE - if (allocation->next) { - allocation->next->previous = allocation; - } + if (allocation->next) { + allocation->next->previous = allocation; + } - allocation->previous = NULL; + allocation->previous = NULL; #endif - fiber_pool->allocations = allocation; - fiber_pool->vacancies = vacancies; - fiber_pool->count += count; + fiber_pool->allocations = allocation; + fiber_pool->vacancies = vacancies; + fiber_pool->count += count; + } + RB_VM_LOCK_LEAVE(); return allocation; } @@ -647,41 +663,46 @@ fiber_pool_allocation_free(struct fiber_pool_allocation * allocation) static struct fiber_pool_stack fiber_pool_stack_acquire(struct fiber_pool * fiber_pool) { - struct fiber_pool_vacancy * vacancy = fiber_pool_vacancy_pop(fiber_pool); + struct fiber_pool_vacancy * vacancy ; + RB_VM_LOCK_ENTER(); + { + vacancy = fiber_pool_vacancy_pop(fiber_pool); - if (DEBUG) fprintf(stderr, "fiber_pool_stack_acquire: %p used=%"PRIuSIZE"\n", (void*)fiber_pool->vacancies, fiber_pool->used); + if (DEBUG) fprintf(stderr, "fiber_pool_stack_acquire: %p used=%"PRIuSIZE"\n", (void*)fiber_pool->vacancies, fiber_pool->used); - if (!vacancy) { - const size_t maximum = FIBER_POOL_ALLOCATION_MAXIMUM_SIZE; - const size_t minimum = fiber_pool->initial_count; + if (!vacancy) { + const size_t maximum = FIBER_POOL_ALLOCATION_MAXIMUM_SIZE; + const size_t minimum = fiber_pool->initial_count; - size_t count = fiber_pool->count; - if (count > maximum) count = maximum; - if (count < minimum) count = minimum; + size_t count = fiber_pool->count; + if (count > maximum) count = maximum; + if (count < minimum) count = minimum; - fiber_pool_expand(fiber_pool, count); + fiber_pool_expand(fiber_pool, count); - // The free list should now contain some stacks: - VM_ASSERT(fiber_pool->vacancies); + // The free list should now contain some stacks: + VM_ASSERT(fiber_pool->vacancies); - vacancy = fiber_pool_vacancy_pop(fiber_pool); - } + vacancy = fiber_pool_vacancy_pop(fiber_pool); + } - VM_ASSERT(vacancy); - VM_ASSERT(vacancy->stack.base); + VM_ASSERT(vacancy); + VM_ASSERT(vacancy->stack.base); #if defined(COROUTINE_SANITIZE_ADDRESS) - __asan_unpoison_memory_region(fiber_pool_stack_poison_base(&vacancy->stack), fiber_pool_stack_poison_size(&vacancy->stack)); + __asan_unpoison_memory_region(fiber_pool_stack_poison_base(&vacancy->stack), fiber_pool_stack_poison_size(&vacancy->stack)); #endif - // Take the top item from the free list: - fiber_pool->used += 1; + // Take the top item from the free list: + fiber_pool->used += 1; #ifdef FIBER_POOL_ALLOCATION_FREE - vacancy->stack.allocation->used += 1; + vacancy->stack.allocation->used += 1; #endif - fiber_pool_stack_reset(&vacancy->stack); + fiber_pool_stack_reset(&vacancy->stack); + } + RB_VM_LOCK_LEAVE(); return vacancy->stack; } @@ -752,46 +773,53 @@ static void fiber_pool_stack_release(struct fiber_pool_stack * stack) { struct fiber_pool * pool = stack->pool; - struct fiber_pool_vacancy * vacancy = fiber_pool_vacancy_pointer(stack->base, stack->size); + RB_VM_LOCK_ENTER(); + { + struct fiber_pool_vacancy * vacancy = fiber_pool_vacancy_pointer(stack->base, stack->size); - if (DEBUG) fprintf(stderr, "fiber_pool_stack_release: %p used=%"PRIuSIZE"\n", stack->base, stack->pool->used); + if (DEBUG) fprintf(stderr, "fiber_pool_stack_release: %p used=%"PRIuSIZE"\n", stack->base, stack->pool->used); - // Copy the stack details into the vacancy area: - vacancy->stack = *stack; - // After this point, be careful about updating/using state in stack, since it's copied to the vacancy area. + // Copy the stack details into the vacancy area: + vacancy->stack = *stack; + // After this point, be careful about updating/using state in stack, since it's copied to the vacancy area. - // Reset the stack pointers and reserve space for the vacancy data: - fiber_pool_vacancy_reset(vacancy); + // Reset the stack pointers and reserve space for the vacancy data: + fiber_pool_vacancy_reset(vacancy); - // Push the vacancy into the vancancies list: - pool->vacancies = fiber_pool_vacancy_push(vacancy, pool->vacancies); - pool->used -= 1; + // Push the vacancy into the vancancies list: + pool->vacancies = fiber_pool_vacancy_push(vacancy, pool->vacancies); + pool->used -= 1; #ifdef FIBER_POOL_ALLOCATION_FREE - struct fiber_pool_allocation * allocation = stack->allocation; + struct fiber_pool_allocation * allocation = stack->allocation; - allocation->used -= 1; + allocation->used -= 1; - // Release address space and/or dirty memory: - if (allocation->used == 0) { - fiber_pool_allocation_free(allocation); - } - else if (stack->pool->free_stacks) { - fiber_pool_stack_free(&vacancy->stack); - } + // Release address space and/or dirty memory: + if (allocation->used == 0) { + fiber_pool_allocation_free(allocation); + } + else if (stack->pool->free_stacks) { + fiber_pool_stack_free(&vacancy->stack); + } #else - // This is entirely optional, but clears the dirty flag from the stack - // memory, so it won't get swapped to disk when there is memory pressure: - if (stack->pool->free_stacks) { - fiber_pool_stack_free(&vacancy->stack); - } + // This is entirely optional, but clears the dirty flag from the stack + // memory, so it won't get swapped to disk when there is memory pressure: + if (stack->pool->free_stacks) { + fiber_pool_stack_free(&vacancy->stack); + } #endif + } + RB_VM_LOCK_LEAVE(); } static inline void ec_switch(rb_thread_t *th, rb_fiber_t *fiber) { rb_execution_context_t *ec = &fiber->cont.saved_ec; +#ifdef RUBY_ASAN_ENABLED + ec->machine.asan_fake_stack_handle = asan_get_thread_fake_stack_handle(); +#endif rb_ractor_set_current_ec(th->ractor, th->ec = ec); // ruby_current_execution_context_ptr = th->ec = ec; @@ -814,6 +842,10 @@ fiber_restore_thread(rb_thread_t *th, rb_fiber_t *fiber) VM_ASSERT(th->ec->fiber_ptr == fiber); } +#ifndef COROUTINE_DECL +# define COROUTINE_DECL COROUTINE +#endif +NORETURN(static COROUTINE_DECL fiber_entry(struct coroutine_context * from, struct coroutine_context * to)); static COROUTINE fiber_entry(struct coroutine_context * from, struct coroutine_context * to) { @@ -1019,13 +1051,8 @@ cont_mark(void *ptr) cont->machine.stack + cont->machine.stack_size); } else { - /* fiber */ - const rb_fiber_t *fiber = (rb_fiber_t*)cont; - - if (!FIBER_TERMINATED_P(fiber)) { - rb_gc_mark_locations(cont->machine.stack, - cont->machine.stack + cont->machine.stack_size); - } + /* fiber machine context is marked as part of rb_execution_context_mark, no need to + * do anything here. */ } } @@ -1051,7 +1078,6 @@ cont_free(void *ptr) if (cont->type == CONTINUATION_CONTEXT) { ruby_xfree(cont->saved_ec.vm_stack); - ruby_xfree(cont->ensure_array); RUBY_FREE_UNLESS_NULL(cont->machine.stack); } else { @@ -1062,10 +1088,8 @@ cont_free(void *ptr) RUBY_FREE_UNLESS_NULL(cont->saved_vm_stack.ptr); - if (jit_cont_enabled) { - VM_ASSERT(cont->jit_cont != NULL); - jit_cont_free(cont->jit_cont); - } + VM_ASSERT(cont->jit_cont != NULL); + jit_cont_free(cont->jit_cont); /* free rb_cont_t or rb_fiber_t */ ruby_xfree(ptr); RUBY_FREE_LEAVE("cont"); @@ -1294,26 +1318,42 @@ rb_jit_cont_each_iseq(rb_iseq_callback callback, void *data) if (cont->ec->vm_stack == NULL) continue; - const rb_control_frame_t *cfp; - for (cfp = RUBY_VM_END_CONTROL_FRAME(cont->ec) - 1; ; cfp = RUBY_VM_NEXT_CONTROL_FRAME(cfp)) { - const rb_iseq_t *iseq; - if (cfp->pc && (iseq = cfp->iseq) != NULL && imemo_type((VALUE)iseq) == imemo_iseq) { - callback(iseq, data); + const rb_control_frame_t *cfp = cont->ec->cfp; + while (!RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(cont->ec, cfp)) { + if (cfp->pc && cfp->iseq && imemo_type((VALUE)cfp->iseq) == imemo_iseq) { + callback(cfp->iseq, data); } + cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp); + } + } +} + +#if USE_YJIT +// Update the jit_return of all CFPs to leave_exit unless it's leave_exception or not set. +// This prevents jit_exec_exception from jumping to the caller after invalidation. +void +rb_yjit_cancel_jit_return(void *leave_exit, void *leave_exception) +{ + struct rb_jit_cont *cont; + for (cont = first_jit_cont; cont != NULL; cont = cont->next) { + if (cont->ec->vm_stack == NULL) + continue; - if (cfp == cont->ec->cfp) - break; // reached the most recent cfp + const rb_control_frame_t *cfp = cont->ec->cfp; + while (!RUBY_VM_CONTROL_FRAME_STACK_OVERFLOW_P(cont->ec, cfp)) { + if (cfp->jit_return && cfp->jit_return != leave_exception) { + ((rb_control_frame_t *)cfp)->jit_return = leave_exit; + } + cfp = RUBY_VM_PREVIOUS_CONTROL_FRAME(cfp); } } } +#endif // Finish working with jit_cont. void rb_jit_cont_finish(void) { - if (!jit_cont_enabled) - return; - struct rb_jit_cont *cont, *next; for (cont = first_jit_cont; cont != NULL; cont = next) { next = cont->next; @@ -1326,9 +1366,8 @@ static void cont_init_jit_cont(rb_context_t *cont) { VM_ASSERT(cont->jit_cont == NULL); - if (jit_cont_enabled) { - cont->jit_cont = jit_cont_new(&(cont->saved_ec)); - } + // We always allocate this since YJIT may be enabled later + cont->jit_cont = jit_cont_new(&(cont->saved_ec)); } struct rb_execution_context_struct * @@ -1375,15 +1414,11 @@ rb_fiberptr_blocking(struct rb_fiber_struct *fiber) return fiber->blocking; } -// Start working with jit_cont. +// Initialize the jit_cont_lock void rb_jit_cont_init(void) { - if (!jit_cont_enabled) - return; - rb_native_mutex_initialize(&jit_cont_lock); - cont_init_jit_cont(&GET_EC()->fiber_ptr->cont); } #if 0 @@ -1447,22 +1482,6 @@ cont_capture(volatile int *volatile stat) VM_ASSERT(cont->saved_ec.cfp != NULL); cont_save_machine_stack(th, cont); - /* backup ensure_list to array for search in another context */ - { - rb_ensure_list_t *p; - int size = 0; - rb_ensure_entry_t *entry; - for (p=th->ec->ensure_list; p; p=p->next) - size++; - entry = cont->ensure_array = ALLOC_N(rb_ensure_entry_t,size+1); - for (p=th->ec->ensure_list; p; p=p->next) { - if (!p->entry.marker) - p->entry.marker = rb_ary_hidden_new(0); /* dummy object */ - *entry++ = p->entry; - } - entry->marker = 0; - } - if (ruby_setjmp(cont->jmpbuf)) { VALUE value; @@ -1505,6 +1524,51 @@ cont_restore_thread(rb_context_t *cont) rb_raise(rb_eRuntimeError, "can't call across trace_func"); } +#if defined(__wasm__) && !defined(__EMSCRIPTEN__) + if (th->ec->tag != sec->tag) { + /* find the lowest common ancestor tag of the current EC and the saved EC */ + + struct rb_vm_tag *lowest_common_ancestor = NULL; + size_t num_tags = 0; + size_t num_saved_tags = 0; + for (struct rb_vm_tag *tag = th->ec->tag; tag != NULL; tag = tag->prev) { + ++num_tags; + } + for (struct rb_vm_tag *tag = sec->tag; tag != NULL; tag = tag->prev) { + ++num_saved_tags; + } + + size_t min_tags = num_tags <= num_saved_tags ? num_tags : num_saved_tags; + + struct rb_vm_tag *tag = th->ec->tag; + while (num_tags > min_tags) { + tag = tag->prev; + --num_tags; + } + + struct rb_vm_tag *saved_tag = sec->tag; + while (num_saved_tags > min_tags) { + saved_tag = saved_tag->prev; + --num_saved_tags; + } + + while (min_tags > 0) { + if (tag == saved_tag) { + lowest_common_ancestor = tag; + break; + } + tag = tag->prev; + saved_tag = saved_tag->prev; + --min_tags; + } + + /* free all the jump buffers between the current EC's tag and the lowest common ancestor tag */ + for (struct rb_vm_tag *tag = th->ec->tag; tag != lowest_common_ancestor; tag = tag->prev) { + rb_vm_tag_jmpbuf_deinit(&tag->buf); + } + } +#endif + /* copy vm stack */ #ifdef CAPTURE_JUST_VALID_VM_STACK MEMCPY(th->ec->vm_stack, @@ -1523,7 +1587,6 @@ cont_restore_thread(rb_context_t *cont) th->ec->tag = sec->tag; th->ec->root_lep = sec->root_lep; th->ec->root_svar = sec->root_svar; - th->ec->ensure_list = sec->ensure_list; th->ec->errinfo = sec->errinfo; VM_ASSERT(th->ec->vm_stack != NULL); @@ -1555,11 +1618,10 @@ fiber_setcontext(rb_fiber_t *new_fiber, rb_fiber_t *old_fiber) } } - /* exchange machine_stack_start between old_fiber and new_fiber */ + /* these values are used in rb_gc_mark_machine_context to mark the fiber's stack. */ old_fiber->cont.saved_ec.machine.stack_start = th->ec->machine.stack_start; + old_fiber->cont.saved_ec.machine.stack_end = FIBER_TERMINATED_P(old_fiber) ? NULL : th->ec->machine.stack_end; - /* old_fiber->machine.stack_end should be NULL */ - old_fiber->cont.saved_ec.machine.stack_end = NULL; // if (DEBUG) fprintf(stderr, "fiber_setcontext: %p[%p] -> %p[%p]\n", (void*)old_fiber, old_fiber->stack.base, (void*)new_fiber, new_fiber->stack.base); @@ -1593,9 +1655,9 @@ cont_restore_1(rb_context_t *cont) cont_restore_thread(cont); /* restore machine stack */ -#if defined(_M_AMD64) && !defined(__MINGW64__) +#if (defined(_M_AMD64) && !defined(__MINGW64__)) || defined(_M_ARM64) { - /* workaround for x64 SEH */ + /* workaround for x64 and arm64 SEH on Windows */ jmp_buf buf; setjmp(buf); _JUMP_BUFFER *bp = (void*)&cont->jmpbuf; @@ -1762,6 +1824,13 @@ rb_callcc(VALUE self) return rb_yield(val); } } +#ifdef RUBY_ASAN_ENABLED +/* callcc can't possibly work with ASAN; see bug #20273. Also this function + * definition below avoids a "defined and not used" warning. */ +MAYBE_UNUSED(static void notusing_callcc(void)) { rb_callcc(Qnil); } +# define rb_callcc rb_f_notimplement +#endif + static VALUE make_passing_arg(int argc, const VALUE *argv) @@ -1780,80 +1849,6 @@ make_passing_arg(int argc, const VALUE *argv) typedef VALUE e_proc(VALUE); -/* CAUTION!! : Currently, error in rollback_func is not supported */ -/* same as rb_protect if set rollback_func to NULL */ -void -ruby_register_rollback_func_for_ensure(e_proc *ensure_func, e_proc *rollback_func) -{ - st_table **table_p = &GET_VM()->ensure_rollback_table; - if (UNLIKELY(*table_p == NULL)) { - *table_p = st_init_numtable(); - } - st_insert(*table_p, (st_data_t)ensure_func, (st_data_t)rollback_func); -} - -static inline e_proc * -lookup_rollback_func(e_proc *ensure_func) -{ - st_table *table = GET_VM()->ensure_rollback_table; - st_data_t val; - if (table && st_lookup(table, (st_data_t)ensure_func, &val)) - return (e_proc *) val; - return (e_proc *) Qundef; -} - - -static inline void -rollback_ensure_stack(VALUE self,rb_ensure_list_t *current,rb_ensure_entry_t *target) -{ - rb_ensure_list_t *p; - rb_ensure_entry_t *entry; - size_t i, j; - size_t cur_size; - size_t target_size; - size_t base_point; - e_proc *func; - - cur_size = 0; - for (p=current; p; p=p->next) - cur_size++; - target_size = 0; - for (entry=target; entry->marker; entry++) - target_size++; - - /* search common stack point */ - p = current; - base_point = cur_size; - while (base_point) { - if (target_size >= base_point && - p->entry.marker == target[target_size - base_point].marker) - break; - base_point --; - p = p->next; - } - - /* rollback function check */ - for (i=0; i < target_size - base_point; i++) { - if (!lookup_rollback_func(target[i].e_proc)) { - rb_raise(rb_eRuntimeError, "continuation called from out of critical rb_ensure scope"); - } - } - /* pop ensure stack */ - while (cur_size > base_point) { - /* escape from ensure block */ - (*current->entry.e_proc)(current->entry.data2); - current = current->next; - cur_size--; - } - /* push ensure stack */ - for (j = 0; j < i; j++) { - func = lookup_rollback_func(target[i - j - 1].e_proc); - if (!UNDEF_P((VALUE)func)) { - (*func)(target[i - j - 1].data2); - } - } -} - NORETURN(static VALUE rb_cont_call(int argc, VALUE *argv, VALUE contval)); /* @@ -1885,7 +1880,6 @@ rb_cont_call(int argc, VALUE *argv, VALUE contval) rb_raise(rb_eRuntimeError, "continuation called across fiber"); } } - rollback_ensure_stack(contval, th->ec->ensure_list, cont->ensure_array); cont->argc = argc; cont->value = make_passing_arg(argc, argv); @@ -1962,7 +1956,7 @@ rb_cont_call(int argc, VALUE *argv, VALUE contval) * == Non-blocking Fibers * * The concept of non-blocking fiber was introduced in Ruby 3.0. - * A non-blocking fiber, when reaching a operation that would normally block + * A non-blocking fiber, when reaching an operation that would normally block * the fiber (like sleep, or wait for another process or I/O) * will yield control to other fibers and allow the scheduler to * handle blocking and waking up (resuming) this fiber when it can proceed. @@ -2190,7 +2184,7 @@ rb_fiber_storage_set(VALUE self, VALUE value) static VALUE rb_fiber_storage_aref(VALUE class, VALUE key) { - Check_Type(key, T_SYMBOL); + key = rb_to_symbol(key); VALUE storage = fiber_storage_get(fiber_current(), FALSE); if (storage == Qnil) return Qnil; @@ -2211,7 +2205,7 @@ rb_fiber_storage_aref(VALUE class, VALUE key) static VALUE rb_fiber_storage_aset(VALUE class, VALUE key, VALUE value) { - Check_Type(key, T_SYMBOL); + key = rb_to_symbol(key); VALUE storage = fiber_storage_get(fiber_current(), value != Qnil); if (storage == Qnil) return Qnil; @@ -2365,7 +2359,7 @@ rb_fiber_initialize(int argc, VALUE* argv, VALUE self) VALUE rb_fiber_new_storage(rb_block_call_func_t func, VALUE obj, VALUE storage) { - return fiber_initialize(fiber_alloc(rb_cFiber), rb_proc_new(func, obj), rb_fiber_pool_default(Qnil), 1, storage); + return fiber_initialize(fiber_alloc(rb_cFiber), rb_proc_new(func, obj), rb_fiber_pool_default(Qnil), 0, storage); } VALUE @@ -2552,11 +2546,10 @@ rb_fiber_start(rb_fiber_t *fiber) void rb_threadptr_root_fiber_setup(rb_thread_t *th) { - rb_fiber_t *fiber = ruby_mimmalloc(sizeof(rb_fiber_t)); + rb_fiber_t *fiber = ruby_mimcalloc(1, sizeof(rb_fiber_t)); if (!fiber) { rb_bug("%s", strerror(errno)); /* ... is it possible to call rb_bug here? */ } - MEMZERO(fiber, rb_fiber_t, 1); fiber->cont.type = FIBER_CONTEXT; fiber->cont.saved_ec.fiber_ptr = fiber; fiber->cont.saved_ec.thread_ptr = th; @@ -2564,10 +2557,6 @@ rb_threadptr_root_fiber_setup(rb_thread_t *th) fiber->killed = 0; fiber_status_set(fiber, FIBER_RESUMED); /* skip CREATED */ th->ec = &fiber->cont.saved_ec; - // When rb_threadptr_root_fiber_setup is called for the first time, rb_rjit_enabled and - // rb_yjit_enabled_p() are still false. So this does nothing and rb_jit_cont_init() that is - // called later will take care of it. However, you still have to call cont_init_jit_cont() - // here for other Ractors, which are not initialized by rb_jit_cont_init(). cont_init_jit_cont(&fiber->cont); } @@ -2578,12 +2567,12 @@ rb_threadptr_root_fiber_release(rb_thread_t *th) /* ignore. A root fiber object will free th->ec */ } else { - rb_execution_context_t *ec = GET_EC(); + rb_execution_context_t *ec = rb_current_execution_context(false); VM_ASSERT(th->ec->fiber_ptr->cont.type == FIBER_CONTEXT); VM_ASSERT(th->ec->fiber_ptr->cont.self == 0); - if (th->ec == ec) { + if (ec && th->ec == ec) { rb_ractor_set_current_ec(th->ractor, NULL); } fiber_free(th->ec->fiber_ptr); @@ -3214,7 +3203,13 @@ rb_fiber_s_yield(int argc, VALUE *argv, VALUE klass) static VALUE fiber_raise(rb_fiber_t *fiber, VALUE exception) { - if (FIBER_SUSPENDED_P(fiber) && !fiber->yielding) { + if (fiber == fiber_current()) { + rb_exc_raise(exception); + } + else if (fiber->resuming_fiber) { + return fiber_raise(fiber->resuming_fiber, exception); + } + else if (FIBER_SUSPENDED_P(fiber) && !fiber->yielding) { return fiber_transfer_kw(fiber, -1, &exception, RB_NO_KEYWORDS); } else { @@ -3250,6 +3245,10 @@ rb_fiber_raise(VALUE fiber, int argc, const VALUE *argv) * the exception, and the third parameter is an array of callback information. * Exceptions are caught by the +rescue+ clause of begin...end * blocks. + * + * Raises +FiberError+ if called on a Fiber belonging to another +Thread+. + * + * See Kernel#raise for more information. */ static VALUE rb_fiber_m_raise(int argc, VALUE *argv, VALUE self) @@ -3261,12 +3260,18 @@ rb_fiber_m_raise(int argc, VALUE *argv, VALUE self) * call-seq: * fiber.kill -> nil * - * Terminates +fiber+ by raising an uncatchable exception, returning - * the terminated Fiber. + * Terminates the fiber by raising an uncatchable exception. + * It only terminates the given fiber and no other fiber, returning +nil+ to + * another fiber if that fiber was calling #resume or #transfer. + * + * Fiber#kill only interrupts another fiber when it is in Fiber.yield. + * If called on the current fiber then it raises that exception at the Fiber#kill call site. * * If the fiber has not been started, transition directly to the terminated state. * * If the fiber is already terminated, does nothing. + * + * Raises FiberError if called on a fiber belonging to another thread. */ static VALUE rb_fiber_m_kill(VALUE self) @@ -3282,7 +3287,8 @@ rb_fiber_m_kill(VALUE self) else if (fiber->status != FIBER_TERMINATED) { if (fiber_current() == fiber) { fiber_check_killed(fiber); - } else { + } + else { fiber_raise(fiber_ptr(self), Qnil); } } @@ -3490,6 +3496,10 @@ Init_Cont(void) rb_define_singleton_method(rb_cFiber, "schedule", rb_fiber_s_schedule, -1); #ifdef RB_EXPERIMENTAL_FIBER_POOL + /* + * Document-class: Fiber::Pool + * :nodoc: experimental + */ rb_cFiberPool = rb_define_class_under(rb_cFiber, "Pool", rb_cObject); rb_define_alloc_func(rb_cFiberPool, fiber_pool_alloc); rb_define_method(rb_cFiberPool, "initialize", rb_fiber_pool_initialize, -1); diff --git a/coroutine/amd64/Context.S b/coroutine/amd64/Context.S index 056c276a317c3c..4b94d31f30839f 100644 --- a/coroutine/amd64/Context.S +++ b/coroutine/amd64/Context.S @@ -5,13 +5,21 @@ ## Copyright, 2018, by Samuel Williams. ## +/* Important - do _not_ include in this file; doing so will + * cause an incorrect .note.gnu.property section to be emitted. We have + * one at the bottom of this file */ + #define TOKEN_PASTE(x,y) x##y -#define PREFIXED_SYMBOL(prefix,name) TOKEN_PASTE(prefix,name) .text -.globl PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer) -PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer): +.globl PREFIXED_SYMBOL(coroutine_transfer) +PREFIXED_SYMBOL(coroutine_transfer): + +#if defined(__CET__) && (__CET__ & 0x01) != 0 + /* IBT landing pad */ + endbr64 +#endif # Make space on the stack for 6 registers: subq $48, %rsp @@ -50,3 +58,31 @@ PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer): #if (defined(__linux__) || defined(__FreeBSD__)) && defined(__ELF__) .section .note.GNU-stack,"",%progbits #endif + +#if defined(__ELF__) + +#if defined(__CET__) && (__CET__ & 0x01) != 0 +# define IBT_FLAG 0x01 +#else +# define IBT_FLAG 0x00 +#endif + +/* We do _NOT_ support CET shadow-stack. Do _not_ add the property for + * this to the Context.o object. If you require CET shadow-stack support, + * for now, consider building with --with-coroutine=ucontext */ +#define SHSTK_FLAG 0x00 + +.pushsection .note.gnu.property, "a" +.p2align 3 +.long 0x4 /* Name size ("GNU\0") */ +.long 0x10 /* Descriptor size */ +.long 0x5 /* Type: NT_GNU_PROPERTY_TYPE_0 */ +.asciz "GNU" /* Name */ +# Begin descriptor +.long 0xc0000002 /* Property type: GNU_PROPERTY_X86_FEATURE_1_AND */ +.long 0x4 /* Property size */ +.long (IBT_FLAG | SHSTK_FLAG) +.long 0x0 /* 8-byte alignment padding */ +/* End descriptor */ +.popsection +#endif diff --git a/coroutine/amd64/Context.h b/coroutine/amd64/Context.h index 44daa4e01a8861..65aa6383044973 100644 --- a/coroutine/amd64/Context.h +++ b/coroutine/amd64/Context.h @@ -69,7 +69,7 @@ static inline void coroutine_initialize( context->stack_pointer = (void**)((uintptr_t)top & ~0xF); *--context->stack_pointer = NULL; - *--context->stack_pointer = (void*)start; + *--context->stack_pointer = (void*)(uintptr_t)start; context->stack_pointer -= COROUTINE_REGISTERS; memset(context->stack_pointer, 0, sizeof(void*) * COROUTINE_REGISTERS); diff --git a/coroutine/arm32/Context.S b/coroutine/arm32/Context.S index 1850c4c4080602..945e4f82d5d61b 100644 --- a/coroutine/arm32/Context.S +++ b/coroutine/arm32/Context.S @@ -6,16 +6,15 @@ ## #define TOKEN_PASTE(x,y) x##y -#define PREFIXED_SYMBOL(prefix,name) TOKEN_PASTE(prefix,name) .file "Context.S" .text -.globl PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer) +.globl PREFIXED_SYMBOL(coroutine_transfer) .align 2 -.type PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer),%function +.type PREFIXED_SYMBOL(coroutine_transfer),%function .syntax unified -PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer): +PREFIXED_SYMBOL(coroutine_transfer): # Save caller state (8 registers + return address) push {r4-r11,lr} diff --git a/coroutine/arm32/Context.h b/coroutine/arm32/Context.h index 09410eb25dc4c4..7529dd2efc74a5 100644 --- a/coroutine/arm32/Context.h +++ b/coroutine/arm32/Context.h @@ -44,7 +44,7 @@ static inline void coroutine_initialize( char * top = (char*)stack + size; context->stack_pointer = (void**)((uintptr_t)top & ~0xF); - *--context->stack_pointer = (void*)start; + *--context->stack_pointer = (void*)(uintptr_t)start; context->stack_pointer -= COROUTINE_REGISTERS; memset(context->stack_pointer, 0, sizeof(void*) * COROUTINE_REGISTERS); diff --git a/coroutine/arm64/Context.S b/coroutine/arm64/Context.S index 07d50d30df39ee..ce219c0c4d375c 100644 --- a/coroutine/arm64/Context.S +++ b/coroutine/arm64/Context.S @@ -6,7 +6,6 @@ ## #define TOKEN_PASTE(x,y) x##y -#define PREFIXED_SYMBOL(prefix,name) TOKEN_PASTE(prefix,name) #if defined(__APPLE__) #define x29 fp @@ -18,26 +17,63 @@ .align 2 #endif -.global PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer) -PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer): +#if defined(__ARM_FEATURE_PAC_DEFAULT) && (__ARM_FEATURE_PAC_DEFAULT & 0x02) != 0 +# error "-mbranch-protection flag specified b-key but Context.S does not support this" +#endif + +#if defined(_WIN32) +## Add more space for certain TEB values on each stack +#define TEB_OFFSET 0x20 +#else +#define TEB_OFFSET 0x00 +#endif + +## NOTE(PAC): Use we HINT mnemonics instead of PAC mnemonics to +## keep compatibility with those assemblers that don't support PAC. +## +## See "Providing protection for complex software" for more details about PAC/BTI +## https://developer.arm.com/architectures/learn-the-architecture/providing-protection-for-complex-software + +.global PREFIXED_SYMBOL(coroutine_transfer) +PREFIXED_SYMBOL(coroutine_transfer): +#if defined(__ARM_FEATURE_PAC_DEFAULT) && (__ARM_FEATURE_PAC_DEFAULT != 0) + # paciasp (it also acts as BTI landing pad, so no need to insert BTI also) + hint #25 +#elif defined(__ARM_FEATURE_BTI_DEFAULT) && (__ARM_FEATURE_BTI_DEFAULT != 0) + # For the case PAC is not enabled but BTI is. + # bti c + hint #34 +#endif # Make space on the stack for caller registers - sub sp, sp, 0xb0 + sub sp, sp, 0xa0 + TEB_OFFSET # Save caller registers - stp d8, d9, [sp, 0x00] - stp d10, d11, [sp, 0x10] - stp d12, d13, [sp, 0x20] - stp d14, d15, [sp, 0x30] - stp x19, x20, [sp, 0x40] - stp x21, x22, [sp, 0x50] - stp x23, x24, [sp, 0x60] - stp x25, x26, [sp, 0x70] - stp x27, x28, [sp, 0x80] - stp x29, x30, [sp, 0x90] - - # Save return address - str x30, [sp, 0xa0] + stp d8, d9, [sp, 0x00 + TEB_OFFSET] + stp d10, d11, [sp, 0x10 + TEB_OFFSET] + stp d12, d13, [sp, 0x20 + TEB_OFFSET] + stp d14, d15, [sp, 0x30 + TEB_OFFSET] + stp x19, x20, [sp, 0x40 + TEB_OFFSET] + stp x21, x22, [sp, 0x50 + TEB_OFFSET] + stp x23, x24, [sp, 0x60 + TEB_OFFSET] + stp x25, x26, [sp, 0x70 + TEB_OFFSET] + stp x27, x28, [sp, 0x80 + TEB_OFFSET] + stp x29, x30, [sp, 0x90 + TEB_OFFSET] + +#if defined(_WIN32) + # Save certain values from Thread Environment Block (TEB) + # x18 points to the TEB on Windows + # Read TeStackBase and TeStackLimit at ksarm64.h from TEB + ldp x5, x6, [x18, #0x08] + # Save them + stp x5, x6, [sp, #0x00] + # Read TeDeallocationStack at ksarm64.h from TEB + ldr x5, [x18, #0x1478] + # Read TeFiberData at ksarm64.h from TEB + ldr x6, [x18, #0x20] + # Save current fiber data and deallocation stack + stp x5, x6, [sp, #0x10] +#endif # Save stack pointer to x0 (first argument) mov x2, sp @@ -47,27 +83,78 @@ PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer): ldr x3, [x1, 0] mov sp, x3 +#if defined(_WIN32) + # Restore stack base and limit + ldp x5, x6, [sp, #0x00] + # Write TeStackBase and TeStackLimit at ksarm64.h to TEB + stp x5, x6, [x18, #0x08] + # Restore fiber data and deallocation stack + ldp x5, x6, [sp, #0x10] + # Write TeDeallocationStack at ksarm64.h to TEB + str x5, [x18, #0x1478] + # Write TeFiberData at ksarm64.h to TEB + str x6, [x18, #0x20] +#endif + # Restore caller registers - ldp d8, d9, [sp, 0x00] - ldp d10, d11, [sp, 0x10] - ldp d12, d13, [sp, 0x20] - ldp d14, d15, [sp, 0x30] - ldp x19, x20, [sp, 0x40] - ldp x21, x22, [sp, 0x50] - ldp x23, x24, [sp, 0x60] - ldp x25, x26, [sp, 0x70] - ldp x27, x28, [sp, 0x80] - ldp x29, x30, [sp, 0x90] - - # Load return address into x4 - ldr x4, [sp, 0xa0] + ldp d8, d9, [sp, 0x00 + TEB_OFFSET] + ldp d10, d11, [sp, 0x10 + TEB_OFFSET] + ldp d12, d13, [sp, 0x20 + TEB_OFFSET] + ldp d14, d15, [sp, 0x30 + TEB_OFFSET] + ldp x19, x20, [sp, 0x40 + TEB_OFFSET] + ldp x21, x22, [sp, 0x50 + TEB_OFFSET] + ldp x23, x24, [sp, 0x60 + TEB_OFFSET] + ldp x25, x26, [sp, 0x70 + TEB_OFFSET] + ldp x27, x28, [sp, 0x80 + TEB_OFFSET] + ldp x29, x30, [sp, 0x90 + TEB_OFFSET] # Pop stack frame - add sp, sp, 0xb0 + add sp, sp, 0xa0 + TEB_OFFSET - # Jump to return address (in x4) - ret x4 +#if defined(__ARM_FEATURE_PAC_DEFAULT) && (__ARM_FEATURE_PAC_DEFAULT != 0) + # autiasp: Authenticate x30 (LR) with SP and key A + hint #29 +#endif + + # Jump to return address (in x30) + ret #if defined(__linux__) && defined(__ELF__) .section .note.GNU-stack,"",%progbits #endif + +#if (defined(__ARM_FEATURE_BTI_DEFAULT) && __ARM_FEATURE_BTI_DEFAULT != 0) || (defined(__ARM_FEATURE_PAC_DEFAULT) && __ARM_FEATURE_PAC_DEFAULT != 0) +#if defined(__ELF__) +/* See "ELF for the Arm 64-bit Architecture (AArch64)" + https://github.com/ARM-software/abi-aa/blob/2023Q3/aaelf64/aaelf64.rst#program-property */ +# define GNU_PROPERTY_AARCH64_FEATURE_1_BTI (1<<0) +# define GNU_PROPERTY_AARCH64_FEATURE_1_PAC (1<<1) + +# if defined(__ARM_FEATURE_BTI_DEFAULT) && __ARM_FEATURE_BTI_DEFAULT != 0 +# define BTI_FLAG GNU_PROPERTY_AARCH64_FEATURE_1_BTI +# else +# define BTI_FLAG 0 +# endif +# if defined(__ARM_FEATURE_PAC_DEFAULT) && __ARM_FEATURE_PAC_DEFAULT != 0 +# define PAC_FLAG GNU_PROPERTY_AARCH64_FEATURE_1_PAC +# else +# define PAC_FLAG 0 +# endif + + # The note section format is described by Note Section in Chapter 5 + # of "System V Application Binary Interface, Edition 4.1". + .pushsection .note.gnu.property, "a" + .p2align 3 + .long 0x4 /* Name size ("GNU\0") */ + .long 0x10 /* Descriptor size */ + .long 0x5 /* Type: NT_GNU_PROPERTY_TYPE_0 */ + .asciz "GNU" /* Name */ + # Begin descriptor + .long 0xc0000000 /* Property type: GNU_PROPERTY_AARCH64_FEATURE_1_AND */ + .long 0x4 /* Property size */ + .long (BTI_FLAG|PAC_FLAG) + .long 0x0 /* 8-byte alignment padding */ + # End descriptor + .popsection +#endif +#endif diff --git a/coroutine/arm64/Context.asm b/coroutine/arm64/Context.asm new file mode 100644 index 00000000000000..866fa628e78e88 --- /dev/null +++ b/coroutine/arm64/Context.asm @@ -0,0 +1,81 @@ + TTL coroutine/arm64/Context.asm + + AREA |.drectve|, DRECTVE + + EXPORT |coroutine_transfer| + + AREA |.text$mn|, CODE, ARM64 + +;; Add more space for certain TEB values on each stack +TEB_OFFSET EQU 0x20 + +;; Incomplete implementation +coroutine_transfer PROC + ; Make space on the stack for caller registers + sub sp, sp, 0xa0 + TEB_OFFSET + + ; Save caller registers + stp d8, d9, [sp, 0x00 + TEB_OFFSET] + stp d10, d11, [sp, 0x10 + TEB_OFFSET] + stp d12, d13, [sp, 0x20 + TEB_OFFSET] + stp d14, d15, [sp, 0x30 + TEB_OFFSET] + stp x19, x20, [sp, 0x40 + TEB_OFFSET] + stp x21, x22, [sp, 0x50 + TEB_OFFSET] + stp x23, x24, [sp, 0x60 + TEB_OFFSET] + stp x25, x26, [sp, 0x70 + TEB_OFFSET] + stp x27, x28, [sp, 0x80 + TEB_OFFSET] + stp x29, x30, [sp, 0x90 + TEB_OFFSET] + + ;; Save certain values from Thread Environment Block (TEB) x18 + ;; points to the TEB on Windows + ;; Read TeStackBase and TeStackLimit at ksarm64.h from TEB + ldp x5, x6, [x18, #0x08] + ;; Save them + stp x5, x6, [sp, #0x00] + ;; Read TeDeallocationStack at ksarm64.h from TEB + ldr x5, [x18, #0x1478] + ;; Read TeFiberData at ksarm64.h from TEB + ldr x6, [x18, #0x20] + ;; Save current fiber data and deallocation stack + stp x5, x6, [sp, #0x10] + + ; Save stack pointer to x0 (first argument) + mov x2, sp + str x2, [x0, 0] + + ; Load stack pointer from x1 (second argument) + ldr x3, [x1, 0] + mov sp, x3 + + ;; Restore stack base and limit + ldp x5, x6, [sp, #0x00] + ;; Write TeStackBase and TeStackLimit at ksarm64.h to TEB + stp x5, x6, [x18, #0x08] + ;; Restore fiber data and deallocation stack + ldp x5, x6, [sp, #0x10] + ;; Write TeDeallocationStack at ksarm64.h to TEB + str x5, [x18, #0x1478] + ;; Write TeFiberData at ksarm64.h to TEB + str x6, [x18, #0x20] + + ; Restore caller registers + ldp d8, d9, [sp, 0x00 + TEB_OFFSET] + ldp d10, d11, [sp, 0x10 + TEB_OFFSET] + ldp d12, d13, [sp, 0x20 + TEB_OFFSET] + ldp d14, d15, [sp, 0x30 + TEB_OFFSET] + ldp x19, x20, [sp, 0x40 + TEB_OFFSET] + ldp x21, x22, [sp, 0x50 + TEB_OFFSET] + ldp x23, x24, [sp, 0x60 + TEB_OFFSET] + ldp x25, x26, [sp, 0x70 + TEB_OFFSET] + ldp x27, x28, [sp, 0x80 + TEB_OFFSET] + ldp x29, x30, [sp, 0x90 + TEB_OFFSET] + + ; Pop stack frame + add sp, sp, 0xa0 + TEB_OFFSET + + ; Jump to return address (in x30) + ret + + endp + + end diff --git a/coroutine/arm64/Context.h b/coroutine/arm64/Context.h index 1472621f480170..468e4155b2b700 100644 --- a/coroutine/arm64/Context.h +++ b/coroutine/arm64/Context.h @@ -15,9 +15,21 @@ #include #include +#if defined __GNUC__ #define COROUTINE __attribute__((noreturn)) void +#define COROUTINE_DECL COROUTINE +#elif defined _MSC_VER +#define COROUTINE __declspec(noreturn) void +#define COROUTINE_DECL void +#endif + +#if defined(_WIN32) +#define TEB_OFFSET 0x20 +#else +#define TEB_OFFSET 0x00 +#endif -enum {COROUTINE_REGISTERS = 0xb0 / 8}; +enum {COROUTINE_REGISTERS = (0xa0 + TEB_OFFSET) / 8}; #if defined(__SANITIZE_ADDRESS__) #define COROUTINE_SANITIZE_ADDRESS @@ -44,12 +56,26 @@ struct coroutine_context #endif }; -typedef COROUTINE(* coroutine_start)(struct coroutine_context *from, struct coroutine_context *self); +typedef COROUTINE_DECL(* coroutine_start)(struct coroutine_context *from, struct coroutine_context *self); static inline void coroutine_initialize_main(struct coroutine_context * context) { context->stack_pointer = NULL; } +static inline void *ptrauth_sign_instruction_addr(void *addr, void *modifier) { +#if defined(__ARM_FEATURE_PAC_DEFAULT) && __ARM_FEATURE_PAC_DEFAULT != 0 + // Sign the given instruction address with the given modifier and key A + register void *r17 __asm("r17") = addr; + register void *r16 __asm("r16") = modifier; + // Use HINT mnemonic instead of PACIA1716 for compatibility with older assemblers. + __asm ("hint #8;" : "+r"(r17) : "r"(r16)); + addr = r17; +#else + // No-op if PAC is not enabled +#endif + return addr; +} + static inline void coroutine_initialize( struct coroutine_context *context, coroutine_start start, @@ -66,12 +92,21 @@ static inline void coroutine_initialize( // Stack grows down. Force 16-byte alignment. char * top = (char*)stack + size; - context->stack_pointer = (void**)((uintptr_t)top & ~0xF); + top = (char *)((uintptr_t)top & ~0xF); + context->stack_pointer = (void**)top; context->stack_pointer -= COROUTINE_REGISTERS; memset(context->stack_pointer, 0, sizeof(void*) * COROUTINE_REGISTERS); - context->stack_pointer[0xa0 / 8] = (void*)start; + void *addr = (void*)(uintptr_t)start; + context->stack_pointer[(0x98 + TEB_OFFSET) / 8] = ptrauth_sign_instruction_addr(addr, (void*)top); +#if defined(_WIN32) + // save top address of stack as base in TEB + context->stack_pointer[0x00 / 8] = (char*)stack + size; + // save botton address of stack as limit and deallocation stack in TEB + context->stack_pointer[0x08 / 8] = stack; + context->stack_pointer[0x10 / 8] = stack; +#endif } struct coroutine_context * coroutine_transfer(struct coroutine_context * current, struct coroutine_context * target); diff --git a/coroutine/asyncify/Context.h b/coroutine/asyncify/Context.h index 7dba829a1dfd50..71791a400492b5 100644 --- a/coroutine/asyncify/Context.h +++ b/coroutine/asyncify/Context.h @@ -13,6 +13,7 @@ #include #include +#include #include "wasm/asyncify.h" #include "wasm/machine.h" #include "wasm/fiber.h" @@ -47,10 +48,13 @@ static inline void coroutine_initialize_main(struct coroutine_context * context) static inline void coroutine_initialize(struct coroutine_context *context, coroutine_start start, void *stack, size_t size) { - if (ASYNCIFY_CORO_DEBUG) fprintf(stderr, "[%s] entry (context = %p, stack = %p ... %p)\n", __func__, context, stack, (char *)stack + size); + // Linear stack pointer must be always aligned down to 16 bytes. + // https://github.com/WebAssembly/tool-conventions/blob/c74267a5897c1bdc9aa60adeaf41816387d3cd12/BasicCABI.md#the-linear-stack + uintptr_t sp = ((uintptr_t)stack + size) & ~0xF; + if (ASYNCIFY_CORO_DEBUG) fprintf(stderr, "[%s] entry (context = %p, stack = %p ... %p)\n", __func__, context, stack, (char *)sp); rb_wasm_init_context(&context->fc, coroutine_trampoline, start, context); // record the initial stack pointer position to restore it after resumption - context->current_sp = (char *)stack + size; + context->current_sp = (char *)sp; context->stack_base = stack; context->size = size; } diff --git a/coroutine/loongarch64/Context.S b/coroutine/loongarch64/Context.S index 662f5dfb6c7af8..6e10cd032bea8d 100644 --- a/coroutine/loongarch64/Context.S +++ b/coroutine/loongarch64/Context.S @@ -1,11 +1,10 @@ #define TOKEN_PASTE(x,y) x##y -#define PREFIXED_SYMBOL(prefix,name) TOKEN_PASTE(prefix,name) .text .align 2 -.global PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer) -PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer): +.global PREFIXED_SYMBOL(coroutine_transfer) +PREFIXED_SYMBOL(coroutine_transfer): # Make space on the stack for caller registers addi.d $sp, $sp, -0xa0 diff --git a/coroutine/loongarch64/Context.h b/coroutine/loongarch64/Context.h index 668c9a965e4174..82b85b36e9e411 100644 --- a/coroutine/loongarch64/Context.h +++ b/coroutine/loongarch64/Context.h @@ -36,7 +36,7 @@ static inline void coroutine_initialize( context->stack_pointer -= COROUTINE_REGISTERS; memset(context->stack_pointer, 0, sizeof(void*) * COROUTINE_REGISTERS); - context->stack_pointer[0x90 / 8] = (void*)start; + context->stack_pointer[0x90 / 8] = (void*)(uintptr_t)start; } struct coroutine_context * coroutine_transfer(struct coroutine_context * current, struct coroutine_context * target); diff --git a/coroutine/ppc/Context.S b/coroutine/ppc/Context.S index cdda93e1797c15..f44b2419b4dfee 100644 --- a/coroutine/ppc/Context.S +++ b/coroutine/ppc/Context.S @@ -3,21 +3,20 @@ ; Some relevant examples: https://github.com/gcc-mirror/gcc/blob/master/libphobos/libdruntime/config/powerpc/switchcontext.S ; https://github.com/gcc-mirror/gcc/blob/master/libgcc/config/rs6000/darwin-gpsave.S ; https://www.ibm.com/docs/en/aix/7.2?topic=epilogs-saving-gprs-only -; ppc32 version may be re-written compactly with stmw/lwm, but the code wonʼt be faster, see: https://github.com/ruby/ruby/pull/5927#issuecomment-1139730541 +; ppc32 version may be re-written compactly with stmw/lwm, but the code won't be faster, see: https://github.com/ruby/ruby/pull/5927#issuecomment-1139730541 ; Notice that this code is only for Darwin (macOS). Darwin ABI differs from AIX and ELF. ; To add support for AIX, *BSD or *Linux, please make separate implementations. #define TOKEN_PASTE(x,y) x##y -#define PREFIXED_SYMBOL(prefix,name) TOKEN_PASTE(prefix,name) .machine ppc7400 ; = G4, Rosetta .text -.globl PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer) +.globl PREFIXED_SYMBOL(coroutine_transfer) .align 2 -PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer): +PREFIXED_SYMBOL(coroutine_transfer): ; Make space on the stack for caller registers ; (Should we rather use red zone? See libphobos example.) subi r1,r1,80 diff --git a/coroutine/ppc/Context.h b/coroutine/ppc/Context.h index 1fce1125794500..8035d08556d77d 100644 --- a/coroutine/ppc/Context.h +++ b/coroutine/ppc/Context.h @@ -13,7 +13,7 @@ enum { COROUTINE_REGISTERS = - 20 /* 19 general purpose registers (r13–r31) and 1 return address */ + 20 /* 19 general purpose registers (r13-r31) and 1 return address */ + 4 /* space for fiber_entry() to store the link register */ }; diff --git a/coroutine/ppc64/Context.S b/coroutine/ppc64/Context.S index f8561e0e7d0bee..20a47c61c6914e 100644 --- a/coroutine/ppc64/Context.S +++ b/coroutine/ppc64/Context.S @@ -8,15 +8,14 @@ ; To add support for AIX, *BSD or *Linux, please make separate implementations. #define TOKEN_PASTE(x,y) x##y -#define PREFIXED_SYMBOL(prefix,name) TOKEN_PASTE(prefix,name) .machine ppc64 ; = G5 .text -.globl PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer) +.globl PREFIXED_SYMBOL(coroutine_transfer) .align 2 -PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer): +PREFIXED_SYMBOL(coroutine_transfer): ; Make space on the stack for caller registers ; (Should we rather use red zone? See libphobos example.) subi r1,r1,160 diff --git a/coroutine/ppc64/Context.h b/coroutine/ppc64/Context.h index 3e6f77f55af182..085b475ed58563 100644 --- a/coroutine/ppc64/Context.h +++ b/coroutine/ppc64/Context.h @@ -12,7 +12,7 @@ enum { COROUTINE_REGISTERS = - 20 /* 19 general purpose registers (r13–r31) and 1 return address */ + 20 /* 19 general purpose registers (r13-r31) and 1 return address */ + 4 /* space for fiber_entry() to store the link register */ }; diff --git a/coroutine/ppc64le/Context.S b/coroutine/ppc64le/Context.S index 61be9efcf0461a..f7bcae2c3af400 100644 --- a/coroutine/ppc64le/Context.S +++ b/coroutine/ppc64le/Context.S @@ -1,14 +1,13 @@ #define TOKEN_PASTE(x,y) x##y -#define PREFIXED_SYMBOL(prefix,name) TOKEN_PASTE(prefix,name) .text .align 2 -.globl PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer) -.type PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer), @function -PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer): +.globl PREFIXED_SYMBOL(coroutine_transfer) +.type PREFIXED_SYMBOL(coroutine_transfer), @function +PREFIXED_SYMBOL(coroutine_transfer): # Make space on the stack for caller registers - addi 1,1,-152 + addi 1,1,-160 # Save caller registers std 14,0(1) @@ -34,6 +33,10 @@ PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer): mflr 0 std 0,144(1) + # Save caller special register + mfcr 0 + std 0, 152(1) + # Save stack pointer to first argument std 1,0(3) @@ -64,8 +67,14 @@ PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer): ld 0,144(1) mtlr 0 + # Load special registers + ld 0,152(1) + # Restore cr register cr2, cr3 and cr4 (field index 3,4,5) + # (field index is 1-based, field 1 = cr0) using a mask (32|16|8 = 56) + mtcrf 56,0 + # Pop stack frame - addi 1,1,152 + addi 1,1,160 # Jump to return address blr diff --git a/coroutine/ppc64le/Context.h b/coroutine/ppc64le/Context.h index fbfaa2ee63fcca..63ea9f19ff96e7 100644 --- a/coroutine/ppc64le/Context.h +++ b/coroutine/ppc64le/Context.h @@ -12,7 +12,7 @@ enum { COROUTINE_REGISTERS = - 19 /* 18 general purpose registers (r14-r31) and 1 return address */ + 20 /* 18 general purpose registers (r14-r31), 1 special register (cr) and 1 return address */ + 4 /* space for fiber_entry() to store the link register */ }; diff --git a/coroutine/riscv64/Context.S b/coroutine/riscv64/Context.S index cc4e872f84b3dd..8e7fc74ffc1ee5 100644 --- a/coroutine/riscv64/Context.S +++ b/coroutine/riscv64/Context.S @@ -1,11 +1,10 @@ #define TOKEN_PASTE(x,y) x##y -#define PREFIXED_SYMBOL(prefix,name) TOKEN_PASTE(prefix,name) .text .align 2 -.global PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer) -PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer): +.global PREFIXED_SYMBOL(coroutine_transfer) +PREFIXED_SYMBOL(coroutine_transfer): # Make space on the stack for caller registers addi sp, sp, -0xd0 diff --git a/coroutine/riscv64/Context.h b/coroutine/riscv64/Context.h index 9ce1140e0b826d..3660fb5577a43e 100644 --- a/coroutine/riscv64/Context.h +++ b/coroutine/riscv64/Context.h @@ -36,7 +36,7 @@ static inline void coroutine_initialize( context->stack_pointer -= COROUTINE_REGISTERS; memset(context->stack_pointer, 0, sizeof(void*) * COROUTINE_REGISTERS); - context->stack_pointer[0xc0 / 8] = (void*)start; + context->stack_pointer[0xc0 / 8] = (void*)(uintptr_t)start; } struct coroutine_context * coroutine_transfer(struct coroutine_context * current, struct coroutine_context * target); diff --git a/coroutine/win32/Context.h b/coroutine/win32/Context.h index 902fd1246f0876..c1c8fbcd13a2c3 100644 --- a/coroutine/win32/Context.h +++ b/coroutine/win32/Context.h @@ -16,6 +16,7 @@ #include #define COROUTINE __declspec(noreturn) void __fastcall +#define COROUTINE_DECL void __fastcall #define COROUTINE_LIMITED_ADDRESS_SPACE /* This doesn't include thread information block */ @@ -45,7 +46,7 @@ static inline void coroutine_initialize( char * top = (char*)stack + size; context->stack_pointer = (void**)((uintptr_t)top & ~0xF); - *--context->stack_pointer = (void*)start; + *--context->stack_pointer = (void*)(uintptr_t)start; /* Windows Thread Information Block */ *--context->stack_pointer = (void*)0xFFFFFFFF; /* fs:[0] */ diff --git a/coroutine/win64/Context.h b/coroutine/win64/Context.h index aaa4caeaf9fc48..23b21b5c1c00d8 100644 --- a/coroutine/win64/Context.h +++ b/coroutine/win64/Context.h @@ -16,6 +16,7 @@ #include #define COROUTINE __declspec(noreturn) void +#define COROUTINE_DECL void enum { COROUTINE_REGISTERS = 8, @@ -30,7 +31,7 @@ struct coroutine_context typedef void(* coroutine_start)(struct coroutine_context *from, struct coroutine_context *self); -void coroutine_trampoline(); +void coroutine_trampoline(void); static inline void coroutine_initialize_main(struct coroutine_context * context) { context->stack_pointer = NULL; @@ -53,7 +54,7 @@ static inline void coroutine_initialize( /* Return address */ *--context->stack_pointer = 0; - *--context->stack_pointer = (void*)start; + *--context->stack_pointer = (void*)(uintptr_t)start; *--context->stack_pointer = (void*)coroutine_trampoline; /* Windows Thread Information Block */ diff --git a/coroutine/x86/Context.S b/coroutine/x86/Context.S index f06a417084b4e2..b04e71aa1cbbfa 100644 --- a/coroutine/x86/Context.S +++ b/coroutine/x86/Context.S @@ -6,12 +6,11 @@ ## #define TOKEN_PASTE(x,y) x##y -#define PREFIXED_SYMBOL(prefix,name) TOKEN_PASTE(prefix,name) .text -.globl PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer) -PREFIXED_SYMBOL(SYMBOL_PREFIX,coroutine_transfer): +.globl PREFIXED_SYMBOL(coroutine_transfer) +PREFIXED_SYMBOL(coroutine_transfer): # Save caller registers pushl %ebp diff --git a/coroutine/x86/Context.h b/coroutine/x86/Context.h index d98eaf6486165a..f33b338eabf2a7 100644 --- a/coroutine/x86/Context.h +++ b/coroutine/x86/Context.h @@ -45,7 +45,7 @@ static inline void coroutine_initialize( context->stack_pointer = (void**)((uintptr_t)top & ~0xF); *--context->stack_pointer = NULL; - *--context->stack_pointer = (void*)start; + *--context->stack_pointer = (void*)(uintptr_t)start; context->stack_pointer -= COROUTINE_REGISTERS; memset(context->stack_pointer, 0, sizeof(void*) * COROUTINE_REGISTERS); diff --git a/cygwin/GNUmakefile.in b/cygwin/GNUmakefile.in index 09298590304b53..8e83d73040fe8c 100644 --- a/cygwin/GNUmakefile.in +++ b/cygwin/GNUmakefile.in @@ -2,10 +2,18 @@ gnumake = yes include Makefile +MUNICODE_FLAG := $(if $(filter mingw%,$(target_os)),-municode) +override EXE_LDFLAGS += $(MUNICODE_FLAG) + DLLWRAP = @DLLWRAP@ --target=$(target_os) --driver-name="$(CC)" -windres-cpp := $(CPP) -xc -windres-cpp := --preprocessor=$(firstword $(windres-cpp)) \ - $(addprefix --preprocessor-arg=,$(wordlist 2,$(words $(windres-cpp)),$(windres-cpp))) +ifeq (@USE_LLVM_WINDRES@,yes) # USE_LLVM_WINDRES + # llvm-windres fails when preprocessor options are added + windres-cpp := +else + windres-cpp := $(CPP) -xc + windres-cpp := --preprocessor=$(firstword $(windres-cpp)) \ + $(addprefix --preprocessor-arg=,$(wordlist 2,$(words $(windres-cpp)),$(windres-cpp))) +endif WINDRES = @WINDRES@ $(windres-cpp) -DRC_INVOKED STRIP = @STRIP@ @@ -64,7 +72,7 @@ $(PROGRAM): $(RUBY_INSTALL_NAME).res.$(OBJEXT) $(WPROGRAM): $(RUBYW_INSTALL_NAME).res.$(OBJEXT) @rm -f $@ $(ECHO) linking $@ - $(Q) $(PURIFY) $(CC) -mwindows -e $(SYMBOL_PREFIX)mainCRTStartup $(LDFLAGS) $(XLDFLAGS) \ + $(Q) $(PURIFY) $(CC) $(MUNICODE_FLAG) -mwindows -e $(SYMBOL_PREFIX)mainCRTStartup $(LDFLAGS) $(XLDFLAGS) \ $(MAINOBJ) $(EXTOBJS) $(LIBRUBYARG) $(LIBS) -o $@ $(STUBPROGRAM): $(RUBY_INSTALL_NAME).res.$(OBJEXT) @@ -91,6 +99,8 @@ yes-test-all: export MSYS2_ARG_CONV_EXCL=$(MSYS2_ARG_CONV_EXCL_PARAM) yes-test-almost: export MSYS2_ARG_CONV_EXCL=$(MSYS2_ARG_CONV_EXCL_PARAM) test/% spec/%/ spec/%_spec.rb: export MSYS2_ARG_CONV_EXCL=$(MSYS2_ARG_CONV_EXCL_PARAM) +distclean-local:: + $(RMDIR) win32 endif $(LIBRUBY_SO): $(RUBYDEF) diff --git a/darray.h b/darray.h index 8e1e5763551605..c9035b74b642cd 100644 --- a/darray.h +++ b/darray.h @@ -5,9 +5,6 @@ #include #include -#include "internal/bits.h" -#include "internal/gc.h" - // Type for a dynamic array. Use to declare a dynamic array. // It is a pointer so it fits in st_table nicely. Designed // to be fairly type-safe. @@ -45,7 +42,7 @@ * void rb_darray_append(rb_darray(T) *ptr_to_ary, T element); */ #define rb_darray_append(ptr_to_ary, element) \ - rb_darray_append_impl(ptr_to_ary, element, rb_xrealloc_mul_add) + rb_darray_append_impl(ptr_to_ary, element, rb_darray_realloc_mul_add) #define rb_darray_append_without_gc(ptr_to_ary, element) \ rb_darray_append_impl(ptr_to_ary, element, rb_darray_realloc_mul_add_without_gc) @@ -61,6 +58,20 @@ (*(ptr_to_ary))->meta.size++; \ } while (0) +#define rb_darray_insert_without_gc(ptr_to_ary, idx, element) do { \ + rb_darray_ensure_space((ptr_to_ary), \ + sizeof(**(ptr_to_ary)), \ + sizeof((*(ptr_to_ary))->data[0]), \ + rb_darray_realloc_mul_add_without_gc); \ + MEMMOVE( \ + rb_darray_ref(*(ptr_to_ary), idx + 1), \ + rb_darray_ref(*(ptr_to_ary), idx), \ + (*(ptr_to_ary))->data[0], \ + rb_darray_size(*(ptr_to_ary)) - idx); \ + rb_darray_set(*(ptr_to_ary), idx, element); \ + (*(ptr_to_ary))->meta.size++; \ +} while (0) + // Iterate over items of the array in a for loop // #define rb_darray_foreach(ary, idx_name, elem_ptr_var) \ @@ -80,7 +91,7 @@ */ #define rb_darray_make(ptr_to_ary, size) \ rb_darray_make_impl((ptr_to_ary), size, sizeof(**(ptr_to_ary)), \ - sizeof((*(ptr_to_ary))->data[0]), rb_xcalloc_mul_add) + sizeof((*(ptr_to_ary))->data[0]), rb_darray_calloc_mul_add) #define rb_darray_make_without_gc(ptr_to_ary, size) \ rb_darray_make_impl((ptr_to_ary), size, sizeof(**(ptr_to_ary)), \ @@ -92,7 +103,7 @@ * void rb_darray_resize_capa(rb_darray(T) *ptr_to_ary, size_t capa); */ #define rb_darray_resize_capa_without_gc(ptr_to_ary, capa) \ - rb_darray_resize_capa_impl((ptr_to_ary), rb_darray_next_power_of_two(capa), sizeof(**(ptr_to_ary)), \ + rb_darray_resize_capa_impl((ptr_to_ary), capa, sizeof(**(ptr_to_ary)), \ sizeof((*(ptr_to_ary))->data[0]), rb_darray_realloc_mul_add_without_gc) #define rb_darray_data_ptr(ary) ((ary)->data) @@ -122,6 +133,14 @@ rb_darray_size(const void *ary) return meta ? meta->size : 0; } + +static inline void +rb_darray_pop(void *ary, size_t count) +{ + rb_darray_meta_t *meta = ary; + meta->size -= count; +} + // Get the capacity of the dynamic array. // static inline size_t @@ -135,8 +154,7 @@ rb_darray_capa(const void *ary) static inline void rb_darray_free(void *ary) { - rb_darray_meta_t *meta = ary; - if (meta) ruby_sized_xfree(ary, meta->capa); + xfree(ary); } static inline void @@ -145,12 +163,23 @@ rb_darray_free_without_gc(void *ary) free(ary); } -/* Internal function. Like rb_xcalloc_mul_add but does not trigger GC and does - * not check for overflow in arithmetic. */ +/* Internal function. Like rb_xcalloc_mul_add. */ +static inline void * +rb_darray_calloc_mul_add(size_t x, size_t y, size_t z) +{ + size_t size = rbimpl_size_add_or_raise(rbimpl_size_mul_or_raise(x, y), z); + + void *ptr = xcalloc(1, size); + RUBY_ASSERT(ptr != NULL); + + return ptr; +} + +/* Internal function. Like rb_xcalloc_mul_add but does not trigger GC. */ static inline void * rb_darray_calloc_mul_add_without_gc(size_t x, size_t y, size_t z) { - size_t size = (x * y) + z; + size_t size = rbimpl_size_add_or_raise(rbimpl_size_mul_or_raise(x, y), z); void *ptr = calloc(1, size); if (ptr == NULL) rb_bug("rb_darray_calloc_mul_add_without_gc: failed"); @@ -158,32 +187,35 @@ rb_darray_calloc_mul_add_without_gc(size_t x, size_t y, size_t z) return ptr; } -/* Internal function. Like rb_xrealloc_mul_add but does not trigger GC and does - * not check for overflow in arithmetic. */ +/* Internal function. Like rb_xrealloc_mul_add. */ static inline void * -rb_darray_realloc_mul_add_without_gc(const void *orig_ptr, size_t x, size_t y, size_t z) +rb_darray_realloc_mul_add(void *orig_ptr, size_t x, size_t y, size_t z) { - size_t size = (x * y) + z; + size_t size = rbimpl_size_add_or_raise(rbimpl_size_mul_or_raise(x, y), z); - void *ptr = realloc((void *)orig_ptr, size); - if (ptr == NULL) rb_bug("rb_darray_realloc_mul_add_without_gc: failed"); + void *ptr = xrealloc(orig_ptr, size); + RUBY_ASSERT(ptr != NULL); return ptr; } -/* Internal function. Returns the next power of two that is greater than or - * equal to n. */ -static inline size_t -rb_darray_next_power_of_two(size_t n) +/* Internal function. Like rb_xrealloc_mul_add but does not trigger GC. */ +static inline void * +rb_darray_realloc_mul_add_without_gc(void *orig_ptr, size_t x, size_t y, size_t z) { - return (size_t)(1 << (64 - nlz_int64(n))); + size_t size = rbimpl_size_add_or_raise(rbimpl_size_mul_or_raise(x, y), z); + + void *ptr = realloc(orig_ptr, size); + if (ptr == NULL) rb_bug("rb_darray_realloc_mul_add_without_gc: failed"); + + return ptr; } /* Internal function. Resizes the capacity of a darray. The new capacity must * be greater than or equal to the size of the darray. */ static inline void rb_darray_resize_capa_impl(void *ptr_to_ary, size_t new_capa, size_t header_size, size_t element_size, - void *(*realloc_mul_add_impl)(const void *, size_t, size_t, size_t)) + void *(*realloc_mul_add_impl)(void *, size_t, size_t, size_t)) { rb_darray_meta_t **ptr_to_ptr_to_meta = ptr_to_ary; rb_darray_meta_t *meta = *ptr_to_ptr_to_meta; @@ -196,7 +228,7 @@ rb_darray_resize_capa_impl(void *ptr_to_ary, size_t new_capa, size_t header_size new_ary->size = 0; } - assert(new_ary->size <= new_capa); + RUBY_ASSERT(new_ary->size <= new_capa); new_ary->capa = new_capa; @@ -210,7 +242,7 @@ rb_darray_resize_capa_impl(void *ptr_to_ary, size_t new_capa, size_t header_size // Note: header_size can be bigger than sizeof(rb_darray_meta_t) when T is __int128_t, for example. static inline void rb_darray_ensure_space(void *ptr_to_ary, size_t header_size, size_t element_size, - void *(*realloc_mul_add_impl)(const void *, size_t, size_t, size_t)) + void *(*realloc_mul_add_impl)(void *, size_t, size_t, size_t)) { rb_darray_meta_t **ptr_to_ptr_to_meta = ptr_to_ary; rb_darray_meta_t *meta = *ptr_to_ptr_to_meta; diff --git a/debug.c b/debug.c index b5cba590bab5d3..4717a0bc9c5e90 100644 --- a/debug.c +++ b/debug.c @@ -147,12 +147,20 @@ NODE * ruby_debug_print_node(int level, int debug_level, const char *header, const NODE *node) { if (level < debug_level) { - fprintf(stderr, "DBG> %s: %s (%u)\n", header, - ruby_node_name(nd_type(node)), nd_line(node)); + fprintf(stderr, "DBG> %s: %s (id: %d, line: %d, location: (%d,%d)-(%d,%d))\n", + header, ruby_node_name(nd_type(node)), nd_node_id(node), nd_line(node), + nd_first_lineno(node), nd_first_column(node), + nd_last_lineno(node), nd_last_column(node)); } return (NODE *)node; } +void +ruby_debug_print_n(const NODE *node) +{ + ruby_debug_print_node(0, 1, "", node); +} + void ruby_debug_breakpoint(void) { @@ -177,9 +185,9 @@ ruby_env_debug_option(const char *str, int len, void *arg) int ov; size_t retlen; unsigned long n; +#define NAME_MATCH(name) (len == sizeof(name) - 1 && strncmp(str, (name), len) == 0) #define SET_WHEN(name, var, val) do { \ - if (len == sizeof(name) - 1 && \ - strncmp(str, (name), len) == 0) { \ + if (NAME_MATCH(name)) { \ (var) = (val); \ return 1; \ } \ @@ -207,31 +215,31 @@ ruby_env_debug_option(const char *str, int len, void *arg) --len; \ } \ if (len > 0) { \ - fprintf(stderr, "ignored "name" option: `%.*s'\n", len, str); \ + fprintf(stderr, "ignored "name" option: '%.*s'\n", len, str); \ } \ } while (0) #define SET_WHEN_UINT(name, vals, num, req) \ - if (NAME_MATCH_VALUE(name)) SET_UINT_LIST(name, vals, num); + if (NAME_MATCH_VALUE(name)) { \ + if (!len) req; \ + else SET_UINT_LIST(name, vals, num); \ + return 1; \ + } - SET_WHEN("gc_stress", *ruby_initial_gc_stress_ptr, Qtrue); - SET_WHEN("core", ruby_enable_coredump, 1); - SET_WHEN("ci", ruby_on_ci, 1); - if (NAME_MATCH_VALUE("rgengc")) { - if (!len) ruby_rgengc_debug = 1; - else SET_UINT_LIST("rgengc", &ruby_rgengc_debug, 1); + if (NAME_MATCH("gc_stress")) { + rb_gc_initial_stress_set(Qtrue); return 1; } + SET_WHEN("core", ruby_enable_coredump, 1); + SET_WHEN("ci", ruby_on_ci, 1); + SET_WHEN_UINT("rgengc", &ruby_rgengc_debug, 1, ruby_rgengc_debug = 1); #if defined _WIN32 # if RUBY_MSVCRT_VERSION >= 80 SET_WHEN("rtc_error", ruby_w32_rtc_error, 1); # endif #endif #if defined _WIN32 || defined __CYGWIN__ - if (NAME_MATCH_VALUE("codepage")) { - if (!len) fprintf(stderr, "missing codepage argument"); - else SET_UINT_LIST("codepage", ruby_w32_codepage, numberof(ruby_w32_codepage)); - return 1; - } + SET_WHEN_UINT("codepage", ruby_w32_codepage, numberof(ruby_w32_codepage), + fprintf(stderr, "missing codepage argument")); #endif return 0; } @@ -285,6 +293,12 @@ static const char *dlf_type_names[] = { "func", }; +#ifdef MAX_PATH +#define DEBUG_LOG_MAX_PATH (MAX_PATH-1) +#else +#define DEBUG_LOG_MAX_PATH 255 +#endif + static struct { char *mem; unsigned int cnt; @@ -292,6 +306,7 @@ static struct { unsigned int filters_num; bool show_pid; rb_nativethread_lock_t lock; + char output_file[DEBUG_LOG_MAX_PATH+1]; FILE *output; } debug_log; @@ -393,7 +408,39 @@ setup_debug_log(void) } else { ruby_debug_log_mode |= ruby_debug_log_file; - if ((debug_log.output = fopen(log_config, "w")) == NULL) { + + // pid extension with %p + unsigned long len = strlen(log_config); + + for (unsigned long i=0, j=0; i= DEBUG_LOG_MAX_PATH) { + fprintf(stderr, "RUBY_DEBUG_LOG=%s is too long\n", log_config); + exit(1); + } + } + + if ((debug_log.output = fopen(debug_log.output_file, "w")) == NULL) { fprintf(stderr, "can not open %s for RUBY_DEBUG_LOG\n", log_config); exit(1); } @@ -404,6 +451,10 @@ setup_debug_log(void) (ruby_debug_log_mode & ruby_debug_log_memory) ? "[mem]" : "", (ruby_debug_log_mode & ruby_debug_log_stderr) ? "[stderr]" : "", (ruby_debug_log_mode & ruby_debug_log_file) ? "[file]" : ""); + if (debug_log.output_file[0]) { + fprintf(stderr, "RUBY_DEBUG_LOG filename=%s\n", debug_log.output_file); + } + rb_nativethread_lock_initialize(&debug_log.lock); setup_debug_log_filter(); @@ -570,10 +621,11 @@ ruby_debug_log(const char *file, int line, const char *func_name, const char *fm // ractor information if (ruby_single_main_ractor == NULL) { rb_ractor_t *cr = th ? th->ractor : NULL; + rb_vm_t *vm = GET_VM(); if (r && len < MAX_DEBUG_LOG_MESSAGE_LEN) { - r = snprintf(buff + len, MAX_DEBUG_LOG_MESSAGE_LEN - len, "\tr:#%d/%u", - cr ? (int)rb_ractor_id(cr) : -1, GET_VM()->ractor.cnt); + r = snprintf(buff + len, MAX_DEBUG_LOG_MESSAGE_LEN - len, "\tr:#%d/%u (%u)", + cr ? (int)rb_ractor_id(cr) : -1, vm->ractor.cnt, vm->ractor.sched.running_cnt); if (r < 0) rb_bug("ruby_debug_log returns %d", r); len += r; @@ -631,7 +683,7 @@ debug_log_dump(FILE *out, unsigned int n) int index = current_index - size + i; if (index < 0) index += MAX_DEBUG_LOG; VM_ASSERT(index <= MAX_DEBUG_LOG); - const char *mesg = RUBY_DEBUG_LOG_MEM_ENTRY(index);; + const char *mesg = RUBY_DEBUG_LOG_MEM_ENTRY(index); fprintf(out, "%4u: %s\n", debug_log.cnt - size + i, mesg); } } diff --git a/debug_counter.h b/debug_counter.h index a8b95edded258b..fada7513aa7b10 100644 --- a/debug_counter.h +++ b/debug_counter.h @@ -315,6 +315,10 @@ RB_DEBUG_COUNTER(obj_imemo_parser_strterm) RB_DEBUG_COUNTER(obj_imemo_callinfo) RB_DEBUG_COUNTER(obj_imemo_callcache) RB_DEBUG_COUNTER(obj_imemo_constcache) +RB_DEBUG_COUNTER(obj_imemo_fields) + +RB_DEBUG_COUNTER(opt_new_hit) +RB_DEBUG_COUNTER(opt_new_miss) /* ar_table */ RB_DEBUG_COUNTER(artable_hint_hit) @@ -356,7 +360,7 @@ RB_DEBUG_COUNTER(load_path_is_not_realpath) enum rb_debug_counter_type { #define RB_DEBUG_COUNTER(name) RB_DEBUG_COUNTER_##name, -#include __FILE__ +#include "debug_counter.h" RB_DEBUG_COUNTER_MAX #undef RB_DEBUG_COUNTER }; diff --git a/defs/gmake.mk b/defs/gmake.mk index 155122376ad025..a81d82eadd278c 100644 --- a/defs/gmake.mk +++ b/defs/gmake.mk @@ -37,7 +37,7 @@ TEST_TARGETS := $(patsubst test,test-short,$(TEST_TARGETS)) TEST_DEPENDS := $(filter-out test $(TEST_TARGETS),$(TEST_DEPENDS)) TEST_TARGETS := $(patsubst test-short,btest-ruby test-knownbug test-basic,$(TEST_TARGETS)) TEST_TARGETS := $(patsubst test-basic,test-basic test-leaked-globals,$(TEST_TARGETS)) -TEST_TARGETS := $(patsubst test-bundled-gems,test-bundled-gems-run,$(TEST_TARGETS)) +TEST_TARGETS := $(patsubst test-bundled-gems,test-bundled-gems-spec test-bundled-gems-run,$(TEST_TARGETS)) TEST_TARGETS := $(patsubst test-bundled-gems-run,test-bundled-gems-run $(PREPARE_BUNDLED_GEMS),$(TEST_TARGETS)) TEST_TARGETS := $(patsubst test-bundled-gems-prepare,test-bundled-gems-prepare $(PRECHECK_BUNDLED_GEMS) test-bundled-gems-fetch,$(TEST_TARGETS)) TEST_TARGETS := $(patsubst test-bundler-parallel,test-bundler-parallel $(PREPARE_BUNDLER),$(TEST_TARGETS)) @@ -97,6 +97,7 @@ ORDERED_TEST_TARGETS := $(filter $(TEST_TARGETS), \ test-bundler-prepare test-bundler test-bundler-parallel \ test-bundled-gems-precheck test-bundled-gems-fetch \ test-bundled-gems-prepare test-bundled-gems-run \ + test-bundled-gems-spec \ ) # grep ^yes-test-.*-precheck: template/Makefile.in defs/gmake.mk common.mk @@ -193,15 +194,22 @@ $(SCRIPTBINDIR): $(Q) mkdir $@ .PHONY: commit -commit: $(if $(filter commit,$(MAKECMDGOALS)),$(filter-out commit,$(MAKECMDGOALS))) up +COMMIT_PREPARE := $(subst :,\:,$(filter-out commit do-commit,$(MAKECMDGOALS))) up + +commit: pre-commit $(DOT_WAIT) do-commit $(DOT_WAIT) post_commit +pre-commit: $(COMMIT_PREPARE) +do-commit: $(if $(DOT_WAIT),,pre-commit) @$(BASERUBY) -C "$(srcdir)" -I./tool/lib -rvcs -e 'VCS.detect(".").commit' +post-commit: $(if $(DOT_WAIT),,do-commit) +$(Q) \ { \ $(in-srcdir) \ exec sed -f tool/prereq.status defs/gmake.mk template/Makefile.in common.mk; \ } | \ - $(MAKE) $(mflags) Q=$(Q) ECHO=$(ECHO) srcdir="$(srcdir)" srcs_vpath="" CHDIR="$(CHDIR)" \ - BOOTSTRAPRUBY="$(BOOTSTRAPRUBY)" MINIRUBY="$(BASERUBY)" BASERUBY="$(BASERUBY)" \ + $(MAKE) $(mflags) Q=$(Q) ECHO=$(ECHO) \ + top_srcdir="$(top_srcdir)" srcdir="$(srcdir)" srcs_vpath="" CHDIR="$(CHDIR)" \ + BOOTSTRAPRUBY="$(BOOTSTRAPRUBY)" BOOTSTRAPRUBY_OPT="$(BOOTSTRAPRUBY_OPT)" \ + MINIRUBY="$(BASERUBY)" BASERUBY="$(BASERUBY)" HAVE_BASERUBY="$(HAVE_BASERUBY)" \ VCSUP="" ENC_MK=.top-enc.mk REVISION_FORCE=PHONY CONFIGURE="$(CONFIGURE)" -f - \ update-src srcs all-incs @@ -357,16 +365,18 @@ $(srcdir)/.bundle/.timestamp: define build-gem $(srcdir)/gems/src/$(1)/.git: | $(srcdir)/gems/src $(ECHO) Cloning $(4) - $(Q) $(GIT) clone $(4) $$(@D) + $(Q) $(GIT) clone --depth=1 --no-tags $(4) $$(@D) $(bundled-gem-revision): \ $(if $(if $(wildcard $$(@)),$(filter $(3),$(shell cat $$(@)))),,PHONY) \ | $(srcdir)/.bundle/.timestamp $(srcdir)/gems/src/$(1)/.git $(ECHO) Update $(1) to $(3) $(Q) $(CHDIR) "$(srcdir)/gems/src/$(1)" && \ - $(GIT) fetch origin $(3) && \ - $(GIT) checkout --detach $(3) && \ - : + if [ `$(GIT) rev-parse HEAD` != $(3) ]; then \ + $(GIT) fetch origin $(3) && \ + $(GIT) checkout --detach $(3) && \ + :; \ + fi echo $(3) | $(IFCHANGE) $$(@) - # The repository of minitest does not include minitest.gemspec because it uses hoe. @@ -407,6 +417,17 @@ endif .SECONDARY: update-unicode-ucd-emoji-files .SECONDARY: update-unicode-emoji-files +ifneq ($(DOT_WAIT),) +.NOTPARALLEL: update-unicode +.NOTPARALLEL: update-unicode-files +.NOTPARALLEL: update-unicode-auxiliary-files +.NOTPARALLEL: update-unicode-ucd-emoji-files +.NOTPARALLEL: update-unicode-emoji-files +.NOTPARALLEL: $(UNICODE_FILES) $(UNICODE_PROPERTY_FILES) +.NOTPARALLEL: $(UNICODE_AUXILIARY_FILES) +.NOTPARALLEL: $(UNICODE_UCD_EMOJI_FILES) $(UNICODE_EMOJI_FILES) +endif + ifeq ($(HAVE_GIT),yes) REVISION_LATEST := $(shell $(CHDIR) $(srcdir) && $(GIT) log -1 --format=%H 2>/dev/null) else @@ -421,6 +442,8 @@ $(REVISION_H): PHONY endif include $(top_srcdir)/yjit/yjit.mk +include $(top_srcdir)/zjit/zjit.mk +include $(top_srcdir)/defs/jit.mk # Query on the generated rdoc # @@ -449,6 +472,10 @@ benchmark/%: miniruby$(EXEEXT) update-benchmark-driver PHONY --executables="built-ruby::$(BENCH_RUBY) --disable-gem" \ $(srcdir)/$@ $(BENCH_OPTS) $(OPTS) +clean-local:: TARGET_SO = $(PROGRAM) $(WPROGRAM) $(LIBRUBY_SO) $(STATIC_RUBY) miniruby goruby +clean-local:: + -$(Q)$(RMALL) $(cleanlibs) + clean-srcs-ext:: $(Q)$(RM) $(patsubst $(srcdir)/%,%,$(EXT_SRCS)) @@ -480,13 +507,18 @@ update-deps: # order-only-prerequisites doesn't work for $(RUBYSPEC_CAPIEXT) # because the same named directory exists in the source tree. -$(RUBYSPEC_CAPIEXT)/%.$(DLEXT): $(srcdir)/$(RUBYSPEC_CAPIEXT)/%.c $(srcdir)/$(RUBYSPEC_CAPIEXT)/rubyspec.h $(RUBY_H_INCLUDES) $(LIBRUBY) +$(RUBYSPEC_CAPIEXT)/%.$(DLEXT): $(srcdir)/$(RUBYSPEC_CAPIEXT)/%.c $(RUBYSPEC_CAPIEXT_DEPS) \ + | build-ext $(ECHO) building $@ $(Q) $(MAKEDIRS) $(@D) $(Q) $(DLDSHARED) -L. $(XDLDFLAGS) $(XLDFLAGS) $(LDFLAGS) $(INCFLAGS) $(CPPFLAGS) $(OUTFLAG)$@ $< $(LIBRUBYARG) +ifneq ($(POSTLINK),) + $(Q) $(POSTLINK) +endif $(Q) $(RMALL) $@.* -rubyspec-capiext: $(patsubst %.c,$(RUBYSPEC_CAPIEXT)/%.$(DLEXT),$(notdir $(wildcard $(srcdir)/$(RUBYSPEC_CAPIEXT)/*.c))) +RUBYSPEC_CAPIEXT_SO := $(patsubst %.c,$(RUBYSPEC_CAPIEXT)/%.$(DLEXT),$(notdir $(wildcard $(srcdir)/$(RUBYSPEC_CAPIEXT)/*.c))) +rubyspec-capiext: $(RUBYSPEC_CAPIEXT_SO) @ $(NULLCMD) ifeq ($(ENABLE_SHARED),yes) @@ -499,20 +531,39 @@ spec/%/ spec/%_spec.rb: programs exts PHONY ruby.pc: $(filter-out ruby.pc,$(ruby_pc)) matz: up + $(eval OLD := $(MAJOR).$(MINOR).0) $(eval MINOR := $(shell expr $(MINOR) + 1)) - $(eval message := Development of $(MAJOR).$(MINOR).0 started.) + $(eval NEW := $(MAJOR).$(MINOR).0) + $(eval message := Development of $(NEW) started.) $(eval files := include/ruby/version.h include/ruby/internal/abi.h) + $(GIT) -C $(srcdir) mv -f NEWS.md doc/NEWS/NEWS-$(OLD).md + $(GIT) -C $(srcdir) commit -m "[DOC] Flush NEWS.md" sed -i~ \ -e "s/^\(#define RUBY_API_VERSION_MINOR\) .*/\1 $(MINOR)/" \ -e "s/^\(#define RUBY_ABI_VERSION\) .*/\1 0/" \ $(files:%=$(srcdir)/%) - $(GIT) -C $(srcdir) commit -m "$(message)" $(files) + $(GIT) -C $(srcdir) add $(files) + $(BASERUBY) -C $(srcdir) -p -00 \ + -e 'BEGIN {old, new = ARGV.shift(2); STDOUT.reopen("NEWS.md")}' \ + -e 'case $$.' \ + -e 'when 1; $$_.sub!(/Ruby \K[0-9.]+/, new)' \ + -e 'when 2; $$_.sub!(/\*\*\K[0-9.]+(?=\*\*)/, old)' \ + -e 'end' \ + -e 'next if /^[\[ *]/ =~ $$_' \ + -e '$$_.sub!(/\n{2,}\z/, "\n\n")' \ + $(OLD) $(NEW) doc/NEWS/NEWS-$(OLD).md + $(GIT) -C $(srcdir) add NEWS.md + $(GIT) -C $(srcdir) commit -m "$(message)" tags: $(MAKE) GIT="$(GIT)" -C "$(srcdir)" -f defs/tags.mk + +# ripper_srcs makes all sources at once. invoking this target multiple +# times in parallel means all sources will be built for the number of +# sources times respectively. ifneq ($(DOT_WAIT),) -ripper_srcs: $(addprefix $(DOT_WAIT) ,$(RIPPER_SRCS)) +.NOTPARALLEL: ripper_srcs else ripper_src = $(foreach r,$(RIPPER_SRCS),$(eval $(value r): | $(value ripper_src))\ diff --git a/defs/id.def b/defs/id.def index 2ddde7be70702a..0c32b0d1d4ab97 100644 --- a/defs/id.def +++ b/defs/id.def @@ -8,6 +8,7 @@ firstline, predefined = __LINE__+1, %[\ inspect intern object_id + __id__ const_added const_missing method_missing MethodMissing @@ -59,6 +60,11 @@ firstline, predefined = __LINE__+1, %[\ name nil path + pack + buffer + include? + aborted + exited _ UScore @@ -97,6 +103,8 @@ firstline, predefined = __LINE__+1, %[\ $_ LASTLINE $~ BACKREF $! ERROR_INFO + + Ruby ] # VM ID OP Parser Token diff --git a/defs/jit.mk b/defs/jit.mk new file mode 100644 index 00000000000000..99f21fb51399bb --- /dev/null +++ b/defs/jit.mk @@ -0,0 +1,58 @@ +# Make recipes that deal with the rust code of YJIT and ZJIT. + +# Because of Cargo cache, if the actual binary is not changed from the +# previous build, the mtime is preserved as the cached file. +# This means the target is not updated actually, and it will need to +# rebuild at the next build. +RUST_LIB_TOUCH = touch $@ + +ifneq ($(JIT_CARGO_SUPPORT),no) +# NOTE: MACOSX_DEPLOYMENT_TARGET to match `rustc --print deployment-target` to avoid the warning below. +# ld: warning: object file (target/debug/libjit.a()) was built for +# newer macOS version (15.2) than being linked (15.0) +# This limits us to an older set of macOS API in the rust code, but we don't use any. +$(RUST_LIB): $(srcdir)/jit.rs + $(Q)if [ '$(ZJIT_SUPPORT)' != no -a '$(YJIT_SUPPORT)' != no ]; then \ + echo 'building YJIT and ZJIT ($(JIT_CARGO_SUPPORT:yes=release) mode)'; \ + elif [ '$(ZJIT_SUPPORT)' != no ]; then \ + echo 'building ZJIT ($(JIT_CARGO_SUPPORT) mode)'; \ + elif [ '$(YJIT_SUPPORT)' != no ]; then \ + echo 'building YJIT ($(JIT_CARGO_SUPPORT) mode)'; \ + fi + +$(Q)CARGO_TARGET_DIR='$(CARGO_TARGET_DIR)' \ + CARGO_TERM_PROGRESS_WHEN='never' \ + MACOSX_DEPLOYMENT_TARGET=11.0 \ + $(CARGO) $(CARGO_VERBOSE) build --manifest-path '$(top_srcdir)/Cargo.toml' $(CARGO_BUILD_ARGS) + $(RUST_LIB_TOUCH) +endif + +RUST_LIB_SYMBOLS = $(RUST_LIB:.a=).symbols +$(RUST_LIBOBJ): $(RUST_LIB) + $(ECHO) 'partial linking $(RUST_LIB) into $@' +ifneq ($(findstring darwin,$(target_os)),) + $(Q) $(CC) -nodefaultlibs -r -o $@ -exported_symbols_list $(RUST_LIB_SYMBOLS) $(RUST_LIB) +else + $(Q) $(LD) -r -o $@ --whole-archive $(RUST_LIB) + -$(Q) $(OBJCOPY) --wildcard --keep-global-symbol='$(SYMBOL_PREFIX)rb_*' $(@) +endif + +rust-libobj: $(RUST_LIBOBJ) +rust-lib: $(RUST_LIB) + +# For Darwin only: a list of symbols that we want the glommed Rust static lib to export. +# Unfortunately, using wildcard like '_rb_*' with -exported-symbol does not work, at least +# not on version 820.1. Assume llvm-nm, so XCode 8.0 (from 2016) or newer. +# +# The -exported_symbols_list pulls out the right archive members. Symbols not listed +# in the list are made private extern, which are in turn made local as we're using `ld -r`. +# Note, section about -keep_private_externs in ld's man page hints at this behavior on which +# we rely. +ifneq ($(findstring darwin,$(target_os)),) +$(RUST_LIB_SYMBOLS): $(RUST_LIB) + $(Q) $(tooldir)/darwin-ar $(NM) --defined-only --extern-only $(RUST_LIB) | \ + sed -n -e 's/.* //' -e '/^$(SYMBOL_PREFIX)rb_/p' \ + -e '/^$(SYMBOL_PREFIX)rust_eh_personality/p' \ + > $@ + +$(RUST_LIBOBJ): $(RUST_LIB_SYMBOLS) +endif diff --git a/defs/known_errors.def b/defs/known_errors.def index e9694cfbda684b..23e9e535078042 100644 --- a/defs/known_errors.def +++ b/defs/known_errors.def @@ -1,157 +1,157 @@ -E2BIG -EACCES -EADDRINUSE -EADDRNOTAVAIL -EADV -EAFNOSUPPORT -EAGAIN -EALREADY -EAUTH -EBADARCH -EBADE -EBADEXEC -EBADF -EBADFD -EBADMACHO -EBADMSG -EBADR -EBADRPC -EBADRQC -EBADSLT -EBFONT -EBUSY -ECANCELED -ECAPMODE -ECHILD -ECHRNG -ECOMM -ECONNABORTED -ECONNREFUSED -ECONNRESET -EDEADLK -EDEADLOCK -EDESTADDRREQ -EDEVERR -EDOM -EDOOFUS -EDOTDOT -EDQUOT -EEXIST -EFAULT -EFBIG -EFTYPE -EHOSTDOWN -EHOSTUNREACH -EHWPOISON -EIDRM -EILSEQ -EINPROGRESS -EINTR -EINVAL -EIO -EIPSEC -EISCONN -EISDIR -EISNAM -EKEYEXPIRED -EKEYREJECTED -EKEYREVOKED -EL2HLT -EL2NSYNC -EL3HLT -EL3RST -ELAST -ELIBACC -ELIBBAD -ELIBEXEC -ELIBMAX -ELIBSCN -ELNRNG -ELOOP -EMEDIUMTYPE -EMFILE -EMLINK -EMSGSIZE -EMULTIHOP -ENAMETOOLONG -ENAVAIL -ENEEDAUTH -ENETDOWN -ENETRESET -ENETUNREACH -ENFILE -ENOANO -ENOATTR -ENOBUFS -ENOCSI -ENODATA -ENODEV -ENOENT -ENOEXEC -ENOKEY -ENOLCK -ENOLINK -ENOMEDIUM -ENOMEM -ENOMSG -ENONET -ENOPKG -ENOPOLICY -ENOPROTOOPT -ENOSPC -ENOSR -ENOSTR -ENOSYS -ENOTBLK -ENOTCAPABLE -ENOTCONN -ENOTDIR -ENOTEMPTY -ENOTNAM -ENOTRECOVERABLE -ENOTSOCK -ENOTSUP -ENOTTY -ENOTUNIQ -ENXIO -EOPNOTSUPP -EOVERFLOW -EOWNERDEAD -EPERM -EPFNOSUPPORT -EPIPE -EPROCLIM -EPROCUNAVAIL -EPROGMISMATCH -EPROGUNAVAIL -EPROTO -EPROTONOSUPPORT -EPROTOTYPE -EPWROFF -EQFULL -ERANGE -EREMCHG -EREMOTE -EREMOTEIO -ERESTART -ERFKILL -EROFS -ERPCMISMATCH -ESHLIBVERS -ESHUTDOWN -ESOCKTNOSUPPORT -ESPIPE -ESRCH -ESRMNT -ESTALE -ESTRPIPE -ETIME -ETIMEDOUT -ETOOMANYREFS -ETXTBSY -EUCLEAN -EUNATCH -EUSERS -EWOULDBLOCK -EXDEV -EXFULL +E2BIG Argument list too long +EACCES Permission denied +EADDRINUSE Address already in use +EADDRNOTAVAIL Address not available +EADV Advertise error +EAFNOSUPPORT Address family not supported +EAGAIN Resource temporarily unavailable, try again (may be the same value as EWOULDBLOCK) +EALREADY Connection already in progress +EAUTH Authentication error +EBADARCH Bad CPU type in executable +EBADE Bad exchange +EBADEXEC Bad executable +EBADF Bad file descriptor +EBADFD File descriptor in bad state +EBADMACHO Malformed Macho file +EBADMSG Bad message +EBADR Invalid request descriptor +EBADRPC RPC struct is bad +EBADRQC Invalid request code +EBADSLT Invalid slot +EBFONT Bad font file format +EBUSY Device or resource busy +ECANCELED Operation canceled +ECAPMODE Not permitted in capability mode +ECHILD No child processes +ECHRNG Channel number out of range +ECOMM Communication error on send +ECONNABORTED Connection aborted +ECONNREFUSED Connection refused +ECONNRESET Connection reset +EDEADLK Resource deadlock avoided +EDEADLOCK File locking deadlock error +EDESTADDRREQ Destination address required +EDEVERR Device error; e.g., printer paper out +EDOM Mathematics argument out of domain of function +EDOOFUS Improper function use +EDOTDOT RFS specific error +EDQUOT Disk quota exceeded +EEXIST File exists +EFAULT Bad address +EFBIG File too large +EFTYPE Invalid file type or format +EHOSTDOWN Host is down +EHOSTUNREACH Host is unreachable +EHWPOISON Memory page has hardware error +EIDRM Identifier removed +EILSEQ Invalid or incomplete multibyte or wide character +EINPROGRESS Operation in progress +EINTR Interrupted function call +EINVAL Invalid argument +EIO Input/output error +EIPSEC IPsec processing failure +EISCONN Socket is connected +EISDIR Is a directory +EISNAM Is a named file type +EKEYEXPIRED Key has expired +EKEYREJECTED Key was rejected by service +EKEYREVOKED Key has been revoked +EL2HLT Level 2 halted +EL2NSYNC Level 2 not synchronized +EL3HLT Level 3 halted +EL3RST Level 3 reset +ELIBACC Cannot access a needed shared library +ELIBBAD Accessing a corrupted shared library +ELIBEXEC Cannot exec a shared library directly +ELIBMAX Attempting to link in too many shared libraries +ELIBSCN .lib section in a.out corrupted +ELNRNG Link number out of range +ELOOP Too many levels of symbolic links +EMEDIUMTYPE Wrong medium type +EMFILE Too many open files +EMLINK Too many links +EMSGSIZE Message too long +EMULTIHOP Multihop attempted +ENAMETOOLONG Filename too long +ENAVAIL No XENIX semaphores available +ENEEDAUTH Need authenticator +ENETDOWN Network is down +ENETRESET Connection aborted by network +ENETUNREACH Network unreachable +ENFILE Too many open files in system +ENOANO No anode +ENOATTR Attribute not found +ENOBUFS No buffer space available +ENOCSI No CSI structure available +ENODATA No data available +ENODEV No such device +ENOENT No such file or directory +ENOEXEC Exec format error +ENOKEY Required key not available +ENOLCK No locks available +ENOLINK Link has been severed +ENOMEDIUM No medium found +ENOMEM Not enough space/cannot allocate memory +ENOMSG No message of the desired type +ENONET Machine is not on the network +ENOPKG Package not installed +ENOPOLICY No such policy +ENOPROTOOPT Protocol not available +ENOSPC No space left on device +ENOSR No STREAM resources +ENOSTR Not a STREAM +ENOSYS Functionality not implemented +ENOTBLK Block device required +ENOTCAPABLE Capabilities insufficient +ENOTCONN The socket is not connected +ENOTDIR Not a directory +ENOTEMPTY Directory not empty +ENOTNAM Not a XENIX named type file +ENOTRECOVERABLE State not recoverable +ENOTSOCK Not a socket +ENOTSUP Operation not supported +ENOTTY Inappropriate I/O control operation +ENOTUNIQ Name not unique on network +ENXIO No such device or address +EOPNOTSUPP Operation not supported on socket +EOVERFLOW Value too large to be stored in data type +EOWNERDEAD Owner died +EPERM Operation not permitted +EPFNOSUPPORT Protocol family not supported +EPIPE Broken pipe +EPROCLIM Too many processes +EPROCUNAVAIL Bad procedure for program +EPROGMISMATCH Program version wrong +EPROGUNAVAIL RPC program isn't available +EPROTO Protocol error +EPROTONOSUPPORT Protocol not supported +EPROTOTYPE Protocol wrong type for socket +EPWROFF Device power is off +EQFULL Interface output queue is full +ERANGE Result too large +EREMCHG Remote address changed +EREMOTE Object is remote +EREMOTEIO Remote I/O error +ERESTART Interrupted system call should be restarted +ERFKILL Operation not possible due to RF-kill +EROFS Read-only file system +ERPCMISMATCH RPC version wrong +ESHLIBVERS Shared library version mismatch +ESHUTDOWN Cannot send after transport endpoint shutdown +ESOCKTNOSUPPORT Socket type not supported +ESPIPE Illegal seek +ESRCH No such process +ESRMNT Server mount error +ESTALE Stale file handle +ESTRPIPE Streams pipe error +ETIME Timer expired +ETIMEDOUT Connection timed out +ETOOMANYREFS Too many references: cannot splice +ETXTBSY Text file busy +EUCLEAN Structure needs cleaning +EUNATCH Protocol driver not attached +EUSERS Too many users +EWOULDBLOCK Operation would block +EXDEV Invalid cross-device link +EXFULL Exchange full +ELAST Largest errno value diff --git a/dir.c b/dir.c index 4dbdc44e8a6e34..b934f2795c90e0 100644 --- a/dir.c +++ b/dir.c @@ -22,10 +22,6 @@ #include #endif -#ifndef O_CLOEXEC -# define O_CLOEXEC 0 -#endif - #ifndef USE_OPENDIR_AT # if defined(HAVE_FDOPENDIR) && defined(HAVE_DIRFD) && \ defined(HAVE_OPENAT) && defined(HAVE_FSTATAT) @@ -35,8 +31,12 @@ # endif #endif -#if USE_OPENDIR_AT -# include +#ifdef HAVE_FCNTL_H +# include +#endif + +#ifndef O_CLOEXEC +# define O_CLOEXEC 0 #endif #undef HAVE_DIRENT_NAMLEN @@ -113,6 +113,7 @@ char *strchr(char*,char); #include "internal/gc.h" #include "internal/io.h" #include "internal/object.h" +#include "internal/imemo.h" #include "internal/vm.h" #include "ruby/encoding.h" #include "ruby/ruby.h" @@ -142,6 +143,50 @@ char *strchr(char*,char); # define IS_WIN32 0 #endif +#ifdef HAVE_GETATTRLIST +struct getattrlist_args { + const char *path; + int fd; + struct attrlist *list; + void *buf; + size_t size; + unsigned int options; +}; + +# define GETATTRLIST_ARGS(list_, buf_, options_) (struct getattrlist_args) \ + {.list = list_, .buf = buf_, .size = sizeof(buf_), .options = options_} + +static void * +nogvl_getattrlist(void *args) +{ + struct getattrlist_args *arg = args; + return (void *)(VALUE)getattrlist(arg->path, arg->list, arg->buf, arg->size, arg->options); +} + +static int +gvl_getattrlist(struct getattrlist_args *args, const char *path) +{ + args->path = path; + return IO_WITHOUT_GVL_INT(nogvl_getattrlist, args); +} + +# ifdef HAVE_FGETATTRLIST +static void * +nogvl_fgetattrlist(void *args) +{ + struct getattrlist_args *arg = args; + return (void *)(VALUE)fgetattrlist(arg->fd, arg->list, arg->buf, arg->size, arg->options); +} + +static int +gvl_fgetattrlist(struct getattrlist_args *args, int fd) +{ + args->fd = fd; + return IO_WITHOUT_GVL_INT(nogvl_fgetattrlist, args); +} +# endif +#endif + #if NORMALIZE_UTF8PATH # if defined HAVE_FGETATTRLIST || !defined HAVE_GETATTRLIST # define need_normalization(dirp, path) need_normalization(dirp) @@ -154,10 +199,11 @@ need_normalization(DIR *dirp, const char *path) # if defined HAVE_FGETATTRLIST || defined HAVE_GETATTRLIST u_int32_t attrbuf[SIZEUP32(fsobj_tag_t)]; struct attrlist al = {ATTR_BIT_MAP_COUNT, 0, ATTR_CMN_OBJTAG,}; + struct getattrlist_args args = GETATTRLIST_ARGS(&al, attrbuf, 0); # if defined HAVE_FGETATTRLIST - int ret = fgetattrlist(dirfd(dirp), &al, attrbuf, sizeof(attrbuf), 0); + int ret = gvl_fgetattrlist(&args, dirfd(dirp)); # else - int ret = getattrlist(path, &al, attrbuf, sizeof(attrbuf), 0); + int ret = gvl_getattrlist(&args, path); # endif if (!ret) { const fsobj_tag_t *tag = (void *)(attrbuf+1); @@ -471,23 +517,21 @@ dir_free(void *ptr) struct dir_data *dir = ptr; if (dir->dir) closedir(dir->dir); - xfree(dir); } -static size_t -dir_memsize(const void *ptr) -{ - return sizeof(struct dir_data); -} - -RUBY_REFERENCES_START(dir_refs) - REF_EDGE(dir_data, path), -RUBY_REFERENCES_END +RUBY_REFERENCES(dir_refs) = { + RUBY_REF_EDGE(struct dir_data, path), + RUBY_REF_END +}; static const rb_data_type_t dir_data_type = { "dir", - {REFS_LIST_PTR(dir_refs), dir_free, dir_memsize,}, - 0, NULL, RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_DECL_MARKING + { + RUBY_REFS_LIST_PTR(dir_refs), + dir_free, + NULL, // Nothing allocated externally, so don't need a memsize function + }, + 0, NULL, RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_DECL_MARKING | RUBY_TYPED_EMBEDDABLE }; static VALUE dir_close(VALUE); @@ -510,7 +554,7 @@ nogvl_opendir(void *ptr) { const char *path = ptr; - return (void *)opendir(path); + return opendir(path); } static DIR * @@ -521,12 +565,31 @@ opendir_without_gvl(const char *path) u.in = path; - return rb_thread_call_without_gvl(nogvl_opendir, u.out, RUBY_UBF_IO, 0); + return IO_WITHOUT_GVL(nogvl_opendir, u.out); } else return opendir(path); } +static void +close_dir_data(struct dir_data *dp) +{ + if (dp->dir) { + if (closedir(dp->dir) < 0) { + dp->dir = NULL; + rb_sys_fail("closedir"); + } + dp->dir = NULL; + } +} + +static void +check_closedir(DIR *dirp) +{ + if (closedir(dirp) < 0) + rb_sys_fail("closedir"); +} + static VALUE dir_initialize(rb_execution_context_t *ec, VALUE dir, VALUE dirname, VALUE enc) { @@ -541,8 +604,7 @@ dir_initialize(rb_execution_context_t *ec, VALUE dir, VALUE dirname, VALUE enc) dirname = rb_str_dup_frozen(dirname); TypedData_Get_Struct(dir, struct dir_data, &dir_data_type, dp); - if (dp->dir) closedir(dp->dir); - dp->dir = NULL; + close_dir_data(dp); RB_OBJ_WRITE(dir, &dp->path, Qnil); dp->enc = fsenc; path = RSTRING_PTR(dirname); @@ -556,7 +618,8 @@ dir_initialize(rb_execution_context_t *ec, VALUE dir, VALUE dirname, VALUE enc) else if (e == EIO) { u_int32_t attrbuf[1]; struct attrlist al = {ATTR_BIT_MAP_COUNT, 0}; - if (getattrlist(path, &al, attrbuf, sizeof(attrbuf), FSOPT_NOFOLLOW) == 0) { + struct getattrlist_args args = GETATTRLIST_ARGS(&al, attrbuf, FSOPT_NOFOLLOW); + if (gvl_getattrlist(&args, path) == 0) { dp->dir = opendir_without_gvl(path); } } @@ -589,6 +652,12 @@ dir_s_close(rb_execution_context_t *ec, VALUE klass, VALUE dir) } # if defined(HAVE_FDOPENDIR) && defined(HAVE_DIRFD) +static void * +nogvl_fdopendir(void *fd) +{ + return fdopendir((int)(VALUE)fd); +} + /* * call-seq: * Dir.for_fd(fd) -> dir @@ -615,7 +684,7 @@ dir_s_for_fd(VALUE klass, VALUE fd) struct dir_data *dp; VALUE dir = TypedData_Make_Struct(klass, struct dir_data, &dir_data_type, dp); - if (!(dp->dir = fdopendir(NUM2INT(fd)))) { + if (!(dp->dir = IO_WITHOUT_GVL(nogvl_fdopendir, (void *)(VALUE)NUM2INT(fd)))) { rb_sys_fail("fdopendir"); UNREACHABLE_RETURN(Qnil); } @@ -757,8 +826,28 @@ fundamental_encoding_p(rb_encoding *enc) } } # define READDIR(dir, enc) rb_w32_readdir((dir), (enc)) +# define READDIR_NOGVL READDIR #else -# define READDIR(dir, enc) readdir((dir)) +NORETURN(static void *sys_failure(void *function)); +static void * +sys_failure(void *function) +{ + rb_sys_fail(function); +} + +static void * +nogvl_readdir(void *dir) +{ + rb_errno_set(0); + if ((dir = readdir(dir)) == NULL) { + if (rb_errno()) + rb_thread_call_with_gvl(sys_failure, (void *)"readdir"); + } + return dir; +} + +# define READDIR(dir, enc) IO_WITHOUT_GVL(nogvl_readdir, (void *)(dir)) +# define READDIR_NOGVL(dir, enc) nogvl_readdir((dir)) #endif /* safe to use without GVL */ @@ -805,7 +894,7 @@ dir_read(VALUE dir) struct dirent *dp; GetDIR(dir, dirp); - errno = 0; + rb_errno_set(0); if ((dp = READDIR(dirp->dir, dirp->enc)) != NULL) { return rb_external_str_new_with_enc(dp->d_name, NAMLEN(dp), dirp->enc); } @@ -903,7 +992,8 @@ dir_tell(VALUE dir) long pos; GetDIR(dir, dirp); - pos = telldir(dirp->dir); + if((pos = telldir(dirp->dir)) < 0) + rb_sys_fail("telldir"); return rb_int2inum(pos); } #else @@ -1022,8 +1112,7 @@ dir_close(VALUE dir) dirp = dir_get(dir); if (!dirp->dir) return Qnil; - closedir(dirp->dir); - dirp->dir = NULL; + close_dir_data(dirp); return Qnil; } @@ -1039,16 +1128,68 @@ nogvl_chdir(void *ptr) static void dir_chdir0(VALUE path) { - if (chdir(RSTRING_PTR(path)) < 0) + if (IO_WITHOUT_GVL_INT(nogvl_chdir, (void*)RSTRING_PTR(path)) < 0) rb_sys_fail_path(path); } -static int chdir_blocking = 0; -static VALUE chdir_thread = Qnil; +static struct { + VALUE thread; + VALUE path; + int line; + int blocking; +} chdir_lock = { + .blocking = 0, .thread = Qnil, + .path = Qnil, .line = 0, +}; + +static void +chdir_enter(void) +{ + if (chdir_lock.blocking == 0) { + chdir_lock.path = rb_source_location(&chdir_lock.line); + } + chdir_lock.blocking++; + if (NIL_P(chdir_lock.thread)) { + chdir_lock.thread = rb_thread_current(); + } +} + +static void +chdir_leave(void) +{ + chdir_lock.blocking--; + if (chdir_lock.blocking == 0) { + chdir_lock.thread = Qnil; + chdir_lock.path = Qnil; + chdir_lock.line = 0; + } +} + +static int +chdir_alone_block_p(void) +{ + int block_given = rb_block_given_p(); + if (chdir_lock.blocking > 0) { + if (rb_thread_current() != chdir_lock.thread) + rb_raise(rb_eRuntimeError, "conflicting chdir during another chdir block"); + if (!block_given) { + if (!NIL_P(chdir_lock.path)) { + rb_warn("conflicting chdir during another chdir block\n" + "%" PRIsVALUE ":%d: note: previous chdir was here", + chdir_lock.path, chdir_lock.line); + } + else { + rb_warn("conflicting chdir during another chdir block"); + } + } + } + return block_given; +} struct chdir_data { VALUE old_path, new_path; int done; + bool yield_path; }; static VALUE @@ -1057,10 +1198,8 @@ chdir_yield(VALUE v) struct chdir_data *args = (void *)v; dir_chdir0(args->new_path); args->done = TRUE; - chdir_blocking++; - if (NIL_P(chdir_thread)) - chdir_thread = rb_thread_current(); - return rb_yield(args->new_path); + chdir_enter(); + return args->yield_path ? rb_yield(args->new_path) : rb_yield_values2(0, NULL); } static VALUE @@ -1068,14 +1207,34 @@ chdir_restore(VALUE v) { struct chdir_data *args = (void *)v; if (args->done) { - chdir_blocking--; - if (chdir_blocking == 0) - chdir_thread = Qnil; + chdir_leave(); dir_chdir0(args->old_path); } return Qnil; } +static VALUE +chdir_path(VALUE path, bool yield_path) +{ + if (chdir_alone_block_p()) { + struct chdir_data args; + + args.old_path = rb_str_encode_ospath(rb_dir_getwd()); + args.new_path = path; + args.done = FALSE; + args.yield_path = yield_path; + return rb_ensure(chdir_yield, (VALUE)&args, chdir_restore, (VALUE)&args); + } + else { + char *p = RSTRING_PTR(path); + int r = IO_WITHOUT_GVL_INT(nogvl_chdir, p); + if (r < 0) + rb_sys_fail_path(path); + } + + return INT2FIX(0); +} + /* * call-seq: * Dir.chdir(new_dirpath) -> 0 @@ -1102,7 +1261,7 @@ chdir_restore(VALUE v) * * - Calls the block with the argument. * - Changes to the given directory. - * - Executes the block + * - Executes the block (yielding the new path). * - Restores the previous working directory. * - Returns the block's return value. * @@ -1156,30 +1315,7 @@ dir_s_chdir(int argc, VALUE *argv, VALUE obj) path = rb_str_new2(dist); } - if (chdir_blocking > 0) { - if (rb_thread_current() != chdir_thread) - rb_raise(rb_eRuntimeError, "conflicting chdir during another chdir block"); - if (!rb_block_given_p()) - rb_warn("conflicting chdir during another chdir block"); - } - - if (rb_block_given_p()) { - struct chdir_data args; - - args.old_path = rb_str_encode_ospath(rb_dir_getwd()); - args.new_path = path; - args.done = FALSE; - return rb_ensure(chdir_yield, (VALUE)&args, chdir_restore, (VALUE)&args); - } - else { - char *p = RSTRING_PTR(path); - int r = (int)(VALUE)rb_thread_call_without_gvl(nogvl_chdir, p, - RUBY_UBF_IO, 0); - if (r < 0) - rb_sys_fail_path(path); - } - - return INT2FIX(0); + return chdir_path(path, true); } #if defined(HAVE_FCHDIR) && defined(HAVE_DIRFD) && HAVE_FCHDIR && HAVE_DIRFD @@ -1194,7 +1330,7 @@ nogvl_fchdir(void *ptr) static void dir_fchdir(int fd) { - if (fchdir(fd) < 0) + if (IO_WITHOUT_GVL_INT(nogvl_fchdir, (void *)&fd) < 0) rb_sys_fail("fchdir"); } @@ -1210,9 +1346,7 @@ fchdir_yield(VALUE v) struct fchdir_data *args = (void *)v; dir_fchdir(args->fd); args->done = TRUE; - chdir_blocking++; - if (NIL_P(chdir_thread)) - chdir_thread = rb_thread_current(); + chdir_enter(); return rb_yield_values(0); } @@ -1221,9 +1355,7 @@ fchdir_restore(VALUE v) { struct fchdir_data *args = (void *)v; if (args->done) { - chdir_blocking--; - if (chdir_blocking == 0) - chdir_thread = Qnil; + chdir_leave(); dir_fchdir(RB_NUM2INT(dir_fileno(args->old_dir))); } dir_close(args->old_dir); @@ -1248,16 +1380,14 @@ fchdir_restore(VALUE v) * Dir.pwd # => "/var/spool/mail" * dir = Dir.new('/usr') * fd = dir.fileno - * Dir.fchdir(fd) do - * Dir.pwd # => "/usr" - * end - * Dir.pwd # => "/var/spool/mail" + * Dir.fchdir(fd) + * Dir.pwd # => "/usr" * * With a block, temporarily changes the working directory: * * - Calls the block with the argument. * - Changes to the given directory. - * - Executes the block + * - Executes the block (yields no args). * - Restores the previous working directory. * - Returns the block's return value. * @@ -1265,7 +1395,9 @@ fchdir_restore(VALUE v) * * Dir.chdir('/var/spool/mail') * Dir.pwd # => "/var/spool/mail" - * Dir.chdir('/tmp') do + * dir = Dir.new('/tmp') + * fd = dir.fileno + * Dir.fchdir(fd) do * Dir.pwd # => "/tmp" * end * Dir.pwd # => "/var/spool/mail" @@ -1287,14 +1419,7 @@ dir_s_fchdir(VALUE klass, VALUE fd_value) { int fd = RB_NUM2INT(fd_value); - if (chdir_blocking > 0) { - if (rb_thread_current() != chdir_thread) - rb_raise(rb_eRuntimeError, "conflicting chdir during another chdir block"); - if (!rb_block_given_p()) - rb_warn("conflicting chdir during another chdir block"); - } - - if (rb_block_given_p()) { + if (chdir_alone_block_p()) { struct fchdir_data args; args.old_dir = dir_s_alloc(klass); dir_initialize(NULL, args.old_dir, rb_fstring_cstr("."), Qnil); @@ -1303,8 +1428,7 @@ dir_s_fchdir(VALUE klass, VALUE fd_value) return rb_ensure(fchdir_yield, (VALUE)&args, fchdir_restore, (VALUE)&args); } else { - int r = (int)(VALUE)rb_thread_call_without_gvl(nogvl_fchdir, &fd, - RUBY_UBF_IO, 0); + int r = IO_WITHOUT_GVL_INT(nogvl_fchdir, &fd); if (r < 0) rb_sys_fail("fchdir"); } @@ -1317,27 +1441,35 @@ dir_s_fchdir(VALUE klass, VALUE fd_value) /* * call-seq: - * chdir -> nil + * chdir -> 0 + * chdir { ... } -> object * - * Changes the current working directory to the path of +self+: + * Changes the current working directory to +self+: * * Dir.pwd # => "/" * dir = Dir.new('example') * dir.chdir - * dir.pwd # => "/example" + * Dir.pwd # => "/example" + * + * With a block, temporarily changes the working directory: + * + * - Calls the block. + * - Changes to the given directory. + * - Executes the block (yields no args). + * - Restores the previous working directory. + * - Returns the block's return value. * + * Uses Dir.fchdir if available, and Dir.chdir if not, see those + * methods for caveats. */ static VALUE dir_chdir(VALUE dir) { #if defined(HAVE_FCHDIR) && defined(HAVE_DIRFD) && HAVE_FCHDIR && HAVE_DIRFD - dir_s_fchdir(rb_cDir, dir_fileno(dir)); + return dir_s_fchdir(rb_cDir, dir_fileno(dir)); #else - VALUE path = dir_get(dir)->path; - dir_s_chdir(1, &path, rb_cDir); + return chdir_path(dir_get(dir)->path, false); #endif - - return Qnil; } #ifndef _WIN32 @@ -1348,19 +1480,15 @@ rb_dir_getwd_ospath(void) VALUE cwd; VALUE path_guard; -#undef RUBY_UNTYPED_DATA_WARNING -#define RUBY_UNTYPED_DATA_WARNING 0 - path_guard = Data_Wrap_Struct((VALUE)0, NULL, RUBY_DEFAULT_FREE, NULL); + path_guard = rb_imemo_tmpbuf_auto_free_pointer(); path = ruby_getcwd(); - DATA_PTR(path_guard) = path; + rb_imemo_tmpbuf_set_ptr(path_guard, path); #ifdef __APPLE__ cwd = rb_str_normalize_ospath(path, strlen(path)); #else cwd = rb_str_new2(path); #endif - DATA_PTR(path_guard) = 0; - - xfree(path); + rb_free_tmp_buffer(&path_guard); return cwd; } #endif @@ -1422,6 +1550,12 @@ check_dirname(VALUE dir) } #if defined(HAVE_CHROOT) +static void * +nogvl_chroot(void *dirname) +{ + return (void *)(VALUE)chroot((const char *)dirname); +} + /* * call-seq: * Dir.chroot(dirpath) -> 0 @@ -1438,7 +1572,7 @@ static VALUE dir_s_chroot(VALUE dir, VALUE path) { path = check_dirname(path); - if (chroot(RSTRING_PTR(path)) == -1) + if (IO_WITHOUT_GVL_INT(nogvl_chroot, (void *)RSTRING_PTR(path)) == -1) rb_sys_fail_path(path); return INT2FIX(0); @@ -1492,7 +1626,7 @@ dir_s_mkdir(int argc, VALUE *argv, VALUE obj) path = check_dirname(path); m.path = RSTRING_PTR(path); - r = (int)(VALUE)rb_thread_call_without_gvl(nogvl_mkdir, &m, RUBY_UBF_IO, 0); + r = IO_WITHOUT_GVL_INT(nogvl_mkdir, &m); if (r < 0) rb_sys_fail_path(path); @@ -1525,7 +1659,7 @@ dir_s_rmdir(VALUE obj, VALUE dir) dir = check_dirname(dir); p = RSTRING_PTR(dir); - r = (int)(VALUE)rb_thread_call_without_gvl(nogvl_rmdir, (void *)p, RUBY_UBF_IO, 0); + r = IO_WITHOUT_GVL_INT(nogvl_rmdir, (void *)p); if (r < 0) rb_sys_fail_path(dir); @@ -1615,11 +1749,11 @@ to_be_ignored(int e) } #ifdef _WIN32 -#define STAT(p, s) rb_w32_ustati128((p), (s)) -#undef lstat -#define lstat(p, s) rb_w32_ulstati128((p), (s)) +#define STAT(args) (int)(VALUE)nogvl_stat(&(args)) +#define LSTAT(args) (int)(VALUE)nogvl_lstat(&(args)) #else -#define STAT(p, s) stat((p), (s)) +#define STAT(args) IO_WITHOUT_GVL_INT(nogvl_stat, (void *)&(args)) +#define LSTAT(args) IO_WITHOUT_GVL_INT(nogvl_lstat, (void *)&(args)) #endif typedef int ruby_glob_errfunc(const char*, VALUE, const void*, int); @@ -1640,14 +1774,50 @@ at_subpath(int fd, size_t baselen, const char *path) return *path ? path : "."; } +#if USE_OPENDIR_AT +struct fstatat_args { + int fd; + int flag; + const char *path; + struct stat *pst; +}; + +static void * +nogvl_fstatat(void *args) +{ + struct fstatat_args *arg = (struct fstatat_args *)args; + return (void *)(VALUE)fstatat(arg->fd, arg->path, arg->pst, arg->flag); +} +#else +struct stat_args { + const char *path; + struct stat *pst; +}; + +static void * +nogvl_stat(void *args) +{ + struct stat_args *arg = (struct stat_args *)args; + return (void *)(VALUE)stat(arg->path, arg->pst); +} +#endif + /* System call with warning */ static int do_stat(int fd, size_t baselen, const char *path, struct stat *pst, int flags, rb_encoding *enc) { #if USE_OPENDIR_AT - int ret = fstatat(fd, at_subpath(fd, baselen, path), pst, 0); + struct fstatat_args args; + args.fd = fd; + args.path = path; + args.pst = pst; + args.flag = 0; + int ret = IO_WITHOUT_GVL_INT(nogvl_fstatat, (void *)&args); #else - int ret = STAT(path, pst); + struct stat_args args; + args.path = path; + args.pst = pst; + int ret = STAT(args); #endif if (ret < 0 && !to_be_ignored(errno)) sys_warning(path, enc); @@ -1656,13 +1826,30 @@ do_stat(int fd, size_t baselen, const char *path, struct stat *pst, int flags, r } #if defined HAVE_LSTAT || defined lstat || USE_OPENDIR_AT +#if !USE_OPENDIR_AT +static void * +nogvl_lstat(void *args) +{ + struct stat_args *arg = (struct stat_args *)args; + return (void *)(VALUE)lstat(arg->path, arg->pst); +} +#endif + static int do_lstat(int fd, size_t baselen, const char *path, struct stat *pst, int flags, rb_encoding *enc) { #if USE_OPENDIR_AT - int ret = fstatat(fd, at_subpath(fd, baselen, path), pst, AT_SYMLINK_NOFOLLOW); + struct fstatat_args args; + args.fd = fd; + args.path = path; + args.pst = pst; + args.flag = AT_SYMLINK_NOFOLLOW; + int ret = IO_WITHOUT_GVL_INT(nogvl_fstatat, (void *)&args); #else - int ret = lstat(path, pst); + struct stat_args args; + args.path = path; + args.pst = pst; + int ret = LSTAT(args); #endif if (ret < 0 && !to_be_ignored(errno)) sys_warning(path, enc); @@ -1723,7 +1910,7 @@ nogvl_opendir_at(void *ptr) /* fallthrough*/ case 0: if (fd >= 0) close(fd); - errno = e; + rb_errno_set(e); } } #else /* !USE_OPENDIR_AT */ @@ -1744,7 +1931,7 @@ opendir_at(int basefd, const char *path) oaa.path = path; if (vm_initialized) - return rb_thread_call_without_gvl(nogvl_opendir_at, &oaa, RUBY_UBF_IO, 0); + return IO_WITHOUT_GVL(nogvl_opendir_at, &oaa); else return nogvl_opendir_at(&oaa); } @@ -2023,14 +2210,15 @@ is_case_sensitive(DIR *dirp, const char *path) const vol_capabilities_attr_t *const cap = attrbuf[0].cap; const int idx = VOL_CAPABILITIES_FORMAT; const uint32_t mask = VOL_CAP_FMT_CASE_SENSITIVE; - + struct getattrlist_args args = GETATTRLIST_ARGS(&al, attrbuf, FSOPT_NOFOLLOW); # if defined HAVE_FGETATTRLIST - if (fgetattrlist(dirfd(dirp), &al, attrbuf, sizeof(attrbuf), FSOPT_NOFOLLOW)) - return -1; + int ret = gvl_fgetattrlist(&args, dirfd(dirp)); # else - if (getattrlist(path, &al, attrbuf, sizeof(attrbuf), FSOPT_NOFOLLOW)) - return -1; + int ret = gvl_getattrlist(&args, path); # endif + if (ret) + return -1; + if (!(cap->valid[idx] & mask)) return -1; return (cap->capabilities[idx] & mask) != 0; @@ -2053,7 +2241,8 @@ replace_real_basename(char *path, long base, rb_encoding *enc, int norm_p, int f IF_NORMALIZE_UTF8PATH(VALUE utf8str = Qnil); *type = path_noent; - if (getattrlist(path, &al, attrbuf, sizeof(attrbuf), FSOPT_NOFOLLOW)) { + struct getattrlist_args args = GETATTRLIST_ARGS(&al, attrbuf, FSOPT_NOFOLLOW); + if (gvl_getattrlist(&args, path)) { if (!to_be_ignored(errno)) sys_warning(path, enc); return path; @@ -2426,7 +2615,7 @@ static void glob_dir_finish(ruby_glob_entries_t *ent, int flags) { if (flags & FNM_GLOB_NOSORT) { - closedir(ent->nosort.dirp); + check_closedir(ent->nosort.dirp); ent->nosort.dirp = NULL; } else if (ent->sort.entries) { @@ -2457,7 +2646,7 @@ glob_opendir(ruby_glob_entries_t *ent, DIR *dirp, int flags, rb_encoding *enc) #ifdef _WIN32 if ((capacity = dirp->nfiles) > 0) { if (!(newp = GLOB_ALLOC_N(rb_dirent_t, capacity))) { - closedir(dirp); + check_closedir(dirp); return NULL; } ent->sort.entries = newp; @@ -2477,7 +2666,7 @@ glob_opendir(ruby_glob_entries_t *ent, DIR *dirp, int flags, rb_encoding *enc) ent->sort.entries[count++] = rdp; ent->sort.count = count; } - closedir(dirp); + check_closedir(dirp); if (count < capacity) { if (!(newp = GLOB_REALLOC_N(ent->sort.entries, count))) { glob_dir_finish(ent, 0); @@ -2492,7 +2681,7 @@ glob_opendir(ruby_glob_entries_t *ent, DIR *dirp, int flags, rb_encoding *enc) nomem: glob_dir_finish(ent, 0); - closedir(dirp); + check_closedir(dirp); return NULL; } @@ -2655,7 +2844,7 @@ glob_helper( # if NORMALIZE_UTF8PATH if (!(norm_p || magical || recursive)) { - closedir(dirp); + check_closedir(dirp); goto literally; } # endif @@ -3116,7 +3305,7 @@ push_glob(VALUE ary, VALUE str, VALUE base, int flags) fd = AT_FDCWD; if (!NIL_P(base)) { if (!RB_TYPE_P(base, T_STRING) || !rb_enc_check(str, base)) { - struct dir_data *dirp = DATA_PTR(base); + struct dir_data *dirp = RTYPEDDATA_GET_DATA(base); if (!dirp->dir) dir_closed(); #ifdef HAVE_DIRFD if ((fd = dirfd(dirp->dir)) == -1) @@ -3357,7 +3546,7 @@ dir_s_each_child(int argc, VALUE *argv, VALUE io) * "main.rb" * * If no block is given, returns an enumerator. - */ + */ static VALUE dir_each_child_m(VALUE dir) { @@ -3478,6 +3667,9 @@ file_s_fnmatch(int argc, VALUE *argv, VALUE obj) * call-seq: * Dir.home(user_name = nil) -> dirpath * + * Returns the home directory path of the user specified with +user_name+ + * if it is not +nil+, or the current login user: + * * Dir.home # => "/home/me" * Dir.home('root') # => "/root" * @@ -3492,7 +3684,7 @@ dir_s_home(int argc, VALUE *argv, VALUE obj) rb_check_arity(argc, 0, 1); user = (argc > 0) ? argv[0] : Qnil; if (!NIL_P(user)) { - SafeStringValue(user); + StringValue(user); rb_must_asciicompat(user); u = StringValueCStr(user); if (*u) { @@ -3514,6 +3706,7 @@ dir_s_home(int argc, VALUE *argv, VALUE obj) * Dir.exist?('/nosuch') # => false * Dir.exist?('/example/main.rb') # => false * + * Same as File.directory?. * */ VALUE @@ -3543,13 +3736,13 @@ nogvl_dir_empty_p(void *ptr) return (void *)INT2FIX(e); } } - while ((dp = READDIR(dir, NULL)) != NULL) { + while ((dp = READDIR_NOGVL(dir, NULL)) != NULL) { if (!to_be_skipped(dp)) { result = Qfalse; break; } } - closedir(dir); + check_closedir(dir); return (void *)result; } @@ -3585,12 +3778,13 @@ rb_dir_s_empty_p(VALUE obj, VALUE dirname) { u_int32_t attrbuf[SIZEUP32(fsobj_tag_t)]; struct attrlist al = {ATTR_BIT_MAP_COUNT, 0, ATTR_CMN_OBJTAG,}; - if (getattrlist(path, &al, attrbuf, sizeof(attrbuf), 0) != 0) + struct getattrlist_args args = GETATTRLIST_ARGS(&al, attrbuf, 0); + if (gvl_getattrlist(&args, path) != 0) rb_sys_fail_path(orig); if (*(const fsobj_tag_t *)(attrbuf+1) == VT_HFS) { al.commonattr = 0; al.dirattr = ATTR_DIR_ENTRYCOUNT; - if (getattrlist(path, &al, attrbuf, sizeof(attrbuf), 0) == 0) { + if (gvl_getattrlist(&args, path) == 0) { if (attrbuf[0] >= 2 * sizeof(u_int32_t)) return RBOOL(attrbuf[1] == 0); if (false_on_notdir) return Qfalse; @@ -3600,8 +3794,7 @@ rb_dir_s_empty_p(VALUE obj, VALUE dirname) } #endif - result = (VALUE)rb_thread_call_without_gvl(nogvl_dir_empty_p, (void *)path, - RUBY_UBF_IO, 0); + result = (VALUE)IO_WITHOUT_GVL(nogvl_dir_empty_p, (void *)path); if (FIXNUM_P(result)) { rb_syserr_fail_path((int)FIX2LONG(result), orig); } @@ -3611,6 +3804,9 @@ rb_dir_s_empty_p(VALUE obj, VALUE dirname) void Init_Dir(void) { + rb_gc_register_address(&chdir_lock.path); + rb_gc_register_address(&chdir_lock.thread); + rb_cDir = rb_define_class("Dir", rb_cObject); rb_include_module(rb_cDir, rb_mEnumerable); @@ -3654,12 +3850,20 @@ Init_Dir(void) rb_define_singleton_method(rb_cFile,"fnmatch", file_s_fnmatch, -1); rb_define_singleton_method(rb_cFile,"fnmatch?", file_s_fnmatch, -1); + + /* {File::FNM_NOESCAPE}[rdoc-ref:File::Constants@File-3A-3AFNM_NOESCAPE] */ rb_file_const("FNM_NOESCAPE", INT2FIX(FNM_NOESCAPE)); + /* {File::FNM_PATHNAME}[rdoc-ref:File::Constants@File-3A-3AFNM_PATHNAME] */ rb_file_const("FNM_PATHNAME", INT2FIX(FNM_PATHNAME)); + /* {File::FNM_DOTMATCH}[rdoc-ref:File::Constants@File-3A-3AFNM_DOTMATCH] */ rb_file_const("FNM_DOTMATCH", INT2FIX(FNM_DOTMATCH)); + /* {File::FNM_CASEFOLD}[rdoc-ref:File::Constants@File-3A-3AFNM_CASEFOLD] */ rb_file_const("FNM_CASEFOLD", INT2FIX(FNM_CASEFOLD)); + /* {File::FNM_EXTGLOB}[rdoc-ref:File::Constants@File-3A-3AFNM_EXTGLOB] */ rb_file_const("FNM_EXTGLOB", INT2FIX(FNM_EXTGLOB)); + /* {File::FNM_SYSCASE}[rdoc-ref:File::Constants@File-3A-3AFNM_SYSCASE] */ rb_file_const("FNM_SYSCASE", INT2FIX(FNM_SYSCASE)); + /* {File::FNM_SHORTNAME}[rdoc-ref:File::Constants@File-3A-3AFNM_SHORTNAME] */ rb_file_const("FNM_SHORTNAME", INT2FIX(FNM_SHORTNAME)); } diff --git a/dir.rb b/dir.rb index 7de62da921410b..a05bd18630b923 100644 --- a/dir.rb +++ b/dir.rb @@ -46,14 +46,14 @@ # The stream has a _position_, which is the index of an entry in the directory: # # - The initial position is zero (before the first entry). -# - \Method #tell (aliased as #pos) returns the position. -# - \Method #pos= sets the position (but ignores a value outside the stream), +# - Method #tell (aliased as #pos) returns the position. +# - Method #pos= sets the position (but ignores a value outside the stream), # and returns the position. -# - \Method #seek is like #pos=, but returns +self+ (convenient for chaining). -# - \Method #read, if not at end-of-stream, reads the next entry and increments +# - Method #seek is like #pos=, but returns +self+ (convenient for chaining). +# - Method #read, if not at end-of-stream, reads the next entry and increments # the position; # if at end-of-stream, does not increment the position. -# - \Method #rewind sets the position to zero. +# - Method #rewind sets the position to zero. # # Examples (using the {simple file tree}[rdoc-ref:Dir@About+the+Examples]): # @@ -83,7 +83,7 @@ # # == What's Here # -# First, what's elsewhere. \Class \Dir: +# First, what's elsewhere. Class \Dir: # # - Inherits from {class Object}[rdoc-ref:Object@What-27s+Here]. # - Includes {module Enumerable}[rdoc-ref:Enumerable@What-27s+Here], @@ -224,8 +224,8 @@ def self.[](*args, base: nil, sort: true) end # call-seq: - # Dir.glob(*patterns, flags: 0, base: nil, sort: true) -> array - # Dir.glob(*patterns, flags: 0, base: nil, sort: true) {|entry_name| ... } -> nil + # Dir.glob(patterns, flags: 0, base: nil, sort: true) -> array + # Dir.glob(patterns, flags: 0, base: nil, sort: true) {|entry_name| ... } -> nil # # Forms an array _entry_names_ of the entry names selected by the arguments. # @@ -320,7 +320,7 @@ def self.[](*args, base: nil, sort: true) # Dir.glob('io.?') # => ["io.c"] # # - '[_set_]': Matches any one character in the string _set_; - # behaves like a {Regexp character class}[rdoc-ref:regexp.rdoc@Character+Classes], + # behaves like a {Regexp character class}[rdoc-ref:Regexp@Character+Classes], # including set negation ('[^a-z]'): # # Dir.glob('*.[a-z][a-z]').take(3) @@ -328,7 +328,7 @@ def self.[](*args, base: nil, sort: true) # # - '{_abc_,_xyz_}': # Matches either string _abc_ or string _xyz_; - # behaves like {Regexp alternation}[rdoc-ref:regexp.rdoc@Alternation]: + # behaves like {Regexp alternation}[rdoc-ref:Regexp@Alternation]: # # Dir.glob('{LEGAL,BSDL}') # => ["LEGAL", "BSDL"] # @@ -408,6 +408,7 @@ def self.[](*args, base: nil, sort: true) # specifies that patterns may match short names if they exist; Windows only. # def self.glob(pattern, _flags = 0, flags: _flags, base: nil, sort: true) + Primitive.attr! :use_block Primitive.dir_s_glob(pattern, flags, base, sort) end end diff --git a/dln.c b/dln.c index 77bfe91b2875b5..5f6b1f0564c7b6 100644 --- a/dln.c +++ b/dln.c @@ -26,6 +26,7 @@ static void dln_loaderror(const char *format, ...); #include "dln.h" #include "internal.h" #include "internal/compilers.h" +#include "internal/namespace.h" #ifdef HAVE_STDLIB_H # include @@ -107,36 +108,45 @@ dln_loaderror(const char *format, ...) #endif #if defined(_WIN32) || defined(USE_DLN_DLOPEN) -static size_t -init_funcname_len(const char **file) +struct string_part { + const char *ptr; + size_t len; +}; + +static struct string_part +init_funcname_len(const char *file) { - const char *p = *file, *base, *dot = NULL; + const char *p = file, *base, *dot = NULL; /* Load the file as an object one */ for (base = p; *p; p++) { /* Find position of last '/' */ if (*p == '.' && !dot) dot = p; if (isdirsep(*p)) base = p+1, dot = NULL; } - *file = base; /* Delete suffix if it exists */ - return (dot ? dot : p) - base; + const size_t len = (dot ? dot : p) - base; + return (struct string_part){base, len}; } -static const char funcname_prefix[sizeof(FUNCNAME_PREFIX) - 1] = FUNCNAME_PREFIX; - -#define init_funcname(buf, file) do {\ - const char *base = (file);\ - const size_t flen = init_funcname_len(&base);\ - const size_t plen = sizeof(funcname_prefix);\ - char *const tmp = ALLOCA_N(char, plen+flen+1);\ - if (!tmp) {\ - dln_memerror();\ - }\ - memcpy(tmp, funcname_prefix, plen);\ - memcpy(tmp+plen, base, flen);\ - tmp[plen+flen] = '\0';\ - *(buf) = tmp;\ +static inline char * +concat_funcname(char *buf, const char *prefix, size_t plen, const struct string_part base) +{ + if (!buf) { + dln_memerror(); + } + memcpy(buf, prefix, plen); + memcpy(buf + plen, base.ptr, base.len); + buf[plen + base.len] = '\0'; + return buf; +} + +#define build_funcname(prefix, buf, file) do {\ + const struct string_part f = init_funcname_len(file);\ + const size_t plen = sizeof(prefix "") - 1;\ + *(buf) = concat_funcname(ALLOCA_N(char, plen+f.len+1), prefix, plen, f);\ } while (0) + +#define init_funcname(buf, file) build_funcname(FUNCNAME_PREFIX, buf, file) #endif #ifdef USE_DLN_DLOPEN @@ -272,13 +282,15 @@ rb_w32_check_imported(HMODULE ext, HMODULE mine) static bool dln_incompatible_func(void *handle, const char *funcname, void *const fp, const char **libname) { - Dl_info dli; void *ex = dlsym(handle, funcname); if (!ex) return false; if (ex == fp) return false; +# if defined(HAVE_DLADDR) && !defined(__CYGWIN__) + Dl_info dli; if (dladdr(ex, &dli)) { *libname = dli.dli_fname; } +# endif return true; } @@ -371,10 +383,14 @@ dln_open(const char *file) # endif # ifndef RTLD_GLOBAL # define RTLD_GLOBAL 0 +# endif +# ifndef RTLD_LOCAL +# define RTLD_LOCAL 0 /* TODO: 0??? some systems (including libc) use 0x00100 for RTLD_GLOBAL, 0x00000 for RTLD_LOCAL */ # endif /* Load file */ - handle = dlopen(file, RTLD_LAZY|RTLD_GLOBAL); + int mode = rb_namespace_available() ? RTLD_LAZY|RTLD_LOCAL : RTLD_LAZY|RTLD_GLOBAL; + handle = dlopen(file, mode); if (handle == NULL) { error = dln_strerror(); goto failed; @@ -419,33 +435,63 @@ dln_open(const char *file) static void * dln_sym(void *handle, const char *symbol) { - void *func; - const char *error; - #if defined(_WIN32) - char message[1024]; + return GetProcAddress(handle, symbol); +#elif defined(USE_DLN_DLOPEN) + return dlsym(handle, symbol); +#endif +} + +static uintptr_t +dln_sym_func(void *handle, const char *symbol) +{ + void *func = dln_sym(handle, symbol); - func = GetProcAddress(handle, symbol); if (func == NULL) { + const char *error; +#if defined(_WIN32) + char message[1024]; error = dln_strerror(); - goto failed; - } - #elif defined(USE_DLN_DLOPEN) - func = dlsym(handle, symbol); - if (func == NULL) { const size_t errlen = strlen(error = dln_strerror()) + 1; error = memcpy(ALLOCA_N(char, errlen), error, errlen); - goto failed; - } #endif + dln_loaderror("%s - %s", error, symbol); + } + return (uintptr_t)func; +} - return func; +#define dln_sym_callable(rettype, argtype, handle, symbol) \ + (*(rettype (*)argtype)dln_sym_func(handle, symbol)) +#endif - failed: - dln_loaderror("%s - %s", error, symbol); -} +void * +dln_symbol(void *handle, const char *symbol) +{ +#if defined(_WIN32) || defined(USE_DLN_DLOPEN) + if (EXTERNAL_PREFIX[0]) { + const size_t symlen = strlen(symbol); + char *const tmp = ALLOCA_N(char, symlen + sizeof(EXTERNAL_PREFIX)); + if (!tmp) dln_memerror(); + memcpy(tmp, EXTERNAL_PREFIX, sizeof(EXTERNAL_PREFIX) - 1); + memcpy(tmp + sizeof(EXTERNAL_PREFIX) - 1, symbol, symlen + 1); + symbol = tmp; + } + if (handle == NULL) { +# if defined(USE_DLN_DLOPEN) + handle = dlopen(NULL, RTLD_LAZY | RTLD_GLOBAL); +# elif defined(_WIN32) + handle = rb_libruby_handle(); +# else + return NULL; +# endif + } + return dln_sym(handle, symbol); +#else + return NULL; #endif +} + #if defined(RUBY_DLN_CHECK_ABI) && defined(USE_DLN_DLOPEN) static bool @@ -456,26 +502,23 @@ abi_check_enabled_p(void) } #endif -void * -dln_load(const char *file) +static void * +dln_load_and_init(const char *file, const char *init_fct_name) { #if defined(_WIN32) || defined(USE_DLN_DLOPEN) void *handle = dln_open(file); #ifdef RUBY_DLN_CHECK_ABI - unsigned long long (*abi_version_fct)(void) = (unsigned long long(*)(void))dln_sym(handle, "ruby_abi_version"); - unsigned long long binary_abi_version = (*abi_version_fct)(); - if (binary_abi_version != ruby_abi_version() && abi_check_enabled_p()) { + typedef unsigned long long abi_version_number; + abi_version_number binary_abi_version = + dln_sym_callable(abi_version_number, (void), handle, EXTERNAL_PREFIX "ruby_abi_version")(); + if (binary_abi_version != RUBY_ABI_VERSION && abi_check_enabled_p()) { dln_loaderror("incompatible ABI version of binary - %s", file); } #endif - char *init_fct_name; - init_funcname(&init_fct_name, file); - void (*init_fct)(void) = (void(*)(void))dln_sym(handle, init_fct_name); - /* Call the init code */ - (*init_fct)(); + dln_sym_callable(void, (void), handle, init_fct_name)(); return handle; @@ -483,6 +526,7 @@ dln_load(const char *file) { void (*init_fct)(void); + /* TODO: check - AIX's load system call will return the first/last symbol/function? */ init_fct = (void(*)(void))load((char*)file, 1, 0); if (init_fct == NULL) { aix_loaderror(file); @@ -499,3 +543,29 @@ dln_load(const char *file) return 0; /* dummy return */ } + +void * +dln_load(const char *file) +{ +#if defined(_WIN32) || defined(USE_DLN_DLOPEN) + char *init_fct_name; + init_funcname(&init_fct_name, file); + return dln_load_and_init(file, init_fct_name); +#else + dln_notimplement(); + return 0; +#endif +} + +void * +dln_load_feature(const char *file, const char *fname) +{ +#if defined(_WIN32) || defined(USE_DLN_DLOPEN) + char *init_fct_name; + init_funcname(&init_fct_name, fname); + return dln_load_and_init(file, init_fct_name); +#else + dln_notimplement(); + return 0; +#endif +} diff --git a/dln.h b/dln.h index 902f753450a30a..711abf592c605e 100644 --- a/dln.h +++ b/dln.h @@ -25,6 +25,8 @@ RUBY_SYMBOL_EXPORT_BEGIN char *dln_find_exe_r(const char*,const char*,char*,size_t DLN_FIND_EXTRA_ARG_DECL); char *dln_find_file_r(const char*,const char*,char*,size_t DLN_FIND_EXTRA_ARG_DECL); void *dln_load(const char*); +void *dln_load_feature(const char*, const char*); +void *dln_symbol(void*,const char*); RUBY_SYMBOL_EXPORT_END diff --git a/dln_find.c b/dln_find.c index 91c51394a95463..ae37b9dde42426 100644 --- a/dln_find.c +++ b/dln_find.c @@ -11,11 +11,9 @@ #ifdef RUBY_EXPORT #include "ruby/ruby.h" -#define dln_warning rb_warning -#define dln_warning_arg +#define dln_warning(...) rb_warning(__VA_ARGS__) #else -#define dln_warning fprintf -#define dln_warning_arg stderr, +#define dln_warning(...) fprintf(stderr, __VA_ARGS__) #endif #include "dln.h" @@ -109,7 +107,7 @@ dln_find_1(const char *fname, const char *path, char *fbuf, size_t size, static const char pathname_too_long[] = "openpath: pathname too long (ignored)\n\ \tDirectory \"%.*s\"%s\n\tFile \"%.*s\"%s\n"; -#define PATHNAME_TOO_LONG() dln_warning(dln_warning_arg pathname_too_long, \ +#define PATHNAME_TOO_LONG() dln_warning(pathname_too_long, \ ((bp - fbuf) > 100 ? 100 : (int)(bp - fbuf)), fbuf, \ ((bp - fbuf) > 100 ? "..." : ""), \ (fnlen > 100 ? 100 : (int)fnlen), fname, \ @@ -120,8 +118,7 @@ dln_find_1(const char *fname, const char *path, char *fbuf, size_t size, RETURN_IF(!fname); fnlen = strlen(fname); if (fnlen >= size) { - dln_warning(dln_warning_arg - "openpath: pathname too long (ignored)\n\tFile \"%.*s\"%s\n", + dln_warning("openpath: pathname too long (ignored)\n\tFile \"%.*s\"%s\n", (fnlen > 100 ? 100 : (int)fnlen), fname, (fnlen > 100 ? "..." : "")); return NULL; diff --git a/dmydln.c b/dmydln.c index d05cda0b8eb922..62a89e2da530e7 100644 --- a/dmydln.c +++ b/dmydln.c @@ -1,3 +1,6 @@ +// This file is used by miniruby, not ruby. +// ruby uses dln.c. + #include "ruby/ruby.h" NORETURN(void *dln_load(const char *)); @@ -8,3 +11,21 @@ dln_load(const char *file) UNREACHABLE_RETURN(NULL); } + +NORETURN(void *dln_load_feature(const char*,const char*)); +void* +dln_load_feature(const char *file, const char *fname) +{ + rb_loaderror("this executable file can't load extension libraries"); + + UNREACHABLE_RETURN(NULL); +} + +NORETURN(void *dln_symbol(void*,const char*)); +void* +dln_symbol(void *handle, const char *symbol) +{ + rb_loaderror("this executable file can't load extension libraries"); + + UNREACHABLE_RETURN(NULL); +} diff --git a/dmyenc.c b/dmyenc.c index 75b8a2da43a06a..47718412814c6a 100644 --- a/dmyenc.c +++ b/dmyenc.c @@ -1,3 +1,17 @@ +// This file is used by dynamically-linked ruby, which has no +// statically-linked encodings other than the builtin encodings. +// +// - miniruby does not use this Init_enc. Instead, "miniinit.c" +// provides Init_enc, which defines only the builtin encodings. +// +// - Dynamically-linked ruby uses this Init_enc, which requires +// "enc/encdb.so" to load the builtin encodings and set up the +// optional encodings. +// +// - Statically-linked ruby does not use this Init_enc. Instead, +// "enc/encinit.c" (which is a generated file) defines Init_enc, +// which activates the encodings. + #define require(name) ruby_require_internal(name, (unsigned int)sizeof(name)-1) int ruby_require_internal(const char *, int); diff --git a/dmyext.c b/dmyext.c index 4d273f7faffc5a..66be95ab4ef892 100644 --- a/dmyext.c +++ b/dmyext.c @@ -1,3 +1,17 @@ +// This file is used by dynamically-linked ruby, which has no +// statically-linked extension libraries. +// +// - miniruby does not use this Init_ext. Instead, "miniinit.c" +// provides Init_enc, which does nothing too. It does not support +// require'ing extension libraries. +// +// - Dynamically-linked ruby uses this Init_ext, which does +// nothing. It loads extension libraries by dlopen, etc. +// +// - Statically-linked ruby does not use this Init_ext. Instead, +// "ext/extinit.c" (which is a generated file) defines Init_ext, +// which activates the (statically-linked) extension libraries. + void Init_ext(void) { diff --git a/doc/.document b/doc/.document index 4b90648377d32c..6e6caa83336322 100644 --- a/doc/.document +++ b/doc/.document @@ -1,10 +1,12 @@ *.md *.rb -*.rdoc +[^_]*.rdoc contributing NEWS syntax optparse +date rdoc regexp yjit +ruby diff --git a/doc/ChangeLog/ChangeLog-1.9.3 b/doc/ChangeLog/ChangeLog-1.9.3 index 0f80eed2d5d0b9..03a7f3eabffd10 100644 --- a/doc/ChangeLog/ChangeLog-1.9.3 +++ b/doc/ChangeLog/ChangeLog-1.9.3 @@ -9012,7 +9012,7 @@ Thu Dec 2 01:24:39 2010 NARUSE, Yui Thu Dec 2 01:02:03 2010 NARUSE, Yui - * ext/json: Update github/flori/json from 1.4.2+ to + * ext/json: Update github/ruby/json from 1.4.2+ to e22b2f2bdfe6a9b0. this fixes some bugs. Thu Dec 2 00:05:44 2010 NARUSE, Yui diff --git a/doc/ChangeLog/ChangeLog-2.0.0 b/doc/ChangeLog/ChangeLog-2.0.0 index 9e654db1893a91..de47b66a6947ba 100644 --- a/doc/ChangeLog/ChangeLog-2.0.0 +++ b/doc/ChangeLog/ChangeLog-2.0.0 @@ -14426,7 +14426,7 @@ Tue May 8 02:34:26 2012 NARUSE, Yui Mon May 7 21:19:17 2012 NARUSE, Yui * ext/json: Merge JSON 1.7.1. - https://github.com/flori/json/commit/e5b9a9465c1159fae533bca320d950b772bcb4ac + https://github.com/ruby/json/commit/e5b9a9465c1159fae533bca320d950b772bcb4ac Mon May 7 22:54:22 2012 Martin Bosslet diff --git a/doc/ChangeLog/ChangeLog-2.1.0 b/doc/ChangeLog/ChangeLog-2.1.0 index 5b670b31c97c8c..b6977dbccdd980 100644 --- a/doc/ChangeLog/ChangeLog-2.1.0 +++ b/doc/ChangeLog/ChangeLog-2.1.0 @@ -659,7 +659,7 @@ Mon Dec 9 02:10:32 2013 NARUSE, Yui * lib/net/http/responses.rb: Add `HTTPIMUsed`, as it is also supported by rack/rails. - RFC - http://tools.ietf.org/html/rfc3229 + RFC - https://www.rfc-editor.org/rfc/rfc3229 by Vipul A M https://github.com/ruby/ruby/pull/447 fix GH-447 @@ -2167,7 +2167,7 @@ Wed Nov 20 11:46:38 2013 NARUSE, Yui * ext/json: merge JSON 1.8.1. https://github.com/nurse/json/compare/002ac2771ce32776b32ccd2d06e5604de6c36dcd...e09ffc0d7da25d0393873936c118c188c78dbac3 * Remove Rubinius exception since transcoding should be working now. - * Fix https://github.com/flori/json/issues/162 reported by Marc-Andre + * Fix https://github.com/ruby/json/issues/162 reported by Marc-Andre Lafortune . Thanks! * Applied patches by Yui NARUSE to suppress warning with -Wchar-subscripts and better validate UTF-8 strings. @@ -17913,7 +17913,7 @@ Tue Feb 12 12:02:35 2013 NARUSE, Yui * ext/json: merge JSON 1.7.7. This includes security fix. [CVE-2013-0269] - https://github.com/flori/json/commit/d0a62f3ced7560daba2ad546d83f0479a5ae2cf2 + https://github.com/ruby/json/commit/d0a62f3ced7560daba2ad546d83f0479a5ae2cf2 https://groups.google.com/d/topic/rubyonrails-security/4_YvCpLzL58/discussion Mon Feb 11 23:08:48 2013 Tanaka Akira diff --git a/doc/ChangeLog/ChangeLog-2.2.0 b/doc/ChangeLog/ChangeLog-2.2.0 index 5a7dbf826d3135..0edcf0122b190d 100644 --- a/doc/ChangeLog/ChangeLog-2.2.0 +++ b/doc/ChangeLog/ChangeLog-2.2.0 @@ -5648,7 +5648,7 @@ Wed Aug 6 04:16:05 2014 NARUSE, Yui * lib/net/http/requests.rb (Net::HTTP::Options::RESPONSE_HAS_BODY): OPTIONS requests may have response bodies. [Feature #8429] - http://tools.ietf.org/html/rfc7231#section-4.3.7 + https://www.rfc-editor.org/rfc/rfc7231#section-4.3.7 Wed Aug 6 03:18:04 2014 NARUSE, Yui diff --git a/doc/ChangeLog/ChangeLog-2.3.0 b/doc/ChangeLog/ChangeLog-2.3.0 index 94996cffd0de92..e6161838957e67 100644 --- a/doc/ChangeLog/ChangeLog-2.3.0 +++ b/doc/ChangeLog/ChangeLog-2.3.0 @@ -1211,7 +1211,7 @@ Sun Dec 6 08:39:05 2015 SHIBATA Hiroshi upstream changes. https://github.com/ruby/ruby/commit/4d059bf9f5f10f3d3088de49fc87e5555db7770d - https://github.com/flori/json/commit/d4c99de78905d96c3f301f48b2c789943bb3f098 + https://github.com/ruby/json/commit/d4c99de78905d96c3f301f48b2c789943bb3f098 * ext/json/lib/json/version.rb: ditto. @@ -10989,7 +10989,7 @@ Fri Feb 13 21:16:00 2015 Yusuke Endoh Fri Feb 13 14:19:06 2015 SHIBATA Hiroshi - * ext/json: merge upstream from flori/json + * ext/json: merge upstream from ruby/json change usage of TypedData. [Feature #10739][ruby-core:67564] Thu Feb 12 18:34:01 2015 multisnow @@ -11556,7 +11556,7 @@ Tue Jan 13 21:08:22 2015 SHIBATA Hiroshi * ext/json, test/json: merge JSON HEAD(259dee6) separate implementation of Typed_Data macro. - https://github.com/flori/json/compare/v1.8.1...v1.8.2 + https://github.com/ruby/json/compare/v1.8.1...v1.8.2 Tue Jan 13 14:16:35 2015 Nobuyoshi Nakada @@ -12009,7 +12009,7 @@ Mon Dec 29 10:37:27 2014 Thiago Lewin Mon Dec 29 07:27:23 2014 SHIBATA Hiroshi * ext/json, test/json: merge JSON HEAD(17fe8e7) - https://github.com/flori/json/compare/v1.8.1...17fe8e7 + https://github.com/ruby/json/compare/v1.8.1...17fe8e7 Sun Dec 28 23:49:37 2014 Michal Papis diff --git a/doc/ChangeLog/ChangeLog-2.4.0 b/doc/ChangeLog/ChangeLog-2.4.0 index a297a579d1d4ba..5e126fbd90e282 100644 --- a/doc/ChangeLog/ChangeLog-2.4.0 +++ b/doc/ChangeLog/ChangeLog-2.4.0 @@ -2668,8 +2668,8 @@ Wed Jul 6 07:11:27 2016 Shugo Maeda Tue Jul 5 20:49:30 2016 SHIBATA Hiroshi * ext/json/*, test/json/*: Update json-2.0.1. - Changes of 2.0.0: https://github.com/flori/json/blob/f679ebd0c69a94e3e70a897ac9a229f5779c2ee1/CHANGES.md#2015-09-11-200 - Changes of 2.0.1: https://github.com/flori/json/blob/f679ebd0c69a94e3e70a897ac9a229f5779c2ee1/CHANGES.md#2016-07-01-201 + Changes of 2.0.0: https://github.com/ruby/json/blob/f679ebd0c69a94e3e70a897ac9a229f5779c2ee1/CHANGES.md#2015-09-11-200 + Changes of 2.0.1: https://github.com/ruby/json/blob/f679ebd0c69a94e3e70a897ac9a229f5779c2ee1/CHANGES.md#2016-07-01-201 [Feature #12542][ruby-dev:49706][fix GH-1395] Tue Jul 5 19:39:49 2016 Naohisa Goto @@ -7356,7 +7356,7 @@ Thu Mar 17 11:51:48 2016 NARUSE, Yui Note: CryptGenRandom function is PRNG and doesn't check its entropy, so it won't block. [Bug #12139] https://msdn.microsoft.com/ja-jp/library/windows/desktop/aa379942.aspx - https://tools.ietf.org/html/rfc4086#section-7.1.3 + https://www.rfc-editor.org/rfc/rfc4086#section-7.1.3 https://eprint.iacr.org/2007/419.pdf http://www.cs.huji.ac.il/~dolev/pubs/thesis/msc-thesis-leo.pdf diff --git a/doc/NEWS/NEWS-3.0.0.md b/doc/NEWS/NEWS-3.0.0.md index bdbd47327bde3d..004fa4bf678bf8 100644 --- a/doc/NEWS/NEWS-3.0.0.md +++ b/doc/NEWS/NEWS-3.0.0.md @@ -741,7 +741,7 @@ end foo(42) ``` -``` +```console $ typeprof test.rb # Classes class Object diff --git a/doc/NEWS/NEWS-3.1.0.md b/doc/NEWS/NEWS-3.1.0.md index fe292fc414cf41..686003894e399b 100644 --- a/doc/NEWS/NEWS-3.1.0.md +++ b/doc/NEWS/NEWS-3.1.0.md @@ -552,7 +552,7 @@ Example: `title = json[:article][:title]` If `json` is nil, it shows: -``` +```console $ ruby test.rb test.rb:2:in `
': undefined method `[]' for nil:NilClass (NoMethodError) @@ -562,7 +562,7 @@ title = json[:article][:title] If `json[:article]` returns nil, it shows: -``` +```console $ ruby test.rb test.rb:2:in `
': undefined method `[]' for nil:NilClass (NoMethodError) diff --git a/doc/NEWS/NEWS-3.2.0.md b/doc/NEWS/NEWS-3.2.0.md index 33a7b85c47f98b..3a48c1964d04de 100644 --- a/doc/NEWS/NEWS-3.2.0.md +++ b/doc/NEWS/NEWS-3.2.0.md @@ -623,13 +623,13 @@ The following deprecated methods are removed. Psych and fiddle supported the static build with specific version of libyaml and libffi sources. You can build psych with libyaml-0.2.5 like this. - ```bash + ```console $ ./configure --with-libyaml-source-dir=/path/to/libyaml-0.2.5 ``` And you can build fiddle with libffi-3.4.4 like this. - ```bash + ```console $ ./configure --with-libffi-source-dir=/path/to/libffi-3.4.4 ``` diff --git a/doc/NEWS/NEWS-3.3.0.md b/doc/NEWS/NEWS-3.3.0.md new file mode 100644 index 00000000000000..364786d754062e --- /dev/null +++ b/doc/NEWS/NEWS-3.3.0.md @@ -0,0 +1,529 @@ +# NEWS for Ruby 3.3.0 + +This document is a list of user-visible feature changes +since the **3.2.0** release, except for bug fixes. + +Note that each entry is kept to a minimum, see links for details. + +## Command line options + +* A new `performance` warning category was introduced. + They are not displayed by default even in verbose mode. + Turn them on with `-W:performance` or `Warning[:performance] = true`. [[Feature #19538]] + +* A new `RUBY_CRASH_REPORT` environment variable was introduced to allow + redirecting Ruby crash reports to a file or sub command. See the `BUG REPORT ENVIRONMENT` + section of the ruby manpage for further details. [[Feature #19790]] + +## Core classes updates + +Note: We're only listing outstanding class updates. + +* Array + + * Array#pack now raises ArgumentError for unknown directives. [[Bug #19150]] + +* Dir + + * Dir.for_fd added for returning a Dir object for the directory specified + by the provided directory file descriptor. [[Feature #19347]] + * Dir.fchdir added for changing the directory to the directory specified + by the provided directory file descriptor. [[Feature #19347]] + * Dir#chdir added for changing the directory to the directory specified by + the provided `Dir` object. [[Feature #19347]] + +* Encoding + + * `Encoding#replicate` has been removed, it was already deprecated. [[Feature #18949]] + +* Fiber + + * Introduce Fiber#kill. [[Bug #595]] + + ```ruby + fiber = Fiber.new do + while true + puts "Yielding..." + Fiber.yield + end + ensure + puts "Exiting..." + end + + fiber.resume + # Yielding... + fiber.kill + # Exiting... + ``` + +* MatchData + + * MatchData#named_captures now accepts optional `symbolize_names` + keyword. [[Feature #19591]] + +* Module + + * Module#set_temporary_name added for setting a temporary name for a + module. [[Feature #19521]] + +* ObjectSpace::WeakKeyMap + + * New core class to build collections with weak references. + The class use equality semantic to lookup keys like a regular hash, + but it doesn't hold strong references on the keys. [[Feature #18498]] + +* ObjectSpace::WeakMap + + * ObjectSpace::WeakMap#delete was added to eagerly clear weak map + entries. [[Feature #19561]] + +* Proc + * Now Proc#dup and Proc#clone call `#initialize_dup` and `#initialize_clone` + hooks respectively. [[Feature #19362]] + +* Process + + * New Process.warmup method that notify the Ruby virtual machine that the boot sequence is finished, + and that now is a good time to optimize the application. This is useful + for long-running applications. The actual optimizations performed are entirely + implementation-specific and may change in the future without notice. [[Feature #18885]] + +* Process::Status + + * Process::Status#& and Process::Status#>> are deprecated. [[Bug #19868]] + +* Range + + * Range#reverse_each can now process beginless ranges with an Integer endpoint. [[Feature #18515]] + * Range#reverse_each now raises TypeError for endless ranges. [[Feature #18551]] + * Range#overlap? added for checking if two ranges overlap. [[Feature #19839]] + +* Refinement + + * Add Refinement#target as an alternative of Refinement#refined_class. + Refinement#refined_class is deprecated and will be removed in Ruby + 3.4. [[Feature #19714]] + +* Regexp + + * The cache-based optimization now supports lookarounds and atomic groupings. That is, match + for Regexp containing these extensions can now also be performed in linear time to the length + of the input string. However, these cannot contain captures and cannot be nested. [[Feature #19725]] + +* String + + * String#unpack now raises ArgumentError for unknown directives. [[Bug #19150]] + * String#bytesplice now accepts new arguments index/length or range of the + source string to be copied. [[Feature #19314]] + +* Thread::Queue + + * Thread::Queue#freeze now raises TypeError. [[Bug #17146]] + +* Thread::SizedQueue + + * Thread::SizedQueue#freeze now raises TypeError. [[Bug #17146]] + +* Time + + * Time.new with a string argument became stricter. [[Bug #19293]] + + ```ruby + Time.new('2023-12-20') + # no time information (ArgumentError) + ``` + +* TracePoint + + * TracePoint supports `rescue` event. When the raised exception was rescued, + the TracePoint will fire the hook. `rescue` event only supports Ruby-level + `rescue`. [[Feature #19572]] + +## Stdlib updates + +* RubyGems and Bundler warn if users do `require` the following gems without adding them to Gemfile or gemspec. + This is because they will become the bundled gems in the future version of Ruby. This warning is suppressed + if you use bootsnap gem. We recommend to run your application with `DISABLE_BOOTSNAP=1` environmental variable + at least once. This is limitation of this version. + [[Feature #19351]] [[Feature #19776]] [[Feature #19843]] + * abbrev + * base64 + * bigdecimal + * csv + * drb + * getoptlong + * mutex_m + * nkf + * observer + * racc + * resolv-replace + * rinda + * syslog + +* Socket#recv and Socket#recv_nonblock returns `nil` instead of an empty string on closed + connections. Socket#recvmsg and Socket#recvmsg_nonblock returns `nil` instead of an empty packet on closed + connections. [[Bug #19012]] + +* Name resolution such as Socket.getaddrinfo, Socket.getnameinfo, Addrinfo.getaddrinfo, etc. + can now be interrupted. [[Feature #19965]] + +* Random::Formatter#alphanumeric is extended to accept optional `chars` + keyword argument. [[Feature #18183]] + +The following default gem is added. + +* prism 0.19.0 + +The following default gems are updated. + +* RubyGems 3.5.3 +* abbrev 0.1.2 +* base64 0.2.0 +* benchmark 0.3.0 +* bigdecimal 3.1.5 +* bundler 2.5.3 +* cgi 0.4.1 +* csv 3.2.8 +* date 3.3.4 +* delegate 0.3.1 +* drb 2.2.0 +* english 0.8.0 +* erb 4.0.3 +* error_highlight 0.6.0 +* etc 1.4.3 +* fcntl 1.1.0 +* fiddle 1.1.2 +* fileutils 1.7.2 +* find 0.2.0 +* getoptlong 0.2.1 +* io-console 0.7.1 +* io-nonblock 0.3.0 +* io-wait 0.3.1 +* ipaddr 1.2.6 +* irb 1.11.0 +* json 2.7.1 +* logger 1.6.0 +* mutex_m 0.2.0 +* net-http 0.4.0 +* net-protocol 0.2.2 +* nkf 0.1.3 +* observer 0.1.2 +* open-uri 0.4.1 +* open3 0.2.1 +* openssl 3.2.0 +* optparse 0.4.0 +* ostruct 0.6.0 +* pathname 0.3.0 +* pp 0.5.0 +* prettyprint 0.2.0 +* pstore 0.1.3 +* psych 5.1.2 +* rdoc 6.6.2 +* readline 0.0.4 +* reline 0.4.1 +* resolv 0.3.0 +* rinda 0.2.0 +* securerandom 0.3.1 +* set 1.1.0 +* shellwords 0.2.0 +* singleton 0.2.0 +* stringio 3.1.0 +* strscan 3.0.7 +* syntax_suggest 2.0.0 +* syslog 0.1.2 +* tempfile 0.2.1 +* time 0.3.0 +* timeout 0.4.1 +* tmpdir 0.2.0 +* tsort 0.2.0 +* un 0.3.0 +* uri 0.13.0 +* weakref 0.1.3 +* win32ole 1.8.10 +* yaml 0.3.0 +* zlib 3.1.0 + +The following bundled gem is promoted from default gems. + +* racc 1.7.3 + +The following bundled gems are updated. + +* minitest 5.20.0 +* rake 13.1.0 +* test-unit 3.6.1 +* rexml 3.2.6 +* rss 0.3.0 +* net-ftp 0.3.3 +* net-imap 0.4.9 +* net-smtp 0.4.0 +* rbs 3.4.0 +* typeprof 0.21.9 +* debug 1.9.1 + +See GitHub releases like [Logger](https://github.com/ruby/logger/releases) or +changelog for details of the default gems or bundled gems. + +### Prism + +* Introduced [the Prism parser](https://github.com/ruby/prism) as a default gem + * Prism is a portable, error tolerant, and maintainable recursive descent parser for the Ruby language +* Prism is production ready and actively maintained, you can use it in place of Ripper + * There is [extensive documentation](https://ruby.github.io/prism/) on how to use Prism + * Prism is both a C library that will be used internally by CRuby and a Ruby gem that can be used by any tooling which needs to parse Ruby code + * Notable methods in the Prism API are: + * `Prism.parse(source)` which returns the AST as part of a parse result object + * `Prism.parse_comments(source)` which returns the comments + * `Prism.parse_success?(source)` which returns true if there are no errors +* You can make pull requests or issues directly on [the Prism repository](https://github.com/ruby/prism) if you are interested in contributing +* You can now use `ruby --parser=prism` or `RUBYOPT="--parser=prism"` to experiment with the Prism compiler. Please note that this flag is for debugging only. + +## Compatibility issues + +* Subprocess creation/forking via the following file open methods is deprecated. [[Feature #19630]] + * Kernel#open + * URI.open + * IO.binread + * IO.foreach + * IO.readlines + * IO.read + * IO.write + +* When given a non-lambda, non-literal block, Kernel#lambda with now raises + ArgumentError instead of returning it unmodified. These usages have been + issuing warnings under the `Warning[:deprecated]` category since Ruby 3.0.0. + [[Feature #19777]] + +* The `RUBY_GC_HEAP_INIT_SLOTS` environment variable has been deprecated and + removed. Environment variables `RUBY_GC_HEAP_%d_INIT_SLOTS` should be + used instead. [[Feature #19785]] + +* `it` calls without arguments in a block with no ordinary parameters are + deprecated. `it` will be a reference to the first block parameter in Ruby 3.4. + [[Feature #18980]] + +* Error message for NoMethodError have changed to not use the target object's `#inspect` + for efficiency, and says "instance of ClassName" instead. [[Feature #18285]] + + ```ruby + ([1] * 100).nonexisting + # undefined method `nonexisting' for an instance of Array (NoMethodError) + ``` + +* Now anonymous parameters forwarding is disallowed inside a block + that uses anonymous parameters. [[Feature #19370]] + +## Stdlib compatibility issues + +* `racc` is promoted to bundled gems. + * You need to add `racc` to your `Gemfile` if you use `racc` under bundler environment. +* `ext/readline` is retired + * We have `reline` that is pure Ruby implementation compatible with `ext/readline` API. + We rely on `reline` in the future. If you need to use `ext/readline`, you can install + `ext/readline` via rubygems.org with `gem install readline-ext`. + * We no longer need to install libraries like `libreadline` or `libedit`. + +## C API updates + +* `rb_postponed_job` updates + * New APIs and deprecated APIs (see comments for details) + * added: `rb_postponed_job_preregister()` + * added: `rb_postponed_job_trigger()` + * deprecated: `rb_postponed_job_register()` (and semantic change. see below) + * deprecated: `rb_postponed_job_register_one()` + * The postponed job APIs have been changed to address some rare crashes. + To solve the issue, we introduced new two APIs and deprecated current APIs. + The semantics of these functions have also changed slightly; `rb_postponed_job_register` + now behaves like the `once` variant in that multiple calls with the same + `func` might be coalesced into a single execution of the `func` + [[Feature #20057]] + +* Some updates for internal thread event hook APIs + * `rb_internal_thread_event_data_t` with a target Ruby thread (VALUE) + and callback functions (`rb_internal_thread_event_callback`) receive it. + https://github.com/ruby/ruby/pull/8885 + * The following functions are introduced to manipulate Ruby thread local data + from internal thread event hook APIs (they are introduced since Ruby 3.2). + https://github.com/ruby/ruby/pull/8936 + * `rb_internal_thread_specific_key_create()` + * `rb_internal_thread_specific_get()` + * `rb_internal_thread_specific_set()` + +* `rb_profile_thread_frames()` is introduced to get a frames from + a specific thread. + [[Feature #10602]] + +* `rb_data_define()` is introduced to define `Data`. [[Feature #19757]] + +* `rb_ext_resolve_symbol()` is introduced to search a function from + extension libraries. [[Feature #20005]] + +* IO related updates: + * The details of `rb_io_t` will be hidden and deprecated attributes + are added for each members. [[Feature #19057]] + * `rb_io_path(VALUE io)` is introduced to get a path of `io`. + * `rb_io_closed_p(VALUE io)` to get opening or closing of `io`. + * `rb_io_mode(VALUE io)` to get the mode of `io`. + * `rb_io_open_descriptor()` is introduced to make an IO object from a file + descriptor. + +## Implementation improvements + +### Parser + +* Replace Bison with [Lrama LALR parser generator](https://github.com/ruby/lrama). + No need to install Bison to build Ruby from source code anymore. + We will no longer suffer bison compatibility issues and we can use new features by just implementing it to Lrama. [[Feature #19637]] + * See [The future vision of Ruby Parser](https://rubykaigi.org/2023/presentations/spikeolaf.html) for detail. + * Lrama internal parser is a LR parser generated by Racc for maintainability. + * Parameterizing Rules `(?, *, +)` are supported, it will be used in Ruby parse.y. + +### GC / Memory management + +* Major performance improvements over Ruby 3.2 + * Young objects referenced by old objects are no longer immediately + promoted to the old generation. This significantly reduces the frequency of + major GC collections. [[Feature #19678]] + * A new `REMEMBERED_WB_UNPROTECTED_OBJECTS_LIMIT_RATIO` tuning variable was + introduced to control the number of unprotected objects cause a major GC + collection to trigger. The default is set to `0.01` (1%). This significantly + reduces the frequency of major GC collection. [[Feature #19571]] + * Write Barriers were implemented for many core types that were missing them, + notably `Time`, `Enumerator`, `MatchData`, `Method`, `File::Stat`, `BigDecimal` + and several others. This significantly reduces minor GC collection time and major + GC collection frequency. + * Most core classes are now using Variable Width Allocation, notably `Hash`, `Time`, + `Thread::Backtrace`, `Thread::Backtrace::Location`, `File::Stat`, `Method`. + This makes these classes faster to allocate and free, use less memory and reduce + heap fragmentation. +* `defined?(@ivar)` is optimized with Object Shapes. + +### YJIT + +* Major performance improvements over Ruby 3.2 + * Support for splat and rest arguments has been improved. + * Registers are allocated for stack operations of the virtual machine. + * More calls with optional arguments are compiled. Exception handlers are also compiled. + * Unsupported call types and megamorphic call sites no longer exit to the interpreter. + * Basic methods like Rails `#blank?` and + [specialized `#present?`](https://github.com/rails/rails/pull/49909) are inlined. + * `Integer#*`, `Integer#!=`, `String#!=`, `String#getbyte`, + `Kernel#block_given?`, `Kernel#is_a?`, `Kernel#instance_of?`, and `Module#===` + are specially optimized. + * Compilation speed is now slightly faster than Ruby 3.2. + * Now more than 3x faster than the interpreter on Optcarrot! +* Significantly improved memory usage over Ruby 3.2 + * Metadata for compiled code uses a lot less memory. + * `--yjit-call-threshold` is automatically raised from 30 to 120 + when the application has more than 40,000 ISEQs. + * `--yjit-cold-threshold` is added to skip compiling cold ISEQs. + * More compact code is generated on Arm64. +* Code GC is now disabled by default + * `--yjit-exec-mem-size` is treated as a hard limit where compilation of new code stops. + * No sudden drops in performance due to code GC. + Better copy-on-write behavior on servers reforking with + [Pitchfork](https://github.com/shopify/pitchfork). + * You can still enable code GC if desired with `--yjit-code-gc` +* Add `RubyVM::YJIT.enable` that can enable YJIT at run-time + * You can start YJIT without modifying command-line arguments or environment variables. + Rails 7.2 will [enable YJIT by default](https://github.com/rails/rails/pull/49947) + using this method. + * This can also be used to enable YJIT only once your application is + done booting. `--yjit-disable` can be used if you want to use other + YJIT options while disabling YJIT at boot. +* More YJIT stats are available by default + * `yjit_alloc_size` and several more metadata-related stats are now available by default. + * `ratio_in_yjit` stat produced by `--yjit-stats` is now available in release builds, + a special stats or dev build is no longer required to access most stats. +* Add more profiling capabilities + * `--yjit-perf` is added to facilitate profiling with Linux perf. + * `--yjit-trace-exits` now supports sampling with `--yjit-trace-exits-sample-rate=N` +* More thorough testing and multiple bug fixes +* `--yjit-stats=quiet` is added to avoid printing stats on exit. + +### MJIT + +* MJIT is removed. + * `--disable-jit-support` is removed. Consider using `--disable-yjit --disable-rjit` instead. + +### RJIT + +* Introduced a pure-Ruby JIT compiler RJIT. + * RJIT supports only x86\_64 architecture on Unix platforms. + * Unlike MJIT, it doesn't require a C compiler at runtime. +* RJIT exists only for experimental purposes. + * You should keep using YJIT in production. + +### M:N Thread scheduler + +* M:N Thread scheduler is introduced. [[Feature #19842]] + * Background: Ruby 1.8 and before, M:1 thread scheduler (M Ruby threads + with 1 native thread. Called as User level threads or Green threads) + is used. Ruby 1.9 and later, 1:1 thread scheduler (1 Ruby thread with + 1 native thread). M:1 threads takes lower resources compare with 1:1 + threads because it needs only 1 native threads. However it is difficult + to support context switching for all of blocking operation so 1:1 + threads are employed from Ruby 1.9. M:N thread scheduler uses N native + threads for M Ruby threads (N is small number in general). It doesn't + need same number of native threads as Ruby threads (similar to the M:1 + thread scheduler). Also our M:N threads supports blocking operations + well same as 1:1 threads. See the ticket for more details. + Our M:N thread scheduler refers on the goroutine scheduler in the + Go language. + * In a ractor, only 1 thread can run in a same time because of + implementation. Therefore, applications that use only one Ractor + (most applications) M:N thread scheduler works as M:1 thread scheduler + with further extension from Ruby 1.8. + * M:N thread scheduler can introduce incompatibility for C-extensions, + so it is disabled by default on the main Ractors. + `RUBY_MN_THREADS=1` environment variable will enable it. + On non-main Ractors, M:N thread scheduler is enabled (and can not + disable it now). + * `N` (the number of native threads) can be specified with `RUBY_MAX_CPU` + environment variable. The default is 8. + Note that more than `N` native threads are used to support many kind of + blocking operations. + +[Bug #595]: https://bugs.ruby-lang.org/issues/595 +[Feature #10602]: https://bugs.ruby-lang.org/issues/10602 +[Bug #17146]: https://bugs.ruby-lang.org/issues/17146 +[Feature #18183]: https://bugs.ruby-lang.org/issues/18183 +[Feature #18285]: https://bugs.ruby-lang.org/issues/18285 +[Feature #18498]: https://bugs.ruby-lang.org/issues/18498 +[Feature #18515]: https://bugs.ruby-lang.org/issues/18515 +[Feature #18551]: https://bugs.ruby-lang.org/issues/18551 +[Feature #18885]: https://bugs.ruby-lang.org/issues/18885 +[Feature #18949]: https://bugs.ruby-lang.org/issues/18949 +[Feature #18980]: https://bugs.ruby-lang.org/issues/18980 +[Bug #19012]: https://bugs.ruby-lang.org/issues/19012 +[Feature #19057]: https://bugs.ruby-lang.org/issues/19057 +[Bug #19150]: https://bugs.ruby-lang.org/issues/19150 +[Bug #19293]: https://bugs.ruby-lang.org/issues/19293 +[Feature #19314]: https://bugs.ruby-lang.org/issues/19314 +[Feature #19347]: https://bugs.ruby-lang.org/issues/19347 +[Feature #19351]: https://bugs.ruby-lang.org/issues/19351 +[Feature #19362]: https://bugs.ruby-lang.org/issues/19362 +[Feature #19370]: https://bugs.ruby-lang.org/issues/19370 +[Feature #19521]: https://bugs.ruby-lang.org/issues/19521 +[Feature #19538]: https://bugs.ruby-lang.org/issues/19538 +[Feature #19561]: https://bugs.ruby-lang.org/issues/19561 +[Feature #19571]: https://bugs.ruby-lang.org/issues/19571 +[Feature #19572]: https://bugs.ruby-lang.org/issues/19572 +[Feature #19591]: https://bugs.ruby-lang.org/issues/19591 +[Feature #19630]: https://bugs.ruby-lang.org/issues/19630 +[Feature #19637]: https://bugs.ruby-lang.org/issues/19637 +[Feature #19678]: https://bugs.ruby-lang.org/issues/19678 +[Feature #19714]: https://bugs.ruby-lang.org/issues/19714 +[Feature #19725]: https://bugs.ruby-lang.org/issues/19725 +[Feature #19757]: https://bugs.ruby-lang.org/issues/19757 +[Feature #19776]: https://bugs.ruby-lang.org/issues/19776 +[Feature #19777]: https://bugs.ruby-lang.org/issues/19777 +[Feature #19785]: https://bugs.ruby-lang.org/issues/19785 +[Feature #19790]: https://bugs.ruby-lang.org/issues/19790 +[Feature #19839]: https://bugs.ruby-lang.org/issues/19839 +[Feature #19842]: https://bugs.ruby-lang.org/issues/19842 +[Feature #19843]: https://bugs.ruby-lang.org/issues/19843 +[Bug #19868]: https://bugs.ruby-lang.org/issues/19868 +[Feature #19965]: https://bugs.ruby-lang.org/issues/19965 +[Feature #20005]: https://bugs.ruby-lang.org/issues/20005 +[Feature #20057]: https://bugs.ruby-lang.org/issues/20057 diff --git a/doc/NEWS/NEWS-3.4.0.md b/doc/NEWS/NEWS-3.4.0.md new file mode 100644 index 00000000000000..e9cc3a95690bf7 --- /dev/null +++ b/doc/NEWS/NEWS-3.4.0.md @@ -0,0 +1,962 @@ +# NEWS for Ruby 3.4.0 + +This document is a list of user-visible feature changes +since the **3.3.0** release, except for bug fixes. + +Note that each entry is kept to a minimum, see links for details. + +## Language changes + +* `it` is added to reference a block parameter. [[Feature #18980]] + +* String literals in files without a `frozen_string_literal` comment now emit a deprecation warning + when they are mutated. + These warnings can be enabled with `-W:deprecated` or by setting `Warning[:deprecated] = true`. + To disable this change, you can run Ruby with the `--disable-frozen-string-literal` + command line argument. [[Feature #20205]] + + * `String#+@` now duplicates when mutating the string would emit + a deprecation warning, offered as a replacement for the + `str.dup if str.frozen?` pattern. + +* Keyword splatting `nil` when calling methods is now supported. + `**nil` is treated similarly to `**{}`, passing no keywords, + and not calling any conversion methods. [[Bug #20064]] + +* Block passing is no longer allowed in index assignment + (e.g. `a[0, &b] = 1`). [[Bug #19918]] + +* Keyword arguments are no longer allowed in index assignment + (e.g. `a[0, kw: 1] = 2`). [[Bug #20218]] + +* The toplevel name `::Ruby` is reserved now, and the definition will be warned + when `Warning[:deprecated]`. [[Feature #20884]] + +## Core classes updates + +Note: We're only listing outstanding class updates. + + +* Array + + * `Array#fetch_values` was added. [[Feature #20702]] + +* Exception + + * `Exception#set_backtrace` now accepts arrays of `Thread::Backtrace::Location`. + `Kernel#raise`, `Thread#raise` and `Fiber#raise` also accept this new format. [[Feature #13557]] + +* Fiber::Scheduler + + * An optional `Fiber::Scheduler#blocking_operation_wait` hook allows blocking operations to be moved out of the + event loop in order to reduce latency and improve multi-core processor utilization. [[Feature #20876]] + +* GC + + * `GC.config` added to allow setting configuration variables on the Garbage + Collector. [[Feature #20443]] + + * GC configuration parameter `rgengc_allow_full_mark` introduced. When `false` + GC will only mark young objects. Default is `true`. [[Feature #20443]] + +* Hash + + * `Hash.new` now accepts an optional `capacity:` argument, to preallocate the hash with a given capacity. + This can improve performance when building large hashes incrementally by saving on reallocation and + rehashing of keys. [[Feature #19236]] + +* IO::Buffer + + * `IO::Buffer#copy` can release the GVL, allowing other threads to run while copying data. [[Feature #20902]] + +* Integer + + * `Integer#**` used to return `Float::INFINITY` when the return value is large, but now returns an `Integer`. + If the return value is extremely large, it raises an exception. + [[Feature #20811]] + +* MatchData + + * `MatchData#bytebegin` and `MatchData#byteend` have been added. [[Feature #20576]] + +* Object + + * `Object#singleton_method` now returns methods in modules prepended to or included in the + receiver's singleton class. [[Bug #20620]] + + ```rb + o = Object.new + o.extend(Module.new{def a = 1}) + o.singleton_method(:a).call #=> 1 + ``` + +* Ractor + + * `require` in Ractor is allowed. The requiring process will be run on + the main Ractor. + `Ractor._require(feature)` is added to run requiring process on the + main Ractor. + [[Feature #20627]] + + * `Ractor.main?` is added. [[Feature #20627]] + + * `Ractor.[]` and `Ractor.[]=` are added to access the ractor local storage + of the current Ractor. [[Feature #20715]] + + * `Ractor.store_if_absent(key){ init }` is added to initialize ractor local + variables in thread-safety. [[Feature #20875]] + +* Range + + * `Range#size` now raises `TypeError` if the range is not iterable. [[Misc #18984]] + * `Range#step` now consistently has a semantics of iterating by using `+` operator + for all types, not only numerics. [[Feature #18368]] + + ```ruby + (Time.utc(2022, 2, 24)..).step(24*60*60).take(3) + #=> [2022-02-24 00:00:00 UTC, 2022-02-25 00:00:00 UTC, 2022-02-26 00:00:00 UTC] + ``` + +* Rational + + * `Rational#**` used to return `Float::INFINITY` or `Float::NAN` + when the numerator of the return value is large, but now returns an `Rational`. + If it is extremely large, it raises an exception. [[Feature #20811]] + +* RubyVM::AbstractSyntaxTree + + * Add `RubyVM::AbstractSyntaxTree::Node#locations` method which returns location objects + associated with the AST node. [[Feature #20624]] + * Add `RubyVM::AbstractSyntaxTree::Location` class which holds location information. [[Feature #20624]] + + +* String + + * `String#append_as_bytes` was added to more easily and efficiently work with binary buffers and protocols. + It directly concatenate the arguments into the string without any encoding validation or conversion. + [[Feature #20594]] + +* Symbol + + * The string returned by `Symbol#to_s` now emits a deprecation warning when mutated, and will be + frozen in a future version of Ruby. + These warnings can be enabled with `-W:deprecated` or by setting `Warning[:deprecated] = true`. + [[Feature #20350]] + +* Time + + * On Windows, now `Time#zone` encodes the system timezone name in UTF-8 + instead of the active code page, if it contains non-ASCII characters. + [[Bug #20929]] + + * `Time#xmlschema`, and its `Time#iso8601` alias have been moved into the core Time + class while previously it was an extension provided by the `time` gem. [[Feature #20707]] + +* Warning + + * Add `Warning.categories` method which returns a list of possible warning categories. + [[Feature #20293]] + +## Stdlib updates + +We only list stdlib changes that are notable feature changes. + +* RubyGems + + * Add `--attestation` option to gem push. It enabled to store signature of build artifact to sigstore.dev. + +* Bundler + + * Add a `lockfile_checksums` configuration to include checksums in fresh lockfiles. + * Add bundle lock `--add-checksums` to add checksums to an existing lockfile. + +* JSON + + * Performance improvements `JSON.parse` about 1.5 times faster than json-2.7.x. + +* Tempfile + + * The keyword argument `anonymous: true` is implemented for Tempfile.create. + `Tempfile.create(anonymous: true)` removes the created temporary file immediately. + So applications don't need to remove the file. + [[Feature #20497]] + +* win32/sspi.rb + + * This library is now extracted from the Ruby repository to [ruby/net-http-sspi]. + [[Feature #20775]] + +* Socket + + * `Socket::ResolutionError` and `Socket::ResolutionError#error_code` was added. + [[Feature #20018]] + +* IRB + + * Interactive method completion is now improved with type information by default. + [[Feature #20778]] + +Other changes are listed in the following sections. we also listed release history from the previous bundled version that is Ruby 3.3.0 if it has GitHub releases. + +The following default gem is added. + +* win32-registry 0.1.0 + +The following default gems are updated. + +* RubyGems 3.6.2 +* benchmark 0.4.0 +* bundler 2.6.2 +* date 3.4.1 +* delegate 0.4.0 +* did_you_mean 2.0.0 +* digest 3.2.0 +* erb 4.0.4 +* error_highlight 0.7.0 +* etc 1.4.5 +* fcntl 1.2.0 +* fiddle 1.1.6 +* fileutils 1.7.3 +* io-console 0.8.0 +* io-nonblock 0.3.1 +* ipaddr 1.2.7 +* irb 1.14.3 +* json 2.9.1 +* logger 1.6.4 +* net-http 0.6.0 +* open-uri 0.5.0 +* openssl 3.3.0 +* optparse 0.6.0 +* ostruct 0.6.1 +* pathname 0.4.0 +* pp 0.6.2 +* prism 1.2.0 +* pstore 0.1.4 +* psych 5.2.2 +* rdoc 6.10.0 +* reline 0.6.0 +* resolv 0.6.0 +* securerandom 0.4.1 +* set 1.1.1 +* shellwords 0.2.2 +* singleton 0.3.0 +* stringio 3.1.2 +* strscan 3.1.2 +* syntax_suggest 2.0.2 +* tempfile 0.3.1 +* time 0.4.1 +* timeout 0.4.3 +* tmpdir 0.3.1 +* uri 1.0.2 +* win32ole 1.9.1 +* yaml 0.4.0 +* zlib 3.2.1 + + * 3.5.3 to [v3.5.4][RubyGems-v3.5.4], [v3.5.5][RubyGems-v3.5.5], [v3.5.6][RubyGems-v3.5.6], [v3.5.7][RubyGems-v3.5.7], [v3.5.8][RubyGems-v3.5.8], [v3.5.9][RubyGems-v3.5.9], [v3.5.10][RubyGems-v3.5.10], [v3.5.11][RubyGems-v3.5.11], [v3.5.12][RubyGems-v3.5.12], [v3.5.13][RubyGems-v3.5.13], [v3.5.14][RubyGems-v3.5.14], [v3.5.15][RubyGems-v3.5.15], [v3.5.16][RubyGems-v3.5.16], [v3.5.17][RubyGems-v3.5.17], [v3.5.18][RubyGems-v3.5.18], [v3.5.19][RubyGems-v3.5.19], [v3.5.20][RubyGems-v3.5.20], [v3.5.21][RubyGems-v3.5.21], [v3.5.22][RubyGems-v3.5.22], [v3.5.23][RubyGems-v3.5.23], [v3.6.0][RubyGems-v3.6.0], [v3.6.1][RubyGems-v3.6.1], [v3.6.2][RubyGems-v3.6.2] +* [benchmark][benchmark] 0.4.0 + * 0.3.0 to [v0.4.0][benchmark-v0.4.0] +* [bundler][bundler] 2.6.2 + * 2.5.3 to [v2.5.4][bundler-v2.5.4], [v2.5.5][bundler-v2.5.5], [v2.5.6][bundler-v2.5.6], [v2.5.7][bundler-v2.5.7], [v2.5.8][bundler-v2.5.8], [v2.5.9][bundler-v2.5.9], [v2.5.10][bundler-v2.5.10], [v2.5.11][bundler-v2.5.11], [v2.5.12][bundler-v2.5.12], [v2.5.13][bundler-v2.5.13], [v2.5.14][bundler-v2.5.14], [v2.5.15][bundler-v2.5.15], [v2.5.16][bundler-v2.5.16], [v2.5.17][bundler-v2.5.17], [v2.5.18][bundler-v2.5.18], [v2.5.19][bundler-v2.5.19], [v2.5.20][bundler-v2.5.20], [v2.5.21][bundler-v2.5.21], [v2.5.22][bundler-v2.5.22], [v2.5.23][bundler-v2.5.23], [v2.6.0][bundler-v2.6.0], [v2.6.1][bundler-v2.6.1], [v2.6.2][bundler-v2.6.2] +* [date][date] 3.4.1 + * 3.3.4 to [v3.4.0][date-v3.4.0], [v3.4.1][date-v3.4.1] +* [delegate][delegate] 0.4.0 + * 0.3.1 to [v0.4.0][delegate-v0.4.0] +* [did_you_mean][did_you_mean] 2.0.0 + * 1.6.3 to [v2.0.0][did_you_mean-v2.0.0] +* [digest][digest] 3.2.0 + * 3.1.1 to [v3.2.0.pre0][digest-v3.2.0.pre0], [v3.2.0][digest-v3.2.0] +* [erb][erb] 4.0.4 + * 4.0.3 to [v4.0.4][erb-v4.0.4] +* [error_highlight][error_highlight] 0.7.0 + * 0.6.0 to [v0.7.0][error_highlight-v0.7.0] +* [etc][etc] 1.4.5 + * 1.4.3 to [v1.4.4][etc-v1.4.4], [v1.4.5][etc-v1.4.5] +* [fcntl][fcntl] 1.2.0 + * 1.1.0 to [v1.2.0][fcntl-v1.2.0] +* [fiddle][fiddle] 1.1.6 + * 1.1.2 to [v1.1.3][fiddle-v1.1.3], [v1.1.4][fiddle-v1.1.4], [v1.1.5][fiddle-v1.1.5], [v1.1.6][fiddle-v1.1.6] +* [fileutils][fileutils] 1.7.3 + * 1.7.2 to [v1.7.3][fileutils-v1.7.3] +* [io-console][io-console] 0.8.0 + * 0.7.1 to [v0.7.2][io-console-v0.7.2], [v0.8.0.beta1][io-console-v0.8.0.beta1], [v0.8.0][io-console-v0.8.0] +* [io-nonblock][io-nonblock] 0.3.1 + * 0.3.0 to [v0.3.1][io-nonblock-v0.3.1] +* [ipaddr][ipaddr] 1.2.7 + * 1.2.6 to [v1.2.7][ipaddr-v1.2.7] +* [irb][irb] 1.14.3 + * 1.11.0 to [v1.11.1][irb-v1.11.1], [v1.11.2][irb-v1.11.2], [v1.12.0][irb-v1.12.0], [v1.13.0][irb-v1.13.0], [v1.13.1][irb-v1.13.1], [v1.13.2][irb-v1.13.2], [v1.14.0][irb-v1.14.0], [v1.14.1][irb-v1.14.1], [v1.14.2][irb-v1.14.2], [v1.14.3][irb-v1.14.3] +* [json][json] 2.9.1 + * 2.7.1 to [v2.7.2][json-v2.7.2], [v2.7.3.rc1][json-v2.7.3.rc1], [v2.7.3][json-v2.7.3], [v2.7.4][json-v2.7.4], [v2.7.5][json-v2.7.5], [v2.7.6][json-v2.7.6], [v2.8.0][json-v2.8.0], [v2.8.1][json-v2.8.1], [v2.8.2][json-v2.8.2], [v2.9.0][json-v2.9.0], [v2.9.1][json-v2.9.1] +* [logger][logger] 1.6.4 + * 1.6.0 to [v1.6.1][logger-v1.6.1], [v1.6.2][logger-v1.6.2], [v1.6.3][logger-v1.6.3], [v1.6.4][logger-v1.6.4] +* [net-http][net-http] 0.6.0 + * 0.4.0 to [v0.4.1][net-http-v0.4.1], [v0.5.0][net-http-v0.5.0], [v0.6.0][net-http-v0.6.0] +* [open-uri][open-uri] 0.5.0 + * 0.4.1 to [v0.5.0][open-uri-v0.5.0] +* [optparse][optparse] 0.6.0 + * 0.4.0 to [v0.5.0][optparse-v0.5.0], [v0.6.0][optparse-v0.6.0] +* [ostruct][ostruct] 0.6.1 + * 0.6.0 to [v0.6.1][ostruct-v0.6.1] +* [pathname][pathname] 0.4.0 + * 0.3.0 to [v0.4.0][pathname-v0.4.0] +* [pp][pp] 0.6.2 + * 0.5.0 to [v0.6.0][pp-v0.6.0], [v0.6.1][pp-v0.6.1], [v0.6.2][pp-v0.6.2] +* [prism][prism] 1.2.0 + * 0.19.0 to [v0.20.0][prism-v0.20.0], [v0.21.0][prism-v0.21.0], [v0.22.0][prism-v0.22.0], [v0.23.0][prism-v0.23.0], [v0.24.0][prism-v0.24.0], [v0.25.0][prism-v0.25.0], [v0.26.0][prism-v0.26.0], [v0.27.0][prism-v0.27.0], [v0.28.0][prism-v0.28.0], [v0.29.0][prism-v0.29.0], [v0.30.0][prism-v0.30.0], [v1.0.0][prism-v1.0.0], [v1.1.0][prism-v1.1.0], [v1.2.0][prism-v1.2.0] +* [pstore][pstore] 0.1.4 + * 0.1.3 to [v0.1.4][pstore-v0.1.4] +* [psych][psych] 5.2.2 + * 5.1.2 to [v5.2.0.beta1][psych-v5.2.0.beta1], [v5.2.0.beta2][psych-v5.2.0.beta2], [v5.2.0.beta3][psych-v5.2.0.beta3], [v5.2.0.beta4][psych-v5.2.0.beta4], [v5.2.0.beta5][psych-v5.2.0.beta5], [v5.2.0.beta6][psych-v5.2.0.beta6], [v5.2.0.beta7][psych-v5.2.0.beta7], [v5.2.0][psych-v5.2.0], [v5.2.1][psych-v5.2.1], [v5.2.2][psych-v5.2.2] +* [rdoc][rdoc] 6.10.0 + * 6.6.2 to [v6.7.0][rdoc-v6.7.0], [v6.8.0][rdoc-v6.8.0], [v6.8.1][rdoc-v6.8.1], [v6.9.0][rdoc-v6.9.0], [v6.9.1][rdoc-v6.9.1], [v6.10.0][rdoc-v6.10.0] +* [reline][reline] 0.6.0 + * 0.4.1 to [v0.4.2][reline-v0.4.2], [v0.4.3][reline-v0.4.3], [v0.5.0.pre.1][reline-v0.5.0.pre.1], [v0.5.0][reline-v0.5.0], [v0.5.1][reline-v0.5.1], [v0.5.2][reline-v0.5.2], [v0.5.3][reline-v0.5.3], [v0.5.4][reline-v0.5.4], [v0.5.5][reline-v0.5.5], [v0.5.6][reline-v0.5.6], [v0.5.7][reline-v0.5.7], [v0.5.8][reline-v0.5.8], [v0.5.9][reline-v0.5.9], [v0.5.10][reline-v0.5.10], [v0.5.11][reline-v0.5.11], [v0.5.12][reline-v0.5.12], [v0.6.0][reline-v0.6.0] +* [resolv][resolv] 0.6.0 + * 0.3.0 to [v0.4.0][resolv-v0.4.0], [v0.5.0][resolv-v0.5.0], [v0.6.0][resolv-v0.6.0] +* [securerandom][securerandom] 0.4.1 + * 0.3.1 to [v0.3.2][securerandom-v0.3.2], [v0.4.0][securerandom-v0.4.0], [v0.4.1][securerandom-v0.4.1] +* [set][set] 1.1.1 + * 1.1.0 to [v1.1.1][set-v1.1.1] +* [shellwords][shellwords] 0.2.2 + * 0.2.0 to [v0.2.1][shellwords-v0.2.1], [v0.2.2][shellwords-v0.2.2] +* [singleton][singleton] 0.3.0 + * 0.2.0 to [v0.3.0][singleton-v0.3.0] +* [stringio][stringio] 3.1.2 + * 3.1.0 to [v3.1.1][stringio-v3.1.1], [v3.1.2][stringio-v3.1.2] +* [strscan][strscan] 3.1.2 + * 3.0.7 to [v3.0.8][strscan-v3.0.8], [v3.0.9][strscan-v3.0.9], [v3.1.0][strscan-v3.1.0], [v3.1.1][strscan-v3.1.1], [v3.1.2][strscan-v3.1.2] +* [syntax_suggest][syntax_suggest] 2.0.2 + * 2.0.0 to [v2.0.1][syntax_suggest-v2.0.1], [v2.0.2][syntax_suggest-v2.0.2] +* [tempfile][tempfile] 0.3.1 + * 0.2.1 to [v0.3.0][tempfile-v0.3.0], [v0.3.1][tempfile-v0.3.1] +* [time][time] 0.4.1 + * 0.3.0 to [v0.4.0][time-v0.4.0], [v0.4.1][time-v0.4.1] +* [timeout][timeout] 0.4.3 + * 0.4.1 to [v0.4.2][timeout-v0.4.2], [v0.4.3][timeout-v0.4.3] +* [tmpdir][tmpdir] 0.3.1 + * 0.2.0 to [v0.3.0][tmpdir-v0.3.0], [v0.3.1][tmpdir-v0.3.1] +* [uri][uri] 1.0.2 + * 0.13.0 to [v0.13.1][uri-v0.13.1], [v1.0.0][uri-v1.0.0], [v1.0.1][uri-v1.0.1], [v1.0.2][uri-v1.0.2] +* [win32ole][win32ole] 1.9.1 + * 1.8.10 to [v1.9.0][win32ole-v1.9.0], [v1.9.1][win32ole-v1.9.1] +* [yaml][yaml] 0.4.0 + * 0.3.0 to [v0.4.0][yaml-v0.4.0] +* [zlib][zlib] 3.2.1 + * 3.1.0 to [v3.1.1][zlib-v3.1.1], [v3.2.0][zlib-v3.2.0], [v3.2.1][zlib-v3.2.1] + +The following bundled gem is added. + +* [repl_type_completor][repl_type_completor] 0.1.9 + +The following bundled gems are updated. + +* [minitest][minitest] 5.25.4 + * 5.20.0 to [v5.25.4][minitest-v5.25.4] +* [power_assert][power_assert] 2.0.5 + * 2.0.3 to [v2.0.4][power_assert-v2.0.4], [v2.0.5][power_assert-v2.0.5] +* [rake][rake] 13.2.1 + * 13.1.0 to [v13.2.0][rake-v13.2.0], [v13.2.1][rake-v13.2.1] +* [test-unit][test-unit] 3.6.7 + * 3.6.1 to [3.6.2][test-unit-3.6.2], [3.6.3][test-unit-3.6.3], [3.6.4][test-unit-3.6.4], [3.6.5][test-unit-3.6.5], [3.6.6][test-unit-3.6.6], [3.6.7][test-unit-3.6.7] +* [rexml][rexml] 3.4.0 + * 3.2.6 to [v3.2.7][rexml-v3.2.7], [v3.2.8][rexml-v3.2.8], [v3.2.9][rexml-v3.2.9], [v3.3.0][rexml-v3.3.0], [v3.3.1][rexml-v3.3.1], [v3.3.2][rexml-v3.3.2], [v3.3.3][rexml-v3.3.3], [v3.3.4][rexml-v3.3.4], [v3.3.5][rexml-v3.3.5], [v3.3.6][rexml-v3.3.6], [v3.3.7][rexml-v3.3.7], [v3.3.8][rexml-v3.3.8], [v3.3.9][rexml-v3.3.9], [v3.4.0][rexml-v3.4.0] +* [rss][rss] 0.3.1 + * 0.3.0 to [0.3.1][rss-0.3.1] +* [net-ftp][net-ftp] 0.3.8 + * 0.3.3 to [v0.3.4][net-ftp-v0.3.4], [v0.3.5][net-ftp-v0.3.5], [v0.3.6][net-ftp-v0.3.6], [v0.3.7][net-ftp-v0.3.7], [v0.3.8][net-ftp-v0.3.8] +* [net-imap][net-imap] 0.5.4 + * 0.4.9 to [v0.4.9.1][net-imap-v0.4.9.1], [v0.4.10][net-imap-v0.4.10], [v0.4.11][net-imap-v0.4.11], [v0.4.12][net-imap-v0.4.12], [v0.4.13][net-imap-v0.4.13], [v0.4.14][net-imap-v0.4.14], [v0.4.15][net-imap-v0.4.15], [v0.4.16][net-imap-v0.4.16], [v0.4.17][net-imap-v0.4.17], [v0.5.0][net-imap-v0.5.0], [v0.4.18][net-imap-v0.4.18], [v0.5.1][net-imap-v0.5.1], [v0.5.2][net-imap-v0.5.2], [v0.5.3][net-imap-v0.5.3], [v0.5.4][net-imap-v0.5.4] +* [net-smtp][net-smtp] 0.5.0 + * 0.4.0 to [v0.4.0.1][net-smtp-v0.4.0.1], [v0.5.0][net-smtp-v0.5.0] +* [prime][prime] 0.1.3 + * 0.1.2 to [v0.1.3][prime-v0.1.3] +* [rbs][rbs] 3.8.0 + * 3.4.0 to [v3.4.1][rbs-v3.4.1], [v3.4.2][rbs-v3.4.2], [v3.4.3][rbs-v3.4.3], [v3.4.4][rbs-v3.4.4], [v3.5.0.pre.1][rbs-v3.5.0.pre.1], [v3.5.0.pre.2][rbs-v3.5.0.pre.2], [v3.5.0][rbs-v3.5.0], [v3.5.1][rbs-v3.5.1], [v3.5.2][rbs-v3.5.2], [v3.5.3][rbs-v3.5.3], [v3.6.0.dev.1][rbs-v3.6.0.dev.1], [v3.6.0.pre.1][rbs-v3.6.0.pre.1], [v3.6.0.pre.2][rbs-v3.6.0.pre.2], [v3.6.0.pre.3][rbs-v3.6.0.pre.3], [v3.6.0][rbs-v3.6.0], [v3.6.1][rbs-v3.6.1], [v3.7.0.dev.1][rbs-v3.7.0.dev.1], [v3.7.0.pre.1][rbs-v3.7.0.pre.1], [v3.7.0][rbs-v3.7.0], [v3.8.0.pre.1][rbs-v3.8.0.pre.1] [v3.8.0][rbs-v3.8.0] +* [typeprof][typeprof] 0.30.1 + * 0.21.9 to [v0.30.1][typeprof-v0.30.1] +* [debug][debug] 1.10.0 + * 1.9.1 to [v1.9.2][debug-v1.9.2], [v1.10.0][debug-v1.10.0] +* [racc][racc] 1.8.1 + * 1.7.3 to [v1.8.0][racc-v1.8.0], [v1.8.1][racc-v1.8.1] + +The following bundled gems are promoted from default gems. + +* [mutex_m][mutex_m] 0.3.0 + * 0.2.0 to [v0.3.0][mutex_m-v0.3.0] +* [getoptlong][getoptlong] 0.2.1 +* [base64][base64] 0.2.0 +* [bigdecimal][bigdecimal] 3.1.8 + * 3.1.5 to [v3.1.6][bigdecimal-v3.1.6], [v3.1.7][bigdecimal-v3.1.7], [v3.1.8][bigdecimal-v3.1.8] +* [observer][observer] 0.1.2 +* [abbrev][abbrev] 0.1.2 +* [resolv-replace][resolv-replace] 0.1.1 +* [rinda][rinda] 0.2.0 +* [drb][drb] 2.2.1 + * 2.2.0 to [v2.2.1][drb-v2.2.1] +* [nkf][nkf] 0.2.0 + * 0.1.3 to [v0.2.0][nkf-v0.2.0] +* [syslog][syslog] 0.2.0 + * 0.1.2 to [v0.2.0][syslog-v0.2.0] +* [csv][csv] 3.3.2 + * 3.2.8 to [v3.2.9][csv-v3.2.9], [v3.3.0][csv-v3.3.0], [v3.3.1][csv-v3.3.1], [v3.3.2][csv-v3.3.2] + +## Supported platforms + +## Compatibility issues + +* Error messages and backtrace displays have been changed. + + * Use a single quote instead of a backtick as an opening quote. [[Feature #16495]] + * Display a class name before a method name (only when the class has a permanent name). [[Feature #19117]] + * Extra `rescue`/`ensure` frames are no longer available on the backtrace. [[Feature #20275]] + * `Kernel#caller`, `Thread::Backtrace::Location`’s methods, etc. are also changed accordingly. + + Old: + ``` + test.rb:1:in `foo': undefined method `time' for an instance of Integer + from test.rb:2:in `
' + ``` + + New: + ``` + test.rb:1:in 'Object#foo': undefined method 'time' for an instance of Integer + from test.rb:2:in '
' + ``` + +* `Hash#inspect` rendering have been changed. [[Bug #20433]] + + * Symbol keys are displayed using the modern symbol key syntax: `"{user: 1}"` + * Other keys now have spaces around `=>`: `'{"user" => 1}'`, while previously they didn't: `'{"user"=>1}'` + +* `Kernel#Float()` now accepts a decimal string with decimal part omitted. [[Feature #20705]] + + ```rb + Float("1.") #=> 1.0 (previously, an ArgumentError was raised) + Float("1.E-1") #=> 0.1 (previously, an ArgumentError was raised) + ``` + +* `String#to_f` now accepts a decimal string with decimal part omitted. [[Feature #20705]] + Note that the result changes when an exponent is specified. + + ```rb + "1.".to_f #=> 1.0 + "1.E-1".to_f #=> 0.1 (previously, 1.0 was returned) + ``` + +* `Refinement#refined_class` has been removed. [[Feature #19714]] + +## Stdlib compatibility issues + +* DidYouMean + + * `DidYouMean::SPELL_CHECKERS[]=` and `DidYouMean::SPELL_CHECKERS.merge!` are removed. + +* Net::HTTP + + * Removed the following deprecated constants: + * `Net::HTTP::ProxyMod` + * `Net::NetPrivate::HTTPRequest` + * `Net::HTTPInformationCode` + * `Net::HTTPSuccessCode` + * `Net::HTTPRedirectionCode` + * `Net::HTTPRetriableCode` + * `Net::HTTPClientErrorCode` + * `Net::HTTPFatalErrorCode` + * `Net::HTTPServerErrorCode` + * `Net::HTTPResponseReceiver` + * `Net::HTTPResponceReceiver` + + These constants were deprecated from 2012. + +* Timeout + + * Reject negative values for `Timeout.timeout`. [[Bug #20795]] + +* URI + + * Switched default parser to RFC 3986 compliant from RFC 2396 compliant. + [[Bug #19266]] + +## C API updates + +* `rb_newobj` and `rb_newobj_of` (and corresponding macros `RB_NEWOBJ`, `RB_NEWOBJ_OF`, `NEWOBJ`, `NEWOBJ_OF`) have been removed. [[Feature #20265]] +* Removed deprecated function `rb_gc_force_recycle`. [[Feature #18290]] + +## Implementation improvements + +* The default parser is now Prism. + To use the conventional parser, use the command-line argument `--parser=parse.y`. + [[Feature #20564]] + +* Happy Eyeballs version 2 (RFC8305), an algorithm that ensures faster and more reliable connections + by attempting IPv6 and IPv4 concurrently, is used in `Socket.tcp` and `TCPSocket.new`. + To disable it globally, set the environment variable `RUBY_TCP_NO_FAST_FALLBACK=1` or + call `Socket.tcp_fast_fallback=false`. + Or to disable it on a per-method basis, use the keyword argument `fast_fallback: false`. + [[Feature #20108]] [[Feature #20782]] + +* Alternative garbage collector (GC) implementations can be loaded dynamically + through the modular garbage collector feature. To enable this feature, + configure Ruby with `--with-modular-gc` at build time. GC libraries can be + loaded at runtime using the environment variable `RUBY_GC_LIBRARY`. + [[Feature #20351]] + +* Ruby's built-in garbage collector has been split into a separate file at + `gc/default/default.c` and interacts with Ruby using an API defined in + `gc/gc_impl.h`. The built-in garbage collector can now also be built as a + library using `make modular-gc MODULAR_GC=default` and enabled using the + environment variable `RUBY_GC_LIBRARY=default`. [[Feature #20470]] + +* An experimental GC library is provided based on [MMTk](https://www.mmtk.io/). + This GC library can be built using `make modular-gc MODULAR_GC=mmtk` and + enabled using the environment variable `RUBY_GC_LIBRARY=mmtk`. This requires + the Rust toolchain on the build machine. [[Feature #20860]] + +### YJIT + +#### New features + +* Command-line options + * `--yjit-mem-size` introduces a unified memory limit (default 128MiB) to track total YJIT memory usage, + providing a more intuitive alternative to the old `--yjit-exec-mem-size` option. + * `--yjit-trace-exits=COUNTER` allows tracing of counted exits and fallbacks. + * `--yjit-perf=codegen` allows profiling of JIT code based on YJIT's codegen functions. + * `--yjit-log` enables a compilation log to track what gets compiled. +* Ruby API + * `RubyVM::YJIT.enable(log: true)` also enables a compilation log. + * `RubyVM::YJIT.log` provides access to the tail of the compilation log at run-time. +* YJIT stats + * `RubyVM::YJIT.runtime_stats` now always provides additional statistics on + invalidation, inlining, and metadata encoding. + * `RubyVM::YJIT.runtime_stats[:iseq_calls]` is added to profile non-inlined Ruby method calls. + * `RubyVM::YJIT.runtime_stats[:cfunc_calls]` is truncated to the top 20 entries for better performance. + +#### New optimizations + +* Compressed context reduces memory needed to store YJIT metadata +* Allocate registers for local variables and Ruby method arguments +* When YJIT is enabled, use more Core primitives written in Ruby: + * `Array#each`, `Array#select`, `Array#map` rewritten in Ruby for better performance [[Feature #20182]]. +* Ability to inline small/trivial methods such as: + * Empty methods + * Methods returning a constant + * Methods returning `self` + * Methods directly returning an argument +* Specialized codegen for many more runtime methods +* Optimize `String#getbyte`, `String#setbyte` and other string methods +* Optimize bitwise operations to speed up low-level bit/byte manipulation +* Support shareable constants in multi-ractor mode +* Various other incremental optimizations + +## Miscellaneous changes + +* Passing a block to a method which doesn't use the passed block will show + a warning on verbose mode (`-w`). + In connection with this, a new `strict_unused_block` warning category was introduced. + Turn them on with `-W:strict_unused_block` or `Warning[:strict_unused_block] = true`. + [[Feature #15554]] + +* Redefining some core methods that are specially optimized by the interpreter + and JIT like `String#freeze` or `Integer#+` now emits a performance class + warning (`-W:performance` or `Warning[:performance] = true`). + [[Feature #20429]] + +[Feature #13557]: https://bugs.ruby-lang.org/issues/13557 +[Feature #15554]: https://bugs.ruby-lang.org/issues/15554 +[Feature #16495]: https://bugs.ruby-lang.org/issues/16495 +[Feature #18290]: https://bugs.ruby-lang.org/issues/18290 +[Feature #18368]: https://bugs.ruby-lang.org/issues/18368 +[Feature #18980]: https://bugs.ruby-lang.org/issues/18980 +[Misc #18984]: https://bugs.ruby-lang.org/issues/18984 +[Feature #19117]: https://bugs.ruby-lang.org/issues/19117 +[Feature #19236]: https://bugs.ruby-lang.org/issues/19236 +[Bug #19266]: https://bugs.ruby-lang.org/issues/19266 +[Feature #19714]: https://bugs.ruby-lang.org/issues/19714 +[Bug #19918]: https://bugs.ruby-lang.org/issues/19918 +[Feature #20018]: https://bugs.ruby-lang.org/issues/20018 +[Bug #20064]: https://bugs.ruby-lang.org/issues/20064 +[Feature #20108]: https://bugs.ruby-lang.org/issues/20108 +[Feature #20182]: https://bugs.ruby-lang.org/issues/20182 +[Feature #20205]: https://bugs.ruby-lang.org/issues/20205 +[Bug #20218]: https://bugs.ruby-lang.org/issues/20218 +[Feature #20265]: https://bugs.ruby-lang.org/issues/20265 +[Feature #20275]: https://bugs.ruby-lang.org/issues/20275 +[Feature #20293]: https://bugs.ruby-lang.org/issues/20293 +[Feature #20350]: https://bugs.ruby-lang.org/issues/20350 +[Feature #20351]: https://bugs.ruby-lang.org/issues/20351 +[Feature #20429]: https://bugs.ruby-lang.org/issues/20429 +[Bug #20433]: https://bugs.ruby-lang.org/issues/20433 +[Feature #20443]: https://bugs.ruby-lang.org/issues/20443 +[Feature #20470]: https://bugs.ruby-lang.org/issues/20470 +[Feature #20497]: https://bugs.ruby-lang.org/issues/20497 +[Feature #20564]: https://bugs.ruby-lang.org/issues/20564 +[Feature #20576]: https://bugs.ruby-lang.org/issues/20576 +[Feature #20594]: https://bugs.ruby-lang.org/issues/20594 +[Bug #20620]: https://bugs.ruby-lang.org/issues/20620 +[Feature #20624]: https://bugs.ruby-lang.org/issues/20624 +[Feature #20627]: https://bugs.ruby-lang.org/issues/20627 +[Feature #20702]: https://bugs.ruby-lang.org/issues/20702 +[Feature #20705]: https://bugs.ruby-lang.org/issues/20705 +[Feature #20707]: https://bugs.ruby-lang.org/issues/20707 +[Feature #20715]: https://bugs.ruby-lang.org/issues/20715 +[Feature #20775]: https://bugs.ruby-lang.org/issues/20775 +[Feature #20778]: https://bugs.ruby-lang.org/issues/20778 +[Feature #20782]: https://bugs.ruby-lang.org/issues/20782 +[Bug #20795]: https://bugs.ruby-lang.org/issues/20795 +[Feature #20811]: https://bugs.ruby-lang.org/issues/20811 +[Feature #20860]: https://bugs.ruby-lang.org/issues/20860 +[Feature #20875]: https://bugs.ruby-lang.org/issues/20875 +[Feature #20876]: https://bugs.ruby-lang.org/issues/20876 +[Feature #20884]: https://bugs.ruby-lang.org/issues/20884 +[Feature #20902]: https://bugs.ruby-lang.org/issues/20902 +[Bug #20929]: https://bugs.ruby-lang.org/issues/20929 +[RubyGems-v3.5.4]: https://github.com/rubygems/rubygems/releases/tag/v3.5.4 +[RubyGems-v3.5.5]: https://github.com/rubygems/rubygems/releases/tag/v3.5.5 +[RubyGems-v3.5.6]: https://github.com/rubygems/rubygems/releases/tag/v3.5.6 +[RubyGems-v3.5.7]: https://github.com/rubygems/rubygems/releases/tag/v3.5.7 +[RubyGems-v3.5.8]: https://github.com/rubygems/rubygems/releases/tag/v3.5.8 +[RubyGems-v3.5.9]: https://github.com/rubygems/rubygems/releases/tag/v3.5.9 +[RubyGems-v3.5.10]: https://github.com/rubygems/rubygems/releases/tag/v3.5.10 +[RubyGems-v3.5.11]: https://github.com/rubygems/rubygems/releases/tag/v3.5.11 +[RubyGems-v3.5.12]: https://github.com/rubygems/rubygems/releases/tag/v3.5.12 +[RubyGems-v3.5.13]: https://github.com/rubygems/rubygems/releases/tag/v3.5.13 +[RubyGems-v3.5.14]: https://github.com/rubygems/rubygems/releases/tag/v3.5.14 +[RubyGems-v3.5.15]: https://github.com/rubygems/rubygems/releases/tag/v3.5.15 +[RubyGems-v3.5.16]: https://github.com/rubygems/rubygems/releases/tag/v3.5.16 +[RubyGems-v3.5.17]: https://github.com/rubygems/rubygems/releases/tag/v3.5.17 +[RubyGems-v3.5.18]: https://github.com/rubygems/rubygems/releases/tag/v3.5.18 +[RubyGems-v3.5.19]: https://github.com/rubygems/rubygems/releases/tag/v3.5.19 +[RubyGems-v3.5.20]: https://github.com/rubygems/rubygems/releases/tag/v3.5.20 +[RubyGems-v3.5.21]: https://github.com/rubygems/rubygems/releases/tag/v3.5.21 +[RubyGems-v3.5.22]: https://github.com/rubygems/rubygems/releases/tag/v3.5.22 +[RubyGems-v3.5.23]: https://github.com/rubygems/rubygems/releases/tag/v3.5.23 +[RubyGems-v3.6.0]: https://github.com/rubygems/rubygems/releases/tag/v3.6.0 +[RubyGems-v3.6.1]: https://github.com/rubygems/rubygems/releases/tag/v3.6.1 +[RubyGems-v3.6.2]: https://github.com/rubygems/rubygems/releases/tag/v3.6.2 +[benchmark-v0.4.0]: https://github.com/ruby/benchmark/releases/tag/v0.4.0 +[bundler-v2.5.4]: https://github.com/rubygems/rubygems/releases/tag/bundler-v2.5.4 +[bundler-v2.5.5]: https://github.com/rubygems/rubygems/releases/tag/bundler-v2.5.5 +[bundler-v2.5.6]: https://github.com/rubygems/rubygems/releases/tag/bundler-v2.5.6 +[bundler-v2.5.7]: https://github.com/rubygems/rubygems/releases/tag/bundler-v2.5.7 +[bundler-v2.5.8]: https://github.com/rubygems/rubygems/releases/tag/bundler-v2.5.8 +[bundler-v2.5.9]: https://github.com/rubygems/rubygems/releases/tag/bundler-v2.5.9 +[bundler-v2.5.10]: https://github.com/rubygems/rubygems/releases/tag/bundler-v2.5.10 +[bundler-v2.5.11]: https://github.com/rubygems/rubygems/releases/tag/bundler-v2.5.11 +[bundler-v2.5.12]: https://github.com/rubygems/rubygems/releases/tag/bundler-v2.5.12 +[bundler-v2.5.13]: https://github.com/rubygems/rubygems/releases/tag/bundler-v2.5.13 +[bundler-v2.5.14]: https://github.com/rubygems/rubygems/releases/tag/bundler-v2.5.14 +[bundler-v2.5.15]: https://github.com/rubygems/rubygems/releases/tag/bundler-v2.5.15 +[bundler-v2.5.16]: https://github.com/rubygems/rubygems/releases/tag/bundler-v2.5.16 +[bundler-v2.5.17]: https://github.com/rubygems/rubygems/releases/tag/bundler-v2.5.17 +[bundler-v2.5.18]: https://github.com/rubygems/rubygems/releases/tag/bundler-v2.5.18 +[bundler-v2.5.19]: https://github.com/rubygems/rubygems/releases/tag/bundler-v2.5.19 +[bundler-v2.5.20]: https://github.com/rubygems/rubygems/releases/tag/bundler-v2.5.20 +[bundler-v2.5.21]: https://github.com/rubygems/rubygems/releases/tag/bundler-v2.5.21 +[bundler-v2.5.22]: https://github.com/rubygems/rubygems/releases/tag/bundler-v2.5.22 +[bundler-v2.5.23]: https://github.com/rubygems/rubygems/releases/tag/bundler-v2.5.23 +[bundler-v2.6.0]: https://github.com/rubygems/rubygems/releases/tag/bundler-v2.6.0 +[bundler-v2.6.1]: https://github.com/rubygems/rubygems/releases/tag/bundler-v2.6.1 +[bundler-v2.6.2]: https://github.com/rubygems/rubygems/releases/tag/bundler-v2.6.2 +[date-v3.4.0]: https://github.com/ruby/date/releases/tag/v3.4.0 +[date-v3.4.1]: https://github.com/ruby/date/releases/tag/v3.4.1 +[delegate-v0.4.0]: https://github.com/ruby/delegate/releases/tag/v0.4.0 +[did_you_mean-v2.0.0]: https://github.com/ruby/did_you_mean/releases/tag/v2.0.0 +[digest-v3.2.0.pre0]: https://github.com/ruby/digest/releases/tag/v3.2.0.pre0 +[digest-v3.2.0]: https://github.com/ruby/digest/releases/tag/v3.2.0 +[erb-v4.0.4]: https://github.com/ruby/erb/releases/tag/v4.0.4 +[etc-v1.4.4]: https://github.com/ruby/etc/releases/tag/v1.4.4 +[etc-v1.4.5]: https://github.com/ruby/etc/releases/tag/v1.4.5 +[fcntl-v1.2.0]: https://github.com/ruby/fcntl/releases/tag/v1.2.0 +[fiddle-v1.1.3]: https://github.com/ruby/fiddle/releases/tag/v1.1.3 +[fiddle-v1.1.4]: https://github.com/ruby/fiddle/releases/tag/v1.1.4 +[fiddle-v1.1.5]: https://github.com/ruby/fiddle/releases/tag/v1.1.5 +[fiddle-v1.1.6]: https://github.com/ruby/fiddle/releases/tag/v1.1.6 +[fileutils-v1.7.3]: https://github.com/ruby/fileutils/releases/tag/v1.7.3 +[io-console-v0.7.2]: https://github.com/ruby/io-console/releases/tag/v0.7.2 +[io-console-v0.8.0.beta1]: https://github.com/ruby/io-console/releases/tag/v0.8.0.beta1 +[io-console-v0.8.0]: https://github.com/ruby/io-console/releases/tag/v0.8.0 +[io-nonblock-v0.3.1]: https://github.com/ruby/io-nonblock/releases/tag/v0.3.1 +[ipaddr-v1.2.7]: https://github.com/ruby/ipaddr/releases/tag/v1.2.7 +[irb-v1.11.1]: https://github.com/ruby/irb/releases/tag/v1.11.1 +[irb-v1.11.2]: https://github.com/ruby/irb/releases/tag/v1.11.2 +[irb-v1.12.0]: https://github.com/ruby/irb/releases/tag/v1.12.0 +[irb-v1.13.0]: https://github.com/ruby/irb/releases/tag/v1.13.0 +[irb-v1.13.1]: https://github.com/ruby/irb/releases/tag/v1.13.1 +[irb-v1.13.2]: https://github.com/ruby/irb/releases/tag/v1.13.2 +[irb-v1.14.0]: https://github.com/ruby/irb/releases/tag/v1.14.0 +[irb-v1.14.1]: https://github.com/ruby/irb/releases/tag/v1.14.1 +[irb-v1.14.2]: https://github.com/ruby/irb/releases/tag/v1.14.2 +[irb-v1.14.3]: https://github.com/ruby/irb/releases/tag/v1.14.3 +[json-v2.7.2]: https://github.com/ruby/json/releases/tag/v2.7.2 +[json-v2.7.3.rc1]: https://github.com/ruby/json/releases/tag/v2.7.3.rc1 +[json-v2.7.3]: https://github.com/ruby/json/releases/tag/v2.7.3 +[json-v2.7.4]: https://github.com/ruby/json/releases/tag/v2.7.4 +[json-v2.7.5]: https://github.com/ruby/json/releases/tag/v2.7.5 +[json-v2.7.6]: https://github.com/ruby/json/releases/tag/v2.7.6 +[json-v2.8.0]: https://github.com/ruby/json/releases/tag/v2.8.0 +[json-v2.8.1]: https://github.com/ruby/json/releases/tag/v2.8.1 +[json-v2.8.2]: https://github.com/ruby/json/releases/tag/v2.8.2 +[json-v2.9.0]: https://github.com/ruby/json/releases/tag/v2.9.0 +[json-v2.9.1]: https://github.com/ruby/json/releases/tag/v2.9.1 +[logger-v1.6.1]: https://github.com/ruby/logger/releases/tag/v1.6.1 +[logger-v1.6.2]: https://github.com/ruby/logger/releases/tag/v1.6.2 +[logger-v1.6.3]: https://github.com/ruby/logger/releases/tag/v1.6.3 +[logger-v1.6.4]: https://github.com/ruby/logger/releases/tag/v1.6.4 +[net-http-v0.4.1]: https://github.com/ruby/net-http/releases/tag/v0.4.1 +[net-http-v0.5.0]: https://github.com/ruby/net-http/releases/tag/v0.5.0 +[net-http-v0.6.0]: https://github.com/ruby/net-http/releases/tag/v0.6.0 +[open-uri-v0.5.0]: https://github.com/ruby/open-uri/releases/tag/v0.5.0 +[optparse-v0.5.0]: https://github.com/ruby/optparse/releases/tag/v0.5.0 +[optparse-v0.6.0]: https://github.com/ruby/optparse/releases/tag/v0.6.0 +[ostruct-v0.6.1]: https://github.com/ruby/ostruct/releases/tag/v0.6.1 +[pathname-v0.4.0]: https://github.com/ruby/pathname/releases/tag/v0.4.0 +[pp-v0.6.0]: https://github.com/ruby/pp/releases/tag/v0.6.0 +[pp-v0.6.1]: https://github.com/ruby/pp/releases/tag/v0.6.1 +[pp-v0.6.2]: https://github.com/ruby/pp/releases/tag/v0.6.2 +[prism-v0.20.0]: https://github.com/ruby/prism/releases/tag/v0.20.0 +[prism-v0.21.0]: https://github.com/ruby/prism/releases/tag/v0.21.0 +[prism-v0.22.0]: https://github.com/ruby/prism/releases/tag/v0.22.0 +[prism-v0.23.0]: https://github.com/ruby/prism/releases/tag/v0.23.0 +[prism-v0.24.0]: https://github.com/ruby/prism/releases/tag/v0.24.0 +[prism-v0.25.0]: https://github.com/ruby/prism/releases/tag/v0.25.0 +[prism-v0.26.0]: https://github.com/ruby/prism/releases/tag/v0.26.0 +[prism-v0.27.0]: https://github.com/ruby/prism/releases/tag/v0.27.0 +[prism-v0.28.0]: https://github.com/ruby/prism/releases/tag/v0.28.0 +[prism-v0.29.0]: https://github.com/ruby/prism/releases/tag/v0.29.0 +[prism-v0.30.0]: https://github.com/ruby/prism/releases/tag/v0.30.0 +[prism-v1.0.0]: https://github.com/ruby/prism/releases/tag/v1.0.0 +[prism-v1.1.0]: https://github.com/ruby/prism/releases/tag/v1.1.0 +[prism-v1.2.0]: https://github.com/ruby/prism/releases/tag/v1.2.0 +[pstore-v0.1.4]: https://github.com/ruby/pstore/releases/tag/v0.1.4 +[psych-v5.2.0.beta1]: https://github.com/ruby/psych/releases/tag/v5.2.0.beta1 +[psych-v5.2.0]: https://github.com/ruby/psych/releases/tag/v5.2.0 +[psych-v5.2.0.beta2]: https://github.com/ruby/psych/releases/tag/v5.2.0.beta2 +[psych-v5.2.0.beta3]: https://github.com/ruby/psych/releases/tag/v5.2.0.beta3 +[psych-v5.2.0.beta4]: https://github.com/ruby/psych/releases/tag/v5.2.0.beta4 +[psych-v5.2.0.beta5]: https://github.com/ruby/psych/releases/tag/v5.2.0.beta5 +[psych-v5.2.0.beta6]: https://github.com/ruby/psych/releases/tag/v5.2.0.beta6 +[psych-v5.2.0.beta7]: https://github.com/ruby/psych/releases/tag/v5.2.0.beta7 +[psych-v5.2.1]: https://github.com/ruby/psych/releases/tag/v5.2.1 +[psych-v5.2.2]: https://github.com/ruby/psych/releases/tag/v5.2.2 +[rdoc-v6.7.0]: https://github.com/ruby/rdoc/releases/tag/v6.7.0 +[rdoc-v6.8.0]: https://github.com/ruby/rdoc/releases/tag/v6.8.0 +[rdoc-v6.8.1]: https://github.com/ruby/rdoc/releases/tag/v6.8.1 +[rdoc-v6.9.0]: https://github.com/ruby/rdoc/releases/tag/v6.9.0 +[rdoc-v6.9.1]: https://github.com/ruby/rdoc/releases/tag/v6.9.1 +[rdoc-v6.10.0]: https://github.com/ruby/rdoc/releases/tag/v6.10.0 +[reline-v0.5.0.pre.1]: https://github.com/ruby/reline/releases/tag/v0.5.0.pre.1 +[reline-v0.4.2]: https://github.com/ruby/reline/releases/tag/v0.4.2 +[reline-v0.4.3]: https://github.com/ruby/reline/releases/tag/v0.4.3 +[reline-v0.5.0]: https://github.com/ruby/reline/releases/tag/v0.5.0 +[reline-v0.5.1]: https://github.com/ruby/reline/releases/tag/v0.5.1 +[reline-v0.5.2]: https://github.com/ruby/reline/releases/tag/v0.5.2 +[reline-v0.5.3]: https://github.com/ruby/reline/releases/tag/v0.5.3 +[reline-v0.5.4]: https://github.com/ruby/reline/releases/tag/v0.5.4 +[reline-v0.5.5]: https://github.com/ruby/reline/releases/tag/v0.5.5 +[reline-v0.5.6]: https://github.com/ruby/reline/releases/tag/v0.5.6 +[reline-v0.5.7]: https://github.com/ruby/reline/releases/tag/v0.5.7 +[reline-v0.5.8]: https://github.com/ruby/reline/releases/tag/v0.5.8 +[reline-v0.5.9]: https://github.com/ruby/reline/releases/tag/v0.5.9 +[reline-v0.5.10]: https://github.com/ruby/reline/releases/tag/v0.5.10 +[reline-v0.5.11]: https://github.com/ruby/reline/releases/tag/v0.5.11 +[reline-v0.5.12]: https://github.com/ruby/reline/releases/tag/v0.5.12 +[reline-v0.6.0]: https://github.com/ruby/reline/releases/tag/v0.6.0 +[resolv-v0.4.0]: https://github.com/ruby/resolv/releases/tag/v0.4.0 +[resolv-v0.5.0]: https://github.com/ruby/resolv/releases/tag/v0.5.0 +[resolv-v0.6.0]: https://github.com/ruby/resolv/releases/tag/v0.6.0 +[securerandom-v0.3.2]: https://github.com/ruby/securerandom/releases/tag/v0.3.2 +[securerandom-v0.4.0]: https://github.com/ruby/securerandom/releases/tag/v0.4.0 +[securerandom-v0.4.1]: https://github.com/ruby/securerandom/releases/tag/v0.4.1 +[set-v1.1.1]: https://github.com/ruby/set/releases/tag/v1.1.1 +[shellwords-v0.2.1]: https://github.com/ruby/shellwords/releases/tag/v0.2.1 +[shellwords-v0.2.2]: https://github.com/ruby/shellwords/releases/tag/v0.2.2 +[singleton-v0.3.0]: https://github.com/ruby/singleton/releases/tag/v0.3.0 +[stringio-v3.1.1]: https://github.com/ruby/stringio/releases/tag/v3.1.1 +[stringio-v3.1.2]: https://github.com/ruby/stringio/releases/tag/v3.1.2 +[strscan-v3.0.8]: https://github.com/ruby/strscan/releases/tag/v3.0.8 +[strscan-v3.0.9]: https://github.com/ruby/strscan/releases/tag/v3.0.9 +[strscan-v3.1.0]: https://github.com/ruby/strscan/releases/tag/v3.1.0 +[strscan-v3.1.1]: https://github.com/ruby/strscan/releases/tag/v3.1.1 +[strscan-v3.1.2]: https://github.com/ruby/strscan/releases/tag/v3.1.2 +[syntax_suggest-v2.0.1]: https://github.com/ruby/syntax_suggest/releases/tag/v2.0.1 +[syntax_suggest-v2.0.2]: https://github.com/ruby/syntax_suggest/releases/tag/v2.0.2 +[tempfile-v0.3.0]: https://github.com/ruby/tempfile/releases/tag/v0.3.0 +[tempfile-v0.3.1]: https://github.com/ruby/tempfile/releases/tag/v0.3.1 +[time-v0.4.0]: https://github.com/ruby/time/releases/tag/v0.4.0 +[time-v0.4.1]: https://github.com/ruby/time/releases/tag/v0.4.1 +[timeout-v0.4.2]: https://github.com/ruby/timeout/releases/tag/v0.4.2 +[timeout-v0.4.3]: https://github.com/ruby/timeout/releases/tag/v0.4.3 +[tmpdir-v0.3.0]: https://github.com/ruby/tmpdir/releases/tag/v0.3.0 +[tmpdir-v0.3.1]: https://github.com/ruby/tmpdir/releases/tag/v0.3.1 +[uri-v0.13.1]: https://github.com/ruby/uri/releases/tag/v0.13.1 +[uri-v1.0.0]: https://github.com/ruby/uri/releases/tag/v1.0.0 +[uri-v1.0.1]: https://github.com/ruby/uri/releases/tag/v1.0.1 +[uri-v1.0.2]: https://github.com/ruby/uri/releases/tag/v1.0.2 +[win32ole-v1.9.0]: https://github.com/ruby/win32ole/releases/tag/v1.9.0 +[win32ole-v1.9.1]: https://github.com/ruby/win32ole/releases/tag/v1.9.1 +[yaml-v0.4.0]: https://github.com/ruby/yaml/releases/tag/v0.4.0 +[zlib-v3.1.1]: https://github.com/ruby/zlib/releases/tag/v3.1.1 +[zlib-v3.2.0]: https://github.com/ruby/zlib/releases/tag/v3.2.0 +[zlib-v3.2.1]: https://github.com/ruby/zlib/releases/tag/v3.2.1 +[minitest-v5.25.4]: https://github.com/seattlerb/minitest/releases/tag/v5.25.4 +[power_assert-v2.0.4]: https://github.com/ruby/power_assert/releases/tag/v2.0.4 +[power_assert-v2.0.5]: https://github.com/ruby/power_assert/releases/tag/v2.0.5 +[rake-v13.2.0]: https://github.com/ruby/rake/releases/tag/v13.2.0 +[rake-v13.2.1]: https://github.com/ruby/rake/releases/tag/v13.2.1 +[test-unit-3.6.2]: https://github.com/test-unit/test-unit/releases/tag/3.6.2 +[test-unit-3.6.3]: https://github.com/test-unit/test-unit/releases/tag/3.6.3 +[test-unit-3.6.4]: https://github.com/test-unit/test-unit/releases/tag/3.6.4 +[test-unit-3.6.5]: https://github.com/test-unit/test-unit/releases/tag/3.6.5 +[test-unit-3.6.6]: https://github.com/test-unit/test-unit/releases/tag/3.6.6 +[test-unit-3.6.7]: https://github.com/test-unit/test-unit/releases/tag/3.6.7 +[rexml-v3.2.7]: https://github.com/ruby/rexml/releases/tag/v3.2.7 +[rexml-v3.2.8]: https://github.com/ruby/rexml/releases/tag/v3.2.8 +[rexml-v3.2.9]: https://github.com/ruby/rexml/releases/tag/v3.2.9 +[rexml-v3.3.0]: https://github.com/ruby/rexml/releases/tag/v3.3.0 +[rexml-v3.3.1]: https://github.com/ruby/rexml/releases/tag/v3.3.1 +[rexml-v3.3.2]: https://github.com/ruby/rexml/releases/tag/v3.3.2 +[rexml-v3.3.3]: https://github.com/ruby/rexml/releases/tag/v3.3.3 +[rexml-v3.3.4]: https://github.com/ruby/rexml/releases/tag/v3.3.4 +[rexml-v3.3.5]: https://github.com/ruby/rexml/releases/tag/v3.3.5 +[rexml-v3.3.6]: https://github.com/ruby/rexml/releases/tag/v3.3.6 +[rexml-v3.3.7]: https://github.com/ruby/rexml/releases/tag/v3.3.7 +[rexml-v3.3.8]: https://github.com/ruby/rexml/releases/tag/v3.3.8 +[rexml-v3.3.9]: https://github.com/ruby/rexml/releases/tag/v3.3.9 +[rexml-v3.4.0]: https://github.com/ruby/rexml/releases/tag/v3.4.0 +[rss-0.3.1]: https://github.com/ruby/rss/releases/tag/0.3.1 +[net-ftp-v0.3.4]: https://github.com/ruby/net-ftp/releases/tag/v0.3.4 +[net-ftp-v0.3.5]: https://github.com/ruby/net-ftp/releases/tag/v0.3.5 +[net-ftp-v0.3.6]: https://github.com/ruby/net-ftp/releases/tag/v0.3.6 +[net-ftp-v0.3.7]: https://github.com/ruby/net-ftp/releases/tag/v0.3.7 +[net-ftp-v0.3.8]: https://github.com/ruby/net-ftp/releases/tag/v0.3.8 +[net-imap-v0.4.9.1]: https://github.com/ruby/net-imap/releases/tag/v0.4.9.1 +[net-imap-v0.4.10]: https://github.com/ruby/net-imap/releases/tag/v0.4.10 +[net-imap-v0.4.11]: https://github.com/ruby/net-imap/releases/tag/v0.4.11 +[net-imap-v0.4.12]: https://github.com/ruby/net-imap/releases/tag/v0.4.12 +[net-imap-v0.4.13]: https://github.com/ruby/net-imap/releases/tag/v0.4.13 +[net-imap-v0.4.14]: https://github.com/ruby/net-imap/releases/tag/v0.4.14 +[net-imap-v0.4.15]: https://github.com/ruby/net-imap/releases/tag/v0.4.15 +[net-imap-v0.4.16]: https://github.com/ruby/net-imap/releases/tag/v0.4.16 +[net-imap-v0.4.17]: https://github.com/ruby/net-imap/releases/tag/v0.4.17 +[net-imap-v0.5.0]: https://github.com/ruby/net-imap/releases/tag/v0.5.0 +[net-imap-v0.4.18]: https://github.com/ruby/net-imap/releases/tag/v0.4.18 +[net-imap-v0.5.1]: https://github.com/ruby/net-imap/releases/tag/v0.5.1 +[net-imap-v0.5.2]: https://github.com/ruby/net-imap/releases/tag/v0.5.2 +[net-imap-v0.5.3]: https://github.com/ruby/net-imap/releases/tag/v0.5.3 +[net-imap-v0.5.4]: https://github.com/ruby/net-imap/releases/tag/v0.5.4 +[net-smtp-v0.4.0.1]: https://github.com/ruby/net-smtp/releases/tag/v0.4.0.1 +[net-smtp-v0.5.0]: https://github.com/ruby/net-smtp/releases/tag/v0.5.0 +[prime-v0.1.3]: https://github.com/ruby/prime/releases/tag/v0.1.3 +[rbs-v3.4.1]: https://github.com/ruby/rbs/releases/tag/v3.4.1 +[rbs-v3.4.2]: https://github.com/ruby/rbs/releases/tag/v3.4.2 +[rbs-v3.4.3]: https://github.com/ruby/rbs/releases/tag/v3.4.3 +[rbs-v3.4.4]: https://github.com/ruby/rbs/releases/tag/v3.4.4 +[rbs-v3.5.0.pre.1]: https://github.com/ruby/rbs/releases/tag/v3.5.0.pre.1 +[rbs-v3.5.0.pre.2]: https://github.com/ruby/rbs/releases/tag/v3.5.0.pre.2 +[rbs-v3.5.0]: https://github.com/ruby/rbs/releases/tag/v3.5.0 +[rbs-v3.5.1]: https://github.com/ruby/rbs/releases/tag/v3.5.1 +[rbs-v3.5.2]: https://github.com/ruby/rbs/releases/tag/v3.5.2 +[rbs-v3.5.3]: https://github.com/ruby/rbs/releases/tag/v3.5.3 +[rbs-v3.6.0.dev.1]: https://github.com/ruby/rbs/releases/tag/v3.6.0.dev.1 +[rbs-v3.6.0.pre.1]: https://github.com/ruby/rbs/releases/tag/v3.6.0.pre.1 +[rbs-v3.6.0.pre.2]: https://github.com/ruby/rbs/releases/tag/v3.6.0.pre.2 +[rbs-v3.6.0.pre.3]: https://github.com/ruby/rbs/releases/tag/v3.6.0.pre.3 +[rbs-v3.6.0]: https://github.com/ruby/rbs/releases/tag/v3.6.0 +[rbs-v3.6.1]: https://github.com/ruby/rbs/releases/tag/v3.6.1 +[rbs-v3.7.0.dev.1]: https://github.com/ruby/rbs/releases/tag/v3.7.0.dev.1 +[rbs-v3.7.0.pre.1]: https://github.com/ruby/rbs/releases/tag/v3.7.0.pre.1 +[rbs-v3.7.0]: https://github.com/ruby/rbs/releases/tag/v3.7.0 +[rbs-v3.8.0.pre.1]: https://github.com/ruby/rbs/releases/tag/v3.8.0.pre.1 +[rbs-v3.8.0]: https://github.com/ruby/rbs/releases/tag/v3.8.0 +[debug-v1.9.2]: https://github.com/ruby/debug/releases/tag/v1.9.2 +[debug-v1.10.0]: https://github.com/ruby/debug/releases/tag/v1.10.0 +[racc-v1.8.0]: https://github.com/ruby/racc/releases/tag/v1.8.0 +[racc-v1.8.1]: https://github.com/ruby/racc/releases/tag/v1.8.1 +[mutex_m-v0.3.0]: https://github.com/ruby/mutex_m/releases/tag/v0.3.0 +[bigdecimal-v3.1.6]: https://github.com/ruby/bigdecimal/releases/tag/v3.1.6 +[bigdecimal-v3.1.7]: https://github.com/ruby/bigdecimal/releases/tag/v3.1.7 +[bigdecimal-v3.1.8]: https://github.com/ruby/bigdecimal/releases/tag/v3.1.8 +[drb-v2.2.1]: https://github.com/ruby/drb/releases/tag/v2.2.1 +[nkf-v0.2.0]: https://github.com/ruby/nkf/releases/tag/v0.2.0 +[syslog-v0.2.0]: https://github.com/ruby/syslog/releases/tag/v0.2.0 +[csv-v3.2.9]: https://github.com/ruby/csv/releases/tag/v3.2.9 +[csv-v3.3.0]: https://github.com/ruby/csv/releases/tag/v3.3.0 +[csv-v3.3.1]: https://github.com/ruby/csv/releases/tag/v3.3.1 +[csv-v3.3.2]: https://github.com/ruby/csv/releases/tag/v3.3.2 +[ruby/net-http-sspi]: https://github.com/ruby/net-http-sspi +[typeprof-v0.30.1]: https://github.com/ruby/typeprof/releases/tag/v0.30.1 + +[RubyGems]: https://github.com/rubygems/rubygems +[benchmark]: https://github.com/ruby/benchmark +[bundler]: https://github.com/rubygems/rubygems +[date]: https://github.com/ruby/date +[delegate]: https://github.com/ruby/delegate +[did_you_mean]: https://github.com/ruby/did_you_mean +[digest]: https://github.com/ruby/digest +[erb]: https://github.com/ruby/erb +[error_highlight]: https://github.com/ruby/error_highlight +[etc]: https://github.com/ruby/etc +[fcntl]: https://github.com/ruby/fcntl +[fiddle]: https://github.com/ruby/fiddle +[fileutils]: https://github.com/ruby/fileutils +[io-console]: https://github.com/ruby/io-console +[io-nonblock]: https://github.com/ruby/io-nonblock +[ipaddr]: https://github.com/ruby/ipaddr +[irb]: https://github.com/ruby/irb +[json]: https://github.com/ruby/json +[logger]: https://github.com/ruby/logger +[net-http]: https://github.com/ruby/net-http +[open-uri]: https://github.com/ruby/open-uri +[optparse]: https://github.com/ruby/optparse +[ostruct]: https://github.com/ruby/ostruct +[pathname]: https://github.com/ruby/pathname +[pp]: https://github.com/ruby/pp +[prism]: https://github.com/ruby/prism +[pstore]: https://github.com/ruby/pstore +[psych]: https://github.com/ruby/psych +[rdoc]: https://github.com/ruby/rdoc +[reline]: https://github.com/ruby/reline +[resolv]: https://github.com/ruby/resolv +[securerandom]: https://github.com/ruby/securerandom +[set]: https://github.com/ruby/set +[shellwords]: https://github.com/ruby/shellwords +[singleton]: https://github.com/ruby/singleton +[stringio]: https://github.com/ruby/stringio +[strscan]: https://github.com/ruby/strscan +[syntax_suggest]: https://github.com/ruby/syntax_suggest +[tempfile]: https://github.com/ruby/tempfile +[time]: https://github.com/ruby/time +[timeout]: https://github.com/ruby/timeout +[tmpdir]: https://github.com/ruby/tmpdir +[uri]: https://github.com/ruby/uri +[win32ole]: https://github.com/ruby/win32ole +[yaml]: https://github.com/ruby/yaml +[zlib]: https://github.com/ruby/zlib + +[repl_type_completor]: https://github.com/ruby/repl_type_completor +[minitest]: https://github.com/seattlerb/minitest +[power_assert]: https://github.com/ruby/power_assert +[rake]: https://github.com/ruby/rake +[test-unit]: https://github.com/test-unit/test-unit +[rexml]: https://github.com/ruby/rexml +[rss]: https://github.com/ruby/rss +[net-ftp]: https://github.com/ruby/net-ftp +[net-imap]: https://github.com/ruby/net-imap +[net-smtp]: https://github.com/ruby/net-smtp +[prime]: https://github.com/ruby/prime +[rbs]: https://github.com/ruby/rbs +[typeprof]: https://github.com/ruby/typeprof +[debug]: https://github.com/ruby/debug +[racc]: https://github.com/ruby/racc +[mutex_m]: https://github.com/ruby/mutex_m +[getoptlong]: https://github.com/ruby/getoptlong +[base64]: https://github.com/ruby/base64 +[bigdecimal]: https://github.com/ruby/bigdecimal +[observer]: https://github.com/ruby/observer +[abbrev]: https://github.com/ruby/abbrev +[resolv-replace]: https://github.com/ruby/resolv-replace +[rinda]: https://github.com/ruby/rinda +[drb]: https://github.com/ruby/drb +[nkf]: https://github.com/ruby/nkf +[syslog]: https://github.com/ruby/syslog +[csv]: https://github.com/ruby/csv diff --git a/doc/_regexp.rdoc b/doc/_regexp.rdoc new file mode 100644 index 00000000000000..45a307fad660d3 --- /dev/null +++ b/doc/_regexp.rdoc @@ -0,0 +1,1284 @@ +A {regular expression}[https://en.wikipedia.org/wiki/Regular_expression] +(also called a _regexp_) is a match pattern (also simply called a _pattern_). + +A common notation for a regexp uses enclosing slash characters: + + /foo/ + +A regexp may be applied to a target string; +The part of the string (if any) that matches the pattern is called a _match_, +and may be said to match: + + re = /red/ + re.match?('redirect') # => true # Match at beginning of target. + re.match?('bored') # => true # Match at end of target. + re.match?('credit') # => true # Match within target. + re.match?('foo') # => false # No match. + +== \Regexp Uses + +A regexp may be used: + +- To extract substrings based on a given pattern: + + re = /foo/ # => /foo/ + re.match('food') # => # + re.match('good') # => nil + + See sections {Method match}[rdoc-ref:Regexp@Method+match] + and {Operator =~}[rdoc-ref:Regexp@Operator+-3D~]. + +- To determine whether a string matches a given pattern: + + re.match?('food') # => true + re.match?('good') # => false + + See section {Method match?}[rdoc-ref:Regexp@Method+match-3F]. + +- As an argument for calls to certain methods in other classes and modules; + most such methods accept an argument that may be either a string + or the (much more powerful) regexp. + + See {Regexp Methods}[rdoc-ref:regexp/methods.rdoc]. + +== \Regexp Objects + +A regexp object has: + +- A source; see {Sources}[rdoc-ref:Regexp@Sources]. + +- Several modes; see {Modes}[rdoc-ref:Regexp@Modes]. + +- A timeout; see {Timeouts}[rdoc-ref:Regexp@Timeouts]. + +- An encoding; see {Encodings}[rdoc-ref:Regexp@Encodings]. + +== Creating a \Regexp + +A regular expression may be created with: + +- A regexp literal using slash characters + (see {Regexp Literals}[rdoc-ref:syntax/literals.rdoc@Regexp+Literals]): + + # This is a very common usage. + /foo/ # => /foo/ + +- A %r regexp literal + (see {%r: Regexp Literals}[rdoc-ref:syntax/literals.rdoc@25r-3A+Regexp+Literals]): + + # Same delimiter character at beginning and end; + # useful for avoiding escaping characters + %r/name\/value pair/ # => /name\/value pair/ + %r:name/value pair: # => /name\/value pair/ + %r|name/value pair| # => /name\/value pair/ + + # Certain "paired" characters can be delimiters. + %r[foo] # => /foo/ + %r{foo} # => /foo/ + %r(foo) # => /foo/ + %r # => /foo/ + +- Method Regexp.new. + +== Method match + +Each of the methods Regexp#match, String#match, and Symbol#match +returns a MatchData object if a match was found, +nil+ otherwise; +each also sets {global variables}[rdoc-ref:Regexp@Global+Variables]: + + 'food'.match(/foo/) # => # + 'food'.match(/bar/) # => nil + +== Operator =~ + +Each of the operators Regexp#=~, String#=~, and Symbol#=~ +returns an integer offset if a match was found, +nil+ otherwise; +each also sets {global variables}[rdoc-ref:Regexp@Global+Variables]: + + /bar/ =~ 'foo bar' # => 4 + 'foo bar' =~ /bar/ # => 4 + /baz/ =~ 'foo bar' # => nil + +== Method match? + +Each of the methods Regexp#match?, String#match?, and Symbol#match? +returns +true+ if a match was found, +false+ otherwise; +none sets {global variables}[rdoc-ref:Regexp@Global+Variables]: + + 'food'.match?(/foo/) # => true + 'food'.match?(/bar/) # => false + +== Global Variables + +Certain regexp-oriented methods assign values to global variables: + +- #match: see {Method match}[rdoc-ref:Regexp@Method+match]. +- #=~: see {Operator =~}[rdoc-ref:Regexp@Operator+-3D~]. + +The affected global variables are: + +- $~: Returns a MatchData object, or +nil+. +- $&: Returns the matched part of the string, or +nil+. +- $`: Returns the part of the string to the left of the match, or +nil+. +- $': Returns the part of the string to the right of the match, or +nil+. +- $+: Returns the last group matched, or +nil+. +- $1, $2, etc.: Returns the first, second, etc., + matched group, or +nil+. + Note that $0 is quite different; + it returns the name of the currently executing program. + +These variables, except for $~, are shorthands for methods of +$~. See MatchData@Global+variables+equivalence. + +Examples: + + # Matched string, but no matched groups. + 'foo bar bar baz'.match('bar') + $~ # => # + $& # => "bar" + $` # => "foo " + $' # => " bar baz" + $+ # => nil + $1 # => nil + + # Matched groups. + /s(\w{2}).*(c)/.match('haystack') + $~ # => # + $& # => "stac" + $` # => "hay" + $' # => "k" + $+ # => "c" + $1 # => "ta" + $2 # => "c" + $3 # => nil + + # No match. + 'foo'.match('bar') + $~ # => nil + $& # => nil + $` # => nil + $' # => nil + $+ # => nil + $1 # => nil + +Note that Regexp#match?, String#match?, and Symbol#match? +do not set global variables. + +== Sources + +As seen above, the simplest regexp uses a literal expression as its source: + + re = /foo/ # => /foo/ + re.match('food') # => # + re.match('good') # => nil + +A rich collection of available _subexpressions_ +gives the regexp great power and flexibility: + +- {Special characters}[rdoc-ref:Regexp@Special+Characters] +- {Source literals}[rdoc-ref:Regexp@Source+Literals] +- {Character classes}[rdoc-ref:Regexp@Character+Classes] +- {Shorthand character classes}[rdoc-ref:Regexp@Shorthand+Character+Classes] +- {Anchors}[rdoc-ref:Regexp@Anchors] +- {Alternation}[rdoc-ref:Regexp@Alternation] +- {Quantifiers}[rdoc-ref:Regexp@Quantifiers] +- {Groups and captures}[rdoc-ref:Regexp@Groups+and+Captures] +- {Unicode}[rdoc-ref:Regexp@Unicode] +- {POSIX Bracket Expressions}[rdoc-ref:Regexp@POSIX+Bracket+Expressions] +- {Comments}[rdoc-ref:Regexp@Comments] + +=== Special Characters + +\Regexp special characters, called _metacharacters_, +have special meanings in certain contexts; +depending on the context, these are sometimes metacharacters: + + . ? - + * ^ \ | $ ( ) [ ] { } + +To match a metacharacter literally, backslash-escape it: + + # Matches one or more 'o' characters. + /o+/.match('foo') # => # + # Would match 'o+'. + /o\+/.match('foo') # => nil + +To match a backslash literally, backslash-escape it: + + /\./.match('\.') # => # + /\\./.match('\.') # => # + +Method Regexp.escape returns an escaped string: + + Regexp.escape('.?-+*^\|$()[]{}') + # => "\\.\\?\\-\\+\\*\\^\\\\\\|\\$\\(\\)\\[\\]\\{\\}" + +=== Source Literals + +The source literal largely behaves like a double-quoted string; +see {Double-Quoted String Literals}[rdoc-ref:syntax/literals.rdoc@Double-Quoted+String+Literals]. + +In particular, a source literal may contain interpolated expressions: + + s = 'foo' # => "foo" + /#{s}/ # => /foo/ + /#{s.capitalize}/ # => /Foo/ + /#{2 + 2}/ # => /4/ + +There are differences between an ordinary string literal and a source literal; +see {Shorthand Character Classes}[rdoc-ref:Regexp@Shorthand+Character+Classes]. + +- \s in an ordinary string literal is equivalent to a space character; + in a source literal, it's shorthand for matching a whitespace character. +- In an ordinary string literal, these are (needlessly) escaped characters; + in a source literal, they are shorthands for various matching characters: + + \w \W \d \D \h \H \S \R + +=== Character Classes + +A character class is delimited by square brackets; +it specifies that certain characters match at a given point in the target string: + + # This character class will match any vowel. + re = /B[aeiou]rd/ + re.match('Bird') # => # + re.match('Bard') # => # + re.match('Byrd') # => nil + +A character class may contain hyphen characters to specify ranges of characters: + + # These regexps have the same effect. + /[abcdef]/.match('foo') # => # + /[a-f]/.match('foo') # => # + /[a-cd-f]/.match('foo') # => # + +When the first character of a character class is a caret (^), +the sense of the class is inverted: it matches any character _except_ those specified. + + /[^a-eg-z]/.match('f') # => # + +A character class may contain another character class. +By itself this isn't useful because [a-z[0-9]] +describes the same set as [a-z0-9]. + +However, character classes also support the && operator, +which performs set intersection on its arguments. +The two can be combined as follows: + + /[a-w&&[^c-g]z]/ # ([a-w] AND ([^c-g] OR z)) + +This is equivalent to: + + /[abh-w]/ + +=== Shorthand Character Classes + +Each of the following metacharacters serves as a shorthand +for a character class: + +- /./: Matches any character except a newline: + + /./.match('foo') # => # + /./.match("\n") # => nil + +- /./m: Matches any character, including a newline; + see {Multiline Mode}[rdoc-ref:Regexp@Multiline+Mode]: + + /./m.match("\n") # => # + +- /\w/: Matches a word character: equivalent to [a-zA-Z0-9_]: + + /\w/.match(' foo') # => # + /\w/.match(' _') # => # + /\w/.match(' ') # => nil + +- /\W/: Matches a non-word character: equivalent to [^a-zA-Z0-9_]: + + /\W/.match(' ') # => # + /\W/.match('_') # => nil + +- /\d/: Matches a digit character: equivalent to [0-9]: + + /\d/.match('THX1138') # => # + /\d/.match('foo') # => nil + +- /\D/: Matches a non-digit character: equivalent to [^0-9]: + + /\D/.match('123Jump!') # => # + /\D/.match('123') # => nil + +- /\h/: Matches a hexdigit character: equivalent to [0-9a-fA-F]: + + /\h/.match('xyz fedcba9876543210') # => # + /\h/.match('xyz') # => nil + +- /\H/: Matches a non-hexdigit character: equivalent to [^0-9a-fA-F]: + + /\H/.match('fedcba9876543210xyz') # => # + /\H/.match('fedcba9876543210') # => nil + +- /\s/: Matches a whitespace character: equivalent to /[ \t\r\n\f\v]/: + + /\s/.match('foo bar') # => # + /\s/.match('foo') # => nil + +- /\S/: Matches a non-whitespace character: equivalent to /[^ \t\r\n\f\v]/: + + /\S/.match(" \t\r\n\f\v foo") # => # + /\S/.match(" \t\r\n\f\v") # => nil + +- /\R/: Matches a linebreak, platform-independently: + + /\R/.match("\r") # => # # Carriage return (CR) + /\R/.match("\n") # => # # Newline (LF) + /\R/.match("\f") # => # # Formfeed (FF) + /\R/.match("\v") # => # # Vertical tab (VT) + /\R/.match("\r\n") # => # # CRLF + /\R/.match("\u0085") # => # # Next line (NEL) + /\R/.match("\u2028") # => # # Line separator (LSEP) + /\R/.match("\u2029") # => # # Paragraph separator (PSEP) + +=== Anchors + +An anchor is a metasequence that matches a zero-width position between +characters in the target string. + +For a subexpression with no anchor, +matching may begin anywhere in the target string: + + /real/.match('surrealist') # => # + +For a subexpression with an anchor, +matching must begin at the matched anchor. + +==== Boundary Anchors + +Each of these anchors matches a boundary: + +- ^: Matches the beginning of a line: + + /^bar/.match("foo\nbar") # => # + /^ar/.match("foo\nbar") # => nil + +- $: Matches the end of a line: + + /bar$/.match("foo\nbar") # => # + /ba$/.match("foo\nbar") # => nil + +- \A: Matches the beginning of the string: + + /\Afoo/.match('foo bar') # => # + /\Afoo/.match(' foo bar') # => nil + +- \Z: Matches the end of the string; + if string ends with a single newline, + it matches just before the ending newline: + + /foo\Z/.match('bar foo') # => # + /foo\Z/.match('foo bar') # => nil + /foo\Z/.match("bar foo\n") # => # + /foo\Z/.match("bar foo\n\n") # => nil + +- \z: Matches the end of the string: + + /foo\z/.match('bar foo') # => # + /foo\z/.match('foo bar') # => nil + /foo\z/.match("bar foo\n") # => nil + +- \b: Matches word boundary when not inside brackets; + matches backspace ("0x08") when inside brackets: + + /foo\b/.match('foo bar') # => # + /foo\b/.match('foobar') # => nil + +- \B: Matches non-word boundary: + + /foo\B/.match('foobar') # => # + /foo\B/.match('foo bar') # => nil + +- \G: Matches first matching position: + + In methods like String#gsub and String#scan, it changes on each iteration. + It initially matches the beginning of subject, and in each following iteration it matches where the last match finished. + + " a b c".gsub(/ /, '_') # => "____a_b_c" + " a b c".gsub(/\G /, '_') # => "____a b c" + + In methods like Regexp#match and String#match + that take an optional offset, it matches where the search begins. + + "hello, world".match(/,/, 3) # => # + "hello, world".match(/\G,/, 3) # => nil + +==== Lookaround Anchors + +Lookahead anchors: + +- (?=_pat_): Positive lookahead assertion: + ensures that the following characters match _pat_, + but doesn't include those characters in the matched substring. + +- (?!_pat_): Negative lookahead assertion: + ensures that the following characters do not match _pat_, + but doesn't include those characters in the matched substring. + +Lookbehind anchors: + +- (?<=_pat_): Positive lookbehind assertion: + ensures that the preceding characters match _pat_, but + doesn't include those characters in the matched substring. + +- (?: Negative lookbehind assertion: + ensures that the preceding characters do not match + _pat_, but doesn't include those characters in the matched substring. + +The pattern below uses positive lookahead and positive lookbehind to match +text appearing in ... tags +without including the tags in the match: + + /(?<=)\w+(?=<\/b>)/.match("Fortune favors the bold.") + # => # + +The pattern in lookbehind must be fixed-width. +But top-level alternatives can be of various lengths. +ex. (?<=a|bc) is OK. (?<=aaa(?:b|cd)) is not allowed. + +==== Match-Reset Anchor + +- \K: Match reset: + the matched content preceding \K in the regexp is excluded from the result. + For example, the following two regexps are almost equivalent: + + /ab\Kc/.match('abc') # => # + /(?<=ab)c/.match('abc') # => # + + These match same string and $& equals 'c', + while the matched position is different. + + As are the following two regexps: + + /(a)\K(b)\Kc/ + /(?<=(?<=(a))(b))c/ + +=== Alternation + +The vertical bar metacharacter (|) may be used within parentheses +to express alternation: +two or more subexpressions any of which may match the target string. + +Two alternatives: + + re = /(a|b)/ + re.match('foo') # => nil + re.match('bar') # => # + +Four alternatives: + + re = /(a|b|c|d)/ + re.match('shazam') # => # + re.match('cold') # => # + +Each alternative is a subexpression, and may be composed of other subexpressions: + + re = /([a-c]|[x-z])/ + re.match('bar') # => # + re.match('ooz') # => # + +Method Regexp.union provides a convenient way to construct +a regexp with alternatives. + +=== Quantifiers + +A simple regexp matches one character: + + /\w/.match('Hello') # => # + +An added _quantifier_ specifies how many matches are required or allowed: + +- * - Matches zero or more times: + + /\w*/.match('') + # => # + /\w*/.match('x') + # => # + /\w*/.match('xyz') + # => # + +- + - Matches one or more times: + + /\w+/.match('') # => nil + /\w+/.match('x') # => # + /\w+/.match('xyz') # => # + +- ? - Matches zero or one times: + + /\w?/.match('') # => # + /\w?/.match('x') # => # + /\w?/.match('xyz') # => # + +- {_n_} - Matches exactly _n_ times: + + /\w{2}/.match('') # => nil + /\w{2}/.match('x') # => nil + /\w{2}/.match('xyz') # => # + +- {_min_,} - Matches _min_ or more times: + + /\w{2,}/.match('') # => nil + /\w{2,}/.match('x') # => nil + /\w{2,}/.match('xy') # => # + /\w{2,}/.match('xyz') # => # + +- {,_max_} - Matches _max_ or fewer times: + + /\w{,2}/.match('') # => # + /\w{,2}/.match('x') # => # + /\w{,2}/.match('xyz') # => # + +- {_min_,_max_} - + Matches at least _min_ times and at most _max_ times: + + /\w{1,2}/.match('') # => nil + /\w{1,2}/.match('x') # => # + /\w{1,2}/.match('xyz') # => # + +==== Greedy, Lazy, or Possessive Matching + +Quantifier matching may be greedy, lazy, or possessive: + +- In _greedy_ matching, as many occurrences as possible are matched + while still allowing the overall match to succeed. + Greedy quantifiers: *, +, ?, + {min, max} and its variants. +- In _lazy_ matching, the minimum number of occurrences are matched. + Lazy quantifiers: *?, +?, ??, + {min, max}? and its variants. +- In _possessive_ matching, once a match is found, there is no backtracking; + that match is retained, even if it jeopardises the overall match. + Possessive quantifiers: *+, ++, ?+. + Note that {min, max} and its variants do _not_ support possessive matching. + +More: + +- About greedy and lazy matching, see + {Choosing Minimal or Maximal Repetition}[https://doc.lagout.org/programmation/Regular%20Expressions/Regular%20Expressions%20Cookbook_%20Detailed%20Solutions%20in%20Eight%20Programming%20Languages%20%282nd%20ed.%29%20%5BGoyvaerts%20%26%20Levithan%202012-09-06%5D.pdf#tutorial-backtrack]. +- About possessive matching, see + {Eliminate Needless Backtracking}[https://doc.lagout.org/programmation/Regular%20Expressions/Regular%20Expressions%20Cookbook_%20Detailed%20Solutions%20in%20Eight%20Programming%20Languages%20%282nd%20ed.%29%20%5BGoyvaerts%20%26%20Levithan%202012-09-06%5D.pdf#tutorial-backtrack]. + +=== Groups and Captures + +A simple regexp has (at most) one match: + + re = /\d\d\d\d-\d\d-\d\d/ + re.match('1943-02-04') # => # + re.match('1943-02-04').size # => 1 + re.match('foo') # => nil + +Adding one or more pairs of parentheses, (_subexpression_), +defines _groups_, which may result in multiple matched substrings, +called _captures_: + + re = /(\d\d\d\d)-(\d\d)-(\d\d)/ + re.match('1943-02-04') # => # + re.match('1943-02-04').size # => 4 + +The first capture is the entire matched string; +the other captures are the matched substrings from the groups. + +A group may have a {quantifier}[rdoc-ref:Regexp@Quantifiers]: + + re = /July 4(th)?/ + re.match('July 4') # => # + re.match('July 4th') # => # + + re = /(foo)*/ + re.match('') # => # + re.match('foo') # => # + re.match('foofoo') # => # + + re = /(foo)+/ + re.match('') # => nil + re.match('foo') # => # + re.match('foofoo') # => # + +The returned \MatchData object gives access to the matched substrings: + + re = /(\d\d\d\d)-(\d\d)-(\d\d)/ + md = re.match('1943-02-04') + # => # + md[0] # => "1943-02-04" + md[1] # => "1943" + md[2] # => "02" + md[3] # => "04" + +==== Non-Capturing Groups + +A group may be made non-capturing; +it is still a group (and, for example, can have a quantifier), +but its matching substring is not included among the captures. + +A non-capturing group begins with ?: (inside the parentheses): + + # Don't capture the year. + re = /(?:\d\d\d\d)-(\d\d)-(\d\d)/ + md = re.match('1943-02-04') # => # + +==== Backreferences + +A group match may also be referenced within the regexp itself; +such a reference is called a +backreference+: + + /[csh](..) [csh]\1 in/.match('The cat sat in the hat') + # => # + +This table shows how each subexpression in the regexp above +matches a substring in the target string: + + | Subexpression in Regexp | Matching Substring in Target String | + |---------------------------|-------------------------------------| + | First '[csh]' | Character 'c' | + | '(..)' | First substring 'at' | + | First space ' ' | First space character ' ' | + | Second '[csh]' | Character 's' | + | '\1' (backreference 'at') | Second substring 'at' | + | ' in' | Substring ' in' | + +A regexp may contain any number of groups: + +- For a large number of groups: + + - The ordinary \\_n_ notation applies only for _n_ in range (1..9). + - The MatchData[_n_] notation applies for any non-negative _n_. + +- \0 is a special backreference, referring to the entire matched string; + it may not be used within the regexp itself, + but may be used outside it (for example, in a substitution method call): + + 'The cat sat in the hat'.gsub(/[csh]at/, '\0s') + # => "The cats sats in the hats" + +==== Named Captures + +As seen above, a capture can be referred to by its number. +A capture can also have a name, +prefixed as ?<_name_> or ?'_name_', +and the name (symbolized) may be used as an index in MatchData[]: + + md = /\$(?\d+)\.(?'cents'\d+)/.match("$3.67") + # => # + md[:dollars] # => "3" + md[:cents] # => "67" + # The capture numbers are still valid. + md[2] # => "67" + +When a regexp contains a named capture, there are no unnamed captures: + + /\$(?\d+)\.(\d+)/.match("$3.67") + # => # + +A named group may be backreferenced as \k<_name_>: + + /(?[aeiou]).\k.\k/.match('ototomy') + # => # + +When (and only when) a regexp contains named capture groups +and appears before the =~ operator, +the captured substrings are assigned to local variables with corresponding names: + + /\$(?\d+)\.(?\d+)/ =~ '$3.67' + dollars # => "3" + cents # => "67" + +Method Regexp#named_captures returns a hash of the capture names and substrings; +method Regexp#names returns an array of the capture names. + +==== Atomic Grouping + +A group may be made _atomic_ with (?>_subexpression_). + +This causes the subexpression to be matched +independently of the rest of the expression, +so that the matched substring becomes fixed for the remainder of the match, +unless the entire subexpression must be abandoned and subsequently revisited. + +In this way _subexpression_ is treated as a non-divisible whole. +Atomic grouping is typically used to optimise patterns +to prevent needless backtracking . + +Example (without atomic grouping): + + /".*"/.match('"Quote"') # => # + +Analysis: + +1. The leading subexpression " in the pattern matches the first character + " in the target string. +2. The next subexpression .* matches the next substring Quote“ + (including the trailing double-quote). +3. Now there is nothing left in the target string to match + the trailing subexpression " in the pattern; + this would cause the overall match to fail. +4. The matched substring is backtracked by one position: Quote. +5. The final subexpression " now matches the final substring ", + and the overall match succeeds. + +If subexpression .* is grouped atomically, +the backtracking is disabled, and the overall match fails: + + /"(?>.*)"/.match('"Quote"') # => nil + +Atomic grouping can affect performance; +see {Atomic Group}[https://www.regular-expressions.info/atomic.html]. + +==== Subexpression Calls + +As seen above, a backreference number (\\_n_) or name (\k<_name_>) +gives access to a captured _substring_; +the corresponding regexp _subexpression_ may also be accessed, +via the number (\\gn) or name (\g<_name_>): + + /\A(?\(\g*\))*\z/.match('(())') + # ^1 + # ^2 + # ^3 + # ^4 + # ^5 + # ^6 + # ^7 + # ^8 + # ^9 + # ^10 + +The pattern: + +1. Matches at the beginning of the string, i.e. before the first character. +2. Enters a named group +paren+. +3. Matches the first character in the string, '('. +4. Calls the +paren+ group again, i.e. recurses back to the second step. +5. Re-enters the +paren+ group. +6. Matches the second character in the string, '('. +7. Attempts to call +paren+ a third time, + but fails because doing so would prevent an overall successful match. +8. Matches the third character in the string, ')'; + marks the end of the second recursive call +9. Matches the fourth character in the string, ')'. +10. Matches the end of the string. + +See {Subexpression calls}[https://learnbyexample.github.io/Ruby_Regexp/groupings-and-backreferences.html?highlight=subexpression#subexpression-calls]. + +==== Conditionals + +The conditional construct takes the form (?(_cond_)_yes_|_no_), where: + +- _cond_ may be a capture number or name. +- The match to be applied is _yes_ if _cond_ is captured; + otherwise the match to be applied is _no_. +- If not needed, |_no_ may be omitted. + +Examples: + + re = /\A(foo)?(?(1)(T)|(F))\z/ + re.match('fooT') # => # + re.match('F') # => # + re.match('fooF') # => nil + re.match('T') # => nil + + re = /\A(?foo)?(?()(T)|(F))\z/ + re.match('fooT') # => # + re.match('F') # => # + re.match('fooF') # => nil + re.match('T') # => nil + + +==== Absence Operator + +The absence operator is a special group that matches anything which does _not_ match the contained subexpressions. + + /(?~real)/.match('surrealist') # => # + /(?~real)ist/.match('surrealist') # => # + /sur(?~real)ist/.match('surrealist') # => nil + +=== Unicode + +==== Unicode Properties + +The /\p{_property_name_}/ construct (with lowercase +p+) +matches characters using a Unicode property name, +much like a character class; +property +Alpha+ specifies alphabetic characters: + + /\p{Alpha}/.match('a') # => # + /\p{Alpha}/.match('1') # => nil + +A property can be inverted +by prefixing the name with a caret character (^): + + /\p{^Alpha}/.match('1') # => # + /\p{^Alpha}/.match('a') # => nil + +Or by using \P (uppercase +P+): + + /\P{Alpha}/.match('1') # => # + /\P{Alpha}/.match('a') # => nil + +See {Unicode Properties}[rdoc-ref:regexp/unicode_properties.rdoc] +for regexps based on the numerous properties. + +Some commonly-used properties correspond to POSIX bracket expressions: + +- /\p{Alnum}/: Alphabetic and numeric character +- /\p{Alpha}/: Alphabetic character +- /\p{Blank}/: Space or tab +- /\p{Cntrl}/: Control character +- /\p{Digit}/: Digit + characters, and similar) +- /\p{Lower}/: Lowercase alphabetical character +- /\p{Print}/: Like \p{Graph}, but includes the space character +- /\p{Punct}/: Punctuation character +- /\p{Space}/: Whitespace character ([:blank:], newline, + carriage return, etc.) +- /\p{Upper}/: Uppercase alphabetical +- /\p{XDigit}/: Digit allowed in a hexadecimal number (i.e., 0-9a-fA-F) + +These are also commonly used: + +- /\p{Emoji}/: Unicode emoji. +- /\p{Graph}/: Characters excluding /\p{Cntrl}/ and /\p{Space}/. + Note that invisible characters under the Unicode + {"Format"}[https://www.compart.com/en/unicode/category/Cf] category are included. +- /\p{Word}/: A member in one of these Unicode character + categories (see below) or having one of these Unicode properties: + + - Unicode categories: + - +Mark+ (+M+). + - Decimal Number (+Nd+) + - Connector Punctuation (+Pc+). + + - Unicode properties: + - +Alpha+ + - Join_Control + +- /\p{ASCII}/: A character in the ASCII character set. +- /\p{Any}/: Any Unicode character (including unassigned characters). +- /\p{Assigned}/: An assigned character. + +==== Unicode Character Categories + +A Unicode character category name: + +- May be either its full name or its abbreviated name. +- Is case-insensitive. +- Treats a space, a hyphen, and an underscore as equivalent. + +Examples: + + /\p{lu}/ # => /\p{lu}/ + /\p{LU}/ # => /\p{LU}/ + /\p{Uppercase Letter}/ # => /\p{Uppercase Letter}/ + /\p{Uppercase_Letter}/ # => /\p{Uppercase_Letter}/ + /\p{UPPERCASE-LETTER}/ # => /\p{UPPERCASE-LETTER}/ + +Below are the Unicode character category abbreviations and names. +Enumerations of characters in each category are at the links. + +Letters: + +- +L+, +Letter+: +LC+, +Lm+, or +Lo+. +- +LC+, +Cased_Letter+: +Ll+, +Lt+, or +Lu+. +- {Lu, Lowercase_Letter}[https://www.compart.com/en/unicode/category/Ll]. +- {Lu, Modifier_Letter}[https://www.compart.com/en/unicode/category/Lm]. +- {Lu, Other_Letter}[https://www.compart.com/en/unicode/category/Lo]. +- {Lu, Titlecase_Letter}[https://www.compart.com/en/unicode/category/Lt]. +- {Lu, Uppercase_Letter}[https://www.compart.com/en/unicode/category/Lu]. + +Marks: + +- +M+, +Mark+: +Mc+, +Me+, or +Mn+. +- {Mc, Spacing_Mark}[https://www.compart.com/en/unicode/category/Mc]. +- {Me, Enclosing_Mark}[https://www.compart.com/en/unicode/category/Me]. +- {Mn, Nonapacing_Mark}[https://www.compart.com/en/unicode/category/Mn]. + +Numbers: + +- +N+, +Number+: +Nd+, +Nl+, or +No+. +- {Nd, Decimal_Number}[https://www.compart.com/en/unicode/category/Nd]. +- {Nl, Letter_Number}[https://www.compart.com/en/unicode/category/Nl]. +- {No, Other_Number}[https://www.compart.com/en/unicode/category/No]. + +Punctuation: + +- +P+, +Punctuation+: +Pc+, +Pd+, +Pe+, +Pf+, +Pi+, +Po+, or +Ps+. +- {Pc, Connector_Punctuation}[https://www.compart.com/en/unicode/category/Pc]. +- {Pd, Dash_Punctuation}[https://www.compart.com/en/unicode/category/Pd]. +- {Pe, Close_Punctuation}[https://www.compart.com/en/unicode/category/Pe]. +- {Pf, Final_Punctuation}[https://www.compart.com/en/unicode/category/Pf]. +- {Pi, Initial_Punctuation}[https://www.compart.com/en/unicode/category/Pi]. +- {Po, Other_Punctuation}[https://www.compart.com/en/unicode/category/Po]. +- {Ps, Open_Punctuation}[https://www.compart.com/en/unicode/category/Ps]. + +- +S+, +Symbol+: +Sc+, +Sk+, +Sm+, or +So+. +- {Sc, Currency_Symbol}[https://www.compart.com/en/unicode/category/Sc]. +- {Sk, Modifier_Symbol}[https://www.compart.com/en/unicode/category/Sk]. +- {Sm, Math_Symbol}[https://www.compart.com/en/unicode/category/Sm]. +- {So, Other_Symbol}[https://www.compart.com/en/unicode/category/So]. + +- +Z+, +Separator+: +Zl+, +Zp+, or +Zs+. +- {Zl, Line_Separator}[https://www.compart.com/en/unicode/category/Zl]. +- {Zp, Paragraph_Separator}[https://www.compart.com/en/unicode/category/Zp]. +- {Zs, Space_Separator}[https://www.compart.com/en/unicode/category/Zs]. + +- +C+, +Other+: +Cc+, +Cf+, +Cn+, +Co+, or +Cs+. +- {Cc, Control}[https://www.compart.com/en/unicode/category/Cc]. +- {Cf, Format}[https://www.compart.com/en/unicode/category/Cf]. +- {Cn, Unassigned}[https://www.compart.com/en/unicode/category/Cn]. +- {Co, Private_Use}[https://www.compart.com/en/unicode/category/Co]. +- {Cs, Surrogate}[https://www.compart.com/en/unicode/category/Cs]. + +==== Unicode Scripts and Blocks + +Among the Unicode properties are: + +- {Unicode scripts}[https://en.wikipedia.org/wiki/Script_(Unicode)]; + see {supported scripts}[https://www.unicode.org/standard/supported.html]. +- {Unicode blocks}[https://en.wikipedia.org/wiki/Unicode_block]; + see {supported blocks}[http://www.unicode.org/Public/UNIDATA/Blocks.txt]. + +=== POSIX Bracket Expressions + +A POSIX bracket expression is also similar to a character class. +These expressions provide a portable alternative to the above, +with the added benefit of encompassing non-ASCII characters: + +- /\d/ matches only ASCII decimal digits +0+ through +9+. +- /[[:digit:]]/ matches any character in the Unicode + Decimal Number (+Nd+) category; + see below. + +The POSIX bracket expressions: + +- /[[:digit:]]/: Matches a {Unicode digit}[https://www.compart.com/en/unicode/category/Nd]: + + /[[:digit:]]/.match('9') # => # + /[[:digit:]]/.match("\u1fbf9") # => # + +- /[[:xdigit:]]/: Matches a digit allowed in a hexadecimal number; + equivalent to [0-9a-fA-F]. + +- /[[:upper:]]/: Matches a {Unicode uppercase letter}[https://www.compart.com/en/unicode/category/Lu]: + + /[[:upper:]]/.match('A') # => # + /[[:upper:]]/.match("\u00c6") # => # + +- /[[:lower:]]/: Matches a {Unicode lowercase letter}[https://www.compart.com/en/unicode/category/Ll]: + + /[[:lower:]]/.match('a') # => # + /[[:lower:]]/.match("\u01fd") # => # + +- /[[:alpha:]]/: Matches /[[:upper:]]/ or /[[:lower:]]/. + +- /[[:alnum:]]/: Matches /[[:alpha:]]/ or /[[:digit:]]/. + +- /[[:space:]]/: Matches {Unicode space character}[https://www.compart.com/en/unicode/category/Zs]: + + /[[:space:]]/.match(' ') # => # + /[[:space:]]/.match("\u2005") # => # + +- /[[:blank:]]/: Matches /[[:space:]]/ or tab character: + + /[[:blank:]]/.match(' ') # => # + /[[:blank:]]/.match("\u2005") # => # + /[[:blank:]]/.match("\t") # => # + +- /[[:cntrl:]]/: Matches {Unicode control character}[https://www.compart.com/en/unicode/category/Cc]: + + /[[:cntrl:]]/.match("\u0000") # => # + /[[:cntrl:]]/.match("\u009f") # => # + +- /[[:graph:]]/: Matches any character + except /[[:space:]]/ or /[[:cntrl:]]/. + +- /[[:print:]]/: Matches /[[:graph:]]/ or space character. + +- /[[:punct:]]/: Matches any (Unicode punctuation character}[https://www.compart.com/en/unicode/category/Po]: + +Ruby also supports these (non-POSIX) bracket expressions: + +- /[[:ascii:]]/: Matches a character in the ASCII character set. +- /[[:word:]]/: Matches a character in one of these Unicode character + categories or having one of these Unicode properties: + + - Unicode categories: + - +Mark+ (+M+). + - Decimal Number (+Nd+) + - Connector Punctuation (+Pc+). + + - Unicode properties: + - +Alpha+ + - Join_Control + +=== Comments + +A comment may be included in a regexp pattern +using the (?#_comment_) construct, +where _comment_ is a substring that is to be ignored. +arbitrary text ignored by the regexp engine: + + /foo(?#Ignore me)bar/.match('foobar') # => # + +The comment may not include an unescaped terminator character. + +See also {Extended Mode}[rdoc-ref:Regexp@Extended+Mode]. + +== Modes + +Each of these modifiers sets a mode for the regexp: + +- +i+: /_pattern_/i sets + {Case-Insensitive Mode}[rdoc-ref:Regexp@Case-Insensitive+Mode]. +- +m+: /_pattern_/m sets + {Multiline Mode}[rdoc-ref:Regexp@Multiline+Mode]. +- +x+: /_pattern_/x sets + {Extended Mode}[rdoc-ref:Regexp@Extended+Mode]. +- +o+: /_pattern_/o sets + {Interpolation Mode}[rdoc-ref:Regexp@Interpolation+Mode]. + +Any, all, or none of these may be applied. + +Modifiers +i+, +m+, and +x+ may be applied to subexpressions: + +- (?_modifier_) turns the mode "on" for ensuing subexpressions +- (?-_modifier_) turns the mode "off" for ensuing subexpressions +- (?_modifier_:_subexp_) turns the mode "on" for _subexp_ within the group +- (?-_modifier_:_subexp_) turns the mode "off" for _subexp_ within the group + +Example: + + re = /(?i)te(?-i)st/ + re.match('test') # => # + re.match('TEst') # => # + re.match('TEST') # => nil + re.match('teST') # => nil + + re = /t(?i:e)st/ + re.match('test') # => # + re.match('tEst') # => # + re.match('tEST') # => nil + +Method Regexp#options returns an integer whose value showing +the settings for case-insensitivity mode, multiline mode, and extended mode. + +=== Case-Insensitive Mode + +By default, a regexp is case-sensitive: + + /foo/.match('FOO') # => nil + +Modifier +i+ enables case-insensitive mode: + + /foo/i.match('FOO') + # => # + +Method Regexp#casefold? returns whether the mode is case-insensitive. + +=== Multiline Mode + +The multiline-mode in Ruby is what is commonly called a "dot-all mode": + +- Without the +m+ modifier, the subexpression . does not match newlines: + + /a.c/.match("a\nc") # => nil + +- With the modifier, it does match: + + /a.c/m.match("a\nc") # => # + +Unlike other languages, the modifier +m+ does not affect the anchors ^ and $. +These anchors always match at line-boundaries in Ruby. + +=== Extended Mode + +Modifier +x+ enables extended mode, which means that: + +- Literal white space in the pattern is to be ignored. +- Character # marks the remainder of its containing line as a comment, + which is also to be ignored for matching purposes. + +In extended mode, whitespace and comments may be used +to form a self-documented regexp. + +Regexp not in extended mode (matches some Roman numerals): + + pattern = '^M{0,3}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$' + re = /#{pattern}/ + re.match('MCMXLIII') # => # + +Regexp in extended mode: + + pattern = <<-EOT + ^ # beginning of string + M{0,3} # thousands - 0 to 3 Ms + (CM|CD|D?C{0,3}) # hundreds - 900 (CM), 400 (CD), 0-300 (0 to 3 Cs), + # or 500-800 (D, followed by 0 to 3 Cs) + (XC|XL|L?X{0,3}) # tens - 90 (XC), 40 (XL), 0-30 (0 to 3 Xs), + # or 50-80 (L, followed by 0 to 3 Xs) + (IX|IV|V?I{0,3}) # ones - 9 (IX), 4 (IV), 0-3 (0 to 3 Is), + # or 5-8 (V, followed by 0 to 3 Is) + $ # end of string + EOT + re = /#{pattern}/x + re.match('MCMXLIII') # => # + +=== Interpolation Mode + +Modifier +o+ means that the first time a literal regexp with interpolations +is encountered, +the generated Regexp object is saved and used for all future evaluations +of that literal regexp. +Without modifier +o+, the generated Regexp is not saved, +so each evaluation of the literal regexp generates a new Regexp object. + +Without modifier +o+: + + def letters; sleep 5; /[A-Z][a-z]/; end + words = %w[abc def xyz] + start = Time.now + words.each {|word| word.match(/\A[#{letters}]+\z/) } + Time.now - start # => 15.0174892 + +With modifier +o+: + + start = Time.now + words.each {|word| word.match(/\A[#{letters}]+\z/o) } + Time.now - start # => 5.0010866 + +Note that if the literal regexp does not have interpolations, +the +o+ behavior is the default. + +== Encodings + +By default, a regexp with only US-ASCII characters has US-ASCII encoding: + + re = /foo/ + re.source.encoding # => # + re.encoding # => # + +A regular expression containing non-US-ASCII characters +is assumed to use the source encoding. +This can be overridden with one of the following modifiers. + +- /_pat_/n: US-ASCII if only containing US-ASCII characters, + otherwise ASCII-8BIT: + + /foo/n.encoding # => # + /foo\xff/n.encoding # => # + /foo\x7f/n.encoding # => # + +- /_pat_/u: UTF-8 + + /foo/u.encoding # => # + +- /_pat_/e: EUC-JP + + /foo/e.encoding # => # + +- /_pat_/s: Windows-31J + + /foo/s.encoding # => # + +A regexp can be matched against a target string when either: + +- They have the same encoding. +- The regexp's encoding is a fixed encoding and the string + contains only ASCII characters. + Method Regexp#fixed_encoding? returns whether the regexp + has a fixed encoding. + +If a match between incompatible encodings is attempted an +Encoding::CompatibilityError exception is raised. + +Example: + + re = eval("# encoding: ISO-8859-1\n/foo\\xff?/") + re.encoding # => # + re =~ "foo".encode("UTF-8") # => 0 + re =~ "foo\u0100" # Raises Encoding::CompatibilityError + +The encoding may be explicitly fixed by including Regexp::FIXEDENCODING +in the second argument for Regexp.new: + + # Regexp with encoding ISO-8859-1. + re = Regexp.new("a".force_encoding('iso-8859-1'), Regexp::FIXEDENCODING) + re.encoding # => # + # Target string with encoding UTF-8. + s = "a\u3042" + s.encoding # => # + re.match(s) # Raises Encoding::CompatibilityError. + +== Timeouts + +When either a regexp source or a target string comes from untrusted input, +malicious values could become a denial-of-service attack; +to prevent such an attack, it is wise to set a timeout. + +\Regexp has two timeout values: + +- A class default timeout, used for a regexp whose instance timeout is +nil+; + this default is initially +nil+, and may be set by method Regexp.timeout=: + + Regexp.timeout # => nil + Regexp.timeout = 3.0 + Regexp.timeout # => 3.0 + +- An instance timeout, which defaults to +nil+ and may be set in Regexp.new: + + re = Regexp.new('foo', timeout: 5.0) + re.timeout # => 5.0 + +When regexp.timeout is +nil+, the timeout "falls through" to Regexp.timeout; +when regexp.timeout is non-+nil+, that value controls timing out: + + | regexp.timeout Value | Regexp.timeout Value | Result | + |----------------------|----------------------|-----------------------------| + | nil | nil | Never times out. | + | nil | Float | Times out in Float seconds. | + | Float | Any | Times out in Float seconds. | + +== Optimization + +For certain values of the pattern and target string, +matching time can grow polynomially or exponentially in relation to the input size; +the potential vulnerability arising from this is the {regular expression denial-of-service}[https://en.wikipedia.org/wiki/ReDoS] (ReDoS) attack. + +\Regexp matching can apply an optimization to prevent ReDoS attacks. +When the optimization is applied, matching time increases linearly (not polynomially or exponentially) +in relation to the input size, and a ReDoS attach is not possible. + +This optimization is applied if the pattern meets these criteria: + +- No backreferences. +- No subexpression calls. +- No nested lookaround anchors or atomic groups. +- No nested quantifiers with counting (i.e. no nested {n}, + {min,}, {,max}, or {min,max} style quantifiers) + +You can use method Regexp.linear_time? to determine whether a pattern meets these criteria: + + Regexp.linear_time?(/a*/) # => true + Regexp.linear_time?('a*') # => true + Regexp.linear_time?(/(a*)\1/) # => false + +However, an untrusted source may not be safe even if the method returns +true+, +because the optimization uses memoization (which may invoke large memory consumption). + +== References + +Read (online PDF books): + +- {Mastering Regular Expressions}[https://ia902508.us.archive.org/10/items/allitebooks-02/Mastering%20Regular%20Expressions%2C%203rd%20Edition.pdf] + by Jeffrey E.F. Friedl. +- {Regular Expressions Cookbook}[https://doc.lagout.org/programmation/Regular%20Expressions/Regular%20Expressions%20Cookbook_%20Detailed%20Solutions%20in%20Eight%20Programming%20Languages%20%282nd%20ed.%29%20%5BGoyvaerts%20%26%20Levithan%202012-09-06%5D.pdf] + by Jan Goyvaerts & Steven Levithan. + +Explore, test (interactive online editor): + +- {Rubular}[https://rubular.com/]. diff --git a/doc/_timezones.rdoc b/doc/_timezones.rdoc new file mode 100644 index 00000000000000..a2ac46584fd75a --- /dev/null +++ b/doc/_timezones.rdoc @@ -0,0 +1,163 @@ +== Timezone Specifiers + +Certain +Time+ methods accept arguments that specify timezones: + +- Time.at: keyword argument +in:+. +- Time.new: positional argument +zone+ or keyword argument +in:+. +- Time.now: keyword argument +in:+. +- Time#getlocal: positional argument +zone+. +- Time#localtime: positional argument +zone+. + +The value given with any of these must be one of the following +(each detailed below): + +- {Hours/minutes offset}[rdoc-ref:Time@Hours-2FMinutes+Offsets]. +- {Single-letter offset}[rdoc-ref:Time@Single-Letter+Offsets]. +- {Integer offset}[rdoc-ref:Time@Integer+Offsets]. +- {Timezone object}[rdoc-ref:Time@Timezone+Objects]. +- {Timezone name}[rdoc-ref:Time@Timezone+Names]. + +=== Hours/Minutes Offsets + +The zone value may be a string offset from UTC +in the form '+HH:MM' or '-HH:MM', +where: + +- +HH+ is the 2-digit hour in the range 0..23. +- +MM+ is the 2-digit minute in the range 0..59. + +Examples: + + t = Time.utc(2000, 1, 1, 20, 15, 1) # => 2000-01-01 20:15:01 UTC + Time.at(t, in: '-23:59') # => 1999-12-31 20:16:01 -2359 + Time.at(t, in: '+23:59') # => 2000-01-02 20:14:01 +2359 + +=== Single-Letter Offsets + +The zone value may be a letter in the range 'A'..'I' +or 'K'..'Z'; +see {List of military time zones}[https://en.wikipedia.org/wiki/List_of_military_time_zones]: + + t = Time.utc(2000, 1, 1, 20, 15, 1) # => 2000-01-01 20:15:01 UTC + Time.at(t, in: 'A') # => 2000-01-01 21:15:01 +0100 + Time.at(t, in: 'I') # => 2000-01-02 05:15:01 +0900 + Time.at(t, in: 'K') # => 2000-01-02 06:15:01 +1000 + Time.at(t, in: 'Y') # => 2000-01-01 08:15:01 -1200 + Time.at(t, in: 'Z') # => 2000-01-01 20:15:01 UTC + +=== \Integer Offsets + +The zone value may be an integer number of seconds +in the range -86399..86399: + + t = Time.utc(2000, 1, 1, 20, 15, 1) # => 2000-01-01 20:15:01 UTC + Time.at(t, in: -86399) # => 1999-12-31 20:15:02 -235959 + Time.at(t, in: 86399) # => 2000-01-02 20:15:00 +235959 + +=== Timezone Objects + +The zone value may be an object responding to certain timezone methods, an +instance of {Timezone}[https://github.com/panthomakos/timezone] and +{TZInfo}[https://tzinfo.github.io] for example. + +The timezone methods are: + +- +local_to_utc+: + + Called when Time.new is invoked with +tz+ as the value of positional + argument +zone+ or keyword argument +in:+. + + Argument:: a {Time-like object}[rdoc-ref:Time@Time-Like+Objects]. + Returns:: a {Time-like object}[rdoc-ref:Time@Time-Like+Objects] in the UTC timezone. + +- +utc_to_local+: + + Called when Time.at or Time.now is invoked with +tz+ as the value for + keyword argument +in:+, and when Time#getlocal or Time#localtime is called + with +tz+ as the value for positional argument +zone+. + + The UTC offset will be calculated as the difference between the + original time and the returned object as an +Integer+. + If the object is in fixed offset, its +utc_offset+ is also counted. + + Argument:: a {Time-like object}[rdoc-ref:Time@Time-Like+Objects]. + Returns:: a {Time-like object}[rdoc-ref:Time@Time-Like+Objects] in the local timezone. + +A custom timezone class may have these instance methods, +which will be called if defined: + +- +abbr+: + + Called when Time#strftime is invoked with a format involving %Z. + + Argument:: a {Time-like object}[rdoc-ref:Time@Time-Like+Objects]. + Returns:: a string abbreviation for the timezone name. + +- +dst?+: + + Called when Time.at or Time.now is invoked with +tz+ as the value for + keyword argument +in:+, and when Time#getlocal or Time#localtime is + called with +tz+ as the value for positional argument +zone+. + + Argument:: a {Time-like object}[rdoc-ref:Time@Time-Like+Objects]. + Returns:: whether the time is daylight saving time. + +- +name+: + + Called when Marshal.dump(t) is invoked + + Argument:: none. + Returns:: the string name of the timezone. + +==== +Time+-Like Objects + +A +Time+-like object is a container object capable of interfacing with +timezone libraries for timezone conversion. + +The argument to the timezone conversion methods above will have attributes +similar to Time, except that timezone related attributes are meaningless. + +The objects returned by +local_to_utc+ and +utc_to_local+ methods of the +timezone object may be of the same class as their arguments, of arbitrary +object classes, or of class Integer. + +For a returned class other than +Integer+, the class must have the +following methods: + +- +year+ +- +mon+ +- +mday+ +- +hour+ +- +min+ +- +sec+ +- +isdst+ +- +to_i+ + +For a returned +Integer+, its components, decomposed in UTC, are +interpreted as times in the specified timezone. + +=== Timezone Names + +If the class (the receiver of class methods, or the class of the receiver +of instance methods) has +find_timezone+ singleton method, this method is +called to achieve the corresponding timezone object from a timezone name. + +For example, using {Timezone}[https://github.com/panthomakos/timezone]: + class TimeWithTimezone < Time + require 'timezone' + def self.find_timezone(z) = Timezone[z] + end + + TimeWithTimezone.now(in: "America/New_York") #=> 2023-12-25 00:00:00 -0500 + TimeWithTimezone.new("2023-12-25 America/New_York") #=> 2023-12-25 00:00:00 -0500 + +Or, using {TZInfo}[https://tzinfo.github.io]: + class TimeWithTZInfo < Time + require 'tzinfo' + def self.find_timezone(z) = TZInfo::Timezone.get(z) + end + + TimeWithTZInfo.now(in: "America/New_York") #=> 2023-12-25 00:00:00 -0500 + TimeWithTZInfo.new("2023-12-25 America/New_York") #=> 2023-12-25 00:00:00 -0500 + +You can define this method per subclasses, or on the toplevel Time class. diff --git a/doc/bsearch.rdoc b/doc/bsearch.rdoc index ca8091fc0da3a6..90705853d7c32e 100644 --- a/doc/bsearch.rdoc +++ b/doc/bsearch.rdoc @@ -1,4 +1,4 @@ -== Binary Searching += Binary Searching A few Ruby methods support binary searching in a collection: diff --git a/doc/case_mapping.rdoc b/doc/case_mapping.rdoc index 3c4215497383ed..d40155db031f43 100644 --- a/doc/case_mapping.rdoc +++ b/doc/case_mapping.rdoc @@ -1,4 +1,4 @@ -== Case Mapping += Case Mapping Some string-oriented methods use case mapping. @@ -24,7 +24,7 @@ In Symbol: - Symbol#swapcase - Symbol#upcase -=== Default Case Mapping +== Default Case Mapping By default, all of these methods use full Unicode case mapping, which is suitable for most languages. @@ -37,7 +37,7 @@ Context-dependent case mapping as described in {Table 3-17 (Context Specification for Casing) of the Unicode standard}[https://www.unicode.org/versions/latest/ch03.pdf] is currently not supported. -In most cases, case conversions of a string have the same number of characters. +In most cases, the case conversion of a string has the same number of characters as before. There are exceptions (see also +:fold+ below): s = "\u00DF" # => "ß" @@ -58,25 +58,18 @@ Case changes may not be reversible: s.downcase.upcase # => "HELLO WORLD!" # Different from original s. Case changing methods may not maintain Unicode normalization. -See String#unicode_normalize). +See String#unicode_normalize. -=== Options for Case Mapping +== Case Mappings Except for +casecmp+ and +casecmp?+, each of the case-mapping methods listed above -accepts optional arguments, *options. +accepts an optional argument, mapping. -The arguments may be: +The argument is one of: -- +:ascii+ only. -- +:fold+ only. -- +:turkic+ or +:lithuanian+ or both. - -The options: - -- +:ascii+: - ASCII-only mapping: - uppercase letters ('A'..'Z') are mapped to lowercase letters ('a'..'z); +- +:ascii+: ASCII-only mapping. + Uppercase letters ('A'..'Z') are mapped to lowercase letters ('a'..'z); other characters are not changed s = "Foo \u00D8 \u00F8 Bar" # => "Foo Ø ø Bar" @@ -85,8 +78,8 @@ The options: s.upcase(:ascii) # => "FOO Ø ø BAR" s.downcase(:ascii) # => "foo Ø ø bar" -- +:turkic+: - Full Unicode case mapping, adapted for the Turkic languages +- +:turkic+: Full Unicode case mapping. + For the Turkic languages that distinguish dotted and dotless I, for example Turkish and Azeri. s = 'Türkiye' # => "Türkiye" @@ -97,11 +90,8 @@ The options: s.downcase # => "türkiye" s.downcase(:turkic) # => "türkıye" # No dot above. -- +:lithuanian+: - Not yet implemented. - - +:fold+ (available only for String#downcase, String#downcase!, - and Symbol#downcase): + and Symbol#downcase). Unicode case folding, which is more far-reaching than Unicode case mapping. diff --git a/doc/character_selectors.rdoc b/doc/character_selectors.rdoc index e01b0e6a25286b..47cf242be7382b 100644 --- a/doc/character_selectors.rdoc +++ b/doc/character_selectors.rdoc @@ -1,6 +1,6 @@ -== Character Selectors += Character Selectors -=== Character Selector +== Character Selector A _character_ _selector_ is a string argument accepted by certain Ruby methods. Each of these instance methods accepts one or more character selectors: @@ -70,7 +70,7 @@ In a character selector, these three characters get special treatment: "hello\r\nworld".delete("\\r") # => "hello\r\nwold" "hello\r\nworld".delete("\\\r") # => "hello\nworld" -=== Multiple Character Selectors +== Multiple Character Selectors These instance methods accept multiple character selectors: diff --git a/doc/command_injection.rdoc b/doc/command_injection.rdoc index 4408b1839dadb4..ee33d4a04e6629 100644 --- a/doc/command_injection.rdoc +++ b/doc/command_injection.rdoc @@ -1,4 +1,4 @@ -== Command Injection += Command Injection Some Ruby core methods accept string data that includes text to be executed as a system command. @@ -7,11 +7,17 @@ They should not be called with unknown or unsanitized commands. These methods include: +- Kernel.exec +- Kernel.spawn - Kernel.system -- Kernel.open - {\`command` (backtick method)}[rdoc-ref:Kernel#`] (also called by the expression %x[command]). -- IO.popen(command). +- IO.popen (when called with other than "-"). + +Some methods execute a system command only if the given path name starts +with a |: + +- Kernel.open(command). - IO.read(command). - IO.write(command). - IO.binread(command). @@ -21,7 +27,7 @@ These methods include: - URI.open(command). Note that some of these methods do not execute commands when called -from subclass \File: +from subclass +File+: - File.read(path). - File.write(path). diff --git a/doc/command_line/environment.md b/doc/command_line/environment.md new file mode 100644 index 00000000000000..8f6d595f6c2f25 --- /dev/null +++ b/doc/command_line/environment.md @@ -0,0 +1,174 @@ +## Environment + +Certain command-line options affect the execution environment +of the invoked Ruby program. + +### About the Examples + +The examples here use command-line option `-e`, +which passes the Ruby code to be executed on the command line itself: + +```console +$ ruby -e 'puts "Hello, World."' +``` + +### Option `-C` + +The argument to option `-C` specifies a working directory +for the invoked Ruby program; +does not change the working directory for the current process: + +```console +$ basename `pwd` +ruby +$ ruby -C lib -e 'puts File.basename(Dir.pwd)' +lib +$ basename `pwd` +ruby +``` + +Whitespace between the option and its argument may be omitted. + +### Option `-I` + +The argument to option `-I` specifies a directory +to be added to the array in global variable `$LOAD_PATH`; +the option may be given more than once: + +```console +$ pushd /tmp +$ ruby -e 'p $LOAD_PATH.size' +8 +$ ruby -I my_lib -I some_lib -e 'p $LOAD_PATH.size' +10 +$ ruby -I my_lib -I some_lib -e 'p $LOAD_PATH.take(2)' +["/tmp/my_lib", "/tmp/some_lib"] +$ popd +``` + +Whitespace between the option and its argument may be omitted. + +### Option `-r` + +The argument to option `-r` specifies a library to be required +before executing the Ruby program; +the option may be given more than once: + +```console +$ ruby -e 'p defined?(JSON); p defined?(CSV)' +nil +nil +$ ruby -r CSV -r JSON -e 'p defined?(JSON); p defined?(CSV)' +"constant" +"constant" +``` + +Whitespace between the option and its argument may be omitted. + +### Option `-0` + +Option `-0` defines the input record separator `$/` +for the invoked Ruby program. + +The optional argument to the option must be octal digits, +each in the range `0..7`; +these digits are prefixed with digit `0` to form an octal value: + +- If no argument is given, the input record separator is `0x00`. +- If the argument is `0`, the input record separator is `''`; + see {Special Line Separator Values}[rdoc-ref:IO@Special+Line+Separator+Values]. +- If the argument is in range `(1..0377)`, + it becomes the character value of the input record separator `$/`. +- Otherwise, the input record separator is `nil`. + +Examples: + +```console +$ ruby -0 -e 'p $/' +"\x00" +$ ruby -00 -e 'p $/' +"" +$ ruby -012 -e 'p $/' +"\n" +$ ruby -015 -e 'p $/' +"\r" +$ ruby -0377 -e 'p $/' +"\xFF" +$ ruby -0400 -e 'p $/' +nil +``` + +The option may not be separated from its argument by whitespace. + +### Option `-d` + +Some code in (or called by) the Ruby program may include statements or blocks +conditioned by the global variable `$DEBUG` (e.g., `if $DEBUG`); +these commonly write to `$stdout` or `$stderr`. + +The default value for `$DEBUG` is `false`; +option `-d` (or `--debug`) sets it to `true`: + +```console +$ ruby -e 'p $DEBUG' +false +$ ruby -d -e 'p $DEBUG' +true +``` + +### Option '-w' + +Option `-w` (lowercase letter) is equivalent to option `-W1` (uppercase letter). + +### Option `-W` + +Any Ruby code can create a warning message by calling method Kernel#warn; +methods in the Ruby core and standard libraries can also create warning messages. +Such a message may be printed on `$stderr` +(or not, depending on certain settings). + +Option `-W` helps determine whether a particular warning message +will be written, +by setting the initial value of global variable `$-W`: + +- `-W0`: Sets `$-W` to `0` (silent; no warnings). +- `-W1`: Sets `$-W` to `1` (moderate verbosity). +- `-W2`: Sets `$-W` to `2` (high verbosity). +- `-W`: Same as `-W2` (high verbosity). +- Option not given: Same as `-W1` (moderate verbosity). + +The value of `$-W`, in turn, determines which warning messages (if any) +are to be printed to `$stdout` (see Kernel#warn): + +```console +$ ruby -W1 -e 'p $foo' +nil +$ ruby -W2 -e 'p $foo' +-e:1: warning: global variable '$foo' not initialized +nil +``` + +Ruby code may also define warnings for certain categories; +these are the default settings for the defined categories: + +```ruby +Warning[:experimental] # => true +Warning[:deprecated] # => false +Warning[:performance] # => false +``` + +They may also be set: + +```ruby +Warning[:experimental] = false +Warning[:deprecated] = true +Warning[:performance] = true +``` + +You can suppress a category by prefixing `no-` to the category name: + +```console +$ ruby -W:no-experimental -e 'p IO::Buffer.new' +# +``` + diff --git a/doc/contributing.md b/doc/contributing.md deleted file mode 100644 index a6c63de9b2ff7c..00000000000000 --- a/doc/contributing.md +++ /dev/null @@ -1,12 +0,0 @@ -# Contributing to Ruby - -This guide outlines ways to get started with contributing to Ruby: - -* [Reporting issues](contributing/reporting_issues.md): How to report issues, how to request features, and how backporting works -* [Building Ruby](contributing/building_ruby.md): How to build Ruby on your local machine for development -* [Testing Ruby](contributing/testing_ruby.md): How to test Ruby on your local machine once you've built it -* [Making changes to Ruby](contributing/making_changes_to_ruby.md): How to submit pull requests - to change Ruby's documentation, code, test suite, or standard libraries -* [Making changes to Ruby standard libraries](contributing/making_changes_to_stdlibs.md): How to build, test, and contribute to Ruby standard libraries -* [Making changes to Ruby documentation](contributing/documentation_guide.md): How to make changes to Ruby documentation -* [Benchmarking Ruby](https://github.com/ruby/ruby/tree/master/benchmark#make-benchmark): How to benchmark Ruby diff --git a/doc/contributing/building_ruby.md b/doc/contributing/building_ruby.md index b96fa4bc0bd921..a0486cb931de68 100644 --- a/doc/contributing/building_ruby.md +++ b/doc/contributing/building_ruby.md @@ -8,48 +8,73 @@ For RubyGems, you will also need: - * OpenSSL 1.1.x or 3.0.x / LibreSSL - * libyaml 0.1.7 or later - * zlib + * [OpenSSL] 1.1.x or 3.0.x / [LibreSSL] + * [libyaml] 0.1.7 or later + * [zlib] If you want to build from the git repository, you will also need: - * autoconf - 2.67 or later - * gperf - 3.1 or later + * [autoconf] - 2.67 or later + * [gperf] - 3.1 or later * Usually unneeded; only if you edit some source files using gperf - * ruby - 2.5 or later - * We can upgrade this version to system ruby version of the latest Ubuntu LTS. + * ruby - 3.0 or later + * We can upgrade this version to system ruby version of the latest + Ubuntu LTS. + * git - 2.32 or later + * Anterior versions may work; 2.32 or later will prevent build + errors in case your system `.gitconfig` uses `$HOME` paths. 2. Install optional, recommended dependencies: - * libffi (to build fiddle) - * gmp (if you with to accelerate Bignum operations) - * libexecinfo (FreeBSD) - * rustc - 1.58.0 or later, if you wish to build - [YJIT](https://docs.ruby-lang.org/en/master/RubyVM/YJIT.html). + * [libffi] (to build fiddle) + * [gmp] (if you wish to accelerate Bignum operations) + * [rustc] - 1.58.0 or later, if you wish to build + [YJIT](rdoc-ref:RubyVM::YJIT). - If you installed the libraries needed for extensions (openssl, readline, libyaml, zlib) into other than the OS default place, - typically using Homebrew on macOS, add `--with-EXTLIB-dir` options to `CONFIGURE_ARGS` environment variable. + If you want to link the libraries (e.g., gmp) installed into other than + the OS default place, typically using Homebrew on macOS, pass the + `--with-opt-dir` (or `--with-gmp-dir` for gmp) option to `configure`. - ``` shell + ```sh + configure --with-opt-dir=$(brew --prefix gmp):$(brew --prefix jemalloc) + ``` + + As for the libraries needed for particular extensions only and not for + Ruby (openssl, readline, libyaml, zlib), you can add `--with-EXTLIB-dir` + options to the command line or to `CONFIGURE_ARGS` environment variable. + The command line options will be embedded in `rbconfig.rb`, while the + latter environment variable is not embedded and is only used when + building the extension libraries. + + ```sh export CONFIGURE_ARGS="" for ext in openssl readline libyaml zlib; do CONFIGURE_ARGS="${CONFIGURE_ARGS} --with-$ext-dir=$(brew --prefix $ext)" done ``` +[OpenSSL]: https://www.openssl.org +[LibreSSL]: https://www.libressl.org +[libyaml]: https://github.com/yaml/libyaml/ +[zlib]: https://www.zlib.net +[autoconf]: https://www.gnu.org/software/autoconf/ +[gperf]: https://www.gnu.org/software/gperf/ +[libffi]: https://sourceware.org/libffi/ +[gmp]: https://gmplib.org +[rustc]: https://www.rust-lang.org + ## Quick start guide 1. Download ruby source code: - Select one of the bellow. + Select one of the below. 1. Build from the tarball: - Download the latest tarball from [ruby-lang.org](https://www.ruby-lang.org/en/downloads/) and - extract it. Example for Ruby 3.0.2: + Download the latest tarball from [Download Ruby] page and extract + it. Example for Ruby 3.0.2: - ``` shell + ```sh tar -xzf ruby-3.0.2.tar.gz cd ruby-3.0.2 ``` @@ -58,50 +83,108 @@ Checkout the CRuby source code: - ``` shell + ```sh git clone https://github.com/ruby/ruby.git cd ruby ``` - Generate the configure file: + Run the GNU Autoconf script (which generates the `configure` script): - ``` shell + ```sh ./autogen.sh ``` -2. Create a `build` directory separate from the source directory: +2. Create a `build` directory inside the repository directory: - ``` shell + ```sh mkdir build && cd build ``` - While it's not necessary to build in a separate directory, it's good practice to do so. + While it's not necessary to build in a dedicated directory like this, it's good + practice to do so. -3. We'll install Ruby in `~/.rubies/ruby-master`, so create the directory: +3. We'll eventually install our new Ruby in `~/.rubies/ruby-master`, so we'll create that directory: - ``` shell + ```sh mkdir ~/.rubies ``` -4. Run configure: +4. Run the `configure` script (which generates the `Makefile`): - ``` shell + ```sh ../configure --prefix="${HOME}/.rubies/ruby-master" ``` - - If you are frequently building Ruby, add the `--disable-install-doc` flag to not build documentation which will speed up the build process. + - Also `-C` (or `--config-cache`) would reduce time to configure from the + next time. 5. Build Ruby: - ``` shell - make install + ```sh + make ``` 6. [Run tests](testing_ruby.md) to confirm your build succeeded. +7. Install our newly-compiled Ruby into `~/.rubies/ruby-master`: + + ```sh + make install + ``` + + - If you need to run `make install` with `sudo` and want to avoid document + generation with different permissions, you can use `make SUDO=sudo + install`. + +8. You can then try your new Ruby out, for example: + + ```sh + ~/.rubies/ruby-master/bin/ruby -e "puts 'Hello, World!'" + ``` + +By the end, your repo will look like this: + +```text +ruby +├── autogen.sh # Pre-existing Autoconf script, used in step 1 +├── configure # Generated in step 1, which generates the `Makefile` in step 4 +├── build # Created in step 2 and populated in step 4 +│ ├── GNUmakefile # Generated by `../configure` +│ ├── Makefile # Generated by `../configure` +│ ├── object.o # Compiled object file, built my `make` +│ └── ... other compiled `.o` object files +│ +│ # Other interesting files: +├── include +│ └── ruby.h # The main public header +├── internal +│ ├── object.h +│ └── ... other header files used by the `.c` files in the repo root. +├── lib +│ └── # Default gems, like `bundler`, `erb`, `set`, `yaml`, etc. +├── spec +│ └── # A mirror of the Ruby specification from github.com/ruby/spec +├── test +│ ├── ruby +│ └── ... +├── object.c +└── ... other `.c` files +``` + +[Download Ruby]: https://www.ruby-lang.org/en/downloads/ + ### Unexplainable Build Errors -If you are having unexplainable build errors, after saving all your work, try running `git clean -xfd` in the source root to remove all git ignored local files. If you are working from a source directory that's been updated several times, you may have temporary build artifacts from previous releases which can cause build failures. +If you are having unexplainable build errors, after saving all your work, try +running `git clean -xfd` in the source root to remove all git ignored local +files. If you are working from a source directory that's been updated several +times, you may have temporary build artifacts from previous releases which can +cause build failures. + +## Building on Windows + +The documentation for building on Windows can be found in [the separated +file](../windows.md). ## More details @@ -110,18 +193,21 @@ about Ruby's build to help out. ### Running make scripts in parallel -In GNU make and BSD make implementations, to run a specific make script in parallel, pass the flag `-j`. For instance, -to run tests on 8 processes, use: +In GNU make[^caution-gmake-3] and BSD make implementations, to run a specific make script in +parallel, pass the flag `-j`. For instance, to run tests +on 8 processes, use: -``` shell +```sh make test-all -j8 ``` We can also set `MAKEFLAGS` to run _all_ `make` commands in parallel. -Having the right `--jobs` flag will ensure all processors are utilized when building software projects. To do this effectively, you can set `MAKEFLAGS` in your shell configuration/profile: +Having the right `--jobs` flag will ensure all processors are utilized when +building software projects. To do this effectively, you can set `MAKEFLAGS` in +your shell configuration/profile: -``` shell +```sh # On macOS with Fish shell: export MAKEFLAGS="--jobs "(sysctl -n hw.ncpu) @@ -135,20 +221,25 @@ export MAKEFLAGS="--jobs "(nproc) export MAKEFLAGS="--jobs $(nproc)" ``` +[^caution-gmake-3]: **CAUTION**: GNU make 3 is missing some features for parallel execution, we +recommend to upgrade to GNU make 4 or later. + ### Miniruby vs Ruby -Miniruby is a version of Ruby which has no external dependencies and lacks certain features. -It can be useful in Ruby development because it allows for faster build times. Miniruby is -built before Ruby. A functional Miniruby is required to build Ruby. To build Miniruby: +Miniruby is a version of Ruby which has no external dependencies and lacks +certain features. It can be useful in Ruby development because it allows for +faster build times. Miniruby is built before Ruby. A functional Miniruby is +required to build Ruby. To build Miniruby: -``` shell +```sh make miniruby ``` ## Debugging -You can use either lldb or gdb for debugging. Before debugging, you need to create a `test.rb` -with the Ruby script you'd like to run. You can use the following make targets: +You can use either lldb or gdb for debugging. Before debugging, you need to +create a `test.rb` with the Ruby script you'd like to run. You can use the +following make targets: * `make run`: Runs `test.rb` using Miniruby * `make lldb`: Runs `test.rb` using Miniruby in lldb @@ -157,33 +248,95 @@ with the Ruby script you'd like to run. You can use the following make targets: * `make lldb-ruby`: Runs `test.rb` using Ruby in lldb * `make gdb-ruby`: Runs `test.rb` using Ruby in gdb +For VS Code users, you can set up editor-based debugging experience by running: + +```shell +cp -r misc/.vscode .vscode +``` + +This will add launch configurations for debugging Ruby itself by running `test.rb` with `lldb`. + +**Note**: if you build Ruby under the `./build` folder, you'll need to update `.vscode/launch.json`'s program entry accordingly to: `"${workspaceFolder}/build/ruby"` + ### Compiling for Debugging -You should configure Ruby without optimization and other flags that may interfere with debugging: +You can compile Ruby with the `RUBY_DEBUG` macro to enable debugging on some +features. One example is debugging object shapes in Ruby with +`RubyVM::Shape.of(object)`. -``` shell -./configure --enable-debug-env optflags="-O0 -fno-omit-frame-pointer" +Additionally Ruby can be compiled to support the `RUBY_DEBUG` environment +variable to enable debugging on some features. An example is using +`RUBY_DEBUG=gc_stress` to debug GC-related issues. + +There is also support for the `RUBY_DEBUG_LOG` environment variable to log a +lot of information about what the VM is doing, via the `USE_RUBY_DEBUG_LOG` +macro. + +You should also configure Ruby without optimization and other flags that may +interfere with debugging by changing the optimization flags. + +Bringing it all together: + +```sh +./configure cppflags="-DRUBY_DEBUG=1 -DUSE_RUBY_DEBUG_LOG=1" --enable-debug-env optflags="-O0 -fno-omit-frame-pointer" ``` ### Building with Address Sanitizer -Using the address sanitizer is a great way to detect memory issues. +Using the address sanitizer (ASAN) is a great way to detect memory issues. It +can detect memory safety issues in Ruby itself, and also in any C extensions +compiled with and loaded into a Ruby compiled with ASAN. -``` shell +```sh ./autogen.sh mkdir build && cd build -export ASAN_OPTIONS="halt_on_error=0:use_sigaltstack=0:detect_leaks=0" -../configure cppflags="-fsanitize=address -fno-omit-frame-pointer" optflags=-O0 LDFLAGS="-fsanitize=address -fno-omit-frame-pointer" +../configure CC=clang-18 cflags="-fsanitize=address -fno-omit-frame-pointer -DUSE_MN_THREADS=0" # and any other options you might like make ``` -On Linux it is important to specify `-O0` when debugging. This is especially true for ASAN which sometimes works incorrectly at higher optimisation levels. +The compiled Ruby will now automatically crash with a report and a backtrace +if ASAN detects a memory safety issue. To run Ruby's test suite under ASAN, +issue the following command. Note that this will take quite a long time (over +two hours on my laptop); the `RUBY_TEST_TIMEOUT_SCALE` and +`SYNTAX_SUGEST_TIMEOUT` variables are required to make sure tests don't +spuriously fail with timeouts when in fact they're just slow. + +```sh +RUBY_TEST_TIMEOUT_SCALE=5 SYNTAX_SUGGEST_TIMEOUT=600 make check +``` + +Please note, however, the following caveats! + +* ASAN will not work properly on any currently released version of Ruby; the + necessary support is currently only present on Ruby's master branch (and the + whole test suite passes only as of commit [Revision 9d0a5148]). +* Due to [Bug #20243], Clang generates code for threadlocal variables which + doesn't work with M:N threading. Thus, it's necessary to disable M:N + threading support at build time for now (with the `-DUSE_MN_THREADS=0` + configure argument). +* ASAN will only work when using Clang version 18 or later - it requires + [llvm/llvm-project#75290] related to multithreaded `fork`. +* ASAN has only been tested so far with Clang on Linux. It may or may not work + with other compilers or on other platforms - please file an issue on + [Ruby Issue Tracking System] if you run into problems with such configurations + (or, to report that they actually work properly!) +* In particular, although I have not yet tried it, I have reason to believe + ASAN will _not_ work properly on macOS yet - the fix for the multithreaded + fork issue was actually reverted for macOS (see [llvm/llvm-project#75659]). + Please open an issue on [Ruby Issue Tracking System] if this is a problem for + you. + +[Revision 9d0a5148]: https://bugs.ruby-lang.org/projects/ruby-master/repository/git/revisions/9d0a5148ae062a0481a4a18fbeb9cfd01dc10428 +[Bug #20243]: https://bugs.ruby-lang.org/issues/20243 +[llvm/llvm-project#75290]: https://github.com/llvm/llvm-project/pull/75290 +[llvm/llvm-project#75659]: https://github.com/llvm/llvm-project/pull/75659#issuecomment-1861584777 +[Ruby Issue Tracking System]: https://bugs.ruby-lang.org ## How to measure coverage of C and Ruby code You need to be able to use gcc (gcov) and lcov visualizer. -``` shell +```sh ./autogen.sh ./configure --enable-gcov make @@ -194,11 +347,12 @@ make lcov open lcov-out/index.html ``` -If you need only C code coverage, you can remove `COVERAGE=true` from the above process. -You can also use `gcov` command directly to get per-file coverage. +If you need only C code coverage, you can remove `COVERAGE=true` from the +above process. You can also use `gcov` command directly to get per-file +coverage. -If you need only Ruby code coverage, you can remove `--enable-gcov`. -Note that `test-coverage.dat` accumulates all runs of `make test-all`. -Make sure that you remove the file if you want to measure one test run. +If you need only Ruby code coverage, you can remove `--enable-gcov`. Note +that `test-coverage.dat` accumulates all runs of `make test-all`. Make sure +that you remove the file if you want to measure one test run. You can see the coverage result of CI: https://rubyci.org/coverage diff --git a/doc/contributing/contributing.md b/doc/contributing/contributing.md new file mode 100644 index 00000000000000..a2ed00ab90c1b0 --- /dev/null +++ b/doc/contributing/contributing.md @@ -0,0 +1,35 @@ +# Contributing to Ruby + +## Ruby Issues + +To report an issue in the Ruby core: + +* [Report issues](reporting_issues.md). + +## Ruby Core + +To contribute to the Ruby core functionality, +you'll need initially to: + +* [Build Ruby](building_ruby.md) on your system. +* [Test Ruby](testing_ruby.md), to make sure the build is correct. + +Then: + +* [Make changes to Ruby](making_changes_to_ruby.md). + +And possibly: + +* [Benchmark Ruby](https://github.com/ruby/ruby/tree/master/benchmark#make-benchmark). + +## Ruby Documentation + +To contribute to the Ruby core documentation, see: + +* [Making changes to the Ruby documentation](documentation_guide.md). + +## Ruby Standard Library + +To contribute to the Ruby Standard Library, see: + +* [Making changes to the Ruby Standard Library](making_changes_to_stdlibs.md). diff --git a/doc/contributing/documentation_guide.md b/doc/contributing/documentation_guide.md index 6cb2b8d7dc434b..a913aa10865506 100644 --- a/doc/contributing/documentation_guide.md +++ b/doc/contributing/documentation_guide.md @@ -7,7 +7,7 @@ in the Ruby core and in the Ruby standard library. ## Generating documentation Most Ruby documentation lives in the source files and is written in -[RDoc format](rdoc-ref:RDoc::Markup). +[RDoc format](https://ruby.github.io/rdoc/RDoc/MarkupReference.html). Some pages live under the `doc` folder and can be written in either `.rdoc` or `.md` format, determined by the file extension. @@ -20,10 +20,12 @@ build directory: make html ``` +If you don't have a build directory, follow the [quick start +guide](building_ruby.md#label-Quick+start+guide) up to step 4. + Then you can preview your changes by opening `{build folder}/.ext/html/index.html` file in your browser. - ## Goal The goal of Ruby documentation is to impart the most important @@ -42,14 +44,13 @@ Use your judgment about what the user needs to know. - Group sentences into (ideally short) paragraphs, each covering a single topic. - Organize material with - [headings](rdoc-ref:RDoc::MarkupReference@Headings). + [headings]. - Refer to authoritative and relevant sources using - [links](rdoc-ref:RDoc::MarkupReference@Links). + [links](https://ruby.github.io/rdoc/RDoc/MarkupReference.html#class-RDoc::MarkupReference-label-Links). - Use simple verb tenses: simple present, simple past, simple future. - Use simple sentence structure, not compound or complex structure. - Avoid: - - Excessive comma-separated phrases; - consider a [list](rdoc-ref:RDoc::MarkupReference@Lists). + - Excessive comma-separated phrases; consider a [list]. - Idioms and culture-specific references. - Overuse of headings. - Using US-ASCII-incompatible characters in C source files; @@ -93,7 +94,7 @@ involving new files `doc/*.rdoc`: Example: - ``` + ```c /* * call-seq: * each_byte {|byte| ... } -> self @@ -108,7 +109,7 @@ involving new files `doc/*.rdoc`: Ruby is documented using RDoc. For information on \RDoc syntax and features, see the -[RDoc Markup Reference](rdoc-ref:RDoc::Markup@RDoc+Markup+Reference). +[RDoc Markup Reference](https://ruby.github.io/rdoc/RDoc/MarkupReference.html). ### Output from `irb` @@ -127,22 +128,21 @@ a #=> [2, 3, 1] ### Headings -Organize a long discussion for a class or module with [headings](rdoc-ref:RDoc::MarkupReference@Headings). +Organize a long discussion for a class or module with [headings]. Do not use formal headings in the documentation for a method or constant. In the rare case where heading-like structures are needed within the documentation for a method or constant, use -[bold text](rdoc-ref:RDoc::MarkupReference@Bold) +[bold text](https://ruby.github.io/rdoc/RDoc/MarkupReference.html#class-RDoc::MarkupReference-label-Bold) as pseudo-headings. ### Blank Lines A blank line begins a new paragraph. -A [code block](rdoc-ref:RDoc::MarkupReference@Code+Blocks) -or [list](rdoc-ref:RDoc::MarkupReference@Lists) -should be preceded by and followed by a blank line. +A [code block](https://ruby.github.io/rdoc/RDoc/MarkupReference.html#class-RDoc::MarkupReference-label-Code+Blocks) +or [list] should be preceded by and followed by a blank line. This is unnecessary for the HTML output, but helps in the `ri` output. ### \Method Names @@ -162,45 +162,139 @@ For a method name in text: Code or commands embedded in running text (i.e., not in a code block) should marked up as -[monofont](rdoc-ref:RDoc::MarkupReference@Monofont). +[monofont]. Code that is a simple string should include the quote marks. ### Auto-Linking +Most often, the name of a class, module, or method +is auto-linked: + +```rdoc +- Float. +- Enumerable. +- File.new +- File#read. +``` + +renders as: + +> - Float. +> - Enumerable. +> - File.new +> - File#read. + In general, \RDoc's auto-linking should not be suppressed. -For example, we should write `Array`, not `\Array`. +For example, we should write just plain _Float_ (which is auto-linked): -We might consider whether to suppress when: +```rdoc +Returns a Float. +``` -- The word in question does not refer to a Ruby entity - (e.g., some uses of _Class_ or _English_). -- The reference is to the current class document - (e.g., _Array_ in the documentation for class `Array`). -- The same reference is repeated many times - (e.g., _RDoc_ on this page). -- The reference is to a class or module that users - usually don't deal with, including these: +which renders as: - - \Class. - - \Method. - - \Module. +> Returns a Float. -Most often, the name of a class, module, or method -will be autolinked: +However, _do_ suppress auto-linking when the word in question +does not refer to a Ruby entity (e.g., some uses of _Class_ or _English_): -- Array. -- Enumerable. -- File.new -- File#read. +```rdoc +Class variables can be tricky. +``` + +renders as: + +> Class variables can be tricky. + +Also, _do_ suppress auto-linking when the word in question +refers to the current document +(e.g., _Float_ in the documentation for class Float). + +In this case you may consider forcing the name to +[monofont], +which suppresses auto-linking, and also emphasizes that the word is a class name: + +```rdoc +A +Float+ object represents .... +``` + +renders as: + +> A `Float` object represents .... + +For a _very_ few, _very_ often-discussed classes, +you might consider avoiding the capitalized class name altogether. +For example, for some mentions of arrays, +you might write simply the lowercase _array_. + +Instead of: + +```rdoc +For an empty Array, .... +``` + +which renders as: + +> For an empty Array, .... + +you might write: + +```rdoc +For an empty array, .... +``` + +which renders as: + +> For an empty array, .... + +This more casual usage avoids both auto-linking and distracting font changes, +and is unlikely to cause confusion. + +This principle may be usefully applied, in particular, for: -If not, or if you suppress autolinking, consider forcing -[monofont](rdoc-ref:RDoc::MarkupReference@Monofont). +- An array. +- An integer. +- A hash. +- A string. + +However, it should be applied _only_ when referring to an _instance_ of the class, +and _never_ when referring to the class itself. + +### Explicit Links + +When writing an explicit link, follow these guidelines. + +#### +rdoc-ref+ Scheme + +Use the +rdoc-ref+ scheme for: + +- A link in core documentation to other core documentation. +- A link in core documentation to documentation in a standard library package. +- A link in a standard library package to other documentation in that same + standard library package. + +See section "+rdoc-ref+ Scheme" in [links]. + +#### URL-Based Link + +Use a full URL-based link for: + +- A link in standard library documentation to documentation in the core. +- A link in standard library documentation to documentation in a different + standard library package. + +Doing so ensures that the link will valid even when the package documentation +is built independently (separately from the core documentation). + +The link should lead to a target in https://docs.ruby-lang.org/en/master/. + +Also use a full URL-based link for a link to an off-site document. ### Variable Names The name of a variable (as specified in its call-seq) should be marked up as -[monofont](rdoc-ref:RDoc::MarkupReference@Monofont). +[monofont]. Also, use monofont text for the name of a transient variable (i.e., one defined and used only in the discussion, such as +n+). @@ -216,16 +310,21 @@ may not render them properly. In particular, avoid building tables with HTML tags (, etc.). -Alternatives are: +Alternatives: + +- A {verbatim text block}[https://ruby.github.io/rdoc/RDoc/MarkupReference.html#class-RDoc::MarkupReference-label-Verbatim+Text+Blocks], + using spaces and punctuation to format the text; + note that {text markup}[https://ruby.github.io/rdoc/RDoc/MarkupReference.html#class-RDoc::MarkupReference-label-Text+Markup] + will not be honored: + + - Example {source}[https://github.com/ruby/ruby/blob/34d802f32f00df1ac0220b62f72605827c16bad8/file.c#L6570-L6596]. + - Corresponding {output}[rdoc-ref:File@Read-2FWrite+Mode]. -- The GFM (GitHub Flavored Markdown) table extension, - which is enabled by default. See - {GFM tables extension}[https://github.github.com/gfm/#tables-extension-]. +- (Markdown format only): A {Github Flavored Markdown (GFM) table}[https://github.github.com/gfm/#tables-extension-], + using special formatting for the text: -- A {verbatim text block}[rdoc-ref:RDoc::MarkupReference@Verbatim+Text+Blocks], - using spaces and punctuation to format the text. - Note that {text markup}[rdoc-ref:RDoc::MarkupReference@Text+Markup] - will not be honored. + - Example {source}[https://github.com/ruby/ruby/blob/34d802f32f00df1ac0220b62f72605827c16bad8/doc/contributing/glossary.md?plain=1]. + - Corresponding {output}[https://docs.ruby-lang.org/en/master/contributing/glossary_md.html]. ## Documenting Classes and Modules @@ -255,9 +354,11 @@ Guidelines: - The section title is `What's Here`. - Consider listing the parent class and any included modules; consider - [links](rdoc-ref:RDoc::MarkupReference@Links) - to their "What's Here" sections if those exist. -- List methods as a bullet list: + [links] to their "What's Here" sections if those exist. +- All methods mentioned in the left-pane table of contents + should be listed (including any methods extended from another class). +- Attributes (which are not included in the TOC) may also be listed. +- Display methods as items in one or more bullet lists: - Begin each item with the method name, followed by a colon and a short description. @@ -265,7 +366,7 @@ Guidelines: (and do not list the aliases separately). - Check the rendered documentation to determine whether \RDoc has recognized the method and linked to it; if not, manually insert a - [link](rdoc-ref:RDoc::MarkupReference@Links). + [link](https://ruby.github.io/rdoc/RDoc/MarkupReference.html#class-RDoc::MarkupReference-label-Links). - If there are numerous entries, consider grouping them into subsections with headings. - If there are more than a few such subsections, @@ -279,6 +380,7 @@ The general structure of the method documentation should be: - Calling sequence (for methods written in C). - Synopsis (short description). +- In-brief examples (optional) - Details and examples. - Argument description (if necessary). - Corner cases and exceptions. @@ -290,17 +392,17 @@ For methods written in Ruby, \RDoc documents the calling sequence automatically. For methods written in C, \RDoc cannot determine what arguments the method accepts, so those need to be documented using \RDoc directive -[`call-seq:`](rdoc-ref:RDoc::MarkupReference@Directives+for+Method+Documentation). +[`call-seq:`](https://ruby.github.io/rdoc/RDoc/MarkupReference.html#class-RDoc::MarkupReference-label-Directives+for+Method+Documentation). For a singleton method, use the form: -``` +```rdoc class_name.method_name(method_args) {|block_args| ... } -> return_type ``` Example: -``` +```rdoc * call-seq: * Hash.new(default_value = nil) -> new_hash * Hash.new {|hash, key| ... } -> new_hash @@ -309,23 +411,32 @@ Example: For an instance method, use the form (omitting any prefix, just as RDoc does for a Ruby-coded method): -``` +```rdoc method_name(method_args) {|block_args| ... } -> return_type ``` + For example, in Array, use: -``` +```rdoc * call-seq: * count -> integer * count(obj) -> integer * count {|element| ... } -> integer ``` -``` -* call-seq: +```rdoc +* call-seq: * <=> other -> -1, 0, 1, or nil ``` +For a binary-operator style method (e.g., Array#&), +cite `self` in the call-seq (not, e.g., `array` or `receiver`): + +```rdoc +* call-seq: +* self & other_array -> new_array +``` + Arguments: - If the method does not accept arguments, omit the parentheses. @@ -337,15 +448,17 @@ Arguments: or an explicit argument, use a `call-seq` with optional arguments. For example, use: - ``` - respond_to?(symbol, include_all = false) -> true or false + ```rdoc + * call-seq: + * respond_to?(symbol, include_all = false) -> true or false ``` - If the behavior is different with an omitted or an explicit argument, use a `call-seq` with separate lines. For example, in Enumerable, use: - ``` + ```rdoc + * call-seq: * max -> element * max(n) -> array ``` @@ -355,6 +468,14 @@ Block: - If the method does not accept a block, omit the block. - If the method accepts a block, the `call-seq` should have `{|args| ... }`, not `{|args| block }` or `{|args| code }`. +- If the method accepts a block, but returns an Enumerator when the block is omitted, + the `call-seq` should show both forms: + + ```rdoc + * call-seq: + * array.select {|element| ... } -> new_array + * array.select -> new_enumerator + ``` Return types: @@ -383,14 +504,22 @@ an entire paragraph. For `Array#count`, the synopsis is: -``` -Returns a count of specified elements. -``` +> Returns a count of specified elements. This is great as it is short and descriptive. Avoid documenting too much in the synopsis, stick to the most important information for the benefit of the reader. +### In-Brief Examples + +For a method whose documentation is lengthy, +consider adding an "in-brief" passage, +showing examples that summarize the method's uses. + +The passage may answer some users' questions +(without their having to read long documentation); +see Array#[] and Array#[]=. + ### Details and Examples Most non-trivial methods benefit from examples, as well as details @@ -413,6 +542,15 @@ do not add an example if it provides the same information given in the synopsis or details. The purpose of examples is not to prove what the details are stating. +Many methods that can take an optional block call the block if it is given, +but return a new Enumerator if the block is not given; +in that case, do not provide an example, +but do state the fact (with the auto-linking uppercase Enumerator): + +```rdoc +* With no block given, returns a new Enumerator. +``` + ### Argument Description (if necessary) For methods that require arguments, if not obvious and not explicitly @@ -429,7 +567,7 @@ argument passed if it is not obvious, not explicitly mentioned in the details, and not implicitly shown in the examples. If there is more than one argument or block argument, use a -[labeled list](rdoc-ref:RDoc::MarkupReference@Labeled+Lists). +[labeled list](https://ruby.github.io/rdoc/RDoc/MarkupReference.html#class-RDoc::MarkupReference-label-Labeled+Lists). ### Corner Cases and Exceptions @@ -469,3 +607,7 @@ mention `Hash#fetch` as a related method, and `Hash#merge` might mention For methods that accept multiple argument types, in some cases it can be useful to document the different argument types separately. It's best to use a separate paragraph for each case you are discussing. + +[headings]: https://ruby.github.io/rdoc/RDoc/MarkupReference.html#class-RDoc::MarkupReference-label-Headings +[list]: https://ruby.github.io/rdoc/RDoc/MarkupReference.html#class-RDoc::MarkupReference-label-Lists +[monofont]: https://ruby.github.io/rdoc/RDoc/MarkupReference.html#class-RDoc::MarkupReference-label-Monofont diff --git a/doc/contributing/glossary.md b/doc/contributing/glossary.md index 0d27d28c96f4de..6f9c33502820ce 100644 --- a/doc/contributing/glossary.md +++ b/doc/contributing/glossary.md @@ -8,9 +8,10 @@ Just a list of acronyms I've run across in the Ruby source code and their meanin | `bop` | Basic Operator. Relates to methods like `Integer` plus and minus which can be optimized as long as they haven't been redefined. | | `cc` | Call Cache. An inline cache structure for the call site. Stored in the `cd` | | `cd` | Call Data. A data structure that points at the `ci` and the `cc`. `iseq` objects points at the `cd`, and access call information and call caches via this structure | +| CFG | Control Flow Graph. Representation of the program where all control-flow and data dependencies have been made explicit by unrolling the stack and local variables. | | `cfp`| Control Frame Pointer. Represents a Ruby stack frame. Calling a method pushes a new frame (cfp), returning pops a frame. Points at the `pc`, `sp`, `ep`, and the corresponding `iseq`| | `ci` | Call Information. Refers to an `rb_callinfo` struct. Contains call information about the call site, including number of parameters to be passed, whether it they are keyword arguments or not, etc. Used in conjunction with the `cc` and `cd`. | -| `cref` | Class reference. A structure pointing to the class reference where `klass_or_self`, visibility scope, and refinements are stored. It also stores a pointer to the next class in the hierachy referenced by `rb_cref_struct * next`. The Class reference is lexically scoped. | +| `cref` | Class reference. A structure pointing to the class reference where `klass_or_self`, visibility scope, and refinements are stored. It also stores a pointer to the next class in the hierarchy referenced by `rb_cref_struct * next`. The Class reference is lexically scoped. | | CRuby | Implementation of Ruby written in C | | `cvar` | Class Variable. Refers to a Ruby class variable like `@@foo` | | `dvar` | Dynamic Variable. Used by the parser to refer to local variables that are defined outside of the current lexical scope. For example `def foo; bar = 1; -> { p bar }; end` the "bar" inside the block is a `dvar` | @@ -25,10 +26,11 @@ Just a list of acronyms I've run across in the Ruby source code and their meanin | `insns` | Instructions. Usually an array of YARV instructions. | | `ivar` | Instance Variable. Refers to a Ruby instance variable like `@foo` | | `imemo` | Internal Memo. A tagged struct whose memory is managed by Ruby's GC, but contains internal information and isn't meant to be exposed to Ruby programs. Contains various information depending on the type. See the `imemo_type` enum for different types. | +| `IVC` | Instance Variable Cache. Cache specifically for instance variable access | | JIT | Just In Time compiler | | `lep` | Local Environment Pointer. An `ep` which is tagged `VM_ENV_FLAG_LOCAL`. Usually this is the `ep` of a method (rather than a block, whose `ep` isn't "local") | | `local` | Local. Refers to a local variable. | -| `me` | Method Entry. Refers to an `rb_method_entry_t` struct, the internal representation of a Ruby method. +| `me` | Method Entry. Refers to an `rb_method_entry_t` struct, the internal representation of a Ruby method. | | MRI | Matz's Ruby Implementation | | `pc` | Program Counter. Usually the instruction that will be executed _next_ by the VM. Pointed to by the `cfp` and incremented by the VM | | `sp` | Stack Pointer. The top of the stack. The VM executes instructions in the `iseq` and instructions will push and pop values on the stack. The VM updates the `sp` on the `cfp` to point at the top of the stack| diff --git a/doc/contributing/making_changes_to_stdlibs.md b/doc/contributing/making_changes_to_stdlibs.md index 3b33092fead20f..721ba842896a25 100644 --- a/doc/contributing/making_changes_to_stdlibs.md +++ b/doc/contributing/making_changes_to_stdlibs.md @@ -14,7 +14,7 @@ You can find the list of maintainers [here](https://docs.ruby-lang.org/en/master First, install its dependencies using: -``` +```shell bundle install ``` @@ -22,7 +22,7 @@ bundle install If the library has a `/ext` directory, it has C files that you need to compile with: -``` +```shell bundle exec rake compile ``` @@ -32,18 +32,18 @@ All standard libraries use [test-unit](https://github.com/test-unit/test-unit) a To run all tests: -``` +```shell bundle exec rake test ``` To run a single test file: -``` +```shell bundle exec rake test TEST="test/test_foo.rb" ``` To run a single test case: -``` +```shell bundle exec rake test TEST="test/test_foo.rb" TESTOPS="--name=/test_mytest/" ``` diff --git a/doc/contributing/reporting_issues.md b/doc/contributing/reporting_issues.md index 25516ffc6bcbf4..a1a22957129336 100644 --- a/doc/contributing/reporting_issues.md +++ b/doc/contributing/reporting_issues.md @@ -52,19 +52,30 @@ your feature it could help persuade Ruby core. Here is a template you can use for a feature proposal: -``` -[Abstract] - Briefly summarize your feature -[Background] - Describe current behavior -[Proposal] - Describe your feature in detail -[Use cases] - Give specific example uses of your feature -[Discussion] - Describe why this feature is necessary and better than using existing features -[See also] - Link to other related resources (such as implementations in other languages) +```markdown +# Abstract + +Briefly summarize your feature + +# Background + +Describe current behavior + +# Proposal + +Describe your feature in detail + +# Use cases + +Give specific example uses of your feature + +# Discussion + +Describe why this feature is necessary and better than using existing features + +# See also + +Link to other related resources (such as implementations in other languages) ``` ## Backport requests diff --git a/doc/contributing/testing_ruby.md b/doc/contributing/testing_ruby.md index 8decc24083538b..4c7ce7f6a8e5a9 100644 --- a/doc/contributing/testing_ruby.md +++ b/doc/contributing/testing_ruby.md @@ -1,5 +1,9 @@ # Testing Ruby +All the commands below assume that you're running them from the `build/` directory made during [Building Ruby](building_ruby.md). + +Most commands below should work with [GNU make](https://www.gnu.org/software/make/) (the default on Linux and macOS), [BSD make](https://man.freebsd.org/cgi/man.cgi?make(1)) and [NMAKE](https://learn.microsoft.com/en-us/cpp/build/reference/nmake-reference), except where indicated otherwise. + ## Test suites There are several test suites in the Ruby codebase: @@ -8,137 +12,144 @@ We can run any of the make scripts [in parallel](building_ruby.md#label-Running+ 1. [bootstraptest/](https://github.com/ruby/ruby/tree/master/bootstraptest) - This is a small test suite that runs on Miniruby (see [building Ruby](building_ruby.md#label-Miniruby+vs+Ruby)). We can run it with: + This is a small test suite that runs on [Miniruby](building_ruby.md#label-Miniruby+vs+Ruby). We can run it with: - ``` + ```sh make btest ``` - To run it with logs, we can use: + To run individual bootstrap tests, we can either specify a list of filenames or use the `--sets` flag in the variable `BTESTS`: - ``` - make btest OPTS=-v + ```sh + make btest BTESTS="../bootstraptest/test_string.rb ../bootstraptest/test_class.rb" + make btest BTESTS="--sets=string,class" ``` - To run individual bootstrap tests, we can either specify a list of filenames or use the `--sets` flag in the variable `BTESTS`: + To run these tests with verbose logging, we can add `-v` to the `OPTS`: - ``` - make btest BTESTS="bootstraptest/test_fork.rb bootstraptest/tes_gc.rb" - make btest BTESTS="--sets=fork,gc" + ```sh + make btest OPTS="--sets=string,class -v" ``` If we want to run the bootstrap test suite on Ruby (not Miniruby), we can use: - ``` + ```sh make test ``` - To run it with logs, we can use: + To run these tests with verbose logging, we can add `-v` to the `OPTS`: - ``` + ```sh make test OPTS=-v ``` - To run a file or directory with GNU make, we can use: + (GNU make only) To run a specific file, we can use: + ```sh + make ../test/ruby/test_string.rb ``` - make test/ruby/test_foo.rb - make test/ruby/test_foo.rb TESTOPTS="-n /test_bar/" + + You can use the `-n` test option to run a specific test with a regex: + + ```sh + make ../test/ruby/test_string.rb TESTOPTS="-n /test_.*_to_s/" ``` 2. [test/](https://github.com/ruby/ruby/tree/master/test) This is a more comprehensive test suite that runs on Ruby. We can run it with: - ``` + ```sh make test-all ``` - We can run a specific test directory in this suite using the `TESTS` option, for example: + We can run a specific test file or directory in this suite using the `TESTS` option, for example: - ``` - make test-all TESTS=test/rubygems - ``` - - We can run a specific test file in this suite by also using the `TESTS` option, for example: - - ``` - make test-all TESTS=test/ruby/test_array.rb + ```sh + make test-all TESTS="../test/ruby/" + make test-all TESTS="../test/ruby/test_string.rb" ``` We can run a specific test in this suite using the `TESTS` option, specifying first the file name, and then the test name, prefixed with `--name`. For example: - ``` - make test-all TESTS="../test/ruby/test_alias.rb --name=TestAlias#test_alias_with_zsuper_method" + ```sh + make test-all TESTS="../test/ruby/test_string.rb --name=TestString#test_to_s" ``` - To run these specs with logs, we can use: + To run these tests with verbose logging, we can add `-v` to `TESTS`: - ``` + ```sh make test-all TESTS=-v ``` We can display the help of the `TESTS` option: - ``` - $ make test-all TESTS=--help + ```sh + make test-all TESTS=--help ``` - If we would like to run both the `test/` and `bootstraptest/` test suites, we can run + We can run all the tests in `test/`, `bootstraptest/` and `spec/` (the `spec/` is explained in a later section) all together with: - ``` + ```sh make check ``` 3. [spec/ruby](https://github.com/ruby/ruby/tree/master/spec/ruby) - This is a test suite that exists in [the Ruby spec repository](https://github.com/ruby/spec) and is mirrored into the `spec/ruby` directory in the Ruby repository. It tests the behavior of the Ruby programming language. We can run this using: + This is a test suite defined in [the Ruby spec repository](https://github.com/ruby/spec), and is periodically mirrored into the `spec/ruby` directory of this repository. It tests the behavior of the Ruby programming language. We can run this using: - ``` + ```sh make test-spec ``` - To run a specific directory, we can use `SPECOPTS` to specify the directory: + We can run a specific test file or directory in this suite using the `SPECOPTS` option, for example: - ``` - make test-spec SPECOPTS=spec/ruby/core/array - ``` - - To run a specific file, we can also use `SPECOPTS` to specify the file: - - ``` - make test-spec SPECOPTS=spec/ruby/core/array/any_spec.rb + ```sh + make test-spec SPECOPTS="../spec/ruby/core/string/" + make test-spec SPECOPTS="../spec/ruby/core/string/to_s_spec.rb" ``` To run a specific test, we can use the `--example` flag to match against the test name: - ``` - make test-spec SPECOPTS="../spec/ruby/core/array/any_spec.rb --example='is false if the array is empty'" + ```sh + make test-spec SPECOPTS="../spec/ruby/core/string/to_s_spec.rb --example='returns self when self.class == String'" ``` - To run these specs with logs, we can use: + To run these specs with verbose logging, we can add `-v` to the `SPECOPTS`: - ``` - make test-spec SPECOPTS=-Vfs + ```sh + make test-spec SPECOPTS="../spec/ruby/core/string/to_s_spec.rb -Vfs" ``` - To run a ruby-spec file or directory with GNU make, we can use + (GNU make only) To run a ruby-spec file or directory, we can use - ``` - make spec/ruby/core/foo/bar_spec.rb + ```sh + make ../spec/ruby/core/string/to_s_spec.rb ``` 4. [spec/bundler](https://github.com/ruby/ruby/tree/master/spec/bundler) - The bundler test suite exists in [the RubyGems repository](https://github.com/rubygems/rubygems/tree/master/bundler/spec) and is mirrored into the `spec/bundler` directory in the Ruby repository. We can run this using: + The bundler test suite is defined in [the RubyGems repository](https://github.com/rubygems/rubygems/tree/master/bundler/spec), and is periodically mirrored into the `spec/ruby` directory of this repository. We can run this using: - ``` + ```sh make test-bundler ``` To run a specific bundler spec file, we can use `BUNDLER_SPECS` as follows: + ```sh + make test-bundler BUNDLER_SPECS=commands/exec_spec.rb ``` - $ make test-bundler BUNDLER_SPECS=commands/exec_spec.rb - ``` + +## Troubleshooting + +### Running test suites on s390x CPU Architecture + +If we see failing tests related to the zlib library on s390x CPU architecture, we can run the test suites with `DFLTCC=0` to pass: + +```sh +DFLTCC=0 make check +``` + +The failures can happen with the zlib library applying the patch [madler/zlib#410](https://github.com/madler/zlib/pull/410) to enable the deflate algorithm producing a different compressed byte stream. We manage this issue at [[ruby-core:114942][Bug #19909]](https://bugs.ruby-lang.org/issues/19909). diff --git a/doc/csv/recipes/generating.rdoc b/doc/csv/recipes/generating.rdoc index a6bd88a7147a1e..e61838d31a5b3c 100644 --- a/doc/csv/recipes/generating.rdoc +++ b/doc/csv/recipes/generating.rdoc @@ -163,7 +163,7 @@ This example defines and uses two custom write converters to strip and upcase ge === RFC 4180 Compliance By default, \CSV generates data that is compliant with -{RFC 4180}[https://tools.ietf.org/html/rfc4180] +{RFC 4180}[https://www.rfc-editor.org/rfc/rfc4180] with respect to: - Column separator. - Quote character. diff --git a/doc/csv/recipes/parsing.rdoc b/doc/csv/recipes/parsing.rdoc index f3528fbdf1bc8b..1b7071e33f6543 100644 --- a/doc/csv/recipes/parsing.rdoc +++ b/doc/csv/recipes/parsing.rdoc @@ -191,7 +191,7 @@ Output: === RFC 4180 Compliance By default, \CSV parses data that is compliant with -{RFC 4180}[https://tools.ietf.org/html/rfc4180] +{RFC 4180}[https://www.rfc-editor.org/rfc/rfc4180] with respect to: - Row separator. - Column separator. diff --git a/doc/date/calendars.rdoc b/doc/date/calendars.rdoc index b8690841b1d45c..4e6fd8334bda50 100644 --- a/doc/date/calendars.rdoc +++ b/doc/date/calendars.rdoc @@ -18,7 +18,7 @@ The reasons for the difference are religious/political histories. - On October 15, 1582, several countries changed from the Julian calendar to the Gregorian calendar; these included Italy, Poland, Portugal, and Spain. - Other contries in the Western world retained the Julian calendar. + Other countries in the Western world retained the Julian calendar. - On September 14, 1752, most of the British empire changed from the Julian calendar to the Gregorian calendar. @@ -31,7 +31,7 @@ See also {a concrete example here}[rdoc-ref:DateTime@When+should+you+use+DateTim === Argument +start+ Certain methods in class \Date handle differences in the -{Julian and Gregorian calendars}[rdoc-ref:calendars.rdoc@Julian+and+Gregorian+Calendars] +{Julian and Gregorian calendars}[rdoc-ref:date/calendars.rdoc@Julian+and+Gregorian+Calendars] by accepting an optional argument +start+, whose value may be: - Date::ITALY (the default): the created date is Julian diff --git a/doc/distribution.md b/doc/distribution.md index bc89a7500a6ec0..164e1b7109a1ab 100644 --- a/doc/distribution.md +++ b/doc/distribution.md @@ -8,7 +8,7 @@ This document outlines the expected way to distribute Ruby, with a specific focu The tarball for official releases is created by the release manager. The release manager uploads the tarball to the [Ruby website](https://www.ruby-lang.org/en/downloads/). -Downstream distributors should use the official release tarballs as part of their build process. This ensures that the tarball is created in a consistent way, and that the tarball is crytographically verified. +Downstream distributors should use the official release tarballs as part of their build process. This ensures that the tarball is created in a consistent way, and that the tarball is cryptographically verified. ### Using the nightly tarball for testing @@ -19,7 +19,8 @@ See the Snapshots section of the [Ruby website](https://www.ruby-lang.org/en/dow This can be useful if the nightly tarball does not have all changes yet. At Ruby source tree cloned using git: -```sh-session + +```console $ ./autogen.sh $ ./configure -C $ make diff --git a/doc/encodings.rdoc b/doc/encodings.rdoc index f5e718b3cda57e..eaee2efd62b46a 100644 --- a/doc/encodings.rdoc +++ b/doc/encodings.rdoc @@ -1,6 +1,6 @@ -== Encodings += Encodings -=== The Basics +== The Basics A {character encoding}[https://en.wikipedia.org/wiki/Character_encoding], often shortened to _encoding_, is a mapping between: @@ -12,9 +12,9 @@ Some character sets contain only 1-byte characters; {US-ASCII}[https://en.wikipedia.org/wiki/ASCII], for example, has 256 1-byte characters. This string, encoded in US-ASCII, has six characters that are stored as six bytes: - s = 'Hello!'.encode('US-ASCII') # => "Hello!" - s.encoding # => # - s.bytes # => [72, 101, 108, 108, 111, 33] + s = 'Hello!'.encode(Encoding::US_ASCII) # => "Hello!" + s.encoding # => # + s.bytes # => [72, 101, 108, 108, 111, 33] Other encodings may involve multi-byte characters. {UTF-8}[https://en.wikipedia.org/wiki/UTF-8], for example, @@ -30,22 +30,22 @@ Other characters, such as the Euro symbol, are multi-byte: s = "\u20ac" # => "€" s.bytes # => [226, 130, 172] -=== The \Encoding \Class +== The \Encoding Class -==== \Encoding Objects +=== \Encoding Objects Ruby encodings are defined by constants in class \Encoding. There can be only one instance of \Encoding for each of these constants. -\Method Encoding.list returns an array of \Encoding objects (one for each constant): +Method Encoding.list returns an array of \Encoding objects (one for each constant): Encoding.list.size # => 103 Encoding.list.first.class # => Encoding Encoding.list.take(3) # => [#, #, #] -==== Names and Aliases +=== Names and Aliases -\Method Encoding#name returns the name of an \Encoding: +Method Encoding#name returns the name of an \Encoding: Encoding::ASCII_8BIT.name # => "ASCII-8BIT" Encoding::WINDOWS_31J.name # => "Windows-31J" @@ -58,29 +58,29 @@ method Encoding#names returns an array containing the name and all aliases: Encoding::WINDOWS_31J.names #=> ["Windows-31J", "CP932", "csWindows31J", "SJIS", "PCK"] -\Method Encoding.aliases returns a hash of all alias/name pairs: +Method Encoding.aliases returns a hash of all alias/name pairs: Encoding.aliases.size # => 71 Encoding.aliases.take(3) # => [["BINARY", "ASCII-8BIT"], ["CP437", "IBM437"], ["CP720", "IBM720"]] -\Method Encoding.name_list returns an array of all the encoding names and aliases: +Method Encoding.name_list returns an array of all the encoding names and aliases: Encoding.name_list.size # => 175 Encoding.name_list.take(3) # => ["ASCII-8BIT", "UTF-8", "US-ASCII"] -\Method +name_list+ returns more entries than method +list+ +Method +name_list+ returns more entries than method +list+ because it includes both the names and their aliases. -\Method Encoding.find returns the \Encoding for a given name or alias, if it exists: +Method Encoding.find returns the \Encoding for a given name or alias, if it exists: Encoding.find("US-ASCII") # => # Encoding.find("US-ASCII").class # => Encoding -==== Default Encodings +=== Default Encodings -\Method Encoding.find, above, also returns a default \Encoding +Method Encoding.find, above, also returns a default \Encoding for each of these special names: - +external+: the default external \Encoding: @@ -100,27 +100,27 @@ for each of these special names: Encoding.find("filesystem") # => # -\Method Encoding.default_external returns the default external \Encoding: +Method Encoding.default_external returns the default external \Encoding: Encoding.default_external # => # -\Method Encoding.default_external= sets that value: +Method Encoding.default_external= sets that value: - Encoding.default_external = 'US-ASCII' # => "US-ASCII" - Encoding.default_external # => # + Encoding.default_external = Encoding::US_ASCII # => # + Encoding.default_external # => # -\Method Encoding.default_internal returns the default internal \Encoding: +Method Encoding.default_internal returns the default internal \Encoding: Encoding.default_internal # => nil -\Method Encoding.default_internal= sets the default internal \Encoding: +Method Encoding.default_internal= sets the default internal \Encoding: - Encoding.default_internal = 'US-ASCII' # => "US-ASCII" - Encoding.default_internal # => # + Encoding.default_internal = Encoding::US_ASCII # => # + Encoding.default_internal # => # -==== Compatible Encodings +=== Compatible Encodings -\Method Encoding.compatible? returns whether two given objects are encoding-compatible +Method Encoding.compatible? returns whether two given objects are encoding-compatible (that is, whether they can be concatenated); returns the \Encoding of the concatenated string, or +nil+ if incompatible: @@ -128,62 +128,63 @@ returns the \Encoding of the concatenated string, or +nil+ if incompatible: eng = 'text' Encoding.compatible?(rus, eng) # => # - s0 = "\xa1\xa1".force_encoding('iso-8859-1') # => "\xA1\xA1" - s1 = "\xa1\xa1".force_encoding('euc-jp') # => "\x{A1A1}" - Encoding.compatible?(s0, s1) # => nil + s0 = "\xa1\xa1".force_encoding(Encoding::ISO_8859_1) # => "\xA1\xA1" + s1 = "\xa1\xa1".force_encoding(Encoding::EUCJP) # => "\x{A1A1}" + Encoding.compatible?(s0, s1) # => nil -=== \String \Encoding +== \String \Encoding A Ruby String object has an encoding that is an instance of class \Encoding. The encoding may be retrieved by method String#encoding. The default encoding for a string literal is the script encoding; -see (Script Encoding)[rdoc-ref:encodings.rdoc@Script+Encoding]. +see {Script Encoding}[rdoc-ref:encodings.rdoc@Script+Encoding]. 's'.encoding # => # The default encoding for a string created with method String.new is: +- For no argument, ASCII-8BIT. - For a \String object argument, the encoding of that string. - For a string literal, the script encoding; see {Script Encoding}[rdoc-ref:encodings.rdoc@Script+Encoding]. In either case, any encoding may be specified: - s = String.new(encoding: 'UTF-8') # => "" - s.encoding # => # - s = String.new('foo', encoding: 'ASCII-8BIT') # => "foo" - s.encoding # => # + s = String.new(encoding: Encoding::UTF_8) # => "" + s.encoding # => # + s = String.new('foo', encoding: Encoding::BINARY) # => "foo" + s.encoding # => # The encoding for a string may be changed: - s = "R\xC3\xA9sum\xC3\xA9" # => "Résumé" - s.encoding # => # - s.force_encoding('ISO-8859-1') # => "R\xC3\xA9sum\xC3\xA9" - s.encoding # => # + s = "R\xC3\xA9sum\xC3\xA9" # => "Résumé" + s.encoding # => # + s.force_encoding(Encoding::ISO_8859_1) # => "R\xC3\xA9sum\xC3\xA9" + s.encoding # => # Changing the assigned encoding does not alter the content of the string; it changes only the way the content is to be interpreted: - s # => "R\xC3\xA9sum\xC3\xA9" - s.force_encoding('UTF-8') # => "Résumé" + s # => "R\xC3\xA9sum\xC3\xA9" + s.force_encoding(Encoding::UTF_8) # => "Résumé" The actual content of a string may also be altered; see {Transcoding a String}[#label-Transcoding+a+String]. Here are a couple of useful query methods: - s = "abc".force_encoding("UTF-8") # => "abc" - s.ascii_only? # => true - s = "abc\u{6666}".force_encoding("UTF-8") # => "abc晦" - s.ascii_only? # => false + s = "abc".force_encoding(Encoding::UTF_8) # => "abc" + s.ascii_only? # => true + s = "abc\u{6666}".force_encoding(Encoding::UTF_8) # => "abc晦" + s.ascii_only? # => false - s = "\xc2\xa1".force_encoding("UTF-8") # => "¡" - s.valid_encoding? # => true - s = "\xc2".force_encoding("UTF-8") # => "\xC2" - s.valid_encoding? # => false + s = "\xc2\xa1".force_encoding(Encoding::UTF_8) # => "¡" + s.valid_encoding? # => true + s = "\xc2".force_encoding(Encoding::UTF_8) # => "\xC2" + s.valid_encoding? # => false -=== \Symbol and \Regexp Encodings +== \Symbol and \Regexp Encodings The string stored in a Symbol or Regexp object also has an encoding; the encoding may be retrieved by method Symbol#encoding or Regexp#encoding. @@ -194,20 +195,20 @@ The default encoding for these, however, is: - The script encoding, otherwise; see (Script Encoding)[rdoc-ref:encodings.rdoc@Script+Encoding]. -=== Filesystem \Encoding +== Filesystem \Encoding The filesystem encoding is the default \Encoding for a string from the filesystem: Encoding.find("filesystem") # => # -=== Locale \Encoding +== Locale \Encoding The locale encoding is the default encoding for a string from the environment, other than from the filesystem: Encoding.find('locale') # => # -=== Stream Encodings +== Stream Encodings Certain stream objects can have two encodings; these objects include instances of: @@ -222,7 +223,7 @@ The two encodings are: - An _internal_ _encoding_, which (if not +nil+) specifies the encoding to be used for the string constructed from the stream. -==== External \Encoding +=== External \Encoding The external encoding, which is an \Encoding object, specifies how bytes read from the stream are to be interpreted as characters. @@ -248,9 +249,9 @@ For an \IO or \File object, the external encoding may be set by: For an \IO, \File, \ARGF, or \StringIO object, the external encoding may be set by: -- \Methods +set_encoding+ or (except for \ARGF) +set_encoding_by_bom+. +- Methods +set_encoding+ or (except for \ARGF) +set_encoding_by_bom+. -==== Internal \Encoding +=== Internal \Encoding The internal encoding, which is an \Encoding object or +nil+, specifies how characters read from the stream @@ -274,9 +275,9 @@ For an \IO or \File object, the internal encoding may be set by: For an \IO, \File, \ARGF, or \StringIO object, the internal encoding may be set by: -- \Method +set_encoding+. +- Method +set_encoding+. -=== Script \Encoding +== Script \Encoding A Ruby script has a script encoding, which may be retrieved by: @@ -291,7 +292,7 @@ followed by a colon, space and the Encoding name or alias: # encoding: ISO-8859-1 __ENCODING__ #=> # -=== Transcoding +== Transcoding _Transcoding_ is the process of changing a sequence of characters from one encoding to another. @@ -302,7 +303,7 @@ but the bytes that represent them may change. The handling for characters that cannot be represented in the destination encoding may be specified by @Encoding+Options. -==== Transcoding a \String +=== Transcoding a \String Each of these methods transcodes a string: @@ -317,7 +318,7 @@ Each of these methods transcodes a string: - String#unicode_normalize!: Like String#unicode_normalize, but transcodes +self+ in place. -=== Transcoding a Stream +== Transcoding a Stream Each of these methods may transcode a stream; whether it does so depends on the external and internal encodings: @@ -336,8 +337,8 @@ then reads the file into a new string, encoding it as UTF-8: s = "R\u00E9sum\u00E9" path = 't.tmp' - ext_enc = 'ISO-8859-1' - int_enc = 'UTF-8' + ext_enc = Encoding::ISO_8859_1 + int_enc = Encoding::UTF_8 File.write(path, s, external_encoding: ext_enc) raw_text = File.binread(path) @@ -352,7 +353,7 @@ Output: "R\xE9sum\xE9" "Résumé" -=== \Encoding Options +== \Encoding Options A number of methods in the Ruby core accept keyword arguments as encoding options. @@ -372,8 +373,8 @@ These keyword-value pairs specify encoding options: Examples: s = "\x80foo\x80" - s.encode('ISO-8859-3') # Raises Encoding::InvalidByteSequenceError. - s.encode('ISO-8859-3', invalid: :replace) # => "?foo?" + s.encode(Encoding::ISO_8859_3) # Raises Encoding::InvalidByteSequenceError. + s.encode(Encoding::ISO_8859_3, invalid: :replace) # => "?foo?" - For an undefined character: @@ -384,8 +385,8 @@ These keyword-value pairs specify encoding options: Examples: s = "\x80foo\x80" - "\x80".encode('UTF-8', 'ASCII-8BIT') # Raises Encoding::UndefinedConversionError. - s.encode('UTF-8', 'ASCII-8BIT', undef: :replace) # => "�foo�" + "\x80".encode(Encoding::UTF_8, Encoding::BINARY) # Raises Encoding::UndefinedConversionError. + s.encode(Encoding::UTF_8, Encoding::BINARY, undef: :replace) # => "�foo�" - Replacement string: @@ -399,7 +400,7 @@ These keyword-value pairs specify encoding options: s = "\xA5foo\xA5" options = {:undef => :replace, :replace => 'xyzzy'} - s.encode('UTF-8', 'ISO-8859-3', **options) # => "xyzzyfooxyzzy" + s.encode(Encoding::UTF_8, Encoding::ISO_8859_3, **options) # => "xyzzyfooxyzzy" - Replacement fallback: @@ -419,12 +420,12 @@ These keyword-value pairs specify encoding options: hash = {"\u3042" => 'xyzzy'} hash.default = 'XYZZY' - s.encode('ASCII', fallback: h) # => "xyzzyfooXYZZY" + s.encode(Encoding::US_ASCII, fallback: hash) # => "xyzzyfooXYZZY" def (fallback = "U+%.4X").escape(x) self % x.unpack("U") end - "\u{3042}".encode("US-ASCII", fallback: fallback.method(:escape)) # => "U+3042" + "\u{3042}".encode(Encoding::US_ASCII, fallback: fallback.method(:escape)) # => "U+3042" proc = Proc.new {|x| x == "\u3042" ? 'xyzzy' : 'XYZZY' } s.encode('ASCII', fallback: proc) # => "XYZZYfooXYZZY" @@ -457,8 +458,8 @@ These keyword-value pairs specify encoding options: Examples: s = 'foo"<&>"bar' + "\u3042" - s.encode('ASCII', xml: :text) # => "foo\"<&>\"barあ" - s.encode('ASCII', xml: :attr) # => "\"foo"<&>"barあ\"" + s.encode(Encoding::US_ASCII, xml: :text) # => "foo\"<&>\"barあ" + s.encode(Encoding::US_ASCII, xml: :attr) # => "\"foo"<&>"barあ\"" - Newlines: @@ -475,7 +476,7 @@ These keyword-value pairs specify encoding options: Examples: - s = "\n \r \r\n" # => "\n \r \r\n" - s.encode('ASCII', cr_newline: true) # => "\r \r \r\r" - s.encode('ASCII', crlf_newline: true) # => "\r\n \r \r\r\n" - s.encode('ASCII', universal_newline: true) # => "\n \n \n" + s = "\n \r \r\n" # => "\n \r \r\n" + s.encode(Encoding::US_ASCII, cr_newline: true) # => "\r \r \r\r" + s.encode(Encoding::US_ASCII, crlf_newline: true) # => "\r\n \r \r\r\n" + s.encode(Encoding::US_ASCII, universal_newline: true) # => "\n \n \n" diff --git a/doc/exceptions.md b/doc/exceptions.md new file mode 100644 index 00000000000000..2c47455911376f --- /dev/null +++ b/doc/exceptions.md @@ -0,0 +1,521 @@ +# Exceptions + +Ruby code can raise exceptions. + +Most often, a raised exception is meant to alert the running program +that an unusual (i.e., _exceptional_) situation has arisen, +and may need to be handled. + +Code throughout the Ruby core, Ruby standard library, and Ruby gems generates exceptions +in certain circumstances: + +```rb +File.open('nope.txt') # Raises Errno::ENOENT: "No such file or directory" +``` + +## Raised Exceptions + +A raised exception transfers program execution, one way or another. + +### Unrescued Exceptions + +If an exception not _rescued_ +(see [Rescued Exceptions](#label-Rescued+Exceptions) below), +execution transfers to code in the Ruby interpreter +that prints a message and exits the program (or thread): + +```console +$ ruby -e "raise" +-e:1:in '
': unhandled exception +``` + +### Rescued Exceptions + +An exception handler may determine what is to happen +when an exception is raised; +the handler may _rescue_ an exception, +and may prevent the program from exiting. + +A simple example: + +```rb +begin + raise 'Boom!' # Raises an exception, transfers control. + puts 'Will not get here.' +rescue + puts 'Rescued an exception.' # Control transferred to here; program does not exit. +end +puts 'Got here.' +``` + +Output: + +``` +Rescued an exception. +Got here. +``` + +An exception handler has several elements: + +| Element | Use | +|-----------------------------|------------------------------------------------------------------------------------------| +| Begin clause. | Begins the handler and contains the code whose raised exception, if any, may be rescued. | +| One or more rescue clauses. | Each contains "rescuing" code, which is to be executed for certain exceptions. | +| Else clause (optional). | Contains code to be executed if no exception is raised. | +| Ensure clause (optional). | Contains code to be executed whether or not an exception is raised, or is rescued. | +| end statement. | Ends the handler. ` | + +#### Begin Clause + +The begin clause begins the exception handler: + +- May start with a `begin` statement; + see also [Begin-Less Exception Handlers](#label-Begin-Less+Exception+Handlers). +- Contains code whose raised exception (if any) is covered + by the handler. +- Ends with the first following `rescue` statement. + +#### Rescue Clauses + +A rescue clause: + +- Starts with a `rescue` statement. +- Contains code that is to be executed for certain raised exceptions. +- Ends with the first following `rescue`, + `else`, `ensure`, or `end` statement. + +##### Rescued Exceptions + +A `rescue` statement may include one or more classes +that are to be rescued; +if none is given, StandardError is assumed. + +The rescue clause rescues both the specified class +(or StandardError if none given) or any of its subclasses; +see [Built-In Exception Class Hierarchy](rdoc-ref:Exception@Built-In+Exception+Class+Hierarchy). + +```rb +begin + 1 / 0 # Raises ZeroDivisionError, a subclass of StandardError. +rescue + puts "Rescued #{$!.class}" +end +``` + +Output: + +``` +Rescued ZeroDivisionError +``` + +If the `rescue` statement specifies an exception class, +only that class (or one of its subclasses) is rescued; +this example exits with a ZeroDivisionError, +which was not rescued because it is not ArgumentError or one of its subclasses: + +```rb +begin + 1 / 0 +rescue ArgumentError + puts "Rescued #{$!.class}" +end +``` + +A `rescue` statement may specify multiple classes, +which means that its code rescues an exception +of any of the given classes (or their subclasses): + +```rb +begin + 1 / 0 +rescue FloatDomainError, ZeroDivisionError + puts "Rescued #{$!.class}" +end +``` + +##### Multiple Rescue Clauses + +An exception handler may contain multiple rescue clauses; +in that case, the first clause that rescues the exception does so, +and those before and after are ignored: + +```rb +begin + Dir.open('nosuch') +rescue Errno::ENOTDIR + puts "Rescued #{$!.class}" +rescue Errno::ENOENT + puts "Rescued #{$!.class}" +end +``` + +Output: + +``` +Rescued Errno::ENOENT +``` + +##### Capturing the Rescued \Exception + +A `rescue` statement may specify a variable +whose value becomes the rescued exception +(an instance of Exception or one of its subclasses: + +```rb +begin + 1 / 0 +rescue => x + puts x.class + puts x.message +end +``` + +Output: + +``` +ZeroDivisionError +divided by 0 +``` + +##### Global Variables + +Two read-only global variables always have `nil` value +except in a rescue clause; +they're: + +- `$!`: contains the rescued exception. +- `$@`: contains its backtrace. + +Example: + +```rb +begin + 1 / 0 +rescue + p $! + p $@ +end +``` + +Output: + +``` +# +["t.rb:2:in 'Integer#/'", "t.rb:2:in '
'"] +``` + +##### Cause + +In a rescue clause, the method Exception#cause returns the previous value of `$!`, +which may be `nil`; +elsewhere, the method returns `nil`. + +Example: + +```rb +begin + raise('Boom 0') +rescue => x0 + puts "Exception: #{x0.inspect}; $!: #{$!.inspect}; cause: #{x0.cause.inspect}." + begin + raise('Boom 1') + rescue => x1 + puts "Exception: #{x1.inspect}; $!: #{$!.inspect}; cause: #{x1.cause.inspect}." + begin + raise('Boom 2') + rescue => x2 + puts "Exception: #{x2.inspect}; $!: #{$!.inspect}; cause: #{x2.cause.inspect}." + end + end +end +``` + +Output: + +``` +Exception: #; $!: #; cause: nil. +Exception: #; $!: #; cause: #. +Exception: #; $!: #; cause: #. +``` + +#### Else Clause + +The `else` clause: + +- Starts with an `else` statement. +- Contains code that is to be executed if no exception is raised in the begin clause. +- Ends with the first following `ensure` or `end` statement. + +```rb +begin + puts 'Begin.' +rescue + puts 'Rescued an exception!' +else + puts 'No exception raised.' +end +``` + +Output: + +``` +Begin. +No exception raised. +``` + +#### Ensure Clause + +The ensure clause: + +- Starts with an `ensure` statement. +- Contains code that is to be executed + regardless of whether an exception is raised, + and regardless of whether a raised exception is handled. +- Ends with the first following `end` statement. + +```rb +def foo(boom: false) + puts 'Begin.' + raise 'Boom!' if boom +rescue + puts 'Rescued an exception!' +else + puts 'No exception raised.' +ensure + puts 'Always do this.' +end + +foo(boom: true) +foo(boom: false) +``` + +Output: + +``` +Begin. +Rescued an exception! +Always do this. +Begin. +No exception raised. +Always do this. +``` + +#### End Statement + +The `end` statement ends the handler. + +Code following it is reached only if any raised exception is rescued. + +#### Begin-Less \Exception Handlers + +As seen above, an exception handler may be implemented with `begin` and `end`. + +An exception handler may also be implemented as: + +- A method body: + + ```rb + def foo(boom: false) # Serves as beginning of exception handler. + puts 'Begin.' + raise 'Boom!' if boom + rescue + puts 'Rescued an exception!' + else + puts 'No exception raised.' + end # Serves as end of exception handler. + ``` + +- A block: + + ```rb + Dir.chdir('.') do |dir| # Serves as beginning of exception handler. + raise 'Boom!' + rescue + puts 'Rescued an exception!' + end # Serves as end of exception handler. + ``` + +#### Re-Raising an \Exception + +It can be useful to rescue an exception, but allow its eventual effect; +for example, a program can rescue an exception, log data about it, +and then "reinstate" the exception. + +This may be done via the `raise` method, but in a special way; +a rescuing clause: + + - Captures an exception. + - Does whatever is needed concerning the exception (such as logging it). + - Calls method `raise` with no argument, + which raises the rescued exception: + +```rb +begin + 1 / 0 +rescue ZeroDivisionError + # Do needful things (like logging). + raise # Raised exception will be ZeroDivisionError, not RuntimeError. +end +``` + +Output: + +``` +ruby t.rb +t.rb:2:in 'Integer#/': divided by 0 (ZeroDivisionError) + from t.rb:2:in '
' +``` + +#### Retrying + +It can be useful to retry a begin clause; +for example, if it must access a possibly-volatile resource +(such as a web page), +it can be useful to try the access more than once +(in the hope that it may become available): + +```rb +retries = 0 +begin + puts "Try ##{retries}." + raise 'Boom' +rescue + puts "Rescued retry ##{retries}." + if (retries += 1) < 3 + puts 'Retrying' + retry + else + puts 'Giving up.' + raise + end +end +``` + +``` +Try #0. +Rescued retry #0. +Retrying +Try #1. +Rescued retry #1. +Retrying +Try #2. +Rescued retry #2. +Giving up. +# RuntimeError ('Boom') raised. +``` + +Note that the retry re-executes the entire begin clause, +not just the part after the point of failure. + +## Raising an \Exception + +Method Kernel#raise raises an exception. + +## Custom Exceptions + +To provide additional or alternate information, +you may create custom exception classes. +Each should be a subclass of one of the built-in exception classes +(commonly StandardError or RuntimeError); +see [Built-In Exception Class Hierarchy](rdoc-ref:Exception@Built-In+Exception+Class+Hierarchy). + +```rb +class MyException < StandardError; end +``` + +## Messages + +Every `Exception` object has a message, +which is a string that is set at the time the object is created; +see Exception.new. + +The message cannot be changed, but you can create a similar object with a different message; +see Exception#exception. + +This method returns the message as defined: + +- Exception#message. + +Two other methods return enhanced versions of the message: + +- Exception#detailed_message: adds exception class name, with optional highlighting. +- Exception#full_message: adds exception class name and backtrace, with optional highlighting. + +Each of the two methods above accepts keyword argument `highlight`; +if the value of keyword `highlight` is `true`, +the returned string includes bolding and underlining ANSI codes (see below) +to enhance the appearance of the message. + +Any exception class (Ruby or custom) may choose to override either of these methods, +and may choose to interpret keyword argument highlight: true +to mean that the returned message should contain +[ANSI codes](https://en.wikipedia.org/wiki/ANSI_escape_code) +that specify color, bolding, and underlining. + +Because the enhanced message may be written to a non-terminal device +(e.g., into an HTML page), +it is best to limit the ANSI codes to these widely-supported codes: + +- Begin font color: + + | Color | ANSI Code | + |---------|------------------| + | Red | \\e[31m | + | Green | \\e[32m | + | Yellow | \\e[33m | + | Blue | \\e[34m | + | Magenta | \\e[35m | + | Cyan | \\e[36m | + +
+ +- Begin font attribute: + + | Attribute | ANSI Code | + |-----------|-----------------| + | Bold | \\e[1m | + | Underline | \\e[4m | + +
+ +- End all of the above: + + | Color | ANSI Code | + |-------|-----------------| + | Reset | \\e[0m | + +It's also best to craft a message that is conveniently human-readable, +even if the ANSI codes are included "as-is" +(rather than interpreted as font directives). + +## Backtraces + +A _backtrace_ is a record of the methods currently +in the [call stack](https://en.wikipedia.org/wiki/Call_stack); +each such method has been called, but has not yet returned. + +These methods return backtrace information: + +- Exception#backtrace: returns the backtrace as an array of strings or `nil`. +- Exception#backtrace_locations: returns the backtrace as an array + of Thread::Backtrace::Location objects or `nil`. + Each Thread::Backtrace::Location object gives detailed information about a called method. + +By default, Ruby sets the backtrace of the exception to the location where it +was raised. + +The developer might adjust this by either providing +backtrace+ argument +to Kernel#raise, or using Exception#set_backtrace. + +Note that: + +- by default, both +backtrace+ and +backtrace_locations+ represent the same backtrace; +- if the developer sets the backtrace by one of the above methods to an array of + Thread::Backtrace::Location, they still represent the same backtrace; +- if the developer sets the backtrace to a string or an array of strings: + - by Kernel#raise: +backtrace_locations+ become +nil+; + - by Exception#set_backtrace: +backtrace_locations+ preserve the original + value; +- if the developer sets the backtrace to +nil+ by Exception#set_backtrace, + +backtrace_locations+ preserve the original value; but if the exception is then + reraised, both +backtrace+ and +backtrace_locations+ become the location of reraise. diff --git a/doc/extension.ja.rdoc b/doc/extension.ja.rdoc index bde907c9168b9f..2f7856f3d439df 100644 --- a/doc/extension.ja.rdoc +++ b/doc/extension.ja.rdoc @@ -780,9 +780,14 @@ RUBY_TYPED_WB_PROTECTED :: メソッドの実装に適切にライトバリアを挿入する責任があります. さもなくばRubyは実行時にクラッシュする可能性があります. - ライトバリアについてはdoc/extension.ja.rdocのAppendix D - "世代別GC"も参照してください. + ライトバリアについては{世代別 + GC}[rdoc-ref:@Appendix+D.+-E4-B8-96-E4-BB-A3-E5-88-A5GC] + も参照してください. +このマクロは例外を発生させる可能性があることに注意してくださ +い. ラップされる sval が,解放する必要があるリソース (割り +当てられたメモリ,外部ライブラリからのハンドルなど) を保持し +ている場合は,rb_protect を使用する必要があります. Cの構造体の割当と対応するオブジェクトの生成を同時に行うマク ロとして以下のものが提供されています. @@ -1731,7 +1736,7 @@ have_func(func, header) :: ックする.funcが標準ではリンクされないライブラリ内のもので ある時には先にhave_libraryでそのライブラリをチェックしてお く事.チェックに成功すると,プリプロセッサマクロ - `HAVE_{FUNC}` を定義し,trueを返す. + HAVE_{FUNC} を定義し,trueを返す. have_var(var, header) :: @@ -1739,44 +1744,44 @@ have_var(var, header) :: クする.varが標準ではリンクされないライブラリ内のものであ る時には先にhave_libraryでそのライブラリをチェックしておく 事.チェックに成功すると,プリプロセッサマクロ - `HAVE_{VAR}` を定義し,trueを返す. + HAVE_{VAR} を定義し,trueを返す. have_header(header) :: ヘッダファイルの存在をチェックする.チェックに成功すると, - プリプロセッサマクロ `HAVE_{HEADER_H}` を定義し,trueを返す. + プリプロセッサマクロ HAVE_{HEADER_H} を定義し,trueを返す. (スラッシュやドットはアンダースコアに置換される) find_header(header, path...) :: ヘッダファイルheaderの存在を -Ipath を追加しながらチェック する.チェックに成功すると,プリプロセッサマクロ - `HAVE_{HEADER_H}` を定義し,trueを返す. + HAVE_{HEADER_H} を定義し,trueを返す. (スラッシュやドットはアンダースコアに置換される) have_struct_member(type, member[, header[, opt]]) :: ヘッダファイルheaderをインクルードして型typeが定義され, なおかつメンバmemberが存在するかをチェックする.チェックに - 成功すると,プリプロセッサマクロ `HAVE_{TYPE}_{MEMBER}` を + 成功すると,プリプロセッサマクロ HAVE_{TYPE}_{MEMBER} を 定義し,trueを返す. have_type(type, header, opt) :: ヘッダファイルheaderをインクルードして型typeが存在するかを チェックする.チェックに成功すると,プリプロセッサマクロ - `HAVE_TYPE_{TYPE}` を定義し,trueを返す. + HAVE_TYPE_{TYPE} を定義し,trueを返す. check_sizeof(type, header) :: ヘッダファイルheaderをインクルードして型typeのchar単位サイ ズを調べる.チェックに成功すると,プリプロセッサマクロ - `SIZEOF_{TYPE}` を定義し,そのサイズを返す.定義されていな + SIZEOF_{TYPE} を定義し,そのサイズを返す.定義されていな いときはnilを返す. -append_cppflags(array-of-flags[, opt]) -append_cflags(array-of-flags[, opt]) -append_ldflags(array-of-flags[, opt]) +append_cppflags(array-of-flags[, opt]) :: +append_cflags(array-of-flags[, opt]) :: +append_ldflags(array-of-flags[, opt]) :: 各flagが使用可能であれば,それぞれ$CPPFLAGS, $CFLAGS, $LDFLAGSに追加する.コンパイラのフラグには移植性がないので, @@ -1850,8 +1855,9 @@ RGenGCは,過去の拡張ライブラリに(ほぼ)互換性を保つよ スするようなコードは書かないようにして下さい.代わりに,rb_ary_aref(), rb_ary_store() などの,適切な API 関数を利用するようにして下さい. -そのほか,対応についての詳細は extension.rdoc の「Appendix D. Generational -GC」を参照して下さい. +そのほか,対応についての詳細は {Appendix D. Generational +GC}[rdoc-ref:extension.rdoc@Appendix+D.+Generational+GC]を参 +照して下さい. == Appendix E. Ractor サポート @@ -1860,10 +1866,12 @@ Ruby 3.0 から、Ruby プログラムを並列に実行するための仕組み なります。サポートしていないライブラリは、メイン Ractor 以外で実行すると エラーになります(Ractor::UnsafeError)。 -Ractor をサポートするための詳細は、extension.rdoc の「Appendix F. Ractor -support」を参照してください。 +Ractor をサポートするための詳細は、{Appendix F. Ractor +support}[rdoc-ref:extension.rdoc@Appendix+F.+Ractor+support] +を参照してください。 - -:enddoc: Local variables: -:enddoc: fill-column: 60 -:enddoc: end: +-- +Local variables: +fill-column: 60 +end: +++ diff --git a/doc/extension.rdoc b/doc/extension.rdoc index 50892725999ae8..ba59d107ab4c84 100644 --- a/doc/extension.rdoc +++ b/doc/extension.rdoc @@ -747,18 +747,24 @@ RUBY_TYPED_WB_PROTECTED :: barriers in all implementations of methods of that object as appropriate. Otherwise Ruby might crash while running. - More about write barriers can be found in "Generational GC" in - Appendix D. + More about write barriers can be found in {Generational + GC}[rdoc-ref:@Appendix+D.+Generational+GC]. RUBY_TYPED_FROZEN_SHAREABLE :: - This flag indicates that the object is shareable object - if the object is frozen. See Appendix F more details. + This flag indicates that the object is shareable object if the object + is frozen. See {Ractor support}[rdoc-ref:@Appendix+F.+Ractor+support] + more details. If this flag is not set, the object can not become a shareable object by Ractor.make_shareable() method. -You can allocate and wrap the structure in one step. +Note that this macro can raise an exception. If sval to be wrapped +holds a resource needs to be released (e.g., allocated memory, handle +from an external library, and etc), you will have to use rb_protect. + +You can allocate and wrap the structure in one step, in more +preferable manner. TypedData_Make_Struct(klass, type, data_type, sval) @@ -767,6 +773,10 @@ the structure, which is also allocated. This macro works like: (sval = ZALLOC(type), TypedData_Wrap_Struct(klass, data_type, sval)) +However, you should use this macro instead of "allocation then wrap" +like the above code if it is simply allocated, because the latter can +raise a NoMemoryError and sval will be memory leaked in that case. + Arguments klass and data_type work like their counterparts in TypedData_Wrap_Struct(). A pointer to the allocated structure will be assigned to sval, which should be a pointer of the type specified. @@ -779,26 +789,26 @@ approach to marking and reference updating is provided, by declaring offset references to the VALUES in your struct. Doing this allows the Ruby GC to support marking these references and GC -compaction without the need to define the `dmark` and `dcompact` callbacks. +compaction without the need to define the +dmark+ and +dcompact+ callbacks. You must define a static list of VALUE pointers to the offsets within your struct where the references are located, and set the "data" member to point to -this reference list. The reference list must end with `END_REFS` +this reference list. The reference list must end with +RUBY_END_REFS+. Some Macros have been provided to make edge referencing easier: -* RUBY_TYPED_DECL_MARKING =A flag that can be set on the `ruby_data_type_t` to indicate that references are being declared as edges. +* RUBY_TYPED_DECL_MARKING =A flag that can be set on the +ruby_data_type_t+ to indicate that references are being declared as edges. -* RUBY_REFERENCES_START(ref_list_name) - Define `ref_list_name` as a list of references +* RUBY_REFERENCES(ref_list_name) - Define _ref_list_name_ as a list of references -* RUBY_REFERENCES_END - Mark the end of the references list. This will take care of terminating the list correctly +* RUBY_REF_END - The end mark of the references list. -* RUBY_REF_EDGE\(struct, member\) - Declare `member` as a VALUE edge from `struct`. Use this after `RUBY_REFERENCES_START` +* RUBY_REF_EDGE(struct, member) - Declare _member_ as a VALUE edge from _struct_. Use this after +RUBY_REFERENCES_START+ -* +REFS_LIST_PTR+ - Coerce the reference list into a format that can be - accepted by the existing `dmark` interface. +* +RUBY_REFS_LIST_PTR+ - Coerce the reference list into a format that can be + accepted by the existing +dmark+ interface. -The example below is from `Dir` (defined in `dir.c`) +The example below is from Dir (defined in +dir.c+) // The struct being wrapped. Notice this contains 3 members of which the second // is a VALUE reference to another ruby object. @@ -808,18 +818,19 @@ The example below is from `Dir` (defined in `dir.c`) rb_encoding *enc; } - // Define a reference list `dir_refs` containing a single entry to `path`, and - // terminating with RUBY_REF_END - RUBY_REFERENCES_START(dir_refs) - REF_EDGE(dir_data, path), - RUBY_REFERENCES_END + // Define a reference list `dir_refs` containing a single entry to `path`. + // Needs terminating with RUBY_REF_END + RUBY_REFERENCES(dir_refs) = { + RUBY_REF_EDGE(dir_data, path), + RUBY_REF_END + }; // Override the "dmark" field with the defined reference list now that we // no longer need a marking callback and add RUBY_TYPED_DECL_MARKING to the // flags field static const rb_data_type_t dir_data_type = { "dir", - {REFS_LIST_PTR(dir_refs), dir_free, dir_memsize,}, + {RUBY_REFS_LIST_PTR(dir_refs), dir_free, dir_memsize,}, 0, NULL, RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_DECL_MARKING }; @@ -2208,70 +2219,72 @@ Ractor safety around C extensions has the following properties: To make a "Ractor-safe" C extension, we need to check the following points: -(1) Do not share unshareable objects between ractors +1. Do not share unshareable objects between ractors -For example, C's global variable can lead sharing an unshareable objects -between ractors. + For example, C's global variable can lead sharing an unshareable objects + between ractors. - VALUE g_var; - VALUE set(VALUE self, VALUE v){ return g_var = v; } - VALUE get(VALUE self){ return g_var; } + VALUE g_var; + VALUE set(VALUE self, VALUE v){ return g_var = v; } + VALUE get(VALUE self){ return g_var; } -set() and get() pair can share an unshareable objects using g_var, and -it is Ractor-unsafe. + set() and get() pair can share an unshareable objects using g_var, and + it is Ractor-unsafe. -Not only using global variables directly, some indirect data structure -such as global st_table can share the objects, so please take care. + Not only using global variables directly, some indirect data structure + such as global st_table can share the objects, so please take care. -Note that class and module objects are shareable objects, so you can -keep the code "cFoo = rb_define_class(...)" with C's global variables. + Note that class and module objects are shareable objects, so you can + keep the code "cFoo = rb_define_class(...)" with C's global variables. -(2) Check the thread-safety of the extension +2. Check the thread-safety of the extension -An extension should be thread-safe. For example, the following code is -not thread-safe: + An extension should be thread-safe. For example, the following code is + not thread-safe: - bool g_called = false; - VALUE call(VALUE self) { - if (g_called) rb_raise("recursive call is not allowed."); - g_called = true; - VALUE ret = do_something(); - g_called = false; - return ret; - } + bool g_called = false; + VALUE call(VALUE self) { + if (g_called) rb_raise("recursive call is not allowed."); + g_called = true; + VALUE ret = do_something(); + g_called = false; + return ret; + } -because g_called global variable should be synchronized by other -ractor's threads. To avoid such data-race, some synchronization should -be used. Check include/ruby/thread_native.h and include/ruby/atomic.h. + because g_called global variable should be synchronized by other + ractor's threads. To avoid such data-race, some synchronization should + be used. Check include/ruby/thread_native.h and include/ruby/atomic.h. -With Ractors, all objects given as method parameters and the receiver (self) -are guaranteed to be from the current Ractor or to be shareable. As a -consequence, it is easier to make code ractor-safe than to make code generally -thread-safe. For example, we don't need to lock an array object to access the -element of it. + With Ractors, all objects given as method parameters and the receiver (self) + are guaranteed to be from the current Ractor or to be shareable. As a + consequence, it is easier to make code ractor-safe than to make code generally + thread-safe. For example, we don't need to lock an array object to access the + element of it. -(3) Check the thread-safety of any used library +3. Check the thread-safety of any used library -If the extension relies on an external library, such as a function foo() from -a library libfoo, the function libfoo foo() should be thread safe. + If the extension relies on an external library, such as a function foo() from + a library libfoo, the function libfoo foo() should be thread safe. -(4) Make an object shareable +4. Make an object shareable -This is not required to make an extension Ractor-safe. + This is not required to make an extension Ractor-safe. -If an extension provides special objects defined by rb_data_type_t, -consider these objects can become shareable or not. + If an extension provides special objects defined by rb_data_type_t, + consider these objects can become shareable or not. -RUBY_TYPED_FROZEN_SHAREABLE flag indicates that these objects can be -shareable objects if the object is frozen. This means that if the object -is frozen, the mutation of wrapped data is not allowed. + RUBY_TYPED_FROZEN_SHAREABLE flag indicates that these objects can be + shareable objects if the object is frozen. This means that if the object + is frozen, the mutation of wrapped data is not allowed. -(5) Others +5. Others -There are possibly other points or requirements which must be considered in the -making of a Ractor-safe extension. This document will be extended as they are -discovered. + There are possibly other points or requirements which must be considered in the + making of a Ractor-safe extension. This document will be extended as they are + discovered. -:enddoc: Local variables: -:enddoc: fill-column: 70 -:enddoc: end: +-- +Local variables: +fill-column: 70 +end: +++ diff --git a/doc/fiber.md b/doc/fiber.md index a334faf7396187..d9011cce2f2bbd 100644 --- a/doc/fiber.md +++ b/doc/fiber.md @@ -6,7 +6,7 @@ Fibers provide a mechanism for cooperative concurrency. Fibers execute a user-provided block. During the execution, the block may call `Fiber.yield` or `Fiber.transfer` to switch to another fiber. `Fiber#resume` is used to continue execution from the point where `Fiber.yield` was called. -``` ruby +```rb #!/usr/bin/env ruby puts "1: Start program." @@ -38,13 +38,13 @@ instrumentation. To set the scheduler for the current thread: -``` ruby +```rb Fiber.set_scheduler(MyScheduler.new) ``` When the thread exits, there is an implicit call to `set_scheduler`: -``` ruby +```rb Fiber.set_scheduler(nil) ``` @@ -60,7 +60,7 @@ no changes. This is the interface you need to implement. -``` ruby +```rb class Scheduler # Wait for the specified process ID to exit. # This hook is optional. @@ -166,7 +166,7 @@ program. Fibers can be used to create non-blocking execution contexts. -``` ruby +```rb Fiber.new do puts Fiber.current.blocking? # false @@ -184,7 +184,7 @@ end.resume We also introduce a new method which simplifies the creation of these non-blocking fibers: -``` ruby +```rb Fiber.schedule do puts Fiber.current.blocking? # false end @@ -196,7 +196,7 @@ fibers. You can also create blocking execution contexts: -``` ruby +```rb Fiber.new(blocking: true) do # Won't use the scheduler: sleep(n) @@ -212,6 +212,64 @@ I/O. Windows is a notable example where socket I/O can be non-blocking but pipe I/O is blocking. Provided that there *is* a scheduler and the current thread *is non-blocking*, the operation will invoke the scheduler. +##### `IO#close` + +Closing an IO interrupts all blocking operations on that IO. When a thread calls `IO#close`, it first attempts to interrupt any threads or fibers that are blocked on that IO. The closing thread waits until all blocked threads and fibers have been properly interrupted and removed from the IO's blocking list. Each interrupted thread or fiber receives an `IOError` and is cleanly removed from the blocking operation. Only after all blocking operations have been interrupted and cleaned up will the actual file descriptor be closed, ensuring proper resource cleanup and preventing potential race conditions. + +For fibers managed by a scheduler, the interruption process involves calling `rb_fiber_scheduler_fiber_interrupt` on the scheduler. This allows the scheduler to handle the interruption in a way that's appropriate for its event loop implementation. The scheduler can then notify the fiber, which will receive an `IOError` and be removed from the blocking operation. This mechanism ensures that fiber-based concurrency works correctly with IO operations, even when those operations are interrupted by `IO#close`. + +```mermaid +sequenceDiagram + participant ThreadB + participant ThreadA + participant Scheduler + participant IO + participant Fiber1 + participant Fiber2 + + Note over ThreadA: Thread A has a fiber scheduler + activate Scheduler + ThreadA->>Fiber1: Schedule Fiber 1 + activate Fiber1 + Fiber1->>IO: IO.read + IO->>Scheduler: rb_thread_io_blocking_region + deactivate Fiber1 + + ThreadA->>Fiber2: Schedule Fiber 2 + activate Fiber2 + Fiber2->>IO: IO.read + IO->>Scheduler: rb_thread_io_blocking_region + deactivate Fiber2 + + Note over Fiber1,Fiber2: Both fibers blocked on same IO + + Note over ThreadB: IO.close + activate ThreadB + ThreadB->>IO: thread_io_close_notify_all + Note over ThreadB: rb_mutex_sleep + + IO->>Scheduler: rb_fiber_scheduler_fiber_interrupt(Fiber1) + Scheduler->>Fiber1: fiber_interrupt with IOError + activate Fiber1 + Note over IO: fiber_interrupt causes removal from blocking list + Fiber1->>IO: rb_io_blocking_operation_exit() + IO-->>ThreadB: Wakeup thread + deactivate Fiber1 + + IO->>Scheduler: rb_fiber_scheduler_fiber_interrupt(Fiber2) + Scheduler->>Fiber2: fiber_interrupt with IOError + activate Fiber2 + Note over IO: fiber_interrupt causes removal from blocking list + Fiber2->>IO: rb_io_blocking_operation_exit() + IO-->>ThreadB: Wakeup thread + deactivate Fiber2 + deactivate Scheduler + + Note over ThreadB: Blocking operations list empty + ThreadB->>IO: close(fd) + deactivate ThreadB +``` + #### Mutex The `Mutex` class can be used in a non-blocking context and is fiber specific. diff --git a/doc/format_specifications.rdoc b/doc/format_specifications.rdoc index e589524f279365..bdfdc249536b36 100644 --- a/doc/format_specifications.rdoc +++ b/doc/format_specifications.rdoc @@ -1,4 +1,4 @@ -== Format Specifications += Format Specifications Several Ruby core classes have instance method +printf+ or +sprintf+: @@ -37,12 +37,12 @@ It consists of: Except for the leading percent character, the only required part is the type specifier, so we begin with that. -=== Type Specifiers +== Type Specifiers This section provides a brief explanation of each type specifier. The links lead to the details and examples. -==== \Integer Type Specifiers +=== \Integer Type Specifiers - +b+ or +B+: Format +argument+ as a binary integer. See {Specifiers b and B}[rdoc-ref:format_specifications.rdoc@Specifiers+b+and+B]. @@ -54,7 +54,7 @@ The links lead to the details and examples. - +x+ or +X+: Format +argument+ as a hexadecimal integer. See {Specifiers x and X}[rdoc-ref:format_specifications.rdoc@Specifiers+x+and+X]. -==== Floating-Point Type Specifiers +=== Floating-Point Type Specifiers - +a+ or +A+: Format +argument+ as hexadecimal floating-point number. See {Specifiers a and A}[rdoc-ref:format_specifications.rdoc@Specifiers+a+and+A]. @@ -65,7 +65,7 @@ The links lead to the details and examples. - +g+ or +G+: Format +argument+ in a "general" format. See {Specifiers g and G}[rdoc-ref:format_specifications.rdoc@Specifiers+g+and+G]. -==== Other Type Specifiers +=== Other Type Specifiers - +c+: Format +argument+ as a character. See {Specifier c}[rdoc-ref:format_specifications.rdoc@Specifier+c]. @@ -76,7 +76,7 @@ The links lead to the details and examples. - %: Format +argument+ ('%') as a single percent character. See {Specifier %}[rdoc-ref:format_specifications.rdoc@Specifier+-25]. -=== Flags +== Flags The effect of a flag may vary greatly among type specifiers. These remarks are general in nature. @@ -85,7 +85,7 @@ See {type-specific details}[rdoc-ref:format_specifications.rdoc@Type+Specifier+D Multiple flags may be given with single type specifier; order does not matter. -==== ' ' Flag +=== ' ' Flag Insert a space before a non-negative number: @@ -97,49 +97,49 @@ Insert a minus sign for negative value: sprintf('%d', -10) # => "-10" sprintf('% d', -10) # => "-10" -==== '#' Flag +=== '#' Flag Use an alternate format; varies among types: sprintf('%x', 100) # => "64" sprintf('%#x', 100) # => "0x64" -==== '+' Flag +=== '+' Flag Add a leading plus sign for a non-negative number: sprintf('%x', 100) # => "64" sprintf('%+x', 100) # => "+64" -==== '-' Flag +=== '-' Flag Left justify the value in its field: sprintf('%6d', 100) # => " 100" sprintf('%-6d', 100) # => "100 " -==== '0' Flag +=== '0' Flag Left-pad with zeros instead of spaces: sprintf('%6d', 100) # => " 100" sprintf('%06d', 100) # => "000100" -==== '*' Flag +=== '*' Flag Use the next argument as the field width: sprintf('%d', 20, 14) # => "20" sprintf('%*d', 20, 14) # => " 14" -==== 'n$' Flag +=== 'n$' Flag Format the (1-based) nth argument into this field: sprintf("%s %s", 'world', 'hello') # => "world hello" sprintf("%2$s %1$s", 'world', 'hello') # => "hello world" -=== Width Specifier +== Width Specifier In general, a width specifier determines the minimum width (in characters) of the formatted field: @@ -152,7 +152,7 @@ of the formatted field: # Ignore if too small. sprintf('%1d', 100) # => "100" -=== Precision Specifier +== Precision Specifier A precision specifier is a decimal point followed by zero or more decimal digits. @@ -194,9 +194,9 @@ the number of characters to write: sprintf('%s', Time.now) # => "2022-05-04 11:59:16 -0400" sprintf('%.10s', Time.now) # => "2022-05-04" -=== Type Specifier Details and Examples +== Type Specifier Details and Examples -==== Specifiers +a+ and +A+ +=== Specifiers +a+ and +A+ Format +argument+ as hexadecimal floating-point number: @@ -209,7 +209,7 @@ Format +argument+ as hexadecimal floating-point number: sprintf('%A', 4096) # => "0X1P+12" sprintf('%A', -4096) # => "-0X1P+12" -==== Specifiers +b+ and +B+ +=== Specifiers +b+ and +B+ The two specifiers +b+ and +B+ behave identically except when flag '#'+ is used. @@ -226,14 +226,16 @@ Format +argument+ as a binary integer: sprintf('%#b', 4) # => "0b100" sprintf('%#B', 4) # => "0B100" -==== Specifier +c+ +=== Specifier +c+ Format +argument+ as a single character: sprintf('%c', 'A') # => "A" sprintf('%c', 65) # => "A" -==== Specifier +d+ +This behaves like String#<<, except for raising ArgumentError instead of RangeError. + +=== Specifier +d+ Format +argument+ as a decimal integer: @@ -242,7 +244,7 @@ Format +argument+ as a decimal integer: Flag '#' does not apply. -==== Specifiers +e+ and +E+ +=== Specifiers +e+ and +E+ Format +argument+ in {scientific notation}[https://en.wikipedia.org/wiki/Scientific_notation]: @@ -250,7 +252,7 @@ Format +argument+ in sprintf('%e', 3.14159) # => "3.141590e+00" sprintf('%E', -3.14159) # => "-3.141590E+00" -==== Specifier +f+ +=== Specifier +f+ Format +argument+ as a floating-point number: @@ -259,7 +261,7 @@ Format +argument+ as a floating-point number: Flag '#' does not apply. -==== Specifiers +g+ and +G+ +=== Specifiers +g+ and +G+ Format +argument+ using exponential form (+e+/+E+ specifier) if the exponent is less than -4 or greater than or equal to the precision. @@ -281,7 +283,7 @@ Otherwise format +argument+ using floating-point form (+f+ specifier): sprintf('%#G', 100000000000) # => "1.00000E+11" sprintf('%#G', 0.000000000001) # => "1.00000E-12" -==== Specifier +o+ +=== Specifier +o+ Format +argument+ as an octal integer. If +argument+ is negative, it will be formatted as a two's complement @@ -296,14 +298,14 @@ prefixed with +..7+: sprintf('%#o', 16) # => "020" sprintf('%#o', -16) # => "..760" -==== Specifier +p+ +=== Specifier +p+ Format +argument+ as a string via argument.inspect: t = Time.now sprintf('%p', t) # => "2022-05-01 13:42:07.1645683 -0500" -==== Specifier +s+ +=== Specifier +s+ Format +argument+ as a string via argument.to_s: @@ -312,7 +314,7 @@ Format +argument+ as a string via argument.to_s: Flag '#' does not apply. -==== Specifiers +x+ and +X+ +=== Specifiers +x+ and +X+ Format +argument+ as a hexadecimal integer. If +argument+ is negative, it will be formatted as a two's complement @@ -329,7 +331,7 @@ prefixed with +..f+: # Alternate format for negative value. sprintf('%#x', -100) # => "0x..f9c" -==== Specifier % +=== Specifier % Format +argument+ ('%') as a single percent character: @@ -337,7 +339,7 @@ Format +argument+ ('%') as a single percent character: Flags do not apply. -=== Reference by Name +== Reference by Name For more complex formatting, Ruby supports a reference by name. %s style uses format style, but %{name} style doesn't. diff --git a/doc/forwardable.rd.ja b/doc/forwardable.rd.ja index 171724b2e50d26..53e82025133425 100644 --- a/doc/forwardable.rd.ja +++ b/doc/forwardable.rd.ja @@ -1,4 +1,4 @@ - -- forwatable.rb + -- forwardable.rb $Release Version: 1.1 $ $Revision$ diff --git a/doc/globals.rdoc b/doc/globals.rdoc index 1d7cda69f952a6..9466005be76aab 100644 --- a/doc/globals.rdoc +++ b/doc/globals.rdoc @@ -1,69 +1,416 @@ -# -*- mode: rdoc; coding: utf-8; fill-column: 74; -*- - -== Pre-defined global variables - -$!:: The Exception object set by Kernel#raise. -$@:: The same as $!.backtrace. -$~:: The information about the last match in the current scope (thread-local and frame-local). -$&:: The string matched by the last successful match. -$`:: The string to the left of the last successful match. -$':: The string to the right of the last successful match. -$+:: The highest group matched by the last successful match. -$1:: The Nth group of the last successful match. May be > 1. -$=:: This variable is no longer effective. Deprecated. -$/:: The input record separator, newline by default. Aliased to $-0. -$\:: The output record separator for Kernel#print and IO#write. Default is +nil+. -$,:: The output field separator for Kernel#print and Array#join. Non-nil $, will be deprecated. -$;:: The default separator for String#split. Non-nil $; will be deprecated. Aliased to $-F. -$.:: The current input line number of the last file that was read. -$<:: The same as ARGF. -$>:: The default output stream for Kernel#print and Kernel#printf. $stdout by default. -$_:: The last input line of string by gets or readline. -$0:: Contains the name of the script being executed. May be assignable. -$*:: The same as ARGV. -$$:: The process number of the Ruby running this script. Same as Process.pid. -$?:: The status of the last executed child process (thread-local). -$LOAD_PATH:: Load path for searching Ruby scripts and extension libraries used - by Kernel#load and Kernel#require. Aliased to $: and $-I. - Has a singleton method $LOAD_PATH.resolve_feature_path(feature) - that returns [+:rb+ or +:so+, path], which resolves the feature to - the path the original Kernel#require method would load. -$LOADED_FEATURES:: The array contains the module names loaded by require. - Aliased to $". -$DEBUG:: The debug flag, which is set by the -d switch. Enabling debug - output prints each exception raised to $stderr (but not its - backtrace). Setting this to a true value enables debug output as - if -d were given on the command line. Setting this to a false - value disables debug output. Aliased to $-d. -$FILENAME:: Current input filename from ARGF. Same as ARGF.filename. -$stderr:: The current standard error output. -$stdin:: The current standard input. -$stdout:: The current standard output. -$VERBOSE:: The verbose flag, which is set by the -w or -v switch. - Setting this to a true value enables warnings as if -w or -v were given - on the command line. Setting this to +nil+ disables warnings, - including from Kernel#warn. Aliased to $-v and $-w. -$-a:: True if option -a is set. Read-only variable. -$-i:: In in-place-edit mode, this variable holds the extension, otherwise +nil+. -$-l:: True if option -l is set. Read-only variable. -$-p:: True if option -p is set. Read-only variable. - -== Pre-defined global constants - -STDIN:: The standard input. The default value for $stdin. -STDOUT:: The standard output. The default value for $stdout. -STDERR:: The standard error output. The default value for $stderr. -ENV:: The hash contains current environment variables. -ARGF:: The virtual concatenation of the files given on command line (or from $stdin if no files were given). -ARGV:: An Array of command line arguments given for the script. -DATA:: The file object of the script, pointing just after __END__. -TOPLEVEL_BINDING:: The Binding of the top level scope. -RUBY_VERSION:: The Ruby language version. -RUBY_RELEASE_DATE:: The release date string. -RUBY_PLATFORM:: The platform identifier. -RUBY_PATCHLEVEL:: The patchlevel for this Ruby. If this is a development build of Ruby the patchlevel will be -1. -RUBY_REVISION:: The GIT commit hash for this Ruby. -RUBY_COPYRIGHT:: The copyright string for Ruby. -RUBY_ENGINE:: The name of the Ruby implementation. -RUBY_ENGINE_VERSION:: The version of the Ruby implementation. -RUBY_DESCRIPTION:: The same as ruby --version, a String describing various aspects of the Ruby implementation. += Pre-Defined Global Variables + +Some of the pre-defined global variables have synonyms +that are available via module English. +For each of those, the \English synonym is given. + +To use the module: + + require 'English' + +== Exceptions + +=== $! (\Exception) + +Contains the Exception object set by Kernel#raise: + + begin + raise RuntimeError.new('Boo!') + rescue RuntimeError + p $! + end + +Output: + + # + +English - $ERROR_INFO + +=== $@ (Backtrace) + +Same as $!.backtrace; +returns an array of backtrace positions: + + begin + raise RuntimeError.new('Boo!') + rescue RuntimeError + pp $@.take(4) + end + +Output: + + ["(irb):338:in `'", + "/snap/ruby/317/lib/ruby/3.2.0/irb/workspace.rb:119:in `eval'", + "/snap/ruby/317/lib/ruby/3.2.0/irb/workspace.rb:119:in `evaluate'", + "/snap/ruby/317/lib/ruby/3.2.0/irb/context.rb:502:in `evaluate'"] + +English - $ERROR_POSITION. + +== Pattern Matching + +These global variables store information about the most recent +successful match in the current scope. + +For details and examples, +see {Regexp Global Variables}[rdoc-ref:Regexp@Global+Variables]. + +=== $~ (\MatchData) + +MatchData object created from the match; +thread-local and frame-local. + +English - $LAST_MATCH_INFO. + +=== $& (Matched Substring) + +The matched string. + +English - $MATCH. + +=== $` (Pre-Match Substring) + +The string to the left of the match. + +English - $PREMATCH. + +=== $' (Post-Match Substring) + +The string to the right of the match. + +English - $POSTMATCH. + +=== $+ (Last Matched Group) + +The last group matched. + +English - $LAST_PAREN_MATCH. + +=== $1, $2, \Etc. (Matched Group) + +For $_n_ the _nth_ group of the match. + +No \English. + +== Separators + +=== $/ (Input Record Separator) + +An input record separator, initially newline. + +English - $INPUT_RECORD_SEPARATOR, $RS. + +Aliased as $-0. + +=== $\\ (Output Record Separator) + +An output record separator, initially +nil+. + +English - $OUTPUT_RECORD_SEPARATOR, $ORS. + +== Streams + +=== $stdin (Standard Input) + +The current standard input stream; initially: + + $stdin # => #> + +=== $stdout (Standard Output) + +The current standard output stream; initially: + + $stdout # => #> + +=== $stderr (Standard Error) + +The current standard error stream; initially: + + $stderr # => #> + +=== $< (\ARGF or $stdin) + +Points to stream ARGF if not empty, else to stream $stdin; read-only. + +English - $DEFAULT_INPUT. + +=== $> (Default Standard Output) + +An output stream, initially $stdout. + +English - $DEFAULT_OUTPUT + +=== $. (Input Position) + +The input position (line number) in the most recently read stream. + +English - $INPUT_LINE_NUMBER, $NR + +=== $_ (Last Read Line) + +The line (string) from the most recently read stream. + +English - $LAST_READ_LINE. + +== Processes + +=== $0 + +Initially, contains the name of the script being executed; +may be reassigned. + +=== $* (\ARGV) + +Points to ARGV. + +English - $ARGV. + +=== $$ (Process ID) + +The process ID of the current process. Same as Process.pid. + +English - $PROCESS_ID, $PID. + +=== $? (Child Status) + +Initially +nil+, otherwise the Process::Status object +created for the most-recently exited child process; +thread-local. + +English - $CHILD_STATUS. + +=== $LOAD_PATH (Load Path) + +Contains the array of paths to be searched +by Kernel#load and Kernel#require. + +Singleton method $LOAD_PATH.resolve_feature_path(feature) +returns: + +- [:rb, _path_], where +path+ is the path to the Ruby file + to be loaded for the given +feature+. +- [:so+ _path_], where +path+ is the path to the shared object file + to be loaded for the given +feature+. +- +nil+ if there is no such +feature+ and +path+. + +Examples: + + $LOAD_PATH.resolve_feature_path('timeout') + # => [:rb, "/snap/ruby/317/lib/ruby/3.2.0/timeout.rb"] + $LOAD_PATH.resolve_feature_path('date_core') + # => [:so, "/snap/ruby/317/lib/ruby/3.2.0/x86_64-linux/date_core.so"] + $LOAD_PATH.resolve_feature_path('foo') + # => nil + +Aliased as $: and $-I. + +=== $LOADED_FEATURES + +Contains an array of the paths to the loaded files: + + $LOADED_FEATURES.take(10) + # => + ["enumerator.so", + "thread.rb", + "fiber.so", + "rational.so", + "complex.so", + "ruby2_keywords.rb", + "/snap/ruby/317/lib/ruby/3.2.0/x86_64-linux/enc/encdb.so", + "/snap/ruby/317/lib/ruby/3.2.0/x86_64-linux/enc/trans/transdb.so", + "/snap/ruby/317/lib/ruby/3.2.0/x86_64-linux/rbconfig.rb", + "/snap/ruby/317/lib/ruby/3.2.0/rubygems/compatibility.rb"] + +Aliased as $". + +== Debugging + +=== $FILENAME + +The value returned by method ARGF.filename. + +=== $DEBUG + +Initially +true+ if command-line option -d or --debug is given, +otherwise initially +false+; +may be set to either value in the running program. + +When +true+, prints each raised exception to $stderr. + +Aliased as $-d. + +=== $VERBOSE + +Initially +true+ if command-line option -v or -w is given, +otherwise initially +false+; +may be set to either value, or to +nil+, in the running program. + +When +true+, enables Ruby warnings. + +When +nil+, disables warnings, including those from Kernel#warn. + +Aliased as $-v and $-w. + +== Other Variables + +=== $-a + +Whether command-line option -a was given; read-only. + +=== $-i + +Contains the extension given with command-line option -i, +or +nil+ if none. + +An alias of ARGF.inplace_mode. + +=== $-l + +Whether command-line option -l was set; read-only. + +=== $-p + +Whether command-line option -p was given; read-only. + +== Deprecated + +=== $= + +=== $, + +=== $; + += Pre-Defined Global Constants + += Streams + +=== STDIN + +The standard input stream (the default value for $stdin): + + STDIN # => #> + +=== STDOUT + +The standard output stream (the default value for $stdout): + + STDOUT # => #> + +=== STDERR + +The standard error stream (the default value for $stderr): + + STDERR # => #> + +== Environment + +=== ENV + +A hash of the contains current environment variables names and values: + + ENV.take(5) + # => + [["COLORTERM", "truecolor"], + ["DBUS_SESSION_BUS_ADDRESS", "unix:path=/run/user/1000/bus"], + ["DESKTOP_SESSION", "ubuntu"], + ["DISPLAY", ":0"], + ["GDMSESSION", "ubuntu"]] + +=== ARGF + +The virtual concatenation of the files given on the command line, or from +$stdin if no files were given, "-" is given, or after +all files have been read. + +=== ARGV + +An array of the given command-line arguments. + +=== TOPLEVEL_BINDING + +The Binding of the top level scope: + + TOPLEVEL_BINDING # => # + +=== RUBY_VERSION + +The Ruby version: + + RUBY_VERSION # => "3.2.2" + +=== RUBY_RELEASE_DATE + +The release date string: + + RUBY_RELEASE_DATE # => "2023-03-30" + +=== RUBY_PLATFORM + +The platform identifier: + + RUBY_PLATFORM # => "x86_64-linux" + +=== RUBY_PATCHLEVEL + +The integer patch level for this Ruby: + + RUBY_PATCHLEVEL # => 53 + +For a development build the patch level will be -1. + +=== RUBY_REVISION + +The git commit hash for this Ruby: + + RUBY_REVISION # => "e51014f9c05aa65cbf203442d37fef7c12390015" + +=== RUBY_COPYRIGHT + +The copyright string: + + RUBY_COPYRIGHT + # => "ruby - Copyright (C) 1993-2023 Yukihiro Matsumoto" + +=== RUBY_ENGINE + +The name of the Ruby implementation: + + RUBY_ENGINE # => "ruby" + +=== RUBY_ENGINE_VERSION + +The version of the Ruby implementation: + + RUBY_ENGINE_VERSION # => "3.2.2" + +=== RUBY_DESCRIPTION + +The description of the Ruby implementation: + + RUBY_DESCRIPTION + # => "ruby 3.2.2 (2023-03-30 revision e51014f9c0) [x86_64-linux]" + +== Embedded \Data + +=== DATA + +Defined if and only if the program has this line: + + __END__ + +When defined, DATA is a File object +containing the lines following the __END__, +positioned at the first of those lines: + + p DATA + DATA.each_line { |line| p line } + __END__ + Foo + Bar + Baz + +Output: + + # + "Foo\n" + "Bar\n" + "Baz\n" diff --git a/doc/hash_inclusion.rdoc b/doc/hash_inclusion.rdoc new file mode 100644 index 00000000000000..05c2b0932a50ef --- /dev/null +++ b/doc/hash_inclusion.rdoc @@ -0,0 +1,31 @@ +== \Hash Inclusion + +A hash is set-like in that it cannot have duplicate entries +(or even duplicate keys). +\Hash inclusion can therefore based on the idea of +{subset and superset}[https://en.wikipedia.org/wiki/Subset]. + +Two hashes may be tested for inclusion, +based on comparisons of their entries. + +An entry h0[k0] in one hash +is equal to an entry h1[k1] in another hash +if and only if the two keys are equal (k0 == k1) +and their two values are equal (h0[k0] == h1[h1]). + +A hash may be a subset or a superset of another hash: + +- Subset (included in or equal to another): + + - \Hash +h0+ is a _subset_ of hash +h1+ (see Hash#<=) + if each entry in +h0+ is equal to an entry in +h1+. + - Further, +h0+ is a proper subset of +h1+ (see Hash#<) + if +h1+ is larger than +h0+. + +- Superset (including or equal to another): + + - \Hash +h0+ is a _superset_ of hash +h1+ (see Hash#>=) + if each entry in +h1+ is equal to an entry in +h0+. + - Further, +h0+ is a proper superset of +h1+ (see Hash#>) + if +h0+ is larger than +h1+. + diff --git a/doc/implicit_conversion.rdoc b/doc/implicit_conversion.rdoc index ba15fa4bf40682..e2440961250adc 100644 --- a/doc/implicit_conversion.rdoc +++ b/doc/implicit_conversion.rdoc @@ -1,4 +1,4 @@ -== Implicit Conversions += Implicit Conversions Some Ruby methods accept one or more objects that can be either: @@ -15,7 +15,7 @@ a specific conversion method: * Integer: +to_int+ * String: +to_str+ -=== Array-Convertible Objects +== Array-Convertible Objects An Array-convertible object is an object that: @@ -69,7 +69,7 @@ This class is not Array-convertible (method +to_ary+ returns non-Array): # Raises TypeError (can't convert NotArrayConvertible to Array (NotArrayConvertible#to_ary gives Symbol)) a.replace(NotArrayConvertible.new) -=== Hash-Convertible Objects +== Hash-Convertible Objects A Hash-convertible object is an object that: @@ -123,7 +123,7 @@ This class is not Hash-convertible (method +to_hash+ returns non-Hash): # Raises TypeError (can't convert NotHashConvertible to Hash (ToHashReturnsNonHash#to_hash gives Symbol)) h.merge(NotHashConvertible.new) -=== Integer-Convertible Objects +== Integer-Convertible Objects An Integer-convertible object is an object that: @@ -171,7 +171,7 @@ This class is not Integer-convertible (method +to_int+ returns non-Integer): # Raises TypeError (can't convert NotIntegerConvertible to Integer (NotIntegerConvertible#to_int gives Symbol)) Array.new(NotIntegerConvertible.new) -=== String-Convertible Objects +== String-Convertible Objects A String-convertible object is an object that: * Has instance method +to_str+. diff --git a/doc/index.md b/doc/index.md new file mode 100644 index 00000000000000..596825a19c55c6 --- /dev/null +++ b/doc/index.md @@ -0,0 +1,65 @@ +# Ruby Documentation + +Welcome to the official Ruby programming language documentation. + +## Getting Started + +New to Ruby? Start with our [Getting Started Guide](https://www.ruby-lang.org/en/documentation/quickstart/). + +## Core Classes and Modules + +Explore the essential classes and modules: + +- [String](String.html) - Text manipulation and string utilities. +- [Symbol](Symbol.html) - Named identifiers inside the Ruby interpreter. +- [Array](Array.html) - Ordered collections of objects. +- [Hash](Hash.html) - Key-value pairs for efficient data retrieval. +- [Integer](Integer.html) - \Integer number class. +- [Float](Float.html) - Floating-point number class. +- [Enumerable](Enumerable.html) - Collection traversal and searching. +- [File](File.html) - \File operations and handling. +- [IO](IO.html) - Input/output functionality. +- [Time](Time.html) - \Time representation. +- [Regexp](Regexp.html) - Regular expressions for pattern matching. +- [Range](Range.html) - Representing a range of values. +- [Exception](Exception.html) - Base class for all exceptions. +- [Thread](Thread.html) - Multithreading and concurrency. + +## Language Reference + +Deep dive into Ruby's syntax and features: + +- [Ruby Syntax](rdoc-ref:syntax.rdoc) +- [Exceptions](rdoc-ref:exceptions.md) +- [Implicit Conversions](rdoc-ref:implicit_conversion.rdoc) + +## Standard Libraries + +There are some standard libraries included in Ruby that are also commonly used, such as: + +- [Date](Date.html) - \Date representation. +- [JSON](JSON.html) - \JSON encoding and decoding. +- [ERB](ERB.html) - Embedded Ruby for templating. +- [Net::HTTP](Net/HTTP.html) - HTTP client library. + +Use the following links to access the comprehensive set of libraries included with Ruby: + +- [Standard Library Documentation](rdoc-ref:standard_library.md) +- [Maintainers](rdoc-ref:maintainers.md) + +## Contribute to Ruby + +Get involved with the Ruby community: + +- [Contribution Guide](rdoc-ref:contributing/contributing.md) +- [Documentation Guide](rdoc-ref:contributing/documentation_guide.md) +- [Reporting Issues](rdoc-ref:contributing/reporting_issues.md) +- [Building Ruby](rdoc-ref:contributing/building_ruby.md) +- [Testing Ruby](rdoc-ref:contributing/testing_ruby.md) +- [Issue Tracker](https://bugs.ruby-lang.org/projects/ruby-master/issues) + +## Additional Resources + +- [Ruby Homepage](https://www.ruby-lang.org/) +- [RubyGems](https://rubygems.org/) +- [Ruby Community](https://www.ruby-lang.org/en/community/) diff --git a/doc/irb/irb-tools.rd.ja b/doc/irb/irb-tools.rd.ja deleted file mode 100644 index b997f0edeaf31f..00000000000000 --- a/doc/irb/irb-tools.rd.ja +++ /dev/null @@ -1,184 +0,0 @@ -irb関連おまけコマンドとライブラリ - $Release Version: 0.7.1 $ - $Revision$ - by Keiju ISHITSUKA(Nihon Rational Co.,Ltd.) - -=begin - -:コマンド: -* rtags -- ruby tags command - -:関数ライブラリ: -* xmp -- irb version of gotoken xmp-function - -:クラスライブラリ: -* frame.rb -- frame tracer -* completion.rb -- irb completor - -= rtags - -rtagsはemacs及びvi用の, TAGファイルをつくるコマンドです. - -== 使い方 - - rtags [-vi] file.... - -カレントディレクトリにemacs用のTAGSファイルができます. -viオプションを -つけた時にはvi用のtagsファイルを作成します. - -emacsの場合, 通常のetags.elがそのまま使えます. 検索可能なのは, - -* クラス -* メソッド -* 特異メソッド -* alias -* attrで宣言されたアクセサ(パラメータがシンボルか文字列リテラルに限る) -* attr_XXXで宣言されたアクセサ(パラメータがシンボルか文字列リテラルに限る) - -です. - -Cなどで使っているのと違うのは, コンプリーションに関する部分で, - -関数名は, - - 関数名( - -クラスは, - - ::クラス名::....::クラス名 - -メソッドは, - - ::クラス名::....::クラス名#メソッド名 - -特異メソッド(クラスメソッド)は - - ::クラス名::....::クラス名.メソッド名 - -でコンプリーションを行なうところです. - -= xmp.rb - -ごとけんxmpの上位互換バージョンです. ただ, 非常に重いのでごとけんxmpで -は対応できない時に, 使用すると良いでしょう. - -== 使い方 - -=== 関数として使う. - - require "irb/xmp" - xmp <1 - foo - ==>1 - -=== XMPインスタンスを用いる. - -この場合は, XMPがコンテキスト情報を持つので, 変数の値などを保持してい -ます. - - require "irb/xmp" - xmp = XMP.new - xmp.puts <1 - foo - ==>1 - foo - ==>1 - -== コンテキストに関して - -XMPメソッド群のコンテキストは, 呼び出す前のコンテキストで評価されます. -明示的にコンテキストを指定するとそのコンテキストで評価します. - -例: - - xmp "foo", an_binding - -:注: -マルチスレッドには対応していません. - -= frame.rb -現在実行中のフレーム情報を取り扱うためのクラスです. - -* IRB::Frame.top(n = 0) - 上からn番目のコンテキストを取り出します. nは0が最上位になります. -* IRB::Frame.bottom(n = 0) - 下からn番目のコンテキストを取り出します. nは0が最下位になります. -* IRB::Frame.sender - センダになっているオブジェクトを取り出します. センダとは, そのメソッ - ドを呼び出した側のselfのことです. - -:注: -set_trace_funcを用いてRubyの実行をトレースしています. マルチスレッドに -は対応していません. - -= completion.rb -irbのcompletion機能を提供するものです. - -== 使い方 - - % irb -r irb/completion - -とするか, ~/.irbrc 中に - - require "irb/completion" - -を入れてください. irb実行中に require "irb/completion" してもよいです. - -irb実行中に (TAB) を押すとコンプレーションします. - -トップレベルで(TAB)を押すとすべての構文要素, クラス, メソッドの候補がで -ます. 候補が唯一ならば完全に補完します. - - irb(main):001:0> in - in inspect instance_eval - include install_alias_method instance_of? - initialize install_aliases instance_variables - irb(main):001:0> inspect - "main" - irb(main):002:0> foo = Object.new - # - - ((|変数名.|))の後に(TAB)を押すと, そのオブジェクトのメソッド一覧がでま - す. - - irb(main):003:0> foo. - foo.== foo.frozen? foo.protected_methods - foo.=== foo.hash foo.public_methods - foo.=~ foo.id foo.respond_to? - foo.__id__ foo.inspect foo.send - foo.__send__ foo.instance_eval foo.singleton_methods - foo.class foo.instance_of? foo.taint - foo.clone foo.instance_variables foo.tainted? - foo.display foo.is_a? foo.to_a - foo.dup foo.kind_of? foo.to_s - foo.eql? foo.method foo.type - foo.equal? foo.methods foo.untaint - foo.extend foo.nil? - foo.freeze foo.private_methods - -=end - -% Begin Emacs Environment -% Local Variables: -% mode: text -% comment-column: 0 -% comment-start: "%" -% comment-end: "\n" -% End: -% - diff --git a/doc/irb/irb.rd.ja b/doc/irb/irb.rd.ja deleted file mode 100644 index c51e0bd60d566b..00000000000000 --- a/doc/irb/irb.rd.ja +++ /dev/null @@ -1,425 +0,0 @@ -irb -- interactive ruby - $Release Version: 0.9.5 $ - $Revision$ - by Keiju ISHITSUKA(keiju@ruby-lang.org) -=begin -= irbとは? - -irbはinteractive rubyの略です. rubyの式を標準入力から簡単に入力/実行する -ためのツールです. - -= 起動 - - % irb - -で行ないます. - -= 使い方 - -irbの使い方は, Rubyさえ知っていればいたって簡単です. 基本的には irb と -いうコマンドを実行するだけです. irbを実行すると, 以下のようなプロンプ -トが表れてきます. 後は, rubyの式を入れて下さい. 式が完結した時点で実行 -されます. - - dim% irb - irb(main):001:0> 1+2 - 3 - irb(main):002:0> class Foo - irb(main):003:1> def foo - irb(main):004:2> print 1 - irb(main):005:2> end - irb(main):006:1> end - nil - irb(main):007:0> - -また, irbはReadlineモジュールにも対応しています. Readlineモジュールが -インストールされている時には, それを使うのが標準の動作になります. - -= コマンドオプション - - irb.rb [options] file_name opts - options: - -f ~/.irbrc を読み込まない. - -d $DEBUG をtrueにする(ruby -d と同じ) - -r load-module ruby -r と同じ. - -I path $LOAD_PATH に path を追加する. - -U ruby -U と同じ. - -E enc ruby -E と同じ. - -w ruby -w と同じ. - -W[level=2] ruby -W と同じ. - --context-mode n 新しいワークスペースを作成した時に関連する Binding - オブジェクトの作成方法を 0 から 3 のいずれかに設定する. - --echo 実行結果を表示する(デフォルト). - --noecho 実行結果を表示しない. - --echo-on-assignment - 代入時に実行結果を表示する. - --noecho-on-assignment - 代入時に実行結果を表示しない. - --truncate-echo-on-assignment - 代入時に省略された実行結果を表示する(デフォルト). - --inspect 結果出力にinspectを用いる. - --noinspect 結果出力にinspectを用いない. - --singleline シングルラインエディタを利用する. - --nosingleline シングルラインエディタを利用しない. デフォルトの動 - 作は, inf-ruby-mode以外でシングルラインエディタを利 - 用しようとする. - --colorize 色付けを利用する. - --nocolorize 色付けを利用しない. - --autocomplete オートコンプリートを利用する. - --noautocomplete オートコンプリートを利用しない. - --prompt prompt-mode - --prompt-mode prompt-mode - プロンプトモードを切替えます. 現在定義されているプ - ロンプトモードは, default, simple, xmp, inf-rubyが - 用意されています. - --inf-ruby-mode emacsのinf-ruby-mode用のプロンプト表示を行なう. 特 - に指定がない限り, ラインエディタは使わなくなる. - --simple-prompt - 非常にシンプルなプロンプトを用いるモードです. - --noprompt プロンプト表示を行なわない. - --single-irb irb 中で self を実行して得られるオブジェクトをサ - ブ irb と共有する. - --tracer コマンド実行時にトレースを行なう. - --back-trace-limit n - バックトレース表示をバックトレースの頭から n, 後ろ - からnだけ行なう. デフォルトは16 - - --verbose 詳細なメッセージを出力する. - --noverbose 詳細なメッセージを出力しない(デフォルト). - -v, --version irbのバージョンを表示する. - -h, --help irb のヘルプを表示する. - -- 以降のコマンドライン引数をオプションとして扱わない. - -= コンフィギュレーション - -irb起動時に``~/.irbrc''を読み込みます. もし存在しない場合は, -``.irbrc'', ``irb.rc'', ``_irbrc'', ``$irbrc''の順にloadを試みます. - -オプションを設定する代わりに, 以下のコマンドでもデフォルトの動作を設定 -できます. - - IRB.conf[:IRB_NAME]="irb" - IRB.conf[:USE_TRACER]=false - IRB.conf[:USE_LOADER]=false - IRB.conf[:IGNORE_SIGINT]=true - IRB.conf[:IGNORE_EOF]=false - IRB.conf[:INSPECT_MODE]=nil - IRB.conf[:IRB_RC] = nil - IRB.conf[:BACK_TRACE_LIMIT]=16 - IRB.conf[:USE_LOADER] = false - IRB.conf[:USE_SINGLELINE] = nil - IRB.conf[:USE_TRACER] = false - IRB.conf[:IGNORE_SIGINT] = true - IRB.conf[:IGNORE_EOF] = false - IRB.conf[:PROMPT_MODE] = :DEFAULT - IRB.conf[:PROMPT] = {...} - IRB.conf[:VERBOSE]=true - -== プロンプトの設定 - -プロンプトをカスタマイズしたい時には, - - IRB.conf[:PROMPT] - -を用います. 例えば, .irbrcの中で下のような式を記述します: - - IRB.conf[:PROMPT][:MY_PROMPT] = { # プロンプトモードの名前 - :PROMPT_I => nil, # 通常のプロンプト - :PROMPT_S => nil, # 文字列などの継続行のプロンプト - :PROMPT_C => nil, # 式が継続している時のプロンプト - :RETURN => " ==>%s\n" # リターン時のプロンプト - } - -プロンプトモードを指定したい時には, - - irb --prompt my-prompt - -でそのプロンプトモードで起動されます. または, .irbrcに下式を記述しても -OKです. - - IRB.conf[:PROMPT_MODE] = :MY_PROMPT - -PROMPT_I, PROMPT_S, PROMPT_Cは, フォーマットを指定します. - - %N 起動しているコマンド名が出力される. - %m mainオブジェクト(self)がto_sで出力される. - %M mainオブジェクト(self)がinspectされて出力される. - %l 文字列中のタイプを表す(", ', /, ], `]'は%wの中の時) - %NNi インデントのレベルを表す. NNは数字が入りprintfの%NNdと同じ. 省 - 略可能 - %NNn 行番号を表します. - %% % - -例えば, デフォルトのプロンプトモードは: - - IRB.conf[:PROMPT][:DEFAULT] = { - :PROMPT_I => "%N(%m):%03n:%i> ", - :PROMPT_S => "%N(%m):%03n:%i%l ", - :PROMPT_C => "%N(%m):%03n:%i* ", - :RETURN => "=> %s\n" - } - -となっています. - -RETURNは, 現在のところprintf形式です. 将来仕様が変わるかも知れません. - -== サブirbの設定 - -コマンドラインオプションおよびIRB.confは(サブ)irb起動時のデフォルトの -設定を決めるもので, `5. コマンド'にあるconfで個別の(サブ)irbの設定がで -きるようになっています. - -IRB.conf[:IRB_RC]にprocが設定されていると, サブirbを起動する時にその -procをirbのコンテキストを引数として呼び出します. これによって個別のサ -ブirbごとに設定を変えることができるようになります. - - -= コマンド - -irb拡張コマンドは, 簡単な名前と頭に`irb_'をつけた名前と両方定義されて -います. これは, 簡単な名前がoverrideされた時のためです. - ---- exit, quit, irb_exit - 終了する. - サブirbの場合, そのサブirbを終了する. - ---- conf, irb_context - irbの現在の設定を表示する. 設定の変更は, confにメッセージを送るこ - とによって行なえる. - ---- conf.eval_history = N - 実行結果のヒストリ機能の設定. - nnは整数かnilで nn>0 であればその数だけヒストリにためる。nn==0の時は - 無制限に記憶する、nilだとヒストリ機能はやめる(デフォルト). - ---- Conf.back_trace_limit - バックトレース表示をバックトレースの頭からn, 後ろからnだけ行なう. - デフォルトは16 - ---- conf.ignore_eof = true/false - ^Dが入力された時の動作を設定する. trueの時は^Dを無視する, falseの - 時はirbを終了する. - ---- conf.ignore_sigint= true/false - ^Cが入力された時の動作を設定する. false時は, irbを終了する. trueの - 時の動作は以下のようになる: - 入力中: これまで入力したものをキャンセルしトップレベルに戻る. - 実行中: 実行を中止する. - ---- conf.inf_ruby_mode = true/false - inf-ruby-mode用のプロンプト表示を行なう. デフォルトはfalse. 特に指定 - がない限り, ラインエディタは使わなくなる. - ---- conf.inspect_mode = true/false/nil - インスペクトモードを設定する. - true: インスペクトして表示する. - false: 通常のprintで表示する. - nil: 通常モードであれば, inspect modeとなり, mathモードの時は, non - inspect modeとなる. - ---- conf.use_loader = true/false - load/require時にirbのfile読み込み機能を用いるモードのスイッチ(デフォ - ルトは用いない). このモードはIRB全体に反映される. - ---- conf.prompt_c - ifの直後など, 行が継続している時のプロンプト. - ---- conf.prompt_i - 通常のプロンプト. - ---- conf.prompt_s - 文字列中などを表すプロンプト. - ---- conf.rc - ~/.irbrcを読み込んだかどうか? - ---- conf.use_prompt = true/false - プロンプト表示するかどうか? デフォルトではプロンプトを表示する. - ---- conf.use_multiline = true/false/nil - マルチラインエディタを使うかどうか? - true: マルチラインエディタを使う. - false: マルチラインエディタを使わない. - nil: (デフォルト)inf-ruby-mode以外でマルチラインエディタを利用しよう - とする. - ---- conf.use_singleline = true/false/nil - シングルラインエディタを使うかどうか? - true: シングルラインエディタを使う. - false: シングルラインエディタを使わない. - nil: (デフォルト)inf-ruby-modeとマルチラインエディタ以外でシングルラ - インエディタを利用しようとする. -# -#--- conf.verbose=T/F -# irbからいろいろなメッセージを出力するか? - ---- cws, chws, irb_cws, irb_chws, irb_change_workspace [obj] - objをselfとする. objが省略されたときは, home workspace, すなわち - irbを起動したときのmain objectをselfとする. - ---- pushws, irb_pushws, irb_push_workspace [obj] - UNIXシェルコマンドのpushdと同様. - ---- popws, irb_popws, irb_pop_workspace - UNIXシェルコマンドのpopdと同様. - ---- irb [obj] - サブirbを立ちあげる. objが指定された時は, そのobjをselfとする. - ---- jobs, irb_jobs - サブirbのリスト - ---- fg n, irb_fg n - 指定したサブirbにスイッチする. nは, 次のものを指定する. - - irb番号 - スレッド - irbオブジェクト - self(irb objで起動した時のobj) - ---- kill n, irb_kill n - サブirbをkillする. nはfgと同じ. - ---- source, irb_source path - UNIXシェルコマンドのsourceと似ている. 現在の環境上でpath内のスクリ - プトを評価する. - ---- irb_load path, prev - - Rubyのloadのirb版. - -= システム変数 - ---- _ - 前の計算の実行結果を覚えている(ローカル変数). ---- __ - 実行結果の履歴を覚えている. - __[line_no]で、その行で実行した結果を得ることができる. line_noが負の - 時には、最新の結果から-line_no前の結果を得ることができる. - -= 使用例 - -以下のような感じです. - - dim% ruby irb.rb - irb(main):001:0> irb # サブirbの立ちあげ - irb#1(main):001:0> jobs # サブirbのリスト - #0->irb on main (# : stop) - #1->irb#1 on main (# : running) - nil - irb#1(main):002:0> fg 0 # jobのスイッチ - nil - irb(main):002:0> class Foo;end - nil - irb(main):003:0> irb Foo # Fooをコンテキストしてirb - # 立ちあげ - irb#2(Foo):001:0> def foo # Foo#fooの定義 - irb#2(Foo):002:1> print 1 - irb#2(Foo):003:1> end - nil - irb#2(Foo):004:0> fg 0 # jobをスイッチ - nil - irb(main):004:0> jobs # jobのリスト - #0->irb on main (# : running) - #1->irb#1 on main (# : stop) - #2->irb#2 on Foo (# : stop) - nil - irb(main):005:0> Foo.instance_methods # Foo#fooがちゃんと定義さ - # れている - ["foo"] - irb(main):006:0> fg 2 # jobをスイッチ - nil - irb#2(Foo):005:0> def bar # Foo#barを定義 - irb#2(Foo):006:1> print "bar" - irb#2(Foo):007:1> end - nil - irb#2(Foo):010:0> Foo.instance_methods - ["bar", "foo"] - irb#2(Foo):011:0> fg 0 - nil - irb(main):007:0> f = Foo.new - # - irb(main):008:0> irb f # Fooのインスタンスでirbを - # 立ちあげる. - irb#3(#):001:0> jobs - #0->irb on main (# : stop) - #1->irb#1 on main (# : stop) - #2->irb#2 on Foo (# : stop) - #3->irb#3 on # (# : running) - nil - irb#3(#):002:0> foo # f.fooの実行 - nil - irb#3(#):003:0> bar # f.barの実行 - barnil - irb#3(#):004:0> kill 1, 2, 3# jobのkill - nil - irb(main):009:0> jobs - #0->irb on main (# : running) - nil - irb(main):010:0> exit # 終了 - dim% - -= 使用上の制限 - -irbは, 評価できる時点(式が閉じた時点)での逐次実行を行ないます. したがっ -て, rubyを直接使った時と, 若干異なる動作を行なう場合があります. - -現在明らかになっている問題点を説明します. - -== ローカル変数の宣言 - -rubyでは, 以下のプログラムはエラーになります. - - eval "foo = 0" - foo - -- - -:2: undefined local variable or method `foo' for # (NameError) - --- - NameError - -ところが, irbを用いると - - >> eval "foo = 0" - => 0 - >> foo - => 0 - -となり, エラーを起こしません. これは, rubyが最初にスクリプト全体をコン -パイルしてローカル変数を決定するからです. それに対し, irbは実行可能に -なる(式が閉じる)と自動的に評価しているからです. 上記の例では, - - eval "foo = 0" - -を行なった時点で評価を行ない, その時点で変数が定義されるため, 次式で -変数fooは定義されているからです. - -このようなrubyとirbの動作の違いを解決したい場合は, begin...endで括って -バッチ的に実行して下さい: - - >> begin - ?> eval "foo = 0" - >> foo - >> end - NameError: undefined local variable or method `foo' for # - (irb):3 - (irb_local_binding):1:in `eval' - -== ヒアドキュメント - -現在のところヒアドキュメントの実装は不完全です. - -== シンボル - -シンボルであるかどうかの判断を間違えることがあります. 具体的には式が完了 -しているのに継続行と見なすことがあります. - -=end - -% Begin Emacs Environment -% Local Variables: -% mode: text -% comment-column: 0 -% comment-start: "%" -% comment-end: "\n" -% End: -% diff --git a/doc/maintainers.md b/doc/maintainers.md index 11f729f9515c56..7d217a166534a9 100644 --- a/doc/maintainers.md +++ b/doc/maintainers.md @@ -1,7 +1,16 @@ # Maintainers -This page describes the current module, library, and extension maintainers of Ruby. + +This page describes the current branch, module, library, and extension maintainers of Ruby. + +## Branch Maintainers + +A branch maintainer is responsible for backporting commits into stable branches +and publishing Ruby patch releases. + +[The list of current branch maintainers is available in the wiki](https://github.com/ruby/ruby/wiki/Release-Engineering). ## Module Maintainers + A module maintainer is responsible for a certain part of Ruby. * The maintainer fixes bugs of the part. Particularly, they should fix @@ -20,489 +29,599 @@ consensus on ruby-core/ruby-dev before changing/adding. Some of submaintainers have commit right, others don't. ### Language core features including security -* Yukihiro Matsumoto (matz) + +* Yukihiro Matsumoto ([matz]) ### Evaluator -* Koichi Sasada (ko1) + +* Koichi Sasada ([ko1]) ### Core classes -* Yukihiro Matsumoto (matz) + +* Yukihiro Matsumoto ([matz]) ## Standard Library Maintainers + ### Libraries + #### lib/mkmf.rb + * *unmaintained* #### lib/rubygems.rb, lib/rubygems/* -* Eric Hodel (drbrain) -* Hiroshi SHIBATA (hsbt) + +* Eric Hodel ([drbrain]) +* Hiroshi SHIBATA ([hsbt]) * https://github.com/rubygems/rubygems #### lib/unicode_normalize.rb, lib/unicode_normalize/* -* Martin J. Dürst + +* Martin J. Dürst ([duerst]) ### Extensions + #### ext/continuation -* Koichi Sasada (ko1) + +* Koichi Sasada ([ko1]) #### ext/coverage -* Yusuke Endoh (mame) + +* Yusuke Endoh ([mame]) #### ext/fiber -* Koichi Sasada (ko1) + +* Koichi Sasada ([ko1]) #### ext/monitor -* Koichi Sasada (ko1) + +* Koichi Sasada ([ko1]) #### ext/objspace + * *unmaintained* #### ext/pty + * *unmaintained* #### ext/ripper + * *unmaintained* #### ext/socket -* Tanaka Akira (akr) + +* Tanaka Akira ([akr]) * API change needs matz's approval #### ext/win32 -* NAKAMURA Usaku (usa) -## Default gems Maintainers -### Libraries -#### lib/abbrev.rb -* Akinori MUSHA (knu) -* https://github.com/ruby/abbrev -* https://rubygems.org/gems/abbrev +* NAKAMURA Usaku ([unak]) -#### lib/base64.rb -* Yusuke Endoh (mame) -* https://github.com/ruby/base64 -* https://rubygems.org/gems/base64 +## Default gems Maintainers -#### lib/benchmark.rb -* *unmaintained* -* https://github.com/ruby/benchmark -* https://rubygems.org/gems/benchmark +### Libraries #### lib/bundler.rb, lib/bundler/* -* Hiroshi SHIBATA (hsbt) + +* Hiroshi SHIBATA ([hsbt]) * https://github.com/rubygems/rubygems * https://rubygems.org/gems/bundler -#### lib/cgi.rb, lib/cgi/* -* *unmaintained* -* https://github.com/ruby/cgi -* https://rubygems.org/gems/cgi +#### lib/cgi/escape.rb -#### lib/csv.rb -* Kenta Murata (mrkn) -* Kouhei Sutou (kou) -* https://github.com/ruby/csv -* https://rubygems.org/gems/csv +* *unmaintained* #### lib/English.rb + * *unmaintained* * https://github.com/ruby/English * https://rubygems.org/gems/English #### lib/delegate.rb + * *unmaintained* * https://github.com/ruby/delegate * https://rubygems.org/gems/delegate #### lib/did_you_mean.rb -* Yuki Nishijima (yuki24) + +* Yuki Nishijima ([yuki24]) * https://github.com/ruby/did_you_mean * https://rubygems.org/gems/did_you_mean #### ext/digest, ext/digest/* -* Akinori MUSHA (knu) + +* Akinori MUSHA ([knu]) * https://github.com/ruby/digest * https://rubygems.org/gems/digest -#### lib/drb.rb, lib/drb/* -* Masatoshi SEKI (seki) -* https://github.com/ruby/drb -* https://rubygems.org/gems/drb - #### lib/erb.rb -* Masatoshi SEKI (seki) -* Takashi Kokubun (k0kubun) + +* Masatoshi SEKI ([seki]) +* Takashi Kokubun ([k0kubun]) * https://github.com/ruby/erb * https://rubygems.org/gems/erb #### lib/error_highlight.rb, lib/error_highlight/* -* Yusuke Endoh (mame) + +* Yusuke Endoh ([mame]) * https://github.com/ruby/error_highlight * https://rubygems.org/gems/error_highlight #### lib/fileutils.rb + * *unmaintained* * https://github.com/ruby/fileutils * https://rubygems.org/gems/fileutils #### lib/find.rb -* Kazuki Tsujimoto (ktsj) + +* Kazuki Tsujimoto ([k-tsj]) * https://github.com/ruby/find * https://rubygems.org/gems/find #### lib/forwardable.rb -* Keiju ISHITSUKA (keiju) + +* Keiju ISHITSUKA ([keiju]) * https://github.com/ruby/forwardable * https://rubygems.org/gems/forwardable -#### lib/getoptlong.rb -* *unmaintained* -* https://github.com/ruby/getoptlong -* https://rubygems.org/gems/getoptlong - #### lib/ipaddr.rb -* Akinori MUSHA (knu) + +* Akinori MUSHA ([knu]) * https://github.com/ruby/ipaddr * https://rubygems.org/gems/ipaddr -#### lib/irb.rb, lib/irb/* -* aycabta -* https://github.com/ruby/irb -* https://rubygems.org/gems/irb - #### lib/optparse.rb, lib/optparse/* -* Nobuyuki Nakada (nobu) -* https://github.com/ruby/optparse -#### lib/logger.rb -* Naotoshi Seo (sonots) -* https://github.com/ruby/logger -* https://rubygems.org/gems/logger - -#### lib/mutex_m.rb -* Keiju ISHITSUKA (keiju) -* https://github.com/ruby/mutex_m -* https://rubygems.org/gems/mutex_m +* Nobuyuki Nakada ([nobu]) +* https://github.com/ruby/optparse #### lib/net/http.rb, lib/net/https.rb -* NARUSE, Yui (naruse) + +* NARUSE, Yui ([nurse]) * https://github.com/ruby/net-http * https://rubygems.org/gems/net-http #### lib/net/protocol.rb + * *unmaintained* * https://github.com/ruby/net-protocol * https://rubygems.org/gems/net-protocol -#### lib/observer.rb -* *unmaintained* -* https://github.com/ruby/observer -* https://rubygems.org/gems/observer - #### lib/open3.rb + * *unmaintained* * https://github.com/ruby/open3 * https://rubygems.org/gems/open3 #### lib/open-uri.rb -* Tanaka Akira (akr) -* https://github.com/ruby/open-uri -#### lib/ostruct.rb -* Marc-André Lafortune (marcandre) -* https://github.com/ruby/ostruct -* https://rubygems.org/gems/ostruct +* Tanaka Akira ([akr]) +* https://github.com/ruby/open-uri #### lib/pp.rb -* Tanaka Akira (akr) + +* Tanaka Akira ([akr]) * https://github.com/ruby/pp * https://rubygems.org/gems/pp #### lib/prettyprint.rb -* Tanaka Akira (akr) + +* Tanaka Akira ([akr]) * https://github.com/ruby/prettyprint * https://rubygems.org/gems/prettyprint -#### lib/pstore.rb -* *unmaintained* -* https://github.com/ruby/pstore -* https://rubygems.org/gems/pstore +#### lib/prism.rb -#### lib/readline.rb -* aycabta -* https://github.com/ruby/readline -* https://rubygems.org/gems/readline +* Kevin Newton ([kddnewton]) +* Eileen Uchitelle ([eileencodes]) +* Aaron Patterson ([tenderlove]) +* https://github.com/ruby/prism +* https://rubygems.org/gems/prism #### lib/resolv.rb -* Tanaka Akira (akr) + +* Tanaka Akira ([akr]) * https://github.com/ruby/resolv * https://rubygems.org/gems/resolv -#### lib/resolv-replace.rb -* Tanaka Akira (akr) -* https://github.com/ruby/resolv-replace -* https://rubygems.org/gems/resolv-replace - -#### lib/rdoc.rb, lib/rdoc/* -* Eric Hodel (drbrain) -* Hiroshi SHIBATA (hsbt) -* https://github.com/ruby/rdoc -* https://rubygems.org/gems/rdoc - -#### lib/reline.rb, lib/reline/* -* aycabta -* https://github.com/ruby/reline -* https://rubygems.org/gems/reline - -#### lib/rinda/* -* Masatoshi SEKI (seki) -* https://github.com/ruby/rinda -* https://rubygems.org/gems/rinda - #### lib/securerandom.rb -* Tanaka Akira (akr) + +* Tanaka Akira ([akr]) * https://github.com/ruby/securerandom * https://rubygems.org/gems/securerandom -#### lib/set.rb -* Akinori MUSHA (knu) -* https://github.com/ruby/set -* https://rubygems.org/gems/set - #### lib/shellwords.rb -* Akinori MUSHA (knu) + +* Akinori MUSHA ([knu]) * https://github.com/ruby/shellwords * https://rubygems.org/gems/shellwords #### lib/singleton.rb -* Yukihiro Matsumoto (matz) + +* Yukihiro Matsumoto ([matz]) * https://github.com/ruby/singleton * https://rubygems.org/gems/singleton #### lib/tempfile.rb + * *unmaintained* * https://github.com/ruby/tempfile * https://rubygems.org/gems/tempfile #### lib/time.rb -* Tanaka Akira (akr) + +* Tanaka Akira ([akr]) * https://github.com/ruby/time * https://rubygems.org/gems/time #### lib/timeout.rb -* Yukihiro Matsumoto (matz) + +* Yukihiro Matsumoto ([matz]) * https://github.com/ruby/timeout * https://rubygems.org/gems/timeout #### lib/thwait.rb -* Keiju ISHITSUKA (keiju) + +* Keiju ISHITSUKA ([keiju]) * https://github.com/ruby/thwait * https://rubygems.org/gems/thwait #### lib/tmpdir.rb + * *unmaintained* * https://github.com/ruby/tmpdir * https://rubygems.org/gems/tmpdir #### lib/tsort.rb -* Tanaka Akira (akr) + +* Tanaka Akira ([akr]) * https://github.com/ruby/tsort * https://rubygems.org/gems/tsort #### lib/un.rb -* WATANABE Hirofumi (eban) + +* WATANABE Hirofumi ([eban]) * https://github.com/ruby/un * https://rubygems.org/gems/un #### lib/uri.rb, lib/uri/* -* NARUSE, Yui (naruse) + +* NARUSE, Yui ([nurse]) * https://github.com/ruby/uri * https://rubygems.org/gems/uri #### lib/yaml.rb, lib/yaml/* -* Aaron Patterson (tenderlove) -* Hiroshi SHIBATA (hsbt) + +* Aaron Patterson ([tenderlove]) +* Hiroshi SHIBATA ([hsbt]) * https://github.com/ruby/yaml * https://rubygems.org/gems/yaml #### lib/weakref.rb + * *unmaintained* * https://github.com/ruby/weakref * https://rubygems.org/gems/weakref ### Extensions -#### ext/bigdecimal -* Kenta Murata (mrkn) https://github.com/ruby/bigdecimal -* https://rubygems.org/gems/bigdecimal #### ext/cgi -* Nobuyoshi Nakada (nobu) -* https://github.com/ruby/cgi -* https://rubygems.org/gems/cgi + +* Nobuyoshi Nakada ([nobu]) #### ext/date + * *unmaintained* * https://github.com/ruby/date * https://rubygems.org/gems/date #### ext/etc + * *unmaintained* * https://github.com/ruby/etc * https://rubygems.org/gems/etc #### ext/fcntl + * *unmaintained* * https://github.com/ruby/fcntl * https://rubygems.org/gems/fcntl -#### ext/fiddle -* Aaron Patterson (tenderlove) -* https://github.com/ruby/fiddle -* https://rubygems.org/gems/fiddle - #### ext/io/console -* Nobuyuki Nakada (nobu) + +* Nobuyuki Nakada ([nobu]) * https://github.com/ruby/io-console * https://rubygems.org/gems/io-console #### ext/io/nonblock -* Nobuyuki Nakada (nobu) + +* Nobuyuki Nakada ([nobu]) * https://github.com/ruby/io-nonblock * https://rubygems.org/gems/io-nonblock #### ext/io/wait -* Nobuyuki Nakada (nobu) + +* Nobuyuki Nakada ([nobu]) * https://github.com/ruby/io-wait * https://rubygems.org/gems/io-wait #### ext/json -* NARUSE, Yui (naruse) -* Hiroshi SHIBATA (hsbt) -* https://github.com/flori/json -* https://rubygems.org/gems/json -#### ext/nkf -* NARUSE, Yui (naruse) -* https://github.com/ruby/nkf -* https://rubygems.org/gems/nkf +* NARUSE, Yui ([nurse]) +* Hiroshi SHIBATA ([hsbt]) +* Jean Boussier ([byroot]) +* https://github.com/ruby/json +* https://rubygems.org/gems/json #### ext/openssl -* Kazuki Yamaguchi (rhe) + +* Kazuki Yamaguchi ([rhenium]) * https://github.com/ruby/openssl * https://rubygems.org/gems/openssl #### ext/pathname -* Tanaka Akira (akr) + +* Tanaka Akira ([akr]) * https://github.com/ruby/pathname * https://rubygems.org/gems/pathname #### ext/psych -* Aaron Patterson (tenderlove) -* Hiroshi SHIBATA (hsbt) + +* Aaron Patterson ([tenderlove]) +* Hiroshi SHIBATA ([hsbt]) * https://github.com/ruby/psych * https://rubygems.org/gems/psych #### ext/stringio -* Nobuyuki Nakada (nobu) + +* Nobuyuki Nakada ([nobu]) * https://github.com/ruby/stringio * https://rubygems.org/gems/stringio #### ext/strscan -* Kouhei Sutou (kou) + +* Kouhei Sutou ([kou]) * https://github.com/ruby/strscan * https://rubygems.org/gems/strscan -#### ext/syslog -* Akinori MUSHA (knu) -* https://github.com/ruby/syslog -* https://rubygems.org/gems/syslog - -#### ext/win32ole -* Masaki Suketa (suke) -* https://github.com/ruby/win32ole -* https://rubygems.org/gems/win32ole - #### ext/zlib -* NARUSE, Yui (naruse) + +* NARUSE, Yui ([nurse]) * https://github.com/ruby/zlib * https://rubygems.org/gems/zlib ## Bundled gems upstream repositories + ### minitest -* https://github.com/seattlerb/minitest + +* https://github.com/minitest/minitest ### power_assert + * https://github.com/ruby/power_assert ### rake + * https://github.com/ruby/rake ### test-unit + * https://github.com/test-unit/test-unit ### rexml + * https://github.com/ruby/rexml ### rss + * https://github.com/ruby/rss ### net-ftp + * https://github.com/ruby/net-ftp ### net-imap + * https://github.com/ruby/net-imap ### net-pop + * https://github.com/ruby/net-pop ### net-smtp + * https://github.com/ruby/net-smtp ### matrix + * https://github.com/ruby/matrix ### prime + * https://github.com/ruby/prime ### rbs + * https://github.com/ruby/rbs ### typeprof + * https://github.com/ruby/typeprof ### debug + * https://github.com/ruby/debug ### racc + * https://github.com/ruby/racc +#### mutex_m + +* https://github.com/ruby/mutex_m + +#### getoptlong + +* https://github.com/ruby/getoptlong + +#### base64 + +* https://github.com/ruby/base64 + +#### bigdecimal + +* https://github.com/ruby/bigdecimal + +#### observer + +* https://github.com/ruby/observer + +#### abbrev + +* https://github.com/ruby/abbrev + +#### resolv-replace + +* https://github.com/ruby/resolv-replace + +#### rinda + +* https://github.com/ruby/rinda + +#### drb + +* https://github.com/ruby/drb + +#### nkf + +* https://github.com/ruby/nkf + +#### syslog + +* https://github.com/ruby/syslog + +#### csv + +* https://github.com/ruby/csv + +#### ostruct + +* https://github.com/ruby/ostruct + +#### pstore + +* https://github.com/ruby/pstore + +#### benchmark + +* https://github.com/ruby/benchmark + +#### logger + +* https://github.com/ruby/logger + +#### rdoc + +* https://github.com/ruby/rdoc + +#### win32ole + +* https://github.com/ruby/win32ole + +#### irb + +* https://github.com/ruby/irb + +#### reline + +* https://github.com/ruby/reline + +#### readline + +* https://github.com/ruby/readline + +#### fiddle + +* https://github.com/ruby/fiddle ## Platform Maintainers + ### mswin64 (Microsoft Windows) -* NAKAMURA Usaku (usa) + +* NAKAMURA Usaku ([unak]) ### mingw32 (Minimalist GNU for Windows) -* Nobuyoshi Nakada (nobu) + +* Nobuyoshi Nakada ([nobu]) ### AIX -* Yutaka Kanemoto (kanemoto) + +* Yutaka Kanemoto ([kanemoto]) ### FreeBSD -* Akinori MUSHA (knu) + +* Akinori MUSHA ([knu]) ### Solaris -* Naohisa Goto (ngoto) + +* Naohisa Goto ([ngoto]) ### RHEL, CentOS -* KOSAKI Motohiro (kosaki) + +* KOSAKI Motohiro ([kosaki]) ### macOS -* Kenta Murata (mrkn) + +* Kenta Murata ([mrkn]) ### OpenBSD -* Jeremy Evans (jeremyevans0) + +* Jeremy Evans ([jeremyevans]) ### cygwin, ... + * none. (Maintainer WANTED) ### WebAssembly/WASI -* Yuta Saito (katei) + +* Yuta Saito ([kateinoigakukun]) + +[akr]: https://github.com/akr +[byroot]: https://github.com/byroot +[colby-swandale]: https://github.com/colby-swandale +[drbrain]: https://github.com/drbrain +[duerst]: https://github.com/duerst +[eban]: https://github.com/eban +[eileencodes]: https://github.com/eileencodes +[hasumikin]: https://github.com/hasumikin +[hsbt]: https://github.com/hsbt +[ima1zumi]: https://github.com/ima1zumi +[jeremyevans]: https://github.com/jeremyevans +[k-tsj]: https://github.com/k-tsj +[k0kubun]: https://github.com/k0kubun +[kanemoto]: https://github.com/kanemoto +[kateinoigakukun]: https://github.com/kateinoigakukun +[kddnewton]: https://github.com/kddnewton +[keiju]: https://github.com/keiju +[knu]: https://github.com/knu +[ko1]: https://github.com/ko1 +[kosaki]: https://github.com/kosaki +[kou]: https://github.com/kou +[mame]: https://github.com/mame +[marcandre]: https://github.com/marcandre +[matz]: https://github.com/matz +[mrkn]: https://github.com/mrkn +[ngoto]: https://github.com/ngoto +[nobu]: https://github.com/nobu +[nurse]: https://github.com/nurse +[rhenium]: https://github.com/rhenium +[seki]: https://github.com/seki +[suketa]: https://github.com/suketa +[sonots]: https://github.com/sonots +[st0012]: https://github.com/st0012 +[tenderlove]: https://github.com/tenderlove +[tompng]: https://github.com/tompng +[unak]: https://github.com/unak +[yuki24]: https://github.com/yuki24 diff --git a/doc/marshal.rdoc b/doc/marshal.rdoc index abf9467262a3e9..740064ade66afa 100644 --- a/doc/marshal.rdoc +++ b/doc/marshal.rdoc @@ -188,9 +188,9 @@ bytes: result += (byte * 2 ** (exp * 8)) end -=== Class and Module +=== +Class+ and +Module+ -"c" represents a Class object, "m" represents a Module and "M" represents +"c" represents a +Class+ object, "m" represents a +Module+ and "M" represents either a class or module (this is an old-style for compatibility). No class or module content is included, this type is only a reference. Following the type byte is a byte sequence which is used to look up an existing class or @@ -301,6 +301,11 @@ sequence containing the user-defined representation of the object. The class method +_load+ is called on the class with a string created from the byte-sequence. +This type is not recommended for newly created classes, because of some +restrictions: + +- cannot have recursive reference + === User Marshal "U" represents an object with a user-defined serialization format using the diff --git a/doc/matchdata/bytebegin.rdoc b/doc/matchdata/bytebegin.rdoc new file mode 100644 index 00000000000000..5b40a7ef73ce4a --- /dev/null +++ b/doc/matchdata/bytebegin.rdoc @@ -0,0 +1,30 @@ +Returns the offset (in bytes) of the beginning of the specified match. + +When non-negative integer argument +n+ is given, +returns the offset of the beginning of the nth match: + + m = /(.)(.)(\d+)(\d)/.match("THX1138.") + # => # + m[0] # => "HX1138" + m.bytebegin(0) # => 1 + m[3] # => "113" + m.bytebegin(3) # => 3 + + m = /(т)(е)(с)/.match('тест') + # => # + m[0] # => "тес" + m.bytebegin(0) # => 0 + m[3] # => "с" + m.bytebegin(3) # => 4 + +When string or symbol argument +name+ is given, +returns the offset of the beginning for the named match: + + m = /(?.)(.)(?.)/.match("hoge") + # => # + m[:foo] # => "h" + m.bytebegin('foo') # => 0 + m[:bar] # => "g" + m.bytebegin(:bar) # => 2 + +Related: MatchData#byteend, MatchData#byteoffset. diff --git a/doc/matchdata/byteend.rdoc b/doc/matchdata/byteend.rdoc new file mode 100644 index 00000000000000..eb576640220b05 --- /dev/null +++ b/doc/matchdata/byteend.rdoc @@ -0,0 +1,30 @@ +Returns the offset (in bytes) of the end of the specified match. + +When non-negative integer argument +n+ is given, +returns the offset of the end of the nth match: + + m = /(.)(.)(\d+)(\d)/.match("THX1138.") + # => # + m[0] # => "HX1138" + m.byteend(0) # => 7 + m[3] # => "113" + m.byteend(3) # => 6 + + m = /(т)(е)(с)/.match('тест') + # => # + m[0] # => "тес" + m.byteend(0) # => 6 + m[3] # => "с" + m.byteend(3) # => 6 + +When string or symbol argument +name+ is given, +returns the offset of the end for the named match: + + m = /(?.)(.)(?.)/.match("hoge") + # => # + m[:foo] # => "h" + m.byteend('foo') # => 1 + m[:bar] # => "g" + m.byteend(:bar) # => 3 + +Related: MatchData#bytebegin, MatchData#byteoffset. diff --git a/doc/math/math.rdoc b/doc/math/math.rdoc index 7a89df951ce483..29783755646b3c 100644 --- a/doc/math/math.rdoc +++ b/doc/math/math.rdoc @@ -1,4 +1,4 @@ -\Module \Math provides methods for basic trigonometric, +Module \Math provides methods for basic trigonometric, logarithmic, and transcendental functions, and for extracting roots. You can write its constants and method calls thus: diff --git a/doc/namespace.md b/doc/namespace.md new file mode 100644 index 00000000000000..eee6b940725bbb --- /dev/null +++ b/doc/namespace.md @@ -0,0 +1,418 @@ +# Namespace - Ruby's in-process separation of Classes and Modules + +Namespace is designed to provide separated spaces in a Ruby process, to isolate applications and libraries. + +## Known issues + +* Experimental warning is shown when ruby starts with `RUBY_NAMESPACE=1` (specify `-W:no-experimental` option to hide it) +* `bundle install` may fail +* `require 'active_support'` may fail +* A wrong current namespace detection happens sometimes in the root namespace + +## TODOs + +* Identify the CI failure cause and restore temporarily skipped tests (mmtk, test/ruby/test_allocation on i686) +* Reconstruct current/loading namespace management based on control frames +* Add the loaded namespace on iseq to check if another namespace tries running the iseq (add a field only when VM_CHECK_MODE?) +* Delete per-namespace extension files (.so) lazily or process exit +* Collect rb_classext_t entries for a namespace when the namespace is collected +* Allocate an rb_namespace_t entry as the root namespace at first, then construct the contents and wrap it as rb_cNamespace instance later (to eliminate root/builtin two namespaces situation) +* Assign its own TOPLEVEL_BINDING in namespaces +* Fix `warn` in namespaces to refer `$VERBOSE` in the namespace +* Make an internal data container `Namespace::Entry` invisible +* More test cases about `$LOAD_PATH` and `$LOADED_FEATURES` +* Return classpath and nesting without the namespace prefix in the namespace itself [#21316](https://bugs.ruby-lang.org/issues/21316), [#21318](https://bugs.ruby-lang.org/issues/21318) + +## How to use + +### Enabling namespace + +First, an environment variable should be set at the ruby process bootup: `RUBY_NAMESPACE=1`. +The only valid value is `1` to enable namespace. Other values (or unset `RUBY_NAMESPACE`) means disabling namespace. And setting the value after Ruby program starts doesn't work. + +### Using namespace + +`Namespace` class is the entrypoint of namespaces. + +```ruby +ns = Namespace.new +ns.require('something') # or require_relative, load +``` + +The required file (either .rb or .so/.dll/.bundle) is loaded in the namespace (`ns` here). The required/loaded files from `something` will be loaded in the namespace recursively. + +```ruby +# something.rb + +X = 1 + +class Something + def self.x = X + def x = ::X +end +``` + +Classes/modules, those methods and constants defined in the namespace can be accessed via `ns` object. + +```ruby +p ns::Something.x # 1 + +X = 2 +p X # 2 +p ::X # 2 +p ns::Something.x # 1 +p ns::X # 1 +``` + +Instance methods defined in the namespace also run with definitions in the namespace. + +```ruby +s = ns::Something.new + +p s.x # 1 +``` + +## Specifications + +### Namespace types + +There are two namespace types: + +* Root namespace +* User namespace + +There is the root namespace, just a single namespace in a Ruby process. Ruby bootstrap runs in the root namespace, and all builtin classes/modules are defined in the root namespace. (See "Builtin classes and modules".) + +User namespaces are to run user-written programs and libraries loaded from user programs. The user's main program (specified by the `ruby` command line argument) is executed in the "main" namespace, which is a user namespace automatically created at the end of Ruby's bootstrap, copied from the root namespace. + +When `Namespace.new` is called, an "optional" namespace (a user, non-main namespace) is created, copied from the root namespace. All user namespaces are flat, copied from the root namespace. + +### Namespace class and instances + +`Namespace` is a top level class, as a subclass of `Module`, and `Namespace` instances are a kind of `Module`. + +### Classes and modules defined in namespace + +The classes and modules, newly defined in a namespace `ns`, are defined under `ns`. For example, if a class `A` is defined in `ns`, it is actually defined as `ns::A`. + +In the namespace `ns`, `ns::A` can be referred to as `A` (and `::A`). From outside of `ns`, it can be referred to as `ns::A`. + +The main namespace is exceptional. Top level classes and modules defined in the main namespace are just top level classes and modules. + +### Classes and modules reopened in namespace + +In namespaces, builtin classes/modules are visible and can be reopened. Those classes/modules can be reopened using `class` or `module` clauses, and class/module definitions can be changed. + +The changed definitions are visible only in the namespace. In other namespaces, builtin classes/modules and those instances work without changed definitions. + +```ruby +# in foo.rb +class String + BLANK_PATTERN = /\A\s*\z/ + def blank? + self =~ BLANK_PATTERN + end +end + +module Foo + def self.foo = "foo" + + def self.foo_is_blank? + foo.blank? + end +end + +Foo.foo.blank? #=> false +"foo".blank? #=> false + +# in main.rb +ns = Namespace.new +ns.require('foo') + +Foo.foo_is_blank? #=> false (#blank? called in ns) + +Foo.foo.blank? # NoMethodError +"foo".blank? # NoMethodError +String::BLANK_PATTERN # NameError +``` + +The main namespace and `ns` are different namespaces, so monkey patches in main are also invisible in `ns`. + +### Builtin classes and modules + +In the namespace context, "builtin" classes and modules are classes and modules: + +* Accessible without any `require` calls in user scripts +* Defined before any user program start running +* Including classes/modules loaded by `prelude.rb` (including RubyGems `Gem`, for example) + +Hereafter, "builtin classes and modules" will be referred to as just "builtin classes". + +### Builtin classes referred via namespace objects + +Builtin classes in a namespace `ns` can be referred from other namespace. For example, `ns::String` is a valid reference, and `String` and `ns::String` are identical (`String == ns::String`, `String.object_id == ns::String.object_id`). + +`ns::String`-like reference returns just a `String` in the current namespace, so its definition is `String` in the namespace, not in `ns`. + +```ruby +# foo.rb +class String + def self.foo = "foo" +end + +# main.rb +ns = Namespace.new +ns.require('foo') + +ns::String.foo # NoMethodError +``` + +### Class instance variables, class variables, constants + +Builtin classes can have different sets of class instance variables, class variables and constants between namespaces. + +```ruby +# foo.rb +class Array + @v = "foo" + @@v = "_foo_" + V = "FOO" +end + +Array.instance_variable_get(:@v) #=> "foo" +Array.class_variable_get(:@@v) #=> "_foo_" +Array.const_get(:V) #=> "FOO" + +# main.rb +ns = Namespace.new +ns.require('foo') + +Array.instance_variable_get(:@v) #=> nil +Array.class_variable_get(:@@v) # NameError +Array.const_get(:V) # NameError +``` + +### Global variables + +In namespaces, changes on global variables are also isolated in the namespace. Changes on global variables in a namespace are visible/applied only in the namespace. + +```ruby +# foo.rb +$foo = "foo" +$VERBOSE = nil + +puts "This appears: '#{$foo}'" + +# main.rb +p $foo #=> nil +p $VERBOSE #=> false + +ns = Namespace.new +ns.require('foo') # "This appears: 'foo'" + +p $foo #=> nil +p $VERBOSE #=> false +``` + +### Top level constants + +Usually, top level constants are defined as constants of `Object`. In namespaces, top level constants are constants of `Object` in the namespace. And the namespace object `ns`'s constants are strictly equal to constants of `Object`. + +```ruby +# foo.rb +FOO = 100 + +FOO #=> 100 +Object::FOO #=> 100 + +# main.rb +ns = Namespace.new +ns.require('foo') + +ns::FOO #=> 100 + +FOO # NameError +Object::FOO # NameError +``` + +### Top level methods + +Top level methods are private instance methods of `Object`, in each namespace. + +```ruby +# foo.rb +def yay = "foo" + +class Foo + def self.say = yay +end + +Foo.say #=> "foo" +yay #=> "foo" + +# main.rb +ns = Namespace.new +ns.require('foo') + +ns.Foo.say #=> "foo" + +yay # NoMethodError +``` + +There is no way to expose top level methods in namespaces to another namespace. +(See "Expose top level methods as a method of the namespace object" in "Discussions" section below) + +### Namespace scopes + +Namespace works in file scope. One `.rb` file runs in a single namespace. + +Once a file is loaded in a namespace `ns`, all methods/procs defined/created in the file run in `ns`. + +## Implementation details + +#### Object Shapes + +Once builtin classes are copied and modified in namespaces, its instance variable management fallbacks from Object Shapes to a traditional iv table (st_table) because RClass stores the shape in its `flags`, not in `rb_classext_t`. + +#### Size of RClass and rb_classext_t + +Namespace requires to move some fields from RClass to `rb_classext_t`, then the size of RClass and `rb_classext_t` is now larger than `4 * RVALUE_SIZE`. It's against the expectation of [Variable Width Allocation](https://rubykaigi.org/2021-takeout/presentations/peterzhu2118.html). + +Now the `STATIC_ASSERT` to check the size is commented-out. (See "Minimize the size of RClass and rb_classext_t" in "Discussion" section below) + +#### ISeq inline method/constant cache + +As described above in "Namespace scopes", an ".rb" file runs in a namespace. So method/constant resolution will be done in a namespace consistently. + +That means ISeq inline caches work well even with namespaces. Otherwise, it's a bug. + +#### Method call global cache (gccct) + +`rb_funcall()` C function refers to the global cc cache table (gccct), and the cache key is calculated with the current namespace. + +So, `rb_funcall()` calls have a performance penalty when namespace is enabled. + +#### Current namespace and loading namespace + +The current namespace is the namespace that the executing code is in. `Namespace.current` returns the current namespace object. + +The loading namespace is an internally managed namespace to determine the namespace to load newly required/loaded files. For example, `ns` is the loading namespace when `ns.require("foo")` is called. + +## Discussions + +#### Namespace#inspect + +Currently, `Namespace#inspect` returns values like `"#"`. This results in the very redundant and poorly visible classpath outside the namespace. + +```ruby +# foo.rb +class C; end + +# main.rb +ns = Namespace.new +ns.require('foo') + +p ns::C # "#::C" +``` + +And currently, if a namespace is assigned to a constant `NS1`, the classpath output will be `NS1::C`. But the namespace object can be brought to another namespace and the constant `NS1` in the namespace is something different. So the constant-based classpath for namespace is not safe basically. + +So we should find a better format to show namespaces. Options are: + +* `NS1::C` (only when this namespace is created and assigned to NS1 in the current namespace) +* `#::C` (with namespace type and without preceding 0) +* or something else + +#### Namespace#eval + +Testing namespace features needs to create files to be loaded in namespaces. It's not easy nor casual. + +If `Namespace` class has an instance method `#eval` to evaluate code in the namespace, it can be helpful. + +#### More builtin methods written in Ruby + +If namespace is enabled by default, builtin methods can be written in Ruby because it can't be overridden by users' monkey patches. Builtin Ruby methods can be JIT-ed, and it could bring performance reward. + +#### Monkey patching methods called by builtin methods + +Builtin methods sometimes call other builtin methods. For example, `Hash#map` calls `Hash#each` to retrieve entries to be mapped. Without namespace, Ruby users can overwrite `Hash#each` and expect the behavior change of `Hash#map` as a result. + +But with namespaces, `Hash#map` runs in the root namespace. Ruby users can define `Hash#each` only in user namespaces, so users cannot change `Hash#map`'s behavior in this case. To achieve it, users should override both`Hash#map` and `Hash#each` (or only `Hash#map`). + +It is a breaking change. + +It's an option to change the behavior of methods in the root namespace to refer to definitions in user namespaces. But if we do so, that means we can't proceed with "More builtin methods written in Ruby". + +#### Context of \$LOAD\_PATH and \$LOADED\_FEATURES + +Global variables `$LOAD_PATH` and `$LOADED_FEATURES` control `require` method behaviors. So those namespaces are determined by the loading namespace instead of the current namespace. + +This could potentially conflict with the user's expectations. We should find the solution. + +#### Expose top level methods as a method of the namespace object + +Currently, top level methods in namespaces are not accessible from outside of the namespace. But there might be a use case to call other namespace's top level methods. + +#### Split root and builtin namespace + +NOTE: "builtin" namespace is a different one from the "builtin" namespace in the current implementation + +Currently, the single "root" namespace is the source of classext CoW. And also, the "root" namespace can load additional files after starting main script evaluation by calling methods which contain lines like `require "openssl"`. + +That means, user namespaces can have different sets of definitions according to when it is created. + +``` +[root] + | + |----[main] + | + |(require "openssl" called in root) + | + |----[ns1] having OpenSSL + | + |(remove_const called for OpenSSL in root) + | + |----[ns2] without OpenSSL +``` + +This could cause unexpected behavior differences between user namespaces. It should NOT be a problem because user scripts which refer to `OpenSSL` should call `require "openssl"` by themselves. +But in the worst case, a script (without `require "openssl"`) runs well in `ns1`, but doesn't run in `ns2`. This situation looks like a "random failure" to users. + +An option possible to prevent this situation is to have "root" and "builtin" namespaces. + +* root + * The namespace for the Ruby process bootstrap, then the source of CoW + * After starting the main namespace, no code runs in this namespace +* builtin + * The namespace copied from the root namespace at the same time with "main" + * Methods and procs defined in the "root" namespace run in this namespace + * Classes and modules required will be loaded in this namespace + +This design realizes a consistent source of namespace CoW. + +#### Separate cc_tbl and callable_m_tbl, cvc_tbl for less classext CoW + +The fields of `rb_classext_t` contains several cache(-like) data, `cc_tbl`(callcache table), `callable_m_tbl`(table of resolved complemented methods) and `cvc_tbl`(class variable cache table). + +The classext CoW is triggered when the contents of `rb_classext_t` are changed, including `cc_tbl`, `callable_m_tbl`, and `cvc_tbl`. But those three tables are changed by just calling methods or referring class variables. So, currently, classext CoW is triggered much more times than the original expectation. + +If we can move those three tables outside of `rb_classext_t`, the number of copied `rb_classext_t` will be much less than the current implementation. + +#### Object Shapes per namespace + +Now the classext CoW requires RClass and `rb_classext_t` to fallback its instance variable management from Object Shapes to the traditional `st_table`. It may have a performance penalty. + +If we can apply Object Shapes on `rb_classext_t` instead of `RClass`, per-namespace classext can have its own shapes, and it may be able to avoid the performance penalty. + +#### Minimize the size of RClass and rb_classext_t + +As described in "Size of RClass and rb_classext_t" section above, the size of RClass and `rb_classext_t` is currently larger than `4 * RVALUE_SIZE` (`20 * VALUE_SIZE`). Now the size is `23 * VALUE_SIZE + 7 bits`. + +The fields possibly removed from `rb_classext_t` are: + +* `cc_tbl`, `callable_m_tbl`, `cvc_tbl` (See the section "Separate cc_tbl and callable_m_tbl, cvc_tbl for less classext CoW" above) +* `ns_super_subclasses`, `module_super_subclasses` + * `RCLASSEXT_SUBCLASSES(RCLASS_EXT_PRIME(RCLASSEXT_SUPER(klass)))->ns_subclasses` can replace it + * These fields are used only in GC, how's the actual performance benefit? + +If we can move or remove those fields, the size satisfies the assertion (`<= 4 * RVALUE_SIZE`). diff --git a/doc/optparse/argument_converters.rdoc b/doc/optparse/argument_converters.rdoc index 4b4b30e8de58b5..532729871c5187 100644 --- a/doc/optparse/argument_converters.rdoc +++ b/doc/optparse/argument_converters.rdoc @@ -377,4 +377,4 @@ Executions: $ ruby match_converter.rb --capitalize foo ["Foo", String] $ ruby match_converter.rb --capitalize "foo bar" - match_converter.rb:9:in `
': invalid argument: --capitalize foo bar (OptionParser::InvalidArgument) + match_converter.rb:9:in '
': invalid argument: --capitalize foo bar (OptionParser::InvalidArgument) diff --git a/doc/optparse/option_params.rdoc b/doc/optparse/option_params.rdoc index 55f9b53dfff266..575ee66cdb0e17 100644 --- a/doc/optparse/option_params.rdoc +++ b/doc/optparse/option_params.rdoc @@ -31,7 +31,7 @@ Contents: - {Long Names with Optional Arguments}[#label-Long+Names+with+Optional+Arguments] - {Long Names with Negation}[#label-Long+Names+with+Negation] - {Mixed Names}[#label-Mixed+Names] -- {Argument Styles}[#label-Argument+Styles] +- {Argument Strings}[#label-Argument+Strings] - {Argument Values}[#label-Argument+Values] - {Explicit Argument Values}[#label-Explicit+Argument+Values] - {Explicit Values in Array}[#label-Explicit+Values+in+Array] @@ -91,7 +91,7 @@ Executions: Usage: short_required [options] -xXXX Short name with required argument $ ruby short_required.rb -x - short_required.rb:6:in `
': missing argument: -x (OptionParser::MissingArgument) + short_required.rb:6:in '
': missing argument: -x (OptionParser::MissingArgument) $ ruby short_required.rb -x FOO ["-x", "FOO"] @@ -181,7 +181,7 @@ Executions: Usage: long_required [options] --xxx XXX Long name with required argument $ ruby long_required.rb --xxx - long_required.rb:6:in `
': missing argument: --xxx (OptionParser::MissingArgument) + long_required.rb:6:in '
': missing argument: --xxx (OptionParser::MissingArgument) $ ruby long_required.rb --xxx FOO ["--xxx", "FOO"] @@ -243,11 +243,11 @@ Usage: mixed_names [options] $ ruby mixed_names.rb --xxx ["--xxx", true] $ ruby mixed_names.rb -y - mixed_names.rb:12:in `
': missing argument: -y (OptionParser::MissingArgument) + mixed_names.rb:12:in '
': missing argument: -y (OptionParser::MissingArgument) $ ruby mixed_names.rb -y FOO ["--yyy", "FOO"] $ ruby mixed_names.rb --yyy - mixed_names.rb:12:in `
': missing argument: --yyy (OptionParser::MissingArgument) + mixed_names.rb:12:in '
': missing argument: --yyy (OptionParser::MissingArgument) $ ruby mixed_names.rb --yyy BAR ["--yyy", "BAR"] $ ruby mixed_names.rb -z @@ -279,7 +279,7 @@ Executions: Usage: argument_keywords [options] -x, --xxx Required argument $ ruby argument_styles.rb --xxx - argument_styles.rb:6:in `
': missing argument: --xxx (OptionParser::MissingArgument) + argument_styles.rb:6:in '
': missing argument: --xxx (OptionParser::MissingArgument) $ ruby argument_styles.rb --xxx FOO ["--xxx", "FOO"] @@ -298,7 +298,7 @@ Executions: Usage: argument_strings [options] -x, --xxx=XXX Required argument $ ruby argument_strings.rb --xxx - argument_strings.rb:9:in `
': missing argument: --xxx (OptionParser::MissingArgument) + argument_strings.rb:9:in '
': missing argument: --xxx (OptionParser::MissingArgument) $ ruby argument_strings.rb --xxx FOO ["--xxx", "FOO"] @@ -331,7 +331,7 @@ Executions: -xXXX Values for required argument -y [YYY] Values for optional argument $ ruby explicit_array_values.rb -x - explicit_array_values.rb:9:in `
': missing argument: -x (OptionParser::MissingArgument) + explicit_array_values.rb:9:in '
': missing argument: -x (OptionParser::MissingArgument) $ ruby explicit_array_values.rb -x foo ["-x", "foo"] $ ruby explicit_array_values.rb -x f @@ -339,9 +339,9 @@ Executions: $ ruby explicit_array_values.rb -x bar ["-x", "bar"] $ ruby explicit_array_values.rb -y ba - explicit_array_values.rb:9:in `
': ambiguous argument: -y ba (OptionParser::AmbiguousArgument) + explicit_array_values.rb:9:in '
': ambiguous argument: -y ba (OptionParser::AmbiguousArgument) $ ruby explicit_array_values.rb -x baz - explicit_array_values.rb:9:in `
': invalid argument: -x baz (OptionParser::InvalidArgument) + explicit_array_values.rb:9:in '
': invalid argument: -x baz (OptionParser::InvalidArgument) ===== Explicit Values in Hash @@ -361,7 +361,7 @@ Executions: -xXXX Values for required argument -y [YYY] Values for optional argument $ ruby explicit_hash_values.rb -x - explicit_hash_values.rb:9:in `
': missing argument: -x (OptionParser::MissingArgument) + explicit_hash_values.rb:9:in '
': missing argument: -x (OptionParser::MissingArgument) $ ruby explicit_hash_values.rb -x foo ["-x", 0] $ ruby explicit_hash_values.rb -x f @@ -369,7 +369,7 @@ Executions: $ ruby explicit_hash_values.rb -x bar ["-x", 1] $ ruby explicit_hash_values.rb -x baz - explicit_hash_values.rb:9:in `
': invalid argument: -x baz (OptionParser::InvalidArgument) + explicit_hash_values.rb:9:in '
': invalid argument: -x baz (OptionParser::InvalidArgument) $ ruby explicit_hash_values.rb -y ["-y", nil] $ ruby explicit_hash_values.rb -y baz @@ -377,14 +377,15 @@ Executions: $ ruby explicit_hash_values.rb -y bat ["-y", 3] $ ruby explicit_hash_values.rb -y ba - explicit_hash_values.rb:9:in `
': ambiguous argument: -y ba (OptionParser::AmbiguousArgument) + explicit_hash_values.rb:9:in '
': ambiguous argument: -y ba (OptionParser::AmbiguousArgument) $ ruby explicit_hash_values.rb -y bam ["-y", nil] ==== Argument Value Patterns You can restrict permissible argument values -by specifying a Regexp that the given argument must match. +by specifying a +Regexp+ that the given argument must match, +or a +Range+ or +Array+ that the converted value must be included in. File +matched_values.rb+ defines options with matched argument values. @@ -395,12 +396,22 @@ Executions: $ ruby matched_values.rb --help Usage: matched_values [options] --xxx XXX Matched values + --yyy YYY Check by range + --zzz ZZZ Check by list $ ruby matched_values.rb --xxx foo ["--xxx", "foo"] $ ruby matched_values.rb --xxx FOO ["--xxx", "FOO"] $ ruby matched_values.rb --xxx bar - matched_values.rb:6:in `
': invalid argument: --xxx bar (OptionParser::InvalidArgument) + matched_values.rb:12:in '
': invalid argument: --xxx bar (OptionParser::InvalidArgument) + $ ruby matched_values.rb --yyy 1 + ["--yyy", 1] + $ ruby matched_values.rb --yyy 4 + matched_values.rb:12:in '
': invalid argument: --yyy 4 (OptionParser::InvalidArgument) + $ ruby matched_values.rb --zzz 1 + ["--zzz", 1] + $ ruby matched_values.rb --zzz 2 + matched_values.rb:12:in '
': invalid argument: --zzz 2 (OptionParser::InvalidArgument) === Argument Converters diff --git a/doc/optparse/ruby/argument_abbreviation.rb b/doc/optparse/ruby/argument_abbreviation.rb new file mode 100644 index 00000000000000..49007ebe69595f --- /dev/null +++ b/doc/optparse/ruby/argument_abbreviation.rb @@ -0,0 +1,9 @@ +require 'optparse' +parser = OptionParser.new +parser.on('-x', '--xxx=VALUE', %w[ABC def], 'Argument abbreviations') do |value| + p ['--xxx', value] +end +parser.on('-y', '--yyy=VALUE', {"abc"=>"XYZ", def: "FOO"}, 'Argument abbreviations') do |value| + p ['--yyy', value] +end +parser.parse! diff --git a/doc/optparse/ruby/matched_values.rb b/doc/optparse/ruby/matched_values.rb index f184ca8474a852..a1aba140e6d86a 100644 --- a/doc/optparse/ruby/matched_values.rb +++ b/doc/optparse/ruby/matched_values.rb @@ -3,4 +3,10 @@ parser.on('--xxx XXX', /foo/i, 'Matched values') do |value| p ['--xxx', value] end +parser.on('--yyy YYY', Integer, 'Check by range', 1..3) do |value| + p ['--yyy', value] +end +parser.on('--zzz ZZZ', Integer, 'Check by list', [1, 3, 4]) do |value| + p ['--zzz', value] +end parser.parse! diff --git a/doc/optparse/tutorial.rdoc b/doc/optparse/tutorial.rdoc index b104379cf767cc..1134f94ddf0d46 100644 --- a/doc/optparse/tutorial.rdoc +++ b/doc/optparse/tutorial.rdoc @@ -111,7 +111,7 @@ Executions: ["x", true] ["input_file.txt", "output_file.txt"] $ ruby basic.rb -a - basic.rb:16:in `
': invalid option: -a (OptionParser::InvalidOption) + basic.rb:16:in '
': invalid option: -a (OptionParser::InvalidOption) === Defining Options @@ -232,11 +232,11 @@ Executions: $ ruby mixed_names.rb --xxx ["--xxx", true] $ ruby mixed_names.rb -y - mixed_names.rb:12:in `
': missing argument: -y (OptionParser::MissingArgument) + mixed_names.rb:12:in '
': missing argument: -y (OptionParser::MissingArgument) $ ruby mixed_names.rb -y FOO ["--yyy", "FOO"] $ ruby mixed_names.rb --yyy - mixed_names.rb:12:in `
': missing argument: --yyy (OptionParser::MissingArgument) + mixed_names.rb:12:in '
': missing argument: --yyy (OptionParser::MissingArgument) $ ruby mixed_names.rb --yyy BAR ["--yyy", "BAR"] $ ruby mixed_names.rb -z @@ -270,9 +270,9 @@ Executions: $ ruby name_abbrev.rb --draft ["--draft", true] $ ruby name_abbrev.rb --d - name_abbrev.rb:9:in `
': ambiguous option: --d (OptionParser::AmbiguousOption) + name_abbrev.rb:9:in '
': ambiguous option: --d (OptionParser::AmbiguousOption) $ ruby name_abbrev.rb --dr - name_abbrev.rb:9:in `
': ambiguous option: --dr (OptionParser::AmbiguousOption) + name_abbrev.rb:9:in '
': ambiguous option: --dr (OptionParser::AmbiguousOption) $ ruby name_abbrev.rb --dry ["--dry-run", true] $ ruby name_abbrev.rb --dra @@ -285,7 +285,7 @@ You can disable abbreviation using method +require_exact+. Executions: $ ruby no_abbreviation.rb --dry-ru - no_abbreviation.rb:10:in `
': invalid option: --dry-ru (OptionParser::InvalidOption) + no_abbreviation.rb:10:in '
': invalid option: --dry-ru (OptionParser::InvalidOption) $ ruby no_abbreviation.rb --dry-run ["--dry-run", true] @@ -323,7 +323,7 @@ Executions: Omitting a required argument raises an error: $ ruby required_argument.rb -x - required_argument.rb:9:in `
': missing argument: -x (OptionParser::MissingArgument) + required_argument.rb:9:in '
': missing argument: -x (OptionParser::MissingArgument) ==== Option with Optional Argument @@ -351,6 +351,29 @@ Executions: Omitting an optional argument does not raise an error. +==== Argument Abbreviations + +Specify an argument list as an Array or a Hash. + + :include: ruby/argument_abbreviation.rb + +When an argument is abbreviated, the expanded argument yielded. + +Executions: + + $ ruby argument_abbreviation.rb --help + Usage: argument_abbreviation [options] + Usage: argument_abbreviation [options] + -x, --xxx=VALUE Argument abbreviations + -y, --yyy=VALUE Argument abbreviations + $ ruby argument_abbreviation.rb --xxx A + ["--xxx", "ABC"] + $ ruby argument_abbreviation.rb --xxx c + argument_abbreviation.rb:9:in '
': invalid argument: --xxx c (OptionParser::InvalidArgument) + $ ruby argument_abbreviation.rb --yyy a --yyy d + ["--yyy", "XYZ"] + ["--yyy", "FOO"] + === Argument Values Permissible argument values may be restricted @@ -380,7 +403,7 @@ Executions: -xXXX Values for required argument -y [YYY] Values for optional argument $ ruby explicit_array_values.rb -x - explicit_array_values.rb:9:in `
': missing argument: -x (OptionParser::MissingArgument) + explicit_array_values.rb:9:in '
': missing argument: -x (OptionParser::MissingArgument) $ ruby explicit_array_values.rb -x foo ["-x", "foo"] $ ruby explicit_array_values.rb -x f @@ -388,9 +411,9 @@ Executions: $ ruby explicit_array_values.rb -x bar ["-x", "bar"] $ ruby explicit_array_values.rb -y ba - explicit_array_values.rb:9:in `
': ambiguous argument: -y ba (OptionParser::AmbiguousArgument) + explicit_array_values.rb:9:in '
': ambiguous argument: -y ba (OptionParser::AmbiguousArgument) $ ruby explicit_array_values.rb -x baz - explicit_array_values.rb:9:in `
': invalid argument: -x baz (OptionParser::InvalidArgument) + explicit_array_values.rb:9:in '
': invalid argument: -x baz (OptionParser::InvalidArgument) ===== Explicit Values in Hash @@ -410,7 +433,7 @@ Executions: -xXXX Values for required argument -y [YYY] Values for optional argument $ ruby explicit_hash_values.rb -x - explicit_hash_values.rb:9:in `
': missing argument: -x (OptionParser::MissingArgument) + explicit_hash_values.rb:9:in '
': missing argument: -x (OptionParser::MissingArgument) $ ruby explicit_hash_values.rb -x foo ["-x", 0] $ ruby explicit_hash_values.rb -x f @@ -418,7 +441,7 @@ Executions: $ ruby explicit_hash_values.rb -x bar ["-x", 1] $ ruby explicit_hash_values.rb -x baz - explicit_hash_values.rb:9:in `
': invalid argument: -x baz (OptionParser::InvalidArgument) + explicit_hash_values.rb:9:in '
': invalid argument: -x baz (OptionParser::InvalidArgument) $ ruby explicit_hash_values.rb -y ["-y", nil] $ ruby explicit_hash_values.rb -y baz @@ -426,7 +449,7 @@ Executions: $ ruby explicit_hash_values.rb -y bat ["-y", 3] $ ruby explicit_hash_values.rb -y ba - explicit_hash_values.rb:9:in `
': ambiguous argument: -y ba (OptionParser::AmbiguousArgument) + explicit_hash_values.rb:9:in '
': ambiguous argument: -y ba (OptionParser::AmbiguousArgument) $ ruby explicit_hash_values.rb -y bam ["-y", nil] @@ -449,7 +472,7 @@ Executions: $ ruby matched_values.rb --xxx FOO ["--xxx", "FOO"] $ ruby matched_values.rb --xxx bar - matched_values.rb:6:in `
': invalid argument: --xxx bar (OptionParser::InvalidArgument) + matched_values.rb:6:in '
': invalid argument: --xxx bar (OptionParser::InvalidArgument) === Keyword Argument +into+ @@ -501,7 +524,7 @@ Executions: -y, --yyyYYY Short and long, required argument -z, --zzz [ZZZ] Short and long, optional argument $ ruby missing_options.rb --yyy FOO - missing_options.rb:11:in `
': Missing required options: [:xxx, :zzz] (RuntimeError) + missing_options.rb:11:in '
': Missing required options: [:xxx, :zzz] (RuntimeError) ==== Default Values for Options diff --git a/doc/packed_data.rdoc b/doc/packed_data.rdoc index 05d9ab758a0a8b..b33eed58e7e47c 100644 --- a/doc/packed_data.rdoc +++ b/doc/packed_data.rdoc @@ -1,15 +1,116 @@ -== Packed \Data += Packed \Data + +== Quick Reference + +These tables summarize the directives for packing and unpacking. + +=== For Integers + + Directive | Meaning + --------------|--------------------------------------------------------------- + C | 8-bit unsigned (unsigned char) + S | 16-bit unsigned, native endian (uint16_t) + L | 32-bit unsigned, native endian (uint32_t) + Q | 64-bit unsigned, native endian (uint64_t) + J | pointer width unsigned, native endian (uintptr_t) + + c | 8-bit signed (signed char) + s | 16-bit signed, native endian (int16_t) + l | 32-bit signed, native endian (int32_t) + q | 64-bit signed, native endian (int64_t) + j | pointer width signed, native endian (intptr_t) + + S_ S! | unsigned short, native endian + I I_ I! | unsigned int, native endian + L_ L! | unsigned long, native endian + Q_ Q! | unsigned long long, native endian + | (raises ArgumentError if the platform has no long long type) + J! | uintptr_t, native endian (same with J) + + s_ s! | signed short, native endian + i i_ i! | signed int, native endian + l_ l! | signed long, native endian + q_ q! | signed long long, native endian + | (raises ArgumentError if the platform has no long long type) + j! | intptr_t, native endian (same with j) + + S> s> S!> s!> | each the same as the directive without >, but big endian + L> l> L!> l!> | S> is the same as n + I!> i!> | L> is the same as N + Q> q> Q!> q!> | + J> j> J!> j!> | + + S< s< S!< s!< | each the same as the directive without <, but little endian + L< l< L!< l!< | S< is the same as v + I!< i!< | L< is the same as V + Q< q< Q!< q!< | + J< j< J!< j!< | + + n | 16-bit unsigned, network (big-endian) byte order + N | 32-bit unsigned, network (big-endian) byte order + v | 16-bit unsigned, VAX (little-endian) byte order + V | 32-bit unsigned, VAX (little-endian) byte order + + U | UTF-8 character + w | BER-compressed integer + +=== For Floats + + Directive | Meaning + ----------|-------------------------------------------------- + D d | double-precision, native format + F f | single-precision, native format + E | double-precision, little-endian byte order + e | single-precision, little-endian byte order + G | double-precision, network (big-endian) byte order + g | single-precision, network (big-endian) byte order + +=== For Strings + + Directive | Meaning + ----------|----------------------------------------------------------------- + A | arbitrary binary string (remove trailing nulls and ASCII spaces) + a | arbitrary binary string + Z | null-terminated string + B | bit string (MSB first) + b | bit string (LSB first) + H | hex string (high nibble first) + h | hex string (low nibble first) + u | UU-encoded string + M | quoted-printable, MIME encoding (see RFC2045) + m | base64 encoded string (RFC 2045) (default) + | (base64 encoded string (RFC 4648) if followed by 0) + P | pointer to a structure (fixed-length string) + p | pointer to a null-terminated string + +=== Additional Directives for Packing + + Directive | Meaning + ----------|---------------------------------------------------------------- + @ | moves to absolute position + X | back up a byte + x | null byte + +=== Additional Directives for Unpacking + + Directive | Meaning + ----------|---------------------------------------------------------------- + @ | skip to the offset given by the length argument + X | skip backward one byte + x | skip forward one byte + +== Packing and Unpacking Certain Ruby core methods deal with packing and unpacking data: -- \Method Array#pack: +- Method Array#pack: Formats each element in array +self+ into a binary string; returns that string. -- \Method String#unpack: +- Method String#unpack: Extracts data from string +self+, forming objects that become the elements of a new array; returns that array. -- \Method String#unpack1: +- Method String#unpack1: Does the same, but unpacks and returns only the first extracted object. Each of these methods accepts a string +template+, @@ -64,9 +165,9 @@ If elements don't fit the provided directive, only least significant bits are en [257].pack("C").unpack("C") # => [1] -=== Packing \Method +== Packing Method -\Method Array#pack accepts optional keyword argument +Method Array#pack accepts optional keyword argument +buffer+ that specifies the target string (instead of a new string): [65, 66].pack('C*', buffer: 'foo') # => "fooAB" @@ -76,7 +177,7 @@ The method can accept a block: # Packed string is passed to the block. [65, 66].pack('C*') {|s| p s } # => "AB" -=== Unpacking Methods +== Unpacking Methods Methods String#unpack and String#unpack1 each accept an optional keyword argument +offset+ that specifies an offset @@ -95,12 +196,12 @@ Both methods can accept a block: # The single unpacked object is passed to the block. 'AB'.unpack1('C*') {|ele| p ele } # => 65 -=== \Integer Directives +== \Integer Directives Each integer directive specifies the packing or unpacking for one element in the input or output array. -==== 8-Bit \Integer Directives +=== 8-Bit \Integer Directives - 'c' - 8-bit signed integer (like C signed char): @@ -116,7 +217,7 @@ for one element in the input or output array. s = [0, 1, -1].pack('C*') # => "\x00\x01\xFF" s.unpack('C*') # => [0, 1, 255] -==== 16-Bit \Integer Directives +=== 16-Bit \Integer Directives - 's' - 16-bit signed integer, native-endian (like C int16_t): @@ -146,7 +247,7 @@ for one element in the input or output array. s.unpack('v*') # => [0, 1, 65535, 32767, 32768, 65535] -==== 32-Bit \Integer Directives +=== 32-Bit \Integer Directives - 'l' - 32-bit signed integer, native-endian (like C int32_t): @@ -178,7 +279,7 @@ for one element in the input or output array. s.unpack('v*') # => [0, 0, 1, 0, 65535, 65535] -==== 64-Bit \Integer Directives +=== 64-Bit \Integer Directives - 'q' - 64-bit signed integer, native-endian (like C int64_t): @@ -196,7 +297,7 @@ for one element in the input or output array. s.unpack('Q*') # => [578437695752307201, 17940646550795321087] -==== Platform-Dependent \Integer Directives +=== Platform-Dependent \Integer Directives - 'i' - Platform-dependent width signed integer, native-endian (like C int): @@ -214,25 +315,23 @@ for one element in the input or output array. s.unpack('I*') # => [67305985, 4244504319] -==== Pointer Directives - -- 'j' - 64-bit pointer-width signed integer, - native-endian (like C intptr_t): +- 'j' - Pointer-width signed integer, native-endian + (like C intptr_t): s = [67305985, -50462977].pack('j*') # => "\x01\x02\x03\x04\x00\x00\x00\x00\xFF\xFE\xFD\xFC\xFF\xFF\xFF\xFF" s.unpack('j*') # => [67305985, -50462977] -- 'j' - 64-bit pointer-width unsigned integer, - native-endian (like C uintptr_t): +- 'J' - Pointer-width unsigned integer, native-endian + (like C uintptr_t): s = [67305985, 4244504319].pack('J*') # => "\x01\x02\x03\x04\x00\x00\x00\x00\xFF\xFE\xFD\xFC\x00\x00\x00\x00" s.unpack('J*') # => [67305985, 4244504319] -==== Other \Integer Directives +=== Other \Integer Directives - 'U' - UTF-8 character: @@ -242,38 +341,37 @@ for one element in the input or output array. # => [4194304] - 'w' - BER-encoded integer - (see {BER enocding}[https://en.wikipedia.org/wiki/X.690#BER_encoding]): + (see {BER encoding}[https://en.wikipedia.org/wiki/X.690#BER_encoding]): s = [1073741823].pack('w*') # => "\x83\xFF\xFF\xFF\x7F" s.unpack('w*') # => [1073741823] -==== Modifiers for \Integer Directives - -For directives in -'i', -'I', -'s', -'S', -'l', -'L', -'q', -'Q', -'j', and -'J', -these modifiers may be suffixed: - -- '!' or '_' - Underlying platform’s native size. +=== Modifiers for \Integer Directives + +For the following directives, '!' or '_' modifiers may be +suffixed as underlying platform’s native size. + +- 'i', 'I' - C int, always native size. +- 's', 'S' - C short. +- 'l', 'L' - C long. +- 'q', 'Q' - C long long, if available. +- 'j', 'J' - C intptr_t, always native size. + +Native size modifiers are silently ignored for always native size directives. + +The endian modifiers also may be suffixed in the directives above: + - '>' - Big-endian. - '<' - Little-endian. -=== \Float Directives +== \Float Directives Each float directive specifies the packing or unpacking for one element in the input or output array. -==== Single-Precision \Float Directives +=== Single-Precision \Float Directives - 'F' or 'f' - Native format: @@ -290,7 +388,7 @@ for one element in the input or output array. s = [3.0].pack('g') # => "@@\x00\x00" s.unpack('g') # => [3.0] -==== Double-Precision \Float Directives +=== Double-Precision \Float Directives - 'D' or 'd' - Native format: @@ -317,12 +415,12 @@ A float directive may be infinity or not-a-number: [nan].pack('f') # => "\x00\x00\xC0\x7F" "\x00\x00\xC0\x7F".unpack('f') # => [NaN] -=== \String Directives +== \String Directives Each string directive specifies the packing or unpacking for one byte in the input or output string. -==== Binary \String Directives +=== Binary \String Directives - 'A' - Arbitrary binary string (space padded; count is width); +nil+ is treated as the empty string: @@ -380,7 +478,7 @@ for one byte in the input or output string. "foo".unpack('Z*') # => ["foo"] "foo\0bar".unpack('Z*') # => ["foo"] # Does not read past "\0". -==== Bit \String Directives +=== Bit \String Directives - 'B' - Bit string (high byte first): @@ -424,7 +522,7 @@ for one byte in the input or output string. "\x01".unpack("b2") # => ["10"] "\x01".unpack("b3") # => ["100"] -==== Hex \String Directives +=== Hex \String Directives - 'H' - Hex string (high nibble first): @@ -470,7 +568,7 @@ for one byte in the input or output string. "\x01\xfe".unpack('h4') # => ["10ef"] "\x01\xfe".unpack('h5') # => ["10ef"] -==== Pointer \String Directives +=== Pointer \String Directives - 'P' - Pointer to a structure (fixed-length string): @@ -488,7 +586,7 @@ for one byte in the input or output string. ("\0" * 8).unpack("p") # => [nil] [nil].pack("p") # => "\x00\x00\x00\x00\x00\x00\x00\x00" -==== Other \String Directives +=== Other \String Directives - 'M' - Quoted printable, MIME encoding; text mode, but input must use LF and output LF; @@ -557,34 +655,52 @@ for one byte in the input or output string. - 'u' - UU-encoded string: - [0].pack("U") # => "\u0000" - [0x3fffffff].pack("U") # => "\xFC\xBF\xBF\xBF\xBF\xBF" - [0x40000000].pack("U") # => "\xFD\x80\x80\x80\x80\x80" - [0x7fffffff].pack("U") # => "\xFD\xBF\xBF\xBF\xBF\xBF" + [""].pack("u") # => "" + ["a"].pack("u") # => "!80``\n" + ["aaa"].pack("u") # => "#86%A\n" -=== Offset Directives + "".unpack("u") # => [""] + "#86)C\n".unpack("u") # => ["abc"] + +== Offset Directives - '@' - Begin packing at the given byte offset; - for packing, null fill if necessary: + for packing, null fill or shrink if necessary: - [1, 2].pack("C@0C") # => "\x02" - [1, 2].pack("C@1C") # => "\x01\x02" - [1, 2].pack("C@5C") # => "\x01\x00\x00\x00\x00\x02" + [1, 2].pack("C@0C") # => "\x02" + [1, 2].pack("C@1C") # => "\x01\x02" + [1, 2].pack("C@5C") # => "\x01\x00\x00\x00\x00\x02" + [*1..5].pack("CCCC@2C") # => "\x01\x02\x05" + + For unpacking, cannot to move to outside the string: "\x01\x00\x00\x02".unpack("C@3C") # => [1, 2] "\x00".unpack("@1C") # => [nil] + "\x00".unpack("@2C") # Raises ArgumentError. -- 'X' - Back up a byte: +- 'X' - For packing, shrink for the given byte offset: [0, 1, 2].pack("CCXC") # => "\x00\x02" [0, 1, 2].pack("CCX2C") # => "\x02" + + For unpacking; rewind unpacking position for the given byte offset: + "\x00\x02".unpack("CCXC") # => [0, 2, 2] -=== Null Byte Direcive + Cannot to move to outside the string: -- 'x' - Null byte: + [0, 1, 2].pack("CCX3C") # Raises ArgumentError. + "\x00\x02".unpack("CX3C") # Raises ArgumentError. + +- 'x' - Begin packing at after the given byte offset; + for packing, null fill if necessary: [].pack("x0") # => "" [].pack("x") # => "\x00" [].pack("x8") # => "\x00\x00\x00\x00\x00\x00\x00\x00" + + For unpacking, cannot to move to outside the string: + "\x00\x00\x02".unpack("CxC") # => [0, 2] + "\x00\x00\x02".unpack("x3C") # => [nil] + "\x00\x00\x02".unpack("x4C") # Raises ArgumentError diff --git a/doc/pty/README.expect.ja b/doc/pty/README.expect.ja index 7c0456f24fe504..a4eb6b01df24a0 100644 --- a/doc/pty/README.expect.ja +++ b/doc/pty/README.expect.ja @@ -1,21 +1,23 @@ - README for expect += README for expect by A. Ito, 28 October, 1998 - Expectライブラリは,tcl の expect パッケージと似たような機能を +Expectライブラリは,tcl の expect パッケージと似たような機能を IOクラスに追加します. - 追加されるメソッドの使い方は次の通りです. +追加されるメソッドの使い方は次の通りです. - IO#expect(pattern,timeout=9999999) +[IO#expect(pattern,timeout=9999999)] -pattern は String か Regexp のインスタンス,timeout は Fixnum -のインスタンスです.timeout は省略できます. - このメソッドがブロックなしで呼ばれた場合,まずレシーバである -IOオブジェクトから pattern にマッチするパターンが読みこまれる -まで待ちます.パターンが得られたら,そのパターンに関する配列を -返します.配列の最初の要素は,pattern にマッチするまでに読みこ -まれた内容の文字列です.2番目以降の要素は,pattern の正規表現 -の中にアンカーがあった場合に,そのアンカーにマッチする部分です. -もしタイムアウトが起きた場合は,このメソッドはnilを返します. - このメソッドがブロック付きで呼ばれた場合には,マッチした要素の -配列がブロック引数として渡され,ブロックが評価されます. + _pattern_ は String か Regexp のインスタンス,_timeout_ は Fixnum + のインスタンスです._timeout_ は省略できます. + + このメソッドがブロックなしで呼ばれた場合,まずレシーバである + IOオブジェクトから _pattern_ にマッチするパターンが読みこまれる + まで待ちます.パターンが得られたら,そのパターンに関する配列を + 返します.配列の最初の要素は,_pattern_ にマッチするまでに読みこ + まれた内容の文字列です.2番目以降の要素は,_pattern_ の正規表現 + の中にアンカーがあった場合に,そのアンカーにマッチする部分です. + もしタイムアウトが起きた場合は,このメソッドは +nil+ を返します. + + このメソッドがブロック付きで呼ばれた場合には,マッチした要素の + 配列がブロック引数として渡され,ブロックが評価されます. diff --git a/doc/pty/README.ja b/doc/pty/README.ja index 2d83ffa033e067..a26b4932ff904e 100644 --- a/doc/pty/README.ja +++ b/doc/pty/README.ja @@ -1,27 +1,26 @@ -pty 拡張モジュール version 0.3 by A.ito += pty 拡張モジュール version 0.3 by A.ito 1. はじめに -この拡張モジュールは,仮想tty (pty) を通して適当なコマンドを -実行する機能を ruby に提供します. + この拡張モジュールは,仮想tty (pty) を通して適当なコマンドを + 実行する機能を ruby に提供します. 2. インストール -次のようにしてインストールしてください. + 次のようにしてインストールしてください. -(1) ruby extconf.rb + 1. ruby extconf.rb + を実行すると Makefile が生成されます. - を実行すると Makefile が生成されます. - -(2) make; make install を実行してください. + 2. make; make install を実行してください. 3. 何ができるか -この拡張モジュールは,PTY というモジュールを定義します.その中 -には,次のようなモジュール関数が含まれています. + この拡張モジュールは,PTY というモジュールを定義します.その中 + には,次のようなモジュール関数が含まれています. - getpty(command) - spawn(command) + [PTY.getpty(command)] + [PTY.spawn(command)] この関数は,仮想ttyを確保し,指定されたコマンドをその仮想tty の向こうで実行し,配列を返します.戻り値は3つの要素からなる @@ -35,12 +34,7 @@ pty 拡張モジュール version 0.3 by A.ito のみ例外が発生します.子プロセスをモニターしているスレッドはブロッ クを抜けるときに終了します. - protect_signal - reset_signal - - 廃止予定です. - - PTY.open + [PTY.open] 仮想ttyを確保し,マスター側に対応するIOオブジェクトとスレーブ側に 対応するFileオブジェクトの配列を返します.ブロック付きで呼び出さ @@ -48,7 +42,7 @@ pty 拡張モジュール version 0.3 by A.ito クから返された結果を返します.また、このマスターIOとスレーブFile は、ブロックを抜けるときにクローズ済みでなければクローズされます. - PTY.check(pid[, raise=false]) + [PTY.check(pid[, raise=false])] pidで指定された子プロセスの状態をチェックし,実行中であればnilを 返します.終了しているか停止している場合、第二引数が偽であれば、 @@ -57,20 +51,20 @@ pty 拡張モジュール version 0.3 by A.ito 4. 利用について -伊藤彰則が著作権を保有します. + 伊藤彰則が著作権を保有します. -ソースプログラムまたはドキュメントに元の著作権表示が改変されずに -表示されている場合に限り,誰でも,このソフトウェアを無償かつ著作 -権者に無断で利用・配布・改変できます.利用目的は限定されていませ -ん. + ソースプログラムまたはドキュメントに元の著作権表示が改変されずに + 表示されている場合に限り,誰でも,このソフトウェアを無償かつ著作 + 権者に無断で利用・配布・改変できます.利用目的は限定されていませ + ん. -このプログラムの利用・配布その他このプログラムに関係する行為によ -って生じたいかなる損害に対しても,作者は一切責任を負いません. + このプログラムの利用・配布その他このプログラムに関係する行為によ + って生じたいかなる損害に対しても,作者は一切責任を負いません. 5. バグ報告等 -バグレポートは歓迎します. + バグレポートは歓迎します. aito@ei5sun.yz.yamagata-u.ac.jp -まで電子メールでバグレポートをお送りください. + まで電子メールでバグレポートをお送りください. diff --git a/doc/ractor.md b/doc/ractor.md index 3ead5105018a6e..6a1cff4e7be83f 100644 --- a/doc/ractor.md +++ b/doc/ractor.md @@ -204,8 +204,8 @@ For message sending and receiving, there are two types of APIs: push type and pu * When a Ractor is terminated, the Ractor's ports are closed. * There are 3 ways to send an object as a message * (1) Send a reference: Sending a shareable object, send only a reference to the object (fast) - * (2) Copy an object: Sending an unshareable object by copying an object deeply (slow). Note that you can not send an object which does not support deep copy. Some `T_DATA` objects are not supported. - * (3) Move an object: Sending an unshareable object reference with a membership. Sender Ractor can not access moved objects anymore (raise an exception) after moving it. Current implementation makes new object as a moved object for receiver Ractor and copies references of sending object to moved object. + * (2) Copy an object: Sending an unshareable object by copying an object deeply (slow). Note that you can not send an object which does not support deep copy. Some `T_DATA` objects (objects whose class is defined in a C extension, such as `StringIO`) are not supported. + * (3) Move an object: Sending an unshareable object reference with a membership. Sender Ractor can not access moved objects anymore (raise an exception) after moving it. Current implementation makes new object as a moved object for receiver Ractor and copies references of sending object to moved object. `T_DATA` objects are not supported. * You can choose "Copy" and "Move" by the `move:` keyword, `Ractor#send(obj, move: true/false)` and `Ractor.yield(obj, move: true/false)` (default is `false` (COPY)). ### Sending/Receiving ports @@ -259,7 +259,6 @@ r.take # Receive from r's outgoing port The last example shows the following ractor network. ``` - +------+ +---+ * main |------> * r *---+ +------+ +---+ | @@ -335,7 +334,7 @@ as << obj as.sort == ['r1', 'r2'] #=> true ``` -Complex example: +\Complex example: ```ruby pipe = Ractor.new do @@ -875,17 +874,17 @@ p Ractor.select(*rs, Ractor.current) #=> [:receive, "r0r10r9r8r7r6r5r4r3r2r1"] r.send "e0" p Ractor.select(*rs, Ractor.current) #=> -# terminated with exception (report_on_exception is true): -Traceback (most recent call last): - 2: from /home/ko1/src/ruby/trunk/test.rb:7:in `block (2 levels) in
' - 1: from /home/ko1/src/ruby/trunk/test.rb:7:in `loop' -/home/ko1/src/ruby/trunk/test.rb:9:in `block (3 levels) in
': unhandled exception -Traceback (most recent call last): - 2: from /home/ko1/src/ruby/trunk/test.rb:7:in `block (2 levels) in
' - 1: from /home/ko1/src/ruby/trunk/test.rb:7:in `loop' -/home/ko1/src/ruby/trunk/test.rb:9:in `block (3 levels) in
': unhandled exception - 1: from /home/ko1/src/ruby/trunk/test.rb:21:in `
' -:69:in `select': thrown by remote Ractor. (Ractor::RemoteError) +# terminated with exception (report_on_exception is true): +# Traceback (most recent call last): +# 2: from /home/ko1/src/ruby/trunk/test.rb:7:in `block (2 levels) in
' +# 1: from /home/ko1/src/ruby/trunk/test.rb:7:in `loop' +# /home/ko1/src/ruby/trunk/test.rb:9:in `block (3 levels) in
': unhandled exception +# Traceback (most recent call last): +# 2: from /home/ko1/src/ruby/trunk/test.rb:7:in `block (2 levels) in
' +# 1: from /home/ko1/src/ruby/trunk/test.rb:7:in `loop' +# /home/ko1/src/ruby/trunk/test.rb:9:in `block (3 levels) in
': unhandled exception +# 1: from /home/ko1/src/ruby/trunk/test.rb:21:in `
' +# :69:in `select': thrown by remote Ractor. (Ractor::RemoteError) ``` ```ruby diff --git a/doc/rdoc/markup_reference.rb b/doc/rdoc/markup_reference.rb deleted file mode 100644 index dac5c847082ac4..00000000000000 --- a/doc/rdoc/markup_reference.rb +++ /dev/null @@ -1,1257 +0,0 @@ -require 'rdoc' - -# \Class \RDoc::MarkupReference exists only to provide a suitable home -# for a reference document for \RDoc markup. -# -# All objects defined in this class -- classes, modules, methods, aliases, -# attributes, and constants -- are solely for illustrating \RDoc markup, -# and have no other legitimate use. -# -# = \RDoc Markup Reference -# -# Notes: -# -# - Examples in this reference are Ruby code and comments; -# certain differences from other sources -# (such as C code and comments) are noted. -# - An example that shows rendered HTML output -# displays that output in a blockquote: -# -# Rendered HTML: -# >>> -# Some stuff -# -# \RDoc-generated documentation is derived from and controlled by: -# -# - Single-line or multi-line comments that precede certain definitions; -# see {Markup in Comments}[rdoc-ref:RDoc::MarkupReference@Markup+in+Comments]. -# - \RDoc directives in trailing comments (on the same line as code); -# see :nodoc:, :doc:, and :notnew:. -# - \RDoc directives in single-line comments; -# see other {Directives}[rdoc-ref:RDoc::MarkupReference@Directives]. -# - The Ruby code itself (but not from C code); -# see {Documentation Derived from Ruby Code}[rdoc-ref:RDoc::MarkupReference@Documentation+Derived+from+Ruby+Code]. -# -# == Markup in Comments -# -# The treatment of markup in comments varies according to the type of file: -# -# - .rb (Ruby code file): markup is parsed from Ruby comments. -# - .c (C code file): markup is parsed from C comments. -# - .rdoc (RDoc text file): markup is parsed from the entire file. -# -# The comment associated with -# a Ruby class, module, method, alias, constant, or attribute -# becomes the documentation for that defined object: -# -# - In a Ruby file, that comment immediately precedes -# the definition of the object. -# - In a C file, that comment immediately precedes -# the function that implements a method, -# or otherwise immediately precedes the definition of the object. -# -# In either a Ruby or a C file, -# \RDoc ignores comments that do not precede object definitions. -# -# In an \RDoc file, the text is not associated with any code object, -# but may (depending on how the documentation is built), -# become a separate page. -# -# Almost all examples on this page are all RDoc-like; -# that is, they have no comment markers like Ruby # -# or C /* ... */. -# -# === Margins -# -# In a multi-line comment, -# \RDoc looks for the comment's natural left margin, -# which becomes the base margin for the comment -# and is the initial current margin for the comment. -# -# The current margin can change, and does so, for example in a list. -# -# === Blocks -# -# It's convenient to think of \RDoc markup input as a sequence of _blocks_ -# of various types (details at the links): -# -# - {Paragraph}[rdoc-ref:RDoc::MarkupReference@Paragraphs]: -# an ordinary paragraph. -# - {Verbatim text block}[rdoc-ref:RDoc::MarkupReference@Verbatim+Text+Blocks]: -# a block of text to be rendered literally. -# - {Code block}[rdoc-ref:RDoc::MarkupReference@Code+Blocks]: -# a verbatim text block containing Ruby code, -# to be rendered with code highlighting. -# - {Block quote}[rdoc-ref:RDoc::MarkupReference@Block+Quotes]: -# a longish quoted passage, to be rendered with indentation -# instead of quote marks. -# - {List}[rdoc-ref:RDoc::MarkupReference@Lists]: items for -# a bullet list, numbered list, lettered list, or labeled list. -# - {Heading}[rdoc-ref:RDoc::MarkupReference@Headings]: -# a section heading. -# - {Horizontal rule}[rdoc-ref:RDoc::MarkupReference@Horizontal+Rules]: -# a line across the rendered page. -# - {Directive}[rdoc-ref:RDoc::MarkupReference@Directives]: -# various special directions for the rendering. -# - {Text Markup}[rdoc-ref:RDoc:MarkupReference@Text+Markup]: -# text to be rendered in a special way. -# -# About the blocks: -# -# - Except for a paragraph, a block is distinguished by its indentation, -# or by unusual initial or embedded characters. -# - Any block may appear independently -# (that is, not nested in another block); -# some blocks may be nested, as detailed below. -# -# ==== Paragraphs -# -# A paragraph consists of one or more non-empty lines of ordinary text, -# each beginning at the current margin. -# -# Note: Here, ordinary text means text that is not identified -# by indentation, or by unusual initial or embedded characters. -# See below. -# -# Paragraphs are separated by one or more empty lines. -# -# Example input: -# -# \RDoc produces HTML and command-line documentation for Ruby projects. -# \RDoc includes the rdoc and ri tools for generating and displaying -# documentation from the command-line. -# -# You'll love it. -# -# Rendered HTML: -# >>> -# \RDoc produces HTML and command-line documentation for Ruby projects. -# \RDoc includes the rdoc and ri tools for generating and displaying -# documentation from the command-line. -# -# You'll love it. -# -# A paragraph may contain nested blocks, including: -# -# - {Verbatim text blocks}[rdoc-ref:RDoc::MarkupReference@Verbatim+Text+Blocks]. -# - {Code blocks}[rdoc-ref:RDoc::MarkupReference@Code+Blocks]. -# - {Block quotes}[rdoc-ref:RDoc::MarkupReference@Block+Quotes]. -# - {Lists}[rdoc-ref:RDoc::MarkupReference@Lists]. -# - {Headings}[rdoc-ref:RDoc::MarkupReference@Headings]. -# - {Horizontal rules}[rdoc-ref:RDoc::MarkupReference@Horizontal+Rules]. -# - {Text Markup}[rdoc-ref:RDoc:MarkupReference@Text+Markup]. -# -# ==== Verbatim Text Blocks -# -# Text indented farther than the current margin becomes a verbatim text block -# (or a code block, described next). -# In the rendered HTML, such text: -# -# - Is indented. -# - Has a contrasting background color. -# -# The verbatim text block ends at the first line beginning at the current margin. -# -# Example input: -# -# This is not verbatim text. -# -# This is verbatim text. -# Whitespace is honored. # See? -# Whitespace is honored. # See? -# -# This is still the same verbatim text block. -# -# This is not verbatim text. -# -# Rendered HTML: -# >>> -# This is not verbatim text. -# -# This is verbatim text. -# Whitespace is honored. # See? -# Whitespace is honored. # See? -# -# This is still the same verbatim text block. -# -# This is not verbatim text. -# -# A verbatim text block may not contain nested blocks of any kind -# -- it's verbatim. -# -# ==== Code Blocks -# -# A special case of verbatim text is the code block, -# which is merely verbatim text that \RDoc recognizes as Ruby code: -# -# In the rendered HTML, the code block: -# -# - Is indented. -# - Has a contrasting background color. -# - Has syntax highlighting. -# -# Example input: -# -# Consider this method: -# -# def foo(name = '', value = 0) -# @name = name # Whitespace is still honored. -# @value = value -# end -# -# -# Rendered HTML: -# >>> -# Consider this method: -# -# def foo(name = '', value = 0) -# @name = name # Whitespace is still honored. -# @value = value -# end -# -# Pro tip: If your indented Ruby code does not get highlighted, -# it may contain a syntax error. -# -# A code block may not contain nested blocks of any kind -# -- it's verbatim. -# -# ==== Block Quotes -# -# You can use the characters >>> (unindented), -# followed by indented text, to treat the text -# as a {block quote}[https://en.wikipedia.org/wiki/Block_quotation]: -# -# Example input: -# -# Here's a block quote: -# >>> -# Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer -# commodo quam iaculis massa posuere, dictum fringilla justo pulvinar. -# Quisque turpis erat, pharetra eu dui at, sollicitudin accumsan nulla. -# -# Aenean congue ligula eu ligula molestie, eu pellentesque purus -# faucibus. In id leo non ligula condimentum lobortis. Duis vestibulum, -# diam in pellentesque aliquet, mi tellus placerat sapien, id euismod -# purus magna ut tortor. -# -# Rendered HTML: -# -# >>> -# Here's a block quote: -# >>> -# Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer -# commodo quam iaculis massa posuere, dictum fringilla justo pulvinar. -# Quisque turpis erat, pharetra eu dui at, sollicitudin accumsan nulla. -# -# Aenean congue ligula eu ligula molestie, eu pellentesque purus -# faucibus. In id leo non ligula condimentum lobortis. Duis vestibulum, -# diam in pellentesque aliquet, mi tellus placerat sapien, id euismod -# purus magna ut tortor. -# -# Note that, unlike verbatim text, single newlines are not honored, -# but that a double newline begins a new paragraph in the block quote. -# -# A block quote may contain nested blocks, including: -# -# - Other block quotes. -# - {Paragraphs}[rdoc-ref:RDoc::MarkupReference@Paragraphs]. -# - {Verbatim text blocks}[rdoc-ref:RDoc::MarkupReference@Verbatim+Text+Blocks]. -# - {Code blocks}[rdoc-ref:RDoc::MarkupReference@Code+Blocks]. -# - {Lists}[rdoc-ref:RDoc::MarkupReference@Lists]. -# - {Headings}[rdoc-ref:RDoc::MarkupReference@Headings]. -# - {Horizontal rules}[rdoc-ref:RDoc::MarkupReference@Horizontal+Rules]. -# - {Text Markup}[rdoc-ref:RDoc:MarkupReference@Text+Markup]. -# -# ==== Lists -# -# Each type of list item is marked by a special beginning: -# -# - Bullet list item: Begins with a hyphen or asterisk. -# - Numbered list item: Begins with digits and a period. -# - Lettered list item: Begins with an alphabetic character and a period. -# - Labeled list item: Begins with one of: -# - Square-bracketed text. -# - A word followed by two colons. -# -# A list begins with a list item and continues, even across blank lines, -# as long as list items of the same type are found at the same indentation level. -# -# A new list resets the current margin inward. -# Additional lines of text aligned at that margin -# are part of the continuing list item. -# -# A list item may be continued on additional lines that are aligned -# with the first line. See examples below. -# -# A list item may contain nested blocks, including: -# -# - Other lists of any type. -# - {Paragraphs}[rdoc-ref:RDoc::MarkupReference@Paragraphs]. -# - {Verbatim text blocks}[rdoc-ref:RDoc::MarkupReference@Verbatim+Text+Blocks]. -# - {Code blocks}[rdoc-ref:RDoc::MarkupReference@Code+Blocks]. -# - {Block quotes}[rdoc-ref:RDoc::MarkupReference@Block+Quotes]. -# - {Headings}[rdoc-ref:RDoc::MarkupReference@Headings]. -# - {Horizontal rules}[rdoc-ref:RDoc::MarkupReference@Horizontal+Rules]. -# - {Text Markup}[rdoc-ref:RDoc:MarkupReference@Text+Markup]. -# -# ===== Bullet Lists -# -# A bullet list item begins with a hyphen or asterisk. -# -# Example input: -# -# - An item. -# - Another. -# - An item spanning -# multiple lines. -# -# * Yet another. -# - Last one. -# -# Rendered HTML: -# >>> -# - An item. -# - Another. -# - An item spanning -# multiple lines. -# -# * Yet another. -# - Last one. -# -# ===== Numbered Lists -# -# A numbered list item begins with digits and a period. -# -# The items are automatically re-numbered. -# -# Example input: -# -# 100. An item. -# 10. Another. -# 1. An item spanning -# multiple lines. -# -# 1. Yet another. -# 1000. Last one. -# -# Rendered HTML: -# >>> -# 100. An item. -# 10. Another. -# 1. An item spanning -# multiple lines. -# -# 1. Yet another. -# 1000. Last one. -# -# ===== Lettered Lists -# -# A lettered list item begins with letters and a period. -# -# The items are automatically "re-lettered." -# -# Example input: -# -# z. An item. -# y. Another. -# x. An item spanning -# multiple lines. -# -# x. Yet another. -# a. Last one. -# -# Rendered HTML: -# >>> -# z. An item. -# y. Another. -# -# x. Yet another. -# a. Last one. -# -# ===== Labeled Lists -# -# A labeled list item begins with one of: -# -# - Square-bracketed text: the label and text are on two lines. -# - A word followed by two colons: the label and text are on the same line. -# -# Example input: -# -# [foo] An item. -# bat:: Another. -# [bag] An item spanning -# multiple lines. -# -# [bar baz] Yet another. -# bam:: Last one. -# -# Rendered HTML: -# >>> -# [foo] An item. -# bat:: Another. -# [bag] An item spanning -# multiple lines. -# -# [bar baz] Yet another. -# bam:: Last one. -# -# ==== Headings -# -# A heading begins with up to six equal-signs, followed by heading text. -# Whitespace between those and the heading text is optional. -# -# Examples: -# -# = Section 1 -# == Section 1.1 -# === Section 1.1.1 -# === Section 1.1.2 -# == Section 1.2 -# = Section 2 -# = Foo -# == Bar -# === Baz -# ==== Bam -# ===== Bat -# ====== Bad -# ============Still a Heading (Level 6) -# \== Not a Heading -# -# A heading may contain only one type of nested block: -# -# - {Text Markup}[rdoc-ref:RDoc:MarkupReference@Text+Markup]. -# -# ==== Horizontal Rules -# -# A horizontal rule consists of a line with three or more hyphens -# and nothing more. -# -# Example input: -# -# --- -# --- Not a horizontal rule. -# -# -- Also not a horizontal rule. -# --- -# -# Rendered HTML: -# >>> -# --- -# --- Not a horizontal rule. -# -# -- Also not a horizontal rule. -# --- -# -# ==== Directives -# -# ===== Directives for Allowing or Suppressing Documentation -# -# - # :stopdoc:: -# -# - Appears on a line by itself. -# - Specifies that \RDoc should ignore markup -# until next :startdoc: directive or end-of-file. -# -# - # :startdoc:: -# -# - Appears on a line by itself. -# - Specifies that \RDoc should resume parsing markup. -# -# - # :enddoc:: -# -# - Appears on a line by itself. -# - Specifies that \RDoc should ignore markup to end-of-file -# regardless of other directives. -# -# - # :nodoc:: -# -# - Appended to a line of code -# that defines a class, module, method, alias, constant, or attribute. -# - Specifies that the defined object should not be documented. -# -# - # :nodoc: all: -# -# - Appended to a line of code -# that defines a class or module. -# - Specifies that the class or module should not be documented. -# By default, however, a nested class or module _will_ be documented. -# -# - # :doc:: -# -# - Appended to a line of code -# that defines a class, module, method, alias, constant, or attribute. -# - Specifies the defined object should be documented, even if otherwise -# would not be documented. -# -# - # :notnew: (aliased as :not_new: and :not-new:): -# -# - Appended to a line of code -# that defines instance method +initialize+. -# - Specifies that singleton method +new+ should not be documented. -# By default, Ruby fakes a corresponding singleton method +new+, -# which \RDoc includes in the documentation. -# Note that instance method +initialize+ is private, and so by default -# is not documented. -# -# For Ruby code, but not for other \RDoc sources, -# there is a shorthand for :stopdoc: and :startdoc:: -# -# # Documented. -# #-- -# # Not documented. -# #++ -# # Documented. -# -# For C code, any of directives :startdoc:, :enddoc:, -# and :nodoc: may appear in a stand-alone comment: -# -# /* :startdoc: */ -# /* :stopdoc: */ -# /* :enddoc: */ -# -# ===== Directive for Specifying \RDoc Source Format -# -# - # :markup: _type_: -# -# - Appears on a line by itself. -# - Specifies the format for the \RDoc input; -# parameter +type+ is one of +markdown+, +rd+, +rdoc+, +tomdoc+. -# -# ===== Directives for HTML Output -# -# - # :title: _text_: -# -# - Appears on a line by itself. -# - Specifies the title for the HTML output. -# -# - # :main: _filename_: -# - Appears on a line by itself. -# - Specifies the HTML file to be displayed first. -# -# ===== Directives for Method Documentation -# -# - # :call-seq:: -# -# - Appears on a line by itself. -# - Specifies the calling sequence to be reported in the HTML, -# overriding the actual calling sequence in the code. -# See method #call_seq_directive. -# -# Note that \RDoc can build the calling sequence for a Ruby-coded method, -# but not for other languages. -# You may want to override that by explicitly giving a :call-seq: -# directive if you want to include: -# -# - A return type, which is not automatically inferred. -# - Multiple calling sequences. -# -# For C code, the directive may appear in a stand-alone comment. -# -# - # :args: _arg_names_ (aliased as :arg:): -# -# - Appears on a line by itself. -# - Specifies the arguments to be reported in the HTML, -# overriding the actual arguments in the code. -# See method #args_directive. -# -# - # :yields: _arg_names_ (aliased as :yield:): -# -# - Appears on a line by itself. -# - Specifies the yield arguments to be reported in the HTML, -# overriding the actual yield in the code. -# See method #yields_directive. -# -# ===== Directives for Organizing Documentation -# -# By default, \RDoc groups: -# -# - Singleton methods together in alphabetical order. -# - Instance methods and their aliases together in alphabetical order. -# - Attributes and their aliases together in alphabetical order. -# -# You can use directives to modify those behaviors. -# -# - # :section: _section_title_: -# -# - Appears on a line by itself. -# - Specifies that following methods are to be grouped into the section -# with the given section_title, -# or into the default section if no title is given. -# The directive remains in effect until another such directive is given, -# but may be temporarily overridden by directive :category:. -# See below. -# -# The comment block containing this directive: -# -# - Must be separated by a blank line from the documentation for the next item. -# - May have one or more lines preceding the directive. -# These will be removed, along with any trailing lines that match them. -# Such lines may be visually helpful. -# - Lines of text that are not so removed become the descriptive text -# for the section. -# -# Example: -# -# # ---------------------------------------- -# # :section: My Section -# # This is the section that I wrote. -# # See it glisten in the noon-day sun. -# # ---------------------------------------- -# -# ## -# # Comment for some_method -# def some_method -# # ... -# end -# -# You can use directive :category: to temporarily -# override the current section. -# -# - # :category: _section_title_: -# -# - Appears on a line by itself. -# - Specifies that just one following method is to be included -# in the given section, or in the default section if no title is given. -# Subsequent methods are to be grouped into the current section. -# -# ===== Directive for Including a File -# -# - # :include: _filepath_: -# -# - Appears on a line by itself. -# - Specifies that the contents of the given file -# are to be included at this point. -# The file content is shifted to have the same indentation as the colon -# at the start of the directive. -# -# The file is searched for in the directories -# given with the --include command-line option, -# or by default in the current directory. -# -# For C code, the directive may appear in a stand-alone comment -# -# ==== Text Markup -# -# Text markup is metatext that affects HTML rendering: -# -# - Typeface: italic, bold, monofont. -# - Character conversions: copyright, trademark, certain punctuation. -# - Links. -# - Escapes: marking text as "not markup." -# -# ===== Typeface Markup -# -# Typeface markup can specify that text is to be rendered -# as italic, bold, or monofont. -# -# Typeface markup may contain only one type of nested block: -# -# - More typeface markup: -# italic, bold, monofont. -# -# ====== Italic -# -# Text may be marked as italic via HTML tag or . -# -# Example input: -# -# Italicized words in a paragraph. -# -# >>> -# Italicized words in a block quote. -# -# - Italicized words in a list item. -# -# ====== Italicized words in a Heading -# -# Italicized passage containing *bold* and +monofont+. -# -# Rendered HTML: -# >>> -# Italicized words in a paragraph. -# -# >>> -# Italicized words in a block quote. -# -# - Italicized words in a list item. -# -# ====== Italicized words in a Heading -# -# Italicized passage containing *bold* and +monofont+. -# -# A single word may be italicized via a shorthand: -# prefixed and suffixed underscores. -# -# Example input: -# -# _Italic_ in a paragraph. -# -# >>> -# _Italic_ in a block quote. -# -# - _Italic_ in a list item. -# -# ====== _Italic_ in a Heading -# -# Rendered HTML: -# >>> -# _Italic_ in a paragraph. -# -# >>> -# _Italic_ in a block quote. -# -# - _Italic_ in a list item. -# -# ====== _Italic_ in a Heading -# -# ====== Bold -# -# Text may be marked as bold via HTML tag . -# -# Example input: -# -# Bold words in a paragraph. -# -# >>> -# Bold words in a block quote. -# -# - Bold words in a list item. -# -# ====== Bold words in a Heading -# -# Bold passage containing _italics_ and +monofont+. -# -# Rendered HTML: -# -# >>> -# Bold words in a paragraph. -# -# >>> -# Bold words in a block quote. -# -# - Bold words in a list item. -# -# ====== Bold words in a Heading -# -# Bold passage containing _italics_ and +monofont+. -# -# A single word may be made bold via a shorthand: -# prefixed and suffixed asterisks. -# -# Example input: -# -# *Bold* in a paragraph. -# -# >>> -# *Bold* in a block quote. -# -# - *Bold* in a list item. -# -# ===== *Bold* in a Heading -# -# Rendered HTML: -# -# >>> -# *Bold* in a paragraph. -# -# >>> -# *Bold* in a block quote. -# -# - *Bold* in a list item. -# -# ===== *Bold* in a Heading -# -# ====== Monofont -# -# Text may be marked as monofont -# -- sometimes called 'typewriter font' -- -# via HTML tag or . -# -# Example input: -# -# Monofont words in a paragraph. -# -# >>> -# Monofont words in a block quote. -# -# - Monofont words in a list item. -# -# ====== Monofont words in heading -# -# Monofont passage containing _italics_ and *bold*. -# -# Rendered HTML: -# -# >>> -# Monofont words in a paragraph. -# -# >>> -# Monofont words in a block quote. -# -# - Monofont words in a list item. -# -# ====== Monofont words in heading -# -# Monofont passage containing _italics_ and *bold*. -# -# A single word may be made monofont by a shorthand: -# prefixed and suffixed plus-signs. -# -# Example input: -# -# +Monofont+ in a paragraph. -# -# >>> -# +Monofont+ in a block quote. -# -# - +Monofont+ in a list item. -# -# ====== +Monofont+ in a Heading -# -# Rendered HTML: -# -# >>> -# +Monofont+ in a paragraph. -# -# >>> -# +Monofont+ in a block quote. -# -# - +Monofont+ in a list item. -# -# ====== +Monofont+ in a Heading -# -# ==== Character Conversions -# -# Certain combinations of characters may be converted to special characters; -# whether the conversion occurs depends on whether the special character -# is available in the current encoding. -# -# - (c) converts to (c) (copyright character); must be lowercase. -# -# - (r) converts to (r) (registered trademark character); must be lowercase. -# -# - 'foo' converts to 'foo' (smart single-quotes). -# -# - "foo" converts to "foo" (smart double-quotes). -# -# - foo ... bar converts to foo ... bar (1-character ellipsis). -# -# - foo -- bar converts to foo -- bar (1-character en-dash). -# -# - foo --- bar converts to foo --- bar (1-character em-dash). -# -# ==== Links -# -# Certain strings in \RDoc text are converted to links. -# Any such link may be suppressed by prefixing a backslash. -# This section shows how to link to various -# targets. -# -# [Class] -# -# - On-page: DummyClass links to DummyClass. -# - Off-page: RDoc::Alias links to RDoc::Alias. -# -# [Module] -# -# - On-page: DummyModule links to DummyModule. -# - Off-page: RDoc links to RDoc. -# -# [Constant] -# -# - On-page: DUMMY_CONSTANT links to DUMMY_CONSTANT. -# - Off-page: RDoc::Text::MARKUP_FORMAT links to RDoc::Text::MARKUP_FORMAT. -# -# [Singleton Method] -# -# - On-page: ::dummy_singleton_method links to ::dummy_singleton_method. -# - Off-pageRDoc::TokenStream::to_html links to RDoc::TokenStream::to_html. -# -# Note: Occasionally \RDoc is not linked to a method whose name -# has only special characters. Check whether the links you were expecting -# are actually there. If not, you'll need to put in an explicit link; -# see below. -# -# Pro tip: The link to any method is available in the alphabetical table of contents -# at the top left of the page for the class or module. -# -# [Instance Method] -# -# - On-page: #dummy_instance_method links to #dummy_instance_method. -# - Off-page: RDoc::Alias#html_name links to RDoc::Alias#html_name. -# -# See the Note and Pro Tip immediately above. -# -# [Attribute] -# -# - On-page: #dummy_attribute links to #dummy_attribute. -# - Off-page: RDoc::Alias#name links to RDoc::Alias#name. -# -# [Alias] -# -# - On-page: #dummy_instance_alias links to #dummy_instance_alias. -# - Off-page: RDoc::Alias#new_name links to RDoc::Alias#new_name. -# -# [Protocol +http+] -# -# - Linked: http://yahoo.com links to http://yahoo.com. -# -# [Protocol +https+] -# -# - Linked: https://github.com links to https://github.com. -# -# [Protocol +www+] -# -# - Linked: www.yahoo.com links to www.yahoo.com. -# -# [Protocol +ftp+] -# -# - Linked: ftp://nosuch.site links to ftp://nosuch.site. -# -# [Protocol +mailto+] -# -# - Linked: mailto:/foo@bar.com links to mailto://foo@bar.com. -# -# [Protocol +irc+] -# -# - link: irc://irc.freenode.net/ruby links to irc://irc.freenode.net/ruby. -# -# [Image Filename Extensions] -# -# - Link: https://www.ruby-lang.org/images/header-ruby-logo@2x.png is -# converted to an in-line HTML +img+ tag, which displays the image in the HTML: -# -# https://www.ruby-lang.org/images/header-ruby-logo@2x.png -# -# Also works for +bmp+, +gif+, +jpeg+, and +jpg+ files. -# -# Note: Works only for a fully qualified URL. -# -# [Heading] -# -# - Link: RDoc::RD@LICENSE links to RDoc::RDoc::RD@LICENSE. -# -# Note that spaces in the actual heading are represented by + characters -# in the linkable text. -# -# - Link: RDoc::Options@Saved+Options -# links to RDoc::Options@Saved+Options. -# -# Punctuation and other special characters must be escaped like CGI.escape. -# -# Pro tip: The link to any heading is available in the alphabetical table of contents -# at the top left of the page for the class or module. -# -# [Section] -# -# See {Directives for Organizing Documentation}[#class-RDoc::MarkupReference-label-Directives+for+Organizing+Documentation]. -# -# - Link: RDoc::Markup::ToHtml@Visitor links to RDoc::Markup::ToHtml@Visitor. -# -# If a section and a heading share the same name, the link target is the section. -# -# [Single-Word Text Link] -# -# Use square brackets to create single-word text link: -# -# - GitHub[https://github.com] links to GitHub[https://github.com]. -# -# [Multi-Word Text Link] -# -# Use square brackets and curly braces to create a multi-word text link. -# -# - {GitHub home page}[https://github.com] links to -# {GitHub home page}[https://github.com]. -# -# [rdoc-ref Scheme] -# -# A link with the rdoc-ref: scheme links to the referenced item, -# if that item exists. -# The referenced item may be a class, module, method, file, etc. -# -# - Class: Alias[rdoc-ref:RDoc::Alias] links to Alias[rdoc-ref:RDoc::Alias]. -# - Module: RDoc[rdoc-ref:RDoc] links to RDoc[rdoc-ref:RDoc]. -# - Method: foo[rdoc-ref:RDoc::Markup::ToHtml#handle_regexp_RDOCLINK] -# links to foo[rdoc-ref:RDoc::Markup::ToHtml#handle_regexp_RDOCLINK]. -# - Constant: bar[rdoc-ref:RDoc::Markup::ToHtml::LIST_TYPE_TO_HTML] -# links to bar[rdoc-ref:RDoc::Markup::ToHtml::LIST_TYPE_TO_HTML]. -# - Attribute: baz[rdoc-ref:RDoc::Markup::ToHtml#code_object] -# links to baz[rdoc-ref:RDoc::Markup::ToHtml#code_object]. -# - Alias: bad[rdoc-ref:RDoc::MarkupReference#dummy_instance_alias] links to -# bad[rdoc-ref:RDoc::MarkupReference#dummy_instance_alias]. -# -# If the referenced item does not exist, no link is generated -# and entire rdoc-ref: square-bracketed clause is removed -# from the resulting text. -# -# - Nosuch[rdoc-ref:RDoc::Nosuch] is rendered as -# Nosuch[rdoc-ref:RDoc::Nosuch]. -# -# -# [rdoc-label Scheme] -# -# [Simple] -# -# You can specify a link target using this form, -# where the second part cites the id of an HTML element. -# -# This link refers to the constant +DUMMY_CONSTANT+ on this page: -# -# - {DUMMY_CONSTANT}[rdoc-label:DUMMY_CONSTANT] -# -# Thus: -# -# {DUMMY_CONSTANT}[rdoc-label:DUMMY_CONSTANT] -# -# [With Return] -# -# You can specify both a link target and a local label -# that can be used as the target for a return link. -# These two links refer to each other: -# -# - {go to addressee}[rdoc-label:addressee:sender] -# - {return to sender}[rdoc-label:sender:addressee] -# -# Thus: -# -# {go to addressee}[rdoc-label:addressee:sender] -# -# Some text. -# -# {return to sender}[rdoc-label:sender:addressee] -# -# [link: Scheme] -# -# - link:README_rdoc.html links to link:README_rdoc.html. -# -# [rdoc-image Scheme] -# -# Use the rdoc-image scheme to display an image that is also a link: -# -# # {rdoc-image:path/to/image}[link_target] -# -# - Link: {rdoc-image:https://www.ruby-lang.org/images/header-ruby-logo@2x.png}[https://www.ruby-lang.org] -# displays image https://www.ruby-lang.org/images/header-ruby-logo@2x.png -# as a link to https://www.ruby-lang.org. -# -# {rdoc-image:https://www.ruby-lang.org/images/header-ruby-logo@2x.png}[https://www.ruby-lang.org] -# -# A relative path as the target also works: -# -# - Link: {rdoc-image:https://www.ruby-lang.org/images/header-ruby-logo@2x.png}[./Alias.html] links to ./Alias.html -# -# {rdoc-image:https://www.ruby-lang.org/images/header-ruby-logo@2x.png}[./Alias.html] -# -# === Escaping Text -# -# Text that would otherwise be interpreted as markup -# can be "escaped," so that it is not interpreted as markup; -# the escape character is the backslash ('\\'). -# -# In a verbatim text block or a code block, -# the escape character is always preserved: -# -# Example input: -# -# This is not verbatim text. -# -# This is verbatim text, with an escape character \. -# -# This is not a code block. -# -# def foo -# 'String with an escape character.' -# end -# -# Rendered HTML: -# -# >>> -# This is not verbatim text. -# -# This is verbatim text, with an escape character \. -# -# This is not a code block. -# -# def foo -# 'This is a code block with an escape character \.' -# end -# -# In typeface markup (italic, bold, or monofont), -# an escape character is preserved unless it is immediately -# followed by nested typeface markup. -# -# Example input: -# -# This list is about escapes; it contains: -# -# - Monofont text with unescaped nested _italic_. -# - Monofont text with escaped nested \_italic_. -# - Monofont text with an escape character \. -# -# Rendered HTML: -# -# >>> -# This list is about escapes; it contains: -# -# - Monofont text with unescaped nested _italic_. -# - Monofont text with escaped nested \_italic_. -# - Monofont text with an escape character \ . -# -# In other text-bearing blocks -# (paragraphs, block quotes, list items, headings): -# -# - A single escape character immediately followed by markup -# escapes the markup. -# - A single escape character followed by whitespace is preserved. -# - A single escape character anywhere else is ignored. -# - A double escape character is rendered as a single backslash. -# -# Example input: -# -# This list is about escapes; it contains: -# -# - An unescaped class name, RDoc, that will become a link. -# - An escaped class name, \RDoc, that will not become a link. -# - An escape character followed by whitespace \ . -# - An escape character \that is ignored. -# - A double escape character \\ that is rendered -# as a single backslash. -# -# Rendered HTML: -# -# >>> -# This list is about escapes; it contains: -# -# - An unescaped class name, RDoc, that will become a link. -# - An escaped class name, \RDoc, that will not become a link. -# - An escape character followed by whitespace \ . -# - An escape character \that is ignored. -# - A double escape character \\ that is rendered -# as a single backslash. -# -# == Documentation Derived from Ruby Code -# -# [Class] -# -# By default, \RDoc documents: -# -# - \Class name. -# - Parent class. -# - Singleton methods. -# - Instance methods. -# - Aliases. -# - Constants. -# - Attributes. -# -# [Module] -# -# By default, \RDoc documents: -# -# - \Module name. -# - \Singleton methods. -# - Instance methods. -# - Aliases. -# - Constants. -# - Attributes. -# -# [Method] -# -# By default, \RDoc documents: -# -# - \Method name. -# - Arguments. -# - Yielded values. -# -# See #method. -# -# [Alias] -# -# By default, \RDoc documents: -# -# - Alias name. -# - Aliased name. -# -# See #dummy_instance_alias and #dummy_instance_method. -# -# [Constant] -# -# By default, \RDoc documents: -# -# - \Constant name. -# -# See DUMMY_CONSTANT. -# -# [Attribute] -# -# By default, \RDoc documents: -# -# - Attribute name. -# - Attribute type ([R], [W], or [RW]) -# -# See #dummy_attribute. -# -class RDoc::MarkupReference - - class DummyClass; end - module DummyModule; end - def self.dummy_singleton_method(foo, bar); end - def dummy_instance_method(foo, bar); end; - alias dummy_instance_alias dummy_instance_method - attr_accessor :dummy_attribute - alias dummy_attribute_alias dummy_attribute - DUMMY_CONSTANT = '' - - # :call-seq: - # call_seq_directive(foo, bar) - # Can be anything -> bar - # Also anything more -> baz or bat - # - # The :call-seq: directive overrides the actual calling sequence - # found in the Ruby code. - # - # - It can specify anything at all. - # - It can have multiple calling sequences. - # - # This one includes Can be anything -> foo, which is nonsense. - # - # Note that the "arrow" is two characters, hyphen and right angle-bracket, - # which is made into a single character in the HTML. - # - # Click on the calling sequence to see the code. - # - # Here is the :call-seq: directive given for the method: - # - # :call-seq: - # call_seq_directive(foo, bar) - # Can be anything -> bar - # Also anything more -> baz or bat - # - def call_seq_directive - nil - end - - # The :args: directive overrides the actual arguments found in the Ruby code. - # - # Click on the calling sequence to see the code. - # - def args_directive(foo, bar) # :args: baz - nil - end - - # The :yields: directive overrides the actual yield found in the Ruby code. - # - # Click on the calling sequence to see the code. - # - def yields_directive(foo, bar) # :yields: 'bat' - yield 'baz' - end - - # This method is documented only by \RDoc, except for these comments. - # - # Click on the calling sequence to see the code. - # - def method(foo, bar) - yield 'baz' - end - -end diff --git a/doc/regexp.rdoc b/doc/regexp.rdoc deleted file mode 100644 index c797c782f144bc..00000000000000 --- a/doc/regexp.rdoc +++ /dev/null @@ -1,1242 +0,0 @@ -A {regular expression}[https://en.wikipedia.org/wiki/Regular_expression] -(also called a _regexp_) is a match pattern (also simply called a _pattern_). - -A common notation for a regexp uses enclosing slash characters: - - /foo/ - -A regexp may be applied to a target string; -The part of the string (if any) that matches the pattern is called a _match_, -and may be said to match: - - re = /red/ - re.match?('redirect') # => true # Match at beginning of target. - re.match?('bored') # => true # Match at end of target. - re.match?('credit') # => true # Match within target. - re.match?('foo') # => false # No match. - -== \Regexp Uses - -A regexp may be used: - -- To extract substrings based on a given pattern: - - re = /foo/ # => /foo/ - re.match('food') # => # - re.match('good') # => nil - - See sections {Method match}[rdoc-ref:regexp.rdoc@Method+match] - and {Operator =~}[rdoc-ref:regexp.rdoc@Operator+-3D~]. - -- To determine whether a string matches a given pattern: - - re.match?('food') # => true - re.match?('good') # => false - - See section {Method match?}[rdoc-ref:regexp.rdoc@Method+match-3F]. - -- As an argument for calls to certain methods in other classes and modules; - most such methods accept an argument that may be either a string - or the (much more powerful) regexp. - - See {Regexp Methods}[./Regexp/methods_rdoc.html]. - -== \Regexp Objects - -A regexp object has: - -- A source; see {Sources}[rdoc-ref:regexp.rdoc@Sources]. - -- Several modes; see {Modes}[rdoc-ref:regexp.rdoc@Modes]. - -- A timeout; see {Timeouts}[rdoc-ref:regexp.rdoc@Timeouts]. - -- An encoding; see {Encodings}[rdoc-ref:regexp.rdoc@Encodings]. - -== Creating a \Regexp - -A regular expression may be created with: - -- A regexp literal using slash characters - (see {Regexp Literals}[https://docs.ruby-lang.org/en/master/syntax/literals_rdoc.html#label-Regexp+Literals]): - - # This is a very common usage. - /foo/ # => /foo/ - -- A %r regexp literal - (see {%r: Regexp Literals}[https://docs.ruby-lang.org/en/master/syntax/literals_rdoc.html#label-25r-3A+Regexp+Literals]): - - # Same delimiter character at beginning and end; - # useful for avoiding escaping characters - %r/name\/value pair/ # => /name\/value pair/ - %r:name/value pair: # => /name\/value pair/ - %r|name/value pair| # => /name\/value pair/ - - # Certain "paired" characters can be delimiters. - %r[foo] # => /foo/ - %r{foo} # => /foo/ - %r(foo) # => /foo/ - %r # => /foo/ - -- \Method Regexp.new. - -== \Method match - -Each of the methods Regexp#match, String#match, and Symbol#match -returns a MatchData object if a match was found, +nil+ otherwise; -each also sets {global variables}[rdoc-ref:regexp.rdoc@Global+Variables]: - - 'food'.match(/foo/) # => # - 'food'.match(/bar/) # => nil - -== Operator =~ - -Each of the operators Regexp#=~, String#=~, and Symbol#=~ -returns an integer offset if a match was found, +nil+ otherwise; -each also sets {global variables}[rdoc-ref:regexp.rdoc@Global+Variables]: - - /bar/ =~ 'foo bar' # => 4 - 'foo bar' =~ /bar/ # => 4 - /baz/ =~ 'foo bar' # => nil - -== \Method match? - -Each of the methods Regexp#match?, String#match?, and Symbol#match? -returns +true+ if a match was found, +false+ otherwise; -none sets {global variables}[rdoc-ref:regexp.rdoc@Global+Variables]: - - 'food'.match?(/foo/) # => true - 'food'.match?(/bar/) # => false - -== Global Variables - -Certain regexp-oriented methods assign values to global variables: - -- #match: see {Method match}[rdoc-ref:regexp.rdoc@Method+match]. -- #=~: see {Operator =~}[rdoc-ref:regexp.rdoc@Operator+-3D~]. - -The affected global variables are: - -- $~: Returns a MatchData object, or +nil+. -- $&: Returns the matched part of the string, or +nil+. -- $`: Returns the part of the string to the left of the match, or +nil+. -- $': Returns the part of the string to the right of the match, or +nil+. -- $+: Returns the last group matched, or +nil+. -- $1, $2, etc.: Returns the first, second, etc., - matched group, or +nil+. - Note that $0 is quite different; - it returns the name of the currently executing program. - -Examples: - - # Matched string, but no matched groups. - 'foo bar bar baz'.match('bar') - $~ # => # - $& # => "bar" - $` # => "foo " - $' # => " bar baz" - $+ # => nil - $1 # => nil - - # Matched groups. - /s(\w{2}).*(c)/.match('haystack') - $~ # => # - $& # => "stac" - $` # => "hay" - $' # => "k" - $+ # => "c" - $1 # => "ta" - $2 # => "c" - $3 # => nil - - # No match. - 'foo'.match('bar') - $~ # => nil - $& # => nil - $` # => nil - $' # => nil - $+ # => nil - $1 # => nil - -Note that Regexp#match?, String#match?, and Symbol#match? -do not set global variables. - -== Sources - -As seen above, the simplest regexp uses a literal expression as its source: - - re = /foo/ # => /foo/ - re.match('food') # => # - re.match('good') # => nil - -A rich collection of available _subexpressions_ -gives the regexp great power and flexibility: - -- {Special characters}[rdoc-ref:regexp.rdoc@Special+Characters] -- {Source literals}[rdoc-ref:regexp.rdoc@Source+Literals] -- {Character classes}[rdoc-ref:regexp.rdoc@Character+Classes] -- {Shorthand character classes}[rdoc-ref:regexp.rdoc@Shorthand+Character+Classes] -- {Anchors}[rdoc-ref:regexp.rdoc@Anchors] -- {Alternation}[rdoc-ref:regexp.rdoc@Alternation] -- {Quantifiers}[rdoc-ref:regexp.rdoc@Quantifiers] -- {Groups and captures}[rdoc-ref:regexp.rdoc@Groups+and+Captures] -- {Unicode}[rdoc-ref:regexp.rdoc@Unicode] -- {POSIX Bracket Expressions}[rdoc-ref:regexp.rdoc@POSIX+Bracket+Expressions] -- {Comments}[rdoc-ref:regexp.rdoc@Comments] - -=== Special Characters - -\Regexp special characters, called _metacharacters_, -have special meanings in certain contexts; -depending on the context, these are sometimes metacharacters: - - . ? - + * ^ \ | $ ( ) [ ] { } - -To match a metacharacter literally, backslash-escape it: - - # Matches one or more 'o' characters. - /o+/.match('foo') # => # - # Would match 'o+'. - /o\+/.match('foo') # => nil - -To match a backslash literally, backslash-escape it: - - /\./.match('\.') # => # - /\\./.match('\.') # => # - -Method Regexp.escape returns an escaped string: - - Regexp.escape('.?-+*^\|$()[]{}') - # => "\\.\\?\\-\\+\\*\\^\\\\\\|\\$\\(\\)\\[\\]\\{\\}" - -=== Source Literals - -The source literal largely behaves like a double-quoted string; -see {String Literals}[rdoc-ref:syntax/literals.rdoc@String+Literals]. - -In particular, a source literal may contain interpolated expressions: - - s = 'foo' # => "foo" - /#{s}/ # => /foo/ - /#{s.capitalize}/ # => /Foo/ - /#{2 + 2}/ # => /4/ - -There are differences between an ordinary string literal and a source literal; -see {Shorthand Character Classes}[rdoc-ref:regexp.rdoc@Shorthand+Character+Classes]. - -- \s in an ordinary string literal is equivalent to a space character; - in a source literal, it's shorthand for matching a whitespace character. -- In an ordinary string literal, these are (needlessly) escaped characters; - in a source literal, they are shorthands for various matching characters: - - \w \W \d \D \h \H \S \R - -=== Character Classes - -A character class is delimited by square brackets; -it specifies that certain characters match at a given point in the target string: - - # This character class will match any vowel. - re = /B[aeiou]rd/ - re.match('Bird') # => # - re.match('Bard') # => # - re.match('Byrd') # => nil - -A character class may contain hyphen characters to specify ranges of characters: - - # These regexps have the same effect. - /[abcdef]/.match('foo') # => # - /[a-f]/.match('foo') # => # - /[a-cd-f]/.match('foo') # => # - -When the first character of a character class is a caret (^), -the sense of the class is inverted: it matches any character _except_ those specified. - - /[^a-eg-z]/.match('f') # => # - -A character class may contain another character class. -By itself this isn't useful because [a-z[0-9]] -describes the same set as [a-z0-9]. - -However, character classes also support the && operator, -which performs set intersection on its arguments. -The two can be combined as follows: - - /[a-w&&[^c-g]z]/ # ([a-w] AND ([^c-g] OR z)) - -This is equivalent to: - - /[abh-w]/ - -=== Shorthand Character Classes - -Each of the following metacharacters serves as a shorthand -for a character class: - -- /./: Matches any character except a newline: - - /./.match('foo') # => # - /./.match("\n") # => nil - -- /./m: Matches any character, including a newline; - see {Multiline Mode}[rdoc-ref:regexp.rdoc@Multiline+Mode}: - - /./m.match("\n") # => # - -- /\w/: Matches a word character: equivalent to [a-zA-Z0-9_]: - - /\w/.match(' foo') # => # - /\w/.match(' _') # => # - /\w/.match(' ') # => nil - -- /\W/: Matches a non-word character: equivalent to [^a-zA-Z0-9_]: - - /\W/.match(' ') # => # - /\W/.match('_') # => nil - -- /\d/: Matches a digit character: equivalent to [0-9]: - - /\d/.match('THX1138') # => # - /\d/.match('foo') # => nil - -- /\D/: Matches a non-digit character: equivalent to [^0-9]: - - /\D/.match('123Jump!') # => # - /\D/.match('123') # => nil - -- /\h/: Matches a hexdigit character: equivalent to [0-9a-fA-F]: - - /\h/.match('xyz fedcba9876543210') # => # - /\h/.match('xyz') # => nil - -- /\H/: Matches a non-hexdigit character: equivalent to [^0-9a-fA-F]: - - /\H/.match('fedcba9876543210xyz') # => # - /\H/.match('fedcba9876543210') # => nil - -- /\s/: Matches a whitespace character: equivalent to /[ \t\r\n\f\v]/: - - /\s/.match('foo bar') # => # - /\s/.match('foo') # => nil - -- /\S/: Matches a non-whitespace character: equivalent to /[^ \t\r\n\f\v]/: - - /\S/.match(" \t\r\n\f\v foo") # => # - /\S/.match(" \t\r\n\f\v") # => nil - -- /\R/: Matches a linebreak, platform-independently: - - /\R/.match("\r") # => # # Carriage return (CR) - /\R/.match("\n") # => # # Newline (LF) - /\R/.match("\f") # => # # Formfeed (FF) - /\R/.match("\v") # => # # Vertical tab (VT) - /\R/.match("\r\n") # => # # CRLF - /\R/.match("\u0085") # => # # Next line (NEL) - /\R/.match("\u2028") # => # # Line separator (LSEP) - /\R/.match("\u2029") # => # # Paragraph separator (PSEP) - -=== Anchors - -An anchor is a metasequence that matches a zero-width position between -characters in the target string. - -For a subexpression with no anchor, -matching may begin anywhere in the target string: - - /real/.match('surrealist') # => # - -For a subexpression with an anchor, -matching must begin at the matched anchor. - -==== Boundary Anchors - -Each of these anchors matches a boundary: - -- ^: Matches the beginning of a line: - - /^bar/.match("foo\nbar") # => # - /^ar/.match("foo\nbar") # => nil - -- $: Matches the end of a line: - - /bar$/.match("foo\nbar") # => # - /ba$/.match("foo\nbar") # => nil - -- \A: Matches the beginning of the string: - - /\Afoo/.match('foo bar') # => # - /\Afoo/.match(' foo bar') # => nil - -- \Z: Matches the end of the string; - if string ends with a single newline, - it matches just before the ending newline: - - /foo\Z/.match('bar foo') # => # - /foo\Z/.match('foo bar') # => nil - /foo\Z/.match("bar foo\n") # => # - /foo\Z/.match("bar foo\n\n") # => nil - -- \z: Matches the end of the string: - - /foo\z/.match('bar foo') # => # - /foo\z/.match('foo bar') # => nil - /foo\z/.match("bar foo\n") # => nil - -- \b: Matches word boundary when not inside brackets; - matches backspace ("0x08") when inside brackets: - - /foo\b/.match('foo bar') # => # - /foo\b/.match('foobar') # => nil - -- \B: Matches non-word boundary: - - /foo\B/.match('foobar') # => # - /foo\B/.match('foo bar') # => nil - -- \G: Matches first matching position: - - In methods like String#gsub and String#scan, it changes on each iteration. - It initially matches the beginning of subject, and in each following iteration it matches where the last match finished. - - " a b c".gsub(/ /, '_') # => "____a_b_c" - " a b c".gsub(/\G /, '_') # => "____a b c" - - In methods like Regexp#match and String#match - that take an optional offset, it matches where the search begins. - - "hello, world".match(/,/, 3) # => # - "hello, world".match(/\G,/, 3) # => nil - -==== Lookaround Anchors - -Lookahead anchors: - -- (?=_pat_): Positive lookahead assertion: - ensures that the following characters match _pat_, - but doesn't include those characters in the matched substring. - -- (?!_pat_): Negative lookahead assertion: - ensures that the following characters do not match _pat_, - but doesn't include those characters in the matched substring. - -Lookbehind anchors: - -- (?<=_pat_): Positive lookbehind assertion: - ensures that the preceding characters match _pat_, but - doesn't include those characters in the matched substring. - -- (?: Negative lookbehind assertion: - ensures that the preceding characters do not match - _pat_, but doesn't include those characters in the matched substring. - -The pattern below uses positive lookahead and positive lookbehind to match -text appearing in ... tags -without including the tags in the match: - - /(?<=)\w+(?=<\/b>)/.match("Fortune favors the bold.") - # => # - -==== Match-Reset Anchor - -- \K: Match reset: - the matched content preceding \K in the regexp is excluded from the result. - For example, the following two regexps are almost equivalent: - - /ab\Kc/.match('abc') # => # - /(?<=ab)c/.match('abc') # => # - - These match same string and $& equals 'c', - while the matched position is different. - - As are the following two regexps: - - /(a)\K(b)\Kc/ - /(?<=(?<=(a))(b))c/ - -=== Alternation - -The vertical bar metacharacter (|) may be used within parentheses -to express alternation: -two or more subexpressions any of which may match the target string. - -Two alternatives: - - re = /(a|b)/ - re.match('foo') # => nil - re.match('bar') # => # - -Four alternatives: - - re = /(a|b|c|d)/ - re.match('shazam') # => # - re.match('cold') # => # - -Each alternative is a subexpression, and may be composed of other subexpressions: - - re = /([a-c]|[x-z])/ - re.match('bar') # => # - re.match('ooz') # => # - -\Method Regexp.union provides a convenient way to construct -a regexp with alternatives. - -=== Quantifiers - -A simple regexp matches one character: - - /\w/.match('Hello') # => # - -An added _quantifier_ specifies how many matches are required or allowed: - -- * - Matches zero or more times: - - /\w*/.match('') - # => # - /\w*/.match('x') - # => # - /\w*/.match('xyz') - # => # - -- + - Matches one or more times: - - /\w+/.match('') # => nil - /\w+/.match('x') # => # - /\w+/.match('xyz') # => # - -- ? - Matches zero or one times: - - /\w?/.match('') # => # - /\w?/.match('x') # => # - /\w?/.match('xyz') # => # - -- {_n_} - Matches exactly _n_ times: - - /\w{2}/.match('') # => nil - /\w{2}/.match('x') # => nil - /\w{2}/.match('xyz') # => # - -- {_min_,} - Matches _min_ or more times: - - /\w{2,}/.match('') # => nil - /\w{2,}/.match('x') # => nil - /\w{2,}/.match('xy') # => # - /\w{2,}/.match('xyz') # => # - -- {,_max_} - Matches _max_ or fewer times: - - /\w{,2}/.match('') # => # - /\w{,2}/.match('x') # => # - /\w{,2}/.match('xyz') # => # - -- {_min_,_max_} - - Matches at least _min_ times and at most _max_ times: - - /\w{1,2}/.match('') # => nil - /\w{1,2}/.match('x') # => # - /\w{1,2}/.match('xyz') # => # - -==== Greedy, Lazy, or Possessive Matching - -Quantifier matching may be greedy, lazy, or possessive: - -- In _greedy_ matching, as many occurrences as possible are matched - while still allowing the overall match to succeed. - Greedy quantifiers: *, +, ?, - {min, max} and its variants. -- In _lazy_ matching, the minimum number of occurrences are matched. - Lazy quantifiers: *?, +?, ??, - {min, max}? and its variants. -- In _possessive_ matching, once a match is found, there is no backtracking; - that match is retained, even if it jeopardises the overall match. - Possessive quantifiers: *+, ++, ?+. - Note that {min, max} and its variants do _not_ support possessive matching. - -More: - -- About greedy and lazy matching, see - {Choosing Minimal or Maximal Repetition}[https://doc.lagout.org/programmation/Regular%20Expressions/Regular%20Expressions%20Cookbook_%20Detailed%20Solutions%20in%20Eight%20Programming%20Languages%20%282nd%20ed.%29%20%5BGoyvaerts%20%26%20Levithan%202012-09-06%5D.pdf#tutorial-backtrack]. -- About possessive matching, see - {Eliminate Needless Backtracking}[https://doc.lagout.org/programmation/Regular%20Expressions/Regular%20Expressions%20Cookbook_%20Detailed%20Solutions%20in%20Eight%20Programming%20Languages%20%282nd%20ed.%29%20%5BGoyvaerts%20%26%20Levithan%202012-09-06%5D.pdf#tutorial-backtrack]. - -=== Groups and Captures - -A simple regexp has (at most) one match: - - re = /\d\d\d\d-\d\d-\d\d/ - re.match('1943-02-04') # => # - re.match('1943-02-04').size # => 1 - re.match('foo') # => nil - -Adding one or more pairs of parentheses, (_subexpression_), -defines _groups_, which may result in multiple matched substrings, -called _captures_: - - re = /(\d\d\d\d)-(\d\d)-(\d\d)/ - re.match('1943-02-04') # => # - re.match('1943-02-04').size # => 4 - -The first capture is the entire matched string; -the other captures are the matched substrings from the groups. - -A group may have a -{quantifier}[rdoc-ref:regexp.rdoc@Quantifiers]: - - re = /July 4(th)?/ - re.match('July 4') # => # - re.match('July 4th') # => # - - re = /(foo)*/ - re.match('') # => # - re.match('foo') # => # - re.match('foofoo') # => # - - re = /(foo)+/ - re.match('') # => nil - re.match('foo') # => # - re.match('foofoo') # => # - -The returned \MatchData object gives access to the matched substrings: - - re = /(\d\d\d\d)-(\d\d)-(\d\d)/ - md = re.match('1943-02-04') - # => # - md[0] # => "1943-02-04" - md[1] # => "1943" - md[2] # => "02" - md[3] # => "04" - -==== Non-Capturing Groups - -A group may be made non-capturing; -it is still a group (and, for example, can have a quantifier), -but its matching substring is not included among the captures. - -A non-capturing group begins with ?: (inside the parentheses): - - # Don't capture the year. - re = /(?:\d\d\d\d)-(\d\d)-(\d\d)/ - md = re.match('1943-02-04') # => # - -==== Backreferences - -A group match may also be referenced within the regexp itself; -such a reference is called a +backreference+: - - /[csh](..) [csh]\1 in/.match('The cat sat in the hat') - # => # - -This table shows how each subexpression in the regexp above -matches a substring in the target string: - - | Subexpression in Regexp | Matching Substring in Target String | - |---------------------------|-------------------------------------| - | First '[csh]' | Character 'c' | - | '(..)' | First substring 'at' | - | First space ' ' | First space character ' ' | - | Second '[csh]' | Character 's' | - | '\1' (backreference 'at') | Second substring 'at' | - | ' in' | Substring ' in' | - -A regexp may contain any number of groups: - -- For a large number of groups: - - - The ordinary \\_n_ notation applies only for _n_ in range (1..9). - - The MatchData[_n_] notation applies for any non-negative _n_. - -- \0 is a special backreference, referring to the entire matched string; - it may not be used within the regexp itself, - but may be used outside it (for example, in a substitution method call): - - 'The cat sat in the hat'.gsub(/[csh]at/, '\0s') - # => "The cats sats in the hats" - -==== Named Captures - -As seen above, a capture can be referred to by its number. -A capture can also have a name, -prefixed as ?<_name_> or ?'_name_', -and the name (symbolized) may be used as an index in MatchData[]: - - md = /\$(?\d+)\.(?'cents'\d+)/.match("$3.67") - # => # - md[:dollars] # => "3" - md[:cents] # => "67" - # The capture numbers are still valid. - md[2] # => "67" - -When a regexp contains a named capture, there are no unnamed captures: - - /\$(?\d+)\.(\d+)/.match("$3.67") - # => # - -A named group may be backreferenced as \k<_name_>: - - /(?[aeiou]).\k.\k/.match('ototomy') - # => # - -When (and only when) a regexp contains named capture groups -and appears before the =~ operator, -the captured substrings are assigned to local variables with corresponding names: - - /\$(?\d+)\.(?\d+)/ =~ '$3.67' - dollars # => "3" - cents # => "67" - -\Method Regexp#named_captures returns a hash of the capture names and substrings; -method Regexp#names returns an array of the capture names. - -==== Atomic Grouping - -A group may be made _atomic_ with (?>_subexpression_). - -This causes the subexpression to be matched -independently of the rest of the expression, -so that the matched substring becomes fixed for the remainder of the match, -unless the entire subexpression must be abandoned and subsequently revisited. - -In this way _subexpression_ is treated as a non-divisible whole. -Atomic grouping is typically used to optimise patterns -to prevent needless backtracking . - -Example (without atomic grouping): - - /".*"/.match('"Quote"') # => # - -Analysis: - -1. The leading subexpression " in the pattern matches the first character - " in the target string. -2. The next subexpression .* matches the next substring Quote“ - (including the trailing double-quote). -3. Now there is nothing left in the target string to match - the trailing subexpression " in the pattern; - this would cause the overall match to fail. -4. The matched substring is backtracked by one position: Quote. -5. The final subexpression " now matches the final substring ", - and the overall match succeeds. - -If subexpression .* is grouped atomically, -the backtracking is disabled, and the overall match fails: - - /"(?>.*)"/.match('"Quote"') # => nil - -Atomic grouping can affect performance; -see {Atomic Group}[https://www.regular-expressions.info/atomic.html]. - -==== Subexpression Calls - -As seen above, a backreference number (\\_n_) or name (\k<_name_>) -gives access to a captured _substring_; -the corresponding regexp _subexpression_ may also be accessed, -via the number (\\gn) or name (\g<_name_>): - - /\A(?\(\g*\))*\z/.match('(())') - # ^1 - # ^2 - # ^3 - # ^4 - # ^5 - # ^6 - # ^7 - # ^8 - # ^9 - # ^10 - -The pattern: - -1. Matches at the beginning of the string, i.e. before the first character. -2. Enters a named group +paren+. -3. Matches the first character in the string, '('. -4. Calls the +paren+ group again, i.e. recurses back to the second step. -5. Re-enters the +paren+ group. -6. Matches the second character in the string, '('. -7. Attempts to call +paren+ a third time, - but fails because doing so would prevent an overall successful match. -8. Matches the third character in the string, ')'; - marks the end of the second recursive call -9. Matches the fourth character in the string, ')'. -10. Matches the end of the string. - -See {Subexpression calls}[https://learnbyexample.github.io/Ruby_Regexp/groupings-and-backreferences.html?highlight=subexpression#subexpression-calls]. - -==== Conditionals - -The conditional construct takes the form (?(_cond_)_yes_|_no_), where: - -- _cond_ may be a capture number or name. -- The match to be applied is _yes_ if_cond_ is captured; - otherwise the match to be applied is _no_. -- If not needed, |_no_ may be omitted. - -Examples: - - re = /\A(foo)?(?(1)(T)|(F))\z/ - re.match('fooT') # => # - re.match('F') # => # - re.match('fooF') # => nil - re.match('T') # => nil - - re = /\A(?foo)?(?()(T)|(F))\z/ - re.match('fooT') # => # - re.match('F') # => # - re.match('fooF') # => nil - re.match('T') # => nil - - -==== Absence Operator - -The absence operator is a special group that matches anything which does _not_ match the contained subexpressions. - - /(?~real)/.match('surrealist') # => # - /(?~real)ist/.match('surrealist') # => # - /sur(?~real)ist/.match('surrealist') # => nil - -=== Unicode - -==== Unicode Properties - -The /\p{_property_name_}/ construct (with lowercase +p+) -matches characters using a Unicode property name, -much like a character class; -property +Alpha+ specifies alphabetic characters: - - /\p{Alpha}/.match('a') # => # - /\p{Alpha}/.match('1') # => nil - -A property can be inverted -by prefixing the name with a caret character (^): - - /\p{^Alpha}/.match('1') # => # - /\p{^Alpha}/.match('a') # => nil - -Or by using \P (uppercase +P+): - - /\P{Alpha}/.match('1') # => # - /\P{Alpha}/.match('a') # => nil - -See {Unicode Properties}[./Regexp/unicode_properties_rdoc.html] -for regexps based on the numerous properties. - -Some commonly-used properties correspond to POSIX bracket expressions: - -- /\p{Alnum}/: Alphabetic and numeric character -- /\p{Alpha}/: Alphabetic character -- /\p{Blank}/: Space or tab -- /\p{Cntrl}/: Control character -- /\p{Digit}/: Digit - characters, and similar) -- /\p{Lower}/: Lowercase alphabetical character -- /\p{Print}/: Like \p{Graph}, but includes the space character -- /\p{Punct}/: Punctuation character -- /\p{Space}/: Whitespace character ([:blank:], newline, - carriage return, etc.) -- /\p{Upper}/: Uppercase alphabetical -- /\p{XDigit}/: Digit allowed in a hexadecimal number (i.e., 0-9a-fA-F) - -These are also commonly used: - -- /\p{Emoji}/: Unicode emoji. -- /\p{Graph}/: Non-blank character - (excludes spaces, control characters, and similar). -- /\p{Word}/: A member of one of the following Unicode character - categories (see below): - - - +Mark+ (+M+). - - +Letter+ (+L+). - - +Number+ (+N+) - - Connector Punctuation (+Pc+). - -- /\p{ASCII}/: A character in the ASCII character set. -- /\p{Any}/: Any Unicode character (including unassigned characters). -- /\p{Assigned}/: An assigned character. - -==== Unicode Character Categories - -A Unicode character category name: - -- May be either its full name or its abbreviated name. -- Is case-insensitive. -- Treats a space, a hyphen, and an underscore as equivalent. - -Examples: - - /\p{lu}/ # => /\p{lu}/ - /\p{LU}/ # => /\p{LU}/ - /\p{Uppercase Letter}/ # => /\p{Uppercase Letter}/ - /\p{Uppercase_Letter}/ # => /\p{Uppercase_Letter}/ - /\p{UPPERCASE-LETTER}/ # => /\p{UPPERCASE-LETTER}/ - -Below are the Unicode character category abbreviations and names. -Enumerations of characters in each category are at the links. - -Letters: - -- +L+, +Letter+: +LC+, +Lm+, or +Lo+. -- +LC+, +Cased_Letter+: +Ll+, +Lt+, or +Lu+. -- {Lu, Lowercase_Letter}[https://www.compart.com/en/unicode/category/Ll]. -- {Lu, Modifier_Letter}[https://www.compart.com/en/unicode/category/Lm]. -- {Lu, Other_Letter}[https://www.compart.com/en/unicode/category/Lo]. -- {Lu, Titlecase_Letter}[https://www.compart.com/en/unicode/category/Lt]. -- {Lu, Uppercase_Letter}[https://www.compart.com/en/unicode/category/Lu]. - -Marks: - -- +M+, +Mark+: +Mc+, +Me+, or +Mn+. -- {Mc, Spacing_Mark}[https://www.compart.com/en/unicode/category/Mc]. -- {Me, Enclosing_Mark}[https://www.compart.com/en/unicode/category/Me]. -- {Mn, Nonapacing_Mark}[https://www.compart.com/en/unicode/category/Mn]. - -Numbers: - -- +N+, +Number+: +Nd+, +Nl+, or +No+. -- {Nd, Decimal_Number}[https://www.compart.com/en/unicode/category/Nd]. -- {Nl, Letter_Number}[https://www.compart.com/en/unicode/category/Nl]. -- {No, Other_Number}[https://www.compart.com/en/unicode/category/No]. - -Punctation: - -- +P+, +Punctuation+: +Pc+, +Pd+, +Pe+, +Pf+, +Pi+, +Po+, or +Ps+. -- {Pc, Connector_Punctuation}[https://www.compart.com/en/unicode/category/Pc]. -- {Pd, Dash_Punctuation}[https://www.compart.com/en/unicode/category/Pd]. -- {Pe, Close_Punctuation}[https://www.compart.com/en/unicode/category/Pe]. -- {Pf, Final_Punctuation}[https://www.compart.com/en/unicode/category/Pf]. -- {Pi, Initial_Punctuation}[https://www.compart.com/en/unicode/category/Pi]. -- {Po, Open_Punctuation}[https://www.compart.com/en/unicode/category/Po]. -- {Ps, Open_Punctuation}[https://www.compart.com/en/unicode/category/Ps]. - -- +S+, +Symbol+: +Sc+, +Sk+, +Sm+, or +So+. -- {Sc, Currency_Symbol}[https://www.compart.com/en/unicode/category/Sc]. -- {Sk, Modifier_Symbol}[https://www.compart.com/en/unicode/category/Sk]. -- {Sm, Math_Symbol}[https://www.compart.com/en/unicode/category/Sm]. -- {So, Other_Symbol}[https://www.compart.com/en/unicode/category/So]. - -- +Z+, +Separator+: +Zl+, +Zp+, or +Zs+. -- {Zl, Line_Separator}[https://www.compart.com/en/unicode/category/Zl]. -- {Zp, Paragraph_Separator}[https://www.compart.com/en/unicode/category/Zp]. -- {Zs, Space_Separator}[https://www.compart.com/en/unicode/category/Zs]. - -- +C+, +Other+: +Cc+, +Cf+, +Cn+, +Co+, or +Cs+. -- {Cc, Control}[https://www.compart.com/en/unicode/category/Cc]. -- {Cf, Format}[https://www.compart.com/en/unicode/category/Cf]. -- {Cn, Unassigned}[https://www.compart.com/en/unicode/category/Cn]. -- {Co, Private_Use}[https://www.compart.com/en/unicode/category/Co]. -- {Cs, Surrogate}[https://www.compart.com/en/unicode/category/Cs]. - -==== Unicode Scripts and Blocks - -Among the Unicode properties are: - -- {Unicode scripts}[https://en.wikipedia.org/wiki/Script_(Unicode)]; - see {supported scripts}[https://www.unicode.org/standard/supported.html]. -- {Unicode blocks}[https://en.wikipedia.org/wiki/Unicode_block]; - see {supported blocks}[http://www.unicode.org/Public/UNIDATA/Blocks.txt]. - -=== POSIX Bracket Expressions - -A POSIX bracket expression is also similar to a character class. -These expressions provide a portable alternative to the above, -with the added benefit of encompassing non-ASCII characters: - -- /\d/ matches only ASCII decimal digits +0+ through +9+. -- /[[:digit:]]/ matches any character in the Unicode - Decimal Number (+Nd+) category; - see below. - -The POSIX bracket expressions: - -- /[[:digit:]]/: Matches a {Unicode digit}[https://www.compart.com/en/unicode/category/Nd]: - - /[[:digit:]]/.match('9') # => # - /[[:digit:]]/.match("\u1fbf9") # => # - -- /[[:xdigit:]]/: Matches a digit allowed in a hexadecimal number; - equivalent to [0-9a-fA-F]. - -- /[[:upper:]]/: Matches a {Unicode uppercase letter}[https://www.compart.com/en/unicode/category/Lu]: - - /[[:upper:]]/.match('A') # => # - /[[:upper:]]/.match("\u00c6") # => # - -- /[[:lower:]]/: Matches a {Unicode lowercase letter}[https://www.compart.com/en/unicode/category/Ll]: - - /[[:lower:]]/.match('a') # => # - /[[:lower:]]/.match("\u01fd") # => # - -- /[[:alpha:]]/: Matches /[[:upper:]]/ or /[[:lower:]]/. - -- /[[:alnum:]]/: Matches /[[:alpha:]]/ or /[[:digit:]]/. - -- /[[:space:]]/: Matches {Unicode space character}[https://www.compart.com/en/unicode/category/Zs]: - - /[[:space:]]/.match(' ') # => # - /[[:space:]]/.match("\u2005") # => # - -- /[[:blank:]]/: Matches /[[:space:]]/ or tab character: - - /[[:blank:]]/.match(' ') # => # - /[[:blank:]]/.match("\u2005") # => # - /[[:blank:]]/.match("\t") # => # - -- /[[:cntrl:]]/: Matches {Unicode control character}[https://www.compart.com/en/unicode/category/Cc]: - - /[[:cntrl:]]/.match("\u0000") # => # - /[[:cntrl:]]/.match("\u009f") # => # - -- /[[:graph:]]/: Matches any character - except /[[:space:]]/ or /[[:cntrl:]]/. - -- /[[:print:]]/: Matches /[[:graph:]]/ or space character. - -- /[[:punct:]]/: Matches any (Unicode punctuation character}[https://www.compart.com/en/unicode/category/Po]: - -Ruby also supports these (non-POSIX) bracket expressions: - -- /[[:ascii:]]/: Matches a character in the ASCII character set. -- /[[:word:]]/: Matches a character in one of these Unicode character - categories (see below): - - - +Mark+ (+M+). - - +Letter+ (+L+). - - +Number+ (+N+) - - Connector Punctuation (+Pc+). - -=== Comments - -A comment may be included in a regexp pattern -using the (?#_comment_) construct, -where _comment_ is a substring that is to be ignored. -arbitrary text ignored by the regexp engine: - - /foo(?#Ignore me)bar/.match('foobar') # => # - -The comment may not include an unescaped terminator character. - -See also {Extended Mode}[rdoc-ref:regexp.rdoc@Extended+Mode]. - -== Modes - -Each of these modifiers sets a mode for the regexp: - -- +i+: /_pattern_/i sets - {Case-Insensitive Mode}[rdoc-ref:regexp.rdoc@Case-Insensitive+Mode]. -- +m+: /_pattern_/m sets - {Multiline Mode}[rdoc-ref:regexp.rdoc@Multiline+Mode]. -- +x+: /_pattern_/x sets - {Extended Mode}[rdoc-ref:regexp.rdoc@Extended+Mode]. -- +o+: /_pattern_/o sets - {Interpolation Mode}[rdoc-ref:regexp.rdoc@Interpolation+Mode]. - -Any, all, or none of these may be applied. - -Modifiers +i+, +m+, and +x+ may be applied to subexpressions: - -- (?_modifier_) turns the mode "on" for ensuing subexpressions -- (?-_modifier_) turns the mode "off" for ensuing subexpressions -- (?_modifier_:_subexp_) turns the mode "on" for _subexp_ within the group -- (?-_modifier_:_subexp_) turns the mode "off" for _subexp_ within the group - -Example: - - re = /(?i)te(?-i)st/ - re.match('test') # => # - re.match('TEst') # => # - re.match('TEST') # => nil - re.match('teST') # => nil - - re = /t(?i:e)st/ - re.match('test') # => # - re.match('tEst') # => # - re.match('tEST') # => nil - -\Method Regexp#options returns an integer whose value showing -the settings for case-insensitivity mode, multiline mode, and extended mode. - -=== Case-Insensitive Mode - -By default, a regexp is case-sensitive: - - /foo/.match('FOO') # => nil - -Modifier +i+ enables case-insensitive mode: - - /foo/i.match('FOO') - # => # - -\Method Regexp#casefold? returns whether the mode is case-insensitive. - -=== Multiline Mode - -The multiline-mode in Ruby is what is commonly called a "dot-all mode": - -- Without the +m+ modifier, the subexpression . does not match newlines: - - /a.c/.match("a\nc") # => nil - -- With the modifier, it does match: - - /a.c/m.match("a\nc") # => # - -Unlike other languages, the modifier +m+ does not affect the anchors ^ and $. -These anchors always match at line-boundaries in Ruby. - -=== Extended Mode - -Modifier +x+ enables extended mode, which means that: - -- Literal white space in the pattern is to be ignored. -- Character # marks the remainder of its containing line as a comment, - which is also to be ignored for matching purposes. - -In extended mode, whitespace and comments may be used -to form a self-documented regexp. - -Regexp not in extended mode (matches some Roman numerals): - - pattern = '^M{0,3}(CM|CD|D?C{0,3})(XC|XL|L?X{0,3})(IX|IV|V?I{0,3})$' - re = /#{pattern}/ - re.match('MCMXLIII') # => # - -Regexp in extended mode: - - pattern = <<-EOT - ^ # beginning of string - M{0,3} # thousands - 0 to 3 Ms - (CM|CD|D?C{0,3}) # hundreds - 900 (CM), 400 (CD), 0-300 (0 to 3 Cs), - # or 500-800 (D, followed by 0 to 3 Cs) - (XC|XL|L?X{0,3}) # tens - 90 (XC), 40 (XL), 0-30 (0 to 3 Xs), - # or 50-80 (L, followed by 0 to 3 Xs) - (IX|IV|V?I{0,3}) # ones - 9 (IX), 4 (IV), 0-3 (0 to 3 Is), - # or 5-8 (V, followed by 0 to 3 Is) - $ # end of string - EOT - re = /#{pattern}/x - re.match('MCMXLIII') # => # - -=== Interpolation Mode - -Modifier +o+ means that the first time a literal regexp with interpolations -is encountered, -the generated Regexp object is saved and used for all future evaluations -of that literal regexp. -Without modifier +o+, the generated Regexp is not saved, -so each evaluation of the literal regexp generates a new Regexp object. - -Without modifier +o+: - - def letters; sleep 5; /[A-Z][a-z]/; end - words = %w[abc def xyz] - start = Time.now - words.each {|word| word.match(/\A[#{letters}]+\z/) } - Time.now - start # => 15.0174892 - -With modifier +o+: - - start = Time.now - words.each {|word| word.match(/\A[#{letters}]+\z/o) } - Time.now - start # => 5.0010866 - -Note that if the literal regexp does not have interpolations, -the +o+ behavior is the default. - -== Encodings - -By default, a regexp with only US-ASCII characters has US-ASCII encoding: - - re = /foo/ - re.source.encoding # => # - re.encoding # => # - -A regular expression containing non-US-ASCII characters -is assumed to use the source encoding. -This can be overridden with one of the following modifiers. - -- /_pat_/n: US-ASCII if only containing US-ASCII characters, - otherwise ASCII-8BIT: - - /foo/n.encoding # => # - /foo\xff/n.encoding # => # - /foo\x7f/n.encoding # => # - -- /_pat_/u: UTF-8 - - /foo/u.encoding # => # - -- /_pat_/e: EUC-JP - - /foo/e.encoding # => # - -- /_pat_/s: Windows-31J - - /foo/s.encoding # => # - -A regexp can be matched against a target string when either: - -- They have the same encoding. -- The regexp's encoding is a fixed encoding and the string - contains only ASCII characters. - Method Regexp#fixed_encoding? returns whether the regexp - has a fixed encoding. - -If a match between incompatible encodings is attempted an -Encoding::CompatibilityError exception is raised. - -Example: - - re = eval("# encoding: ISO-8859-1\n/foo\\xff?/") - re.encoding # => # - re =~ "foo".encode("UTF-8") # => 0 - re =~ "foo\u0100" # Raises Encoding::CompatibilityError - -The encoding may be explicitly fixed by including Regexp::FIXEDENCODING -in the second argument for Regexp.new: - - # Regexp with encoding ISO-8859-1. - re = Regexp.new("a".force_encoding('iso-8859-1'), Regexp::FIXEDENCODING) - re.encoding # => # - # Target string with encoding UTF-8. - s = "a\u3042" - s.encoding # => # - re.match(s) # Raises Encoding::CompatibilityError. - -== Timeouts - -When either a regexp source or a target string comes from untrusted input, -malicious values could become a denial-of-service attack; -to prevent such an attack, it is wise to set a timeout. - -\Regexp has two timeout values: - -- A class default timeout, used for a regexp whose instance timeout is +nil+; - this default is initially +nil+, and may be set by method Regexp.timeout=: - - Regexp.timeout # => nil - Regexp.timeout = 3.0 - Regexp.timeout # => 3.0 - -- An instance timeout, which defaults to +nil+ and may be set in Regexp.new: - - re = Regexp.new('foo', timeout: 5.0) - re.timeout # => 5.0 - -When regexp.timeout is +nil+, the timeout "falls through" to Regexp.timeout; -when regexp.timeout is non-+nil+, that value controls timing out: - - | regexp.timeout Value | Regexp.timeout Value | Result | - |----------------------|----------------------|-----------------------------| - | nil | nil | Never times out. | - | nil | Float | Times out in Float seconds. | - | Float | Any | Times out in Float seconds. | - -== References - -Read (online PDF books): - -- {Mastering Regular Expressions}[https://ia902508.us.archive.org/10/items/allitebooks-02/Mastering%20Regular%20Expressions%2C%203rd%20Edition.pdf] - by Jeffrey E.F. Friedl. -- {Regular Expressions Cookbook}[https://doc.lagout.org/programmation/Regular%20Expressions/Regular%20Expressions%20Cookbook_%20Detailed%20Solutions%20in%20Eight%20Programming%20Languages%20%282nd%20ed.%29%20%5BGoyvaerts%20%26%20Levithan%202012-09-06%5D.pdf] - by Jan Goyvaerts & Steven Levithan. - -Explore, test (interactive online editor): - -- {Rubular}[https://rubular.com/]. diff --git a/doc/regexp/unicode_properties.rdoc b/doc/regexp/unicode_properties.rdoc index a1d7ecc38041c7..f1f1f9d6a9d37a 100644 --- a/doc/regexp/unicode_properties.rdoc +++ b/doc/regexp/unicode_properties.rdoc @@ -79,9 +79,13 @@ Older versions may not support all of these. - \p{Hyphen} - \p{IDS_Binary_Operator}, \p{IDSB} - \p{IDS_Trinary_Operator}, \p{IDST} +- \p{IDS_Unary_Operator}, \p{IDSU} +- \p{ID_Compat_Math_Continue} +- \p{ID_Compat_Math_Start} - \p{Ideographic}, \p{Ideo} - \p{Join_Control}, \p{Join_C} - \p{Logical_Order_Exception}, \p{LOE} +- \p{Modifier_Combining_Mark}, \p{MCM} - \p{Noncharacter_Code_Point}, \p{NChar} - \p{Other_Alphabetic}, \p{OAlpha} - \p{Other_Default_Ignorable_Code_Point}, \p{ODI} @@ -120,6 +124,9 @@ Older versions may not support all of these. - \p{Grapheme_Link}, \p{Gr_Link} - \p{ID_Continue}, \p{IDC} - \p{ID_Start}, \p{IDS} +- \p{InCB_Consonant} +- \p{InCB_Extend} +- \p{InCB_Linker} - \p{Lowercase}, \p{Lower} - \p{Math} - \p{Uppercase}, \p{Upper} @@ -167,6 +174,7 @@ Older versions may not support all of these. - \p{Elbasan}, \p{Elba} - \p{Elymaic}, \p{Elym} - \p{Ethiopic}, \p{Ethi} +- \p{Garay}, \p{Gara} - \p{Georgian}, \p{Geor} - \p{Glagolitic}, \p{Glag} - \p{Gothic}, \p{Goth} @@ -175,6 +183,7 @@ Older versions may not support all of these. - \p{Gujarati}, \p{Gujr} - \p{Gunjala_Gondi}, \p{Gong} - \p{Gurmukhi}, \p{Guru} +- \p{Gurung_Khema}, \p{Gukh} - \p{Han}, \p{Hani} - \p{Hangul}, \p{Hang} - \p{Hanifi_Rohingya}, \p{Rohg} @@ -197,6 +206,7 @@ Older versions may not support all of these. - \p{Khmer}, \p{Khmr} - \p{Khojki}, \p{Khoj} - \p{Khudawadi}, \p{Sind} +- \p{Kirat_Rai}, \p{Krai} - \p{Lao}, \p{Laoo} - \p{Latin}, \p{Latn} - \p{Lepcha}, \p{Lepc} @@ -234,6 +244,7 @@ Older versions may not support all of these. - \p{Nyiakeng_Puachue_Hmong}, \p{Hmnp} - \p{Ogham}, \p{Ogam} - \p{Ol_Chiki}, \p{Olck} +- \p{Ol_Onal}, \p{Onao} - \p{Old_Hungarian}, \p{Hung} - \p{Old_Italic}, \p{Ital} - \p{Old_North_Arabian}, \p{Narb} @@ -265,6 +276,7 @@ Older versions may not support all of these. - \p{Sora_Sompeng}, \p{Sora} - \p{Soyombo}, \p{Soyo} - \p{Sundanese}, \p{Sund} +- \p{Sunuwar}, \p{Sunu} - \p{Syloti_Nagri}, \p{Sylo} - \p{Syriac}, \p{Syrc} - \p{Tagalog}, \p{Tglg} @@ -282,7 +294,9 @@ Older versions may not support all of these. - \p{Tibetan}, \p{Tibt} - \p{Tifinagh}, \p{Tfng} - \p{Tirhuta}, \p{Tirh} +- \p{Todhri}, \p{Todr} - \p{Toto} +- \p{Tulu_Tigalari}, \p{Tutg} - \p{Ugaritic}, \p{Ugar} - \p{Unknown}, \p{Zzzz} - \p{Vai}, \p{Vaii} @@ -348,6 +362,7 @@ Older versions may not support all of these. - \p{In_CJK_Unified_Ideographs_Extension_F} - \p{In_CJK_Unified_Ideographs_Extension_G} - \p{In_CJK_Unified_Ideographs_Extension_H} +- \p{In_CJK_Unified_Ideographs_Extension_I} - \p{In_Carian} - \p{In_Caucasian_Albanian} - \p{In_Chakma} @@ -389,6 +404,7 @@ Older versions may not support all of these. - \p{In_Early_Dynastic_Cuneiform} - \p{In_Egyptian_Hieroglyph_Format_Controls} - \p{In_Egyptian_Hieroglyphs} +- \p{In_Egyptian_Hieroglyphs_Extended_A} - \p{In_Elbasan} - \p{In_Elymaic} - \p{In_Emoticons} @@ -401,6 +417,7 @@ Older versions may not support all of these. - \p{In_Ethiopic_Extended_A} - \p{In_Ethiopic_Extended_B} - \p{In_Ethiopic_Supplement} +- \p{In_Garay} - \p{In_General_Punctuation} - \p{In_Geometric_Shapes} - \p{In_Geometric_Shapes_Extended} @@ -416,6 +433,7 @@ Older versions may not support all of these. - \p{In_Gujarati} - \p{In_Gunjala_Gondi} - \p{In_Gurmukhi} +- \p{In_Gurung_Khema} - \p{In_Halfwidth_and_Fullwidth_Forms} - \p{In_Hangul_Compatibility_Jamo} - \p{In_Hangul_Jamo} @@ -455,6 +473,7 @@ Older versions may not support all of these. - \p{In_Khmer_Symbols} - \p{In_Khojki} - \p{In_Khudawadi} +- \p{In_Kirat_Rai} - \p{In_Lao} - \p{In_Latin_1_Supplement} - \p{In_Latin_Extended_A} @@ -510,6 +529,7 @@ Older versions may not support all of these. - \p{In_Myanmar} - \p{In_Myanmar_Extended_A} - \p{In_Myanmar_Extended_B} +- \p{In_Myanmar_Extended_C} - \p{In_NKo} - \p{In_Nabataean} - \p{In_Nag_Mundari} @@ -522,6 +542,7 @@ Older versions may not support all of these. - \p{In_Nyiakeng_Puachue_Hmong} - \p{In_Ogham} - \p{In_Ol_Chiki} +- \p{In_Ol_Onal} - \p{In_Old_Hungarian} - \p{In_Old_Italic} - \p{In_Old_North_Arabian} @@ -568,6 +589,7 @@ Older versions may not support all of these. - \p{In_Specials} - \p{In_Sundanese} - \p{In_Sundanese_Supplement} +- \p{In_Sunuwar} - \p{In_Superscripts_and_Subscripts} - \p{In_Supplemental_Arrows_A} - \p{In_Supplemental_Arrows_B} @@ -581,6 +603,7 @@ Older versions may not support all of these. - \p{In_Syloti_Nagri} - \p{In_Symbols_and_Pictographs_Extended_A} - \p{In_Symbols_for_Legacy_Computing} +- \p{In_Symbols_for_Legacy_Computing_Supplement} - \p{In_Syriac} - \p{In_Syriac_Supplement} - \p{In_Tagalog} @@ -603,8 +626,10 @@ Older versions may not support all of these. - \p{In_Tibetan} - \p{In_Tifinagh} - \p{In_Tirhuta} +- \p{In_Todhri} - \p{In_Toto} - \p{In_Transport_and_Map_Symbols} +- \p{In_Tulu_Tigalari} - \p{In_Ugaritic} - \p{In_Unified_Canadian_Aboriginal_Syllabics} - \p{In_Unified_Canadian_Aboriginal_Syllabics_Extended} @@ -658,6 +683,8 @@ Older versions may not support all of these. - \p{Age_13_0} - \p{Age_14_0} - \p{Age_15_0} +- \p{Age_15_1} +- \p{Age_16_0} - \p{Age_1_1} - \p{Age_2_0} - \p{Age_2_1} diff --git a/doc/reline/face.md b/doc/reline/face.md new file mode 100644 index 00000000000000..1fa916123b5363 --- /dev/null +++ b/doc/reline/face.md @@ -0,0 +1,111 @@ +# Face + +With the `Reline::Face` class, you can modify the text color and text decorations in your terminal emulator. +This is primarily used to customize the appearance of the method completion dialog in IRB. + +## Usage + +### ex: Change the background color of the completion dialog cyan to blue + +```ruby +Reline::Face.config(:completion_dialog) do |conf| + conf.define :default, foreground: :white, background: :blue + # ^^^^^ `:cyan` by default + conf.define :enhanced, foreground: :white, background: :magenta + conf.define :scrollbar, foreground: :white, background: :blue +end +``` + +If you provide the above code to an IRB session in some way, you can apply the configuration. +It's generally done by writing it in `.irbrc`. + +Regarding `.irbrc`, please refer to the following link: [https://docs.ruby-lang.org/en/master/IRB.html](https://docs.ruby-lang.org/en/master/IRB.html) + +## Available parameters + +`Reline::Face` internally creates SGR (Select Graphic Rendition) code according to the block parameter of `Reline::Face.config` method. + +| Key | Value | SGR Code (numeric part following "\e[")| +|:------------|:------------------|-----:| +| :foreground | :black | 30 | +| | :red | 31 | +| | :green | 32 | +| | :yellow | 33 | +| | :blue | 34 | +| | :magenta | 35 | +| | :cyan | 36 | +| | :white | 37 | +| | :bright_black | 90 | +| | :gray | 90 | +| | :bright_red | 91 | +| | :bright_green | 92 | +| | :bright_yellow | 93 | +| | :bright_blue | 94 | +| | :bright_magenta | 95 | +| | :bright_cyan | 96 | +| | :bright_white | 97 | +| :background | :black | 40 | +| | :red | 41 | +| | :green | 42 | +| | :yellow | 43 | +| | :blue | 44 | +| | :magenta | 45 | +| | :cyan | 46 | +| | :white | 47 | +| | :bright_black | 100 | +| | :gray | 100 | +| | :bright_red | 101 | +| | :bright_green | 102 | +| | :bright_yellow | 103 | +| | :bright_blue | 104 | +| | :bright_magenta | 105 | +| | :bright_cyan | 106 | +| | :bright_white | 107 | +| :style | :reset | 0 | +| | :bold | 1 | +| | :faint | 2 | +| | :italicized | 3 | +| | :underlined | 4 | +| | :slowly_blinking | 5 | +| | :blinking | 5 | +| | :rapidly_blinking | 6 | +| | :negative | 7 | +| | :concealed | 8 | +| | :crossed_out | 9 | + +- The value for `:style` can be both a Symbol and an Array + ```ruby + # Single symbol + conf.define :default, style: :bold + # Array + conf.define :default, style: [:bold, :negative] + ``` +- The availability of specific SGR codes depends on your terminal emulator +- You can specify a hex color code to `:foreground` and `:background` color like `foreground: "#FF1020"`. Its availability also depends on your terminal emulator + +## Debugging + +You can see the current Face configuration by `Reline::Face.configs` method + +Example: + +```ruby +irb(main):001:0> Reline::Face.configs +=> +{:default=> + {:default=>{:style=>:reset, :escape_sequence=>"\e[0m"}, + :enhanced=>{:style=>:reset, :escape_sequence=>"\e[0m"}, + :scrollbar=>{:style=>:reset, :escape_sequence=>"\e[0m"}}, + :completion_dialog=> + {:default=>{:foreground=>:white, :background=>:cyan, :escape_sequence=>"\e[0m\e[37;46m"}, + :enhanced=>{:foreground=>:white, :background=>:magenta, :escape_sequence=>"\e[0m\e[37;45m"}, + :scrollbar=>{:foreground=>:white, :background=>:cyan, :escape_sequence=>"\e[0m\e[37;46m"}}} +``` + +## 256-Color and TrueColor + +Reline will automatically detect if your terminal emulator supports truecolor with `ENV['COLORTERM] in 'truecolor' | '24bit'`. When this env is not set, Reline will fallback to 256-color. +If your terminal emulator supports truecolor but does not set COLORTERM env, add this line to `.irbrc`. +```ruby +Reline::Face.force_truecolor +``` diff --git a/doc/rjit/README.md b/doc/rjit/README.md deleted file mode 100644 index e3795e35b868f3..00000000000000 --- a/doc/rjit/README.md +++ /dev/null @@ -1,53 +0,0 @@ -# RJIT: Ruby JIT - -This document has some tips that might be useful when you work on RJIT. - -## Project purpose - -This project is for experimental purposes. -For production deployment, consider using YJIT instead. - -## Supported platforms - -The following platforms are assumed to work. `linux-x86_64` is tested on CI. - -* OS: Linux, macOS, BSD -* Arch: x86\_64 - -## configure -### --enable-rjit - -On supported platforms, `--enable-rjit` is set by default. You usually don't need to specify this. -You may still manually pass `--enable-rjit` to try RJIT on unsupported platforms. - -### --enable-rjit=dev - -It enables `--rjit-dump-disasm` if libcapstone is available. - -It also enables `vm_insns_count` and `ratio_in_rjit` in `--rjit-stats`. -However, it makes the interpreter a little slower. - -### --enable-rjit=disasm - -It enables `--rjit-dump-disasm` if libcapstone is available. - -## make -### rjit-bindgen - -If you see an "RJIT bindgen" GitHub Actions failure, please commit the `git diff` shown on the failed job. - -For doing the same thing locally, run `make rjit-bindgen` after installing libclang. -macOS seems to have libclang by default. On Ubuntu, you can install it with `apt install libclang1`. - -## ruby -### --rjit-stats - -This prints RJIT stats at exit. Some stats are available only with `--enable-rjit=dev` on configure. - -### --rjit-dump-disasm - -This dumps all JIT code. You need to install libcapstone before configure and use `--enable-rjit=dev` -or `--enable-rjit=disasm` on configure. - -* Ubuntu: `sudo apt-get install -y libcapstone-dev` -* macOS: `brew install capstone` diff --git a/doc/ruby/option_dump.md b/doc/ruby/option_dump.md new file mode 100644 index 00000000000000..a156484bf6866d --- /dev/null +++ b/doc/ruby/option_dump.md @@ -0,0 +1,265 @@ +# Option `--dump` + +For other argument values, +see {Option --dump}[options_md.html#label--dump-3A+Dump+Items]. + +For the examples here, we use this program: + +```console +$ cat t.rb +puts 'Foo' +``` + +The supported dump items: + +- `insns`: Instruction sequences: + + ```sh + $ ruby --dump=insns t.rb + == disasm: #@t.rb:1 (1,0)-(1,10)> (catch: FALSE) + 0000 putself ( 1)[Li] + 0001 putstring "Foo" + 0003 opt_send_without_block + 0005 leave + ``` + +- `parsetree`: {Abstract syntax tree}[https://en.wikipedia.org/wiki/Abstract_syntax_tree] + (AST): + + ```console + $ ruby --dump=parsetree t.rb + ########################################################### + ## Do NOT use this node dump for any purpose other than ## + ## debug and research. Compatibility is not guaranteed. ## + ########################################################### + + # @ NODE_SCOPE (line: 1, location: (1,0)-(1,10)) + # +- nd_tbl: (empty) + # +- nd_args: + # | (null node) + # +- nd_body: + # @ NODE_FCALL (line: 1, location: (1,0)-(1,10))* + # +- nd_mid: :puts + # +- nd_args: + # @ NODE_LIST (line: 1, location: (1,5)-(1,10)) + # +- nd_alen: 1 + # +- nd_head: + # | @ NODE_STR (line: 1, location: (1,5)-(1,10)) + # | +- nd_lit: "Foo" + # +- nd_next: + # (null node) + ``` + +- `yydebug`: Debugging information from yacc parser generator: + + ``` + $ ruby --dump=yydebug t.rb + Starting parse + Entering state 0 + Reducing stack by rule 1 (line 1295): + lex_state: NONE -> BEG at line 1296 + vtable_alloc:12392: 0x0000558453df1a00 + vtable_alloc:12393: 0x0000558453df1a60 + cmdarg_stack(push): 0 at line 12406 + cond_stack(push): 0 at line 12407 + -> $$ = nterm $@1 (1.0-1.0: ) + Stack now 0 + Entering state 2 + Reading a token: + lex_state: BEG -> CMDARG at line 9049 + Next token is token "local variable or method" (1.0-1.4: puts) + Shifting token "local variable or method" (1.0-1.4: puts) + Entering state 35 + Reading a token: Next token is token "string literal" (1.5-1.6: ) + Reducing stack by rule 742 (line 5567): + $1 = token "local variable or method" (1.0-1.4: puts) + -> $$ = nterm operation (1.0-1.4: ) + Stack now 0 2 + Entering state 126 + Reducing stack by rule 78 (line 1794): + $1 = nterm operation (1.0-1.4: ) + -> $$ = nterm fcall (1.0-1.4: ) + Stack now 0 2 + Entering state 80 + Next token is token "string literal" (1.5-1.6: ) + Reducing stack by rule 292 (line 2723): + cmdarg_stack(push): 1 at line 2737 + -> $$ = nterm $@16 (1.4-1.4: ) + Stack now 0 2 80 + Entering state 235 + Next token is token "string literal" (1.5-1.6: ) + Shifting token "string literal" (1.5-1.6: ) + Entering state 216 + Reducing stack by rule 607 (line 4706): + -> $$ = nterm string_contents (1.6-1.6: ) + Stack now 0 2 80 235 216 + Entering state 437 + Reading a token: Next token is token "literal content" (1.6-1.9: "Foo") + Shifting token "literal content" (1.6-1.9: "Foo") + Entering state 503 + Reducing stack by rule 613 (line 4802): + $1 = token "literal content" (1.6-1.9: "Foo") + -> $$ = nterm string_content (1.6-1.9: ) + Stack now 0 2 80 235 216 437 + Entering state 507 + Reducing stack by rule 608 (line 4716): + $1 = nterm string_contents (1.6-1.6: ) + $2 = nterm string_content (1.6-1.9: ) + -> $$ = nterm string_contents (1.6-1.9: ) + Stack now 0 2 80 235 216 + Entering state 437 + Reading a token: + lex_state: CMDARG -> END at line 7276 + Next token is token "terminator" (1.9-1.10: ) + Shifting token "terminator" (1.9-1.10: ) + Entering state 508 + Reducing stack by rule 590 (line 4569): + $1 = token "string literal" (1.5-1.6: ) + $2 = nterm string_contents (1.6-1.9: ) + $3 = token "terminator" (1.9-1.10: ) + -> $$ = nterm string1 (1.5-1.10: ) + Stack now 0 2 80 235 + Entering state 109 + Reducing stack by rule 588 (line 4559): + $1 = nterm string1 (1.5-1.10: ) + -> $$ = nterm string (1.5-1.10: ) + Stack now 0 2 80 235 + Entering state 108 + Reading a token: + lex_state: END -> BEG at line 9200 + Next token is token '\n' (1.10-1.10: ) + Reducing stack by rule 586 (line 4541): + $1 = nterm string (1.5-1.10: ) + -> $$ = nterm strings (1.5-1.10: ) + Stack now 0 2 80 235 + Entering state 107 + Reducing stack by rule 307 (line 2837): + $1 = nterm strings (1.5-1.10: ) + -> $$ = nterm primary (1.5-1.10: ) + Stack now 0 2 80 235 + Entering state 90 + Next token is token '\n' (1.10-1.10: ) + Reducing stack by rule 261 (line 2553): + $1 = nterm primary (1.5-1.10: ) + -> $$ = nterm arg (1.5-1.10: ) + Stack now 0 2 80 235 + Entering state 220 + Next token is token '\n' (1.10-1.10: ) + Reducing stack by rule 270 (line 2586): + $1 = nterm arg (1.5-1.10: ) + -> $$ = nterm arg_value (1.5-1.10: ) + Stack now 0 2 80 235 + Entering state 221 + Next token is token '\n' (1.10-1.10: ) + Reducing stack by rule 297 (line 2779): + $1 = nterm arg_value (1.5-1.10: ) + -> $$ = nterm args (1.5-1.10: ) + Stack now 0 2 80 235 + Entering state 224 + Next token is token '\n' (1.10-1.10: ) + Reducing stack by rule 772 (line 5626): + -> $$ = nterm none (1.10-1.10: ) + Stack now 0 2 80 235 224 + Entering state 442 + Reducing stack by rule 296 (line 2773): + $1 = nterm none (1.10-1.10: ) + + -> $$ = nterm opt_block_arg (1.10-1.10: ) + Stack now 0 2 80 235 224 + Entering state 441 + Reducing stack by rule 288 (line 2696): + $1 = nterm args (1.5-1.10: ) + $2 = nterm opt_block_arg (1.10-1.10: ) + -> $$ = nterm call_args (1.5-1.10: ) + Stack now 0 2 80 235 + Entering state 453 + Reducing stack by rule 293 (line 2723): + $1 = nterm $@16 (1.4-1.4: ) + $2 = nterm call_args (1.5-1.10: ) + cmdarg_stack(pop): 0 at line 2754 + -> $$ = nterm command_args (1.4-1.10: ) + Stack now 0 2 80 + Entering state 333 + Next token is token '\n' (1.10-1.10: ) + Reducing stack by rule 79 (line 1804): + $1 = nterm fcall (1.0-1.4: ) + $2 = nterm command_args (1.4-1.10: ) + -> $$ = nterm command (1.0-1.10: ) + Stack now 0 2 + Entering state 81 + Next token is token '\n' (1.10-1.10: ) + Reducing stack by rule 73 (line 1770): + $1 = nterm command (1.0-1.10: ) + -> $$ = nterm command_call (1.0-1.10: ) + Stack now 0 2 + Entering state 78 + Reducing stack by rule 51 (line 1659): + $1 = nterm command_call (1.0-1.10: ) + -> $$ = nterm expr (1.0-1.10: ) + Stack now 0 2 + Entering state 75 + Next token is token '\n' (1.10-1.10: ) + Reducing stack by rule 39 (line 1578): + $1 = nterm expr (1.0-1.10: ) + -> $$ = nterm stmt (1.0-1.10: ) + Stack now 0 2 + Entering state 73 + Next token is token '\n' (1.10-1.10: ) + Reducing stack by rule 8 (line 1354): + $1 = nterm stmt (1.0-1.10: ) + -> $$ = nterm top_stmt (1.0-1.10: ) + Stack now 0 2 + Entering state 72 + Reducing stack by rule 5 (line 1334): + $1 = nterm top_stmt (1.0-1.10: ) + -> $$ = nterm top_stmts (1.0-1.10: ) + Stack now 0 2 + Entering state 71 + Next token is token '\n' (1.10-1.10: ) + Shifting token '\n' (1.10-1.10: ) + Entering state 311 + Reducing stack by rule 769 (line 5618): + $1 = token '\n' (1.10-1.10: ) + -> $$ = nterm term (1.10-1.10: ) + Stack now 0 2 71 + Entering state 313 + Reducing stack by rule 770 (line 5621): + $1 = nterm term (1.10-1.10: ) + -> $$ = nterm terms (1.10-1.10: ) + Stack now 0 2 71 + Entering state 314 + Reading a token: Now at end of input. + Reducing stack by rule 759 (line 5596): + $1 = nterm terms (1.10-1.10: ) + -> $$ = nterm opt_terms (1.10-1.10: ) + Stack now 0 2 71 + Entering state 312 + Reducing stack by rule 3 (line 1321): + $1 = nterm top_stmts (1.0-1.10: ) + $2 = nterm opt_terms (1.10-1.10: ) + -> $$ = nterm top_compstmt (1.0-1.10: ) + Stack now 0 2 + Entering state 70 + Reducing stack by rule 2 (line 1295): + $1 = nterm $@1 (1.0-1.0: ) + $2 = nterm top_compstmt (1.0-1.10: ) + vtable_free:12426: p->lvtbl->args(0x0000558453df1a00) + vtable_free:12427: p->lvtbl->vars(0x0000558453df1a60) + cmdarg_stack(pop): 0 at line 12428 + cond_stack(pop): 0 at line 12429 + -> $$ = nterm program (1.0-1.10: ) + Stack now 0 + Entering state 1 + Now at end of input. + Shifting token "end-of-input" (1.10-1.10: ) + Entering state 3 + Stack now 0 1 3 + Cleanup: popping token "end-of-input" (1.10-1.10: ) + Cleanup: popping nterm program (1.0-1.10: ) + ``` + +Additional flags can follow dump items. + +- `+comment`: Add comments to AST. +- `+error-tolerant`: Parse in error-tolerant mode. +- `-optimize`: Disable optimizations for instruction sequences. diff --git a/doc/ruby/options.md b/doc/ruby/options.md new file mode 100644 index 00000000000000..bfbd2530de397e --- /dev/null +++ b/doc/ruby/options.md @@ -0,0 +1,724 @@ +# Ruby Command-Line Options + +## About the Examples + +Some examples here use command-line option `-e`, +which passes the Ruby code to be executed on the command line itself: + +```console +$ ruby -e 'puts "Hello, World."' +``` + +Some examples here assume that file `desiderata.txt` exists: + +```console +$ cat desiderata.txt +Go placidly amid the noise and the haste, +and remember what peace there may be in silence. +As far as possible, without surrender, +be on good terms with all persons. +``` + +## Options + +### `-0`: Set `$/` (Input Record Separator) + +Option `-0` defines the input record separator `$/` +for the invoked Ruby program. + +The optional argument to the option must be octal digits, +each in the range `0..7`; +these digits are prefixed with digit `0` to form an octal value. + +If no argument is given, the input record separator is `0x00`. + +If an argument is given, it must immediately follow the option +(no intervening whitespace or equal-sign character `'='`); +argument values: + +- `0`: the input record separator is `''`; + see {Special Line Separator Values}[rdoc-ref:IO@Special+Line+Separator+Values]. +- In range `(1..0377)`: + the input record separator `$/` is set to the character value of the argument. +- Any other octal value: the input record separator is `nil`. + +Examples: + +```console +$ ruby -0 -e 'p $/' +"\x00" +ruby -00 -e 'p $/' +"" +$ ruby -012 -e 'p $/' +"\n" +$ ruby -015 -e 'p $/' +"\r" +$ ruby -0377 -e 'p $/' +"\xFF" +$ ruby -0400 -e 'p $/' +nil +``` + +See also: + +- {Option -a}[rdoc-ref:ruby/options.md@a-3A+Split+Input+Lines+into+Fields]: + Split input lines into fields. +- {Option -F}[rdoc-ref:ruby/options.md@F-3A+Set+Input+Field+Separator]: + Set input field separator. +- {Option -l}[rdoc-ref:ruby/options.md@l-3A+Set+Output+Record+Separator-3B+Chop+Lines]: + Set output record separator; chop lines. +- {Option -n}[rdoc-ref:ruby/options.md@n-3A+Run+Program+in+gets+Loop]: + Run program in `gets` loop. +- {Option -p}[rdoc-ref:ruby/options.md@p-3A+-n-2C+with+Printing]: + `-n`, with printing. + +### `-a`: Split Input Lines into Fields + +Option `-a`, when given with either of options `-n` or `-p`, +splits the string at `$_` into an array of strings at `$F`: + +```console +$ ruby -an -e 'p $F' desiderata.txt +["Go", "placidly", "amid", "the", "noise", "and", "the", "haste,"] +["and", "remember", "what", "peace", "there", "may", "be", "in", "silence."] +["As", "far", "as", "possible,", "without", "surrender,"] +["be", "on", "good", "terms", "with", "all", "persons."] +``` + +For the splitting, +the default record separator is `$/`, +and the default field separator is `$;`. + +See also: + +- {Option -0}[rdoc-ref:ruby/options.md@0-3A+Set+-24-2F+-28Input+Record+Separator-29]: + Set `$/` (input record separator). +- {Option -F}[rdoc-ref:ruby/options.md@F-3A+Set+Input+Field+Separator]: + Set input field separator. +- {Option -l}[rdoc-ref:ruby/options.md@l-3A+Set+Output+Record+Separator-3B+Chop+Lines]: + Set output record separator; chop lines. +- {Option -n}[rdoc-ref:ruby/options.md@n-3A+Run+Program+in+gets+Loop]: + Run program in `gets` loop. +- {Option -p}[rdoc-ref:ruby/options.md@p-3A+-n-2C+with+Printing]: + `-n`, with printing. + +### `-c`: Check Syntax + +Option `-c` specifies that the specified Ruby program +should be checked for syntax, but not actually executed: + +```console +$ ruby -e 'puts "Foo"' +Foo +$ ruby -c -e 'puts "Foo"' +Syntax OK +``` + +### `-C`: Set Working Directory + +The argument to option `-C` specifies a working directory +for the invoked Ruby program; +does not change the working directory for the current process: + +```console +$ basename `pwd` +ruby +$ ruby -C lib -e 'puts File.basename(Dir.pwd)' +lib +$ basename `pwd` +ruby +``` + +Whitespace between the option and its argument may be omitted. + +### `-d`: Set `$DEBUG` to `true` + +Some code in (or called by) the Ruby program may include statements or blocks +conditioned by the global variable `$DEBUG` (e.g., `if $DEBUG`); +these commonly write to `$stdout` or `$stderr`. + +The default value for `$DEBUG` is `false`; +option `-d` sets it to `true`: + +```console +$ ruby -e 'p $DEBUG' +false +$ ruby -d -e 'p $DEBUG' +true +``` + +Option `--debug` is an alias for option `-d`. + +### `-e`: Execute Given Ruby Code + +Option `-e` requires an argument, which is Ruby code to be executed; +the option may be given more than once: + +```console +$ ruby -e 'puts "Foo"' -e 'puts "Bar"' +Foo +Bar +``` + +Whitespace between the option and its argument may be omitted. + +The command may include other options, +but should not include arguments (which, if given, are ignored). + +### `-E`: Set Default Encodings + +Option `-E` requires an argument, which specifies either the default external encoding, +or both the default external and internal encodings for the invoked Ruby program: + +```console +# No option -E. +$ ruby -e 'p [Encoding::default_external, Encoding::default_internal]' +[#, nil] +# Option -E with default external encoding. +$ ruby -E cesu-8 -e 'p [Encoding::default_external, Encoding::default_internal]' +[#, nil] +# Option -E with default external and internal encodings. +$ ruby -E utf-8:cesu-8 -e 'p [Encoding::default_external, Encoding::default_internal]' +[#, #] +``` + +Whitespace between the option and its argument may be omitted. + +See also: + +- {Option --external-encoding}[options_md.html#label--external-encoding-3A+Set+Default+External+Encoding]: + Set default external encoding. +- {Option --internal-encoding}[options_md.html#label--internal-encoding-3A+Set+Default+Internal+Encoding]: + Set default internal encoding. + +Option `--encoding` is an alias for option `-E`. + +### `-F`: Set Input Field Separator + +Option `-F`, when given with option `-a`, +specifies that its argument is to be the input field separator to be used for splitting: + +```console +$ ruby -an -Fs -e 'p $F' desiderata.txt +["Go placidly amid the noi", "e and the ha", "te,\n"] +["and remember what peace there may be in ", "ilence.\n"] +["A", " far a", " po", "", "ible, without ", "urrender,\n"] +["be on good term", " with all per", "on", ".\n"] +``` + +The argument may be a regular expression: + +```console +$ ruby -an -F'[.,]\s*' -e 'p $F' desiderata.txt +["Go placidly amid the noise and the haste"] +["and remember what peace there may be in silence"] +["As far as possible", "without surrender"] +["be on good terms with all persons"] +``` + +The argument must immediately follow the option +(no intervening whitespace or equal-sign character `'='`). + +See also: + +- {Option -0}[rdoc-ref:ruby/options.md@0-3A+Set+-24-2F+-28Input+Record+Separator-29]: + Set `$/` (input record separator). +- {Option -a}[rdoc-ref:ruby/options.md@a-3A+Split+Input+Lines+into+Fields]: + Split input lines into fields. +- {Option -l}[rdoc-ref:ruby/options.md@l-3A+Set+Output+Record+Separator-3B+Chop+Lines]: + Set output record separator; chop lines. +- {Option -n}[rdoc-ref:ruby/options.md@n-3A+Run+Program+in+gets+Loop]: + Run program in `gets` loop. +- {Option -p}[rdoc-ref:ruby/options.md@p-3A+-n-2C+with+Printing]: + `-n`, with printing. + +### `-h`: Print Short Help Message + +Option `-h` prints a short help message +that includes single-hyphen options (e.g. `-I`), +and largely omits double-hyphen options (e.g., `--version`). + +Arguments and additional options are ignored. + +For a longer help message, use option `--help`. + +### `-i`: Set \ARGF In-Place Mode + +Option `-i` sets the \ARGF in-place mode for the invoked Ruby program; +see ARGF#inplace_mode=: + +```console +$ ruby -e 'p ARGF.inplace_mode' +nil +$ ruby -i -e 'p ARGF.inplace_mode' +"" +$ ruby -i.bak -e 'p ARGF.inplace_mode' +".bak" +``` + +### `-I`: Add to `$LOAD_PATH` + +The argument to option `-I` specifies a directory +to be added to the array in global variable `$LOAD_PATH`; +the option may be given more than once: + +```console +$ pushd /tmp +$ ruby -e 'p $LOAD_PATH.size' +8 +$ ruby -I my_lib -I some_lib -e 'p $LOAD_PATH.size' +10 +$ ruby -I my_lib -I some_lib -e 'p $LOAD_PATH.take(2)' +["/tmp/my_lib", "/tmp/some_lib"] +$ popd +``` + +Whitespace between the option and its argument may be omitted. + +### `-l`: Set Output Record Separator; Chop Lines + +Option `-l`, when given with option `-n` or `-p`, +modifies line-ending processing by: + +- Setting global variable output record separator `$\` + to the current value of input record separator `$/`; + this affects line-oriented output (such a the output from Kernel#puts). +- Calling String#chop! on each line read. + +Without option `-l` (unchopped): + +```console +$ ruby -n -e 'p $_' desiderata.txt +"Go placidly amid the noise and the haste,\n" +"and remember what peace there may be in silence.\n" +"As far as possible, without surrender,\n" +"be on good terms with all persons.\n" +``` + +With option `-l' (chopped): + +```console +$ ruby -ln -e 'p $_' desiderata.txt +"Go placidly amid the noise and the haste," +"and remember what peace there may be in silence." +"As far as possible, without surrender," +"be on good terms with all persons." +``` + +See also: + +- {Option -0}[rdoc-ref:ruby/options.md@0-3A+Set+-24-2F+-28Input+Record+Separator-29]: + Set `$/` (input record separator). +- {Option -a}[rdoc-ref:ruby/options.md@a-3A+Split+Input+Lines+into+Fields]: + Split input lines into fields. +- {Option -F}[rdoc-ref:ruby/options.md@F-3A+Set+Input+Field+Separator]: + Set input field separator. +- {Option -n}[rdoc-ref:ruby/options.md@n-3A+Run+Program+in+gets+Loop]: + Run program in `gets` loop. +- {Option -p}[rdoc-ref:ruby/options.md@p-3A+-n-2C+with+Printing]: + `-n`, with printing. + +### `-n`: Run Program in `gets` Loop + +Option `-n` runs your program in a `Kernel#gets` loop: + +```ruby +while gets + # Your Ruby code. +end +``` + +Note that `gets` reads the next line and sets global variable `$_` +to the last read line: + +```console +$ ruby -n -e 'puts $_' desiderata.txt +Go placidly amid the noise and the haste, +and remember what peace there may be in silence. +As far as possible, without surrender, +be on good terms with all persons. +``` + +See also: + +- {Option -0}[rdoc-ref:ruby/options.md@0-3A+Set+-24-2F+-28Input+Record+Separator-29]: + Set `$/` (input record separator). +- {Option -a}[rdoc-ref:ruby/options.md@a-3A+Split+Input+Lines+into+Fields]: + Split input lines into fields. +- {Option -F}[rdoc-ref:ruby/options.md@F-3A+Set+Input+Field+Separator]: + Set input field separator. +- {Option -l}[rdoc-ref:ruby/options.md@l-3A+Set+Output+Record+Separator-3B+Chop+Lines]: + Set output record separator; chop lines. +- {Option -p}[rdoc-ref:ruby/options.md@p-3A+-n-2C+with+Printing]: + `-n`, with printing. + +### `-p`: `-n`, with Printing + +Option `-p` is like option `-n`, but also prints each line: + +```console +$ ruby -p -e 'puts $_.size' desiderata.txt +42 +Go placidly amid the noise and the haste, +49 +and remember what peace there may be in silence. +39 +As far as possible, without surrender, +35 +be on good terms with all persons. +``` + +See also: + +- {Option -0}[rdoc-ref:ruby/options.md@0-3A+Set+-24-2F+-28Input+Record+Separator-29]: + Set `$/` (input record separator). +- {Option -a}[rdoc-ref:ruby/options.md@a-3A+Split+Input+Lines+into+Fields]: + Split input lines into fields. +- {Option -F}[rdoc-ref:ruby/options.md@F-3A+Set+Input+Field+Separator]: + Set input field separator. +- {Option -l}[rdoc-ref:ruby/options.md@l-3A+Set+Output+Record+Separator-3B+Chop+Lines]: + Set output record separator; chop lines. +- {Option -n}[rdoc-ref:ruby/options.md@n-3A+Run+Program+in+gets+Loop]: + Run program in `gets` loop. + +### `-r`: Require Library + +The argument to option `-r` specifies a library to be required +before executing the Ruby program; +the option may be given more than once: + +```console +$ ruby -e 'p defined?(JSON); p defined?(CSV)' +nil +nil +$ ruby -r CSV -r JSON -e 'p defined?(JSON); p defined?(CSV)' +"constant" +"constant" +``` + +Whitespace between the option and its argument may be omitted. + +### `-s`: Define Global Variable + +Option `-s` specifies that a "custom option" is to define a global variable +in the invoked Ruby program: + +- The custom option must appear _after_ the program name. +- The custom option must begin with single hyphen (e.g., `-foo`), + not two hyphens (e.g., `--foo`). +- The name of the global variable is based on the option name: + global variable `$foo` for custom option`-foo`. +- The value of the global variable is the string option argument if given, + `true` otherwise. + +More than one custom option may be given: + +```console +$ cat t.rb +p [$foo, $bar] +$ ruby t.rb +[nil, nil] +$ ruby -s t.rb -foo=baz +["baz", nil] +$ ruby -s t.rb -foo +[true, nil] +$ ruby -s t.rb -foo=baz -bar=bat +["baz", "bat"] +``` + +The option may not be used with +{option -e}[rdoc-ref:ruby/options.md@e-3A+Execute+Given+Ruby+Code] + +### `-S`: Search Directories in `ENV['PATH']` + +Option `-S` specifies that the Ruby interpreter +is to search (if necessary) the directories whose paths are in the program's +`PATH` environment variable; +the program is executed in the shell's current working directory +(not necessarily in the directory where the program is found). + +This example uses adds path `'tmp/'` to the `PATH` environment variable: + +```console +$ export PATH=/tmp:$PATH +$ echo "puts File.basename(Dir.pwd)" > /tmp/t.rb +$ ruby -S t.rb +ruby +``` + +### `-v`: Print Version; Set `$VERBOSE` + +Options `-v` prints the Ruby version and sets global variable `$VERBOSE`: + +```console +$ ruby -e 'p $VERBOSE' +false +$ ruby -v -e 'p $VERBOSE' +ruby 3.3.0 (2023-12-25 revision 5124f9ac75) [x64-mingw-ucrt] +true +``` + +### `-w`: Synonym for `-W1` + +Option `-w` (lowercase letter) is equivalent to option `-W1` (uppercase letter). + +### `-W`: Set \Warning Policy + +Any Ruby code can create a warning message by calling method Kernel#warn; +methods in the Ruby core and standard libraries can also create warning messages. +Such a message may be printed on `$stderr` +(or not, depending on certain settings). + +Option `-W` helps determine whether a particular warning message +will be written, +by setting the initial value of global variable `$-W`: + +- `-W0`: Sets `$-W` to `0` (silent; no warnings). +- `-W1`: Sets `$-W` to `1` (moderate verbosity). +- `-W2`: Sets `$-W` to `2` (high verbosity). +- `-W`: Same as `-W2` (high verbosity). +- Option not given: Same as `-W1` (moderate verbosity). + +The value of `$-W`, in turn, determines which warning messages (if any) +are to be printed to `$stdout` (see Kernel#warn): + +```console +$ ruby -W1 -e 'p $foo' +nil +$ ruby -W2 -e 'p $foo' +-e:1: warning: global variable '$foo' not initialized +nil +``` + +Ruby code may also define warnings for certain categories; +these are the default settings for the defined categories: + +```rb +Warning[:experimental] # => true +Warning[:deprecated] # => false +Warning[:performance] # => false +``` + +They may also be set: + +```rb +Warning[:experimental] = false +Warning[:deprecated] = true +Warning[:performance] = true +``` + +You can suppress a category by prefixing `no-` to the category name: + +```console +$ ruby -W:no-experimental -e 'p IO::Buffer.new' +# +``` + +### `-x`: Execute Ruby Code Found in Text + +Option `-x` executes a Ruby program whose code is embedded +in other, non-code, text: + +The ruby code: + +- Begins after the first line beginning with `'#!` and containing string `'ruby'`. +- Ends before any one of: + + - End-of-file. + - A line consisting of `'__END__'`, + - Character `Ctrl-D` or `Ctrl-Z`. + +Example: + +```console +$ cat t.txt +Leading garbage. +#!ruby +puts File.basename(Dir.pwd) +__END__ +Trailing garbage. + +$ ruby -x t.txt +ruby +``` + +The optional argument specifies the directory where the text file +is to be found; +the Ruby code is executed in that directory: + +```console +$ cp t.txt /tmp/ +$ ruby -x/tmp t.txt +tmp +$ + +``` + +If an argument is given, it must immediately follow the option +(no intervening whitespace or equal-sign character `'='`). + +### `--backtrace-limit`: Set Backtrace Limit + +Option `--backtrace-limit` sets a limit on the number of entries +to be displayed in a backtrace. + +See Thread::Backtrace.limit. + +### `--copyright`: Print Ruby Copyright + +Option `--copyright` prints a copyright message: + +```console +$ ruby --copyright +ruby - Copyright (C) 1993-2024 Yukihiro Matsumoto +``` + +### `--debug`: Alias for `-d` + +Option `--debug` is an alias for +{option -d}[rdoc-ref:ruby/options.md@d-3A+Set+-24DEBUG+to+true]. + +### `--disable`: Disable Features + +Option `--disable` specifies features to be disabled; +the argument is a comma-separated list of the features to be disabled: + +```sh +ruby --disable=gems,rubyopt t.rb +``` + +The supported features: + +- `gems`: Rubygems (default: enabled). +- `did_you_mean`: [`did_you_mean`](https://github.com/ruby/did_you_mean) (default: enabled). +- `rubyopt`: `RUBYOPT` environment variable (default: enabled). +- `frozen-string-literal`: Freeze all string literals (default: disabled). +- `jit`: JIT compiler (default: disabled). + +See also {option --enable}[options_md.html#label--enable-3A+Enable+Features]. + +### `--dump`: Dump Items + +Option `--dump` specifies items to be dumped; +the argument is a comma-separated list of the items. + +Some of the argument values cause the command to behave as if a different +option was given: + +- `--dump=copyright`: + Same as {option \-\-copyright}[options_md.html#label--copyright-3A+Print+Ruby+Copyright]. +- `--dump=help`: + Same as {option \-\-help}[options_md.html#label--help-3A+Print+Help+Message]. +- `--dump=syntax`: + Same as {option -c}[rdoc-ref:ruby/options.md@c-3A+Check+Syntax]. +- `--dump=usage`: + Same as {option -h}[rdoc-ref:ruby/options.md@h-3A+Print+Short+Help+Message]. +- `--dump=version`: + Same as {option \-\-version}[options_md.html#label--version-3A+Print+Ruby+Version]. + +For other argument values and examples, +see {Option --dump}[option_dump_md.html]. + +### `--enable`: Enable Features + +Option `--enable` specifies features to be enabled; +the argument is a comma-separated list of the features to be enabled. + +```sh +ruby --enable=gems,rubyopt t.rb +``` + +For the features, +see {option --disable}[options_md.html#label--disable-3A+Disable+Features]. + +### `--encoding`: Alias for `-E`. + +Option `--encoding` is an alias for +{option -E}[rdoc-ref:ruby/options.md@E-3A+Set+Default+Encodings]. + +### `--external-encoding`: Set Default External \Encoding + +Option `--external-encoding` +sets the default external encoding for the invoked Ruby program; +for values of +encoding+, +see {Encoding: Names and Aliases}[rdoc-ref:encodings.rdoc@Names+and+Aliases]. + +```console +$ ruby -e 'puts Encoding::default_external' +UTF-8 +$ ruby --external-encoding=cesu-8 -e 'puts Encoding::default_external' +CESU-8 +``` + +### `--help`: Print Help Message + +Option `--help` prints a long help message. + +Arguments and additional options are ignored. + +For a shorter help message, use option `-h`. + +### `--internal-encoding`: Set Default Internal \Encoding + +Option `--internal-encoding` +sets the default internal encoding for the invoked Ruby program; +for values of +encoding+, +see {Encoding: Names and Aliases}[rdoc-ref:encodings.rdoc@Names+and+Aliases]. + +```console +$ ruby -e 'puts Encoding::default_internal.nil?' +true +$ ruby --internal-encoding=cesu-8 -e 'puts Encoding::default_internal' +CESU-8 +``` + +### `--verbose`: Set `$VERBOSE` + +Option `--verbose` sets global variable `$VERBOSE` to `true` +and disables input from `$stdin`. + +### `--version`: Print Ruby Version + +Option `--version` prints the version of the Ruby interpreter, then exits. + +## Experimental Options + +These options are experimental in the current Ruby release, +and may be modified or withdrawn in later releases. + +### `--jit` + +Option `-jit` enables JIT compilation with the default option. + +#### `--jit-debug` + +Option `--jit-debug` enables JIT debugging (very slow); +adds compiler flags if given. + +#### `--jit-max-cache=num` + +Option `--jit-max-cache=num` sets the maximum number of methods +to be JIT-ed in a cache; default: 100). + +#### `--jit-min-calls=num` + +Option `jit-min-calls=num` sets the minimum number of calls to trigger JIT +(for testing); default: 10000). + +#### `--jit-save-temps` + +Option `--jit-save-temps` saves JIT temporary files in $TMP or /tmp (for testing). + +#### `--jit-verbose` + +Option `--jit-verbose` prints JIT logs of level `num` or less +to `$stderr`; default: 0. + +#### `--jit-wait` + +Option `--jit-wait` waits until JIT compilation finishes every time (for testing). + +#### `--jit-warnings` + +Option `--jit-warnings` enables printing of JIT warnings. + diff --git a/doc/security.rdoc b/doc/security.rdoc index ae20ed30fa2349..af9970d336e5ff 100644 --- a/doc/security.rdoc +++ b/doc/security.rdoc @@ -37,7 +37,7 @@ programs for configuration and database persistence of Ruby object trees. Similar to +Marshal+, it is able to deserialize into arbitrary Ruby classes. For example, the following YAML data will create an +ERB+ object when -deserialized: +deserialized, using the +unsafe_load+ method: !ruby/object:ERB src: puts `uname` @@ -53,19 +53,16 @@ method, variable and constant names. The reason for this is that symbols are simply integers with names attached to them, so they are faster to look up in hashtables. -Starting in version 2.2, most symbols can be garbage collected; these are -called mortal symbols. Most symbols you create (e.g. by calling -+to_sym+) are mortal. +Most symbols can be garbage collected; these are called _mortal_ +symbols. Most symbols you create (e.g. by calling +to_sym+) are mortal. -Immortal symbols on the other hand will never be garbage collected. +_Immortal_ symbols on the other hand will never be garbage collected. They are created when modifying code: * defining a method (e.g. with +define_method+), * setting an instance variable (e.g. with +instance_variable_set+), * creating a variable or constant (e.g. with +const_set+) -C extensions that have not been updated and are still calling `SYM2ID` +C extensions that have not been updated and are still calling +SYM2ID+ will create immortal symbols. -Bugs in 2.2.0: +send+ and +__send__+ also created immortal symbols, -and calling methods with keyword arguments could also create some. Don't create immortal symbols from user inputs. Otherwise, this would allow a user to mount a denial of service attack against your application by @@ -128,12 +125,3 @@ Note that the use of +public_send+ is also dangerous, as +send+ itself is public: 1.public_send("send", "eval", "...ruby code to be executed...") - -== DRb - -As DRb allows remote clients to invoke arbitrary methods, it is not suitable to -expose to untrusted clients. - -When using DRb, try to avoid exposing it over the network if possible. If this -isn't possible and you need to expose DRb to the world, you *must* configure an -appropriate security policy with DRb::ACL. diff --git a/doc/standard_library.md b/doc/standard_library.md new file mode 100644 index 00000000000000..0c48ac0cdd7e0a --- /dev/null +++ b/doc/standard_library.md @@ -0,0 +1,225 @@ +# Ruby Standard Library + +The Ruby Standard Library is a large collection of classes and modules you can +require in your code to gain additional features. + +Below is an overview of the libraries and extensions, followed by a brief description +of each. + +## Libraries + +- `MakeMakefile`: A module used to generate a Makefile for C extensions +- `RbConfig`: Information about your Ruby configuration and build +- `Gem`: A package management framework for Ruby + +## Extensions + +- `Coverage`: Provides coverage measurement for Ruby +- `Monitor`: Provides a reentrant mutex +- `objspace`: Extends the ObjectSpace module to add methods for internal statistics +- `PTY`: Creates and manages pseudo-terminals +- `Ripper`: Provides an interface for parsing Ruby programs into S-expressions +- `Socket`: Accesses underlying OS socket implementations + +# Default gems + +- Default gems are shipped with Ruby releases and also available as rubygems. +- Default gems are not uninstallable from the Ruby installation. +- Default gems can be updated using rubygems. + - e.g. `gem update json` +- Default gems can be used with bundler environments like `unbundled_env`. +- Default gems can be used at any version in a Gemfile. + - e.g. `gem "json", ">= 2.6"` + +## Libraries + +- Bundler ([GitHub][bundler]): Manage your Ruby application's gem dependencies +- Delegator ([GitHub][delegate]): Provides three abilities to delegate method calls to an object +- DidYouMean ([GitHub][did_you_mean]): "Did you mean?" experience in Ruby +- English ([GitHub][English]): Provides references to special global variables with less cryptic names +- ERB ([GitHub][erb]): An easy-to-use but powerful templating system for Ruby +- ErrorHighlight ([GitHub][error_highlight]): Highlight error locations in your code +- FileUtils ([GitHub][fileutils]): Several file utility methods for copying, moving, removing, etc. +- Find ([GitHub][find]): This module supports top-down traversal of a set of file paths +- Forwardable ([GitHub][forwardable]): Provides delegation of specified methods to a designated object +- IPAddr ([GitHub][ipaddr]): Provides methods to manipulate IPv4 and IPv6 IP addresses +- OptionParser ([GitHub][optparse]): Ruby-oriented class for command-line option analysis +- Net::HTTP ([GitHub][net-http]): HTTP client API for Ruby +- Open3 ([GitHub][open3]): Provides access to stdin, stdout, and stderr when running other programs +- OpenURI ([GitHub][open-uri]): An easy-to-use wrapper for URI::HTTP, URI::HTTPS, and URI::FTP +- PP ([GitHub][pp]): Provides a PrettyPrinter for Ruby objects +- PrettyPrint ([GitHub][prettyprint]): Implements a pretty printing algorithm for readable structure +- Prism ([GitHub][prism]): A portable, error-tolerant Ruby parser +- Resolv ([GitHub][resolv]): Thread-aware DNS resolver library in Ruby +- SecureRandom ([GitHub][securerandom]): Interface for a secure random number generator +- Shellwords ([GitHub][shellwords]): Manipulates strings with the word parsing rules of the UNIX Bourne shell +- Singleton ([GitHub][singleton]): Implementation of the Singleton pattern for Ruby +- Tempfile ([GitHub][tempfile]): A utility class for managing temporary files +- Time ([GitHub][time]): Extends the Time class with methods for parsing and conversion +- Timeout ([GitHub][timeout]): Auto-terminate potentially long-running operations in Ruby +- TmpDir ([GitHub][tmpdir]): Extends the Dir class to manage the OS temporary file path +- TSort ([GitHub][tsort]): Topological sorting using Tarjan's algorithm +- UN ([GitHub][un]): Utilities to replace common UNIX commands +- URI ([GitHub][uri]): A Ruby module providing support for Uniform Resource Identifiers +- YAML ([GitHub][yaml]): The Ruby client library for the Psych YAML implementation +- WeakRef ([GitHub][weakref]): Allows a referenced object to be garbage-collected + +## Extensions + +- Date ([GitHub][date]): Represents dates, with a subclass for dates with time and timezones +- Digest ([GitHub][digest]): Provides a framework for message digest libraries +- Etc ([GitHub][etc]): Provides access to information typically stored in the UNIX /etc directory +- Fcntl ([GitHub][fcntl]): Loads constants defined in the OS fcntl.h C header file +- IO.console ([GitHub][io-console]): Extensions for the IO class, including `IO.console`, `IO.winsize`, etc. +- IO#nonblock ([GitHub][io-nonblock]): Enable non-blocking mode with IO class. +- IO#wait ([GitHub][io-wait]): Provides the feature for waiting until IO is readable or writable without blocking. +- JSON ([GitHub][json]): Implements JavaScript Object Notation for Ruby +- OpenSSL ([GitHub][openssl]): Provides SSL, TLS, and general-purpose cryptography for Ruby +- Pathname ([GitHub][pathname]): Representation of the name of a file or directory on the filesystem +- Psych ([GitHub][psych]): A YAML parser and emitter for Ruby +- StringIO ([GitHub][stringio]): Pseudo-I/O on String objects +- StringScanner ([GitHub][strscan]): Provides lexical scanning operations on a String +- Zlib ([GitHub][zlib]): Ruby interface for the zlib compression/decompression library + +# Bundled gems + +- Bundled gems are shipped with Ruby releases and also available as rubygems. + - They are only bundled with Ruby releases. + - They can be uninstalled from the Ruby installation. + - They need to be declared in a Gemfile when used with bundler. + +## Libraries + +- [minitest]: A test library supporting TDD, BDD, mocking, and benchmarking +- [power_assert]: Power Assert for Ruby +- [rake][rake-doc] ([GitHub][rake]): Ruby build program with capabilities similar to make +- [test-unit]: A compatibility layer for MiniTest +- [rexml][rexml-doc] ([GitHub][rexml]): An XML toolkit for Ruby +- [rss]: A family of libraries supporting various XML-based "feeds" +- [net-ftp]: Support for the File Transfer Protocol +- [net-imap]: Ruby client API for the Internet Message Access Protocol +- [net-pop]: Ruby client library for POP3 +- [net-smtp]: Simple Mail Transfer Protocol client library for Ruby +- [matrix]: Represents a mathematical matrix +- [prime]: Prime numbers and factorization library +- [rbs]: RBS is a language to describe the structure of Ruby programs +- [typeprof]: A type analysis tool for Ruby code based on abstract interpretation +- [debug]: Debugging functionality for Ruby +- [racc][racc-doc] ([GitHub][racc]): A LALR(1) parser generator written in Ruby +- [mutex_m]: Mixin to extend objects to be handled like a Mutex +- [getoptlong]: Parse command line options similar to the GNU C getopt_long() +- [base64]: Support for encoding and decoding binary data using a Base64 representation +- [bigdecimal]: Provides arbitrary-precision floating point decimal arithmetic +- [observer]: Provides a mechanism for the publish/subscribe pattern in Ruby +- [abbrev]: Calculates a set of unique abbreviations for a given set of strings +- [resolv-replace]: Replace Socket DNS with Resolv +- [rinda]: The Linda distributed computing paradigm in Ruby +- [drb]: Distributed object system for Ruby +- [nkf]: Ruby extension for the Network Kanji Filter +- [syslog]: Ruby interface for the POSIX system logging facility +- [csv][csv-doc] ([GitHub][csv]): Provides an interface to read and write CSV files and data +- [ostruct]: A class to build custom data structures, similar to a Hash +- [benchmark]: Provides methods to measure and report the time used to execute code +- [logger][logger-doc] ([GitHub][logger]): Provides a simple logging utility for outputting messages +- [pstore]: Implements a file-based persistence mechanism based on a Hash +- [win32ole]: Provides an interface for OLE Automation in Ruby +- [reline][reline-doc] ([GitHub][reline]): GNU Readline and Editline in a pure Ruby implementation +- [readline]: Wrapper for the Readline extension and Reline +- [fiddle]: A libffi wrapper for Ruby + +## Tools + +- [IRB][irb-doc] ([GitHub][irb]): Interactive Ruby command-line tool for REPL (Read Eval Print Loop) +- [RDoc][rdoc-doc] ([GitHub][rdoc]): Documentation generator for Ruby + +[abbrev]: https://github.com/ruby/abbrev +[base64]: https://github.com/ruby/base64 +[benchmark]: https://github.com/ruby/benchmark +[bigdecimal]: https://github.com/ruby/bigdecimal +[bundler]: https://github.com/rubygems/rubygems +[csv]: https://github.com/ruby/csv +[date]: https://github.com/ruby/date +[debug]: https://github.com/ruby/debug +[delegate]: https://github.com/ruby/delegate +[did_you_mean]: https://github.com/ruby/did_you_mean +[digest]: https://github.com/ruby/digest +[drb]: https://github.com/ruby/drb +[English]: https://github.com/ruby/English +[erb]: https://github.com/ruby/erb +[error_highlight]: https://github.com/ruby/error_highlight +[etc]: https://github.com/ruby/etc +[fcntl]: https://github.com/ruby/fcntl +[fiddle]: https://github.com/ruby/fiddle +[fileutils]: https://github.com/ruby/fileutils +[find]: https://github.com/ruby/find +[forwardable]: https://github.com/ruby/forwardable +[getoptlong]: https://github.com/ruby/getoptlong +[io-console]: https://github.com/ruby/io-console +[io-nonblock]: https://github.com/ruby/io-nonblock +[io-wait]: https://github.com/ruby/io-wait +[ipaddr]: https://github.com/ruby/ipaddr +[irb]: https://github.com/ruby/irb +[json]: https://github.com/ruby/json +[logger]: https://github.com/ruby/logger +[matrix]: https://github.com/ruby/matrix +[minitest]: https://github.com/seattlerb/minitest +[mutex_m]: https://github.com/ruby/mutex_m +[net-ftp]: https://github.com/ruby/net-ftp +[net-http]: https://github.com/ruby/net-http +[net-imap]: https://github.com/ruby/net-imap +[net-pop]: https://github.com/ruby/net-pop +[net-smtp]: https://github.com/ruby/net-smtp +[nkf]: https://github.com/ruby/nkf +[observer]: https://github.com/ruby/observer +[open-uri]: https://github.com/ruby/open-uri +[open3]: https://github.com/ruby/open3 +[openssl]: https://github.com/ruby/openssl +[optparse]: https://github.com/ruby/optparse +[ostruct]: https://github.com/ruby/ostruct +[pathname]: https://github.com/ruby/pathname +[power_assert]: https://github.com/ruby/power_assert +[pp]: https://github.com/ruby/pp +[prettyprint]: https://github.com/ruby/prettyprint +[prime]: https://github.com/ruby/prime +[prism]: https://github.com/ruby/prism +[pstore]: https://github.com/ruby/pstore +[psych]: https://github.com/ruby/psych +[racc]: https://github.com/ruby/racc +[rake]: https://github.com/ruby/rake +[rbs]: https://github.com/ruby/rbs +[rdoc]: https://github.com/ruby/rdoc +[readline]: https://github.com/ruby/readline +[reline]: https://github.com/ruby/reline +[resolv-replace]: https://github.com/ruby/resolv-replace +[resolv]: https://github.com/ruby/resolv +[rexml]: https://github.com/ruby/rexml +[rinda]: https://github.com/ruby/rinda +[rss]: https://github.com/ruby/rss +[securerandom]: https://github.com/ruby/securerandom +[shellwords]: https://github.com/ruby/shellwords +[singleton]: https://github.com/ruby/singleton +[stringio]: https://github.com/ruby/stringio +[strscan]: https://github.com/ruby/strscan +[syslog]: https://github.com/ruby/syslog +[tempfile]: https://github.com/ruby/tempfile +[test-unit]: https://github.com/test-unit/test-unit +[time]: https://github.com/ruby/time +[timeout]: https://github.com/ruby/timeout +[tmpdir]: https://github.com/ruby/tmpdir +[tsort]: https://github.com/ruby/tsort +[typeprof]: https://github.com/ruby/typeprof +[un]: https://github.com/ruby/un +[uri]: https://github.com/ruby/uri +[weakref]: https://github.com/ruby/weakref +[win32ole]: https://github.com/ruby/win32ole +[yaml]: https://github.com/ruby/yaml +[zlib]: https://github.com/ruby/zlib + +[reline-doc]: https://ruby.github.io/reline/ +[rake-doc]: https://ruby.github.io/rake/ +[irb-doc]: https://ruby.github.io/irb/ +[rdoc-doc]: https://ruby.github.io/rdoc/ +[logger-doc]: https://ruby.github.io/logger/ +[racc-doc]: https://ruby.github.io/racc/ +[csv-doc]: https://ruby.github.io/csv/ +[rexml-doc]: https://ruby.github.io/rexml/ diff --git a/doc/standard_library.rdoc b/doc/standard_library.rdoc deleted file mode 100644 index b4baaca18b1ead..00000000000000 --- a/doc/standard_library.rdoc +++ /dev/null @@ -1,131 +0,0 @@ -= Ruby Standard Library - -The Ruby Standard Library is a vast collection of classes and modules that you -can require in your code for additional features. - -Below is an overview of libraries and extensions followed by a brief -description. - -== Libraries - -MakeMakefile:: Module used to generate a Makefile for C extensions -RbConfig:: Information of your configure and build of Ruby -Gem:: Package management framework for Ruby - -== Extensions - -Coverage:: Provides coverage measurement for Ruby -Monitor:: Provides an object or module to use safely by more than one thread -objspace:: Extends ObjectSpace module to add methods for internal statistics -PTY:: Creates and manages pseudo terminals -Ripper:: Provides an interface for parsing Ruby programs into S-expressions -Socket:: Access underlying OS socket implementations - -= Default gems - -* default gems are shipped with Ruby releases and also available as rubygems. -* default gems are not uninstallable from Ruby installation. -* default gems can be updated used by rubygems. - * e.g. `gem update json` -* default gems can be used with bundler environment like `unbundled_env`. -* default gems can be used any version on Gemfile. - * e.g. `gem "json", ">= 2.6"` - -== Libraries - -Abbrev:: Calculates a set of unique abbreviations for a given set of strings -Base64:: Support for encoding and decoding binary data using a Base64 representation -Benchmark:: Provides methods to measure and report the time used to execute code -Bundler:: Manage your Ruby application's gem dependencies -CGI:: Support for the Common Gateway Interface protocol -CSV:: Provides an interface to read and write CSV files and data -Delegator:: Provides three abilities to delegate method calls to an object -DidYouMean:: "Did you mean?" experience in Ruby -DRb:: Distributed object system for Ruby -English:: Provides references to special global variables with less cryptic names -ERB:: An easy to use but powerful templating system for Ruby -ErrorHighlight:: Highlight error location in your code -FileUtils:: Several file utility methods for copying, moving, removing, etc -Find:: This module supports top-down traversal of a set of file paths -Forwardable:: Provides delegation of specified methods to a designated object -GetoptLong:: Parse command line options similar to the GNU C getopt_long() -IPAddr:: Provides methods to manipulate IPv4 and IPv6 IP addresses -IRB:: Interactive Ruby command-line tool for REPL (Read Eval Print Loop) -OptionParser:: Ruby-oriented class for command-line option analysis -Logger:: Provides a simple logging utility for outputting messages -Mutex_m:: Mixin to extend objects to be handled like a Mutex -Net::HTTP:: HTTP client api for Ruby -Observable:: Provides a mechanism for publish/subscribe pattern in Ruby -Open3:: Provides access to stdin, stdout and stderr when running other programs -OpenStruct:: Class to build custom data structures, similar to a Hash -OpenURI:: An easy-to-use wrapper for Net::HTTP, Net::HTTPS and Net::FTP -PP:: Provides a PrettyPrinter for Ruby objects -PrettyPrinter:: Implements a pretty printing algorithm for readable structure -PStore:: Implements a file based persistence mechanism based on a Hash -Readline:: Wrapper for Readline extencion and Reline -Reline:: GNU Readline and Editline by pure Ruby implementation. -Resolv:: Thread-aware DNS resolver library in Ruby -resolv-replace.rb:: Replace Socket DNS with Resolv -RDoc:: Produces HTML and command-line documentation for Ruby -Rinda:: The Linda distributed computing paradigm in Ruby -SecureRandom:: Interface for secure random number generator -Set:: Provides a class to deal with collections of unordered, unique values -Shellwords:: Manipulates strings with word parsing rules of UNIX Bourne shell -Singleton:: Implementation of the Singleton pattern for Ruby -Tempfile:: A utility class for managing temporary files -Time:: Extends the Time class with methods for parsing and conversion -Timeout:: Auto-terminate potentially long-running operations in Ruby -tmpdir.rb:: Extends the Dir class to manage the OS temporary file path -TSort:: Topological sorting using Tarjan's algorithm -un.rb:: Utilities to replace common UNIX commands -URI:: A Ruby module providing support for Uniform Resource Identifiers -YAML:: Ruby client library for the Psych YAML implementation -WeakRef:: Allows a referenced object to be garbage-collected - -== Extensions - -BigDecimal:: Provides arbitrary-precision floating point decimal arithmetic -Date:: A subclass of Object includes Comparable module for handling dates -DateTime:: Subclass of Date to handling dates, hours, minutes, seconds, offsets -Digest:: Provides a framework for message digest libraries -Etc:: Provides access to information typically stored in UNIX /etc directory -Fcntl:: Loads constants defined in the OS fcntl.h C header file -Fiddle:: A libffi wrapper for Ruby -IO:: Extensions for Ruby IO class, including #wait, #nonblock and ::console -JSON:: Implements Javascript Object Notation for Ruby -NKF:: Ruby extension for Network Kanji Filter -OpenSSL:: Provides SSL, TLS and general purpose cryptography for Ruby -Pathname:: Representation of the name of a file or directory on the filesystem -Psych:: A YAML parser and emitter for Ruby -StringIO:: Pseudo I/O on String objects -StringScanner:: Provides lexical scanning operations on a String -Syslog:: Ruby interface for the POSIX system logging facility -WIN32OLE:: Provides an interface for OLE Automation in Ruby -Zlib:: Ruby interface for the zlib compression/decompression library - -= Bundled gems - -* bundled gems are shipped with Ruby releases and also available as rubygems. -* bundled gems are same as normal gems like `rails`, `rack`. - * They are only bundled with Ruby releases. - * They can be uninstallable from Ruby installation. - * They are needed to declare in Gemfile when use with bundler. - -== Libraries - -MiniTest:: A test suite with TDD, BDD, mocking and benchmarking -PowerAssert:: Power Assert for Ruby. -Rake:: Ruby build program with capabilities similar to make -Test::Unit:: A compatibility layer for MiniTest -REXML:: An XML toolkit for Ruby -RSS:: Family of libraries that support various formats of XML "feeds" -Net::FTP:: Support for the File Transfer Protocol -Net::IMAP:: Ruby client api for Internet Message Access Protocol -Net::POP3:: Ruby client library for POP3 -Net::SMTP:: Simple Mail Transfer Protocol client library for Ruby -Matrix:: Represents a mathematical matrix. -Prime:: Prime numbers and factorization library -RBS:: RBS is a language to describe the structure of Ruby programs -TypeProf:: A type analysis tool for Ruby code based on abstract interpretation -DEBUGGER__:: Debugging functionality for Ruby -Racc:: A LALR(1) parser generator written in Ruby. diff --git a/doc/strftime_formatting.rdoc b/doc/strftime_formatting.rdoc index 30a629bf683083..5c7b33155df9ec 100644 --- a/doc/strftime_formatting.rdoc +++ b/doc/strftime_formatting.rdoc @@ -1,4 +1,4 @@ -== Formats for Dates and Times += Formats for Dates and Times Several Ruby time-related classes have instance method +strftime+, which returns a formatted string representing all or part of a date or time: @@ -32,9 +32,9 @@ It consists of: Except for the leading percent character, the only required part is the conversion specifier, so we begin with that. -=== Conversion Specifiers +== Conversion Specifiers -==== \Date (Year, Month, Day) +=== \Date (Year, Month, Day) - %Y - Year including century, zero-padded: @@ -87,7 +87,7 @@ the only required part is the conversion specifier, so we begin with that. Time.new(2002, 1, 1).strftime('%j') # => "001" Time.new(2002, 12, 31).strftime('%j') # => "365" -==== \Time (Hour, Minute, Second, Subsecond) +=== \Time (Hour, Minute, Second, Subsecond) - %H - Hour of the day, in range (0..23), zero-padded: @@ -152,7 +152,7 @@ the only required part is the conversion specifier, so we begin with that. Time.now.strftime('%s') # => "1656505136" -==== Timezone +=== Timezone - %z - Timezone as hour and minute offset from UTC: @@ -162,7 +162,7 @@ the only required part is the conversion specifier, so we begin with that. Time.now.strftime('%Z') # => "Central Daylight Time" -==== Weekday +=== Weekday - %A - Full weekday name: @@ -184,7 +184,7 @@ the only required part is the conversion specifier, so we begin with that. t.strftime('%a') # => "Sun" t.strftime('%w') # => "0" -==== Week Number +=== Week Number - %U - Week number of the year, in range (0..53), zero-padded, where each week begins on a Sunday: @@ -200,7 +200,7 @@ the only required part is the conversion specifier, so we begin with that. t.strftime('%a') # => "Sun" t.strftime('%W') # => "25" -==== Week Dates +=== Week Dates See {ISO 8601 week dates}[https://en.wikipedia.org/wiki/ISO_8601#Week_dates]. @@ -223,7 +223,7 @@ See {ISO 8601 week dates}[https://en.wikipedia.org/wiki/ISO_8601#Week_dates]. t0.strftime('%V') # => "52" t1.strftime('%V') # => "01" -==== Literals +=== Literals - %n - Newline character "\n": @@ -237,7 +237,7 @@ See {ISO 8601 week dates}[https://en.wikipedia.org/wiki/ISO_8601#Week_dates]. Time.now.strftime('%%') # => "%" -==== Shorthand Conversion Specifiers +=== Shorthand Conversion Specifiers Each shorthand specifier here is shown with its corresponding longhand specifier. @@ -294,14 +294,14 @@ longhand specifier. DateTime.now.strftime('%a %b %e %H:%M:%S %Z %Y') # => "Wed Jun 29 08:32:18 -05:00 2022" -=== Flags +== Flags Flags may affect certain formatting specifications. Multiple flags may be given with a single conversion specified; order does not matter. -==== Padding Flags +=== Padding Flags - 0 - Pad with zeroes: @@ -315,7 +315,7 @@ order does not matter. Time.new(10).strftime('%-Y') # => "10" -==== Casing Flags +=== Casing Flags - ^ - Upcase result: @@ -328,7 +328,7 @@ order does not matter. Time.now.strftime('%^p') # => "AM" Time.now.strftime('%#p') # => "am" -==== Timezone Flags +=== Timezone Flags - : - Put timezone as colon-separated hours and minutes: @@ -338,7 +338,7 @@ order does not matter. Time.now.strftime('%::z') # => "-05:00:00" -=== Width Specifiers +== Width Specifiers The integer width specifier gives a minimum width for the returned string: @@ -348,15 +348,15 @@ The integer width specifier gives a minimum width for the returned string: Time.new(2002, 12).strftime('%10B') # => " December" Time.new(2002, 12).strftime('%3B') # => "December" # Ignored if too small. -== Specialized Format Strings += Specialized Format Strings Here are a few specialized format strings, each based on an external standard. -=== HTTP Format +== HTTP Format The HTTP date format is based on -{RFC 2616}[https://datatracker.ietf.org/doc/html/rfc2616], +{RFC 2616}[https://www.rfc-editor.org/rfc/rfc2616], and treats dates in the format '%a, %d %b %Y %T GMT': d = Date.new(2001, 2, 3) # => # @@ -368,10 +368,10 @@ and treats dates in the format '%a, %d %b %Y %T GMT': Date._httpdate(httpdate) # => {:wday=>6, :mday=>3, :mon=>2, :year=>2001, :hour=>0, :min=>0, :sec=>0, :zone=>"GMT", :offset=>0} -=== RFC 3339 Format +== RFC 3339 Format The RFC 3339 date format is based on -{RFC 3339}[https://datatracker.ietf.org/doc/html/rfc3339]: +{RFC 3339}[https://www.rfc-editor.org/rfc/rfc3339]: d = Date.new(2001, 2, 3) # => # # Return 3339-formatted string. @@ -382,10 +382,10 @@ The RFC 3339 date format is based on Date._rfc3339(rfc3339) # => {:year=>2001, :mon=>2, :mday=>3, :hour=>0, :min=>0, :sec=>0, :zone=>"+00:00", :offset=>0} -=== RFC 2822 Format +== RFC 2822 Format The RFC 2822 date format is based on -{RFC 2822}[https://datatracker.ietf.org/doc/html/rfc2822], +{RFC 2822}[https://www.rfc-editor.org/rfc/rfc2822], and treats dates in the format '%a, %-d %b %Y %T %z']: d = Date.new(2001, 2, 3) # => # @@ -397,7 +397,7 @@ and treats dates in the format '%a, %-d %b %Y %T %z']: Date._rfc2822(rfc2822) # => {:wday=>6, :mday=>3, :mon=>2, :year=>2001, :hour=>0, :min=>0, :sec=>0, :zone=>"+0000", :offset=>0} -=== JIS X 0301 Format +== JIS X 0301 Format The JIS X 0301 format includes the {Japanese era name}[https://en.wikipedia.org/wiki/Japanese_era_name], @@ -412,7 +412,7 @@ with the first letter of the romanized era name prefixed: # Return hash parsed from 0301-formatted string. Date._jisx0301(jisx0301) # => {:year=>2001, :mon=>2, :mday=>3} -=== ISO 8601 Format Specifications +== ISO 8601 Format Specifications This section shows format specifications that are compatible with {ISO 8601}[https://en.wikipedia.org/wiki/ISO_8601]. @@ -422,7 +422,7 @@ Examples in this section assume: t = Time.now # => 2022-06-29 16:49:25.465246 -0500 -==== Dates +=== Dates See {ISO 8601 dates}[https://en.wikipedia.org/wiki/ISO_8601#Dates]. @@ -473,7 +473,7 @@ See {ISO 8601 dates}[https://en.wikipedia.org/wiki/ISO_8601#Dates]. t.strftime('%Y-%j') # => "2022-180" -==== Times +=== Times See {ISO 8601 times}[https://en.wikipedia.org/wiki/ISO_8601#Times]. @@ -514,7 +514,7 @@ See {ISO 8601 times}[https://en.wikipedia.org/wiki/ISO_8601#Times]. - {Coordinated Universal Time (UTC)}[https://en.wikipedia.org/wiki/ISO_8601#Coordinated_Universal_Time_(UTC)]. - {Time offsets from UTC}[https://en.wikipedia.org/wiki/ISO_8601#Time_offsets_from_UTC]. -==== Combined \Date and \Time +=== Combined \Date and \Time See {ISO 8601 Combined date and time representations}[https://en.wikipedia.org/wiki/ISO_8601#Combined_date_and_time_representations]. diff --git a/doc/string.rb b/doc/string.rb new file mode 100644 index 00000000000000..d68b40743b9d77 --- /dev/null +++ b/doc/string.rb @@ -0,0 +1,560 @@ +# A +String+ object has an arbitrary sequence of bytes, +# typically representing text or binary data. +# A +String+ object may be created using String::new or as literals. +# +# String objects differ from Symbol objects in that Symbol objects are +# designed to be used as identifiers, instead of text or data. +# +# You can create a +String+ object explicitly with: +# +# - A {string literal}[rdoc-ref:syntax/literals.rdoc@String+Literals]. +# - A {heredoc literal}[rdoc-ref:syntax/literals.rdoc@Here+Document+Literals]. +# +# You can convert certain objects to Strings with: +# +# - Method #String. +# +# Some +String+ methods modify +self+. +# Typically, a method whose name ends with ! modifies +self+ +# and returns +self+; +# often, a similarly named method (without the !) +# returns a new string. +# +# In general, if both bang and non-bang versions of a method exist, +# the bang method mutates and the non-bang method does not. +# However, a method without a bang can also mutate, such as String#replace. +# +# == Substitution Methods +# +# These methods perform substitutions: +# +# - String#sub: One substitution (or none); returns a new string. +# - String#sub!: One substitution (or none); returns +self+ if any changes, +# +nil+ otherwise. +# - String#gsub: Zero or more substitutions; returns a new string. +# - String#gsub!: Zero or more substitutions; returns +self+ if any changes, +# +nil+ otherwise. +# +# Each of these methods takes: +# +# - A first argument, +pattern+ (String or Regexp), +# that specifies the substring(s) to be replaced. +# +# - Either of the following: +# +# - A second argument, +replacement+ (String or Hash), +# that determines the replacing string. +# - A block that will determine the replacing string. +# +# The examples in this section mostly use the String#sub and String#gsub methods; +# the principles illustrated apply to all four substitution methods. +# +# Argument +pattern+ +# +# Argument +pattern+ is commonly a regular expression: +# +# s = 'hello' +# s.sub(/[aeiou]/, '*') # => "h*llo" +# s.gsub(/[aeiou]/, '*') # => "h*ll*" +# s.gsub(/[aeiou]/, '') # => "hll" +# s.sub(/ell/, 'al') # => "halo" +# s.gsub(/xyzzy/, '*') # => "hello" +# 'THX1138'.gsub(/\d+/, '00') # => "THX00" +# +# When +pattern+ is a string, all its characters are treated +# as ordinary characters (not as Regexp special characters): +# +# 'THX1138'.gsub('\d+', '00') # => "THX1138" +# +# +String+ +replacement+ +# +# If +replacement+ is a string, that string determines +# the replacing string that is substituted for the matched text. +# +# Each of the examples above uses a simple string as the replacing string. +# +# +String+ +replacement+ may contain back-references to the pattern's captures: +# +# - \n (_n_ is a non-negative integer) refers to $n. +# - \k refers to the named capture +name+. +# +# See Regexp for details. +# +# Note that within the string +replacement+, a character combination +# such as $& is treated as ordinary text, not as +# a special match variable. +# However, you may refer to some special match variables using these +# combinations: +# +# - \& and \0 correspond to $&, +# which contains the complete matched text. +# - \' corresponds to $', +# which contains the string after the match. +# - \` corresponds to $`, +# which contains the string before the match. +# - \\+ corresponds to $+, +# which contains the last capture group. +# +# See Regexp for details. +# +# Note that \\\\ is interpreted as an escape, i.e., a single backslash. +# +# Note also that a string literal consumes backslashes. +# See {String Literals}[rdoc-ref:syntax/literals.rdoc@String+Literals] for details about string literals. +# +# A back-reference is typically preceded by an additional backslash. +# For example, if you want to write a back-reference \& in +# +replacement+ with a double-quoted string literal, you need to write +# "..\\\\&..". +# +# If you want to write a non-back-reference string \& in +# +replacement+, you need to first escape the backslash to prevent +# this method from interpreting it as a back-reference, and then you +# need to escape the backslashes again to prevent a string literal from +# consuming them: "..\\\\\\\\&..". +# +# You may want to use the block form to avoid excessive backslashes. +# +# \Hash +replacement+ +# +# If the argument +replacement+ is a hash, and +pattern+ matches one of its keys, +# the replacing string is the value for that key: +# +# h = {'foo' => 'bar', 'baz' => 'bat'} +# 'food'.sub('foo', h) # => "bard" +# +# Note that a symbol key does not match: +# +# h = {foo: 'bar', baz: 'bat'} +# 'food'.sub('foo', h) # => "d" +# +# Block +# +# In the block form, the current match string is passed to the block; +# the block's return value becomes the replacing string: +# +# s = '@' +# '1234'.gsub(/\d/) { |match| s.succ! } # => "ABCD" +# +# Special match variables such as $1, $2, $`, +# $&, and $' are set appropriately. +# +# == Whitespace in Strings +# +# In the class +String+, _whitespace_ is defined as a contiguous sequence of characters +# consisting of any mixture of the following: +# +# - NL (null): "\x00", "\u0000". +# - HT (horizontal tab): "\x09", "\t". +# - LF (line feed): "\x0a", "\n". +# - VT (vertical tab): "\x0b", "\v". +# - FF (form feed): "\x0c", "\f". +# - CR (carriage return): "\x0d", "\r". +# - SP (space): "\x20", " ". +# +# +# Whitespace is relevant for the following methods: +# +# - #lstrip, #lstrip!: Strip leading whitespace. +# - #rstrip, #rstrip!: Strip trailing whitespace. +# - #strip, #strip!: Strip leading and trailing whitespace. +# +# == +String+ Slices +# +# A _slice_ of a string is a substring selected by certain criteria. +# +# These instance methods utilize slicing: +# +# - String#[] (aliased as String#slice): Returns a slice copied from +self+. +# - String#[]=: Mutates +self+ with the slice replaced. +# - String#slice!: Mutates +self+ with the slice removed and returns the removed slice. +# +# Each of the above methods takes arguments that determine the slice +# to be copied or replaced. +# +# The arguments have several forms. +# For a string +string+, the forms are: +# +# - string[index] +# - string[start, length] +# - string[range] +# - string[regexp, capture = 0] +# - string[substring] +# +# string[index] +# +# When a non-negative integer argument +index+ is given, +# the slice is the 1-character substring found in +self+ at character offset +index+: +# +# 'bar'[0] # => "b" +# 'bar'[2] # => "r" +# 'bar'[20] # => nil +# 'тест'[2] # => "с" +# 'こんにちは'[4] # => "は" +# +# When a negative integer +index+ is given, +# the slice begins at the offset given by counting backward from the end of +self+: +# +# 'bar'[-3] # => "b" +# 'bar'[-1] # => "r" +# 'bar'[-20] # => nil +# +# string[start, length] +# +# When non-negative integer arguments +start+ and +length+ are given, +# the slice begins at character offset +start+, if it exists, +# and continues for +length+ characters, if available: +# +# 'foo'[0, 2] # => "fo" +# 'тест'[1, 2] # => "ес" +# 'こんにちは'[2, 2] # => "にち" +# # Zero length. +# 'foo'[2, 0] # => "" +# # Length not entirely available. +# 'foo'[1, 200] # => "oo" +# # Start out of range. +# 'foo'[4, 2] # => nil +# +# Special case: if +start+ equals the length of +self+, +# the slice is a new empty string: +# +# 'foo'[3, 2] # => "" +# 'foo'[3, 200] # => "" +# +# When a negative +start+ and non-negative +length+ are given, +# the slice begins by counting backward from the end of +self+, +# and continues for +length+ characters, if available: +# +# 'foo'[-2, 2] # => "oo" +# 'foo'[-2, 200] # => "oo" +# # Start out of range. +# 'foo'[-4, 2] # => nil +# +# When a negative +length+ is given, there is no slice: +# +# 'foo'[1, -1] # => nil +# 'foo'[-2, -1] # => nil +# +# string[range] +# +# When a Range argument +range+ is given, +# it creates a substring of +string+ using the indices in +range+. +# The slice is then determined as above: +# +# 'foo'[0..1] # => "fo" +# 'foo'[0, 2] # => "fo" +# +# 'foo'[2...2] # => "" +# 'foo'[2, 0] # => "" +# +# 'foo'[1..200] # => "oo" +# 'foo'[1, 200] # => "oo" +# +# 'foo'[4..5] # => nil +# 'foo'[4, 2] # => nil +# +# 'foo'[-4..-3] # => nil +# 'foo'[-4, 2] # => nil +# +# 'foo'[3..4] # => "" +# 'foo'[3, 2] # => "" +# +# 'foo'[-2..-1] # => "oo" +# 'foo'[-2, 2] # => "oo" +# +# 'foo'[-2..197] # => "oo" +# 'foo'[-2, 200] # => "oo" +# +# string[regexp, capture = 0] +# +# When the Regexp argument +regexp+ is given, +# and the +capture+ argument is 0, +# the slice is the first matching substring found in +self+: +# +# 'foo'[/o/] # => "o" +# 'foo'[/x/] # => nil +# s = 'hello there' +# s[/[aeiou](.)\1/] # => "ell" +# s[/[aeiou](.)\1/, 0] # => "ell" +# +# If the argument +capture+ is provided and not 0, +# it should be either a capture group index (integer) +# or a capture group name (String or Symbol); +# the slice is the specified capture (see Regexp@Groups and Captures): +# +# s = 'hello there' +# s[/[aeiou](.)\1/, 1] # => "l" +# s[/(?[aeiou])(?[^aeiou])/, "non_vowel"] # => "l" +# s[/(?[aeiou])(?[^aeiou])/, :vowel] # => "e" +# +# If an invalid capture group index is given, there is no slice. +# If an invalid capture group name is given, +IndexError+ is raised. +# +# string[substring] +# +# When the single +String+ argument +substring+ is given, +# it returns the substring from +self+ if found, otherwise +nil+: +# +# 'foo'['oo'] # => "oo" +# 'foo'['xx'] # => nil +# +# == What's Here +# +# First, what's elsewhere. Class +String+: +# +# - Inherits from the {Object class}[rdoc-ref:Object@What-27s+Here]. +# - Includes the {Comparable module}[rdoc-ref:Comparable@What-27s+Here]. +# +# Here, class +String+ provides methods that are useful for: +# +# - {Creating a \String}[rdoc-ref:String@Creating+a+String]. +# - {Freezing/Unfreezing a \String}[rdoc-ref:String@Freezing-2FUnfreezing]. +# - {Querying a \String}[rdoc-ref:String@Querying]. +# - {Comparing Strings}[rdoc-ref:String@Comparing]. +# - {Modifying a \String}[rdoc-ref:String@Modifying]. +# - {Converting to a new \String}[rdoc-ref:String@Converting+to+New+String]. +# - {Converting to a non-\String}[rdoc-ref:String@Converting+to+Non--5CString]. +# - {Iterating over a \String}[rdoc-ref:String@Iterating]. +# +# === Creating a \String +# +# - ::new: Returns a new string. +# - ::try_convert: Returns a new string created from a given object. +# +# === Freezing/Unfreezing +# +# - #+@: Returns a string that is not frozen: +self+ if not frozen; +# +self.dup+ otherwise. +# - #-@ (aliased as #dedup): Returns a string that is frozen: +self+ if already frozen; +# +self.freeze+ otherwise. +# - #freeze: Freezes +self+ if not already frozen; returns +self+. +# +# === Querying +# +# _Counts_ +# +# - #length (aliased as #size): Returns the count of characters (not bytes). +# - #empty?: Returns +true+ if +self.length+ is zero; +false+ otherwise. +# - #bytesize: Returns the count of bytes. +# - #count: Returns the count of substrings matching given strings. +# +# _Substrings_ +# +# - #=~: Returns the index of the first substring that matches a given +# Regexp or other object; returns +nil+ if no match is found. +# - #byteindex: Returns the byte index of the first occurrence of a given substring. +# - #byterindex: Returns the byte index of the last occurrence of a given substring. +# - #index: Returns the index of the _first_ occurrence of a given substring; +# returns +nil+ if none found. +# - #rindex: Returns the index of the _last_ occurrence of a given substring; +# returns +nil+ if none found. +# - #include?: Returns +true+ if the string contains a given substring; +false+ otherwise. +# - #match: Returns a MatchData object if the string matches a given Regexp; +nil+ otherwise. +# - #match?: Returns +true+ if the string matches a given Regexp; +false+ otherwise. +# - #start_with?: Returns +true+ if the string begins with any of the given substrings. +# - #end_with?: Returns +true+ if the string ends with any of the given substrings. +# +# _Encodings_ +# +# - #encoding\: Returns the Encoding object that represents the encoding of the string. +# - #unicode_normalized?: Returns +true+ if the string is in Unicode normalized form; +false+ otherwise. +# - #valid_encoding?: Returns +true+ if the string contains only characters that are valid +# for its encoding. +# - #ascii_only?: Returns +true+ if the string has only ASCII characters; +false+ otherwise. +# +# _Other_ +# +# - #sum: Returns a basic checksum for the string: the sum of each byte. +# - #hash: Returns the integer hash code. +# +# === Comparing +# +# - #== (aliased as #===): Returns +true+ if a given other string has the same content as +self+. +# - #eql?: Returns +true+ if the content is the same as the given other string. +# - #<=>: Returns -1, 0, or 1 as a given other string is smaller than, +# equal to, or larger than +self+. +# - #casecmp: Ignoring case, returns -1, 0, or 1 as +# +self+ is smaller than, equal to, or larger than a given other string. +# - #casecmp?: Ignoring case, returns whether a given other string is equal to +self+. +# +# === Modifying +# +# Each of these methods modifies +self+. +# +# _Insertion_ +# +# - #insert: Returns +self+ with a given string inserted at a specified offset. +# - #<<: Returns +self+ concatenated with a given string or integer. +# - #append_as_bytes: Returns +self+ concatenated with strings without performing any +# encoding validation or conversion. +# +# _Substitution_ +# +# - #bytesplice: Replaces bytes of +self+ with bytes from a given string; returns +self+. +# - #sub!: Replaces the first substring that matches a given pattern with a given replacement string; +# returns +self+ if any changes, +nil+ otherwise. +# - #gsub!: Replaces each substring that matches a given pattern with a given replacement string; +# returns +self+ if any changes, +nil+ otherwise. +# - #succ! (aliased as #next!): Returns +self+ modified to become its own successor. +# - #initialize_copy (aliased as #replace): Returns +self+ with its entire content replaced by a given string. +# - #reverse!: Returns +self+ with its characters in reverse order. +# - #setbyte: Sets the byte at a given integer offset to a given value; returns the argument. +# - #tr!: Replaces specified characters in +self+ with specified replacement characters; +# returns +self+ if any changes, +nil+ otherwise. +# - #tr_s!: Replaces specified characters in +self+ with specified replacement characters, +# removing duplicates from the substrings that were modified; +# returns +self+ if any changes, +nil+ otherwise. +# +# _Casing_ +# +# - #capitalize!: Upcases the initial character and downcases all others; +# returns +self+ if any changes, +nil+ otherwise. +# - #downcase!: Downcases all characters; returns +self+ if any changes, +nil+ otherwise. +# - #upcase!: Upcases all characters; returns +self+ if any changes, +nil+ otherwise. +# - #swapcase!: Upcases each downcase character and downcases each upcase character; +# returns +self+ if any changes, +nil+ otherwise. +# +# _Encoding_ +# +# - #encode!: Returns +self+ with all characters transcoded from one encoding to another. +# - #unicode_normalize!: Unicode-normalizes +self+; returns +self+. +# - #scrub!: Replaces each invalid byte with a given character; returns +self+. +# - #force_encoding: Changes the encoding to a given encoding; returns +self+. +# +# _Deletion_ +# +# - #clear: Removes all content, so that +self+ is empty; returns +self+. +# - #slice!, #[]=: Removes a substring determined by a given index, start/length, range, regexp, or substring. +# - #squeeze!: Removes contiguous duplicate characters; returns +self+. +# - #delete!: Removes characters as determined by the intersection of substring arguments. +# - #delete_prefix!: Removes leading prefix; returns +self+ if any changes, +nil+ otherwise. +# - #delete_suffix!: Removes trailing suffix; returns +self+ if any changes, +nil+ otherwise. +# - #lstrip!: Removes leading whitespace; returns +self+ if any changes, +nil+ otherwise. +# - #rstrip!: Removes trailing whitespace; returns +self+ if any changes, +nil+ otherwise. +# - #strip!: Removes leading and trailing whitespace; returns +self+ if any changes, +nil+ otherwise. +# - #chomp!: Removes the trailing record separator, if found; returns +self+ if any changes, +nil+ otherwise. +# - #chop!: Removes trailing newline characters if found; otherwise removes the last character; +# returns +self+ if any changes, +nil+ otherwise. +# +# === Converting to New \String +# +# Each of these methods returns a new +String+ based on +self+, +# often just a modified copy of +self+. +# +# _Extension_ +# +# - #*: Returns the concatenation of multiple copies of +self+. +# - #+: Returns the concatenation of +self+ and a given other string. +# - #center: Returns a copy of +self+, centered by specified padding. +# - #concat: Returns the concatenation of +self+ with given other strings. +# - #prepend: Returns the concatenation of a given other string with +self+. +# - #ljust: Returns a copy of +self+ of a given length, right-padded with a given other string. +# - #rjust: Returns a copy of +self+ of a given length, left-padded with a given other string. +# +# _Encoding_ +# +# - #b: Returns a copy of +self+ with ASCII-8BIT encoding. +# - #scrub: Returns a copy of +self+ with each invalid byte replaced with a given character. +# - #unicode_normalize: Returns a copy of +self+ with each character Unicode-normalized. +# - #encode: Returns a copy of +self+ with all characters transcoded from one encoding to another. +# +# _Substitution_ +# +# - #dump: Returns a copy of +self+ with all non-printing characters replaced by \xHH notation +# and all special characters escaped. +# - #undump: Returns a copy of +self+ with all \xNN notations replaced by \uNNNN notations +# and all escaped characters unescaped. +# - #sub: Returns a copy of +self+ with the first substring matching a given pattern +# replaced with a given replacement string. +# - #gsub: Returns a copy of +self+ with each substring that matches a given pattern +# replaced with a given replacement string. +# - #succ (aliased as #next): Returns the string that is the successor to +self+. +# - #reverse: Returns a copy of +self+ with its characters in reverse order. +# - #tr: Returns a copy of +self+ with specified characters replaced with specified replacement characters. +# - #tr_s: Returns a copy of +self+ with specified characters replaced with +# specified replacement characters, +# removing duplicates from the substrings that were modified. +# - #%: Returns the string resulting from formatting a given object into +self+. +# +# _Casing_ +# +# - #capitalize: Returns a copy of +self+ with the first character upcased +# and all other characters downcased. +# - #downcase: Returns a copy of +self+ with all characters downcased. +# - #upcase: Returns a copy of +self+ with all characters upcased. +# - #swapcase: Returns a copy of +self+ with all upcase characters downcased +# and all downcase characters upcased. +# +# _Deletion_ +# +# - #delete: Returns a copy of +self+ with characters removed. +# - #delete_prefix: Returns a copy of +self+ with a given prefix removed. +# - #delete_suffix: Returns a copy of +self+ with a given suffix removed. +# - #lstrip: Returns a copy of +self+ with leading whitespace removed. +# - #rstrip: Returns a copy of +self+ with trailing whitespace removed. +# - #strip: Returns a copy of +self+ with leading and trailing whitespace removed. +# - #chomp: Returns a copy of +self+ with a trailing record separator removed, if found. +# - #chop: Returns a copy of +self+ with trailing newline characters or the last character removed. +# - #squeeze: Returns a copy of +self+ with contiguous duplicate characters removed. +# - #[] (aliased as #slice): Returns a substring determined by a given index, start/length, range, regexp, or string. +# - #byteslice: Returns a substring determined by a given index, start/length, or range. +# - #chr: Returns the first character. +# +# _Duplication_ +# +# - #to_s (aliased as #to_str): If +self+ is a subclass of +String+, returns +self+ copied into a +String+; +# otherwise, returns +self+. +# +# === Converting to Non-\String +# +# Each of these methods converts the contents of +self+ to a non-+String+. +# +# Characters, Bytes, and Clusters +# +# - #bytes: Returns an array of the bytes in +self+. +# - #chars: Returns an array of the characters in +self+. +# - #codepoints: Returns an array of the integer ordinals in +self+. +# - #getbyte: Returns the integer byte at the given index in +self+. +# - #grapheme_clusters: Returns an array of the grapheme clusters in +self+. +# +# _Splitting_ +# +# - #lines: Returns an array of the lines in +self+, as determined by a given record separator. +# - #partition: Returns a 3-element array determined by the first substring that matches +# a given substring or regexp. +# - #rpartition: Returns a 3-element array determined by the last substring that matches +# a given substring or regexp. +# - #split: Returns an array of substrings determined by a given delimiter -- regexp or string -- +# or, if a block is given, passes those substrings to the block. +# +# _Matching_ +# +# - #scan: Returns an array of substrings matching a given regexp or string, or, +# if a block is given, passes each matching substring to the block. +# - #unpack: Returns an array of substrings extracted from +self+ according to a given format. +# - #unpack1: Returns the first substring extracted from +self+ according to a given format. +# +# _Numerics_ +# +# - #hex: Returns the integer value of the leading characters, interpreted as hexadecimal digits. +# - #oct: Returns the integer value of the leading characters, interpreted as octal digits. +# - #ord: Returns the integer ordinal of the first character in +self+. +# - #to_i: Returns the integer value of leading characters, interpreted as an integer. +# - #to_f: Returns the floating-point value of leading characters, interpreted as a floating-point number. +# +# Strings and Symbols +# +# - #inspect: Returns a copy of +self+, enclosed in double quotes, with special characters escaped. +# - #intern (aliased as #to_sym): Returns the symbol corresponding to +self+. +# +# === Iterating +# +# - #each_byte: Calls the given block with each successive byte in +self+. +# - #each_char: Calls the given block with each successive character in +self+. +# - #each_codepoint: Calls the given block with each successive integer codepoint in +self+. +# - #each_grapheme_cluster: Calls the given block with each successive grapheme cluster in +self+. +# - #each_line: Calls the given block with each successive line in +self+, +# as determined by a given record separator. +# - #upto: Calls the given block with each string value returned by successive calls to #succ. + +class String; end diff --git a/doc/string/b.rdoc b/doc/string/b.rdoc index f8ad2910b4c82a..8abd6d9532bb3e 100644 --- a/doc/string/b.rdoc +++ b/doc/string/b.rdoc @@ -12,3 +12,5 @@ the underlying bytes are not modified: t = s.b # => "\xE4\x82\x95" t.encoding # => # t.bytes # => [228, 130, 149] + +Related: see {Converting to New String}[rdoc-ref:String@Converting+to+New+String]. diff --git a/doc/string/bytes.rdoc b/doc/string/bytes.rdoc index a9e89f1cd1a733..f4b071f6306394 100644 --- a/doc/string/bytes.rdoc +++ b/doc/string/bytes.rdoc @@ -4,3 +4,5 @@ Returns an array of the bytes in +self+: 'тест'.bytes # => [209, 130, 208, 181, 209, 129, 209, 130] 'こんにちは'.bytes # => [227, 129, 147, 227, 130, 147, 227, 129, 171, 227, 129, 161, 227, 129, 175] + +Related: see {Converting to Non-String}[rdoc-ref:String@Converting+to+Non--5CString]. diff --git a/doc/string/bytesize.rdoc b/doc/string/bytesize.rdoc index b0567ff67b2547..5166dd7dc614ac 100644 --- a/doc/string/bytesize.rdoc +++ b/doc/string/bytesize.rdoc @@ -1,11 +1,15 @@ -Returns the count of bytes (not characters) in +self+: +Returns the count of bytes in +self+. - 'foo'.bytesize # => 3 - 'тест'.bytesize # => 8 - 'こんにちは'.bytesize # => 15 +Note that the byte count may be different from the character count (returned by #size): -Contrast with String#length: + s = 'foo' + s.bytesize # => 3 + s.size # => 3 + s = 'тест' + s.bytesize # => 8 + s.size # => 4 + s = 'こんにちは' + s.bytesize # => 15 + s.size # => 5 - 'foo'.length # => 3 - 'тест'.length # => 4 - 'こんにちは'.length # => 5 +Related: see {Querying}[rdoc-ref:String@Querying]. diff --git a/doc/string/byteslice.rdoc b/doc/string/byteslice.rdoc new file mode 100644 index 00000000000000..d70441fb2b6d6d --- /dev/null +++ b/doc/string/byteslice.rdoc @@ -0,0 +1,54 @@ +Returns a substring of +self+, or +nil+ if the substring cannot be constructed. + +With integer arguments +offset+ and +length+ given, +returns the substring beginning at the given +offset+ +and of the given +length+ (as available): + + s = '0123456789' # => "0123456789" + s.byteslice(2) # => "2" + s.byteslice(200) # => nil + s.byteslice(4, 3) # => "456" + s.byteslice(4, 30) # => "456789" + +Returns +nil+ if +length+ is negative or +offset+ falls outside of +self+: + + s.byteslice(4, -1) # => nil + s.byteslice(40, 2) # => nil + +Counts backwards from the end of +self+ +if +offset+ is negative: + + s = '0123456789' # => "0123456789" + s.byteslice(-4) # => "6" + s.byteslice(-4, 3) # => "678" + +With Range argument +range+ given, returns +byteslice(range.begin, range.size): + + s = '0123456789' # => "0123456789" + s.byteslice(4..6) # => "456" + s.byteslice(-6..-4) # => "456" + s.byteslice(5..2) # => "" # range.size is zero. + s.byteslice(40..42) # => nil + +The starting and ending offsets need not be on character boundaries: + + s = 'こんにちは' + s.byteslice(0, 3) # => "こ" + s.byteslice(1, 3) # => "\x81\x93\xE3" + +The encodings of +self+ and the returned substring +are always the same: + + s.encoding # => # + s.byteslice(0, 3).encoding # => # + s.byteslice(1, 3).encoding # => # + +But, depending on the character boundaries, +the encoding of the returned substring may not be valid: + + s.valid_encoding? # => true + s.byteslice(0, 3).valid_encoding? # => true + s.byteslice(1, 3).valid_encoding? # => false + +Related: see {Converting to New String}[rdoc-ref:String@Converting+to+New+String]. diff --git a/doc/string/bytesplice.rdoc b/doc/string/bytesplice.rdoc new file mode 100644 index 00000000000000..5689ef4a2ba79b --- /dev/null +++ b/doc/string/bytesplice.rdoc @@ -0,0 +1,66 @@ +Replaces target bytes in +self+ with source bytes from the given string +str+; +returns +self+. + +In the first form, arguments +offset+ and +length+ determine the target bytes, +and the source bytes are all of the given +str+: + + '0123456789'.bytesplice(0, 3, 'abc') # => "abc3456789" + '0123456789'.bytesplice(3, 3, 'abc') # => "012abc6789" + '0123456789'.bytesplice(0, 50, 'abc') # => "abc" + '0123456789'.bytesplice(50, 3, 'abc') # Raises IndexError. + +The counts of the target bytes and source source bytes may be different: + + '0123456789'.bytesplice(0, 6, 'abc') # => "abc6789" # Shorter source. + '0123456789'.bytesplice(0, 1, 'abc') # => "abc123456789" # Shorter target. + +And either count may be zero (i.e., specifying an empty string): + + '0123456789'.bytesplice(0, 3, '') # => "3456789" # Empty source. + '0123456789'.bytesplice(0, 0, 'abc') # => "abc0123456789" # Empty target. + +In the second form, just as in the first, +arugments +offset+ and +length+ determine the target bytes; +argument +str+ _contains_ the source bytes, +and the additional arguments +str_offset+ and +str_length+ +determine the actual source bytes: + + '0123456789'.bytesplice(0, 3, 'abc', 0, 3) # => "abc3456789" + '0123456789'.bytesplice(0, 3, 'abc', 1, 1) # => "b3456789" # Shorter source. + '0123456789'.bytesplice(0, 1, 'abc', 0, 3) # => "abc123456789" # Shorter target. + '0123456789'.bytesplice(0, 3, 'abc', 1, 0) # => "3456789" # Empty source. + '0123456789'.bytesplice(0, 0, 'abc', 0, 3) # => "abc0123456789" # Empty target. + +In the third form, argument +range+ determines the target bytes +and the source bytes are all of the given +str+: + + '0123456789'.bytesplice(0..2, 'abc') # => "abc3456789" + '0123456789'.bytesplice(3..5, 'abc') # => "012abc6789" + '0123456789'.bytesplice(0..5, 'abc') # => "abc6789" # Shorter source. + '0123456789'.bytesplice(0..0, 'abc') # => "abc123456789" # Shorter target. + '0123456789'.bytesplice(0..2, '') # => "3456789" # Empty source. + '0123456789'.bytesplice(0...0, 'abc') # => "abc0123456789" # Empty target. + +In the fourth form, just as in the third, +arugment +range+ determines the target bytes; +argument +str+ _contains_ the source bytes, +and the additional argument +str_range+ +determines the actual source bytes: + + '0123456789'.bytesplice(0..2, 'abc', 0..2) # => "abc3456789" + '0123456789'.bytesplice(3..5, 'abc', 0..2) # => "012abc6789" + '0123456789'.bytesplice(0..2, 'abc', 0..1) # => "ab3456789" # Shorter source. + '0123456789'.bytesplice(0..1, 'abc', 0..2) # => "abc23456789" # Shorter target. + '0123456789'.bytesplice(0..2, 'abc', 0...0) # => "3456789" # Empty source. + '0123456789'.bytesplice(0...0, 'abc', 0..2) # => "abc0123456789" # Empty target. + +In any of the forms, the beginnings and endings of both source and target +must be on character boundaries. + +In these examples, +self+ has five 3-byte characters, +and so has character boundaries at offsets 0, 3, 6, 9, 12, and 15. + + 'こんにちは'.bytesplice(0, 3, 'abc') # => "abcんにちは" + 'こんにちは'.bytesplice(1, 3, 'abc') # Raises IndexError. + 'こんにちは'.bytesplice(0, 2, 'abc') # Raises IndexError. + diff --git a/doc/string/center.rdoc b/doc/string/center.rdoc index d53d921ad52092..343f6ba263acae 100644 --- a/doc/string/center.rdoc +++ b/doc/string/center.rdoc @@ -2,15 +2,19 @@ Returns a centered copy of +self+. If integer argument +size+ is greater than the size (in characters) of +self+, returns a new string of length +size+ that is a copy of +self+, -centered and padded on both ends with +pad_string+: +centered and padded on one or both ends with +pad_string+: - 'hello'.center(10) # => " hello " - ' hello'.center(10) # => " hello " - 'hello'.center(10, 'ab') # => "abhelloaba" - 'тест'.center(10) # => " тест " - 'こんにちは'.center(10) # => " こんにちは " + 'hello'.center(6) # => "hello " # Padded on one end. + 'hello'.center(10) # => " hello " # Padded on both ends. + 'hello'.center(20, '-|') # => "-|-|-|-hello-|-|-|-|" # Some padding repeated. + 'hello'.center(10, 'abcdefg') # => "abhelloabc" # Some padding not used. + ' hello '.center(13) # => " hello " + 'тест'.center(10) # => " тест " + 'こんにちは'.center(10) # => " こんにちは " # Multi-byte characters. -If +size+ is not greater than the size of +self+, returns a copy of +self+: +If +size+ is less than or equal to the size of +self+, returns an unpadded copy of +self+: - 'hello'.center(5) # => "hello" - 'hello'.center(1) # => "hello" + 'hello'.center(5) # => "hello" + 'hello'.center(-10) # => "hello" + +Related: see {Converting to New String}[rdoc-ref:String@Converting+to+New+String]. diff --git a/doc/string/chars.rdoc b/doc/string/chars.rdoc index d24a1cc3a925ca..094384271b1a77 100644 --- a/doc/string/chars.rdoc +++ b/doc/string/chars.rdoc @@ -3,3 +3,6 @@ Returns an array of the characters in +self+: 'hello'.chars # => ["h", "e", "l", "l", "o"] 'тест'.chars # => ["т", "е", "с", "т"] 'こんにちは'.chars # => ["こ", "ん", "に", "ち", "は"] + ''.chars # => [] + +Related: see {Converting to Non-String}[rdoc-ref:String@Converting+to+Non--5CString]. diff --git a/doc/string/chomp.rdoc b/doc/string/chomp.rdoc index b6fb9ff38ccc50..6ec7664f6b6832 100644 --- a/doc/string/chomp.rdoc +++ b/doc/string/chomp.rdoc @@ -25,5 +25,8 @@ removes multiple trailing occurrences of "\n" or "\r\n" When +line_sep+ is neither "\n" nor '', removes a single trailing line separator if there is one: - 'abcd'.chomp('d') # => "abc" - 'abcdd'.chomp('d') # => "abcd" + 'abcd'.chomp('cd') # => "ab" + 'abcdcd'.chomp('cd') # => "abcd" + 'abcd'.chomp('xx') # => "abcd" + +Related: see {Converting to New String}[rdoc-ref:String@Converting+to+New+String]. diff --git a/doc/string/chop.rdoc b/doc/string/chop.rdoc index 8ef82f8a492548..2c48e911292eff 100644 --- a/doc/string/chop.rdoc +++ b/doc/string/chop.rdoc @@ -13,4 +13,7 @@ Otherwise removes the last character if it exists. 'こんにちは'.chop # => "こんにち" ''.chop # => "" -If you only need to remove the newline separator at the end of the string, String#chomp is a better alternative. +If you only need to remove the newline separator at the end of the string, +String#chomp is a better alternative. + +Related: see {Converting to New String}[rdoc-ref:String@Converting+to+New+String]. diff --git a/doc/string/chr.rdoc b/doc/string/chr.rdoc new file mode 100644 index 00000000000000..1ada3854cbeb27 --- /dev/null +++ b/doc/string/chr.rdoc @@ -0,0 +1,8 @@ +Returns a string containing the first character of +self+: + + 'hello'.chr # => "h" + 'тест'.chr # => "т" + 'こんにちは'.chr # => "こ" + ''.chr # => "" + +Related: see {Converting to New String}[rdoc-ref:String@Converting+to+New+String]. diff --git a/doc/string/codepoints.rdoc b/doc/string/codepoints.rdoc index 0c55d3f4b95c35..d9586d2e0bc2a5 100644 --- a/doc/string/codepoints.rdoc +++ b/doc/string/codepoints.rdoc @@ -4,3 +4,6 @@ each codepoint is the integer value for a character: 'hello'.codepoints # => [104, 101, 108, 108, 111] 'тест'.codepoints # => [1090, 1077, 1089, 1090] 'こんにちは'.codepoints # => [12371, 12435, 12395, 12385, 12399] + ''.codepoints # => [] + +Related: see {Converting to Non-String}[rdoc-ref:String@Converting+to+Non--5CString]. diff --git a/doc/string/concat.rdoc b/doc/string/concat.rdoc new file mode 100644 index 00000000000000..2ba0c714af57d3 --- /dev/null +++ b/doc/string/concat.rdoc @@ -0,0 +1,12 @@ +Concatenates each object in +objects+ to +self+; returns +self+: + + 'foo'.concat('bar', 'baz') # => "foobarbaz" + +For each given object +object+ that is an integer, +the value is considered a codepoint and converted to a character before concatenation: + + 'foo'.concat(32, 'bar', 32, 'baz') # => "foo bar baz" # Embeds spaces. + 'те'.concat(1089, 1090) # => "тест" + 'こん'.concat(12395, 12385, 12399) # => "こんにちは" + +Related: see {Converting to New String}[rdoc-ref:String@Converting+to+New+String]. diff --git a/doc/string/count.rdoc b/doc/string/count.rdoc new file mode 100644 index 00000000000000..092c672d7d113b --- /dev/null +++ b/doc/string/count.rdoc @@ -0,0 +1,78 @@ +Returns the total number of characters in +self+ that are specified by the given selectors. + +For one 1-character selector, +returns the count of instances of that character: + + s = 'abracadabra' + s.count('a') # => 5 + s.count('b') # => 2 + s.count('x') # => 0 + s.count('') # => 0 + + s = 'тест' + s.count('т') # => 2 + s.count('е') # => 1 + + s = 'よろしくお願いします' + s.count('よ') # => 1 + s.count('し') # => 2 + +For one multi-character selector, +returns the count of instances for all specified characters: + + s = 'abracadabra' + s.count('ab') # => 7 + s.count('abc') # => 8 + s.count('abcd') # => 9 + s.count('abcdr') # => 11 + s.count('abcdrx') # => 11 + +Order and repetition do not matter: + + s.count('ba') == s.count('ab') # => true + s.count('baab') == s.count('ab') # => true + +For multiple selectors, +forms a single selector that is the intersection of characters in all selectors +and returns the count of instances for that selector: + + s = 'abcdefg' + s.count('abcde', 'dcbfg') == s.count('bcd') # => true + s.count('abc', 'def') == s.count('') # => true + +In a character selector, three characters get special treatment: + +- A caret ('^') functions as a _negation_ operator + for the immediately following characters: + + s = 'abracadabra' + s.count('^bc') # => 8 # Count of all except 'b' and 'c'. + +- A hyphen ('-') between two other characters defines a _range_ of characters: + + s = 'abracadabra' + s.count('a-c') # => 8 # Count of all 'a', 'b', and 'c'. + +- A backslash ('\') acts as an escape for a caret, a hyphen, + or another backslash: + + s = 'abracadabra' + s.count('\^bc') # => 3 # Count of '^', 'b', and 'c'. + s.count('a\-c') # => 6 # Count of 'a', '-', and 'c'. + 'foo\bar\baz'.count('\\') # => 2 # Count of '\'. + +These usages may be mixed: + + s = 'abracadabra' + s.count('a-cq-t') # => 10 # Multiple ranges. + s.count('ac-d') # => 7 # Range mixed with plain characters. + s.count('^a-c') # => 3 # Range mixed with negation. + +For multiple selectors, all forms may be used, including negations, ranges, and escapes. + + s = 'abracadabra' + s.count('^abc', '^def') == s.count('^abcdef') # => true + s.count('a-e', 'c-g') == s.count('cde') # => true + s.count('^abc', 'c-g') == s.count('defg') # => true + +Related: see {Querying}[rdoc-ref:String@Querying]. diff --git a/doc/string/delete.rdoc b/doc/string/delete.rdoc new file mode 100644 index 00000000000000..e8ff4c0ae400af --- /dev/null +++ b/doc/string/delete.rdoc @@ -0,0 +1,79 @@ +Returns a new string that is a copy of +self+ with certain characters removed; +the removed characters are all instances of those specified by the given string +selectors+. + +For one 1-character selector, +removes all instances of that character: + + s = 'abracadabra' + s.delete('a') # => "brcdbr" + s.delete('b') # => "aracadara" + s.delete('x') # => "abracadabra" + s.delete('') # => "abracadabra" + + s = 'тест' + s.delete('т') # => "ес" + s.delete('е') # => "тст" + + s = 'よろしくお願いします' + s.delete('よ') # => "ろしくお願いします" + s.delete('し') # => "よろくお願います" + +For one multi-character selector, +removes all instances of the specified characters: + + s = 'abracadabra' + s.delete('ab') # => "rcdr" + s.delete('abc') # => "rdr" + s.delete('abcd') # => "rr" + s.delete('abcdr') # => "" + s.delete('abcdrx') # => "" + +Order and repetition do not matter: + + s.delete('ba') == s.delete('ab') # => true + s.delete('baab') == s.delete('ab') # => true + +For multiple selectors, +forms a single selector that is the intersection of characters in all selectors +and removes all instances of characters specified by that selector: + + s = 'abcdefg' + s.delete('abcde', 'dcbfg') == s.delete('bcd') # => true + s.delete('abc', 'def') == s.delete('') # => true + +In a character selector, three characters get special treatment: + +- A caret ('^') functions as a _negation_ operator + for the immediately following characters: + + s = 'abracadabra' + s.delete('^bc') # => "bcb" # Deletes all except 'b' and 'c'. + +- A hyphen ('-') between two other characters defines a _range_ of characters: + + s = 'abracadabra' + s.delete('a-c') # => "rdr" # Deletes all 'a', 'b', and 'c'. + +- A backslash ('\') acts as an escape for a caret, a hyphen, + or another backslash: + + s = 'abracadabra' + s.delete('\^bc') # => "araadara" # Deletes all '^', 'b', and 'c'. + s.delete('a\-c') # => "brdbr" # Deletes all 'a', '-', and 'c'. + 'foo\bar\baz'.delete('\\') # => "foobarbaz" # Deletes all '\'. + +These usages may be mixed: + + s = 'abracadabra' + s.delete('a-cq-t') # => "d" # Multiple ranges. + s.delete('ac-d') # => "brbr" # Range mixed with plain characters. + s.delete('^a-c') # => "abacaaba" # Range mixed with negation. + +For multiple selectors, all forms may be used, including negations, ranges, and escapes. + + s = 'abracadabra' + s.delete('^abc', '^def') == s.delete('^abcdef') # => true + s.delete('a-e', 'c-g') == s.delete('cde') # => true + s.delete('^abc', 'c-g') == s.delete('defg') # => true + +Related: see {Converting to New String}[rdoc-ref:String@Converting+to+New+String]. diff --git a/doc/string/delete_prefix.rdoc b/doc/string/delete_prefix.rdoc index fa9d8abd38f372..1135f3d19d26ed 100644 --- a/doc/string/delete_prefix.rdoc +++ b/doc/string/delete_prefix.rdoc @@ -1,8 +1,10 @@ -Returns a copy of +self+ with leading substring prefix removed: +Returns a copy of +self+ with leading substring +prefix+ removed: - 'hello'.delete_prefix('hel') # => "lo" - 'hello'.delete_prefix('llo') # => "hello" + 'oof'.delete_prefix('o') # => "of" + 'oof'.delete_prefix('oo') # => "f" + 'oof'.delete_prefix('oof') # => "" + 'oof'.delete_prefix('x') # => "oof" 'тест'.delete_prefix('те') # => "ст" 'こんにちは'.delete_prefix('こん') # => "にちは" -Related: String#delete_prefix!, String#delete_suffix. +Related: see {Converting to New String}[rdoc-ref:String@Converting+to+New+String]. diff --git a/doc/string/delete_suffix.rdoc b/doc/string/delete_suffix.rdoc index 4862b725cfc646..2fb70ce012aabc 100644 --- a/doc/string/delete_suffix.rdoc +++ b/doc/string/delete_suffix.rdoc @@ -1,8 +1,11 @@ Returns a copy of +self+ with trailing substring suffix removed: - 'hello'.delete_suffix('llo') # => "he" - 'hello'.delete_suffix('hel') # => "hello" - 'тест'.delete_suffix('ст') # => "те" + 'foo'.delete_suffix('o') # => "fo" + 'foo'.delete_suffix('oo') # => "f" + 'foo'.delete_suffix('foo') # => "" + 'foo'.delete_suffix('f') # => "foo" + 'foo'.delete_suffix('x') # => "foo" + 'тест'.delete_suffix('ст') # => "те" 'こんにちは'.delete_suffix('ちは') # => "こんに" -Related: String#delete_suffix!, String#delete_prefix. +Related: see {Converting to New String}[rdoc-ref:String@Converting+to+New+String]. diff --git a/doc/string/new.rdoc b/doc/string/new.rdoc index d955e61c8737a9..e2752d6e1fd16a 100644 --- a/doc/string/new.rdoc +++ b/doc/string/new.rdoc @@ -1,34 +1,38 @@ -Returns a new \String that is a copy of +string+. +Returns a new \String object containing the given +string+. -With no arguments, returns the empty string with the Encoding ASCII-8BIT: +The +options+ are optional keyword options (see below). - s = String.new - s # => "" - s.encoding # => # +With no argument given and keyword +encoding+ also not given, +returns an empty string with the Encoding ASCII-8BIT: -With optional argument +string+ and no keyword arguments, -returns a copy of +string+ with the same encoding: + s = String.new # => "" + s.encoding # => # - String.new('foo') # => "foo" - String.new('тест') # => "тест" - String.new('こんにちは') # => "こんにちは" +With argument +string+ given and keyword option +encoding+ not given, +returns a new string with the same encoding as +string+: + + s0 = 'foo'.encode(Encoding::UTF_16) + s1 = String.new(s0) + s1.encoding # => # (Unlike \String.new, a {string literal}[rdoc-ref:syntax/literals.rdoc@String+Literals] like '' or a {here document literal}[rdoc-ref:syntax/literals.rdoc@Here+Document+Literals] always has {script encoding}[rdoc-ref:encodings.rdoc@Script+Encoding].) -With optional keyword argument +encoding+, returns a copy of +string+ -with the specified encoding; +With keyword option +encoding+ given, +returns a string with the specified encoding; the +encoding+ may be an Encoding object, an encoding name, or an encoding name alias: + String.new(encoding: Encoding::US_ASCII).encoding # => # + String.new('', encoding: Encoding::US_ASCII).encoding # => # String.new('foo', encoding: Encoding::US_ASCII).encoding # => # String.new('foo', encoding: 'US-ASCII').encoding # => # String.new('foo', encoding: 'ASCII').encoding # => # The given encoding need not be valid for the string's content, -and that validity is not checked: +and its validity is not checked: s = String.new('こんにちは', encoding: 'ascii') s.valid_encoding? # => false @@ -37,15 +41,11 @@ But the given +encoding+ itself is checked: String.new('foo', encoding: 'bar') # Raises ArgumentError. -With optional keyword argument +capacity+, returns a copy of +string+ -(or an empty string, if +string+ is not given); -the given +capacity+ is advisory only, +With keyword option +capacity+ given, +the given value is advisory only, and may or may not set the size of the internal buffer, which may in turn affect performance: - String.new(capacity: 1) - String.new('foo', capacity: 4096) - -The +string+, +encoding+, and +capacity+ arguments may all be used together: - - String.new('hello', encoding: 'UTF-8', capacity: 25) + String.new('foo', capacity: 1) # Buffer size is at least 4 (includes terminal null byte). + String.new('foo', capacity: 4096) # Buffer size is at least 4; + # may be equal to, greater than, or less than 4096. diff --git a/doc/string/split.rdoc b/doc/string/split.rdoc index 2b5e14ddb699db..131c14b83fcbda 100644 --- a/doc/string/split.rdoc +++ b/doc/string/split.rdoc @@ -9,37 +9,37 @@ When +field_sep+ is $;: (see below). - If $; is a string, - the split ocurs just as if +field_sep+ were given as that string + the split occurs just as if +field_sep+ were given as that string (see below). -When +field_sep+ is ' ' and +limit+ is +nil+, +When +field_sep+ is ' ' and +limit+ is +0+ (its default value), the split occurs at each sequence of whitespace: - 'abc def ghi'.split(' ') => ["abc", "def", "ghi"] + 'abc def ghi'.split(' ') # => ["abc", "def", "ghi"] "abc \n\tdef\t\n ghi".split(' ') # => ["abc", "def", "ghi"] - 'abc def ghi'.split(' ') => ["abc", "def", "ghi"] - ''.split(' ') => [] + 'abc def ghi'.split(' ') # => ["abc", "def", "ghi"] + ''.split(' ') # => [] When +field_sep+ is a string different from ' ' -and +limit+ is +nil+, +and +limit+ is +0+, the split occurs at each occurrence of +field_sep+; trailing empty substrings are not returned: - 'abracadabra'.split('ab') => ["", "racad", "ra"] - 'aaabcdaaa'.split('a') => ["", "", "", "bcd"] - ''.split('a') => [] - '3.14159'.split('1') => ["3.", "4", "59"] + 'abracadabra'.split('ab') # => ["", "racad", "ra"] + 'aaabcdaaa'.split('a') # => ["", "", "", "bcd"] + ''.split('a') # => [] + '3.14159'.split('1') # => ["3.", "4", "59"] '!@#$%^$&*($)_+'.split('$') # => ["!@#", "%^", "&*(", ")_+"] - 'тест'.split('т') => ["", "ес"] - 'こんにちは'.split('に') => ["こん", "ちは"] + 'тест'.split('т') # => ["", "ес"] + 'こんにちは'.split('に') # => ["こん", "ちは"] -When +field_sep+ is a Regexp and +limit+ is +nil+, +When +field_sep+ is a Regexp and +limit+ is +0+, the split occurs at each occurrence of a match; trailing empty substrings are not returned: 'abracadabra'.split(/ab/) # => ["", "racad", "ra"] - 'aaabcdaaa'.split(/a/) => ["", "", "", "bcd"] - 'aaabcdaaa'.split(//) => ["a", "a", "a", "b", "c", "d", "a", "a", "a"] + 'aaabcdaaa'.split(/a/) # => ["", "", "", "bcd"] + 'aaabcdaaa'.split(//) # => ["a", "a", "a", "b", "c", "d", "a", "a", "a"] '1 + 1 == 2'.split(/\W+/) # => ["1", "1", "2"] If the \Regexp contains groups, their matches are also included @@ -47,12 +47,10 @@ in the returned array: '1:2:3'.split(/(:)()()/, 2) # => ["1", ":", "", "", "2:3"] -As seen above, if +limit+ is +nil+, -trailing empty substrings are not returned; -the same is true if +limit+ is zero: +As seen above, if +limit+ is +0+, +trailing empty substrings are not returned: - 'aaabcdaaa'.split('a') => ["", "", "", "bcd"] - 'aaabcdaaa'.split('a', 0) # => ["", "", "", "bcd"] + 'aaabcdaaa'.split('a') # => ["", "", "", "bcd"] If +limit+ is positive integer +n+, no more than n - 1- splits occur, so that at most +n+ substrings are returned, @@ -67,13 +65,13 @@ and trailing empty substrings are included: Note that if +field_sep+ is a \Regexp containing groups, their matches are in the returned array, but do not count toward the limit. -If +limit+ is negative, it behaves the same as if +limit+ was +nil+, +If +limit+ is negative, it behaves the same as if +limit+ was zero, meaning that there is no limit, and trailing empty substrings are included: 'aaabcdaaa'.split('a', -1) # => ["", "", "", "bcd", "", "", ""] -If a block is given, it is called with each substring: +If a block is given, it is called with each substring and returns +self+: 'abc def ghi'.split(' ') {|substring| p substring } @@ -82,5 +80,20 @@ Output: "abc" "def" "ghi" + => "abc def ghi" + +Note that the above example is functionally the same as calling +#each+ after ++#split+ and giving the same block. However, the above example has better +performance because it avoids the creation of an intermediate array. Also, +note the different return values. + + 'abc def ghi'.split(' ').each {|substring| p substring } + +Output: + + "abc" + "def" + "ghi" + => ["abc", "def", "ghi"] Related: String#partition, String#rpartition. diff --git a/doc/strscan/helper_methods.md b/doc/strscan/helper_methods.md new file mode 100644 index 00000000000000..9fb1d79bba91f7 --- /dev/null +++ b/doc/strscan/helper_methods.md @@ -0,0 +1,124 @@ +## Helper Methods + +These helper methods display values returned by scanner's methods. + +### `put_situation(scanner)` + +Display scanner's situation: + +- Byte position (`#pos`). +- Character position (`#charpos`) +- Target string (`#rest`) and size (`#rest_size`). + +```rb +scanner = StringScanner.new('foobarbaz') +scanner.scan(/foo/) +put_situation(scanner) +# Situation: +# pos: 3 +# charpos: 3 +# rest: "barbaz" +# rest_size: 6 +``` + +### `put_match_values(scanner)` + +Display the scanner's match values: + +```rb +scanner = StringScanner.new('Fri Dec 12 1975 14:39') +pattern = /(?\w+) (?\w+) (?\d+) / +scanner.match?(pattern) +put_match_values(scanner) +# Basic match values: +# matched?: true +# matched_size: 11 +# pre_match: "" +# matched : "Fri Dec 12 " +# post_match: "1975 14:39" +# Captured match values: +# size: 4 +# captures: ["Fri", "Dec", "12"] +# named_captures: {"wday"=>"Fri", "month"=>"Dec", "day"=>"12"} +# values_at: ["Fri Dec 12 ", "Fri", "Dec", "12", nil] +# []: +# [0]: "Fri Dec 12 " +# [1]: "Fri" +# [2]: "Dec" +# [3]: "12" +# [4]: nil +``` + +### `match_values_cleared?(scanner)` + +Returns whether the scanner's match values are all properly cleared: + +```rb +scanner = StringScanner.new('foobarbaz') +match_values_cleared?(scanner) # => true +put_match_values(scanner) +# Basic match values: +# matched?: false +# matched_size: nil +# pre_match: nil +# matched : nil +# post_match: nil +# Captured match values: +# size: nil +# captures: nil +# named_captures: {} +# values_at: nil +# [0]: nil +scanner.scan(/foo/) +match_values_cleared?(scanner) # => false +``` + +## The Code + +```rb +def put_situation(scanner) + puts '# Situation:' + puts "# pos: #{scanner.pos}" + puts "# charpos: #{scanner.charpos}" + puts "# rest: #{scanner.rest.inspect}" + puts "# rest_size: #{scanner.rest_size}" +end + +def put_match_values(scanner) + puts '# Basic match values:' + puts "# matched?: #{scanner.matched?}" + value = scanner.matched_size || 'nil' + puts "# matched_size: #{value}" + puts "# pre_match: #{scanner.pre_match.inspect}" + puts "# matched : #{scanner.matched.inspect}" + puts "# post_match: #{scanner.post_match.inspect}" + puts '# Captured match values:' + puts "# size: #{scanner.size}" + puts "# captures: #{scanner.captures}" + puts "# named_captures: #{scanner.named_captures}" + if scanner.size.nil? + puts "# values_at: #{scanner.values_at(0)}" + puts "# [0]: #{scanner[0]}" + else + puts "# values_at: #{scanner.values_at(*(0..scanner.size))}" + puts "# []:" + scanner.size.times do |i| + puts "# [#{i}]: #{scanner[i].inspect}" + end + end +end + +def match_values_cleared?(scanner) + scanner.matched? == false && + scanner.matched_size.nil? && + scanner.matched.nil? && + scanner.pre_match.nil? && + scanner.post_match.nil? && + scanner.size.nil? && + scanner[0].nil? && + scanner.captures.nil? && + scanner.values_at(0..1).nil? && + scanner.named_captures == {} +end +``` + diff --git a/doc/strscan/link_refs.txt b/doc/strscan/link_refs.txt new file mode 100644 index 00000000000000..19f6f7ce5c9533 --- /dev/null +++ b/doc/strscan/link_refs.txt @@ -0,0 +1,17 @@ +[1]: rdoc-ref:StringScanner@Stored+String +[2]: rdoc-ref:StringScanner@Byte+Position+-28Position-29 +[3]: rdoc-ref:StringScanner@Target+Substring +[4]: rdoc-ref:StringScanner@Setting+the+Target+Substring +[5]: rdoc-ref:StringScanner@Traversing+the+Target+Substring +[6]: https://docs.ruby-lang.org/en/master/Regexp.html +[7]: rdoc-ref:StringScanner@Character+Position +[8]: https://docs.ruby-lang.org/en/master/String.html#method-i-5B-5D +[9]: rdoc-ref:StringScanner@Match+Values +[10]: rdoc-ref:StringScanner@Fixed-Anchor+Property +[11]: rdoc-ref:StringScanner@Positions +[13]: rdoc-ref:StringScanner@Captured+Match+Values +[14]: rdoc-ref:StringScanner@Querying+the+Target+Substring +[15]: rdoc-ref:StringScanner@Searching+the+Target+Substring +[16]: https://docs.ruby-lang.org/en/master/Regexp.html#class-Regexp-label-Groups+and+Captures +[17]: rdoc-ref:StringScanner@Matching +[18]: rdoc-ref:StringScanner@Basic+Match+Values diff --git a/doc/strscan/methods/get_byte.md b/doc/strscan/methods/get_byte.md new file mode 100644 index 00000000000000..3208d77158b342 --- /dev/null +++ b/doc/strscan/methods/get_byte.md @@ -0,0 +1,30 @@ +call-seq: + get_byte -> byte_as_character or nil + +Returns the next byte, if available: + +- If the [position][2] + is not at the end of the [stored string][1]: + + - Returns the next byte. + - Increments the [byte position][2]. + - Adjusts the [character position][7]. + + ```rb + scanner = StringScanner.new(HIRAGANA_TEXT) + # => # + scanner.string # => "こんにちは" + [scanner.get_byte, scanner.pos, scanner.charpos] # => ["\xE3", 1, 1] + [scanner.get_byte, scanner.pos, scanner.charpos] # => ["\x81", 2, 2] + [scanner.get_byte, scanner.pos, scanner.charpos] # => ["\x93", 3, 1] + [scanner.get_byte, scanner.pos, scanner.charpos] # => ["\xE3", 4, 2] + [scanner.get_byte, scanner.pos, scanner.charpos] # => ["\x82", 5, 3] + [scanner.get_byte, scanner.pos, scanner.charpos] # => ["\x93", 6, 2] + ``` + +- Otherwise, returns `nil`, and does not change the positions. + + ```rb + scanner.terminate + [scanner.get_byte, scanner.pos, scanner.charpos] # => [nil, 15, 5] + ``` diff --git a/doc/strscan/methods/get_charpos.md b/doc/strscan/methods/get_charpos.md new file mode 100644 index 00000000000000..954fcf5b44e599 --- /dev/null +++ b/doc/strscan/methods/get_charpos.md @@ -0,0 +1,19 @@ +call-seq: + charpos -> character_position + +Returns the [character position][7] (initially zero), +which may be different from the [byte position][2] +given by method #pos: + +```rb +scanner = StringScanner.new(HIRAGANA_TEXT) +scanner.string # => "こんにちは" +scanner.getch # => "こ" # 3-byte character. +scanner.getch # => "ん" # 3-byte character. +put_situation(scanner) +# Situation: +# pos: 6 +# charpos: 2 +# rest: "にちは" +# rest_size: 9 +``` diff --git a/doc/strscan/methods/get_pos.md b/doc/strscan/methods/get_pos.md new file mode 100644 index 00000000000000..81bbb2345e9268 --- /dev/null +++ b/doc/strscan/methods/get_pos.md @@ -0,0 +1,14 @@ +call-seq: + pos -> byte_position + +Returns the integer [byte position][2], +which may be different from the [character position][7]: + +```rb +scanner = StringScanner.new(HIRAGANA_TEXT) +scanner.string # => "こんにちは" +scanner.pos # => 0 +scanner.getch # => "こ" # 3-byte character. +scanner.charpos # => 1 +scanner.pos # => 3 +``` diff --git a/doc/strscan/methods/getch.md b/doc/strscan/methods/getch.md new file mode 100644 index 00000000000000..3dd70e4c5be04a --- /dev/null +++ b/doc/strscan/methods/getch.md @@ -0,0 +1,43 @@ +call-seq: + getch -> character or nil + +Returns the next (possibly multibyte) character, +if available: + +- If the [position][2] + is at the beginning of a character: + + - Returns the character. + - Increments the [character position][7] by 1. + - Increments the [byte position][2] + by the size (in bytes) of the character. + + ```rb + scanner = StringScanner.new(HIRAGANA_TEXT) + scanner.string # => "こんにちは" + [scanner.getch, scanner.pos, scanner.charpos] # => ["こ", 3, 1] + [scanner.getch, scanner.pos, scanner.charpos] # => ["ん", 6, 2] + [scanner.getch, scanner.pos, scanner.charpos] # => ["に", 9, 3] + [scanner.getch, scanner.pos, scanner.charpos] # => ["ち", 12, 4] + [scanner.getch, scanner.pos, scanner.charpos] # => ["は", 15, 5] + [scanner.getch, scanner.pos, scanner.charpos] # => [nil, 15, 5] + ``` + +- If the [position][2] is within a multi-byte character + (that is, not at its beginning), + behaves like #get_byte (returns a 1-byte character): + + ```rb + scanner.pos = 1 + [scanner.getch, scanner.pos, scanner.charpos] # => ["\x81", 2, 2] + [scanner.getch, scanner.pos, scanner.charpos] # => ["\x93", 3, 1] + [scanner.getch, scanner.pos, scanner.charpos] # => ["ん", 6, 2] + ``` + +- If the [position][2] is at the end of the [stored string][1], + returns `nil` and does not modify the positions: + + ```rb + scanner.terminate + [scanner.getch, scanner.pos, scanner.charpos] # => [nil, 15, 5] + ``` diff --git a/doc/strscan/methods/scan.md b/doc/strscan/methods/scan.md new file mode 100644 index 00000000000000..22ddd368b6f324 --- /dev/null +++ b/doc/strscan/methods/scan.md @@ -0,0 +1,51 @@ +call-seq: + scan(pattern) -> substring or nil + +Attempts to [match][17] the given `pattern` +at the beginning of the [target substring][3]. + +If the match succeeds: + +- Returns the matched substring. +- Increments the [byte position][2] by substring.bytesize, + and may increment the [character position][7]. +- Sets [match values][9]. + +```rb +scanner = StringScanner.new(HIRAGANA_TEXT) +scanner.string # => "こんにちは" +scanner.pos = 6 +scanner.scan(/に/) # => "に" +put_match_values(scanner) +# Basic match values: +# matched?: true +# matched_size: 3 +# pre_match: "こん" +# matched : "に" +# post_match: "ちは" +# Captured match values: +# size: 1 +# captures: [] +# named_captures: {} +# values_at: ["に", nil] +# []: +# [0]: "に" +# [1]: nil +put_situation(scanner) +# Situation: +# pos: 9 +# charpos: 3 +# rest: "ちは" +# rest_size: 6 +``` + +If the match fails: + +- Returns `nil`. +- Does not increment byte and character positions. +- Clears match values. + +```rb +scanner.scan(/nope/) # => nil +match_values_cleared?(scanner) # => true +``` diff --git a/doc/strscan/methods/scan_until.md b/doc/strscan/methods/scan_until.md new file mode 100644 index 00000000000000..9a8c7c02f68336 --- /dev/null +++ b/doc/strscan/methods/scan_until.md @@ -0,0 +1,52 @@ +call-seq: + scan_until(pattern) -> substring or nil + +Attempts to [match][17] the given `pattern` +anywhere (at any [position][2]) in the [target substring][3]. + +If the match attempt succeeds: + +- Sets [match values][9]. +- Sets the [byte position][2] to the end of the matched substring; + may adjust the [character position][7]. +- Returns the matched substring. + + +```rb +scanner = StringScanner.new(HIRAGANA_TEXT) +scanner.string # => "こんにちは" +scanner.pos = 6 +scanner.scan_until(/ち/) # => "にち" +put_match_values(scanner) +# Basic match values: +# matched?: true +# matched_size: 3 +# pre_match: "こんに" +# matched : "ち" +# post_match: "は" +# Captured match values: +# size: 1 +# captures: [] +# named_captures: {} +# values_at: ["ち", nil] +# []: +# [0]: "ち" +# [1]: nil +put_situation(scanner) +# Situation: +# pos: 12 +# charpos: 4 +# rest: "は" +# rest_size: 3 +``` + +If the match attempt fails: + +- Clears match data. +- Returns `nil`. +- Does not update positions. + +```rb +scanner.scan_until(/nope/) # => nil +match_values_cleared?(scanner) # => true +``` diff --git a/doc/strscan/methods/set_pos.md b/doc/strscan/methods/set_pos.md new file mode 100644 index 00000000000000..3b7abe65e3379a --- /dev/null +++ b/doc/strscan/methods/set_pos.md @@ -0,0 +1,27 @@ +call-seq: + pos = n -> n + pointer = n -> n + +Sets the [byte position][2] and the [character position][11]; +returns `n`. + +Does not affect [match values][9]. + +For non-negative `n`, sets the position to `n`: + +```rb +scanner = StringScanner.new(HIRAGANA_TEXT) +scanner.string # => "こんにちは" +scanner.pos = 3 # => 3 +scanner.rest # => "んにちは" +scanner.charpos # => 1 +``` + +For negative `n`, counts from the end of the [stored string][1]: + +```rb +scanner.pos = -9 # => -9 +scanner.pos # => 6 +scanner.rest # => "にちは" +scanner.charpos # => 2 +``` diff --git a/doc/strscan/methods/skip.md b/doc/strscan/methods/skip.md new file mode 100644 index 00000000000000..10a329e0e42f93 --- /dev/null +++ b/doc/strscan/methods/skip.md @@ -0,0 +1,43 @@ +call-seq: + skip(pattern) match_size or nil + +Attempts to [match][17] the given `pattern` +at the beginning of the [target substring][3]; + +If the match succeeds: + +- Increments the [byte position][2] by substring.bytesize, + and may increment the [character position][7]. +- Sets [match values][9]. +- Returns the size (bytes) of the matched substring. + +```rb +scanner = StringScanner.new(HIRAGANA_TEXT) +scanner.string # => "こんにちは" +scanner.pos = 6 +scanner.skip(/に/) # => 3 +put_match_values(scanner) +# Basic match values: +# matched?: true +# matched_size: 3 +# pre_match: "こん" +# matched : "に" +# post_match: "ちは" +# Captured match values: +# size: 1 +# captures: [] +# named_captures: {} +# values_at: ["に", nil] +# []: +# [0]: "に" +# [1]: nil +put_situation(scanner) +# Situation: +# pos: 9 +# charpos: 3 +# rest: "ちは" +# rest_size: 6 + +scanner.skip(/nope/) # => nil +match_values_cleared?(scanner) # => true +``` diff --git a/doc/strscan/methods/skip_until.md b/doc/strscan/methods/skip_until.md new file mode 100644 index 00000000000000..b7dacf6da1ee13 --- /dev/null +++ b/doc/strscan/methods/skip_until.md @@ -0,0 +1,49 @@ +call-seq: + skip_until(pattern) -> matched_substring_size or nil + +Attempts to [match][17] the given `pattern` +anywhere (at any [position][2]) in the [target substring][3]; +does not modify the positions. + +If the match attempt succeeds: + +- Sets [match values][9]. +- Returns the size of the matched substring. + +```rb +scanner = StringScanner.new(HIRAGANA_TEXT) +scanner.string # => "こんにちは" +scanner.pos = 6 +scanner.skip_until(/ち/) # => 6 +put_match_values(scanner) +# Basic match values: +# matched?: true +# matched_size: 3 +# pre_match: "こんに" +# matched : "ち" +# post_match: "は" +# Captured match values: +# size: 1 +# captures: [] +# named_captures: {} +# values_at: ["ち", nil] +# []: +# [0]: "ち" +# [1]: nil +put_situation(scanner) +# Situation: +# pos: 12 +# charpos: 4 +# rest: "は" +# rest_size: 3 +``` + +If the match attempt fails: + +- Clears match values. +- Returns `nil`. + +```rb +scanner.skip_until(/nope/) # => nil +match_values_cleared?(scanner) # => true +``` diff --git a/doc/strscan/methods/terminate.md b/doc/strscan/methods/terminate.md new file mode 100644 index 00000000000000..b03b37d2a289ab --- /dev/null +++ b/doc/strscan/methods/terminate.md @@ -0,0 +1,30 @@ +call-seq: + terminate -> self + +Sets the scanner to end-of-string; +returns +self+: + +- Sets both [positions][11] to end-of-stream. +- Clears [match values][9]. + +```rb +scanner = StringScanner.new(HIRAGANA_TEXT) +scanner.string # => "こんにちは" +scanner.scan_until(/に/) +put_situation(scanner) +# Situation: +# pos: 9 +# charpos: 3 +# rest: "ちは" +# rest_size: 6 +match_values_cleared?(scanner) # => false + +scanner.terminate # => # +put_situation(scanner) +# Situation: +# pos: 15 +# charpos: 5 +# rest: "" +# rest_size: 0 +match_values_cleared?(scanner) # => true +``` diff --git a/doc/strscan/strscan.md b/doc/strscan/strscan.md new file mode 100644 index 00000000000000..1211a687c271a8 --- /dev/null +++ b/doc/strscan/strscan.md @@ -0,0 +1,544 @@ +\Class `StringScanner` supports processing a stored string as a stream; +this code creates a new `StringScanner` object with string `'foobarbaz'`: + +```rb +require 'strscan' +scanner = StringScanner.new('foobarbaz') +``` + +## About the Examples + +All examples here assume that `StringScanner` has been required: + +```rb +require 'strscan' +``` + +Some examples here assume that these constants are defined: + +```rb +MULTILINE_TEXT = <<~EOT +Go placidly amid the noise and haste, +and remember what peace there may be in silence. +EOT + +HIRAGANA_TEXT = 'こんにちは' + +ENGLISH_TEXT = 'Hello' +``` + +Some examples here assume that certain helper methods are defined: + +- `put_situation(scanner)`: + Displays the values of the scanner's + methods #pos, #charpos, #rest, and #rest_size. +- `put_match_values(scanner)`: + Displays the scanner's [match values][9]. +- `match_values_cleared?(scanner)`: + Returns whether the scanner's [match values][9] are cleared. + +See examples [here][ext/strscan/helper_methods_md.html]. + +## The `StringScanner` \Object + +This code creates a `StringScanner` object +(we'll call it simply a _scanner_), +and shows some of its basic properties: + +```rb +scanner = StringScanner.new('foobarbaz') +scanner.string # => "foobarbaz" +put_situation(scanner) +# Situation: +# pos: 0 +# charpos: 0 +# rest: "foobarbaz" +# rest_size: 9 +``` + +The scanner has: + +* A stored string, which is: + + * Initially set by StringScanner.new(string) to the given `string` + (`'foobarbaz'` in the example above). + * Modifiable by methods #string=(new_string) and #concat(more_string). + * Returned by method #string. + + More at [Stored String][1] below. + +* A _position_; + a zero-based index into the bytes of the stored string (_not_ into its characters): + + * Initially set by StringScanner.new to `0`. + * Returned by method #pos. + * Modifiable explicitly by methods #reset, #terminate, and #pos=(new_pos). + * Modifiable implicitly (various traversing methods, among others). + + More at [Byte Position][2] below. + +* A target substring, + which is a trailing substring of the stored string; + it extends from the current position to the end of the stored string: + + * Initially set by StringScanner.new(string) to the given `string` + (`'foobarbaz'` in the example above). + * Returned by method #rest. + * Modified by any modification to either the stored string or the position. + + Most importantly: + the searching and traversing methods operate on the target substring, + which may be (and often is) less than the entire stored string. + + More at [Target Substring][3] below. + +## Stored \String + +The stored string is the string stored in the `StringScanner` object. + +Each of these methods sets, modifies, or returns the stored string: + +| Method | Effect | +|----------------------|-------------------------------------------------| +| ::new(string) | Creates a new scanner for the given string. | +| #string=(new_string) | Replaces the existing stored string. | +| #concat(more_string) | Appends a string to the existing stored string. | +| #string | Returns the stored string. | + +## Positions + +A `StringScanner` object maintains a zero-based byte position +and a zero-based character position. + +Each of these methods explicitly sets positions: + +| Method | Effect | +|--------------------------|-----------------------------------------------------------| +| #reset | Sets both positions to zero (beginning of stored string). | +| #terminate | Sets both positions to the end of the stored string. | +| #pos=(new_byte_position) | Sets byte position; adjusts character position. | + +### Byte Position (Position) + +The byte position (or simply _position_) +is a zero-based index into the bytes in the scanner's stored string; +for a new `StringScanner` object, the byte position is zero. + +When the byte position is: + +* Zero (at the beginning), the target substring is the entire stored string. +* Equal to the size of the stored string (at the end), + the target substring is the empty string `''`. + +To get or set the byte position: + +* \#pos: returns the byte position. +* \#pos=(new_pos): sets the byte position. + +Many methods use the byte position as the basis for finding matches; +many others set, increment, or decrement the byte position: + +```rb +scanner = StringScanner.new('foobar') +scanner.pos # => 0 +scanner.scan(/foo/) # => "foo" # Match found. +scanner.pos # => 3 # Byte position incremented. +scanner.scan(/foo/) # => nil # Match not found. +scanner.pos # => 3 # Byte position not changed. +``` + +Some methods implicitly modify the byte position; +see: + +* [Setting the Target Substring][4]. +* [Traversing the Target Substring][5]. + +The values of these methods are derived directly from the values of #pos and #string: + +- \#charpos: the [character position][7]. +- \#rest: the [target substring][3]. +- \#rest_size: `rest.size`. + +### Character Position + +The character position is a zero-based index into the _characters_ +in the stored string; +for a new `StringScanner` object, the character position is zero. + +\Method #charpos returns the character position; +its value may not be reset explicitly. + +Some methods change (increment or reset) the character position; +see: + +* [Setting the Target Substring][4]. +* [Traversing the Target Substring][5]. + +Example (string includes multi-byte characters): + +```rb +scanner = StringScanner.new(ENGLISH_TEXT) # Five 1-byte characters. +scanner.concat(HIRAGANA_TEXT) # Five 3-byte characters +scanner.string # => "Helloこんにちは" # Twenty bytes in all. +put_situation(scanner) +# Situation: +# pos: 0 +# charpos: 0 +# rest: "Helloこんにちは" +# rest_size: 20 +scanner.scan(/Hello/) # => "Hello" # Five 1-byte characters. +put_situation(scanner) +# Situation: +# pos: 5 +# charpos: 5 +# rest: "こんにちは" +# rest_size: 15 +scanner.getch # => "こ" # One 3-byte character. +put_situation(scanner) +# Situation: +# pos: 8 +# charpos: 6 +# rest: "んにちは" +# rest_size: 12 +``` + +## Target Substring + +The target substring is the the part of the [stored string][1] +that extends from the current [byte position][2] to the end of the stored string; +it is always either: + +- The entire stored string (byte position is zero). +- A trailing substring of the stored string (byte position positive). + +The target substring is returned by method #rest, +and its size is returned by method #rest_size. + +Examples: + +```rb +scanner = StringScanner.new('foobarbaz') +put_situation(scanner) +# Situation: +# pos: 0 +# charpos: 0 +# rest: "foobarbaz" +# rest_size: 9 +scanner.pos = 3 +put_situation(scanner) +# Situation: +# pos: 3 +# charpos: 3 +# rest: "barbaz" +# rest_size: 6 +scanner.pos = 9 +put_situation(scanner) +# Situation: +# pos: 9 +# charpos: 9 +# rest: "" +# rest_size: 0 +``` + +### Setting the Target Substring + +The target substring is set whenever: + +* The [stored string][1] is set (position reset to zero; target substring set to stored string). +* The [byte position][2] is set (target substring adjusted accordingly). + +### Querying the Target Substring + +This table summarizes (details and examples at the links): + +| Method | Returns | +|------------|-----------------------------------| +| #rest | Target substring. | +| #rest_size | Size (bytes) of target substring. | + +### Searching the Target Substring + +A _search_ method examines the target substring, +but does not advance the [positions][11] +or (by implication) shorten the target substring. + +This table summarizes (details and examples at the links): + +| Method | Returns | Sets Match Values? | +|-----------------------|-----------------------------------------------|--------------------| +| #check(pattern) | Matched leading substring or +nil+. | Yes. | +| #check_until(pattern) | Matched substring (anywhere) or +nil+. | Yes. | +| #exist?(pattern) | Matched substring (anywhere) end index. | Yes. | +| #match?(pattern) | Size of matched leading substring or +nil+. | Yes. | +| #peek(size) | Leading substring of given length (bytes). | No. | +| #peek_byte | Integer leading byte or +nil+. | No. | +| #rest | Target substring (from byte position to end). | No. | + +### Traversing the Target Substring + +A _traversal_ method examines the target substring, +and, if successful: + +- Advances the [positions][11]. +- Shortens the target substring. + + +This table summarizes (details and examples at links): + +| Method | Returns | Sets Match Values? | +|----------------------|------------------------------------------------------|--------------------| +| #get_byte | Leading byte or +nil+. | No. | +| #getch | Leading character or +nil+. | No. | +| #scan(pattern) | Matched leading substring or +nil+. | Yes. | +| #scan_byte | Integer leading byte or +nil+. | No. | +| #scan_until(pattern) | Matched substring (anywhere) or +nil+. | Yes. | +| #skip(pattern) | Matched leading substring size or +nil+. | Yes. | +| #skip_until(pattern) | Position delta to end-of-matched-substring or +nil+. | Yes. | +| #unscan | +self+. | No. | + +## Querying the Scanner + +Each of these methods queries the scanner object +without modifying it (details and examples at links) + +| Method | Returns | +|---------------------|----------------------------------| +| #beginning_of_line? | +true+ or +false+. | +| #charpos | Character position. | +| #eos? | +true+ or +false+. | +| #fixed_anchor? | +true+ or +false+. | +| #inspect | String representation of +self+. | +| #pos | Byte position. | +| #rest | Target substring. | +| #rest_size | Size of target substring. | +| #string | Stored string. | + +## Matching + +`StringScanner` implements pattern matching via Ruby class [Regexp][6], +and its matching behaviors are the same as Ruby's +except for the [fixed-anchor property][10]. + +### Matcher Methods + +Each matcher method takes a single argument `pattern`, +and attempts to find a matching substring in the [target substring][3]. + +| Method | Pattern Type | Matches Target Substring | Success Return | May Update Positions? | +|--------------|-------------------|--------------------------|--------------------|-----------------------| +| #check | Regexp or String. | At beginning. | Matched substring. | No. | +| #check_until | Regexp or String. | Anywhere. | Substring. | No. | +| #match? | Regexp or String. | At beginning. | Match size. | No. | +| #exist? | Regexp or String. | Anywhere. | Substring size. | No. | +| #scan | Regexp or String. | At beginning. | Matched substring. | Yes. | +| #scan_until | Regexp or String. | Anywhere. | Substring. | Yes. | +| #skip | Regexp or String. | At beginning. | Match size. | Yes. | +| #skip_until | Regexp or String. | Anywhere. | Substring size. | Yes. | + +
+ +Which matcher you choose will depend on: + +- Where you want to find a match: + + - Only at the beginning of the target substring: + #check, #match?, #scan, #skip. + - Anywhere in the target substring: + #check_until, #exist?, #scan_until, #skip_until. + +- Whether you want to: + + - Traverse, by advancing the positions: + #scan, #scan_until, #skip, #skip_until. + - Keep the positions unchanged: + #check, #check_until, #match?, #exist?. + +- What you want for the return value: + + - The matched substring: #check, #scan. + - The substring: #check_until, #scan_until. + - The match size: #match?, #skip. + - The substring size: #exist?, #skip_until. + +### Match Values + +The match values in a `StringScanner` object +generally contain the results of the most recent attempted match. + +Each match value may be thought of as: + +* _Clear_: Initially, or after an unsuccessful match attempt: + usually, `false`, `nil`, or `{}`. +* _Set_: After a successful match attempt: + `true`, string, array, or hash. + +Each of these methods clears match values: + +- ::new(string). +- \#reset. +- \#terminate. + +Each of these methods attempts a match based on a pattern, +and either sets match values (if successful) or clears them (if not); + +- \#check(pattern) +- \#check_until(pattern) +- \#exist?(pattern) +- \#match?(pattern) +- \#scan(pattern) +- \#scan_until(pattern) +- \#skip(pattern) +- \#skip_until(pattern) + +#### Basic Match Values + +Basic match values are those not related to captures. + +Each of these methods returns a basic match value: + +| Method | Return After Match | Return After No Match | +|-----------------|----------------------------------------|-----------------------| +| #matched? | +true+. | +false+. | +| #matched_size | Size of matched substring. | +nil+. | +| #matched | Matched substring. | +nil+. | +| #pre_match | Substring preceding matched substring. | +nil+. | +| #post_match | Substring following matched substring. | +nil+. | + +
+ +See examples below. + +#### Captured Match Values + +Captured match values are those related to [captures][16]. + +Each of these methods returns a captured match value: + +| Method | Return After Match | Return After No Match | +|-----------------|-----------------------------------------|-----------------------| +| #size | Count of captured substrings. | +nil+. | +| #[](n) | nth captured substring. | +nil+. | +| #captures | Array of all captured substrings. | +nil+. | +| #values_at(*n) | Array of specified captured substrings. | +nil+. | +| #named_captures | Hash of named captures. | {}. | + +
+ +See examples below. + +#### Match Values Examples + +Successful basic match attempt (no captures): + +```rb +scanner = StringScanner.new('foobarbaz') +scanner.exist?(/bar/) +put_match_values(scanner) +# Basic match values: +# matched?: true +# matched_size: 3 +# pre_match: "foo" +# matched : "bar" +# post_match: "baz" +# Captured match values: +# size: 1 +# captures: [] +# named_captures: {} +# values_at: ["bar", nil] +# []: +# [0]: "bar" +# [1]: nil +``` + +Failed basic match attempt (no captures); + +```rb +scanner = StringScanner.new('foobarbaz') +scanner.exist?(/nope/) +match_values_cleared?(scanner) # => true +``` + +Successful unnamed capture match attempt: + +```rb +scanner = StringScanner.new('foobarbazbatbam') +scanner.exist?(/(foo)bar(baz)bat(bam)/) +put_match_values(scanner) +# Basic match values: +# matched?: true +# matched_size: 15 +# pre_match: "" +# matched : "foobarbazbatbam" +# post_match: "" +# Captured match values: +# size: 4 +# captures: ["foo", "baz", "bam"] +# named_captures: {} +# values_at: ["foobarbazbatbam", "foo", "baz", "bam", nil] +# []: +# [0]: "foobarbazbatbam" +# [1]: "foo" +# [2]: "baz" +# [3]: "bam" +# [4]: nil +``` + +Successful named capture match attempt; +same as unnamed above, except for #named_captures: + +```rb +scanner = StringScanner.new('foobarbazbatbam') +scanner.exist?(/(?foo)bar(?baz)bat(?bam)/) +scanner.named_captures # => {"x"=>"foo", "y"=>"baz", "z"=>"bam"} +``` + +Failed unnamed capture match attempt: + +```rb +scanner = StringScanner.new('somestring') +scanner.exist?(/(foo)bar(baz)bat(bam)/) +match_values_cleared?(scanner) # => true +``` + +Failed named capture match attempt; +same as unnamed above, except for #named_captures: + +```rb +scanner = StringScanner.new('somestring') +scanner.exist?(/(?foo)bar(?baz)bat(?bam)/) +match_values_cleared?(scanner) # => false +scanner.named_captures # => {"x"=>nil, "y"=>nil, "z"=>nil} +``` + +## Fixed-Anchor Property + +Pattern matching in `StringScanner` is the same as in Ruby's, +except for its fixed-anchor property, +which determines the meaning of `'\A'`: + +* `false` (the default): matches the current byte position. + + ```rb + scanner = StringScanner.new('foobar') + scanner.scan(/\A./) # => "f" + scanner.scan(/\A./) # => "o" + scanner.scan(/\A./) # => "o" + scanner.scan(/\A./) # => "b" + ``` + +* `true`: matches the beginning of the target substring; + never matches unless the byte position is zero: + + ```rb + scanner = StringScanner.new('foobar', fixed_anchor: true) + scanner.scan(/\A./) # => "f" + scanner.scan(/\A./) # => nil + scanner.reset + scanner.scan(/\A./) # => "f" + ``` + +The fixed-anchor property is set when the `StringScanner` object is created, +and may not be modified +(see StringScanner.new); +method #fixed_anchor? returns the setting. + diff --git a/doc/syntax.rdoc b/doc/syntax.rdoc index 5895673f36a8f9..cb427b6f0f03a2 100644 --- a/doc/syntax.rdoc +++ b/doc/syntax.rdoc @@ -12,7 +12,7 @@ Assignment[rdoc-ref:syntax/assignment.rdoc] :: +if+, +unless+, +while+, +until+, +for+, +break+, +next+, +redo+ {Pattern matching}[rdoc-ref:syntax/pattern_matching.rdoc] :: - Experimental structural pattern matching and variable binding syntax + Structural pattern matching and variable binding syntax Methods[rdoc-ref:syntax/methods.rdoc] :: Method and method argument syntax @@ -37,3 +37,6 @@ Miscellaneous[rdoc-ref:syntax/miscellaneous.rdoc] :: Comments[rdoc-ref:syntax/comments.rdoc] :: Line and block code comments + +Operators[rdoc-ref:syntax/operators.rdoc] :: + Operator method behaviors diff --git a/doc/syntax/assignment.rdoc b/doc/syntax/assignment.rdoc index e30cb35adf8e48..f45f5bc0ea9504 100644 --- a/doc/syntax/assignment.rdoc +++ b/doc/syntax/assignment.rdoc @@ -162,9 +162,7 @@ Here is an example of instance variable usage: p object1.value # prints "some value" p object2.value # prints "other value" -An uninitialized instance variable has a value of +nil+. If you run Ruby with -warnings enabled, you will get a warning when accessing an uninitialized -instance variable. +An uninitialized instance variable has a value of +nil+. The +value+ method has access to the value set by the +initialize+ method, but only for the same object. diff --git a/doc/syntax/calling_methods.rdoc b/doc/syntax/calling_methods.rdoc index da061dbfdb4f92..bf5916e99aa071 100644 --- a/doc/syntax/calling_methods.rdoc +++ b/doc/syntax/calling_methods.rdoc @@ -30,7 +30,7 @@ NoMethodError. You may also use :: to designate a receiver, but this is rarely used due to the potential for confusion with :: for namespaces. -=== Chaining \Method Calls +=== Chaining Method Calls You can "chain" method calls by immediately following one method call with another. @@ -210,7 +210,7 @@ definition. If a keyword argument is given that the method did not list, and the method definition does not accept arbitrary keyword arguments, an ArgumentError will be raised. -Keyword argument value can be omitted, meaning the value will be be fetched +Keyword argument value can be omitted, meaning the value will be fetched from the context by the name of the key keyword1 = 'some value' @@ -291,16 +291,16 @@ override local arguments outside the block in the caller's scope: This prints: hello main this is block - place is world + place is: world So the +place+ variable in the block is not the same +place+ variable as outside the block. Removing ; place from the block arguments gives this result: hello main this is block - place is block + place is: block -=== Array to Arguments Conversion +=== Unpacking Positional Arguments Given the following method: @@ -322,17 +322,59 @@ Both are equivalent to: my_method(1, 2, 3) -If the method accepts keyword arguments, the splat operator will convert a -hash at the end of the array into keyword arguments: +The * unpacking operator can be applied to any object, not only +arrays. If the object responds to a #to_a method, this method +is called, and is expected to return an Array, and elements of this array are passed +as separate positional arguments: - def my_method(a, b, c: 3) + class Name + def initialize(name) + @name = name + end + + def to_a = @name.split(' ') end - arguments = [1, 2, { c: 4 }] - my_method(*arguments) + name = Name.new('Jane Doe') + p(*name) + # prints separate values: + # Jane + # Doe + +If the object doesn't have a #to_a method, the object itself is passed +as one argument: + + class Name + def initialize(name) + @name = name + end + end + + name = Name.new('Jane Doe') + p(*name) + # Prints the object itself: + # # -Note that this behavior is currently deprecated and will emit a warning. -This behavior will be removed in Ruby 3.0. +This allows to handle one or many arguments polymorphically. Note also that +nil+ +has NilClass#to_a defined to return an empty array, so conditional unpacking is +possible: + + my_method(*(some_arguments if some_condition?)) + +If #to_a method exists and does not return an Array, it would be an +error on unpacking: + + class Name + def initialize(name) + @name = name + end + + def to_a = @name + end + + name = Name.new('Jane Doe') + p(*name) + # can't convert Name to Array (Name#to_a gives String) (TypeError) You may also use the ** (described next) to convert a Hash into keyword arguments. @@ -341,12 +383,13 @@ If the number of objects in the Array do not match the number of arguments for the method, an ArgumentError will be raised. If the splat operator comes first in the call, parentheses must be used to -avoid a warning: +avoid an ambiguity of interpretation as an unpacking operator or multiplication +operator. In this case, Ruby issues a warning in verbose mode: - my_method *arguments # warning + my_method *arguments # warning: '*' interpreted as argument prefix my_method(*arguments) # no warning -=== Hash to Keyword Arguments Conversion +=== Unpacking Keyword Arguments Given the following method: @@ -368,6 +411,35 @@ Both are equivalent to: my_method(first: 3, second: 4, third: 5) +The ** unpacking operator can be applied to any object, not only +hashes. If the object responds to a #to_hash method, this method +is called, and is expected to return an Hash, and elements of this hash are passed +as keyword arguments: + + class Name + def initialize(name) + @name = name + end + + def to_hash = {first: @name.split(' ').first, last: @name.split(' ').last} + end + + name = Name.new('Jane Doe') + p(**name) + # Prints: {name: "Jane", last: "Doe"} + +Unlike * operator, ** raises an error when used on an +object that doesn't respond to #to_hash. The one exception is ++nil+, which doesn't explicitly define this method, but is still allowed to +be used in ** unpacking, not adding any keyword arguments. + +Again, this allows for conditional unpacking: + + my_method(some: params, **(some_extra_params if pass_extra_params?)) + +Like * operator, ** raises an error when the object responds +to #to_hash, but it doesn't return a Hash. + If the method definition uses the keyword splat operator to gather arbitrary keyword arguments, they will not be gathered by *: diff --git a/doc/syntax/control_expressions.rdoc b/doc/syntax/control_expressions.rdoc index 5350585f15e99b..3de6cd293f55c8 100644 --- a/doc/syntax/control_expressions.rdoc +++ b/doc/syntax/control_expressions.rdoc @@ -189,7 +189,7 @@ The same is true for +unless+. The +case+ expression can be used in two ways. The most common way is to compare an object against multiple patterns. The -patterns are matched using the +===+ method which is aliased to +==+ on +patterns are matched using the === method which is aliased to == on Object. Other classes must override it to give meaningful behavior. See Module#=== and Regexp#=== for examples. @@ -255,7 +255,7 @@ Again, the +then+ and +else+ are optional. The result value of a +case+ expression is the last value executed in the expression. -Since Ruby 2.7, +case+ expressions also provide a more powerful experimental +Since Ruby 2.7, +case+ expressions also provide a more powerful pattern matching feature via the +in+ keyword: case {a: 1, b: 2, c: 3} diff --git a/doc/syntax/exceptions.rdoc b/doc/syntax/exceptions.rdoc index 31e2f0175c5f7e..cdf9d367a7eade 100644 --- a/doc/syntax/exceptions.rdoc +++ b/doc/syntax/exceptions.rdoc @@ -86,7 +86,7 @@ To always run some code whether an exception was raised or not, use +ensure+: rescue # ... ensure - # this always runs + # this always runs BUT does not implicitly return the last evaluated statement. end You may also run some code when an exception is not raised: @@ -96,7 +96,11 @@ You may also run some code when an exception is not raised: rescue # ... else - # this runs only when no exception was raised + # this runs only when no exception was raised AND return the last evaluated statement ensure - # ... + # this always runs. + # It is evaluated after the evaluation of either the `rescue` or the `else` block. + # It will not return implicitly. end + +NB : Without explicit +return+ in the +ensure+ block, +begin+/+end+ block will return the last evaluated statement before entering in the +ensure+ block. diff --git a/doc/keywords.rdoc b/doc/syntax/keywords.rdoc similarity index 99% rename from doc/keywords.rdoc rename to doc/syntax/keywords.rdoc index cb1cff33f0be87..7c368205efabba 100644 --- a/doc/keywords.rdoc +++ b/doc/syntax/keywords.rdoc @@ -1,4 +1,4 @@ -== Keywords += Keywords The following keywords are used by Ruby. diff --git a/doc/syntax/literals.rdoc b/doc/syntax/literals.rdoc index 0c1e4a434be6fb..46bb7673f3e040 100644 --- a/doc/syntax/literals.rdoc +++ b/doc/syntax/literals.rdoc @@ -136,9 +136,9 @@ Also \Rational numbers may be imaginary numbers. 12.3ir #=> Syntax error -== Strings +== \String Literals -=== \String Literals +=== Double-Quoted \String Literals The most common way of writing strings is using ": @@ -150,35 +150,14 @@ Any internal " must be escaped: "This string has a quote: \". As you can see, it is escaped" -Double-quote strings allow escaped characters such as \n for -newline, \t for tab, etc. The full list of supported escape -sequences are as follows: +Double-quoted strings allow escape sequences described in +{Escape Sequences}[#label-Escape+Sequences]. - \a bell, ASCII 07h (BEL) - \b backspace, ASCII 08h (BS) - \t horizontal tab, ASCII 09h (TAB) - \n newline (line feed), ASCII 0Ah (LF) - \v vertical tab, ASCII 0Bh (VT) - \f form feed, ASCII 0Ch (FF) - \r carriage return, ASCII 0Dh (CR) - \e escape, ASCII 1Bh (ESC) - \s space, ASCII 20h (SPC) - \\ backslash, \ - \nnn octal bit pattern, where nnn is 1-3 octal digits ([0-7]) - \xnn hexadecimal bit pattern, where nn is 1-2 hexadecimal digits ([0-9a-fA-F]) - \unnnn Unicode character, where nnnn is exactly 4 hexadecimal digits ([0-9a-fA-F]) - \u{nnnn ...} Unicode character(s), where each nnnn is 1-6 hexadecimal digits ([0-9a-fA-F]) - \cx or \C-x control character, where x is an ASCII printable character - \M-x meta character, where x is an ASCII printable character - \M-\C-x meta control character, where x is an ASCII printable character - \M-\cx same as above - \c\M-x same as above - \c? or \C-? delete, ASCII 7Fh (DEL) - -Any other character following a backslash is interpreted as the +In a double-quoted string, +any other character following a backslash is interpreted as the character itself. -Double-quote strings allow interpolation of other values using +Double-quoted strings allow interpolation of other values using #{...}: "One plus one is two: #{1 + 1}" @@ -190,8 +169,14 @@ You can also use #@foo, #@@foo and #$foo as a shorthand for, respectively, #{ @foo }, #{ @@foo } and #{ $foo }. +See also: + +* {% and %Q: Interpolable String Literals}[#label-25+and+-25Q-3A+Interpolable+String+Literals] + +=== Single-Quoted \String Literals + Interpolation may be disabled by escaping the "#" character or using -single-quote strings: +single-quoted strings: '#{1 + 1}' #=> "\#{1 + 1}" @@ -199,6 +184,16 @@ In addition to disabling interpolation, single-quoted strings also disable all escape sequences except for the single-quote (\') and backslash (\\\\). +In a single-quoted string, +any other character following a backslash is interpreted as is: +a backslash and the character itself. + +See also: + +* {%q: Non-Interpolable String Literals}[#label-25q-3A+Non-Interpolable+String+Literals] + +=== Literal String Concatenation + Adjacent string literals are automatically concatenated by the interpreter: "con" "cat" "en" "at" "ion" #=> "concatenation" @@ -209,12 +204,14 @@ Any combination of adjacent single-quote, double-quote, percent strings will be concatenated as long as a percent-string is not last. %q{a} 'b' "c" #=> "abc" - "a" 'b' %q{c} #=> NameError: uninitialized constant q + "a" 'b' %q{c} #=> NoMethodError: undefined method 'q' for main + +=== Character Literal There is also a character literal notation to represent single character strings, which syntax is a question mark (?) -followed by a single character or escape sequence that corresponds to -a single codepoint in the script encoding: +followed by a single character or escape sequence (except continuation line) +that corresponds to a single codepoint in the script encoding: ?a #=> "a" ?abc #=> SyntaxError @@ -228,10 +225,45 @@ a single codepoint in the script encoding: ?\C-\M-a #=> "\x81", same as above ?あ #=> "あ" -See also: +=== Escape Sequences -* {%q: Non-Interpolable String Literals}[#label-25q-3A+Non-Interpolable+String+Literals] -* {% and %Q: Interpolable String Literals}[#label-25+and+-25Q-3A+Interpolable+String+Literals] +Some characters can be represented as escape sequences in +double-quoted strings, +character literals, +here document literals (non-quoted, double-quoted, and with backticks), +double-quoted symbols, +double-quoted symbol keys in Hash literals, +Regexp literals, and +several percent literals (%, %Q, %W, %I, %r, %x). + +They allow escape sequences such as \n for +newline, \t for tab, etc. The full list of supported escape +sequences are as follows: + + \a bell, ASCII 07h (BEL) + \b backspace, ASCII 08h (BS) + \t horizontal tab, ASCII 09h (TAB) + \n newline (line feed), ASCII 0Ah (LF) + \v vertical tab, ASCII 0Bh (VT) + \f form feed, ASCII 0Ch (FF) + \r carriage return, ASCII 0Dh (CR) + \e escape, ASCII 1Bh (ESC) + \s space, ASCII 20h (SPC) + \\ backslash, \ + \nnn octal bit pattern, where nnn is 1-3 octal digits ([0-7]) + \xnn hexadecimal bit pattern, where nn is 1-2 hexadecimal digits ([0-9a-fA-F]) + \unnnn Unicode character, where nnnn is exactly 4 hexadecimal digits ([0-9a-fA-F]) + \u{nnnn ...} Unicode character(s), where each nnnn is 1-6 hexadecimal digits ([0-9a-fA-F]) + \cx or \C-x control character, where x is an ASCII printable character + \M-x meta character, where x is an ASCII printable character + \M-\C-x meta control character, where x is an ASCII printable character + \M-\cx same as above + \c\M-x same as above + \c? or \C-? delete, ASCII 7Fh (DEL) + \ continuation line (empty string) + +The last one, \, represents an empty string instead of a character. +It is used to fold a line in a string. === Here Document Literals @@ -283,9 +315,10 @@ its end is a multiple of eight. The amount to be removed is counted in terms of the number of spaces. If the boundary appears in the middle of a tab, that tab is not removed. -A heredoc allows interpolation and escaped characters. You may disable -interpolation and escaping by surrounding the opening identifier with single -quotes: +A heredoc allows interpolation and the escape sequences described in +{Escape Sequences}[#label-Escape+Sequences]. +You may disable interpolation and the escaping by surrounding the opening +identifier with single quotes: expected_result = <<-'EXPECTED' One plus one is #{1 + 1} @@ -326,12 +359,15 @@ details on what symbols are and when ruby creates them internally. You may reference a symbol using a colon: :my_symbol. -You may also create symbols by interpolation: +You may also create symbols by interpolation and escape sequences described in +{Escape Sequences}[#label-Escape+Sequences] with double-quotes: :"my_symbol1" :"my_symbol#{1 + 1}" + :"foo\sbar" -Like strings, a single-quote may be used to disable interpolation: +Like strings, a single-quote may be used to disable interpolation and +escape sequences: :'my_symbol#{1 + 1}' #=> :"my_symbol\#{1 + 1}" @@ -451,7 +487,12 @@ may use these paired delimiters: * ( and ). * { and }. * < and >. -* Any other character, as both beginning and ending delimiters. +* Non-alphanumeric ASCII character except above, as both beginning and ending delimiters. + +The delimiters can be escaped with a backslash. +However, the first four pairs (brackets, parenthesis, braces, and +angle brackets) are allowed without backslash as far as they are correctly +paired. These are demonstrated in the next section. @@ -460,13 +501,20 @@ These are demonstrated in the next section. You can write a non-interpolable string with %q. The created string is the same as if you created it with single quotes: - %[foo bar baz] # => "foo bar baz" # Using []. - %(foo bar baz) # => "foo bar baz" # Using (). - %{foo bar baz} # => "foo bar baz" # Using {}. - % # => "foo bar baz" # Using <>. - %|foo bar baz| # => "foo bar baz" # Using two |. - %:foo bar baz: # => "foo bar baz" # Using two :. + %q[foo bar baz] # => "foo bar baz" # Using []. + %q(foo bar baz) # => "foo bar baz" # Using (). + %q{foo bar baz} # => "foo bar baz" # Using {}. + %q # => "foo bar baz" # Using <>. + %q|foo bar baz| # => "foo bar baz" # Using two |. + %q:foo bar baz: # => "foo bar baz" # Using two :. %q(1 + 1 is #{1 + 1}) # => "1 + 1 is \#{1 + 1}" # No interpolation. + %q[foo[bar]baz] # => "foo[bar]baz" # brackets can be nested. + %q(foo(bar)baz) # => "foo(bar)baz" # parenthesis can be nested. + %q{foo{bar}baz} # => "foo{bar}baz" # braces can be nested. + %qbaz> # => "foobaz" # angle brackets can be nested. + +This is similar to single-quoted string but only backslashes and +the specified delimiters can be escaped with a backslash. === % and %Q: Interpolable String Literals @@ -476,30 +524,63 @@ or with its alias %: %[foo bar baz] # => "foo bar baz" %(1 + 1 is #{1 + 1}) # => "1 + 1 is 2" # Interpolation. +This is similar to double-quoted string. +It allow escape sequences described in +{Escape Sequences}[#label-Escape+Sequences]. +Other escaped characters (a backslash followed by a character) are +interpreted as the character. + === %w and %W: String-Array Literals -You can write an array of strings with %w (non-interpolable) -or %W (interpolable): +You can write an array of strings as whitespace-separated words +with %w (non-interpolable) or %W (interpolable): %w[foo bar baz] # => ["foo", "bar", "baz"] %w[1 % *] # => ["1", "%", "*"] # Use backslash to embed spaces in the strings. %w[foo\ bar baz\ bat] # => ["foo bar", "baz bat"] + %W[foo\ bar baz\ bat] # => ["foo bar", "baz bat"] %w(#{1 + 1}) # => ["\#{1", "+", "1}"] %W(#{1 + 1}) # => ["2"] + # The nested delimiters evaluated to a flat array of strings + # (not nested array). + %w[foo[bar baz]qux] # => ["foo[bar", "baz]qux"] + +The following characters are considered as white spaces to separate words: + +* space, ASCII 20h (SPC) +* form feed, ASCII 0Ch (FF) +* newline (line feed), ASCII 0Ah (LF) +* carriage return, ASCII 0Dh (CR) +* horizontal tab, ASCII 09h (TAB) +* vertical tab, ASCII 0Bh (VT) + +The white space characters can be escaped with a backslash to make them +part of a word. + +%W allow escape sequences described in +{Escape Sequences}[#label-Escape+Sequences]. +However the continuation line \ is not usable because +it is interpreted as the escaped newline described above. + === %i and %I: Symbol-Array Literals -You can write an array of symbols with %i (non-interpolable) -or %I (interpolable): +You can write an array of symbols as whitespace-separated words +with %i (non-interpolable) or %I (interpolable): %i[foo bar baz] # => [:foo, :bar, :baz] %i[1 % *] # => [:"1", :%, :*] # Use backslash to embed spaces in the symbols. %i[foo\ bar baz\ bat] # => [:"foo bar", :"baz bat"] + %I[foo\ bar baz\ bat] # => [:"foo bar", :"baz bat"] %i(#{1 + 1}) # => [:"\#{1", :+, :"1}"] %I(#{1 + 1}) # => [:"2"] +The white space characters and its escapes are interpreted as the same as +string-array literals described in +{%w and %W: String-Array Literals}[#label-25w+and+-25W-3A+String-Array+Literals]. + === %s: Symbol Literals You can write a symbol with %s: @@ -507,6 +588,10 @@ You can write a symbol with %s: %s[foo] # => :foo %s[foo bar] # => :"foo bar" +This is non-interpolable. +No interpolation allowed. +Only backslashes and the specified delimiters can be escaped with a backslash. + === %r: Regexp Literals You can write a regular expression with %r; @@ -531,4 +616,10 @@ See {Regexp modes}[rdoc-ref:Regexp@Modes] for details. You can write and execute a shell command with %x: - %x(echo 1) # => "1\n" + %x(echo 1) # => "1\n" + %x[echo #{1 + 2}] # => "3\n" + %x[echo \u0030] # => "0\n" + +This is interpolable. +%x allow escape sequences described in +{Escape Sequences}[#label-Escape+Sequences]. diff --git a/doc/syntax/modules_and_classes.rdoc b/doc/syntax/modules_and_classes.rdoc index 024815a5a6f613..9e05c5c774e0a3 100644 --- a/doc/syntax/modules_and_classes.rdoc +++ b/doc/syntax/modules_and_classes.rdoc @@ -40,9 +40,9 @@ functionality: remove_method :my_method end -Reopening classes is a very powerful feature of Ruby, but it is best to only -reopen classes you own. Reopening classes you do not own may lead to naming -conflicts or difficult to diagnose bugs. +Reopening modules (or classes) is a very powerful feature of Ruby, but it is +best to only reopen modules you own. Reopening modules you do not own may lead +to naming conflicts or difficult to diagnose bugs. == Nesting @@ -259,6 +259,28 @@ includes a minimum of built-in methods. You can use BasicObject to create an independent inheritance structure. See the BasicObject documentation for further details. +Just like modules, classes can also be reopened. You can omit its superclass +when you reopen a class. Specifying a different superclass than the previous +definition will raise an error. + + class C + end + + class D < C + end + + # OK + class D < C + end + + # OK + class D + end + + # TypeError: superclass mismatch for class D + class D < String + end + == Inheritance Any method defined on a class is callable from its subclass: diff --git a/doc/syntax/operators.rdoc b/doc/syntax/operators.rdoc new file mode 100644 index 00000000000000..d3045ac99e35b3 --- /dev/null +++ b/doc/syntax/operators.rdoc @@ -0,0 +1,75 @@ += Operators + +In Ruby, operators such as +, are defined as methods on the class. +Literals[rdoc-ref:syntax/literals.rdoc] define their methods within the lower +level, C language. String class, for example. + +Ruby objects can define or overload their own implementation for most operators. + +Here is an example: + + class Foo < String + def +(str) + self.concat(str).concat("another string") + end + end + + foobar = Foo.new("test ") + puts foobar + "baz " + +This prints: + + test baz another string + +What operators are available is dependent on the implementing class. + +== Operator Behavior + +How a class behaves to a given operator is specific to that class, since +operators are method implementations. + +When using an operator, it's the expression on the left-hand side of the +operation that specifies the behavior. + + 'a' * 3 #=> "aaa" + 3 * 'a' # TypeError: String can't be coerced into Integer + +== Logical Operators + +Logical operators are not methods, and therefore cannot be +redefined/overloaded. They are tokenized at a lower level. + +Short-circuit logical operators (&&, ||, +and, and or) do not always result in a boolean value. +Similar to blocks, it's the last evaluated expression that defines the result +of the operation. + +=== &&, and + +Both &&/and operators provide short-circuiting by executing each +side of the operator, left to right, and stopping at the first occurrence of a +falsey expression. The expression that defines the result is the last one +executed, whether it be the final expression, or the first occurrence of a falsey +expression. + +Some examples: + + true && 9 && "string" #=> "string" + (1 + 2) && nil && "string" #=> nil + (a = 1) && (b = false) && (c = "string") #=> false + + puts a #=> 1 + puts b #=> false + puts c #=> nil + +In this last example, c was initialized, but not defined. + +=== ||, or + +The means by which ||/or short-circuits, is to return the result of +the first expression that is truthy. + +Some examples: + + (1 + 2) || true || "string" #=> 3 + false || nil || "string" #=> "string" diff --git a/doc/syntax/pattern_matching.rdoc b/doc/syntax/pattern_matching.rdoc index e49c09a1f8b3e2..c43919ba14e5f4 100644 --- a/doc/syntax/pattern_matching.rdoc +++ b/doc/syntax/pattern_matching.rdoc @@ -221,7 +221,7 @@ For hash patterns, even a simpler form exists: key-only specification (without a end #=> "matched: 1" -Binding works for nested patterns as well: +\Binding works for nested patterns as well: case {name: 'John', friends: [{name: 'Jane'}, {name: 'Rajesh'}]} in name:, friends: [{name: first_friend}, *] @@ -247,9 +247,9 @@ The "rest" part of a pattern also can be bound to a variable: else "not matched" end - #=> "matched: 1, {:b=>2, :c=>3}" + #=> "matched: 1, {b: 2, c: 3}" -Binding to variables currently does NOT work for alternative patterns joined with |: +\Binding to variables currently does NOT work for alternative patterns joined with |: case {a: 1, b: 2} in {a: } | Array @@ -422,7 +422,8 @@ These core and library classes implement deconstruction: == Guard clauses -+if+ can be used to attach an additional condition (guard clause) when the pattern matches. This condition may use bound variables: ++if+ can be used to attach an additional condition (guard clause) when the pattern matches in +case+/+in+ expressions. +This condition may use bound variables: case [1, 2] in a, b if b == a*2 @@ -450,6 +451,11 @@ These core and library classes implement deconstruction: end #=> "matched" +Note that => and +in+ operator can not have a guard clause. +The following examples is parsed as a standalone expression with modifier +if+. + + [1, 2] in a, b if b == a*2 + == Appendix A. Pattern syntax Approximate syntax is: diff --git a/doc/timezones.rdoc b/doc/timezones.rdoc deleted file mode 100644 index c3aae88fdec809..00000000000000 --- a/doc/timezones.rdoc +++ /dev/null @@ -1,108 +0,0 @@ -== Timezones - -=== Timezone Specifiers - -Certain \Time methods accept arguments that specify timezones: - -- Time.at: keyword argument +in:+. -- Time.new: positional argument +zone+ or keyword argument +in:+. -- Time.now: keyword argument +in:+. -- Time#getlocal: positional argument +zone+. -- Time#localtime: positional argument +zone+. - -The value given with any of these must be one of the following -(each detailed below): - -- {Hours/minutes offset}[rdoc-ref:timezones.rdoc@Hours-2FMinutes+Offsets]. -- {Single-letter offset}[rdoc-ref:timezones.rdoc@Single-Letter+Offsets]. -- {Integer offset}[rdoc-ref:timezones.rdoc@Integer+Offsets]. -- {Timezone object}[rdoc-ref:timezones.rdoc@Timezone+Objects]. - -==== Hours/Minutes Offsets - -The zone value may be a string offset from UTC -in the form '+HH:MM' or '-HH:MM', -where: - -- +HH+ is the 2-digit hour in the range 0..23. -- +MM+ is the 2-digit minute in the range 0..59. - -Examples: - - t = Time.utc(2000, 1, 1, 20, 15, 1) # => 2000-01-01 20:15:01 UTC - Time.at(t, in: '-23:59') # => 1999-12-31 20:16:01 -2359 - Time.at(t, in: '+23:59') # => 2000-01-02 20:14:01 +2359 - -==== Single-Letter Offsets - -The zone value may be a letter in the range 'A'..'I' -or 'K'..'Z'; -see {List of military time zones}[https://en.wikipedia.org/wiki/List_of_military_time_zones]: - - t = Time.utc(2000, 1, 1, 20, 15, 1) # => 2000-01-01 20:15:01 UTC - Time.at(t, in: 'A') # => 2000-01-01 21:15:01 +0100 - Time.at(t, in: 'I') # => 2000-01-02 05:15:01 +0900 - Time.at(t, in: 'K') # => 2000-01-02 06:15:01 +1000 - Time.at(t, in: 'Y') # => 2000-01-01 08:15:01 -1200 - Time.at(t, in: 'Z') # => 2000-01-01 20:15:01 UTC - -==== \Integer Offsets - -The zone value may be an integer number of seconds -in the range -86399..86399: - - t = Time.utc(2000, 1, 1, 20, 15, 1) # => 2000-01-01 20:15:01 UTC - Time.at(t, in: -86399) # => 1999-12-31 20:15:02 -235959 - Time.at(t, in: 86399) # => 2000-01-02 20:15:00 +235959 - -==== Timezone Objects - -In most cases, the zone value may be an object -responding to certain timezone methods. - -\Exceptions (timezone object not allowed): - -- Time.new with positional argument +zone+. -- Time.now with keyword argument +in:+. - -The timezone methods are: - -- +local_to_utc+: - - - Called when Time.new is invoked with +tz+ - as the value of positional argument +zone+ or keyword argument +in:+. - - Argument: a Time::tm object. - - Returns: a \Time-like object in the UTC timezone. - -- +utc_to_local+: - - - Called when Time.at or Time.now is invoked with +tz+ - as the value for keyword argument +in:+, - and when Time#getlocal or Time#localtime is called with +tz+ - as the value for positional argument +zone+. - - Argument: a Time::tm object. - - Returns: a \Time-like object in the local timezone. - -A custom timezone class may have these instance methods, -which will be called if defined: - -- +abbr+: - - - Called when Time#strftime is invoked with a format involving %Z. - - Argument: a Time::tm object. - - Returns: a string abbreviation for the timezone name. - -- +dst?+: - - - Called when Time.at or Time.now is invoked with +tz+ - as the value for keyword argument +in:+, - and when Time#getlocal or Time#localtime is called with +tz+ - as the value for positional argument +zone+. - - Argument: a Time::tm object. - - Returns: whether the time is daylight saving time. - -- +name+: - - - Called when Marshal.dump(t) is invoked - - Argument: none. - - Returns: the string name of the timezone. diff --git a/doc/windows.md b/doc/windows.md index 8159b25861b6b3..13c797875e6a3d 100644 --- a/doc/windows.md +++ b/doc/windows.md @@ -2,9 +2,9 @@ Ruby supports a few native build platforms for Windows. -* mswin: Build using Microsoft Visual C++ compiler +* mswin: Build using Microsoft Visual C++ compiler with vcruntimeXXX.dll * mingw-msvcrt: Build using compiler for Mingw with msvcrtXX.dll -* mingw-ucrt: Build using compiler for Mingw with vcruntime.dll +* mingw-ucrt: Build using compiler for Mingw with Windows Universal CRT ## Building Ruby using Mingw with UCRT @@ -16,41 +16,52 @@ editor. Ruby core development can be done either in Windows `cmd` like: -``` +```batch +ridk install ridk enable ucrt64 -pacman -S --needed %MINGW_PACKAGE_PREFIX%-openssl %MINGW_PACKAGE_PREFIX%-libyaml +pacman -S --needed %MINGW_PACKAGE_PREFIX%-openssl %MINGW_PACKAGE_PREFIX%-libyaml %MINGW_PACKAGE_PREFIX%-libffi + +mkdir c:\work\ruby +cd /d c:\work\ruby + +git clone https://github.com/ruby/ruby src -cd c:\ -mkdir work -cd work -git clone https://github.com/ruby/ruby +sh ./src/autogen.sh -cd c:\work\ruby -sh autogen.sh -sh configure -C --disable-install-doc +mkdir build +cd build +sh ../src/configure -C --disable-install-doc make ``` or in MSYS2 `bash` like: -``` +```bash +ridk install ridk enable ucrt64 bash -pacman -S --needed $MINGW_PACKAGE_PREFIX-openssl $MINGW_PACKAGE_PREFIX-libyaml +pacman -S --needed $MINGW_PACKAGE_PREFIX-openssl $MINGW_PACKAGE_PREFIX-libyaml $MINGW_PACKAGE_PREFIX-libffi + +mkdir /c/work/ruby +cd /c/work/ruby -cd /c/ -mkdir work -cd work -git clone https://github.com/ruby/ruby -cd ruby +git clone https://github.com/ruby/ruby src -./autogen.sh -./configure -C --disable-install-doc +./src/autogen.sh +cd build +../src/configure -C --disable-install-doc make ``` +If you have other MSYS2 environment via other package manager like `scoop`, you need to specify `$MINGW_PACKAGE_PREFIX` is `mingw-w64-ucrt-x86_64`. +And you need to add `--with-opt-dir` option to `configure` command like: + +```batch +sh ../../ruby/configure -C --disable-install-doc --with-opt-dir=C:\Users\username\scoop\apps\msys2\current\ucrt64 +``` + [RubyInstaller-Devkit]: https://rubyinstaller.org/ [git-for-windows]: https://gitforwindows.org/ [VSCode]: https://code.visualstudio.com/ @@ -59,39 +70,77 @@ make ### Requirement -1. Windows 7 or later. +1. Windows 10/Windows Server 2016 or later. -2. Visual C++ 12.0 (2013) or later. +2. Visual C++ 14.0 (2015) or later. **Note** if you want to build x64 version, use native compiler for x64. -3. Please set environment variable `INCLUDE`, `LIB`, `PATH` - to run required commands properly from the command line. + The minimum requirement is here: + * VC++/MSVC on VS 2017/2019/2022 version build tools. + * Windows 10/11 SDK + + You can install Visual Studio Build Tools with `winget`. + `win32\install-buildtools.cmd` is a batch file to install the + minimum requirements excluding the IDE etc. + +3. Please set environment variable `INCLUDE`, `LIB`, `PATH` to run + required commands properly from the command line. These are set + properly by `vsdevcmd.bat` or `vcvarall*.bat` usually. You can run + the following command to set them in your command line. + + To native build: + + ``` + cmd /k win32\vssetup.cmd + ``` + + To cross build arm64 binary: + + ``` + cmd /k win32\vssetup.cmd -arch arm64 + ``` + + To cross build x64 binary: + + ``` + cmd /k win32\vssetup.cmd -arch x64 + ``` + + See `win32\vssetup.cmd -help` for other command line options. **Note** building ruby requires following commands. - * nmake - * cl - * ml - * lib - * dumpbin + * `nmake` + * `cl` + * `ml` + * `lib` + * `dumpbin` 4. If you want to build from GIT source, following commands are required. - * patch - * sed - * ruby 2.0 or later + * `git` + * `ruby` 3.0 or later You can use [scoop](https://scoop.sh/) to install them like: - ``` - scoop install git ruby sed patch + ```batch + scoop install git ruby ``` -5. You need to install required libraries using [vcpkg](https://vcpkg.io/) like: + The windows version of `git` configured with `autocrlf` is `true`. The Ruby + test suite may fail with `autocrlf` set to `true`. You can set it to `false` + like: + ```batch + git config --global core.autocrlf false ``` - vcpkg --triplet x64-windows install openssl libffi libyaml zlib + +5. You need to install required libraries using [vcpkg](https://vcpkg.io/) on + directory of ruby repository like: + + ```batch + vcpkg --triplet x64-windows install ``` 6. Enable Command Extension of your command line. It's the default behavior @@ -102,30 +151,37 @@ make 1. Execute `win32\configure.bat` on your build directory. You can specify the target platform as an argument. - For example, run `configure --target=i686-mswin32` + For example, run `configure --target=i686-mswin32`. You can also specify the install directory. - For example, run `configure --prefix=` + For example, run `configure --prefix=`. Default of the install directory is `/usr` . - The default _PLATFORM_ is `i386-mswin32_`_MSRTVERSION_ on 32-bit - platforms, or `x64-mswin64_`_MSRTVERSION_ on x64 platforms. - _MSRTVERSION_ is the 2- or 3-digits version of the Microsoft - Runtime Library. -2. Change _RUBY_INSTALL_NAME_ and _RUBY_SO_NAME_ in `Makefile` - if you want to change the name of the executable files. - And add _RUBYW_INSTALL_NAME_ to change the name of the - executable without console window if also you want. +2. If you want to append to the executable and DLL file names, + specify `--program-prefix` and `--program-suffix`, like + `win32\configure.bat --program-suffix=-$(MAJOR)$(MINOR)`. + + Also, the `--install-name` and `--so-name` options specify the + exact base names of the executable and DLL files, respectively, + like `win32\configure.bat --install-name=$(RUBY_BASE_NAME)-$(MAJOR)$(MINOR)`. + + By default, the name for the executable without a console window + is generated from the _RUBY_INSTALL_NAME_ specified as above by + replacing `ruby` with `rubyw`. If you want to make it different + more, modify _RUBYW_INSTALL_NAME_ directly in the Makefile. 3. You need specify vcpkg directory to use `--with-opt-dir` - option like `configure --with-opt-dir=C:\vcpkg\installed\x64-windows` + option like `win32\configure.bat --with-opt-dir=C:/vcpkg_installed/x64-windows` 4. Run `nmake up` if you are building from GIT source. 5. Run `nmake` -6. Run `nmake check` +6. Run `nmake prepare-vcpkg` with administrator privilege if you need to + copy vcpkg installed libraries like `libssl-3-x64.dll` to the build directory. -7. Run `nmake install` +7. Run `nmake check` + +8. Run `nmake install` ### Build examples @@ -137,7 +193,7 @@ make install directory: C:\usr\local ``` - ``` + ```batch C: cd \ruby win32\configure --prefix=/usr/local @@ -154,7 +210,7 @@ make install directory: C:\usr\local ``` - ``` + ```batch C: cd \ruby mkdir mswin32 @@ -173,7 +229,7 @@ make install directory: C:\usr\local ``` - ``` + ```batch D: cd D:\build\ruby C:\src\ruby\win32\configure --prefix=/usr/local @@ -190,7 +246,7 @@ make install directory: C:\usr\local ``` - ``` + ```batch C: cd \ruby win32\configure --prefix=/usr/local --target=x64-mswin64 @@ -209,6 +265,18 @@ You can build ruby in any directory including the source directory, except `win32` directory in the source directory. This is restriction originating in the path search method of `NMAKE`. +### Dependency management + +Ruby uses [vcpkg](https://vcpkg.io/) to manage dependencies on mswin platform. + +You can update and install it under the build directory like: + +```batch +nmake update-vcpkg # Update baseline version of vcpkg +nmake install-vcpkg # Install vcpkg from build directory +``` + + ## Icons Any icon files(`*.ico`) in the build directory, directories specified with diff --git a/doc/yarv_frame_layout.md b/doc/yarv_frame_layout.md new file mode 100644 index 00000000000000..ea8ad013cf85a6 --- /dev/null +++ b/doc/yarv_frame_layout.md @@ -0,0 +1,77 @@ +# YARV Frame Layout + +This document is an introduction to what happens on the VM stack as the VM +services calls. The code holds the ultimate truth for this subject, so beware +that this document can become stale. + +We'll walk through the following program, with explanation at selected points +in execution and abridged disassembly listings: + +```ruby +def foo(x, y) + z = x.casecmp(y) +end + +foo(:one, :two) +``` + +First, after arguments are evaluated and right before the `send` to `foo`: + +``` + ┌────────────┐ + putself │ :two │ + putobject :one 0x2 ├────────────┤ + putobject :two │ :one │ +► send <:foo, argc:2> 0x1 ├────────────┤ + leave │ self │ + 0x0 └────────────┘ +``` + +The `put*` instructions have pushed 3 items onto the stack. It's now time to +add a new control frame for `foo`. The following is the shape of the stack +after one instruction in `foo`: + +``` + cfp->sp=0x8 at this point. + 0x8 ┌────────────┐◄──Stack space for temporaries + │ :one │ live above the environment. + 0x7 ├────────────┤ + getlocal x@0 │ < flags > │ foo's rb_control_frame_t +► getlocal y@1 0x6 ├────────────┤◄──has cfp->ep=0x6 + send <:casecmp, argc:1> │ │ + dup 0x5 ├────────────┤ The flags, block, and CME triple + setlocal z@2 │ │ (VM_ENV_DATA_SIZE) form an + leave 0x4 ├────────────┤ environment. They can be used to + │ z (nil) │ figure out what local variables + 0x3 ├────────────┤ are below them. + │ :two │ + 0x2 ├────────────┤ Notice how the arguments, now + │ :one │ locals, never moved. This layout + 0x1 ├────────────┤ allows for argument transfer + │ self │ without copying. + 0x0 └────────────┘ +``` + +Given that locals have lower address than `cfp->ep`, it makes sense then that +`getlocal` in `insns.def` has `val = *(vm_get_ep(GET_EP(), level) - idx);`. +When accessing variables in the immediate scope, where `level=0`, it's +essentially `val = cfp->ep[-idx];`. + +Note that this EP-relative index has a different basis the index that comes +after "@" in disassembly listings. The "@" index is relative to the 0th local +(`x` in this case). + +## Q&A + +Q: It seems that the receiver is always at an offset relative to EP, + like locals. Couldn't we use EP to access it instead of using `cfp->self`? + +A: Not all calls put the `self` in the callee on the stack. Two + examples are `Proc#call`, where the receiver is the Proc object, but `self` + inside the callee is `Proc#receiver`, and `yield`, where the receiver isn't + pushed onto the stack before the arguments. + +Q: Why have `cfp->ep` when it seems that everything is below `cfp->sp`? + +A: In the example, `cfp->ep` points to the stack, but it can also point to the + GC heap. Blocks can capture and evacuate their environment to the heap. diff --git a/doc/yjit/yjit.md b/doc/yjit/yjit.md index 8aac4ec555e7a5..0024c780b909d3 100644 --- a/doc/yjit/yjit.md +++ b/doc/yjit/yjit.md @@ -4,26 +4,29 @@

- YJIT - Yet Another Ruby JIT =========================== YJIT is a lightweight, minimalistic Ruby JIT built inside CRuby. It lazily compiles code using a Basic Block Versioning (BBV) architecture. -The target use case is that of servers running Ruby on Rails. YJIT is currently supported for macOS, Linux and BSD on x86-64 and arm64/aarch64 CPUs. This project is open source and falls under the same license as CRuby.

If you're using YJIT in production, please share your success stories with us! -

+

If you wish to learn more about the approach taken, here are some conference talks and publications: + +- MPLR 2023 talk: [Evaluating YJIT’s Performance in a Production Context: A Pragmatic Approach](https://www.youtube.com/watch?v=pVRmPZcNUhc) +- RubyKaigi 2023 keynote: [Optimizing YJIT’s Performance, from Inception to Production](https://www.youtube.com/watch?v=X0JRhh8w_4I) +- RubyKaigi 2023 keynote: [Fitting Rust YJIT into CRuby](https://www.youtube.com/watch?v=GI7vvAgP_Qs) - RubyKaigi 2022 keynote: [Stories from developing YJIT](https://www.youtube.com/watch?v=EMchdR9C8XM) - RubyKaigi 2022 talk: [Building a Lightweight IR and Backend for YJIT](https://www.youtube.com/watch?v=BbLGqTxTRp0) - RubyKaigi 2021 talk: [YJIT: Building a New JIT Compiler Inside CRuby](https://www.youtube.com/watch?v=PBVLf3yfMs8) - Blog post: [YJIT: Building a New JIT Compiler Inside CRuby](https://pointersgonewild.com/2021/06/02/yjit-building-a-new-jit-compiler-inside-cruby/) +- MPLR 2023 paper: [Evaluating YJIT’s Performance in a Production Context: A Pragmatic Approach](https://dl.acm.org/doi/10.1145/3617651.3622982) - VMIL 2021 paper: [YJIT: A Basic Block Versioning JIT Compiler for CRuby](https://dl.acm.org/doi/10.1145/3486606.3486781) - MoreVMs 2021 talk: [YJIT: Building a New JIT Compiler Inside CRuby](https://www.youtube.com/watch?v=vucLAqv7qpc) - ECOOP 2016 talk: [Interprocedural Type Specialization of JavaScript Programs Without Type Analysis](https://www.youtube.com/watch?v=sRNBY7Ss97A) @@ -31,43 +34,50 @@ If you wish to learn more about the approach taken, here are some conference tal - ECOOP 2015 talk: [Simple and Effective Type Check Removal through Lazy Basic Block Versioning](https://www.youtube.com/watch?v=S-aHBuoiYE0) - ECOOP 2015 paper: [Simple and Effective Type Check Removal through Lazy Basic Block Versioning](https://arxiv.org/pdf/1411.0352.pdf) -To cite YJIT in your publications, please cite the VMIL 2021 paper: +To cite YJIT in your publications, please cite the MPLR 2023 paper: -``` -@inproceedings{yjit_vmil2021, -author = {Chevalier-Boisvert, Maxime and Gibbs, Noah and Boussier, Jean and Wu, Si Xing (Alan) and Patterson, Aaron and Newton, Kevin and Hawthorn, John}, -title = {YJIT: A Basic Block Versioning JIT Compiler for CRuby}, -year = {2021}, -isbn = {9781450391092}, +```BibTeX +@inproceedings{yjit_mplr_2023, +author = {Chevalier-Boisvert, Maxime and Kokubun, Takashi and Gibbs, Noah and Wu, Si Xing (Alan) and Patterson, Aaron and Issroff, Jemma}, +title = {Evaluating YJIT’s Performance in a Production Context: A Pragmatic Approach}, +year = {2023}, +isbn = {9798400703805}, publisher = {Association for Computing Machinery}, address = {New York, NY, USA}, -url = {https://doi.org/10.1145/3486606.3486781}, -doi = {10.1145/3486606.3486781}, -booktitle = {Proceedings of the 13th ACM SIGPLAN International Workshop on Virtual Machines and Intermediate Languages}, -pages = {25–32}, -numpages = {8}, -keywords = {ruby, dynamically typed, compiler, optimization, just-in-time, bytecode}, -location = {Chicago, IL, USA}, -series = {VMIL 2021} +url = {https://doi.org/10.1145/3617651.3622982}, +doi = {10.1145/3617651.3622982}, +booktitle = {Proceedings of the 20th ACM SIGPLAN International Conference on Managed Programming Languages and Runtimes}, +pages = {20–33}, +numpages = {14}, +keywords = {dynamically typed, optimization, just-in-time, virtual machine, ruby, compiler, bytecode}, +location = {Cascais, Portugal}, +series = {MPLR 2023} } ``` ## Current Limitations -YJIT may not be suitable for certain applications. It currently only supports macOS and Linux on x86-64 and arm64/aarch64 CPUs. YJIT will use more memory than the Ruby interpreter because the JIT compiler needs to generate machine code in memory and maintain additional state information. -You can change how much executable memory is allocated using [YJIT's command-line options](#command-line-options). There is a slight performance tradeoff because allocating less executable memory could result in the generated machine code being collected more often. +YJIT may not be suitable for certain applications. It currently only supports macOS, Linux and BSD on x86-64 and arm64/aarch64 CPUs. YJIT will use more memory than the Ruby interpreter because the JIT compiler needs to generate machine code in memory and maintain additional state information. +You can change how much executable memory is allocated using [YJIT's command-line options](#command-line-options). ## Installation ### Requirements You will need to install: -- A C compiler such as GCC or Clang -- GNU Make and Autoconf -- The Rust compiler `rustc` and Cargo (if you want to build in dev/debug mode) - - The Rust version must be [>= 1.58.0](../../yjit/Cargo.toml). -To install the Rust build toolchain, we suggest following the [recommended installation method][rust-install]. Rust also provides first class [support][editor-tools] for many source code editors. + - All the usual build tools for Ruby. See [Building Ruby](../contributing/building_ruby.md) + - The Rust compiler `rustc` + - The Rust version must be [>= 1.58.0](../../yjit/Cargo.toml). + - Optionally, only if you wish to build in dev/debug mode, Rust's `cargo` + +If you don't intend on making code changes to YJIT itself, we recommend +obtaining `rustc` through your OS's package manager since that +likely reuses the same vendor which provides the C toolchain. + +If you will be changing YJIT's Rust code, we suggest using the +[first-party installation method][rust-install] for Rust. Rust also provides +first class [support][editor-tools] for many source code editors. [rust-install]: https://www.rust-lang.org/tools/install [editor-tools]: https://www.rust-lang.org/tools @@ -87,7 +97,7 @@ The YJIT `ruby` binary can be built with either GCC or Clang. It can be built ei # Configure in release mode for maximum performance, build and install ./autogen.sh ./configure --enable-yjit --prefix=$HOME/.rubies/ruby-yjit --disable-install-doc -make -j install +make -j && make install ``` or @@ -96,7 +106,7 @@ or # Configure in lower-performance dev (debug) mode for development, build and install ./autogen.sh ./configure --enable-yjit=dev --prefix=$HOME/.rubies/ruby-yjit --disable-install-doc -make -j install +make -j && make install ``` Dev mode includes extended YJIT statistics, but can be slow. For only statistics you can configure in stats mode: @@ -105,7 +115,7 @@ Dev mode includes extended YJIT statistics, but can be slow. For only statistics # Configure in extended-stats mode without slow runtime checks, build and install ./autogen.sh ./configure --enable-yjit=stats --prefix=$HOME/.rubies/ruby-yjit --disable-install-doc -make -j install +make -j && make install ``` On macOS, you may need to specify where to find some libraries: @@ -117,7 +127,7 @@ brew install openssl libyaml # Configure in dev (debug) mode for development, build and install ./autogen.sh ./configure --enable-yjit=dev --prefix=$HOME/.rubies/ruby-yjit --disable-install-doc --with-opt-dir="$(brew --prefix openssl):$(brew --prefix readline):$(brew --prefix libyaml)" -make -j install +make -j && make install ``` Typically configure will choose the default C compiler. To specify the C compiler, use @@ -157,59 +167,137 @@ You can dump statistics about compilation and execution by running YJIT with the ./miniruby --yjit-stats myscript.rb ``` +You can see what YJIT has compiled by running YJIT with the `--yjit-log` command-line option: + +```sh +./miniruby --yjit-log myscript.rb +``` + The machine code generated for a given method can be printed by adding `puts RubyVM::YJIT.disasm(method(:method_name))` to a Ruby script. Note that no code will be generated if the method is not compiled. -### Command-Line Options +

Command-Line Options

YJIT supports all command-line options supported by upstream CRuby, but also adds a few YJIT-specific options: - `--yjit`: enable YJIT (disabled by default) -- `--yjit-call-threshold=N`: number of calls after which YJIT begins to compile a function (default 30) -- `--yjit-exec-mem-size=N`: size of the executable memory block to allocate, in MiB (default 64 MiB) +- `--yjit-mem-size=N`: soft limit on YJIT memory usage in MiB (default: 128). Tries to limit `code_region_size + yjit_alloc_size` +- `--yjit-exec-mem-size=N`: hard limit on executable memory block in MiB. Limits `code_region_size` +- `--yjit-call-threshold=N`: number of calls after which YJIT begins to compile a function. + It defaults to 30, and it's then increased to 120 when the number of ISEQs in the process reaches 40,000. +- `--yjit-cold-threshold=N`: number of global calls after which an ISEQ is considered cold and not + compiled, lower values mean less code is compiled (default 200K) - `--yjit-stats`: print statistics after the execution of a program (incurs a run-time cost) -- `--yjit-stats=quiet`: gather statistics while running a program but don't print them. Stats are accessible through `RubyVM::YJIT.runtime_stats`. (incurs a run-time cost) -- `--yjit-trace-exits`: produce a Marshal dump of backtraces from specific exits. Automatically enables `--yjit-stats` (must configure and build with `--enable-yjit=stats` to use this) -- `--yjit-max-versions=N`: maximum number of versions to generate per basic block (default 4) -- `--yjit-greedy-versioning`: greedy versioning mode (disabled by default, may increase code size) +- `--yjit-stats=quiet`: gather statistics while running a program but don't print them. Stats are accessible through `RubyVM::YJIT.runtime_stats`. (incurs a run-time cost) +- `--yjit-log[=file|dir]`: log all compilation events to the specified file or directory. If no name is supplied, the last 1024 log entries will be printed to stderr when the application exits. +- `--yjit-log=quiet`: gather a circular buffer of recent YJIT compilations. The compilation log entries are accessible through `RubyVM::YJIT.log` and old entries will be discarded if the buffer is not drained quickly. (incurs a run-time cost) +- `--yjit-disable`: disable YJIT despite other `--yjit*` flags for lazily enabling it with `RubyVM::YJIT.enable` +- `--yjit-code-gc`: enable code GC (disabled by default as of Ruby 3.3). + It will cause all machine code to be discarded when the executable memory size limit is hit, meaning JIT compilation will then start over. + This can allow you to use a lower executable memory size limit, but may cause a slight drop in performance when the limit is hit. +- `--yjit-perf`: enable frame pointers and profiling with the `perf` tool +- `--yjit-trace-exits`: produce a Marshal dump of backtraces from all exits. Automatically enables `--yjit-stats` +- `--yjit-trace-exits=COUNTER`: produce a Marshal dump of backtraces from a counted exit or a fallback. Automatically enables `--yjit-stats` +- `--yjit-trace-exits-sample-rate=N`: trace exit locations only every Nth occurrence. Automatically enables `--yjit-trace-exits` Note that there is also an environment variable `RUBY_YJIT_ENABLE` which can be used to enable YJIT. This can be useful for some deployment scripts where specifying an extra command-line option to Ruby is not practical. -You can verify that YJIT is enabled by checking that `ruby -v --yjit` includes the string `+YJIT`: +You can also enable YJIT at run-time using `RubyVM::YJIT.enable`. This can allow you to enable YJIT after your application is done +booting, which makes it possible to avoid compiling any initialization code. + +You can verify that YJIT is enabled using `RubyVM::YJIT.enabled?` or by checking that `ruby --yjit -v` includes the string `+YJIT`: ```sh -ruby -v --yjit +ruby --yjit -v ruby 3.3.0dev (2023-01-31T15:11:10Z master 2a0bf269c9) +YJIT dev [x86_64-darwin22] + +ruby --yjit -e "p RubyVM::YJIT.enabled?" +true + +ruby -e "RubyVM::YJIT.enable; p RubyVM::YJIT.enabled?" +true ``` ### Benchmarking -We have collected a set of benchmarks and implemented a simple benchmarking harness in the [yjit-bench](https://github.com/Shopify/yjit-bench) repository. This benchmarking harness is designed to disable CPU frequency scaling, set process affinity and disable address space randomization so that the variance between benchmarking runs will be as small as possible. Please kindly note that we are at an early stage in this project. +We have collected a set of benchmarks and implemented a simple benchmarking harness in the [yjit-bench](https://github.com/Shopify/yjit-bench) repository. This benchmarking harness is designed to disable CPU frequency scaling, set process affinity and disable address space randomization so that the variance between benchmarking runs will be as small as possible. + +## Performance Tips for Production Deployments + +While YJIT options default to what we think would work well for most workloads, +they might not necessarily be the best configuration for your application. +This section covers tips on improving YJIT performance in case YJIT does not +speed up your application in production. + +### Increasing --yjit-mem-size -### Performance Tips +The `--yjit-mem-size` value can be used to set the maximum amount of memory that YJIT +is allowed to use. This corresponds to the total of `RubyVM::YJIT.runtime_stats[:code_region_size]` +and `RubyVM::YJIT.runtime_stats[:yjit_alloc_size]` +Increasing the `--yjit-mem-size` value means more code +can be optimized by YJIT, at the cost of more memory usage. + +If you start Ruby with `--yjit-stats`, e.g. using an environment variable `RUBYOPT=--yjit-stats`, +`RubyVM::YJIT.runtime_stats[:ratio_in_yjit]` shows the percentage of total YARV instructions +executed by YJIT as opposed to the CRuby interpreter. +Ideally, `ratio_in_yjit` should be as large as 99%, and increasing `--yjit-mem-size` often +helps improving `ratio_in_yjit`. + +### Running workers as long as possible + +It's helpful to call the same code as many times as possible before a process restarts. +If a process is killed too frequently, the time taken for compiling methods may outweigh +the speedup obtained by compiling them. + +You should monitor the number of requests each process has served. +If you're periodically killing worker processes, e.g. with `unicorn-worker-killer` or `puma_worker_killer`, +you may want to reduce the killing frequency or increase the limit. + +## Reducing YJIT Memory Usage + +YJIT allocates memory for JIT code and metadata. Enabling YJIT generally results in more memory usage. +This section goes over tips on minimizing YJIT memory usage in case it uses more than your capacity. + +### Decreasing --yjit-mem-size + +YJIT uses memory for compiled code and metadata. You can change the maximum amount of memory +that YJIT can use by specifying a different `--yjit-mem-size` command-line option. The default value +is currently `128`. +When changing this value, you may want to monitor `RubyVM::YJIT.runtime_stats[:ratio_in_yjit]` +as explained above. + +### Enabling YJIT lazily + +If you enable YJIT by `--yjit` options or `RUBY_YJIT_ENABLE=1`, YJIT may compile code that is +used only during the application boot. `RubyVM::YJIT.enable` allows you to enable YJIT from Ruby code, +and you can call this after your application is initialized, e.g. on Unicorn's `after_fork` hook. +If you use any YJIT options (`--yjit-*`), YJIT will start at boot by default, but `--yjit-disable` +allows you to start Ruby with the YJIT-disabled mode while passing YJIT tuning options. + +## Code Optimization Tips This section contains tips on writing Ruby code that will run as fast as possible on YJIT. Some of this advice is based on current limitations of YJIT, while other advice is broadly applicable. It probably won't be practical to apply these tips everywhere in your codebase. You should ideally start by profiling your application using a tool such as [stackprof](https://github.com/tmm1/stackprof) so that you can determine which methods make up most of the execution time. You can then refactor the specific methods that make up the largest fractions of the execution time. We do not recommend modifying your entire codebase based on the current limitations of YJIT. -- Use exceptions for error recovery only, not as part of normal control-flow +- Avoid using `OpenStruct` - Avoid redefining basic integer operations (i.e. +, -, <, >, etc.) - Avoid redefining the meaning of `nil`, equality, etc. - Avoid allocating objects in the hot parts of your code - Minimize layers of indirection - - Avoid classes that wrap objects if you can - - Avoid methods that just call another method, trivial one liner methods -- Try to write code so that the same variables always have the same type -- Use while loops if you can, instead of `integer.times` - - This is not idiomatic Ruby, but could help in hot methods -- CRuby method calls are costly. Avoid things such as methods that only return a value from a hash or return a constant. + - Avoid writing wrapper classes if you can (e.g. a class that only wraps a Ruby hash) + - Avoid methods that just call another method +- Ruby method calls are costly. Avoid things such as methods that only return a value from a hash +- Try to write code so that the same variables and method arguments always have the same type +- Avoid using `TracePoint` as it can cause YJIT to deoptimize code +- Avoid using `binding` as it can cause YJIT to deoptimize code You can also use the `--yjit-stats` command-line option to see which bytecodes cause YJIT to exit, and refactor your code to avoid using these instructions in the hottest methods of your code. ### Other Statistics -If you run `ruby` with `--yjit --yjit-stats`, YJIT will track and return performance statistics in `RubyVM::YJIT.runtime_stats`. +If you run `ruby` with `--yjit-stats`, YJIT will track and return performance statistics in `RubyVM::YJIT.runtime_stats`. ```rb -$ RUBYOPT="--yjit --yjit-stats" irb +$ RUBYOPT="--yjit-stats" irb irb(main):001:0> RubyVM::YJIT.runtime_stats => {:inline_code_size=>340745, @@ -224,41 +312,43 @@ irb(main):001:0> RubyVM::YJIT.runtime_stats Some of the counters include: -* :yjit_insns_count - how many Ruby bytecode instructions have been executed -* :binding_allocations - number of bindings allocated -* :binding_set - number of variables set via a binding -* :code_gc_count - number of garbage collections of compiled code since process start -* :vm_insns_count - number of instructions executed by the Ruby interpreter -* :compiled_iseq_count - number of bytecode sequences compiled -* :inline_code_size - size in bytes of compiled YJIT blocks -* :outline_code_size - size in bytes of YJIT error-handling compiled code -* :side_exit_count - number of side exits taken at runtime -* :total_exit_count - number of exits, including side exits, taken at runtime -* :avg_len_in_yjit - avg. number of instructions in compiled blocks before exiting to interpreter +* `:yjit_insns_count` - how many Ruby bytecode instructions have been executed +* `:binding_allocations` - number of bindings allocated +* `:binding_set` - number of variables set via a binding +* `:code_gc_count` - number of garbage collections of compiled code since process start +* `:vm_insns_count` - number of instructions executed by the Ruby interpreter +* `:compiled_iseq_count` - number of bytecode sequences compiled +* `:inline_code_size` - size in bytes of compiled YJIT blocks +* `:outline_code_size` - size in bytes of YJIT error-handling compiled code +* `:side_exit_count` - number of side exits taken at runtime +* `:total_exit_count` - number of exits, including side exits, taken at runtime +* `:avg_len_in_yjit` - avg. number of instructions in compiled blocks before exiting to interpreter -Counters starting with "exit_" show reasons for YJIT code taking a side exit (return to the interpreter.) See yjit_hacking.md for more details. +Counters starting with "exit_" show reasons for YJIT code taking a side exit (return to the interpreter.) -Performance counter names are not guaranteed to remain the same between Ruby versions. If you're curious what one does, it's usually best to search the source code for it — but it may change in a later Ruby version. +Performance counter names are not guaranteed to remain the same between Ruby versions. If you're curious what each counter means, +it's usually best to search the source code for it — but it may change in a later Ruby version. -The printed text after a --yjit-stats run includes other information that may be named differently than the information in runtime_stats. +The printed text after a `--yjit-stats` run includes other information that may be named differently than the information in `RubyVM::YJIT.runtime_stats`. ## Contributing -We welcome open source contributors. You should feel free to open new issues to report bugs or just to ask questions. +We welcome open source contributions. You should feel free to open new issues to report bugs or just to ask questions. Suggestions on how to make this readme file more helpful for new contributors are most welcome. Bug fixes and bug reports are very valuable to us. If you find a bug in YJIT, it's very possible be that nobody has reported it before, or that we don't have a good reproduction for it, so please open an issue and provide as much information as you can about your configuration and a description of how you encountered the problem. List the commands you used to run YJIT so that we can easily reproduce the issue on our end and investigate it. If you are able to produce a small program reproducing the error to help us track it down, that is very much appreciated as well. -If you would like to contribute a large patch to YJIT, we suggest opening an issue or a discussion on this repository so that +If you would like to contribute a large patch to YJIT, we suggest opening an issue or a discussion on the [Shopify/ruby repository](https://github.com/Shopify/ruby/issues) so that we can have an active discussion. A common problem is that sometimes people submit large pull requests to open source projects without prior communication, and we have to reject them because the work they implemented does not fit within the design of the -project. We want to save you time and frustration, so please reach out and we can have a productive discussion as to how -you can contribute things we will want to merge into YJIT. +project. We want to save you time and frustration, so please reach out so we can have a productive discussion as to how +you can contribute patches we will want to merge into YJIT. ### Source Code Organization The YJIT source code is divided between: + - `yjit.c`: code YJIT uses to interface with the rest of CRuby - `yjit.h`: C definitions YJIT exposes to the rest of the CRuby - `yjit.rb`: `YJIT` Ruby module that is exposed to Ruby @@ -267,10 +357,11 @@ The YJIT source code is divided between: - `yjit/src/core.rb`: basic block versioning logic, core structure of YJIT - `yjit/src/stats.rs`: gathering of run-time statistics - `yjit/src/options.rs`: handling of command-line options -- `yjit/bindgen/src/main.rs`: C bindings exposed to the Rust codebase through bindgen - `yjit/src/cruby.rs`: C bindings manually exposed to the Rust codebase +- `yjit/bindgen/src/main.rs`: C bindings exposed to the Rust codebase through bindgen The core of CRuby's interpreter logic is found in: + - `insns.def`: defines Ruby's bytecode instructions (gets compiled into `vm.inc`) - `vm_insnshelper.c`: logic used by Ruby's bytecode instructions - `vm_exec.c`: Ruby interpreter loop @@ -292,6 +383,7 @@ add them to `yjit/cruby.rs` instead. ### Coding & Debugging Protips There are multiple test suites: + - `make btest` (see `/bootstraptest`) - `make test-all` - `make test-spec` @@ -310,12 +402,18 @@ Or single-threaded like this, to more easily identify which specific test is fai make test-all TESTOPTS=--verbose RUN_OPTS="--yjit-call-threshold=1" ``` -To debug a single test in `test-all`: +To run a single test file with `test-all`: ```sh make test-all TESTS='test/-ext-/marshal/test_usrmarshal.rb' RUNRUBYOPT=--debugger=lldb RUN_OPTS="--yjit-call-threshold=1" ``` +It's also possible to filter tests by name to run a single test: + +```sh +make test-all TESTS='-n /test_float_plus/' RUN_OPTS="--yjit-call-threshold=1" +``` + You can also run one specific test in `btest`: ```sh @@ -342,7 +440,7 @@ instructions below, but there are a few caveats listed further down. First, install Rosetta: -```sh +```console $ softwareupdate --install-rosetta ``` @@ -350,13 +448,13 @@ Now any command can be run with Rosetta via the `arch` command line tool. Then you can start your shell in an x86 environment: -```sh +```console $ arch -x86_64 zsh ``` You can double check your current architecture via the `arch` command: -```sh +```console $ arch -x86_64 zsh $ arch i386 @@ -364,7 +462,7 @@ i386 You may need to set the default target for `rustc` to x86-64, e.g. -```sh +```console $ rustup default stable-x86_64-apple-darwin ``` @@ -376,3 +474,71 @@ While in your i386 shell, install Cargo and Homebrew, then hack away! 2. Cargo will install in $HOME/.cargo by default, and I don't know a good way to change architectures after install If you use Fish shell you can [read this link](https://tenderlovemaking.com/2022/01/07/homebrew-rosetta-and-ruby.html) for information on making the dev environment easier. + +## Profiling with Linux perf + +`--yjit-perf` allows you to profile JIT-ed methods along with other native functions using Linux perf. +When you run Ruby with `perf record`, perf looks up `/tmp/perf-{pid}.map` to resolve symbols in JIT code, +and this option lets YJIT write method symbols into that file as well as enabling frame pointers. + +### Call graph + +Here's an example way to use this option with [Firefox Profiler](https://profiler.firefox.com) +(See also: [Profiling with Linux perf](https://profiler.firefox.com/docs/#/./guide-perf-profiling)): + +```bash +# Compile the interpreter with frame pointers enabled +./configure --enable-yjit --prefix=$HOME/.rubies/ruby-yjit --disable-install-doc cflags=-fno-omit-frame-pointer +make -j && make install + +# [Optional] Allow running perf without sudo +echo 0 | sudo tee /proc/sys/kernel/kptr_restrict +echo -1 | sudo tee /proc/sys/kernel/perf_event_paranoid + +# Profile Ruby with --yjit-perf +cd ../yjit-bench +PERF="record --call-graph fp" ruby --yjit-perf -Iharness-perf benchmarks/liquid-render/benchmark.rb + +# View results on Firefox Profiler https://profiler.firefox.com. +# Create /tmp/test.perf as below and upload it using "Load a profile from file". +perf script --fields +pid > /tmp/test.perf +``` + +### YJIT codegen + +You can also profile the number of cycles consumed by code generated by each YJIT function. + +```bash +# Install perf +apt-get install linux-tools-common linux-tools-generic linux-tools-`uname -r` + +# [Optional] Allow running perf without sudo +echo 0 | sudo tee /proc/sys/kernel/kptr_restrict +echo -1 | sudo tee /proc/sys/kernel/perf_event_paranoid + +# Profile Ruby with --yjit-perf=codegen +cd ../yjit-bench +PERF=record ruby --yjit-perf=codegen -Iharness-perf benchmarks/lobsters/benchmark.rb + +# Aggregate results +perf script > /tmp/perf.txt +../ruby/misc/yjit_perf.py /tmp/perf.txt +``` + +#### Building perf with Python support + +The above instructions work fine for most people, but you could also use +a handy `perf script -s` interface if you build perf from source. + +```bash +# Build perf from source for Python support +sudo apt-get install libpython3-dev python3-pip flex libtraceevent-dev \ + libelf-dev libunwind-dev libaudit-dev libslang2-dev libdw-dev +git clone --depth=1 https://github.com/torvalds/linux +cd linux/tools/perf +make +make install + +# Aggregate results +perf script -s ../ruby/misc/yjit_perf.py +``` diff --git a/doc/yjit/yjit_hacking.md b/doc/yjit/yjit_hacking.md deleted file mode 100644 index 4c4d742b73e13a..00000000000000 --- a/doc/yjit/yjit_hacking.md +++ /dev/null @@ -1,75 +0,0 @@ -# YJIT Hacking - -## Code Generation and Assembly Language - -YJIT’s basic purpose is to take ISEQs and generate machine code. - -Documentation on each Ruby bytecode can be found in insns.def. - -YJIT uses those bytecodes as the “Basic Blocks” in Lazy Basic Block Versioning (LBBV.) For more deep details of LBBV, see yjit.md in this directory. - -Current YJIT has a simple assembler as a backend. Each method that generates code does it by emitting machine code: - -``` -# Excerpt of yjit_gen_exit() from yjit_codegen.c, Sept 2021 -// Generate an exit to return to the interpreter -static uint32_t -yjit_gen_exit(VALUE *exit_pc, ctx_t *ctx, codeblock_t *cb) -{ - const uint32_t code_pos = cb->write_pos; - - ADD_COMMENT(cb, "exit to interpreter"); - - // Generate the code to exit to the interpreters - // Write the adjusted SP back into the CFP - if (ctx->sp_offset != 0) { - x86opnd_t stack_pointer = ctx_sp_opnd(ctx, 0); - lea(cb, REG_SP, stack_pointer); - mov(cb, member_opnd(REG_CFP, rb_control_frame_t, sp), REG_SP); - } - - // Update CFP->PC - mov(cb, RAX, const_ptr_opnd(exit_pc)); - mov(cb, member_opnd(REG_CFP, rb_control_frame_t, pc), RAX); -``` - -Later there will be a more complex backend. - -## Code Generation vs Code Execution - -When you see lea() call above (“load effective address,”) it’s not running the LEA x86 instruction. It’s generating an LEA instruction to the codeblock pointer in the first argument. It will execute that instruction later, when the codeblock gets executed. - -This is subtle because YJIT will often wait to compile the method until you’re about to run it -- that’s when it knows the most about what types of arguments the method will receive. So it’s a compile-time instruction, but often it will defer compile-time until just barely before runtime. - -The ctx structure tracks what is known at compile time about the arguments being passed into the Ruby bytecode. Often YJIT will “peek” at an expected type before it generates machine code. - -## Inlined and Outlined Code - -When YJIT is generating code, it needs a code pointer. In many cases it needs two, usually called “cb” (codeblock) and “ocb” (out-of-line codeblock.) - -cb is for “inlined” normal code and ocb is for “outline” code such as exits. Inlined code is normal generated code for Ruby operations, while outlined code is for unusual and error conditions, such as encountering an unexpected parameter type and exiting to the interpreter. - -The purpose of the outlined code block is to keep things we believe are going to be infrequent somewhere else. That way we can keep the code in the inline block more linear and compact. Linear code, with as few branches as possible, is more easily predicted by the CPU. An exception or unsupported operation will cause YJIT to generate outlined code to handle it. - -If you search for ocb in yjit_codegen.c, you can see some places where out-of-line code is generated. - -YJIT statistics are only gathered when RUBY_DEBUG or YJIT_STATS is true. In some cases the code to increment YJIT statistics will be generated out-of-line, especially if those statistics are gathered when a side exit happens. - -## Statistics and Comments - -When RUBY_DEBUG is defined to a true value, YJIT will emit comments into the generated machine code. This can make disassemblies a lot more readable. When RUBY_DEBUG or YJIT_STATS is defined and stats are active (--yjit-stats or export YJIT_STATS=1), code will be generated to collect statistics during the run, and a report will be printed when the process exits. - -## Entering and Exiting the Interpreter - -YJIT won’t generate machine code for an ISEQ until it’s been run a certain number of times (10 by default.) Then, the next time the interpreter would call that ISEQ, it will call the generated machine code version instead. If YJIT hits an unexpected or unsupported operation, it will return to the normal interpreter. - -If YJIT returns to the interpreter, the behaviour will be correct but slower. YJIT only optimises part of some operations - for instance, YJIT will not optimise a BMETHOD call yet. - -When the interpreter calls to a YJIT-optimised method again, control will return to YJIT’s generated machine code. The more time that’s spent in YJIT-generated code (“ratio in YJIT,”) the more CPU time YJIT can save with its optimisations. - -## Side Exits - -When YJIT has compiled an ISEQ and is running it later, sometimes it will hit an unexpected condition. It might see a parameter of a different type than before, or square-brackets might be used on a hash when they were first used on an array. In those cases, the generated code will contain a call to return to the interpreter at runtime, called a “side exit.” - -Side exits are generated as out-of-line code. - diff --git a/doc/zjit.md b/doc/zjit.md new file mode 100644 index 00000000000000..f337487af88764 --- /dev/null +++ b/doc/zjit.md @@ -0,0 +1,123 @@ +# ZJIT: ADVANCED RUBY JIT PROTOTYPE + +## Build Instructions + +To build ZJIT on macOS: +``` +./autogen.sh +./configure --enable-zjit=dev --prefix=$HOME/.rubies/ruby-zjit --disable-install-doc --with-opt-dir="$(brew --prefix openssl):$(brew --prefix readline):$(brew --prefix libyaml)" +make -j miniruby +``` + +## Useful dev commands + +To view YARV output for code snippets: +``` +./miniruby --dump=insns -e0 +``` + +To run code snippets with ZJIT: +``` +./miniruby --zjit -e0 +``` + +You can also try https://www.rubyexplorer.xyz/ to view Ruby YARV disasm output with syntax highlighting +in a way that can be easily shared with other team members. + +## Testing + +Make sure you have a `--enable-zjit=dev` build, and run `brew install cargo-nextest` first. + +### make zjit-test-all + +This command runs all ZJIT tests: `make zjit-test` and `test/ruby/test_zjit.rb`. + +``` +make zjit-test-all +``` + +### make zjit-test + +This command runs Rust unit tests. + +``` +make zjit-test +``` + +You can also run a single test case by specifying the function name: + +``` +make zjit-test ZJIT_TESTS=test_putobject +``` + +If you expect that your changes cause tests to fail and they do, you can have +`expect-test` fix the expected value for you by putting `UPDATE_EXPECT=1` +before your test command, like so: + +``` +UPDATE_EXPECT=1 make zjit-test ZJIT_TESTS=test_putobject +``` + +Test changes will be reviewed alongside code changes. + +
+ +Setting up zjit-test + +ZJIT uses `cargo-nextest` for Rust unit tests instead of `cargo test`. +`cargo-nextest` runs each test in its own process, which is valuable since +CRuby only supports booting once per process, and most APIs are not thread +safe. Use `brew install cargo-nextest` to install it on macOS, otherwise, refer +to for installation +instructions. + +Since it uses Cargo, you'll also need a `configure --enable-zjit=dev ...` build +for `make zjit-test`. Since the tests need to link against CRuby, directly +calling `cargo test`, or `cargo nextest` likely won't build. Make sure to +use `make`. + +
+ +### test/ruby/test\_zjit.rb + +This command runs Ruby execution tests. + +``` +make test-all TESTS="test/ruby/test_zjit.rb" +``` + +You can also run a single test case by matching the method name: + +``` +make test-all TESTS="test/ruby/test_zjit.rb -n TestZJIT#test_putobject" +``` + +## ZJIT Glossary + +This glossary contains terms that are helpful for understanding ZJIT. + +Please note that some terms may appear in CRuby internals too but with different meanings. + +| Term | Definition | +| --- | -----------| +| HIR | High-level Intermediate Representation. High-level (Ruby semantics) graph representation in static single-assignment (SSA) form | +| LIR | Low-level Intermediate Representation. Low-level IR used in the backend for assembly generation | +| SSA | Static Single Assignment. A form where each variable is assigned exactly once | +| `opnd` | Operand. An operand to an IR instruction (can be register, memory, immediate, etc.) | +| `dst` | Destination. The output operand of an instruction where the result is stored | +| VReg | Virtual Register. A virtual register that gets lowered to physical register or memory | +| `insn_id` | Instruction ID. An index of an instruction in a function | +| `block_id` | The index of a basic block, which effectively acts like a pointer | +| `branch` | Control flow edge between basic blocks in the compiled code | +| `cb` | Code Block. Memory region for generated machine code | +| `entry` | The starting address of compiled code for an ISEQ | +| Patch Point | Location in generated code that can be modified later in case assumptions get invalidated | +| Frame State | Captured state of the Ruby stack frame at a specific point for deoptimization | +| Guard | A run-time check that ensures assumptions are still valid | +| `invariant` | An assumption that JIT code relies on, requiring invalidation if broken | +| Deopt | Deoptimization. Process of falling back from JIT code to interpreter | +| Side Exit | Exit from JIT code back to interpreter | +| Type Lattice | Hierarchy of types used for type inference and optimization | +| Constant Folding | Optimization that evaluates constant expressions at compile time | +| RSP | x86-64 stack pointer register used for native stack operations | +| Register Spilling | Process of moving register values to memory when running out of physical registers | diff --git a/enc/Makefile.in b/enc/Makefile.in index dd8ca1b5281aad..ce93fdd22d2350 100644 --- a/enc/Makefile.in +++ b/enc/Makefile.in @@ -40,6 +40,7 @@ BUILTRUBY = $(topdir)/miniruby$(EXEEXT) empty = AR = @AR@ +LD = @LD@ CC = @CC@ ARFLAGS = @ARFLAGS@$(empty) RANLIB = @RANLIB@ @@ -51,11 +52,12 @@ optflags = @optflags@ debugflags = @debugflags@ warnflags = @warnflags@ CCDLFLAGS = @CCDLFLAGS@ -INCFLAGS = -I. -I$(arch_hdrdir) -I$(hdrdir) -I$(top_srcdir) +INCFLAGS = -I. -I$(arch_hdrdir) -I$(hdrdir) -I$(top_srcdir) @incflags@ DEFS = @DEFS@ CPPFLAGS = @CPPFLAGS@ -DONIG_ENC_REGISTER=rb_enc_register LDFLAGS = @LDFLAGS@ LDSHARED = @LDSHARED@ +POSTLINK = @POSTLINK@ ldflags = $(LDFLAGS) dldflags = @DLDFLAGS@ extdldflags = @EXTDLDFLAGS@ @@ -70,6 +72,7 @@ WORKDIRS = @WORKDIRS@ NULLCMD = @NULLCMD@ RM = @RM@ +RMALL = @RMALL@ RMDIR = @RMDIR@ RMDIRS = @RMDIRS@ MAKEDIRS = @MAKEDIRS@ @@ -81,6 +84,9 @@ all: make-workdir: $(Q)$(MAKEDIRS) $(WORKDIRS) +.PHONY: encs all modencs libencs enc libenc trans libtrans srcs +.PHONY: clean distclean realclean clean-srcs + clean: distclean: clean diff --git a/enc/depend b/enc/depend index 47a20e957acdb5..a458b63887e858 100644 --- a/enc/depend +++ b/enc/depend @@ -35,6 +35,7 @@ ENCSOS =<%ENCS.map {|e|%> $(ENCSODIR)/<%=e%>.$(DLEXT) \ <%}%> # ENCCLEANLIBS = <%=cleanlibs.map {|clean| clean.gsub(/\$\*(\.\w+)?/) {"$(ENCOBJS#{$1 ? ":.#{CONFIG["OBJEXT"]}=#{$1}" : ""})"} + .gsub(/\$\(\KTARGET_SO(?=[:\)])/) {"ENCSOS"} }.join(" ")%> ENCCLEANOBJS = <%=cleanobjs.map {|clean| clean.gsub(/\$\*(\.\w+)?/) {"$(ENCOBJS#{$1 ? ":.#{CONFIG["OBJEXT"]}=#{$1}" : ""})"} @@ -51,6 +52,7 @@ TRANSSOS =<%TRANS.map {|e|%> $(ENCSODIR)/<%=e%>.$(DLEXT) \ <%}%> # TRANSCLEANLIBS = <%=cleanlibs.map {|clean| clean.gsub(/\$\*(\.\w+)?/) {"$(TRANSOBJS#{$1 ? ":.#{CONFIG["OBJEXT"]}=#{$1}" : ""})"} + .gsub(/\$\(\KTARGET_SO(?=[:\)])/) {"TRANSSOS"} }.join(" ")%> TRANSCLEANOBJS = <%=cleanobjs.map {|clean| clean.gsub(/\$\*(\.\w+)?/) {"$(TRANSOBJS#{$1 ? ":.#{CONFIG["OBJEXT"]}=#{$1}" : ""})"} @@ -58,12 +60,8 @@ TRANSCLEANOBJS = <%=cleanobjs.map {|clean| LIBTRANS=enc/libtrans.$(LIBEXT) UNICODE_HDR_DIR = --missing-unicode-header-dir-- -encs: all -% if MODULE_TYPE == :static -all: libenc libtrans -% else -all: enc trans -%end +encs all: <%= MODULE_TYPE == :static ? "lib" : "mod" %>encs +modencs: enc trans libencs: libenc libtrans enc: $(ENCSOS) libenc: $(LIBENC) @@ -155,7 +153,7 @@ enc/trans/transdb.$(OBJEXT): transdb.h clean: % %w[$(ENCSOS) $(LIBENC) $(ENCOBJS) $(ENCCLEANOBJS) $(ENCCLEANLIBS) $(TRANSSOS) $(LIBTRANS) $(TRANSOBJS) $(TRANSCLEANOBJS) $(TRANSCLEANLIBS) $(ENC_TRANS_D) $(ENC_TRANS_SO_D)].each do |clean| - $(Q)$(RM) <%=pathrep[clean]%> + $(Q)$(RMALL) <%=pathrep[clean]%> % end % unless inplace $(Q)$(RM) enc/unicode/*/casefold.h enc/unicode/*/name2ctype.h @@ -319,6 +317,7 @@ enc/ascii.$(OBJEXT): internal/intern/re.h enc/ascii.$(OBJEXT): internal/intern/ruby.h enc/ascii.$(OBJEXT): internal/intern/select.h enc/ascii.$(OBJEXT): internal/intern/select/largesize.h +enc/ascii.$(OBJEXT): internal/intern/set.h enc/ascii.$(OBJEXT): internal/intern/signal.h enc/ascii.$(OBJEXT): internal/intern/sprintf.h enc/ascii.$(OBJEXT): internal/intern/string.h @@ -338,6 +337,7 @@ enc/ascii.$(OBJEXT): internal/special_consts.h enc/ascii.$(OBJEXT): internal/static_assert.h enc/ascii.$(OBJEXT): internal/stdalign.h enc/ascii.$(OBJEXT): internal/stdbool.h +enc/ascii.$(OBJEXT): internal/stdckdint.h enc/ascii.$(OBJEXT): internal/symbol.h enc/ascii.$(OBJEXT): internal/value.h enc/ascii.$(OBJEXT): internal/value_type.h @@ -480,6 +480,7 @@ enc/big5.$(OBJEXT): internal/intern/re.h enc/big5.$(OBJEXT): internal/intern/ruby.h enc/big5.$(OBJEXT): internal/intern/select.h enc/big5.$(OBJEXT): internal/intern/select/largesize.h +enc/big5.$(OBJEXT): internal/intern/set.h enc/big5.$(OBJEXT): internal/intern/signal.h enc/big5.$(OBJEXT): internal/intern/sprintf.h enc/big5.$(OBJEXT): internal/intern/string.h @@ -499,6 +500,7 @@ enc/big5.$(OBJEXT): internal/special_consts.h enc/big5.$(OBJEXT): internal/static_assert.h enc/big5.$(OBJEXT): internal/stdalign.h enc/big5.$(OBJEXT): internal/stdbool.h +enc/big5.$(OBJEXT): internal/stdckdint.h enc/big5.$(OBJEXT): internal/symbol.h enc/big5.$(OBJEXT): internal/value.h enc/big5.$(OBJEXT): internal/value_type.h @@ -651,6 +653,7 @@ enc/cesu_8.$(OBJEXT): internal/intern/re.h enc/cesu_8.$(OBJEXT): internal/intern/ruby.h enc/cesu_8.$(OBJEXT): internal/intern/select.h enc/cesu_8.$(OBJEXT): internal/intern/select/largesize.h +enc/cesu_8.$(OBJEXT): internal/intern/set.h enc/cesu_8.$(OBJEXT): internal/intern/signal.h enc/cesu_8.$(OBJEXT): internal/intern/sprintf.h enc/cesu_8.$(OBJEXT): internal/intern/string.h @@ -670,6 +673,7 @@ enc/cesu_8.$(OBJEXT): internal/special_consts.h enc/cesu_8.$(OBJEXT): internal/static_assert.h enc/cesu_8.$(OBJEXT): internal/stdalign.h enc/cesu_8.$(OBJEXT): internal/stdbool.h +enc/cesu_8.$(OBJEXT): internal/stdckdint.h enc/cesu_8.$(OBJEXT): internal/symbol.h enc/cesu_8.$(OBJEXT): internal/value.h enc/cesu_8.$(OBJEXT): internal/value_type.h @@ -812,6 +816,7 @@ enc/cp949.$(OBJEXT): internal/intern/re.h enc/cp949.$(OBJEXT): internal/intern/ruby.h enc/cp949.$(OBJEXT): internal/intern/select.h enc/cp949.$(OBJEXT): internal/intern/select/largesize.h +enc/cp949.$(OBJEXT): internal/intern/set.h enc/cp949.$(OBJEXT): internal/intern/signal.h enc/cp949.$(OBJEXT): internal/intern/sprintf.h enc/cp949.$(OBJEXT): internal/intern/string.h @@ -831,6 +836,7 @@ enc/cp949.$(OBJEXT): internal/special_consts.h enc/cp949.$(OBJEXT): internal/static_assert.h enc/cp949.$(OBJEXT): internal/stdalign.h enc/cp949.$(OBJEXT): internal/stdbool.h +enc/cp949.$(OBJEXT): internal/stdckdint.h enc/cp949.$(OBJEXT): internal/symbol.h enc/cp949.$(OBJEXT): internal/value.h enc/cp949.$(OBJEXT): internal/value_type.h @@ -972,6 +978,7 @@ enc/emacs_mule.$(OBJEXT): internal/intern/re.h enc/emacs_mule.$(OBJEXT): internal/intern/ruby.h enc/emacs_mule.$(OBJEXT): internal/intern/select.h enc/emacs_mule.$(OBJEXT): internal/intern/select/largesize.h +enc/emacs_mule.$(OBJEXT): internal/intern/set.h enc/emacs_mule.$(OBJEXT): internal/intern/signal.h enc/emacs_mule.$(OBJEXT): internal/intern/sprintf.h enc/emacs_mule.$(OBJEXT): internal/intern/string.h @@ -991,6 +998,7 @@ enc/emacs_mule.$(OBJEXT): internal/special_consts.h enc/emacs_mule.$(OBJEXT): internal/static_assert.h enc/emacs_mule.$(OBJEXT): internal/stdalign.h enc/emacs_mule.$(OBJEXT): internal/stdbool.h +enc/emacs_mule.$(OBJEXT): internal/stdckdint.h enc/emacs_mule.$(OBJEXT): internal/symbol.h enc/emacs_mule.$(OBJEXT): internal/value.h enc/emacs_mule.$(OBJEXT): internal/value_type.h @@ -1142,6 +1150,7 @@ enc/encdb.$(OBJEXT): internal/intern/re.h enc/encdb.$(OBJEXT): internal/intern/ruby.h enc/encdb.$(OBJEXT): internal/intern/select.h enc/encdb.$(OBJEXT): internal/intern/select/largesize.h +enc/encdb.$(OBJEXT): internal/intern/set.h enc/encdb.$(OBJEXT): internal/intern/signal.h enc/encdb.$(OBJEXT): internal/intern/sprintf.h enc/encdb.$(OBJEXT): internal/intern/string.h @@ -1161,6 +1170,7 @@ enc/encdb.$(OBJEXT): internal/special_consts.h enc/encdb.$(OBJEXT): internal/static_assert.h enc/encdb.$(OBJEXT): internal/stdalign.h enc/encdb.$(OBJEXT): internal/stdbool.h +enc/encdb.$(OBJEXT): internal/stdckdint.h enc/encdb.$(OBJEXT): internal/symbol.h enc/encdb.$(OBJEXT): internal/value.h enc/encdb.$(OBJEXT): internal/value_type.h @@ -1305,6 +1315,7 @@ enc/euc_jp.$(OBJEXT): internal/intern/re.h enc/euc_jp.$(OBJEXT): internal/intern/ruby.h enc/euc_jp.$(OBJEXT): internal/intern/select.h enc/euc_jp.$(OBJEXT): internal/intern/select/largesize.h +enc/euc_jp.$(OBJEXT): internal/intern/set.h enc/euc_jp.$(OBJEXT): internal/intern/signal.h enc/euc_jp.$(OBJEXT): internal/intern/sprintf.h enc/euc_jp.$(OBJEXT): internal/intern/string.h @@ -1324,6 +1335,7 @@ enc/euc_jp.$(OBJEXT): internal/special_consts.h enc/euc_jp.$(OBJEXT): internal/static_assert.h enc/euc_jp.$(OBJEXT): internal/stdalign.h enc/euc_jp.$(OBJEXT): internal/stdbool.h +enc/euc_jp.$(OBJEXT): internal/stdckdint.h enc/euc_jp.$(OBJEXT): internal/symbol.h enc/euc_jp.$(OBJEXT): internal/value.h enc/euc_jp.$(OBJEXT): internal/value_type.h @@ -1465,6 +1477,7 @@ enc/euc_kr.$(OBJEXT): internal/intern/re.h enc/euc_kr.$(OBJEXT): internal/intern/ruby.h enc/euc_kr.$(OBJEXT): internal/intern/select.h enc/euc_kr.$(OBJEXT): internal/intern/select/largesize.h +enc/euc_kr.$(OBJEXT): internal/intern/set.h enc/euc_kr.$(OBJEXT): internal/intern/signal.h enc/euc_kr.$(OBJEXT): internal/intern/sprintf.h enc/euc_kr.$(OBJEXT): internal/intern/string.h @@ -1484,6 +1497,7 @@ enc/euc_kr.$(OBJEXT): internal/special_consts.h enc/euc_kr.$(OBJEXT): internal/static_assert.h enc/euc_kr.$(OBJEXT): internal/stdalign.h enc/euc_kr.$(OBJEXT): internal/stdbool.h +enc/euc_kr.$(OBJEXT): internal/stdckdint.h enc/euc_kr.$(OBJEXT): internal/symbol.h enc/euc_kr.$(OBJEXT): internal/value.h enc/euc_kr.$(OBJEXT): internal/value_type.h @@ -1625,6 +1639,7 @@ enc/euc_tw.$(OBJEXT): internal/intern/re.h enc/euc_tw.$(OBJEXT): internal/intern/ruby.h enc/euc_tw.$(OBJEXT): internal/intern/select.h enc/euc_tw.$(OBJEXT): internal/intern/select/largesize.h +enc/euc_tw.$(OBJEXT): internal/intern/set.h enc/euc_tw.$(OBJEXT): internal/intern/signal.h enc/euc_tw.$(OBJEXT): internal/intern/sprintf.h enc/euc_tw.$(OBJEXT): internal/intern/string.h @@ -1644,6 +1659,7 @@ enc/euc_tw.$(OBJEXT): internal/special_consts.h enc/euc_tw.$(OBJEXT): internal/static_assert.h enc/euc_tw.$(OBJEXT): internal/stdalign.h enc/euc_tw.$(OBJEXT): internal/stdbool.h +enc/euc_tw.$(OBJEXT): internal/stdckdint.h enc/euc_tw.$(OBJEXT): internal/symbol.h enc/euc_tw.$(OBJEXT): internal/value.h enc/euc_tw.$(OBJEXT): internal/value_type.h @@ -1785,6 +1801,7 @@ enc/gb18030.$(OBJEXT): internal/intern/re.h enc/gb18030.$(OBJEXT): internal/intern/ruby.h enc/gb18030.$(OBJEXT): internal/intern/select.h enc/gb18030.$(OBJEXT): internal/intern/select/largesize.h +enc/gb18030.$(OBJEXT): internal/intern/set.h enc/gb18030.$(OBJEXT): internal/intern/signal.h enc/gb18030.$(OBJEXT): internal/intern/sprintf.h enc/gb18030.$(OBJEXT): internal/intern/string.h @@ -1804,6 +1821,7 @@ enc/gb18030.$(OBJEXT): internal/special_consts.h enc/gb18030.$(OBJEXT): internal/static_assert.h enc/gb18030.$(OBJEXT): internal/stdalign.h enc/gb18030.$(OBJEXT): internal/stdbool.h +enc/gb18030.$(OBJEXT): internal/stdckdint.h enc/gb18030.$(OBJEXT): internal/symbol.h enc/gb18030.$(OBJEXT): internal/value.h enc/gb18030.$(OBJEXT): internal/value_type.h @@ -1945,6 +1963,7 @@ enc/gb2312.$(OBJEXT): internal/intern/re.h enc/gb2312.$(OBJEXT): internal/intern/ruby.h enc/gb2312.$(OBJEXT): internal/intern/select.h enc/gb2312.$(OBJEXT): internal/intern/select/largesize.h +enc/gb2312.$(OBJEXT): internal/intern/set.h enc/gb2312.$(OBJEXT): internal/intern/signal.h enc/gb2312.$(OBJEXT): internal/intern/sprintf.h enc/gb2312.$(OBJEXT): internal/intern/string.h @@ -1964,6 +1983,7 @@ enc/gb2312.$(OBJEXT): internal/special_consts.h enc/gb2312.$(OBJEXT): internal/static_assert.h enc/gb2312.$(OBJEXT): internal/stdalign.h enc/gb2312.$(OBJEXT): internal/stdbool.h +enc/gb2312.$(OBJEXT): internal/stdckdint.h enc/gb2312.$(OBJEXT): internal/symbol.h enc/gb2312.$(OBJEXT): internal/value.h enc/gb2312.$(OBJEXT): internal/value_type.h @@ -2105,6 +2125,7 @@ enc/gbk.$(OBJEXT): internal/intern/re.h enc/gbk.$(OBJEXT): internal/intern/ruby.h enc/gbk.$(OBJEXT): internal/intern/select.h enc/gbk.$(OBJEXT): internal/intern/select/largesize.h +enc/gbk.$(OBJEXT): internal/intern/set.h enc/gbk.$(OBJEXT): internal/intern/signal.h enc/gbk.$(OBJEXT): internal/intern/sprintf.h enc/gbk.$(OBJEXT): internal/intern/string.h @@ -2124,6 +2145,7 @@ enc/gbk.$(OBJEXT): internal/special_consts.h enc/gbk.$(OBJEXT): internal/static_assert.h enc/gbk.$(OBJEXT): internal/stdalign.h enc/gbk.$(OBJEXT): internal/stdbool.h +enc/gbk.$(OBJEXT): internal/stdckdint.h enc/gbk.$(OBJEXT): internal/symbol.h enc/gbk.$(OBJEXT): internal/value.h enc/gbk.$(OBJEXT): internal/value_type.h @@ -2266,6 +2288,7 @@ enc/iso_8859_1.$(OBJEXT): internal/intern/re.h enc/iso_8859_1.$(OBJEXT): internal/intern/ruby.h enc/iso_8859_1.$(OBJEXT): internal/intern/select.h enc/iso_8859_1.$(OBJEXT): internal/intern/select/largesize.h +enc/iso_8859_1.$(OBJEXT): internal/intern/set.h enc/iso_8859_1.$(OBJEXT): internal/intern/signal.h enc/iso_8859_1.$(OBJEXT): internal/intern/sprintf.h enc/iso_8859_1.$(OBJEXT): internal/intern/string.h @@ -2285,6 +2308,7 @@ enc/iso_8859_1.$(OBJEXT): internal/special_consts.h enc/iso_8859_1.$(OBJEXT): internal/static_assert.h enc/iso_8859_1.$(OBJEXT): internal/stdalign.h enc/iso_8859_1.$(OBJEXT): internal/stdbool.h +enc/iso_8859_1.$(OBJEXT): internal/stdckdint.h enc/iso_8859_1.$(OBJEXT): internal/symbol.h enc/iso_8859_1.$(OBJEXT): internal/value.h enc/iso_8859_1.$(OBJEXT): internal/value_type.h @@ -2427,6 +2451,7 @@ enc/iso_8859_10.$(OBJEXT): internal/intern/re.h enc/iso_8859_10.$(OBJEXT): internal/intern/ruby.h enc/iso_8859_10.$(OBJEXT): internal/intern/select.h enc/iso_8859_10.$(OBJEXT): internal/intern/select/largesize.h +enc/iso_8859_10.$(OBJEXT): internal/intern/set.h enc/iso_8859_10.$(OBJEXT): internal/intern/signal.h enc/iso_8859_10.$(OBJEXT): internal/intern/sprintf.h enc/iso_8859_10.$(OBJEXT): internal/intern/string.h @@ -2446,6 +2471,7 @@ enc/iso_8859_10.$(OBJEXT): internal/special_consts.h enc/iso_8859_10.$(OBJEXT): internal/static_assert.h enc/iso_8859_10.$(OBJEXT): internal/stdalign.h enc/iso_8859_10.$(OBJEXT): internal/stdbool.h +enc/iso_8859_10.$(OBJEXT): internal/stdckdint.h enc/iso_8859_10.$(OBJEXT): internal/symbol.h enc/iso_8859_10.$(OBJEXT): internal/value.h enc/iso_8859_10.$(OBJEXT): internal/value_type.h @@ -2587,6 +2613,7 @@ enc/iso_8859_11.$(OBJEXT): internal/intern/re.h enc/iso_8859_11.$(OBJEXT): internal/intern/ruby.h enc/iso_8859_11.$(OBJEXT): internal/intern/select.h enc/iso_8859_11.$(OBJEXT): internal/intern/select/largesize.h +enc/iso_8859_11.$(OBJEXT): internal/intern/set.h enc/iso_8859_11.$(OBJEXT): internal/intern/signal.h enc/iso_8859_11.$(OBJEXT): internal/intern/sprintf.h enc/iso_8859_11.$(OBJEXT): internal/intern/string.h @@ -2606,6 +2633,7 @@ enc/iso_8859_11.$(OBJEXT): internal/special_consts.h enc/iso_8859_11.$(OBJEXT): internal/static_assert.h enc/iso_8859_11.$(OBJEXT): internal/stdalign.h enc/iso_8859_11.$(OBJEXT): internal/stdbool.h +enc/iso_8859_11.$(OBJEXT): internal/stdckdint.h enc/iso_8859_11.$(OBJEXT): internal/symbol.h enc/iso_8859_11.$(OBJEXT): internal/value.h enc/iso_8859_11.$(OBJEXT): internal/value_type.h @@ -2748,6 +2776,7 @@ enc/iso_8859_13.$(OBJEXT): internal/intern/re.h enc/iso_8859_13.$(OBJEXT): internal/intern/ruby.h enc/iso_8859_13.$(OBJEXT): internal/intern/select.h enc/iso_8859_13.$(OBJEXT): internal/intern/select/largesize.h +enc/iso_8859_13.$(OBJEXT): internal/intern/set.h enc/iso_8859_13.$(OBJEXT): internal/intern/signal.h enc/iso_8859_13.$(OBJEXT): internal/intern/sprintf.h enc/iso_8859_13.$(OBJEXT): internal/intern/string.h @@ -2767,6 +2796,7 @@ enc/iso_8859_13.$(OBJEXT): internal/special_consts.h enc/iso_8859_13.$(OBJEXT): internal/static_assert.h enc/iso_8859_13.$(OBJEXT): internal/stdalign.h enc/iso_8859_13.$(OBJEXT): internal/stdbool.h +enc/iso_8859_13.$(OBJEXT): internal/stdckdint.h enc/iso_8859_13.$(OBJEXT): internal/symbol.h enc/iso_8859_13.$(OBJEXT): internal/value.h enc/iso_8859_13.$(OBJEXT): internal/value_type.h @@ -2909,6 +2939,7 @@ enc/iso_8859_14.$(OBJEXT): internal/intern/re.h enc/iso_8859_14.$(OBJEXT): internal/intern/ruby.h enc/iso_8859_14.$(OBJEXT): internal/intern/select.h enc/iso_8859_14.$(OBJEXT): internal/intern/select/largesize.h +enc/iso_8859_14.$(OBJEXT): internal/intern/set.h enc/iso_8859_14.$(OBJEXT): internal/intern/signal.h enc/iso_8859_14.$(OBJEXT): internal/intern/sprintf.h enc/iso_8859_14.$(OBJEXT): internal/intern/string.h @@ -2928,6 +2959,7 @@ enc/iso_8859_14.$(OBJEXT): internal/special_consts.h enc/iso_8859_14.$(OBJEXT): internal/static_assert.h enc/iso_8859_14.$(OBJEXT): internal/stdalign.h enc/iso_8859_14.$(OBJEXT): internal/stdbool.h +enc/iso_8859_14.$(OBJEXT): internal/stdckdint.h enc/iso_8859_14.$(OBJEXT): internal/symbol.h enc/iso_8859_14.$(OBJEXT): internal/value.h enc/iso_8859_14.$(OBJEXT): internal/value_type.h @@ -3070,6 +3102,7 @@ enc/iso_8859_15.$(OBJEXT): internal/intern/re.h enc/iso_8859_15.$(OBJEXT): internal/intern/ruby.h enc/iso_8859_15.$(OBJEXT): internal/intern/select.h enc/iso_8859_15.$(OBJEXT): internal/intern/select/largesize.h +enc/iso_8859_15.$(OBJEXT): internal/intern/set.h enc/iso_8859_15.$(OBJEXT): internal/intern/signal.h enc/iso_8859_15.$(OBJEXT): internal/intern/sprintf.h enc/iso_8859_15.$(OBJEXT): internal/intern/string.h @@ -3089,6 +3122,7 @@ enc/iso_8859_15.$(OBJEXT): internal/special_consts.h enc/iso_8859_15.$(OBJEXT): internal/static_assert.h enc/iso_8859_15.$(OBJEXT): internal/stdalign.h enc/iso_8859_15.$(OBJEXT): internal/stdbool.h +enc/iso_8859_15.$(OBJEXT): internal/stdckdint.h enc/iso_8859_15.$(OBJEXT): internal/symbol.h enc/iso_8859_15.$(OBJEXT): internal/value.h enc/iso_8859_15.$(OBJEXT): internal/value_type.h @@ -3231,6 +3265,7 @@ enc/iso_8859_16.$(OBJEXT): internal/intern/re.h enc/iso_8859_16.$(OBJEXT): internal/intern/ruby.h enc/iso_8859_16.$(OBJEXT): internal/intern/select.h enc/iso_8859_16.$(OBJEXT): internal/intern/select/largesize.h +enc/iso_8859_16.$(OBJEXT): internal/intern/set.h enc/iso_8859_16.$(OBJEXT): internal/intern/signal.h enc/iso_8859_16.$(OBJEXT): internal/intern/sprintf.h enc/iso_8859_16.$(OBJEXT): internal/intern/string.h @@ -3250,6 +3285,7 @@ enc/iso_8859_16.$(OBJEXT): internal/special_consts.h enc/iso_8859_16.$(OBJEXT): internal/static_assert.h enc/iso_8859_16.$(OBJEXT): internal/stdalign.h enc/iso_8859_16.$(OBJEXT): internal/stdbool.h +enc/iso_8859_16.$(OBJEXT): internal/stdckdint.h enc/iso_8859_16.$(OBJEXT): internal/symbol.h enc/iso_8859_16.$(OBJEXT): internal/value.h enc/iso_8859_16.$(OBJEXT): internal/value_type.h @@ -3392,6 +3428,7 @@ enc/iso_8859_2.$(OBJEXT): internal/intern/re.h enc/iso_8859_2.$(OBJEXT): internal/intern/ruby.h enc/iso_8859_2.$(OBJEXT): internal/intern/select.h enc/iso_8859_2.$(OBJEXT): internal/intern/select/largesize.h +enc/iso_8859_2.$(OBJEXT): internal/intern/set.h enc/iso_8859_2.$(OBJEXT): internal/intern/signal.h enc/iso_8859_2.$(OBJEXT): internal/intern/sprintf.h enc/iso_8859_2.$(OBJEXT): internal/intern/string.h @@ -3411,6 +3448,7 @@ enc/iso_8859_2.$(OBJEXT): internal/special_consts.h enc/iso_8859_2.$(OBJEXT): internal/static_assert.h enc/iso_8859_2.$(OBJEXT): internal/stdalign.h enc/iso_8859_2.$(OBJEXT): internal/stdbool.h +enc/iso_8859_2.$(OBJEXT): internal/stdckdint.h enc/iso_8859_2.$(OBJEXT): internal/symbol.h enc/iso_8859_2.$(OBJEXT): internal/value.h enc/iso_8859_2.$(OBJEXT): internal/value_type.h @@ -3553,6 +3591,7 @@ enc/iso_8859_3.$(OBJEXT): internal/intern/re.h enc/iso_8859_3.$(OBJEXT): internal/intern/ruby.h enc/iso_8859_3.$(OBJEXT): internal/intern/select.h enc/iso_8859_3.$(OBJEXT): internal/intern/select/largesize.h +enc/iso_8859_3.$(OBJEXT): internal/intern/set.h enc/iso_8859_3.$(OBJEXT): internal/intern/signal.h enc/iso_8859_3.$(OBJEXT): internal/intern/sprintf.h enc/iso_8859_3.$(OBJEXT): internal/intern/string.h @@ -3572,6 +3611,7 @@ enc/iso_8859_3.$(OBJEXT): internal/special_consts.h enc/iso_8859_3.$(OBJEXT): internal/static_assert.h enc/iso_8859_3.$(OBJEXT): internal/stdalign.h enc/iso_8859_3.$(OBJEXT): internal/stdbool.h +enc/iso_8859_3.$(OBJEXT): internal/stdckdint.h enc/iso_8859_3.$(OBJEXT): internal/symbol.h enc/iso_8859_3.$(OBJEXT): internal/value.h enc/iso_8859_3.$(OBJEXT): internal/value_type.h @@ -3714,6 +3754,7 @@ enc/iso_8859_4.$(OBJEXT): internal/intern/re.h enc/iso_8859_4.$(OBJEXT): internal/intern/ruby.h enc/iso_8859_4.$(OBJEXT): internal/intern/select.h enc/iso_8859_4.$(OBJEXT): internal/intern/select/largesize.h +enc/iso_8859_4.$(OBJEXT): internal/intern/set.h enc/iso_8859_4.$(OBJEXT): internal/intern/signal.h enc/iso_8859_4.$(OBJEXT): internal/intern/sprintf.h enc/iso_8859_4.$(OBJEXT): internal/intern/string.h @@ -3733,6 +3774,7 @@ enc/iso_8859_4.$(OBJEXT): internal/special_consts.h enc/iso_8859_4.$(OBJEXT): internal/static_assert.h enc/iso_8859_4.$(OBJEXT): internal/stdalign.h enc/iso_8859_4.$(OBJEXT): internal/stdbool.h +enc/iso_8859_4.$(OBJEXT): internal/stdckdint.h enc/iso_8859_4.$(OBJEXT): internal/symbol.h enc/iso_8859_4.$(OBJEXT): internal/value.h enc/iso_8859_4.$(OBJEXT): internal/value_type.h @@ -3874,6 +3916,7 @@ enc/iso_8859_5.$(OBJEXT): internal/intern/re.h enc/iso_8859_5.$(OBJEXT): internal/intern/ruby.h enc/iso_8859_5.$(OBJEXT): internal/intern/select.h enc/iso_8859_5.$(OBJEXT): internal/intern/select/largesize.h +enc/iso_8859_5.$(OBJEXT): internal/intern/set.h enc/iso_8859_5.$(OBJEXT): internal/intern/signal.h enc/iso_8859_5.$(OBJEXT): internal/intern/sprintf.h enc/iso_8859_5.$(OBJEXT): internal/intern/string.h @@ -3893,6 +3936,7 @@ enc/iso_8859_5.$(OBJEXT): internal/special_consts.h enc/iso_8859_5.$(OBJEXT): internal/static_assert.h enc/iso_8859_5.$(OBJEXT): internal/stdalign.h enc/iso_8859_5.$(OBJEXT): internal/stdbool.h +enc/iso_8859_5.$(OBJEXT): internal/stdckdint.h enc/iso_8859_5.$(OBJEXT): internal/symbol.h enc/iso_8859_5.$(OBJEXT): internal/value.h enc/iso_8859_5.$(OBJEXT): internal/value_type.h @@ -4034,6 +4078,7 @@ enc/iso_8859_6.$(OBJEXT): internal/intern/re.h enc/iso_8859_6.$(OBJEXT): internal/intern/ruby.h enc/iso_8859_6.$(OBJEXT): internal/intern/select.h enc/iso_8859_6.$(OBJEXT): internal/intern/select/largesize.h +enc/iso_8859_6.$(OBJEXT): internal/intern/set.h enc/iso_8859_6.$(OBJEXT): internal/intern/signal.h enc/iso_8859_6.$(OBJEXT): internal/intern/sprintf.h enc/iso_8859_6.$(OBJEXT): internal/intern/string.h @@ -4053,6 +4098,7 @@ enc/iso_8859_6.$(OBJEXT): internal/special_consts.h enc/iso_8859_6.$(OBJEXT): internal/static_assert.h enc/iso_8859_6.$(OBJEXT): internal/stdalign.h enc/iso_8859_6.$(OBJEXT): internal/stdbool.h +enc/iso_8859_6.$(OBJEXT): internal/stdckdint.h enc/iso_8859_6.$(OBJEXT): internal/symbol.h enc/iso_8859_6.$(OBJEXT): internal/value.h enc/iso_8859_6.$(OBJEXT): internal/value_type.h @@ -4194,6 +4240,7 @@ enc/iso_8859_7.$(OBJEXT): internal/intern/re.h enc/iso_8859_7.$(OBJEXT): internal/intern/ruby.h enc/iso_8859_7.$(OBJEXT): internal/intern/select.h enc/iso_8859_7.$(OBJEXT): internal/intern/select/largesize.h +enc/iso_8859_7.$(OBJEXT): internal/intern/set.h enc/iso_8859_7.$(OBJEXT): internal/intern/signal.h enc/iso_8859_7.$(OBJEXT): internal/intern/sprintf.h enc/iso_8859_7.$(OBJEXT): internal/intern/string.h @@ -4213,6 +4260,7 @@ enc/iso_8859_7.$(OBJEXT): internal/special_consts.h enc/iso_8859_7.$(OBJEXT): internal/static_assert.h enc/iso_8859_7.$(OBJEXT): internal/stdalign.h enc/iso_8859_7.$(OBJEXT): internal/stdbool.h +enc/iso_8859_7.$(OBJEXT): internal/stdckdint.h enc/iso_8859_7.$(OBJEXT): internal/symbol.h enc/iso_8859_7.$(OBJEXT): internal/value.h enc/iso_8859_7.$(OBJEXT): internal/value_type.h @@ -4354,6 +4402,7 @@ enc/iso_8859_8.$(OBJEXT): internal/intern/re.h enc/iso_8859_8.$(OBJEXT): internal/intern/ruby.h enc/iso_8859_8.$(OBJEXT): internal/intern/select.h enc/iso_8859_8.$(OBJEXT): internal/intern/select/largesize.h +enc/iso_8859_8.$(OBJEXT): internal/intern/set.h enc/iso_8859_8.$(OBJEXT): internal/intern/signal.h enc/iso_8859_8.$(OBJEXT): internal/intern/sprintf.h enc/iso_8859_8.$(OBJEXT): internal/intern/string.h @@ -4373,6 +4422,7 @@ enc/iso_8859_8.$(OBJEXT): internal/special_consts.h enc/iso_8859_8.$(OBJEXT): internal/static_assert.h enc/iso_8859_8.$(OBJEXT): internal/stdalign.h enc/iso_8859_8.$(OBJEXT): internal/stdbool.h +enc/iso_8859_8.$(OBJEXT): internal/stdckdint.h enc/iso_8859_8.$(OBJEXT): internal/symbol.h enc/iso_8859_8.$(OBJEXT): internal/value.h enc/iso_8859_8.$(OBJEXT): internal/value_type.h @@ -4515,6 +4565,7 @@ enc/iso_8859_9.$(OBJEXT): internal/intern/re.h enc/iso_8859_9.$(OBJEXT): internal/intern/ruby.h enc/iso_8859_9.$(OBJEXT): internal/intern/select.h enc/iso_8859_9.$(OBJEXT): internal/intern/select/largesize.h +enc/iso_8859_9.$(OBJEXT): internal/intern/set.h enc/iso_8859_9.$(OBJEXT): internal/intern/signal.h enc/iso_8859_9.$(OBJEXT): internal/intern/sprintf.h enc/iso_8859_9.$(OBJEXT): internal/intern/string.h @@ -4534,6 +4585,7 @@ enc/iso_8859_9.$(OBJEXT): internal/special_consts.h enc/iso_8859_9.$(OBJEXT): internal/static_assert.h enc/iso_8859_9.$(OBJEXT): internal/stdalign.h enc/iso_8859_9.$(OBJEXT): internal/stdbool.h +enc/iso_8859_9.$(OBJEXT): internal/stdckdint.h enc/iso_8859_9.$(OBJEXT): internal/symbol.h enc/iso_8859_9.$(OBJEXT): internal/value.h enc/iso_8859_9.$(OBJEXT): internal/value_type.h @@ -4675,6 +4727,7 @@ enc/koi8_r.$(OBJEXT): internal/intern/re.h enc/koi8_r.$(OBJEXT): internal/intern/ruby.h enc/koi8_r.$(OBJEXT): internal/intern/select.h enc/koi8_r.$(OBJEXT): internal/intern/select/largesize.h +enc/koi8_r.$(OBJEXT): internal/intern/set.h enc/koi8_r.$(OBJEXT): internal/intern/signal.h enc/koi8_r.$(OBJEXT): internal/intern/sprintf.h enc/koi8_r.$(OBJEXT): internal/intern/string.h @@ -4694,6 +4747,7 @@ enc/koi8_r.$(OBJEXT): internal/special_consts.h enc/koi8_r.$(OBJEXT): internal/static_assert.h enc/koi8_r.$(OBJEXT): internal/stdalign.h enc/koi8_r.$(OBJEXT): internal/stdbool.h +enc/koi8_r.$(OBJEXT): internal/stdckdint.h enc/koi8_r.$(OBJEXT): internal/symbol.h enc/koi8_r.$(OBJEXT): internal/value.h enc/koi8_r.$(OBJEXT): internal/value_type.h @@ -4835,6 +4889,7 @@ enc/koi8_u.$(OBJEXT): internal/intern/re.h enc/koi8_u.$(OBJEXT): internal/intern/ruby.h enc/koi8_u.$(OBJEXT): internal/intern/select.h enc/koi8_u.$(OBJEXT): internal/intern/select/largesize.h +enc/koi8_u.$(OBJEXT): internal/intern/set.h enc/koi8_u.$(OBJEXT): internal/intern/signal.h enc/koi8_u.$(OBJEXT): internal/intern/sprintf.h enc/koi8_u.$(OBJEXT): internal/intern/string.h @@ -4854,6 +4909,7 @@ enc/koi8_u.$(OBJEXT): internal/special_consts.h enc/koi8_u.$(OBJEXT): internal/static_assert.h enc/koi8_u.$(OBJEXT): internal/stdalign.h enc/koi8_u.$(OBJEXT): internal/stdbool.h +enc/koi8_u.$(OBJEXT): internal/stdckdint.h enc/koi8_u.$(OBJEXT): internal/symbol.h enc/koi8_u.$(OBJEXT): internal/value.h enc/koi8_u.$(OBJEXT): internal/value_type.h @@ -4998,6 +5054,7 @@ enc/shift_jis.$(OBJEXT): internal/intern/re.h enc/shift_jis.$(OBJEXT): internal/intern/ruby.h enc/shift_jis.$(OBJEXT): internal/intern/select.h enc/shift_jis.$(OBJEXT): internal/intern/select/largesize.h +enc/shift_jis.$(OBJEXT): internal/intern/set.h enc/shift_jis.$(OBJEXT): internal/intern/signal.h enc/shift_jis.$(OBJEXT): internal/intern/sprintf.h enc/shift_jis.$(OBJEXT): internal/intern/string.h @@ -5017,6 +5074,7 @@ enc/shift_jis.$(OBJEXT): internal/special_consts.h enc/shift_jis.$(OBJEXT): internal/static_assert.h enc/shift_jis.$(OBJEXT): internal/stdalign.h enc/shift_jis.$(OBJEXT): internal/stdbool.h +enc/shift_jis.$(OBJEXT): internal/stdckdint.h enc/shift_jis.$(OBJEXT): internal/symbol.h enc/shift_jis.$(OBJEXT): internal/value.h enc/shift_jis.$(OBJEXT): internal/value_type.h @@ -5157,6 +5215,7 @@ enc/trans/big5.$(OBJEXT): internal/intern/re.h enc/trans/big5.$(OBJEXT): internal/intern/ruby.h enc/trans/big5.$(OBJEXT): internal/intern/select.h enc/trans/big5.$(OBJEXT): internal/intern/select/largesize.h +enc/trans/big5.$(OBJEXT): internal/intern/set.h enc/trans/big5.$(OBJEXT): internal/intern/signal.h enc/trans/big5.$(OBJEXT): internal/intern/sprintf.h enc/trans/big5.$(OBJEXT): internal/intern/string.h @@ -5176,6 +5235,7 @@ enc/trans/big5.$(OBJEXT): internal/special_consts.h enc/trans/big5.$(OBJEXT): internal/static_assert.h enc/trans/big5.$(OBJEXT): internal/stdalign.h enc/trans/big5.$(OBJEXT): internal/stdbool.h +enc/trans/big5.$(OBJEXT): internal/stdckdint.h enc/trans/big5.$(OBJEXT): internal/symbol.h enc/trans/big5.$(OBJEXT): internal/value.h enc/trans/big5.$(OBJEXT): internal/value_type.h @@ -5315,6 +5375,7 @@ enc/trans/cesu_8.$(OBJEXT): internal/intern/re.h enc/trans/cesu_8.$(OBJEXT): internal/intern/ruby.h enc/trans/cesu_8.$(OBJEXT): internal/intern/select.h enc/trans/cesu_8.$(OBJEXT): internal/intern/select/largesize.h +enc/trans/cesu_8.$(OBJEXT): internal/intern/set.h enc/trans/cesu_8.$(OBJEXT): internal/intern/signal.h enc/trans/cesu_8.$(OBJEXT): internal/intern/sprintf.h enc/trans/cesu_8.$(OBJEXT): internal/intern/string.h @@ -5334,6 +5395,7 @@ enc/trans/cesu_8.$(OBJEXT): internal/special_consts.h enc/trans/cesu_8.$(OBJEXT): internal/static_assert.h enc/trans/cesu_8.$(OBJEXT): internal/stdalign.h enc/trans/cesu_8.$(OBJEXT): internal/stdbool.h +enc/trans/cesu_8.$(OBJEXT): internal/stdckdint.h enc/trans/cesu_8.$(OBJEXT): internal/symbol.h enc/trans/cesu_8.$(OBJEXT): internal/value.h enc/trans/cesu_8.$(OBJEXT): internal/value_type.h @@ -5473,6 +5535,7 @@ enc/trans/chinese.$(OBJEXT): internal/intern/re.h enc/trans/chinese.$(OBJEXT): internal/intern/ruby.h enc/trans/chinese.$(OBJEXT): internal/intern/select.h enc/trans/chinese.$(OBJEXT): internal/intern/select/largesize.h +enc/trans/chinese.$(OBJEXT): internal/intern/set.h enc/trans/chinese.$(OBJEXT): internal/intern/signal.h enc/trans/chinese.$(OBJEXT): internal/intern/sprintf.h enc/trans/chinese.$(OBJEXT): internal/intern/string.h @@ -5492,6 +5555,7 @@ enc/trans/chinese.$(OBJEXT): internal/special_consts.h enc/trans/chinese.$(OBJEXT): internal/static_assert.h enc/trans/chinese.$(OBJEXT): internal/stdalign.h enc/trans/chinese.$(OBJEXT): internal/stdbool.h +enc/trans/chinese.$(OBJEXT): internal/stdckdint.h enc/trans/chinese.$(OBJEXT): internal/symbol.h enc/trans/chinese.$(OBJEXT): internal/value.h enc/trans/chinese.$(OBJEXT): internal/value_type.h @@ -5631,6 +5695,7 @@ enc/trans/ebcdic.$(OBJEXT): internal/intern/re.h enc/trans/ebcdic.$(OBJEXT): internal/intern/ruby.h enc/trans/ebcdic.$(OBJEXT): internal/intern/select.h enc/trans/ebcdic.$(OBJEXT): internal/intern/select/largesize.h +enc/trans/ebcdic.$(OBJEXT): internal/intern/set.h enc/trans/ebcdic.$(OBJEXT): internal/intern/signal.h enc/trans/ebcdic.$(OBJEXT): internal/intern/sprintf.h enc/trans/ebcdic.$(OBJEXT): internal/intern/string.h @@ -5650,6 +5715,7 @@ enc/trans/ebcdic.$(OBJEXT): internal/special_consts.h enc/trans/ebcdic.$(OBJEXT): internal/static_assert.h enc/trans/ebcdic.$(OBJEXT): internal/stdalign.h enc/trans/ebcdic.$(OBJEXT): internal/stdbool.h +enc/trans/ebcdic.$(OBJEXT): internal/stdckdint.h enc/trans/ebcdic.$(OBJEXT): internal/symbol.h enc/trans/ebcdic.$(OBJEXT): internal/value.h enc/trans/ebcdic.$(OBJEXT): internal/value_type.h @@ -5789,6 +5855,7 @@ enc/trans/emoji.$(OBJEXT): internal/intern/re.h enc/trans/emoji.$(OBJEXT): internal/intern/ruby.h enc/trans/emoji.$(OBJEXT): internal/intern/select.h enc/trans/emoji.$(OBJEXT): internal/intern/select/largesize.h +enc/trans/emoji.$(OBJEXT): internal/intern/set.h enc/trans/emoji.$(OBJEXT): internal/intern/signal.h enc/trans/emoji.$(OBJEXT): internal/intern/sprintf.h enc/trans/emoji.$(OBJEXT): internal/intern/string.h @@ -5808,6 +5875,7 @@ enc/trans/emoji.$(OBJEXT): internal/special_consts.h enc/trans/emoji.$(OBJEXT): internal/static_assert.h enc/trans/emoji.$(OBJEXT): internal/stdalign.h enc/trans/emoji.$(OBJEXT): internal/stdbool.h +enc/trans/emoji.$(OBJEXT): internal/stdckdint.h enc/trans/emoji.$(OBJEXT): internal/symbol.h enc/trans/emoji.$(OBJEXT): internal/value.h enc/trans/emoji.$(OBJEXT): internal/value_type.h @@ -5947,6 +6015,7 @@ enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/re.h enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/ruby.h enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/select.h enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/select/largesize.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/set.h enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/signal.h enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/sprintf.h enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/intern/string.h @@ -5966,6 +6035,7 @@ enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/special_consts.h enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/static_assert.h enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/stdalign.h enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/stdbool.h +enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/stdckdint.h enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/symbol.h enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/value.h enc/trans/emoji_iso2022_kddi.$(OBJEXT): internal/value_type.h @@ -6105,6 +6175,7 @@ enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/re.h enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/ruby.h enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/select.h enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/select/largesize.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/set.h enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/signal.h enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/sprintf.h enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/intern/string.h @@ -6124,6 +6195,7 @@ enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/special_consts.h enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/static_assert.h enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/stdalign.h enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/stdbool.h +enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/stdckdint.h enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/symbol.h enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/value.h enc/trans/emoji_sjis_docomo.$(OBJEXT): internal/value_type.h @@ -6263,6 +6335,7 @@ enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/re.h enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/ruby.h enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/select.h enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/select/largesize.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/set.h enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/signal.h enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/sprintf.h enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/intern/string.h @@ -6282,6 +6355,7 @@ enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/special_consts.h enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/static_assert.h enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/stdalign.h enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/stdbool.h +enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/stdckdint.h enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/symbol.h enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/value.h enc/trans/emoji_sjis_kddi.$(OBJEXT): internal/value_type.h @@ -6421,6 +6495,7 @@ enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/re.h enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/ruby.h enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/select.h enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/select/largesize.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/set.h enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/signal.h enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/sprintf.h enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/intern/string.h @@ -6440,6 +6515,7 @@ enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/special_consts.h enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/static_assert.h enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/stdalign.h enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/stdbool.h +enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/stdckdint.h enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/symbol.h enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/value.h enc/trans/emoji_sjis_softbank.$(OBJEXT): internal/value_type.h @@ -6579,6 +6655,7 @@ enc/trans/escape.$(OBJEXT): internal/intern/re.h enc/trans/escape.$(OBJEXT): internal/intern/ruby.h enc/trans/escape.$(OBJEXT): internal/intern/select.h enc/trans/escape.$(OBJEXT): internal/intern/select/largesize.h +enc/trans/escape.$(OBJEXT): internal/intern/set.h enc/trans/escape.$(OBJEXT): internal/intern/signal.h enc/trans/escape.$(OBJEXT): internal/intern/sprintf.h enc/trans/escape.$(OBJEXT): internal/intern/string.h @@ -6598,6 +6675,7 @@ enc/trans/escape.$(OBJEXT): internal/special_consts.h enc/trans/escape.$(OBJEXT): internal/static_assert.h enc/trans/escape.$(OBJEXT): internal/stdalign.h enc/trans/escape.$(OBJEXT): internal/stdbool.h +enc/trans/escape.$(OBJEXT): internal/stdckdint.h enc/trans/escape.$(OBJEXT): internal/symbol.h enc/trans/escape.$(OBJEXT): internal/value.h enc/trans/escape.$(OBJEXT): internal/value_type.h @@ -6737,6 +6815,7 @@ enc/trans/gb18030.$(OBJEXT): internal/intern/re.h enc/trans/gb18030.$(OBJEXT): internal/intern/ruby.h enc/trans/gb18030.$(OBJEXT): internal/intern/select.h enc/trans/gb18030.$(OBJEXT): internal/intern/select/largesize.h +enc/trans/gb18030.$(OBJEXT): internal/intern/set.h enc/trans/gb18030.$(OBJEXT): internal/intern/signal.h enc/trans/gb18030.$(OBJEXT): internal/intern/sprintf.h enc/trans/gb18030.$(OBJEXT): internal/intern/string.h @@ -6756,6 +6835,7 @@ enc/trans/gb18030.$(OBJEXT): internal/special_consts.h enc/trans/gb18030.$(OBJEXT): internal/static_assert.h enc/trans/gb18030.$(OBJEXT): internal/stdalign.h enc/trans/gb18030.$(OBJEXT): internal/stdbool.h +enc/trans/gb18030.$(OBJEXT): internal/stdckdint.h enc/trans/gb18030.$(OBJEXT): internal/symbol.h enc/trans/gb18030.$(OBJEXT): internal/value.h enc/trans/gb18030.$(OBJEXT): internal/value_type.h @@ -6895,6 +6975,7 @@ enc/trans/gbk.$(OBJEXT): internal/intern/re.h enc/trans/gbk.$(OBJEXT): internal/intern/ruby.h enc/trans/gbk.$(OBJEXT): internal/intern/select.h enc/trans/gbk.$(OBJEXT): internal/intern/select/largesize.h +enc/trans/gbk.$(OBJEXT): internal/intern/set.h enc/trans/gbk.$(OBJEXT): internal/intern/signal.h enc/trans/gbk.$(OBJEXT): internal/intern/sprintf.h enc/trans/gbk.$(OBJEXT): internal/intern/string.h @@ -6914,6 +6995,7 @@ enc/trans/gbk.$(OBJEXT): internal/special_consts.h enc/trans/gbk.$(OBJEXT): internal/static_assert.h enc/trans/gbk.$(OBJEXT): internal/stdalign.h enc/trans/gbk.$(OBJEXT): internal/stdbool.h +enc/trans/gbk.$(OBJEXT): internal/stdckdint.h enc/trans/gbk.$(OBJEXT): internal/symbol.h enc/trans/gbk.$(OBJEXT): internal/value.h enc/trans/gbk.$(OBJEXT): internal/value_type.h @@ -6976,6 +7058,7 @@ enc/trans/iso2022.$(OBJEXT): internal/attr/nodiscard.h enc/trans/iso2022.$(OBJEXT): internal/attr/noexcept.h enc/trans/iso2022.$(OBJEXT): internal/attr/noinline.h enc/trans/iso2022.$(OBJEXT): internal/attr/nonnull.h +enc/trans/iso2022.$(OBJEXT): internal/attr/nonstring.h enc/trans/iso2022.$(OBJEXT): internal/attr/noreturn.h enc/trans/iso2022.$(OBJEXT): internal/attr/packed_struct.h enc/trans/iso2022.$(OBJEXT): internal/attr/pure.h @@ -7053,6 +7136,7 @@ enc/trans/iso2022.$(OBJEXT): internal/intern/re.h enc/trans/iso2022.$(OBJEXT): internal/intern/ruby.h enc/trans/iso2022.$(OBJEXT): internal/intern/select.h enc/trans/iso2022.$(OBJEXT): internal/intern/select/largesize.h +enc/trans/iso2022.$(OBJEXT): internal/intern/set.h enc/trans/iso2022.$(OBJEXT): internal/intern/signal.h enc/trans/iso2022.$(OBJEXT): internal/intern/sprintf.h enc/trans/iso2022.$(OBJEXT): internal/intern/string.h @@ -7072,6 +7156,7 @@ enc/trans/iso2022.$(OBJEXT): internal/special_consts.h enc/trans/iso2022.$(OBJEXT): internal/static_assert.h enc/trans/iso2022.$(OBJEXT): internal/stdalign.h enc/trans/iso2022.$(OBJEXT): internal/stdbool.h +enc/trans/iso2022.$(OBJEXT): internal/stdckdint.h enc/trans/iso2022.$(OBJEXT): internal/symbol.h enc/trans/iso2022.$(OBJEXT): internal/value.h enc/trans/iso2022.$(OBJEXT): internal/value_type.h @@ -7211,6 +7296,7 @@ enc/trans/japanese.$(OBJEXT): internal/intern/re.h enc/trans/japanese.$(OBJEXT): internal/intern/ruby.h enc/trans/japanese.$(OBJEXT): internal/intern/select.h enc/trans/japanese.$(OBJEXT): internal/intern/select/largesize.h +enc/trans/japanese.$(OBJEXT): internal/intern/set.h enc/trans/japanese.$(OBJEXT): internal/intern/signal.h enc/trans/japanese.$(OBJEXT): internal/intern/sprintf.h enc/trans/japanese.$(OBJEXT): internal/intern/string.h @@ -7230,6 +7316,7 @@ enc/trans/japanese.$(OBJEXT): internal/special_consts.h enc/trans/japanese.$(OBJEXT): internal/static_assert.h enc/trans/japanese.$(OBJEXT): internal/stdalign.h enc/trans/japanese.$(OBJEXT): internal/stdbool.h +enc/trans/japanese.$(OBJEXT): internal/stdckdint.h enc/trans/japanese.$(OBJEXT): internal/symbol.h enc/trans/japanese.$(OBJEXT): internal/value.h enc/trans/japanese.$(OBJEXT): internal/value_type.h @@ -7369,6 +7456,7 @@ enc/trans/japanese_euc.$(OBJEXT): internal/intern/re.h enc/trans/japanese_euc.$(OBJEXT): internal/intern/ruby.h enc/trans/japanese_euc.$(OBJEXT): internal/intern/select.h enc/trans/japanese_euc.$(OBJEXT): internal/intern/select/largesize.h +enc/trans/japanese_euc.$(OBJEXT): internal/intern/set.h enc/trans/japanese_euc.$(OBJEXT): internal/intern/signal.h enc/trans/japanese_euc.$(OBJEXT): internal/intern/sprintf.h enc/trans/japanese_euc.$(OBJEXT): internal/intern/string.h @@ -7388,6 +7476,7 @@ enc/trans/japanese_euc.$(OBJEXT): internal/special_consts.h enc/trans/japanese_euc.$(OBJEXT): internal/static_assert.h enc/trans/japanese_euc.$(OBJEXT): internal/stdalign.h enc/trans/japanese_euc.$(OBJEXT): internal/stdbool.h +enc/trans/japanese_euc.$(OBJEXT): internal/stdckdint.h enc/trans/japanese_euc.$(OBJEXT): internal/symbol.h enc/trans/japanese_euc.$(OBJEXT): internal/value.h enc/trans/japanese_euc.$(OBJEXT): internal/value_type.h @@ -7527,6 +7616,7 @@ enc/trans/japanese_sjis.$(OBJEXT): internal/intern/re.h enc/trans/japanese_sjis.$(OBJEXT): internal/intern/ruby.h enc/trans/japanese_sjis.$(OBJEXT): internal/intern/select.h enc/trans/japanese_sjis.$(OBJEXT): internal/intern/select/largesize.h +enc/trans/japanese_sjis.$(OBJEXT): internal/intern/set.h enc/trans/japanese_sjis.$(OBJEXT): internal/intern/signal.h enc/trans/japanese_sjis.$(OBJEXT): internal/intern/sprintf.h enc/trans/japanese_sjis.$(OBJEXT): internal/intern/string.h @@ -7546,6 +7636,7 @@ enc/trans/japanese_sjis.$(OBJEXT): internal/special_consts.h enc/trans/japanese_sjis.$(OBJEXT): internal/static_assert.h enc/trans/japanese_sjis.$(OBJEXT): internal/stdalign.h enc/trans/japanese_sjis.$(OBJEXT): internal/stdbool.h +enc/trans/japanese_sjis.$(OBJEXT): internal/stdckdint.h enc/trans/japanese_sjis.$(OBJEXT): internal/symbol.h enc/trans/japanese_sjis.$(OBJEXT): internal/value.h enc/trans/japanese_sjis.$(OBJEXT): internal/value_type.h @@ -7685,6 +7776,7 @@ enc/trans/korean.$(OBJEXT): internal/intern/re.h enc/trans/korean.$(OBJEXT): internal/intern/ruby.h enc/trans/korean.$(OBJEXT): internal/intern/select.h enc/trans/korean.$(OBJEXT): internal/intern/select/largesize.h +enc/trans/korean.$(OBJEXT): internal/intern/set.h enc/trans/korean.$(OBJEXT): internal/intern/signal.h enc/trans/korean.$(OBJEXT): internal/intern/sprintf.h enc/trans/korean.$(OBJEXT): internal/intern/string.h @@ -7704,6 +7796,7 @@ enc/trans/korean.$(OBJEXT): internal/special_consts.h enc/trans/korean.$(OBJEXT): internal/static_assert.h enc/trans/korean.$(OBJEXT): internal/stdalign.h enc/trans/korean.$(OBJEXT): internal/stdbool.h +enc/trans/korean.$(OBJEXT): internal/stdckdint.h enc/trans/korean.$(OBJEXT): internal/symbol.h enc/trans/korean.$(OBJEXT): internal/value.h enc/trans/korean.$(OBJEXT): internal/value_type.h @@ -7842,6 +7935,7 @@ enc/trans/newline.$(OBJEXT): internal/intern/re.h enc/trans/newline.$(OBJEXT): internal/intern/ruby.h enc/trans/newline.$(OBJEXT): internal/intern/select.h enc/trans/newline.$(OBJEXT): internal/intern/select/largesize.h +enc/trans/newline.$(OBJEXT): internal/intern/set.h enc/trans/newline.$(OBJEXT): internal/intern/signal.h enc/trans/newline.$(OBJEXT): internal/intern/sprintf.h enc/trans/newline.$(OBJEXT): internal/intern/string.h @@ -7861,6 +7955,7 @@ enc/trans/newline.$(OBJEXT): internal/special_consts.h enc/trans/newline.$(OBJEXT): internal/static_assert.h enc/trans/newline.$(OBJEXT): internal/stdalign.h enc/trans/newline.$(OBJEXT): internal/stdbool.h +enc/trans/newline.$(OBJEXT): internal/stdckdint.h enc/trans/newline.$(OBJEXT): internal/symbol.h enc/trans/newline.$(OBJEXT): internal/value.h enc/trans/newline.$(OBJEXT): internal/value_type.h @@ -8000,6 +8095,7 @@ enc/trans/single_byte.$(OBJEXT): internal/intern/re.h enc/trans/single_byte.$(OBJEXT): internal/intern/ruby.h enc/trans/single_byte.$(OBJEXT): internal/intern/select.h enc/trans/single_byte.$(OBJEXT): internal/intern/select/largesize.h +enc/trans/single_byte.$(OBJEXT): internal/intern/set.h enc/trans/single_byte.$(OBJEXT): internal/intern/signal.h enc/trans/single_byte.$(OBJEXT): internal/intern/sprintf.h enc/trans/single_byte.$(OBJEXT): internal/intern/string.h @@ -8019,6 +8115,7 @@ enc/trans/single_byte.$(OBJEXT): internal/special_consts.h enc/trans/single_byte.$(OBJEXT): internal/static_assert.h enc/trans/single_byte.$(OBJEXT): internal/stdalign.h enc/trans/single_byte.$(OBJEXT): internal/stdbool.h +enc/trans/single_byte.$(OBJEXT): internal/stdckdint.h enc/trans/single_byte.$(OBJEXT): internal/symbol.h enc/trans/single_byte.$(OBJEXT): internal/value.h enc/trans/single_byte.$(OBJEXT): internal/value_type.h @@ -8158,6 +8255,7 @@ enc/trans/transdb.$(OBJEXT): internal/intern/re.h enc/trans/transdb.$(OBJEXT): internal/intern/ruby.h enc/trans/transdb.$(OBJEXT): internal/intern/select.h enc/trans/transdb.$(OBJEXT): internal/intern/select/largesize.h +enc/trans/transdb.$(OBJEXT): internal/intern/set.h enc/trans/transdb.$(OBJEXT): internal/intern/signal.h enc/trans/transdb.$(OBJEXT): internal/intern/sprintf.h enc/trans/transdb.$(OBJEXT): internal/intern/string.h @@ -8177,6 +8275,7 @@ enc/trans/transdb.$(OBJEXT): internal/special_consts.h enc/trans/transdb.$(OBJEXT): internal/static_assert.h enc/trans/transdb.$(OBJEXT): internal/stdalign.h enc/trans/transdb.$(OBJEXT): internal/stdbool.h +enc/trans/transdb.$(OBJEXT): internal/stdckdint.h enc/trans/transdb.$(OBJEXT): internal/symbol.h enc/trans/transdb.$(OBJEXT): internal/value.h enc/trans/transdb.$(OBJEXT): internal/value_type.h @@ -8317,6 +8416,7 @@ enc/trans/utf8_mac.$(OBJEXT): internal/intern/re.h enc/trans/utf8_mac.$(OBJEXT): internal/intern/ruby.h enc/trans/utf8_mac.$(OBJEXT): internal/intern/select.h enc/trans/utf8_mac.$(OBJEXT): internal/intern/select/largesize.h +enc/trans/utf8_mac.$(OBJEXT): internal/intern/set.h enc/trans/utf8_mac.$(OBJEXT): internal/intern/signal.h enc/trans/utf8_mac.$(OBJEXT): internal/intern/sprintf.h enc/trans/utf8_mac.$(OBJEXT): internal/intern/string.h @@ -8336,6 +8436,7 @@ enc/trans/utf8_mac.$(OBJEXT): internal/special_consts.h enc/trans/utf8_mac.$(OBJEXT): internal/static_assert.h enc/trans/utf8_mac.$(OBJEXT): internal/stdalign.h enc/trans/utf8_mac.$(OBJEXT): internal/stdbool.h +enc/trans/utf8_mac.$(OBJEXT): internal/stdckdint.h enc/trans/utf8_mac.$(OBJEXT): internal/symbol.h enc/trans/utf8_mac.$(OBJEXT): internal/value.h enc/trans/utf8_mac.$(OBJEXT): internal/value_type.h @@ -8475,6 +8576,7 @@ enc/trans/utf_16_32.$(OBJEXT): internal/intern/re.h enc/trans/utf_16_32.$(OBJEXT): internal/intern/ruby.h enc/trans/utf_16_32.$(OBJEXT): internal/intern/select.h enc/trans/utf_16_32.$(OBJEXT): internal/intern/select/largesize.h +enc/trans/utf_16_32.$(OBJEXT): internal/intern/set.h enc/trans/utf_16_32.$(OBJEXT): internal/intern/signal.h enc/trans/utf_16_32.$(OBJEXT): internal/intern/sprintf.h enc/trans/utf_16_32.$(OBJEXT): internal/intern/string.h @@ -8494,6 +8596,7 @@ enc/trans/utf_16_32.$(OBJEXT): internal/special_consts.h enc/trans/utf_16_32.$(OBJEXT): internal/static_assert.h enc/trans/utf_16_32.$(OBJEXT): internal/stdalign.h enc/trans/utf_16_32.$(OBJEXT): internal/stdbool.h +enc/trans/utf_16_32.$(OBJEXT): internal/stdckdint.h enc/trans/utf_16_32.$(OBJEXT): internal/symbol.h enc/trans/utf_16_32.$(OBJEXT): internal/value.h enc/trans/utf_16_32.$(OBJEXT): internal/value_type.h @@ -8636,6 +8739,7 @@ enc/unicode.$(OBJEXT): internal/intern/re.h enc/unicode.$(OBJEXT): internal/intern/ruby.h enc/unicode.$(OBJEXT): internal/intern/select.h enc/unicode.$(OBJEXT): internal/intern/select/largesize.h +enc/unicode.$(OBJEXT): internal/intern/set.h enc/unicode.$(OBJEXT): internal/intern/signal.h enc/unicode.$(OBJEXT): internal/intern/sprintf.h enc/unicode.$(OBJEXT): internal/intern/string.h @@ -8655,6 +8759,7 @@ enc/unicode.$(OBJEXT): internal/special_consts.h enc/unicode.$(OBJEXT): internal/static_assert.h enc/unicode.$(OBJEXT): internal/stdalign.h enc/unicode.$(OBJEXT): internal/stdbool.h +enc/unicode.$(OBJEXT): internal/stdckdint.h enc/unicode.$(OBJEXT): internal/symbol.h enc/unicode.$(OBJEXT): internal/value.h enc/unicode.$(OBJEXT): internal/value_type.h @@ -8806,6 +8911,7 @@ enc/us_ascii.$(OBJEXT): internal/intern/re.h enc/us_ascii.$(OBJEXT): internal/intern/ruby.h enc/us_ascii.$(OBJEXT): internal/intern/select.h enc/us_ascii.$(OBJEXT): internal/intern/select/largesize.h +enc/us_ascii.$(OBJEXT): internal/intern/set.h enc/us_ascii.$(OBJEXT): internal/intern/signal.h enc/us_ascii.$(OBJEXT): internal/intern/sprintf.h enc/us_ascii.$(OBJEXT): internal/intern/string.h @@ -8825,6 +8931,7 @@ enc/us_ascii.$(OBJEXT): internal/special_consts.h enc/us_ascii.$(OBJEXT): internal/static_assert.h enc/us_ascii.$(OBJEXT): internal/stdalign.h enc/us_ascii.$(OBJEXT): internal/stdbool.h +enc/us_ascii.$(OBJEXT): internal/stdckdint.h enc/us_ascii.$(OBJEXT): internal/symbol.h enc/us_ascii.$(OBJEXT): internal/value.h enc/us_ascii.$(OBJEXT): internal/value_type.h @@ -8968,6 +9075,7 @@ enc/utf_16be.$(OBJEXT): internal/intern/re.h enc/utf_16be.$(OBJEXT): internal/intern/ruby.h enc/utf_16be.$(OBJEXT): internal/intern/select.h enc/utf_16be.$(OBJEXT): internal/intern/select/largesize.h +enc/utf_16be.$(OBJEXT): internal/intern/set.h enc/utf_16be.$(OBJEXT): internal/intern/signal.h enc/utf_16be.$(OBJEXT): internal/intern/sprintf.h enc/utf_16be.$(OBJEXT): internal/intern/string.h @@ -8987,6 +9095,7 @@ enc/utf_16be.$(OBJEXT): internal/special_consts.h enc/utf_16be.$(OBJEXT): internal/static_assert.h enc/utf_16be.$(OBJEXT): internal/stdalign.h enc/utf_16be.$(OBJEXT): internal/stdbool.h +enc/utf_16be.$(OBJEXT): internal/stdckdint.h enc/utf_16be.$(OBJEXT): internal/symbol.h enc/utf_16be.$(OBJEXT): internal/value.h enc/utf_16be.$(OBJEXT): internal/value_type.h @@ -9129,6 +9238,7 @@ enc/utf_16le.$(OBJEXT): internal/intern/re.h enc/utf_16le.$(OBJEXT): internal/intern/ruby.h enc/utf_16le.$(OBJEXT): internal/intern/select.h enc/utf_16le.$(OBJEXT): internal/intern/select/largesize.h +enc/utf_16le.$(OBJEXT): internal/intern/set.h enc/utf_16le.$(OBJEXT): internal/intern/signal.h enc/utf_16le.$(OBJEXT): internal/intern/sprintf.h enc/utf_16le.$(OBJEXT): internal/intern/string.h @@ -9148,6 +9258,7 @@ enc/utf_16le.$(OBJEXT): internal/special_consts.h enc/utf_16le.$(OBJEXT): internal/static_assert.h enc/utf_16le.$(OBJEXT): internal/stdalign.h enc/utf_16le.$(OBJEXT): internal/stdbool.h +enc/utf_16le.$(OBJEXT): internal/stdckdint.h enc/utf_16le.$(OBJEXT): internal/symbol.h enc/utf_16le.$(OBJEXT): internal/value.h enc/utf_16le.$(OBJEXT): internal/value_type.h @@ -9290,6 +9401,7 @@ enc/utf_32be.$(OBJEXT): internal/intern/re.h enc/utf_32be.$(OBJEXT): internal/intern/ruby.h enc/utf_32be.$(OBJEXT): internal/intern/select.h enc/utf_32be.$(OBJEXT): internal/intern/select/largesize.h +enc/utf_32be.$(OBJEXT): internal/intern/set.h enc/utf_32be.$(OBJEXT): internal/intern/signal.h enc/utf_32be.$(OBJEXT): internal/intern/sprintf.h enc/utf_32be.$(OBJEXT): internal/intern/string.h @@ -9309,6 +9421,7 @@ enc/utf_32be.$(OBJEXT): internal/special_consts.h enc/utf_32be.$(OBJEXT): internal/static_assert.h enc/utf_32be.$(OBJEXT): internal/stdalign.h enc/utf_32be.$(OBJEXT): internal/stdbool.h +enc/utf_32be.$(OBJEXT): internal/stdckdint.h enc/utf_32be.$(OBJEXT): internal/symbol.h enc/utf_32be.$(OBJEXT): internal/value.h enc/utf_32be.$(OBJEXT): internal/value_type.h @@ -9451,6 +9564,7 @@ enc/utf_32le.$(OBJEXT): internal/intern/re.h enc/utf_32le.$(OBJEXT): internal/intern/ruby.h enc/utf_32le.$(OBJEXT): internal/intern/select.h enc/utf_32le.$(OBJEXT): internal/intern/select/largesize.h +enc/utf_32le.$(OBJEXT): internal/intern/set.h enc/utf_32le.$(OBJEXT): internal/intern/signal.h enc/utf_32le.$(OBJEXT): internal/intern/sprintf.h enc/utf_32le.$(OBJEXT): internal/intern/string.h @@ -9470,6 +9584,7 @@ enc/utf_32le.$(OBJEXT): internal/special_consts.h enc/utf_32le.$(OBJEXT): internal/static_assert.h enc/utf_32le.$(OBJEXT): internal/stdalign.h enc/utf_32le.$(OBJEXT): internal/stdbool.h +enc/utf_32le.$(OBJEXT): internal/stdckdint.h enc/utf_32le.$(OBJEXT): internal/symbol.h enc/utf_32le.$(OBJEXT): internal/value.h enc/utf_32le.$(OBJEXT): internal/value_type.h @@ -9621,6 +9736,7 @@ enc/utf_8.$(OBJEXT): internal/intern/re.h enc/utf_8.$(OBJEXT): internal/intern/ruby.h enc/utf_8.$(OBJEXT): internal/intern/select.h enc/utf_8.$(OBJEXT): internal/intern/select/largesize.h +enc/utf_8.$(OBJEXT): internal/intern/set.h enc/utf_8.$(OBJEXT): internal/intern/signal.h enc/utf_8.$(OBJEXT): internal/intern/sprintf.h enc/utf_8.$(OBJEXT): internal/intern/string.h @@ -9640,6 +9756,7 @@ enc/utf_8.$(OBJEXT): internal/special_consts.h enc/utf_8.$(OBJEXT): internal/static_assert.h enc/utf_8.$(OBJEXT): internal/stdalign.h enc/utf_8.$(OBJEXT): internal/stdbool.h +enc/utf_8.$(OBJEXT): internal/stdckdint.h enc/utf_8.$(OBJEXT): internal/symbol.h enc/utf_8.$(OBJEXT): internal/value.h enc/utf_8.$(OBJEXT): internal/value_type.h @@ -9783,6 +9900,7 @@ enc/windows_1250.$(OBJEXT): internal/intern/re.h enc/windows_1250.$(OBJEXT): internal/intern/ruby.h enc/windows_1250.$(OBJEXT): internal/intern/select.h enc/windows_1250.$(OBJEXT): internal/intern/select/largesize.h +enc/windows_1250.$(OBJEXT): internal/intern/set.h enc/windows_1250.$(OBJEXT): internal/intern/signal.h enc/windows_1250.$(OBJEXT): internal/intern/sprintf.h enc/windows_1250.$(OBJEXT): internal/intern/string.h @@ -9802,6 +9920,7 @@ enc/windows_1250.$(OBJEXT): internal/special_consts.h enc/windows_1250.$(OBJEXT): internal/static_assert.h enc/windows_1250.$(OBJEXT): internal/stdalign.h enc/windows_1250.$(OBJEXT): internal/stdbool.h +enc/windows_1250.$(OBJEXT): internal/stdckdint.h enc/windows_1250.$(OBJEXT): internal/symbol.h enc/windows_1250.$(OBJEXT): internal/value.h enc/windows_1250.$(OBJEXT): internal/value_type.h @@ -9943,6 +10062,7 @@ enc/windows_1251.$(OBJEXT): internal/intern/re.h enc/windows_1251.$(OBJEXT): internal/intern/ruby.h enc/windows_1251.$(OBJEXT): internal/intern/select.h enc/windows_1251.$(OBJEXT): internal/intern/select/largesize.h +enc/windows_1251.$(OBJEXT): internal/intern/set.h enc/windows_1251.$(OBJEXT): internal/intern/signal.h enc/windows_1251.$(OBJEXT): internal/intern/sprintf.h enc/windows_1251.$(OBJEXT): internal/intern/string.h @@ -9962,6 +10082,7 @@ enc/windows_1251.$(OBJEXT): internal/special_consts.h enc/windows_1251.$(OBJEXT): internal/static_assert.h enc/windows_1251.$(OBJEXT): internal/stdalign.h enc/windows_1251.$(OBJEXT): internal/stdbool.h +enc/windows_1251.$(OBJEXT): internal/stdckdint.h enc/windows_1251.$(OBJEXT): internal/symbol.h enc/windows_1251.$(OBJEXT): internal/value.h enc/windows_1251.$(OBJEXT): internal/value_type.h @@ -10104,6 +10225,7 @@ enc/windows_1252.$(OBJEXT): internal/intern/re.h enc/windows_1252.$(OBJEXT): internal/intern/ruby.h enc/windows_1252.$(OBJEXT): internal/intern/select.h enc/windows_1252.$(OBJEXT): internal/intern/select/largesize.h +enc/windows_1252.$(OBJEXT): internal/intern/set.h enc/windows_1252.$(OBJEXT): internal/intern/signal.h enc/windows_1252.$(OBJEXT): internal/intern/sprintf.h enc/windows_1252.$(OBJEXT): internal/intern/string.h @@ -10123,6 +10245,7 @@ enc/windows_1252.$(OBJEXT): internal/special_consts.h enc/windows_1252.$(OBJEXT): internal/static_assert.h enc/windows_1252.$(OBJEXT): internal/stdalign.h enc/windows_1252.$(OBJEXT): internal/stdbool.h +enc/windows_1252.$(OBJEXT): internal/stdckdint.h enc/windows_1252.$(OBJEXT): internal/symbol.h enc/windows_1252.$(OBJEXT): internal/value.h enc/windows_1252.$(OBJEXT): internal/value_type.h @@ -10264,6 +10387,7 @@ enc/windows_1253.$(OBJEXT): internal/intern/re.h enc/windows_1253.$(OBJEXT): internal/intern/ruby.h enc/windows_1253.$(OBJEXT): internal/intern/select.h enc/windows_1253.$(OBJEXT): internal/intern/select/largesize.h +enc/windows_1253.$(OBJEXT): internal/intern/set.h enc/windows_1253.$(OBJEXT): internal/intern/signal.h enc/windows_1253.$(OBJEXT): internal/intern/sprintf.h enc/windows_1253.$(OBJEXT): internal/intern/string.h @@ -10283,6 +10407,7 @@ enc/windows_1253.$(OBJEXT): internal/special_consts.h enc/windows_1253.$(OBJEXT): internal/static_assert.h enc/windows_1253.$(OBJEXT): internal/stdalign.h enc/windows_1253.$(OBJEXT): internal/stdbool.h +enc/windows_1253.$(OBJEXT): internal/stdckdint.h enc/windows_1253.$(OBJEXT): internal/symbol.h enc/windows_1253.$(OBJEXT): internal/value.h enc/windows_1253.$(OBJEXT): internal/value_type.h @@ -10425,6 +10550,7 @@ enc/windows_1254.$(OBJEXT): internal/intern/re.h enc/windows_1254.$(OBJEXT): internal/intern/ruby.h enc/windows_1254.$(OBJEXT): internal/intern/select.h enc/windows_1254.$(OBJEXT): internal/intern/select/largesize.h +enc/windows_1254.$(OBJEXT): internal/intern/set.h enc/windows_1254.$(OBJEXT): internal/intern/signal.h enc/windows_1254.$(OBJEXT): internal/intern/sprintf.h enc/windows_1254.$(OBJEXT): internal/intern/string.h @@ -10444,6 +10570,7 @@ enc/windows_1254.$(OBJEXT): internal/special_consts.h enc/windows_1254.$(OBJEXT): internal/static_assert.h enc/windows_1254.$(OBJEXT): internal/stdalign.h enc/windows_1254.$(OBJEXT): internal/stdbool.h +enc/windows_1254.$(OBJEXT): internal/stdckdint.h enc/windows_1254.$(OBJEXT): internal/symbol.h enc/windows_1254.$(OBJEXT): internal/value.h enc/windows_1254.$(OBJEXT): internal/value_type.h @@ -10586,6 +10713,7 @@ enc/windows_1257.$(OBJEXT): internal/intern/re.h enc/windows_1257.$(OBJEXT): internal/intern/ruby.h enc/windows_1257.$(OBJEXT): internal/intern/select.h enc/windows_1257.$(OBJEXT): internal/intern/select/largesize.h +enc/windows_1257.$(OBJEXT): internal/intern/set.h enc/windows_1257.$(OBJEXT): internal/intern/signal.h enc/windows_1257.$(OBJEXT): internal/intern/sprintf.h enc/windows_1257.$(OBJEXT): internal/intern/string.h @@ -10605,6 +10733,7 @@ enc/windows_1257.$(OBJEXT): internal/special_consts.h enc/windows_1257.$(OBJEXT): internal/static_assert.h enc/windows_1257.$(OBJEXT): internal/stdalign.h enc/windows_1257.$(OBJEXT): internal/stdbool.h +enc/windows_1257.$(OBJEXT): internal/stdckdint.h enc/windows_1257.$(OBJEXT): internal/symbol.h enc/windows_1257.$(OBJEXT): internal/value.h enc/windows_1257.$(OBJEXT): internal/value_type.h @@ -10749,6 +10878,7 @@ enc/windows_31j.$(OBJEXT): internal/intern/re.h enc/windows_31j.$(OBJEXT): internal/intern/ruby.h enc/windows_31j.$(OBJEXT): internal/intern/select.h enc/windows_31j.$(OBJEXT): internal/intern/select/largesize.h +enc/windows_31j.$(OBJEXT): internal/intern/set.h enc/windows_31j.$(OBJEXT): internal/intern/signal.h enc/windows_31j.$(OBJEXT): internal/intern/sprintf.h enc/windows_31j.$(OBJEXT): internal/intern/string.h @@ -10768,6 +10898,7 @@ enc/windows_31j.$(OBJEXT): internal/special_consts.h enc/windows_31j.$(OBJEXT): internal/static_assert.h enc/windows_31j.$(OBJEXT): internal/stdalign.h enc/windows_31j.$(OBJEXT): internal/stdbool.h +enc/windows_31j.$(OBJEXT): internal/stdckdint.h enc/windows_31j.$(OBJEXT): internal/symbol.h enc/windows_31j.$(OBJEXT): internal/value.h enc/windows_31j.$(OBJEXT): internal/value_type.h diff --git a/enc/ebcdic.h b/enc/ebcdic.h index a3b380a32760ad..5109bf7065abb1 100644 --- a/enc/ebcdic.h +++ b/enc/ebcdic.h @@ -7,5 +7,5 @@ ENC_ALIAS("ebcdic-cp-us", "IBM037"); * hopefully the most widely used one. * * See http://www.iana.org/assignments/character-sets/character-sets.xhtml - * http://tools.ietf.org/html/rfc1345 + * https://www.rfc-editor.org/rfc/rfc1345 */ diff --git a/enc/encinit.c.erb b/enc/encinit.c.erb index 120408f8e331b9..3662ba200d5b14 100644 --- a/enc/encinit.c.erb +++ b/enc/encinit.c.erb @@ -1,3 +1,6 @@ +/* Automatically generated from <%= erb.filename %> + * Do not edit<%# directly%>. + */ /* Copyright 2012 Google Inc. Some Rights Reserved. * Author: yugui@google.com (Yugui Sonoda) */ diff --git a/enc/jis/props.h.blt b/enc/jis/props.h.blt index 508a0844498441..865ae6b6516b7f 100644 --- a/enc/jis/props.h.blt +++ b/enc/jis/props.h.blt @@ -1,5 +1,5 @@ /* ANSI-C code produced by gperf version 3.1 */ -/* Command-line: gperf -k1,3 -7 -c -j1 -i1 -t -C -P -t --ignore-case -H onig_jis_property_hash -Q onig_jis_property_pool -N onig_jis_property enc/jis/props.kwd */ +/* Command-line: gperf -L ANSI-C -k1,3 -7 -c -j1 -i1 -t -C -P -t --ignore-case -H onig_jis_property_hash -Q onig_jis_property_pool -N onig_jis_property enc/jis/props.kwd */ #if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \ && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \ @@ -28,7 +28,6 @@ #error "gperf generated tables don't work with this execution character set. Please report a bug to ." #endif -#define gperf_offsetof(s, n) (short)offsetof(struct s##_t, s##_str##n) #line 1 "enc/jis/props.kwd" /* -*- c -*- */ #define GPERF_DOWNCASE 1 @@ -82,7 +81,7 @@ struct enc_property; #ifndef GPERF_DOWNCASE #define GPERF_DOWNCASE 1 -static const unsigned char gperf_downcase[256] = +static unsigned char gperf_downcase[256] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, @@ -180,19 +179,19 @@ onig_jis_property (register const char *str, register size_t len) { {-1}, {-1}, {-1}, {-1}, {-1}, #line 48 "enc/jis/props.kwd" - {gperf_offsetof(onig_jis_property_pool, 5), onigenc_jis_han}, + {(int)(size_t)&((struct onig_jis_property_pool_t *)0)->onig_jis_property_pool_str5, onigenc_jis_han}, {-1}, #line 49 "enc/jis/props.kwd" - {gperf_offsetof(onig_jis_property_pool, 7), onigenc_jis_latin}, + {(int)(size_t)&((struct onig_jis_property_pool_t *)0)->onig_jis_property_pool_str7, onigenc_jis_latin}, #line 50 "enc/jis/props.kwd" - {gperf_offsetof(onig_jis_property_pool, 8), onigenc_jis_greek}, + {(int)(size_t)&((struct onig_jis_property_pool_t *)0)->onig_jis_property_pool_str8, onigenc_jis_greek}, {-1}, #line 46 "enc/jis/props.kwd" - {gperf_offsetof(onig_jis_property_pool, 10), onigenc_jis_hiragana}, + {(int)(size_t)&((struct onig_jis_property_pool_t *)0)->onig_jis_property_pool_str10, onigenc_jis_hiragana}, #line 47 "enc/jis/props.kwd" - {gperf_offsetof(onig_jis_property_pool, 11), onigenc_jis_katakana}, + {(int)(size_t)&((struct onig_jis_property_pool_t *)0)->onig_jis_property_pool_str11, onigenc_jis_katakana}, #line 51 "enc/jis/props.kwd" - {gperf_offsetof(onig_jis_property_pool, 12), onigenc_jis_cyrillic} + {(int)(size_t)&((struct onig_jis_property_pool_t *)0)->onig_jis_property_pool_str12, onigenc_jis_cyrillic} }; if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) diff --git a/enc/make_encmake.rb b/enc/make_encmake.rb index fcfc2c92678b3d..96d1944bcba31c 100755 --- a/enc/make_encmake.rb +++ b/enc/make_encmake.rb @@ -121,39 +121,32 @@ def target_transcoders ATRANS, TRANS = target_transcoders if File.exist?(depend = File.join($srcdir, "depend")) - if ERB.instance_method(:initialize).parameters.assoc(:key) # Ruby 2.6+ - erb = ERB.new(File.read(depend), trim_mode: '%') - else - erb = ERB.new(File.read(depend), nil, '%') - end + erb = ERB.new(File.read(depend), trim_mode: '%') erb.filename = depend tmp = erb.result(binding) - dep = "\n#### depend ####\n\n" << depend_rules(tmp).join + dep = "\n#### depend ####\n\n" + depend_rules(tmp).join else dep = "" end mkin = File.read(File.join($srcdir, "Makefile.in")) -mkin.gsub!(/@(#{CONFIG.keys.join('|')})@/) {CONFIG[$1]} +# Variables that should not be expanded in Makefile.in to allow +# overriding inherited variables at make-time. +not_expand_vars = %w(CFLAGS) +mkin.gsub!(/@(#{RbConfig::CONFIG.keys.join('|')})@/) do + not_expand_vars.include?($1) ? CONFIG[$1] : RbConfig::CONFIG[$1] +end File.open(ARGV[0], 'wb') {|f| f.puts mkin, dep } if MODULE_TYPE == :static filename = "encinit.c.erb" - if ERB.instance_method(:initialize).parameters.assoc(:key) # Ruby 2.6+ - erb = ERB.new(File.read(File.join($srcdir, filename)), trim_mode: '%-') - else - erb = ERB.new(File.read(File.join($srcdir, filename)), nil, '%-') - end + erb = ERB.new(File.read(File.join($srcdir, filename)), trim_mode: '%-') erb.filename = "enc/#{filename}" tmp = erb.result(binding) begin Dir.mkdir 'enc' rescue Errno::EEXIST end - File.open("enc/encinit.c", "w") {|f| - f.puts "/* Automatically generated from enc/encinit.c.erb" - f.puts " * Do not edit." - f.puts " */" - f.puts tmp - } + require 'tool/lib/output' + Output.new(path: "enc/encinit.c", ifchange: true).write(tmp) end diff --git a/enc/trans/ibm864-tbl.rb b/enc/trans/ibm864-tbl.rb new file mode 100644 index 00000000000000..13f8a27f1d89cf --- /dev/null +++ b/enc/trans/ibm864-tbl.rb @@ -0,0 +1,126 @@ +IBM864_TO_UCS_TBL = [ + ["80",0x00B0], + ["81",0x00B7], + ["82",0x2219], + ["83",0x221A], + ["84",0x2592], + ["85",0x2500], + ["86",0x2502], + ["87",0x253C], + ["88",0x2524], + ["89",0x252C], + ["8A",0x251C], + ["8B",0x2534], + ["8C",0x2510], + ["8D",0x250C], + ["8E",0x2514], + ["8F",0x2518], + ["90",0x03B2], + ["91",0x221E], + ["92",0x03C6], + ["93",0x00B1], + ["94",0x00BD], + ["95",0x00BC], + ["96",0x2248], + ["97",0x00AB], + ["98",0x00BB], + ["99",0xFEF7], + ["9A",0xFEF8], + ["9D",0xFEFB], + ["9E",0xFEFC], + ["9F",0xFE73], + ["A0",0x00A0], + ["A1",0x00AD], + ["A2",0xFE82], + ["A3",0x00A3], + ["A4",0x00A4], + ["A5",0xFE84], + ["A7",0x20AC], # Euro sign from CCSID 864 + ["A8",0xFE8E], + ["A9",0xFE8F], + ["AA",0xFE95], + ["AB",0xFE99], + ["AC",0x060C], + ["AD",0xFE9D], + ["AE",0xFEA1], + ["AF",0xFEA5], + ["B0",0x0660], + ["B1",0x0661], + ["B2",0x0662], + ["B3",0x0663], + ["B4",0x0664], + ["B5",0x0665], + ["B6",0x0666], + ["B7",0x0667], + ["B8",0x0668], + ["B9",0x0669], + ["BA",0xFED1], + ["BB",0x061B], + ["BC",0xFEB1], + ["BD",0xFEB5], + ["BE",0xFEB9], + ["BF",0x061F], + ["C0",0x00A2], + ["C1",0xFE80], + ["C2",0xFE81], + ["C3",0xFE83], + ["C4",0xFE85], + ["C5",0xFECA], + ["C6",0xFE8B], + ["C7",0xFE8D], + ["C8",0xFE91], + ["C9",0xFE93], + ["CA",0xFE97], + ["CB",0xFE9B], + ["CC",0xFE9F], + ["CD",0xFEA3], + ["CE",0xFEA7], + ["CF",0xFEA9], + ["D0",0xFEAB], + ["D1",0xFEAD], + ["D2",0xFEAF], + ["D3",0xFEB3], + ["D4",0xFEB7], + ["D5",0xFEBB], + ["D6",0xFEBF], + ["D7",0xFEC1], + ["D8",0xFEC5], + ["D9",0xFECB], + ["DA",0xFECF], + ["DB",0x00A6], + ["DC",0x00AC], + ["DD",0x00F7], + ["DE",0x00D7], + ["DF",0xFEC9], + ["E0",0x0640], + ["E1",0xFED3], + ["E2",0xFED7], + ["E3",0xFEDB], + ["E4",0xFEDF], + ["E5",0xFEE3], + ["E6",0xFEE7], + ["E7",0xFEEB], + ["E8",0xFEED], + ["E9",0xFEEF], + ["EA",0xFEF3], + ["EB",0xFEBD], + ["EC",0xFECC], + ["ED",0xFECE], + ["EE",0xFECD], + ["EF",0xFEE1], + ["F0",0xFE7D], + ["F1",0x0651], + ["F2",0xFEE5], + ["F3",0xFEE9], + ["F4",0xFEEC], + ["F5",0xFEF0], + ["F6",0xFEF2], + ["F7",0xFED0], + ["F8",0xFED5], + ["F9",0xFEF5], + ["FA",0xFEF6], + ["FB",0xFEDD], + ["FC",0xFED9], + ["FD",0xFEF1], + ["FE",0x25A0] +] diff --git a/enc/trans/iso2022.trans b/enc/trans/iso2022.trans index a441f1596dc6ca..bc42bbc19c3c05 100644 --- a/enc/trans/iso2022.trans +++ b/enc/trans/iso2022.trans @@ -1,4 +1,5 @@ #include "transcode_data.h" +#include "ruby/internal/attr/nonstring.h" <% map = { @@ -79,6 +80,34 @@ iso2022jp_init(void *statep) return 0; } +static unsigned char * +iso2022jp_put_state(unsigned char *sp, unsigned char *o, int oldstate, int newstate) +{ + if (oldstate != newstate) { + *o++ = 0x1b; + switch (newstate) { + case G0_ASCII: + *o++ = '('; + *o++ = 'B'; + break; + case G0_JISX0201_KATAKANA: + *o++ = '('; + *o++ = 'I'; + break; + case G0_JISX0208_1978: + *o++ = '$'; + *o++ = '@'; + break; + default: + *o++ = '$'; + *o++ = 'B'; + break; + } + *sp = newstate; + } + return o; +} + static VALUE fun_si_iso2022jp_decoder(void *statep, const unsigned char *s, size_t l) { @@ -154,24 +183,7 @@ fun_so_iso2022jp_encoder(void *statep, const unsigned char *s, size_t l, unsigne else newstate = G0_JISX0208_1983; - if (*sp != newstate) { - if (newstate == G0_ASCII) { - *o++ = 0x1b; - *o++ = '('; - *o++ = 'B'; - } - else if (newstate == G0_JISX0208_1978) { - *o++ = 0x1b; - *o++ = '$'; - *o++ = '@'; - } - else { - *o++ = 0x1b; - *o++ = '$'; - *o++ = 'B'; - } - *sp = newstate; - } + o = iso2022jp_put_state(sp, o, *sp, newstate); if (l == 1) { *o++ = s[0] & 0x7f; @@ -202,10 +214,7 @@ finish_iso2022jp_encoder(void *statep, unsigned char *o, size_t osize) if (*sp == G0_ASCII) return 0; - *o++ = 0x1b; - *o++ = '('; - *o++ = 'B'; - *sp = G0_ASCII; + o = iso2022jp_put_state(sp, o, *sp, G0_ASCII); return o - output0; } @@ -399,24 +408,7 @@ fun_so_cp5022x_encoder(void *statep, const unsigned char *s, size_t l, else newstate = G0_JISX0208_1983; - if (*sp != newstate) { - if (newstate == G0_ASCII) { - *o++ = 0x1b; - *o++ = '('; - *o++ = 'B'; - } - else if (newstate == G0_JISX0201_KATAKANA) { - *o++ = 0x1b; - *o++ = '('; - *o++ = 'I'; - } - else { - *o++ = 0x1b; - *o++ = '$'; - *o++ = 'B'; - } - *sp = newstate; - } + o = iso2022jp_put_state(sp, o, sp[0], newstate); if (l == 1) { *o++ = s[0] & 0x7f; @@ -443,15 +435,26 @@ rb_cp50221_encoder = { iso2022jp_encoder_reset_sequence_size, finish_iso2022jp_encoder }; -static const char *tbl0208 = - "\x21\x23\x21\x56\x21\x57\x21\x22\x21\x26\x25\x72\x25\x21\x25\x23" \ - "\x25\x25\x25\x27\x25\x29\x25\x63\x25\x65\x25\x67\x25\x43\x21\x3C" \ - "\x25\x22\x25\x24\x25\x26\x25\x28\x25\x2A\x25\x2B\x25\x2D\x25\x2F" \ - "\x25\x31\x25\x33\x25\x35\x25\x37\x25\x39\x25\x3B\x25\x3D\x25\x3F" \ - "\x25\x41\x25\x44\x25\x46\x25\x48\x25\x4A\x25\x4B\x25\x4C\x25\x4D" \ - "\x25\x4E\x25\x4F\x25\x52\x25\x55\x25\x58\x25\x5B\x25\x5E\x25\x5F" \ - "\x25\x60\x25\x61\x25\x62\x25\x64\x25\x66\x25\x68\x25\x69\x25\x6A" \ - "\x25\x6B\x25\x6C\x25\x6D\x25\x6F\x25\x73\x21\x2B\x21\x2C"; +/* JIS0201 to JIS0208 conversion table */ +enum {tbl0208_num = 0xDF - 0xA1 + 1}; +RBIMPL_ATTR_NONSTRING_ARRAY() static const char tbl0208[tbl0208_num][2] = { + "\x21\x23", "\x21\x56", "\x21\x57", "\x21\x22", + "\x21\x26", "\x25\x72", "\x25\x21", "\x25\x23", + "\x25\x25", "\x25\x27", "\x25\x29", "\x25\x63", + "\x25\x65", "\x25\x67", "\x25\x43", "\x21\x3C", + "\x25\x22", "\x25\x24", "\x25\x26", "\x25\x28", + "\x25\x2A", "\x25\x2B", "\x25\x2D", "\x25\x2F", + "\x25\x31", "\x25\x33", "\x25\x35", "\x25\x37", + "\x25\x39", "\x25\x3B", "\x25\x3D", "\x25\x3F", + "\x25\x41", "\x25\x44", "\x25\x46", "\x25\x48", + "\x25\x4A", "\x25\x4B", "\x25\x4C", "\x25\x4D", + "\x25\x4E", "\x25\x4F", "\x25\x52", "\x25\x55", + "\x25\x58", "\x25\x5B", "\x25\x5E", "\x25\x5F", + "\x25\x60", "\x25\x61", "\x25\x62", "\x25\x64", + "\x25\x66", "\x25\x68", "\x25\x69", "\x25\x6A", + "\x25\x6B", "\x25\x6C", "\x25\x6D", "\x25\x6F", + "\x25\x73", "\x21\x2B", "\x21\x2C" +}; static ssize_t fun_so_cp50220_encoder(void *statep, const unsigned char *s, size_t l, @@ -460,22 +463,21 @@ fun_so_cp50220_encoder(void *statep, const unsigned char *s, size_t l, unsigned char *output0 = o; unsigned char *sp = statep; - if (sp[0] == G0_JISX0201_KATAKANA) { + if (sp[0] == G0_JISX0201_KATAKANA && sp[2]) { int c = sp[2] & 0x7F; - const char *p = tbl0208 + (c - 0x21) * 2; - if (sp[1] != G0_JISX0208_1983) { - *o++ = 0x1b; - *o++ = '$'; - *o++ = 'B'; - } + const char *p = tbl0208[c - 0x21]; + sp[2] = 0; + o = iso2022jp_put_state(sp, o, sp[1], G0_JISX0208_1983); sp[0] = G0_JISX0208_1983; *o++ = *p++; if (l == 2 && s[0] == 0x8E) { if (s[1] == 0xDE) { + /* VOICED SOUND MARK */ *o++ = *p + 1; return o - output0; } else if (s[1] == 0xDF && (0x4A <= c && c <= 0x4E)) { + /* SEMI-VOICED SOUND MARK */ *o++ = *p + 2; return o - output0; } @@ -484,21 +486,25 @@ fun_so_cp50220_encoder(void *statep, const unsigned char *s, size_t l, } if (l == 2 && s[0] == 0x8E) { - const char *p = tbl0208 + (s[1] - 0xA1) * 2; if ((0xA1 <= s[1] && s[1] <= 0xB5) || (0xC5 <= s[1] && s[1] <= 0xC9) || (0xCF <= s[1] && s[1] <= 0xDF)) { - if (*sp != G0_JISX0208_1983) { - *o++ = 0x1b; - *o++ = '$'; - *o++ = 'B'; - *sp = G0_JISX0208_1983; - } + /* May not be followed by a sound mark */ + const char *p = tbl0208[s[1] - 0xA1]; + o = iso2022jp_put_state(sp, o, *sp, G0_JISX0208_1983); *o++ = *p++; *o++ = *p; return o - output0; } + if (s[1] > 0xDF) { /* undef */ + o = iso2022jp_put_state(sp, o, *sp, G0_JISX0201_KATAKANA); + *o++ = s[1] & 0x7F; + sp[2] = 0; + return o - output0; + } + + /* Katakana that may be followed by a sound mark */ sp[2] = s[1]; sp[1] = sp[0]; sp[0] = G0_JISX0201_KATAKANA; @@ -518,23 +524,16 @@ finish_cp50220_encoder(void *statep, unsigned char *o, size_t osize) if (*sp == G0_ASCII) return 0; - if (sp[0] == G0_JISX0201_KATAKANA) { + if (sp[0] == G0_JISX0201_KATAKANA && sp[2]) { int c = sp[2] & 0x7F; - const char *p = tbl0208 + (c - 0x21) * 2; - if (sp[1] != G0_JISX0208_1983) { - *o++ = 0x1b; - *o++ = '$'; - *o++ = 'B'; - } + const char *p = tbl0208[c - 0x21]; + o = iso2022jp_put_state(sp, o, sp[1], G0_JISX0208_1983); sp[0] = G0_JISX0208_1983; *o++ = *p++; *o++ = *p; } - *o++ = 0x1b; - *o++ = '('; - *o++ = 'B'; - *sp = G0_ASCII; + o = iso2022jp_put_state(sp, o, sp[0], G0_ASCII); return o - output0; } @@ -564,4 +563,3 @@ TRANS_INIT(iso2022) rb_register_transcoder(&rb_cp50220_encoder); rb_register_transcoder(&rb_cp50221_encoder); } - diff --git a/enc/trans/single_byte.trans b/enc/trans/single_byte.trans index 0d5407b9188bf4..c326cbebea1143 100644 --- a/enc/trans/single_byte.trans +++ b/enc/trans/single_byte.trans @@ -61,6 +61,7 @@ transcode_tblgen_singlebyte "IBM861" transcode_tblgen_singlebyte "IBM862" transcode_tblgen_singlebyte "IBM863" + transcode_tblgen_singlebyte "IBM864" transcode_tblgen_singlebyte "IBM865" transcode_tblgen_singlebyte "IBM866" transcode_tblgen_singlebyte "IBM869" diff --git a/enc/unicode.c b/enc/unicode.c index 18fba02476af66..cbfc6cdf589681 100644 --- a/enc/unicode.c +++ b/enc/unicode.c @@ -801,7 +801,6 @@ onigenc_unicode_case_map(OnigCaseFoldType* flagP, return (int )(to - to_start); } -#if 0 const char onigenc_unicode_version_string[] = #ifdef ONIG_UNICODE_VERSION_STRING ONIG_UNICODE_VERSION_STRING @@ -817,4 +816,3 @@ const int onigenc_unicode_version_number[3] = { 0 #endif }; -#endif diff --git a/enc/unicode/15.0.0/casefold.h b/enc/unicode/15.0.0/casefold.h deleted file mode 100644 index 51120d867d1794..00000000000000 --- a/enc/unicode/15.0.0/casefold.h +++ /dev/null @@ -1,7629 +0,0 @@ -/* DO NOT EDIT THIS FILE. */ -/* Generated by enc-case-folding.rb */ - -#if defined ONIG_UNICODE_VERSION_STRING && !( \ - ONIG_UNICODE_VERSION_MAJOR == 15 && \ - ONIG_UNICODE_VERSION_MINOR == 0 && \ - ONIG_UNICODE_VERSION_TEENY == 0 && \ - 1) -# error ONIG_UNICODE_VERSION_STRING mismatch -#endif -#define ONIG_UNICODE_VERSION_STRING "15.0.0" -#define ONIG_UNICODE_VERSION_MAJOR 15 -#define ONIG_UNICODE_VERSION_MINOR 0 -#define ONIG_UNICODE_VERSION_TEENY 0 - -static const CaseFold_11_Type CaseFold_11_Table[] = { -#define CaseFold (*(CaseFold_11_Type (*)[1528])(CaseFold_11_Table+0)) - {0x0041, {1|F|D, {0x0061}}}, - {0x0042, {1|F|D, {0x0062}}}, - {0x0043, {1|F|D, {0x0063}}}, - {0x0044, {1|F|D, {0x0064}}}, - {0x0045, {1|F|D, {0x0065}}}, - {0x0046, {1|F|D, {0x0066}}}, - {0x0047, {1|F|D, {0x0067}}}, - {0x0048, {1|F|D, {0x0068}}}, - {0x004a, {1|F|D, {0x006a}}}, - {0x004b, {1|F|D, {0x006b}}}, - {0x004c, {1|F|D, {0x006c}}}, - {0x004d, {1|F|D, {0x006d}}}, - {0x004e, {1|F|D, {0x006e}}}, - {0x004f, {1|F|D, {0x006f}}}, - {0x0050, {1|F|D, {0x0070}}}, - {0x0051, {1|F|D, {0x0071}}}, - {0x0052, {1|F|D, {0x0072}}}, - {0x0053, {1|F|D, {0x0073}}}, - {0x0054, {1|F|D, {0x0074}}}, - {0x0055, {1|F|D, {0x0075}}}, - {0x0056, {1|F|D, {0x0076}}}, - {0x0057, {1|F|D, {0x0077}}}, - {0x0058, {1|F|D, {0x0078}}}, - {0x0059, {1|F|D, {0x0079}}}, - {0x005a, {1|F|D, {0x007a}}}, - {0x00b5, {1|F|SU|I(0), {0x03bc}}}, - {0x00c0, {1|F|D, {0x00e0}}}, - {0x00c1, {1|F|D, {0x00e1}}}, - {0x00c2, {1|F|D, {0x00e2}}}, - {0x00c3, {1|F|D, {0x00e3}}}, - {0x00c4, {1|F|D, {0x00e4}}}, - {0x00c5, {1|F|D, {0x00e5}}}, - {0x00c6, {1|F|D, {0x00e6}}}, - {0x00c7, {1|F|D, {0x00e7}}}, - {0x00c8, {1|F|D, {0x00e8}}}, - {0x00c9, {1|F|D, {0x00e9}}}, - {0x00ca, {1|F|D, {0x00ea}}}, - {0x00cb, {1|F|D, {0x00eb}}}, - {0x00cc, {1|F|D, {0x00ec}}}, - {0x00cd, {1|F|D, {0x00ed}}}, - {0x00ce, {1|F|D, {0x00ee}}}, - {0x00cf, {1|F|D, {0x00ef}}}, - {0x00d0, {1|F|D, {0x00f0}}}, - {0x00d1, {1|F|D, {0x00f1}}}, - {0x00d2, {1|F|D, {0x00f2}}}, - {0x00d3, {1|F|D, {0x00f3}}}, - {0x00d4, {1|F|D, {0x00f4}}}, - {0x00d5, {1|F|D, {0x00f5}}}, - {0x00d6, {1|F|D, {0x00f6}}}, - {0x00d8, {1|F|D, {0x00f8}}}, - {0x00d9, {1|F|D, {0x00f9}}}, - {0x00da, {1|F|D, {0x00fa}}}, - {0x00db, {1|F|D, {0x00fb}}}, - {0x00dc, {1|F|D, {0x00fc}}}, - {0x00dd, {1|F|D, {0x00fd}}}, - {0x00de, {1|F|D, {0x00fe}}}, - {0x00df, {2|F|ST|SU|I(1), {0x0073, 0x0073}}}, - {0x0100, {1|F|D, {0x0101}}}, - {0x0102, {1|F|D, {0x0103}}}, - {0x0104, {1|F|D, {0x0105}}}, - {0x0106, {1|F|D, {0x0107}}}, - {0x0108, {1|F|D, {0x0109}}}, - {0x010a, {1|F|D, {0x010b}}}, - {0x010c, {1|F|D, {0x010d}}}, - {0x010e, {1|F|D, {0x010f}}}, - {0x0110, {1|F|D, {0x0111}}}, - {0x0112, {1|F|D, {0x0113}}}, - {0x0114, {1|F|D, {0x0115}}}, - {0x0116, {1|F|D, {0x0117}}}, - {0x0118, {1|F|D, {0x0119}}}, - {0x011a, {1|F|D, {0x011b}}}, - {0x011c, {1|F|D, {0x011d}}}, - {0x011e, {1|F|D, {0x011f}}}, - {0x0120, {1|F|D, {0x0121}}}, - {0x0122, {1|F|D, {0x0123}}}, - {0x0124, {1|F|D, {0x0125}}}, - {0x0126, {1|F|D, {0x0127}}}, - {0x0128, {1|F|D, {0x0129}}}, - {0x012a, {1|F|D, {0x012b}}}, - {0x012c, {1|F|D, {0x012d}}}, - {0x012e, {1|F|D, {0x012f}}}, - {0x0132, {1|F|D, {0x0133}}}, - {0x0134, {1|F|D, {0x0135}}}, - {0x0136, {1|F|D, {0x0137}}}, - {0x0139, {1|F|D, {0x013a}}}, - {0x013b, {1|F|D, {0x013c}}}, - {0x013d, {1|F|D, {0x013e}}}, - {0x013f, {1|F|D, {0x0140}}}, - {0x0141, {1|F|D, {0x0142}}}, - {0x0143, {1|F|D, {0x0144}}}, - {0x0145, {1|F|D, {0x0146}}}, - {0x0147, {1|F|D, {0x0148}}}, - {0x0149, {2|F|SU|I(5), {0x02bc, 0x006e}}}, - {0x014a, {1|F|D, {0x014b}}}, - {0x014c, {1|F|D, {0x014d}}}, - {0x014e, {1|F|D, {0x014f}}}, - {0x0150, {1|F|D, {0x0151}}}, - {0x0152, {1|F|D, {0x0153}}}, - {0x0154, {1|F|D, {0x0155}}}, - {0x0156, {1|F|D, {0x0157}}}, - {0x0158, {1|F|D, {0x0159}}}, - {0x015a, {1|F|D, {0x015b}}}, - {0x015c, {1|F|D, {0x015d}}}, - {0x015e, {1|F|D, {0x015f}}}, - {0x0160, {1|F|D, {0x0161}}}, - {0x0162, {1|F|D, {0x0163}}}, - {0x0164, {1|F|D, {0x0165}}}, - {0x0166, {1|F|D, {0x0167}}}, - {0x0168, {1|F|D, {0x0169}}}, - {0x016a, {1|F|D, {0x016b}}}, - {0x016c, {1|F|D, {0x016d}}}, - {0x016e, {1|F|D, {0x016f}}}, - {0x0170, {1|F|D, {0x0171}}}, - {0x0172, {1|F|D, {0x0173}}}, - {0x0174, {1|F|D, {0x0175}}}, - {0x0176, {1|F|D, {0x0177}}}, - {0x0178, {1|F|D, {0x00ff}}}, - {0x0179, {1|F|D, {0x017a}}}, - {0x017b, {1|F|D, {0x017c}}}, - {0x017d, {1|F|D, {0x017e}}}, - {0x017f, {1|F|SU|I(7), {0x0073}}}, - {0x0181, {1|F|D, {0x0253}}}, - {0x0182, {1|F|D, {0x0183}}}, - {0x0184, {1|F|D, {0x0185}}}, - {0x0186, {1|F|D, {0x0254}}}, - {0x0187, {1|F|D, {0x0188}}}, - {0x0189, {1|F|D, {0x0256}}}, - {0x018a, {1|F|D, {0x0257}}}, - {0x018b, {1|F|D, {0x018c}}}, - {0x018e, {1|F|D, {0x01dd}}}, - {0x018f, {1|F|D, {0x0259}}}, - {0x0190, {1|F|D, {0x025b}}}, - {0x0191, {1|F|D, {0x0192}}}, - {0x0193, {1|F|D, {0x0260}}}, - {0x0194, {1|F|D, {0x0263}}}, - {0x0196, {1|F|D, {0x0269}}}, - {0x0197, {1|F|D, {0x0268}}}, - {0x0198, {1|F|D, {0x0199}}}, - {0x019c, {1|F|D, {0x026f}}}, - {0x019d, {1|F|D, {0x0272}}}, - {0x019f, {1|F|D, {0x0275}}}, - {0x01a0, {1|F|D, {0x01a1}}}, - {0x01a2, {1|F|D, {0x01a3}}}, - {0x01a4, {1|F|D, {0x01a5}}}, - {0x01a6, {1|F|D, {0x0280}}}, - {0x01a7, {1|F|D, {0x01a8}}}, - {0x01a9, {1|F|D, {0x0283}}}, - {0x01ac, {1|F|D, {0x01ad}}}, - {0x01ae, {1|F|D, {0x0288}}}, - {0x01af, {1|F|D, {0x01b0}}}, - {0x01b1, {1|F|D, {0x028a}}}, - {0x01b2, {1|F|D, {0x028b}}}, - {0x01b3, {1|F|D, {0x01b4}}}, - {0x01b5, {1|F|D, {0x01b6}}}, - {0x01b7, {1|F|D, {0x0292}}}, - {0x01b8, {1|F|D, {0x01b9}}}, - {0x01bc, {1|F|D, {0x01bd}}}, - {0x01c4, {1|F|D|ST|I(8), {0x01c6}}}, - {0x01c5, {1|F|D|IT|SU|I(9), {0x01c6}}}, - {0x01c7, {1|F|D|ST|I(12), {0x01c9}}}, - {0x01c8, {1|F|D|IT|SU|I(13), {0x01c9}}}, - {0x01ca, {1|F|D|ST|I(16), {0x01cc}}}, - {0x01cb, {1|F|D|IT|SU|I(17), {0x01cc}}}, - {0x01cd, {1|F|D, {0x01ce}}}, - {0x01cf, {1|F|D, {0x01d0}}}, - {0x01d1, {1|F|D, {0x01d2}}}, - {0x01d3, {1|F|D, {0x01d4}}}, - {0x01d5, {1|F|D, {0x01d6}}}, - {0x01d7, {1|F|D, {0x01d8}}}, - {0x01d9, {1|F|D, {0x01da}}}, - {0x01db, {1|F|D, {0x01dc}}}, - {0x01de, {1|F|D, {0x01df}}}, - {0x01e0, {1|F|D, {0x01e1}}}, - {0x01e2, {1|F|D, {0x01e3}}}, - {0x01e4, {1|F|D, {0x01e5}}}, - {0x01e6, {1|F|D, {0x01e7}}}, - {0x01e8, {1|F|D, {0x01e9}}}, - {0x01ea, {1|F|D, {0x01eb}}}, - {0x01ec, {1|F|D, {0x01ed}}}, - {0x01ee, {1|F|D, {0x01ef}}}, - {0x01f0, {2|F|SU|I(20), {0x006a, 0x030c}}}, - {0x01f1, {1|F|D|ST|I(22), {0x01f3}}}, - {0x01f2, {1|F|D|IT|SU|I(23), {0x01f3}}}, - {0x01f4, {1|F|D, {0x01f5}}}, - {0x01f6, {1|F|D, {0x0195}}}, - {0x01f7, {1|F|D, {0x01bf}}}, - {0x01f8, {1|F|D, {0x01f9}}}, - {0x01fa, {1|F|D, {0x01fb}}}, - {0x01fc, {1|F|D, {0x01fd}}}, - {0x01fe, {1|F|D, {0x01ff}}}, - {0x0200, {1|F|D, {0x0201}}}, - {0x0202, {1|F|D, {0x0203}}}, - {0x0204, {1|F|D, {0x0205}}}, - {0x0206, {1|F|D, {0x0207}}}, - {0x0208, {1|F|D, {0x0209}}}, - {0x020a, {1|F|D, {0x020b}}}, - {0x020c, {1|F|D, {0x020d}}}, - {0x020e, {1|F|D, {0x020f}}}, - {0x0210, {1|F|D, {0x0211}}}, - {0x0212, {1|F|D, {0x0213}}}, - {0x0214, {1|F|D, {0x0215}}}, - {0x0216, {1|F|D, {0x0217}}}, - {0x0218, {1|F|D, {0x0219}}}, - {0x021a, {1|F|D, {0x021b}}}, - {0x021c, {1|F|D, {0x021d}}}, - {0x021e, {1|F|D, {0x021f}}}, - {0x0220, {1|F|D, {0x019e}}}, - {0x0222, {1|F|D, {0x0223}}}, - {0x0224, {1|F|D, {0x0225}}}, - {0x0226, {1|F|D, {0x0227}}}, - {0x0228, {1|F|D, {0x0229}}}, - {0x022a, {1|F|D, {0x022b}}}, - {0x022c, {1|F|D, {0x022d}}}, - {0x022e, {1|F|D, {0x022f}}}, - {0x0230, {1|F|D, {0x0231}}}, - {0x0232, {1|F|D, {0x0233}}}, - {0x023a, {1|F|D, {0x2c65}}}, - {0x023b, {1|F|D, {0x023c}}}, - {0x023d, {1|F|D, {0x019a}}}, - {0x023e, {1|F|D, {0x2c66}}}, - {0x0241, {1|F|D, {0x0242}}}, - {0x0243, {1|F|D, {0x0180}}}, - {0x0244, {1|F|D, {0x0289}}}, - {0x0245, {1|F|D, {0x028c}}}, - {0x0246, {1|F|D, {0x0247}}}, - {0x0248, {1|F|D, {0x0249}}}, - {0x024a, {1|F|D, {0x024b}}}, - {0x024c, {1|F|D, {0x024d}}}, - {0x024e, {1|F|D, {0x024f}}}, - {0x0345, {1|F|SU|I(26), {0x03b9}}}, - {0x0370, {1|F|D, {0x0371}}}, - {0x0372, {1|F|D, {0x0373}}}, - {0x0376, {1|F|D, {0x0377}}}, - {0x037f, {1|F|D, {0x03f3}}}, - {0x0386, {1|F|D, {0x03ac}}}, - {0x0388, {1|F|D, {0x03ad}}}, - {0x0389, {1|F|D, {0x03ae}}}, - {0x038a, {1|F|D, {0x03af}}}, - {0x038c, {1|F|D, {0x03cc}}}, - {0x038e, {1|F|D, {0x03cd}}}, - {0x038f, {1|F|D, {0x03ce}}}, - {0x0390, {3|F|SU|I(27), {0x03b9, 0x0308, 0x0301}}}, - {0x0391, {1|F|D, {0x03b1}}}, - {0x0392, {1|F|D, {0x03b2}}}, - {0x0393, {1|F|D, {0x03b3}}}, - {0x0394, {1|F|D, {0x03b4}}}, - {0x0395, {1|F|D, {0x03b5}}}, - {0x0396, {1|F|D, {0x03b6}}}, - {0x0397, {1|F|D, {0x03b7}}}, - {0x0398, {1|F|D, {0x03b8}}}, - {0x0399, {1|F|D, {0x03b9}}}, - {0x039a, {1|F|D, {0x03ba}}}, - {0x039b, {1|F|D, {0x03bb}}}, - {0x039c, {1|F|D, {0x03bc}}}, - {0x039d, {1|F|D, {0x03bd}}}, - {0x039e, {1|F|D, {0x03be}}}, - {0x039f, {1|F|D, {0x03bf}}}, - {0x03a0, {1|F|D, {0x03c0}}}, - {0x03a1, {1|F|D, {0x03c1}}}, - {0x03a3, {1|F|D, {0x03c3}}}, - {0x03a4, {1|F|D, {0x03c4}}}, - {0x03a5, {1|F|D, {0x03c5}}}, - {0x03a6, {1|F|D, {0x03c6}}}, - {0x03a7, {1|F|D, {0x03c7}}}, - {0x03a8, {1|F|D, {0x03c8}}}, - {0x03a9, {1|F|D, {0x03c9}}}, - {0x03aa, {1|F|D, {0x03ca}}}, - {0x03ab, {1|F|D, {0x03cb}}}, - {0x03b0, {3|F|SU|I(30), {0x03c5, 0x0308, 0x0301}}}, - {0x03c2, {1|F|SU|I(33), {0x03c3}}}, - {0x03cf, {1|F|D, {0x03d7}}}, - {0x03d0, {1|F|SU|I(34), {0x03b2}}}, - {0x03d1, {1|F|SU|I(35), {0x03b8}}}, - {0x03d5, {1|F|SU|I(36), {0x03c6}}}, - {0x03d6, {1|F|SU|I(37), {0x03c0}}}, - {0x03d8, {1|F|D, {0x03d9}}}, - {0x03da, {1|F|D, {0x03db}}}, - {0x03dc, {1|F|D, {0x03dd}}}, - {0x03de, {1|F|D, {0x03df}}}, - {0x03e0, {1|F|D, {0x03e1}}}, - {0x03e2, {1|F|D, {0x03e3}}}, - {0x03e4, {1|F|D, {0x03e5}}}, - {0x03e6, {1|F|D, {0x03e7}}}, - {0x03e8, {1|F|D, {0x03e9}}}, - {0x03ea, {1|F|D, {0x03eb}}}, - {0x03ec, {1|F|D, {0x03ed}}}, - {0x03ee, {1|F|D, {0x03ef}}}, - {0x03f0, {1|F|SU|I(38), {0x03ba}}}, - {0x03f1, {1|F|SU|I(39), {0x03c1}}}, - {0x03f4, {1|F|D, {0x03b8}}}, - {0x03f5, {1|F|SU|I(40), {0x03b5}}}, - {0x03f7, {1|F|D, {0x03f8}}}, - {0x03f9, {1|F|D, {0x03f2}}}, - {0x03fa, {1|F|D, {0x03fb}}}, - {0x03fd, {1|F|D, {0x037b}}}, - {0x03fe, {1|F|D, {0x037c}}}, - {0x03ff, {1|F|D, {0x037d}}}, - {0x0400, {1|F|D, {0x0450}}}, - {0x0401, {1|F|D, {0x0451}}}, - {0x0402, {1|F|D, {0x0452}}}, - {0x0403, {1|F|D, {0x0453}}}, - {0x0404, {1|F|D, {0x0454}}}, - {0x0405, {1|F|D, {0x0455}}}, - {0x0406, {1|F|D, {0x0456}}}, - {0x0407, {1|F|D, {0x0457}}}, - {0x0408, {1|F|D, {0x0458}}}, - {0x0409, {1|F|D, {0x0459}}}, - {0x040a, {1|F|D, {0x045a}}}, - {0x040b, {1|F|D, {0x045b}}}, - {0x040c, {1|F|D, {0x045c}}}, - {0x040d, {1|F|D, {0x045d}}}, - {0x040e, {1|F|D, {0x045e}}}, - {0x040f, {1|F|D, {0x045f}}}, - {0x0410, {1|F|D, {0x0430}}}, - {0x0411, {1|F|D, {0x0431}}}, - {0x0412, {1|F|D, {0x0432}}}, - {0x0413, {1|F|D, {0x0433}}}, - {0x0414, {1|F|D, {0x0434}}}, - {0x0415, {1|F|D, {0x0435}}}, - {0x0416, {1|F|D, {0x0436}}}, - {0x0417, {1|F|D, {0x0437}}}, - {0x0418, {1|F|D, {0x0438}}}, - {0x0419, {1|F|D, {0x0439}}}, - {0x041a, {1|F|D, {0x043a}}}, - {0x041b, {1|F|D, {0x043b}}}, - {0x041c, {1|F|D, {0x043c}}}, - {0x041d, {1|F|D, {0x043d}}}, - {0x041e, {1|F|D, {0x043e}}}, - {0x041f, {1|F|D, {0x043f}}}, - {0x0420, {1|F|D, {0x0440}}}, - {0x0421, {1|F|D, {0x0441}}}, - {0x0422, {1|F|D, {0x0442}}}, - {0x0423, {1|F|D, {0x0443}}}, - {0x0424, {1|F|D, {0x0444}}}, - {0x0425, {1|F|D, {0x0445}}}, - {0x0426, {1|F|D, {0x0446}}}, - {0x0427, {1|F|D, {0x0447}}}, - {0x0428, {1|F|D, {0x0448}}}, - {0x0429, {1|F|D, {0x0449}}}, - {0x042a, {1|F|D, {0x044a}}}, - {0x042b, {1|F|D, {0x044b}}}, - {0x042c, {1|F|D, {0x044c}}}, - {0x042d, {1|F|D, {0x044d}}}, - {0x042e, {1|F|D, {0x044e}}}, - {0x042f, {1|F|D, {0x044f}}}, - {0x0460, {1|F|D, {0x0461}}}, - {0x0462, {1|F|D, {0x0463}}}, - {0x0464, {1|F|D, {0x0465}}}, - {0x0466, {1|F|D, {0x0467}}}, - {0x0468, {1|F|D, {0x0469}}}, - {0x046a, {1|F|D, {0x046b}}}, - {0x046c, {1|F|D, {0x046d}}}, - {0x046e, {1|F|D, {0x046f}}}, - {0x0470, {1|F|D, {0x0471}}}, - {0x0472, {1|F|D, {0x0473}}}, - {0x0474, {1|F|D, {0x0475}}}, - {0x0476, {1|F|D, {0x0477}}}, - {0x0478, {1|F|D, {0x0479}}}, - {0x047a, {1|F|D, {0x047b}}}, - {0x047c, {1|F|D, {0x047d}}}, - {0x047e, {1|F|D, {0x047f}}}, - {0x0480, {1|F|D, {0x0481}}}, - {0x048a, {1|F|D, {0x048b}}}, - {0x048c, {1|F|D, {0x048d}}}, - {0x048e, {1|F|D, {0x048f}}}, - {0x0490, {1|F|D, {0x0491}}}, - {0x0492, {1|F|D, {0x0493}}}, - {0x0494, {1|F|D, {0x0495}}}, - {0x0496, {1|F|D, {0x0497}}}, - {0x0498, {1|F|D, {0x0499}}}, - {0x049a, {1|F|D, {0x049b}}}, - {0x049c, {1|F|D, {0x049d}}}, - {0x049e, {1|F|D, {0x049f}}}, - {0x04a0, {1|F|D, {0x04a1}}}, - {0x04a2, {1|F|D, {0x04a3}}}, - {0x04a4, {1|F|D, {0x04a5}}}, - {0x04a6, {1|F|D, {0x04a7}}}, - {0x04a8, {1|F|D, {0x04a9}}}, - {0x04aa, {1|F|D, {0x04ab}}}, - {0x04ac, {1|F|D, {0x04ad}}}, - {0x04ae, {1|F|D, {0x04af}}}, - {0x04b0, {1|F|D, {0x04b1}}}, - {0x04b2, {1|F|D, {0x04b3}}}, - {0x04b4, {1|F|D, {0x04b5}}}, - {0x04b6, {1|F|D, {0x04b7}}}, - {0x04b8, {1|F|D, {0x04b9}}}, - {0x04ba, {1|F|D, {0x04bb}}}, - {0x04bc, {1|F|D, {0x04bd}}}, - {0x04be, {1|F|D, {0x04bf}}}, - {0x04c0, {1|F|D, {0x04cf}}}, - {0x04c1, {1|F|D, {0x04c2}}}, - {0x04c3, {1|F|D, {0x04c4}}}, - {0x04c5, {1|F|D, {0x04c6}}}, - {0x04c7, {1|F|D, {0x04c8}}}, - {0x04c9, {1|F|D, {0x04ca}}}, - {0x04cb, {1|F|D, {0x04cc}}}, - {0x04cd, {1|F|D, {0x04ce}}}, - {0x04d0, {1|F|D, {0x04d1}}}, - {0x04d2, {1|F|D, {0x04d3}}}, - {0x04d4, {1|F|D, {0x04d5}}}, - {0x04d6, {1|F|D, {0x04d7}}}, - {0x04d8, {1|F|D, {0x04d9}}}, - {0x04da, {1|F|D, {0x04db}}}, - {0x04dc, {1|F|D, {0x04dd}}}, - {0x04de, {1|F|D, {0x04df}}}, - {0x04e0, {1|F|D, {0x04e1}}}, - {0x04e2, {1|F|D, {0x04e3}}}, - {0x04e4, {1|F|D, {0x04e5}}}, - {0x04e6, {1|F|D, {0x04e7}}}, - {0x04e8, {1|F|D, {0x04e9}}}, - {0x04ea, {1|F|D, {0x04eb}}}, - {0x04ec, {1|F|D, {0x04ed}}}, - {0x04ee, {1|F|D, {0x04ef}}}, - {0x04f0, {1|F|D, {0x04f1}}}, - {0x04f2, {1|F|D, {0x04f3}}}, - {0x04f4, {1|F|D, {0x04f5}}}, - {0x04f6, {1|F|D, {0x04f7}}}, - {0x04f8, {1|F|D, {0x04f9}}}, - {0x04fa, {1|F|D, {0x04fb}}}, - {0x04fc, {1|F|D, {0x04fd}}}, - {0x04fe, {1|F|D, {0x04ff}}}, - {0x0500, {1|F|D, {0x0501}}}, - {0x0502, {1|F|D, {0x0503}}}, - {0x0504, {1|F|D, {0x0505}}}, - {0x0506, {1|F|D, {0x0507}}}, - {0x0508, {1|F|D, {0x0509}}}, - {0x050a, {1|F|D, {0x050b}}}, - {0x050c, {1|F|D, {0x050d}}}, - {0x050e, {1|F|D, {0x050f}}}, - {0x0510, {1|F|D, {0x0511}}}, - {0x0512, {1|F|D, {0x0513}}}, - {0x0514, {1|F|D, {0x0515}}}, - {0x0516, {1|F|D, {0x0517}}}, - {0x0518, {1|F|D, {0x0519}}}, - {0x051a, {1|F|D, {0x051b}}}, - {0x051c, {1|F|D, {0x051d}}}, - {0x051e, {1|F|D, {0x051f}}}, - {0x0520, {1|F|D, {0x0521}}}, - {0x0522, {1|F|D, {0x0523}}}, - {0x0524, {1|F|D, {0x0525}}}, - {0x0526, {1|F|D, {0x0527}}}, - {0x0528, {1|F|D, {0x0529}}}, - {0x052a, {1|F|D, {0x052b}}}, - {0x052c, {1|F|D, {0x052d}}}, - {0x052e, {1|F|D, {0x052f}}}, - {0x0531, {1|F|D, {0x0561}}}, - {0x0532, {1|F|D, {0x0562}}}, - {0x0533, {1|F|D, {0x0563}}}, - {0x0534, {1|F|D, {0x0564}}}, - {0x0535, {1|F|D, {0x0565}}}, - {0x0536, {1|F|D, {0x0566}}}, - {0x0537, {1|F|D, {0x0567}}}, - {0x0538, {1|F|D, {0x0568}}}, - {0x0539, {1|F|D, {0x0569}}}, - {0x053a, {1|F|D, {0x056a}}}, - {0x053b, {1|F|D, {0x056b}}}, - {0x053c, {1|F|D, {0x056c}}}, - {0x053d, {1|F|D, {0x056d}}}, - {0x053e, {1|F|D, {0x056e}}}, - {0x053f, {1|F|D, {0x056f}}}, - {0x0540, {1|F|D, {0x0570}}}, - {0x0541, {1|F|D, {0x0571}}}, - {0x0542, {1|F|D, {0x0572}}}, - {0x0543, {1|F|D, {0x0573}}}, - {0x0544, {1|F|D, {0x0574}}}, - {0x0545, {1|F|D, {0x0575}}}, - {0x0546, {1|F|D, {0x0576}}}, - {0x0547, {1|F|D, {0x0577}}}, - {0x0548, {1|F|D, {0x0578}}}, - {0x0549, {1|F|D, {0x0579}}}, - {0x054a, {1|F|D, {0x057a}}}, - {0x054b, {1|F|D, {0x057b}}}, - {0x054c, {1|F|D, {0x057c}}}, - {0x054d, {1|F|D, {0x057d}}}, - {0x054e, {1|F|D, {0x057e}}}, - {0x054f, {1|F|D, {0x057f}}}, - {0x0550, {1|F|D, {0x0580}}}, - {0x0551, {1|F|D, {0x0581}}}, - {0x0552, {1|F|D, {0x0582}}}, - {0x0553, {1|F|D, {0x0583}}}, - {0x0554, {1|F|D, {0x0584}}}, - {0x0555, {1|F|D, {0x0585}}}, - {0x0556, {1|F|D, {0x0586}}}, - {0x0587, {2|F|ST|SU|I(41), {0x0565, 0x0582}}}, - {0x10a0, {1|F|D, {0x2d00}}}, - {0x10a1, {1|F|D, {0x2d01}}}, - {0x10a2, {1|F|D, {0x2d02}}}, - {0x10a3, {1|F|D, {0x2d03}}}, - {0x10a4, {1|F|D, {0x2d04}}}, - {0x10a5, {1|F|D, {0x2d05}}}, - {0x10a6, {1|F|D, {0x2d06}}}, - {0x10a7, {1|F|D, {0x2d07}}}, - {0x10a8, {1|F|D, {0x2d08}}}, - {0x10a9, {1|F|D, {0x2d09}}}, - {0x10aa, {1|F|D, {0x2d0a}}}, - {0x10ab, {1|F|D, {0x2d0b}}}, - {0x10ac, {1|F|D, {0x2d0c}}}, - {0x10ad, {1|F|D, {0x2d0d}}}, - {0x10ae, {1|F|D, {0x2d0e}}}, - {0x10af, {1|F|D, {0x2d0f}}}, - {0x10b0, {1|F|D, {0x2d10}}}, - {0x10b1, {1|F|D, {0x2d11}}}, - {0x10b2, {1|F|D, {0x2d12}}}, - {0x10b3, {1|F|D, {0x2d13}}}, - {0x10b4, {1|F|D, {0x2d14}}}, - {0x10b5, {1|F|D, {0x2d15}}}, - {0x10b6, {1|F|D, {0x2d16}}}, - {0x10b7, {1|F|D, {0x2d17}}}, - {0x10b8, {1|F|D, {0x2d18}}}, - {0x10b9, {1|F|D, {0x2d19}}}, - {0x10ba, {1|F|D, {0x2d1a}}}, - {0x10bb, {1|F|D, {0x2d1b}}}, - {0x10bc, {1|F|D, {0x2d1c}}}, - {0x10bd, {1|F|D, {0x2d1d}}}, - {0x10be, {1|F|D, {0x2d1e}}}, - {0x10bf, {1|F|D, {0x2d1f}}}, - {0x10c0, {1|F|D, {0x2d20}}}, - {0x10c1, {1|F|D, {0x2d21}}}, - {0x10c2, {1|F|D, {0x2d22}}}, - {0x10c3, {1|F|D, {0x2d23}}}, - {0x10c4, {1|F|D, {0x2d24}}}, - {0x10c5, {1|F|D, {0x2d25}}}, - {0x10c7, {1|F|D, {0x2d27}}}, - {0x10cd, {1|F|D, {0x2d2d}}}, - {0x13f8, {1|F|U, {0x13f0}}}, - {0x13f9, {1|F|U, {0x13f1}}}, - {0x13fa, {1|F|U, {0x13f2}}}, - {0x13fb, {1|F|U, {0x13f3}}}, - {0x13fc, {1|F|U, {0x13f4}}}, - {0x13fd, {1|F|U, {0x13f5}}}, - {0x1c80, {1|F|SU|I(45), {0x0432}}}, - {0x1c81, {1|F|SU|I(46), {0x0434}}}, - {0x1c82, {1|F|SU|I(47), {0x043e}}}, - {0x1c83, {1|F|SU|I(48), {0x0441}}}, - {0x1c84, {1|F|SU|I(49), {0x0442}}}, - {0x1c85, {1|F|SU|I(50), {0x0442}}}, - {0x1c86, {1|F|SU|I(51), {0x044a}}}, - {0x1c87, {1|F|SU|I(52), {0x0463}}}, - {0x1c88, {1|F|SU|I(53), {0xa64b}}}, - {0x1c90, {1|F|D, {0x10d0}}}, - {0x1c91, {1|F|D, {0x10d1}}}, - {0x1c92, {1|F|D, {0x10d2}}}, - {0x1c93, {1|F|D, {0x10d3}}}, - {0x1c94, {1|F|D, {0x10d4}}}, - {0x1c95, {1|F|D, {0x10d5}}}, - {0x1c96, {1|F|D, {0x10d6}}}, - {0x1c97, {1|F|D, {0x10d7}}}, - {0x1c98, {1|F|D, {0x10d8}}}, - {0x1c99, {1|F|D, {0x10d9}}}, - {0x1c9a, {1|F|D, {0x10da}}}, - {0x1c9b, {1|F|D, {0x10db}}}, - {0x1c9c, {1|F|D, {0x10dc}}}, - {0x1c9d, {1|F|D, {0x10dd}}}, - {0x1c9e, {1|F|D, {0x10de}}}, - {0x1c9f, {1|F|D, {0x10df}}}, - {0x1ca0, {1|F|D, {0x10e0}}}, - {0x1ca1, {1|F|D, {0x10e1}}}, - {0x1ca2, {1|F|D, {0x10e2}}}, - {0x1ca3, {1|F|D, {0x10e3}}}, - {0x1ca4, {1|F|D, {0x10e4}}}, - {0x1ca5, {1|F|D, {0x10e5}}}, - {0x1ca6, {1|F|D, {0x10e6}}}, - {0x1ca7, {1|F|D, {0x10e7}}}, - {0x1ca8, {1|F|D, {0x10e8}}}, - {0x1ca9, {1|F|D, {0x10e9}}}, - {0x1caa, {1|F|D, {0x10ea}}}, - {0x1cab, {1|F|D, {0x10eb}}}, - {0x1cac, {1|F|D, {0x10ec}}}, - {0x1cad, {1|F|D, {0x10ed}}}, - {0x1cae, {1|F|D, {0x10ee}}}, - {0x1caf, {1|F|D, {0x10ef}}}, - {0x1cb0, {1|F|D, {0x10f0}}}, - {0x1cb1, {1|F|D, {0x10f1}}}, - {0x1cb2, {1|F|D, {0x10f2}}}, - {0x1cb3, {1|F|D, {0x10f3}}}, - {0x1cb4, {1|F|D, {0x10f4}}}, - {0x1cb5, {1|F|D, {0x10f5}}}, - {0x1cb6, {1|F|D, {0x10f6}}}, - {0x1cb7, {1|F|D, {0x10f7}}}, - {0x1cb8, {1|F|D, {0x10f8}}}, - {0x1cb9, {1|F|D, {0x10f9}}}, - {0x1cba, {1|F|D, {0x10fa}}}, - {0x1cbd, {1|F|D, {0x10fd}}}, - {0x1cbe, {1|F|D, {0x10fe}}}, - {0x1cbf, {1|F|D, {0x10ff}}}, - {0x1e00, {1|F|D, {0x1e01}}}, - {0x1e02, {1|F|D, {0x1e03}}}, - {0x1e04, {1|F|D, {0x1e05}}}, - {0x1e06, {1|F|D, {0x1e07}}}, - {0x1e08, {1|F|D, {0x1e09}}}, - {0x1e0a, {1|F|D, {0x1e0b}}}, - {0x1e0c, {1|F|D, {0x1e0d}}}, - {0x1e0e, {1|F|D, {0x1e0f}}}, - {0x1e10, {1|F|D, {0x1e11}}}, - {0x1e12, {1|F|D, {0x1e13}}}, - {0x1e14, {1|F|D, {0x1e15}}}, - {0x1e16, {1|F|D, {0x1e17}}}, - {0x1e18, {1|F|D, {0x1e19}}}, - {0x1e1a, {1|F|D, {0x1e1b}}}, - {0x1e1c, {1|F|D, {0x1e1d}}}, - {0x1e1e, {1|F|D, {0x1e1f}}}, - {0x1e20, {1|F|D, {0x1e21}}}, - {0x1e22, {1|F|D, {0x1e23}}}, - {0x1e24, {1|F|D, {0x1e25}}}, - {0x1e26, {1|F|D, {0x1e27}}}, - {0x1e28, {1|F|D, {0x1e29}}}, - {0x1e2a, {1|F|D, {0x1e2b}}}, - {0x1e2c, {1|F|D, {0x1e2d}}}, - {0x1e2e, {1|F|D, {0x1e2f}}}, - {0x1e30, {1|F|D, {0x1e31}}}, - {0x1e32, {1|F|D, {0x1e33}}}, - {0x1e34, {1|F|D, {0x1e35}}}, - {0x1e36, {1|F|D, {0x1e37}}}, - {0x1e38, {1|F|D, {0x1e39}}}, - {0x1e3a, {1|F|D, {0x1e3b}}}, - {0x1e3c, {1|F|D, {0x1e3d}}}, - {0x1e3e, {1|F|D, {0x1e3f}}}, - {0x1e40, {1|F|D, {0x1e41}}}, - {0x1e42, {1|F|D, {0x1e43}}}, - {0x1e44, {1|F|D, {0x1e45}}}, - {0x1e46, {1|F|D, {0x1e47}}}, - {0x1e48, {1|F|D, {0x1e49}}}, - {0x1e4a, {1|F|D, {0x1e4b}}}, - {0x1e4c, {1|F|D, {0x1e4d}}}, - {0x1e4e, {1|F|D, {0x1e4f}}}, - {0x1e50, {1|F|D, {0x1e51}}}, - {0x1e52, {1|F|D, {0x1e53}}}, - {0x1e54, {1|F|D, {0x1e55}}}, - {0x1e56, {1|F|D, {0x1e57}}}, - {0x1e58, {1|F|D, {0x1e59}}}, - {0x1e5a, {1|F|D, {0x1e5b}}}, - {0x1e5c, {1|F|D, {0x1e5d}}}, - {0x1e5e, {1|F|D, {0x1e5f}}}, - {0x1e60, {1|F|D, {0x1e61}}}, - {0x1e62, {1|F|D, {0x1e63}}}, - {0x1e64, {1|F|D, {0x1e65}}}, - {0x1e66, {1|F|D, {0x1e67}}}, - {0x1e68, {1|F|D, {0x1e69}}}, - {0x1e6a, {1|F|D, {0x1e6b}}}, - {0x1e6c, {1|F|D, {0x1e6d}}}, - {0x1e6e, {1|F|D, {0x1e6f}}}, - {0x1e70, {1|F|D, {0x1e71}}}, - {0x1e72, {1|F|D, {0x1e73}}}, - {0x1e74, {1|F|D, {0x1e75}}}, - {0x1e76, {1|F|D, {0x1e77}}}, - {0x1e78, {1|F|D, {0x1e79}}}, - {0x1e7a, {1|F|D, {0x1e7b}}}, - {0x1e7c, {1|F|D, {0x1e7d}}}, - {0x1e7e, {1|F|D, {0x1e7f}}}, - {0x1e80, {1|F|D, {0x1e81}}}, - {0x1e82, {1|F|D, {0x1e83}}}, - {0x1e84, {1|F|D, {0x1e85}}}, - {0x1e86, {1|F|D, {0x1e87}}}, - {0x1e88, {1|F|D, {0x1e89}}}, - {0x1e8a, {1|F|D, {0x1e8b}}}, - {0x1e8c, {1|F|D, {0x1e8d}}}, - {0x1e8e, {1|F|D, {0x1e8f}}}, - {0x1e90, {1|F|D, {0x1e91}}}, - {0x1e92, {1|F|D, {0x1e93}}}, - {0x1e94, {1|F|D, {0x1e95}}}, - {0x1e96, {2|F|SU|I(54), {0x0068, 0x0331}}}, - {0x1e97, {2|F|SU|I(56), {0x0074, 0x0308}}}, - {0x1e98, {2|F|SU|I(58), {0x0077, 0x030a}}}, - {0x1e99, {2|F|SU|I(60), {0x0079, 0x030a}}}, - {0x1e9a, {2|F|SU|I(62), {0x0061, 0x02be}}}, - {0x1e9b, {1|F|SU|I(64), {0x1e61}}}, - {0x1e9e, {2|F|SL|I(65), {0x0073, 0x0073}}}, - {0x1ea0, {1|F|D, {0x1ea1}}}, - {0x1ea2, {1|F|D, {0x1ea3}}}, - {0x1ea4, {1|F|D, {0x1ea5}}}, - {0x1ea6, {1|F|D, {0x1ea7}}}, - {0x1ea8, {1|F|D, {0x1ea9}}}, - {0x1eaa, {1|F|D, {0x1eab}}}, - {0x1eac, {1|F|D, {0x1ead}}}, - {0x1eae, {1|F|D, {0x1eaf}}}, - {0x1eb0, {1|F|D, {0x1eb1}}}, - {0x1eb2, {1|F|D, {0x1eb3}}}, - {0x1eb4, {1|F|D, {0x1eb5}}}, - {0x1eb6, {1|F|D, {0x1eb7}}}, - {0x1eb8, {1|F|D, {0x1eb9}}}, - {0x1eba, {1|F|D, {0x1ebb}}}, - {0x1ebc, {1|F|D, {0x1ebd}}}, - {0x1ebe, {1|F|D, {0x1ebf}}}, - {0x1ec0, {1|F|D, {0x1ec1}}}, - {0x1ec2, {1|F|D, {0x1ec3}}}, - {0x1ec4, {1|F|D, {0x1ec5}}}, - {0x1ec6, {1|F|D, {0x1ec7}}}, - {0x1ec8, {1|F|D, {0x1ec9}}}, - {0x1eca, {1|F|D, {0x1ecb}}}, - {0x1ecc, {1|F|D, {0x1ecd}}}, - {0x1ece, {1|F|D, {0x1ecf}}}, - {0x1ed0, {1|F|D, {0x1ed1}}}, - {0x1ed2, {1|F|D, {0x1ed3}}}, - {0x1ed4, {1|F|D, {0x1ed5}}}, - {0x1ed6, {1|F|D, {0x1ed7}}}, - {0x1ed8, {1|F|D, {0x1ed9}}}, - {0x1eda, {1|F|D, {0x1edb}}}, - {0x1edc, {1|F|D, {0x1edd}}}, - {0x1ede, {1|F|D, {0x1edf}}}, - {0x1ee0, {1|F|D, {0x1ee1}}}, - {0x1ee2, {1|F|D, {0x1ee3}}}, - {0x1ee4, {1|F|D, {0x1ee5}}}, - {0x1ee6, {1|F|D, {0x1ee7}}}, - {0x1ee8, {1|F|D, {0x1ee9}}}, - {0x1eea, {1|F|D, {0x1eeb}}}, - {0x1eec, {1|F|D, {0x1eed}}}, - {0x1eee, {1|F|D, {0x1eef}}}, - {0x1ef0, {1|F|D, {0x1ef1}}}, - {0x1ef2, {1|F|D, {0x1ef3}}}, - {0x1ef4, {1|F|D, {0x1ef5}}}, - {0x1ef6, {1|F|D, {0x1ef7}}}, - {0x1ef8, {1|F|D, {0x1ef9}}}, - {0x1efa, {1|F|D, {0x1efb}}}, - {0x1efc, {1|F|D, {0x1efd}}}, - {0x1efe, {1|F|D, {0x1eff}}}, - {0x1f08, {1|F|D, {0x1f00}}}, - {0x1f09, {1|F|D, {0x1f01}}}, - {0x1f0a, {1|F|D, {0x1f02}}}, - {0x1f0b, {1|F|D, {0x1f03}}}, - {0x1f0c, {1|F|D, {0x1f04}}}, - {0x1f0d, {1|F|D, {0x1f05}}}, - {0x1f0e, {1|F|D, {0x1f06}}}, - {0x1f0f, {1|F|D, {0x1f07}}}, - {0x1f18, {1|F|D, {0x1f10}}}, - {0x1f19, {1|F|D, {0x1f11}}}, - {0x1f1a, {1|F|D, {0x1f12}}}, - {0x1f1b, {1|F|D, {0x1f13}}}, - {0x1f1c, {1|F|D, {0x1f14}}}, - {0x1f1d, {1|F|D, {0x1f15}}}, - {0x1f28, {1|F|D, {0x1f20}}}, - {0x1f29, {1|F|D, {0x1f21}}}, - {0x1f2a, {1|F|D, {0x1f22}}}, - {0x1f2b, {1|F|D, {0x1f23}}}, - {0x1f2c, {1|F|D, {0x1f24}}}, - {0x1f2d, {1|F|D, {0x1f25}}}, - {0x1f2e, {1|F|D, {0x1f26}}}, - {0x1f2f, {1|F|D, {0x1f27}}}, - {0x1f38, {1|F|D, {0x1f30}}}, - {0x1f39, {1|F|D, {0x1f31}}}, - {0x1f3a, {1|F|D, {0x1f32}}}, - {0x1f3b, {1|F|D, {0x1f33}}}, - {0x1f3c, {1|F|D, {0x1f34}}}, - {0x1f3d, {1|F|D, {0x1f35}}}, - {0x1f3e, {1|F|D, {0x1f36}}}, - {0x1f3f, {1|F|D, {0x1f37}}}, - {0x1f48, {1|F|D, {0x1f40}}}, - {0x1f49, {1|F|D, {0x1f41}}}, - {0x1f4a, {1|F|D, {0x1f42}}}, - {0x1f4b, {1|F|D, {0x1f43}}}, - {0x1f4c, {1|F|D, {0x1f44}}}, - {0x1f4d, {1|F|D, {0x1f45}}}, - {0x1f50, {2|F|SU|I(66), {0x03c5, 0x0313}}}, - {0x1f52, {3|F|SU|I(68), {0x03c5, 0x0313, 0x0300}}}, - {0x1f54, {3|F|SU|I(71), {0x03c5, 0x0313, 0x0301}}}, - {0x1f56, {3|F|SU|I(74), {0x03c5, 0x0313, 0x0342}}}, - {0x1f59, {1|F|D, {0x1f51}}}, - {0x1f5b, {1|F|D, {0x1f53}}}, - {0x1f5d, {1|F|D, {0x1f55}}}, - {0x1f5f, {1|F|D, {0x1f57}}}, - {0x1f68, {1|F|D, {0x1f60}}}, - {0x1f69, {1|F|D, {0x1f61}}}, - {0x1f6a, {1|F|D, {0x1f62}}}, - {0x1f6b, {1|F|D, {0x1f63}}}, - {0x1f6c, {1|F|D, {0x1f64}}}, - {0x1f6d, {1|F|D, {0x1f65}}}, - {0x1f6e, {1|F|D, {0x1f66}}}, - {0x1f6f, {1|F|D, {0x1f67}}}, - {0x1f80, {2|F|ST|SU|I(77), {0x1f00, 0x03b9}}}, - {0x1f81, {2|F|ST|SU|I(80), {0x1f01, 0x03b9}}}, - {0x1f82, {2|F|ST|SU|I(83), {0x1f02, 0x03b9}}}, - {0x1f83, {2|F|ST|SU|I(86), {0x1f03, 0x03b9}}}, - {0x1f84, {2|F|ST|SU|I(89), {0x1f04, 0x03b9}}}, - {0x1f85, {2|F|ST|SU|I(92), {0x1f05, 0x03b9}}}, - {0x1f86, {2|F|ST|SU|I(95), {0x1f06, 0x03b9}}}, - {0x1f87, {2|F|ST|SU|I(98), {0x1f07, 0x03b9}}}, - {0x1f88, {2|F|IT|SL|SU|I(101), {0x1f00, 0x03b9}}}, - {0x1f89, {2|F|IT|SL|SU|I(106), {0x1f01, 0x03b9}}}, - {0x1f8a, {2|F|IT|SL|SU|I(111), {0x1f02, 0x03b9}}}, - {0x1f8b, {2|F|IT|SL|SU|I(116), {0x1f03, 0x03b9}}}, - {0x1f8c, {2|F|IT|SL|SU|I(121), {0x1f04, 0x03b9}}}, - {0x1f8d, {2|F|IT|SL|SU|I(126), {0x1f05, 0x03b9}}}, - {0x1f8e, {2|F|IT|SL|SU|I(131), {0x1f06, 0x03b9}}}, - {0x1f8f, {2|F|IT|SL|SU|I(136), {0x1f07, 0x03b9}}}, - {0x1f90, {2|F|ST|SU|I(141), {0x1f20, 0x03b9}}}, - {0x1f91, {2|F|ST|SU|I(144), {0x1f21, 0x03b9}}}, - {0x1f92, {2|F|ST|SU|I(147), {0x1f22, 0x03b9}}}, - {0x1f93, {2|F|ST|SU|I(150), {0x1f23, 0x03b9}}}, - {0x1f94, {2|F|ST|SU|I(153), {0x1f24, 0x03b9}}}, - {0x1f95, {2|F|ST|SU|I(156), {0x1f25, 0x03b9}}}, - {0x1f96, {2|F|ST|SU|I(159), {0x1f26, 0x03b9}}}, - {0x1f97, {2|F|ST|SU|I(162), {0x1f27, 0x03b9}}}, - {0x1f98, {2|F|IT|SL|SU|I(165), {0x1f20, 0x03b9}}}, - {0x1f99, {2|F|IT|SL|SU|I(170), {0x1f21, 0x03b9}}}, - {0x1f9a, {2|F|IT|SL|SU|I(175), {0x1f22, 0x03b9}}}, - {0x1f9b, {2|F|IT|SL|SU|I(180), {0x1f23, 0x03b9}}}, - {0x1f9c, {2|F|IT|SL|SU|I(185), {0x1f24, 0x03b9}}}, - {0x1f9d, {2|F|IT|SL|SU|I(190), {0x1f25, 0x03b9}}}, - {0x1f9e, {2|F|IT|SL|SU|I(195), {0x1f26, 0x03b9}}}, - {0x1f9f, {2|F|IT|SL|SU|I(200), {0x1f27, 0x03b9}}}, - {0x1fa0, {2|F|ST|SU|I(205), {0x1f60, 0x03b9}}}, - {0x1fa1, {2|F|ST|SU|I(208), {0x1f61, 0x03b9}}}, - {0x1fa2, {2|F|ST|SU|I(211), {0x1f62, 0x03b9}}}, - {0x1fa3, {2|F|ST|SU|I(214), {0x1f63, 0x03b9}}}, - {0x1fa4, {2|F|ST|SU|I(217), {0x1f64, 0x03b9}}}, - {0x1fa5, {2|F|ST|SU|I(220), {0x1f65, 0x03b9}}}, - {0x1fa6, {2|F|ST|SU|I(223), {0x1f66, 0x03b9}}}, - {0x1fa7, {2|F|ST|SU|I(226), {0x1f67, 0x03b9}}}, - {0x1fa8, {2|F|IT|SL|SU|I(229), {0x1f60, 0x03b9}}}, - {0x1fa9, {2|F|IT|SL|SU|I(234), {0x1f61, 0x03b9}}}, - {0x1faa, {2|F|IT|SL|SU|I(239), {0x1f62, 0x03b9}}}, - {0x1fab, {2|F|IT|SL|SU|I(244), {0x1f63, 0x03b9}}}, - {0x1fac, {2|F|IT|SL|SU|I(249), {0x1f64, 0x03b9}}}, - {0x1fad, {2|F|IT|SL|SU|I(254), {0x1f65, 0x03b9}}}, - {0x1fae, {2|F|IT|SL|SU|I(259), {0x1f66, 0x03b9}}}, - {0x1faf, {2|F|IT|SL|SU|I(264), {0x1f67, 0x03b9}}}, - {0x1fb2, {2|F|ST|SU|I(269), {0x1f70, 0x03b9}}}, - {0x1fb3, {2|F|ST|SU|I(273), {0x03b1, 0x03b9}}}, - {0x1fb4, {2|F|ST|SU|I(276), {0x03ac, 0x03b9}}}, - {0x1fb6, {2|F|SU|I(280), {0x03b1, 0x0342}}}, - {0x1fb7, {3|F|ST|SU|I(282), {0x03b1, 0x0342, 0x03b9}}}, - {0x1fb8, {1|F|D, {0x1fb0}}}, - {0x1fb9, {1|F|D, {0x1fb1}}}, - {0x1fba, {1|F|D, {0x1f70}}}, - {0x1fbb, {1|F|D, {0x1f71}}}, - {0x1fbc, {2|F|IT|SL|SU|I(288), {0x03b1, 0x03b9}}}, - {0x1fbe, {1|F|SU|I(293), {0x03b9}}}, - {0x1fc2, {2|F|ST|SU|I(294), {0x1f74, 0x03b9}}}, - {0x1fc3, {2|F|ST|SU|I(298), {0x03b7, 0x03b9}}}, - {0x1fc4, {2|F|ST|SU|I(301), {0x03ae, 0x03b9}}}, - {0x1fc6, {2|F|SU|I(305), {0x03b7, 0x0342}}}, - {0x1fc7, {3|F|ST|SU|I(307), {0x03b7, 0x0342, 0x03b9}}}, - {0x1fc8, {1|F|D, {0x1f72}}}, - {0x1fc9, {1|F|D, {0x1f73}}}, - {0x1fca, {1|F|D, {0x1f74}}}, - {0x1fcb, {1|F|D, {0x1f75}}}, - {0x1fcc, {2|F|IT|SL|SU|I(313), {0x03b7, 0x03b9}}}, - {0x1fd2, {3|F|SU|I(318), {0x03b9, 0x0308, 0x0300}}}, - {0x1fd3, {3|F|SU|I(321), {0x03b9, 0x0308, 0x0301}}}, - {0x1fd6, {2|F|SU|I(324), {0x03b9, 0x0342}}}, - {0x1fd7, {3|F|SU|I(326), {0x03b9, 0x0308, 0x0342}}}, - {0x1fd8, {1|F|D, {0x1fd0}}}, - {0x1fd9, {1|F|D, {0x1fd1}}}, - {0x1fda, {1|F|D, {0x1f76}}}, - {0x1fdb, {1|F|D, {0x1f77}}}, - {0x1fe2, {3|F|SU|I(329), {0x03c5, 0x0308, 0x0300}}}, - {0x1fe3, {3|F|SU|I(332), {0x03c5, 0x0308, 0x0301}}}, - {0x1fe4, {2|F|SU|I(335), {0x03c1, 0x0313}}}, - {0x1fe6, {2|F|SU|I(337), {0x03c5, 0x0342}}}, - {0x1fe7, {3|F|SU|I(339), {0x03c5, 0x0308, 0x0342}}}, - {0x1fe8, {1|F|D, {0x1fe0}}}, - {0x1fe9, {1|F|D, {0x1fe1}}}, - {0x1fea, {1|F|D, {0x1f7a}}}, - {0x1feb, {1|F|D, {0x1f7b}}}, - {0x1fec, {1|F|D, {0x1fe5}}}, - {0x1ff2, {2|F|ST|SU|I(342), {0x1f7c, 0x03b9}}}, - {0x1ff3, {2|F|ST|SU|I(346), {0x03c9, 0x03b9}}}, - {0x1ff4, {2|F|ST|SU|I(349), {0x03ce, 0x03b9}}}, - {0x1ff6, {2|F|SU|I(353), {0x03c9, 0x0342}}}, - {0x1ff7, {3|F|ST|SU|I(355), {0x03c9, 0x0342, 0x03b9}}}, - {0x1ff8, {1|F|D, {0x1f78}}}, - {0x1ff9, {1|F|D, {0x1f79}}}, - {0x1ffa, {1|F|D, {0x1f7c}}}, - {0x1ffb, {1|F|D, {0x1f7d}}}, - {0x1ffc, {2|F|IT|SL|SU|I(361), {0x03c9, 0x03b9}}}, - {0x2126, {1|F|D, {0x03c9}}}, - {0x212a, {1|F|D, {0x006b}}}, - {0x212b, {1|F|D, {0x00e5}}}, - {0x2132, {1|F|D, {0x214e}}}, - {0x2160, {1|F|D, {0x2170}}}, - {0x2161, {1|F|D, {0x2171}}}, - {0x2162, {1|F|D, {0x2172}}}, - {0x2163, {1|F|D, {0x2173}}}, - {0x2164, {1|F|D, {0x2174}}}, - {0x2165, {1|F|D, {0x2175}}}, - {0x2166, {1|F|D, {0x2176}}}, - {0x2167, {1|F|D, {0x2177}}}, - {0x2168, {1|F|D, {0x2178}}}, - {0x2169, {1|F|D, {0x2179}}}, - {0x216a, {1|F|D, {0x217a}}}, - {0x216b, {1|F|D, {0x217b}}}, - {0x216c, {1|F|D, {0x217c}}}, - {0x216d, {1|F|D, {0x217d}}}, - {0x216e, {1|F|D, {0x217e}}}, - {0x216f, {1|F|D, {0x217f}}}, - {0x2183, {1|F|D, {0x2184}}}, - {0x24b6, {1|F|D, {0x24d0}}}, - {0x24b7, {1|F|D, {0x24d1}}}, - {0x24b8, {1|F|D, {0x24d2}}}, - {0x24b9, {1|F|D, {0x24d3}}}, - {0x24ba, {1|F|D, {0x24d4}}}, - {0x24bb, {1|F|D, {0x24d5}}}, - {0x24bc, {1|F|D, {0x24d6}}}, - {0x24bd, {1|F|D, {0x24d7}}}, - {0x24be, {1|F|D, {0x24d8}}}, - {0x24bf, {1|F|D, {0x24d9}}}, - {0x24c0, {1|F|D, {0x24da}}}, - {0x24c1, {1|F|D, {0x24db}}}, - {0x24c2, {1|F|D, {0x24dc}}}, - {0x24c3, {1|F|D, {0x24dd}}}, - {0x24c4, {1|F|D, {0x24de}}}, - {0x24c5, {1|F|D, {0x24df}}}, - {0x24c6, {1|F|D, {0x24e0}}}, - {0x24c7, {1|F|D, {0x24e1}}}, - {0x24c8, {1|F|D, {0x24e2}}}, - {0x24c9, {1|F|D, {0x24e3}}}, - {0x24ca, {1|F|D, {0x24e4}}}, - {0x24cb, {1|F|D, {0x24e5}}}, - {0x24cc, {1|F|D, {0x24e6}}}, - {0x24cd, {1|F|D, {0x24e7}}}, - {0x24ce, {1|F|D, {0x24e8}}}, - {0x24cf, {1|F|D, {0x24e9}}}, - {0x2c00, {1|F|D, {0x2c30}}}, - {0x2c01, {1|F|D, {0x2c31}}}, - {0x2c02, {1|F|D, {0x2c32}}}, - {0x2c03, {1|F|D, {0x2c33}}}, - {0x2c04, {1|F|D, {0x2c34}}}, - {0x2c05, {1|F|D, {0x2c35}}}, - {0x2c06, {1|F|D, {0x2c36}}}, - {0x2c07, {1|F|D, {0x2c37}}}, - {0x2c08, {1|F|D, {0x2c38}}}, - {0x2c09, {1|F|D, {0x2c39}}}, - {0x2c0a, {1|F|D, {0x2c3a}}}, - {0x2c0b, {1|F|D, {0x2c3b}}}, - {0x2c0c, {1|F|D, {0x2c3c}}}, - {0x2c0d, {1|F|D, {0x2c3d}}}, - {0x2c0e, {1|F|D, {0x2c3e}}}, - {0x2c0f, {1|F|D, {0x2c3f}}}, - {0x2c10, {1|F|D, {0x2c40}}}, - {0x2c11, {1|F|D, {0x2c41}}}, - {0x2c12, {1|F|D, {0x2c42}}}, - {0x2c13, {1|F|D, {0x2c43}}}, - {0x2c14, {1|F|D, {0x2c44}}}, - {0x2c15, {1|F|D, {0x2c45}}}, - {0x2c16, {1|F|D, {0x2c46}}}, - {0x2c17, {1|F|D, {0x2c47}}}, - {0x2c18, {1|F|D, {0x2c48}}}, - {0x2c19, {1|F|D, {0x2c49}}}, - {0x2c1a, {1|F|D, {0x2c4a}}}, - {0x2c1b, {1|F|D, {0x2c4b}}}, - {0x2c1c, {1|F|D, {0x2c4c}}}, - {0x2c1d, {1|F|D, {0x2c4d}}}, - {0x2c1e, {1|F|D, {0x2c4e}}}, - {0x2c1f, {1|F|D, {0x2c4f}}}, - {0x2c20, {1|F|D, {0x2c50}}}, - {0x2c21, {1|F|D, {0x2c51}}}, - {0x2c22, {1|F|D, {0x2c52}}}, - {0x2c23, {1|F|D, {0x2c53}}}, - {0x2c24, {1|F|D, {0x2c54}}}, - {0x2c25, {1|F|D, {0x2c55}}}, - {0x2c26, {1|F|D, {0x2c56}}}, - {0x2c27, {1|F|D, {0x2c57}}}, - {0x2c28, {1|F|D, {0x2c58}}}, - {0x2c29, {1|F|D, {0x2c59}}}, - {0x2c2a, {1|F|D, {0x2c5a}}}, - {0x2c2b, {1|F|D, {0x2c5b}}}, - {0x2c2c, {1|F|D, {0x2c5c}}}, - {0x2c2d, {1|F|D, {0x2c5d}}}, - {0x2c2e, {1|F|D, {0x2c5e}}}, - {0x2c2f, {1|F|D, {0x2c5f}}}, - {0x2c60, {1|F|D, {0x2c61}}}, - {0x2c62, {1|F|D, {0x026b}}}, - {0x2c63, {1|F|D, {0x1d7d}}}, - {0x2c64, {1|F|D, {0x027d}}}, - {0x2c67, {1|F|D, {0x2c68}}}, - {0x2c69, {1|F|D, {0x2c6a}}}, - {0x2c6b, {1|F|D, {0x2c6c}}}, - {0x2c6d, {1|F|D, {0x0251}}}, - {0x2c6e, {1|F|D, {0x0271}}}, - {0x2c6f, {1|F|D, {0x0250}}}, - {0x2c70, {1|F|D, {0x0252}}}, - {0x2c72, {1|F|D, {0x2c73}}}, - {0x2c75, {1|F|D, {0x2c76}}}, - {0x2c7e, {1|F|D, {0x023f}}}, - {0x2c7f, {1|F|D, {0x0240}}}, - {0x2c80, {1|F|D, {0x2c81}}}, - {0x2c82, {1|F|D, {0x2c83}}}, - {0x2c84, {1|F|D, {0x2c85}}}, - {0x2c86, {1|F|D, {0x2c87}}}, - {0x2c88, {1|F|D, {0x2c89}}}, - {0x2c8a, {1|F|D, {0x2c8b}}}, - {0x2c8c, {1|F|D, {0x2c8d}}}, - {0x2c8e, {1|F|D, {0x2c8f}}}, - {0x2c90, {1|F|D, {0x2c91}}}, - {0x2c92, {1|F|D, {0x2c93}}}, - {0x2c94, {1|F|D, {0x2c95}}}, - {0x2c96, {1|F|D, {0x2c97}}}, - {0x2c98, {1|F|D, {0x2c99}}}, - {0x2c9a, {1|F|D, {0x2c9b}}}, - {0x2c9c, {1|F|D, {0x2c9d}}}, - {0x2c9e, {1|F|D, {0x2c9f}}}, - {0x2ca0, {1|F|D, {0x2ca1}}}, - {0x2ca2, {1|F|D, {0x2ca3}}}, - {0x2ca4, {1|F|D, {0x2ca5}}}, - {0x2ca6, {1|F|D, {0x2ca7}}}, - {0x2ca8, {1|F|D, {0x2ca9}}}, - {0x2caa, {1|F|D, {0x2cab}}}, - {0x2cac, {1|F|D, {0x2cad}}}, - {0x2cae, {1|F|D, {0x2caf}}}, - {0x2cb0, {1|F|D, {0x2cb1}}}, - {0x2cb2, {1|F|D, {0x2cb3}}}, - {0x2cb4, {1|F|D, {0x2cb5}}}, - {0x2cb6, {1|F|D, {0x2cb7}}}, - {0x2cb8, {1|F|D, {0x2cb9}}}, - {0x2cba, {1|F|D, {0x2cbb}}}, - {0x2cbc, {1|F|D, {0x2cbd}}}, - {0x2cbe, {1|F|D, {0x2cbf}}}, - {0x2cc0, {1|F|D, {0x2cc1}}}, - {0x2cc2, {1|F|D, {0x2cc3}}}, - {0x2cc4, {1|F|D, {0x2cc5}}}, - {0x2cc6, {1|F|D, {0x2cc7}}}, - {0x2cc8, {1|F|D, {0x2cc9}}}, - {0x2cca, {1|F|D, {0x2ccb}}}, - {0x2ccc, {1|F|D, {0x2ccd}}}, - {0x2cce, {1|F|D, {0x2ccf}}}, - {0x2cd0, {1|F|D, {0x2cd1}}}, - {0x2cd2, {1|F|D, {0x2cd3}}}, - {0x2cd4, {1|F|D, {0x2cd5}}}, - {0x2cd6, {1|F|D, {0x2cd7}}}, - {0x2cd8, {1|F|D, {0x2cd9}}}, - {0x2cda, {1|F|D, {0x2cdb}}}, - {0x2cdc, {1|F|D, {0x2cdd}}}, - {0x2cde, {1|F|D, {0x2cdf}}}, - {0x2ce0, {1|F|D, {0x2ce1}}}, - {0x2ce2, {1|F|D, {0x2ce3}}}, - {0x2ceb, {1|F|D, {0x2cec}}}, - {0x2ced, {1|F|D, {0x2cee}}}, - {0x2cf2, {1|F|D, {0x2cf3}}}, - {0xa640, {1|F|D, {0xa641}}}, - {0xa642, {1|F|D, {0xa643}}}, - {0xa644, {1|F|D, {0xa645}}}, - {0xa646, {1|F|D, {0xa647}}}, - {0xa648, {1|F|D, {0xa649}}}, - {0xa64a, {1|F|D, {0xa64b}}}, - {0xa64c, {1|F|D, {0xa64d}}}, - {0xa64e, {1|F|D, {0xa64f}}}, - {0xa650, {1|F|D, {0xa651}}}, - {0xa652, {1|F|D, {0xa653}}}, - {0xa654, {1|F|D, {0xa655}}}, - {0xa656, {1|F|D, {0xa657}}}, - {0xa658, {1|F|D, {0xa659}}}, - {0xa65a, {1|F|D, {0xa65b}}}, - {0xa65c, {1|F|D, {0xa65d}}}, - {0xa65e, {1|F|D, {0xa65f}}}, - {0xa660, {1|F|D, {0xa661}}}, - {0xa662, {1|F|D, {0xa663}}}, - {0xa664, {1|F|D, {0xa665}}}, - {0xa666, {1|F|D, {0xa667}}}, - {0xa668, {1|F|D, {0xa669}}}, - {0xa66a, {1|F|D, {0xa66b}}}, - {0xa66c, {1|F|D, {0xa66d}}}, - {0xa680, {1|F|D, {0xa681}}}, - {0xa682, {1|F|D, {0xa683}}}, - {0xa684, {1|F|D, {0xa685}}}, - {0xa686, {1|F|D, {0xa687}}}, - {0xa688, {1|F|D, {0xa689}}}, - {0xa68a, {1|F|D, {0xa68b}}}, - {0xa68c, {1|F|D, {0xa68d}}}, - {0xa68e, {1|F|D, {0xa68f}}}, - {0xa690, {1|F|D, {0xa691}}}, - {0xa692, {1|F|D, {0xa693}}}, - {0xa694, {1|F|D, {0xa695}}}, - {0xa696, {1|F|D, {0xa697}}}, - {0xa698, {1|F|D, {0xa699}}}, - {0xa69a, {1|F|D, {0xa69b}}}, - {0xa722, {1|F|D, {0xa723}}}, - {0xa724, {1|F|D, {0xa725}}}, - {0xa726, {1|F|D, {0xa727}}}, - {0xa728, {1|F|D, {0xa729}}}, - {0xa72a, {1|F|D, {0xa72b}}}, - {0xa72c, {1|F|D, {0xa72d}}}, - {0xa72e, {1|F|D, {0xa72f}}}, - {0xa732, {1|F|D, {0xa733}}}, - {0xa734, {1|F|D, {0xa735}}}, - {0xa736, {1|F|D, {0xa737}}}, - {0xa738, {1|F|D, {0xa739}}}, - {0xa73a, {1|F|D, {0xa73b}}}, - {0xa73c, {1|F|D, {0xa73d}}}, - {0xa73e, {1|F|D, {0xa73f}}}, - {0xa740, {1|F|D, {0xa741}}}, - {0xa742, {1|F|D, {0xa743}}}, - {0xa744, {1|F|D, {0xa745}}}, - {0xa746, {1|F|D, {0xa747}}}, - {0xa748, {1|F|D, {0xa749}}}, - {0xa74a, {1|F|D, {0xa74b}}}, - {0xa74c, {1|F|D, {0xa74d}}}, - {0xa74e, {1|F|D, {0xa74f}}}, - {0xa750, {1|F|D, {0xa751}}}, - {0xa752, {1|F|D, {0xa753}}}, - {0xa754, {1|F|D, {0xa755}}}, - {0xa756, {1|F|D, {0xa757}}}, - {0xa758, {1|F|D, {0xa759}}}, - {0xa75a, {1|F|D, {0xa75b}}}, - {0xa75c, {1|F|D, {0xa75d}}}, - {0xa75e, {1|F|D, {0xa75f}}}, - {0xa760, {1|F|D, {0xa761}}}, - {0xa762, {1|F|D, {0xa763}}}, - {0xa764, {1|F|D, {0xa765}}}, - {0xa766, {1|F|D, {0xa767}}}, - {0xa768, {1|F|D, {0xa769}}}, - {0xa76a, {1|F|D, {0xa76b}}}, - {0xa76c, {1|F|D, {0xa76d}}}, - {0xa76e, {1|F|D, {0xa76f}}}, - {0xa779, {1|F|D, {0xa77a}}}, - {0xa77b, {1|F|D, {0xa77c}}}, - {0xa77d, {1|F|D, {0x1d79}}}, - {0xa77e, {1|F|D, {0xa77f}}}, - {0xa780, {1|F|D, {0xa781}}}, - {0xa782, {1|F|D, {0xa783}}}, - {0xa784, {1|F|D, {0xa785}}}, - {0xa786, {1|F|D, {0xa787}}}, - {0xa78b, {1|F|D, {0xa78c}}}, - {0xa78d, {1|F|D, {0x0265}}}, - {0xa790, {1|F|D, {0xa791}}}, - {0xa792, {1|F|D, {0xa793}}}, - {0xa796, {1|F|D, {0xa797}}}, - {0xa798, {1|F|D, {0xa799}}}, - {0xa79a, {1|F|D, {0xa79b}}}, - {0xa79c, {1|F|D, {0xa79d}}}, - {0xa79e, {1|F|D, {0xa79f}}}, - {0xa7a0, {1|F|D, {0xa7a1}}}, - {0xa7a2, {1|F|D, {0xa7a3}}}, - {0xa7a4, {1|F|D, {0xa7a5}}}, - {0xa7a6, {1|F|D, {0xa7a7}}}, - {0xa7a8, {1|F|D, {0xa7a9}}}, - {0xa7aa, {1|F|D, {0x0266}}}, - {0xa7ab, {1|F|D, {0x025c}}}, - {0xa7ac, {1|F|D, {0x0261}}}, - {0xa7ad, {1|F|D, {0x026c}}}, - {0xa7ae, {1|F|D, {0x026a}}}, - {0xa7b0, {1|F|D, {0x029e}}}, - {0xa7b1, {1|F|D, {0x0287}}}, - {0xa7b2, {1|F|D, {0x029d}}}, - {0xa7b3, {1|F|D, {0xab53}}}, - {0xa7b4, {1|F|D, {0xa7b5}}}, - {0xa7b6, {1|F|D, {0xa7b7}}}, - {0xa7b8, {1|F|D, {0xa7b9}}}, - {0xa7ba, {1|F|D, {0xa7bb}}}, - {0xa7bc, {1|F|D, {0xa7bd}}}, - {0xa7be, {1|F|D, {0xa7bf}}}, - {0xa7c0, {1|F|D, {0xa7c1}}}, - {0xa7c2, {1|F|D, {0xa7c3}}}, - {0xa7c4, {1|F|D, {0xa794}}}, - {0xa7c5, {1|F|D, {0x0282}}}, - {0xa7c6, {1|F|D, {0x1d8e}}}, - {0xa7c7, {1|F|D, {0xa7c8}}}, - {0xa7c9, {1|F|D, {0xa7ca}}}, - {0xa7d0, {1|F|D, {0xa7d1}}}, - {0xa7d6, {1|F|D, {0xa7d7}}}, - {0xa7d8, {1|F|D, {0xa7d9}}}, - {0xa7f5, {1|F|D, {0xa7f6}}}, - {0xab70, {1|F|U, {0x13a0}}}, - {0xab71, {1|F|U, {0x13a1}}}, - {0xab72, {1|F|U, {0x13a2}}}, - {0xab73, {1|F|U, {0x13a3}}}, - {0xab74, {1|F|U, {0x13a4}}}, - {0xab75, {1|F|U, {0x13a5}}}, - {0xab76, {1|F|U, {0x13a6}}}, - {0xab77, {1|F|U, {0x13a7}}}, - {0xab78, {1|F|U, {0x13a8}}}, - {0xab79, {1|F|U, {0x13a9}}}, - {0xab7a, {1|F|U, {0x13aa}}}, - {0xab7b, {1|F|U, {0x13ab}}}, - {0xab7c, {1|F|U, {0x13ac}}}, - {0xab7d, {1|F|U, {0x13ad}}}, - {0xab7e, {1|F|U, {0x13ae}}}, - {0xab7f, {1|F|U, {0x13af}}}, - {0xab80, {1|F|U, {0x13b0}}}, - {0xab81, {1|F|U, {0x13b1}}}, - {0xab82, {1|F|U, {0x13b2}}}, - {0xab83, {1|F|U, {0x13b3}}}, - {0xab84, {1|F|U, {0x13b4}}}, - {0xab85, {1|F|U, {0x13b5}}}, - {0xab86, {1|F|U, {0x13b6}}}, - {0xab87, {1|F|U, {0x13b7}}}, - {0xab88, {1|F|U, {0x13b8}}}, - {0xab89, {1|F|U, {0x13b9}}}, - {0xab8a, {1|F|U, {0x13ba}}}, - {0xab8b, {1|F|U, {0x13bb}}}, - {0xab8c, {1|F|U, {0x13bc}}}, - {0xab8d, {1|F|U, {0x13bd}}}, - {0xab8e, {1|F|U, {0x13be}}}, - {0xab8f, {1|F|U, {0x13bf}}}, - {0xab90, {1|F|U, {0x13c0}}}, - {0xab91, {1|F|U, {0x13c1}}}, - {0xab92, {1|F|U, {0x13c2}}}, - {0xab93, {1|F|U, {0x13c3}}}, - {0xab94, {1|F|U, {0x13c4}}}, - {0xab95, {1|F|U, {0x13c5}}}, - {0xab96, {1|F|U, {0x13c6}}}, - {0xab97, {1|F|U, {0x13c7}}}, - {0xab98, {1|F|U, {0x13c8}}}, - {0xab99, {1|F|U, {0x13c9}}}, - {0xab9a, {1|F|U, {0x13ca}}}, - {0xab9b, {1|F|U, {0x13cb}}}, - {0xab9c, {1|F|U, {0x13cc}}}, - {0xab9d, {1|F|U, {0x13cd}}}, - {0xab9e, {1|F|U, {0x13ce}}}, - {0xab9f, {1|F|U, {0x13cf}}}, - {0xaba0, {1|F|U, {0x13d0}}}, - {0xaba1, {1|F|U, {0x13d1}}}, - {0xaba2, {1|F|U, {0x13d2}}}, - {0xaba3, {1|F|U, {0x13d3}}}, - {0xaba4, {1|F|U, {0x13d4}}}, - {0xaba5, {1|F|U, {0x13d5}}}, - {0xaba6, {1|F|U, {0x13d6}}}, - {0xaba7, {1|F|U, {0x13d7}}}, - {0xaba8, {1|F|U, {0x13d8}}}, - {0xaba9, {1|F|U, {0x13d9}}}, - {0xabaa, {1|F|U, {0x13da}}}, - {0xabab, {1|F|U, {0x13db}}}, - {0xabac, {1|F|U, {0x13dc}}}, - {0xabad, {1|F|U, {0x13dd}}}, - {0xabae, {1|F|U, {0x13de}}}, - {0xabaf, {1|F|U, {0x13df}}}, - {0xabb0, {1|F|U, {0x13e0}}}, - {0xabb1, {1|F|U, {0x13e1}}}, - {0xabb2, {1|F|U, {0x13e2}}}, - {0xabb3, {1|F|U, {0x13e3}}}, - {0xabb4, {1|F|U, {0x13e4}}}, - {0xabb5, {1|F|U, {0x13e5}}}, - {0xabb6, {1|F|U, {0x13e6}}}, - {0xabb7, {1|F|U, {0x13e7}}}, - {0xabb8, {1|F|U, {0x13e8}}}, - {0xabb9, {1|F|U, {0x13e9}}}, - {0xabba, {1|F|U, {0x13ea}}}, - {0xabbb, {1|F|U, {0x13eb}}}, - {0xabbc, {1|F|U, {0x13ec}}}, - {0xabbd, {1|F|U, {0x13ed}}}, - {0xabbe, {1|F|U, {0x13ee}}}, - {0xabbf, {1|F|U, {0x13ef}}}, - {0xfb00, {2|F|ST|SU|I(366), {0x0066, 0x0066}}}, - {0xfb01, {2|F|ST|SU|I(370), {0x0066, 0x0069}}}, - {0xfb02, {2|F|ST|SU|I(374), {0x0066, 0x006c}}}, - {0xfb03, {3|F|ST|SU|I(378), {0x0066, 0x0066, 0x0069}}}, - {0xfb04, {3|F|ST|SU|I(384), {0x0066, 0x0066, 0x006c}}}, - {0xfb05, {2|F|ST|SU|I(390), {0x0073, 0x0074}}}, - {0xfb06, {2|F|ST|SU|I(394), {0x0073, 0x0074}}}, - {0xfb13, {2|F|ST|SU|I(398), {0x0574, 0x0576}}}, - {0xfb14, {2|F|ST|SU|I(402), {0x0574, 0x0565}}}, - {0xfb15, {2|F|ST|SU|I(406), {0x0574, 0x056b}}}, - {0xfb16, {2|F|ST|SU|I(410), {0x057e, 0x0576}}}, - {0xfb17, {2|F|ST|SU|I(414), {0x0574, 0x056d}}}, - {0xff21, {1|F|D, {0xff41}}}, - {0xff22, {1|F|D, {0xff42}}}, - {0xff23, {1|F|D, {0xff43}}}, - {0xff24, {1|F|D, {0xff44}}}, - {0xff25, {1|F|D, {0xff45}}}, - {0xff26, {1|F|D, {0xff46}}}, - {0xff27, {1|F|D, {0xff47}}}, - {0xff28, {1|F|D, {0xff48}}}, - {0xff29, {1|F|D, {0xff49}}}, - {0xff2a, {1|F|D, {0xff4a}}}, - {0xff2b, {1|F|D, {0xff4b}}}, - {0xff2c, {1|F|D, {0xff4c}}}, - {0xff2d, {1|F|D, {0xff4d}}}, - {0xff2e, {1|F|D, {0xff4e}}}, - {0xff2f, {1|F|D, {0xff4f}}}, - {0xff30, {1|F|D, {0xff50}}}, - {0xff31, {1|F|D, {0xff51}}}, - {0xff32, {1|F|D, {0xff52}}}, - {0xff33, {1|F|D, {0xff53}}}, - {0xff34, {1|F|D, {0xff54}}}, - {0xff35, {1|F|D, {0xff55}}}, - {0xff36, {1|F|D, {0xff56}}}, - {0xff37, {1|F|D, {0xff57}}}, - {0xff38, {1|F|D, {0xff58}}}, - {0xff39, {1|F|D, {0xff59}}}, - {0xff3a, {1|F|D, {0xff5a}}}, - {0x10400, {1|F|D, {0x10428}}}, - {0x10401, {1|F|D, {0x10429}}}, - {0x10402, {1|F|D, {0x1042a}}}, - {0x10403, {1|F|D, {0x1042b}}}, - {0x10404, {1|F|D, {0x1042c}}}, - {0x10405, {1|F|D, {0x1042d}}}, - {0x10406, {1|F|D, {0x1042e}}}, - {0x10407, {1|F|D, {0x1042f}}}, - {0x10408, {1|F|D, {0x10430}}}, - {0x10409, {1|F|D, {0x10431}}}, - {0x1040a, {1|F|D, {0x10432}}}, - {0x1040b, {1|F|D, {0x10433}}}, - {0x1040c, {1|F|D, {0x10434}}}, - {0x1040d, {1|F|D, {0x10435}}}, - {0x1040e, {1|F|D, {0x10436}}}, - {0x1040f, {1|F|D, {0x10437}}}, - {0x10410, {1|F|D, {0x10438}}}, - {0x10411, {1|F|D, {0x10439}}}, - {0x10412, {1|F|D, {0x1043a}}}, - {0x10413, {1|F|D, {0x1043b}}}, - {0x10414, {1|F|D, {0x1043c}}}, - {0x10415, {1|F|D, {0x1043d}}}, - {0x10416, {1|F|D, {0x1043e}}}, - {0x10417, {1|F|D, {0x1043f}}}, - {0x10418, {1|F|D, {0x10440}}}, - {0x10419, {1|F|D, {0x10441}}}, - {0x1041a, {1|F|D, {0x10442}}}, - {0x1041b, {1|F|D, {0x10443}}}, - {0x1041c, {1|F|D, {0x10444}}}, - {0x1041d, {1|F|D, {0x10445}}}, - {0x1041e, {1|F|D, {0x10446}}}, - {0x1041f, {1|F|D, {0x10447}}}, - {0x10420, {1|F|D, {0x10448}}}, - {0x10421, {1|F|D, {0x10449}}}, - {0x10422, {1|F|D, {0x1044a}}}, - {0x10423, {1|F|D, {0x1044b}}}, - {0x10424, {1|F|D, {0x1044c}}}, - {0x10425, {1|F|D, {0x1044d}}}, - {0x10426, {1|F|D, {0x1044e}}}, - {0x10427, {1|F|D, {0x1044f}}}, - {0x104b0, {1|F|D, {0x104d8}}}, - {0x104b1, {1|F|D, {0x104d9}}}, - {0x104b2, {1|F|D, {0x104da}}}, - {0x104b3, {1|F|D, {0x104db}}}, - {0x104b4, {1|F|D, {0x104dc}}}, - {0x104b5, {1|F|D, {0x104dd}}}, - {0x104b6, {1|F|D, {0x104de}}}, - {0x104b7, {1|F|D, {0x104df}}}, - {0x104b8, {1|F|D, {0x104e0}}}, - {0x104b9, {1|F|D, {0x104e1}}}, - {0x104ba, {1|F|D, {0x104e2}}}, - {0x104bb, {1|F|D, {0x104e3}}}, - {0x104bc, {1|F|D, {0x104e4}}}, - {0x104bd, {1|F|D, {0x104e5}}}, - {0x104be, {1|F|D, {0x104e6}}}, - {0x104bf, {1|F|D, {0x104e7}}}, - {0x104c0, {1|F|D, {0x104e8}}}, - {0x104c1, {1|F|D, {0x104e9}}}, - {0x104c2, {1|F|D, {0x104ea}}}, - {0x104c3, {1|F|D, {0x104eb}}}, - {0x104c4, {1|F|D, {0x104ec}}}, - {0x104c5, {1|F|D, {0x104ed}}}, - {0x104c6, {1|F|D, {0x104ee}}}, - {0x104c7, {1|F|D, {0x104ef}}}, - {0x104c8, {1|F|D, {0x104f0}}}, - {0x104c9, {1|F|D, {0x104f1}}}, - {0x104ca, {1|F|D, {0x104f2}}}, - {0x104cb, {1|F|D, {0x104f3}}}, - {0x104cc, {1|F|D, {0x104f4}}}, - {0x104cd, {1|F|D, {0x104f5}}}, - {0x104ce, {1|F|D, {0x104f6}}}, - {0x104cf, {1|F|D, {0x104f7}}}, - {0x104d0, {1|F|D, {0x104f8}}}, - {0x104d1, {1|F|D, {0x104f9}}}, - {0x104d2, {1|F|D, {0x104fa}}}, - {0x104d3, {1|F|D, {0x104fb}}}, - {0x10570, {1|F|D, {0x10597}}}, - {0x10571, {1|F|D, {0x10598}}}, - {0x10572, {1|F|D, {0x10599}}}, - {0x10573, {1|F|D, {0x1059a}}}, - {0x10574, {1|F|D, {0x1059b}}}, - {0x10575, {1|F|D, {0x1059c}}}, - {0x10576, {1|F|D, {0x1059d}}}, - {0x10577, {1|F|D, {0x1059e}}}, - {0x10578, {1|F|D, {0x1059f}}}, - {0x10579, {1|F|D, {0x105a0}}}, - {0x1057a, {1|F|D, {0x105a1}}}, - {0x1057c, {1|F|D, {0x105a3}}}, - {0x1057d, {1|F|D, {0x105a4}}}, - {0x1057e, {1|F|D, {0x105a5}}}, - {0x1057f, {1|F|D, {0x105a6}}}, - {0x10580, {1|F|D, {0x105a7}}}, - {0x10581, {1|F|D, {0x105a8}}}, - {0x10582, {1|F|D, {0x105a9}}}, - {0x10583, {1|F|D, {0x105aa}}}, - {0x10584, {1|F|D, {0x105ab}}}, - {0x10585, {1|F|D, {0x105ac}}}, - {0x10586, {1|F|D, {0x105ad}}}, - {0x10587, {1|F|D, {0x105ae}}}, - {0x10588, {1|F|D, {0x105af}}}, - {0x10589, {1|F|D, {0x105b0}}}, - {0x1058a, {1|F|D, {0x105b1}}}, - {0x1058c, {1|F|D, {0x105b3}}}, - {0x1058d, {1|F|D, {0x105b4}}}, - {0x1058e, {1|F|D, {0x105b5}}}, - {0x1058f, {1|F|D, {0x105b6}}}, - {0x10590, {1|F|D, {0x105b7}}}, - {0x10591, {1|F|D, {0x105b8}}}, - {0x10592, {1|F|D, {0x105b9}}}, - {0x10594, {1|F|D, {0x105bb}}}, - {0x10595, {1|F|D, {0x105bc}}}, - {0x10c80, {1|F|D, {0x10cc0}}}, - {0x10c81, {1|F|D, {0x10cc1}}}, - {0x10c82, {1|F|D, {0x10cc2}}}, - {0x10c83, {1|F|D, {0x10cc3}}}, - {0x10c84, {1|F|D, {0x10cc4}}}, - {0x10c85, {1|F|D, {0x10cc5}}}, - {0x10c86, {1|F|D, {0x10cc6}}}, - {0x10c87, {1|F|D, {0x10cc7}}}, - {0x10c88, {1|F|D, {0x10cc8}}}, - {0x10c89, {1|F|D, {0x10cc9}}}, - {0x10c8a, {1|F|D, {0x10cca}}}, - {0x10c8b, {1|F|D, {0x10ccb}}}, - {0x10c8c, {1|F|D, {0x10ccc}}}, - {0x10c8d, {1|F|D, {0x10ccd}}}, - {0x10c8e, {1|F|D, {0x10cce}}}, - {0x10c8f, {1|F|D, {0x10ccf}}}, - {0x10c90, {1|F|D, {0x10cd0}}}, - {0x10c91, {1|F|D, {0x10cd1}}}, - {0x10c92, {1|F|D, {0x10cd2}}}, - {0x10c93, {1|F|D, {0x10cd3}}}, - {0x10c94, {1|F|D, {0x10cd4}}}, - {0x10c95, {1|F|D, {0x10cd5}}}, - {0x10c96, {1|F|D, {0x10cd6}}}, - {0x10c97, {1|F|D, {0x10cd7}}}, - {0x10c98, {1|F|D, {0x10cd8}}}, - {0x10c99, {1|F|D, {0x10cd9}}}, - {0x10c9a, {1|F|D, {0x10cda}}}, - {0x10c9b, {1|F|D, {0x10cdb}}}, - {0x10c9c, {1|F|D, {0x10cdc}}}, - {0x10c9d, {1|F|D, {0x10cdd}}}, - {0x10c9e, {1|F|D, {0x10cde}}}, - {0x10c9f, {1|F|D, {0x10cdf}}}, - {0x10ca0, {1|F|D, {0x10ce0}}}, - {0x10ca1, {1|F|D, {0x10ce1}}}, - {0x10ca2, {1|F|D, {0x10ce2}}}, - {0x10ca3, {1|F|D, {0x10ce3}}}, - {0x10ca4, {1|F|D, {0x10ce4}}}, - {0x10ca5, {1|F|D, {0x10ce5}}}, - {0x10ca6, {1|F|D, {0x10ce6}}}, - {0x10ca7, {1|F|D, {0x10ce7}}}, - {0x10ca8, {1|F|D, {0x10ce8}}}, - {0x10ca9, {1|F|D, {0x10ce9}}}, - {0x10caa, {1|F|D, {0x10cea}}}, - {0x10cab, {1|F|D, {0x10ceb}}}, - {0x10cac, {1|F|D, {0x10cec}}}, - {0x10cad, {1|F|D, {0x10ced}}}, - {0x10cae, {1|F|D, {0x10cee}}}, - {0x10caf, {1|F|D, {0x10cef}}}, - {0x10cb0, {1|F|D, {0x10cf0}}}, - {0x10cb1, {1|F|D, {0x10cf1}}}, - {0x10cb2, {1|F|D, {0x10cf2}}}, - {0x118a0, {1|F|D, {0x118c0}}}, - {0x118a1, {1|F|D, {0x118c1}}}, - {0x118a2, {1|F|D, {0x118c2}}}, - {0x118a3, {1|F|D, {0x118c3}}}, - {0x118a4, {1|F|D, {0x118c4}}}, - {0x118a5, {1|F|D, {0x118c5}}}, - {0x118a6, {1|F|D, {0x118c6}}}, - {0x118a7, {1|F|D, {0x118c7}}}, - {0x118a8, {1|F|D, {0x118c8}}}, - {0x118a9, {1|F|D, {0x118c9}}}, - {0x118aa, {1|F|D, {0x118ca}}}, - {0x118ab, {1|F|D, {0x118cb}}}, - {0x118ac, {1|F|D, {0x118cc}}}, - {0x118ad, {1|F|D, {0x118cd}}}, - {0x118ae, {1|F|D, {0x118ce}}}, - {0x118af, {1|F|D, {0x118cf}}}, - {0x118b0, {1|F|D, {0x118d0}}}, - {0x118b1, {1|F|D, {0x118d1}}}, - {0x118b2, {1|F|D, {0x118d2}}}, - {0x118b3, {1|F|D, {0x118d3}}}, - {0x118b4, {1|F|D, {0x118d4}}}, - {0x118b5, {1|F|D, {0x118d5}}}, - {0x118b6, {1|F|D, {0x118d6}}}, - {0x118b7, {1|F|D, {0x118d7}}}, - {0x118b8, {1|F|D, {0x118d8}}}, - {0x118b9, {1|F|D, {0x118d9}}}, - {0x118ba, {1|F|D, {0x118da}}}, - {0x118bb, {1|F|D, {0x118db}}}, - {0x118bc, {1|F|D, {0x118dc}}}, - {0x118bd, {1|F|D, {0x118dd}}}, - {0x118be, {1|F|D, {0x118de}}}, - {0x118bf, {1|F|D, {0x118df}}}, - {0x16e40, {1|F|D, {0x16e60}}}, - {0x16e41, {1|F|D, {0x16e61}}}, - {0x16e42, {1|F|D, {0x16e62}}}, - {0x16e43, {1|F|D, {0x16e63}}}, - {0x16e44, {1|F|D, {0x16e64}}}, - {0x16e45, {1|F|D, {0x16e65}}}, - {0x16e46, {1|F|D, {0x16e66}}}, - {0x16e47, {1|F|D, {0x16e67}}}, - {0x16e48, {1|F|D, {0x16e68}}}, - {0x16e49, {1|F|D, {0x16e69}}}, - {0x16e4a, {1|F|D, {0x16e6a}}}, - {0x16e4b, {1|F|D, {0x16e6b}}}, - {0x16e4c, {1|F|D, {0x16e6c}}}, - {0x16e4d, {1|F|D, {0x16e6d}}}, - {0x16e4e, {1|F|D, {0x16e6e}}}, - {0x16e4f, {1|F|D, {0x16e6f}}}, - {0x16e50, {1|F|D, {0x16e70}}}, - {0x16e51, {1|F|D, {0x16e71}}}, - {0x16e52, {1|F|D, {0x16e72}}}, - {0x16e53, {1|F|D, {0x16e73}}}, - {0x16e54, {1|F|D, {0x16e74}}}, - {0x16e55, {1|F|D, {0x16e75}}}, - {0x16e56, {1|F|D, {0x16e76}}}, - {0x16e57, {1|F|D, {0x16e77}}}, - {0x16e58, {1|F|D, {0x16e78}}}, - {0x16e59, {1|F|D, {0x16e79}}}, - {0x16e5a, {1|F|D, {0x16e7a}}}, - {0x16e5b, {1|F|D, {0x16e7b}}}, - {0x16e5c, {1|F|D, {0x16e7c}}}, - {0x16e5d, {1|F|D, {0x16e7d}}}, - {0x16e5e, {1|F|D, {0x16e7e}}}, - {0x16e5f, {1|F|D, {0x16e7f}}}, - {0x1e900, {1|F|D, {0x1e922}}}, - {0x1e901, {1|F|D, {0x1e923}}}, - {0x1e902, {1|F|D, {0x1e924}}}, - {0x1e903, {1|F|D, {0x1e925}}}, - {0x1e904, {1|F|D, {0x1e926}}}, - {0x1e905, {1|F|D, {0x1e927}}}, - {0x1e906, {1|F|D, {0x1e928}}}, - {0x1e907, {1|F|D, {0x1e929}}}, - {0x1e908, {1|F|D, {0x1e92a}}}, - {0x1e909, {1|F|D, {0x1e92b}}}, - {0x1e90a, {1|F|D, {0x1e92c}}}, - {0x1e90b, {1|F|D, {0x1e92d}}}, - {0x1e90c, {1|F|D, {0x1e92e}}}, - {0x1e90d, {1|F|D, {0x1e92f}}}, - {0x1e90e, {1|F|D, {0x1e930}}}, - {0x1e90f, {1|F|D, {0x1e931}}}, - {0x1e910, {1|F|D, {0x1e932}}}, - {0x1e911, {1|F|D, {0x1e933}}}, - {0x1e912, {1|F|D, {0x1e934}}}, - {0x1e913, {1|F|D, {0x1e935}}}, - {0x1e914, {1|F|D, {0x1e936}}}, - {0x1e915, {1|F|D, {0x1e937}}}, - {0x1e916, {1|F|D, {0x1e938}}}, - {0x1e917, {1|F|D, {0x1e939}}}, - {0x1e918, {1|F|D, {0x1e93a}}}, - {0x1e919, {1|F|D, {0x1e93b}}}, - {0x1e91a, {1|F|D, {0x1e93c}}}, - {0x1e91b, {1|F|D, {0x1e93d}}}, - {0x1e91c, {1|F|D, {0x1e93e}}}, - {0x1e91d, {1|F|D, {0x1e93f}}}, - {0x1e91e, {1|F|D, {0x1e940}}}, - {0x1e91f, {1|F|D, {0x1e941}}}, - {0x1e920, {1|F|D, {0x1e942}}}, - {0x1e921, {1|F|D, {0x1e943}}}, -#define CaseFold_Locale (*(CaseFold_11_Type (*)[2])(CaseFold_11_Table+1528)) - {0x0049, {1|F|D, {0x0069}}}, - {0x0130, {2|F|D, {0x0069, 0x0307}}}, -}; - -/* ANSI-C code produced by gperf version 3.1 */ -/* Command-line: gperf -7 -k1,2,3 -F,-1 -c -j1 -i1 -t -T -E -C -H onigenc_unicode_CaseFold_11_hash -N onigenc_unicode_CaseFold_11_lookup -n */ - -/* maximum key range = 3080, duplicates = 0 */ - -#ifdef __GNUC__ -__inline -#else -#ifdef __cplusplus -inline -#endif -#endif -/*ARGSUSED*/ -static unsigned int -onigenc_unicode_CaseFold_11_hash(const OnigCodePoint code) -{ - static const unsigned short asso_values[] = - { - 1, 3085, 2, 20, 3, 307, 200, 8, 31, 159, - 2, 253, 33, 967, 3085, 3085, 3085, 3085, 3085, 3085, - 3085, 3085, 3085, 3085, 3085, 3085, 3085, 30, 3085, 3085, - 3085, 3085, 3085, 3085, 3085, 352, 3085, 3085, 3085, 3085, - 3085, 93, 3085, 3085, 3085, 3085, 3085, 3085, 3085, 3085, - 3085, 407, 3085, 3085, 3085, 3085, 3085, 3085, 3085, 201, - 3085, 3085, 14, 13, 373, 1, 3085, 3085, 503, 19, - 3085, 3085, 3085, 3085, 3085, 325, 3085, 3085, 290, 1064, - 484, 28, 1906, 447, 272, 414, 2002, 79, 905, 5, - 11, 22, 2024, 623, 761, 617, 1893, 45, 1874, 113, - 1856, 255, 1823, 96, 1463, 62, 1841, 130, 1798, 331, - 1771, 238, 1977, 147, 1387, 464, 1691, 187, 1639, 181, - 366, 580, 1331, 508, 1287, 547, 1583, 541, 400, 783, - 1944, 657, 1850, 932, 1785, 858, 1645, 681, 1412, 722, - 1622, 972, 1306, 807, 1942, 1282, 283, 1218, 1557, 1055, - 1406, 1258, 1401, 1168, 1327, 864, 893, 1123, 1714, 1195, - 1885, 1083, 2016, 1232, 823, 678, 1420, 1017, 155, 1261, - 86, 1351, 794, 1929, 51, 1525, 50, 221, 4, 1383, - 196, 325, 1, 1562, 102, 1441, 3, 1356, 226, 1304, - 271, 1516, 68, 1752, 37, 1469, 51, 1920, 143, 2059, - 198, 2095, 370, 2069, 137, 718, 407, 1926, 136 - }; - return asso_values[bits_of(code, 2)+81] + asso_values[bits_of(code, 1)+2] + asso_values[bits_of(code, 0)]; -} - -static const CodePointList3 * -onigenc_unicode_CaseFold_11_lookup(const OnigCodePoint code) -{ - enum - { - MIN_CODE_VALUE = 0x41, - MAX_CODE_VALUE = 0x1e921, - TOTAL_KEYWORDS = 1530, - MIN_WORD_LENGTH = 3, - MAX_WORD_LENGTH = 3, - MIN_HASH_VALUE = 5, - MAX_HASH_VALUE = 3084 - }; - - static const short wordlist[] = - { - -1, -1, -1, -1, -1, - /*0x1fe9*/ 850, - -1, - /*0x1f88*/ 775, - /*0x0408*/ 305, - /*0x0108*/ 61, - /*0x10408*/ 1276, - -1, - /*0xab88*/ 1174, - /*0x1f89*/ 776, - /*0x0409*/ 306, - /*0x2c69*/ 964, - /*0x10409*/ 1277, - /*0x2c08*/ 919, - /*0xab89*/ 1175, - /*0x1e88*/ 653, - /*0x1e08*/ 589, - -1, -1, - /*0x2c09*/ 920, - /*0x1f8a*/ 777, - /*0x040a*/ 307, - /*0x010a*/ 62, - /*0x1040a*/ 1278, - /*0x2c88*/ 978, - /*0xab8a*/ 1176, - /*0x1f80*/ 767, - /*0x0400*/ 297, - /*0x0100*/ 57, - /*0x10400*/ 1268, - /*0x2c0a*/ 921, - /*0xab80*/ 1166, - /*0x1e8a*/ 654, - /*0x1e0a*/ 590, - /*0x10c88*/ 1387, - /*0x0508*/ 425, - /*0x2c00*/ 911, - -1, - /*0x1e80*/ 649, - /*0x1e00*/ 585, - /*0x10c89*/ 1388, - /*0x2c8a*/ 979, - -1, - /*0x1f90*/ 783, - /*0x0410*/ 313, - /*0x0110*/ 65, - /*0x10410*/ 1284, - /*0x2c80*/ 974, - /*0xab90*/ 1182, - /*0x1ff3*/ 855, - -1, - /*0x10c8a*/ 1389, - /*0x050a*/ 426, - /*0x2c10*/ 927, - /*0xa780*/ 1106, - /*0x1e90*/ 657, - /*0x1e10*/ 593, - /*0x10c80*/ 1379, - /*0x0500*/ 421, - -1, - /*0x1f98*/ 791, - /*0x0418*/ 321, - /*0x0118*/ 69, - /*0x10418*/ 1292, - /*0x2c90*/ 982, - /*0xab98*/ 1190, - -1, - /*0x00df*/ 56, - /*0x00dd*/ 54, - /*0x10571*/ 1345, - /*0x2c18*/ 935, - /*0xa790*/ 1112, - /*0x1e98*/ 662, - /*0x1e18*/ 597, - /*0x10c90*/ 1395, - /*0x0510*/ 429, - /*0x2c6f*/ 968, - /*0x1f86*/ 773, - /*0x0406*/ 303, - /*0x0106*/ 60, - /*0x10406*/ 1274, - /*0x2c98*/ 986, - /*0xab86*/ 1172, - /*0x10573*/ 1347, - /*0x1fd9*/ 841, - /*0x0059*/ 23, - -1, - /*0x2c06*/ 917, - /*0xa798*/ 1115, - /*0x1e86*/ 652, - /*0x1e06*/ 588, - /*0x10c98*/ 1403, - /*0x0518*/ 433, - -1, - /*0x1f96*/ 789, - /*0x0416*/ 319, - /*0x0116*/ 68, - /*0x10416*/ 1290, - /*0x2c86*/ 977, - /*0xab96*/ 1188, - /*0x1fe7*/ 848, - -1, -1, - /*0x00d9*/ 50, - /*0x2c16*/ 933, - /*0xa786*/ 1109, - /*0x1e96*/ 660, - /*0x1e16*/ 596, - /*0x10c86*/ 1385, - /*0x0506*/ 424, - /*0x2c67*/ 963, - /*0x1f92*/ 785, - /*0x0412*/ 315, - /*0x0112*/ 66, - /*0x10412*/ 1286, - /*0x2c96*/ 985, - /*0xab92*/ 1184, - -1, -1, -1, -1, - /*0x2c12*/ 929, - /*0xa796*/ 1114, - /*0x1e92*/ 658, - /*0x1e12*/ 594, - /*0x10c96*/ 1401, - /*0x0516*/ 432, - -1, - /*0x1f9a*/ 793, - /*0x041a*/ 323, - /*0x011a*/ 70, - /*0x1041a*/ 1294, - /*0x2c92*/ 983, - /*0xab9a*/ 1192, - -1, - /*0x1ffb*/ 862, - /*0x017f*/ 120, - /*0x017b*/ 118, - /*0x2c1a*/ 937, - /*0xa792*/ 1113, - /*0x1e9a*/ 664, - /*0x1e1a*/ 598, - /*0x10c92*/ 1397, - /*0x0512*/ 430, - /*0x2c7f*/ 973, - /*0x1fa0*/ 799, - /*0x0420*/ 329, - /*0x0120*/ 73, - /*0x10420*/ 1300, - /*0x2c9a*/ 987, - /*0xaba0*/ 1198, - /*0x2c75*/ 971, - -1, - /*0x1fd7*/ 839, - /*0x0057*/ 21, - /*0x2c20*/ 943, - /*0xa79a*/ 1116, - /*0x1ea0*/ 667, - /*0x1e20*/ 601, - /*0x10c9a*/ 1405, - /*0x051a*/ 434, - /*0x0388*/ 235, - -1, -1, - /*0x037f*/ 233, - -1, - /*0x2ca0*/ 990, - /*0x0389*/ 236, - /*0x1057f*/ 1358, - /*0xa7f5*/ 1149, - -1, -1, -1, - /*0xa7a0*/ 1119, - -1, - /*0x10575*/ 1349, - /*0x10ca0*/ 1411, - /*0x0520*/ 437, - /*0x038a*/ 237, - /*0x1fa6*/ 805, - /*0x0426*/ 335, - /*0x0126*/ 76, - /*0x10426*/ 1306, - -1, - /*0xaba6*/ 1204, - /*0x1fa4*/ 803, - /*0x0424*/ 333, - /*0x0124*/ 75, - /*0x10424*/ 1304, - /*0x2c26*/ 949, - /*0xaba4*/ 1202, - /*0x1ea6*/ 670, - /*0x1e26*/ 604, - /*0x03f1*/ 288, - /*0x1fe3*/ 845, - /*0x2c24*/ 947, - /*0x1ff7*/ 858, - /*0x1ea4*/ 669, - /*0x1e24*/ 603, - -1, - /*0x2ca6*/ 993, - /*0x0390*/ 241, - /*0x0208*/ 194, - /*0x1c88*/ 538, - /*0x2c63*/ 961, - -1, - /*0x2ca4*/ 992, - /*0xa7a6*/ 1122, - -1, -1, - /*0x10ca6*/ 1417, - /*0x0526*/ 440, - -1, - /*0xa7a4*/ 1121, - -1, -1, - /*0x10ca4*/ 1415, - /*0x0524*/ 439, - /*0x0398*/ 249, - /*0x020a*/ 195, - /*0x0460*/ 345, - /*0x0160*/ 104, - -1, -1, - /*0x1feb*/ 852, - /*0x0200*/ 190, - /*0x1c80*/ 530, - /*0x13fb*/ 527, - -1, - /*0x2c60*/ 959, - /*0x10577*/ 1351, - /*0x1ee0*/ 699, - /*0x1e60*/ 633, - -1, - /*0x2c6b*/ 965, - /*0x0386*/ 234, - /*0x1f9e*/ 797, - /*0x041e*/ 327, - /*0x011e*/ 72, - /*0x1041e*/ 1298, - /*0x2ce0*/ 1022, - /*0xab9e*/ 1196, - /*0x0210*/ 198, - /*0x1c90*/ 539, - -1, - /*0x2ceb*/ 1024, - /*0x2c1e*/ 941, - -1, - /*0x1e9e*/ 666, - /*0x1e1e*/ 600, - -1, -1, - /*0x0396*/ 247, - /*0x1f94*/ 787, - /*0x0414*/ 317, - /*0x0114*/ 67, - /*0x10414*/ 1288, - /*0x2c9e*/ 989, - /*0xab94*/ 1186, - /*0x0218*/ 202, - /*0x1c98*/ 547, - -1, -1, - /*0x2c14*/ 931, - /*0xa79e*/ 1118, - /*0x1e94*/ 659, - /*0x1e14*/ 595, - /*0x10c9e*/ 1409, - /*0x051e*/ 436, - /*0x0392*/ 243, - /*0x1f83*/ 770, - /*0x0403*/ 300, - /*0x048a*/ 362, - /*0x10403*/ 1271, - /*0x2c94*/ 984, - /*0xab83*/ 1169, - /*0x0206*/ 193, - /*0x1c86*/ 536, - /*0x0480*/ 361, - /*0x2c6d*/ 966, - /*0x2c03*/ 914, - /*0x1e908*/ 1502, - /*0x0041*/ 0, - /*0x0141*/ 88, - /*0x10c94*/ 1399, - /*0x0514*/ 431, - /*0x039a*/ 251, - /*0x1e909*/ 1503, - /*0x2183*/ 884, - -1, - /*0x2ced*/ 1025, - -1, - /*0x03ff*/ 296, - /*0x0216*/ 201, - /*0x1c96*/ 545, - /*0x0490*/ 365, - -1, -1, - /*0x1e90a*/ 1504, - /*0x03f5*/ 290, - /*0x00c1*/ 27, - /*0x10c83*/ 1382, - -1, - /*0x03a0*/ 257, - /*0x1e900*/ 1494, - -1, -1, -1, -1, -1, - /*0x0212*/ 199, - /*0x1c92*/ 541, - /*0x0498*/ 369, - /*0x0541*/ 461, - -1, - /*0x0189*/ 126, - -1, -1, -1, -1, -1, - /*0x1e910*/ 1510, - -1, - /*0x1fe4*/ 846, - /*0x0464*/ 347, - /*0x0164*/ 106, - /*0x018a*/ 127, - /*0x021a*/ 203, - /*0x1c9a*/ 549, - /*0x1f9c*/ 795, - /*0x041c*/ 325, - /*0x011c*/ 71, - /*0x1041c*/ 1296, - /*0x2c64*/ 962, - /*0xab9c*/ 1194, - /*0x1ee4*/ 701, - /*0x1e64*/ 635, - /*0x03a6*/ 262, - /*0x1e918*/ 1518, - /*0x2c1c*/ 939, - -1, - /*0x01f1*/ 181, - /*0x1e1c*/ 599, - /*0x03a4*/ 260, - /*0x0220*/ 206, - /*0x1ca0*/ 555, - /*0x0496*/ 368, - -1, -1, - /*0x0190*/ 131, - /*0x2c9c*/ 988, - -1, -1, -1, - /*0x03f7*/ 291, - /*0x1e906*/ 1500, - -1, - /*0xa79c*/ 1117, - -1, -1, - /*0x10c9c*/ 1407, - /*0x051c*/ 435, - -1, - /*0x0492*/ 366, - /*0x1fa7*/ 806, - /*0x0427*/ 336, - /*0x0198*/ 137, - /*0x10427*/ 1307, - /*0x1ff9*/ 860, - /*0xaba7*/ 1205, - /*0x0179*/ 117, - -1, - /*0x1e916*/ 1516, - /*0x1f69*/ 760, - /*0x2c27*/ 950, - /*0x1f08*/ 715, - -1, - /*0x03e0*/ 279, - /*0x0226*/ 209, - /*0x1ca6*/ 561, - /*0x049a*/ 370, - /*0x1f09*/ 716, - -1, - /*0x0186*/ 124, - /*0x0224*/ 208, - /*0x1ca4*/ 559, - -1, -1, -1, - /*0x1e912*/ 1512, - /*0x01d9*/ 169, - -1, - /*0x1f0a*/ 717, - -1, - /*0x039e*/ 255, - /*0x10ca7*/ 1418, - -1, - /*0x04a0*/ 373, - /*0x1faf*/ 814, - /*0x042f*/ 344, - /*0x0196*/ 135, - -1, - /*0x10579*/ 1353, - /*0xabaf*/ 1213, - -1, -1, - /*0x1e91a*/ 1520, - /*0x017d*/ 119, - /*0x2c2f*/ 958, - -1, - /*0xfb00*/ 1230, - /*0x0394*/ 245, - /*0x1f84*/ 771, - /*0x0404*/ 301, - /*0x0104*/ 59, - /*0x10404*/ 1272, - -1, - /*0xab84*/ 1170, - -1, -1, - /*0x1f5f*/ 758, - /*0x1f5d*/ 757, - /*0x2c04*/ 915, - /*0x1e920*/ 1526, - /*0x1e84*/ 651, - /*0x1e04*/ 587, - -1, -1, -1, - /*0x10caf*/ 1426, - -1, - /*0x04a6*/ 376, - /*0x1f18*/ 723, - /*0x2c84*/ 976, - -1, - /*0x021e*/ 205, - /*0x1c9e*/ 553, - /*0x04a4*/ 375, - /*0x1f6f*/ 766, - /*0x1057d*/ 1356, - /*0xa784*/ 1108, - -1, -1, - /*0x10c84*/ 1383, - /*0x0504*/ 423, - /*0x1f82*/ 769, - /*0x0402*/ 299, - /*0x0102*/ 58, - /*0x10402*/ 1270, - -1, - /*0xab82*/ 1168, - /*0x01a0*/ 141, - /*0x0214*/ 200, - /*0x1c94*/ 543, - -1, - /*0x2c02*/ 913, - /*0x1f59*/ 755, - /*0x1e82*/ 650, - /*0x1e02*/ 586, - /*0x01d7*/ 168, - /*0x13f9*/ 525, - /*0xfb06*/ 1236, - /*0x1fa2*/ 801, - /*0x0422*/ 331, - /*0x0122*/ 74, - /*0x10422*/ 1302, - /*0x2c82*/ 975, - /*0xaba2*/ 1200, - -1, -1, - /*0x1c83*/ 533, - /*0x04e0*/ 405, - /*0x2c22*/ 945, - /*0xa782*/ 1107, - /*0x1ea2*/ 668, - /*0x1e22*/ 602, - /*0x10c82*/ 1381, - /*0x0502*/ 422, - /*0xfb16*/ 1240, - -1, - /*0x0241*/ 220, - /*0x03e4*/ 281, - -1, - /*0x2ca2*/ 991, - -1, - /*0x01a6*/ 144, - -1, - /*0x039c*/ 253, - /*0x049e*/ 372, - -1, - /*0xa7a2*/ 1120, - /*0x01a4*/ 143, - -1, - /*0x10ca2*/ 1413, - /*0x0522*/ 438, - -1, - /*0x10a0*/ 484, - /*0x13fd*/ 529, - -1, -1, - /*0x1f1a*/ 725, - /*0x2165*/ 873, - /*0x01f7*/ 185, - /*0x2169*/ 877, - /*0x2161*/ 869, - /*0x0494*/ 367, - /*0x1faa*/ 809, - /*0x042a*/ 339, - /*0x012a*/ 78, - /*0xa660*/ 1043, - -1, - /*0xabaa*/ 1208, - -1, -1, - /*0x1e91e*/ 1524, - -1, - /*0x2c2a*/ 953, - -1, - /*0x1eaa*/ 672, - /*0x1e2a*/ 606, - -1, -1, - /*0x03a7*/ 263, - -1, -1, - /*0x01e0*/ 172, - /*0x03f9*/ 292, - /*0x2caa*/ 995, - /*0x021c*/ 204, - /*0x1c9c*/ 551, - /*0x10a6*/ 490, - /*0x1e914*/ 1514, - -1, - /*0x04c1*/ 390, - /*0xa7aa*/ 1124, - /*0x104c1*/ 1325, - /*0x10a4*/ 488, - /*0x10caa*/ 1421, - /*0x052a*/ 442, - /*0x1fae*/ 813, - /*0x042e*/ 343, - /*0x012e*/ 80, - -1, -1, - /*0xabae*/ 1212, - /*0x1fac*/ 811, - /*0x042c*/ 341, - /*0x012c*/ 79, - /*0x1e903*/ 1497, - /*0x2c2e*/ 957, - /*0xabac*/ 1210, - /*0x1eae*/ 674, - /*0x1e2e*/ 608, - /*0x118a0*/ 1430, - -1, - /*0x2c2c*/ 955, - -1, - /*0x1eac*/ 673, - /*0x1e2c*/ 607, - /*0x0194*/ 134, - /*0x2cae*/ 997, - -1, -1, - /*0x03fd*/ 294, - /*0x1ca7*/ 562, - -1, - /*0x2cac*/ 996, - /*0xa7ae*/ 1128, - /*0x216f*/ 883, - -1, - /*0x10cae*/ 1425, - /*0x052e*/ 444, - -1, - /*0xa7ac*/ 1126, - -1, - /*0x04e4*/ 407, - /*0x10cac*/ 1423, - /*0x052c*/ 443, - /*0x1fa8*/ 807, - /*0x0428*/ 337, - /*0x0128*/ 77, - /*0x049c*/ 371, - -1, - /*0xaba8*/ 1206, - -1, -1, -1, - /*0x118a6*/ 1436, - /*0x2c28*/ 951, - -1, - /*0x1ea8*/ 671, - /*0x1e28*/ 605, - -1, - /*0x118a4*/ 1434, - -1, -1, - /*0x1f6b*/ 762, - /*0xff26*/ 1247, - /*0x1caf*/ 570, - /*0x2ca8*/ 994, - -1, -1, - /*0x2167*/ 875, - /*0xff24*/ 1245, - -1, - /*0x24c1*/ 896, - /*0xa7a8*/ 1123, - /*0x1e91c*/ 1522, - -1, - /*0x10ca8*/ 1419, - /*0x0528*/ 441, - /*0x0204*/ 192, - /*0x1c84*/ 534, - /*0xa664*/ 1045, - -1, - /*0x1f8e*/ 781, - /*0x040e*/ 311, - /*0x010e*/ 64, - /*0x1040e*/ 1282, - /*0xa77b*/ 1103, - /*0xab8e*/ 1180, - /*0x1f8c*/ 779, - /*0x040c*/ 309, - /*0x010c*/ 63, - /*0x1040c*/ 1280, - /*0x2c0e*/ 925, - /*0xab8c*/ 1178, - /*0x1e8e*/ 656, - /*0x1e0e*/ 592, - /*0x01e4*/ 174, - -1, - /*0x2c0c*/ 923, - /*0x10c1*/ 517, - /*0x1e8c*/ 655, - /*0x1e0c*/ 591, - /*0x019c*/ 138, - /*0x2c8e*/ 981, - /*0xfb14*/ 1238, - -1, -1, -1, - /*0x1f6d*/ 764, - /*0x2c8c*/ 980, - -1, - /*0x0202*/ 191, - /*0x1c82*/ 532, - /*0x10c8e*/ 1393, - /*0x050e*/ 428, - -1, -1, -1, -1, - /*0x10c8c*/ 1391, - /*0x050c*/ 427, - /*0xfb03*/ 1233, - /*0x1fb2*/ 815, - -1, - /*0x0132*/ 81, - -1, -1, - /*0xabb2*/ 1216, - /*0x0222*/ 207, - /*0x1ca2*/ 557, - /*0xa726*/ 1066, - /*0x03aa*/ 266, - -1, -1, - /*0x1eb2*/ 676, - /*0x1e32*/ 610, - /*0xa724*/ 1065, - /*0x01a7*/ 145, - -1, -1, -1, -1, -1, - /*0x2cb2*/ 999, - /*0x0054*/ 18, - /*0x0154*/ 98, - /*0x1fb8*/ 820, - -1, - /*0x2126*/ 864, - -1, - /*0xa7b2*/ 1131, - /*0xabb8*/ 1222, - -1, - /*0x10cb2*/ 1429, - /*0x0532*/ 446, - /*0x1ed4*/ 693, - /*0x1e54*/ 627, - /*0x1e904*/ 1498, - /*0x1eb8*/ 679, - /*0x1e38*/ 613, - -1, -1, - /*0x00d4*/ 46, - /*0x2163*/ 871, - /*0x2cd4*/ 1016, - -1, -1, - /*0x2cb8*/ 1002, - /*0x1f1c*/ 727, - -1, - /*0xa760*/ 1094, - /*0x01af*/ 149, - /*0x022a*/ 211, - /*0x1caa*/ 565, - /*0xa7b8*/ 1135, - /*0x0554*/ 480, - -1, -1, - /*0x0538*/ 452, - -1, -1, - /*0x04a2*/ 374, - /*0x10a7*/ 491, - /*0x1ffc*/ 863, - /*0x047c*/ 359, - /*0x0184*/ 123, - -1, - /*0x1fba*/ 822, - /*0x2160*/ 868, - -1, - /*0x1e902*/ 1496, - -1, - /*0xabba*/ 1224, - /*0x216b*/ 879, - -1, - /*0x1efc*/ 713, - /*0x1e7c*/ 647, - -1, -1, - /*0x1eba*/ 680, - /*0x1e3a*/ 614, - -1, -1, - /*0x03a8*/ 264, - -1, - /*0x022e*/ 213, - /*0x1cae*/ 569, - -1, - /*0x2cba*/ 1003, - -1, -1, - /*0x022c*/ 212, - /*0x1cac*/ 567, - -1, -1, - /*0xa7ba*/ 1136, - /*0x10af*/ 499, - /*0x1057c*/ 1355, - /*0x0182*/ 122, - /*0x053a*/ 454, - -1, -1, -1, -1, -1, - /*0x04aa*/ 378, - /*0x1f8d*/ 780, - /*0x040d*/ 310, - -1, - /*0x1040d*/ 1281, - -1, - /*0xab8d*/ 1179, - -1, -1, -1, - /*0x01a2*/ 142, - /*0x2c0d*/ 924, - /*0x1f2f*/ 736, - /*0x216d*/ 881, - /*0x118a7*/ 1437, - /*0x038e*/ 239, - -1, -1, -1, - /*0x0228*/ 210, - /*0x1ca8*/ 563, - /*0x038c*/ 238, - -1, -1, - /*0xff27*/ 1248, - /*0x0130*/ 1529, - -1, -1, - /*0xabb0*/ 1214, - /*0xa78d*/ 1111, - -1, -1, - /*0x10c8d*/ 1392, - /*0x04ae*/ 380, - /*0x1fdb*/ 843, - /*0x1eb0*/ 675, - /*0x1e30*/ 609, - -1, - /*0xfb04*/ 1234, - /*0x04ac*/ 379, - -1, -1, -1, -1, - /*0x2cb0*/ 998, - -1, -1, - /*0x1fbe*/ 825, - /*0x118af*/ 1445, - /*0xa764*/ 1096, - /*0x13fc*/ 528, - /*0xa7b0*/ 1129, - /*0xabbe*/ 1228, - /*0x00db*/ 52, - /*0x10cb0*/ 1427, - /*0x10a2*/ 486, - /*0x020e*/ 197, - -1, - /*0xff2f*/ 1256, - /*0x1ebe*/ 682, - /*0x1e3e*/ 616, - -1, - /*0x020c*/ 196, - /*0x1fd3*/ 837, - /*0x0053*/ 17, - -1, -1, - /*0x2164*/ 872, - /*0x2cbe*/ 1005, - -1, -1, - /*0xfb02*/ 1232, - /*0x04a8*/ 377, - -1, -1, - /*0xa7be*/ 1138, - -1, -1, -1, - /*0x053e*/ 458, - -1, -1, - /*0x00d3*/ 45, - -1, -1, -1, -1, - /*0x01ae*/ 148, - -1, -1, -1, -1, -1, - /*0x01ac*/ 147, - /*0xa779*/ 1102, - /*0x0553*/ 479, - /*0x0232*/ 215, - /*0x1cb2*/ 573, - /*0x1fb6*/ 818, - /*0x10aa*/ 494, - /*0x0136*/ 83, - -1, -1, - /*0xabb6*/ 1220, - /*0x1fca*/ 833, - /*0x004a*/ 8, - /*0x014a*/ 93, - -1, -1, - /*0x048e*/ 364, - /*0x1eb6*/ 678, - /*0x1e36*/ 612, - /*0x118a2*/ 1432, - -1, -1, - /*0x048c*/ 363, - /*0x1eca*/ 688, - /*0x1e4a*/ 622, - -1, - /*0x2cb6*/ 1001, - /*0x1f2a*/ 731, - /*0x1cb8*/ 579, - /*0xff22*/ 1243, - /*0x00ca*/ 36, - -1, - /*0x2cca*/ 1011, - /*0xa7b6*/ 1134, - -1, -1, -1, - /*0x0536*/ 450, - /*0xa77d*/ 1104, - /*0x10ae*/ 498, - /*0x1fcb*/ 834, - /*0x004b*/ 9, - /*0x1e90e*/ 1508, - /*0x054a*/ 470, - -1, - /*0x10ac*/ 496, - -1, -1, - /*0x1e90c*/ 1506, - -1, -1, -1, - /*0x1f87*/ 774, - /*0x0407*/ 304, - -1, - /*0x10407*/ 1275, - /*0x04b2*/ 382, - /*0xab87*/ 1173, - /*0x104b2*/ 1310, - /*0x00cb*/ 37, - /*0x1f2e*/ 735, - -1, - /*0x2c07*/ 918, - /*0x118aa*/ 1440, - -1, -1, - /*0x1f2c*/ 733, - -1, - /*0x023a*/ 216, - /*0x1cba*/ 581, - /*0x018e*/ 129, - -1, - /*0x054b*/ 471, - /*0xff2a*/ 1251, - -1, -1, -1, - /*0x04d4*/ 399, - /*0x10a8*/ 492, - /*0x1fb4*/ 817, - /*0x04b8*/ 385, - /*0x0134*/ 82, - /*0x104b8*/ 1316, - /*0x10c87*/ 1386, - /*0xabb4*/ 1218, - -1, -1, -1, - /*0x03b0*/ 268, - /*0xab71*/ 1151, - -1, - /*0x1eb4*/ 677, - /*0x1e34*/ 611, - -1, -1, - /*0xa722*/ 1064, - /*0x118ae*/ 1444, - -1, -1, - /*0x1f28*/ 729, - /*0x2cb4*/ 1000, - -1, - /*0x118ac*/ 1442, - /*0xab73*/ 1153, - -1, -1, - /*0xff2e*/ 1255, - /*0xa7b4*/ 1133, - -1, -1, - /*0x01b2*/ 151, - /*0x0534*/ 448, - /*0xff2c*/ 1253, - -1, -1, - /*0xa654*/ 1037, - -1, - /*0x04fc*/ 419, - -1, - /*0x1fbc*/ 824, - /*0x10588*/ 1367, - /*0x04ba*/ 386, - -1, - /*0x104ba*/ 1318, - /*0xabbc*/ 1226, - -1, - /*0x10589*/ 1368, - -1, -1, - /*0x0230*/ 214, - /*0x1cb0*/ 571, - /*0x1ebc*/ 681, - /*0x1e3c*/ 615, - -1, - /*0x01b8*/ 155, - /*0x118a8*/ 1438, - /*0x1f0e*/ 721, - /*0x1058a*/ 1369, - -1, - /*0xa72a*/ 1068, - /*0x2cbc*/ 1004, - -1, - /*0x1f0c*/ 719, - /*0x10580*/ 1359, - -1, - /*0xff28*/ 1249, - -1, - /*0xa7bc*/ 1137, - -1, -1, -1, - /*0x053c*/ 456, - /*0x24b8*/ 887, - /*0x023e*/ 219, - /*0x1cbe*/ 583, - /*0x10b2*/ 502, - -1, - /*0x212a*/ 865, - -1, -1, - /*0x10590*/ 1374, - -1, -1, -1, - /*0x1fd6*/ 838, - /*0x0056*/ 20, - /*0x0156*/ 99, - -1, -1, -1, -1, - /*0x01fc*/ 188, - /*0xa72e*/ 1070, - -1, -1, -1, - /*0x1ed6*/ 694, - /*0x1e56*/ 628, - /*0xa72c*/ 1069, - /*0x10b8*/ 508, - -1, -1, - /*0x04b0*/ 381, - /*0x00d6*/ 48, - /*0x104b0*/ 1308, - /*0x2cd6*/ 1017, - /*0x1e90d*/ 1507, - -1, - /*0xab7f*/ 1165, - /*0xab7b*/ 1161, - -1, -1, - /*0xa7d6*/ 1147, - /*0x24ba*/ 889, - /*0x10586*/ 1365, - /*0xab75*/ 1155, - /*0x0556*/ 482, - /*0x1f54*/ 753, - -1, -1, - /*0x1f38*/ 737, - -1, - /*0x1fc4*/ 828, - /*0x0044*/ 3, - -1, - /*0x1cb6*/ 577, - /*0x04be*/ 388, - -1, - /*0x104be*/ 1322, - -1, - /*0x024a*/ 226, - /*0xa728*/ 1067, - /*0x118b2*/ 1448, - -1, - /*0x1ec4*/ 685, - /*0x1e44*/ 619, - /*0xa688*/ 1054, - -1, -1, -1, - /*0x10ba*/ 510, - /*0x00c4*/ 30, - /*0xff32*/ 1259, - /*0x2cc4*/ 1008, - /*0x104d3*/ 1343, - -1, -1, -1, - /*0x10592*/ 1376, - -1, - /*0xa7c4*/ 1141, - /*0x0050*/ 14, - /*0x0150*/ 96, - /*0xa68a*/ 1055, - /*0x0544*/ 464, - -1, - /*0x118b8*/ 1454, - -1, -1, - /*0xa680*/ 1050, - -1, - /*0x1f3a*/ 739, - /*0x1ed0*/ 691, - /*0x1e50*/ 625, - -1, -1, - /*0xff38*/ 1265, - /*0x01db*/ 170, - -1, - /*0x00d0*/ 42, - /*0xab77*/ 1157, - /*0x2cd0*/ 1014, - /*0x1c87*/ 537, - -1, -1, -1, - /*0xa690*/ 1058, - /*0x04b6*/ 384, - /*0xa7d0*/ 1146, - /*0x104b6*/ 1314, - -1, -1, - /*0x0550*/ 476, - /*0x16e5f*/ 1493, - /*0x16e5d*/ 1491, - /*0x104ca*/ 1334, - -1, -1, -1, -1, - /*0x1fcc*/ 835, - /*0x004c*/ 10, - /*0x014c*/ 94, - /*0xa698*/ 1062, - -1, -1, - /*0x01d3*/ 166, - /*0x118ba*/ 1456, - /*0x24be*/ 893, - /*0x1cb4*/ 575, - /*0x1f0d*/ 720, - /*0x10b0*/ 500, - /*0x1ecc*/ 689, - /*0x1e4c*/ 623, - -1, -1, -1, - /*0xff3a*/ 1267, - /*0xa732*/ 1071, - /*0x00cc*/ 38, - /*0xa686*/ 1053, - /*0x2ccc*/ 1012, - /*0x04cb*/ 395, - -1, - /*0x104cb*/ 1335, - -1, -1, -1, -1, - /*0x16e59*/ 1487, - -1, - /*0xa64a*/ 1032, - /*0x054c*/ 472, - -1, -1, - /*0x10be*/ 514, - /*0x2132*/ 867, - /*0xa696*/ 1061, - -1, - /*0xa754*/ 1088, - -1, -1, - /*0xa738*/ 1074, - /*0x1f5b*/ 756, - -1, - /*0x1fc8*/ 831, - /*0x0048*/ 7, - /*0x01ca*/ 161, - -1, -1, -1, -1, - /*0x03d6*/ 274, - -1, - /*0xa692*/ 1059, - -1, - /*0x1f3e*/ 743, - /*0x1ec8*/ 687, - /*0x1e48*/ 621, - /*0x24b6*/ 885, - /*0x1e907*/ 1501, - /*0x04b4*/ 383, - -1, - /*0x104b4*/ 1312, - /*0x00c8*/ 34, - /*0x24ca*/ 905, - /*0x2cc8*/ 1010, - -1, - /*0x118b0*/ 1446, - -1, -1, - /*0xa69a*/ 1063, - -1, - /*0x004e*/ 12, - /*0x014e*/ 95, - -1, - /*0x01cb*/ 162, - /*0x0548*/ 468, - /*0xff30*/ 1257, - -1, -1, -1, -1, - /*0xa73a*/ 1075, - /*0x1ece*/ 690, - /*0x1e4e*/ 624, - /*0x10b6*/ 506, - -1, - /*0x0187*/ 125, - -1, -1, - /*0x00ce*/ 40, - /*0x118be*/ 1460, - /*0x2cce*/ 1013, - /*0x24cb*/ 906, - /*0x1fc2*/ 826, - /*0x0042*/ 1, - -1, - /*0x16e57*/ 1485, - -1, - /*0x10594*/ 1377, - /*0x04bc*/ 387, - -1, - /*0x104bc*/ 1320, - /*0x054e*/ 474, - -1, -1, - /*0x1ec2*/ 684, - /*0x1e42*/ 618, - /*0x1fd2*/ 836, - /*0x0052*/ 16, - /*0x0152*/ 97, - -1, - /*0x1f4a*/ 747, - /*0x00c2*/ 28, - -1, - /*0x2cc2*/ 1007, - /*0x10583*/ 1362, - /*0x03d0*/ 271, - -1, -1, - /*0x1ed2*/ 692, - /*0x1e52*/ 626, - /*0xa7c2*/ 1140, - -1, -1, -1, - /*0x0542*/ 462, - /*0x00d2*/ 44, - -1, - /*0x2cd2*/ 1015, - /*0x0244*/ 222, - -1, -1, -1, - /*0x1fc6*/ 829, - /*0x0046*/ 5, - -1, - /*0x1fd8*/ 840, - /*0x0058*/ 22, - /*0x0158*/ 100, - /*0x0552*/ 478, - /*0x1f4b*/ 748, - /*0x118b6*/ 1452, - -1, -1, - /*0x04d6*/ 400, - /*0x1ec6*/ 686, - /*0x1e46*/ 620, - -1, - /*0x1ed8*/ 695, - /*0x1e58*/ 629, - /*0xab79*/ 1159, - /*0xff36*/ 1263, - /*0x00c6*/ 32, - /*0x01bc*/ 156, - /*0x2cc6*/ 1009, - /*0x00d8*/ 49, - -1, - /*0x2cd8*/ 1018, - /*0x10b4*/ 504, - -1, -1, - /*0xa7c6*/ 1143, - /*0x1fab*/ 810, - /*0x042b*/ 340, - /*0xa7d8*/ 1148, - /*0x0546*/ 466, - /*0xa73e*/ 1077, - /*0xabab*/ 1209, - -1, - /*0x1ec0*/ 683, - /*0x1e40*/ 617, - /*0x24bc*/ 891, - /*0x2c2b*/ 954, - -1, -1, -1, - /*0x00c0*/ 26, - -1, - /*0x2cc0*/ 1006, - /*0x1fec*/ 853, - /*0x046c*/ 351, - /*0x016c*/ 110, - /*0xa656*/ 1038, - /*0x013d*/ 86, - /*0x104c4*/ 1328, - /*0xa7c0*/ 1139, - /*0xabbd*/ 1227, - /*0xab7d*/ 1163, - -1, - /*0x0540*/ 460, - /*0xa7ab*/ 1125, - /*0x1eec*/ 705, - /*0x1e6c*/ 639, - /*0x10cab*/ 1422, - /*0xa694*/ 1060, - -1, -1, - /*0x024c*/ 227, - /*0x10bc*/ 512, - -1, -1, -1, - /*0x1fc9*/ 832, - /*0x0049*/ 1528, - /*0x0149*/ 92, - -1, - /*0x1fa9*/ 808, - /*0x0429*/ 338, - -1, -1, - /*0x04d0*/ 397, - /*0xaba9*/ 1207, - /*0x104d0*/ 1340, - /*0x053d*/ 457, - -1, - /*0x118b4*/ 1450, - /*0x2c29*/ 952, - /*0xa736*/ 1073, - -1, - /*0x1f3c*/ 741, - /*0xa644*/ 1029, - /*0x00c9*/ 35, - -1, - /*0xa74a*/ 1083, - /*0x16e41*/ 1463, - /*0xff34*/ 1261, - /*0x1fda*/ 842, - /*0x005a*/ 24, - /*0x015a*/ 101, - -1, - /*0xa7c9*/ 1145, - /*0x1fea*/ 851, - /*0x046a*/ 350, - /*0x016a*/ 109, - /*0x0549*/ 469, - -1, - /*0x01c4*/ 157, - /*0x10ca9*/ 1420, - /*0x1eda*/ 696, - /*0x1e5a*/ 630, - -1, -1, - /*0x0248*/ 225, - /*0x1eea*/ 704, - /*0x1e6a*/ 638, - /*0x00da*/ 51, - -1, - /*0x2cda*/ 1019, - /*0xa650*/ 1035, - -1, -1, - /*0x03c2*/ 269, - /*0x104cc*/ 1336, - -1, - /*0x24c4*/ 899, - /*0x118bc*/ 1458, - -1, - /*0x10584*/ 1363, - /*0x1fe2*/ 844, - /*0x0462*/ 346, - /*0x0162*/ 105, - -1, - /*0x1fa1*/ 800, - /*0x0421*/ 330, - /*0x1f56*/ 754, - /*0x10421*/ 1301, - -1, - /*0xaba1*/ 1199, - /*0x2c62*/ 960, - /*0x024e*/ 228, - /*0x1ee2*/ 700, - /*0x1e62*/ 634, - /*0x2c21*/ 944, - -1, -1, -1, - /*0x1fc7*/ 830, - /*0x0047*/ 6, - /*0x0147*/ 91, - /*0x2ce2*/ 1023, - -1, - /*0x10c4*/ 520, - /*0x0045*/ 4, - /*0x0145*/ 90, - -1, -1, -1, - /*0x1fb9*/ 821, - /*0xa64c*/ 1033, - /*0x0139*/ 84, - /*0x10582*/ 1361, - /*0xa734*/ 1072, - /*0xabb9*/ 1223, - /*0x10ca1*/ 1412, - /*0x03d8*/ 275, - /*0x00c7*/ 33, - /*0x0055*/ 19, - /*0x104c8*/ 1332, - -1, -1, - /*0x00c5*/ 31, - -1, -1, -1, - /*0xa7c7*/ 1144, - -1, -1, -1, - /*0x0547*/ 467, - /*0xa7c5*/ 1142, - -1, - /*0x0345*/ 229, - -1, - /*0x0545*/ 465, - /*0x00d5*/ 47, - -1, - /*0x1fe8*/ 849, - /*0x0468*/ 349, - /*0x0168*/ 108, - /*0x0539*/ 453, - /*0x03ab*/ 267, - -1, - /*0x24cc*/ 907, - -1, - /*0x104ce*/ 1338, - -1, -1, - /*0x0555*/ 481, - /*0x1ee8*/ 703, - /*0x1e68*/ 637, - /*0x1f50*/ 751, - /*0xa73c*/ 1076, - /*0x0246*/ 224, - /*0xa648*/ 1031, - -1, -1, -1, - /*0x03ec*/ 285, - /*0x1f97*/ 790, - /*0x0417*/ 320, - -1, - /*0x10417*/ 1291, - -1, - /*0xab97*/ 1189, - /*0x1ff2*/ 854, - /*0x0472*/ 354, - /*0x0172*/ 113, - /*0x104c2*/ 1326, - /*0x2c17*/ 934, - /*0x01c8*/ 160, - /*0x1e97*/ 661, - -1, -1, - /*0xa684*/ 1052, - /*0x2c72*/ 970, - -1, - /*0x1ef2*/ 708, - /*0x1e72*/ 642, - -1, - /*0x04d2*/ 398, - /*0xa64e*/ 1034, - /*0x104d2*/ 1342, - /*0x1cab*/ 566, - -1, - /*0x03a9*/ 265, - /*0x2cf2*/ 1026, - -1, - /*0x24c8*/ 903, - -1, - /*0x10c97*/ 1402, - /*0x1f4c*/ 749, - -1, -1, -1, - /*0x0372*/ 231, - -1, - /*0xa756*/ 1089, - -1, - /*0x10572*/ 1346, - -1, - /*0x023d*/ 218, - /*0x1cbd*/ 582, - -1, - /*0xa642*/ 1028, - /*0x03da*/ 276, - -1, - /*0xa682*/ 1051, - /*0x104c6*/ 1330, - /*0x04d8*/ 401, - /*0x03ea*/ 284, - -1, -1, - /*0x046e*/ 352, - /*0x016e*/ 111, - /*0x24ce*/ 909, - -1, -1, - /*0xa652*/ 1036, - -1, -1, -1, - /*0x2c6e*/ 967, - /*0x015e*/ 103, - /*0x1eee*/ 706, - /*0x1e6e*/ 640, - -1, - /*0x1ca9*/ 564, - -1, -1, - /*0x04c0*/ 389, - -1, - /*0x104c0*/ 1324, - /*0x1ede*/ 698, - /*0x1e5e*/ 632, - /*0xa744*/ 1080, - /*0x1f48*/ 745, - /*0x03e2*/ 280, - /*0x24c2*/ 897, - -1, - /*0x00de*/ 55, - /*0x03a1*/ 258, - /*0x2cde*/ 1021, - -1, - /*0xa646*/ 1030, - -1, -1, - /*0xa658*/ 1039, - -1, -1, -1, -1, - /*0x04ec*/ 411, - /*0x1fc3*/ 827, - /*0x0043*/ 2, - /*0x0143*/ 89, - /*0x104bd*/ 1321, - -1, - /*0x1fe6*/ 847, - /*0x0466*/ 348, - /*0x0166*/ 107, - -1, -1, - /*0xa750*/ 1086, - -1, - /*0x10c2*/ 518, - -1, -1, - /*0xa640*/ 1027, - -1, - /*0x1ee6*/ 702, - /*0x1e66*/ 636, - /*0x00c3*/ 29, - -1, - /*0x03d5*/ 273, - /*0x04c9*/ 394, - -1, - /*0x104c9*/ 1333, - /*0x24c6*/ 901, - /*0x1fad*/ 812, - /*0x042d*/ 342, - /*0x1058e*/ 1372, - -1, - /*0x1ca1*/ 556, - /*0xabad*/ 1211, - /*0x0543*/ 463, - -1, - /*0x1058c*/ 1370, - -1, - /*0x2c2d*/ 956, - /*0xa66c*/ 1049, - -1, -1, -1, -1, - /*0x03e8*/ 283, - -1, -1, -1, - /*0x04da*/ 402, - /*0x1f52*/ 752, - /*0x0245*/ 223, - /*0x24c0*/ 895, - /*0xa74c*/ 1084, - /*0x04ea*/ 410, - -1, - /*0x01ec*/ 178, - /*0xa7ad*/ 1127, - /*0x1cb9*/ 580, - -1, - /*0x10cad*/ 1424, - -1, -1, -1, -1, -1, -1, - /*0x0397*/ 248, - /*0x1fbb*/ 823, - /*0xab7c*/ 1162, - /*0x013b*/ 85, - -1, -1, - /*0xabbb*/ 1225, - -1, -1, - /*0x24bd*/ 892, - -1, -1, - /*0x10c0*/ 516, - -1, - /*0x04e2*/ 406, - -1, - /*0x01a9*/ 146, - /*0x10ab*/ 495, - /*0x1fa5*/ 804, - /*0x0425*/ 334, - /*0xa65a*/ 1040, - /*0x10425*/ 1305, - -1, - /*0xaba5*/ 1203, - /*0x1fb7*/ 819, - /*0xa66a*/ 1048, - -1, -1, - /*0x2c25*/ 948, - /*0xabb7*/ 1221, - /*0x24c9*/ 904, - /*0xa748*/ 1082, - /*0x04c7*/ 393, - /*0x053b*/ 455, - /*0x104c7*/ 1331, - -1, - /*0x10bd*/ 513, - /*0x04c5*/ 392, - /*0x1f2b*/ 732, - /*0x104c5*/ 1329, - -1, - /*0x01ea*/ 177, - /*0x1c97*/ 546, - -1, - /*0x1e921*/ 1527, - /*0x104b9*/ 1317, - -1, -1, -1, - /*0x10ca5*/ 1416, - -1, -1, - /*0xa662*/ 1044, - /*0x03ee*/ 286, - -1, - /*0x1f6c*/ 763, - /*0x0537*/ 451, - /*0x1f3d*/ 742, - /*0xa74e*/ 1085, - -1, - /*0xa68e*/ 1057, - /*0x10a9*/ 493, - /*0x03de*/ 278, - -1, -1, -1, - /*0xa68c*/ 1056, - -1, - /*0x01e2*/ 173, - -1, - /*0x1fa3*/ 802, - /*0x0423*/ 332, - /*0x04e8*/ 409, - /*0x10423*/ 1303, - /*0x118ab*/ 1441, - /*0xaba3*/ 1201, - -1, -1, - /*0x1f49*/ 746, - -1, - /*0x2c23*/ 946, - /*0xa742*/ 1079, - /*0x1f29*/ 730, - -1, - /*0xff2b*/ 1252, - -1, - /*0x01c7*/ 159, - -1, -1, -1, -1, - /*0x01c5*/ 158, - -1, - /*0x118bd*/ 1459, - /*0x004d*/ 11, - /*0xa752*/ 1087, - -1, -1, -1, - /*0x03e6*/ 282, - /*0x04f2*/ 414, - /*0x10ca3*/ 1414, - -1, -1, - /*0x24c7*/ 902, - /*0x01d5*/ 167, - -1, - /*0x1f6a*/ 761, - /*0x1058d*/ 1371, - /*0x24c5*/ 900, - /*0xa668*/ 1047, - -1, - /*0x00cd*/ 39, - -1, -1, - /*0x24b9*/ 888, - -1, - /*0x10a1*/ 485, - /*0x118a9*/ 1439, - -1, - /*0x1e917*/ 1517, - /*0xa746*/ 1081, - -1, - /*0x16e54*/ 1482, - /*0xa758*/ 1090, - /*0x054d*/ 473, - /*0x01e8*/ 176, - -1, - /*0xff29*/ 1250, - -1, -1, - /*0x10c7*/ 522, - /*0x0470*/ 353, - /*0x0170*/ 112, - -1, - /*0x0243*/ 221, - /*0x10c5*/ 521, - -1, -1, -1, -1, - /*0x2c70*/ 969, - /*0x10b9*/ 509, - /*0x1ef0*/ 707, - /*0x1e70*/ 641, - /*0xa740*/ 1078, - -1, - /*0x04ee*/ 412, - /*0x0197*/ 136, - -1, - /*0x1f9d*/ 796, - /*0x041d*/ 326, - -1, - /*0x1041d*/ 1297, - /*0x01f2*/ 182, - /*0xab9d*/ 1195, - /*0x04de*/ 404, - -1, -1, -1, - /*0x2c1d*/ 940, - /*0x0370*/ 230, - /*0x1cad*/ 568, - /*0x1f39*/ 738, - -1, - /*0x10570*/ 1344, - -1, - /*0xa76c*/ 1100, - /*0x212b*/ 866, - /*0xabb5*/ 1219, - -1, -1, -1, -1, - /*0x118a1*/ 1431, - -1, - /*0x03a5*/ 261, - /*0x1f9b*/ 794, - /*0x041b*/ 324, - -1, - /*0x1041b*/ 1295, - /*0x10c9d*/ 1408, - /*0xab9b*/ 1193, - /*0x00b5*/ 25, - /*0xff21*/ 1242, - /*0x216c*/ 880, - -1, - /*0x2c1b*/ 938, - /*0x04c3*/ 391, - /*0x1e9b*/ 665, - /*0x104c3*/ 1327, - -1, - /*0x1f68*/ 759, - /*0x04e6*/ 408, - /*0xa65e*/ 1042, - -1, - /*0x0535*/ 449, - -1, -1, - /*0x118b9*/ 1455, - /*0x023b*/ 217, - /*0x01ee*/ 179, - /*0x1f95*/ 788, - /*0x0415*/ 318, - -1, - /*0x10415*/ 1289, - -1, - /*0xab95*/ 1187, - /*0x10c9b*/ 1406, - /*0xff39*/ 1266, - /*0x01de*/ 171, - -1, - /*0x2c15*/ 932, - -1, - /*0xa75a*/ 1091, - -1, -1, -1, - /*0x1ca5*/ 560, - /*0xa76a*/ 1099, - /*0x1f99*/ 792, - /*0x0419*/ 322, - -1, - /*0x10419*/ 1293, - /*0x1cb7*/ 578, - /*0xab99*/ 1191, - /*0xfb17*/ 1241, - -1, - /*0x03a3*/ 259, - /*0x1fb3*/ 816, - /*0x2c19*/ 936, - /*0xa666*/ 1046, - /*0x1e99*/ 663, - /*0x10c95*/ 1400, - /*0xabb3*/ 1217, - /*0x1f93*/ 786, - /*0x0413*/ 316, - /*0x216a*/ 878, - /*0x10413*/ 1287, - /*0x16e5b*/ 1489, - /*0xab93*/ 1185, - -1, -1, -1, -1, - /*0x2c13*/ 930, - /*0xa762*/ 1095, - /*0x01e6*/ 175, - -1, -1, - /*0x0587*/ 483, - /*0x10c99*/ 1404, - /*0x10587*/ 1366, - /*0x1f91*/ 784, - /*0x0411*/ 314, - /*0x104bb*/ 1319, - /*0x10411*/ 1285, - /*0xa7b3*/ 1132, - /*0xab91*/ 1183, - -1, - /*0x24c3*/ 898, - /*0x0533*/ 447, - -1, - /*0x2c11*/ 928, - /*0x2162*/ 870, - /*0x004f*/ 13, - /*0x10c93*/ 1398, - /*0x1f6e*/ 765, - /*0x16e53*/ 1481, - -1, - /*0x1ca3*/ 558, - -1, - /*0x1f8f*/ 782, - /*0x040f*/ 312, - -1, - /*0x1040f*/ 1283, - -1, - /*0xab8f*/ 1181, - /*0x104b7*/ 1315, - -1, -1, -1, - /*0x2c0f*/ 926, - /*0x00cf*/ 41, - /*0x10c91*/ 1396, - /*0x1f81*/ 768, - /*0x0401*/ 298, - /*0x10c3*/ 519, - /*0x10401*/ 1269, - /*0x03f0*/ 287, - /*0xab81*/ 1167, - -1, -1, -1, -1, - /*0x2c01*/ 912, - /*0x054f*/ 475, - -1, -1, - /*0x1ff4*/ 856, - /*0x0474*/ 355, - /*0x0174*/ 114, - -1, - /*0x10c8f*/ 1394, - /*0xa768*/ 1098, - -1, - /*0x047e*/ 360, - -1, - /*0x039d*/ 254, - /*0x16e4a*/ 1472, - /*0x015c*/ 102, - /*0x1ef4*/ 709, - /*0x1e74*/ 643, - /*0x10ad*/ 497, - -1, - /*0x2c7e*/ 972, - /*0x10c81*/ 1380, - /*0x1efe*/ 714, - /*0x1e7e*/ 648, - -1, - /*0x1edc*/ 697, - /*0x1e5c*/ 631, - /*0x2168*/ 876, - /*0x013f*/ 87, - -1, - /*0x24bb*/ 890, - /*0xabbf*/ 1229, - /*0x00dc*/ 53, - /*0xabb1*/ 1215, - /*0x2cdc*/ 1020, - /*0x01b7*/ 154, - -1, -1, - /*0x10574*/ 1348, - /*0x1f2d*/ 734, - /*0x039b*/ 252, - -1, -1, - /*0x16e4b*/ 1473, - /*0x1057e*/ 1357, - -1, -1, -1, -1, -1, - /*0x04cd*/ 396, - -1, - /*0x104cd*/ 1337, - /*0x24b7*/ 886, - -1, - /*0x1c9d*/ 552, - /*0xa7b1*/ 1130, - /*0x10bb*/ 511, - /*0x053f*/ 459, - /*0x10cb1*/ 1428, - /*0x0531*/ 445, - /*0x1f9f*/ 798, - /*0x041f*/ 328, - -1, - /*0x1041f*/ 1299, - /*0x0395*/ 246, - /*0xab9f*/ 1197, - -1, -1, - /*0x1cb5*/ 576, - -1, - /*0x2c1f*/ 942, - -1, -1, - /*0x10a5*/ 489, - /*0x118ad*/ 1443, - -1, -1, - /*0x1f3b*/ 740, - -1, - /*0x10b7*/ 507, - -1, - /*0x1c9b*/ 550, - /*0x0399*/ 250, - /*0xa76e*/ 1101, - /*0xff2d*/ 1254, - /*0x1f85*/ 772, - /*0x0405*/ 302, - /*0x04f0*/ 413, - /*0x10405*/ 1273, - -1, - /*0xab85*/ 1171, - /*0x10c9f*/ 1410, - /*0xa75e*/ 1093, - -1, -1, - /*0x2c05*/ 916, - -1, - /*0x0393*/ 244, - -1, -1, - /*0x0051*/ 15, - /*0x216e*/ 882, - -1, - /*0x01cd*/ 163, - -1, -1, - /*0x1c95*/ 544, - /*0x1f8b*/ 778, - /*0x040b*/ 308, - -1, - /*0x1040b*/ 1279, - -1, - /*0xab8b*/ 1177, - /*0x118bb*/ 1457, - -1, - /*0x0391*/ 242, - /*0x10c85*/ 1384, - /*0x2c0b*/ 922, - /*0x00d1*/ 43, - -1, -1, - /*0x24cd*/ 908, - /*0x104b5*/ 1313, - -1, - /*0x1c99*/ 548, - /*0x10a3*/ 487, - /*0x03cf*/ 270, - -1, -1, - /*0xa766*/ 1097, - /*0x118a5*/ 1435, - /*0x0551*/ 477, - /*0x1e91d*/ 1523, - /*0x1cb3*/ 574, - /*0x038f*/ 240, - /*0xa78b*/ 1110, - /*0x118b7*/ 1453, - -1, - /*0x10c8b*/ 1390, - /*0x1c93*/ 542, - /*0xff25*/ 1246, - /*0x01f0*/ 180, - /*0x1ff6*/ 857, - /*0x0476*/ 356, - /*0x0176*/ 115, - -1, - /*0xff37*/ 1264, - /*0x2166*/ 874, - /*0x10cd*/ 523, - -1, -1, -1, - /*0x1ffa*/ 861, - /*0x047a*/ 358, - /*0x1ef6*/ 710, - /*0x1e76*/ 644, - -1, - /*0x1c91*/ 540, - -1, - /*0x1e91b*/ 1521, - /*0x019d*/ 139, - /*0x03f4*/ 289, - -1, -1, - /*0x1efa*/ 712, - /*0x1e7a*/ 646, - /*0x16e56*/ 1484, - /*0x03fe*/ 295, - -1, - /*0x1f4d*/ 750, - /*0x03dc*/ 277, - -1, - /*0x0376*/ 232, - -1, - /*0x01b5*/ 153, - -1, - /*0x10576*/ 1350, - -1, - /*0x1ff8*/ 859, - /*0x0478*/ 357, - /*0x0178*/ 116, - -1, - /*0x118a3*/ 1433, - -1, - /*0x1e915*/ 1515, - -1, - /*0x1057a*/ 1354, - /*0x104b3*/ 1311, - -1, - /*0x1c81*/ 531, - /*0x1ef8*/ 711, - /*0x1e78*/ 645, - /*0xff23*/ 1244, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, - /*0x1e919*/ 1519, - -1, - /*0x16e44*/ 1466, - -1, -1, -1, -1, -1, -1, - -1, - /*0x10578*/ 1352, - -1, -1, -1, -1, - /*0x1e913*/ 1513, - /*0x039f*/ 256, - /*0x10b5*/ 505, - -1, -1, - /*0x104cf*/ 1339, - -1, -1, - /*0x1cbf*/ 584, - /*0x1f1d*/ 728, - /*0x1cb1*/ 572, - -1, -1, -1, -1, - /*0x16e50*/ 1478, - -1, -1, - /*0x1e911*/ 1511, - -1, -1, -1, - /*0x01b3*/ 152, - -1, -1, -1, -1, - /*0x13fa*/ 526, - /*0x0193*/ 133, - -1, -1, -1, -1, -1, -1, - -1, - /*0x1f1b*/ 726, - /*0x1e90f*/ 1509, - /*0x04f4*/ 415, - -1, - /*0x03d1*/ 272, - -1, -1, - /*0x1c9f*/ 554, - /*0x04fe*/ 420, - -1, - /*0x0191*/ 132, - /*0x04dc*/ 403, - -1, -1, - /*0x1e901*/ 1495, - -1, -1, - /*0x13f8*/ 524, - -1, - /*0x16e4c*/ 1474, - -1, - /*0x01cf*/ 164, - -1, - /*0x118b5*/ 1451, - -1, -1, - /*0x104bf*/ 1323, - -1, - /*0x104b1*/ 1309, - /*0x018f*/ 130, - -1, - /*0x10b3*/ 503, - /*0x1c85*/ 535, - /*0xff35*/ 1262, - -1, -1, -1, - /*0xfb15*/ 1239, - -1, - /*0x24cf*/ 910, - -1, -1, - /*0x0181*/ 121, - /*0x1f19*/ 724, - -1, -1, -1, -1, -1, - /*0xa65c*/ 1041, - -1, -1, -1, -1, -1, -1, - /*0x01f4*/ 183, - /*0x03fa*/ 293, - -1, -1, -1, -1, - /*0x01fe*/ 189, - -1, - /*0x16e48*/ 1470, - -1, -1, -1, -1, -1, - /*0xfb13*/ 1237, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, - /*0x01b1*/ 150, - -1, -1, -1, -1, - /*0x1e91f*/ 1525, - -1, -1, - /*0x118b3*/ 1449, - -1, -1, - /*0x16e4e*/ 1476, - -1, -1, -1, - /*0x1f0f*/ 722, - /*0x24bf*/ 894, - -1, - /*0xff33*/ 1260, - -1, - /*0x104d1*/ 1341, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, - /*0x1e905*/ 1499, - -1, -1, - /*0x019f*/ 140, - /*0x16e42*/ 1464, - -1, -1, -1, -1, -1, - /*0xfb01*/ 1231, - -1, -1, - /*0x10bf*/ 515, - -1, - /*0x10b1*/ 501, - -1, -1, - /*0x16e52*/ 1480, - -1, -1, -1, - /*0x1e90b*/ 1505, - -1, -1, -1, -1, -1, -1, - -1, -1, - /*0x04f6*/ 416, - -1, -1, - /*0x1f3f*/ 744, - -1, -1, -1, -1, -1, -1, - /*0x04fa*/ 418, - /*0x01d1*/ 165, - -1, - /*0x16e46*/ 1468, - -1, -1, - /*0x16e58*/ 1486, - -1, -1, - /*0x018b*/ 128, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, - /*0x04f8*/ 417, - /*0x16e40*/ 1462, - -1, - /*0x118bf*/ 1461, - -1, - /*0x118b1*/ 1447, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, - /*0xff31*/ 1258, - -1, -1, - /*0x01f6*/ 184, - -1, -1, -1, -1, -1, -1, - -1, -1, - /*0xab72*/ 1152, - /*0x01fa*/ 187, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, - /*0xfb05*/ 1235, - -1, -1, -1, -1, -1, -1, - /*0x16e49*/ 1471, - -1, -1, - /*0x1f0b*/ 718, - -1, -1, -1, -1, - /*0x01f8*/ 186, - -1, -1, -1, -1, -1, -1, - -1, -1, - /*0xa77e*/ 1105, - -1, -1, - /*0xa75c*/ 1092, - -1, -1, -1, - /*0x16e5a*/ 1488, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, - /*0x16e47*/ 1469, - -1, -1, -1, -1, - /*0x16e45*/ 1467, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, - /*0x16e55*/ 1483, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, - /*0x16e5e*/ 1492, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, - /*0x16e43*/ 1465, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, - /*0xab70*/ 1150, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, - /*0x16e4d*/ 1475, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, - /*0x10595*/ 1378, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, - /*0xab74*/ 1154, - -1, -1, -1, -1, -1, - /*0xab7e*/ 1164, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, - /*0x10591*/ 1375, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - /*0x1058f*/ 1373, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - /*0x10581*/ 1360, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, - /*0x16e4f*/ 1477, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - /*0xab76*/ 1156, - -1, -1, -1, -1, -1, - /*0x10585*/ 1364, - -1, -1, -1, - /*0xab7a*/ 1160, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, - /*0x16e5c*/ 1490, - -1, -1, -1, -1, - /*0xab78*/ 1158, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, - /*0x16e51*/ 1479 - }; - - if (code <= MAX_CODE_VALUE && code >= MIN_CODE_VALUE) - { - register unsigned int key = onigenc_unicode_CaseFold_11_hash(code); - - if (key <= MAX_HASH_VALUE) - { - register short s = wordlist[key]; - - if (s >= 0 && code1_equal(code, CaseFold_11_Table[s].from)) - return &CaseFold_11_Table[s].to; - } - } - return 0; -} - -static const CaseUnfold_11_Type CaseUnfold_11_Table[] = { -#define CaseUnfold_11 (*(CaseUnfold_11_Type (*)[1395])(CaseUnfold_11_Table+0)) - {0x0061, {1|U, {0x0041}}}, - {0x0062, {1|U, {0x0042}}}, - {0x0063, {1|U, {0x0043}}}, - {0x0064, {1|U, {0x0044}}}, - {0x0065, {1|U, {0x0045}}}, - {0x0066, {1|U, {0x0046}}}, - {0x0067, {1|U, {0x0047}}}, - {0x0068, {1|U, {0x0048}}}, - {0x006a, {1|U, {0x004a}}}, - {0x006b, {2|U, {0x004b, 0x212a}}}, - {0x006c, {1|U, {0x004c}}}, - {0x006d, {1|U, {0x004d}}}, - {0x006e, {1|U, {0x004e}}}, - {0x006f, {1|U, {0x004f}}}, - {0x0070, {1|U, {0x0050}}}, - {0x0071, {1|U, {0x0051}}}, - {0x0072, {1|U, {0x0052}}}, - {0x0073, {2|U, {0x0053, 0x017f}}}, - {0x0074, {1|U, {0x0054}}}, - {0x0075, {1|U, {0x0055}}}, - {0x0076, {1|U, {0x0056}}}, - {0x0077, {1|U, {0x0057}}}, - {0x0078, {1|U, {0x0058}}}, - {0x0079, {1|U, {0x0059}}}, - {0x007a, {1|U, {0x005a}}}, - {0x00e0, {1|U, {0x00c0}}}, - {0x00e1, {1|U, {0x00c1}}}, - {0x00e2, {1|U, {0x00c2}}}, - {0x00e3, {1|U, {0x00c3}}}, - {0x00e4, {1|U, {0x00c4}}}, - {0x00e5, {2|U, {0x00c5, 0x212b}}}, - {0x00e6, {1|U, {0x00c6}}}, - {0x00e7, {1|U, {0x00c7}}}, - {0x00e8, {1|U, {0x00c8}}}, - {0x00e9, {1|U, {0x00c9}}}, - {0x00ea, {1|U, {0x00ca}}}, - {0x00eb, {1|U, {0x00cb}}}, - {0x00ec, {1|U, {0x00cc}}}, - {0x00ed, {1|U, {0x00cd}}}, - {0x00ee, {1|U, {0x00ce}}}, - {0x00ef, {1|U, {0x00cf}}}, - {0x00f0, {1|U, {0x00d0}}}, - {0x00f1, {1|U, {0x00d1}}}, - {0x00f2, {1|U, {0x00d2}}}, - {0x00f3, {1|U, {0x00d3}}}, - {0x00f4, {1|U, {0x00d4}}}, - {0x00f5, {1|U, {0x00d5}}}, - {0x00f6, {1|U, {0x00d6}}}, - {0x00f8, {1|U, {0x00d8}}}, - {0x00f9, {1|U, {0x00d9}}}, - {0x00fa, {1|U, {0x00da}}}, - {0x00fb, {1|U, {0x00db}}}, - {0x00fc, {1|U, {0x00dc}}}, - {0x00fd, {1|U, {0x00dd}}}, - {0x00fe, {1|U, {0x00de}}}, - {0x00ff, {1|U, {0x0178}}}, - {0x0101, {1|U, {0x0100}}}, - {0x0103, {1|U, {0x0102}}}, - {0x0105, {1|U, {0x0104}}}, - {0x0107, {1|U, {0x0106}}}, - {0x0109, {1|U, {0x0108}}}, - {0x010b, {1|U, {0x010a}}}, - {0x010d, {1|U, {0x010c}}}, - {0x010f, {1|U, {0x010e}}}, - {0x0111, {1|U, {0x0110}}}, - {0x0113, {1|U, {0x0112}}}, - {0x0115, {1|U, {0x0114}}}, - {0x0117, {1|U, {0x0116}}}, - {0x0119, {1|U, {0x0118}}}, - {0x011b, {1|U, {0x011a}}}, - {0x011d, {1|U, {0x011c}}}, - {0x011f, {1|U, {0x011e}}}, - {0x0121, {1|U, {0x0120}}}, - {0x0123, {1|U, {0x0122}}}, - {0x0125, {1|U, {0x0124}}}, - {0x0127, {1|U, {0x0126}}}, - {0x0129, {1|U, {0x0128}}}, - {0x012b, {1|U, {0x012a}}}, - {0x012d, {1|U, {0x012c}}}, - {0x012f, {1|U, {0x012e}}}, - {0x0133, {1|U, {0x0132}}}, - {0x0135, {1|U, {0x0134}}}, - {0x0137, {1|U, {0x0136}}}, - {0x013a, {1|U, {0x0139}}}, - {0x013c, {1|U, {0x013b}}}, - {0x013e, {1|U, {0x013d}}}, - {0x0140, {1|U, {0x013f}}}, - {0x0142, {1|U, {0x0141}}}, - {0x0144, {1|U, {0x0143}}}, - {0x0146, {1|U, {0x0145}}}, - {0x0148, {1|U, {0x0147}}}, - {0x014b, {1|U, {0x014a}}}, - {0x014d, {1|U, {0x014c}}}, - {0x014f, {1|U, {0x014e}}}, - {0x0151, {1|U, {0x0150}}}, - {0x0153, {1|U, {0x0152}}}, - {0x0155, {1|U, {0x0154}}}, - {0x0157, {1|U, {0x0156}}}, - {0x0159, {1|U, {0x0158}}}, - {0x015b, {1|U, {0x015a}}}, - {0x015d, {1|U, {0x015c}}}, - {0x015f, {1|U, {0x015e}}}, - {0x0161, {1|U, {0x0160}}}, - {0x0163, {1|U, {0x0162}}}, - {0x0165, {1|U, {0x0164}}}, - {0x0167, {1|U, {0x0166}}}, - {0x0169, {1|U, {0x0168}}}, - {0x016b, {1|U, {0x016a}}}, - {0x016d, {1|U, {0x016c}}}, - {0x016f, {1|U, {0x016e}}}, - {0x0171, {1|U, {0x0170}}}, - {0x0173, {1|U, {0x0172}}}, - {0x0175, {1|U, {0x0174}}}, - {0x0177, {1|U, {0x0176}}}, - {0x017a, {1|U, {0x0179}}}, - {0x017c, {1|U, {0x017b}}}, - {0x017e, {1|U, {0x017d}}}, - {0x0180, {1|U, {0x0243}}}, - {0x0183, {1|U, {0x0182}}}, - {0x0185, {1|U, {0x0184}}}, - {0x0188, {1|U, {0x0187}}}, - {0x018c, {1|U, {0x018b}}}, - {0x0192, {1|U, {0x0191}}}, - {0x0195, {1|U, {0x01f6}}}, - {0x0199, {1|U, {0x0198}}}, - {0x019a, {1|U, {0x023d}}}, - {0x019e, {1|U, {0x0220}}}, - {0x01a1, {1|U, {0x01a0}}}, - {0x01a3, {1|U, {0x01a2}}}, - {0x01a5, {1|U, {0x01a4}}}, - {0x01a8, {1|U, {0x01a7}}}, - {0x01ad, {1|U, {0x01ac}}}, - {0x01b0, {1|U, {0x01af}}}, - {0x01b4, {1|U, {0x01b3}}}, - {0x01b6, {1|U, {0x01b5}}}, - {0x01b9, {1|U, {0x01b8}}}, - {0x01bd, {1|U, {0x01bc}}}, - {0x01bf, {1|U, {0x01f7}}}, - {0x01c6, {2|U|ST, {0x01c4, 0x01c5}}}, - {0x01c9, {2|U|ST, {0x01c7, 0x01c8}}}, - {0x01cc, {2|U|ST, {0x01ca, 0x01cb}}}, - {0x01ce, {1|U, {0x01cd}}}, - {0x01d0, {1|U, {0x01cf}}}, - {0x01d2, {1|U, {0x01d1}}}, - {0x01d4, {1|U, {0x01d3}}}, - {0x01d6, {1|U, {0x01d5}}}, - {0x01d8, {1|U, {0x01d7}}}, - {0x01da, {1|U, {0x01d9}}}, - {0x01dc, {1|U, {0x01db}}}, - {0x01dd, {1|U, {0x018e}}}, - {0x01df, {1|U, {0x01de}}}, - {0x01e1, {1|U, {0x01e0}}}, - {0x01e3, {1|U, {0x01e2}}}, - {0x01e5, {1|U, {0x01e4}}}, - {0x01e7, {1|U, {0x01e6}}}, - {0x01e9, {1|U, {0x01e8}}}, - {0x01eb, {1|U, {0x01ea}}}, - {0x01ed, {1|U, {0x01ec}}}, - {0x01ef, {1|U, {0x01ee}}}, - {0x01f3, {2|U|ST, {0x01f1, 0x01f2}}}, - {0x01f5, {1|U, {0x01f4}}}, - {0x01f9, {1|U, {0x01f8}}}, - {0x01fb, {1|U, {0x01fa}}}, - {0x01fd, {1|U, {0x01fc}}}, - {0x01ff, {1|U, {0x01fe}}}, - {0x0201, {1|U, {0x0200}}}, - {0x0203, {1|U, {0x0202}}}, - {0x0205, {1|U, {0x0204}}}, - {0x0207, {1|U, {0x0206}}}, - {0x0209, {1|U, {0x0208}}}, - {0x020b, {1|U, {0x020a}}}, - {0x020d, {1|U, {0x020c}}}, - {0x020f, {1|U, {0x020e}}}, - {0x0211, {1|U, {0x0210}}}, - {0x0213, {1|U, {0x0212}}}, - {0x0215, {1|U, {0x0214}}}, - {0x0217, {1|U, {0x0216}}}, - {0x0219, {1|U, {0x0218}}}, - {0x021b, {1|U, {0x021a}}}, - {0x021d, {1|U, {0x021c}}}, - {0x021f, {1|U, {0x021e}}}, - {0x0223, {1|U, {0x0222}}}, - {0x0225, {1|U, {0x0224}}}, - {0x0227, {1|U, {0x0226}}}, - {0x0229, {1|U, {0x0228}}}, - {0x022b, {1|U, {0x022a}}}, - {0x022d, {1|U, {0x022c}}}, - {0x022f, {1|U, {0x022e}}}, - {0x0231, {1|U, {0x0230}}}, - {0x0233, {1|U, {0x0232}}}, - {0x023c, {1|U, {0x023b}}}, - {0x023f, {1|U, {0x2c7e}}}, - {0x0240, {1|U, {0x2c7f}}}, - {0x0242, {1|U, {0x0241}}}, - {0x0247, {1|U, {0x0246}}}, - {0x0249, {1|U, {0x0248}}}, - {0x024b, {1|U, {0x024a}}}, - {0x024d, {1|U, {0x024c}}}, - {0x024f, {1|U, {0x024e}}}, - {0x0250, {1|U, {0x2c6f}}}, - {0x0251, {1|U, {0x2c6d}}}, - {0x0252, {1|U, {0x2c70}}}, - {0x0253, {1|U, {0x0181}}}, - {0x0254, {1|U, {0x0186}}}, - {0x0256, {1|U, {0x0189}}}, - {0x0257, {1|U, {0x018a}}}, - {0x0259, {1|U, {0x018f}}}, - {0x025b, {1|U, {0x0190}}}, - {0x025c, {1|U, {0xa7ab}}}, - {0x0260, {1|U, {0x0193}}}, - {0x0261, {1|U, {0xa7ac}}}, - {0x0263, {1|U, {0x0194}}}, - {0x0265, {1|U, {0xa78d}}}, - {0x0266, {1|U, {0xa7aa}}}, - {0x0268, {1|U, {0x0197}}}, - {0x0269, {1|U, {0x0196}}}, - {0x026a, {1|U, {0xa7ae}}}, - {0x026b, {1|U, {0x2c62}}}, - {0x026c, {1|U, {0xa7ad}}}, - {0x026f, {1|U, {0x019c}}}, - {0x0271, {1|U, {0x2c6e}}}, - {0x0272, {1|U, {0x019d}}}, - {0x0275, {1|U, {0x019f}}}, - {0x027d, {1|U, {0x2c64}}}, - {0x0280, {1|U, {0x01a6}}}, - {0x0282, {1|U, {0xa7c5}}}, - {0x0283, {1|U, {0x01a9}}}, - {0x0287, {1|U, {0xa7b1}}}, - {0x0288, {1|U, {0x01ae}}}, - {0x0289, {1|U, {0x0244}}}, - {0x028a, {1|U, {0x01b1}}}, - {0x028b, {1|U, {0x01b2}}}, - {0x028c, {1|U, {0x0245}}}, - {0x0292, {1|U, {0x01b7}}}, - {0x029d, {1|U, {0xa7b2}}}, - {0x029e, {1|U, {0xa7b0}}}, - {0x0371, {1|U, {0x0370}}}, - {0x0373, {1|U, {0x0372}}}, - {0x0377, {1|U, {0x0376}}}, - {0x037b, {1|U, {0x03fd}}}, - {0x037c, {1|U, {0x03fe}}}, - {0x037d, {1|U, {0x03ff}}}, - {0x03ac, {1|U, {0x0386}}}, - {0x03ad, {1|U, {0x0388}}}, - {0x03ae, {1|U, {0x0389}}}, - {0x03af, {1|U, {0x038a}}}, - {0x03b1, {1|U, {0x0391}}}, - {0x03b2, {2|U, {0x0392, 0x03d0}}}, - {0x03b3, {1|U, {0x0393}}}, - {0x03b4, {1|U, {0x0394}}}, - {0x03b5, {2|U, {0x0395, 0x03f5}}}, - {0x03b6, {1|U, {0x0396}}}, - {0x03b7, {1|U, {0x0397}}}, - {0x03b8, {3|U, {0x0398, 0x03d1, 0x03f4}}}, - {0x03b9, {3|U, {0x0399, 0x0345, 0x1fbe}}}, - {0x03ba, {2|U, {0x039a, 0x03f0}}}, - {0x03bb, {1|U, {0x039b}}}, - {0x03bc, {2|U, {0x039c, 0x00b5}}}, - {0x03bd, {1|U, {0x039d}}}, - {0x03be, {1|U, {0x039e}}}, - {0x03bf, {1|U, {0x039f}}}, - {0x03c0, {2|U, {0x03a0, 0x03d6}}}, - {0x03c1, {2|U, {0x03a1, 0x03f1}}}, - {0x03c3, {2|U, {0x03a3, 0x03c2}}}, - {0x03c4, {1|U, {0x03a4}}}, - {0x03c5, {1|U, {0x03a5}}}, - {0x03c6, {2|U, {0x03a6, 0x03d5}}}, - {0x03c7, {1|U, {0x03a7}}}, - {0x03c8, {1|U, {0x03a8}}}, - {0x03c9, {2|U, {0x03a9, 0x2126}}}, - {0x03ca, {1|U, {0x03aa}}}, - {0x03cb, {1|U, {0x03ab}}}, - {0x03cc, {1|U, {0x038c}}}, - {0x03cd, {1|U, {0x038e}}}, - {0x03ce, {1|U, {0x038f}}}, - {0x03d7, {1|U, {0x03cf}}}, - {0x03d9, {1|U, {0x03d8}}}, - {0x03db, {1|U, {0x03da}}}, - {0x03dd, {1|U, {0x03dc}}}, - {0x03df, {1|U, {0x03de}}}, - {0x03e1, {1|U, {0x03e0}}}, - {0x03e3, {1|U, {0x03e2}}}, - {0x03e5, {1|U, {0x03e4}}}, - {0x03e7, {1|U, {0x03e6}}}, - {0x03e9, {1|U, {0x03e8}}}, - {0x03eb, {1|U, {0x03ea}}}, - {0x03ed, {1|U, {0x03ec}}}, - {0x03ef, {1|U, {0x03ee}}}, - {0x03f2, {1|U, {0x03f9}}}, - {0x03f3, {1|U, {0x037f}}}, - {0x03f8, {1|U, {0x03f7}}}, - {0x03fb, {1|U, {0x03fa}}}, - {0x0430, {1|U, {0x0410}}}, - {0x0431, {1|U, {0x0411}}}, - {0x0432, {2|U, {0x0412, 0x1c80}}}, - {0x0433, {1|U, {0x0413}}}, - {0x0434, {2|U, {0x0414, 0x1c81}}}, - {0x0435, {1|U, {0x0415}}}, - {0x0436, {1|U, {0x0416}}}, - {0x0437, {1|U, {0x0417}}}, - {0x0438, {1|U, {0x0418}}}, - {0x0439, {1|U, {0x0419}}}, - {0x043a, {1|U, {0x041a}}}, - {0x043b, {1|U, {0x041b}}}, - {0x043c, {1|U, {0x041c}}}, - {0x043d, {1|U, {0x041d}}}, - {0x043e, {2|U, {0x041e, 0x1c82}}}, - {0x043f, {1|U, {0x041f}}}, - {0x0440, {1|U, {0x0420}}}, - {0x0441, {2|U, {0x0421, 0x1c83}}}, - {0x0442, {3|U, {0x0422, 0x1c84, 0x1c85}}}, - {0x0443, {1|U, {0x0423}}}, - {0x0444, {1|U, {0x0424}}}, - {0x0445, {1|U, {0x0425}}}, - {0x0446, {1|U, {0x0426}}}, - {0x0447, {1|U, {0x0427}}}, - {0x0448, {1|U, {0x0428}}}, - {0x0449, {1|U, {0x0429}}}, - {0x044a, {2|U, {0x042a, 0x1c86}}}, - {0x044b, {1|U, {0x042b}}}, - {0x044c, {1|U, {0x042c}}}, - {0x044d, {1|U, {0x042d}}}, - {0x044e, {1|U, {0x042e}}}, - {0x044f, {1|U, {0x042f}}}, - {0x0450, {1|U, {0x0400}}}, - {0x0451, {1|U, {0x0401}}}, - {0x0452, {1|U, {0x0402}}}, - {0x0453, {1|U, {0x0403}}}, - {0x0454, {1|U, {0x0404}}}, - {0x0455, {1|U, {0x0405}}}, - {0x0456, {1|U, {0x0406}}}, - {0x0457, {1|U, {0x0407}}}, - {0x0458, {1|U, {0x0408}}}, - {0x0459, {1|U, {0x0409}}}, - {0x045a, {1|U, {0x040a}}}, - {0x045b, {1|U, {0x040b}}}, - {0x045c, {1|U, {0x040c}}}, - {0x045d, {1|U, {0x040d}}}, - {0x045e, {1|U, {0x040e}}}, - {0x045f, {1|U, {0x040f}}}, - {0x0461, {1|U, {0x0460}}}, - {0x0463, {2|U, {0x0462, 0x1c87}}}, - {0x0465, {1|U, {0x0464}}}, - {0x0467, {1|U, {0x0466}}}, - {0x0469, {1|U, {0x0468}}}, - {0x046b, {1|U, {0x046a}}}, - {0x046d, {1|U, {0x046c}}}, - {0x046f, {1|U, {0x046e}}}, - {0x0471, {1|U, {0x0470}}}, - {0x0473, {1|U, {0x0472}}}, - {0x0475, {1|U, {0x0474}}}, - {0x0477, {1|U, {0x0476}}}, - {0x0479, {1|U, {0x0478}}}, - {0x047b, {1|U, {0x047a}}}, - {0x047d, {1|U, {0x047c}}}, - {0x047f, {1|U, {0x047e}}}, - {0x0481, {1|U, {0x0480}}}, - {0x048b, {1|U, {0x048a}}}, - {0x048d, {1|U, {0x048c}}}, - {0x048f, {1|U, {0x048e}}}, - {0x0491, {1|U, {0x0490}}}, - {0x0493, {1|U, {0x0492}}}, - {0x0495, {1|U, {0x0494}}}, - {0x0497, {1|U, {0x0496}}}, - {0x0499, {1|U, {0x0498}}}, - {0x049b, {1|U, {0x049a}}}, - {0x049d, {1|U, {0x049c}}}, - {0x049f, {1|U, {0x049e}}}, - {0x04a1, {1|U, {0x04a0}}}, - {0x04a3, {1|U, {0x04a2}}}, - {0x04a5, {1|U, {0x04a4}}}, - {0x04a7, {1|U, {0x04a6}}}, - {0x04a9, {1|U, {0x04a8}}}, - {0x04ab, {1|U, {0x04aa}}}, - {0x04ad, {1|U, {0x04ac}}}, - {0x04af, {1|U, {0x04ae}}}, - {0x04b1, {1|U, {0x04b0}}}, - {0x04b3, {1|U, {0x04b2}}}, - {0x04b5, {1|U, {0x04b4}}}, - {0x04b7, {1|U, {0x04b6}}}, - {0x04b9, {1|U, {0x04b8}}}, - {0x04bb, {1|U, {0x04ba}}}, - {0x04bd, {1|U, {0x04bc}}}, - {0x04bf, {1|U, {0x04be}}}, - {0x04c2, {1|U, {0x04c1}}}, - {0x04c4, {1|U, {0x04c3}}}, - {0x04c6, {1|U, {0x04c5}}}, - {0x04c8, {1|U, {0x04c7}}}, - {0x04ca, {1|U, {0x04c9}}}, - {0x04cc, {1|U, {0x04cb}}}, - {0x04ce, {1|U, {0x04cd}}}, - {0x04cf, {1|U, {0x04c0}}}, - {0x04d1, {1|U, {0x04d0}}}, - {0x04d3, {1|U, {0x04d2}}}, - {0x04d5, {1|U, {0x04d4}}}, - {0x04d7, {1|U, {0x04d6}}}, - {0x04d9, {1|U, {0x04d8}}}, - {0x04db, {1|U, {0x04da}}}, - {0x04dd, {1|U, {0x04dc}}}, - {0x04df, {1|U, {0x04de}}}, - {0x04e1, {1|U, {0x04e0}}}, - {0x04e3, {1|U, {0x04e2}}}, - {0x04e5, {1|U, {0x04e4}}}, - {0x04e7, {1|U, {0x04e6}}}, - {0x04e9, {1|U, {0x04e8}}}, - {0x04eb, {1|U, {0x04ea}}}, - {0x04ed, {1|U, {0x04ec}}}, - {0x04ef, {1|U, {0x04ee}}}, - {0x04f1, {1|U, {0x04f0}}}, - {0x04f3, {1|U, {0x04f2}}}, - {0x04f5, {1|U, {0x04f4}}}, - {0x04f7, {1|U, {0x04f6}}}, - {0x04f9, {1|U, {0x04f8}}}, - {0x04fb, {1|U, {0x04fa}}}, - {0x04fd, {1|U, {0x04fc}}}, - {0x04ff, {1|U, {0x04fe}}}, - {0x0501, {1|U, {0x0500}}}, - {0x0503, {1|U, {0x0502}}}, - {0x0505, {1|U, {0x0504}}}, - {0x0507, {1|U, {0x0506}}}, - {0x0509, {1|U, {0x0508}}}, - {0x050b, {1|U, {0x050a}}}, - {0x050d, {1|U, {0x050c}}}, - {0x050f, {1|U, {0x050e}}}, - {0x0511, {1|U, {0x0510}}}, - {0x0513, {1|U, {0x0512}}}, - {0x0515, {1|U, {0x0514}}}, - {0x0517, {1|U, {0x0516}}}, - {0x0519, {1|U, {0x0518}}}, - {0x051b, {1|U, {0x051a}}}, - {0x051d, {1|U, {0x051c}}}, - {0x051f, {1|U, {0x051e}}}, - {0x0521, {1|U, {0x0520}}}, - {0x0523, {1|U, {0x0522}}}, - {0x0525, {1|U, {0x0524}}}, - {0x0527, {1|U, {0x0526}}}, - {0x0529, {1|U, {0x0528}}}, - {0x052b, {1|U, {0x052a}}}, - {0x052d, {1|U, {0x052c}}}, - {0x052f, {1|U, {0x052e}}}, - {0x0561, {1|U, {0x0531}}}, - {0x0562, {1|U, {0x0532}}}, - {0x0563, {1|U, {0x0533}}}, - {0x0564, {1|U, {0x0534}}}, - {0x0565, {1|U, {0x0535}}}, - {0x0566, {1|U, {0x0536}}}, - {0x0567, {1|U, {0x0537}}}, - {0x0568, {1|U, {0x0538}}}, - {0x0569, {1|U, {0x0539}}}, - {0x056a, {1|U, {0x053a}}}, - {0x056b, {1|U, {0x053b}}}, - {0x056c, {1|U, {0x053c}}}, - {0x056d, {1|U, {0x053d}}}, - {0x056e, {1|U, {0x053e}}}, - {0x056f, {1|U, {0x053f}}}, - {0x0570, {1|U, {0x0540}}}, - {0x0571, {1|U, {0x0541}}}, - {0x0572, {1|U, {0x0542}}}, - {0x0573, {1|U, {0x0543}}}, - {0x0574, {1|U, {0x0544}}}, - {0x0575, {1|U, {0x0545}}}, - {0x0576, {1|U, {0x0546}}}, - {0x0577, {1|U, {0x0547}}}, - {0x0578, {1|U, {0x0548}}}, - {0x0579, {1|U, {0x0549}}}, - {0x057a, {1|U, {0x054a}}}, - {0x057b, {1|U, {0x054b}}}, - {0x057c, {1|U, {0x054c}}}, - {0x057d, {1|U, {0x054d}}}, - {0x057e, {1|U, {0x054e}}}, - {0x057f, {1|U, {0x054f}}}, - {0x0580, {1|U, {0x0550}}}, - {0x0581, {1|U, {0x0551}}}, - {0x0582, {1|U, {0x0552}}}, - {0x0583, {1|U, {0x0553}}}, - {0x0584, {1|U, {0x0554}}}, - {0x0585, {1|U, {0x0555}}}, - {0x0586, {1|U, {0x0556}}}, - {0x10d0, {1|U|IT, {0x1c90}}}, - {0x10d1, {1|U|IT, {0x1c91}}}, - {0x10d2, {1|U|IT, {0x1c92}}}, - {0x10d3, {1|U|IT, {0x1c93}}}, - {0x10d4, {1|U|IT, {0x1c94}}}, - {0x10d5, {1|U|IT, {0x1c95}}}, - {0x10d6, {1|U|IT, {0x1c96}}}, - {0x10d7, {1|U|IT, {0x1c97}}}, - {0x10d8, {1|U|IT, {0x1c98}}}, - {0x10d9, {1|U|IT, {0x1c99}}}, - {0x10da, {1|U|IT, {0x1c9a}}}, - {0x10db, {1|U|IT, {0x1c9b}}}, - {0x10dc, {1|U|IT, {0x1c9c}}}, - {0x10dd, {1|U|IT, {0x1c9d}}}, - {0x10de, {1|U|IT, {0x1c9e}}}, - {0x10df, {1|U|IT, {0x1c9f}}}, - {0x10e0, {1|U|IT, {0x1ca0}}}, - {0x10e1, {1|U|IT, {0x1ca1}}}, - {0x10e2, {1|U|IT, {0x1ca2}}}, - {0x10e3, {1|U|IT, {0x1ca3}}}, - {0x10e4, {1|U|IT, {0x1ca4}}}, - {0x10e5, {1|U|IT, {0x1ca5}}}, - {0x10e6, {1|U|IT, {0x1ca6}}}, - {0x10e7, {1|U|IT, {0x1ca7}}}, - {0x10e8, {1|U|IT, {0x1ca8}}}, - {0x10e9, {1|U|IT, {0x1ca9}}}, - {0x10ea, {1|U|IT, {0x1caa}}}, - {0x10eb, {1|U|IT, {0x1cab}}}, - {0x10ec, {1|U|IT, {0x1cac}}}, - {0x10ed, {1|U|IT, {0x1cad}}}, - {0x10ee, {1|U|IT, {0x1cae}}}, - {0x10ef, {1|U|IT, {0x1caf}}}, - {0x10f0, {1|U|IT, {0x1cb0}}}, - {0x10f1, {1|U|IT, {0x1cb1}}}, - {0x10f2, {1|U|IT, {0x1cb2}}}, - {0x10f3, {1|U|IT, {0x1cb3}}}, - {0x10f4, {1|U|IT, {0x1cb4}}}, - {0x10f5, {1|U|IT, {0x1cb5}}}, - {0x10f6, {1|U|IT, {0x1cb6}}}, - {0x10f7, {1|U|IT, {0x1cb7}}}, - {0x10f8, {1|U|IT, {0x1cb8}}}, - {0x10f9, {1|U|IT, {0x1cb9}}}, - {0x10fa, {1|U|IT, {0x1cba}}}, - {0x10fd, {1|U|IT, {0x1cbd}}}, - {0x10fe, {1|U|IT, {0x1cbe}}}, - {0x10ff, {1|U|IT, {0x1cbf}}}, - {0x13a0, {1|D, {0xab70}}}, - {0x13a1, {1|D, {0xab71}}}, - {0x13a2, {1|D, {0xab72}}}, - {0x13a3, {1|D, {0xab73}}}, - {0x13a4, {1|D, {0xab74}}}, - {0x13a5, {1|D, {0xab75}}}, - {0x13a6, {1|D, {0xab76}}}, - {0x13a7, {1|D, {0xab77}}}, - {0x13a8, {1|D, {0xab78}}}, - {0x13a9, {1|D, {0xab79}}}, - {0x13aa, {1|D, {0xab7a}}}, - {0x13ab, {1|D, {0xab7b}}}, - {0x13ac, {1|D, {0xab7c}}}, - {0x13ad, {1|D, {0xab7d}}}, - {0x13ae, {1|D, {0xab7e}}}, - {0x13af, {1|D, {0xab7f}}}, - {0x13b0, {1|D, {0xab80}}}, - {0x13b1, {1|D, {0xab81}}}, - {0x13b2, {1|D, {0xab82}}}, - {0x13b3, {1|D, {0xab83}}}, - {0x13b4, {1|D, {0xab84}}}, - {0x13b5, {1|D, {0xab85}}}, - {0x13b6, {1|D, {0xab86}}}, - {0x13b7, {1|D, {0xab87}}}, - {0x13b8, {1|D, {0xab88}}}, - {0x13b9, {1|D, {0xab89}}}, - {0x13ba, {1|D, {0xab8a}}}, - {0x13bb, {1|D, {0xab8b}}}, - {0x13bc, {1|D, {0xab8c}}}, - {0x13bd, {1|D, {0xab8d}}}, - {0x13be, {1|D, {0xab8e}}}, - {0x13bf, {1|D, {0xab8f}}}, - {0x13c0, {1|D, {0xab90}}}, - {0x13c1, {1|D, {0xab91}}}, - {0x13c2, {1|D, {0xab92}}}, - {0x13c3, {1|D, {0xab93}}}, - {0x13c4, {1|D, {0xab94}}}, - {0x13c5, {1|D, {0xab95}}}, - {0x13c6, {1|D, {0xab96}}}, - {0x13c7, {1|D, {0xab97}}}, - {0x13c8, {1|D, {0xab98}}}, - {0x13c9, {1|D, {0xab99}}}, - {0x13ca, {1|D, {0xab9a}}}, - {0x13cb, {1|D, {0xab9b}}}, - {0x13cc, {1|D, {0xab9c}}}, - {0x13cd, {1|D, {0xab9d}}}, - {0x13ce, {1|D, {0xab9e}}}, - {0x13cf, {1|D, {0xab9f}}}, - {0x13d0, {1|D, {0xaba0}}}, - {0x13d1, {1|D, {0xaba1}}}, - {0x13d2, {1|D, {0xaba2}}}, - {0x13d3, {1|D, {0xaba3}}}, - {0x13d4, {1|D, {0xaba4}}}, - {0x13d5, {1|D, {0xaba5}}}, - {0x13d6, {1|D, {0xaba6}}}, - {0x13d7, {1|D, {0xaba7}}}, - {0x13d8, {1|D, {0xaba8}}}, - {0x13d9, {1|D, {0xaba9}}}, - {0x13da, {1|D, {0xabaa}}}, - {0x13db, {1|D, {0xabab}}}, - {0x13dc, {1|D, {0xabac}}}, - {0x13dd, {1|D, {0xabad}}}, - {0x13de, {1|D, {0xabae}}}, - {0x13df, {1|D, {0xabaf}}}, - {0x13e0, {1|D, {0xabb0}}}, - {0x13e1, {1|D, {0xabb1}}}, - {0x13e2, {1|D, {0xabb2}}}, - {0x13e3, {1|D, {0xabb3}}}, - {0x13e4, {1|D, {0xabb4}}}, - {0x13e5, {1|D, {0xabb5}}}, - {0x13e6, {1|D, {0xabb6}}}, - {0x13e7, {1|D, {0xabb7}}}, - {0x13e8, {1|D, {0xabb8}}}, - {0x13e9, {1|D, {0xabb9}}}, - {0x13ea, {1|D, {0xabba}}}, - {0x13eb, {1|D, {0xabbb}}}, - {0x13ec, {1|D, {0xabbc}}}, - {0x13ed, {1|D, {0xabbd}}}, - {0x13ee, {1|D, {0xabbe}}}, - {0x13ef, {1|D, {0xabbf}}}, - {0x13f0, {1|D, {0x13f8}}}, - {0x13f1, {1|D, {0x13f9}}}, - {0x13f2, {1|D, {0x13fa}}}, - {0x13f3, {1|D, {0x13fb}}}, - {0x13f4, {1|D, {0x13fc}}}, - {0x13f5, {1|D, {0x13fd}}}, - {0x1d79, {1|U, {0xa77d}}}, - {0x1d7d, {1|U, {0x2c63}}}, - {0x1d8e, {1|U, {0xa7c6}}}, - {0x1e01, {1|U, {0x1e00}}}, - {0x1e03, {1|U, {0x1e02}}}, - {0x1e05, {1|U, {0x1e04}}}, - {0x1e07, {1|U, {0x1e06}}}, - {0x1e09, {1|U, {0x1e08}}}, - {0x1e0b, {1|U, {0x1e0a}}}, - {0x1e0d, {1|U, {0x1e0c}}}, - {0x1e0f, {1|U, {0x1e0e}}}, - {0x1e11, {1|U, {0x1e10}}}, - {0x1e13, {1|U, {0x1e12}}}, - {0x1e15, {1|U, {0x1e14}}}, - {0x1e17, {1|U, {0x1e16}}}, - {0x1e19, {1|U, {0x1e18}}}, - {0x1e1b, {1|U, {0x1e1a}}}, - {0x1e1d, {1|U, {0x1e1c}}}, - {0x1e1f, {1|U, {0x1e1e}}}, - {0x1e21, {1|U, {0x1e20}}}, - {0x1e23, {1|U, {0x1e22}}}, - {0x1e25, {1|U, {0x1e24}}}, - {0x1e27, {1|U, {0x1e26}}}, - {0x1e29, {1|U, {0x1e28}}}, - {0x1e2b, {1|U, {0x1e2a}}}, - {0x1e2d, {1|U, {0x1e2c}}}, - {0x1e2f, {1|U, {0x1e2e}}}, - {0x1e31, {1|U, {0x1e30}}}, - {0x1e33, {1|U, {0x1e32}}}, - {0x1e35, {1|U, {0x1e34}}}, - {0x1e37, {1|U, {0x1e36}}}, - {0x1e39, {1|U, {0x1e38}}}, - {0x1e3b, {1|U, {0x1e3a}}}, - {0x1e3d, {1|U, {0x1e3c}}}, - {0x1e3f, {1|U, {0x1e3e}}}, - {0x1e41, {1|U, {0x1e40}}}, - {0x1e43, {1|U, {0x1e42}}}, - {0x1e45, {1|U, {0x1e44}}}, - {0x1e47, {1|U, {0x1e46}}}, - {0x1e49, {1|U, {0x1e48}}}, - {0x1e4b, {1|U, {0x1e4a}}}, - {0x1e4d, {1|U, {0x1e4c}}}, - {0x1e4f, {1|U, {0x1e4e}}}, - {0x1e51, {1|U, {0x1e50}}}, - {0x1e53, {1|U, {0x1e52}}}, - {0x1e55, {1|U, {0x1e54}}}, - {0x1e57, {1|U, {0x1e56}}}, - {0x1e59, {1|U, {0x1e58}}}, - {0x1e5b, {1|U, {0x1e5a}}}, - {0x1e5d, {1|U, {0x1e5c}}}, - {0x1e5f, {1|U, {0x1e5e}}}, - {0x1e61, {2|U, {0x1e60, 0x1e9b}}}, - {0x1e63, {1|U, {0x1e62}}}, - {0x1e65, {1|U, {0x1e64}}}, - {0x1e67, {1|U, {0x1e66}}}, - {0x1e69, {1|U, {0x1e68}}}, - {0x1e6b, {1|U, {0x1e6a}}}, - {0x1e6d, {1|U, {0x1e6c}}}, - {0x1e6f, {1|U, {0x1e6e}}}, - {0x1e71, {1|U, {0x1e70}}}, - {0x1e73, {1|U, {0x1e72}}}, - {0x1e75, {1|U, {0x1e74}}}, - {0x1e77, {1|U, {0x1e76}}}, - {0x1e79, {1|U, {0x1e78}}}, - {0x1e7b, {1|U, {0x1e7a}}}, - {0x1e7d, {1|U, {0x1e7c}}}, - {0x1e7f, {1|U, {0x1e7e}}}, - {0x1e81, {1|U, {0x1e80}}}, - {0x1e83, {1|U, {0x1e82}}}, - {0x1e85, {1|U, {0x1e84}}}, - {0x1e87, {1|U, {0x1e86}}}, - {0x1e89, {1|U, {0x1e88}}}, - {0x1e8b, {1|U, {0x1e8a}}}, - {0x1e8d, {1|U, {0x1e8c}}}, - {0x1e8f, {1|U, {0x1e8e}}}, - {0x1e91, {1|U, {0x1e90}}}, - {0x1e93, {1|U, {0x1e92}}}, - {0x1e95, {1|U, {0x1e94}}}, - {0x1ea1, {1|U, {0x1ea0}}}, - {0x1ea3, {1|U, {0x1ea2}}}, - {0x1ea5, {1|U, {0x1ea4}}}, - {0x1ea7, {1|U, {0x1ea6}}}, - {0x1ea9, {1|U, {0x1ea8}}}, - {0x1eab, {1|U, {0x1eaa}}}, - {0x1ead, {1|U, {0x1eac}}}, - {0x1eaf, {1|U, {0x1eae}}}, - {0x1eb1, {1|U, {0x1eb0}}}, - {0x1eb3, {1|U, {0x1eb2}}}, - {0x1eb5, {1|U, {0x1eb4}}}, - {0x1eb7, {1|U, {0x1eb6}}}, - {0x1eb9, {1|U, {0x1eb8}}}, - {0x1ebb, {1|U, {0x1eba}}}, - {0x1ebd, {1|U, {0x1ebc}}}, - {0x1ebf, {1|U, {0x1ebe}}}, - {0x1ec1, {1|U, {0x1ec0}}}, - {0x1ec3, {1|U, {0x1ec2}}}, - {0x1ec5, {1|U, {0x1ec4}}}, - {0x1ec7, {1|U, {0x1ec6}}}, - {0x1ec9, {1|U, {0x1ec8}}}, - {0x1ecb, {1|U, {0x1eca}}}, - {0x1ecd, {1|U, {0x1ecc}}}, - {0x1ecf, {1|U, {0x1ece}}}, - {0x1ed1, {1|U, {0x1ed0}}}, - {0x1ed3, {1|U, {0x1ed2}}}, - {0x1ed5, {1|U, {0x1ed4}}}, - {0x1ed7, {1|U, {0x1ed6}}}, - {0x1ed9, {1|U, {0x1ed8}}}, - {0x1edb, {1|U, {0x1eda}}}, - {0x1edd, {1|U, {0x1edc}}}, - {0x1edf, {1|U, {0x1ede}}}, - {0x1ee1, {1|U, {0x1ee0}}}, - {0x1ee3, {1|U, {0x1ee2}}}, - {0x1ee5, {1|U, {0x1ee4}}}, - {0x1ee7, {1|U, {0x1ee6}}}, - {0x1ee9, {1|U, {0x1ee8}}}, - {0x1eeb, {1|U, {0x1eea}}}, - {0x1eed, {1|U, {0x1eec}}}, - {0x1eef, {1|U, {0x1eee}}}, - {0x1ef1, {1|U, {0x1ef0}}}, - {0x1ef3, {1|U, {0x1ef2}}}, - {0x1ef5, {1|U, {0x1ef4}}}, - {0x1ef7, {1|U, {0x1ef6}}}, - {0x1ef9, {1|U, {0x1ef8}}}, - {0x1efb, {1|U, {0x1efa}}}, - {0x1efd, {1|U, {0x1efc}}}, - {0x1eff, {1|U, {0x1efe}}}, - {0x1f00, {1|U, {0x1f08}}}, - {0x1f01, {1|U, {0x1f09}}}, - {0x1f02, {1|U, {0x1f0a}}}, - {0x1f03, {1|U, {0x1f0b}}}, - {0x1f04, {1|U, {0x1f0c}}}, - {0x1f05, {1|U, {0x1f0d}}}, - {0x1f06, {1|U, {0x1f0e}}}, - {0x1f07, {1|U, {0x1f0f}}}, - {0x1f10, {1|U, {0x1f18}}}, - {0x1f11, {1|U, {0x1f19}}}, - {0x1f12, {1|U, {0x1f1a}}}, - {0x1f13, {1|U, {0x1f1b}}}, - {0x1f14, {1|U, {0x1f1c}}}, - {0x1f15, {1|U, {0x1f1d}}}, - {0x1f20, {1|U, {0x1f28}}}, - {0x1f21, {1|U, {0x1f29}}}, - {0x1f22, {1|U, {0x1f2a}}}, - {0x1f23, {1|U, {0x1f2b}}}, - {0x1f24, {1|U, {0x1f2c}}}, - {0x1f25, {1|U, {0x1f2d}}}, - {0x1f26, {1|U, {0x1f2e}}}, - {0x1f27, {1|U, {0x1f2f}}}, - {0x1f30, {1|U, {0x1f38}}}, - {0x1f31, {1|U, {0x1f39}}}, - {0x1f32, {1|U, {0x1f3a}}}, - {0x1f33, {1|U, {0x1f3b}}}, - {0x1f34, {1|U, {0x1f3c}}}, - {0x1f35, {1|U, {0x1f3d}}}, - {0x1f36, {1|U, {0x1f3e}}}, - {0x1f37, {1|U, {0x1f3f}}}, - {0x1f40, {1|U, {0x1f48}}}, - {0x1f41, {1|U, {0x1f49}}}, - {0x1f42, {1|U, {0x1f4a}}}, - {0x1f43, {1|U, {0x1f4b}}}, - {0x1f44, {1|U, {0x1f4c}}}, - {0x1f45, {1|U, {0x1f4d}}}, - {0x1f51, {1|U, {0x1f59}}}, - {0x1f53, {1|U, {0x1f5b}}}, - {0x1f55, {1|U, {0x1f5d}}}, - {0x1f57, {1|U, {0x1f5f}}}, - {0x1f60, {1|U, {0x1f68}}}, - {0x1f61, {1|U, {0x1f69}}}, - {0x1f62, {1|U, {0x1f6a}}}, - {0x1f63, {1|U, {0x1f6b}}}, - {0x1f64, {1|U, {0x1f6c}}}, - {0x1f65, {1|U, {0x1f6d}}}, - {0x1f66, {1|U, {0x1f6e}}}, - {0x1f67, {1|U, {0x1f6f}}}, - {0x1f70, {1|U, {0x1fba}}}, - {0x1f71, {1|U, {0x1fbb}}}, - {0x1f72, {1|U, {0x1fc8}}}, - {0x1f73, {1|U, {0x1fc9}}}, - {0x1f74, {1|U, {0x1fca}}}, - {0x1f75, {1|U, {0x1fcb}}}, - {0x1f76, {1|U, {0x1fda}}}, - {0x1f77, {1|U, {0x1fdb}}}, - {0x1f78, {1|U, {0x1ff8}}}, - {0x1f79, {1|U, {0x1ff9}}}, - {0x1f7a, {1|U, {0x1fea}}}, - {0x1f7b, {1|U, {0x1feb}}}, - {0x1f7c, {1|U, {0x1ffa}}}, - {0x1f7d, {1|U, {0x1ffb}}}, - {0x1fb0, {1|U, {0x1fb8}}}, - {0x1fb1, {1|U, {0x1fb9}}}, - {0x1fd0, {1|U, {0x1fd8}}}, - {0x1fd1, {1|U, {0x1fd9}}}, - {0x1fe0, {1|U, {0x1fe8}}}, - {0x1fe1, {1|U, {0x1fe9}}}, - {0x1fe5, {1|U, {0x1fec}}}, - {0x214e, {1|U, {0x2132}}}, - {0x2170, {1|U, {0x2160}}}, - {0x2171, {1|U, {0x2161}}}, - {0x2172, {1|U, {0x2162}}}, - {0x2173, {1|U, {0x2163}}}, - {0x2174, {1|U, {0x2164}}}, - {0x2175, {1|U, {0x2165}}}, - {0x2176, {1|U, {0x2166}}}, - {0x2177, {1|U, {0x2167}}}, - {0x2178, {1|U, {0x2168}}}, - {0x2179, {1|U, {0x2169}}}, - {0x217a, {1|U, {0x216a}}}, - {0x217b, {1|U, {0x216b}}}, - {0x217c, {1|U, {0x216c}}}, - {0x217d, {1|U, {0x216d}}}, - {0x217e, {1|U, {0x216e}}}, - {0x217f, {1|U, {0x216f}}}, - {0x2184, {1|U, {0x2183}}}, - {0x24d0, {1|U, {0x24b6}}}, - {0x24d1, {1|U, {0x24b7}}}, - {0x24d2, {1|U, {0x24b8}}}, - {0x24d3, {1|U, {0x24b9}}}, - {0x24d4, {1|U, {0x24ba}}}, - {0x24d5, {1|U, {0x24bb}}}, - {0x24d6, {1|U, {0x24bc}}}, - {0x24d7, {1|U, {0x24bd}}}, - {0x24d8, {1|U, {0x24be}}}, - {0x24d9, {1|U, {0x24bf}}}, - {0x24da, {1|U, {0x24c0}}}, - {0x24db, {1|U, {0x24c1}}}, - {0x24dc, {1|U, {0x24c2}}}, - {0x24dd, {1|U, {0x24c3}}}, - {0x24de, {1|U, {0x24c4}}}, - {0x24df, {1|U, {0x24c5}}}, - {0x24e0, {1|U, {0x24c6}}}, - {0x24e1, {1|U, {0x24c7}}}, - {0x24e2, {1|U, {0x24c8}}}, - {0x24e3, {1|U, {0x24c9}}}, - {0x24e4, {1|U, {0x24ca}}}, - {0x24e5, {1|U, {0x24cb}}}, - {0x24e6, {1|U, {0x24cc}}}, - {0x24e7, {1|U, {0x24cd}}}, - {0x24e8, {1|U, {0x24ce}}}, - {0x24e9, {1|U, {0x24cf}}}, - {0x2c30, {1|U, {0x2c00}}}, - {0x2c31, {1|U, {0x2c01}}}, - {0x2c32, {1|U, {0x2c02}}}, - {0x2c33, {1|U, {0x2c03}}}, - {0x2c34, {1|U, {0x2c04}}}, - {0x2c35, {1|U, {0x2c05}}}, - {0x2c36, {1|U, {0x2c06}}}, - {0x2c37, {1|U, {0x2c07}}}, - {0x2c38, {1|U, {0x2c08}}}, - {0x2c39, {1|U, {0x2c09}}}, - {0x2c3a, {1|U, {0x2c0a}}}, - {0x2c3b, {1|U, {0x2c0b}}}, - {0x2c3c, {1|U, {0x2c0c}}}, - {0x2c3d, {1|U, {0x2c0d}}}, - {0x2c3e, {1|U, {0x2c0e}}}, - {0x2c3f, {1|U, {0x2c0f}}}, - {0x2c40, {1|U, {0x2c10}}}, - {0x2c41, {1|U, {0x2c11}}}, - {0x2c42, {1|U, {0x2c12}}}, - {0x2c43, {1|U, {0x2c13}}}, - {0x2c44, {1|U, {0x2c14}}}, - {0x2c45, {1|U, {0x2c15}}}, - {0x2c46, {1|U, {0x2c16}}}, - {0x2c47, {1|U, {0x2c17}}}, - {0x2c48, {1|U, {0x2c18}}}, - {0x2c49, {1|U, {0x2c19}}}, - {0x2c4a, {1|U, {0x2c1a}}}, - {0x2c4b, {1|U, {0x2c1b}}}, - {0x2c4c, {1|U, {0x2c1c}}}, - {0x2c4d, {1|U, {0x2c1d}}}, - {0x2c4e, {1|U, {0x2c1e}}}, - {0x2c4f, {1|U, {0x2c1f}}}, - {0x2c50, {1|U, {0x2c20}}}, - {0x2c51, {1|U, {0x2c21}}}, - {0x2c52, {1|U, {0x2c22}}}, - {0x2c53, {1|U, {0x2c23}}}, - {0x2c54, {1|U, {0x2c24}}}, - {0x2c55, {1|U, {0x2c25}}}, - {0x2c56, {1|U, {0x2c26}}}, - {0x2c57, {1|U, {0x2c27}}}, - {0x2c58, {1|U, {0x2c28}}}, - {0x2c59, {1|U, {0x2c29}}}, - {0x2c5a, {1|U, {0x2c2a}}}, - {0x2c5b, {1|U, {0x2c2b}}}, - {0x2c5c, {1|U, {0x2c2c}}}, - {0x2c5d, {1|U, {0x2c2d}}}, - {0x2c5e, {1|U, {0x2c2e}}}, - {0x2c5f, {1|U, {0x2c2f}}}, - {0x2c61, {1|U, {0x2c60}}}, - {0x2c65, {1|U, {0x023a}}}, - {0x2c66, {1|U, {0x023e}}}, - {0x2c68, {1|U, {0x2c67}}}, - {0x2c6a, {1|U, {0x2c69}}}, - {0x2c6c, {1|U, {0x2c6b}}}, - {0x2c73, {1|U, {0x2c72}}}, - {0x2c76, {1|U, {0x2c75}}}, - {0x2c81, {1|U, {0x2c80}}}, - {0x2c83, {1|U, {0x2c82}}}, - {0x2c85, {1|U, {0x2c84}}}, - {0x2c87, {1|U, {0x2c86}}}, - {0x2c89, {1|U, {0x2c88}}}, - {0x2c8b, {1|U, {0x2c8a}}}, - {0x2c8d, {1|U, {0x2c8c}}}, - {0x2c8f, {1|U, {0x2c8e}}}, - {0x2c91, {1|U, {0x2c90}}}, - {0x2c93, {1|U, {0x2c92}}}, - {0x2c95, {1|U, {0x2c94}}}, - {0x2c97, {1|U, {0x2c96}}}, - {0x2c99, {1|U, {0x2c98}}}, - {0x2c9b, {1|U, {0x2c9a}}}, - {0x2c9d, {1|U, {0x2c9c}}}, - {0x2c9f, {1|U, {0x2c9e}}}, - {0x2ca1, {1|U, {0x2ca0}}}, - {0x2ca3, {1|U, {0x2ca2}}}, - {0x2ca5, {1|U, {0x2ca4}}}, - {0x2ca7, {1|U, {0x2ca6}}}, - {0x2ca9, {1|U, {0x2ca8}}}, - {0x2cab, {1|U, {0x2caa}}}, - {0x2cad, {1|U, {0x2cac}}}, - {0x2caf, {1|U, {0x2cae}}}, - {0x2cb1, {1|U, {0x2cb0}}}, - {0x2cb3, {1|U, {0x2cb2}}}, - {0x2cb5, {1|U, {0x2cb4}}}, - {0x2cb7, {1|U, {0x2cb6}}}, - {0x2cb9, {1|U, {0x2cb8}}}, - {0x2cbb, {1|U, {0x2cba}}}, - {0x2cbd, {1|U, {0x2cbc}}}, - {0x2cbf, {1|U, {0x2cbe}}}, - {0x2cc1, {1|U, {0x2cc0}}}, - {0x2cc3, {1|U, {0x2cc2}}}, - {0x2cc5, {1|U, {0x2cc4}}}, - {0x2cc7, {1|U, {0x2cc6}}}, - {0x2cc9, {1|U, {0x2cc8}}}, - {0x2ccb, {1|U, {0x2cca}}}, - {0x2ccd, {1|U, {0x2ccc}}}, - {0x2ccf, {1|U, {0x2cce}}}, - {0x2cd1, {1|U, {0x2cd0}}}, - {0x2cd3, {1|U, {0x2cd2}}}, - {0x2cd5, {1|U, {0x2cd4}}}, - {0x2cd7, {1|U, {0x2cd6}}}, - {0x2cd9, {1|U, {0x2cd8}}}, - {0x2cdb, {1|U, {0x2cda}}}, - {0x2cdd, {1|U, {0x2cdc}}}, - {0x2cdf, {1|U, {0x2cde}}}, - {0x2ce1, {1|U, {0x2ce0}}}, - {0x2ce3, {1|U, {0x2ce2}}}, - {0x2cec, {1|U, {0x2ceb}}}, - {0x2cee, {1|U, {0x2ced}}}, - {0x2cf3, {1|U, {0x2cf2}}}, - {0x2d00, {1|U, {0x10a0}}}, - {0x2d01, {1|U, {0x10a1}}}, - {0x2d02, {1|U, {0x10a2}}}, - {0x2d03, {1|U, {0x10a3}}}, - {0x2d04, {1|U, {0x10a4}}}, - {0x2d05, {1|U, {0x10a5}}}, - {0x2d06, {1|U, {0x10a6}}}, - {0x2d07, {1|U, {0x10a7}}}, - {0x2d08, {1|U, {0x10a8}}}, - {0x2d09, {1|U, {0x10a9}}}, - {0x2d0a, {1|U, {0x10aa}}}, - {0x2d0b, {1|U, {0x10ab}}}, - {0x2d0c, {1|U, {0x10ac}}}, - {0x2d0d, {1|U, {0x10ad}}}, - {0x2d0e, {1|U, {0x10ae}}}, - {0x2d0f, {1|U, {0x10af}}}, - {0x2d10, {1|U, {0x10b0}}}, - {0x2d11, {1|U, {0x10b1}}}, - {0x2d12, {1|U, {0x10b2}}}, - {0x2d13, {1|U, {0x10b3}}}, - {0x2d14, {1|U, {0x10b4}}}, - {0x2d15, {1|U, {0x10b5}}}, - {0x2d16, {1|U, {0x10b6}}}, - {0x2d17, {1|U, {0x10b7}}}, - {0x2d18, {1|U, {0x10b8}}}, - {0x2d19, {1|U, {0x10b9}}}, - {0x2d1a, {1|U, {0x10ba}}}, - {0x2d1b, {1|U, {0x10bb}}}, - {0x2d1c, {1|U, {0x10bc}}}, - {0x2d1d, {1|U, {0x10bd}}}, - {0x2d1e, {1|U, {0x10be}}}, - {0x2d1f, {1|U, {0x10bf}}}, - {0x2d20, {1|U, {0x10c0}}}, - {0x2d21, {1|U, {0x10c1}}}, - {0x2d22, {1|U, {0x10c2}}}, - {0x2d23, {1|U, {0x10c3}}}, - {0x2d24, {1|U, {0x10c4}}}, - {0x2d25, {1|U, {0x10c5}}}, - {0x2d27, {1|U, {0x10c7}}}, - {0x2d2d, {1|U, {0x10cd}}}, - {0xa641, {1|U, {0xa640}}}, - {0xa643, {1|U, {0xa642}}}, - {0xa645, {1|U, {0xa644}}}, - {0xa647, {1|U, {0xa646}}}, - {0xa649, {1|U, {0xa648}}}, - {0xa64b, {2|U, {0xa64a, 0x1c88}}}, - {0xa64d, {1|U, {0xa64c}}}, - {0xa64f, {1|U, {0xa64e}}}, - {0xa651, {1|U, {0xa650}}}, - {0xa653, {1|U, {0xa652}}}, - {0xa655, {1|U, {0xa654}}}, - {0xa657, {1|U, {0xa656}}}, - {0xa659, {1|U, {0xa658}}}, - {0xa65b, {1|U, {0xa65a}}}, - {0xa65d, {1|U, {0xa65c}}}, - {0xa65f, {1|U, {0xa65e}}}, - {0xa661, {1|U, {0xa660}}}, - {0xa663, {1|U, {0xa662}}}, - {0xa665, {1|U, {0xa664}}}, - {0xa667, {1|U, {0xa666}}}, - {0xa669, {1|U, {0xa668}}}, - {0xa66b, {1|U, {0xa66a}}}, - {0xa66d, {1|U, {0xa66c}}}, - {0xa681, {1|U, {0xa680}}}, - {0xa683, {1|U, {0xa682}}}, - {0xa685, {1|U, {0xa684}}}, - {0xa687, {1|U, {0xa686}}}, - {0xa689, {1|U, {0xa688}}}, - {0xa68b, {1|U, {0xa68a}}}, - {0xa68d, {1|U, {0xa68c}}}, - {0xa68f, {1|U, {0xa68e}}}, - {0xa691, {1|U, {0xa690}}}, - {0xa693, {1|U, {0xa692}}}, - {0xa695, {1|U, {0xa694}}}, - {0xa697, {1|U, {0xa696}}}, - {0xa699, {1|U, {0xa698}}}, - {0xa69b, {1|U, {0xa69a}}}, - {0xa723, {1|U, {0xa722}}}, - {0xa725, {1|U, {0xa724}}}, - {0xa727, {1|U, {0xa726}}}, - {0xa729, {1|U, {0xa728}}}, - {0xa72b, {1|U, {0xa72a}}}, - {0xa72d, {1|U, {0xa72c}}}, - {0xa72f, {1|U, {0xa72e}}}, - {0xa733, {1|U, {0xa732}}}, - {0xa735, {1|U, {0xa734}}}, - {0xa737, {1|U, {0xa736}}}, - {0xa739, {1|U, {0xa738}}}, - {0xa73b, {1|U, {0xa73a}}}, - {0xa73d, {1|U, {0xa73c}}}, - {0xa73f, {1|U, {0xa73e}}}, - {0xa741, {1|U, {0xa740}}}, - {0xa743, {1|U, {0xa742}}}, - {0xa745, {1|U, {0xa744}}}, - {0xa747, {1|U, {0xa746}}}, - {0xa749, {1|U, {0xa748}}}, - {0xa74b, {1|U, {0xa74a}}}, - {0xa74d, {1|U, {0xa74c}}}, - {0xa74f, {1|U, {0xa74e}}}, - {0xa751, {1|U, {0xa750}}}, - {0xa753, {1|U, {0xa752}}}, - {0xa755, {1|U, {0xa754}}}, - {0xa757, {1|U, {0xa756}}}, - {0xa759, {1|U, {0xa758}}}, - {0xa75b, {1|U, {0xa75a}}}, - {0xa75d, {1|U, {0xa75c}}}, - {0xa75f, {1|U, {0xa75e}}}, - {0xa761, {1|U, {0xa760}}}, - {0xa763, {1|U, {0xa762}}}, - {0xa765, {1|U, {0xa764}}}, - {0xa767, {1|U, {0xa766}}}, - {0xa769, {1|U, {0xa768}}}, - {0xa76b, {1|U, {0xa76a}}}, - {0xa76d, {1|U, {0xa76c}}}, - {0xa76f, {1|U, {0xa76e}}}, - {0xa77a, {1|U, {0xa779}}}, - {0xa77c, {1|U, {0xa77b}}}, - {0xa77f, {1|U, {0xa77e}}}, - {0xa781, {1|U, {0xa780}}}, - {0xa783, {1|U, {0xa782}}}, - {0xa785, {1|U, {0xa784}}}, - {0xa787, {1|U, {0xa786}}}, - {0xa78c, {1|U, {0xa78b}}}, - {0xa791, {1|U, {0xa790}}}, - {0xa793, {1|U, {0xa792}}}, - {0xa794, {1|U, {0xa7c4}}}, - {0xa797, {1|U, {0xa796}}}, - {0xa799, {1|U, {0xa798}}}, - {0xa79b, {1|U, {0xa79a}}}, - {0xa79d, {1|U, {0xa79c}}}, - {0xa79f, {1|U, {0xa79e}}}, - {0xa7a1, {1|U, {0xa7a0}}}, - {0xa7a3, {1|U, {0xa7a2}}}, - {0xa7a5, {1|U, {0xa7a4}}}, - {0xa7a7, {1|U, {0xa7a6}}}, - {0xa7a9, {1|U, {0xa7a8}}}, - {0xa7b5, {1|U, {0xa7b4}}}, - {0xa7b7, {1|U, {0xa7b6}}}, - {0xa7b9, {1|U, {0xa7b8}}}, - {0xa7bb, {1|U, {0xa7ba}}}, - {0xa7bd, {1|U, {0xa7bc}}}, - {0xa7bf, {1|U, {0xa7be}}}, - {0xa7c1, {1|U, {0xa7c0}}}, - {0xa7c3, {1|U, {0xa7c2}}}, - {0xa7c8, {1|U, {0xa7c7}}}, - {0xa7ca, {1|U, {0xa7c9}}}, - {0xa7d1, {1|U, {0xa7d0}}}, - {0xa7d7, {1|U, {0xa7d6}}}, - {0xa7d9, {1|U, {0xa7d8}}}, - {0xa7f6, {1|U, {0xa7f5}}}, - {0xab53, {1|U, {0xa7b3}}}, - {0xff41, {1|U, {0xff21}}}, - {0xff42, {1|U, {0xff22}}}, - {0xff43, {1|U, {0xff23}}}, - {0xff44, {1|U, {0xff24}}}, - {0xff45, {1|U, {0xff25}}}, - {0xff46, {1|U, {0xff26}}}, - {0xff47, {1|U, {0xff27}}}, - {0xff48, {1|U, {0xff28}}}, - {0xff49, {1|U, {0xff29}}}, - {0xff4a, {1|U, {0xff2a}}}, - {0xff4b, {1|U, {0xff2b}}}, - {0xff4c, {1|U, {0xff2c}}}, - {0xff4d, {1|U, {0xff2d}}}, - {0xff4e, {1|U, {0xff2e}}}, - {0xff4f, {1|U, {0xff2f}}}, - {0xff50, {1|U, {0xff30}}}, - {0xff51, {1|U, {0xff31}}}, - {0xff52, {1|U, {0xff32}}}, - {0xff53, {1|U, {0xff33}}}, - {0xff54, {1|U, {0xff34}}}, - {0xff55, {1|U, {0xff35}}}, - {0xff56, {1|U, {0xff36}}}, - {0xff57, {1|U, {0xff37}}}, - {0xff58, {1|U, {0xff38}}}, - {0xff59, {1|U, {0xff39}}}, - {0xff5a, {1|U, {0xff3a}}}, - {0x10428, {1|U, {0x10400}}}, - {0x10429, {1|U, {0x10401}}}, - {0x1042a, {1|U, {0x10402}}}, - {0x1042b, {1|U, {0x10403}}}, - {0x1042c, {1|U, {0x10404}}}, - {0x1042d, {1|U, {0x10405}}}, - {0x1042e, {1|U, {0x10406}}}, - {0x1042f, {1|U, {0x10407}}}, - {0x10430, {1|U, {0x10408}}}, - {0x10431, {1|U, {0x10409}}}, - {0x10432, {1|U, {0x1040a}}}, - {0x10433, {1|U, {0x1040b}}}, - {0x10434, {1|U, {0x1040c}}}, - {0x10435, {1|U, {0x1040d}}}, - {0x10436, {1|U, {0x1040e}}}, - {0x10437, {1|U, {0x1040f}}}, - {0x10438, {1|U, {0x10410}}}, - {0x10439, {1|U, {0x10411}}}, - {0x1043a, {1|U, {0x10412}}}, - {0x1043b, {1|U, {0x10413}}}, - {0x1043c, {1|U, {0x10414}}}, - {0x1043d, {1|U, {0x10415}}}, - {0x1043e, {1|U, {0x10416}}}, - {0x1043f, {1|U, {0x10417}}}, - {0x10440, {1|U, {0x10418}}}, - {0x10441, {1|U, {0x10419}}}, - {0x10442, {1|U, {0x1041a}}}, - {0x10443, {1|U, {0x1041b}}}, - {0x10444, {1|U, {0x1041c}}}, - {0x10445, {1|U, {0x1041d}}}, - {0x10446, {1|U, {0x1041e}}}, - {0x10447, {1|U, {0x1041f}}}, - {0x10448, {1|U, {0x10420}}}, - {0x10449, {1|U, {0x10421}}}, - {0x1044a, {1|U, {0x10422}}}, - {0x1044b, {1|U, {0x10423}}}, - {0x1044c, {1|U, {0x10424}}}, - {0x1044d, {1|U, {0x10425}}}, - {0x1044e, {1|U, {0x10426}}}, - {0x1044f, {1|U, {0x10427}}}, - {0x104d8, {1|U, {0x104b0}}}, - {0x104d9, {1|U, {0x104b1}}}, - {0x104da, {1|U, {0x104b2}}}, - {0x104db, {1|U, {0x104b3}}}, - {0x104dc, {1|U, {0x104b4}}}, - {0x104dd, {1|U, {0x104b5}}}, - {0x104de, {1|U, {0x104b6}}}, - {0x104df, {1|U, {0x104b7}}}, - {0x104e0, {1|U, {0x104b8}}}, - {0x104e1, {1|U, {0x104b9}}}, - {0x104e2, {1|U, {0x104ba}}}, - {0x104e3, {1|U, {0x104bb}}}, - {0x104e4, {1|U, {0x104bc}}}, - {0x104e5, {1|U, {0x104bd}}}, - {0x104e6, {1|U, {0x104be}}}, - {0x104e7, {1|U, {0x104bf}}}, - {0x104e8, {1|U, {0x104c0}}}, - {0x104e9, {1|U, {0x104c1}}}, - {0x104ea, {1|U, {0x104c2}}}, - {0x104eb, {1|U, {0x104c3}}}, - {0x104ec, {1|U, {0x104c4}}}, - {0x104ed, {1|U, {0x104c5}}}, - {0x104ee, {1|U, {0x104c6}}}, - {0x104ef, {1|U, {0x104c7}}}, - {0x104f0, {1|U, {0x104c8}}}, - {0x104f1, {1|U, {0x104c9}}}, - {0x104f2, {1|U, {0x104ca}}}, - {0x104f3, {1|U, {0x104cb}}}, - {0x104f4, {1|U, {0x104cc}}}, - {0x104f5, {1|U, {0x104cd}}}, - {0x104f6, {1|U, {0x104ce}}}, - {0x104f7, {1|U, {0x104cf}}}, - {0x104f8, {1|U, {0x104d0}}}, - {0x104f9, {1|U, {0x104d1}}}, - {0x104fa, {1|U, {0x104d2}}}, - {0x104fb, {1|U, {0x104d3}}}, - {0x10597, {1|U, {0x10570}}}, - {0x10598, {1|U, {0x10571}}}, - {0x10599, {1|U, {0x10572}}}, - {0x1059a, {1|U, {0x10573}}}, - {0x1059b, {1|U, {0x10574}}}, - {0x1059c, {1|U, {0x10575}}}, - {0x1059d, {1|U, {0x10576}}}, - {0x1059e, {1|U, {0x10577}}}, - {0x1059f, {1|U, {0x10578}}}, - {0x105a0, {1|U, {0x10579}}}, - {0x105a1, {1|U, {0x1057a}}}, - {0x105a3, {1|U, {0x1057c}}}, - {0x105a4, {1|U, {0x1057d}}}, - {0x105a5, {1|U, {0x1057e}}}, - {0x105a6, {1|U, {0x1057f}}}, - {0x105a7, {1|U, {0x10580}}}, - {0x105a8, {1|U, {0x10581}}}, - {0x105a9, {1|U, {0x10582}}}, - {0x105aa, {1|U, {0x10583}}}, - {0x105ab, {1|U, {0x10584}}}, - {0x105ac, {1|U, {0x10585}}}, - {0x105ad, {1|U, {0x10586}}}, - {0x105ae, {1|U, {0x10587}}}, - {0x105af, {1|U, {0x10588}}}, - {0x105b0, {1|U, {0x10589}}}, - {0x105b1, {1|U, {0x1058a}}}, - {0x105b3, {1|U, {0x1058c}}}, - {0x105b4, {1|U, {0x1058d}}}, - {0x105b5, {1|U, {0x1058e}}}, - {0x105b6, {1|U, {0x1058f}}}, - {0x105b7, {1|U, {0x10590}}}, - {0x105b8, {1|U, {0x10591}}}, - {0x105b9, {1|U, {0x10592}}}, - {0x105bb, {1|U, {0x10594}}}, - {0x105bc, {1|U, {0x10595}}}, - {0x10cc0, {1|U, {0x10c80}}}, - {0x10cc1, {1|U, {0x10c81}}}, - {0x10cc2, {1|U, {0x10c82}}}, - {0x10cc3, {1|U, {0x10c83}}}, - {0x10cc4, {1|U, {0x10c84}}}, - {0x10cc5, {1|U, {0x10c85}}}, - {0x10cc6, {1|U, {0x10c86}}}, - {0x10cc7, {1|U, {0x10c87}}}, - {0x10cc8, {1|U, {0x10c88}}}, - {0x10cc9, {1|U, {0x10c89}}}, - {0x10cca, {1|U, {0x10c8a}}}, - {0x10ccb, {1|U, {0x10c8b}}}, - {0x10ccc, {1|U, {0x10c8c}}}, - {0x10ccd, {1|U, {0x10c8d}}}, - {0x10cce, {1|U, {0x10c8e}}}, - {0x10ccf, {1|U, {0x10c8f}}}, - {0x10cd0, {1|U, {0x10c90}}}, - {0x10cd1, {1|U, {0x10c91}}}, - {0x10cd2, {1|U, {0x10c92}}}, - {0x10cd3, {1|U, {0x10c93}}}, - {0x10cd4, {1|U, {0x10c94}}}, - {0x10cd5, {1|U, {0x10c95}}}, - {0x10cd6, {1|U, {0x10c96}}}, - {0x10cd7, {1|U, {0x10c97}}}, - {0x10cd8, {1|U, {0x10c98}}}, - {0x10cd9, {1|U, {0x10c99}}}, - {0x10cda, {1|U, {0x10c9a}}}, - {0x10cdb, {1|U, {0x10c9b}}}, - {0x10cdc, {1|U, {0x10c9c}}}, - {0x10cdd, {1|U, {0x10c9d}}}, - {0x10cde, {1|U, {0x10c9e}}}, - {0x10cdf, {1|U, {0x10c9f}}}, - {0x10ce0, {1|U, {0x10ca0}}}, - {0x10ce1, {1|U, {0x10ca1}}}, - {0x10ce2, {1|U, {0x10ca2}}}, - {0x10ce3, {1|U, {0x10ca3}}}, - {0x10ce4, {1|U, {0x10ca4}}}, - {0x10ce5, {1|U, {0x10ca5}}}, - {0x10ce6, {1|U, {0x10ca6}}}, - {0x10ce7, {1|U, {0x10ca7}}}, - {0x10ce8, {1|U, {0x10ca8}}}, - {0x10ce9, {1|U, {0x10ca9}}}, - {0x10cea, {1|U, {0x10caa}}}, - {0x10ceb, {1|U, {0x10cab}}}, - {0x10cec, {1|U, {0x10cac}}}, - {0x10ced, {1|U, {0x10cad}}}, - {0x10cee, {1|U, {0x10cae}}}, - {0x10cef, {1|U, {0x10caf}}}, - {0x10cf0, {1|U, {0x10cb0}}}, - {0x10cf1, {1|U, {0x10cb1}}}, - {0x10cf2, {1|U, {0x10cb2}}}, - {0x118c0, {1|U, {0x118a0}}}, - {0x118c1, {1|U, {0x118a1}}}, - {0x118c2, {1|U, {0x118a2}}}, - {0x118c3, {1|U, {0x118a3}}}, - {0x118c4, {1|U, {0x118a4}}}, - {0x118c5, {1|U, {0x118a5}}}, - {0x118c6, {1|U, {0x118a6}}}, - {0x118c7, {1|U, {0x118a7}}}, - {0x118c8, {1|U, {0x118a8}}}, - {0x118c9, {1|U, {0x118a9}}}, - {0x118ca, {1|U, {0x118aa}}}, - {0x118cb, {1|U, {0x118ab}}}, - {0x118cc, {1|U, {0x118ac}}}, - {0x118cd, {1|U, {0x118ad}}}, - {0x118ce, {1|U, {0x118ae}}}, - {0x118cf, {1|U, {0x118af}}}, - {0x118d0, {1|U, {0x118b0}}}, - {0x118d1, {1|U, {0x118b1}}}, - {0x118d2, {1|U, {0x118b2}}}, - {0x118d3, {1|U, {0x118b3}}}, - {0x118d4, {1|U, {0x118b4}}}, - {0x118d5, {1|U, {0x118b5}}}, - {0x118d6, {1|U, {0x118b6}}}, - {0x118d7, {1|U, {0x118b7}}}, - {0x118d8, {1|U, {0x118b8}}}, - {0x118d9, {1|U, {0x118b9}}}, - {0x118da, {1|U, {0x118ba}}}, - {0x118db, {1|U, {0x118bb}}}, - {0x118dc, {1|U, {0x118bc}}}, - {0x118dd, {1|U, {0x118bd}}}, - {0x118de, {1|U, {0x118be}}}, - {0x118df, {1|U, {0x118bf}}}, - {0x16e60, {1|U, {0x16e40}}}, - {0x16e61, {1|U, {0x16e41}}}, - {0x16e62, {1|U, {0x16e42}}}, - {0x16e63, {1|U, {0x16e43}}}, - {0x16e64, {1|U, {0x16e44}}}, - {0x16e65, {1|U, {0x16e45}}}, - {0x16e66, {1|U, {0x16e46}}}, - {0x16e67, {1|U, {0x16e47}}}, - {0x16e68, {1|U, {0x16e48}}}, - {0x16e69, {1|U, {0x16e49}}}, - {0x16e6a, {1|U, {0x16e4a}}}, - {0x16e6b, {1|U, {0x16e4b}}}, - {0x16e6c, {1|U, {0x16e4c}}}, - {0x16e6d, {1|U, {0x16e4d}}}, - {0x16e6e, {1|U, {0x16e4e}}}, - {0x16e6f, {1|U, {0x16e4f}}}, - {0x16e70, {1|U, {0x16e50}}}, - {0x16e71, {1|U, {0x16e51}}}, - {0x16e72, {1|U, {0x16e52}}}, - {0x16e73, {1|U, {0x16e53}}}, - {0x16e74, {1|U, {0x16e54}}}, - {0x16e75, {1|U, {0x16e55}}}, - {0x16e76, {1|U, {0x16e56}}}, - {0x16e77, {1|U, {0x16e57}}}, - {0x16e78, {1|U, {0x16e58}}}, - {0x16e79, {1|U, {0x16e59}}}, - {0x16e7a, {1|U, {0x16e5a}}}, - {0x16e7b, {1|U, {0x16e5b}}}, - {0x16e7c, {1|U, {0x16e5c}}}, - {0x16e7d, {1|U, {0x16e5d}}}, - {0x16e7e, {1|U, {0x16e5e}}}, - {0x16e7f, {1|U, {0x16e5f}}}, - {0x1e922, {1|U, {0x1e900}}}, - {0x1e923, {1|U, {0x1e901}}}, - {0x1e924, {1|U, {0x1e902}}}, - {0x1e925, {1|U, {0x1e903}}}, - {0x1e926, {1|U, {0x1e904}}}, - {0x1e927, {1|U, {0x1e905}}}, - {0x1e928, {1|U, {0x1e906}}}, - {0x1e929, {1|U, {0x1e907}}}, - {0x1e92a, {1|U, {0x1e908}}}, - {0x1e92b, {1|U, {0x1e909}}}, - {0x1e92c, {1|U, {0x1e90a}}}, - {0x1e92d, {1|U, {0x1e90b}}}, - {0x1e92e, {1|U, {0x1e90c}}}, - {0x1e92f, {1|U, {0x1e90d}}}, - {0x1e930, {1|U, {0x1e90e}}}, - {0x1e931, {1|U, {0x1e90f}}}, - {0x1e932, {1|U, {0x1e910}}}, - {0x1e933, {1|U, {0x1e911}}}, - {0x1e934, {1|U, {0x1e912}}}, - {0x1e935, {1|U, {0x1e913}}}, - {0x1e936, {1|U, {0x1e914}}}, - {0x1e937, {1|U, {0x1e915}}}, - {0x1e938, {1|U, {0x1e916}}}, - {0x1e939, {1|U, {0x1e917}}}, - {0x1e93a, {1|U, {0x1e918}}}, - {0x1e93b, {1|U, {0x1e919}}}, - {0x1e93c, {1|U, {0x1e91a}}}, - {0x1e93d, {1|U, {0x1e91b}}}, - {0x1e93e, {1|U, {0x1e91c}}}, - {0x1e93f, {1|U, {0x1e91d}}}, - {0x1e940, {1|U, {0x1e91e}}}, - {0x1e941, {1|U, {0x1e91f}}}, - {0x1e942, {1|U, {0x1e920}}}, - {0x1e943, {1|U, {0x1e921}}}, -#define CaseUnfold_11_Locale (*(CaseUnfold_11_Type (*)[1])(CaseUnfold_11_Table+1395)) - {0x0069, {1|U, {0x0049}}}, -}; - -/* ANSI-C code produced by gperf version 3.1 */ -/* Command-line: gperf -7 -k1,2,3 -F,-1 -c -j1 -i1 -t -T -E -C -H onigenc_unicode_CaseUnfold_11_hash -N onigenc_unicode_CaseUnfold_11_lookup -n */ - -/* maximum key range = 2771, duplicates = 0 */ - -#ifdef __GNUC__ -__inline -#else -#ifdef __cplusplus -inline -#endif -#endif -/*ARGSUSED*/ -static unsigned int -onigenc_unicode_CaseUnfold_11_hash(const OnigCodePoint code) -{ - static const unsigned short asso_values[] = - { - 1, 2774, 2, 2, 4, 421, 9, 371, 231, 463, - 37, 20, 2, 3, 419, 408, 2774, 2774, 2774, 2774, - 2774, 2774, 2774, 2774, 2774, 2774, 2774, 2774, 2774, 112, - 2774, 2774, 2774, 2774, 2774, 2774, 2774, 120, 2774, 2774, - 2774, 2774, 2774, 1, 2774, 2774, 2774, 2774, 2774, 2774, - 2774, 2774, 2774, 355, 2774, 2774, 2774, 2774, 2774, 2774, - 2774, 2774, 10, 9, 7, 8, 244, 689, 226, 993, - 561, 710, 104, 1429, 36, 1190, 28, 15, 114, 1768, - 241, 1003, 87, 285, 26, 1399, 78, 1360, 7, 1455, - 90, 1076, 113, 10, 724, 1460, 167, 1727, 155, 1040, - 67, 754, 66, 705, 246, 886, 331, 1140, 430, 1251, - 864, 768, 643, 1064, 1591, 865, 834, 720, 1700, 671, - 1581, 657, 1794, 842, 1782, 1050, 1537, 1024, 1760, 814, - 975, 440, 1187, 407, 1440, 951, 1384, 909, 1320, 555, - 1567, 541, 1723, 525, 383, 501, 1179, 250, 1596, 342, - 1575, 352, 1501, 194, 1559, 70, 1512, 85, 1509, 129, - 467, 100, 1413, 1, 1485, 25, 1351, 35, 1088, 55, - 1262, 45, 1277, 160, 1245, 317, 118, 220, 1300, 596, - 1100, 373, 1632, 617, 1337, 1236, 1500, 1152, 148, 793, - 1538, 979, 385, 1228 - }; - return asso_values[bits_of(code, 2)+66] + asso_values[bits_of(code, 1)+4] + asso_values[bits_of(code, 0)]; -} - -static const CodePointList3 * -onigenc_unicode_CaseUnfold_11_lookup(const OnigCodePoint code) -{ - enum - { - MIN_CODE_VALUE = 0x61, - MAX_CODE_VALUE = 0x1e943, - TOTAL_KEYWORDS = 1396, - MIN_WORD_LENGTH = 3, - MAX_WORD_LENGTH = 3, - MIN_HASH_VALUE = 3, - MAX_HASH_VALUE = 2773 - }; - - static const short wordlist[] = - { - -1, -1, -1, - /*0x13e1*/ 589, - /*0x0461*/ 340, - /*0x04e1*/ 400, - /*0x0061*/ 0, - -1, - /*0x104e1*/ 1184, - /*0x1e61*/ 661, - /*0x1ee1*/ 720, - /*0x0161*/ 102, - /*0x2ce1*/ 953, - -1, - /*0x049b*/ 365, - -1, -1, - /*0x24e1*/ 840, - /*0x1e1b*/ 626, - /*0x048b*/ 357, - /*0x011b*/ 69, - /*0x2c9b*/ 918, - /*0x03e1*/ 280, - /*0x1e0b*/ 618, - /*0x1e8b*/ 682, - /*0x010b*/ 61, - /*0x2c8b*/ 910, - /*0x13e3*/ 591, - /*0x0463*/ 341, - /*0x04e3*/ 401, - /*0x0063*/ 2, - -1, - /*0x104e3*/ 1186, - /*0x1e63*/ 662, - /*0x1ee3*/ 721, - /*0x0163*/ 103, - /*0x2ce3*/ 954, - /*0x13e5*/ 593, - /*0x0465*/ 342, - /*0x04e5*/ 402, - /*0x0065*/ 4, - /*0x24e3*/ 842, - /*0x104e5*/ 1188, - /*0x1e65*/ 663, - /*0x1ee5*/ 722, - /*0x0165*/ 104, - /*0x03e3*/ 281, - /*0x13e9*/ 597, - /*0x0469*/ 344, - /*0x04e9*/ 404, - /*0x0069*/ 1395, - /*0x24e5*/ 844, - /*0x104e9*/ 1192, - /*0x1e69*/ 665, - /*0x1ee9*/ 724, - /*0x0169*/ 106, - /*0x03e5*/ 282, - /*0x13e7*/ 595, - /*0x0467*/ 343, - /*0x04e7*/ 403, - /*0x0067*/ 6, - /*0x24e9*/ 848, - /*0x104e7*/ 1190, - /*0x1e67*/ 664, - /*0x1ee7*/ 723, - /*0x0167*/ 105, - /*0x03e9*/ 284, - -1, - /*0x13a4*/ 528, - /*0x13a2*/ 526, - -1, - /*0x24e7*/ 846, - /*0x13d9*/ 581, - /*0x0459*/ 333, - /*0x04d9*/ 396, - -1, - /*0x03e7*/ 283, - /*0x104d9*/ 1176, - /*0x1e59*/ 657, - /*0x1ed9*/ 716, - /*0x0159*/ 98, - /*0x2cd9*/ 949, - -1, -1, -1, -1, - /*0x24d9*/ 832, - /*0x13db*/ 583, - /*0x045b*/ 335, - /*0x04db*/ 397, - /*0xa761*/ 1065, - /*0x03d9*/ 276, - /*0x104db*/ 1178, - /*0x1e5b*/ 658, - /*0x1edb*/ 717, - /*0x015b*/ 99, - /*0x2cdb*/ 950, - -1, -1, -1, -1, - /*0x24db*/ 834, - /*0x13df*/ 587, - /*0x045f*/ 339, - /*0x04df*/ 399, - -1, - /*0x03db*/ 277, - /*0x104df*/ 1182, - /*0x1e5f*/ 660, - /*0x1edf*/ 719, - /*0x015f*/ 101, - /*0x2cdf*/ 952, - -1, -1, - /*0xa763*/ 1066, - /*0x2c61*/ 897, - /*0x24df*/ 838, - /*0x10ce1*/ 1279, - -1, -1, - /*0x13ee*/ 602, - /*0x03df*/ 279, - /*0x10e1*/ 495, - /*0x006e*/ 12, - /*0xa765*/ 1067, - /*0x104ee*/ 1197, - -1, -1, -1, - /*0x2cee*/ 956, - -1, - /*0x13dd*/ 585, - /*0x045d*/ 337, - /*0x04dd*/ 398, - /*0xa769*/ 1069, - -1, - /*0x104dd*/ 1180, - /*0x1e5d*/ 659, - /*0x1edd*/ 718, - /*0x015d*/ 100, - /*0x2cdd*/ 951, - /*0x10ce3*/ 1281, - -1, -1, - /*0xa767*/ 1068, - /*0x24dd*/ 836, - /*0x10e3*/ 497, - -1, -1, - /*0x2c65*/ 898, - /*0x03dd*/ 278, - /*0x10ce5*/ 1283, - -1, - /*0x007a*/ 24, - -1, - /*0x104fa*/ 1209, - /*0x10e5*/ 499, - /*0x13a0*/ 524, - /*0x017a*/ 114, - /*0xa759*/ 1061, - -1, - /*0x10ce9*/ 1287, - /*0x13eb*/ 599, - /*0x046b*/ 345, - /*0x04eb*/ 405, - /*0x006b*/ 9, - /*0x10e9*/ 503, - /*0x104eb*/ 1194, - /*0x1e6b*/ 666, - /*0x1eeb*/ 725, - /*0x016b*/ 107, - /*0x10ce7*/ 1285, - -1, -1, - /*0xa75b*/ 1062, - -1, - /*0x10e7*/ 501, - -1, -1, -1, -1, - /*0x03eb*/ 285, - -1, -1, - /*0x2c59*/ 890, - -1, - /*0x10cd9*/ 1271, - -1, -1, - /*0xa75f*/ 1064, - -1, - /*0x10d9*/ 487, - -1, -1, -1, -1, - /*0x13d7*/ 579, - /*0x0457*/ 331, - /*0x04d7*/ 395, - /*0x2c5b*/ 892, - -1, - /*0x10cdb*/ 1273, - /*0x1e57*/ 656, - /*0x1ed7*/ 715, - /*0x0157*/ 97, - /*0x2cd7*/ 948, - /*0x10db*/ 489, - -1, -1, -1, - /*0x24d7*/ 830, - -1, -1, -1, - /*0x2c5f*/ 896, - /*0x03d7*/ 275, - /*0x10cdf*/ 1277, - -1, - /*0xa75d*/ 1063, - -1, -1, - /*0x10df*/ 493, - /*0x13ef*/ 603, - /*0x046f*/ 347, - /*0x04ef*/ 407, - /*0x006f*/ 13, - -1, - /*0x104ef*/ 1198, - /*0x1e6f*/ 668, - /*0x1eef*/ 727, - /*0x016f*/ 109, - -1, -1, - /*0x0261*/ 210, - /*0x10cee*/ 1292, - -1, -1, - /*0xa77a*/ 1073, - -1, - /*0x10ee*/ 508, - -1, - /*0x03ef*/ 287, - /*0x021b*/ 178, - /*0x2c5d*/ 894, - /*0xa661*/ 1014, - /*0x10cdd*/ 1275, - /*0x1f61*/ 777, - /*0x020b*/ 170, - /*0x13a6*/ 530, - /*0xa76b*/ 1070, - /*0x10dd*/ 491, - /*0x1d8e*/ 612, - /*0x13d1*/ 573, - /*0x0451*/ 325, - /*0x04d1*/ 392, - -1, -1, - /*0x0263*/ 211, - /*0x1e51*/ 653, - /*0x1ed1*/ 712, - /*0x0151*/ 94, - /*0x2cd1*/ 945, - -1, -1, -1, -1, - /*0x24d1*/ 824, - /*0x0265*/ 212, - /*0xa663*/ 1015, - /*0x10fa*/ 520, - /*0x1f63*/ 779, - /*0x1f12*/ 746, - -1, -1, -1, -1, - /*0x10ceb*/ 1289, - /*0x0269*/ 215, - /*0xa665*/ 1016, - -1, - /*0x1f65*/ 781, - /*0x10eb*/ 505, - -1, - /*0xa757*/ 1060, - -1, -1, -1, -1, - /*0xa669*/ 1018, - /*0x0491*/ 360, - -1, -1, -1, - /*0x1e11*/ 621, - /*0x1e91*/ 685, - /*0x0111*/ 64, - /*0x2c91*/ 913, - /*0xa79b*/ 1086, - /*0xa667*/ 1017, - -1, - /*0x1f67*/ 783, - -1, - /*0x0259*/ 206, - -1, -1, -1, -1, -1, - /*0x2c57*/ 888, - /*0xa76f*/ 1072, - /*0x10cd7*/ 1269, - /*0x1f24*/ 754, - /*0x1f22*/ 752, - /*0xa659*/ 1010, - -1, - /*0x10d7*/ 485, - -1, - /*0x025b*/ 207, - -1, - /*0x13ed*/ 601, - /*0x046d*/ 346, - /*0x04ed*/ 406, - /*0x006d*/ 11, - /*0x1f14*/ 748, - /*0x104ed*/ 1196, - /*0x1e6d*/ 667, - /*0x1eed*/ 726, - /*0x016d*/ 108, - /*0xa65b*/ 1011, - -1, -1, -1, - /*0x1f10*/ 744, - /*0x13a8*/ 532, - -1, -1, - /*0x10cef*/ 1293, - /*0x10428*/ 1135, - /*0x03ed*/ 286, - /*0xa751*/ 1057, - -1, - /*0x10ef*/ 509, - -1, - /*0xa65f*/ 1013, - /*0x13d3*/ 575, - /*0x0453*/ 327, - /*0x04d3*/ 393, - -1, -1, - /*0x1f06*/ 742, - /*0x1e53*/ 654, - /*0x1ed3*/ 713, - /*0x0153*/ 95, - /*0x2cd3*/ 946, - /*0x13d5*/ 577, - /*0x0455*/ 329, - /*0x04d5*/ 394, - /*0xa7d9*/ 1106, - /*0x24d3*/ 826, - -1, - /*0x1e55*/ 655, - /*0x1ed5*/ 714, - /*0x0155*/ 96, - /*0x2cd5*/ 947, - /*0x2c51*/ 882, - /*0xa794*/ 1083, - /*0x10cd1*/ 1263, - -1, - /*0x24d5*/ 828, - -1, -1, - /*0x10d1*/ 479, - /*0xa65d*/ 1012, - /*0x01e1*/ 151, - -1, - /*0x13f3*/ 607, - /*0x0473*/ 349, - /*0x04f3*/ 409, - /*0x0073*/ 17, - -1, - /*0x104f3*/ 1202, - /*0x1e73*/ 670, - /*0x1ef3*/ 729, - /*0x0173*/ 111, - /*0x2cf3*/ 957, - /*0x13ce*/ 570, - /*0x044e*/ 322, - /*0x04ce*/ 390, - -1, - /*0x1044e*/ 1173, - -1, -1, - /*0x026b*/ 217, - /*0x1f7a*/ 794, - /*0x03f3*/ 289, - /*0x017e*/ 116, - -1, - /*0x01e3*/ 152, - /*0x0192*/ 122, - -1, - /*0x1f20*/ 750, - /*0xa78c*/ 1080, - -1, - /*0xa66b*/ 1019, - /*0x03ce*/ 274, - -1, - /*0xa76d*/ 1071, - /*0x01e5*/ 153, - /*0x0188*/ 120, - /*0x13c3*/ 559, - /*0x0443*/ 311, - /*0x0373*/ 237, - -1, - /*0x10443*/ 1162, - -1, - /*0x1e43*/ 646, - /*0x1ec3*/ 705, - /*0x01e9*/ 155, - /*0x2cc3*/ 938, - -1, -1, - /*0x0561*/ 440, - /*0x1059b*/ 1215, - /*0x00e1*/ 26, - -1, -1, - /*0x0257*/ 205, - /*0x01e7*/ 154, - /*0x03c3*/ 263, - /*0x118d9*/ 1322, - /*0x051b*/ 429, - /*0xa753*/ 1058, - /*0x13aa*/ 534, - /*0x10ced*/ 1291, - /*0xab53*/ 1108, - /*0x050b*/ 421, - /*0x1042a*/ 1137, - /*0xa657*/ 1009, - /*0x10ed*/ 507, - /*0x1f57*/ 775, - -1, - /*0xa755*/ 1059, - /*0x13c1*/ 557, - /*0x0441*/ 309, - /*0x118db*/ 1324, - /*0x0563*/ 442, - /*0x10441*/ 1160, - /*0x00e3*/ 28, - /*0x1e41*/ 645, - /*0x1ec1*/ 704, - -1, - /*0x2cc1*/ 937, - /*0x026f*/ 219, - -1, -1, - /*0x0565*/ 444, - /*0x2c53*/ 884, - /*0x00e5*/ 30, - /*0x10cd3*/ 1265, - /*0x118df*/ 1328, - -1, - /*0x03c1*/ 262, - -1, - /*0x10d3*/ 481, - -1, - /*0x0569*/ 448, - /*0x2c55*/ 886, - /*0x00e9*/ 34, - /*0x10cd5*/ 1267, - /*0x13de*/ 586, - /*0x045e*/ 338, - /*0x1f02*/ 738, - /*0x01df*/ 150, - /*0x10d5*/ 483, - /*0x104de*/ 1181, - /*0x0567*/ 446, - -1, - /*0x00e7*/ 32, - /*0x105a4*/ 1223, - /*0x028b*/ 231, - -1, - /*0xa7d7*/ 1105, - /*0x0251*/ 200, - /*0x24de*/ 837, - -1, - /*0x019a*/ 125, - /*0x018c*/ 121, - /*0x2c73*/ 903, - /*0x118dd*/ 1326, - /*0x1f00*/ 736, - /*0x0292*/ 233, - /*0x1f26*/ 756, - /*0x028a*/ 230, - /*0xa651*/ 1006, - /*0x10f3*/ 513, - /*0x1f51*/ 772, - /*0xa743*/ 1050, - /*0x2c4e*/ 879, - -1, - /*0x10cce*/ 1260, - /*0x0288*/ 228, - /*0x01dd*/ 149, - /*0x10598*/ 1212, - /*0x13cf*/ 571, - /*0x044f*/ 323, - /*0x04cf*/ 391, - /*0x10fe*/ 522, - /*0x1044f*/ 1174, - -1, - /*0x1e4f*/ 652, - /*0x1ecf*/ 711, - /*0x014f*/ 93, - /*0x2ccf*/ 944, - /*0x0586*/ 477, - -1, - /*0x1e924*/ 1363, - /*0x1e922*/ 1361, - /*0x0211*/ 173, - -1, -1, -1, - /*0x2c43*/ 868, - -1, - /*0x10cc3*/ 1249, - -1, - /*0x1059a*/ 1214, - -1, - /*0x13cd*/ 569, - /*0x044d*/ 321, - /*0xa741*/ 1049, - /*0x1f11*/ 745, - /*0x1044d*/ 1172, - /*0x01eb*/ 156, - /*0x1e4d*/ 651, - /*0x1ecd*/ 710, - /*0x014d*/ 92, - /*0x2ccd*/ 943, - /*0xa7d1*/ 1104, - /*0x056e*/ 453, - /*0x019e*/ 126, - /*0x00ee*/ 39, - -1, -1, - /*0x13cb*/ 567, - /*0x044b*/ 319, - -1, - /*0x03cd*/ 273, - /*0x1044b*/ 1170, - -1, - /*0x1e4b*/ 650, - /*0x1ecb*/ 709, - /*0x014b*/ 91, - /*0x2ccb*/ 942, - /*0x118d7*/ 1320, - /*0x2c41*/ 866, - -1, - /*0x10cc1*/ 1247, - /*0x13c9*/ 565, - /*0x0449*/ 317, - -1, - /*0xa66d*/ 1020, - /*0x10449*/ 1168, - /*0x03cb*/ 271, - /*0x1e49*/ 649, - /*0x1ec9*/ 708, - -1, - /*0x2cc9*/ 941, - /*0x105a0*/ 1220, - /*0x057a*/ 465, - -1, - /*0x00fa*/ 50, - -1, - /*0xa791*/ 1081, - -1, - /*0x0253*/ 202, - -1, - /*0x03c9*/ 269, - -1, - /*0x028c*/ 232, - /*0x1059e*/ 1218, - /*0x056b*/ 450, - /*0x2c5e*/ 895, - /*0x00eb*/ 36, - /*0x10cde*/ 1276, - -1, - /*0xa653*/ 1007, - -1, - /*0x1f53*/ 773, - /*0x10de*/ 492, - /*0x16e61*/ 1330, - /*0xa74f*/ 1056, - -1, - /*0x01ef*/ 158, - -1, -1, - /*0xa655*/ 1008, - -1, - /*0x1f55*/ 774, - /*0x13f1*/ 605, - /*0x0471*/ 348, - /*0x04f1*/ 408, - /*0x0071*/ 15, - -1, - /*0x104f1*/ 1200, - /*0x1e71*/ 669, - /*0x1ef1*/ 728, - /*0x0171*/ 110, - -1, -1, - /*0x118d1*/ 1314, - -1, -1, -1, - /*0x16e63*/ 1332, - /*0xa74d*/ 1055, - /*0x2c4f*/ 880, - /*0x0180*/ 117, - /*0x10ccf*/ 1261, - /*0x1f73*/ 787, - /*0x13f5*/ 609, - /*0x0475*/ 350, - /*0x04f5*/ 410, - /*0x0075*/ 19, - /*0x16e65*/ 1334, - /*0x104f5*/ 1204, - /*0x1e75*/ 671, - /*0x1ef5*/ 730, - /*0x0175*/ 112, - -1, -1, - /*0xa74b*/ 1054, - /*0x029e*/ 235, - -1, - /*0x16e69*/ 1338, - /*0x0371*/ 236, - /*0x0582*/ 473, - -1, -1, -1, - /*0x2c4d*/ 878, - /*0x056f*/ 454, - /*0x10ccd*/ 1259, - /*0x00ef*/ 40, - /*0x16e67*/ 1336, - /*0xa749*/ 1053, - /*0x13ae*/ 538, - -1, -1, -1, - /*0x1042e*/ 1141, - /*0xa643*/ 999, - -1, - /*0x1f43*/ 769, - /*0x0580*/ 471, - -1, - /*0x2c4b*/ 876, - -1, - /*0x10ccb*/ 1257, - /*0x105a6*/ 1225, - /*0x13b7*/ 547, - /*0x0437*/ 299, - /*0x04b7*/ 379, - -1, - /*0x10437*/ 1150, - /*0x03ae*/ 244, - /*0x1e37*/ 640, - /*0x1eb7*/ 699, - /*0x0137*/ 82, - /*0x2cb7*/ 932, - /*0x2c49*/ 874, - -1, - /*0x10cc9*/ 1255, - -1, - /*0x13b5*/ 545, - /*0x0435*/ 297, - /*0x04b5*/ 378, - -1, - /*0x10435*/ 1148, - /*0x03b7*/ 252, - /*0x1e35*/ 639, - /*0x1eb5*/ 698, - /*0x0135*/ 81, - /*0x2cb5*/ 931, - /*0xa641*/ 998, - -1, - /*0x1f41*/ 767, - -1, -1, -1, - /*0x01ed*/ 157, - /*0x0282*/ 225, - /*0x1fe1*/ 803, - /*0x03b5*/ 250, - /*0x0481*/ 356, - /*0xa7c3*/ 1101, - /*0x1e926*/ 1365, - -1, - /*0x1e01*/ 613, - /*0x1e81*/ 677, - /*0x0101*/ 56, - /*0x2c81*/ 905, - /*0x118d3*/ 1316, - -1, - /*0x01a8*/ 130, - -1, - /*0x0511*/ 424, - /*0x16e6e*/ 1343, - /*0x13a5*/ 529, - /*0x0280*/ 224, - /*0x04a5*/ 370, - /*0x217a*/ 816, - /*0x118d5*/ 1318, - /*0x10cf1*/ 1295, - /*0x1e25*/ 631, - /*0x1ea5*/ 690, - /*0x0125*/ 74, - /*0x2ca5*/ 923, - /*0x10f1*/ 511, - /*0x1e05*/ 615, - /*0x1e85*/ 679, - /*0x0105*/ 58, - /*0x2c85*/ 907, - /*0x13b3*/ 543, - /*0x0433*/ 295, - /*0x04b3*/ 377, - /*0x1fe5*/ 804, - /*0x10433*/ 1146, - /*0xa7c1*/ 1100, - /*0x1e33*/ 638, - /*0x1eb3*/ 697, - /*0x0133*/ 80, - /*0x2cb3*/ 930, - /*0x2d16*/ 980, - /*0x024f*/ 198, - -1, - /*0x2d1b*/ 985, - /*0x16e7a*/ 1355, - /*0x056d*/ 452, - /*0x10f5*/ 515, - /*0x00ed*/ 38, - /*0x2d0b*/ 969, - /*0x03b3*/ 248, - /*0x118ce*/ 1311, - /*0x105a8*/ 1227, - /*0xa64f*/ 1005, - /*0x01f3*/ 159, - /*0xa737*/ 1044, - -1, - /*0x16e6b*/ 1340, - -1, -1, - /*0x2d12*/ 976, - -1, - /*0x2d0a*/ 968, - -1, - /*0x01ce*/ 141, - /*0x13a3*/ 527, - /*0x024d*/ 197, - /*0x04a3*/ 369, - -1, - /*0xa735*/ 1043, - /*0x2d08*/ 966, - /*0x1e23*/ 630, - /*0x1ea3*/ 689, - /*0x0123*/ 73, - /*0x2ca3*/ 922, - /*0x118c3*/ 1300, - -1, - /*0xa64d*/ 1004, - -1, - /*0x13ad*/ 537, - /*0x2c37*/ 856, - /*0x04ad*/ 374, - /*0x024b*/ 196, - /*0x1042d*/ 1140, - -1, - /*0x1e2d*/ 635, - /*0x1ead*/ 694, - /*0x012d*/ 78, - /*0x2cad*/ 927, - /*0x1e928*/ 1367, - -1, -1, -1, - /*0xa64b*/ 1003, - /*0x2c35*/ 854, - -1, - /*0x0249*/ 195, - -1, - /*0x03ad*/ 243, - -1, - /*0x2d24*/ 994, - /*0x2d22*/ 992, - /*0x0573*/ 458, - /*0xa725*/ 1036, - /*0x00f3*/ 44, - /*0x047b*/ 353, - /*0x04fb*/ 413, - /*0xa649*/ 1002, - /*0x118c1*/ 1298, - /*0x104fb*/ 1210, - /*0x1e7b*/ 674, - /*0x1efb*/ 733, - /*0x2d14*/ 978, - -1, - /*0x057e*/ 469, - /*0x1f04*/ 740, - /*0x00fe*/ 54, - /*0x16e6f*/ 1344, - /*0xa733*/ 1042, - -1, -1, - /*0x2d10*/ 974, - -1, - /*0x03fb*/ 291, - /*0x2d18*/ 982, - /*0x13bf*/ 555, - /*0x043f*/ 307, - /*0x04bf*/ 383, - -1, - /*0x1043f*/ 1158, - -1, - /*0x1e3f*/ 644, - /*0x1ebf*/ 703, - -1, - /*0x2cbf*/ 936, - /*0x118de*/ 1327, - -1, - /*0x0271*/ 220, - /*0x2d06*/ 964, - -1, - /*0x037b*/ 239, - -1, -1, - /*0x2c33*/ 852, - /*0x03bf*/ 260, - /*0x13b2*/ 542, - /*0x0432*/ 294, - /*0x2d1a*/ 984, - /*0x2d0c*/ 970, - /*0x10432*/ 1145, - /*0x1f71*/ 785, - /*0x105aa*/ 1229, - /*0xa723*/ 1035, - /*0x13b9*/ 549, - /*0x0439*/ 301, - /*0x04b9*/ 380, - -1, - /*0x10439*/ 1152, - /*0x0275*/ 222, - /*0x1e39*/ 641, - /*0x1eb9*/ 700, - -1, - /*0x2cb9*/ 933, - -1, - /*0x03b2*/ 247, - /*0x1e943*/ 1394, - /*0xa72d*/ 1040, - -1, -1, - /*0x118cf*/ 1312, - -1, - /*0x1f75*/ 789, - /*0x03b9*/ 254, - -1, -1, - /*0x13ac*/ 536, - /*0x13b1*/ 541, - /*0x0431*/ 293, - /*0x04b1*/ 376, - /*0x1042c*/ 1139, - /*0x10431*/ 1144, - -1, - /*0x1e31*/ 637, - /*0x1eb1*/ 696, - -1, - /*0x2cb1*/ 929, - -1, -1, - /*0x1e92a*/ 1369, - /*0x2d20*/ 990, - -1, -1, -1, - /*0x118cd*/ 1310, - /*0x03ac*/ 242, - /*0x03b1*/ 246, - -1, - /*0x13a7*/ 531, - /*0x1e941*/ 1392, - /*0x04a7*/ 371, - -1, - /*0x2d1e*/ 988, - -1, - /*0x1e27*/ 632, - /*0x1ea7*/ 691, - /*0x0127*/ 75, - /*0x2ca7*/ 924, - -1, -1, - /*0x118cb*/ 1308, - -1, - /*0x1f37*/ 765, - /*0xa73f*/ 1048, - -1, - /*0x16e6d*/ 1342, - -1, -1, -1, -1, -1, - /*0x13c7*/ 563, - /*0x0447*/ 315, - -1, - /*0x118c9*/ 1306, - /*0x10447*/ 1166, - /*0x1f35*/ 763, - /*0x1e47*/ 648, - /*0x1ec7*/ 707, - -1, - /*0x2cc7*/ 940, - /*0x0201*/ 165, - -1, -1, -1, -1, -1, - /*0x01c9*/ 139, - /*0x2c3f*/ 864, - -1, - /*0x03c7*/ 267, - /*0xa739*/ 1045, - -1, -1, - /*0x1f01*/ 737, - /*0x2173*/ 809, - -1, - /*0x0225*/ 182, - -1, -1, - /*0x1fd1*/ 801, - -1, - /*0x0205*/ 167, - -1, - /*0xa7b7*/ 1095, - /*0x214e*/ 805, - -1, - /*0x217e*/ 820, - /*0x2c32*/ 851, - -1, - /*0x1f25*/ 755, - /*0x2d02*/ 960, - /*0x0233*/ 189, - /*0x13c5*/ 561, - /*0x0445*/ 313, - /*0x1f05*/ 741, - /*0x2c39*/ 858, - /*0x10445*/ 1164, - /*0xa7b5*/ 1094, - /*0x1e45*/ 647, - /*0x1ec5*/ 706, - /*0x16e73*/ 1348, - /*0x2cc5*/ 939, - -1, -1, - /*0x1f33*/ 761, - /*0x2d0e*/ 972, - -1, -1, - /*0x2d00*/ 958, - /*0x0584*/ 475, - -1, - /*0x03c5*/ 265, - /*0x16e7e*/ 1359, - -1, - /*0xa727*/ 1037, - /*0xa781*/ 1076, - /*0x13c0*/ 556, - /*0x0440*/ 308, - /*0x2c31*/ 850, - -1, - /*0x10440*/ 1159, - /*0x047d*/ 354, - /*0x04fd*/ 414, - -1, - /*0x0140*/ 86, - /*0x0223*/ 181, - /*0x1e7d*/ 675, - /*0x1efd*/ 734, - /*0x01f5*/ 160, - /*0x1d7d*/ 611, - -1, - /*0xa7a5*/ 1091, - -1, -1, -1, - /*0x03c0*/ 261, - /*0xa785*/ 1078, - /*0xa747*/ 1052, - /*0x1f23*/ 753, - /*0x022d*/ 186, - /*0x1e03*/ 614, - /*0x1e83*/ 678, - /*0x0103*/ 57, - /*0x2c83*/ 906, - -1, -1, - /*0x048f*/ 359, - -1, -1, - /*0x2d11*/ 975, - /*0x1e0f*/ 620, - /*0x1e8f*/ 684, - /*0x010f*/ 63, - /*0x2c8f*/ 912, - /*0xa69b*/ 1034, - /*0x0571*/ 456, - /*0x037d*/ 241, - /*0x00f1*/ 42, - -1, - /*0xa68b*/ 1026, - -1, -1, - /*0x2c47*/ 872, - -1, - /*0x10cc7*/ 1253, - /*0x13bd*/ 553, - /*0x043d*/ 305, - /*0x04bd*/ 382, - -1, - /*0x1043d*/ 1156, - -1, - /*0x1e3d*/ 643, - /*0x1ebd*/ 702, - -1, - /*0x2cbd*/ 935, - -1, - /*0x0575*/ 460, - /*0x1f7b*/ 795, - /*0x00f5*/ 46, - /*0xa745*/ 1051, - /*0xa7a3*/ 1090, - /*0x13a1*/ 525, - -1, - /*0x04a1*/ 368, - /*0x03bd*/ 258, - /*0x023f*/ 191, - /*0xff59*/ 1133, - /*0x1e21*/ 629, - /*0x1ea1*/ 688, - /*0x0121*/ 72, - /*0x2ca1*/ 921, - /*0x13bb*/ 551, - /*0x043b*/ 303, - /*0x04bb*/ 381, - /*0x105ae*/ 1233, - /*0x1043b*/ 1154, - -1, - /*0x1e3b*/ 642, - /*0x1ebb*/ 701, - -1, - /*0x2cbb*/ 934, - -1, -1, -1, - /*0x2c45*/ 870, - /*0x13af*/ 539, - /*0x10cc5*/ 1251, - /*0x04af*/ 375, - /*0x105b7*/ 1241, - /*0x1042f*/ 1142, - /*0x03bb*/ 256, - /*0x1e2f*/ 636, - /*0x1eaf*/ 695, - /*0x012f*/ 79, - /*0x2caf*/ 928, - -1, - /*0x01a5*/ 129, - -1, - /*0x1f32*/ 760, - /*0x0499*/ 364, - -1, - /*0x0185*/ 119, - /*0x105b5*/ 1239, - /*0x1e19*/ 625, - /*0x03af*/ 245, - /*0x0119*/ 68, - /*0x2c99*/ 917, - -1, - /*0x2c40*/ 865, - /*0x13e6*/ 594, - /*0x10cc0*/ 1246, - /*0x1e92e*/ 1373, - /*0x0066*/ 5, - -1, - /*0x104e6*/ 1189, - -1, - /*0x0231*/ 188, - /*0x0581*/ 472, - -1, - /*0x10fd*/ 521, - /*0xa7bf*/ 1099, - /*0x13f2*/ 606, - -1, - /*0x24e6*/ 845, - /*0x0072*/ 16, - /*0x1e937*/ 1382, - /*0x104f2*/ 1201, - -1, - /*0x0501*/ 416, - /*0x1f31*/ 759, - -1, -1, - /*0xa73d*/ 1047, - -1, -1, -1, - /*0x105a5*/ 1224, - /*0x0227*/ 183, - /*0x0585*/ 476, - /*0x1e935*/ 1380, - /*0x03f2*/ 288, - -1, -1, -1, - /*0x0525*/ 434, - /*0x01a3*/ 128, - -1, -1, - /*0xa7b9*/ 1096, - /*0x0505*/ 418, - /*0x1f27*/ 757, - /*0x105b3*/ 1237, - -1, -1, -1, - /*0x1059c*/ 1216, - -1, - /*0x2c3d*/ 862, - /*0xa73b*/ 1046, - /*0x01ad*/ 131, - /*0x0247*/ 194, - /*0x13a9*/ 533, - -1, - /*0x04a9*/ 372, - -1, - /*0x10429*/ 1136, - -1, - /*0x1e29*/ 633, - /*0x1ea9*/ 692, - /*0x0129*/ 76, - /*0x2ca9*/ 925, - /*0xa647*/ 1001, - /*0xa72f*/ 1041, - /*0x1e925*/ 1364, - /*0x0479*/ 352, - /*0x04f9*/ 412, - /*0x0079*/ 23, - /*0x2171*/ 807, - /*0x104f9*/ 1208, - /*0x1e79*/ 673, - /*0x1ef9*/ 732, - -1, - /*0x1d79*/ 610, - /*0x2c3b*/ 860, - /*0x01fb*/ 162, - /*0x105a3*/ 1222, - -1, -1, - /*0x1e933*/ 1378, - -1, - /*0xff57*/ 1131, - -1, - /*0xa7a7*/ 1092, - /*0x0523*/ 433, - -1, -1, -1, -1, - /*0x2175*/ 811, - /*0x105ad*/ 1232, - /*0x13d0*/ 572, - /*0x0450*/ 324, - -1, - /*0x16e71*/ 1346, - -1, - /*0x01bf*/ 137, - -1, - /*0x052d*/ 438, - /*0x13c2*/ 558, - /*0x0442*/ 310, - /*0x04c2*/ 384, - -1, - /*0x10442*/ 1161, - /*0xa645*/ 1000, - /*0x24d0*/ 823, - /*0x1f45*/ 771, - /*0x0142*/ 87, - /*0x1e09*/ 617, - /*0x1e89*/ 681, - /*0x0109*/ 60, - /*0x2c89*/ 909, - /*0x2c66*/ 899, - /*0x1e923*/ 1362, - /*0x10ce6*/ 1284, - /*0x16e75*/ 1350, - -1, - /*0x0240*/ 192, - -1, - /*0x10e6*/ 500, - -1, - /*0x027d*/ 223, - -1, - /*0x057b*/ 466, - /*0x01b9*/ 135, - /*0x00fb*/ 51, - /*0x10cf2*/ 1296, - /*0x1e92d*/ 1372, - -1, -1, - /*0x1f40*/ 766, - /*0x10f2*/ 512, - -1, -1, - /*0x1f7d*/ 797, - /*0x0203*/ 166, - -1, - /*0xff51*/ 1125, - -1, - /*0xa729*/ 1038, - -1, - /*0x047f*/ 355, - /*0x04ff*/ 415, - -1, -1, - /*0x020f*/ 172, - /*0x1e7f*/ 676, - /*0x1eff*/ 735, - /*0x1f03*/ 739, - /*0x0477*/ 351, - /*0x04f7*/ 411, - /*0x0077*/ 21, - -1, - /*0x104f7*/ 1206, - /*0x1e77*/ 672, - /*0x1ef7*/ 731, - /*0x0177*/ 113, - /*0x13ec*/ 600, - -1, -1, - /*0x006c*/ 10, - -1, - /*0x104ec*/ 1195, - /*0x13ab*/ 535, - /*0x105b9*/ 1243, - /*0x04ab*/ 373, - /*0x2cec*/ 955, - /*0x1042b*/ 1138, - -1, - /*0x1e2b*/ 634, - /*0x1eab*/ 693, - /*0x012b*/ 77, - /*0x2cab*/ 926, - /*0x1e93f*/ 1390, - /*0x13e8*/ 596, - -1, -1, - /*0x0068*/ 7, - /*0x118c7*/ 1304, - /*0x104e8*/ 1191, - -1, -1, - /*0x2184*/ 822, - /*0x10f9*/ 519, - /*0x0377*/ 238, - -1, - /*0x105ac*/ 1231, - /*0x105b1*/ 1236, - /*0x24e8*/ 847, - /*0x13ea*/ 598, - /*0xa783*/ 1077, - -1, - /*0x006a*/ 8, - /*0x1e932*/ 1377, - /*0x104ea*/ 1193, - /*0x1f21*/ 751, - /*0x2d04*/ 962, - -1, -1, -1, - /*0xa691*/ 1029, - /*0x1e939*/ 1384, - -1, - /*0x2c50*/ 881, - -1, - /*0x10cd0*/ 1262, - /*0x022f*/ 187, - -1, - /*0x105a7*/ 1226, - -1, - /*0x10d0*/ 478, - /*0x2c42*/ 867, - /*0x13f0*/ 604, - /*0x10cc2*/ 1248, - -1, - /*0x0070*/ 14, - /*0x0527*/ 435, - /*0x104f0*/ 1199, - /*0x0219*/ 177, - -1, - /*0x118c5*/ 1302, - /*0xa7bd*/ 1098, - -1, - /*0x1e92c*/ 1371, - /*0x1e931*/ 1376, - -1, -1, - /*0xa77f*/ 1075, - -1, - /*0xff53*/ 1127, - /*0x0266*/ 213, - -1, - /*0x13c8*/ 564, - /*0x0448*/ 316, - /*0x04c8*/ 387, - -1, - /*0x10448*/ 1167, - /*0xa7a1*/ 1089, - -1, - /*0xff55*/ 1129, - /*0x0148*/ 90, - -1, - /*0x0272*/ 221, - /*0x1f66*/ 782, - /*0x118c0*/ 1297, - /*0x1e927*/ 1366, - -1, - /*0xa7bb*/ 1097, - -1, -1, - /*0xa72b*/ 1039, - /*0x03c8*/ 268, - /*0x0076*/ 20, - -1, - /*0x104f6*/ 1205, - /*0x1f72*/ 786, - -1, -1, -1, - /*0x10ff*/ 523, - -1, - /*0x01fd*/ 163, - -1, - /*0x13e4*/ 592, - -1, - /*0x217b*/ 817, - /*0x0064*/ 3, - /*0x10f7*/ 517, - /*0x104e4*/ 1187, - /*0x2c6c*/ 902, - /*0xff4e*/ 1122, - /*0x10cec*/ 1290, - -1, - /*0xa799*/ 1085, - /*0x0495*/ 362, - /*0x0183*/ 118, - /*0x10ec*/ 506, - /*0x24e4*/ 843, - /*0x1e15*/ 623, - /*0x1e95*/ 687, - /*0x0115*/ 66, - /*0x2c95*/ 915, - /*0x0229*/ 184, - -1, -1, -1, - /*0x2c68*/ 900, - -1, - /*0x10ce8*/ 1286, - -1, -1, - /*0x16e7b*/ 1356, - -1, - /*0x10e8*/ 502, - /*0xff43*/ 1111, - -1, - /*0x13c6*/ 562, - /*0x0446*/ 314, - /*0x04c6*/ 386, - -1, - /*0x10446*/ 1165, - /*0x2c6a*/ 901, - -1, - /*0x10cea*/ 1288, - /*0x0146*/ 89, - -1, - /*0x01bd*/ 136, - /*0x1f79*/ 793, - /*0x10ea*/ 504, - /*0x057d*/ 468, - -1, - /*0x00fd*/ 53, - /*0x0583*/ 474, - /*0x0493*/ 361, - -1, - /*0x03c6*/ 266, - -1, - /*0x1e13*/ 622, - /*0x1e93*/ 686, - /*0x0113*/ 65, - /*0x2c93*/ 914, - /*0x0250*/ 199, - /*0x01a1*/ 127, - /*0x0503*/ 417, - /*0x2d01*/ 959, - /*0x13e0*/ 588, - /*0x10cf0*/ 1294, - /*0xff41*/ 1109, - -1, - /*0x0242*/ 193, - /*0x104e0*/ 1183, - /*0x10f0*/ 510, - /*0x0209*/ 169, - /*0x050f*/ 423, - /*0x1e940*/ 1391, - -1, -1, - /*0xa7a9*/ 1093, - -1, - /*0x24e0*/ 839, - /*0x2d25*/ 995, - -1, - /*0x1f42*/ 768, - -1, - /*0x2c48*/ 873, - /*0x2d05*/ 963, - /*0x10cc8*/ 1254, - /*0x1e07*/ 616, - /*0x1e87*/ 680, - /*0x0107*/ 59, - /*0x2c87*/ 908, - -1, - /*0x13c4*/ 560, - /*0x0444*/ 312, - /*0x04c4*/ 385, - -1, - /*0x10444*/ 1163, - -1, - /*0x0199*/ 124, - /*0x2d1c*/ 986, - /*0x0144*/ 88, - /*0x2c76*/ 904, - /*0x105a1*/ 1221, - -1, -1, -1, -1, - /*0x0283*/ 226, - /*0x10f6*/ 516, - /*0x0497*/ 363, - /*0x0521*/ 432, - /*0x03c4*/ 264, - /*0x105bb*/ 1244, - /*0x1e17*/ 624, - /*0x049d*/ 366, - /*0x0117*/ 67, - /*0x2c97*/ 916, - /*0x10ce4*/ 1282, - /*0x1e1d*/ 627, - -1, - /*0x011d*/ 70, - /*0x2c9d*/ 919, - /*0x10e4*/ 498, - /*0x1e93d*/ 1388, - -1, -1, - /*0x105af*/ 1234, - /*0x026c*/ 218, - /*0xff4f*/ 1123, - /*0x2d23*/ 993, - -1, - /*0x1f77*/ 791, - -1, - /*0x022b*/ 185, - /*0x052f*/ 439, - -1, -1, - /*0x13e2*/ 590, - /*0x10599*/ 1213, - -1, - /*0x0062*/ 1, - -1, - /*0x104e2*/ 1185, - /*0x2d2d*/ 997, - /*0x0268*/ 214, - -1, - /*0x0519*/ 428, - -1, - /*0x2c46*/ 871, - /*0x1e93b*/ 1386, - /*0x10cc6*/ 1252, - /*0x24e2*/ 841, - /*0xff4d*/ 1121, - /*0x13d6*/ 578, - /*0x0456*/ 330, - /*0x0078*/ 22, - -1, - /*0x104f8*/ 1207, - /*0x0566*/ 445, - /*0x026a*/ 216, - /*0x00e6*/ 31, - /*0x13dc*/ 584, - /*0x045c*/ 336, - /*0x1e92f*/ 1374, - /*0x13da*/ 582, - /*0x045a*/ 334, - /*0x104dc*/ 1179, - /*0x24d6*/ 829, - /*0xff4b*/ 1119, - /*0x104da*/ 1177, - /*0x0572*/ 457, - /*0x03f8*/ 290, - /*0x00f2*/ 43, - -1, - /*0x01f9*/ 161, - /*0x24dc*/ 835, - -1, -1, - /*0x24da*/ 833, - /*0x10ce0*/ 1278, - -1, -1, - /*0xff49*/ 1117, - -1, - /*0x10e0*/ 494, - -1, -1, -1, - /*0x118d0*/ 1313, - /*0x13bc*/ 552, - /*0x043c*/ 304, - /*0x217d*/ 819, - -1, - /*0x1043c*/ 1155, - -1, - /*0x1f70*/ 784, - /*0x118c2*/ 1299, - /*0x013c*/ 84, - /*0x017c*/ 115, - -1, -1, - /*0x01d0*/ 142, - /*0x105a9*/ 1228, - -1, - /*0x2c44*/ 869, - /*0x1fb1*/ 799, - /*0x10cc4*/ 1250, - -1, - /*0x03bc*/ 257, - -1, - /*0x0529*/ 436, - /*0x13d8*/ 580, - /*0x0458*/ 332, - -1, -1, -1, - /*0x104d8*/ 1175, - /*0x16e7d*/ 1358, - -1, - /*0x13ca*/ 566, - /*0x044a*/ 318, - /*0x04ca*/ 388, - /*0x0579*/ 464, - /*0x1044a*/ 1169, - /*0x00f9*/ 49, - /*0x24d8*/ 831, - /*0x037c*/ 240, - /*0x13d4*/ 576, - /*0x0454*/ 328, - -1, -1, -1, - /*0x1f76*/ 790, - /*0x13b6*/ 546, - /*0x0436*/ 298, - -1, -1, - /*0x10436*/ 1149, - /*0x03ca*/ 270, - /*0x1e929*/ 1368, - -1, - /*0x24d4*/ 827, - /*0x0215*/ 175, - /*0x13b0*/ 540, - /*0x0430*/ 292, - -1, - /*0x1f64*/ 780, - /*0x10430*/ 1143, - /*0x13d2*/ 574, - /*0x0452*/ 326, - /*0x01ff*/ 164, - /*0x10ce2*/ 1280, - /*0x03b6*/ 251, - -1, -1, - /*0x1f15*/ 749, - /*0x10e2*/ 496, - /*0xa7c8*/ 1102, - -1, -1, - /*0x0509*/ 420, - /*0x2d27*/ 996, - /*0x24d2*/ 825, - -1, -1, - /*0x2c56*/ 887, - -1, - /*0x10cd6*/ 1268, - -1, -1, -1, - /*0x10f8*/ 518, - /*0x10d6*/ 484, - /*0x2c5c*/ 893, - /*0xa7f6*/ 1107, - /*0x10cdc*/ 1274, - /*0x2c5a*/ 891, - /*0xa77c*/ 1074, - /*0x10cda*/ 1272, - -1, - /*0x10dc*/ 490, - /*0x0213*/ 174, - -1, - /*0x10da*/ 488, - /*0x13f4*/ 608, - -1, - /*0x1e942*/ 1393, - /*0x0074*/ 18, - -1, - /*0x104f4*/ 1203, - -1, -1, -1, -1, - /*0x1f13*/ 747, - /*0x0260*/ 209, - -1, -1, - /*0x057f*/ 470, - -1, - /*0x00ff*/ 55, - /*0x2c3c*/ 861, - -1, -1, - /*0x0289*/ 229, - -1, - /*0x0577*/ 462, - -1, - /*0x1f60*/ 776, - -1, -1, - /*0x0207*/ 168, - /*0x2172*/ 808, - /*0x105ab*/ 1230, - -1, - /*0x056c*/ 451, - -1, - /*0x00ec*/ 37, - -1, -1, -1, - /*0x052b*/ 437, - -1, - /*0x2c58*/ 889, - /*0x1f07*/ 743, - /*0x10cd8*/ 1270, - /*0x16e66*/ 1335, - -1, -1, - /*0x118c8*/ 1305, - /*0x10d8*/ 486, - /*0x2c4a*/ 875, - /*0x0568*/ 447, - /*0x10cca*/ 1256, - /*0x00e8*/ 33, - /*0x1f44*/ 770, - /*0xa793*/ 1082, - /*0x0217*/ 176, - /*0x16e72*/ 1347, - /*0x2c54*/ 885, - -1, - /*0x10cd4*/ 1266, - /*0x021d*/ 179, - -1, - /*0xa681*/ 1021, - /*0x2c36*/ 855, - /*0x10d4*/ 482, - /*0x056a*/ 449, - -1, - /*0x00ea*/ 35, - /*0x1e92b*/ 1370, - -1, - /*0x13b4*/ 544, - /*0x0434*/ 296, - -1, - /*0x2c30*/ 849, - /*0x10434*/ 1147, - -1, -1, -1, - /*0x2c52*/ 883, - -1, - /*0x10cd2*/ 1264, - -1, - /*0x2179*/ 815, - /*0xa685*/ 1023, - /*0xa787*/ 1079, - /*0x10d2*/ 480, - /*0x2d03*/ 961, - -1, - /*0x0570*/ 455, - /*0x03b4*/ 249, - /*0x00f0*/ 41, - -1, -1, - /*0x13cc*/ 568, - /*0x044c*/ 320, - /*0x04cc*/ 389, - /*0x2d0f*/ 973, - /*0x1044c*/ 1171, - /*0x1f62*/ 778, - /*0x049f*/ 367, - /*0x0195*/ 123, - /*0x0256*/ 204, - -1, - /*0x1e1f*/ 628, - -1, - /*0x011f*/ 71, - /*0x2c9f*/ 920, - -1, - /*0x16e79*/ 1354, - /*0x025c*/ 208, - /*0xa797*/ 1084, - /*0x118c6*/ 1303, - /*0x03cc*/ 272, - /*0x1f78*/ 792, - -1, - /*0xa79d*/ 1087, - -1, -1, -1, -1, -1, - /*0x10f4*/ 514, - -1, -1, - /*0x01c6*/ 138, - /*0x0576*/ 461, - -1, - /*0x00f6*/ 47, - -1, -1, - /*0x13be*/ 554, - /*0x043e*/ 306, - -1, - /*0x2d21*/ 991, - /*0x1043e*/ 1157, - -1, -1, - /*0x023c*/ 190, - /*0x013e*/ 85, - /*0x0564*/ 443, - /*0x048d*/ 358, - /*0x00e4*/ 29, - -1, -1, - /*0x1e0d*/ 619, - /*0x1e8d*/ 683, - /*0x010d*/ 62, - /*0x2c8d*/ 911, - /*0x0515*/ 426, - /*0x03be*/ 259, - -1, - /*0x1f7c*/ 796, - /*0x13ba*/ 550, - /*0x043a*/ 302, - -1, -1, - /*0x1043a*/ 1153, - -1, - /*0x217f*/ 821, - -1, - /*0x013a*/ 83, - -1, -1, -1, - /*0x13b8*/ 548, - /*0x0438*/ 300, - /*0x2177*/ 813, - /*0x118c4*/ 1301, - /*0x10438*/ 1151, - /*0x2d19*/ 983, - -1, - /*0x03ba*/ 255, - -1, -1, -1, - /*0x0254*/ 203, - -1, -1, -1, -1, -1, -1, - /*0x2c34*/ 853, - /*0x03b8*/ 253, - /*0x16e7f*/ 1360, - -1, -1, - /*0x0513*/ 425, - -1, -1, -1, -1, - /*0x16e77*/ 1352, - -1, - /*0x1f36*/ 764, - -1, - /*0x0252*/ 201, - -1, -1, -1, -1, - /*0x16e6c*/ 1341, - -1, - /*0x00e0*/ 25, - /*0x1f30*/ 758, - /*0x2c4c*/ 877, - -1, - /*0x10ccc*/ 1258, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, - /*0x0507*/ 419, - /*0x16e68*/ 1337, - -1, -1, -1, - /*0xa7ca*/ 1103, - -1, -1, -1, -1, -1, - /*0x118d6*/ 1319, - -1, - /*0x2170*/ 806, - -1, -1, - /*0x16e6a*/ 1339, - -1, - /*0x10597*/ 1211, - /*0x118dc*/ 1325, - /*0x1fd0*/ 800, - -1, - /*0x118da*/ 1323, - /*0x1059d*/ 1217, - /*0x01d6*/ 145, - /*0x2c3e*/ 863, - /*0x0517*/ 427, - -1, - /*0x1f74*/ 788, - -1, -1, - /*0x051d*/ 430, - /*0x01dc*/ 148, - -1, -1, - /*0x01da*/ 147, - -1, - /*0xff47*/ 1115, - -1, - /*0x16e70*/ 1345, - -1, -1, -1, -1, - /*0x0287*/ 227, - -1, -1, - /*0x2c3a*/ 859, - -1, -1, - /*0x2176*/ 812, - -1, -1, -1, -1, -1, - /*0x0562*/ 441, - -1, - /*0x00e2*/ 27, - /*0x2c38*/ 857, - -1, -1, -1, -1, -1, -1, - /*0x2d09*/ 967, - -1, -1, - /*0x118d8*/ 1321, - -1, - /*0x0578*/ 463, - -1, - /*0x00f8*/ 48, - -1, - /*0x029d*/ 234, - /*0x16e76*/ 1351, - /*0x118ca*/ 1307, - -1, - /*0xff45*/ 1113, - -1, -1, - /*0x01d8*/ 146, - -1, -1, - /*0x118d4*/ 1317, - -1, -1, -1, -1, - /*0x16e64*/ 1333, - -1, -1, -1, -1, -1, - /*0x1f34*/ 762, - -1, - /*0x01d4*/ 144, - -1, - /*0x105bc*/ 1245, - -1, -1, -1, - /*0x01b6*/ 134, - -1, - /*0x118d2*/ 1315, - -1, -1, - /*0x057c*/ 467, - /*0x021f*/ 180, - /*0x00fc*/ 52, - -1, -1, - /*0x01b0*/ 132, - -1, -1, -1, -1, - /*0x01d2*/ 143, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, - /*0x1e93c*/ 1387, - -1, -1, -1, -1, -1, -1, - /*0x105b6*/ 1240, - -1, -1, -1, -1, - /*0xa683*/ 1022, - -1, - /*0x020d*/ 171, - /*0x16e60*/ 1329, - -1, - /*0x105b0*/ 1235, - -1, -1, -1, -1, - /*0xa68f*/ 1028, - -1, -1, -1, -1, -1, - /*0xa79f*/ 1088, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, - /*0x1e936*/ 1381, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, - /*0x1e930*/ 1375, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, - /*0x0574*/ 459, - -1, - /*0x00f4*/ 45, - -1, -1, -1, -1, -1, -1, - -1, - /*0x2178*/ 814, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, - /*0x01b4*/ 133, - /*0x16e62*/ 1331, - -1, -1, -1, -1, -1, -1, - -1, - /*0xa699*/ 1033, - /*0x118cc*/ 1309, - -1, -1, - /*0x2d15*/ 979, - -1, -1, - /*0x16e78*/ 1353, - -1, -1, -1, -1, -1, -1, - /*0x01cc*/ 140, - -1, -1, -1, -1, - /*0x217c*/ 818, - -1, -1, - /*0x1fe0*/ 802, - -1, -1, -1, -1, -1, -1, - -1, -1, - /*0x105b4*/ 1238, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, - /*0x2d13*/ 977, - -1, - /*0x16e7c*/ 1357, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - /*0x1059f*/ 1219, - -1, -1, -1, -1, -1, -1, - -1, - /*0x051f*/ 431, - -1, - /*0x1e934*/ 1379, - -1, -1, -1, -1, - /*0x2d07*/ 965, - -1, - /*0xff50*/ 1124, - -1, -1, -1, -1, -1, -1, - -1, - /*0xff42*/ 1110, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, - /*0x2d17*/ 981, - -1, -1, -1, -1, - /*0x2d1d*/ 987, - -1, -1, - /*0x050d*/ 422, - -1, -1, -1, -1, -1, - /*0x2174*/ 810, - /*0xa689*/ 1025, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, - /*0x105b8*/ 1242, - -1, -1, - /*0x1e93e*/ 1389, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, - /*0x16e74*/ 1349, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, - /*0x1e93a*/ 1385, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, - /*0x1e938*/ 1383, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, - /*0x1fb0*/ 798, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, - /*0xff48*/ 1116, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, - /*0xff46*/ 1114, - -1, -1, -1, - /*0xa695*/ 1031, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, - /*0xa693*/ 1030, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - /*0xff44*/ 1112, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, - /*0xa687*/ 1024, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, - /*0x2d1f*/ 989, - -1, -1, -1, -1, -1, -1, - -1, - /*0xa697*/ 1032, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, - /*0xff56*/ 1130, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, - /*0xff5a*/ 1134, - -1, -1, -1, - /*0x2d0d*/ 971, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - /*0xff58*/ 1132, - -1, -1, -1, -1, -1, -1, - -1, - /*0xff4a*/ 1118, - -1, -1, -1, -1, -1, -1, - -1, - /*0xff54*/ 1128, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, - /*0xff52*/ 1126, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - /*0xff4c*/ 1120, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - /*0xa68d*/ 1027 - }; - - if (code <= MAX_CODE_VALUE && code >= MIN_CODE_VALUE) - { - register unsigned int key = onigenc_unicode_CaseUnfold_11_hash(code); - - if (key <= MAX_HASH_VALUE) - { - register short s = wordlist[key]; - - if (s >= 0 && code1_equal(code, CaseUnfold_11_Table[s].from)) - return &CaseUnfold_11_Table[s].to; - } - } - return 0; -} - -static const CaseUnfold_12_Type CaseUnfold_12_Table[] = { -#define CaseUnfold_12 (*(CaseUnfold_12_Type (*)[58])(CaseUnfold_12_Table+0)) - {{0x0061, 0x02be}, {1, {0x1e9a}}}, - {{0x0066, 0x0066}, {1, {0xfb00}}}, - {{0x0066, 0x0069}, {1, {0xfb01}}}, - {{0x0066, 0x006c}, {1, {0xfb02}}}, - {{0x0068, 0x0331}, {1, {0x1e96}}}, - {{0x006a, 0x030c}, {1, {0x01f0}}}, - {{0x0073, 0x0073}, {2, {0x00df, 0x1e9e}}}, - {{0x0073, 0x0074}, {2, {0xfb05, 0xfb06}}}, - {{0x0074, 0x0308}, {1, {0x1e97}}}, - {{0x0077, 0x030a}, {1, {0x1e98}}}, - {{0x0079, 0x030a}, {1, {0x1e99}}}, - {{0x02bc, 0x006e}, {1, {0x0149}}}, - {{0x03ac, 0x03b9}, {1, {0x1fb4}}}, - {{0x03ae, 0x03b9}, {1, {0x1fc4}}}, - {{0x03b1, 0x0342}, {1, {0x1fb6}}}, - {{0x03b1, 0x03b9}, {2, {0x1fb3, 0x1fbc}}}, - {{0x03b7, 0x0342}, {1, {0x1fc6}}}, - {{0x03b7, 0x03b9}, {2, {0x1fc3, 0x1fcc}}}, - {{0x03b9, 0x0342}, {1, {0x1fd6}}}, - {{0x03c1, 0x0313}, {1, {0x1fe4}}}, - {{0x03c5, 0x0313}, {1, {0x1f50}}}, - {{0x03c5, 0x0342}, {1, {0x1fe6}}}, - {{0x03c9, 0x0342}, {1, {0x1ff6}}}, - {{0x03c9, 0x03b9}, {2, {0x1ff3, 0x1ffc}}}, - {{0x03ce, 0x03b9}, {1, {0x1ff4}}}, - {{0x0565, 0x0582}, {1, {0x0587}}}, - {{0x0574, 0x0565}, {1, {0xfb14}}}, - {{0x0574, 0x056b}, {1, {0xfb15}}}, - {{0x0574, 0x056d}, {1, {0xfb17}}}, - {{0x0574, 0x0576}, {1, {0xfb13}}}, - {{0x057e, 0x0576}, {1, {0xfb16}}}, - {{0x1f00, 0x03b9}, {2, {0x1f80, 0x1f88}}}, - {{0x1f01, 0x03b9}, {2, {0x1f81, 0x1f89}}}, - {{0x1f02, 0x03b9}, {2, {0x1f82, 0x1f8a}}}, - {{0x1f03, 0x03b9}, {2, {0x1f83, 0x1f8b}}}, - {{0x1f04, 0x03b9}, {2, {0x1f84, 0x1f8c}}}, - {{0x1f05, 0x03b9}, {2, {0x1f85, 0x1f8d}}}, - {{0x1f06, 0x03b9}, {2, {0x1f86, 0x1f8e}}}, - {{0x1f07, 0x03b9}, {2, {0x1f87, 0x1f8f}}}, - {{0x1f20, 0x03b9}, {2, {0x1f90, 0x1f98}}}, - {{0x1f21, 0x03b9}, {2, {0x1f91, 0x1f99}}}, - {{0x1f22, 0x03b9}, {2, {0x1f92, 0x1f9a}}}, - {{0x1f23, 0x03b9}, {2, {0x1f93, 0x1f9b}}}, - {{0x1f24, 0x03b9}, {2, {0x1f94, 0x1f9c}}}, - {{0x1f25, 0x03b9}, {2, {0x1f95, 0x1f9d}}}, - {{0x1f26, 0x03b9}, {2, {0x1f96, 0x1f9e}}}, - {{0x1f27, 0x03b9}, {2, {0x1f97, 0x1f9f}}}, - {{0x1f60, 0x03b9}, {2, {0x1fa0, 0x1fa8}}}, - {{0x1f61, 0x03b9}, {2, {0x1fa1, 0x1fa9}}}, - {{0x1f62, 0x03b9}, {2, {0x1fa2, 0x1faa}}}, - {{0x1f63, 0x03b9}, {2, {0x1fa3, 0x1fab}}}, - {{0x1f64, 0x03b9}, {2, {0x1fa4, 0x1fac}}}, - {{0x1f65, 0x03b9}, {2, {0x1fa5, 0x1fad}}}, - {{0x1f66, 0x03b9}, {2, {0x1fa6, 0x1fae}}}, - {{0x1f67, 0x03b9}, {2, {0x1fa7, 0x1faf}}}, - {{0x1f70, 0x03b9}, {1, {0x1fb2}}}, - {{0x1f74, 0x03b9}, {1, {0x1fc2}}}, - {{0x1f7c, 0x03b9}, {1, {0x1ff2}}}, -#define CaseUnfold_12_Locale (*(CaseUnfold_12_Type (*)[1])(CaseUnfold_12_Table+58)) - {{0x0069, 0x0307}, {1, {0x0130}}}, -}; - -/* ANSI-C code produced by gperf version 3.1 */ -/* Command-line: gperf -7 -k1,2,3,4,5,6 -F,-1 -c -j1 -i1 -t -T -E -C -H onigenc_unicode_CaseUnfold_12_hash -N onigenc_unicode_CaseUnfold_12_lookup -n */ - -/* maximum key range = 71, duplicates = 0 */ - -#ifdef __GNUC__ -__inline -#else -#ifdef __cplusplus -inline -#endif -#endif -/*ARGSUSED*/ -static unsigned int -onigenc_unicode_CaseUnfold_12_hash(const OnigCodePoint *codes) -{ - static const unsigned char asso_values[] = - { - 3, 58, 54, 57, 56, 16, 8, 2, 43, 82, - 3, 1, 23, 82, 82, 82, 82, 82, 82, 4, - 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, - 82, 82, 52, 51, 50, 49, 48, 47, 46, 45, - 82, 82, 82, 82, 43, 82, 42, 82, 82, 13, - 82, 82, 82, 82, 82, 11, 82, 1, 82, 82, - 14, 82, 1, 82, 82, 31, 3, 82, 82, 30, - 82, 82, 82, 10, 82, 82, 82, 82, 37, 82, - 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, - 82, 82, 82, 82, 82, 82, 37, 15, 36, 35, - 34, 17, 1, 33, 12, 4, 23, 23, 26, 21, - 13, 82, 27, 82, 82, 2, 5, 82, 11, 16, - 82, 15, 82, 82, 23, 82, 8, 82 - }; - return asso_values[bits_at(codes, 5)] + asso_values[bits_at(codes, 4)] + asso_values[bits_at(codes, 3)] + asso_values[bits_at(codes, 2)] + asso_values[bits_at(codes, 1)] + asso_values[bits_at(codes, 0)]; -} - -static const CodePointList2 * -onigenc_unicode_CaseUnfold_12_lookup(const OnigCodePoint *codes) -{ - enum - { - MIN_CODE_VALUE = 0x61, - MAX_CODE_VALUE = 0x1f7c, - TOTAL_KEYWORDS = 59, - MIN_WORD_LENGTH = 6, - MAX_WORD_LENGTH = 6, - MIN_HASH_VALUE = 11, - MAX_HASH_VALUE = 81 - }; - - static const short wordlist[] = - { - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, - /*0x1f66,0x03b9*/ 53, - /*0x1f07,0x03b9*/ 38, - /*0x1f00,0x03b9*/ 31, - /*0x0066,0x0066*/ 1, - /*0x1f74,0x03b9*/ 56, - /*0x0073,0x0073*/ 6, - /*0x0066,0x0069*/ 2, - /*0x1f06,0x03b9*/ 37, - /*0x0073,0x0074*/ 7, - /*0x03b9,0x0342*/ 18, - /*0x03c9,0x03b9*/ 23, - /*0x03b7,0x03b9*/ 17, - /*0x0069,0x0307*/ 58, - /*0x03b1,0x03b9*/ 15, - /*0x1f61,0x03b9*/ 48, - /*0x1f05,0x03b9*/ 36, - /*0x1f65,0x03b9*/ 52, - /*0x0574,0x0576*/ 29, - /*0x03c9,0x0342*/ 22, - /*0x03b7,0x0342*/ 16, - /*0x057e,0x0576*/ 30, - /*0x03b1,0x0342*/ 14, - /*0x1f7c,0x03b9*/ 57, - /*0x0574,0x0565*/ 26, - /*0x0079,0x030a*/ 10, - /*0x0077,0x030a*/ 9, - /*0x1f70,0x03b9*/ 55, - /*0x0574,0x056d*/ 28, - /*0x0066,0x006c*/ 3, - /*0x0574,0x056b*/ 27, - /*0x0061,0x02be*/ 0, - /*0x0068,0x0331*/ 4, - /*0x1f67,0x03b9*/ 54, - /*0x1f64,0x03b9*/ 51, - /*0x1f63,0x03b9*/ 50, - /*0x1f62,0x03b9*/ 49, - /*0x1f60,0x03b9*/ 47, - /*0x03ce,0x03b9*/ 24, - /*0x03c5,0x0342*/ 21, - /*0x03c5,0x0313*/ 20, - /*0x03c1,0x0313*/ 19, - /*0x02bc,0x006e*/ 11, - /*0x03ae,0x03b9*/ 13, - /*0x03ac,0x03b9*/ 12, - /*0x1f27,0x03b9*/ 46, - /*0x1f26,0x03b9*/ 45, - /*0x1f25,0x03b9*/ 44, - /*0x1f24,0x03b9*/ 43, - /*0x1f23,0x03b9*/ 42, - /*0x1f22,0x03b9*/ 41, - /*0x1f21,0x03b9*/ 40, - /*0x1f20,0x03b9*/ 39, - /*0x006a,0x030c*/ 5, - /*0x1f02,0x03b9*/ 33, - /*0x0074,0x0308*/ 8, - /*0x1f04,0x03b9*/ 35, - /*0x1f03,0x03b9*/ 34, - /*0x1f01,0x03b9*/ 32, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - /*0x0565,0x0582*/ 25 - }; - - if (codes[0] <= MAX_CODE_VALUE && codes[0] >= MIN_CODE_VALUE && - codes[1] <= MAX_CODE_VALUE && codes[1] >= MIN_CODE_VALUE) - { - register unsigned int key = onigenc_unicode_CaseUnfold_12_hash(codes); - - if (key <= MAX_HASH_VALUE) - { - register short s = wordlist[key]; - - if (s >= 0 && code2_equal(codes, CaseUnfold_12_Table[s].from)) - return &CaseUnfold_12_Table[s].to; - } - } - return 0; -} - -static const CaseUnfold_13_Type CaseUnfold_13_Table[] = { -#define CaseUnfold_13 (*(CaseUnfold_13_Type (*)[14])(CaseUnfold_13_Table+0)) - {{0x0066, 0x0066, 0x0069}, {1, {0xfb03}}}, - {{0x0066, 0x0066, 0x006c}, {1, {0xfb04}}}, - {{0x03b1, 0x0342, 0x03b9}, {1, {0x1fb7}}}, - {{0x03b7, 0x0342, 0x03b9}, {1, {0x1fc7}}}, - {{0x03b9, 0x0308, 0x0300}, {1, {0x1fd2}}}, - {{0x03b9, 0x0308, 0x0301}, {2, {0x0390, 0x1fd3}}}, - {{0x03b9, 0x0308, 0x0342}, {1, {0x1fd7}}}, - {{0x03c5, 0x0308, 0x0300}, {1, {0x1fe2}}}, - {{0x03c5, 0x0308, 0x0301}, {2, {0x03b0, 0x1fe3}}}, - {{0x03c5, 0x0308, 0x0342}, {1, {0x1fe7}}}, - {{0x03c5, 0x0313, 0x0300}, {1, {0x1f52}}}, - {{0x03c5, 0x0313, 0x0301}, {1, {0x1f54}}}, - {{0x03c5, 0x0313, 0x0342}, {1, {0x1f56}}}, - {{0x03c9, 0x0342, 0x03b9}, {1, {0x1ff7}}}, -}; - -/* ANSI-C code produced by gperf version 3.1 */ -/* Command-line: gperf -7 -k1,2,3,4,5,6,7,8,9 -F,-1 -c -j1 -i1 -t -T -E -C -H onigenc_unicode_CaseUnfold_13_hash -N onigenc_unicode_CaseUnfold_13_lookup -n */ - -/* maximum key range = 20, duplicates = 0 */ - -#ifdef __GNUC__ -__inline -#else -#ifdef __cplusplus -inline -#endif -#endif -/*ARGSUSED*/ -static unsigned int -onigenc_unicode_CaseUnfold_13_hash(const OnigCodePoint *codes) -{ - static const unsigned char asso_values[] = - { - 7, 4, 47, 47, 47, 47, 1, 1, 2, 47, - 47, 47, 47, 47, 47, 47, 47, 47, 47, 1, - 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, - 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, - 47, 47, 47, 47, 47, 47, 47, 47, 47, 11, - 47, 47, 47, 47, 47, 10, 47, 2, 47, 47, - 47, 47, 47, 47, 47, 47, 1, 47, 47, 1, - 47, 47, 47, 9, 47, 47, 47, 47, 47, 47, - 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, - 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, - 47, 47, 1, 47, 47, 2, 47, 47, 1, 47, - 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, - 47, 47, 47, 47, 47, 47, 47, 47 - }; - return asso_values[bits_at(codes, 8)] + asso_values[bits_at(codes, 7)] + asso_values[bits_at(codes, 6)] + asso_values[bits_at(codes, 5)] + asso_values[bits_at(codes, 4)] + asso_values[bits_at(codes, 3)] + asso_values[bits_at(codes, 2)] + asso_values[bits_at(codes, 1)] + asso_values[bits_at(codes, 0)]; -} - -static const CodePointList2 * -onigenc_unicode_CaseUnfold_13_lookup(const OnigCodePoint *codes) -{ - enum - { - MIN_CODE_VALUE = 0x66, - MAX_CODE_VALUE = 0x3c9, - TOTAL_KEYWORDS = 14, - MIN_WORD_LENGTH = 9, - MAX_WORD_LENGTH = 9, - MIN_HASH_VALUE = 27, - MAX_HASH_VALUE = 46 - }; - - static const short wordlist[] = - { - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, - -1, -1, -1, - /*0x03c5,0x0313,0x0342*/ 12, - /*0x03c5,0x0308,0x0342*/ 9, - /*0x03b9,0x0308,0x0342*/ 6, - /*0x03c5,0x0313,0x0301*/ 11, - /*0x03c5,0x0308,0x0301*/ 8, - /*0x03b9,0x0308,0x0301*/ 5, - /*0x03c5,0x0313,0x0300*/ 10, - /*0x03c5,0x0308,0x0300*/ 7, - /*0x03b9,0x0308,0x0300*/ 4, - /*0x03c9,0x0342,0x03b9*/ 13, - /*0x03b7,0x0342,0x03b9*/ 3, - /*0x03b1,0x0342,0x03b9*/ 2, - -1, -1, -1, -1, -1, -1, - /*0x0066,0x0066,0x006c*/ 1, - /*0x0066,0x0066,0x0069*/ 0 - }; - - if (codes[0] <= MAX_CODE_VALUE && codes[0] >= MIN_CODE_VALUE && - codes[1] <= MAX_CODE_VALUE && codes[1] >= MIN_CODE_VALUE && - codes[2] <= MAX_CODE_VALUE && codes[2] >= MIN_CODE_VALUE) - { - register unsigned int key = onigenc_unicode_CaseUnfold_13_hash(codes); - - if (key <= MAX_HASH_VALUE) - { - register short s = wordlist[key]; - - if (s >= 0 && code3_equal(codes, CaseUnfold_13_Table[s].from)) - return &CaseUnfold_13_Table[s].to; - } - } - return 0; -} - -static const OnigCodePoint CaseMappingSpecials[] = { - L(1)|0x039C, - L(2)|0x0053, 0x0073, L(2)|0x0053, 0x0053, - L(2)|0x02BC, 0x004E, - L(1)|0x0053, - L(1)|0x01C5, - L(2)|0x0064, 0x017D, L(1)|0x01C4, - L(1)|0x01C8, - L(2)|0x006C, 0x004A, L(1)|0x01C7, - L(1)|0x01CB, - L(2)|0x006E, 0x004A, L(1)|0x01CA, - L(2)|0x004A, 0x030C, - L(1)|0x01F2, - L(2)|0x0064, 0x005A, L(1)|0x01F1, - L(1)|0x0399, - L(3)|0x0399, 0x0308, 0x0301, - L(3)|0x03A5, 0x0308, 0x0301, - L(1)|0x03A3, - L(1)|0x0392, - L(1)|0x0398, - L(1)|0x03A6, - L(1)|0x03A0, - L(1)|0x039A, - L(1)|0x03A1, - L(1)|0x0395, - L(2)|0x0535, 0x0582, L(2)|0x0535, 0x0552, - L(1)|0x0412, - L(1)|0x0414, - L(1)|0x041E, - L(1)|0x0421, - L(1)|0x0422, - L(1)|0x0422, - L(1)|0x042A, - L(1)|0x0462, - L(1)|0xA64A, - L(2)|0x0048, 0x0331, - L(2)|0x0054, 0x0308, - L(2)|0x0057, 0x030A, - L(2)|0x0059, 0x030A, - L(2)|0x0041, 0x02BE, - L(1)|0x1E60, - L(1)|0x00DF, - L(2)|0x03A5, 0x0313, - L(3)|0x03A5, 0x0313, 0x0300, - L(3)|0x03A5, 0x0313, 0x0301, - L(3)|0x03A5, 0x0313, 0x0342, - L(1)|0x1F88, L(2)|0x1F08, 0x0399, - L(1)|0x1F89, L(2)|0x1F09, 0x0399, - L(1)|0x1F8A, L(2)|0x1F0A, 0x0399, - L(1)|0x1F8B, L(2)|0x1F0B, 0x0399, - L(1)|0x1F8C, L(2)|0x1F0C, 0x0399, - L(1)|0x1F8D, L(2)|0x1F0D, 0x0399, - L(1)|0x1F8E, L(2)|0x1F0E, 0x0399, - L(1)|0x1F8F, L(2)|0x1F0F, 0x0399, - L(2)|0x1F00, 0x0399, L(1)|0x1F80, L(2)|0x1F08, 0x0399, - L(2)|0x1F01, 0x0399, L(1)|0x1F81, L(2)|0x1F09, 0x0399, - L(2)|0x1F02, 0x0399, L(1)|0x1F82, L(2)|0x1F0A, 0x0399, - L(2)|0x1F03, 0x0399, L(1)|0x1F83, L(2)|0x1F0B, 0x0399, - L(2)|0x1F04, 0x0399, L(1)|0x1F84, L(2)|0x1F0C, 0x0399, - L(2)|0x1F05, 0x0399, L(1)|0x1F85, L(2)|0x1F0D, 0x0399, - L(2)|0x1F06, 0x0399, L(1)|0x1F86, L(2)|0x1F0E, 0x0399, - L(2)|0x1F07, 0x0399, L(1)|0x1F87, L(2)|0x1F0F, 0x0399, - L(1)|0x1F98, L(2)|0x1F28, 0x0399, - L(1)|0x1F99, L(2)|0x1F29, 0x0399, - L(1)|0x1F9A, L(2)|0x1F2A, 0x0399, - L(1)|0x1F9B, L(2)|0x1F2B, 0x0399, - L(1)|0x1F9C, L(2)|0x1F2C, 0x0399, - L(1)|0x1F9D, L(2)|0x1F2D, 0x0399, - L(1)|0x1F9E, L(2)|0x1F2E, 0x0399, - L(1)|0x1F9F, L(2)|0x1F2F, 0x0399, - L(2)|0x1F20, 0x0399, L(1)|0x1F90, L(2)|0x1F28, 0x0399, - L(2)|0x1F21, 0x0399, L(1)|0x1F91, L(2)|0x1F29, 0x0399, - L(2)|0x1F22, 0x0399, L(1)|0x1F92, L(2)|0x1F2A, 0x0399, - L(2)|0x1F23, 0x0399, L(1)|0x1F93, L(2)|0x1F2B, 0x0399, - L(2)|0x1F24, 0x0399, L(1)|0x1F94, L(2)|0x1F2C, 0x0399, - L(2)|0x1F25, 0x0399, L(1)|0x1F95, L(2)|0x1F2D, 0x0399, - L(2)|0x1F26, 0x0399, L(1)|0x1F96, L(2)|0x1F2E, 0x0399, - L(2)|0x1F27, 0x0399, L(1)|0x1F97, L(2)|0x1F2F, 0x0399, - L(1)|0x1FA8, L(2)|0x1F68, 0x0399, - L(1)|0x1FA9, L(2)|0x1F69, 0x0399, - L(1)|0x1FAA, L(2)|0x1F6A, 0x0399, - L(1)|0x1FAB, L(2)|0x1F6B, 0x0399, - L(1)|0x1FAC, L(2)|0x1F6C, 0x0399, - L(1)|0x1FAD, L(2)|0x1F6D, 0x0399, - L(1)|0x1FAE, L(2)|0x1F6E, 0x0399, - L(1)|0x1FAF, L(2)|0x1F6F, 0x0399, - L(2)|0x1F60, 0x0399, L(1)|0x1FA0, L(2)|0x1F68, 0x0399, - L(2)|0x1F61, 0x0399, L(1)|0x1FA1, L(2)|0x1F69, 0x0399, - L(2)|0x1F62, 0x0399, L(1)|0x1FA2, L(2)|0x1F6A, 0x0399, - L(2)|0x1F63, 0x0399, L(1)|0x1FA3, L(2)|0x1F6B, 0x0399, - L(2)|0x1F64, 0x0399, L(1)|0x1FA4, L(2)|0x1F6C, 0x0399, - L(2)|0x1F65, 0x0399, L(1)|0x1FA5, L(2)|0x1F6D, 0x0399, - L(2)|0x1F66, 0x0399, L(1)|0x1FA6, L(2)|0x1F6E, 0x0399, - L(2)|0x1F67, 0x0399, L(1)|0x1FA7, L(2)|0x1F6F, 0x0399, - L(2)|0x1FBA, 0x0345, L(2)|0x1FBA, 0x0399, - L(1)|0x1FBC, L(2)|0x0391, 0x0399, - L(2)|0x0386, 0x0345, L(2)|0x0386, 0x0399, - L(2)|0x0391, 0x0342, - L(3)|0x0391, 0x0342, 0x0345, L(3)|0x0391, 0x0342, 0x0399, - L(2)|0x03B1, 0x0399, L(1)|0x1FB3, L(2)|0x0391, 0x0399, - L(1)|0x0399, - L(2)|0x1FCA, 0x0345, L(2)|0x1FCA, 0x0399, - L(1)|0x1FCC, L(2)|0x0397, 0x0399, - L(2)|0x0389, 0x0345, L(2)|0x0389, 0x0399, - L(2)|0x0397, 0x0342, - L(3)|0x0397, 0x0342, 0x0345, L(3)|0x0397, 0x0342, 0x0399, - L(2)|0x03B7, 0x0399, L(1)|0x1FC3, L(2)|0x0397, 0x0399, - L(3)|0x0399, 0x0308, 0x0300, - L(3)|0x0399, 0x0308, 0x0301, - L(2)|0x0399, 0x0342, - L(3)|0x0399, 0x0308, 0x0342, - L(3)|0x03A5, 0x0308, 0x0300, - L(3)|0x03A5, 0x0308, 0x0301, - L(2)|0x03A1, 0x0313, - L(2)|0x03A5, 0x0342, - L(3)|0x03A5, 0x0308, 0x0342, - L(2)|0x1FFA, 0x0345, L(2)|0x1FFA, 0x0399, - L(1)|0x1FFC, L(2)|0x03A9, 0x0399, - L(2)|0x038F, 0x0345, L(2)|0x038F, 0x0399, - L(2)|0x03A9, 0x0342, - L(3)|0x03A9, 0x0342, 0x0345, L(3)|0x03A9, 0x0342, 0x0399, - L(2)|0x03C9, 0x0399, L(1)|0x1FF3, L(2)|0x03A9, 0x0399, - L(2)|0x0046, 0x0066, L(2)|0x0046, 0x0046, - L(2)|0x0046, 0x0069, L(2)|0x0046, 0x0049, - L(2)|0x0046, 0x006C, L(2)|0x0046, 0x004C, - L(3)|0x0046, 0x0066, 0x0069, L(3)|0x0046, 0x0046, 0x0049, - L(3)|0x0046, 0x0066, 0x006C, L(3)|0x0046, 0x0046, 0x004C, - L(2)|0x0053, 0x0074, L(2)|0x0053, 0x0054, - L(2)|0x0053, 0x0074, L(2)|0x0053, 0x0054, - L(2)|0x0544, 0x0576, L(2)|0x0544, 0x0546, - L(2)|0x0544, 0x0565, L(2)|0x0544, 0x0535, - L(2)|0x0544, 0x056B, L(2)|0x0544, 0x053B, - L(2)|0x054E, 0x0576, L(2)|0x054E, 0x0546, - L(2)|0x0544, 0x056D, L(2)|0x0544, 0x053D, -}; diff --git a/enc/unicode/16.0.0/casefold.h b/enc/unicode/16.0.0/casefold.h new file mode 100644 index 00000000000000..f14c0777d77983 --- /dev/null +++ b/enc/unicode/16.0.0/casefold.h @@ -0,0 +1,7804 @@ +/* DO NOT EDIT THIS FILE. */ +/* Generated by enc-case-folding.rb */ + +#if defined ONIG_UNICODE_VERSION_STRING && !( \ + ONIG_UNICODE_VERSION_MAJOR == 16 && \ + ONIG_UNICODE_VERSION_MINOR == 0 && \ + ONIG_UNICODE_VERSION_TEENY == 0 && \ + 1) +# error ONIG_UNICODE_VERSION_STRING mismatch +#endif +#define ONIG_UNICODE_VERSION_STRING "16.0.0" +#define ONIG_UNICODE_VERSION_MAJOR 16 +#define ONIG_UNICODE_VERSION_MINOR 0 +#define ONIG_UNICODE_VERSION_TEENY 0 + +static const CaseFold_11_Type CaseFold_11_Table[] = { +#define CaseFold (*(CaseFold_11_Type (*)[1555])(CaseFold_11_Table+0)) + {0x0041, {1|F|D, {0x0061}}}, + {0x0042, {1|F|D, {0x0062}}}, + {0x0043, {1|F|D, {0x0063}}}, + {0x0044, {1|F|D, {0x0064}}}, + {0x0045, {1|F|D, {0x0065}}}, + {0x0046, {1|F|D, {0x0066}}}, + {0x0047, {1|F|D, {0x0067}}}, + {0x0048, {1|F|D, {0x0068}}}, + {0x004a, {1|F|D, {0x006a}}}, + {0x004b, {1|F|D, {0x006b}}}, + {0x004c, {1|F|D, {0x006c}}}, + {0x004d, {1|F|D, {0x006d}}}, + {0x004e, {1|F|D, {0x006e}}}, + {0x004f, {1|F|D, {0x006f}}}, + {0x0050, {1|F|D, {0x0070}}}, + {0x0051, {1|F|D, {0x0071}}}, + {0x0052, {1|F|D, {0x0072}}}, + {0x0053, {1|F|D, {0x0073}}}, + {0x0054, {1|F|D, {0x0074}}}, + {0x0055, {1|F|D, {0x0075}}}, + {0x0056, {1|F|D, {0x0076}}}, + {0x0057, {1|F|D, {0x0077}}}, + {0x0058, {1|F|D, {0x0078}}}, + {0x0059, {1|F|D, {0x0079}}}, + {0x005a, {1|F|D, {0x007a}}}, + {0x00b5, {1|F|SU|I(0), {0x03bc}}}, + {0x00c0, {1|F|D, {0x00e0}}}, + {0x00c1, {1|F|D, {0x00e1}}}, + {0x00c2, {1|F|D, {0x00e2}}}, + {0x00c3, {1|F|D, {0x00e3}}}, + {0x00c4, {1|F|D, {0x00e4}}}, + {0x00c5, {1|F|D, {0x00e5}}}, + {0x00c6, {1|F|D, {0x00e6}}}, + {0x00c7, {1|F|D, {0x00e7}}}, + {0x00c8, {1|F|D, {0x00e8}}}, + {0x00c9, {1|F|D, {0x00e9}}}, + {0x00ca, {1|F|D, {0x00ea}}}, + {0x00cb, {1|F|D, {0x00eb}}}, + {0x00cc, {1|F|D, {0x00ec}}}, + {0x00cd, {1|F|D, {0x00ed}}}, + {0x00ce, {1|F|D, {0x00ee}}}, + {0x00cf, {1|F|D, {0x00ef}}}, + {0x00d0, {1|F|D, {0x00f0}}}, + {0x00d1, {1|F|D, {0x00f1}}}, + {0x00d2, {1|F|D, {0x00f2}}}, + {0x00d3, {1|F|D, {0x00f3}}}, + {0x00d4, {1|F|D, {0x00f4}}}, + {0x00d5, {1|F|D, {0x00f5}}}, + {0x00d6, {1|F|D, {0x00f6}}}, + {0x00d8, {1|F|D, {0x00f8}}}, + {0x00d9, {1|F|D, {0x00f9}}}, + {0x00da, {1|F|D, {0x00fa}}}, + {0x00db, {1|F|D, {0x00fb}}}, + {0x00dc, {1|F|D, {0x00fc}}}, + {0x00dd, {1|F|D, {0x00fd}}}, + {0x00de, {1|F|D, {0x00fe}}}, + {0x00df, {2|F|ST|SU|I(1), {0x0073, 0x0073}}}, + {0x0100, {1|F|D, {0x0101}}}, + {0x0102, {1|F|D, {0x0103}}}, + {0x0104, {1|F|D, {0x0105}}}, + {0x0106, {1|F|D, {0x0107}}}, + {0x0108, {1|F|D, {0x0109}}}, + {0x010a, {1|F|D, {0x010b}}}, + {0x010c, {1|F|D, {0x010d}}}, + {0x010e, {1|F|D, {0x010f}}}, + {0x0110, {1|F|D, {0x0111}}}, + {0x0112, {1|F|D, {0x0113}}}, + {0x0114, {1|F|D, {0x0115}}}, + {0x0116, {1|F|D, {0x0117}}}, + {0x0118, {1|F|D, {0x0119}}}, + {0x011a, {1|F|D, {0x011b}}}, + {0x011c, {1|F|D, {0x011d}}}, + {0x011e, {1|F|D, {0x011f}}}, + {0x0120, {1|F|D, {0x0121}}}, + {0x0122, {1|F|D, {0x0123}}}, + {0x0124, {1|F|D, {0x0125}}}, + {0x0126, {1|F|D, {0x0127}}}, + {0x0128, {1|F|D, {0x0129}}}, + {0x012a, {1|F|D, {0x012b}}}, + {0x012c, {1|F|D, {0x012d}}}, + {0x012e, {1|F|D, {0x012f}}}, + {0x0132, {1|F|D, {0x0133}}}, + {0x0134, {1|F|D, {0x0135}}}, + {0x0136, {1|F|D, {0x0137}}}, + {0x0139, {1|F|D, {0x013a}}}, + {0x013b, {1|F|D, {0x013c}}}, + {0x013d, {1|F|D, {0x013e}}}, + {0x013f, {1|F|D, {0x0140}}}, + {0x0141, {1|F|D, {0x0142}}}, + {0x0143, {1|F|D, {0x0144}}}, + {0x0145, {1|F|D, {0x0146}}}, + {0x0147, {1|F|D, {0x0148}}}, + {0x0149, {2|F|SU|I(5), {0x02bc, 0x006e}}}, + {0x014a, {1|F|D, {0x014b}}}, + {0x014c, {1|F|D, {0x014d}}}, + {0x014e, {1|F|D, {0x014f}}}, + {0x0150, {1|F|D, {0x0151}}}, + {0x0152, {1|F|D, {0x0153}}}, + {0x0154, {1|F|D, {0x0155}}}, + {0x0156, {1|F|D, {0x0157}}}, + {0x0158, {1|F|D, {0x0159}}}, + {0x015a, {1|F|D, {0x015b}}}, + {0x015c, {1|F|D, {0x015d}}}, + {0x015e, {1|F|D, {0x015f}}}, + {0x0160, {1|F|D, {0x0161}}}, + {0x0162, {1|F|D, {0x0163}}}, + {0x0164, {1|F|D, {0x0165}}}, + {0x0166, {1|F|D, {0x0167}}}, + {0x0168, {1|F|D, {0x0169}}}, + {0x016a, {1|F|D, {0x016b}}}, + {0x016c, {1|F|D, {0x016d}}}, + {0x016e, {1|F|D, {0x016f}}}, + {0x0170, {1|F|D, {0x0171}}}, + {0x0172, {1|F|D, {0x0173}}}, + {0x0174, {1|F|D, {0x0175}}}, + {0x0176, {1|F|D, {0x0177}}}, + {0x0178, {1|F|D, {0x00ff}}}, + {0x0179, {1|F|D, {0x017a}}}, + {0x017b, {1|F|D, {0x017c}}}, + {0x017d, {1|F|D, {0x017e}}}, + {0x017f, {1|F|SU|I(7), {0x0073}}}, + {0x0181, {1|F|D, {0x0253}}}, + {0x0182, {1|F|D, {0x0183}}}, + {0x0184, {1|F|D, {0x0185}}}, + {0x0186, {1|F|D, {0x0254}}}, + {0x0187, {1|F|D, {0x0188}}}, + {0x0189, {1|F|D, {0x0256}}}, + {0x018a, {1|F|D, {0x0257}}}, + {0x018b, {1|F|D, {0x018c}}}, + {0x018e, {1|F|D, {0x01dd}}}, + {0x018f, {1|F|D, {0x0259}}}, + {0x0190, {1|F|D, {0x025b}}}, + {0x0191, {1|F|D, {0x0192}}}, + {0x0193, {1|F|D, {0x0260}}}, + {0x0194, {1|F|D, {0x0263}}}, + {0x0196, {1|F|D, {0x0269}}}, + {0x0197, {1|F|D, {0x0268}}}, + {0x0198, {1|F|D, {0x0199}}}, + {0x019c, {1|F|D, {0x026f}}}, + {0x019d, {1|F|D, {0x0272}}}, + {0x019f, {1|F|D, {0x0275}}}, + {0x01a0, {1|F|D, {0x01a1}}}, + {0x01a2, {1|F|D, {0x01a3}}}, + {0x01a4, {1|F|D, {0x01a5}}}, + {0x01a6, {1|F|D, {0x0280}}}, + {0x01a7, {1|F|D, {0x01a8}}}, + {0x01a9, {1|F|D, {0x0283}}}, + {0x01ac, {1|F|D, {0x01ad}}}, + {0x01ae, {1|F|D, {0x0288}}}, + {0x01af, {1|F|D, {0x01b0}}}, + {0x01b1, {1|F|D, {0x028a}}}, + {0x01b2, {1|F|D, {0x028b}}}, + {0x01b3, {1|F|D, {0x01b4}}}, + {0x01b5, {1|F|D, {0x01b6}}}, + {0x01b7, {1|F|D, {0x0292}}}, + {0x01b8, {1|F|D, {0x01b9}}}, + {0x01bc, {1|F|D, {0x01bd}}}, + {0x01c4, {1|F|D|ST|I(8), {0x01c6}}}, + {0x01c5, {1|F|D|IT|SU|I(9), {0x01c6}}}, + {0x01c7, {1|F|D|ST|I(12), {0x01c9}}}, + {0x01c8, {1|F|D|IT|SU|I(13), {0x01c9}}}, + {0x01ca, {1|F|D|ST|I(16), {0x01cc}}}, + {0x01cb, {1|F|D|IT|SU|I(17), {0x01cc}}}, + {0x01cd, {1|F|D, {0x01ce}}}, + {0x01cf, {1|F|D, {0x01d0}}}, + {0x01d1, {1|F|D, {0x01d2}}}, + {0x01d3, {1|F|D, {0x01d4}}}, + {0x01d5, {1|F|D, {0x01d6}}}, + {0x01d7, {1|F|D, {0x01d8}}}, + {0x01d9, {1|F|D, {0x01da}}}, + {0x01db, {1|F|D, {0x01dc}}}, + {0x01de, {1|F|D, {0x01df}}}, + {0x01e0, {1|F|D, {0x01e1}}}, + {0x01e2, {1|F|D, {0x01e3}}}, + {0x01e4, {1|F|D, {0x01e5}}}, + {0x01e6, {1|F|D, {0x01e7}}}, + {0x01e8, {1|F|D, {0x01e9}}}, + {0x01ea, {1|F|D, {0x01eb}}}, + {0x01ec, {1|F|D, {0x01ed}}}, + {0x01ee, {1|F|D, {0x01ef}}}, + {0x01f0, {2|F|SU|I(20), {0x006a, 0x030c}}}, + {0x01f1, {1|F|D|ST|I(22), {0x01f3}}}, + {0x01f2, {1|F|D|IT|SU|I(23), {0x01f3}}}, + {0x01f4, {1|F|D, {0x01f5}}}, + {0x01f6, {1|F|D, {0x0195}}}, + {0x01f7, {1|F|D, {0x01bf}}}, + {0x01f8, {1|F|D, {0x01f9}}}, + {0x01fa, {1|F|D, {0x01fb}}}, + {0x01fc, {1|F|D, {0x01fd}}}, + {0x01fe, {1|F|D, {0x01ff}}}, + {0x0200, {1|F|D, {0x0201}}}, + {0x0202, {1|F|D, {0x0203}}}, + {0x0204, {1|F|D, {0x0205}}}, + {0x0206, {1|F|D, {0x0207}}}, + {0x0208, {1|F|D, {0x0209}}}, + {0x020a, {1|F|D, {0x020b}}}, + {0x020c, {1|F|D, {0x020d}}}, + {0x020e, {1|F|D, {0x020f}}}, + {0x0210, {1|F|D, {0x0211}}}, + {0x0212, {1|F|D, {0x0213}}}, + {0x0214, {1|F|D, {0x0215}}}, + {0x0216, {1|F|D, {0x0217}}}, + {0x0218, {1|F|D, {0x0219}}}, + {0x021a, {1|F|D, {0x021b}}}, + {0x021c, {1|F|D, {0x021d}}}, + {0x021e, {1|F|D, {0x021f}}}, + {0x0220, {1|F|D, {0x019e}}}, + {0x0222, {1|F|D, {0x0223}}}, + {0x0224, {1|F|D, {0x0225}}}, + {0x0226, {1|F|D, {0x0227}}}, + {0x0228, {1|F|D, {0x0229}}}, + {0x022a, {1|F|D, {0x022b}}}, + {0x022c, {1|F|D, {0x022d}}}, + {0x022e, {1|F|D, {0x022f}}}, + {0x0230, {1|F|D, {0x0231}}}, + {0x0232, {1|F|D, {0x0233}}}, + {0x023a, {1|F|D, {0x2c65}}}, + {0x023b, {1|F|D, {0x023c}}}, + {0x023d, {1|F|D, {0x019a}}}, + {0x023e, {1|F|D, {0x2c66}}}, + {0x0241, {1|F|D, {0x0242}}}, + {0x0243, {1|F|D, {0x0180}}}, + {0x0244, {1|F|D, {0x0289}}}, + {0x0245, {1|F|D, {0x028c}}}, + {0x0246, {1|F|D, {0x0247}}}, + {0x0248, {1|F|D, {0x0249}}}, + {0x024a, {1|F|D, {0x024b}}}, + {0x024c, {1|F|D, {0x024d}}}, + {0x024e, {1|F|D, {0x024f}}}, + {0x0345, {1|F|SU|I(26), {0x03b9}}}, + {0x0370, {1|F|D, {0x0371}}}, + {0x0372, {1|F|D, {0x0373}}}, + {0x0376, {1|F|D, {0x0377}}}, + {0x037f, {1|F|D, {0x03f3}}}, + {0x0386, {1|F|D, {0x03ac}}}, + {0x0388, {1|F|D, {0x03ad}}}, + {0x0389, {1|F|D, {0x03ae}}}, + {0x038a, {1|F|D, {0x03af}}}, + {0x038c, {1|F|D, {0x03cc}}}, + {0x038e, {1|F|D, {0x03cd}}}, + {0x038f, {1|F|D, {0x03ce}}}, + {0x0390, {3|F|SU|I(27), {0x03b9, 0x0308, 0x0301}}}, + {0x0391, {1|F|D, {0x03b1}}}, + {0x0392, {1|F|D, {0x03b2}}}, + {0x0393, {1|F|D, {0x03b3}}}, + {0x0394, {1|F|D, {0x03b4}}}, + {0x0395, {1|F|D, {0x03b5}}}, + {0x0396, {1|F|D, {0x03b6}}}, + {0x0397, {1|F|D, {0x03b7}}}, + {0x0398, {1|F|D, {0x03b8}}}, + {0x0399, {1|F|D, {0x03b9}}}, + {0x039a, {1|F|D, {0x03ba}}}, + {0x039b, {1|F|D, {0x03bb}}}, + {0x039c, {1|F|D, {0x03bc}}}, + {0x039d, {1|F|D, {0x03bd}}}, + {0x039e, {1|F|D, {0x03be}}}, + {0x039f, {1|F|D, {0x03bf}}}, + {0x03a0, {1|F|D, {0x03c0}}}, + {0x03a1, {1|F|D, {0x03c1}}}, + {0x03a3, {1|F|D, {0x03c3}}}, + {0x03a4, {1|F|D, {0x03c4}}}, + {0x03a5, {1|F|D, {0x03c5}}}, + {0x03a6, {1|F|D, {0x03c6}}}, + {0x03a7, {1|F|D, {0x03c7}}}, + {0x03a8, {1|F|D, {0x03c8}}}, + {0x03a9, {1|F|D, {0x03c9}}}, + {0x03aa, {1|F|D, {0x03ca}}}, + {0x03ab, {1|F|D, {0x03cb}}}, + {0x03b0, {3|F|SU|I(30), {0x03c5, 0x0308, 0x0301}}}, + {0x03c2, {1|F|SU|I(33), {0x03c3}}}, + {0x03cf, {1|F|D, {0x03d7}}}, + {0x03d0, {1|F|SU|I(34), {0x03b2}}}, + {0x03d1, {1|F|SU|I(35), {0x03b8}}}, + {0x03d5, {1|F|SU|I(36), {0x03c6}}}, + {0x03d6, {1|F|SU|I(37), {0x03c0}}}, + {0x03d8, {1|F|D, {0x03d9}}}, + {0x03da, {1|F|D, {0x03db}}}, + {0x03dc, {1|F|D, {0x03dd}}}, + {0x03de, {1|F|D, {0x03df}}}, + {0x03e0, {1|F|D, {0x03e1}}}, + {0x03e2, {1|F|D, {0x03e3}}}, + {0x03e4, {1|F|D, {0x03e5}}}, + {0x03e6, {1|F|D, {0x03e7}}}, + {0x03e8, {1|F|D, {0x03e9}}}, + {0x03ea, {1|F|D, {0x03eb}}}, + {0x03ec, {1|F|D, {0x03ed}}}, + {0x03ee, {1|F|D, {0x03ef}}}, + {0x03f0, {1|F|SU|I(38), {0x03ba}}}, + {0x03f1, {1|F|SU|I(39), {0x03c1}}}, + {0x03f4, {1|F|D, {0x03b8}}}, + {0x03f5, {1|F|SU|I(40), {0x03b5}}}, + {0x03f7, {1|F|D, {0x03f8}}}, + {0x03f9, {1|F|D, {0x03f2}}}, + {0x03fa, {1|F|D, {0x03fb}}}, + {0x03fd, {1|F|D, {0x037b}}}, + {0x03fe, {1|F|D, {0x037c}}}, + {0x03ff, {1|F|D, {0x037d}}}, + {0x0400, {1|F|D, {0x0450}}}, + {0x0401, {1|F|D, {0x0451}}}, + {0x0402, {1|F|D, {0x0452}}}, + {0x0403, {1|F|D, {0x0453}}}, + {0x0404, {1|F|D, {0x0454}}}, + {0x0405, {1|F|D, {0x0455}}}, + {0x0406, {1|F|D, {0x0456}}}, + {0x0407, {1|F|D, {0x0457}}}, + {0x0408, {1|F|D, {0x0458}}}, + {0x0409, {1|F|D, {0x0459}}}, + {0x040a, {1|F|D, {0x045a}}}, + {0x040b, {1|F|D, {0x045b}}}, + {0x040c, {1|F|D, {0x045c}}}, + {0x040d, {1|F|D, {0x045d}}}, + {0x040e, {1|F|D, {0x045e}}}, + {0x040f, {1|F|D, {0x045f}}}, + {0x0410, {1|F|D, {0x0430}}}, + {0x0411, {1|F|D, {0x0431}}}, + {0x0412, {1|F|D, {0x0432}}}, + {0x0413, {1|F|D, {0x0433}}}, + {0x0414, {1|F|D, {0x0434}}}, + {0x0415, {1|F|D, {0x0435}}}, + {0x0416, {1|F|D, {0x0436}}}, + {0x0417, {1|F|D, {0x0437}}}, + {0x0418, {1|F|D, {0x0438}}}, + {0x0419, {1|F|D, {0x0439}}}, + {0x041a, {1|F|D, {0x043a}}}, + {0x041b, {1|F|D, {0x043b}}}, + {0x041c, {1|F|D, {0x043c}}}, + {0x041d, {1|F|D, {0x043d}}}, + {0x041e, {1|F|D, {0x043e}}}, + {0x041f, {1|F|D, {0x043f}}}, + {0x0420, {1|F|D, {0x0440}}}, + {0x0421, {1|F|D, {0x0441}}}, + {0x0422, {1|F|D, {0x0442}}}, + {0x0423, {1|F|D, {0x0443}}}, + {0x0424, {1|F|D, {0x0444}}}, + {0x0425, {1|F|D, {0x0445}}}, + {0x0426, {1|F|D, {0x0446}}}, + {0x0427, {1|F|D, {0x0447}}}, + {0x0428, {1|F|D, {0x0448}}}, + {0x0429, {1|F|D, {0x0449}}}, + {0x042a, {1|F|D, {0x044a}}}, + {0x042b, {1|F|D, {0x044b}}}, + {0x042c, {1|F|D, {0x044c}}}, + {0x042d, {1|F|D, {0x044d}}}, + {0x042e, {1|F|D, {0x044e}}}, + {0x042f, {1|F|D, {0x044f}}}, + {0x0460, {1|F|D, {0x0461}}}, + {0x0462, {1|F|D, {0x0463}}}, + {0x0464, {1|F|D, {0x0465}}}, + {0x0466, {1|F|D, {0x0467}}}, + {0x0468, {1|F|D, {0x0469}}}, + {0x046a, {1|F|D, {0x046b}}}, + {0x046c, {1|F|D, {0x046d}}}, + {0x046e, {1|F|D, {0x046f}}}, + {0x0470, {1|F|D, {0x0471}}}, + {0x0472, {1|F|D, {0x0473}}}, + {0x0474, {1|F|D, {0x0475}}}, + {0x0476, {1|F|D, {0x0477}}}, + {0x0478, {1|F|D, {0x0479}}}, + {0x047a, {1|F|D, {0x047b}}}, + {0x047c, {1|F|D, {0x047d}}}, + {0x047e, {1|F|D, {0x047f}}}, + {0x0480, {1|F|D, {0x0481}}}, + {0x048a, {1|F|D, {0x048b}}}, + {0x048c, {1|F|D, {0x048d}}}, + {0x048e, {1|F|D, {0x048f}}}, + {0x0490, {1|F|D, {0x0491}}}, + {0x0492, {1|F|D, {0x0493}}}, + {0x0494, {1|F|D, {0x0495}}}, + {0x0496, {1|F|D, {0x0497}}}, + {0x0498, {1|F|D, {0x0499}}}, + {0x049a, {1|F|D, {0x049b}}}, + {0x049c, {1|F|D, {0x049d}}}, + {0x049e, {1|F|D, {0x049f}}}, + {0x04a0, {1|F|D, {0x04a1}}}, + {0x04a2, {1|F|D, {0x04a3}}}, + {0x04a4, {1|F|D, {0x04a5}}}, + {0x04a6, {1|F|D, {0x04a7}}}, + {0x04a8, {1|F|D, {0x04a9}}}, + {0x04aa, {1|F|D, {0x04ab}}}, + {0x04ac, {1|F|D, {0x04ad}}}, + {0x04ae, {1|F|D, {0x04af}}}, + {0x04b0, {1|F|D, {0x04b1}}}, + {0x04b2, {1|F|D, {0x04b3}}}, + {0x04b4, {1|F|D, {0x04b5}}}, + {0x04b6, {1|F|D, {0x04b7}}}, + {0x04b8, {1|F|D, {0x04b9}}}, + {0x04ba, {1|F|D, {0x04bb}}}, + {0x04bc, {1|F|D, {0x04bd}}}, + {0x04be, {1|F|D, {0x04bf}}}, + {0x04c0, {1|F|D, {0x04cf}}}, + {0x04c1, {1|F|D, {0x04c2}}}, + {0x04c3, {1|F|D, {0x04c4}}}, + {0x04c5, {1|F|D, {0x04c6}}}, + {0x04c7, {1|F|D, {0x04c8}}}, + {0x04c9, {1|F|D, {0x04ca}}}, + {0x04cb, {1|F|D, {0x04cc}}}, + {0x04cd, {1|F|D, {0x04ce}}}, + {0x04d0, {1|F|D, {0x04d1}}}, + {0x04d2, {1|F|D, {0x04d3}}}, + {0x04d4, {1|F|D, {0x04d5}}}, + {0x04d6, {1|F|D, {0x04d7}}}, + {0x04d8, {1|F|D, {0x04d9}}}, + {0x04da, {1|F|D, {0x04db}}}, + {0x04dc, {1|F|D, {0x04dd}}}, + {0x04de, {1|F|D, {0x04df}}}, + {0x04e0, {1|F|D, {0x04e1}}}, + {0x04e2, {1|F|D, {0x04e3}}}, + {0x04e4, {1|F|D, {0x04e5}}}, + {0x04e6, {1|F|D, {0x04e7}}}, + {0x04e8, {1|F|D, {0x04e9}}}, + {0x04ea, {1|F|D, {0x04eb}}}, + {0x04ec, {1|F|D, {0x04ed}}}, + {0x04ee, {1|F|D, {0x04ef}}}, + {0x04f0, {1|F|D, {0x04f1}}}, + {0x04f2, {1|F|D, {0x04f3}}}, + {0x04f4, {1|F|D, {0x04f5}}}, + {0x04f6, {1|F|D, {0x04f7}}}, + {0x04f8, {1|F|D, {0x04f9}}}, + {0x04fa, {1|F|D, {0x04fb}}}, + {0x04fc, {1|F|D, {0x04fd}}}, + {0x04fe, {1|F|D, {0x04ff}}}, + {0x0500, {1|F|D, {0x0501}}}, + {0x0502, {1|F|D, {0x0503}}}, + {0x0504, {1|F|D, {0x0505}}}, + {0x0506, {1|F|D, {0x0507}}}, + {0x0508, {1|F|D, {0x0509}}}, + {0x050a, {1|F|D, {0x050b}}}, + {0x050c, {1|F|D, {0x050d}}}, + {0x050e, {1|F|D, {0x050f}}}, + {0x0510, {1|F|D, {0x0511}}}, + {0x0512, {1|F|D, {0x0513}}}, + {0x0514, {1|F|D, {0x0515}}}, + {0x0516, {1|F|D, {0x0517}}}, + {0x0518, {1|F|D, {0x0519}}}, + {0x051a, {1|F|D, {0x051b}}}, + {0x051c, {1|F|D, {0x051d}}}, + {0x051e, {1|F|D, {0x051f}}}, + {0x0520, {1|F|D, {0x0521}}}, + {0x0522, {1|F|D, {0x0523}}}, + {0x0524, {1|F|D, {0x0525}}}, + {0x0526, {1|F|D, {0x0527}}}, + {0x0528, {1|F|D, {0x0529}}}, + {0x052a, {1|F|D, {0x052b}}}, + {0x052c, {1|F|D, {0x052d}}}, + {0x052e, {1|F|D, {0x052f}}}, + {0x0531, {1|F|D, {0x0561}}}, + {0x0532, {1|F|D, {0x0562}}}, + {0x0533, {1|F|D, {0x0563}}}, + {0x0534, {1|F|D, {0x0564}}}, + {0x0535, {1|F|D, {0x0565}}}, + {0x0536, {1|F|D, {0x0566}}}, + {0x0537, {1|F|D, {0x0567}}}, + {0x0538, {1|F|D, {0x0568}}}, + {0x0539, {1|F|D, {0x0569}}}, + {0x053a, {1|F|D, {0x056a}}}, + {0x053b, {1|F|D, {0x056b}}}, + {0x053c, {1|F|D, {0x056c}}}, + {0x053d, {1|F|D, {0x056d}}}, + {0x053e, {1|F|D, {0x056e}}}, + {0x053f, {1|F|D, {0x056f}}}, + {0x0540, {1|F|D, {0x0570}}}, + {0x0541, {1|F|D, {0x0571}}}, + {0x0542, {1|F|D, {0x0572}}}, + {0x0543, {1|F|D, {0x0573}}}, + {0x0544, {1|F|D, {0x0574}}}, + {0x0545, {1|F|D, {0x0575}}}, + {0x0546, {1|F|D, {0x0576}}}, + {0x0547, {1|F|D, {0x0577}}}, + {0x0548, {1|F|D, {0x0578}}}, + {0x0549, {1|F|D, {0x0579}}}, + {0x054a, {1|F|D, {0x057a}}}, + {0x054b, {1|F|D, {0x057b}}}, + {0x054c, {1|F|D, {0x057c}}}, + {0x054d, {1|F|D, {0x057d}}}, + {0x054e, {1|F|D, {0x057e}}}, + {0x054f, {1|F|D, {0x057f}}}, + {0x0550, {1|F|D, {0x0580}}}, + {0x0551, {1|F|D, {0x0581}}}, + {0x0552, {1|F|D, {0x0582}}}, + {0x0553, {1|F|D, {0x0583}}}, + {0x0554, {1|F|D, {0x0584}}}, + {0x0555, {1|F|D, {0x0585}}}, + {0x0556, {1|F|D, {0x0586}}}, + {0x0587, {2|F|ST|SU|I(41), {0x0565, 0x0582}}}, + {0x10a0, {1|F|D, {0x2d00}}}, + {0x10a1, {1|F|D, {0x2d01}}}, + {0x10a2, {1|F|D, {0x2d02}}}, + {0x10a3, {1|F|D, {0x2d03}}}, + {0x10a4, {1|F|D, {0x2d04}}}, + {0x10a5, {1|F|D, {0x2d05}}}, + {0x10a6, {1|F|D, {0x2d06}}}, + {0x10a7, {1|F|D, {0x2d07}}}, + {0x10a8, {1|F|D, {0x2d08}}}, + {0x10a9, {1|F|D, {0x2d09}}}, + {0x10aa, {1|F|D, {0x2d0a}}}, + {0x10ab, {1|F|D, {0x2d0b}}}, + {0x10ac, {1|F|D, {0x2d0c}}}, + {0x10ad, {1|F|D, {0x2d0d}}}, + {0x10ae, {1|F|D, {0x2d0e}}}, + {0x10af, {1|F|D, {0x2d0f}}}, + {0x10b0, {1|F|D, {0x2d10}}}, + {0x10b1, {1|F|D, {0x2d11}}}, + {0x10b2, {1|F|D, {0x2d12}}}, + {0x10b3, {1|F|D, {0x2d13}}}, + {0x10b4, {1|F|D, {0x2d14}}}, + {0x10b5, {1|F|D, {0x2d15}}}, + {0x10b6, {1|F|D, {0x2d16}}}, + {0x10b7, {1|F|D, {0x2d17}}}, + {0x10b8, {1|F|D, {0x2d18}}}, + {0x10b9, {1|F|D, {0x2d19}}}, + {0x10ba, {1|F|D, {0x2d1a}}}, + {0x10bb, {1|F|D, {0x2d1b}}}, + {0x10bc, {1|F|D, {0x2d1c}}}, + {0x10bd, {1|F|D, {0x2d1d}}}, + {0x10be, {1|F|D, {0x2d1e}}}, + {0x10bf, {1|F|D, {0x2d1f}}}, + {0x10c0, {1|F|D, {0x2d20}}}, + {0x10c1, {1|F|D, {0x2d21}}}, + {0x10c2, {1|F|D, {0x2d22}}}, + {0x10c3, {1|F|D, {0x2d23}}}, + {0x10c4, {1|F|D, {0x2d24}}}, + {0x10c5, {1|F|D, {0x2d25}}}, + {0x10c7, {1|F|D, {0x2d27}}}, + {0x10cd, {1|F|D, {0x2d2d}}}, + {0x13f8, {1|F|U, {0x13f0}}}, + {0x13f9, {1|F|U, {0x13f1}}}, + {0x13fa, {1|F|U, {0x13f2}}}, + {0x13fb, {1|F|U, {0x13f3}}}, + {0x13fc, {1|F|U, {0x13f4}}}, + {0x13fd, {1|F|U, {0x13f5}}}, + {0x1c80, {1|F|SU|I(45), {0x0432}}}, + {0x1c81, {1|F|SU|I(46), {0x0434}}}, + {0x1c82, {1|F|SU|I(47), {0x043e}}}, + {0x1c83, {1|F|SU|I(48), {0x0441}}}, + {0x1c84, {1|F|SU|I(49), {0x0442}}}, + {0x1c85, {1|F|SU|I(50), {0x0442}}}, + {0x1c86, {1|F|SU|I(51), {0x044a}}}, + {0x1c87, {1|F|SU|I(52), {0x0463}}}, + {0x1c88, {1|F|SU|I(53), {0xa64b}}}, + {0x1c89, {1|F|D, {0x1c8a}}}, + {0x1c90, {1|F|D, {0x10d0}}}, + {0x1c91, {1|F|D, {0x10d1}}}, + {0x1c92, {1|F|D, {0x10d2}}}, + {0x1c93, {1|F|D, {0x10d3}}}, + {0x1c94, {1|F|D, {0x10d4}}}, + {0x1c95, {1|F|D, {0x10d5}}}, + {0x1c96, {1|F|D, {0x10d6}}}, + {0x1c97, {1|F|D, {0x10d7}}}, + {0x1c98, {1|F|D, {0x10d8}}}, + {0x1c99, {1|F|D, {0x10d9}}}, + {0x1c9a, {1|F|D, {0x10da}}}, + {0x1c9b, {1|F|D, {0x10db}}}, + {0x1c9c, {1|F|D, {0x10dc}}}, + {0x1c9d, {1|F|D, {0x10dd}}}, + {0x1c9e, {1|F|D, {0x10de}}}, + {0x1c9f, {1|F|D, {0x10df}}}, + {0x1ca0, {1|F|D, {0x10e0}}}, + {0x1ca1, {1|F|D, {0x10e1}}}, + {0x1ca2, {1|F|D, {0x10e2}}}, + {0x1ca3, {1|F|D, {0x10e3}}}, + {0x1ca4, {1|F|D, {0x10e4}}}, + {0x1ca5, {1|F|D, {0x10e5}}}, + {0x1ca6, {1|F|D, {0x10e6}}}, + {0x1ca7, {1|F|D, {0x10e7}}}, + {0x1ca8, {1|F|D, {0x10e8}}}, + {0x1ca9, {1|F|D, {0x10e9}}}, + {0x1caa, {1|F|D, {0x10ea}}}, + {0x1cab, {1|F|D, {0x10eb}}}, + {0x1cac, {1|F|D, {0x10ec}}}, + {0x1cad, {1|F|D, {0x10ed}}}, + {0x1cae, {1|F|D, {0x10ee}}}, + {0x1caf, {1|F|D, {0x10ef}}}, + {0x1cb0, {1|F|D, {0x10f0}}}, + {0x1cb1, {1|F|D, {0x10f1}}}, + {0x1cb2, {1|F|D, {0x10f2}}}, + {0x1cb3, {1|F|D, {0x10f3}}}, + {0x1cb4, {1|F|D, {0x10f4}}}, + {0x1cb5, {1|F|D, {0x10f5}}}, + {0x1cb6, {1|F|D, {0x10f6}}}, + {0x1cb7, {1|F|D, {0x10f7}}}, + {0x1cb8, {1|F|D, {0x10f8}}}, + {0x1cb9, {1|F|D, {0x10f9}}}, + {0x1cba, {1|F|D, {0x10fa}}}, + {0x1cbd, {1|F|D, {0x10fd}}}, + {0x1cbe, {1|F|D, {0x10fe}}}, + {0x1cbf, {1|F|D, {0x10ff}}}, + {0x1e00, {1|F|D, {0x1e01}}}, + {0x1e02, {1|F|D, {0x1e03}}}, + {0x1e04, {1|F|D, {0x1e05}}}, + {0x1e06, {1|F|D, {0x1e07}}}, + {0x1e08, {1|F|D, {0x1e09}}}, + {0x1e0a, {1|F|D, {0x1e0b}}}, + {0x1e0c, {1|F|D, {0x1e0d}}}, + {0x1e0e, {1|F|D, {0x1e0f}}}, + {0x1e10, {1|F|D, {0x1e11}}}, + {0x1e12, {1|F|D, {0x1e13}}}, + {0x1e14, {1|F|D, {0x1e15}}}, + {0x1e16, {1|F|D, {0x1e17}}}, + {0x1e18, {1|F|D, {0x1e19}}}, + {0x1e1a, {1|F|D, {0x1e1b}}}, + {0x1e1c, {1|F|D, {0x1e1d}}}, + {0x1e1e, {1|F|D, {0x1e1f}}}, + {0x1e20, {1|F|D, {0x1e21}}}, + {0x1e22, {1|F|D, {0x1e23}}}, + {0x1e24, {1|F|D, {0x1e25}}}, + {0x1e26, {1|F|D, {0x1e27}}}, + {0x1e28, {1|F|D, {0x1e29}}}, + {0x1e2a, {1|F|D, {0x1e2b}}}, + {0x1e2c, {1|F|D, {0x1e2d}}}, + {0x1e2e, {1|F|D, {0x1e2f}}}, + {0x1e30, {1|F|D, {0x1e31}}}, + {0x1e32, {1|F|D, {0x1e33}}}, + {0x1e34, {1|F|D, {0x1e35}}}, + {0x1e36, {1|F|D, {0x1e37}}}, + {0x1e38, {1|F|D, {0x1e39}}}, + {0x1e3a, {1|F|D, {0x1e3b}}}, + {0x1e3c, {1|F|D, {0x1e3d}}}, + {0x1e3e, {1|F|D, {0x1e3f}}}, + {0x1e40, {1|F|D, {0x1e41}}}, + {0x1e42, {1|F|D, {0x1e43}}}, + {0x1e44, {1|F|D, {0x1e45}}}, + {0x1e46, {1|F|D, {0x1e47}}}, + {0x1e48, {1|F|D, {0x1e49}}}, + {0x1e4a, {1|F|D, {0x1e4b}}}, + {0x1e4c, {1|F|D, {0x1e4d}}}, + {0x1e4e, {1|F|D, {0x1e4f}}}, + {0x1e50, {1|F|D, {0x1e51}}}, + {0x1e52, {1|F|D, {0x1e53}}}, + {0x1e54, {1|F|D, {0x1e55}}}, + {0x1e56, {1|F|D, {0x1e57}}}, + {0x1e58, {1|F|D, {0x1e59}}}, + {0x1e5a, {1|F|D, {0x1e5b}}}, + {0x1e5c, {1|F|D, {0x1e5d}}}, + {0x1e5e, {1|F|D, {0x1e5f}}}, + {0x1e60, {1|F|D, {0x1e61}}}, + {0x1e62, {1|F|D, {0x1e63}}}, + {0x1e64, {1|F|D, {0x1e65}}}, + {0x1e66, {1|F|D, {0x1e67}}}, + {0x1e68, {1|F|D, {0x1e69}}}, + {0x1e6a, {1|F|D, {0x1e6b}}}, + {0x1e6c, {1|F|D, {0x1e6d}}}, + {0x1e6e, {1|F|D, {0x1e6f}}}, + {0x1e70, {1|F|D, {0x1e71}}}, + {0x1e72, {1|F|D, {0x1e73}}}, + {0x1e74, {1|F|D, {0x1e75}}}, + {0x1e76, {1|F|D, {0x1e77}}}, + {0x1e78, {1|F|D, {0x1e79}}}, + {0x1e7a, {1|F|D, {0x1e7b}}}, + {0x1e7c, {1|F|D, {0x1e7d}}}, + {0x1e7e, {1|F|D, {0x1e7f}}}, + {0x1e80, {1|F|D, {0x1e81}}}, + {0x1e82, {1|F|D, {0x1e83}}}, + {0x1e84, {1|F|D, {0x1e85}}}, + {0x1e86, {1|F|D, {0x1e87}}}, + {0x1e88, {1|F|D, {0x1e89}}}, + {0x1e8a, {1|F|D, {0x1e8b}}}, + {0x1e8c, {1|F|D, {0x1e8d}}}, + {0x1e8e, {1|F|D, {0x1e8f}}}, + {0x1e90, {1|F|D, {0x1e91}}}, + {0x1e92, {1|F|D, {0x1e93}}}, + {0x1e94, {1|F|D, {0x1e95}}}, + {0x1e96, {2|F|SU|I(54), {0x0068, 0x0331}}}, + {0x1e97, {2|F|SU|I(56), {0x0074, 0x0308}}}, + {0x1e98, {2|F|SU|I(58), {0x0077, 0x030a}}}, + {0x1e99, {2|F|SU|I(60), {0x0079, 0x030a}}}, + {0x1e9a, {2|F|SU|I(62), {0x0061, 0x02be}}}, + {0x1e9b, {1|F|SU|I(64), {0x1e61}}}, + {0x1e9e, {2|F|SL|I(65), {0x0073, 0x0073}}}, + {0x1ea0, {1|F|D, {0x1ea1}}}, + {0x1ea2, {1|F|D, {0x1ea3}}}, + {0x1ea4, {1|F|D, {0x1ea5}}}, + {0x1ea6, {1|F|D, {0x1ea7}}}, + {0x1ea8, {1|F|D, {0x1ea9}}}, + {0x1eaa, {1|F|D, {0x1eab}}}, + {0x1eac, {1|F|D, {0x1ead}}}, + {0x1eae, {1|F|D, {0x1eaf}}}, + {0x1eb0, {1|F|D, {0x1eb1}}}, + {0x1eb2, {1|F|D, {0x1eb3}}}, + {0x1eb4, {1|F|D, {0x1eb5}}}, + {0x1eb6, {1|F|D, {0x1eb7}}}, + {0x1eb8, {1|F|D, {0x1eb9}}}, + {0x1eba, {1|F|D, {0x1ebb}}}, + {0x1ebc, {1|F|D, {0x1ebd}}}, + {0x1ebe, {1|F|D, {0x1ebf}}}, + {0x1ec0, {1|F|D, {0x1ec1}}}, + {0x1ec2, {1|F|D, {0x1ec3}}}, + {0x1ec4, {1|F|D, {0x1ec5}}}, + {0x1ec6, {1|F|D, {0x1ec7}}}, + {0x1ec8, {1|F|D, {0x1ec9}}}, + {0x1eca, {1|F|D, {0x1ecb}}}, + {0x1ecc, {1|F|D, {0x1ecd}}}, + {0x1ece, {1|F|D, {0x1ecf}}}, + {0x1ed0, {1|F|D, {0x1ed1}}}, + {0x1ed2, {1|F|D, {0x1ed3}}}, + {0x1ed4, {1|F|D, {0x1ed5}}}, + {0x1ed6, {1|F|D, {0x1ed7}}}, + {0x1ed8, {1|F|D, {0x1ed9}}}, + {0x1eda, {1|F|D, {0x1edb}}}, + {0x1edc, {1|F|D, {0x1edd}}}, + {0x1ede, {1|F|D, {0x1edf}}}, + {0x1ee0, {1|F|D, {0x1ee1}}}, + {0x1ee2, {1|F|D, {0x1ee3}}}, + {0x1ee4, {1|F|D, {0x1ee5}}}, + {0x1ee6, {1|F|D, {0x1ee7}}}, + {0x1ee8, {1|F|D, {0x1ee9}}}, + {0x1eea, {1|F|D, {0x1eeb}}}, + {0x1eec, {1|F|D, {0x1eed}}}, + {0x1eee, {1|F|D, {0x1eef}}}, + {0x1ef0, {1|F|D, {0x1ef1}}}, + {0x1ef2, {1|F|D, {0x1ef3}}}, + {0x1ef4, {1|F|D, {0x1ef5}}}, + {0x1ef6, {1|F|D, {0x1ef7}}}, + {0x1ef8, {1|F|D, {0x1ef9}}}, + {0x1efa, {1|F|D, {0x1efb}}}, + {0x1efc, {1|F|D, {0x1efd}}}, + {0x1efe, {1|F|D, {0x1eff}}}, + {0x1f08, {1|F|D, {0x1f00}}}, + {0x1f09, {1|F|D, {0x1f01}}}, + {0x1f0a, {1|F|D, {0x1f02}}}, + {0x1f0b, {1|F|D, {0x1f03}}}, + {0x1f0c, {1|F|D, {0x1f04}}}, + {0x1f0d, {1|F|D, {0x1f05}}}, + {0x1f0e, {1|F|D, {0x1f06}}}, + {0x1f0f, {1|F|D, {0x1f07}}}, + {0x1f18, {1|F|D, {0x1f10}}}, + {0x1f19, {1|F|D, {0x1f11}}}, + {0x1f1a, {1|F|D, {0x1f12}}}, + {0x1f1b, {1|F|D, {0x1f13}}}, + {0x1f1c, {1|F|D, {0x1f14}}}, + {0x1f1d, {1|F|D, {0x1f15}}}, + {0x1f28, {1|F|D, {0x1f20}}}, + {0x1f29, {1|F|D, {0x1f21}}}, + {0x1f2a, {1|F|D, {0x1f22}}}, + {0x1f2b, {1|F|D, {0x1f23}}}, + {0x1f2c, {1|F|D, {0x1f24}}}, + {0x1f2d, {1|F|D, {0x1f25}}}, + {0x1f2e, {1|F|D, {0x1f26}}}, + {0x1f2f, {1|F|D, {0x1f27}}}, + {0x1f38, {1|F|D, {0x1f30}}}, + {0x1f39, {1|F|D, {0x1f31}}}, + {0x1f3a, {1|F|D, {0x1f32}}}, + {0x1f3b, {1|F|D, {0x1f33}}}, + {0x1f3c, {1|F|D, {0x1f34}}}, + {0x1f3d, {1|F|D, {0x1f35}}}, + {0x1f3e, {1|F|D, {0x1f36}}}, + {0x1f3f, {1|F|D, {0x1f37}}}, + {0x1f48, {1|F|D, {0x1f40}}}, + {0x1f49, {1|F|D, {0x1f41}}}, + {0x1f4a, {1|F|D, {0x1f42}}}, + {0x1f4b, {1|F|D, {0x1f43}}}, + {0x1f4c, {1|F|D, {0x1f44}}}, + {0x1f4d, {1|F|D, {0x1f45}}}, + {0x1f50, {2|F|SU|I(66), {0x03c5, 0x0313}}}, + {0x1f52, {3|F|SU|I(68), {0x03c5, 0x0313, 0x0300}}}, + {0x1f54, {3|F|SU|I(71), {0x03c5, 0x0313, 0x0301}}}, + {0x1f56, {3|F|SU|I(74), {0x03c5, 0x0313, 0x0342}}}, + {0x1f59, {1|F|D, {0x1f51}}}, + {0x1f5b, {1|F|D, {0x1f53}}}, + {0x1f5d, {1|F|D, {0x1f55}}}, + {0x1f5f, {1|F|D, {0x1f57}}}, + {0x1f68, {1|F|D, {0x1f60}}}, + {0x1f69, {1|F|D, {0x1f61}}}, + {0x1f6a, {1|F|D, {0x1f62}}}, + {0x1f6b, {1|F|D, {0x1f63}}}, + {0x1f6c, {1|F|D, {0x1f64}}}, + {0x1f6d, {1|F|D, {0x1f65}}}, + {0x1f6e, {1|F|D, {0x1f66}}}, + {0x1f6f, {1|F|D, {0x1f67}}}, + {0x1f80, {2|F|ST|SU|I(77), {0x1f00, 0x03b9}}}, + {0x1f81, {2|F|ST|SU|I(80), {0x1f01, 0x03b9}}}, + {0x1f82, {2|F|ST|SU|I(83), {0x1f02, 0x03b9}}}, + {0x1f83, {2|F|ST|SU|I(86), {0x1f03, 0x03b9}}}, + {0x1f84, {2|F|ST|SU|I(89), {0x1f04, 0x03b9}}}, + {0x1f85, {2|F|ST|SU|I(92), {0x1f05, 0x03b9}}}, + {0x1f86, {2|F|ST|SU|I(95), {0x1f06, 0x03b9}}}, + {0x1f87, {2|F|ST|SU|I(98), {0x1f07, 0x03b9}}}, + {0x1f88, {2|F|IT|SL|SU|I(101), {0x1f00, 0x03b9}}}, + {0x1f89, {2|F|IT|SL|SU|I(106), {0x1f01, 0x03b9}}}, + {0x1f8a, {2|F|IT|SL|SU|I(111), {0x1f02, 0x03b9}}}, + {0x1f8b, {2|F|IT|SL|SU|I(116), {0x1f03, 0x03b9}}}, + {0x1f8c, {2|F|IT|SL|SU|I(121), {0x1f04, 0x03b9}}}, + {0x1f8d, {2|F|IT|SL|SU|I(126), {0x1f05, 0x03b9}}}, + {0x1f8e, {2|F|IT|SL|SU|I(131), {0x1f06, 0x03b9}}}, + {0x1f8f, {2|F|IT|SL|SU|I(136), {0x1f07, 0x03b9}}}, + {0x1f90, {2|F|ST|SU|I(141), {0x1f20, 0x03b9}}}, + {0x1f91, {2|F|ST|SU|I(144), {0x1f21, 0x03b9}}}, + {0x1f92, {2|F|ST|SU|I(147), {0x1f22, 0x03b9}}}, + {0x1f93, {2|F|ST|SU|I(150), {0x1f23, 0x03b9}}}, + {0x1f94, {2|F|ST|SU|I(153), {0x1f24, 0x03b9}}}, + {0x1f95, {2|F|ST|SU|I(156), {0x1f25, 0x03b9}}}, + {0x1f96, {2|F|ST|SU|I(159), {0x1f26, 0x03b9}}}, + {0x1f97, {2|F|ST|SU|I(162), {0x1f27, 0x03b9}}}, + {0x1f98, {2|F|IT|SL|SU|I(165), {0x1f20, 0x03b9}}}, + {0x1f99, {2|F|IT|SL|SU|I(170), {0x1f21, 0x03b9}}}, + {0x1f9a, {2|F|IT|SL|SU|I(175), {0x1f22, 0x03b9}}}, + {0x1f9b, {2|F|IT|SL|SU|I(180), {0x1f23, 0x03b9}}}, + {0x1f9c, {2|F|IT|SL|SU|I(185), {0x1f24, 0x03b9}}}, + {0x1f9d, {2|F|IT|SL|SU|I(190), {0x1f25, 0x03b9}}}, + {0x1f9e, {2|F|IT|SL|SU|I(195), {0x1f26, 0x03b9}}}, + {0x1f9f, {2|F|IT|SL|SU|I(200), {0x1f27, 0x03b9}}}, + {0x1fa0, {2|F|ST|SU|I(205), {0x1f60, 0x03b9}}}, + {0x1fa1, {2|F|ST|SU|I(208), {0x1f61, 0x03b9}}}, + {0x1fa2, {2|F|ST|SU|I(211), {0x1f62, 0x03b9}}}, + {0x1fa3, {2|F|ST|SU|I(214), {0x1f63, 0x03b9}}}, + {0x1fa4, {2|F|ST|SU|I(217), {0x1f64, 0x03b9}}}, + {0x1fa5, {2|F|ST|SU|I(220), {0x1f65, 0x03b9}}}, + {0x1fa6, {2|F|ST|SU|I(223), {0x1f66, 0x03b9}}}, + {0x1fa7, {2|F|ST|SU|I(226), {0x1f67, 0x03b9}}}, + {0x1fa8, {2|F|IT|SL|SU|I(229), {0x1f60, 0x03b9}}}, + {0x1fa9, {2|F|IT|SL|SU|I(234), {0x1f61, 0x03b9}}}, + {0x1faa, {2|F|IT|SL|SU|I(239), {0x1f62, 0x03b9}}}, + {0x1fab, {2|F|IT|SL|SU|I(244), {0x1f63, 0x03b9}}}, + {0x1fac, {2|F|IT|SL|SU|I(249), {0x1f64, 0x03b9}}}, + {0x1fad, {2|F|IT|SL|SU|I(254), {0x1f65, 0x03b9}}}, + {0x1fae, {2|F|IT|SL|SU|I(259), {0x1f66, 0x03b9}}}, + {0x1faf, {2|F|IT|SL|SU|I(264), {0x1f67, 0x03b9}}}, + {0x1fb2, {2|F|ST|SU|I(269), {0x1f70, 0x03b9}}}, + {0x1fb3, {2|F|ST|SU|I(273), {0x03b1, 0x03b9}}}, + {0x1fb4, {2|F|ST|SU|I(276), {0x03ac, 0x03b9}}}, + {0x1fb6, {2|F|SU|I(280), {0x03b1, 0x0342}}}, + {0x1fb7, {3|F|ST|SU|I(282), {0x03b1, 0x0342, 0x03b9}}}, + {0x1fb8, {1|F|D, {0x1fb0}}}, + {0x1fb9, {1|F|D, {0x1fb1}}}, + {0x1fba, {1|F|D, {0x1f70}}}, + {0x1fbb, {1|F|D, {0x1f71}}}, + {0x1fbc, {2|F|IT|SL|SU|I(288), {0x03b1, 0x03b9}}}, + {0x1fbe, {1|F|SU|I(293), {0x03b9}}}, + {0x1fc2, {2|F|ST|SU|I(294), {0x1f74, 0x03b9}}}, + {0x1fc3, {2|F|ST|SU|I(298), {0x03b7, 0x03b9}}}, + {0x1fc4, {2|F|ST|SU|I(301), {0x03ae, 0x03b9}}}, + {0x1fc6, {2|F|SU|I(305), {0x03b7, 0x0342}}}, + {0x1fc7, {3|F|ST|SU|I(307), {0x03b7, 0x0342, 0x03b9}}}, + {0x1fc8, {1|F|D, {0x1f72}}}, + {0x1fc9, {1|F|D, {0x1f73}}}, + {0x1fca, {1|F|D, {0x1f74}}}, + {0x1fcb, {1|F|D, {0x1f75}}}, + {0x1fcc, {2|F|IT|SL|SU|I(313), {0x03b7, 0x03b9}}}, + {0x1fd2, {3|F|SU|I(318), {0x03b9, 0x0308, 0x0300}}}, + {0x1fd3, {3|F|SU|I(321), {0x03b9, 0x0308, 0x0301}}}, + {0x1fd6, {2|F|SU|I(324), {0x03b9, 0x0342}}}, + {0x1fd7, {3|F|SU|I(326), {0x03b9, 0x0308, 0x0342}}}, + {0x1fd8, {1|F|D, {0x1fd0}}}, + {0x1fd9, {1|F|D, {0x1fd1}}}, + {0x1fda, {1|F|D, {0x1f76}}}, + {0x1fdb, {1|F|D, {0x1f77}}}, + {0x1fe2, {3|F|SU|I(329), {0x03c5, 0x0308, 0x0300}}}, + {0x1fe3, {3|F|SU|I(332), {0x03c5, 0x0308, 0x0301}}}, + {0x1fe4, {2|F|SU|I(335), {0x03c1, 0x0313}}}, + {0x1fe6, {2|F|SU|I(337), {0x03c5, 0x0342}}}, + {0x1fe7, {3|F|SU|I(339), {0x03c5, 0x0308, 0x0342}}}, + {0x1fe8, {1|F|D, {0x1fe0}}}, + {0x1fe9, {1|F|D, {0x1fe1}}}, + {0x1fea, {1|F|D, {0x1f7a}}}, + {0x1feb, {1|F|D, {0x1f7b}}}, + {0x1fec, {1|F|D, {0x1fe5}}}, + {0x1ff2, {2|F|ST|SU|I(342), {0x1f7c, 0x03b9}}}, + {0x1ff3, {2|F|ST|SU|I(346), {0x03c9, 0x03b9}}}, + {0x1ff4, {2|F|ST|SU|I(349), {0x03ce, 0x03b9}}}, + {0x1ff6, {2|F|SU|I(353), {0x03c9, 0x0342}}}, + {0x1ff7, {3|F|ST|SU|I(355), {0x03c9, 0x0342, 0x03b9}}}, + {0x1ff8, {1|F|D, {0x1f78}}}, + {0x1ff9, {1|F|D, {0x1f79}}}, + {0x1ffa, {1|F|D, {0x1f7c}}}, + {0x1ffb, {1|F|D, {0x1f7d}}}, + {0x1ffc, {2|F|IT|SL|SU|I(361), {0x03c9, 0x03b9}}}, + {0x2126, {1|F|D, {0x03c9}}}, + {0x212a, {1|F|D, {0x006b}}}, + {0x212b, {1|F|D, {0x00e5}}}, + {0x2132, {1|F|D, {0x214e}}}, + {0x2160, {1|F|D, {0x2170}}}, + {0x2161, {1|F|D, {0x2171}}}, + {0x2162, {1|F|D, {0x2172}}}, + {0x2163, {1|F|D, {0x2173}}}, + {0x2164, {1|F|D, {0x2174}}}, + {0x2165, {1|F|D, {0x2175}}}, + {0x2166, {1|F|D, {0x2176}}}, + {0x2167, {1|F|D, {0x2177}}}, + {0x2168, {1|F|D, {0x2178}}}, + {0x2169, {1|F|D, {0x2179}}}, + {0x216a, {1|F|D, {0x217a}}}, + {0x216b, {1|F|D, {0x217b}}}, + {0x216c, {1|F|D, {0x217c}}}, + {0x216d, {1|F|D, {0x217d}}}, + {0x216e, {1|F|D, {0x217e}}}, + {0x216f, {1|F|D, {0x217f}}}, + {0x2183, {1|F|D, {0x2184}}}, + {0x24b6, {1|F|D, {0x24d0}}}, + {0x24b7, {1|F|D, {0x24d1}}}, + {0x24b8, {1|F|D, {0x24d2}}}, + {0x24b9, {1|F|D, {0x24d3}}}, + {0x24ba, {1|F|D, {0x24d4}}}, + {0x24bb, {1|F|D, {0x24d5}}}, + {0x24bc, {1|F|D, {0x24d6}}}, + {0x24bd, {1|F|D, {0x24d7}}}, + {0x24be, {1|F|D, {0x24d8}}}, + {0x24bf, {1|F|D, {0x24d9}}}, + {0x24c0, {1|F|D, {0x24da}}}, + {0x24c1, {1|F|D, {0x24db}}}, + {0x24c2, {1|F|D, {0x24dc}}}, + {0x24c3, {1|F|D, {0x24dd}}}, + {0x24c4, {1|F|D, {0x24de}}}, + {0x24c5, {1|F|D, {0x24df}}}, + {0x24c6, {1|F|D, {0x24e0}}}, + {0x24c7, {1|F|D, {0x24e1}}}, + {0x24c8, {1|F|D, {0x24e2}}}, + {0x24c9, {1|F|D, {0x24e3}}}, + {0x24ca, {1|F|D, {0x24e4}}}, + {0x24cb, {1|F|D, {0x24e5}}}, + {0x24cc, {1|F|D, {0x24e6}}}, + {0x24cd, {1|F|D, {0x24e7}}}, + {0x24ce, {1|F|D, {0x24e8}}}, + {0x24cf, {1|F|D, {0x24e9}}}, + {0x2c00, {1|F|D, {0x2c30}}}, + {0x2c01, {1|F|D, {0x2c31}}}, + {0x2c02, {1|F|D, {0x2c32}}}, + {0x2c03, {1|F|D, {0x2c33}}}, + {0x2c04, {1|F|D, {0x2c34}}}, + {0x2c05, {1|F|D, {0x2c35}}}, + {0x2c06, {1|F|D, {0x2c36}}}, + {0x2c07, {1|F|D, {0x2c37}}}, + {0x2c08, {1|F|D, {0x2c38}}}, + {0x2c09, {1|F|D, {0x2c39}}}, + {0x2c0a, {1|F|D, {0x2c3a}}}, + {0x2c0b, {1|F|D, {0x2c3b}}}, + {0x2c0c, {1|F|D, {0x2c3c}}}, + {0x2c0d, {1|F|D, {0x2c3d}}}, + {0x2c0e, {1|F|D, {0x2c3e}}}, + {0x2c0f, {1|F|D, {0x2c3f}}}, + {0x2c10, {1|F|D, {0x2c40}}}, + {0x2c11, {1|F|D, {0x2c41}}}, + {0x2c12, {1|F|D, {0x2c42}}}, + {0x2c13, {1|F|D, {0x2c43}}}, + {0x2c14, {1|F|D, {0x2c44}}}, + {0x2c15, {1|F|D, {0x2c45}}}, + {0x2c16, {1|F|D, {0x2c46}}}, + {0x2c17, {1|F|D, {0x2c47}}}, + {0x2c18, {1|F|D, {0x2c48}}}, + {0x2c19, {1|F|D, {0x2c49}}}, + {0x2c1a, {1|F|D, {0x2c4a}}}, + {0x2c1b, {1|F|D, {0x2c4b}}}, + {0x2c1c, {1|F|D, {0x2c4c}}}, + {0x2c1d, {1|F|D, {0x2c4d}}}, + {0x2c1e, {1|F|D, {0x2c4e}}}, + {0x2c1f, {1|F|D, {0x2c4f}}}, + {0x2c20, {1|F|D, {0x2c50}}}, + {0x2c21, {1|F|D, {0x2c51}}}, + {0x2c22, {1|F|D, {0x2c52}}}, + {0x2c23, {1|F|D, {0x2c53}}}, + {0x2c24, {1|F|D, {0x2c54}}}, + {0x2c25, {1|F|D, {0x2c55}}}, + {0x2c26, {1|F|D, {0x2c56}}}, + {0x2c27, {1|F|D, {0x2c57}}}, + {0x2c28, {1|F|D, {0x2c58}}}, + {0x2c29, {1|F|D, {0x2c59}}}, + {0x2c2a, {1|F|D, {0x2c5a}}}, + {0x2c2b, {1|F|D, {0x2c5b}}}, + {0x2c2c, {1|F|D, {0x2c5c}}}, + {0x2c2d, {1|F|D, {0x2c5d}}}, + {0x2c2e, {1|F|D, {0x2c5e}}}, + {0x2c2f, {1|F|D, {0x2c5f}}}, + {0x2c60, {1|F|D, {0x2c61}}}, + {0x2c62, {1|F|D, {0x026b}}}, + {0x2c63, {1|F|D, {0x1d7d}}}, + {0x2c64, {1|F|D, {0x027d}}}, + {0x2c67, {1|F|D, {0x2c68}}}, + {0x2c69, {1|F|D, {0x2c6a}}}, + {0x2c6b, {1|F|D, {0x2c6c}}}, + {0x2c6d, {1|F|D, {0x0251}}}, + {0x2c6e, {1|F|D, {0x0271}}}, + {0x2c6f, {1|F|D, {0x0250}}}, + {0x2c70, {1|F|D, {0x0252}}}, + {0x2c72, {1|F|D, {0x2c73}}}, + {0x2c75, {1|F|D, {0x2c76}}}, + {0x2c7e, {1|F|D, {0x023f}}}, + {0x2c7f, {1|F|D, {0x0240}}}, + {0x2c80, {1|F|D, {0x2c81}}}, + {0x2c82, {1|F|D, {0x2c83}}}, + {0x2c84, {1|F|D, {0x2c85}}}, + {0x2c86, {1|F|D, {0x2c87}}}, + {0x2c88, {1|F|D, {0x2c89}}}, + {0x2c8a, {1|F|D, {0x2c8b}}}, + {0x2c8c, {1|F|D, {0x2c8d}}}, + {0x2c8e, {1|F|D, {0x2c8f}}}, + {0x2c90, {1|F|D, {0x2c91}}}, + {0x2c92, {1|F|D, {0x2c93}}}, + {0x2c94, {1|F|D, {0x2c95}}}, + {0x2c96, {1|F|D, {0x2c97}}}, + {0x2c98, {1|F|D, {0x2c99}}}, + {0x2c9a, {1|F|D, {0x2c9b}}}, + {0x2c9c, {1|F|D, {0x2c9d}}}, + {0x2c9e, {1|F|D, {0x2c9f}}}, + {0x2ca0, {1|F|D, {0x2ca1}}}, + {0x2ca2, {1|F|D, {0x2ca3}}}, + {0x2ca4, {1|F|D, {0x2ca5}}}, + {0x2ca6, {1|F|D, {0x2ca7}}}, + {0x2ca8, {1|F|D, {0x2ca9}}}, + {0x2caa, {1|F|D, {0x2cab}}}, + {0x2cac, {1|F|D, {0x2cad}}}, + {0x2cae, {1|F|D, {0x2caf}}}, + {0x2cb0, {1|F|D, {0x2cb1}}}, + {0x2cb2, {1|F|D, {0x2cb3}}}, + {0x2cb4, {1|F|D, {0x2cb5}}}, + {0x2cb6, {1|F|D, {0x2cb7}}}, + {0x2cb8, {1|F|D, {0x2cb9}}}, + {0x2cba, {1|F|D, {0x2cbb}}}, + {0x2cbc, {1|F|D, {0x2cbd}}}, + {0x2cbe, {1|F|D, {0x2cbf}}}, + {0x2cc0, {1|F|D, {0x2cc1}}}, + {0x2cc2, {1|F|D, {0x2cc3}}}, + {0x2cc4, {1|F|D, {0x2cc5}}}, + {0x2cc6, {1|F|D, {0x2cc7}}}, + {0x2cc8, {1|F|D, {0x2cc9}}}, + {0x2cca, {1|F|D, {0x2ccb}}}, + {0x2ccc, {1|F|D, {0x2ccd}}}, + {0x2cce, {1|F|D, {0x2ccf}}}, + {0x2cd0, {1|F|D, {0x2cd1}}}, + {0x2cd2, {1|F|D, {0x2cd3}}}, + {0x2cd4, {1|F|D, {0x2cd5}}}, + {0x2cd6, {1|F|D, {0x2cd7}}}, + {0x2cd8, {1|F|D, {0x2cd9}}}, + {0x2cda, {1|F|D, {0x2cdb}}}, + {0x2cdc, {1|F|D, {0x2cdd}}}, + {0x2cde, {1|F|D, {0x2cdf}}}, + {0x2ce0, {1|F|D, {0x2ce1}}}, + {0x2ce2, {1|F|D, {0x2ce3}}}, + {0x2ceb, {1|F|D, {0x2cec}}}, + {0x2ced, {1|F|D, {0x2cee}}}, + {0x2cf2, {1|F|D, {0x2cf3}}}, + {0xa640, {1|F|D, {0xa641}}}, + {0xa642, {1|F|D, {0xa643}}}, + {0xa644, {1|F|D, {0xa645}}}, + {0xa646, {1|F|D, {0xa647}}}, + {0xa648, {1|F|D, {0xa649}}}, + {0xa64a, {1|F|D, {0xa64b}}}, + {0xa64c, {1|F|D, {0xa64d}}}, + {0xa64e, {1|F|D, {0xa64f}}}, + {0xa650, {1|F|D, {0xa651}}}, + {0xa652, {1|F|D, {0xa653}}}, + {0xa654, {1|F|D, {0xa655}}}, + {0xa656, {1|F|D, {0xa657}}}, + {0xa658, {1|F|D, {0xa659}}}, + {0xa65a, {1|F|D, {0xa65b}}}, + {0xa65c, {1|F|D, {0xa65d}}}, + {0xa65e, {1|F|D, {0xa65f}}}, + {0xa660, {1|F|D, {0xa661}}}, + {0xa662, {1|F|D, {0xa663}}}, + {0xa664, {1|F|D, {0xa665}}}, + {0xa666, {1|F|D, {0xa667}}}, + {0xa668, {1|F|D, {0xa669}}}, + {0xa66a, {1|F|D, {0xa66b}}}, + {0xa66c, {1|F|D, {0xa66d}}}, + {0xa680, {1|F|D, {0xa681}}}, + {0xa682, {1|F|D, {0xa683}}}, + {0xa684, {1|F|D, {0xa685}}}, + {0xa686, {1|F|D, {0xa687}}}, + {0xa688, {1|F|D, {0xa689}}}, + {0xa68a, {1|F|D, {0xa68b}}}, + {0xa68c, {1|F|D, {0xa68d}}}, + {0xa68e, {1|F|D, {0xa68f}}}, + {0xa690, {1|F|D, {0xa691}}}, + {0xa692, {1|F|D, {0xa693}}}, + {0xa694, {1|F|D, {0xa695}}}, + {0xa696, {1|F|D, {0xa697}}}, + {0xa698, {1|F|D, {0xa699}}}, + {0xa69a, {1|F|D, {0xa69b}}}, + {0xa722, {1|F|D, {0xa723}}}, + {0xa724, {1|F|D, {0xa725}}}, + {0xa726, {1|F|D, {0xa727}}}, + {0xa728, {1|F|D, {0xa729}}}, + {0xa72a, {1|F|D, {0xa72b}}}, + {0xa72c, {1|F|D, {0xa72d}}}, + {0xa72e, {1|F|D, {0xa72f}}}, + {0xa732, {1|F|D, {0xa733}}}, + {0xa734, {1|F|D, {0xa735}}}, + {0xa736, {1|F|D, {0xa737}}}, + {0xa738, {1|F|D, {0xa739}}}, + {0xa73a, {1|F|D, {0xa73b}}}, + {0xa73c, {1|F|D, {0xa73d}}}, + {0xa73e, {1|F|D, {0xa73f}}}, + {0xa740, {1|F|D, {0xa741}}}, + {0xa742, {1|F|D, {0xa743}}}, + {0xa744, {1|F|D, {0xa745}}}, + {0xa746, {1|F|D, {0xa747}}}, + {0xa748, {1|F|D, {0xa749}}}, + {0xa74a, {1|F|D, {0xa74b}}}, + {0xa74c, {1|F|D, {0xa74d}}}, + {0xa74e, {1|F|D, {0xa74f}}}, + {0xa750, {1|F|D, {0xa751}}}, + {0xa752, {1|F|D, {0xa753}}}, + {0xa754, {1|F|D, {0xa755}}}, + {0xa756, {1|F|D, {0xa757}}}, + {0xa758, {1|F|D, {0xa759}}}, + {0xa75a, {1|F|D, {0xa75b}}}, + {0xa75c, {1|F|D, {0xa75d}}}, + {0xa75e, {1|F|D, {0xa75f}}}, + {0xa760, {1|F|D, {0xa761}}}, + {0xa762, {1|F|D, {0xa763}}}, + {0xa764, {1|F|D, {0xa765}}}, + {0xa766, {1|F|D, {0xa767}}}, + {0xa768, {1|F|D, {0xa769}}}, + {0xa76a, {1|F|D, {0xa76b}}}, + {0xa76c, {1|F|D, {0xa76d}}}, + {0xa76e, {1|F|D, {0xa76f}}}, + {0xa779, {1|F|D, {0xa77a}}}, + {0xa77b, {1|F|D, {0xa77c}}}, + {0xa77d, {1|F|D, {0x1d79}}}, + {0xa77e, {1|F|D, {0xa77f}}}, + {0xa780, {1|F|D, {0xa781}}}, + {0xa782, {1|F|D, {0xa783}}}, + {0xa784, {1|F|D, {0xa785}}}, + {0xa786, {1|F|D, {0xa787}}}, + {0xa78b, {1|F|D, {0xa78c}}}, + {0xa78d, {1|F|D, {0x0265}}}, + {0xa790, {1|F|D, {0xa791}}}, + {0xa792, {1|F|D, {0xa793}}}, + {0xa796, {1|F|D, {0xa797}}}, + {0xa798, {1|F|D, {0xa799}}}, + {0xa79a, {1|F|D, {0xa79b}}}, + {0xa79c, {1|F|D, {0xa79d}}}, + {0xa79e, {1|F|D, {0xa79f}}}, + {0xa7a0, {1|F|D, {0xa7a1}}}, + {0xa7a2, {1|F|D, {0xa7a3}}}, + {0xa7a4, {1|F|D, {0xa7a5}}}, + {0xa7a6, {1|F|D, {0xa7a7}}}, + {0xa7a8, {1|F|D, {0xa7a9}}}, + {0xa7aa, {1|F|D, {0x0266}}}, + {0xa7ab, {1|F|D, {0x025c}}}, + {0xa7ac, {1|F|D, {0x0261}}}, + {0xa7ad, {1|F|D, {0x026c}}}, + {0xa7ae, {1|F|D, {0x026a}}}, + {0xa7b0, {1|F|D, {0x029e}}}, + {0xa7b1, {1|F|D, {0x0287}}}, + {0xa7b2, {1|F|D, {0x029d}}}, + {0xa7b3, {1|F|D, {0xab53}}}, + {0xa7b4, {1|F|D, {0xa7b5}}}, + {0xa7b6, {1|F|D, {0xa7b7}}}, + {0xa7b8, {1|F|D, {0xa7b9}}}, + {0xa7ba, {1|F|D, {0xa7bb}}}, + {0xa7bc, {1|F|D, {0xa7bd}}}, + {0xa7be, {1|F|D, {0xa7bf}}}, + {0xa7c0, {1|F|D, {0xa7c1}}}, + {0xa7c2, {1|F|D, {0xa7c3}}}, + {0xa7c4, {1|F|D, {0xa794}}}, + {0xa7c5, {1|F|D, {0x0282}}}, + {0xa7c6, {1|F|D, {0x1d8e}}}, + {0xa7c7, {1|F|D, {0xa7c8}}}, + {0xa7c9, {1|F|D, {0xa7ca}}}, + {0xa7cb, {1|F|D, {0x0264}}}, + {0xa7cc, {1|F|D, {0xa7cd}}}, + {0xa7d0, {1|F|D, {0xa7d1}}}, + {0xa7d6, {1|F|D, {0xa7d7}}}, + {0xa7d8, {1|F|D, {0xa7d9}}}, + {0xa7da, {1|F|D, {0xa7db}}}, + {0xa7dc, {1|F|D, {0x019b}}}, + {0xa7f5, {1|F|D, {0xa7f6}}}, + {0xab70, {1|F|U, {0x13a0}}}, + {0xab71, {1|F|U, {0x13a1}}}, + {0xab72, {1|F|U, {0x13a2}}}, + {0xab73, {1|F|U, {0x13a3}}}, + {0xab74, {1|F|U, {0x13a4}}}, + {0xab75, {1|F|U, {0x13a5}}}, + {0xab76, {1|F|U, {0x13a6}}}, + {0xab77, {1|F|U, {0x13a7}}}, + {0xab78, {1|F|U, {0x13a8}}}, + {0xab79, {1|F|U, {0x13a9}}}, + {0xab7a, {1|F|U, {0x13aa}}}, + {0xab7b, {1|F|U, {0x13ab}}}, + {0xab7c, {1|F|U, {0x13ac}}}, + {0xab7d, {1|F|U, {0x13ad}}}, + {0xab7e, {1|F|U, {0x13ae}}}, + {0xab7f, {1|F|U, {0x13af}}}, + {0xab80, {1|F|U, {0x13b0}}}, + {0xab81, {1|F|U, {0x13b1}}}, + {0xab82, {1|F|U, {0x13b2}}}, + {0xab83, {1|F|U, {0x13b3}}}, + {0xab84, {1|F|U, {0x13b4}}}, + {0xab85, {1|F|U, {0x13b5}}}, + {0xab86, {1|F|U, {0x13b6}}}, + {0xab87, {1|F|U, {0x13b7}}}, + {0xab88, {1|F|U, {0x13b8}}}, + {0xab89, {1|F|U, {0x13b9}}}, + {0xab8a, {1|F|U, {0x13ba}}}, + {0xab8b, {1|F|U, {0x13bb}}}, + {0xab8c, {1|F|U, {0x13bc}}}, + {0xab8d, {1|F|U, {0x13bd}}}, + {0xab8e, {1|F|U, {0x13be}}}, + {0xab8f, {1|F|U, {0x13bf}}}, + {0xab90, {1|F|U, {0x13c0}}}, + {0xab91, {1|F|U, {0x13c1}}}, + {0xab92, {1|F|U, {0x13c2}}}, + {0xab93, {1|F|U, {0x13c3}}}, + {0xab94, {1|F|U, {0x13c4}}}, + {0xab95, {1|F|U, {0x13c5}}}, + {0xab96, {1|F|U, {0x13c6}}}, + {0xab97, {1|F|U, {0x13c7}}}, + {0xab98, {1|F|U, {0x13c8}}}, + {0xab99, {1|F|U, {0x13c9}}}, + {0xab9a, {1|F|U, {0x13ca}}}, + {0xab9b, {1|F|U, {0x13cb}}}, + {0xab9c, {1|F|U, {0x13cc}}}, + {0xab9d, {1|F|U, {0x13cd}}}, + {0xab9e, {1|F|U, {0x13ce}}}, + {0xab9f, {1|F|U, {0x13cf}}}, + {0xaba0, {1|F|U, {0x13d0}}}, + {0xaba1, {1|F|U, {0x13d1}}}, + {0xaba2, {1|F|U, {0x13d2}}}, + {0xaba3, {1|F|U, {0x13d3}}}, + {0xaba4, {1|F|U, {0x13d4}}}, + {0xaba5, {1|F|U, {0x13d5}}}, + {0xaba6, {1|F|U, {0x13d6}}}, + {0xaba7, {1|F|U, {0x13d7}}}, + {0xaba8, {1|F|U, {0x13d8}}}, + {0xaba9, {1|F|U, {0x13d9}}}, + {0xabaa, {1|F|U, {0x13da}}}, + {0xabab, {1|F|U, {0x13db}}}, + {0xabac, {1|F|U, {0x13dc}}}, + {0xabad, {1|F|U, {0x13dd}}}, + {0xabae, {1|F|U, {0x13de}}}, + {0xabaf, {1|F|U, {0x13df}}}, + {0xabb0, {1|F|U, {0x13e0}}}, + {0xabb1, {1|F|U, {0x13e1}}}, + {0xabb2, {1|F|U, {0x13e2}}}, + {0xabb3, {1|F|U, {0x13e3}}}, + {0xabb4, {1|F|U, {0x13e4}}}, + {0xabb5, {1|F|U, {0x13e5}}}, + {0xabb6, {1|F|U, {0x13e6}}}, + {0xabb7, {1|F|U, {0x13e7}}}, + {0xabb8, {1|F|U, {0x13e8}}}, + {0xabb9, {1|F|U, {0x13e9}}}, + {0xabba, {1|F|U, {0x13ea}}}, + {0xabbb, {1|F|U, {0x13eb}}}, + {0xabbc, {1|F|U, {0x13ec}}}, + {0xabbd, {1|F|U, {0x13ed}}}, + {0xabbe, {1|F|U, {0x13ee}}}, + {0xabbf, {1|F|U, {0x13ef}}}, + {0xfb00, {2|F|ST|SU|I(366), {0x0066, 0x0066}}}, + {0xfb01, {2|F|ST|SU|I(370), {0x0066, 0x0069}}}, + {0xfb02, {2|F|ST|SU|I(374), {0x0066, 0x006c}}}, + {0xfb03, {3|F|ST|SU|I(378), {0x0066, 0x0066, 0x0069}}}, + {0xfb04, {3|F|ST|SU|I(384), {0x0066, 0x0066, 0x006c}}}, + {0xfb05, {2|F|ST|SU|I(390), {0x0073, 0x0074}}}, + {0xfb06, {2|F|ST|SU|I(394), {0x0073, 0x0074}}}, + {0xfb13, {2|F|ST|SU|I(398), {0x0574, 0x0576}}}, + {0xfb14, {2|F|ST|SU|I(402), {0x0574, 0x0565}}}, + {0xfb15, {2|F|ST|SU|I(406), {0x0574, 0x056b}}}, + {0xfb16, {2|F|ST|SU|I(410), {0x057e, 0x0576}}}, + {0xfb17, {2|F|ST|SU|I(414), {0x0574, 0x056d}}}, + {0xff21, {1|F|D, {0xff41}}}, + {0xff22, {1|F|D, {0xff42}}}, + {0xff23, {1|F|D, {0xff43}}}, + {0xff24, {1|F|D, {0xff44}}}, + {0xff25, {1|F|D, {0xff45}}}, + {0xff26, {1|F|D, {0xff46}}}, + {0xff27, {1|F|D, {0xff47}}}, + {0xff28, {1|F|D, {0xff48}}}, + {0xff29, {1|F|D, {0xff49}}}, + {0xff2a, {1|F|D, {0xff4a}}}, + {0xff2b, {1|F|D, {0xff4b}}}, + {0xff2c, {1|F|D, {0xff4c}}}, + {0xff2d, {1|F|D, {0xff4d}}}, + {0xff2e, {1|F|D, {0xff4e}}}, + {0xff2f, {1|F|D, {0xff4f}}}, + {0xff30, {1|F|D, {0xff50}}}, + {0xff31, {1|F|D, {0xff51}}}, + {0xff32, {1|F|D, {0xff52}}}, + {0xff33, {1|F|D, {0xff53}}}, + {0xff34, {1|F|D, {0xff54}}}, + {0xff35, {1|F|D, {0xff55}}}, + {0xff36, {1|F|D, {0xff56}}}, + {0xff37, {1|F|D, {0xff57}}}, + {0xff38, {1|F|D, {0xff58}}}, + {0xff39, {1|F|D, {0xff59}}}, + {0xff3a, {1|F|D, {0xff5a}}}, + {0x10400, {1|F|D, {0x10428}}}, + {0x10401, {1|F|D, {0x10429}}}, + {0x10402, {1|F|D, {0x1042a}}}, + {0x10403, {1|F|D, {0x1042b}}}, + {0x10404, {1|F|D, {0x1042c}}}, + {0x10405, {1|F|D, {0x1042d}}}, + {0x10406, {1|F|D, {0x1042e}}}, + {0x10407, {1|F|D, {0x1042f}}}, + {0x10408, {1|F|D, {0x10430}}}, + {0x10409, {1|F|D, {0x10431}}}, + {0x1040a, {1|F|D, {0x10432}}}, + {0x1040b, {1|F|D, {0x10433}}}, + {0x1040c, {1|F|D, {0x10434}}}, + {0x1040d, {1|F|D, {0x10435}}}, + {0x1040e, {1|F|D, {0x10436}}}, + {0x1040f, {1|F|D, {0x10437}}}, + {0x10410, {1|F|D, {0x10438}}}, + {0x10411, {1|F|D, {0x10439}}}, + {0x10412, {1|F|D, {0x1043a}}}, + {0x10413, {1|F|D, {0x1043b}}}, + {0x10414, {1|F|D, {0x1043c}}}, + {0x10415, {1|F|D, {0x1043d}}}, + {0x10416, {1|F|D, {0x1043e}}}, + {0x10417, {1|F|D, {0x1043f}}}, + {0x10418, {1|F|D, {0x10440}}}, + {0x10419, {1|F|D, {0x10441}}}, + {0x1041a, {1|F|D, {0x10442}}}, + {0x1041b, {1|F|D, {0x10443}}}, + {0x1041c, {1|F|D, {0x10444}}}, + {0x1041d, {1|F|D, {0x10445}}}, + {0x1041e, {1|F|D, {0x10446}}}, + {0x1041f, {1|F|D, {0x10447}}}, + {0x10420, {1|F|D, {0x10448}}}, + {0x10421, {1|F|D, {0x10449}}}, + {0x10422, {1|F|D, {0x1044a}}}, + {0x10423, {1|F|D, {0x1044b}}}, + {0x10424, {1|F|D, {0x1044c}}}, + {0x10425, {1|F|D, {0x1044d}}}, + {0x10426, {1|F|D, {0x1044e}}}, + {0x10427, {1|F|D, {0x1044f}}}, + {0x104b0, {1|F|D, {0x104d8}}}, + {0x104b1, {1|F|D, {0x104d9}}}, + {0x104b2, {1|F|D, {0x104da}}}, + {0x104b3, {1|F|D, {0x104db}}}, + {0x104b4, {1|F|D, {0x104dc}}}, + {0x104b5, {1|F|D, {0x104dd}}}, + {0x104b6, {1|F|D, {0x104de}}}, + {0x104b7, {1|F|D, {0x104df}}}, + {0x104b8, {1|F|D, {0x104e0}}}, + {0x104b9, {1|F|D, {0x104e1}}}, + {0x104ba, {1|F|D, {0x104e2}}}, + {0x104bb, {1|F|D, {0x104e3}}}, + {0x104bc, {1|F|D, {0x104e4}}}, + {0x104bd, {1|F|D, {0x104e5}}}, + {0x104be, {1|F|D, {0x104e6}}}, + {0x104bf, {1|F|D, {0x104e7}}}, + {0x104c0, {1|F|D, {0x104e8}}}, + {0x104c1, {1|F|D, {0x104e9}}}, + {0x104c2, {1|F|D, {0x104ea}}}, + {0x104c3, {1|F|D, {0x104eb}}}, + {0x104c4, {1|F|D, {0x104ec}}}, + {0x104c5, {1|F|D, {0x104ed}}}, + {0x104c6, {1|F|D, {0x104ee}}}, + {0x104c7, {1|F|D, {0x104ef}}}, + {0x104c8, {1|F|D, {0x104f0}}}, + {0x104c9, {1|F|D, {0x104f1}}}, + {0x104ca, {1|F|D, {0x104f2}}}, + {0x104cb, {1|F|D, {0x104f3}}}, + {0x104cc, {1|F|D, {0x104f4}}}, + {0x104cd, {1|F|D, {0x104f5}}}, + {0x104ce, {1|F|D, {0x104f6}}}, + {0x104cf, {1|F|D, {0x104f7}}}, + {0x104d0, {1|F|D, {0x104f8}}}, + {0x104d1, {1|F|D, {0x104f9}}}, + {0x104d2, {1|F|D, {0x104fa}}}, + {0x104d3, {1|F|D, {0x104fb}}}, + {0x10570, {1|F|D, {0x10597}}}, + {0x10571, {1|F|D, {0x10598}}}, + {0x10572, {1|F|D, {0x10599}}}, + {0x10573, {1|F|D, {0x1059a}}}, + {0x10574, {1|F|D, {0x1059b}}}, + {0x10575, {1|F|D, {0x1059c}}}, + {0x10576, {1|F|D, {0x1059d}}}, + {0x10577, {1|F|D, {0x1059e}}}, + {0x10578, {1|F|D, {0x1059f}}}, + {0x10579, {1|F|D, {0x105a0}}}, + {0x1057a, {1|F|D, {0x105a1}}}, + {0x1057c, {1|F|D, {0x105a3}}}, + {0x1057d, {1|F|D, {0x105a4}}}, + {0x1057e, {1|F|D, {0x105a5}}}, + {0x1057f, {1|F|D, {0x105a6}}}, + {0x10580, {1|F|D, {0x105a7}}}, + {0x10581, {1|F|D, {0x105a8}}}, + {0x10582, {1|F|D, {0x105a9}}}, + {0x10583, {1|F|D, {0x105aa}}}, + {0x10584, {1|F|D, {0x105ab}}}, + {0x10585, {1|F|D, {0x105ac}}}, + {0x10586, {1|F|D, {0x105ad}}}, + {0x10587, {1|F|D, {0x105ae}}}, + {0x10588, {1|F|D, {0x105af}}}, + {0x10589, {1|F|D, {0x105b0}}}, + {0x1058a, {1|F|D, {0x105b1}}}, + {0x1058c, {1|F|D, {0x105b3}}}, + {0x1058d, {1|F|D, {0x105b4}}}, + {0x1058e, {1|F|D, {0x105b5}}}, + {0x1058f, {1|F|D, {0x105b6}}}, + {0x10590, {1|F|D, {0x105b7}}}, + {0x10591, {1|F|D, {0x105b8}}}, + {0x10592, {1|F|D, {0x105b9}}}, + {0x10594, {1|F|D, {0x105bb}}}, + {0x10595, {1|F|D, {0x105bc}}}, + {0x10c80, {1|F|D, {0x10cc0}}}, + {0x10c81, {1|F|D, {0x10cc1}}}, + {0x10c82, {1|F|D, {0x10cc2}}}, + {0x10c83, {1|F|D, {0x10cc3}}}, + {0x10c84, {1|F|D, {0x10cc4}}}, + {0x10c85, {1|F|D, {0x10cc5}}}, + {0x10c86, {1|F|D, {0x10cc6}}}, + {0x10c87, {1|F|D, {0x10cc7}}}, + {0x10c88, {1|F|D, {0x10cc8}}}, + {0x10c89, {1|F|D, {0x10cc9}}}, + {0x10c8a, {1|F|D, {0x10cca}}}, + {0x10c8b, {1|F|D, {0x10ccb}}}, + {0x10c8c, {1|F|D, {0x10ccc}}}, + {0x10c8d, {1|F|D, {0x10ccd}}}, + {0x10c8e, {1|F|D, {0x10cce}}}, + {0x10c8f, {1|F|D, {0x10ccf}}}, + {0x10c90, {1|F|D, {0x10cd0}}}, + {0x10c91, {1|F|D, {0x10cd1}}}, + {0x10c92, {1|F|D, {0x10cd2}}}, + {0x10c93, {1|F|D, {0x10cd3}}}, + {0x10c94, {1|F|D, {0x10cd4}}}, + {0x10c95, {1|F|D, {0x10cd5}}}, + {0x10c96, {1|F|D, {0x10cd6}}}, + {0x10c97, {1|F|D, {0x10cd7}}}, + {0x10c98, {1|F|D, {0x10cd8}}}, + {0x10c99, {1|F|D, {0x10cd9}}}, + {0x10c9a, {1|F|D, {0x10cda}}}, + {0x10c9b, {1|F|D, {0x10cdb}}}, + {0x10c9c, {1|F|D, {0x10cdc}}}, + {0x10c9d, {1|F|D, {0x10cdd}}}, + {0x10c9e, {1|F|D, {0x10cde}}}, + {0x10c9f, {1|F|D, {0x10cdf}}}, + {0x10ca0, {1|F|D, {0x10ce0}}}, + {0x10ca1, {1|F|D, {0x10ce1}}}, + {0x10ca2, {1|F|D, {0x10ce2}}}, + {0x10ca3, {1|F|D, {0x10ce3}}}, + {0x10ca4, {1|F|D, {0x10ce4}}}, + {0x10ca5, {1|F|D, {0x10ce5}}}, + {0x10ca6, {1|F|D, {0x10ce6}}}, + {0x10ca7, {1|F|D, {0x10ce7}}}, + {0x10ca8, {1|F|D, {0x10ce8}}}, + {0x10ca9, {1|F|D, {0x10ce9}}}, + {0x10caa, {1|F|D, {0x10cea}}}, + {0x10cab, {1|F|D, {0x10ceb}}}, + {0x10cac, {1|F|D, {0x10cec}}}, + {0x10cad, {1|F|D, {0x10ced}}}, + {0x10cae, {1|F|D, {0x10cee}}}, + {0x10caf, {1|F|D, {0x10cef}}}, + {0x10cb0, {1|F|D, {0x10cf0}}}, + {0x10cb1, {1|F|D, {0x10cf1}}}, + {0x10cb2, {1|F|D, {0x10cf2}}}, + {0x10d50, {1|F|D, {0x10d70}}}, + {0x10d51, {1|F|D, {0x10d71}}}, + {0x10d52, {1|F|D, {0x10d72}}}, + {0x10d53, {1|F|D, {0x10d73}}}, + {0x10d54, {1|F|D, {0x10d74}}}, + {0x10d55, {1|F|D, {0x10d75}}}, + {0x10d56, {1|F|D, {0x10d76}}}, + {0x10d57, {1|F|D, {0x10d77}}}, + {0x10d58, {1|F|D, {0x10d78}}}, + {0x10d59, {1|F|D, {0x10d79}}}, + {0x10d5a, {1|F|D, {0x10d7a}}}, + {0x10d5b, {1|F|D, {0x10d7b}}}, + {0x10d5c, {1|F|D, {0x10d7c}}}, + {0x10d5d, {1|F|D, {0x10d7d}}}, + {0x10d5e, {1|F|D, {0x10d7e}}}, + {0x10d5f, {1|F|D, {0x10d7f}}}, + {0x10d60, {1|F|D, {0x10d80}}}, + {0x10d61, {1|F|D, {0x10d81}}}, + {0x10d62, {1|F|D, {0x10d82}}}, + {0x10d63, {1|F|D, {0x10d83}}}, + {0x10d64, {1|F|D, {0x10d84}}}, + {0x10d65, {1|F|D, {0x10d85}}}, + {0x118a0, {1|F|D, {0x118c0}}}, + {0x118a1, {1|F|D, {0x118c1}}}, + {0x118a2, {1|F|D, {0x118c2}}}, + {0x118a3, {1|F|D, {0x118c3}}}, + {0x118a4, {1|F|D, {0x118c4}}}, + {0x118a5, {1|F|D, {0x118c5}}}, + {0x118a6, {1|F|D, {0x118c6}}}, + {0x118a7, {1|F|D, {0x118c7}}}, + {0x118a8, {1|F|D, {0x118c8}}}, + {0x118a9, {1|F|D, {0x118c9}}}, + {0x118aa, {1|F|D, {0x118ca}}}, + {0x118ab, {1|F|D, {0x118cb}}}, + {0x118ac, {1|F|D, {0x118cc}}}, + {0x118ad, {1|F|D, {0x118cd}}}, + {0x118ae, {1|F|D, {0x118ce}}}, + {0x118af, {1|F|D, {0x118cf}}}, + {0x118b0, {1|F|D, {0x118d0}}}, + {0x118b1, {1|F|D, {0x118d1}}}, + {0x118b2, {1|F|D, {0x118d2}}}, + {0x118b3, {1|F|D, {0x118d3}}}, + {0x118b4, {1|F|D, {0x118d4}}}, + {0x118b5, {1|F|D, {0x118d5}}}, + {0x118b6, {1|F|D, {0x118d6}}}, + {0x118b7, {1|F|D, {0x118d7}}}, + {0x118b8, {1|F|D, {0x118d8}}}, + {0x118b9, {1|F|D, {0x118d9}}}, + {0x118ba, {1|F|D, {0x118da}}}, + {0x118bb, {1|F|D, {0x118db}}}, + {0x118bc, {1|F|D, {0x118dc}}}, + {0x118bd, {1|F|D, {0x118dd}}}, + {0x118be, {1|F|D, {0x118de}}}, + {0x118bf, {1|F|D, {0x118df}}}, + {0x16e40, {1|F|D, {0x16e60}}}, + {0x16e41, {1|F|D, {0x16e61}}}, + {0x16e42, {1|F|D, {0x16e62}}}, + {0x16e43, {1|F|D, {0x16e63}}}, + {0x16e44, {1|F|D, {0x16e64}}}, + {0x16e45, {1|F|D, {0x16e65}}}, + {0x16e46, {1|F|D, {0x16e66}}}, + {0x16e47, {1|F|D, {0x16e67}}}, + {0x16e48, {1|F|D, {0x16e68}}}, + {0x16e49, {1|F|D, {0x16e69}}}, + {0x16e4a, {1|F|D, {0x16e6a}}}, + {0x16e4b, {1|F|D, {0x16e6b}}}, + {0x16e4c, {1|F|D, {0x16e6c}}}, + {0x16e4d, {1|F|D, {0x16e6d}}}, + {0x16e4e, {1|F|D, {0x16e6e}}}, + {0x16e4f, {1|F|D, {0x16e6f}}}, + {0x16e50, {1|F|D, {0x16e70}}}, + {0x16e51, {1|F|D, {0x16e71}}}, + {0x16e52, {1|F|D, {0x16e72}}}, + {0x16e53, {1|F|D, {0x16e73}}}, + {0x16e54, {1|F|D, {0x16e74}}}, + {0x16e55, {1|F|D, {0x16e75}}}, + {0x16e56, {1|F|D, {0x16e76}}}, + {0x16e57, {1|F|D, {0x16e77}}}, + {0x16e58, {1|F|D, {0x16e78}}}, + {0x16e59, {1|F|D, {0x16e79}}}, + {0x16e5a, {1|F|D, {0x16e7a}}}, + {0x16e5b, {1|F|D, {0x16e7b}}}, + {0x16e5c, {1|F|D, {0x16e7c}}}, + {0x16e5d, {1|F|D, {0x16e7d}}}, + {0x16e5e, {1|F|D, {0x16e7e}}}, + {0x16e5f, {1|F|D, {0x16e7f}}}, + {0x1e900, {1|F|D, {0x1e922}}}, + {0x1e901, {1|F|D, {0x1e923}}}, + {0x1e902, {1|F|D, {0x1e924}}}, + {0x1e903, {1|F|D, {0x1e925}}}, + {0x1e904, {1|F|D, {0x1e926}}}, + {0x1e905, {1|F|D, {0x1e927}}}, + {0x1e906, {1|F|D, {0x1e928}}}, + {0x1e907, {1|F|D, {0x1e929}}}, + {0x1e908, {1|F|D, {0x1e92a}}}, + {0x1e909, {1|F|D, {0x1e92b}}}, + {0x1e90a, {1|F|D, {0x1e92c}}}, + {0x1e90b, {1|F|D, {0x1e92d}}}, + {0x1e90c, {1|F|D, {0x1e92e}}}, + {0x1e90d, {1|F|D, {0x1e92f}}}, + {0x1e90e, {1|F|D, {0x1e930}}}, + {0x1e90f, {1|F|D, {0x1e931}}}, + {0x1e910, {1|F|D, {0x1e932}}}, + {0x1e911, {1|F|D, {0x1e933}}}, + {0x1e912, {1|F|D, {0x1e934}}}, + {0x1e913, {1|F|D, {0x1e935}}}, + {0x1e914, {1|F|D, {0x1e936}}}, + {0x1e915, {1|F|D, {0x1e937}}}, + {0x1e916, {1|F|D, {0x1e938}}}, + {0x1e917, {1|F|D, {0x1e939}}}, + {0x1e918, {1|F|D, {0x1e93a}}}, + {0x1e919, {1|F|D, {0x1e93b}}}, + {0x1e91a, {1|F|D, {0x1e93c}}}, + {0x1e91b, {1|F|D, {0x1e93d}}}, + {0x1e91c, {1|F|D, {0x1e93e}}}, + {0x1e91d, {1|F|D, {0x1e93f}}}, + {0x1e91e, {1|F|D, {0x1e940}}}, + {0x1e91f, {1|F|D, {0x1e941}}}, + {0x1e920, {1|F|D, {0x1e942}}}, + {0x1e921, {1|F|D, {0x1e943}}}, +#define CaseFold_Locale (*(CaseFold_11_Type (*)[2])(CaseFold_11_Table+1555)) + {0x0049, {1|F|D, {0x0069}}}, + {0x0130, {2|F|D, {0x0069, 0x0307}}}, +}; + +/* ANSI-C code produced by gperf version 3.1 */ +/* Command-line: gperf -7 -k1,2,3 -F,-1 -c -j1 -i1 -t -T -E -C -H onigenc_unicode_CaseFold_11_hash -N onigenc_unicode_CaseFold_11_lookup -n */ + +/* maximum key range = 3358, duplicates = 0 */ + +#ifdef __GNUC__ +__inline +#else +#ifdef __cplusplus +inline +#endif +#endif +/*ARGSUSED*/ +static unsigned int +onigenc_unicode_CaseFold_11_hash(const OnigCodePoint code) +{ + static const unsigned short asso_values[] = + { + 2, 271, 6, 43, 1, 1, 64, 14, 5, 396, + 239, 791, 3364, 3364, 3364, 3364, 3364, 3364, 3364, 3364, + 3364, 3364, 3364, 3364, 3364, 45, 553, 3364, 3364, 3364, + 3364, 3364, 3364, 400, 3364, 3364, 3364, 3364, 3364, 11, + 3364, 3364, 3364, 3364, 3364, 3364, 3364, 3364, 3364, 500, + 3364, 3364, 3364, 3364, 3364, 3364, 3364, 163, 3364, 3364, + 311, 310, 445, 3, 3364, 3364, 129, 15, 3364, 3364, + 3364, 3364, 3364, 410, 3364, 3364, 400, 863, 428, 38, + 2012, 226, 42, 182, 2175, 94, 1252, 7, 12, 24, + 2080, 764, 1166, 684, 1635, 168, 1891, 308, 1977, 153, + 1790, 108, 1520, 261, 1811, 426, 1766, 484, 1720, 506, + 2127, 286, 1445, 411, 1715, 366, 1703, 352, 60, 667, + 1428, 551, 1322, 611, 1650, 597, 631, 614, 1994, 691, + 82, 876, 1670, 870, 1699, 707, 1301, 542, 1886, 816, + 1751, 822, 1813, 1101, 1662, 1117, 3, 1003, 1187, 1134, + 1275, 989, 1600, 933, 1567, 925, 1764, 1197, 1051, 843, + 1847, 1034, 212, 1071, 1244, 1020, 85, 1143, 30, 942, + 17, 1478, 308, 1394, 203, 1476, 26, 1347, 178, 1380, + 24, 1629, 104, 1574, 123, 1553, 520, 1547, 122, 1608, + 2, 135, 38, 1613, 55, 1826, 206, 1996, 281, 2105, + 488, 1794, 348, 1917, 368, 1655, 235 + }; + return asso_values[bits_of(code, 2)+79] + asso_values[bits_of(code, 1)] + asso_values[bits_of(code, 0)]; +} + +static const CodePointList3 * +onigenc_unicode_CaseFold_11_lookup(const OnigCodePoint code) +{ + enum + { + MIN_CODE_VALUE = 0x41, + MAX_CODE_VALUE = 0x1e921, + TOTAL_KEYWORDS = 1557, + MIN_WORD_LENGTH = 3, + MAX_WORD_LENGTH = 3, + MIN_HASH_VALUE = 6, + MAX_HASH_VALUE = 3363 + }; + + static const short wordlist[] = + { + -1, -1, -1, -1, -1, -1, + /*0x0243*/ 221, + /*0x0043*/ 2, + /*0x1fc3*/ 828, + -1, + /*0x0208*/ 194, + /*0x0143*/ 89, + /*0x1f88*/ 776, + /*0x10408*/ 1281, + /*0x0408*/ 305, + /*0x0108*/ 61, + /*0x2c6f*/ 969, + /*0x1f89*/ 777, + /*0x10409*/ 1282, + /*0x0409*/ 306, + /*0xab88*/ 1179, + /*0x2c08*/ 920, + /*0x1fdb*/ 844, + /*0x0388*/ 235, + -1, + /*0xab89*/ 1180, + /*0x2c09*/ 921, + /*0x020a*/ 195, + /*0x0389*/ 236, + /*0x1f8a*/ 778, + /*0x1040a*/ 1283, + /*0x040a*/ 307, + /*0x010a*/ 62, + /*0x2c88*/ 979, + /*0x0059*/ 23, + /*0x1fd9*/ 842, + -1, + /*0xab8a*/ 1181, + /*0x2c0a*/ 922, + -1, + /*0x038a*/ 237, + /*0x0200*/ 190, + -1, + /*0x1f80*/ 768, + /*0x10400*/ 1273, + /*0x0400*/ 297, + /*0x0100*/ 57, + /*0x1f83*/ 771, + /*0x10403*/ 1276, + /*0x0403*/ 300, + /*0x2c8a*/ 980, + /*0xab80*/ 1171, + /*0x2c00*/ 912, + /*0x10c88*/ 1392, + /*0x03f1*/ 288, + /*0xab83*/ 1174, + /*0x2c03*/ 915, + /*0x0189*/ 126, + /*0x10c89*/ 1393, + /*0x2183*/ 885, + /*0x1ff3*/ 856, + -1, + /*0x01db*/ 170, + /*0x1e908*/ 1529, + /*0x2c80*/ 975, + /*0x1fa7*/ 807, + /*0x10427*/ 1312, + /*0x0427*/ 336, + /*0x1e909*/ 1530, + /*0x018a*/ 127, + /*0x10c8a*/ 1394, + -1, -1, + /*0xaba7*/ 1210, + /*0x2c27*/ 951, + /*0x01d9*/ 169, + /*0x03a7*/ 263, + -1, -1, -1, + /*0x1e90a*/ 1531, + -1, + /*0xa780*/ 1107, + /*0x01f1*/ 181, + /*0x10c80*/ 1384, + -1, -1, + /*0x1fb3*/ 817, + /*0x10c83*/ 1387, + /*0x0057*/ 21, + /*0x1fd7*/ 840, + -1, -1, -1, + /*0x1e900*/ 1521, + /*0xabb3*/ 1222, + -1, + /*0x0206*/ 193, + /*0x1e903*/ 1524, + /*0x1f86*/ 774, + /*0x10406*/ 1279, + /*0x0406*/ 303, + /*0x0106*/ 60, + -1, -1, + /*0x01a7*/ 145, + /*0x10ca7*/ 1423, + /*0xab86*/ 1177, + /*0x2c06*/ 918, + /*0x1fe7*/ 849, + /*0x0386*/ 234, + /*0x0216*/ 201, + -1, + /*0x1f96*/ 790, + /*0x10416*/ 1295, + /*0x0416*/ 319, + /*0x0116*/ 68, + -1, + /*0x2c67*/ 964, + -1, + /*0x2c86*/ 978, + /*0xab96*/ 1193, + /*0x2c16*/ 934, + -1, + /*0x0396*/ 247, + -1, + /*0xa7b3*/ 1133, + /*0x01b3*/ 152, + /*0x1fe9*/ 851, + -1, + /*0x01d7*/ 168, + -1, -1, + /*0x216f*/ 884, + /*0x2c96*/ 986, + -1, + /*0x2c6d*/ 967, + /*0x2c69*/ 965, + /*0xa786*/ 1110, + /*0x0186*/ 124, + /*0x10c86*/ 1390, + /*0xfb00*/ 1235, + /*0x0470*/ 353, + /*0x0170*/ 112, + -1, + /*0xfb03*/ 1238, + -1, -1, + /*0x2ced*/ 1026, + /*0x2c70*/ 970, + /*0x1e906*/ 1527, + /*0x03f0*/ 287, + /*0xa796*/ 1115, + /*0x0196*/ 135, + /*0x10c96*/ 1406, + /*0x2165*/ 874, + /*0x0214*/ 200, + /*0x2161*/ 870, + /*0x1f94*/ 788, + /*0x10414*/ 1293, + /*0x0414*/ 317, + /*0x0114*/ 67, + -1, -1, + /*0x1e916*/ 1543, + -1, + /*0xab94*/ 1191, + /*0x2c14*/ 932, + -1, + /*0x0394*/ 245, + -1, + /*0x0210*/ 198, + /*0x1c88*/ 538, + /*0x1f90*/ 784, + /*0x10410*/ 1289, + /*0x0410*/ 313, + /*0x0110*/ 65, + /*0x1c89*/ 539, + -1, + /*0x2c94*/ 985, + /*0x01f0*/ 180, + /*0xab90*/ 1187, + /*0x2c10*/ 928, + /*0x1fe3*/ 846, + /*0x0390*/ 241, + /*0x0204*/ 192, + -1, + /*0x1f84*/ 772, + /*0x10404*/ 1277, + /*0x0404*/ 301, + /*0x0104*/ 59, + -1, + /*0x2c63*/ 962, + -1, + /*0x2c90*/ 983, + /*0xab84*/ 1175, + /*0x2c04*/ 916, + /*0xfb06*/ 1241, + /*0x0194*/ 134, + /*0x10c94*/ 1404, + -1, + /*0x0370*/ 230, + -1, + /*0x1c80*/ 530, + -1, -1, -1, + /*0x1c83*/ 533, + /*0x2c84*/ 977, + /*0x1e914*/ 1541, + -1, + /*0xfb16*/ 1245, + /*0xa790*/ 1113, + /*0x0190*/ 131, + /*0x10c90*/ 1400, + -1, + /*0x0053*/ 17, + /*0x1fd3*/ 838, + -1, -1, + /*0x2c75*/ 972, + -1, + /*0x03f5*/ 290, + -1, + /*0x1e910*/ 1537, + /*0x1ca7*/ 563, + /*0xa784*/ 1109, + /*0x0184*/ 123, + /*0x10c84*/ 1388, + /*0x0202*/ 191, + -1, + /*0x1f82*/ 770, + /*0x10402*/ 1275, + /*0x0402*/ 299, + /*0x0102*/ 58, + /*0x2167*/ 876, + -1, -1, + /*0x1e904*/ 1525, + /*0xab82*/ 1173, + /*0x2c02*/ 914, + -1, -1, + /*0x017f*/ 120, + /*0x0543*/ 463, + -1, -1, + /*0x1cb3*/ 575, + /*0x0508*/ 425, + /*0x2c7f*/ 974, + /*0xa7f5*/ 1154, + /*0x03ff*/ 296, + /*0x2c82*/ 976, + /*0x216d*/ 882, + /*0x2169*/ 878, + -1, + /*0xfb14*/ 1243, + /*0x01d3*/ 166, + -1, + /*0x1c86*/ 536, + -1, -1, -1, -1, + /*0x0218*/ 202, + /*0x050a*/ 426, + /*0x1f98*/ 792, + /*0x10418*/ 1297, + /*0x0418*/ 321, + /*0x0118*/ 69, + /*0xa782*/ 1108, + /*0x0182*/ 122, + /*0x10c82*/ 1386, + /*0x1c96*/ 546, + /*0xab98*/ 1195, + /*0x2c18*/ 936, + /*0x00c3*/ 29, + /*0x0398*/ 249, + /*0x10571*/ 1350, + /*0x0500*/ 421, + -1, -1, + /*0x1e902*/ 1523, + -1, -1, + /*0xfb04*/ 1239, + /*0x1ff7*/ 859, + /*0x2c98*/ 987, + -1, + /*0x0220*/ 206, + /*0x00db*/ 52, + /*0x1fa0*/ 800, + /*0x10420*/ 1305, + /*0x0420*/ 329, + /*0x0120*/ 73, + /*0x10573*/ 1352, + -1, + /*0x03f7*/ 291, + -1, + /*0xaba0*/ 1203, + /*0x2c20*/ 944, + /*0x037f*/ 233, + /*0x03a0*/ 257, + /*0x00d9*/ 50, + -1, + /*0xa798*/ 1116, + /*0x0198*/ 137, + /*0x10c98*/ 1408, + -1, + /*0x2163*/ 872, + -1, + /*0x0212*/ 199, + /*0x2ca0*/ 991, + /*0x1f92*/ 786, + /*0x10412*/ 1291, + /*0x0412*/ 315, + /*0x0112*/ 66, + /*0x1e918*/ 1545, + /*0x1c94*/ 544, + /*0x1e88*/ 654, + /*0x1e08*/ 590, + /*0xab92*/ 1189, + /*0x2c12*/ 930, + /*0x0533*/ 447, + /*0x0392*/ 243, + -1, + /*0x01f7*/ 185, + -1, -1, + /*0xfb02*/ 1237, + /*0xa7a0*/ 1120, + /*0x01a0*/ 141, + /*0x10ca0*/ 1416, + /*0x1c90*/ 540, + /*0x2c92*/ 984, + /*0x0506*/ 424, + /*0x1e8a*/ 655, + /*0x1e0a*/ 591, + -1, -1, -1, -1, + /*0x1e920*/ 1553, + -1, -1, -1, -1, + /*0x1c84*/ 534, + -1, + /*0x0516*/ 432, + /*0x1e80*/ 650, + /*0x1e00*/ 586, + /*0xa792*/ 1114, + /*0x1ffb*/ 863, + /*0x10c92*/ 1402, + /*0x0226*/ 209, + /*0x017b*/ 118, + /*0x1fa6*/ 806, + /*0x10426*/ 1311, + /*0x0426*/ 335, + /*0x0126*/ 76, + /*0x13fb*/ 527, + -1, -1, + /*0x1e912*/ 1539, + /*0xaba6*/ 1209, + /*0x2c26*/ 950, + -1, + /*0x03a6*/ 262, + /*0x0224*/ 208, + -1, + /*0x1fa4*/ 804, + /*0x10424*/ 1309, + /*0x0424*/ 333, + /*0x0124*/ 75, + /*0x10570*/ 1349, + /*0x017d*/ 119, + -1, + /*0x2ca6*/ 994, + /*0xaba4*/ 1207, + /*0x2c24*/ 948, + /*0x13fd*/ 529, + /*0x03a4*/ 260, + -1, + /*0x03fd*/ 294, + -1, -1, -1, -1, -1, -1, + /*0x1c82*/ 532, + /*0x2ca4*/ 993, + -1, + /*0x0514*/ 431, + -1, + /*0xa7a6*/ 1123, + /*0x01a6*/ 144, + /*0x10ca6*/ 1422, + -1, + /*0x104c3*/ 1332, + /*0x04c3*/ 391, + -1, -1, -1, + /*0x10c3*/ 519, + /*0x1e86*/ 653, + /*0x1e06*/ 589, + -1, + /*0x0510*/ 429, + /*0xa7a4*/ 1122, + /*0x01a4*/ 143, + /*0x10ca4*/ 1420, + -1, + /*0x0222*/ 207, + /*0x24c3*/ 899, + /*0x1fa2*/ 802, + /*0x10422*/ 1307, + /*0x0422*/ 331, + /*0x0122*/ 74, + /*0x1e96*/ 661, + /*0x1e16*/ 597, + /*0x048a*/ 362, + /*0x0504*/ 423, + /*0xaba2*/ 1205, + /*0x2c22*/ 946, + /*0x1c98*/ 548, + -1, -1, + /*0x021a*/ 203, + -1, + /*0x1f9a*/ 794, + /*0x1041a*/ 1299, + /*0x041a*/ 323, + /*0x011a*/ 70, + -1, + /*0x0480*/ 361, + /*0x2ca2*/ 992, + -1, + /*0xab9a*/ 1197, + /*0x2c1a*/ 938, + -1, + /*0x039a*/ 251, + -1, -1, -1, + /*0x10575*/ 1354, + /*0x1ef0*/ 708, + /*0x1e70*/ 642, + /*0x1f6f*/ 767, + -1, + /*0x1ca0*/ 556, + /*0x2c9a*/ 988, + /*0x0553*/ 479, + /*0x1f08*/ 716, + /*0xa7a2*/ 1121, + /*0x01a2*/ 142, + /*0x10ca2*/ 1418, + -1, + /*0x1f09*/ 717, + -1, -1, + /*0x10a7*/ 491, + -1, + /*0x1f5b*/ 757, + /*0x1e94*/ 660, + /*0x1e14*/ 596, + /*0x0502*/ 422, + -1, -1, + /*0xa79a*/ 1117, + /*0x1f0a*/ 718, + /*0x10c9a*/ 1410, + /*0x1c92*/ 542, + -1, + /*0x1057f*/ 1363, + /*0x00df*/ 56, + /*0x1f59*/ 756, + -1, + /*0x104b3*/ 1316, + /*0x1e90*/ 658, + /*0x1e10*/ 594, + /*0x1e91a*/ 1547, + /*0x2126*/ 865, + /*0x10b3*/ 503, + /*0x00d3*/ 45, + -1, + /*0x021c*/ 204, + -1, + /*0x1f9c*/ 796, + /*0x1041c*/ 1301, + /*0x041c*/ 325, + /*0x011c*/ 71, + /*0x1ff9*/ 861, + /*0x1e84*/ 652, + /*0x1e04*/ 588, + /*0x0179*/ 117, + /*0xab9c*/ 1199, + /*0x2c1c*/ 940, + -1, + /*0x039c*/ 253, + /*0x13f9*/ 525, + /*0x0518*/ 433, + -1, + /*0x03f9*/ 292, + -1, + /*0x0496*/ 368, + -1, -1, + /*0x021e*/ 205, + /*0x2c9c*/ 989, + /*0x1f9e*/ 798, + /*0x1041e*/ 1303, + /*0x041e*/ 327, + /*0x011e*/ 72, + -1, -1, + /*0x1ca6*/ 562, + -1, + /*0xab9e*/ 1201, + /*0x2c1e*/ 942, + /*0x10577*/ 1356, + /*0x039e*/ 255, + -1, -1, + /*0x1feb*/ 853, + -1, + /*0x0520*/ 437, + /*0xa79c*/ 1118, + /*0x019c*/ 138, + /*0x10c9c*/ 1412, + /*0x1ca4*/ 560, + /*0x2c9e*/ 990, + /*0x04f0*/ 413, + /*0x2c6b*/ 966, + -1, -1, -1, + /*0x1e82*/ 651, + /*0x1e02*/ 587, + /*0x1e91c*/ 1549, + -1, -1, -1, -1, + /*0x023a*/ 216, + /*0x2ceb*/ 1025, + /*0x1fba*/ 823, + -1, + /*0x0512*/ 430, + /*0xa79e*/ 1119, + /*0x0494*/ 367, + /*0x10c9e*/ 1414, + -1, + /*0x022a*/ 211, + /*0xabba*/ 1229, + /*0x1faa*/ 810, + -1, + /*0x042a*/ 339, + /*0x012a*/ 78, + -1, + /*0x118a7*/ 1464, + /*0x1e91e*/ 1551, + -1, + /*0xabaa*/ 1213, + /*0x2c2a*/ 954, + /*0x0490*/ 365, + /*0x03aa*/ 266, + /*0x2cba*/ 1004, + /*0x1f6d*/ 765, + /*0x1f69*/ 761, + /*0x10d5b*/ 1446, + -1, + /*0x1e98*/ 663, + /*0x1e18*/ 598, + -1, + /*0x1ca2*/ 558, + /*0x2caa*/ 996, + /*0x10d65*/ 1456, + -1, + /*0x10d61*/ 1452, + /*0x00dd*/ 54, + -1, + /*0x118b3*/ 1476, + /*0x10d59*/ 1444, + -1, + /*0xa7ba*/ 1137, + -1, -1, -1, -1, + /*0x1c9a*/ 550, + -1, + /*0x0526*/ 440, + -1, + /*0xa7aa*/ 1125, + -1, + /*0x10caa*/ 1426, + /*0x1ea0*/ 668, + /*0x1e20*/ 602, + /*0x022e*/ 213, + -1, + /*0x1fae*/ 814, + -1, + /*0x042e*/ 343, + /*0x012e*/ 80, + -1, + /*0x0524*/ 439, + /*0x1057d*/ 1361, + /*0x104d3*/ 1348, + /*0xabae*/ 1217, + /*0x2c2e*/ 958, + -1, -1, + /*0x022c*/ 212, + -1, + /*0x1fac*/ 812, + /*0x0230*/ 214, + /*0x042c*/ 341, + /*0x012c*/ 79, + /*0x1e92*/ 659, + /*0x1e12*/ 595, + /*0x0130*/ 1556, + /*0x2cae*/ 998, + /*0xabac*/ 1215, + /*0x2c2c*/ 956, + -1, + /*0xabb0*/ 1219, + -1, -1, + /*0x03b0*/ 268, + -1, -1, -1, -1, -1, + /*0x1faf*/ 815, + /*0x2cac*/ 997, + /*0x042f*/ 344, + /*0x10d57*/ 1442, + /*0x2cb0*/ 999, + /*0xa7ae*/ 1129, + /*0x01ae*/ 148, + /*0x10cae*/ 1430, + /*0xabaf*/ 1218, + /*0x2c2f*/ 959, + -1, -1, -1, + /*0x1c9c*/ 552, + /*0x1f5f*/ 759, + /*0x216b*/ 880, + /*0x0522*/ 438, + -1, -1, + /*0xa7ac*/ 1127, + /*0x01ac*/ 147, + /*0x10cac*/ 1428, + /*0xa7b0*/ 1130, + /*0x0498*/ 369, + /*0x10cb0*/ 1432, + -1, -1, -1, + /*0x1ea6*/ 671, + /*0x1e26*/ 605, + -1, + /*0x051a*/ 434, + -1, -1, + /*0x0228*/ 210, + /*0x1c9e*/ 554, + /*0x1fa8*/ 808, + -1, + /*0x0428*/ 337, + /*0x0128*/ 77, + /*0x01af*/ 149, + /*0x10caf*/ 1431, + /*0x1ea4*/ 670, + /*0x1e24*/ 604, + /*0xaba8*/ 1211, + /*0x2c28*/ 952, + /*0x212a*/ 866, + /*0x03a8*/ 264, + /*0x04a0*/ 373, + -1, -1, + /*0x020e*/ 197, + /*0x10a0*/ 484, + /*0x1f8e*/ 782, + /*0x1040e*/ 1287, + /*0x040e*/ 311, + /*0x010e*/ 64, + /*0x2ca8*/ 995, + /*0x0232*/ 215, + -1, + /*0x1fb2*/ 816, + /*0xab8e*/ 1185, + /*0x2c0e*/ 926, + /*0x0132*/ 81, + /*0x038e*/ 239, + -1, -1, -1, + /*0xabb2*/ 1221, + -1, + /*0x0492*/ 366, + /*0x1cba*/ 582, + /*0x1f18*/ 724, + -1, + /*0x2c8e*/ 982, + /*0xa7a8*/ 1124, + /*0x1fb8*/ 821, + /*0x10ca8*/ 1424, + -1, -1, + /*0x1caa*/ 566, + /*0x2cb2*/ 1000, + -1, -1, + /*0xabb8*/ 1227, + -1, -1, + /*0x1ea2*/ 669, + /*0x1e22*/ 603, + /*0x051c*/ 435, + -1, -1, + /*0x10579*/ 1358, + /*0x018e*/ 129, + /*0x10c8e*/ 1398, + -1, + /*0x10d63*/ 1454, + /*0x2cb8*/ 1003, + /*0xff27*/ 1253, + /*0xa7b2*/ 1132, + /*0x01b2*/ 151, + /*0x10cb2*/ 1434, + /*0x1e9a*/ 665, + /*0x1e1a*/ 599, + /*0x1e90e*/ 1535, + -1, -1, -1, -1, -1, -1, + /*0x051e*/ 436, + -1, -1, + /*0x04a6*/ 376, + /*0xa7b8*/ 1136, + /*0x01b8*/ 155, + -1, + /*0x10a6*/ 490, + /*0x1f5d*/ 758, + /*0xff33*/ 1265, + /*0x10d5f*/ 1450, + -1, -1, -1, -1, + /*0x1cae*/ 570, + -1, + /*0x04a4*/ 375, + -1, + /*0x10d53*/ 1438, + /*0x020c*/ 196, + /*0x10a4*/ 488, + /*0x1f8c*/ 780, + /*0x1040c*/ 1285, + /*0x040c*/ 309, + /*0x010c*/ 63, + -1, -1, -1, + /*0x1cac*/ 568, + /*0xab8c*/ 1183, + /*0x2c0c*/ 924, + /*0x1cb0*/ 572, + /*0x038c*/ 238, + -1, + /*0xa77b*/ 1104, + /*0x053a*/ 454, + -1, -1, + /*0xa726*/ 1067, + /*0x118a0*/ 1457, + -1, -1, + /*0x2c8c*/ 981, + -1, + /*0x052a*/ 442, + -1, -1, -1, + /*0x1caf*/ 571, + /*0x1e1c*/ 600, + -1, + /*0x10588*/ 1372, + /*0xa724*/ 1066, + -1, + /*0xa77d*/ 1105, + -1, + /*0x10589*/ 1373, + -1, -1, -1, -1, + /*0x04a2*/ 374, + /*0x10c8c*/ 1396, + -1, -1, + /*0x10a2*/ 486, + -1, -1, + /*0x1058a*/ 1374, + -1, + /*0x1e9e*/ 667, + /*0x1e1e*/ 601, + /*0x1e90c*/ 1533, + /*0x1fbc*/ 825, + /*0x2132*/ 868, + -1, + /*0x049a*/ 370, + /*0x023e*/ 219, + -1, + /*0x1fbe*/ 826, + -1, + /*0xabbc*/ 1231, + /*0x10580*/ 1364, + -1, + /*0x1ca8*/ 564, + -1, + /*0x10583*/ 1367, + /*0xabbe*/ 1233, + -1, -1, + /*0x052e*/ 444, + -1, -1, -1, + /*0x2cbc*/ 1005, + -1, -1, + /*0xa722*/ 1065, + -1, + /*0x0050*/ 14, + /*0x2cbe*/ 1006, + -1, -1, + /*0x0150*/ 96, + /*0x052c*/ 443, + /*0x118a6*/ 1463, + /*0x1eba*/ 681, + /*0x1e3a*/ 615, + /*0x1cb2*/ 574, + -1, -1, + /*0x03d0*/ 271, + /*0xa7bc*/ 1138, + /*0x01bc*/ 156, + /*0x10d5d*/ 1448, + /*0x1eaa*/ 673, + /*0x1e2a*/ 607, + -1, + /*0xa7be*/ 1139, + /*0x118a4*/ 1461, + -1, + /*0x2cd0*/ 1015, + -1, -1, + /*0x1cb8*/ 580, + /*0x1f1a*/ 726, + -1, + /*0x1fb6*/ 819, + /*0xa688*/ 1055, + -1, + /*0x0136*/ 83, + -1, -1, + /*0x1fb4*/ 818, + /*0x049c*/ 371, + /*0xabb6*/ 1225, + /*0x0134*/ 82, + -1, + /*0x10586*/ 1370, + /*0xa7d0*/ 1149, + -1, + /*0xabb4*/ 1223, + -1, -1, -1, + /*0xa68a*/ 1056, + -1, -1, + /*0x2cb6*/ 1002, + -1, -1, -1, -1, -1, + /*0x2cb4*/ 1001, + -1, + /*0x049e*/ 372, + -1, -1, + /*0xa680*/ 1051, + /*0x0528*/ 441, + /*0x1eae*/ 675, + /*0x1e2e*/ 609, + -1, + /*0x118a2*/ 1459, + -1, + /*0xa7b6*/ 1135, + -1, -1, -1, -1, -1, + /*0xa7b4*/ 1134, + -1, + /*0xa779*/ 1103, + /*0x1eac*/ 674, + /*0x1e2c*/ 608, + /*0x050e*/ 428, + /*0x1eb0*/ 676, + /*0x1e30*/ 610, + /*0x024c*/ 227, + /*0x004c*/ 10, + /*0x1fcc*/ 836, + /*0x1f1c*/ 728, + /*0x0532*/ 446, + /*0x014c*/ 94, + -1, -1, + /*0x024a*/ 226, + /*0x004a*/ 8, + /*0x1fca*/ 834, + /*0x104ba*/ 1323, + /*0x04ba*/ 386, + /*0x014a*/ 93, + -1, -1, + /*0x10ba*/ 510, + /*0x10594*/ 1382, + /*0x005a*/ 24, + /*0x1fda*/ 843, + /*0x0538*/ 452, + /*0x04aa*/ 378, + /*0x015a*/ 101, + /*0x2ccc*/ 1013, + -1, + /*0x10aa*/ 494, + /*0x24ba*/ 890, + -1, -1, -1, + /*0x03da*/ 276, + /*0x2cca*/ 1012, + /*0x10590*/ 1379, + -1, -1, + /*0xa686*/ 1054, + -1, -1, -1, + /*0x1f6b*/ 763, + /*0x2cda*/ 1020, + /*0xa7cc*/ 1148, + -1, -1, -1, -1, + /*0x10584*/ 1368, + -1, + /*0xa73a*/ 1076, + /*0xa696*/ 1062, + /*0x01ca*/ 161, + /*0x1ea8*/ 672, + /*0x1e28*/ 606, + -1, -1, -1, -1, + /*0xa72a*/ 1069, + /*0xa7da*/ 1152, + /*0x1cbe*/ 584, + -1, + /*0x1f3a*/ 740, + -1, -1, + /*0x0248*/ 225, + /*0x0048*/ 7, + /*0x1fc8*/ 832, + /*0x04ae*/ 380, + /*0x1e8e*/ 657, + /*0x1e0e*/ 593, + /*0x1f2a*/ 732, + /*0x10ae*/ 498, + -1, -1, -1, + /*0x1eb2*/ 677, + /*0x1e32*/ 611, + /*0x050c*/ 427, + /*0x0244*/ 222, + /*0x0044*/ 3, + /*0x1fc4*/ 829, + /*0x04ac*/ 379, + -1, + /*0x104b0*/ 1313, + /*0x04b0*/ 381, + /*0x10ac*/ 496, + -1, + /*0x2cc8*/ 1011, + /*0x10b0*/ 500, + -1, + /*0x10582*/ 1366, + /*0x1eb8*/ 680, + /*0x1e38*/ 614, + -1, + /*0xa694*/ 1061, + -1, + /*0x0056*/ 20, + /*0x1fd6*/ 839, + /*0xff26*/ 1252, + -1, + /*0x0156*/ 99, + /*0x2cc4*/ 1009, + -1, + /*0xa72e*/ 1071, + -1, + /*0x10af*/ 499, + /*0x01c8*/ 160, + /*0x1cb6*/ 578, + /*0x03d6*/ 274, + /*0xa690*/ 1059, + /*0x0052*/ 16, + /*0x1fd2*/ 837, + /*0xff24*/ 1250, + /*0x1cb4*/ 576, + /*0x0152*/ 97, + /*0x118ba*/ 1483, + /*0x1f2e*/ 736, + /*0xa72c*/ 1070, + /*0x2cd6*/ 1018, + /*0xa7c4*/ 1142, + /*0x01c4*/ 157, + -1, -1, + /*0xa684*/ 1053, + /*0x118aa*/ 1467, + -1, -1, + /*0x004f*/ 13, + -1, + /*0x053c*/ 456, + /*0x1f2c*/ 734, + -1, + /*0x2cd2*/ 1016, + -1, -1, + /*0x053e*/ 458, + /*0xa7d6*/ 1150, + /*0x04a8*/ 377, + -1, + /*0x03cf*/ 270, + -1, + /*0x10a8*/ 492, + -1, -1, -1, -1, -1, + /*0x0054*/ 18, + /*0x1e8c*/ 656, + /*0x1e0c*/ 592, + /*0x1f2f*/ 737, + /*0x0154*/ 98, + -1, -1, + /*0x048e*/ 364, + -1, + /*0x0550*/ 476, + /*0xff22*/ 1248, + -1, -1, + /*0x104b2*/ 1315, + /*0x04b2*/ 382, + -1, -1, -1, + /*0x10b2*/ 502, + -1, + /*0xa682*/ 1052, + /*0x01cf*/ 164, + /*0x2cd4*/ 1017, + /*0x118ae*/ 1471, + -1, + /*0x10592*/ 1381, + /*0xa728*/ 1068, + -1, -1, + /*0x104b8*/ 1321, + /*0x04b8*/ 385, + -1, -1, -1, + /*0x10b8*/ 508, + -1, + /*0x0536*/ 450, + /*0x118ac*/ 1469, + -1, + /*0x1f28*/ 730, + /*0x118b0*/ 1473, + /*0x00d0*/ 42, + /*0x0534*/ 448, + -1, + /*0x24b8*/ 888, + -1, + /*0x0042*/ 1, + /*0x1fc2*/ 827, + -1, -1, + /*0xa732*/ 1072, + -1, + /*0x2cc0*/ 1007, + /*0x1ebc*/ 682, + /*0x1e3c*/ 616, + /*0xa698*/ 1063, + /*0x1f0e*/ 722, + /*0x118af*/ 1472, + /*0x03c2*/ 269, + /*0x1ebe*/ 683, + /*0x1e3e*/ 617, + -1, + /*0x0246*/ 224, + /*0x0046*/ 5, + /*0x1fc6*/ 830, + -1, + /*0xa738*/ 1075, + -1, + /*0x2cc2*/ 1008, + -1, + /*0xa7c0*/ 1140, + -1, + /*0x0058*/ 22, + /*0x1fd8*/ 841, + -1, -1, + /*0x0158*/ 100, + -1, -1, + /*0x1f38*/ 738, + /*0x1ed0*/ 692, + /*0x1e50*/ 626, + -1, -1, + /*0x03d8*/ 275, + /*0x2cc6*/ 1010, + /*0xa7c2*/ 1141, + /*0x048c*/ 363, + -1, -1, -1, + /*0x054c*/ 472, + -1, + /*0x118a8*/ 1465, + /*0x2cd8*/ 1019, + /*0x16e43*/ 1492, + /*0x1f8d*/ 781, + /*0x1040d*/ 1286, + /*0x040d*/ 310, + /*0x054a*/ 470, + -1, -1, + /*0xa692*/ 1060, + /*0xa7c6*/ 1144, + /*0xab8d*/ 1184, + /*0x2c0d*/ 925, + -1, + /*0x1eb6*/ 679, + /*0x1e36*/ 613, + /*0x16e5b*/ 1516, + -1, -1, + /*0xa7d8*/ 1151, + /*0x1eb4*/ 678, + /*0x1e34*/ 612, + /*0x0245*/ 223, + /*0x0045*/ 4, + /*0x118b2*/ 1475, + -1, -1, + /*0x0145*/ 90, + -1, + /*0x16e59*/ 1514, + /*0x00cc*/ 38, + -1, + /*0x024e*/ 228, + /*0x004e*/ 12, + -1, -1, -1, + /*0x014e*/ 95, + /*0x00ca*/ 36, + -1, + /*0x118b8*/ 1481, + -1, + /*0xa78d*/ 1112, + /*0x1f0c*/ 720, + /*0x10c8d*/ 1397, + /*0x104bc*/ 1325, + /*0x04bc*/ 387, + /*0x00da*/ 51, + /*0xff3a*/ 1272, + -1, + /*0x10bc*/ 512, + /*0x104be*/ 1327, + /*0x04be*/ 388, + -1, + /*0x1e90d*/ 1534, + /*0x2cce*/ 1014, + /*0x10be*/ 514, + /*0xff2a*/ 1256, + -1, -1, + /*0x24bc*/ 892, + -1, + /*0x0548*/ 468, + /*0xa7c5*/ 1143, + /*0x01c5*/ 158, + -1, + /*0x24be*/ 894, + -1, -1, + /*0x1ecc*/ 690, + /*0x1e4c*/ 624, + -1, + /*0x104d0*/ 1345, + /*0x04d0*/ 397, + -1, -1, + /*0x0544*/ 464, + /*0x1eca*/ 689, + /*0x1e4a*/ 623, + -1, + /*0x0055*/ 19, + /*0xa650*/ 1036, + /*0xa73c*/ 1077, + -1, + /*0x16e57*/ 1512, + /*0x0345*/ 229, + /*0x1eda*/ 697, + /*0x1e5a*/ 631, + /*0xa73e*/ 1078, + /*0x1f87*/ 775, + /*0x10407*/ 1280, + /*0x0407*/ 304, + /*0x03d5*/ 273, + /*0x0556*/ 482, + /*0x00c8*/ 34, + /*0x1f3c*/ 742, + -1, + /*0xab87*/ 1178, + /*0x2c07*/ 919, + /*0x104b6*/ 1319, + /*0x04b6*/ 384, + /*0x1f3e*/ 744, + -1, + /*0xff2e*/ 1260, + /*0x10b6*/ 506, + /*0x104b4*/ 1317, + /*0x04b4*/ 383, + /*0x0552*/ 478, + /*0x00c4*/ 30, + /*0xa750*/ 1087, + /*0x10b4*/ 504, + /*0x0047*/ 6, + /*0x1fc7*/ 831, + -1, + /*0x24b6*/ 886, + /*0x0147*/ 91, + -1, + /*0xff2c*/ 1258, + -1, -1, + /*0xff30*/ 1262, + /*0x01d5*/ 167, + /*0x1f50*/ 752, + -1, + /*0x054f*/ 475, + /*0x00d6*/ 48, + -1, + /*0xa69a*/ 1064, + /*0xab71*/ 1156, + /*0x0187*/ 125, + /*0x10c87*/ 1391, + -1, -1, + /*0x1ec8*/ 688, + /*0x1e48*/ 622, + -1, + /*0xa736*/ 1074, + /*0xff2f*/ 1261, + /*0x1fb9*/ 822, + /*0x00d2*/ 44, + /*0x1e907*/ 1528, + /*0x0139*/ 84, + /*0xa734*/ 1073, + -1, + /*0x0554*/ 480, + /*0xab73*/ 1158, + /*0xabb9*/ 1228, + /*0x1ec4*/ 686, + /*0x1e44*/ 620, + /*0x118bc*/ 1485, + -1, + /*0xa7c7*/ 1145, + /*0x01c7*/ 159, + -1, + /*0x104cc*/ 1341, + /*0x118be*/ 1487, + /*0x00cf*/ 41, + -1, -1, + /*0x1fab*/ 811, + -1, + /*0x042b*/ 340, + /*0x104ca*/ 1339, + /*0xa64c*/ 1034, + /*0x1ed6*/ 695, + /*0x1e56*/ 629, + -1, + /*0xabab*/ 1214, + /*0x2c2b*/ 955, + /*0x24cc*/ 908, + /*0x03ab*/ 267, + /*0xa64a*/ 1033, + /*0x04da*/ 402, + /*0xff28*/ 1254, + /*0x0540*/ 460, + -1, + /*0x00d4*/ 46, + /*0x24ca*/ 906, + /*0x1ed2*/ 693, + /*0x1e52*/ 627, + /*0xa65a*/ 1041, + -1, -1, -1, + /*0x1fe2*/ 845, + -1, + /*0x0462*/ 346, + /*0x0162*/ 105, + -1, -1, + /*0x0542*/ 462, + /*0xa74c*/ 1085, + -1, + /*0x2c62*/ 961, + -1, + /*0x03e2*/ 280, + -1, + /*0xff32*/ 1264, + /*0xa7ab*/ 1126, + /*0xa74a*/ 1084, + /*0x10cab*/ 1427, + -1, + /*0x16e5f*/ 1520, + /*0x118b6*/ 1479, + /*0x1f4c*/ 750, + /*0x2ce2*/ 1024, + /*0x00c0*/ 26, + /*0x0546*/ 466, + /*0xa75a*/ 1092, + /*0x118b4*/ 1477, + -1, + /*0x16e53*/ 1508, + /*0x1f4a*/ 748, + /*0xff38*/ 1270, + -1, + /*0x1ed4*/ 694, + /*0x1e54*/ 628, + /*0x1fe4*/ 847, + /*0x104c8*/ 1337, + /*0x0464*/ 347, + /*0x0164*/ 106, + -1, + /*0x00c2*/ 28, + -1, + /*0x01e2*/ 173, + /*0xab70*/ 1155, + /*0x2c64*/ 963, + /*0xa648*/ 1032, + /*0x03e4*/ 281, + /*0x10d50*/ 1435, + -1, -1, + /*0x104c4*/ 1333, + /*0x24c8*/ 904, + /*0x015e*/ 103, + -1, -1, + /*0x10c4*/ 520, + -1, + /*0x00c6*/ 32, + -1, + /*0xa644*/ 1030, + /*0x03de*/ 278, + -1, -1, + /*0x1ec0*/ 684, + /*0x1e40*/ 618, + /*0x24c4*/ 900, + /*0x00d8*/ 49, + /*0x1c87*/ 537, + /*0x04d6*/ 400, + -1, + /*0x2cde*/ 1022, + -1, -1, + /*0xa748*/ 1083, + -1, + /*0x01e4*/ 174, + /*0xa656*/ 1039, + -1, + /*0x0545*/ 465, + /*0x1ec2*/ 685, + /*0x1e42*/ 619, + /*0x104d2*/ 1347, + /*0x04d2*/ 398, + /*0x1fa9*/ 809, + -1, + /*0x0429*/ 338, + /*0x1f48*/ 746, + /*0xa744*/ 1081, + /*0x054e*/ 474, + /*0x01de*/ 171, + /*0xa652*/ 1037, + /*0xaba9*/ 1212, + /*0x2c29*/ 953, + -1, + /*0x03a9*/ 265, + -1, + /*0x1ec6*/ 687, + /*0x1e46*/ 621, + /*0x104cf*/ 1344, + -1, + /*0x1fa1*/ 801, + /*0x10421*/ 1306, + /*0x0421*/ 330, + /*0x212b*/ 867, + /*0xa756*/ 1090, + /*0x1ed8*/ 696, + /*0x1e58*/ 630, + -1, + /*0xaba1*/ 1204, + /*0x2c21*/ 945, + /*0x00c5*/ 31, + /*0x03a1*/ 258, + -1, + /*0x24cf*/ 911, + /*0xab75*/ 1160, + -1, + /*0x1cb9*/ 581, + /*0x1f56*/ 755, + /*0xa752*/ 1088, + /*0x04d4*/ 399, + /*0x00ce*/ 40, + -1, -1, + /*0x01a9*/ 146, + /*0x10ca9*/ 1425, + /*0x16e5d*/ 1518, + /*0x1058e*/ 1377, + /*0xa654*/ 1038, + /*0x2162*/ 871, + -1, -1, + /*0x1f52*/ 753, + -1, + /*0x0460*/ 345, + /*0x0160*/ 104, + /*0x0555*/ 481, + /*0x015c*/ 102, + /*0x1cab*/ 567, + -1, -1, + /*0x2c60*/ 960, + /*0x10ca1*/ 1417, + /*0x03e0*/ 279, + /*0xab7f*/ 1170, + /*0x03dc*/ 277, + -1, + /*0x10d5a*/ 1445, + -1, + /*0x104c0*/ 1329, + /*0x04c0*/ 389, + -1, + /*0x1e921*/ 1554, + /*0x2ce0*/ 1023, + /*0x10c0*/ 516, + /*0x2cdc*/ 1021, + /*0xa754*/ 1089, + -1, + /*0xa640*/ 1028, + -1, + /*0x1ece*/ 691, + /*0x1e4e*/ 625, + /*0x2164*/ 873, + -1, + /*0x24c0*/ 896, + /*0x104c2*/ 1331, + -1, + /*0x0547*/ 467, + /*0x00d5*/ 47, + /*0x1f54*/ 754, + /*0x10c2*/ 518, + -1, + /*0x01e0*/ 172, + /*0xa7dc*/ 1153, + /*0xa642*/ 1029, + -1, + /*0x1f97*/ 791, + /*0x10417*/ 1296, + /*0x0417*/ 320, + -1, + /*0x24c2*/ 898, + -1, + /*0x104c6*/ 1335, + -1, + /*0xab97*/ 1194, + /*0x2c17*/ 935, + /*0xa740*/ 1079, + /*0x0397*/ 248, + -1, -1, + /*0xab77*/ 1162, + /*0xa646*/ 1031, + /*0x04d8*/ 401, + /*0x0539*/ 453, + -1, + /*0xff36*/ 1268, + -1, + /*0x24c6*/ 902, + -1, + /*0x00c7*/ 33, + /*0xa658*/ 1040, + /*0xff34*/ 1266, + /*0xa742*/ 1080, + /*0x1fec*/ 854, + /*0xa68e*/ 1058, + /*0x046c*/ 351, + /*0x016c*/ 110, + /*0x1058c*/ 1375, + -1, + /*0x1fea*/ 852, + -1, + /*0x046a*/ 350, + /*0x016a*/ 109, + -1, + /*0x03ec*/ 285, + -1, + /*0x0197*/ 136, + /*0x10c97*/ 1407, + -1, + /*0xa746*/ 1082, + /*0x03ea*/ 284, + -1, + /*0x004b*/ 9, + /*0x1fcb*/ 835, + -1, + /*0x10d56*/ 1441, + -1, + /*0x1e917*/ 1544, + /*0xa758*/ 1091, + -1, + /*0x1fe8*/ 850, + -1, + /*0x0468*/ 349, + /*0x0168*/ 108, + -1, + /*0x104c5*/ 1334, + /*0x04c5*/ 392, + -1, -1, + /*0x10d52*/ 1437, + /*0x10c5*/ 521, + /*0x03e8*/ 283, + -1, + /*0x01ec*/ 178, + /*0x1ca9*/ 565, + /*0x104ce*/ 1343, + -1, -1, -1, + /*0x01ea*/ 177, + /*0x24c5*/ 901, + -1, -1, -1, + /*0xa64e*/ 1035, + /*0x0049*/ 1555, + /*0x1fc9*/ 833, + /*0xab7b*/ 1166, + /*0x2160*/ 869, + /*0x0149*/ 92, + /*0x24ce*/ 910, + /*0x1ca1*/ 557, + /*0xa7cb*/ 1147, + /*0x01cb*/ 162, + /*0x1f0d*/ 721, + -1, + /*0x046e*/ 352, + /*0x016e*/ 111, + -1, + /*0x1ff2*/ 855, + /*0x01e8*/ 176, + /*0x0472*/ 354, + /*0x0172*/ 113, + /*0x2c6e*/ 968, + /*0xfb17*/ 1246, + /*0x03ee*/ 286, + /*0x10d54*/ 1439, + /*0xab7d*/ 1168, + /*0x2c72*/ 971, + -1, -1, -1, + /*0xa74e*/ 1086, + -1, + /*0xa68c*/ 1057, + /*0x1fe6*/ 848, + -1, + /*0x0466*/ 348, + /*0x0166*/ 107, + -1, + /*0x2cf2*/ 1027, + /*0x1f8f*/ 783, + /*0x1040f*/ 1288, + /*0x040f*/ 312, + -1, + /*0xa7c9*/ 1146, + /*0x03e6*/ 282, + -1, -1, + /*0xab8f*/ 1186, + /*0x2c0f*/ 927, + -1, + /*0x038f*/ 240, + -1, + /*0x01ee*/ 179, + -1, + /*0x1fad*/ 813, + -1, + /*0x042d*/ 342, + /*0x01f2*/ 182, + /*0x1ee2*/ 701, + /*0x1e62*/ 635, + -1, + /*0x047e*/ 360, + /*0xabad*/ 1216, + /*0x2c2d*/ 957, + /*0x0241*/ 220, + /*0x0041*/ 0, + /*0x00de*/ 55, + -1, + /*0x2c7e*/ 973, + /*0x0141*/ 88, + /*0x03fe*/ 295, + /*0x104c7*/ 1336, + /*0x04c7*/ 393, + /*0x01e6*/ 175, + -1, -1, + /*0x10c7*/ 522, + /*0x216c*/ 881, + /*0x0372*/ 231, + /*0x018f*/ 130, + /*0x10c8f*/ 1399, + -1, + /*0xabb5*/ 1224, + /*0x216a*/ 879, + /*0x1c97*/ 547, + -1, + /*0x24c7*/ 903, + -1, -1, -1, + /*0x1e90f*/ 1536, + /*0x1ee4*/ 702, + /*0x1e64*/ 636, + /*0xa7ad*/ 1128, + -1, + /*0x10cad*/ 1429, + /*0x10d58*/ 1443, + /*0x104b9*/ 1322, + -1, + /*0x01fe*/ 189, + -1, -1, + /*0x10b9*/ 509, + /*0x1fb7*/ 820, + /*0x2168*/ 877, + /*0x1ede*/ 699, + /*0x1e5e*/ 633, + /*0x1fa5*/ 805, + /*0x10425*/ 1310, + /*0x0425*/ 334, + -1, + /*0xabb7*/ 1226, + /*0x24b9*/ 889, + -1, + /*0x01b5*/ 153, + /*0xaba5*/ 1208, + /*0x2c25*/ 949, + -1, + /*0x03a5*/ 261, + /*0x1fa3*/ 803, + /*0x10423*/ 1308, + /*0x0423*/ 332, + -1, + /*0x10ab*/ 495, + /*0x1f9d*/ 797, + /*0x1041d*/ 1302, + /*0x041d*/ 326, + /*0xaba3*/ 1206, + /*0x2c23*/ 947, + -1, + /*0x03a3*/ 259, + -1, + /*0xab9d*/ 1200, + /*0x2c1d*/ 941, + -1, + /*0x039d*/ 254, + -1, -1, + /*0x216e*/ 883, + -1, -1, -1, -1, + /*0x01b7*/ 154, + /*0x04e2*/ 406, + /*0xab79*/ 1164, + -1, + /*0x1f39*/ 739, + /*0x10ca5*/ 1421, + -1, + /*0x00dc*/ 53, + -1, + /*0xa662*/ 1045, + /*0x023d*/ 218, + -1, -1, -1, -1, + /*0x013d*/ 86, + /*0x2166*/ 875, + /*0x10ca3*/ 1419, + -1, -1, + /*0xabbd*/ 1232, + /*0x019d*/ 139, + /*0x10c9d*/ 1413, + -1, + /*0x004d*/ 11, + /*0x1f2b*/ 733, + -1, + /*0x1f9b*/ 795, + /*0x1041b*/ 1300, + /*0x041b*/ 324, + -1, -1, + /*0x1e91d*/ 1550, + -1, + /*0x04e4*/ 407, + /*0xab9b*/ 1198, + /*0x2c1b*/ 939, + /*0xa762*/ 1096, + /*0x039b*/ 252, + -1, -1, -1, + /*0xa664*/ 1046, + -1, + /*0x1ee0*/ 700, + /*0x1e60*/ 634, + /*0x1edc*/ 698, + /*0x1e5c*/ 632, + /*0x04de*/ 404, + -1, -1, + /*0x1f95*/ 789, + /*0x10415*/ 1294, + /*0x0415*/ 318, + /*0x10d55*/ 1440, + /*0x1ffa*/ 862, + /*0xa65e*/ 1043, + /*0x047a*/ 358, + /*0x118b9*/ 1482, + /*0xab95*/ 1192, + /*0x2c15*/ 933, + -1, + /*0x0395*/ 246, + /*0x13fa*/ 526, + /*0x054b*/ 471, + /*0x01cd*/ 163, + /*0x03fa*/ 293, + -1, + /*0x10c9b*/ 1411, + -1, + /*0xa764*/ 1097, + /*0x1cad*/ 569, + /*0x1f99*/ 793, + /*0x10419*/ 1298, + /*0x0419*/ 322, + -1, -1, + /*0x013f*/ 87, + /*0x1e91b*/ 1548, + /*0x118ab*/ 1468, + /*0xab99*/ 1196, + /*0x2c19*/ 937, + /*0xabbf*/ 1234, + /*0x0399*/ 250, + /*0xa75e*/ 1094, + -1, + /*0x10a9*/ 493, + /*0x1ff4*/ 857, + /*0x1e97*/ 662, + /*0x0474*/ 355, + /*0x0174*/ 114, + /*0x1cb5*/ 577, + /*0x10c95*/ 1405, + -1, -1, + /*0x01fa*/ 187, + /*0x00cb*/ 37, + /*0x0549*/ 469, + /*0x03f4*/ 289, + -1, -1, -1, + /*0x1e915*/ 1542, + /*0x10a1*/ 485, + -1, -1, -1, + /*0x0051*/ 15, + -1, + /*0x10572*/ 1351, + -1, -1, -1, + /*0x10c99*/ 1409, + -1, + /*0x1eec*/ 706, + /*0x1e6c*/ 640, + -1, -1, + /*0x03d1*/ 272, + /*0x1cb7*/ 579, + /*0x1eea*/ 705, + /*0x1e6a*/ 639, + /*0x1e919*/ 1546, + /*0x1ca5*/ 561, + -1, -1, + /*0x01f4*/ 183, + -1, + /*0x00c9*/ 35, + /*0x04e0*/ 405, + /*0x1f29*/ 731, + /*0x04dc*/ 403, + -1, -1, -1, + /*0x1ca3*/ 559, + -1, + /*0xa660*/ 1044, + -1, + /*0xa65c*/ 1042, + /*0x1c9d*/ 553, + /*0x1ee8*/ 704, + /*0x1e68*/ 638, + -1, + /*0x023b*/ 217, + -1, + /*0x1fbb*/ 824, + /*0x01d1*/ 165, + /*0xfb15*/ 1244, + /*0x013b*/ 85, + /*0x1057e*/ 1362, + /*0x1f91*/ 785, + /*0x10411*/ 1290, + /*0x0411*/ 314, + /*0xabbb*/ 1230, + -1, + /*0x10d62*/ 1453, + -1, + /*0x0541*/ 461, + /*0xab91*/ 1188, + /*0x2c11*/ 929, + -1, + /*0x0391*/ 242, + -1, -1, + /*0xa760*/ 1095, + /*0x0535*/ 449, + /*0xa75c*/ 1093, + -1, -1, -1, + /*0x1cbd*/ 583, + -1, -1, -1, + /*0x1eee*/ 707, + /*0x1e6e*/ 641, + /*0x1ffc*/ 864, + -1, + /*0x047c*/ 359, + /*0x1ef2*/ 709, + /*0x1e72*/ 643, + -1, -1, + /*0x118a9*/ 1466, + /*0x13fc*/ 528, + /*0x1c9b*/ 551, + -1, -1, + /*0x10d64*/ 1455, + /*0x00c1*/ 27, + /*0x0191*/ 132, + /*0x10c91*/ 1401, + -1, -1, + /*0x0537*/ 451, + /*0x1ee6*/ 703, + /*0x1e66*/ 637, + /*0x00b5*/ 25, + -1, + /*0x04ec*/ 411, + /*0x118a1*/ 1458, + /*0x1e911*/ 1538, + /*0x10d5e*/ 1449, + -1, -1, + /*0x04ea*/ 410, + -1, + /*0xa66c*/ 1050, + -1, + /*0x1c95*/ 545, + -1, -1, + /*0x1058d*/ 1376, + /*0xa66a*/ 1049, + -1, -1, + /*0x01fc*/ 188, + -1, + /*0x104cb*/ 1340, + /*0x04cb*/ 395, + -1, + /*0x1efe*/ 715, + /*0x1e7e*/ 649, + -1, -1, -1, + /*0x04e8*/ 409, + -1, -1, + /*0xff39*/ 1271, + /*0x1c99*/ 549, + -1, + /*0x1cbf*/ 585, + /*0x24cb*/ 907, + /*0xa668*/ 1048, + /*0xa76c*/ 1101, + /*0x1f93*/ 787, + /*0x10413*/ 1292, + /*0x0413*/ 316, + -1, -1, + /*0xa76a*/ 1100, + -1, -1, + /*0xab93*/ 1190, + /*0x2c13*/ 931, + /*0x053d*/ 457, + /*0x0393*/ 244, + /*0x1f6c*/ 764, + -1, + /*0xff2b*/ 1257, + /*0x104c9*/ 1338, + /*0x04c9*/ 394, + -1, + /*0x1f6a*/ 762, + /*0x1ff6*/ 858, + -1, + /*0x0476*/ 356, + /*0x0176*/ 115, + /*0x054d*/ 473, + /*0x04ee*/ 412, + /*0xabb1*/ 1220, + /*0xa768*/ 1099, + -1, + /*0x16e50*/ 1505, + /*0x04f2*/ 414, + /*0x24c9*/ 905, + -1, + /*0x1f4b*/ 749, + -1, -1, + /*0x1f81*/ 769, + /*0x10401*/ 1274, + /*0x0401*/ 298, + -1, + /*0x1f68*/ 760, + /*0x0193*/ 133, + /*0x10c93*/ 1403, + -1, + /*0xab81*/ 1172, + /*0x2c01*/ 913, + /*0x04e6*/ 408, + -1, -1, + /*0x10d60*/ 1451, + -1, + /*0x10d5c*/ 1447, + /*0x1e913*/ 1540, + /*0x1057a*/ 1359, + /*0xa666*/ 1047, + -1, + /*0x00cd*/ 39, + /*0xa7b1*/ 1131, + /*0x01b1*/ 150, + /*0x10cb1*/ 1433, + /*0x01f6*/ 184, + /*0xa76e*/ 1102, + -1, + /*0x10587*/ 1371, + /*0x0587*/ 483, + -1, + /*0x1f49*/ 747, + -1, -1, -1, -1, + /*0x10ad*/ 497, + /*0x04fe*/ 420, + /*0x053f*/ 459, + /*0x1f6e*/ 766, + /*0x1c91*/ 541, + /*0x0181*/ 121, + /*0x10c81*/ 1385, + /*0x104c1*/ 1330, + /*0x04c1*/ 390, + -1, + /*0x0376*/ 232, + /*0xa766*/ 1098, + /*0x10c1*/ 517, + -1, + /*0x10574*/ 1353, + /*0x104b5*/ 1318, + /*0x1e901*/ 1522, + -1, -1, -1, + /*0x10b5*/ 505, + -1, + /*0x24c1*/ 897, + -1, -1, -1, + /*0x1e9b*/ 666, + -1, + /*0xfb13*/ 1242, + -1, + /*0x1f0f*/ 723, + -1, -1, + /*0x1f8b*/ 779, + /*0x1040b*/ 1284, + /*0x040b*/ 308, + /*0x0551*/ 477, + /*0xa77e*/ 1106, + -1, -1, + /*0x16e4c*/ 1501, + /*0xab8b*/ 1182, + /*0x2c0b*/ 923, + -1, + /*0x104b7*/ 1320, + /*0x1f2d*/ 735, + -1, -1, + /*0x16e4a*/ 1499, + /*0x10b7*/ 507, + /*0xff29*/ 1255, + -1, -1, + /*0x10a5*/ 489, + /*0x1efa*/ 713, + /*0x1e7a*/ 647, + -1, + /*0x16e5a*/ 1515, + /*0x1ff8*/ 860, + /*0x24b7*/ 887, + /*0x0478*/ 357, + /*0x0178*/ 116, + -1, + /*0xfb01*/ 1236, + -1, + /*0x10a3*/ 487, + /*0x13f8*/ 524, + /*0xff21*/ 1247, + /*0x00d1*/ 43, + -1, -1, + /*0x1e99*/ 664, + /*0xa78b*/ 1111, + /*0x018b*/ 128, + /*0x10c8b*/ 1395, + /*0x053b*/ 455, + -1, -1, -1, -1, + /*0x1f9f*/ 799, + /*0x1041f*/ 1304, + /*0x041f*/ 328, + -1, + /*0x1e90b*/ 1532, + -1, + /*0x1ef4*/ 710, + /*0x1e74*/ 644, + /*0xab9f*/ 1202, + /*0x2c1f*/ 943, + /*0x1c93*/ 543, + /*0x039f*/ 256, + -1, -1, -1, -1, + /*0x104bd*/ 1326, + -1, + /*0x01f8*/ 186, + /*0x118ad*/ 1470, + -1, + /*0x10bd*/ 513, + -1, -1, + /*0x16e48*/ 1497, + /*0x1057c*/ 1360, + -1, + /*0x1cb1*/ 573, + -1, + /*0x104cd*/ 1342, + /*0x04cd*/ 396, + /*0x24bd*/ 893, + -1, -1, + /*0x10cd*/ 523, + /*0x1f1d*/ 729, + -1, -1, + /*0x16e44*/ 1493, + /*0x118b5*/ 1478, + /*0x019f*/ 140, + /*0x10c9f*/ 1415, + -1, -1, + /*0x24cd*/ 909, + /*0x1c81*/ 531, + -1, -1, + /*0x1f85*/ 773, + /*0x10405*/ 1278, + /*0x0405*/ 302, + /*0x1e91f*/ 1552, + -1, -1, -1, + /*0x16e56*/ 1511, + /*0xab85*/ 1176, + /*0x2c05*/ 917, + -1, -1, + /*0x04fa*/ 418, + -1, -1, -1, -1, -1, + /*0x1f3d*/ 743, + -1, + /*0x118b7*/ 1480, + /*0x16e52*/ 1507, + -1, -1, + /*0x118a5*/ 1462, + -1, -1, -1, -1, -1, + /*0x104bf*/ 1328, + /*0x1f4d*/ 751, + -1, + /*0x1f1b*/ 727, + -1, + /*0x10bf*/ 515, + /*0x118a3*/ 1460, + -1, + /*0x16e4f*/ 1504, + -1, -1, + /*0x10c85*/ 1389, + -1, -1, + /*0x04f4*/ 415, + /*0x24bf*/ 895, + -1, -1, -1, + /*0x1efc*/ 714, + /*0x1e7c*/ 648, + /*0x1e905*/ 1526, + -1, -1, -1, + /*0x0531*/ 445, + /*0x10576*/ 1355, + -1, + /*0x16e54*/ 1509, + -1, -1, -1, -1, -1, + /*0x104d1*/ 1346, + -1, -1, -1, -1, -1, -1, + -1, + /*0x118bd*/ 1486, + -1, -1, -1, -1, -1, + /*0x1f19*/ 725, + -1, + /*0x1f3f*/ 745, + -1, -1, -1, -1, -1, -1, + -1, + /*0x16e40*/ 1489, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, + /*0xfb05*/ 1240, + -1, -1, -1, -1, + /*0x104bb*/ 1324, + /*0x16e42*/ 1491, + -1, -1, -1, + /*0x10bb*/ 511, + -1, -1, -1, + /*0x1c9f*/ 555, + -1, -1, -1, -1, -1, + /*0x24bb*/ 891, + -1, -1, + /*0x16e46*/ 1495, + -1, -1, -1, -1, -1, -1, + /*0x1ef6*/ 711, + /*0x1e76*/ 645, + /*0x16e58*/ 1513, + -1, -1, -1, + /*0x118bf*/ 1488, + /*0x04fc*/ 419, + -1, -1, -1, -1, -1, -1, + -1, -1, + /*0xff2d*/ 1259, + -1, -1, -1, -1, -1, -1, + -1, -1, + /*0x1f3b*/ 741, + -1, -1, -1, -1, -1, -1, + /*0x1c85*/ 535, + -1, -1, -1, + /*0xff35*/ 1267, + /*0x10578*/ 1357, + -1, -1, -1, -1, -1, -1, + -1, -1, + /*0x16e45*/ 1494, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, + /*0x16e4e*/ 1503, + -1, -1, -1, -1, -1, -1, + -1, -1, + /*0xff37*/ 1269, + -1, -1, -1, + /*0xff25*/ 1251, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, + /*0x118bb*/ 1484, + -1, + /*0xff23*/ 1249, + -1, + /*0x104b1*/ 1314, + -1, -1, + /*0x04f6*/ 416, + -1, + /*0x10b1*/ 501, + -1, -1, -1, -1, + /*0x10d51*/ 1436, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, + /*0x16e55*/ 1510, + -1, -1, -1, -1, -1, + /*0x1ef8*/ 712, + /*0x1e78*/ 646, + -1, -1, -1, -1, -1, -1, + -1, -1, + /*0x1058f*/ 1378, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, + /*0x16e47*/ 1496, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, + /*0x118b1*/ 1474, + -1, -1, -1, -1, -1, -1, + -1, + /*0x04f8*/ 417, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, + /*0x1f0b*/ 719, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, + /*0x16e5e*/ 1519, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, + /*0x10595*/ 1383, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, + /*0x16e5c*/ 1517, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, + /*0xff31*/ 1263, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, + /*0x10591*/ 1380, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, + /*0x16e4b*/ 1500, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, + /*0x16e49*/ 1498, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + /*0x10581*/ 1365, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + /*0x16e41*/ 1490, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, + /*0xab72*/ 1157, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, + /*0xab7e*/ 1169, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, + /*0x16e4d*/ 1502, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, + /*0x10585*/ 1369, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, + /*0x16e51*/ 1506, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, + /*0xab7a*/ 1165, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, + /*0xab74*/ 1159, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + /*0xab7c*/ 1167, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + /*0xab76*/ 1161, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + /*0xab78*/ 1163 + }; + + if (code <= MAX_CODE_VALUE && code >= MIN_CODE_VALUE) + { + register unsigned int key = onigenc_unicode_CaseFold_11_hash(code); + + if (key <= MAX_HASH_VALUE) + { + register short s = wordlist[key]; + + if (s >= 0 && code1_equal(code, CaseFold_11_Table[s].from)) + return &CaseFold_11_Table[s].to; + } + } + return 0; +} + +static const CaseUnfold_11_Type CaseUnfold_11_Table[] = { +#define CaseUnfold_11 (*(CaseUnfold_11_Type (*)[1422])(CaseUnfold_11_Table+0)) + {0x0061, {1|U, {0x0041}}}, + {0x0062, {1|U, {0x0042}}}, + {0x0063, {1|U, {0x0043}}}, + {0x0064, {1|U, {0x0044}}}, + {0x0065, {1|U, {0x0045}}}, + {0x0066, {1|U, {0x0046}}}, + {0x0067, {1|U, {0x0047}}}, + {0x0068, {1|U, {0x0048}}}, + {0x006a, {1|U, {0x004a}}}, + {0x006b, {2|U, {0x004b, 0x212a}}}, + {0x006c, {1|U, {0x004c}}}, + {0x006d, {1|U, {0x004d}}}, + {0x006e, {1|U, {0x004e}}}, + {0x006f, {1|U, {0x004f}}}, + {0x0070, {1|U, {0x0050}}}, + {0x0071, {1|U, {0x0051}}}, + {0x0072, {1|U, {0x0052}}}, + {0x0073, {2|U, {0x0053, 0x017f}}}, + {0x0074, {1|U, {0x0054}}}, + {0x0075, {1|U, {0x0055}}}, + {0x0076, {1|U, {0x0056}}}, + {0x0077, {1|U, {0x0057}}}, + {0x0078, {1|U, {0x0058}}}, + {0x0079, {1|U, {0x0059}}}, + {0x007a, {1|U, {0x005a}}}, + {0x00e0, {1|U, {0x00c0}}}, + {0x00e1, {1|U, {0x00c1}}}, + {0x00e2, {1|U, {0x00c2}}}, + {0x00e3, {1|U, {0x00c3}}}, + {0x00e4, {1|U, {0x00c4}}}, + {0x00e5, {2|U, {0x00c5, 0x212b}}}, + {0x00e6, {1|U, {0x00c6}}}, + {0x00e7, {1|U, {0x00c7}}}, + {0x00e8, {1|U, {0x00c8}}}, + {0x00e9, {1|U, {0x00c9}}}, + {0x00ea, {1|U, {0x00ca}}}, + {0x00eb, {1|U, {0x00cb}}}, + {0x00ec, {1|U, {0x00cc}}}, + {0x00ed, {1|U, {0x00cd}}}, + {0x00ee, {1|U, {0x00ce}}}, + {0x00ef, {1|U, {0x00cf}}}, + {0x00f0, {1|U, {0x00d0}}}, + {0x00f1, {1|U, {0x00d1}}}, + {0x00f2, {1|U, {0x00d2}}}, + {0x00f3, {1|U, {0x00d3}}}, + {0x00f4, {1|U, {0x00d4}}}, + {0x00f5, {1|U, {0x00d5}}}, + {0x00f6, {1|U, {0x00d6}}}, + {0x00f8, {1|U, {0x00d8}}}, + {0x00f9, {1|U, {0x00d9}}}, + {0x00fa, {1|U, {0x00da}}}, + {0x00fb, {1|U, {0x00db}}}, + {0x00fc, {1|U, {0x00dc}}}, + {0x00fd, {1|U, {0x00dd}}}, + {0x00fe, {1|U, {0x00de}}}, + {0x00ff, {1|U, {0x0178}}}, + {0x0101, {1|U, {0x0100}}}, + {0x0103, {1|U, {0x0102}}}, + {0x0105, {1|U, {0x0104}}}, + {0x0107, {1|U, {0x0106}}}, + {0x0109, {1|U, {0x0108}}}, + {0x010b, {1|U, {0x010a}}}, + {0x010d, {1|U, {0x010c}}}, + {0x010f, {1|U, {0x010e}}}, + {0x0111, {1|U, {0x0110}}}, + {0x0113, {1|U, {0x0112}}}, + {0x0115, {1|U, {0x0114}}}, + {0x0117, {1|U, {0x0116}}}, + {0x0119, {1|U, {0x0118}}}, + {0x011b, {1|U, {0x011a}}}, + {0x011d, {1|U, {0x011c}}}, + {0x011f, {1|U, {0x011e}}}, + {0x0121, {1|U, {0x0120}}}, + {0x0123, {1|U, {0x0122}}}, + {0x0125, {1|U, {0x0124}}}, + {0x0127, {1|U, {0x0126}}}, + {0x0129, {1|U, {0x0128}}}, + {0x012b, {1|U, {0x012a}}}, + {0x012d, {1|U, {0x012c}}}, + {0x012f, {1|U, {0x012e}}}, + {0x0133, {1|U, {0x0132}}}, + {0x0135, {1|U, {0x0134}}}, + {0x0137, {1|U, {0x0136}}}, + {0x013a, {1|U, {0x0139}}}, + {0x013c, {1|U, {0x013b}}}, + {0x013e, {1|U, {0x013d}}}, + {0x0140, {1|U, {0x013f}}}, + {0x0142, {1|U, {0x0141}}}, + {0x0144, {1|U, {0x0143}}}, + {0x0146, {1|U, {0x0145}}}, + {0x0148, {1|U, {0x0147}}}, + {0x014b, {1|U, {0x014a}}}, + {0x014d, {1|U, {0x014c}}}, + {0x014f, {1|U, {0x014e}}}, + {0x0151, {1|U, {0x0150}}}, + {0x0153, {1|U, {0x0152}}}, + {0x0155, {1|U, {0x0154}}}, + {0x0157, {1|U, {0x0156}}}, + {0x0159, {1|U, {0x0158}}}, + {0x015b, {1|U, {0x015a}}}, + {0x015d, {1|U, {0x015c}}}, + {0x015f, {1|U, {0x015e}}}, + {0x0161, {1|U, {0x0160}}}, + {0x0163, {1|U, {0x0162}}}, + {0x0165, {1|U, {0x0164}}}, + {0x0167, {1|U, {0x0166}}}, + {0x0169, {1|U, {0x0168}}}, + {0x016b, {1|U, {0x016a}}}, + {0x016d, {1|U, {0x016c}}}, + {0x016f, {1|U, {0x016e}}}, + {0x0171, {1|U, {0x0170}}}, + {0x0173, {1|U, {0x0172}}}, + {0x0175, {1|U, {0x0174}}}, + {0x0177, {1|U, {0x0176}}}, + {0x017a, {1|U, {0x0179}}}, + {0x017c, {1|U, {0x017b}}}, + {0x017e, {1|U, {0x017d}}}, + {0x0180, {1|U, {0x0243}}}, + {0x0183, {1|U, {0x0182}}}, + {0x0185, {1|U, {0x0184}}}, + {0x0188, {1|U, {0x0187}}}, + {0x018c, {1|U, {0x018b}}}, + {0x0192, {1|U, {0x0191}}}, + {0x0195, {1|U, {0x01f6}}}, + {0x0199, {1|U, {0x0198}}}, + {0x019a, {1|U, {0x023d}}}, + {0x019b, {1|U, {0xa7dc}}}, + {0x019e, {1|U, {0x0220}}}, + {0x01a1, {1|U, {0x01a0}}}, + {0x01a3, {1|U, {0x01a2}}}, + {0x01a5, {1|U, {0x01a4}}}, + {0x01a8, {1|U, {0x01a7}}}, + {0x01ad, {1|U, {0x01ac}}}, + {0x01b0, {1|U, {0x01af}}}, + {0x01b4, {1|U, {0x01b3}}}, + {0x01b6, {1|U, {0x01b5}}}, + {0x01b9, {1|U, {0x01b8}}}, + {0x01bd, {1|U, {0x01bc}}}, + {0x01bf, {1|U, {0x01f7}}}, + {0x01c6, {2|U|ST, {0x01c4, 0x01c5}}}, + {0x01c9, {2|U|ST, {0x01c7, 0x01c8}}}, + {0x01cc, {2|U|ST, {0x01ca, 0x01cb}}}, + {0x01ce, {1|U, {0x01cd}}}, + {0x01d0, {1|U, {0x01cf}}}, + {0x01d2, {1|U, {0x01d1}}}, + {0x01d4, {1|U, {0x01d3}}}, + {0x01d6, {1|U, {0x01d5}}}, + {0x01d8, {1|U, {0x01d7}}}, + {0x01da, {1|U, {0x01d9}}}, + {0x01dc, {1|U, {0x01db}}}, + {0x01dd, {1|U, {0x018e}}}, + {0x01df, {1|U, {0x01de}}}, + {0x01e1, {1|U, {0x01e0}}}, + {0x01e3, {1|U, {0x01e2}}}, + {0x01e5, {1|U, {0x01e4}}}, + {0x01e7, {1|U, {0x01e6}}}, + {0x01e9, {1|U, {0x01e8}}}, + {0x01eb, {1|U, {0x01ea}}}, + {0x01ed, {1|U, {0x01ec}}}, + {0x01ef, {1|U, {0x01ee}}}, + {0x01f3, {2|U|ST, {0x01f1, 0x01f2}}}, + {0x01f5, {1|U, {0x01f4}}}, + {0x01f9, {1|U, {0x01f8}}}, + {0x01fb, {1|U, {0x01fa}}}, + {0x01fd, {1|U, {0x01fc}}}, + {0x01ff, {1|U, {0x01fe}}}, + {0x0201, {1|U, {0x0200}}}, + {0x0203, {1|U, {0x0202}}}, + {0x0205, {1|U, {0x0204}}}, + {0x0207, {1|U, {0x0206}}}, + {0x0209, {1|U, {0x0208}}}, + {0x020b, {1|U, {0x020a}}}, + {0x020d, {1|U, {0x020c}}}, + {0x020f, {1|U, {0x020e}}}, + {0x0211, {1|U, {0x0210}}}, + {0x0213, {1|U, {0x0212}}}, + {0x0215, {1|U, {0x0214}}}, + {0x0217, {1|U, {0x0216}}}, + {0x0219, {1|U, {0x0218}}}, + {0x021b, {1|U, {0x021a}}}, + {0x021d, {1|U, {0x021c}}}, + {0x021f, {1|U, {0x021e}}}, + {0x0223, {1|U, {0x0222}}}, + {0x0225, {1|U, {0x0224}}}, + {0x0227, {1|U, {0x0226}}}, + {0x0229, {1|U, {0x0228}}}, + {0x022b, {1|U, {0x022a}}}, + {0x022d, {1|U, {0x022c}}}, + {0x022f, {1|U, {0x022e}}}, + {0x0231, {1|U, {0x0230}}}, + {0x0233, {1|U, {0x0232}}}, + {0x023c, {1|U, {0x023b}}}, + {0x023f, {1|U, {0x2c7e}}}, + {0x0240, {1|U, {0x2c7f}}}, + {0x0242, {1|U, {0x0241}}}, + {0x0247, {1|U, {0x0246}}}, + {0x0249, {1|U, {0x0248}}}, + {0x024b, {1|U, {0x024a}}}, + {0x024d, {1|U, {0x024c}}}, + {0x024f, {1|U, {0x024e}}}, + {0x0250, {1|U, {0x2c6f}}}, + {0x0251, {1|U, {0x2c6d}}}, + {0x0252, {1|U, {0x2c70}}}, + {0x0253, {1|U, {0x0181}}}, + {0x0254, {1|U, {0x0186}}}, + {0x0256, {1|U, {0x0189}}}, + {0x0257, {1|U, {0x018a}}}, + {0x0259, {1|U, {0x018f}}}, + {0x025b, {1|U, {0x0190}}}, + {0x025c, {1|U, {0xa7ab}}}, + {0x0260, {1|U, {0x0193}}}, + {0x0261, {1|U, {0xa7ac}}}, + {0x0263, {1|U, {0x0194}}}, + {0x0264, {1|U, {0xa7cb}}}, + {0x0265, {1|U, {0xa78d}}}, + {0x0266, {1|U, {0xa7aa}}}, + {0x0268, {1|U, {0x0197}}}, + {0x0269, {1|U, {0x0196}}}, + {0x026a, {1|U, {0xa7ae}}}, + {0x026b, {1|U, {0x2c62}}}, + {0x026c, {1|U, {0xa7ad}}}, + {0x026f, {1|U, {0x019c}}}, + {0x0271, {1|U, {0x2c6e}}}, + {0x0272, {1|U, {0x019d}}}, + {0x0275, {1|U, {0x019f}}}, + {0x027d, {1|U, {0x2c64}}}, + {0x0280, {1|U, {0x01a6}}}, + {0x0282, {1|U, {0xa7c5}}}, + {0x0283, {1|U, {0x01a9}}}, + {0x0287, {1|U, {0xa7b1}}}, + {0x0288, {1|U, {0x01ae}}}, + {0x0289, {1|U, {0x0244}}}, + {0x028a, {1|U, {0x01b1}}}, + {0x028b, {1|U, {0x01b2}}}, + {0x028c, {1|U, {0x0245}}}, + {0x0292, {1|U, {0x01b7}}}, + {0x029d, {1|U, {0xa7b2}}}, + {0x029e, {1|U, {0xa7b0}}}, + {0x0371, {1|U, {0x0370}}}, + {0x0373, {1|U, {0x0372}}}, + {0x0377, {1|U, {0x0376}}}, + {0x037b, {1|U, {0x03fd}}}, + {0x037c, {1|U, {0x03fe}}}, + {0x037d, {1|U, {0x03ff}}}, + {0x03ac, {1|U, {0x0386}}}, + {0x03ad, {1|U, {0x0388}}}, + {0x03ae, {1|U, {0x0389}}}, + {0x03af, {1|U, {0x038a}}}, + {0x03b1, {1|U, {0x0391}}}, + {0x03b2, {2|U, {0x0392, 0x03d0}}}, + {0x03b3, {1|U, {0x0393}}}, + {0x03b4, {1|U, {0x0394}}}, + {0x03b5, {2|U, {0x0395, 0x03f5}}}, + {0x03b6, {1|U, {0x0396}}}, + {0x03b7, {1|U, {0x0397}}}, + {0x03b8, {3|U, {0x0398, 0x03d1, 0x03f4}}}, + {0x03b9, {3|U, {0x0399, 0x0345, 0x1fbe}}}, + {0x03ba, {2|U, {0x039a, 0x03f0}}}, + {0x03bb, {1|U, {0x039b}}}, + {0x03bc, {2|U, {0x039c, 0x00b5}}}, + {0x03bd, {1|U, {0x039d}}}, + {0x03be, {1|U, {0x039e}}}, + {0x03bf, {1|U, {0x039f}}}, + {0x03c0, {2|U, {0x03a0, 0x03d6}}}, + {0x03c1, {2|U, {0x03a1, 0x03f1}}}, + {0x03c3, {2|U, {0x03a3, 0x03c2}}}, + {0x03c4, {1|U, {0x03a4}}}, + {0x03c5, {1|U, {0x03a5}}}, + {0x03c6, {2|U, {0x03a6, 0x03d5}}}, + {0x03c7, {1|U, {0x03a7}}}, + {0x03c8, {1|U, {0x03a8}}}, + {0x03c9, {2|U, {0x03a9, 0x2126}}}, + {0x03ca, {1|U, {0x03aa}}}, + {0x03cb, {1|U, {0x03ab}}}, + {0x03cc, {1|U, {0x038c}}}, + {0x03cd, {1|U, {0x038e}}}, + {0x03ce, {1|U, {0x038f}}}, + {0x03d7, {1|U, {0x03cf}}}, + {0x03d9, {1|U, {0x03d8}}}, + {0x03db, {1|U, {0x03da}}}, + {0x03dd, {1|U, {0x03dc}}}, + {0x03df, {1|U, {0x03de}}}, + {0x03e1, {1|U, {0x03e0}}}, + {0x03e3, {1|U, {0x03e2}}}, + {0x03e5, {1|U, {0x03e4}}}, + {0x03e7, {1|U, {0x03e6}}}, + {0x03e9, {1|U, {0x03e8}}}, + {0x03eb, {1|U, {0x03ea}}}, + {0x03ed, {1|U, {0x03ec}}}, + {0x03ef, {1|U, {0x03ee}}}, + {0x03f2, {1|U, {0x03f9}}}, + {0x03f3, {1|U, {0x037f}}}, + {0x03f8, {1|U, {0x03f7}}}, + {0x03fb, {1|U, {0x03fa}}}, + {0x0430, {1|U, {0x0410}}}, + {0x0431, {1|U, {0x0411}}}, + {0x0432, {2|U, {0x0412, 0x1c80}}}, + {0x0433, {1|U, {0x0413}}}, + {0x0434, {2|U, {0x0414, 0x1c81}}}, + {0x0435, {1|U, {0x0415}}}, + {0x0436, {1|U, {0x0416}}}, + {0x0437, {1|U, {0x0417}}}, + {0x0438, {1|U, {0x0418}}}, + {0x0439, {1|U, {0x0419}}}, + {0x043a, {1|U, {0x041a}}}, + {0x043b, {1|U, {0x041b}}}, + {0x043c, {1|U, {0x041c}}}, + {0x043d, {1|U, {0x041d}}}, + {0x043e, {2|U, {0x041e, 0x1c82}}}, + {0x043f, {1|U, {0x041f}}}, + {0x0440, {1|U, {0x0420}}}, + {0x0441, {2|U, {0x0421, 0x1c83}}}, + {0x0442, {3|U, {0x0422, 0x1c84, 0x1c85}}}, + {0x0443, {1|U, {0x0423}}}, + {0x0444, {1|U, {0x0424}}}, + {0x0445, {1|U, {0x0425}}}, + {0x0446, {1|U, {0x0426}}}, + {0x0447, {1|U, {0x0427}}}, + {0x0448, {1|U, {0x0428}}}, + {0x0449, {1|U, {0x0429}}}, + {0x044a, {2|U, {0x042a, 0x1c86}}}, + {0x044b, {1|U, {0x042b}}}, + {0x044c, {1|U, {0x042c}}}, + {0x044d, {1|U, {0x042d}}}, + {0x044e, {1|U, {0x042e}}}, + {0x044f, {1|U, {0x042f}}}, + {0x0450, {1|U, {0x0400}}}, + {0x0451, {1|U, {0x0401}}}, + {0x0452, {1|U, {0x0402}}}, + {0x0453, {1|U, {0x0403}}}, + {0x0454, {1|U, {0x0404}}}, + {0x0455, {1|U, {0x0405}}}, + {0x0456, {1|U, {0x0406}}}, + {0x0457, {1|U, {0x0407}}}, + {0x0458, {1|U, {0x0408}}}, + {0x0459, {1|U, {0x0409}}}, + {0x045a, {1|U, {0x040a}}}, + {0x045b, {1|U, {0x040b}}}, + {0x045c, {1|U, {0x040c}}}, + {0x045d, {1|U, {0x040d}}}, + {0x045e, {1|U, {0x040e}}}, + {0x045f, {1|U, {0x040f}}}, + {0x0461, {1|U, {0x0460}}}, + {0x0463, {2|U, {0x0462, 0x1c87}}}, + {0x0465, {1|U, {0x0464}}}, + {0x0467, {1|U, {0x0466}}}, + {0x0469, {1|U, {0x0468}}}, + {0x046b, {1|U, {0x046a}}}, + {0x046d, {1|U, {0x046c}}}, + {0x046f, {1|U, {0x046e}}}, + {0x0471, {1|U, {0x0470}}}, + {0x0473, {1|U, {0x0472}}}, + {0x0475, {1|U, {0x0474}}}, + {0x0477, {1|U, {0x0476}}}, + {0x0479, {1|U, {0x0478}}}, + {0x047b, {1|U, {0x047a}}}, + {0x047d, {1|U, {0x047c}}}, + {0x047f, {1|U, {0x047e}}}, + {0x0481, {1|U, {0x0480}}}, + {0x048b, {1|U, {0x048a}}}, + {0x048d, {1|U, {0x048c}}}, + {0x048f, {1|U, {0x048e}}}, + {0x0491, {1|U, {0x0490}}}, + {0x0493, {1|U, {0x0492}}}, + {0x0495, {1|U, {0x0494}}}, + {0x0497, {1|U, {0x0496}}}, + {0x0499, {1|U, {0x0498}}}, + {0x049b, {1|U, {0x049a}}}, + {0x049d, {1|U, {0x049c}}}, + {0x049f, {1|U, {0x049e}}}, + {0x04a1, {1|U, {0x04a0}}}, + {0x04a3, {1|U, {0x04a2}}}, + {0x04a5, {1|U, {0x04a4}}}, + {0x04a7, {1|U, {0x04a6}}}, + {0x04a9, {1|U, {0x04a8}}}, + {0x04ab, {1|U, {0x04aa}}}, + {0x04ad, {1|U, {0x04ac}}}, + {0x04af, {1|U, {0x04ae}}}, + {0x04b1, {1|U, {0x04b0}}}, + {0x04b3, {1|U, {0x04b2}}}, + {0x04b5, {1|U, {0x04b4}}}, + {0x04b7, {1|U, {0x04b6}}}, + {0x04b9, {1|U, {0x04b8}}}, + {0x04bb, {1|U, {0x04ba}}}, + {0x04bd, {1|U, {0x04bc}}}, + {0x04bf, {1|U, {0x04be}}}, + {0x04c2, {1|U, {0x04c1}}}, + {0x04c4, {1|U, {0x04c3}}}, + {0x04c6, {1|U, {0x04c5}}}, + {0x04c8, {1|U, {0x04c7}}}, + {0x04ca, {1|U, {0x04c9}}}, + {0x04cc, {1|U, {0x04cb}}}, + {0x04ce, {1|U, {0x04cd}}}, + {0x04cf, {1|U, {0x04c0}}}, + {0x04d1, {1|U, {0x04d0}}}, + {0x04d3, {1|U, {0x04d2}}}, + {0x04d5, {1|U, {0x04d4}}}, + {0x04d7, {1|U, {0x04d6}}}, + {0x04d9, {1|U, {0x04d8}}}, + {0x04db, {1|U, {0x04da}}}, + {0x04dd, {1|U, {0x04dc}}}, + {0x04df, {1|U, {0x04de}}}, + {0x04e1, {1|U, {0x04e0}}}, + {0x04e3, {1|U, {0x04e2}}}, + {0x04e5, {1|U, {0x04e4}}}, + {0x04e7, {1|U, {0x04e6}}}, + {0x04e9, {1|U, {0x04e8}}}, + {0x04eb, {1|U, {0x04ea}}}, + {0x04ed, {1|U, {0x04ec}}}, + {0x04ef, {1|U, {0x04ee}}}, + {0x04f1, {1|U, {0x04f0}}}, + {0x04f3, {1|U, {0x04f2}}}, + {0x04f5, {1|U, {0x04f4}}}, + {0x04f7, {1|U, {0x04f6}}}, + {0x04f9, {1|U, {0x04f8}}}, + {0x04fb, {1|U, {0x04fa}}}, + {0x04fd, {1|U, {0x04fc}}}, + {0x04ff, {1|U, {0x04fe}}}, + {0x0501, {1|U, {0x0500}}}, + {0x0503, {1|U, {0x0502}}}, + {0x0505, {1|U, {0x0504}}}, + {0x0507, {1|U, {0x0506}}}, + {0x0509, {1|U, {0x0508}}}, + {0x050b, {1|U, {0x050a}}}, + {0x050d, {1|U, {0x050c}}}, + {0x050f, {1|U, {0x050e}}}, + {0x0511, {1|U, {0x0510}}}, + {0x0513, {1|U, {0x0512}}}, + {0x0515, {1|U, {0x0514}}}, + {0x0517, {1|U, {0x0516}}}, + {0x0519, {1|U, {0x0518}}}, + {0x051b, {1|U, {0x051a}}}, + {0x051d, {1|U, {0x051c}}}, + {0x051f, {1|U, {0x051e}}}, + {0x0521, {1|U, {0x0520}}}, + {0x0523, {1|U, {0x0522}}}, + {0x0525, {1|U, {0x0524}}}, + {0x0527, {1|U, {0x0526}}}, + {0x0529, {1|U, {0x0528}}}, + {0x052b, {1|U, {0x052a}}}, + {0x052d, {1|U, {0x052c}}}, + {0x052f, {1|U, {0x052e}}}, + {0x0561, {1|U, {0x0531}}}, + {0x0562, {1|U, {0x0532}}}, + {0x0563, {1|U, {0x0533}}}, + {0x0564, {1|U, {0x0534}}}, + {0x0565, {1|U, {0x0535}}}, + {0x0566, {1|U, {0x0536}}}, + {0x0567, {1|U, {0x0537}}}, + {0x0568, {1|U, {0x0538}}}, + {0x0569, {1|U, {0x0539}}}, + {0x056a, {1|U, {0x053a}}}, + {0x056b, {1|U, {0x053b}}}, + {0x056c, {1|U, {0x053c}}}, + {0x056d, {1|U, {0x053d}}}, + {0x056e, {1|U, {0x053e}}}, + {0x056f, {1|U, {0x053f}}}, + {0x0570, {1|U, {0x0540}}}, + {0x0571, {1|U, {0x0541}}}, + {0x0572, {1|U, {0x0542}}}, + {0x0573, {1|U, {0x0543}}}, + {0x0574, {1|U, {0x0544}}}, + {0x0575, {1|U, {0x0545}}}, + {0x0576, {1|U, {0x0546}}}, + {0x0577, {1|U, {0x0547}}}, + {0x0578, {1|U, {0x0548}}}, + {0x0579, {1|U, {0x0549}}}, + {0x057a, {1|U, {0x054a}}}, + {0x057b, {1|U, {0x054b}}}, + {0x057c, {1|U, {0x054c}}}, + {0x057d, {1|U, {0x054d}}}, + {0x057e, {1|U, {0x054e}}}, + {0x057f, {1|U, {0x054f}}}, + {0x0580, {1|U, {0x0550}}}, + {0x0581, {1|U, {0x0551}}}, + {0x0582, {1|U, {0x0552}}}, + {0x0583, {1|U, {0x0553}}}, + {0x0584, {1|U, {0x0554}}}, + {0x0585, {1|U, {0x0555}}}, + {0x0586, {1|U, {0x0556}}}, + {0x10d0, {1|U|IT, {0x1c90}}}, + {0x10d1, {1|U|IT, {0x1c91}}}, + {0x10d2, {1|U|IT, {0x1c92}}}, + {0x10d3, {1|U|IT, {0x1c93}}}, + {0x10d4, {1|U|IT, {0x1c94}}}, + {0x10d5, {1|U|IT, {0x1c95}}}, + {0x10d6, {1|U|IT, {0x1c96}}}, + {0x10d7, {1|U|IT, {0x1c97}}}, + {0x10d8, {1|U|IT, {0x1c98}}}, + {0x10d9, {1|U|IT, {0x1c99}}}, + {0x10da, {1|U|IT, {0x1c9a}}}, + {0x10db, {1|U|IT, {0x1c9b}}}, + {0x10dc, {1|U|IT, {0x1c9c}}}, + {0x10dd, {1|U|IT, {0x1c9d}}}, + {0x10de, {1|U|IT, {0x1c9e}}}, + {0x10df, {1|U|IT, {0x1c9f}}}, + {0x10e0, {1|U|IT, {0x1ca0}}}, + {0x10e1, {1|U|IT, {0x1ca1}}}, + {0x10e2, {1|U|IT, {0x1ca2}}}, + {0x10e3, {1|U|IT, {0x1ca3}}}, + {0x10e4, {1|U|IT, {0x1ca4}}}, + {0x10e5, {1|U|IT, {0x1ca5}}}, + {0x10e6, {1|U|IT, {0x1ca6}}}, + {0x10e7, {1|U|IT, {0x1ca7}}}, + {0x10e8, {1|U|IT, {0x1ca8}}}, + {0x10e9, {1|U|IT, {0x1ca9}}}, + {0x10ea, {1|U|IT, {0x1caa}}}, + {0x10eb, {1|U|IT, {0x1cab}}}, + {0x10ec, {1|U|IT, {0x1cac}}}, + {0x10ed, {1|U|IT, {0x1cad}}}, + {0x10ee, {1|U|IT, {0x1cae}}}, + {0x10ef, {1|U|IT, {0x1caf}}}, + {0x10f0, {1|U|IT, {0x1cb0}}}, + {0x10f1, {1|U|IT, {0x1cb1}}}, + {0x10f2, {1|U|IT, {0x1cb2}}}, + {0x10f3, {1|U|IT, {0x1cb3}}}, + {0x10f4, {1|U|IT, {0x1cb4}}}, + {0x10f5, {1|U|IT, {0x1cb5}}}, + {0x10f6, {1|U|IT, {0x1cb6}}}, + {0x10f7, {1|U|IT, {0x1cb7}}}, + {0x10f8, {1|U|IT, {0x1cb8}}}, + {0x10f9, {1|U|IT, {0x1cb9}}}, + {0x10fa, {1|U|IT, {0x1cba}}}, + {0x10fd, {1|U|IT, {0x1cbd}}}, + {0x10fe, {1|U|IT, {0x1cbe}}}, + {0x10ff, {1|U|IT, {0x1cbf}}}, + {0x13a0, {1|D, {0xab70}}}, + {0x13a1, {1|D, {0xab71}}}, + {0x13a2, {1|D, {0xab72}}}, + {0x13a3, {1|D, {0xab73}}}, + {0x13a4, {1|D, {0xab74}}}, + {0x13a5, {1|D, {0xab75}}}, + {0x13a6, {1|D, {0xab76}}}, + {0x13a7, {1|D, {0xab77}}}, + {0x13a8, {1|D, {0xab78}}}, + {0x13a9, {1|D, {0xab79}}}, + {0x13aa, {1|D, {0xab7a}}}, + {0x13ab, {1|D, {0xab7b}}}, + {0x13ac, {1|D, {0xab7c}}}, + {0x13ad, {1|D, {0xab7d}}}, + {0x13ae, {1|D, {0xab7e}}}, + {0x13af, {1|D, {0xab7f}}}, + {0x13b0, {1|D, {0xab80}}}, + {0x13b1, {1|D, {0xab81}}}, + {0x13b2, {1|D, {0xab82}}}, + {0x13b3, {1|D, {0xab83}}}, + {0x13b4, {1|D, {0xab84}}}, + {0x13b5, {1|D, {0xab85}}}, + {0x13b6, {1|D, {0xab86}}}, + {0x13b7, {1|D, {0xab87}}}, + {0x13b8, {1|D, {0xab88}}}, + {0x13b9, {1|D, {0xab89}}}, + {0x13ba, {1|D, {0xab8a}}}, + {0x13bb, {1|D, {0xab8b}}}, + {0x13bc, {1|D, {0xab8c}}}, + {0x13bd, {1|D, {0xab8d}}}, + {0x13be, {1|D, {0xab8e}}}, + {0x13bf, {1|D, {0xab8f}}}, + {0x13c0, {1|D, {0xab90}}}, + {0x13c1, {1|D, {0xab91}}}, + {0x13c2, {1|D, {0xab92}}}, + {0x13c3, {1|D, {0xab93}}}, + {0x13c4, {1|D, {0xab94}}}, + {0x13c5, {1|D, {0xab95}}}, + {0x13c6, {1|D, {0xab96}}}, + {0x13c7, {1|D, {0xab97}}}, + {0x13c8, {1|D, {0xab98}}}, + {0x13c9, {1|D, {0xab99}}}, + {0x13ca, {1|D, {0xab9a}}}, + {0x13cb, {1|D, {0xab9b}}}, + {0x13cc, {1|D, {0xab9c}}}, + {0x13cd, {1|D, {0xab9d}}}, + {0x13ce, {1|D, {0xab9e}}}, + {0x13cf, {1|D, {0xab9f}}}, + {0x13d0, {1|D, {0xaba0}}}, + {0x13d1, {1|D, {0xaba1}}}, + {0x13d2, {1|D, {0xaba2}}}, + {0x13d3, {1|D, {0xaba3}}}, + {0x13d4, {1|D, {0xaba4}}}, + {0x13d5, {1|D, {0xaba5}}}, + {0x13d6, {1|D, {0xaba6}}}, + {0x13d7, {1|D, {0xaba7}}}, + {0x13d8, {1|D, {0xaba8}}}, + {0x13d9, {1|D, {0xaba9}}}, + {0x13da, {1|D, {0xabaa}}}, + {0x13db, {1|D, {0xabab}}}, + {0x13dc, {1|D, {0xabac}}}, + {0x13dd, {1|D, {0xabad}}}, + {0x13de, {1|D, {0xabae}}}, + {0x13df, {1|D, {0xabaf}}}, + {0x13e0, {1|D, {0xabb0}}}, + {0x13e1, {1|D, {0xabb1}}}, + {0x13e2, {1|D, {0xabb2}}}, + {0x13e3, {1|D, {0xabb3}}}, + {0x13e4, {1|D, {0xabb4}}}, + {0x13e5, {1|D, {0xabb5}}}, + {0x13e6, {1|D, {0xabb6}}}, + {0x13e7, {1|D, {0xabb7}}}, + {0x13e8, {1|D, {0xabb8}}}, + {0x13e9, {1|D, {0xabb9}}}, + {0x13ea, {1|D, {0xabba}}}, + {0x13eb, {1|D, {0xabbb}}}, + {0x13ec, {1|D, {0xabbc}}}, + {0x13ed, {1|D, {0xabbd}}}, + {0x13ee, {1|D, {0xabbe}}}, + {0x13ef, {1|D, {0xabbf}}}, + {0x13f0, {1|D, {0x13f8}}}, + {0x13f1, {1|D, {0x13f9}}}, + {0x13f2, {1|D, {0x13fa}}}, + {0x13f3, {1|D, {0x13fb}}}, + {0x13f4, {1|D, {0x13fc}}}, + {0x13f5, {1|D, {0x13fd}}}, + {0x1c8a, {1|U, {0x1c89}}}, + {0x1d79, {1|U, {0xa77d}}}, + {0x1d7d, {1|U, {0x2c63}}}, + {0x1d8e, {1|U, {0xa7c6}}}, + {0x1e01, {1|U, {0x1e00}}}, + {0x1e03, {1|U, {0x1e02}}}, + {0x1e05, {1|U, {0x1e04}}}, + {0x1e07, {1|U, {0x1e06}}}, + {0x1e09, {1|U, {0x1e08}}}, + {0x1e0b, {1|U, {0x1e0a}}}, + {0x1e0d, {1|U, {0x1e0c}}}, + {0x1e0f, {1|U, {0x1e0e}}}, + {0x1e11, {1|U, {0x1e10}}}, + {0x1e13, {1|U, {0x1e12}}}, + {0x1e15, {1|U, {0x1e14}}}, + {0x1e17, {1|U, {0x1e16}}}, + {0x1e19, {1|U, {0x1e18}}}, + {0x1e1b, {1|U, {0x1e1a}}}, + {0x1e1d, {1|U, {0x1e1c}}}, + {0x1e1f, {1|U, {0x1e1e}}}, + {0x1e21, {1|U, {0x1e20}}}, + {0x1e23, {1|U, {0x1e22}}}, + {0x1e25, {1|U, {0x1e24}}}, + {0x1e27, {1|U, {0x1e26}}}, + {0x1e29, {1|U, {0x1e28}}}, + {0x1e2b, {1|U, {0x1e2a}}}, + {0x1e2d, {1|U, {0x1e2c}}}, + {0x1e2f, {1|U, {0x1e2e}}}, + {0x1e31, {1|U, {0x1e30}}}, + {0x1e33, {1|U, {0x1e32}}}, + {0x1e35, {1|U, {0x1e34}}}, + {0x1e37, {1|U, {0x1e36}}}, + {0x1e39, {1|U, {0x1e38}}}, + {0x1e3b, {1|U, {0x1e3a}}}, + {0x1e3d, {1|U, {0x1e3c}}}, + {0x1e3f, {1|U, {0x1e3e}}}, + {0x1e41, {1|U, {0x1e40}}}, + {0x1e43, {1|U, {0x1e42}}}, + {0x1e45, {1|U, {0x1e44}}}, + {0x1e47, {1|U, {0x1e46}}}, + {0x1e49, {1|U, {0x1e48}}}, + {0x1e4b, {1|U, {0x1e4a}}}, + {0x1e4d, {1|U, {0x1e4c}}}, + {0x1e4f, {1|U, {0x1e4e}}}, + {0x1e51, {1|U, {0x1e50}}}, + {0x1e53, {1|U, {0x1e52}}}, + {0x1e55, {1|U, {0x1e54}}}, + {0x1e57, {1|U, {0x1e56}}}, + {0x1e59, {1|U, {0x1e58}}}, + {0x1e5b, {1|U, {0x1e5a}}}, + {0x1e5d, {1|U, {0x1e5c}}}, + {0x1e5f, {1|U, {0x1e5e}}}, + {0x1e61, {2|U, {0x1e60, 0x1e9b}}}, + {0x1e63, {1|U, {0x1e62}}}, + {0x1e65, {1|U, {0x1e64}}}, + {0x1e67, {1|U, {0x1e66}}}, + {0x1e69, {1|U, {0x1e68}}}, + {0x1e6b, {1|U, {0x1e6a}}}, + {0x1e6d, {1|U, {0x1e6c}}}, + {0x1e6f, {1|U, {0x1e6e}}}, + {0x1e71, {1|U, {0x1e70}}}, + {0x1e73, {1|U, {0x1e72}}}, + {0x1e75, {1|U, {0x1e74}}}, + {0x1e77, {1|U, {0x1e76}}}, + {0x1e79, {1|U, {0x1e78}}}, + {0x1e7b, {1|U, {0x1e7a}}}, + {0x1e7d, {1|U, {0x1e7c}}}, + {0x1e7f, {1|U, {0x1e7e}}}, + {0x1e81, {1|U, {0x1e80}}}, + {0x1e83, {1|U, {0x1e82}}}, + {0x1e85, {1|U, {0x1e84}}}, + {0x1e87, {1|U, {0x1e86}}}, + {0x1e89, {1|U, {0x1e88}}}, + {0x1e8b, {1|U, {0x1e8a}}}, + {0x1e8d, {1|U, {0x1e8c}}}, + {0x1e8f, {1|U, {0x1e8e}}}, + {0x1e91, {1|U, {0x1e90}}}, + {0x1e93, {1|U, {0x1e92}}}, + {0x1e95, {1|U, {0x1e94}}}, + {0x1ea1, {1|U, {0x1ea0}}}, + {0x1ea3, {1|U, {0x1ea2}}}, + {0x1ea5, {1|U, {0x1ea4}}}, + {0x1ea7, {1|U, {0x1ea6}}}, + {0x1ea9, {1|U, {0x1ea8}}}, + {0x1eab, {1|U, {0x1eaa}}}, + {0x1ead, {1|U, {0x1eac}}}, + {0x1eaf, {1|U, {0x1eae}}}, + {0x1eb1, {1|U, {0x1eb0}}}, + {0x1eb3, {1|U, {0x1eb2}}}, + {0x1eb5, {1|U, {0x1eb4}}}, + {0x1eb7, {1|U, {0x1eb6}}}, + {0x1eb9, {1|U, {0x1eb8}}}, + {0x1ebb, {1|U, {0x1eba}}}, + {0x1ebd, {1|U, {0x1ebc}}}, + {0x1ebf, {1|U, {0x1ebe}}}, + {0x1ec1, {1|U, {0x1ec0}}}, + {0x1ec3, {1|U, {0x1ec2}}}, + {0x1ec5, {1|U, {0x1ec4}}}, + {0x1ec7, {1|U, {0x1ec6}}}, + {0x1ec9, {1|U, {0x1ec8}}}, + {0x1ecb, {1|U, {0x1eca}}}, + {0x1ecd, {1|U, {0x1ecc}}}, + {0x1ecf, {1|U, {0x1ece}}}, + {0x1ed1, {1|U, {0x1ed0}}}, + {0x1ed3, {1|U, {0x1ed2}}}, + {0x1ed5, {1|U, {0x1ed4}}}, + {0x1ed7, {1|U, {0x1ed6}}}, + {0x1ed9, {1|U, {0x1ed8}}}, + {0x1edb, {1|U, {0x1eda}}}, + {0x1edd, {1|U, {0x1edc}}}, + {0x1edf, {1|U, {0x1ede}}}, + {0x1ee1, {1|U, {0x1ee0}}}, + {0x1ee3, {1|U, {0x1ee2}}}, + {0x1ee5, {1|U, {0x1ee4}}}, + {0x1ee7, {1|U, {0x1ee6}}}, + {0x1ee9, {1|U, {0x1ee8}}}, + {0x1eeb, {1|U, {0x1eea}}}, + {0x1eed, {1|U, {0x1eec}}}, + {0x1eef, {1|U, {0x1eee}}}, + {0x1ef1, {1|U, {0x1ef0}}}, + {0x1ef3, {1|U, {0x1ef2}}}, + {0x1ef5, {1|U, {0x1ef4}}}, + {0x1ef7, {1|U, {0x1ef6}}}, + {0x1ef9, {1|U, {0x1ef8}}}, + {0x1efb, {1|U, {0x1efa}}}, + {0x1efd, {1|U, {0x1efc}}}, + {0x1eff, {1|U, {0x1efe}}}, + {0x1f00, {1|U, {0x1f08}}}, + {0x1f01, {1|U, {0x1f09}}}, + {0x1f02, {1|U, {0x1f0a}}}, + {0x1f03, {1|U, {0x1f0b}}}, + {0x1f04, {1|U, {0x1f0c}}}, + {0x1f05, {1|U, {0x1f0d}}}, + {0x1f06, {1|U, {0x1f0e}}}, + {0x1f07, {1|U, {0x1f0f}}}, + {0x1f10, {1|U, {0x1f18}}}, + {0x1f11, {1|U, {0x1f19}}}, + {0x1f12, {1|U, {0x1f1a}}}, + {0x1f13, {1|U, {0x1f1b}}}, + {0x1f14, {1|U, {0x1f1c}}}, + {0x1f15, {1|U, {0x1f1d}}}, + {0x1f20, {1|U, {0x1f28}}}, + {0x1f21, {1|U, {0x1f29}}}, + {0x1f22, {1|U, {0x1f2a}}}, + {0x1f23, {1|U, {0x1f2b}}}, + {0x1f24, {1|U, {0x1f2c}}}, + {0x1f25, {1|U, {0x1f2d}}}, + {0x1f26, {1|U, {0x1f2e}}}, + {0x1f27, {1|U, {0x1f2f}}}, + {0x1f30, {1|U, {0x1f38}}}, + {0x1f31, {1|U, {0x1f39}}}, + {0x1f32, {1|U, {0x1f3a}}}, + {0x1f33, {1|U, {0x1f3b}}}, + {0x1f34, {1|U, {0x1f3c}}}, + {0x1f35, {1|U, {0x1f3d}}}, + {0x1f36, {1|U, {0x1f3e}}}, + {0x1f37, {1|U, {0x1f3f}}}, + {0x1f40, {1|U, {0x1f48}}}, + {0x1f41, {1|U, {0x1f49}}}, + {0x1f42, {1|U, {0x1f4a}}}, + {0x1f43, {1|U, {0x1f4b}}}, + {0x1f44, {1|U, {0x1f4c}}}, + {0x1f45, {1|U, {0x1f4d}}}, + {0x1f51, {1|U, {0x1f59}}}, + {0x1f53, {1|U, {0x1f5b}}}, + {0x1f55, {1|U, {0x1f5d}}}, + {0x1f57, {1|U, {0x1f5f}}}, + {0x1f60, {1|U, {0x1f68}}}, + {0x1f61, {1|U, {0x1f69}}}, + {0x1f62, {1|U, {0x1f6a}}}, + {0x1f63, {1|U, {0x1f6b}}}, + {0x1f64, {1|U, {0x1f6c}}}, + {0x1f65, {1|U, {0x1f6d}}}, + {0x1f66, {1|U, {0x1f6e}}}, + {0x1f67, {1|U, {0x1f6f}}}, + {0x1f70, {1|U, {0x1fba}}}, + {0x1f71, {1|U, {0x1fbb}}}, + {0x1f72, {1|U, {0x1fc8}}}, + {0x1f73, {1|U, {0x1fc9}}}, + {0x1f74, {1|U, {0x1fca}}}, + {0x1f75, {1|U, {0x1fcb}}}, + {0x1f76, {1|U, {0x1fda}}}, + {0x1f77, {1|U, {0x1fdb}}}, + {0x1f78, {1|U, {0x1ff8}}}, + {0x1f79, {1|U, {0x1ff9}}}, + {0x1f7a, {1|U, {0x1fea}}}, + {0x1f7b, {1|U, {0x1feb}}}, + {0x1f7c, {1|U, {0x1ffa}}}, + {0x1f7d, {1|U, {0x1ffb}}}, + {0x1fb0, {1|U, {0x1fb8}}}, + {0x1fb1, {1|U, {0x1fb9}}}, + {0x1fd0, {1|U, {0x1fd8}}}, + {0x1fd1, {1|U, {0x1fd9}}}, + {0x1fe0, {1|U, {0x1fe8}}}, + {0x1fe1, {1|U, {0x1fe9}}}, + {0x1fe5, {1|U, {0x1fec}}}, + {0x214e, {1|U, {0x2132}}}, + {0x2170, {1|U, {0x2160}}}, + {0x2171, {1|U, {0x2161}}}, + {0x2172, {1|U, {0x2162}}}, + {0x2173, {1|U, {0x2163}}}, + {0x2174, {1|U, {0x2164}}}, + {0x2175, {1|U, {0x2165}}}, + {0x2176, {1|U, {0x2166}}}, + {0x2177, {1|U, {0x2167}}}, + {0x2178, {1|U, {0x2168}}}, + {0x2179, {1|U, {0x2169}}}, + {0x217a, {1|U, {0x216a}}}, + {0x217b, {1|U, {0x216b}}}, + {0x217c, {1|U, {0x216c}}}, + {0x217d, {1|U, {0x216d}}}, + {0x217e, {1|U, {0x216e}}}, + {0x217f, {1|U, {0x216f}}}, + {0x2184, {1|U, {0x2183}}}, + {0x24d0, {1|U, {0x24b6}}}, + {0x24d1, {1|U, {0x24b7}}}, + {0x24d2, {1|U, {0x24b8}}}, + {0x24d3, {1|U, {0x24b9}}}, + {0x24d4, {1|U, {0x24ba}}}, + {0x24d5, {1|U, {0x24bb}}}, + {0x24d6, {1|U, {0x24bc}}}, + {0x24d7, {1|U, {0x24bd}}}, + {0x24d8, {1|U, {0x24be}}}, + {0x24d9, {1|U, {0x24bf}}}, + {0x24da, {1|U, {0x24c0}}}, + {0x24db, {1|U, {0x24c1}}}, + {0x24dc, {1|U, {0x24c2}}}, + {0x24dd, {1|U, {0x24c3}}}, + {0x24de, {1|U, {0x24c4}}}, + {0x24df, {1|U, {0x24c5}}}, + {0x24e0, {1|U, {0x24c6}}}, + {0x24e1, {1|U, {0x24c7}}}, + {0x24e2, {1|U, {0x24c8}}}, + {0x24e3, {1|U, {0x24c9}}}, + {0x24e4, {1|U, {0x24ca}}}, + {0x24e5, {1|U, {0x24cb}}}, + {0x24e6, {1|U, {0x24cc}}}, + {0x24e7, {1|U, {0x24cd}}}, + {0x24e8, {1|U, {0x24ce}}}, + {0x24e9, {1|U, {0x24cf}}}, + {0x2c30, {1|U, {0x2c00}}}, + {0x2c31, {1|U, {0x2c01}}}, + {0x2c32, {1|U, {0x2c02}}}, + {0x2c33, {1|U, {0x2c03}}}, + {0x2c34, {1|U, {0x2c04}}}, + {0x2c35, {1|U, {0x2c05}}}, + {0x2c36, {1|U, {0x2c06}}}, + {0x2c37, {1|U, {0x2c07}}}, + {0x2c38, {1|U, {0x2c08}}}, + {0x2c39, {1|U, {0x2c09}}}, + {0x2c3a, {1|U, {0x2c0a}}}, + {0x2c3b, {1|U, {0x2c0b}}}, + {0x2c3c, {1|U, {0x2c0c}}}, + {0x2c3d, {1|U, {0x2c0d}}}, + {0x2c3e, {1|U, {0x2c0e}}}, + {0x2c3f, {1|U, {0x2c0f}}}, + {0x2c40, {1|U, {0x2c10}}}, + {0x2c41, {1|U, {0x2c11}}}, + {0x2c42, {1|U, {0x2c12}}}, + {0x2c43, {1|U, {0x2c13}}}, + {0x2c44, {1|U, {0x2c14}}}, + {0x2c45, {1|U, {0x2c15}}}, + {0x2c46, {1|U, {0x2c16}}}, + {0x2c47, {1|U, {0x2c17}}}, + {0x2c48, {1|U, {0x2c18}}}, + {0x2c49, {1|U, {0x2c19}}}, + {0x2c4a, {1|U, {0x2c1a}}}, + {0x2c4b, {1|U, {0x2c1b}}}, + {0x2c4c, {1|U, {0x2c1c}}}, + {0x2c4d, {1|U, {0x2c1d}}}, + {0x2c4e, {1|U, {0x2c1e}}}, + {0x2c4f, {1|U, {0x2c1f}}}, + {0x2c50, {1|U, {0x2c20}}}, + {0x2c51, {1|U, {0x2c21}}}, + {0x2c52, {1|U, {0x2c22}}}, + {0x2c53, {1|U, {0x2c23}}}, + {0x2c54, {1|U, {0x2c24}}}, + {0x2c55, {1|U, {0x2c25}}}, + {0x2c56, {1|U, {0x2c26}}}, + {0x2c57, {1|U, {0x2c27}}}, + {0x2c58, {1|U, {0x2c28}}}, + {0x2c59, {1|U, {0x2c29}}}, + {0x2c5a, {1|U, {0x2c2a}}}, + {0x2c5b, {1|U, {0x2c2b}}}, + {0x2c5c, {1|U, {0x2c2c}}}, + {0x2c5d, {1|U, {0x2c2d}}}, + {0x2c5e, {1|U, {0x2c2e}}}, + {0x2c5f, {1|U, {0x2c2f}}}, + {0x2c61, {1|U, {0x2c60}}}, + {0x2c65, {1|U, {0x023a}}}, + {0x2c66, {1|U, {0x023e}}}, + {0x2c68, {1|U, {0x2c67}}}, + {0x2c6a, {1|U, {0x2c69}}}, + {0x2c6c, {1|U, {0x2c6b}}}, + {0x2c73, {1|U, {0x2c72}}}, + {0x2c76, {1|U, {0x2c75}}}, + {0x2c81, {1|U, {0x2c80}}}, + {0x2c83, {1|U, {0x2c82}}}, + {0x2c85, {1|U, {0x2c84}}}, + {0x2c87, {1|U, {0x2c86}}}, + {0x2c89, {1|U, {0x2c88}}}, + {0x2c8b, {1|U, {0x2c8a}}}, + {0x2c8d, {1|U, {0x2c8c}}}, + {0x2c8f, {1|U, {0x2c8e}}}, + {0x2c91, {1|U, {0x2c90}}}, + {0x2c93, {1|U, {0x2c92}}}, + {0x2c95, {1|U, {0x2c94}}}, + {0x2c97, {1|U, {0x2c96}}}, + {0x2c99, {1|U, {0x2c98}}}, + {0x2c9b, {1|U, {0x2c9a}}}, + {0x2c9d, {1|U, {0x2c9c}}}, + {0x2c9f, {1|U, {0x2c9e}}}, + {0x2ca1, {1|U, {0x2ca0}}}, + {0x2ca3, {1|U, {0x2ca2}}}, + {0x2ca5, {1|U, {0x2ca4}}}, + {0x2ca7, {1|U, {0x2ca6}}}, + {0x2ca9, {1|U, {0x2ca8}}}, + {0x2cab, {1|U, {0x2caa}}}, + {0x2cad, {1|U, {0x2cac}}}, + {0x2caf, {1|U, {0x2cae}}}, + {0x2cb1, {1|U, {0x2cb0}}}, + {0x2cb3, {1|U, {0x2cb2}}}, + {0x2cb5, {1|U, {0x2cb4}}}, + {0x2cb7, {1|U, {0x2cb6}}}, + {0x2cb9, {1|U, {0x2cb8}}}, + {0x2cbb, {1|U, {0x2cba}}}, + {0x2cbd, {1|U, {0x2cbc}}}, + {0x2cbf, {1|U, {0x2cbe}}}, + {0x2cc1, {1|U, {0x2cc0}}}, + {0x2cc3, {1|U, {0x2cc2}}}, + {0x2cc5, {1|U, {0x2cc4}}}, + {0x2cc7, {1|U, {0x2cc6}}}, + {0x2cc9, {1|U, {0x2cc8}}}, + {0x2ccb, {1|U, {0x2cca}}}, + {0x2ccd, {1|U, {0x2ccc}}}, + {0x2ccf, {1|U, {0x2cce}}}, + {0x2cd1, {1|U, {0x2cd0}}}, + {0x2cd3, {1|U, {0x2cd2}}}, + {0x2cd5, {1|U, {0x2cd4}}}, + {0x2cd7, {1|U, {0x2cd6}}}, + {0x2cd9, {1|U, {0x2cd8}}}, + {0x2cdb, {1|U, {0x2cda}}}, + {0x2cdd, {1|U, {0x2cdc}}}, + {0x2cdf, {1|U, {0x2cde}}}, + {0x2ce1, {1|U, {0x2ce0}}}, + {0x2ce3, {1|U, {0x2ce2}}}, + {0x2cec, {1|U, {0x2ceb}}}, + {0x2cee, {1|U, {0x2ced}}}, + {0x2cf3, {1|U, {0x2cf2}}}, + {0x2d00, {1|U, {0x10a0}}}, + {0x2d01, {1|U, {0x10a1}}}, + {0x2d02, {1|U, {0x10a2}}}, + {0x2d03, {1|U, {0x10a3}}}, + {0x2d04, {1|U, {0x10a4}}}, + {0x2d05, {1|U, {0x10a5}}}, + {0x2d06, {1|U, {0x10a6}}}, + {0x2d07, {1|U, {0x10a7}}}, + {0x2d08, {1|U, {0x10a8}}}, + {0x2d09, {1|U, {0x10a9}}}, + {0x2d0a, {1|U, {0x10aa}}}, + {0x2d0b, {1|U, {0x10ab}}}, + {0x2d0c, {1|U, {0x10ac}}}, + {0x2d0d, {1|U, {0x10ad}}}, + {0x2d0e, {1|U, {0x10ae}}}, + {0x2d0f, {1|U, {0x10af}}}, + {0x2d10, {1|U, {0x10b0}}}, + {0x2d11, {1|U, {0x10b1}}}, + {0x2d12, {1|U, {0x10b2}}}, + {0x2d13, {1|U, {0x10b3}}}, + {0x2d14, {1|U, {0x10b4}}}, + {0x2d15, {1|U, {0x10b5}}}, + {0x2d16, {1|U, {0x10b6}}}, + {0x2d17, {1|U, {0x10b7}}}, + {0x2d18, {1|U, {0x10b8}}}, + {0x2d19, {1|U, {0x10b9}}}, + {0x2d1a, {1|U, {0x10ba}}}, + {0x2d1b, {1|U, {0x10bb}}}, + {0x2d1c, {1|U, {0x10bc}}}, + {0x2d1d, {1|U, {0x10bd}}}, + {0x2d1e, {1|U, {0x10be}}}, + {0x2d1f, {1|U, {0x10bf}}}, + {0x2d20, {1|U, {0x10c0}}}, + {0x2d21, {1|U, {0x10c1}}}, + {0x2d22, {1|U, {0x10c2}}}, + {0x2d23, {1|U, {0x10c3}}}, + {0x2d24, {1|U, {0x10c4}}}, + {0x2d25, {1|U, {0x10c5}}}, + {0x2d27, {1|U, {0x10c7}}}, + {0x2d2d, {1|U, {0x10cd}}}, + {0xa641, {1|U, {0xa640}}}, + {0xa643, {1|U, {0xa642}}}, + {0xa645, {1|U, {0xa644}}}, + {0xa647, {1|U, {0xa646}}}, + {0xa649, {1|U, {0xa648}}}, + {0xa64b, {2|U, {0xa64a, 0x1c88}}}, + {0xa64d, {1|U, {0xa64c}}}, + {0xa64f, {1|U, {0xa64e}}}, + {0xa651, {1|U, {0xa650}}}, + {0xa653, {1|U, {0xa652}}}, + {0xa655, {1|U, {0xa654}}}, + {0xa657, {1|U, {0xa656}}}, + {0xa659, {1|U, {0xa658}}}, + {0xa65b, {1|U, {0xa65a}}}, + {0xa65d, {1|U, {0xa65c}}}, + {0xa65f, {1|U, {0xa65e}}}, + {0xa661, {1|U, {0xa660}}}, + {0xa663, {1|U, {0xa662}}}, + {0xa665, {1|U, {0xa664}}}, + {0xa667, {1|U, {0xa666}}}, + {0xa669, {1|U, {0xa668}}}, + {0xa66b, {1|U, {0xa66a}}}, + {0xa66d, {1|U, {0xa66c}}}, + {0xa681, {1|U, {0xa680}}}, + {0xa683, {1|U, {0xa682}}}, + {0xa685, {1|U, {0xa684}}}, + {0xa687, {1|U, {0xa686}}}, + {0xa689, {1|U, {0xa688}}}, + {0xa68b, {1|U, {0xa68a}}}, + {0xa68d, {1|U, {0xa68c}}}, + {0xa68f, {1|U, {0xa68e}}}, + {0xa691, {1|U, {0xa690}}}, + {0xa693, {1|U, {0xa692}}}, + {0xa695, {1|U, {0xa694}}}, + {0xa697, {1|U, {0xa696}}}, + {0xa699, {1|U, {0xa698}}}, + {0xa69b, {1|U, {0xa69a}}}, + {0xa723, {1|U, {0xa722}}}, + {0xa725, {1|U, {0xa724}}}, + {0xa727, {1|U, {0xa726}}}, + {0xa729, {1|U, {0xa728}}}, + {0xa72b, {1|U, {0xa72a}}}, + {0xa72d, {1|U, {0xa72c}}}, + {0xa72f, {1|U, {0xa72e}}}, + {0xa733, {1|U, {0xa732}}}, + {0xa735, {1|U, {0xa734}}}, + {0xa737, {1|U, {0xa736}}}, + {0xa739, {1|U, {0xa738}}}, + {0xa73b, {1|U, {0xa73a}}}, + {0xa73d, {1|U, {0xa73c}}}, + {0xa73f, {1|U, {0xa73e}}}, + {0xa741, {1|U, {0xa740}}}, + {0xa743, {1|U, {0xa742}}}, + {0xa745, {1|U, {0xa744}}}, + {0xa747, {1|U, {0xa746}}}, + {0xa749, {1|U, {0xa748}}}, + {0xa74b, {1|U, {0xa74a}}}, + {0xa74d, {1|U, {0xa74c}}}, + {0xa74f, {1|U, {0xa74e}}}, + {0xa751, {1|U, {0xa750}}}, + {0xa753, {1|U, {0xa752}}}, + {0xa755, {1|U, {0xa754}}}, + {0xa757, {1|U, {0xa756}}}, + {0xa759, {1|U, {0xa758}}}, + {0xa75b, {1|U, {0xa75a}}}, + {0xa75d, {1|U, {0xa75c}}}, + {0xa75f, {1|U, {0xa75e}}}, + {0xa761, {1|U, {0xa760}}}, + {0xa763, {1|U, {0xa762}}}, + {0xa765, {1|U, {0xa764}}}, + {0xa767, {1|U, {0xa766}}}, + {0xa769, {1|U, {0xa768}}}, + {0xa76b, {1|U, {0xa76a}}}, + {0xa76d, {1|U, {0xa76c}}}, + {0xa76f, {1|U, {0xa76e}}}, + {0xa77a, {1|U, {0xa779}}}, + {0xa77c, {1|U, {0xa77b}}}, + {0xa77f, {1|U, {0xa77e}}}, + {0xa781, {1|U, {0xa780}}}, + {0xa783, {1|U, {0xa782}}}, + {0xa785, {1|U, {0xa784}}}, + {0xa787, {1|U, {0xa786}}}, + {0xa78c, {1|U, {0xa78b}}}, + {0xa791, {1|U, {0xa790}}}, + {0xa793, {1|U, {0xa792}}}, + {0xa794, {1|U, {0xa7c4}}}, + {0xa797, {1|U, {0xa796}}}, + {0xa799, {1|U, {0xa798}}}, + {0xa79b, {1|U, {0xa79a}}}, + {0xa79d, {1|U, {0xa79c}}}, + {0xa79f, {1|U, {0xa79e}}}, + {0xa7a1, {1|U, {0xa7a0}}}, + {0xa7a3, {1|U, {0xa7a2}}}, + {0xa7a5, {1|U, {0xa7a4}}}, + {0xa7a7, {1|U, {0xa7a6}}}, + {0xa7a9, {1|U, {0xa7a8}}}, + {0xa7b5, {1|U, {0xa7b4}}}, + {0xa7b7, {1|U, {0xa7b6}}}, + {0xa7b9, {1|U, {0xa7b8}}}, + {0xa7bb, {1|U, {0xa7ba}}}, + {0xa7bd, {1|U, {0xa7bc}}}, + {0xa7bf, {1|U, {0xa7be}}}, + {0xa7c1, {1|U, {0xa7c0}}}, + {0xa7c3, {1|U, {0xa7c2}}}, + {0xa7c8, {1|U, {0xa7c7}}}, + {0xa7ca, {1|U, {0xa7c9}}}, + {0xa7cd, {1|U, {0xa7cc}}}, + {0xa7d1, {1|U, {0xa7d0}}}, + {0xa7d7, {1|U, {0xa7d6}}}, + {0xa7d9, {1|U, {0xa7d8}}}, + {0xa7db, {1|U, {0xa7da}}}, + {0xa7f6, {1|U, {0xa7f5}}}, + {0xab53, {1|U, {0xa7b3}}}, + {0xff41, {1|U, {0xff21}}}, + {0xff42, {1|U, {0xff22}}}, + {0xff43, {1|U, {0xff23}}}, + {0xff44, {1|U, {0xff24}}}, + {0xff45, {1|U, {0xff25}}}, + {0xff46, {1|U, {0xff26}}}, + {0xff47, {1|U, {0xff27}}}, + {0xff48, {1|U, {0xff28}}}, + {0xff49, {1|U, {0xff29}}}, + {0xff4a, {1|U, {0xff2a}}}, + {0xff4b, {1|U, {0xff2b}}}, + {0xff4c, {1|U, {0xff2c}}}, + {0xff4d, {1|U, {0xff2d}}}, + {0xff4e, {1|U, {0xff2e}}}, + {0xff4f, {1|U, {0xff2f}}}, + {0xff50, {1|U, {0xff30}}}, + {0xff51, {1|U, {0xff31}}}, + {0xff52, {1|U, {0xff32}}}, + {0xff53, {1|U, {0xff33}}}, + {0xff54, {1|U, {0xff34}}}, + {0xff55, {1|U, {0xff35}}}, + {0xff56, {1|U, {0xff36}}}, + {0xff57, {1|U, {0xff37}}}, + {0xff58, {1|U, {0xff38}}}, + {0xff59, {1|U, {0xff39}}}, + {0xff5a, {1|U, {0xff3a}}}, + {0x10428, {1|U, {0x10400}}}, + {0x10429, {1|U, {0x10401}}}, + {0x1042a, {1|U, {0x10402}}}, + {0x1042b, {1|U, {0x10403}}}, + {0x1042c, {1|U, {0x10404}}}, + {0x1042d, {1|U, {0x10405}}}, + {0x1042e, {1|U, {0x10406}}}, + {0x1042f, {1|U, {0x10407}}}, + {0x10430, {1|U, {0x10408}}}, + {0x10431, {1|U, {0x10409}}}, + {0x10432, {1|U, {0x1040a}}}, + {0x10433, {1|U, {0x1040b}}}, + {0x10434, {1|U, {0x1040c}}}, + {0x10435, {1|U, {0x1040d}}}, + {0x10436, {1|U, {0x1040e}}}, + {0x10437, {1|U, {0x1040f}}}, + {0x10438, {1|U, {0x10410}}}, + {0x10439, {1|U, {0x10411}}}, + {0x1043a, {1|U, {0x10412}}}, + {0x1043b, {1|U, {0x10413}}}, + {0x1043c, {1|U, {0x10414}}}, + {0x1043d, {1|U, {0x10415}}}, + {0x1043e, {1|U, {0x10416}}}, + {0x1043f, {1|U, {0x10417}}}, + {0x10440, {1|U, {0x10418}}}, + {0x10441, {1|U, {0x10419}}}, + {0x10442, {1|U, {0x1041a}}}, + {0x10443, {1|U, {0x1041b}}}, + {0x10444, {1|U, {0x1041c}}}, + {0x10445, {1|U, {0x1041d}}}, + {0x10446, {1|U, {0x1041e}}}, + {0x10447, {1|U, {0x1041f}}}, + {0x10448, {1|U, {0x10420}}}, + {0x10449, {1|U, {0x10421}}}, + {0x1044a, {1|U, {0x10422}}}, + {0x1044b, {1|U, {0x10423}}}, + {0x1044c, {1|U, {0x10424}}}, + {0x1044d, {1|U, {0x10425}}}, + {0x1044e, {1|U, {0x10426}}}, + {0x1044f, {1|U, {0x10427}}}, + {0x104d8, {1|U, {0x104b0}}}, + {0x104d9, {1|U, {0x104b1}}}, + {0x104da, {1|U, {0x104b2}}}, + {0x104db, {1|U, {0x104b3}}}, + {0x104dc, {1|U, {0x104b4}}}, + {0x104dd, {1|U, {0x104b5}}}, + {0x104de, {1|U, {0x104b6}}}, + {0x104df, {1|U, {0x104b7}}}, + {0x104e0, {1|U, {0x104b8}}}, + {0x104e1, {1|U, {0x104b9}}}, + {0x104e2, {1|U, {0x104ba}}}, + {0x104e3, {1|U, {0x104bb}}}, + {0x104e4, {1|U, {0x104bc}}}, + {0x104e5, {1|U, {0x104bd}}}, + {0x104e6, {1|U, {0x104be}}}, + {0x104e7, {1|U, {0x104bf}}}, + {0x104e8, {1|U, {0x104c0}}}, + {0x104e9, {1|U, {0x104c1}}}, + {0x104ea, {1|U, {0x104c2}}}, + {0x104eb, {1|U, {0x104c3}}}, + {0x104ec, {1|U, {0x104c4}}}, + {0x104ed, {1|U, {0x104c5}}}, + {0x104ee, {1|U, {0x104c6}}}, + {0x104ef, {1|U, {0x104c7}}}, + {0x104f0, {1|U, {0x104c8}}}, + {0x104f1, {1|U, {0x104c9}}}, + {0x104f2, {1|U, {0x104ca}}}, + {0x104f3, {1|U, {0x104cb}}}, + {0x104f4, {1|U, {0x104cc}}}, + {0x104f5, {1|U, {0x104cd}}}, + {0x104f6, {1|U, {0x104ce}}}, + {0x104f7, {1|U, {0x104cf}}}, + {0x104f8, {1|U, {0x104d0}}}, + {0x104f9, {1|U, {0x104d1}}}, + {0x104fa, {1|U, {0x104d2}}}, + {0x104fb, {1|U, {0x104d3}}}, + {0x10597, {1|U, {0x10570}}}, + {0x10598, {1|U, {0x10571}}}, + {0x10599, {1|U, {0x10572}}}, + {0x1059a, {1|U, {0x10573}}}, + {0x1059b, {1|U, {0x10574}}}, + {0x1059c, {1|U, {0x10575}}}, + {0x1059d, {1|U, {0x10576}}}, + {0x1059e, {1|U, {0x10577}}}, + {0x1059f, {1|U, {0x10578}}}, + {0x105a0, {1|U, {0x10579}}}, + {0x105a1, {1|U, {0x1057a}}}, + {0x105a3, {1|U, {0x1057c}}}, + {0x105a4, {1|U, {0x1057d}}}, + {0x105a5, {1|U, {0x1057e}}}, + {0x105a6, {1|U, {0x1057f}}}, + {0x105a7, {1|U, {0x10580}}}, + {0x105a8, {1|U, {0x10581}}}, + {0x105a9, {1|U, {0x10582}}}, + {0x105aa, {1|U, {0x10583}}}, + {0x105ab, {1|U, {0x10584}}}, + {0x105ac, {1|U, {0x10585}}}, + {0x105ad, {1|U, {0x10586}}}, + {0x105ae, {1|U, {0x10587}}}, + {0x105af, {1|U, {0x10588}}}, + {0x105b0, {1|U, {0x10589}}}, + {0x105b1, {1|U, {0x1058a}}}, + {0x105b3, {1|U, {0x1058c}}}, + {0x105b4, {1|U, {0x1058d}}}, + {0x105b5, {1|U, {0x1058e}}}, + {0x105b6, {1|U, {0x1058f}}}, + {0x105b7, {1|U, {0x10590}}}, + {0x105b8, {1|U, {0x10591}}}, + {0x105b9, {1|U, {0x10592}}}, + {0x105bb, {1|U, {0x10594}}}, + {0x105bc, {1|U, {0x10595}}}, + {0x10cc0, {1|U, {0x10c80}}}, + {0x10cc1, {1|U, {0x10c81}}}, + {0x10cc2, {1|U, {0x10c82}}}, + {0x10cc3, {1|U, {0x10c83}}}, + {0x10cc4, {1|U, {0x10c84}}}, + {0x10cc5, {1|U, {0x10c85}}}, + {0x10cc6, {1|U, {0x10c86}}}, + {0x10cc7, {1|U, {0x10c87}}}, + {0x10cc8, {1|U, {0x10c88}}}, + {0x10cc9, {1|U, {0x10c89}}}, + {0x10cca, {1|U, {0x10c8a}}}, + {0x10ccb, {1|U, {0x10c8b}}}, + {0x10ccc, {1|U, {0x10c8c}}}, + {0x10ccd, {1|U, {0x10c8d}}}, + {0x10cce, {1|U, {0x10c8e}}}, + {0x10ccf, {1|U, {0x10c8f}}}, + {0x10cd0, {1|U, {0x10c90}}}, + {0x10cd1, {1|U, {0x10c91}}}, + {0x10cd2, {1|U, {0x10c92}}}, + {0x10cd3, {1|U, {0x10c93}}}, + {0x10cd4, {1|U, {0x10c94}}}, + {0x10cd5, {1|U, {0x10c95}}}, + {0x10cd6, {1|U, {0x10c96}}}, + {0x10cd7, {1|U, {0x10c97}}}, + {0x10cd8, {1|U, {0x10c98}}}, + {0x10cd9, {1|U, {0x10c99}}}, + {0x10cda, {1|U, {0x10c9a}}}, + {0x10cdb, {1|U, {0x10c9b}}}, + {0x10cdc, {1|U, {0x10c9c}}}, + {0x10cdd, {1|U, {0x10c9d}}}, + {0x10cde, {1|U, {0x10c9e}}}, + {0x10cdf, {1|U, {0x10c9f}}}, + {0x10ce0, {1|U, {0x10ca0}}}, + {0x10ce1, {1|U, {0x10ca1}}}, + {0x10ce2, {1|U, {0x10ca2}}}, + {0x10ce3, {1|U, {0x10ca3}}}, + {0x10ce4, {1|U, {0x10ca4}}}, + {0x10ce5, {1|U, {0x10ca5}}}, + {0x10ce6, {1|U, {0x10ca6}}}, + {0x10ce7, {1|U, {0x10ca7}}}, + {0x10ce8, {1|U, {0x10ca8}}}, + {0x10ce9, {1|U, {0x10ca9}}}, + {0x10cea, {1|U, {0x10caa}}}, + {0x10ceb, {1|U, {0x10cab}}}, + {0x10cec, {1|U, {0x10cac}}}, + {0x10ced, {1|U, {0x10cad}}}, + {0x10cee, {1|U, {0x10cae}}}, + {0x10cef, {1|U, {0x10caf}}}, + {0x10cf0, {1|U, {0x10cb0}}}, + {0x10cf1, {1|U, {0x10cb1}}}, + {0x10cf2, {1|U, {0x10cb2}}}, + {0x10d70, {1|U, {0x10d50}}}, + {0x10d71, {1|U, {0x10d51}}}, + {0x10d72, {1|U, {0x10d52}}}, + {0x10d73, {1|U, {0x10d53}}}, + {0x10d74, {1|U, {0x10d54}}}, + {0x10d75, {1|U, {0x10d55}}}, + {0x10d76, {1|U, {0x10d56}}}, + {0x10d77, {1|U, {0x10d57}}}, + {0x10d78, {1|U, {0x10d58}}}, + {0x10d79, {1|U, {0x10d59}}}, + {0x10d7a, {1|U, {0x10d5a}}}, + {0x10d7b, {1|U, {0x10d5b}}}, + {0x10d7c, {1|U, {0x10d5c}}}, + {0x10d7d, {1|U, {0x10d5d}}}, + {0x10d7e, {1|U, {0x10d5e}}}, + {0x10d7f, {1|U, {0x10d5f}}}, + {0x10d80, {1|U, {0x10d60}}}, + {0x10d81, {1|U, {0x10d61}}}, + {0x10d82, {1|U, {0x10d62}}}, + {0x10d83, {1|U, {0x10d63}}}, + {0x10d84, {1|U, {0x10d64}}}, + {0x10d85, {1|U, {0x10d65}}}, + {0x118c0, {1|U, {0x118a0}}}, + {0x118c1, {1|U, {0x118a1}}}, + {0x118c2, {1|U, {0x118a2}}}, + {0x118c3, {1|U, {0x118a3}}}, + {0x118c4, {1|U, {0x118a4}}}, + {0x118c5, {1|U, {0x118a5}}}, + {0x118c6, {1|U, {0x118a6}}}, + {0x118c7, {1|U, {0x118a7}}}, + {0x118c8, {1|U, {0x118a8}}}, + {0x118c9, {1|U, {0x118a9}}}, + {0x118ca, {1|U, {0x118aa}}}, + {0x118cb, {1|U, {0x118ab}}}, + {0x118cc, {1|U, {0x118ac}}}, + {0x118cd, {1|U, {0x118ad}}}, + {0x118ce, {1|U, {0x118ae}}}, + {0x118cf, {1|U, {0x118af}}}, + {0x118d0, {1|U, {0x118b0}}}, + {0x118d1, {1|U, {0x118b1}}}, + {0x118d2, {1|U, {0x118b2}}}, + {0x118d3, {1|U, {0x118b3}}}, + {0x118d4, {1|U, {0x118b4}}}, + {0x118d5, {1|U, {0x118b5}}}, + {0x118d6, {1|U, {0x118b6}}}, + {0x118d7, {1|U, {0x118b7}}}, + {0x118d8, {1|U, {0x118b8}}}, + {0x118d9, {1|U, {0x118b9}}}, + {0x118da, {1|U, {0x118ba}}}, + {0x118db, {1|U, {0x118bb}}}, + {0x118dc, {1|U, {0x118bc}}}, + {0x118dd, {1|U, {0x118bd}}}, + {0x118de, {1|U, {0x118be}}}, + {0x118df, {1|U, {0x118bf}}}, + {0x16e60, {1|U, {0x16e40}}}, + {0x16e61, {1|U, {0x16e41}}}, + {0x16e62, {1|U, {0x16e42}}}, + {0x16e63, {1|U, {0x16e43}}}, + {0x16e64, {1|U, {0x16e44}}}, + {0x16e65, {1|U, {0x16e45}}}, + {0x16e66, {1|U, {0x16e46}}}, + {0x16e67, {1|U, {0x16e47}}}, + {0x16e68, {1|U, {0x16e48}}}, + {0x16e69, {1|U, {0x16e49}}}, + {0x16e6a, {1|U, {0x16e4a}}}, + {0x16e6b, {1|U, {0x16e4b}}}, + {0x16e6c, {1|U, {0x16e4c}}}, + {0x16e6d, {1|U, {0x16e4d}}}, + {0x16e6e, {1|U, {0x16e4e}}}, + {0x16e6f, {1|U, {0x16e4f}}}, + {0x16e70, {1|U, {0x16e50}}}, + {0x16e71, {1|U, {0x16e51}}}, + {0x16e72, {1|U, {0x16e52}}}, + {0x16e73, {1|U, {0x16e53}}}, + {0x16e74, {1|U, {0x16e54}}}, + {0x16e75, {1|U, {0x16e55}}}, + {0x16e76, {1|U, {0x16e56}}}, + {0x16e77, {1|U, {0x16e57}}}, + {0x16e78, {1|U, {0x16e58}}}, + {0x16e79, {1|U, {0x16e59}}}, + {0x16e7a, {1|U, {0x16e5a}}}, + {0x16e7b, {1|U, {0x16e5b}}}, + {0x16e7c, {1|U, {0x16e5c}}}, + {0x16e7d, {1|U, {0x16e5d}}}, + {0x16e7e, {1|U, {0x16e5e}}}, + {0x16e7f, {1|U, {0x16e5f}}}, + {0x1e922, {1|U, {0x1e900}}}, + {0x1e923, {1|U, {0x1e901}}}, + {0x1e924, {1|U, {0x1e902}}}, + {0x1e925, {1|U, {0x1e903}}}, + {0x1e926, {1|U, {0x1e904}}}, + {0x1e927, {1|U, {0x1e905}}}, + {0x1e928, {1|U, {0x1e906}}}, + {0x1e929, {1|U, {0x1e907}}}, + {0x1e92a, {1|U, {0x1e908}}}, + {0x1e92b, {1|U, {0x1e909}}}, + {0x1e92c, {1|U, {0x1e90a}}}, + {0x1e92d, {1|U, {0x1e90b}}}, + {0x1e92e, {1|U, {0x1e90c}}}, + {0x1e92f, {1|U, {0x1e90d}}}, + {0x1e930, {1|U, {0x1e90e}}}, + {0x1e931, {1|U, {0x1e90f}}}, + {0x1e932, {1|U, {0x1e910}}}, + {0x1e933, {1|U, {0x1e911}}}, + {0x1e934, {1|U, {0x1e912}}}, + {0x1e935, {1|U, {0x1e913}}}, + {0x1e936, {1|U, {0x1e914}}}, + {0x1e937, {1|U, {0x1e915}}}, + {0x1e938, {1|U, {0x1e916}}}, + {0x1e939, {1|U, {0x1e917}}}, + {0x1e93a, {1|U, {0x1e918}}}, + {0x1e93b, {1|U, {0x1e919}}}, + {0x1e93c, {1|U, {0x1e91a}}}, + {0x1e93d, {1|U, {0x1e91b}}}, + {0x1e93e, {1|U, {0x1e91c}}}, + {0x1e93f, {1|U, {0x1e91d}}}, + {0x1e940, {1|U, {0x1e91e}}}, + {0x1e941, {1|U, {0x1e91f}}}, + {0x1e942, {1|U, {0x1e920}}}, + {0x1e943, {1|U, {0x1e921}}}, +#define CaseUnfold_11_Locale (*(CaseUnfold_11_Type (*)[1])(CaseUnfold_11_Table+1422)) + {0x0069, {1|U, {0x0049}}}, +}; + +/* ANSI-C code produced by gperf version 3.1 */ +/* Command-line: gperf -7 -k1,2,3 -F,-1 -c -j1 -i1 -t -T -E -C -H onigenc_unicode_CaseUnfold_11_hash -N onigenc_unicode_CaseUnfold_11_lookup -n */ + +/* maximum key range = 2713, duplicates = 0 */ + +#ifdef __GNUC__ +__inline +#else +#ifdef __cplusplus +inline +#endif +#endif +/*ARGSUSED*/ +static unsigned int +onigenc_unicode_CaseUnfold_11_hash(const OnigCodePoint code) +{ + static const unsigned short asso_values[] = + { + 1, 2716, 2, 1, 4, 640, 9, 260, 231, 142, + 589, 20, 2, 3, 434, 372, 2716, 2716, 2716, 2716, + 2716, 2716, 2716, 2716, 2716, 2716, 2716, 2716, 2716, 112, + 404, 141, 2716, 2716, 2716, 2716, 2716, 120, 2716, 2716, + 2716, 2716, 2716, 1, 2716, 2716, 2716, 2716, 2716, 2716, + 2716, 2716, 2716, 395, 2716, 2716, 2716, 2716, 2716, 2716, + 2716, 3, 11, 6, 7, 8, 244, 723, 34, 1143, + 365, 1012, 56, 1546, 12, 1709, 9, 15, 14, 1796, + 241, 917, 87, 227, 47, 1535, 267, 1468, 1, 1612, + 49, 1184, 361, 10, 557, 1704, 51, 1814, 66, 1385, + 338, 786, 740, 659, 125, 801, 354, 1134, 249, 1252, + 327, 756, 193, 1116, 1511, 838, 1898, 703, 1796, 679, + 1745, 629, 1856, 827, 1832, 995, 1531, 973, 1806, 811, + 850, 511, 903, 500, 1517, 935, 1483, 876, 1461, 555, + 1790, 541, 1703, 465, 1274, 531, 1340, 250, 1667, 342, + 1660, 408, 1652, 194, 1622, 85, 1595, 70, 1578, 129, + 1492, 100, 1489, 1, 1450, 25, 1432, 35, 1180, 55, + 1415, 45, 459, 160, 1298, 317, 577, 220, 1224, 594, + 965, 373, 1322, 670, 1062, 1243, 966, 1045, 1124, 1160, + 1223, 1094, 1497, 1314 + }; + return asso_values[bits_of(code, 2)+66] + asso_values[bits_of(code, 1)+4] + asso_values[bits_of(code, 0)]; +} + +static const CodePointList3 * +onigenc_unicode_CaseUnfold_11_lookup(const OnigCodePoint code) +{ + enum + { + MIN_CODE_VALUE = 0x61, + MAX_CODE_VALUE = 0x1e943, + TOTAL_KEYWORDS = 1423, + MIN_WORD_LENGTH = 3, + MAX_WORD_LENGTH = 3, + MIN_HASH_VALUE = 3, + MAX_HASH_VALUE = 2715 + }; + + static const short wordlist[] = + { + -1, -1, -1, + /*0x13e1*/ 591, + /*0x0461*/ 342, + /*0x04e1*/ 402, + /*0x0061*/ 0, + -1, + /*0x104e1*/ 1189, + /*0x1e61*/ 664, + /*0x1ee1*/ 723, + /*0x0161*/ 102, + /*0x2ce1*/ 956, + /*0x1c8a*/ 612, + /*0x049b*/ 367, + -1, -1, + /*0x24e1*/ 843, + /*0x1e1b*/ 629, + /*0x048b*/ 359, + /*0x011b*/ 69, + /*0x2c9b*/ 921, + /*0x03e1*/ 282, + /*0x1e0b*/ 621, + /*0x1e8b*/ 685, + /*0x010b*/ 61, + /*0x2c8b*/ 913, + /*0x13e3*/ 593, + /*0x0463*/ 343, + /*0x04e3*/ 403, + /*0x0063*/ 2, + -1, + /*0x104e3*/ 1191, + /*0x1e63*/ 665, + /*0x1ee3*/ 724, + /*0x0163*/ 103, + /*0x2ce3*/ 957, + /*0x13e5*/ 595, + /*0x0465*/ 344, + /*0x04e5*/ 404, + /*0x0065*/ 4, + /*0x24e3*/ 845, + /*0x104e5*/ 1193, + /*0x1e65*/ 666, + /*0x1ee5*/ 725, + /*0x0165*/ 104, + /*0x03e3*/ 283, + /*0x13e9*/ 599, + /*0x0469*/ 346, + /*0x04e9*/ 406, + /*0x0069*/ 1422, + /*0x24e5*/ 847, + /*0x104e9*/ 1197, + /*0x1e69*/ 668, + /*0x1ee9*/ 727, + /*0x0169*/ 106, + /*0x03e5*/ 284, + /*0x13e7*/ 597, + /*0x0467*/ 345, + /*0x04e7*/ 405, + /*0x0067*/ 6, + /*0x24e9*/ 851, + /*0x104e7*/ 1195, + /*0x1e67*/ 667, + /*0x1ee7*/ 726, + /*0x0167*/ 105, + /*0x03e9*/ 286, + -1, + /*0x13a0*/ 526, + -1, -1, + /*0x24e7*/ 849, + /*0x13db*/ 585, + /*0x045b*/ 337, + /*0x04db*/ 399, + -1, + /*0x03e7*/ 285, + /*0x104db*/ 1183, + /*0x1e5b*/ 661, + /*0x1edb*/ 720, + /*0x015b*/ 99, + /*0x2cdb*/ 953, + -1, -1, -1, -1, + /*0x24db*/ 837, + /*0x13d9*/ 583, + /*0x0459*/ 335, + /*0x04d9*/ 398, + /*0xa761*/ 1068, + /*0x03db*/ 279, + /*0x104d9*/ 1181, + /*0x1e59*/ 660, + /*0x1ed9*/ 719, + /*0x0159*/ 98, + /*0x2cd9*/ 952, + -1, -1, -1, -1, + /*0x24d9*/ 835, + /*0x13df*/ 589, + /*0x045f*/ 341, + /*0x04df*/ 401, + -1, + /*0x03d9*/ 278, + /*0x104df*/ 1187, + /*0x1e5f*/ 663, + /*0x1edf*/ 722, + /*0x015f*/ 101, + /*0x2cdf*/ 955, + -1, -1, + /*0xa763*/ 1069, + -1, + /*0x24df*/ 841, + /*0x10ce1*/ 1284, + -1, -1, -1, + /*0x03df*/ 281, + /*0x10e1*/ 497, + -1, + /*0xa765*/ 1070, + -1, -1, + /*0x13a6*/ 532, + -1, -1, -1, + /*0x13dd*/ 587, + /*0x045d*/ 339, + /*0x04dd*/ 400, + /*0xa769*/ 1072, + -1, + /*0x104dd*/ 1185, + /*0x1e5d*/ 662, + /*0x1edd*/ 721, + /*0x015d*/ 100, + /*0x2cdd*/ 954, + /*0x10ce3*/ 1286, + -1, -1, + /*0xa767*/ 1071, + /*0x24dd*/ 839, + /*0x10e3*/ 499, + -1, -1, -1, + /*0x03dd*/ 280, + /*0x10ce5*/ 1288, + /*0x028a*/ 232, + -1, -1, + /*0x0288*/ 230, + /*0x10e5*/ 501, + /*0x028c*/ 234, + /*0x028b*/ 233, + /*0xa75b*/ 1065, + -1, + /*0x10ce9*/ 1292, + /*0x13eb*/ 601, + /*0x046b*/ 347, + /*0x04eb*/ 407, + /*0x006b*/ 9, + /*0x10e9*/ 505, + /*0x104eb*/ 1199, + /*0x1e6b*/ 669, + /*0x1eeb*/ 728, + /*0x016b*/ 107, + /*0x10ce7*/ 1290, + -1, -1, + /*0xa759*/ 1064, + -1, + /*0x10e7*/ 503, + /*0x0282*/ 227, + -1, + /*0x10d82*/ 1320, + -1, + /*0x03eb*/ 287, + -1, -1, -1, -1, + /*0x10cdb*/ 1278, + -1, -1, + /*0xa75f*/ 1067, + /*0x0292*/ 235, + /*0x10db*/ 491, + -1, -1, + /*0x029e*/ 237, + /*0x13ae*/ 540, + /*0x13d7*/ 581, + /*0x0457*/ 333, + /*0x04d7*/ 397, + /*0x1042e*/ 1146, + -1, + /*0x10cd9*/ 1276, + /*0x1e57*/ 659, + /*0x1ed7*/ 718, + /*0x0157*/ 97, + /*0x2cd7*/ 951, + /*0x10d9*/ 489, + -1, -1, -1, + /*0x24d7*/ 833, + -1, -1, -1, + /*0x03ae*/ 246, + /*0x03d7*/ 277, + /*0x10cdf*/ 1282, + -1, + /*0xa75d*/ 1066, + -1, -1, + /*0x10df*/ 495, + /*0x13ef*/ 605, + /*0x046f*/ 349, + /*0x04ef*/ 409, + /*0x006f*/ 13, + -1, + /*0x104ef*/ 1203, + /*0x1e6f*/ 671, + /*0x1eef*/ 730, + /*0x016f*/ 109, + /*0x0491*/ 362, + -1, + /*0x0261*/ 211, + -1, + /*0x1e11*/ 624, + /*0x1e91*/ 688, + /*0x0111*/ 64, + /*0x2c91*/ 916, + /*0xa79b*/ 1089, + -1, + /*0x03ef*/ 289, + /*0x021b*/ 179, + /*0xa78c*/ 1083, + /*0xa661*/ 1017, + /*0x10cdd*/ 1280, + /*0x1f61*/ 780, + /*0x020b*/ 171, + /*0x1d8e*/ 615, + /*0xa76b*/ 1073, + /*0x10dd*/ 493, + /*0x13aa*/ 536, + /*0x13d1*/ 575, + /*0x0451*/ 327, + /*0x04d1*/ 394, + /*0x1042a*/ 1142, + -1, + /*0x0263*/ 212, + /*0x1e51*/ 656, + /*0x1ed1*/ 715, + /*0x0151*/ 94, + /*0x2cd1*/ 948, + /*0x01e1*/ 152, + -1, -1, -1, + /*0x24d1*/ 827, + /*0x0265*/ 214, + /*0xa663*/ 1018, + -1, + /*0x1f63*/ 782, + /*0x019b*/ 126, + -1, + /*0x0188*/ 120, + -1, + /*0x018c*/ 121, + /*0x10ceb*/ 1294, + /*0x0269*/ 217, + /*0xa665*/ 1019, + /*0x1f02*/ 741, + /*0x1f65*/ 784, + /*0x10eb*/ 507, + -1, + /*0xa757*/ 1063, + -1, -1, + /*0x01e3*/ 153, + -1, + /*0xa669*/ 1021, + -1, -1, -1, + /*0x1f12*/ 749, + -1, -1, -1, + /*0x01e5*/ 154, + -1, + /*0xa667*/ 1020, + /*0xa7db*/ 1111, + /*0x1f67*/ 786, + /*0x1f06*/ 745, + /*0x025b*/ 208, + -1, -1, -1, + /*0x01e9*/ 156, + -1, + /*0x0192*/ 122, + /*0xa76f*/ 1075, + /*0x10cd7*/ 1274, + /*0x1f20*/ 753, + /*0x019e*/ 127, + /*0xa65b*/ 1014, + /*0xa7d9*/ 1110, + /*0x10d7*/ 487, + /*0x01e7*/ 155, + /*0x0259*/ 207, + -1, + /*0x13ed*/ 603, + /*0x046d*/ 348, + /*0x04ed*/ 408, + /*0x006d*/ 11, + -1, + /*0x104ed*/ 1201, + /*0x1e6d*/ 670, + /*0x1eed*/ 729, + /*0x016d*/ 108, + /*0xa659*/ 1013, + /*0x13ac*/ 538, + -1, -1, + /*0x1f10*/ 747, + /*0x1042c*/ 1144, + -1, -1, + /*0x10cef*/ 1298, + -1, + /*0x03ed*/ 288, + /*0xa751*/ 1060, + /*0x13a2*/ 528, + /*0x10ef*/ 511, + -1, + /*0xa65f*/ 1016, + /*0x13d3*/ 577, + /*0x0453*/ 329, + /*0x04d3*/ 395, + -1, + /*0x03ac*/ 244, + -1, + /*0x1e53*/ 657, + /*0x1ed3*/ 716, + /*0x0153*/ 95, + /*0x2cd3*/ 949, + -1, -1, + /*0x13a8*/ 534, + -1, + /*0x24d3*/ 829, + -1, + /*0x10428*/ 1140, + /*0x01df*/ 151, + -1, + /*0x2c61*/ 900, + -1, -1, + /*0x10cd1*/ 1268, + -1, -1, -1, + /*0x1f26*/ 759, + /*0x10d1*/ 481, + /*0xa65d*/ 1015, + -1, -1, + /*0x13f3*/ 609, + /*0x0473*/ 351, + /*0x04f3*/ 411, + /*0x0073*/ 17, + -1, + /*0x104f3*/ 1207, + /*0x1e73*/ 673, + /*0x1ef3*/ 732, + /*0x0173*/ 111, + /*0x2cf3*/ 960, + -1, + /*0x1059b*/ 1220, + /*0x0280*/ 226, + -1, + /*0x10d80*/ 1318, + /*0x01dd*/ 150, + -1, + /*0x026b*/ 219, + /*0xab53*/ 1113, + /*0x03f3*/ 291, + -1, -1, + /*0x2c65*/ 901, + -1, -1, -1, -1, -1, + /*0xa66b*/ 1022, + -1, -1, + /*0xa76d*/ 1074, + /*0x0582*/ 475, + -1, -1, + /*0x13d5*/ 579, + /*0x0455*/ 331, + /*0x04d5*/ 396, + -1, -1, -1, + /*0x1e55*/ 658, + /*0x1ed5*/ 717, + /*0x0155*/ 96, + /*0x2cd5*/ 950, + -1, + /*0x01eb*/ 157, + -1, + /*0xa7d7*/ 1109, + /*0x24d5*/ 831, + /*0x10598*/ 1217, + /*0x0257*/ 206, + /*0x1059e*/ 1223, + -1, + /*0x0586*/ 479, + -1, + /*0xa753*/ 1061, + /*0x2c5b*/ 895, + /*0x10ced*/ 1296, + -1, -1, + /*0x0561*/ 442, + /*0xa657*/ 1012, + /*0x10ed*/ 509, + /*0x1f57*/ 778, + -1, -1, + /*0x105a0*/ 1225, + -1, -1, + /*0x051b*/ 431, + -1, + /*0x2c59*/ 893, + -1, -1, + /*0x050b*/ 423, + -1, + /*0x026f*/ 221, + -1, -1, -1, + /*0xa791*/ 1084, + -1, + /*0x10cd3*/ 1270, + /*0x0211*/ 174, + /*0x0563*/ 444, + /*0x13ea*/ 600, + /*0x2c5f*/ 899, + /*0x10d3*/ 483, + /*0x006a*/ 8, + -1, + /*0x104ea*/ 1198, + /*0x13cd*/ 571, + /*0x044d*/ 323, + /*0x118db*/ 1351, + /*0x0565*/ 446, + /*0x1044d*/ 1177, + /*0x1f11*/ 748, + /*0x1e4d*/ 654, + /*0x1ecd*/ 713, + /*0x014d*/ 92, + /*0x2ccd*/ 946, + -1, -1, + /*0xa7d1*/ 1108, + /*0x0569*/ 450, + /*0x01ef*/ 159, + /*0x0251*/ 201, + -1, + /*0x118d9*/ 1349, + -1, + /*0x03cd*/ 275, + -1, -1, + /*0x1f00*/ 739, + /*0x0567*/ 448, + /*0x2c5d*/ 897, + -1, + /*0xa651*/ 1009, + /*0x10f3*/ 515, + /*0x1f51*/ 775, + /*0xa794*/ 1086, + /*0xa755*/ 1062, + -1, + /*0x118df*/ 1355, + -1, + /*0x105a6*/ 1230, + /*0x13c3*/ 561, + /*0x0443*/ 313, + -1, + /*0x0180*/ 117, + /*0x10443*/ 1167, + -1, + /*0x1e43*/ 649, + /*0x1ec3*/ 708, + /*0x10d84*/ 1322, + /*0x2cc3*/ 941, + /*0x1f14*/ 751, + /*0x13c1*/ 559, + /*0x0441*/ 311, + -1, -1, + /*0x10441*/ 1165, + -1, + /*0x1e41*/ 648, + /*0x1ec1*/ 707, + /*0x03c3*/ 265, + /*0x2cc1*/ 940, + -1, + /*0x10cd5*/ 1272, + -1, -1, -1, + /*0x118dd*/ 1353, + /*0x10d5*/ 485, + -1, -1, + /*0x03c1*/ 264, + /*0x13cf*/ 573, + /*0x044f*/ 325, + /*0x04cf*/ 393, + -1, + /*0x1044f*/ 1179, + -1, + /*0x1e4f*/ 655, + /*0x1ecf*/ 714, + /*0x014f*/ 93, + /*0x2ccf*/ 947, + /*0x13cb*/ 569, + /*0x044b*/ 321, + -1, -1, + /*0x1044b*/ 1175, + -1, + /*0x1e4b*/ 653, + /*0x1ecb*/ 712, + /*0x014b*/ 91, + /*0x2ccb*/ 945, + -1, + /*0xa74d*/ 1058, + -1, + /*0x2c57*/ 891, + /*0x13c9*/ 567, + /*0x0449*/ 319, + /*0x2d16*/ 983, + /*0xa66d*/ 1023, + /*0x10449*/ 1173, + /*0x03cb*/ 273, + /*0x1e49*/ 652, + /*0x1ec9*/ 711, + -1, + /*0x2cc9*/ 944, + /*0x2d0a*/ 971, + /*0x2d1b*/ 988, + /*0x105ae*/ 1238, + /*0x2d08*/ 969, + -1, + /*0x2d0c*/ 973, + /*0x2d0b*/ 972, + /*0x0253*/ 203, + /*0x10cea*/ 1293, + /*0x03c9*/ 271, + -1, + /*0x01ed*/ 158, + /*0x13ee*/ 604, + /*0x10ea*/ 506, + /*0x10ccd*/ 1264, + /*0x006e*/ 12, + /*0x1f22*/ 755, + /*0x104ee*/ 1202, + /*0xa653*/ 1010, + -1, + /*0x1f53*/ 776, + /*0x2cee*/ 959, + /*0xa743*/ 1053, + -1, -1, + /*0x2d02*/ 963, + /*0x118d7*/ 1347, + -1, + /*0x056b*/ 452, + /*0x13f1*/ 607, + /*0x0471*/ 350, + /*0x04f1*/ 410, + /*0x0071*/ 15, + /*0xa741*/ 1052, + /*0x104f1*/ 1205, + /*0x1e71*/ 672, + /*0x1ef1*/ 731, + /*0x0171*/ 110, + /*0x2d12*/ 979, + -1, + /*0x2d18*/ 985, + -1, + /*0x2d1e*/ 991, + /*0x1f04*/ 743, + -1, + /*0x2c51*/ 885, + -1, + /*0x2d06*/ 967, + /*0x01a8*/ 131, + /*0x10cc3*/ 1254, + /*0x0580*/ 473, + /*0x1f73*/ 790, + -1, + /*0xa74f*/ 1059, + -1, + /*0x019a*/ 125, + -1, + /*0x2d20*/ 993, + /*0x105aa*/ 1234, + -1, + /*0x10cc1*/ 1252, + -1, -1, + /*0xa74b*/ 1057, + /*0x13b7*/ 549, + /*0x0437*/ 301, + /*0x04b7*/ 381, + /*0x01f3*/ 160, + /*0x10437*/ 1155, + -1, + /*0x1e37*/ 643, + /*0x1eb7*/ 702, + /*0x0137*/ 82, + /*0x2cb7*/ 935, + -1, + /*0x00e1*/ 26, + -1, + /*0xa749*/ 1056, + /*0x2d10*/ 977, + -1, + /*0x10ccf*/ 1266, + -1, + /*0x118d1*/ 1341, + /*0x03b7*/ 254, + /*0xa655*/ 1011, + /*0x1e926*/ 1392, + /*0x1f55*/ 777, + -1, + /*0x056f*/ 456, + -1, + /*0x10ccb*/ 1262, + -1, -1, -1, + /*0x13a5*/ 531, + /*0x0511*/ 426, + /*0x04a5*/ 372, + -1, -1, + /*0x00e3*/ 28, + /*0x1e25*/ 634, + /*0x1ea5*/ 693, + /*0x0125*/ 74, + /*0x2ca5*/ 926, + /*0x10cc9*/ 1260, + /*0x13f5*/ 611, + /*0x0475*/ 352, + /*0x04f5*/ 412, + /*0x0075*/ 19, + /*0x00e5*/ 30, + /*0x104f5*/ 1209, + /*0x1e75*/ 674, + /*0x1ef5*/ 733, + /*0x0175*/ 112, + /*0x13b5*/ 547, + /*0x0435*/ 299, + /*0x04b5*/ 380, + -1, + /*0x10435*/ 1153, + /*0x00e9*/ 34, + /*0x1e35*/ 642, + /*0x1eb5*/ 701, + /*0x0135*/ 81, + /*0x2cb5*/ 934, + /*0x026a*/ 218, + /*0x16e61*/ 1357, + /*0x10cee*/ 1297, + /*0xa7cd*/ 1107, + -1, + /*0x00e7*/ 32, + /*0x024d*/ 198, + /*0x10ee*/ 510, + -1, + /*0x03b5*/ 252, + -1, -1, + /*0x105ac*/ 1236, + /*0x2c53*/ 887, + /*0x13b3*/ 545, + /*0x0433*/ 297, + /*0x04b3*/ 379, + /*0xa64d*/ 1007, + /*0x10433*/ 1151, + /*0x10cf1*/ 1300, + /*0x1e33*/ 641, + /*0x1eb3*/ 700, + /*0x0133*/ 80, + /*0x2cb3*/ 933, + /*0x10f1*/ 513, + /*0x16e63*/ 1359, + -1, + /*0xa737*/ 1047, + -1, + /*0x1e92e*/ 1400, + -1, -1, -1, + /*0x03b3*/ 250, + /*0x1fe1*/ 806, + /*0x16e65*/ 1361, + /*0x0481*/ 358, + -1, + /*0xa7c3*/ 1104, + /*0x105a8*/ 1232, + /*0x1e01*/ 616, + /*0x1e81*/ 680, + /*0x0101*/ 56, + /*0x2c81*/ 908, + /*0x2c73*/ 906, + /*0x16e69*/ 1365, + /*0x1059a*/ 1219, + /*0x0584*/ 477, + /*0x2173*/ 812, + /*0xa7c1*/ 1103, + /*0x118d3*/ 1343, + /*0x13a4*/ 530, + /*0xa643*/ 1002, + -1, + /*0x1f43*/ 772, + /*0x16e67*/ 1363, + -1, + /*0xa725*/ 1039, + -1, -1, -1, + /*0x056d*/ 454, + -1, + /*0xa641*/ 1001, + -1, + /*0x1f41*/ 770, + -1, + /*0x13ad*/ 539, + /*0x1fe5*/ 807, + /*0x04ad*/ 376, + -1, + /*0x1042d*/ 1145, + /*0x024f*/ 199, + /*0x1e2d*/ 638, + /*0x1ead*/ 697, + /*0x012d*/ 78, + /*0x2cad*/ 930, + /*0xa735*/ 1046, + -1, + /*0x2c55*/ 889, + -1, -1, + /*0x024b*/ 197, + /*0xa64f*/ 1008, + -1, + /*0x1e92a*/ 1396, + /*0x03ad*/ 245, + -1, -1, -1, + /*0x10d73*/ 1305, + -1, -1, + /*0xa64b*/ 1006, + /*0x2d11*/ 978, + -1, + /*0x0249*/ 196, + /*0x13a3*/ 529, + -1, + /*0x04a3*/ 371, + /*0x10f5*/ 517, + /*0xa733*/ 1045, + -1, + /*0x1e23*/ 633, + /*0x1ea3*/ 692, + /*0x0123*/ 73, + /*0x2ca3*/ 925, + /*0xa649*/ 1005, + /*0x2d0e*/ 975, + -1, + /*0x00eb*/ 36, + /*0x2d00*/ 961, + /*0x13a7*/ 533, + -1, + /*0x04a7*/ 373, + -1, + /*0x118d5*/ 1345, + /*0x0573*/ 460, + /*0x1e27*/ 635, + /*0x1ea7*/ 694, + /*0x0127*/ 75, + /*0x2ca7*/ 927, + /*0x13bf*/ 557, + /*0x043f*/ 309, + /*0x04bf*/ 385, + /*0x01c9*/ 140, + /*0x1043f*/ 1163, + -1, + /*0x1e3f*/ 647, + /*0x1ebf*/ 706, + /*0x2c6a*/ 904, + /*0x2cbf*/ 939, + -1, -1, + /*0x2d14*/ 981, + /*0x0271*/ 222, + /*0x2c4d*/ 881, + -1, + /*0x13b9*/ 551, + /*0x0439*/ 303, + /*0x04b9*/ 382, + /*0x03bf*/ 262, + /*0x10439*/ 1157, + -1, + /*0x1e39*/ 644, + /*0x1eb9*/ 703, + -1, + /*0x2cb9*/ 936, + /*0x1f71*/ 788, + /*0x13b1*/ 543, + /*0x0431*/ 295, + /*0x04b1*/ 378, + -1, + /*0x10431*/ 1149, + /*0xa72d*/ 1043, + /*0x1e31*/ 640, + /*0x1eb1*/ 699, + /*0x03b9*/ 256, + /*0x2cb1*/ 932, + -1, + /*0x16e6b*/ 1367, + /*0x13c0*/ 558, + /*0x0440*/ 310, + /*0x1e92c*/ 1398, + -1, + /*0x10440*/ 1164, + -1, + /*0xa7b7*/ 1098, + /*0x03b1*/ 248, + /*0x0140*/ 86, + /*0x00ef*/ 40, + /*0x2c43*/ 871, + -1, + /*0x118cd*/ 1337, + /*0x1e922*/ 1388, + -1, -1, + /*0x10d81*/ 1319, + -1, -1, + /*0x03c0*/ 263, + -1, + /*0x2c41*/ 869, + /*0x1f37*/ 768, + /*0xa723*/ 1038, + -1, -1, + /*0x13c7*/ 565, + /*0x0447*/ 317, + -1, + /*0x1e928*/ 1394, + /*0x10447*/ 1171, + -1, + /*0x1e47*/ 651, + /*0x1ec7*/ 710, + -1, + /*0x2cc7*/ 943, + /*0xa7a5*/ 1094, + -1, + /*0xa727*/ 1040, + /*0x0225*/ 183, + -1, + /*0x2c4f*/ 883, + /*0x056a*/ 451, + -1, + /*0x2d22*/ 995, + /*0x03c7*/ 269, + -1, + /*0x118c3*/ 1327, + /*0xa73f*/ 1051, + -1, + /*0x0275*/ 224, + /*0x2c4b*/ 879, + /*0x1f25*/ 758, + /*0x13c2*/ 560, + /*0x0442*/ 312, + /*0x04c2*/ 386, + /*0xa7b5*/ 1097, + /*0x10442*/ 1166, + /*0x118c1*/ 1325, + /*0x16e6f*/ 1371, + -1, + /*0x0142*/ 87, + -1, + /*0x1f75*/ 792, + /*0xa739*/ 1048, + /*0x2c49*/ 877, + -1, + /*0x2d1a*/ 987, + /*0x01a5*/ 130, + /*0x048f*/ 361, + -1, + /*0x2d04*/ 965, + /*0x1f35*/ 766, + /*0x1e0f*/ 623, + /*0x1e8f*/ 687, + /*0x010f*/ 63, + /*0x2c8f*/ 915, + /*0xa69b*/ 1037, + /*0x118cf*/ 1339, + /*0x01f5*/ 161, + -1, + /*0x1059c*/ 1221, + /*0xa68b*/ 1029, + /*0x0233*/ 190, + /*0xff59*/ 1138, + /*0x13c5*/ 563, + /*0x0445*/ 315, + -1, + /*0x118cb*/ 1335, + /*0x10445*/ 1169, + -1, + /*0x1e45*/ 650, + /*0x1ec5*/ 709, + -1, + /*0x2cc5*/ 942, + -1, + /*0x1f33*/ 764, + -1, -1, -1, + /*0xa781*/ 1079, + -1, + /*0x118c9*/ 1333, + /*0x0201*/ 166, + /*0x03c5*/ 267, + -1, + /*0x00ed*/ 38, + -1, + /*0x2171*/ 810, + -1, -1, + /*0x0373*/ 239, + -1, + /*0xa747*/ 1055, + /*0x10cc0*/ 1251, + /*0x13f2*/ 608, + /*0x1f01*/ 740, + -1, + /*0x0072*/ 16, + /*0x0078*/ 22, + /*0x104f2*/ 1206, + /*0x104f8*/ 1212, + /*0x1fd1*/ 804, + /*0x13bd*/ 555, + /*0x043d*/ 307, + /*0x04bd*/ 384, + -1, + /*0x1043d*/ 1161, + -1, + /*0x1e3d*/ 646, + /*0x1ebd*/ 705, + -1, + /*0x2cbd*/ 938, + /*0x1f24*/ 757, + /*0x03f2*/ 290, + /*0x03f8*/ 292, + /*0x022d*/ 187, + -1, -1, + /*0x2c37*/ 859, + /*0x10cc7*/ 1258, + -1, + /*0x03bd*/ 260, + -1, -1, + /*0x13bb*/ 553, + /*0x043b*/ 305, + /*0x04bb*/ 383, + -1, + /*0x1043b*/ 1159, + /*0x10d71*/ 1303, + /*0x1e3b*/ 645, + /*0x1ebb*/ 704, + /*0x105b7*/ 1246, + /*0x2cbb*/ 937, + -1, + /*0x16e6d*/ 1369, + -1, -1, -1, + /*0x056e*/ 455, + -1, + /*0x00f3*/ 44, + /*0xa7a3*/ 1093, + /*0x03bb*/ 258, + /*0x01ad*/ 132, + /*0x0223*/ 182, + /*0x10cc2*/ 1253, + /*0x1e05*/ 618, + /*0x1e85*/ 682, + /*0x0105*/ 58, + /*0x2c85*/ 910, + /*0xa745*/ 1054, + -1, -1, + /*0x1e943*/ 1421, + -1, + /*0x0571*/ 458, + /*0xa7a7*/ 1095, + /*0x1f23*/ 756, + -1, + /*0x0227*/ 184, + -1, + /*0x105a5*/ 1229, + /*0x2175*/ 814, + -1, + /*0x1e941*/ 1419, + -1, + /*0xa7bf*/ 1102, + /*0x2c35*/ 857, + -1, + /*0x023f*/ 192, + -1, + /*0xff57*/ 1136, + /*0x1f27*/ 760, + /*0x01a3*/ 129, + /*0x0479*/ 354, + /*0x04f9*/ 414, + /*0x0079*/ 23, + /*0x10cc5*/ 1256, + /*0x104f9*/ 1213, + /*0x1e79*/ 676, + /*0x1ef9*/ 735, + /*0x105b5*/ 1244, + /*0xa7b9*/ 1099, + /*0x1d79*/ 613, + -1, -1, -1, -1, + /*0xa73d*/ 1050, + -1, + /*0x16e73*/ 1375, + /*0x2c33*/ 855, + -1, + /*0x0076*/ 20, + -1, + /*0x104f6*/ 1210, + /*0x0231*/ 189, + -1, + /*0x01bf*/ 138, + -1, -1, -1, -1, -1, + /*0x10d75*/ 1307, + /*0x105b3*/ 1242, + -1, + /*0x10cf2*/ 1301, + /*0x0240*/ 193, + /*0x1f31*/ 762, + /*0xa73b*/ 1049, + -1, + /*0x10f2*/ 514, + /*0x10f8*/ 520, + /*0x01b9*/ 136, + -1, -1, -1, -1, -1, + /*0x0525*/ 436, + /*0x1f40*/ 769, + /*0x0581*/ 474, + /*0x047d*/ 356, + /*0x04fd*/ 416, + -1, + /*0x00ea*/ 35, + /*0xff51*/ 1130, + /*0x1e7d*/ 678, + /*0x1efd*/ 737, + -1, + /*0x0575*/ 462, + /*0x1d7d*/ 614, + -1, + /*0x0247*/ 195, + -1, -1, -1, -1, -1, -1, + /*0x2d1c*/ 989, + /*0x105a4*/ 1228, + -1, + /*0x13af*/ 541, + /*0xa647*/ 1004, + /*0x04af*/ 377, + -1, + /*0x1042f*/ 1147, + -1, + /*0x1e2f*/ 639, + /*0x1eaf*/ 698, + /*0x012f*/ 79, + /*0x2caf*/ 931, + -1, + /*0x007a*/ 24, + -1, + /*0x104fa*/ 1214, + /*0x105ad*/ 1237, + -1, + /*0x017a*/ 114, + /*0x0242*/ 194, + /*0x13a9*/ 535, + /*0x03af*/ 247, + /*0x04a9*/ 374, + -1, + /*0x10429*/ 1141, + -1, + /*0x1e29*/ 636, + /*0x1ea9*/ 695, + /*0x0129*/ 76, + /*0x2ca9*/ 928, + /*0xa691*/ 1032, + -1, + /*0x1f42*/ 771, + /*0x020f*/ 173, + /*0x16e6a*/ 1366, + /*0x1e03*/ 617, + /*0x1e83*/ 681, + /*0x0103*/ 57, + /*0x2c83*/ 909, + -1, + /*0x1e937*/ 1409, + /*0x10d85*/ 1323, + /*0x0501*/ 418, + -1, -1, -1, + /*0x105a3*/ 1227, + /*0x047b*/ 355, + /*0x04fb*/ 415, + -1, + /*0x10f9*/ 521, + /*0x104fb*/ 1215, + /*0x1e7b*/ 677, + /*0x1efb*/ 736, + -1, -1, -1, + /*0x2c3f*/ 867, + -1, -1, -1, + /*0x105a7*/ 1231, + /*0xa645*/ 1003, + -1, + /*0x1f45*/ 774, + /*0x03fb*/ 293, + /*0x13e6*/ 596, + /*0x10f6*/ 518, + /*0x0371*/ 238, + /*0x0066*/ 5, + /*0x1e925*/ 1391, + /*0x104e6*/ 1194, + /*0x0499*/ 366, + /*0x2c39*/ 861, + -1, + /*0x052d*/ 440, + /*0x1e19*/ 628, + /*0xff53*/ 1132, + /*0x0119*/ 68, + /*0x2c99*/ 920, + /*0x24e6*/ 848, + /*0x0272*/ 223, + -1, -1, + /*0x2c31*/ 853, + -1, + /*0xa7bd*/ 1101, + /*0x105b9*/ 1248, + -1, + /*0xa72f*/ 1044, + /*0x1e935*/ 1407, + -1, -1, -1, + /*0x1f72*/ 789, + /*0x1f78*/ 795, + /*0x2c40*/ 868, + /*0xa77a*/ 1076, + /*0x105b1*/ 1241, + /*0x10fd*/ 523, + -1, + /*0x2d25*/ 998, + /*0x00ee*/ 39, + -1, -1, + /*0x0523*/ 435, + -1, + /*0xa729*/ 1041, + /*0xa7bb*/ 1100, + -1, + /*0x13f0*/ 606, + -1, -1, + /*0x0070*/ 14, + /*0x1e933*/ 1405, + /*0x104f0*/ 1204, + -1, + /*0x017c*/ 115, + /*0x01bd*/ 137, + /*0x00f1*/ 42, + /*0x0527*/ 437, + -1, + /*0x2c47*/ 875, + -1, -1, + /*0xa785*/ 1081, + -1, -1, + /*0x0205*/ 168, + /*0x10fa*/ 522, + /*0x0477*/ 353, + /*0x04f7*/ 413, + /*0x0077*/ 21, + /*0x118c0*/ 1324, + /*0x104f7*/ 1211, + /*0x1e77*/ 675, + /*0x1ef7*/ 734, + /*0x0177*/ 113, + /*0x13ab*/ 537, + -1, + /*0x04ab*/ 375, + /*0x1f05*/ 744, + /*0x1042b*/ 1143, + /*0xff55*/ 1134, + /*0x1e2b*/ 637, + /*0x1eab*/ 696, + /*0x012b*/ 77, + /*0x2cab*/ 929, + -1, + /*0x2c42*/ 870, + -1, + /*0x1e924*/ 1390, + /*0x16e6e*/ 1370, + -1, -1, -1, -1, + /*0x0185*/ 119, + -1, + /*0x118c7*/ 1331, + /*0x13ce*/ 572, + /*0x044e*/ 324, + /*0x04ce*/ 392, + -1, + /*0x1044e*/ 1178, + /*0x2d01*/ 962, + -1, + /*0x1e92d*/ 1399, + -1, + /*0x16e71*/ 1373, + /*0x0283*/ 228, + -1, + /*0x10d83*/ 1321, + -1, + /*0x1f79*/ 796, + /*0xa7f6*/ 1112, + -1, -1, -1, + /*0x03ce*/ 276, + /*0x10ce6*/ 1289, + /*0x2c45*/ 873, + /*0x2d24*/ 997, + -1, + /*0x13ec*/ 602, + /*0x10e6*/ 502, + /*0x118c2*/ 1326, + /*0x006c*/ 10, + -1, + /*0x104ec*/ 1200, + /*0x01f9*/ 162, + /*0x1f76*/ 793, + -1, + /*0x2cec*/ 958, + -1, + /*0x00f5*/ 46, + /*0xa77c*/ 1077, + /*0x1e923*/ 1389, + /*0x2d2d*/ 1000, + -1, + /*0xff4d*/ 1126, + /*0x047f*/ 357, + /*0x04ff*/ 417, + -1, -1, -1, + /*0x1e7f*/ 679, + /*0x1eff*/ 738, + /*0x13f4*/ 610, + -1, + /*0x027d*/ 225, + /*0x0074*/ 18, + /*0x1e927*/ 1393, + /*0x104f4*/ 1208, + -1, + /*0x2172*/ 811, + /*0x2178*/ 817, + -1, + /*0x118c5*/ 1329, + /*0x2c3d*/ 865, + -1, -1, + /*0x1e93f*/ 1417, + /*0x1f7d*/ 800, + /*0x10cf0*/ 1299, + /*0xa72b*/ 1042, + /*0x13d0*/ 574, + /*0x0450*/ 326, + /*0x2d23*/ 996, + /*0x10f0*/ 512, + -1, -1, + /*0x022f*/ 188, + -1, -1, + /*0xff43*/ 1116, + /*0x050f*/ 425, + -1, + /*0x1e939*/ 1411, + /*0x01fd*/ 164, + /*0x24d0*/ 826, + /*0x2c3b*/ 863, + -1, + /*0x2d27*/ 999, + -1, + /*0x16e75*/ 1377, + /*0xff41*/ 1114, + /*0xa7a9*/ 1096, + /*0x10f7*/ 519, + /*0x1e931*/ 1403, + /*0x0229*/ 185, + -1, -1, + /*0x1f7a*/ 797, + -1, + /*0x105bb*/ 1249, + /*0xa783*/ 1080, + /*0x10d72*/ 1304, + /*0x10d78*/ 1310, + /*0x0203*/ 167, + -1, + /*0x1e940*/ 1418, + /*0x2184*/ 825, + -1, -1, -1, + /*0xff4f*/ 1128, + -1, -1, + /*0x0585*/ 478, + -1, + /*0x13a1*/ 527, + /*0x1f03*/ 742, + /*0x04a1*/ 370, + /*0x10cce*/ 1265, + -1, + /*0xff4b*/ 1124, + /*0x1e21*/ 632, + /*0x1ea1*/ 691, + /*0x0121*/ 72, + /*0x2ca1*/ 924, + -1, -1, -1, + /*0x0572*/ 459, + /*0x0578*/ 465, + -1, + /*0xa77f*/ 1078, + /*0x0183*/ 118, + /*0x1f7b*/ 798, + /*0xff49*/ 1122, + -1, -1, -1, -1, + /*0x2179*/ 818, + /*0x0266*/ 215, + /*0xa799*/ 1088, + /*0x10cec*/ 1295, + -1, + /*0x0219*/ 178, + /*0x13e8*/ 598, + -1, + /*0x10ec*/ 508, + /*0x0068*/ 7, + /*0x01fb*/ 163, + /*0x104e8*/ 1196, + -1, + /*0x2c76*/ 907, + /*0x1f66*/ 785, + -1, -1, + /*0x2176*/ 815, + -1, + /*0x1e942*/ 1420, + /*0x24e8*/ 850, + -1, -1, + /*0x13e4*/ 594, + /*0x10ff*/ 525, + -1, + /*0x0064*/ 3, + -1, + /*0x104e4*/ 1192, + -1, -1, -1, + /*0x10f4*/ 516, + -1, + /*0x0199*/ 124, + -1, + /*0x0505*/ 420, + /*0x24e4*/ 846, + -1, -1, -1, + /*0x13e2*/ 592, + /*0x10d79*/ 1311, + -1, + /*0x0062*/ 1, + /*0x10cd0*/ 1267, + /*0x104e2*/ 1190, + -1, -1, + /*0x217d*/ 822, + /*0x10d0*/ 480, + -1, + /*0x13c8*/ 566, + /*0x0448*/ 318, + /*0x04c8*/ 389, + /*0x24e2*/ 844, + /*0x10448*/ 1172, + /*0x1f7c*/ 799, + /*0x1f70*/ 787, + /*0x10d76*/ 1308, + /*0x0148*/ 90, + /*0x0495*/ 364, + -1, -1, + /*0x2d0f*/ 976, + /*0x1e15*/ 626, + /*0x1e95*/ 690, + /*0x0115*/ 66, + /*0x2c95*/ 918, + /*0x0579*/ 466, + -1, + /*0x03c8*/ 270, + -1, + /*0x022b*/ 186, + /*0x13c6*/ 564, + /*0x0446*/ 316, + /*0x04c6*/ 388, + /*0x1f77*/ 794, + /*0x10446*/ 1170, + /*0x217a*/ 819, + /*0x13e0*/ 590, + /*0x105af*/ 1239, + /*0x0146*/ 89, + /*0x13de*/ 588, + /*0x045e*/ 340, + /*0x104e0*/ 1188, + /*0x0576*/ 463, + -1, + /*0x104de*/ 1186, + /*0x1e93d*/ 1415, + -1, + /*0x10d7d*/ 1315, + -1, + /*0x03c6*/ 268, + /*0x24e0*/ 842, + -1, + /*0x017e*/ 116, + /*0x24de*/ 840, + -1, + /*0x105a9*/ 1233, + -1, -1, + /*0x13b0*/ 542, + /*0x0430*/ 294, + -1, + /*0x0583*/ 476, + /*0x10430*/ 1148, + -1, + /*0x13c4*/ 562, + /*0x0444*/ 314, + /*0x04c4*/ 387, + /*0x1e93b*/ 1413, + /*0x10444*/ 1168, + -1, -1, + /*0x217b*/ 820, + /*0x0144*/ 88, + -1, + /*0x057d*/ 470, + /*0x026c*/ 220, + /*0x10ce8*/ 1291, + /*0x10d7a*/ 1312, + /*0x13bc*/ 554, + /*0x043c*/ 306, + /*0x01ce*/ 142, + /*0x10e8*/ 504, + /*0x1043c*/ 1160, + /*0x03c4*/ 266, + /*0x0493*/ 363, + -1, + /*0x013c*/ 84, + /*0x2c66*/ 902, + /*0x1e13*/ 625, + /*0x1e93*/ 689, + /*0x0113*/ 65, + /*0x2c93*/ 917, + -1, + /*0x10ce4*/ 1287, + -1, -1, + /*0x052f*/ 441, + /*0x03bc*/ 259, + /*0x10e4*/ 500, + /*0x1e07*/ 619, + /*0x1e87*/ 683, + /*0x0107*/ 59, + /*0x2c87*/ 911, + -1, + /*0x057a*/ 467, + /*0x10599*/ 1218, + -1, + /*0x1fb1*/ 802, + -1, -1, -1, + /*0x10ce2*/ 1285, + /*0x1f74*/ 791, + /*0x10d7b*/ 1313, + /*0x0529*/ 438, + /*0x2d05*/ 966, + /*0x10e2*/ 498, + /*0x0250*/ 200, + -1, -1, + /*0x01ff*/ 165, + -1, + /*0x10cc8*/ 1259, + /*0x0503*/ 419, + -1, + /*0x13dc*/ 586, + /*0x045c*/ 338, + -1, -1, -1, + /*0x104dc*/ 1184, + -1, -1, -1, + /*0x217c*/ 821, + /*0x2170*/ 809, + -1, -1, -1, + /*0x24dc*/ 838, + /*0x057b*/ 468, + -1, + /*0x13da*/ 584, + /*0x045a*/ 336, + /*0x10cc6*/ 1257, + -1, + /*0x01d0*/ 143, + /*0x104da*/ 1182, + -1, -1, + /*0x10ce0*/ 1283, + /*0x00f2*/ 43, + /*0x00f8*/ 48, + /*0x10cde*/ 1281, + /*0x2177*/ 816, + /*0x10e0*/ 496, + /*0x24da*/ 836, + -1, + /*0x10de*/ 494, + /*0xa7a1*/ 1092, + /*0x0566*/ 447, + /*0x0497*/ 365, + -1, + /*0x10fe*/ 524, + /*0x0519*/ 430, + /*0x1e17*/ 627, + -1, + /*0x0117*/ 67, + /*0x2c97*/ 919, + /*0x13d8*/ 582, + /*0x0458*/ 334, + -1, -1, + /*0x105ab*/ 1235, + /*0x104d8*/ 1180, + /*0x1f21*/ 754, + /*0x10d7c*/ 1314, + /*0x10d70*/ 1302, + /*0x10cc4*/ 1255, + -1, -1, + /*0x2c4e*/ 882, + -1, + /*0x24d8*/ 834, + -1, + /*0x214e*/ 808, + -1, + /*0xa681*/ 1024, + /*0x1e92f*/ 1401, + -1, -1, + /*0x01a1*/ 128, + /*0x0268*/ 216, + -1, -1, -1, + /*0x10d77*/ 1309, + -1, -1, + /*0x13d6*/ 580, + /*0x0456*/ 332, + /*0x16e72*/ 1374, + /*0x16e78*/ 1380, + /*0x057c*/ 469, + /*0x0570*/ 457, + /*0x2c6c*/ 905, + /*0x1e929*/ 1395, + /*0x13d4*/ 578, + /*0x0454*/ 330, + /*0x0264*/ 213, + -1, -1, -1, + /*0x24d6*/ 832, + /*0x13d2*/ 576, + /*0x0452*/ 328, + -1, -1, + /*0x118ce*/ 1338, + -1, -1, + /*0x24d4*/ 830, + /*0x1f64*/ 783, + /*0x0577*/ 464, + -1, + /*0x217f*/ 824, + -1, -1, + /*0x24d2*/ 828, + /*0x037d*/ 243, + -1, + /*0x00f9*/ 49, + /*0x052b*/ 439, + /*0x2174*/ 813, + /*0x0287*/ 229, + /*0xa7c8*/ 1105, + -1, -1, -1, + /*0x10cdc*/ 1279, + /*0x1f62*/ 781, + -1, -1, -1, + /*0x10dc*/ 492, + /*0x0215*/ 176, + /*0x2d03*/ 964, + /*0x2c50*/ 884, + /*0x00f6*/ 47, + -1, + /*0x13cc*/ 570, + /*0x044c*/ 322, + /*0x04cc*/ 391, + /*0x049d*/ 368, + /*0x1044c*/ 1176, + -1, + /*0x10cda*/ 1277, + /*0x1e1d*/ 630, + /*0x1f15*/ 752, + /*0x011d*/ 70, + /*0x2c9d*/ 922, + /*0x10da*/ 490, + /*0x1e09*/ 620, + /*0x1e89*/ 684, + /*0x0109*/ 60, + /*0x2c89*/ 912, + /*0x0260*/ 210, + /*0x10d7f*/ 1317, + -1, + /*0x03cc*/ 274, + -1, -1, + /*0xff47*/ 1120, + -1, + /*0x0195*/ 123, + /*0x10d74*/ 1306, + -1, -1, + /*0x056c*/ 453, + /*0x1f60*/ 779, + /*0x00fd*/ 53, + /*0x16e79*/ 1381, + -1, + /*0x10cd8*/ 1275, + /*0x118d0*/ 1340, + -1, -1, + /*0x2d19*/ 986, + /*0x10d8*/ 488, + /*0x01c6*/ 139, + -1, -1, + /*0x13b6*/ 548, + /*0x0436*/ 300, + /*0x057f*/ 472, + /*0x037b*/ 241, + /*0x10436*/ 1154, + -1, + /*0x16e76*/ 1378, + /*0xff42*/ 1115, + -1, + /*0x1f30*/ 761, + /*0x0574*/ 461, + -1, -1, -1, + /*0x105a1*/ 1226, + /*0x1f44*/ 773, + /*0x023c*/ 191, + /*0xa793*/ 1085, + /*0x00fa*/ 50, + /*0x03b6*/ 253, + /*0x0213*/ 175, + /*0x10cd6*/ 1273, + -1, -1, -1, + /*0x01b0*/ 133, + /*0x10d6*/ 486, + -1, + /*0xa787*/ 1082, + /*0x10cd4*/ 1271, + /*0x2c68*/ 903, + /*0x0207*/ 169, + /*0x1e92b*/ 1397, + /*0x1f13*/ 750, + /*0x10d4*/ 484, + -1, + /*0x10cd2*/ 1269, + -1, + /*0x16e7d*/ 1385, + /*0xff45*/ 1118, + -1, + /*0x10d2*/ 482, + -1, -1, + /*0x1f07*/ 746, + /*0x13ca*/ 568, + /*0x044a*/ 320, + /*0x04ca*/ 390, + -1, + /*0x1044a*/ 1174, + -1, + /*0x13b4*/ 546, + /*0x0434*/ 298, + /*0x048d*/ 360, + /*0x00fb*/ 51, + /*0x10434*/ 1152, + -1, + /*0x1e0d*/ 622, + /*0x1e8d*/ 686, + /*0x010d*/ 62, + /*0x2c8d*/ 914, + /*0x13be*/ 556, + /*0x043e*/ 308, + /*0x025c*/ 209, + /*0x03ca*/ 272, + /*0x1043e*/ 1162, + /*0x037c*/ 242, + -1, + /*0x16e7a*/ 1382, + /*0x013e*/ 85, + /*0x03b4*/ 251, + /*0x049f*/ 369, + /*0x10ccc*/ 1263, + /*0x0521*/ 434, + /*0x00e6*/ 31, + /*0x1e1f*/ 631, + /*0x2c48*/ 876, + /*0x011f*/ 71, + /*0x2c9f*/ 923, + -1, + /*0x03be*/ 261, + -1, -1, -1, -1, -1, + /*0x0377*/ 240, + /*0x13ba*/ 552, + /*0x043a*/ 304, + /*0xa68f*/ 1031, + -1, + /*0x1043a*/ 1158, + /*0x01dc*/ 149, + -1, + /*0xa797*/ 1087, + /*0x013a*/ 83, + -1, + /*0x0217*/ 177, + /*0x2c46*/ 874, + -1, + /*0x029d*/ 236, + -1, -1, + /*0x0568*/ 449, + /*0x16e7b*/ 1383, + /*0x0289*/ 231, + /*0x03ba*/ 257, + /*0x2c5e*/ 898, + -1, + /*0x01da*/ 148, + -1, + /*0x13b8*/ 550, + /*0x0438*/ 302, + /*0x118c8*/ 1332, + -1, + /*0x10438*/ 1156, + /*0x217e*/ 823, + /*0x00fc*/ 52, + /*0x00f0*/ 41, + -1, + /*0x0564*/ 445, + -1, -1, -1, + /*0x16e66*/ 1362, + -1, + /*0x2c30*/ 852, + -1, -1, -1, + /*0x03b8*/ 255, + -1, + /*0x2c44*/ 872, + -1, -1, + /*0x118c6*/ 1330, + /*0x01d8*/ 147, + /*0x0256*/ 205, + /*0x0562*/ 443, + -1, + /*0x105b0*/ 1240, + -1, -1, -1, + /*0x118de*/ 1354, + /*0x0254*/ 204, + /*0x2c3c*/ 864, + -1, -1, -1, -1, -1, + /*0x0252*/ 202, + /*0x13b2*/ 544, + /*0x0432*/ 296, + -1, + /*0x0515*/ 428, + /*0x10432*/ 1150, + /*0x10d7e*/ 1316, + /*0x10cca*/ 1261, + /*0x105bc*/ 1250, + -1, -1, -1, -1, -1, + /*0x01d6*/ 146, + /*0x16e7c*/ 1384, + /*0x16e70*/ 1372, + /*0x118c4*/ 1328, + -1, -1, + /*0x03b2*/ 249, + -1, + /*0x01d4*/ 145, + -1, -1, -1, -1, -1, -1, + /*0x01d2*/ 144, + -1, -1, + /*0xa685*/ 1026, + /*0x057e*/ 471, + /*0xa79d*/ 1090, + /*0x16e77*/ 1379, + -1, + /*0x021d*/ 180, + -1, -1, + /*0x00ec*/ 37, + /*0x2c5c*/ 896, + /*0x0209*/ 170, + -1, + /*0x2d21*/ 994, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, + /*0x00ff*/ 55, + -1, + /*0x2c5a*/ 894, + -1, -1, -1, -1, -1, + /*0x00f4*/ 45, + /*0x01cc*/ 141, + -1, -1, -1, -1, -1, + /*0x0513*/ 427, + -1, -1, -1, -1, -1, -1, + /*0x118dc*/ 1352, + -1, -1, -1, + /*0x0507*/ 421, + -1, -1, + /*0x2c58*/ 892, + -1, -1, -1, + /*0x10597*/ 1216, + /*0x16e6c*/ 1368, + /*0x1f36*/ 767, + -1, -1, -1, + /*0x118da*/ 1350, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, + /*0x16e7f*/ 1387, + /*0x01b6*/ 135, + -1, -1, -1, -1, -1, -1, + /*0x16e74*/ 1376, + /*0x2c56*/ 890, + -1, -1, -1, -1, + /*0xa7ca*/ 1106, + -1, + /*0x118d8*/ 1348, + /*0x2c54*/ 888, + -1, -1, -1, + /*0x2d15*/ 982, + -1, + /*0x020d*/ 172, + /*0x2c52*/ 886, + -1, -1, -1, -1, -1, -1, + -1, -1, + /*0x1e930*/ 1402, + -1, -1, + /*0x1f34*/ 765, + -1, + /*0xa79f*/ 1091, + -1, -1, + /*0x021f*/ 181, + /*0x0517*/ 429, + -1, -1, -1, + /*0x118d6*/ 1346, + -1, -1, -1, -1, + /*0x00e8*/ 33, + /*0x01b4*/ 134, + /*0x1e93c*/ 1414, + /*0x118d4*/ 1344, + -1, -1, + /*0xa683*/ 1025, + -1, + /*0x1fd0*/ 803, + /*0x2c4c*/ 880, + /*0x118d2*/ 1342, + -1, -1, -1, -1, -1, -1, + /*0x00e4*/ 29, + -1, -1, -1, -1, -1, -1, + /*0x1059d*/ 1222, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, + /*0x00e2*/ 27, + -1, + /*0x2d13*/ 980, + -1, -1, -1, -1, -1, -1, + -1, -1, + /*0x118cc*/ 1336, + /*0xa699*/ 1036, + /*0x2d07*/ 968, + -1, + /*0x16e68*/ 1364, + /*0x2c36*/ 858, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, + /*0x105b6*/ 1245, + -1, + /*0x16e64*/ 1360, + -1, + /*0xff4e*/ 1127, + -1, -1, -1, -1, + /*0x00e0*/ 25, + -1, -1, -1, -1, -1, -1, + -1, + /*0x00fe*/ 54, + /*0x051d*/ 432, + -1, + /*0x16e62*/ 1358, + -1, + /*0x1f32*/ 763, + /*0x0509*/ 422, + -1, -1, -1, -1, -1, -1, + -1, + /*0x2c4a*/ 878, + -1, -1, -1, -1, -1, + /*0x2c34*/ 856, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, + /*0x2c3e*/ 866, + -1, + /*0x2d17*/ 984, + -1, + /*0x105b4*/ 1243, + -1, -1, -1, -1, -1, -1, + -1, + /*0x16e60*/ 1356, + -1, -1, -1, -1, -1, -1, + -1, + /*0x16e7e*/ 1386, + /*0x118ca*/ 1334, + /*0x1059f*/ 1224, + /*0xff50*/ 1129, + -1, -1, + /*0x2c3a*/ 862, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + /*0x1fe0*/ 805, + -1, -1, -1, -1, + /*0x2c38*/ 860, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + /*0x050d*/ 424, + /*0x105b8*/ 1247, + -1, -1, + /*0x1fb0*/ 801, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, + /*0x051f*/ 433, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, + /*0x2c32*/ 854, + -1, + /*0x2d1d*/ 990, + -1, -1, -1, -1, + /*0x2d09*/ 970, + -1, -1, -1, -1, + /*0x1e936*/ 1408, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, + /*0xff48*/ 1121, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, + /*0x1e934*/ 1406, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, + /*0x1e93e*/ 1416, + /*0xff46*/ 1119, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, + /*0x2d0d*/ 974, + -1, -1, -1, -1, + /*0x1e93a*/ 1412, + -1, -1, -1, -1, -1, -1, + -1, -1, + /*0xff44*/ 1117, + -1, -1, -1, + /*0x2d1f*/ 992, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, + /*0x1e938*/ 1410, + -1, -1, -1, + /*0xa695*/ 1034, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, + /*0x1e932*/ 1404, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, + /*0xff5a*/ 1139, + -1, -1, -1, -1, -1, -1, + -1, + /*0xa693*/ 1033, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, + /*0xa687*/ 1027, + -1, -1, -1, -1, -1, -1, + -1, + /*0xff58*/ 1137, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, + /*0xff56*/ 1135, + -1, -1, -1, -1, -1, -1, + -1, + /*0xff54*/ 1133, + -1, -1, -1, -1, -1, -1, + /*0xff52*/ 1131, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + /*0xa697*/ 1035, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, + /*0xff4c*/ 1125, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, + /*0xa689*/ 1028, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + /*0xff4a*/ 1123, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, + /*0xa68d*/ 1030 + }; + + if (code <= MAX_CODE_VALUE && code >= MIN_CODE_VALUE) + { + register unsigned int key = onigenc_unicode_CaseUnfold_11_hash(code); + + if (key <= MAX_HASH_VALUE) + { + register short s = wordlist[key]; + + if (s >= 0 && code1_equal(code, CaseUnfold_11_Table[s].from)) + return &CaseUnfold_11_Table[s].to; + } + } + return 0; +} + +static const CaseUnfold_12_Type CaseUnfold_12_Table[] = { +#define CaseUnfold_12 (*(CaseUnfold_12_Type (*)[58])(CaseUnfold_12_Table+0)) + {{0x0061, 0x02be}, {1, {0x1e9a}}}, + {{0x0066, 0x0066}, {1, {0xfb00}}}, + {{0x0066, 0x0069}, {1, {0xfb01}}}, + {{0x0066, 0x006c}, {1, {0xfb02}}}, + {{0x0068, 0x0331}, {1, {0x1e96}}}, + {{0x006a, 0x030c}, {1, {0x01f0}}}, + {{0x0073, 0x0073}, {2, {0x00df, 0x1e9e}}}, + {{0x0073, 0x0074}, {2, {0xfb05, 0xfb06}}}, + {{0x0074, 0x0308}, {1, {0x1e97}}}, + {{0x0077, 0x030a}, {1, {0x1e98}}}, + {{0x0079, 0x030a}, {1, {0x1e99}}}, + {{0x02bc, 0x006e}, {1, {0x0149}}}, + {{0x03ac, 0x03b9}, {1, {0x1fb4}}}, + {{0x03ae, 0x03b9}, {1, {0x1fc4}}}, + {{0x03b1, 0x0342}, {1, {0x1fb6}}}, + {{0x03b1, 0x03b9}, {2, {0x1fb3, 0x1fbc}}}, + {{0x03b7, 0x0342}, {1, {0x1fc6}}}, + {{0x03b7, 0x03b9}, {2, {0x1fc3, 0x1fcc}}}, + {{0x03b9, 0x0342}, {1, {0x1fd6}}}, + {{0x03c1, 0x0313}, {1, {0x1fe4}}}, + {{0x03c5, 0x0313}, {1, {0x1f50}}}, + {{0x03c5, 0x0342}, {1, {0x1fe6}}}, + {{0x03c9, 0x0342}, {1, {0x1ff6}}}, + {{0x03c9, 0x03b9}, {2, {0x1ff3, 0x1ffc}}}, + {{0x03ce, 0x03b9}, {1, {0x1ff4}}}, + {{0x0565, 0x0582}, {1, {0x0587}}}, + {{0x0574, 0x0565}, {1, {0xfb14}}}, + {{0x0574, 0x056b}, {1, {0xfb15}}}, + {{0x0574, 0x056d}, {1, {0xfb17}}}, + {{0x0574, 0x0576}, {1, {0xfb13}}}, + {{0x057e, 0x0576}, {1, {0xfb16}}}, + {{0x1f00, 0x03b9}, {2, {0x1f80, 0x1f88}}}, + {{0x1f01, 0x03b9}, {2, {0x1f81, 0x1f89}}}, + {{0x1f02, 0x03b9}, {2, {0x1f82, 0x1f8a}}}, + {{0x1f03, 0x03b9}, {2, {0x1f83, 0x1f8b}}}, + {{0x1f04, 0x03b9}, {2, {0x1f84, 0x1f8c}}}, + {{0x1f05, 0x03b9}, {2, {0x1f85, 0x1f8d}}}, + {{0x1f06, 0x03b9}, {2, {0x1f86, 0x1f8e}}}, + {{0x1f07, 0x03b9}, {2, {0x1f87, 0x1f8f}}}, + {{0x1f20, 0x03b9}, {2, {0x1f90, 0x1f98}}}, + {{0x1f21, 0x03b9}, {2, {0x1f91, 0x1f99}}}, + {{0x1f22, 0x03b9}, {2, {0x1f92, 0x1f9a}}}, + {{0x1f23, 0x03b9}, {2, {0x1f93, 0x1f9b}}}, + {{0x1f24, 0x03b9}, {2, {0x1f94, 0x1f9c}}}, + {{0x1f25, 0x03b9}, {2, {0x1f95, 0x1f9d}}}, + {{0x1f26, 0x03b9}, {2, {0x1f96, 0x1f9e}}}, + {{0x1f27, 0x03b9}, {2, {0x1f97, 0x1f9f}}}, + {{0x1f60, 0x03b9}, {2, {0x1fa0, 0x1fa8}}}, + {{0x1f61, 0x03b9}, {2, {0x1fa1, 0x1fa9}}}, + {{0x1f62, 0x03b9}, {2, {0x1fa2, 0x1faa}}}, + {{0x1f63, 0x03b9}, {2, {0x1fa3, 0x1fab}}}, + {{0x1f64, 0x03b9}, {2, {0x1fa4, 0x1fac}}}, + {{0x1f65, 0x03b9}, {2, {0x1fa5, 0x1fad}}}, + {{0x1f66, 0x03b9}, {2, {0x1fa6, 0x1fae}}}, + {{0x1f67, 0x03b9}, {2, {0x1fa7, 0x1faf}}}, + {{0x1f70, 0x03b9}, {1, {0x1fb2}}}, + {{0x1f74, 0x03b9}, {1, {0x1fc2}}}, + {{0x1f7c, 0x03b9}, {1, {0x1ff2}}}, +#define CaseUnfold_12_Locale (*(CaseUnfold_12_Type (*)[1])(CaseUnfold_12_Table+58)) + {{0x0069, 0x0307}, {1, {0x0130}}}, +}; + +/* ANSI-C code produced by gperf version 3.1 */ +/* Command-line: gperf -7 -k1,2,3,4,5,6 -F,-1 -c -j1 -i1 -t -T -E -C -H onigenc_unicode_CaseUnfold_12_hash -N onigenc_unicode_CaseUnfold_12_lookup -n */ + +/* maximum key range = 71, duplicates = 0 */ + +#ifdef __GNUC__ +__inline +#else +#ifdef __cplusplus +inline +#endif +#endif +/*ARGSUSED*/ +static unsigned int +onigenc_unicode_CaseUnfold_12_hash(const OnigCodePoint *codes) +{ + static const unsigned char asso_values[] = + { + 3, 58, 54, 57, 56, 16, 8, 2, 43, 82, + 3, 1, 23, 82, 82, 82, 82, 82, 82, 4, + 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, + 82, 82, 52, 51, 50, 49, 48, 47, 46, 45, + 82, 82, 82, 82, 43, 82, 42, 82, 82, 13, + 82, 82, 82, 82, 82, 11, 82, 1, 82, 82, + 14, 82, 1, 82, 82, 31, 3, 82, 82, 30, + 82, 82, 82, 10, 82, 82, 82, 82, 37, 82, + 82, 82, 82, 82, 82, 82, 82, 82, 82, 82, + 82, 82, 82, 82, 82, 82, 37, 15, 36, 35, + 34, 17, 1, 33, 12, 4, 23, 23, 26, 21, + 13, 82, 27, 82, 82, 2, 5, 82, 11, 16, + 82, 15, 82, 82, 23, 82, 8, 82 + }; + return asso_values[bits_at(codes, 5)] + asso_values[bits_at(codes, 4)] + asso_values[bits_at(codes, 3)] + asso_values[bits_at(codes, 2)] + asso_values[bits_at(codes, 1)] + asso_values[bits_at(codes, 0)]; +} + +static const CodePointList2 * +onigenc_unicode_CaseUnfold_12_lookup(const OnigCodePoint *codes) +{ + enum + { + MIN_CODE_VALUE = 0x61, + MAX_CODE_VALUE = 0x1f7c, + TOTAL_KEYWORDS = 59, + MIN_WORD_LENGTH = 6, + MAX_WORD_LENGTH = 6, + MIN_HASH_VALUE = 11, + MAX_HASH_VALUE = 81 + }; + + static const short wordlist[] = + { + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, + /*0x1f66,0x03b9*/ 53, + /*0x1f07,0x03b9*/ 38, + /*0x1f00,0x03b9*/ 31, + /*0x0066,0x0066*/ 1, + /*0x1f74,0x03b9*/ 56, + /*0x0073,0x0073*/ 6, + /*0x0066,0x0069*/ 2, + /*0x1f06,0x03b9*/ 37, + /*0x0073,0x0074*/ 7, + /*0x03b9,0x0342*/ 18, + /*0x03c9,0x03b9*/ 23, + /*0x03b7,0x03b9*/ 17, + /*0x0069,0x0307*/ 58, + /*0x03b1,0x03b9*/ 15, + /*0x1f61,0x03b9*/ 48, + /*0x1f05,0x03b9*/ 36, + /*0x1f65,0x03b9*/ 52, + /*0x0574,0x0576*/ 29, + /*0x03c9,0x0342*/ 22, + /*0x03b7,0x0342*/ 16, + /*0x057e,0x0576*/ 30, + /*0x03b1,0x0342*/ 14, + /*0x1f7c,0x03b9*/ 57, + /*0x0574,0x0565*/ 26, + /*0x0079,0x030a*/ 10, + /*0x0077,0x030a*/ 9, + /*0x1f70,0x03b9*/ 55, + /*0x0574,0x056d*/ 28, + /*0x0066,0x006c*/ 3, + /*0x0574,0x056b*/ 27, + /*0x0061,0x02be*/ 0, + /*0x0068,0x0331*/ 4, + /*0x1f67,0x03b9*/ 54, + /*0x1f64,0x03b9*/ 51, + /*0x1f63,0x03b9*/ 50, + /*0x1f62,0x03b9*/ 49, + /*0x1f60,0x03b9*/ 47, + /*0x03ce,0x03b9*/ 24, + /*0x03c5,0x0342*/ 21, + /*0x03c5,0x0313*/ 20, + /*0x03c1,0x0313*/ 19, + /*0x02bc,0x006e*/ 11, + /*0x03ae,0x03b9*/ 13, + /*0x03ac,0x03b9*/ 12, + /*0x1f27,0x03b9*/ 46, + /*0x1f26,0x03b9*/ 45, + /*0x1f25,0x03b9*/ 44, + /*0x1f24,0x03b9*/ 43, + /*0x1f23,0x03b9*/ 42, + /*0x1f22,0x03b9*/ 41, + /*0x1f21,0x03b9*/ 40, + /*0x1f20,0x03b9*/ 39, + /*0x006a,0x030c*/ 5, + /*0x1f02,0x03b9*/ 33, + /*0x0074,0x0308*/ 8, + /*0x1f04,0x03b9*/ 35, + /*0x1f03,0x03b9*/ 34, + /*0x1f01,0x03b9*/ 32, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + /*0x0565,0x0582*/ 25 + }; + + if (codes[0] <= MAX_CODE_VALUE && codes[0] >= MIN_CODE_VALUE && + codes[1] <= MAX_CODE_VALUE && codes[1] >= MIN_CODE_VALUE) + { + register unsigned int key = onigenc_unicode_CaseUnfold_12_hash(codes); + + if (key <= MAX_HASH_VALUE) + { + register short s = wordlist[key]; + + if (s >= 0 && code2_equal(codes, CaseUnfold_12_Table[s].from)) + return &CaseUnfold_12_Table[s].to; + } + } + return 0; +} + +static const CaseUnfold_13_Type CaseUnfold_13_Table[] = { +#define CaseUnfold_13 (*(CaseUnfold_13_Type (*)[14])(CaseUnfold_13_Table+0)) + {{0x0066, 0x0066, 0x0069}, {1, {0xfb03}}}, + {{0x0066, 0x0066, 0x006c}, {1, {0xfb04}}}, + {{0x03b1, 0x0342, 0x03b9}, {1, {0x1fb7}}}, + {{0x03b7, 0x0342, 0x03b9}, {1, {0x1fc7}}}, + {{0x03b9, 0x0308, 0x0300}, {1, {0x1fd2}}}, + {{0x03b9, 0x0308, 0x0301}, {2, {0x0390, 0x1fd3}}}, + {{0x03b9, 0x0308, 0x0342}, {1, {0x1fd7}}}, + {{0x03c5, 0x0308, 0x0300}, {1, {0x1fe2}}}, + {{0x03c5, 0x0308, 0x0301}, {2, {0x03b0, 0x1fe3}}}, + {{0x03c5, 0x0308, 0x0342}, {1, {0x1fe7}}}, + {{0x03c5, 0x0313, 0x0300}, {1, {0x1f52}}}, + {{0x03c5, 0x0313, 0x0301}, {1, {0x1f54}}}, + {{0x03c5, 0x0313, 0x0342}, {1, {0x1f56}}}, + {{0x03c9, 0x0342, 0x03b9}, {1, {0x1ff7}}}, +}; + +/* ANSI-C code produced by gperf version 3.1 */ +/* Command-line: gperf -7 -k1,2,3,4,5,6,7,8,9 -F,-1 -c -j1 -i1 -t -T -E -C -H onigenc_unicode_CaseUnfold_13_hash -N onigenc_unicode_CaseUnfold_13_lookup -n */ + +/* maximum key range = 20, duplicates = 0 */ + +#ifdef __GNUC__ +__inline +#else +#ifdef __cplusplus +inline +#endif +#endif +/*ARGSUSED*/ +static unsigned int +onigenc_unicode_CaseUnfold_13_hash(const OnigCodePoint *codes) +{ + static const unsigned char asso_values[] = + { + 7, 4, 47, 47, 47, 47, 1, 1, 2, 47, + 47, 47, 47, 47, 47, 47, 47, 47, 47, 1, + 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, + 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, + 47, 47, 47, 47, 47, 47, 47, 47, 47, 11, + 47, 47, 47, 47, 47, 10, 47, 2, 47, 47, + 47, 47, 47, 47, 47, 47, 1, 47, 47, 1, + 47, 47, 47, 9, 47, 47, 47, 47, 47, 47, + 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, + 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, + 47, 47, 1, 47, 47, 2, 47, 47, 1, 47, + 47, 47, 47, 47, 47, 47, 47, 47, 47, 47, + 47, 47, 47, 47, 47, 47, 47, 47 + }; + return asso_values[bits_at(codes, 8)] + asso_values[bits_at(codes, 7)] + asso_values[bits_at(codes, 6)] + asso_values[bits_at(codes, 5)] + asso_values[bits_at(codes, 4)] + asso_values[bits_at(codes, 3)] + asso_values[bits_at(codes, 2)] + asso_values[bits_at(codes, 1)] + asso_values[bits_at(codes, 0)]; +} + +static const CodePointList2 * +onigenc_unicode_CaseUnfold_13_lookup(const OnigCodePoint *codes) +{ + enum + { + MIN_CODE_VALUE = 0x66, + MAX_CODE_VALUE = 0x3c9, + TOTAL_KEYWORDS = 14, + MIN_WORD_LENGTH = 9, + MAX_WORD_LENGTH = 9, + MIN_HASH_VALUE = 27, + MAX_HASH_VALUE = 46 + }; + + static const short wordlist[] = + { + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, + -1, -1, -1, + /*0x03c5,0x0313,0x0342*/ 12, + /*0x03c5,0x0308,0x0342*/ 9, + /*0x03b9,0x0308,0x0342*/ 6, + /*0x03c5,0x0313,0x0301*/ 11, + /*0x03c5,0x0308,0x0301*/ 8, + /*0x03b9,0x0308,0x0301*/ 5, + /*0x03c5,0x0313,0x0300*/ 10, + /*0x03c5,0x0308,0x0300*/ 7, + /*0x03b9,0x0308,0x0300*/ 4, + /*0x03c9,0x0342,0x03b9*/ 13, + /*0x03b7,0x0342,0x03b9*/ 3, + /*0x03b1,0x0342,0x03b9*/ 2, + -1, -1, -1, -1, -1, -1, + /*0x0066,0x0066,0x006c*/ 1, + /*0x0066,0x0066,0x0069*/ 0 + }; + + if (codes[0] <= MAX_CODE_VALUE && codes[0] >= MIN_CODE_VALUE && + codes[1] <= MAX_CODE_VALUE && codes[1] >= MIN_CODE_VALUE && + codes[2] <= MAX_CODE_VALUE && codes[2] >= MIN_CODE_VALUE) + { + register unsigned int key = onigenc_unicode_CaseUnfold_13_hash(codes); + + if (key <= MAX_HASH_VALUE) + { + register short s = wordlist[key]; + + if (s >= 0 && code3_equal(codes, CaseUnfold_13_Table[s].from)) + return &CaseUnfold_13_Table[s].to; + } + } + return 0; +} + +static const OnigCodePoint CaseMappingSpecials[] = { + L(1)|0x039C, + L(2)|0x0053, 0x0073, L(2)|0x0053, 0x0053, + L(2)|0x02BC, 0x004E, + L(1)|0x0053, + L(1)|0x01C5, + L(2)|0x0064, 0x017D, L(1)|0x01C4, + L(1)|0x01C8, + L(2)|0x006C, 0x004A, L(1)|0x01C7, + L(1)|0x01CB, + L(2)|0x006E, 0x004A, L(1)|0x01CA, + L(2)|0x004A, 0x030C, + L(1)|0x01F2, + L(2)|0x0064, 0x005A, L(1)|0x01F1, + L(1)|0x0399, + L(3)|0x0399, 0x0308, 0x0301, + L(3)|0x03A5, 0x0308, 0x0301, + L(1)|0x03A3, + L(1)|0x0392, + L(1)|0x0398, + L(1)|0x03A6, + L(1)|0x03A0, + L(1)|0x039A, + L(1)|0x03A1, + L(1)|0x0395, + L(2)|0x0535, 0x0582, L(2)|0x0535, 0x0552, + L(1)|0x0412, + L(1)|0x0414, + L(1)|0x041E, + L(1)|0x0421, + L(1)|0x0422, + L(1)|0x0422, + L(1)|0x042A, + L(1)|0x0462, + L(1)|0xA64A, + L(2)|0x0048, 0x0331, + L(2)|0x0054, 0x0308, + L(2)|0x0057, 0x030A, + L(2)|0x0059, 0x030A, + L(2)|0x0041, 0x02BE, + L(1)|0x1E60, + L(1)|0x00DF, + L(2)|0x03A5, 0x0313, + L(3)|0x03A5, 0x0313, 0x0300, + L(3)|0x03A5, 0x0313, 0x0301, + L(3)|0x03A5, 0x0313, 0x0342, + L(1)|0x1F88, L(2)|0x1F08, 0x0399, + L(1)|0x1F89, L(2)|0x1F09, 0x0399, + L(1)|0x1F8A, L(2)|0x1F0A, 0x0399, + L(1)|0x1F8B, L(2)|0x1F0B, 0x0399, + L(1)|0x1F8C, L(2)|0x1F0C, 0x0399, + L(1)|0x1F8D, L(2)|0x1F0D, 0x0399, + L(1)|0x1F8E, L(2)|0x1F0E, 0x0399, + L(1)|0x1F8F, L(2)|0x1F0F, 0x0399, + L(2)|0x1F00, 0x0399, L(1)|0x1F80, L(2)|0x1F08, 0x0399, + L(2)|0x1F01, 0x0399, L(1)|0x1F81, L(2)|0x1F09, 0x0399, + L(2)|0x1F02, 0x0399, L(1)|0x1F82, L(2)|0x1F0A, 0x0399, + L(2)|0x1F03, 0x0399, L(1)|0x1F83, L(2)|0x1F0B, 0x0399, + L(2)|0x1F04, 0x0399, L(1)|0x1F84, L(2)|0x1F0C, 0x0399, + L(2)|0x1F05, 0x0399, L(1)|0x1F85, L(2)|0x1F0D, 0x0399, + L(2)|0x1F06, 0x0399, L(1)|0x1F86, L(2)|0x1F0E, 0x0399, + L(2)|0x1F07, 0x0399, L(1)|0x1F87, L(2)|0x1F0F, 0x0399, + L(1)|0x1F98, L(2)|0x1F28, 0x0399, + L(1)|0x1F99, L(2)|0x1F29, 0x0399, + L(1)|0x1F9A, L(2)|0x1F2A, 0x0399, + L(1)|0x1F9B, L(2)|0x1F2B, 0x0399, + L(1)|0x1F9C, L(2)|0x1F2C, 0x0399, + L(1)|0x1F9D, L(2)|0x1F2D, 0x0399, + L(1)|0x1F9E, L(2)|0x1F2E, 0x0399, + L(1)|0x1F9F, L(2)|0x1F2F, 0x0399, + L(2)|0x1F20, 0x0399, L(1)|0x1F90, L(2)|0x1F28, 0x0399, + L(2)|0x1F21, 0x0399, L(1)|0x1F91, L(2)|0x1F29, 0x0399, + L(2)|0x1F22, 0x0399, L(1)|0x1F92, L(2)|0x1F2A, 0x0399, + L(2)|0x1F23, 0x0399, L(1)|0x1F93, L(2)|0x1F2B, 0x0399, + L(2)|0x1F24, 0x0399, L(1)|0x1F94, L(2)|0x1F2C, 0x0399, + L(2)|0x1F25, 0x0399, L(1)|0x1F95, L(2)|0x1F2D, 0x0399, + L(2)|0x1F26, 0x0399, L(1)|0x1F96, L(2)|0x1F2E, 0x0399, + L(2)|0x1F27, 0x0399, L(1)|0x1F97, L(2)|0x1F2F, 0x0399, + L(1)|0x1FA8, L(2)|0x1F68, 0x0399, + L(1)|0x1FA9, L(2)|0x1F69, 0x0399, + L(1)|0x1FAA, L(2)|0x1F6A, 0x0399, + L(1)|0x1FAB, L(2)|0x1F6B, 0x0399, + L(1)|0x1FAC, L(2)|0x1F6C, 0x0399, + L(1)|0x1FAD, L(2)|0x1F6D, 0x0399, + L(1)|0x1FAE, L(2)|0x1F6E, 0x0399, + L(1)|0x1FAF, L(2)|0x1F6F, 0x0399, + L(2)|0x1F60, 0x0399, L(1)|0x1FA0, L(2)|0x1F68, 0x0399, + L(2)|0x1F61, 0x0399, L(1)|0x1FA1, L(2)|0x1F69, 0x0399, + L(2)|0x1F62, 0x0399, L(1)|0x1FA2, L(2)|0x1F6A, 0x0399, + L(2)|0x1F63, 0x0399, L(1)|0x1FA3, L(2)|0x1F6B, 0x0399, + L(2)|0x1F64, 0x0399, L(1)|0x1FA4, L(2)|0x1F6C, 0x0399, + L(2)|0x1F65, 0x0399, L(1)|0x1FA5, L(2)|0x1F6D, 0x0399, + L(2)|0x1F66, 0x0399, L(1)|0x1FA6, L(2)|0x1F6E, 0x0399, + L(2)|0x1F67, 0x0399, L(1)|0x1FA7, L(2)|0x1F6F, 0x0399, + L(2)|0x1FBA, 0x0345, L(2)|0x1FBA, 0x0399, + L(1)|0x1FBC, L(2)|0x0391, 0x0399, + L(2)|0x0386, 0x0345, L(2)|0x0386, 0x0399, + L(2)|0x0391, 0x0342, + L(3)|0x0391, 0x0342, 0x0345, L(3)|0x0391, 0x0342, 0x0399, + L(2)|0x03B1, 0x0399, L(1)|0x1FB3, L(2)|0x0391, 0x0399, + L(1)|0x0399, + L(2)|0x1FCA, 0x0345, L(2)|0x1FCA, 0x0399, + L(1)|0x1FCC, L(2)|0x0397, 0x0399, + L(2)|0x0389, 0x0345, L(2)|0x0389, 0x0399, + L(2)|0x0397, 0x0342, + L(3)|0x0397, 0x0342, 0x0345, L(3)|0x0397, 0x0342, 0x0399, + L(2)|0x03B7, 0x0399, L(1)|0x1FC3, L(2)|0x0397, 0x0399, + L(3)|0x0399, 0x0308, 0x0300, + L(3)|0x0399, 0x0308, 0x0301, + L(2)|0x0399, 0x0342, + L(3)|0x0399, 0x0308, 0x0342, + L(3)|0x03A5, 0x0308, 0x0300, + L(3)|0x03A5, 0x0308, 0x0301, + L(2)|0x03A1, 0x0313, + L(2)|0x03A5, 0x0342, + L(3)|0x03A5, 0x0308, 0x0342, + L(2)|0x1FFA, 0x0345, L(2)|0x1FFA, 0x0399, + L(1)|0x1FFC, L(2)|0x03A9, 0x0399, + L(2)|0x038F, 0x0345, L(2)|0x038F, 0x0399, + L(2)|0x03A9, 0x0342, + L(3)|0x03A9, 0x0342, 0x0345, L(3)|0x03A9, 0x0342, 0x0399, + L(2)|0x03C9, 0x0399, L(1)|0x1FF3, L(2)|0x03A9, 0x0399, + L(2)|0x0046, 0x0066, L(2)|0x0046, 0x0046, + L(2)|0x0046, 0x0069, L(2)|0x0046, 0x0049, + L(2)|0x0046, 0x006C, L(2)|0x0046, 0x004C, + L(3)|0x0046, 0x0066, 0x0069, L(3)|0x0046, 0x0046, 0x0049, + L(3)|0x0046, 0x0066, 0x006C, L(3)|0x0046, 0x0046, 0x004C, + L(2)|0x0053, 0x0074, L(2)|0x0053, 0x0054, + L(2)|0x0053, 0x0074, L(2)|0x0053, 0x0054, + L(2)|0x0544, 0x0576, L(2)|0x0544, 0x0546, + L(2)|0x0544, 0x0565, L(2)|0x0544, 0x0535, + L(2)|0x0544, 0x056B, L(2)|0x0544, 0x053B, + L(2)|0x054E, 0x0576, L(2)|0x054E, 0x0546, + L(2)|0x0544, 0x056D, L(2)|0x0544, 0x053D, +}; diff --git a/enc/unicode/15.0.0/name2ctype.h b/enc/unicode/16.0.0/name2ctype.h similarity index 83% rename from enc/unicode/15.0.0/name2ctype.h rename to enc/unicode/16.0.0/name2ctype.h index 6bbbb3512ff460..42da74f3181eab 100644 --- a/enc/unicode/15.0.0/name2ctype.h +++ b/enc/unicode/16.0.0/name2ctype.h @@ -43,7 +43,7 @@ static const OnigCodePoint CR_NEWLINE[] = { /* 'Alpha': [[:Alpha:]] */ static const OnigCodePoint CR_Alpha[] = { - 732, + 757, 0x0041, 0x005a, 0x0061, 0x007a, 0x00aa, 0x00aa, @@ -57,7 +57,7 @@ static const OnigCodePoint CR_Alpha[] = { 0x02ec, 0x02ec, 0x02ee, 0x02ee, 0x0345, 0x0345, - 0x0370, 0x0374, + 0x0363, 0x0374, 0x0376, 0x0377, 0x037a, 0x037d, 0x037f, 0x037f, @@ -98,6 +98,7 @@ static const OnigCodePoint CR_Alpha[] = { 0x0860, 0x086a, 0x0870, 0x0887, 0x0889, 0x088e, + 0x0897, 0x0897, 0x08a0, 0x08c9, 0x08d4, 0x08df, 0x08e3, 0x08e9, @@ -311,7 +312,7 @@ static const OnigCodePoint CR_Alpha[] = { 0x1c00, 0x1c36, 0x1c4d, 0x1c4f, 0x1c5a, 0x1c7d, - 0x1c80, 0x1c88, + 0x1c80, 0x1c8a, 0x1c90, 0x1cba, 0x1cbd, 0x1cbf, 0x1ce9, 0x1cec, @@ -319,7 +320,7 @@ static const OnigCodePoint CR_Alpha[] = { 0x1cf5, 0x1cf6, 0x1cfa, 0x1cfa, 0x1d00, 0x1dbf, - 0x1de7, 0x1df4, + 0x1dd3, 0x1df4, 0x1e00, 0x1f15, 0x1f18, 0x1f1d, 0x1f20, 0x1f45, @@ -399,10 +400,10 @@ static const OnigCodePoint CR_Alpha[] = { 0xa67f, 0xa6ef, 0xa717, 0xa71f, 0xa722, 0xa788, - 0xa78b, 0xa7ca, + 0xa78b, 0xa7cd, 0xa7d0, 0xa7d1, 0xa7d3, 0xa7d3, - 0xa7d5, 0xa7d9, + 0xa7d5, 0xa7dc, 0xa7f2, 0xa805, 0xa807, 0xa827, 0xa840, 0xa873, @@ -493,6 +494,7 @@ static const OnigCodePoint CR_Alpha[] = { 0x105a3, 0x105b1, 0x105b3, 0x105b9, 0x105bb, 0x105bc, + 0x105c0, 0x105f3, 0x10600, 0x10736, 0x10740, 0x10755, 0x10760, 0x10767, @@ -530,9 +532,14 @@ static const OnigCodePoint CR_Alpha[] = { 0x10c80, 0x10cb2, 0x10cc0, 0x10cf2, 0x10d00, 0x10d27, + 0x10d4a, 0x10d65, + 0x10d69, 0x10d69, + 0x10d6f, 0x10d85, 0x10e80, 0x10ea9, 0x10eab, 0x10eac, 0x10eb0, 0x10eb1, + 0x10ec2, 0x10ec4, + 0x10efc, 0x10efc, 0x10f00, 0x10f1c, 0x10f27, 0x10f27, 0x10f30, 0x10f45, @@ -576,6 +583,17 @@ static const OnigCodePoint CR_Alpha[] = { 0x11350, 0x11350, 0x11357, 0x11357, 0x1135d, 0x11363, + 0x11380, 0x11389, + 0x1138b, 0x1138b, + 0x1138e, 0x1138e, + 0x11390, 0x113b5, + 0x113b7, 0x113c0, + 0x113c2, 0x113c2, + 0x113c5, 0x113c5, + 0x113c7, 0x113ca, + 0x113cc, 0x113cd, + 0x113d1, 0x113d1, + 0x113d3, 0x113d3, 0x11400, 0x11441, 0x11443, 0x11445, 0x11447, 0x1144a, @@ -614,6 +632,7 @@ static const OnigCodePoint CR_Alpha[] = { 0x11a50, 0x11a97, 0x11a9d, 0x11a9d, 0x11ab0, 0x11af8, + 0x11bc0, 0x11be0, 0x11c00, 0x11c08, 0x11c0a, 0x11c36, 0x11c38, 0x11c3e, @@ -646,7 +665,9 @@ static const OnigCodePoint CR_Alpha[] = { 0x12f90, 0x12ff0, 0x13000, 0x1342f, 0x13441, 0x13446, + 0x13460, 0x143fa, 0x14400, 0x14646, + 0x16100, 0x1612e, 0x16800, 0x16a38, 0x16a40, 0x16a5e, 0x16a70, 0x16abe, @@ -655,6 +676,7 @@ static const OnigCodePoint CR_Alpha[] = { 0x16b40, 0x16b43, 0x16b63, 0x16b77, 0x16b7d, 0x16b8f, + 0x16d40, 0x16d6c, 0x16e40, 0x16e7f, 0x16f00, 0x16f4a, 0x16f4f, 0x16f87, @@ -664,7 +686,7 @@ static const OnigCodePoint CR_Alpha[] = { 0x16ff0, 0x16ff1, 0x17000, 0x187f7, 0x18800, 0x18cd5, - 0x18d00, 0x18d08, + 0x18cff, 0x18d08, 0x1aff0, 0x1aff3, 0x1aff5, 0x1affb, 0x1affd, 0x1affe, @@ -724,6 +746,8 @@ static const OnigCodePoint CR_Alpha[] = { 0x1e290, 0x1e2ad, 0x1e2c0, 0x1e2eb, 0x1e4d0, 0x1e4eb, + 0x1e5d0, 0x1e5ed, + 0x1e5f0, 0x1e5f0, 0x1e7e0, 0x1e7e6, 0x1e7e8, 0x1e7eb, 0x1e7ed, 0x1e7ee, @@ -773,6 +797,7 @@ static const OnigCodePoint CR_Alpha[] = { 0x2b740, 0x2b81d, 0x2b820, 0x2cea1, 0x2ceb0, 0x2ebe0, + 0x2ebf0, 0x2ee5d, 0x2f800, 0x2fa1d, 0x30000, 0x3134a, 0x31350, 0x323af, @@ -800,7 +825,7 @@ static const OnigCodePoint CR_Cntrl[] = { /* 'Digit': [[:Digit:]] */ static const OnigCodePoint CR_Digit[] = { - 64, + 71, 0x0030, 0x0039, 0x0660, 0x0669, 0x06f0, 0x06f9, @@ -840,6 +865,7 @@ static const OnigCodePoint CR_Digit[] = { 0xff10, 0xff19, 0x104a0, 0x104a9, 0x10d30, 0x10d39, + 0x10d40, 0x10d49, 0x11066, 0x1106f, 0x110f0, 0x110f9, 0x11136, 0x1113f, @@ -849,27 +875,33 @@ static const OnigCodePoint CR_Digit[] = { 0x114d0, 0x114d9, 0x11650, 0x11659, 0x116c0, 0x116c9, + 0x116d0, 0x116e3, 0x11730, 0x11739, 0x118e0, 0x118e9, 0x11950, 0x11959, + 0x11bf0, 0x11bf9, 0x11c50, 0x11c59, 0x11d50, 0x11d59, 0x11da0, 0x11da9, 0x11f50, 0x11f59, + 0x16130, 0x16139, 0x16a60, 0x16a69, 0x16ac0, 0x16ac9, 0x16b50, 0x16b59, + 0x16d70, 0x16d79, + 0x1ccf0, 0x1ccf9, 0x1d7ce, 0x1d7ff, 0x1e140, 0x1e149, 0x1e2f0, 0x1e2f9, 0x1e4f0, 0x1e4f9, + 0x1e5f1, 0x1e5fa, 0x1e950, 0x1e959, 0x1fbf0, 0x1fbf9, }; /* CR_Digit */ /* 'Graph': [[:Graph:]] */ static const OnigCodePoint CR_Graph[] = { - 712, + 737, 0x0021, 0x007e, 0x00a1, 0x0377, 0x037a, 0x037f, @@ -894,7 +926,7 @@ static const OnigCodePoint CR_Graph[] = { 0x0860, 0x086a, 0x0870, 0x088e, 0x0890, 0x0891, - 0x0898, 0x0983, + 0x0897, 0x0983, 0x0985, 0x098c, 0x098f, 0x0990, 0x0993, 0x09a8, @@ -1087,11 +1119,10 @@ static const OnigCodePoint CR_Graph[] = { 0x1aa0, 0x1aad, 0x1ab0, 0x1ace, 0x1b00, 0x1b4c, - 0x1b50, 0x1b7e, - 0x1b80, 0x1bf3, + 0x1b4e, 0x1bf3, 0x1bfc, 0x1c37, 0x1c3b, 0x1c49, - 0x1c4d, 0x1c88, + 0x1c4d, 0x1c8a, 0x1c90, 0x1cba, 0x1cbd, 0x1cc7, 0x1cd0, 0x1cfa, @@ -1121,7 +1152,7 @@ static const OnigCodePoint CR_Graph[] = { 0x20a0, 0x20c0, 0x20d0, 0x20f0, 0x2100, 0x218b, - 0x2190, 0x2426, + 0x2190, 0x2429, 0x2440, 0x244a, 0x2460, 0x2b73, 0x2b76, 0x2b95, @@ -1144,22 +1175,22 @@ static const OnigCodePoint CR_Graph[] = { 0x2e80, 0x2e99, 0x2e9b, 0x2ef3, 0x2f00, 0x2fd5, - 0x2ff0, 0x2ffb, + 0x2ff0, 0x2fff, 0x3001, 0x303f, 0x3041, 0x3096, 0x3099, 0x30ff, 0x3105, 0x312f, 0x3131, 0x318e, - 0x3190, 0x31e3, - 0x31f0, 0x321e, + 0x3190, 0x31e5, + 0x31ef, 0x321e, 0x3220, 0xa48c, 0xa490, 0xa4c6, 0xa4d0, 0xa62b, 0xa640, 0xa6f7, - 0xa700, 0xa7ca, + 0xa700, 0xa7cd, 0xa7d0, 0xa7d1, 0xa7d3, 0xa7d3, - 0xa7d5, 0xa7d9, + 0xa7d5, 0xa7dc, 0xa7f2, 0xa82c, 0xa830, 0xa839, 0xa840, 0xa877, @@ -1250,6 +1281,7 @@ static const OnigCodePoint CR_Graph[] = { 0x105a3, 0x105b1, 0x105b3, 0x105b9, 0x105bb, 0x105bc, + 0x105c0, 0x105f3, 0x10600, 0x10736, 0x10740, 0x10755, 0x10760, 0x10767, @@ -1293,11 +1325,15 @@ static const OnigCodePoint CR_Graph[] = { 0x10cc0, 0x10cf2, 0x10cfa, 0x10d27, 0x10d30, 0x10d39, + 0x10d40, 0x10d65, + 0x10d69, 0x10d85, + 0x10d8e, 0x10d8f, 0x10e60, 0x10e7e, 0x10e80, 0x10ea9, 0x10eab, 0x10ead, 0x10eb0, 0x10eb1, - 0x10efd, 0x10f27, + 0x10ec2, 0x10ec4, + 0x10efc, 0x10f27, 0x10f30, 0x10f59, 0x10f70, 0x10f89, 0x10fb0, 0x10fcb, @@ -1337,6 +1373,17 @@ static const OnigCodePoint CR_Graph[] = { 0x1135d, 0x11363, 0x11366, 0x1136c, 0x11370, 0x11374, + 0x11380, 0x11389, + 0x1138b, 0x1138b, + 0x1138e, 0x1138e, + 0x11390, 0x113b5, + 0x113b7, 0x113c0, + 0x113c2, 0x113c2, + 0x113c5, 0x113c5, + 0x113c7, 0x113ca, + 0x113cc, 0x113d5, + 0x113d7, 0x113d8, + 0x113e1, 0x113e2, 0x11400, 0x1145b, 0x1145d, 0x11461, 0x11480, 0x114c7, @@ -1348,6 +1395,7 @@ static const OnigCodePoint CR_Graph[] = { 0x11660, 0x1166c, 0x11680, 0x116b9, 0x116c0, 0x116c9, + 0x116d0, 0x116e3, 0x11700, 0x1171a, 0x1171d, 0x1172b, 0x11730, 0x11746, @@ -1368,6 +1416,8 @@ static const OnigCodePoint CR_Graph[] = { 0x11a50, 0x11aa2, 0x11ab0, 0x11af8, 0x11b00, 0x11b09, + 0x11bc0, 0x11be1, + 0x11bf0, 0x11bf9, 0x11c00, 0x11c08, 0x11c0a, 0x11c36, 0x11c38, 0x11c45, @@ -1391,7 +1441,7 @@ static const OnigCodePoint CR_Graph[] = { 0x11ee0, 0x11ef8, 0x11f00, 0x11f10, 0x11f12, 0x11f3a, - 0x11f3e, 0x11f59, + 0x11f3e, 0x11f5a, 0x11fb0, 0x11fb0, 0x11fc0, 0x11ff1, 0x11fff, 0x12399, @@ -1400,7 +1450,9 @@ static const OnigCodePoint CR_Graph[] = { 0x12480, 0x12543, 0x12f90, 0x12ff2, 0x13000, 0x13455, + 0x13460, 0x143fa, 0x14400, 0x14646, + 0x16100, 0x16139, 0x16800, 0x16a38, 0x16a40, 0x16a5e, 0x16a60, 0x16a69, @@ -1413,6 +1465,7 @@ static const OnigCodePoint CR_Graph[] = { 0x16b5b, 0x16b61, 0x16b63, 0x16b77, 0x16b7d, 0x16b8f, + 0x16d40, 0x16d79, 0x16e40, 0x16e9a, 0x16f00, 0x16f4a, 0x16f4f, 0x16f87, @@ -1421,7 +1474,7 @@ static const OnigCodePoint CR_Graph[] = { 0x16ff0, 0x16ff1, 0x17000, 0x187f7, 0x18800, 0x18cd5, - 0x18d00, 0x18d08, + 0x18cff, 0x18d08, 0x1aff0, 0x1aff3, 0x1aff5, 0x1affb, 0x1affd, 0x1affe, @@ -1436,6 +1489,8 @@ static const OnigCodePoint CR_Graph[] = { 0x1bc80, 0x1bc88, 0x1bc90, 0x1bc99, 0x1bc9c, 0x1bca3, + 0x1cc00, 0x1ccf9, + 0x1cd00, 0x1ceb3, 0x1cf00, 0x1cf2d, 0x1cf30, 0x1cf46, 0x1cf50, 0x1cfc3, @@ -1487,6 +1542,8 @@ static const OnigCodePoint CR_Graph[] = { 0x1e2c0, 0x1e2f9, 0x1e2ff, 0x1e2ff, 0x1e4d0, 0x1e4f9, + 0x1e5d0, 0x1e5fa, + 0x1e5ff, 0x1e5ff, 0x1e7e0, 0x1e7e6, 0x1e7e8, 0x1e7eb, 0x1e7ed, 0x1e7ee, @@ -1556,24 +1613,24 @@ static const OnigCodePoint CR_Graph[] = { 0x1f850, 0x1f859, 0x1f860, 0x1f887, 0x1f890, 0x1f8ad, - 0x1f8b0, 0x1f8b1, + 0x1f8b0, 0x1f8bb, + 0x1f8c0, 0x1f8c1, 0x1f900, 0x1fa53, 0x1fa60, 0x1fa6d, 0x1fa70, 0x1fa7c, - 0x1fa80, 0x1fa88, - 0x1fa90, 0x1fabd, - 0x1fabf, 0x1fac5, - 0x1face, 0x1fadb, - 0x1fae0, 0x1fae8, + 0x1fa80, 0x1fa89, + 0x1fa8f, 0x1fac6, + 0x1face, 0x1fadc, + 0x1fadf, 0x1fae9, 0x1faf0, 0x1faf8, 0x1fb00, 0x1fb92, - 0x1fb94, 0x1fbca, - 0x1fbf0, 0x1fbf9, + 0x1fb94, 0x1fbf9, 0x20000, 0x2a6df, 0x2a700, 0x2b739, 0x2b740, 0x2b81d, 0x2b820, 0x2cea1, 0x2ceb0, 0x2ebe0, + 0x2ebf0, 0x2ee5d, 0x2f800, 0x2fa1d, 0x30000, 0x3134a, 0x31350, 0x323af, @@ -1586,7 +1643,7 @@ static const OnigCodePoint CR_Graph[] = { /* 'Lower': [[:Lower:]] */ static const OnigCodePoint CR_Lower[] = { - 671, + 675, 0x0061, 0x007a, 0x00aa, 0x00aa, 0x00b5, 0x00b5, @@ -1866,6 +1923,7 @@ static const OnigCodePoint CR_Lower[] = { 0x10fc, 0x10ff, 0x13f8, 0x13fd, 0x1c80, 0x1c88, + 0x1c8a, 0x1c8a, 0x1d00, 0x1dbf, 0x1e01, 0x1e01, 0x1e03, 0x1e03, @@ -2198,11 +2256,13 @@ static const OnigCodePoint CR_Lower[] = { 0xa7c3, 0xa7c3, 0xa7c8, 0xa7c8, 0xa7ca, 0xa7ca, + 0xa7cd, 0xa7cd, 0xa7d1, 0xa7d1, 0xa7d3, 0xa7d3, 0xa7d5, 0xa7d5, 0xa7d7, 0xa7d7, 0xa7d9, 0xa7d9, + 0xa7db, 0xa7db, 0xa7f2, 0xa7f4, 0xa7f6, 0xa7f6, 0xa7f8, 0xa7fa, @@ -2223,6 +2283,7 @@ static const OnigCodePoint CR_Lower[] = { 0x10787, 0x107b0, 0x107b2, 0x107ba, 0x10cc0, 0x10cf2, + 0x10d70, 0x10d85, 0x118c0, 0x118df, 0x16e60, 0x16e7f, 0x1d41a, 0x1d433, @@ -2262,7 +2323,7 @@ static const OnigCodePoint CR_Lower[] = { /* 'Print': [[:Print:]] */ static const OnigCodePoint CR_Print[] = { - 709, + 733, 0x0020, 0x007e, 0x00a0, 0x0377, 0x037a, 0x037f, @@ -2287,7 +2348,7 @@ static const OnigCodePoint CR_Print[] = { 0x0860, 0x086a, 0x0870, 0x088e, 0x0890, 0x0891, - 0x0898, 0x0983, + 0x0897, 0x0983, 0x0985, 0x098c, 0x098f, 0x0990, 0x0993, 0x09a8, @@ -2479,11 +2540,10 @@ static const OnigCodePoint CR_Print[] = { 0x1aa0, 0x1aad, 0x1ab0, 0x1ace, 0x1b00, 0x1b4c, - 0x1b50, 0x1b7e, - 0x1b80, 0x1bf3, + 0x1b4e, 0x1bf3, 0x1bfc, 0x1c37, 0x1c3b, 0x1c49, - 0x1c4d, 0x1c88, + 0x1c4d, 0x1c8a, 0x1c90, 0x1cba, 0x1cbd, 0x1cc7, 0x1cd0, 0x1cfa, @@ -2511,7 +2571,7 @@ static const OnigCodePoint CR_Print[] = { 0x20a0, 0x20c0, 0x20d0, 0x20f0, 0x2100, 0x218b, - 0x2190, 0x2426, + 0x2190, 0x2429, 0x2440, 0x244a, 0x2460, 0x2b73, 0x2b76, 0x2b95, @@ -2534,22 +2594,21 @@ static const OnigCodePoint CR_Print[] = { 0x2e80, 0x2e99, 0x2e9b, 0x2ef3, 0x2f00, 0x2fd5, - 0x2ff0, 0x2ffb, - 0x3000, 0x303f, + 0x2ff0, 0x303f, 0x3041, 0x3096, 0x3099, 0x30ff, 0x3105, 0x312f, 0x3131, 0x318e, - 0x3190, 0x31e3, - 0x31f0, 0x321e, + 0x3190, 0x31e5, + 0x31ef, 0x321e, 0x3220, 0xa48c, 0xa490, 0xa4c6, 0xa4d0, 0xa62b, 0xa640, 0xa6f7, - 0xa700, 0xa7ca, + 0xa700, 0xa7cd, 0xa7d0, 0xa7d1, 0xa7d3, 0xa7d3, - 0xa7d5, 0xa7d9, + 0xa7d5, 0xa7dc, 0xa7f2, 0xa82c, 0xa830, 0xa839, 0xa840, 0xa877, @@ -2640,6 +2699,7 @@ static const OnigCodePoint CR_Print[] = { 0x105a3, 0x105b1, 0x105b3, 0x105b9, 0x105bb, 0x105bc, + 0x105c0, 0x105f3, 0x10600, 0x10736, 0x10740, 0x10755, 0x10760, 0x10767, @@ -2683,11 +2743,15 @@ static const OnigCodePoint CR_Print[] = { 0x10cc0, 0x10cf2, 0x10cfa, 0x10d27, 0x10d30, 0x10d39, + 0x10d40, 0x10d65, + 0x10d69, 0x10d85, + 0x10d8e, 0x10d8f, 0x10e60, 0x10e7e, 0x10e80, 0x10ea9, 0x10eab, 0x10ead, 0x10eb0, 0x10eb1, - 0x10efd, 0x10f27, + 0x10ec2, 0x10ec4, + 0x10efc, 0x10f27, 0x10f30, 0x10f59, 0x10f70, 0x10f89, 0x10fb0, 0x10fcb, @@ -2727,6 +2791,17 @@ static const OnigCodePoint CR_Print[] = { 0x1135d, 0x11363, 0x11366, 0x1136c, 0x11370, 0x11374, + 0x11380, 0x11389, + 0x1138b, 0x1138b, + 0x1138e, 0x1138e, + 0x11390, 0x113b5, + 0x113b7, 0x113c0, + 0x113c2, 0x113c2, + 0x113c5, 0x113c5, + 0x113c7, 0x113ca, + 0x113cc, 0x113d5, + 0x113d7, 0x113d8, + 0x113e1, 0x113e2, 0x11400, 0x1145b, 0x1145d, 0x11461, 0x11480, 0x114c7, @@ -2738,6 +2813,7 @@ static const OnigCodePoint CR_Print[] = { 0x11660, 0x1166c, 0x11680, 0x116b9, 0x116c0, 0x116c9, + 0x116d0, 0x116e3, 0x11700, 0x1171a, 0x1171d, 0x1172b, 0x11730, 0x11746, @@ -2758,6 +2834,8 @@ static const OnigCodePoint CR_Print[] = { 0x11a50, 0x11aa2, 0x11ab0, 0x11af8, 0x11b00, 0x11b09, + 0x11bc0, 0x11be1, + 0x11bf0, 0x11bf9, 0x11c00, 0x11c08, 0x11c0a, 0x11c36, 0x11c38, 0x11c45, @@ -2781,7 +2859,7 @@ static const OnigCodePoint CR_Print[] = { 0x11ee0, 0x11ef8, 0x11f00, 0x11f10, 0x11f12, 0x11f3a, - 0x11f3e, 0x11f59, + 0x11f3e, 0x11f5a, 0x11fb0, 0x11fb0, 0x11fc0, 0x11ff1, 0x11fff, 0x12399, @@ -2790,7 +2868,9 @@ static const OnigCodePoint CR_Print[] = { 0x12480, 0x12543, 0x12f90, 0x12ff2, 0x13000, 0x13455, + 0x13460, 0x143fa, 0x14400, 0x14646, + 0x16100, 0x16139, 0x16800, 0x16a38, 0x16a40, 0x16a5e, 0x16a60, 0x16a69, @@ -2803,6 +2883,7 @@ static const OnigCodePoint CR_Print[] = { 0x16b5b, 0x16b61, 0x16b63, 0x16b77, 0x16b7d, 0x16b8f, + 0x16d40, 0x16d79, 0x16e40, 0x16e9a, 0x16f00, 0x16f4a, 0x16f4f, 0x16f87, @@ -2811,7 +2892,7 @@ static const OnigCodePoint CR_Print[] = { 0x16ff0, 0x16ff1, 0x17000, 0x187f7, 0x18800, 0x18cd5, - 0x18d00, 0x18d08, + 0x18cff, 0x18d08, 0x1aff0, 0x1aff3, 0x1aff5, 0x1affb, 0x1affd, 0x1affe, @@ -2826,6 +2907,8 @@ static const OnigCodePoint CR_Print[] = { 0x1bc80, 0x1bc88, 0x1bc90, 0x1bc99, 0x1bc9c, 0x1bca3, + 0x1cc00, 0x1ccf9, + 0x1cd00, 0x1ceb3, 0x1cf00, 0x1cf2d, 0x1cf30, 0x1cf46, 0x1cf50, 0x1cfc3, @@ -2877,6 +2960,8 @@ static const OnigCodePoint CR_Print[] = { 0x1e2c0, 0x1e2f9, 0x1e2ff, 0x1e2ff, 0x1e4d0, 0x1e4f9, + 0x1e5d0, 0x1e5fa, + 0x1e5ff, 0x1e5ff, 0x1e7e0, 0x1e7e6, 0x1e7e8, 0x1e7eb, 0x1e7ed, 0x1e7ee, @@ -2946,24 +3031,24 @@ static const OnigCodePoint CR_Print[] = { 0x1f850, 0x1f859, 0x1f860, 0x1f887, 0x1f890, 0x1f8ad, - 0x1f8b0, 0x1f8b1, + 0x1f8b0, 0x1f8bb, + 0x1f8c0, 0x1f8c1, 0x1f900, 0x1fa53, 0x1fa60, 0x1fa6d, 0x1fa70, 0x1fa7c, - 0x1fa80, 0x1fa88, - 0x1fa90, 0x1fabd, - 0x1fabf, 0x1fac5, - 0x1face, 0x1fadb, - 0x1fae0, 0x1fae8, + 0x1fa80, 0x1fa89, + 0x1fa8f, 0x1fac6, + 0x1face, 0x1fadc, + 0x1fadf, 0x1fae9, 0x1faf0, 0x1faf8, 0x1fb00, 0x1fb92, - 0x1fb94, 0x1fbca, - 0x1fbf0, 0x1fbf9, + 0x1fb94, 0x1fbf9, 0x20000, 0x2a6df, 0x2a700, 0x2b739, 0x2b740, 0x2b81d, 0x2b820, 0x2cea1, 0x2ceb0, 0x2ebe0, + 0x2ebf0, 0x2ee5d, 0x2f800, 0x2fa1d, 0x30000, 0x3134a, 0x31350, 0x323af, @@ -2976,7 +3061,7 @@ static const OnigCodePoint CR_Print[] = { /* 'XPosixPunct': [[:Punct:]] */ static const OnigCodePoint CR_XPosixPunct[] = { - 186, + 193, 0x0021, 0x002f, 0x003a, 0x0040, 0x005b, 0x0060, @@ -3037,8 +3122,9 @@ static const OnigCodePoint CR_XPosixPunct[] = { 0x1a1e, 0x1a1f, 0x1aa0, 0x1aa6, 0x1aa8, 0x1aad, + 0x1b4e, 0x1b4f, 0x1b5a, 0x1b60, - 0x1b7d, 0x1b7e, + 0x1b7d, 0x1b7f, 0x1bfc, 0x1bff, 0x1c3b, 0x1c3f, 0x1c7e, 0x1c7f, @@ -3117,6 +3203,7 @@ static const OnigCodePoint CR_XPosixPunct[] = { 0x10af0, 0x10af6, 0x10b39, 0x10b3f, 0x10b99, 0x10b9c, + 0x10d6e, 0x10d6e, 0x10ead, 0x10ead, 0x10f55, 0x10f59, 0x10f86, 0x10f89, @@ -3131,6 +3218,8 @@ static const OnigCodePoint CR_XPosixPunct[] = { 0x111dd, 0x111df, 0x11238, 0x1123d, 0x112a9, 0x112a9, + 0x113d4, 0x113d5, + 0x113d7, 0x113d8, 0x1144b, 0x1144f, 0x1145a, 0x1145b, 0x1145d, 0x1145d, @@ -3147,6 +3236,7 @@ static const OnigCodePoint CR_XPosixPunct[] = { 0x11a9a, 0x11a9c, 0x11a9e, 0x11aa2, 0x11b00, 0x11b09, + 0x11be1, 0x11be1, 0x11c41, 0x11c45, 0x11c70, 0x11c71, 0x11ef7, 0x11ef8, @@ -3158,10 +3248,12 @@ static const OnigCodePoint CR_XPosixPunct[] = { 0x16af5, 0x16af5, 0x16b37, 0x16b3b, 0x16b44, 0x16b44, + 0x16d6d, 0x16d6f, 0x16e97, 0x16e9a, 0x16fe2, 0x16fe2, 0x1bc9f, 0x1bc9f, 0x1da87, 0x1da8b, + 0x1e5ff, 0x1e5ff, 0x1e95e, 0x1e95f, }; /* CR_XPosixPunct */ @@ -3182,7 +3274,7 @@ static const OnigCodePoint CR_Space[] = { /* 'Upper': [[:Upper:]] */ static const OnigCodePoint CR_Upper[] = { - 651, + 656, 0x0041, 0x005a, 0x00c0, 0x00d6, 0x00d8, 0x00de, @@ -3459,6 +3551,7 @@ static const OnigCodePoint CR_Upper[] = { 0x10c7, 0x10c7, 0x10cd, 0x10cd, 0x13a0, 0x13f5, + 0x1c89, 0x1c89, 0x1c90, 0x1cba, 0x1cbd, 0x1cbf, 0x1e00, 0x1e00, @@ -3785,9 +3878,12 @@ static const OnigCodePoint CR_Upper[] = { 0xa7c2, 0xa7c2, 0xa7c4, 0xa7c7, 0xa7c9, 0xa7c9, + 0xa7cb, 0xa7cc, 0xa7d0, 0xa7d0, 0xa7d6, 0xa7d6, 0xa7d8, 0xa7d8, + 0xa7da, 0xa7da, + 0xa7dc, 0xa7dc, 0xa7f5, 0xa7f5, 0xff21, 0xff3a, 0x10400, 0x10427, @@ -3797,6 +3893,7 @@ static const OnigCodePoint CR_Upper[] = { 0x1058c, 0x10592, 0x10594, 0x10595, 0x10c80, 0x10cb2, + 0x10d50, 0x10d65, 0x118a0, 0x118bf, 0x16e40, 0x16e5f, 0x1d400, 0x1d419, @@ -3846,7 +3943,7 @@ static const OnigCodePoint CR_XDigit[] = { /* 'Word': [[:Word:]] */ static const OnigCodePoint CR_Word[] = { - 770, + 796, 0x0030, 0x0039, 0x0041, 0x005a, 0x005f, 0x005f, @@ -3899,7 +3996,7 @@ static const OnigCodePoint CR_Word[] = { 0x0860, 0x086a, 0x0870, 0x0887, 0x0889, 0x088e, - 0x0898, 0x08e1, + 0x0897, 0x08e1, 0x08e3, 0x0963, 0x0966, 0x096f, 0x0971, 0x0983, @@ -4120,7 +4217,7 @@ static const OnigCodePoint CR_Word[] = { 0x1c00, 0x1c37, 0x1c40, 0x1c49, 0x1c4d, 0x1c7d, - 0x1c80, 0x1c88, + 0x1c80, 0x1c8a, 0x1c90, 0x1cba, 0x1cbd, 0x1cbf, 0x1cd0, 0x1cd2, @@ -4144,6 +4241,7 @@ static const OnigCodePoint CR_Word[] = { 0x1fe0, 0x1fec, 0x1ff2, 0x1ff4, 0x1ff6, 0x1ffc, + 0x200c, 0x200d, 0x203f, 0x2040, 0x2054, 0x2054, 0x2071, 0x2071, @@ -4206,10 +4304,10 @@ static const OnigCodePoint CR_Word[] = { 0xa67f, 0xa6f1, 0xa717, 0xa71f, 0xa722, 0xa788, - 0xa78b, 0xa7ca, + 0xa78b, 0xa7cd, 0xa7d0, 0xa7d1, 0xa7d3, 0xa7d3, - 0xa7d5, 0xa7d9, + 0xa7d5, 0xa7dc, 0xa7f2, 0xa827, 0xa82c, 0xa82c, 0xa840, 0xa873, @@ -4307,6 +4405,7 @@ static const OnigCodePoint CR_Word[] = { 0x105a3, 0x105b1, 0x105b3, 0x105b9, 0x105bb, 0x105bc, + 0x105c0, 0x105f3, 0x10600, 0x10736, 0x10740, 0x10755, 0x10760, 0x10767, @@ -4347,10 +4446,14 @@ static const OnigCodePoint CR_Word[] = { 0x10cc0, 0x10cf2, 0x10d00, 0x10d27, 0x10d30, 0x10d39, + 0x10d40, 0x10d65, + 0x10d69, 0x10d6d, + 0x10d6f, 0x10d85, 0x10e80, 0x10ea9, 0x10eab, 0x10eac, 0x10eb0, 0x10eb1, - 0x10efd, 0x10f1c, + 0x10ec2, 0x10ec4, + 0x10efc, 0x10f1c, 0x10f27, 0x10f27, 0x10f30, 0x10f50, 0x10f70, 0x10f85, @@ -4396,6 +4499,16 @@ static const OnigCodePoint CR_Word[] = { 0x1135d, 0x11363, 0x11366, 0x1136c, 0x11370, 0x11374, + 0x11380, 0x11389, + 0x1138b, 0x1138b, + 0x1138e, 0x1138e, + 0x11390, 0x113b5, + 0x113b7, 0x113c0, + 0x113c2, 0x113c2, + 0x113c5, 0x113c5, + 0x113c7, 0x113ca, + 0x113cc, 0x113d3, + 0x113e1, 0x113e2, 0x11400, 0x1144a, 0x11450, 0x11459, 0x1145e, 0x11461, @@ -4410,6 +4523,7 @@ static const OnigCodePoint CR_Word[] = { 0x11650, 0x11659, 0x11680, 0x116b8, 0x116c0, 0x116c9, + 0x116d0, 0x116e3, 0x11700, 0x1171a, 0x1171d, 0x1172b, 0x11730, 0x11739, @@ -4433,6 +4547,8 @@ static const OnigCodePoint CR_Word[] = { 0x11a50, 0x11a99, 0x11a9d, 0x11a9d, 0x11ab0, 0x11af8, + 0x11bc0, 0x11be0, + 0x11bf0, 0x11bf9, 0x11c00, 0x11c08, 0x11c0a, 0x11c36, 0x11c38, 0x11c40, @@ -4457,7 +4573,7 @@ static const OnigCodePoint CR_Word[] = { 0x11f00, 0x11f10, 0x11f12, 0x11f3a, 0x11f3e, 0x11f42, - 0x11f50, 0x11f59, + 0x11f50, 0x11f5a, 0x11fb0, 0x11fb0, 0x12000, 0x12399, 0x12400, 0x1246e, @@ -4465,7 +4581,9 @@ static const OnigCodePoint CR_Word[] = { 0x12f90, 0x12ff0, 0x13000, 0x1342f, 0x13440, 0x13455, + 0x13460, 0x143fa, 0x14400, 0x14646, + 0x16100, 0x16139, 0x16800, 0x16a38, 0x16a40, 0x16a5e, 0x16a60, 0x16a69, @@ -4478,6 +4596,8 @@ static const OnigCodePoint CR_Word[] = { 0x16b50, 0x16b59, 0x16b63, 0x16b77, 0x16b7d, 0x16b8f, + 0x16d40, 0x16d6c, + 0x16d70, 0x16d79, 0x16e40, 0x16e7f, 0x16f00, 0x16f4a, 0x16f4f, 0x16f87, @@ -4487,7 +4607,7 @@ static const OnigCodePoint CR_Word[] = { 0x16ff0, 0x16ff1, 0x17000, 0x187f7, 0x18800, 0x18cd5, - 0x18d00, 0x18d08, + 0x18cff, 0x18d08, 0x1aff0, 0x1aff3, 0x1aff5, 0x1affb, 0x1affd, 0x1affe, @@ -4502,6 +4622,7 @@ static const OnigCodePoint CR_Word[] = { 0x1bc80, 0x1bc88, 0x1bc90, 0x1bc99, 0x1bc9d, 0x1bc9e, + 0x1ccf0, 0x1ccf9, 0x1cf00, 0x1cf2d, 0x1cf30, 0x1cf46, 0x1d165, 0x1d169, @@ -4563,6 +4684,7 @@ static const OnigCodePoint CR_Word[] = { 0x1e290, 0x1e2ae, 0x1e2c0, 0x1e2f9, 0x1e4d0, 0x1e4f9, + 0x1e5d0, 0x1e5fa, 0x1e7e0, 0x1e7e6, 0x1e7e8, 0x1e7eb, 0x1e7ed, 0x1e7ee, @@ -4613,6 +4735,7 @@ static const OnigCodePoint CR_Word[] = { 0x2b740, 0x2b81d, 0x2b820, 0x2cea1, 0x2ceb0, 0x2ebe0, + 0x2ebf0, 0x2ee5d, 0x2f800, 0x2fa1d, 0x30000, 0x3134a, 0x31350, 0x323af, @@ -4621,7 +4744,7 @@ static const OnigCodePoint CR_Word[] = { /* 'Alnum': [[:Alnum:]] */ static const OnigCodePoint CR_Alnum[] = { - 772, + 802, 0x0030, 0x0039, 0x0041, 0x005a, 0x0061, 0x007a, @@ -4636,7 +4759,7 @@ static const OnigCodePoint CR_Alnum[] = { 0x02ec, 0x02ec, 0x02ee, 0x02ee, 0x0345, 0x0345, - 0x0370, 0x0374, + 0x0363, 0x0374, 0x0376, 0x0377, 0x037a, 0x037d, 0x037f, 0x037f, @@ -4676,6 +4799,7 @@ static const OnigCodePoint CR_Alnum[] = { 0x0860, 0x086a, 0x0870, 0x0887, 0x0889, 0x088e, + 0x0897, 0x0897, 0x08a0, 0x08c9, 0x08d4, 0x08df, 0x08e3, 0x08e9, @@ -4904,7 +5028,7 @@ static const OnigCodePoint CR_Alnum[] = { 0x1c00, 0x1c36, 0x1c40, 0x1c49, 0x1c4d, 0x1c7d, - 0x1c80, 0x1c88, + 0x1c80, 0x1c8a, 0x1c90, 0x1cba, 0x1cbd, 0x1cbf, 0x1ce9, 0x1cec, @@ -4912,7 +5036,7 @@ static const OnigCodePoint CR_Alnum[] = { 0x1cf5, 0x1cf6, 0x1cfa, 0x1cfa, 0x1d00, 0x1dbf, - 0x1de7, 0x1df4, + 0x1dd3, 0x1df4, 0x1e00, 0x1f15, 0x1f18, 0x1f1d, 0x1f20, 0x1f45, @@ -4991,10 +5115,10 @@ static const OnigCodePoint CR_Alnum[] = { 0xa67f, 0xa6ef, 0xa717, 0xa71f, 0xa722, 0xa788, - 0xa78b, 0xa7ca, + 0xa78b, 0xa7cd, 0xa7d0, 0xa7d1, 0xa7d3, 0xa7d3, - 0xa7d5, 0xa7d9, + 0xa7d5, 0xa7dc, 0xa7f2, 0xa805, 0xa807, 0xa827, 0xa840, 0xa873, @@ -5088,6 +5212,7 @@ static const OnigCodePoint CR_Alnum[] = { 0x105a3, 0x105b1, 0x105b3, 0x105b9, 0x105bb, 0x105bc, + 0x105c0, 0x105f3, 0x10600, 0x10736, 0x10740, 0x10755, 0x10760, 0x10767, @@ -5126,9 +5251,14 @@ static const OnigCodePoint CR_Alnum[] = { 0x10cc0, 0x10cf2, 0x10d00, 0x10d27, 0x10d30, 0x10d39, + 0x10d40, 0x10d65, + 0x10d69, 0x10d69, + 0x10d6f, 0x10d85, 0x10e80, 0x10ea9, 0x10eab, 0x10eac, 0x10eb0, 0x10eb1, + 0x10ec2, 0x10ec4, + 0x10efc, 0x10efc, 0x10f00, 0x10f1c, 0x10f27, 0x10f27, 0x10f30, 0x10f45, @@ -5175,6 +5305,17 @@ static const OnigCodePoint CR_Alnum[] = { 0x11350, 0x11350, 0x11357, 0x11357, 0x1135d, 0x11363, + 0x11380, 0x11389, + 0x1138b, 0x1138b, + 0x1138e, 0x1138e, + 0x11390, 0x113b5, + 0x113b7, 0x113c0, + 0x113c2, 0x113c2, + 0x113c5, 0x113c5, + 0x113c7, 0x113ca, + 0x113cc, 0x113cd, + 0x113d1, 0x113d1, + 0x113d3, 0x113d3, 0x11400, 0x11441, 0x11443, 0x11445, 0x11447, 0x1144a, @@ -5194,6 +5335,7 @@ static const OnigCodePoint CR_Alnum[] = { 0x11680, 0x116b5, 0x116b8, 0x116b8, 0x116c0, 0x116c9, + 0x116d0, 0x116e3, 0x11700, 0x1171a, 0x1171d, 0x1172a, 0x11730, 0x11739, @@ -5219,6 +5361,8 @@ static const OnigCodePoint CR_Alnum[] = { 0x11a50, 0x11a97, 0x11a9d, 0x11a9d, 0x11ab0, 0x11af8, + 0x11bc0, 0x11be0, + 0x11bf0, 0x11bf9, 0x11c00, 0x11c08, 0x11c0a, 0x11c36, 0x11c38, 0x11c3e, @@ -5255,7 +5399,10 @@ static const OnigCodePoint CR_Alnum[] = { 0x12f90, 0x12ff0, 0x13000, 0x1342f, 0x13441, 0x13446, + 0x13460, 0x143fa, 0x14400, 0x14646, + 0x16100, 0x1612e, + 0x16130, 0x16139, 0x16800, 0x16a38, 0x16a40, 0x16a5e, 0x16a60, 0x16a69, @@ -5267,6 +5414,8 @@ static const OnigCodePoint CR_Alnum[] = { 0x16b50, 0x16b59, 0x16b63, 0x16b77, 0x16b7d, 0x16b8f, + 0x16d40, 0x16d6c, + 0x16d70, 0x16d79, 0x16e40, 0x16e7f, 0x16f00, 0x16f4a, 0x16f4f, 0x16f87, @@ -5276,7 +5425,7 @@ static const OnigCodePoint CR_Alnum[] = { 0x16ff0, 0x16ff1, 0x17000, 0x187f7, 0x18800, 0x18cd5, - 0x18d00, 0x18d08, + 0x18cff, 0x18d08, 0x1aff0, 0x1aff3, 0x1aff5, 0x1affb, 0x1affd, 0x1affe, @@ -5291,6 +5440,7 @@ static const OnigCodePoint CR_Alnum[] = { 0x1bc80, 0x1bc88, 0x1bc90, 0x1bc99, 0x1bc9e, 0x1bc9e, + 0x1ccf0, 0x1ccf9, 0x1d400, 0x1d454, 0x1d456, 0x1d49c, 0x1d49e, 0x1d49f, @@ -5340,6 +5490,8 @@ static const OnigCodePoint CR_Alnum[] = { 0x1e2f0, 0x1e2f9, 0x1e4d0, 0x1e4eb, 0x1e4f0, 0x1e4f9, + 0x1e5d0, 0x1e5ed, + 0x1e5f0, 0x1e5fa, 0x1e7e0, 0x1e7e6, 0x1e7e8, 0x1e7eb, 0x1e7ed, 0x1e7ee, @@ -5391,6 +5543,7 @@ static const OnigCodePoint CR_Alnum[] = { 0x2b740, 0x2b81d, 0x2b820, 0x2cea1, 0x2ceb0, 0x2ebe0, + 0x2ebf0, 0x2ee5d, 0x2f800, 0x2fa1d, 0x30000, 0x3134a, 0x31350, 0x323af, @@ -5404,7 +5557,7 @@ static const OnigCodePoint CR_ASCII[] = { /* 'Punct': [[:Punct:]] */ static const OnigCodePoint CR_Punct[] = { - 191, + 198, 0x0021, 0x0023, 0x0025, 0x002a, 0x002c, 0x002f, @@ -5470,8 +5623,9 @@ static const OnigCodePoint CR_Punct[] = { 0x1a1e, 0x1a1f, 0x1aa0, 0x1aa6, 0x1aa8, 0x1aad, + 0x1b4e, 0x1b4f, 0x1b5a, 0x1b60, - 0x1b7d, 0x1b7e, + 0x1b7d, 0x1b7f, 0x1bfc, 0x1bff, 0x1c3b, 0x1c3f, 0x1c7e, 0x1c7f, @@ -5550,6 +5704,7 @@ static const OnigCodePoint CR_Punct[] = { 0x10af0, 0x10af6, 0x10b39, 0x10b3f, 0x10b99, 0x10b9c, + 0x10d6e, 0x10d6e, 0x10ead, 0x10ead, 0x10f55, 0x10f59, 0x10f86, 0x10f89, @@ -5564,6 +5719,8 @@ static const OnigCodePoint CR_Punct[] = { 0x111dd, 0x111df, 0x11238, 0x1123d, 0x112a9, 0x112a9, + 0x113d4, 0x113d5, + 0x113d7, 0x113d8, 0x1144b, 0x1144f, 0x1145a, 0x1145b, 0x1145d, 0x1145d, @@ -5580,6 +5737,7 @@ static const OnigCodePoint CR_Punct[] = { 0x11a9a, 0x11a9c, 0x11a9e, 0x11aa2, 0x11b00, 0x11b09, + 0x11be1, 0x11be1, 0x11c41, 0x11c45, 0x11c70, 0x11c71, 0x11ef7, 0x11ef8, @@ -5591,10 +5749,12 @@ static const OnigCodePoint CR_Punct[] = { 0x16af5, 0x16af5, 0x16b37, 0x16b3b, 0x16b44, 0x16b44, + 0x16d6d, 0x16d6f, 0x16e97, 0x16e9a, 0x16fe2, 0x16fe2, 0x1bc9f, 0x1bc9f, 0x1da87, 0x1da8b, + 0x1e5ff, 0x1e5ff, 0x1e95e, 0x1e95f, }; /* CR_Punct */ @@ -5607,7 +5767,7 @@ static const OnigCodePoint CR_Any[] = { /* 'Assigned': - */ static const OnigCodePoint CR_Assigned[] = { - 707, + 731, 0x0000, 0x0377, 0x037a, 0x037f, 0x0384, 0x038a, @@ -5631,7 +5791,7 @@ static const OnigCodePoint CR_Assigned[] = { 0x0860, 0x086a, 0x0870, 0x088e, 0x0890, 0x0891, - 0x0898, 0x0983, + 0x0897, 0x0983, 0x0985, 0x098c, 0x098f, 0x0990, 0x0993, 0x09a8, @@ -5823,11 +5983,10 @@ static const OnigCodePoint CR_Assigned[] = { 0x1aa0, 0x1aad, 0x1ab0, 0x1ace, 0x1b00, 0x1b4c, - 0x1b50, 0x1b7e, - 0x1b80, 0x1bf3, + 0x1b4e, 0x1bf3, 0x1bfc, 0x1c37, 0x1c3b, 0x1c49, - 0x1c4d, 0x1c88, + 0x1c4d, 0x1c8a, 0x1c90, 0x1cba, 0x1cbd, 0x1cc7, 0x1cd0, 0x1cfa, @@ -5854,7 +6013,7 @@ static const OnigCodePoint CR_Assigned[] = { 0x20a0, 0x20c0, 0x20d0, 0x20f0, 0x2100, 0x218b, - 0x2190, 0x2426, + 0x2190, 0x2429, 0x2440, 0x244a, 0x2460, 0x2b73, 0x2b76, 0x2b95, @@ -5877,22 +6036,21 @@ static const OnigCodePoint CR_Assigned[] = { 0x2e80, 0x2e99, 0x2e9b, 0x2ef3, 0x2f00, 0x2fd5, - 0x2ff0, 0x2ffb, - 0x3000, 0x303f, + 0x2ff0, 0x303f, 0x3041, 0x3096, 0x3099, 0x30ff, 0x3105, 0x312f, 0x3131, 0x318e, - 0x3190, 0x31e3, - 0x31f0, 0x321e, + 0x3190, 0x31e5, + 0x31ef, 0x321e, 0x3220, 0xa48c, 0xa490, 0xa4c6, 0xa4d0, 0xa62b, 0xa640, 0xa6f7, - 0xa700, 0xa7ca, + 0xa700, 0xa7cd, 0xa7d0, 0xa7d1, 0xa7d3, 0xa7d3, - 0xa7d5, 0xa7d9, + 0xa7d5, 0xa7dc, 0xa7f2, 0xa82c, 0xa830, 0xa839, 0xa840, 0xa877, @@ -5983,6 +6141,7 @@ static const OnigCodePoint CR_Assigned[] = { 0x105a3, 0x105b1, 0x105b3, 0x105b9, 0x105bb, 0x105bc, + 0x105c0, 0x105f3, 0x10600, 0x10736, 0x10740, 0x10755, 0x10760, 0x10767, @@ -6026,11 +6185,15 @@ static const OnigCodePoint CR_Assigned[] = { 0x10cc0, 0x10cf2, 0x10cfa, 0x10d27, 0x10d30, 0x10d39, + 0x10d40, 0x10d65, + 0x10d69, 0x10d85, + 0x10d8e, 0x10d8f, 0x10e60, 0x10e7e, 0x10e80, 0x10ea9, 0x10eab, 0x10ead, 0x10eb0, 0x10eb1, - 0x10efd, 0x10f27, + 0x10ec2, 0x10ec4, + 0x10efc, 0x10f27, 0x10f30, 0x10f59, 0x10f70, 0x10f89, 0x10fb0, 0x10fcb, @@ -6070,6 +6233,17 @@ static const OnigCodePoint CR_Assigned[] = { 0x1135d, 0x11363, 0x11366, 0x1136c, 0x11370, 0x11374, + 0x11380, 0x11389, + 0x1138b, 0x1138b, + 0x1138e, 0x1138e, + 0x11390, 0x113b5, + 0x113b7, 0x113c0, + 0x113c2, 0x113c2, + 0x113c5, 0x113c5, + 0x113c7, 0x113ca, + 0x113cc, 0x113d5, + 0x113d7, 0x113d8, + 0x113e1, 0x113e2, 0x11400, 0x1145b, 0x1145d, 0x11461, 0x11480, 0x114c7, @@ -6081,6 +6255,7 @@ static const OnigCodePoint CR_Assigned[] = { 0x11660, 0x1166c, 0x11680, 0x116b9, 0x116c0, 0x116c9, + 0x116d0, 0x116e3, 0x11700, 0x1171a, 0x1171d, 0x1172b, 0x11730, 0x11746, @@ -6101,6 +6276,8 @@ static const OnigCodePoint CR_Assigned[] = { 0x11a50, 0x11aa2, 0x11ab0, 0x11af8, 0x11b00, 0x11b09, + 0x11bc0, 0x11be1, + 0x11bf0, 0x11bf9, 0x11c00, 0x11c08, 0x11c0a, 0x11c36, 0x11c38, 0x11c45, @@ -6124,7 +6301,7 @@ static const OnigCodePoint CR_Assigned[] = { 0x11ee0, 0x11ef8, 0x11f00, 0x11f10, 0x11f12, 0x11f3a, - 0x11f3e, 0x11f59, + 0x11f3e, 0x11f5a, 0x11fb0, 0x11fb0, 0x11fc0, 0x11ff1, 0x11fff, 0x12399, @@ -6133,7 +6310,9 @@ static const OnigCodePoint CR_Assigned[] = { 0x12480, 0x12543, 0x12f90, 0x12ff2, 0x13000, 0x13455, + 0x13460, 0x143fa, 0x14400, 0x14646, + 0x16100, 0x16139, 0x16800, 0x16a38, 0x16a40, 0x16a5e, 0x16a60, 0x16a69, @@ -6146,6 +6325,7 @@ static const OnigCodePoint CR_Assigned[] = { 0x16b5b, 0x16b61, 0x16b63, 0x16b77, 0x16b7d, 0x16b8f, + 0x16d40, 0x16d79, 0x16e40, 0x16e9a, 0x16f00, 0x16f4a, 0x16f4f, 0x16f87, @@ -6154,7 +6334,7 @@ static const OnigCodePoint CR_Assigned[] = { 0x16ff0, 0x16ff1, 0x17000, 0x187f7, 0x18800, 0x18cd5, - 0x18d00, 0x18d08, + 0x18cff, 0x18d08, 0x1aff0, 0x1aff3, 0x1aff5, 0x1affb, 0x1affd, 0x1affe, @@ -6169,6 +6349,8 @@ static const OnigCodePoint CR_Assigned[] = { 0x1bc80, 0x1bc88, 0x1bc90, 0x1bc99, 0x1bc9c, 0x1bca3, + 0x1cc00, 0x1ccf9, + 0x1cd00, 0x1ceb3, 0x1cf00, 0x1cf2d, 0x1cf30, 0x1cf46, 0x1cf50, 0x1cfc3, @@ -6220,6 +6402,8 @@ static const OnigCodePoint CR_Assigned[] = { 0x1e2c0, 0x1e2f9, 0x1e2ff, 0x1e2ff, 0x1e4d0, 0x1e4f9, + 0x1e5d0, 0x1e5fa, + 0x1e5ff, 0x1e5ff, 0x1e7e0, 0x1e7e6, 0x1e7e8, 0x1e7eb, 0x1e7ed, 0x1e7ee, @@ -6289,24 +6473,24 @@ static const OnigCodePoint CR_Assigned[] = { 0x1f850, 0x1f859, 0x1f860, 0x1f887, 0x1f890, 0x1f8ad, - 0x1f8b0, 0x1f8b1, + 0x1f8b0, 0x1f8bb, + 0x1f8c0, 0x1f8c1, 0x1f900, 0x1fa53, 0x1fa60, 0x1fa6d, 0x1fa70, 0x1fa7c, - 0x1fa80, 0x1fa88, - 0x1fa90, 0x1fabd, - 0x1fabf, 0x1fac5, - 0x1face, 0x1fadb, - 0x1fae0, 0x1fae8, + 0x1fa80, 0x1fa89, + 0x1fa8f, 0x1fac6, + 0x1face, 0x1fadc, + 0x1fadf, 0x1fae9, 0x1faf0, 0x1faf8, 0x1fb00, 0x1fb92, - 0x1fb94, 0x1fbca, - 0x1fbf0, 0x1fbf9, + 0x1fb94, 0x1fbf9, 0x20000, 0x2a6df, 0x2a700, 0x2b739, 0x2b740, 0x2b81d, 0x2b820, 0x2cea1, 0x2ceb0, 0x2ebe0, + 0x2ebf0, 0x2ee5d, 0x2f800, 0x2fa1d, 0x30000, 0x3134a, 0x31350, 0x323af, @@ -6319,7 +6503,7 @@ static const OnigCodePoint CR_Assigned[] = { /* 'C': Major Category */ static const OnigCodePoint CR_C[] = { - 712, + 736, 0x0000, 0x001f, 0x007f, 0x009f, 0x00ad, 0x00ad, @@ -6346,7 +6530,7 @@ static const OnigCodePoint CR_C[] = { 0x085c, 0x085d, 0x085f, 0x085f, 0x086b, 0x086f, - 0x088f, 0x0897, + 0x088f, 0x0896, 0x08e2, 0x08e2, 0x0984, 0x0984, 0x098d, 0x098e, @@ -6540,12 +6724,11 @@ static const OnigCodePoint CR_C[] = { 0x1a9a, 0x1a9f, 0x1aae, 0x1aaf, 0x1acf, 0x1aff, - 0x1b4d, 0x1b4f, - 0x1b7f, 0x1b7f, + 0x1b4d, 0x1b4d, 0x1bf4, 0x1bfb, 0x1c38, 0x1c3a, 0x1c4a, 0x1c4c, - 0x1c89, 0x1c8f, + 0x1c8b, 0x1c8f, 0x1cbb, 0x1cbc, 0x1cc8, 0x1ccf, 0x1cfb, 0x1cff, @@ -6574,7 +6757,7 @@ static const OnigCodePoint CR_C[] = { 0x20c1, 0x20cf, 0x20f1, 0x20ff, 0x218c, 0x218f, - 0x2427, 0x243f, + 0x242a, 0x243f, 0x244b, 0x245f, 0x2b74, 0x2b75, 0x2b96, 0x2b96, @@ -6597,22 +6780,21 @@ static const OnigCodePoint CR_C[] = { 0x2e9a, 0x2e9a, 0x2ef4, 0x2eff, 0x2fd6, 0x2fef, - 0x2ffc, 0x2fff, 0x3040, 0x3040, 0x3097, 0x3098, 0x3100, 0x3104, 0x3130, 0x3130, 0x318f, 0x318f, - 0x31e4, 0x31ef, + 0x31e6, 0x31ee, 0x321f, 0x321f, 0xa48d, 0xa48f, 0xa4c7, 0xa4cf, 0xa62c, 0xa63f, 0xa6f8, 0xa6ff, - 0xa7cb, 0xa7cf, + 0xa7ce, 0xa7cf, 0xa7d2, 0xa7d2, 0xa7d4, 0xa7d4, - 0xa7da, 0xa7f1, + 0xa7dd, 0xa7f1, 0xa82d, 0xa82f, 0xa83a, 0xa83f, 0xa878, 0xa87f, @@ -6701,7 +6883,8 @@ static const OnigCodePoint CR_C[] = { 0x105a2, 0x105a2, 0x105b2, 0x105b2, 0x105ba, 0x105ba, - 0x105bd, 0x105ff, + 0x105bd, 0x105bf, + 0x105f4, 0x105ff, 0x10737, 0x1073f, 0x10756, 0x1075f, 0x10768, 0x1077f, @@ -6744,11 +6927,15 @@ static const OnigCodePoint CR_C[] = { 0x10cb3, 0x10cbf, 0x10cf3, 0x10cf9, 0x10d28, 0x10d2f, - 0x10d3a, 0x10e5f, + 0x10d3a, 0x10d3f, + 0x10d66, 0x10d68, + 0x10d86, 0x10d8d, + 0x10d90, 0x10e5f, 0x10e7f, 0x10e7f, 0x10eaa, 0x10eaa, 0x10eae, 0x10eaf, - 0x10eb2, 0x10efc, + 0x10eb2, 0x10ec1, + 0x10ec5, 0x10efb, 0x10f28, 0x10f2f, 0x10f5a, 0x10f6f, 0x10f8a, 0x10faf, @@ -6788,7 +6975,18 @@ static const OnigCodePoint CR_C[] = { 0x11358, 0x1135c, 0x11364, 0x11365, 0x1136d, 0x1136f, - 0x11375, 0x113ff, + 0x11375, 0x1137f, + 0x1138a, 0x1138a, + 0x1138c, 0x1138d, + 0x1138f, 0x1138f, + 0x113b6, 0x113b6, + 0x113c1, 0x113c1, + 0x113c3, 0x113c4, + 0x113c6, 0x113c6, + 0x113cb, 0x113cb, + 0x113d6, 0x113d6, + 0x113d9, 0x113e0, + 0x113e3, 0x113ff, 0x1145c, 0x1145c, 0x11462, 0x1147f, 0x114c8, 0x114cf, @@ -6799,7 +6997,8 @@ static const OnigCodePoint CR_C[] = { 0x1165a, 0x1165f, 0x1166d, 0x1167f, 0x116ba, 0x116bf, - 0x116ca, 0x116ff, + 0x116ca, 0x116cf, + 0x116e4, 0x116ff, 0x1171b, 0x1171c, 0x1172c, 0x1172f, 0x11747, 0x117ff, @@ -6819,7 +7018,9 @@ static const OnigCodePoint CR_C[] = { 0x11a48, 0x11a4f, 0x11aa3, 0x11aaf, 0x11af9, 0x11aff, - 0x11b0a, 0x11bff, + 0x11b0a, 0x11bbf, + 0x11be2, 0x11bef, + 0x11bfa, 0x11bff, 0x11c09, 0x11c09, 0x11c37, 0x11c37, 0x11c46, 0x11c4f, @@ -6843,7 +7044,7 @@ static const OnigCodePoint CR_C[] = { 0x11ef9, 0x11eff, 0x11f11, 0x11f11, 0x11f3b, 0x11f3d, - 0x11f5a, 0x11faf, + 0x11f5b, 0x11faf, 0x11fb1, 0x11fbf, 0x11ff2, 0x11ffe, 0x1239a, 0x123ff, @@ -6852,8 +7053,10 @@ static const OnigCodePoint CR_C[] = { 0x12544, 0x12f8f, 0x12ff3, 0x12fff, 0x13430, 0x1343f, - 0x13456, 0x143ff, - 0x14647, 0x167ff, + 0x13456, 0x1345f, + 0x143fb, 0x143ff, + 0x14647, 0x160ff, + 0x1613a, 0x167ff, 0x16a39, 0x16a3f, 0x16a5f, 0x16a5f, 0x16a6a, 0x16a6d, @@ -6865,7 +7068,8 @@ static const OnigCodePoint CR_C[] = { 0x16b5a, 0x16b5a, 0x16b62, 0x16b62, 0x16b78, 0x16b7c, - 0x16b90, 0x16e3f, + 0x16b90, 0x16d3f, + 0x16d7a, 0x16e3f, 0x16e9b, 0x16eff, 0x16f4b, 0x16f4e, 0x16f88, 0x16f8e, @@ -6873,7 +7077,7 @@ static const OnigCodePoint CR_C[] = { 0x16fe5, 0x16fef, 0x16ff2, 0x16fff, 0x187f8, 0x187ff, - 0x18cd6, 0x18cff, + 0x18cd6, 0x18cfe, 0x18d09, 0x1afef, 0x1aff4, 0x1aff4, 0x1affc, 0x1affc, @@ -6888,7 +7092,9 @@ static const OnigCodePoint CR_C[] = { 0x1bc7d, 0x1bc7f, 0x1bc89, 0x1bc8f, 0x1bc9a, 0x1bc9b, - 0x1bca0, 0x1ceff, + 0x1bca0, 0x1cbff, + 0x1ccfa, 0x1ccff, + 0x1ceb4, 0x1ceff, 0x1cf2e, 0x1cf2f, 0x1cf47, 0x1cf4f, 0x1cfc4, 0x1cfff, @@ -6940,7 +7146,9 @@ static const OnigCodePoint CR_C[] = { 0x1e2af, 0x1e2bf, 0x1e2fa, 0x1e2fe, 0x1e300, 0x1e4cf, - 0x1e4fa, 0x1e7df, + 0x1e4fa, 0x1e5cf, + 0x1e5fb, 0x1e5fe, + 0x1e600, 0x1e7df, 0x1e7e7, 0x1e7e7, 0x1e7ec, 0x1e7ec, 0x1e7ef, 0x1e7ef, @@ -7010,24 +7218,24 @@ static const OnigCodePoint CR_C[] = { 0x1f85a, 0x1f85f, 0x1f888, 0x1f88f, 0x1f8ae, 0x1f8af, - 0x1f8b2, 0x1f8ff, + 0x1f8bc, 0x1f8bf, + 0x1f8c2, 0x1f8ff, 0x1fa54, 0x1fa5f, 0x1fa6e, 0x1fa6f, 0x1fa7d, 0x1fa7f, - 0x1fa89, 0x1fa8f, - 0x1fabe, 0x1fabe, - 0x1fac6, 0x1facd, - 0x1fadc, 0x1fadf, - 0x1fae9, 0x1faef, + 0x1fa8a, 0x1fa8e, + 0x1fac7, 0x1facd, + 0x1fadd, 0x1fade, + 0x1faea, 0x1faef, 0x1faf9, 0x1faff, 0x1fb93, 0x1fb93, - 0x1fbcb, 0x1fbef, 0x1fbfa, 0x1ffff, 0x2a6e0, 0x2a6ff, 0x2b73a, 0x2b73f, 0x2b81e, 0x2b81f, 0x2cea2, 0x2ceaf, - 0x2ebe1, 0x2f7ff, + 0x2ebe1, 0x2ebef, + 0x2ee5e, 0x2f7ff, 0x2fa1e, 0x2ffff, 0x3134b, 0x3134f, 0x323b0, 0xe00ff, @@ -7065,7 +7273,7 @@ static const OnigCodePoint CR_Cf[] = { /* 'Cn': General Category */ static const OnigCodePoint CR_Cn[] = { - 707, + 731, 0x0378, 0x0379, 0x0380, 0x0383, 0x038b, 0x038b, @@ -7088,7 +7296,7 @@ static const OnigCodePoint CR_Cn[] = { 0x085f, 0x085f, 0x086b, 0x086f, 0x088f, 0x088f, - 0x0892, 0x0897, + 0x0892, 0x0896, 0x0984, 0x0984, 0x098d, 0x098e, 0x0991, 0x0992, @@ -7280,12 +7488,11 @@ static const OnigCodePoint CR_Cn[] = { 0x1a9a, 0x1a9f, 0x1aae, 0x1aaf, 0x1acf, 0x1aff, - 0x1b4d, 0x1b4f, - 0x1b7f, 0x1b7f, + 0x1b4d, 0x1b4d, 0x1bf4, 0x1bfb, 0x1c38, 0x1c3a, 0x1c4a, 0x1c4c, - 0x1c89, 0x1c8f, + 0x1c8b, 0x1c8f, 0x1cbb, 0x1cbc, 0x1cc8, 0x1ccf, 0x1cfb, 0x1cff, @@ -7312,7 +7519,7 @@ static const OnigCodePoint CR_Cn[] = { 0x20c1, 0x20cf, 0x20f1, 0x20ff, 0x218c, 0x218f, - 0x2427, 0x243f, + 0x242a, 0x243f, 0x244b, 0x245f, 0x2b74, 0x2b75, 0x2b96, 0x2b96, @@ -7335,22 +7542,21 @@ static const OnigCodePoint CR_Cn[] = { 0x2e9a, 0x2e9a, 0x2ef4, 0x2eff, 0x2fd6, 0x2fef, - 0x2ffc, 0x2fff, 0x3040, 0x3040, 0x3097, 0x3098, 0x3100, 0x3104, 0x3130, 0x3130, 0x318f, 0x318f, - 0x31e4, 0x31ef, + 0x31e6, 0x31ee, 0x321f, 0x321f, 0xa48d, 0xa48f, 0xa4c7, 0xa4cf, 0xa62c, 0xa63f, 0xa6f8, 0xa6ff, - 0xa7cb, 0xa7cf, + 0xa7ce, 0xa7cf, 0xa7d2, 0xa7d2, 0xa7d4, 0xa7d4, - 0xa7da, 0xa7f1, + 0xa7dd, 0xa7f1, 0xa82d, 0xa82f, 0xa83a, 0xa83f, 0xa878, 0xa87f, @@ -7440,7 +7646,8 @@ static const OnigCodePoint CR_Cn[] = { 0x105a2, 0x105a2, 0x105b2, 0x105b2, 0x105ba, 0x105ba, - 0x105bd, 0x105ff, + 0x105bd, 0x105bf, + 0x105f4, 0x105ff, 0x10737, 0x1073f, 0x10756, 0x1075f, 0x10768, 0x1077f, @@ -7483,11 +7690,15 @@ static const OnigCodePoint CR_Cn[] = { 0x10cb3, 0x10cbf, 0x10cf3, 0x10cf9, 0x10d28, 0x10d2f, - 0x10d3a, 0x10e5f, + 0x10d3a, 0x10d3f, + 0x10d66, 0x10d68, + 0x10d86, 0x10d8d, + 0x10d90, 0x10e5f, 0x10e7f, 0x10e7f, 0x10eaa, 0x10eaa, 0x10eae, 0x10eaf, - 0x10eb2, 0x10efc, + 0x10eb2, 0x10ec1, + 0x10ec5, 0x10efb, 0x10f28, 0x10f2f, 0x10f5a, 0x10f6f, 0x10f8a, 0x10faf, @@ -7527,7 +7738,18 @@ static const OnigCodePoint CR_Cn[] = { 0x11358, 0x1135c, 0x11364, 0x11365, 0x1136d, 0x1136f, - 0x11375, 0x113ff, + 0x11375, 0x1137f, + 0x1138a, 0x1138a, + 0x1138c, 0x1138d, + 0x1138f, 0x1138f, + 0x113b6, 0x113b6, + 0x113c1, 0x113c1, + 0x113c3, 0x113c4, + 0x113c6, 0x113c6, + 0x113cb, 0x113cb, + 0x113d6, 0x113d6, + 0x113d9, 0x113e0, + 0x113e3, 0x113ff, 0x1145c, 0x1145c, 0x11462, 0x1147f, 0x114c8, 0x114cf, @@ -7538,7 +7760,8 @@ static const OnigCodePoint CR_Cn[] = { 0x1165a, 0x1165f, 0x1166d, 0x1167f, 0x116ba, 0x116bf, - 0x116ca, 0x116ff, + 0x116ca, 0x116cf, + 0x116e4, 0x116ff, 0x1171b, 0x1171c, 0x1172c, 0x1172f, 0x11747, 0x117ff, @@ -7558,7 +7781,9 @@ static const OnigCodePoint CR_Cn[] = { 0x11a48, 0x11a4f, 0x11aa3, 0x11aaf, 0x11af9, 0x11aff, - 0x11b0a, 0x11bff, + 0x11b0a, 0x11bbf, + 0x11be2, 0x11bef, + 0x11bfa, 0x11bff, 0x11c09, 0x11c09, 0x11c37, 0x11c37, 0x11c46, 0x11c4f, @@ -7582,7 +7807,7 @@ static const OnigCodePoint CR_Cn[] = { 0x11ef9, 0x11eff, 0x11f11, 0x11f11, 0x11f3b, 0x11f3d, - 0x11f5a, 0x11faf, + 0x11f5b, 0x11faf, 0x11fb1, 0x11fbf, 0x11ff2, 0x11ffe, 0x1239a, 0x123ff, @@ -7590,8 +7815,10 @@ static const OnigCodePoint CR_Cn[] = { 0x12475, 0x1247f, 0x12544, 0x12f8f, 0x12ff3, 0x12fff, - 0x13456, 0x143ff, - 0x14647, 0x167ff, + 0x13456, 0x1345f, + 0x143fb, 0x143ff, + 0x14647, 0x160ff, + 0x1613a, 0x167ff, 0x16a39, 0x16a3f, 0x16a5f, 0x16a5f, 0x16a6a, 0x16a6d, @@ -7603,7 +7830,8 @@ static const OnigCodePoint CR_Cn[] = { 0x16b5a, 0x16b5a, 0x16b62, 0x16b62, 0x16b78, 0x16b7c, - 0x16b90, 0x16e3f, + 0x16b90, 0x16d3f, + 0x16d7a, 0x16e3f, 0x16e9b, 0x16eff, 0x16f4b, 0x16f4e, 0x16f88, 0x16f8e, @@ -7611,7 +7839,7 @@ static const OnigCodePoint CR_Cn[] = { 0x16fe5, 0x16fef, 0x16ff2, 0x16fff, 0x187f8, 0x187ff, - 0x18cd6, 0x18cff, + 0x18cd6, 0x18cfe, 0x18d09, 0x1afef, 0x1aff4, 0x1aff4, 0x1affc, 0x1affc, @@ -7626,7 +7854,9 @@ static const OnigCodePoint CR_Cn[] = { 0x1bc7d, 0x1bc7f, 0x1bc89, 0x1bc8f, 0x1bc9a, 0x1bc9b, - 0x1bca4, 0x1ceff, + 0x1bca4, 0x1cbff, + 0x1ccfa, 0x1ccff, + 0x1ceb4, 0x1ceff, 0x1cf2e, 0x1cf2f, 0x1cf47, 0x1cf4f, 0x1cfc4, 0x1cfff, @@ -7677,7 +7907,9 @@ static const OnigCodePoint CR_Cn[] = { 0x1e2af, 0x1e2bf, 0x1e2fa, 0x1e2fe, 0x1e300, 0x1e4cf, - 0x1e4fa, 0x1e7df, + 0x1e4fa, 0x1e5cf, + 0x1e5fb, 0x1e5fe, + 0x1e600, 0x1e7df, 0x1e7e7, 0x1e7e7, 0x1e7ec, 0x1e7ec, 0x1e7ef, 0x1e7ef, @@ -7747,24 +7979,24 @@ static const OnigCodePoint CR_Cn[] = { 0x1f85a, 0x1f85f, 0x1f888, 0x1f88f, 0x1f8ae, 0x1f8af, - 0x1f8b2, 0x1f8ff, + 0x1f8bc, 0x1f8bf, + 0x1f8c2, 0x1f8ff, 0x1fa54, 0x1fa5f, 0x1fa6e, 0x1fa6f, 0x1fa7d, 0x1fa7f, - 0x1fa89, 0x1fa8f, - 0x1fabe, 0x1fabe, - 0x1fac6, 0x1facd, - 0x1fadc, 0x1fadf, - 0x1fae9, 0x1faef, + 0x1fa8a, 0x1fa8e, + 0x1fac7, 0x1facd, + 0x1fadd, 0x1fade, + 0x1faea, 0x1faef, 0x1faf9, 0x1faff, 0x1fb93, 0x1fb93, - 0x1fbcb, 0x1fbef, 0x1fbfa, 0x1ffff, 0x2a6e0, 0x2a6ff, 0x2b73a, 0x2b73f, 0x2b81e, 0x2b81f, 0x2cea2, 0x2ceaf, - 0x2ebe1, 0x2f7ff, + 0x2ebe1, 0x2ebef, + 0x2ee5e, 0x2f7ff, 0x2fa1e, 0x2ffff, 0x3134b, 0x3134f, 0x323b0, 0xe0000, @@ -7791,7 +8023,7 @@ static const OnigCodePoint CR_Cs[] = { /* 'L': Major Category */ static const OnigCodePoint CR_L[] = { - 659, + 677, 0x0041, 0x005a, 0x0061, 0x007a, 0x00aa, 0x00aa, @@ -8017,7 +8249,7 @@ static const OnigCodePoint CR_L[] = { 0x1c00, 0x1c23, 0x1c4d, 0x1c4f, 0x1c5a, 0x1c7d, - 0x1c80, 0x1c88, + 0x1c80, 0x1c8a, 0x1c90, 0x1cba, 0x1cbd, 0x1cbf, 0x1ce9, 0x1cec, @@ -8101,10 +8333,10 @@ static const OnigCodePoint CR_L[] = { 0xa6a0, 0xa6e5, 0xa717, 0xa71f, 0xa722, 0xa788, - 0xa78b, 0xa7ca, + 0xa78b, 0xa7cd, 0xa7d0, 0xa7d1, 0xa7d3, 0xa7d3, - 0xa7d5, 0xa7d9, + 0xa7d5, 0xa7dc, 0xa7f2, 0xa801, 0xa803, 0xa805, 0xa807, 0xa80a, @@ -8201,6 +8433,7 @@ static const OnigCodePoint CR_L[] = { 0x105a3, 0x105b1, 0x105b3, 0x105b9, 0x105bb, 0x105bc, + 0x105c0, 0x105f3, 0x10600, 0x10736, 0x10740, 0x10755, 0x10760, 0x10767, @@ -8237,8 +8470,11 @@ static const OnigCodePoint CR_L[] = { 0x10c80, 0x10cb2, 0x10cc0, 0x10cf2, 0x10d00, 0x10d23, + 0x10d4a, 0x10d65, + 0x10d6f, 0x10d85, 0x10e80, 0x10ea9, 0x10eb0, 0x10eb1, + 0x10ec2, 0x10ec4, 0x10f00, 0x10f1c, 0x10f27, 0x10f27, 0x10f30, 0x10f45, @@ -8277,6 +8513,13 @@ static const OnigCodePoint CR_L[] = { 0x1133d, 0x1133d, 0x11350, 0x11350, 0x1135d, 0x11361, + 0x11380, 0x11389, + 0x1138b, 0x1138b, + 0x1138e, 0x1138e, + 0x11390, 0x113b5, + 0x113b7, 0x113b7, + 0x113d1, 0x113d1, + 0x113d3, 0x113d3, 0x11400, 0x11434, 0x11447, 0x1144a, 0x1145f, 0x11461, @@ -8311,6 +8554,7 @@ static const OnigCodePoint CR_L[] = { 0x11a5c, 0x11a89, 0x11a9d, 0x11a9d, 0x11ab0, 0x11af8, + 0x11bc0, 0x11be0, 0x11c00, 0x11c08, 0x11c0a, 0x11c2e, 0x11c40, 0x11c40, @@ -8333,7 +8577,9 @@ static const OnigCodePoint CR_L[] = { 0x12f90, 0x12ff0, 0x13000, 0x1342f, 0x13441, 0x13446, + 0x13460, 0x143fa, 0x14400, 0x14646, + 0x16100, 0x1611d, 0x16800, 0x16a38, 0x16a40, 0x16a5e, 0x16a70, 0x16abe, @@ -8342,6 +8588,7 @@ static const OnigCodePoint CR_L[] = { 0x16b40, 0x16b43, 0x16b63, 0x16b77, 0x16b7d, 0x16b8f, + 0x16d40, 0x16d6c, 0x16e40, 0x16e7f, 0x16f00, 0x16f4a, 0x16f50, 0x16f50, @@ -8350,7 +8597,7 @@ static const OnigCodePoint CR_L[] = { 0x16fe3, 0x16fe3, 0x17000, 0x187f7, 0x18800, 0x18cd5, - 0x18d00, 0x18d08, + 0x18cff, 0x18d08, 0x1aff0, 0x1aff3, 0x1aff5, 0x1affb, 0x1affd, 0x1affe, @@ -8403,6 +8650,8 @@ static const OnigCodePoint CR_L[] = { 0x1e290, 0x1e2ad, 0x1e2c0, 0x1e2eb, 0x1e4d0, 0x1e4eb, + 0x1e5d0, 0x1e5ed, + 0x1e5f0, 0x1e5f0, 0x1e7e0, 0x1e7e6, 0x1e7e8, 0x1e7eb, 0x1e7ed, 0x1e7ee, @@ -8448,6 +8697,7 @@ static const OnigCodePoint CR_L[] = { 0x2b740, 0x2b81d, 0x2b820, 0x2cea1, 0x2ceb0, 0x2ebe0, + 0x2ebf0, 0x2ee5d, 0x2f800, 0x2fa1d, 0x30000, 0x3134a, 0x31350, 0x323af, @@ -8455,7 +8705,7 @@ static const OnigCodePoint CR_L[] = { /* 'LC': General Category */ static const OnigCodePoint CR_LC[] = { - 143, + 145, 0x0041, 0x005a, 0x0061, 0x007a, 0x00b5, 0x00b5, @@ -8485,7 +8735,7 @@ static const OnigCodePoint CR_LC[] = { 0x10fd, 0x10ff, 0x13a0, 0x13f5, 0x13f8, 0x13fd, - 0x1c80, 0x1c88, + 0x1c80, 0x1c8a, 0x1c90, 0x1cba, 0x1cbd, 0x1cbf, 0x1d00, 0x1d2b, @@ -8537,10 +8787,10 @@ static const OnigCodePoint CR_LC[] = { 0xa722, 0xa76f, 0xa771, 0xa787, 0xa78b, 0xa78e, - 0xa790, 0xa7ca, + 0xa790, 0xa7cd, 0xa7d0, 0xa7d1, 0xa7d3, 0xa7d3, - 0xa7d5, 0xa7d9, + 0xa7d5, 0xa7dc, 0xa7f5, 0xa7f6, 0xa7fa, 0xa7fa, 0xab30, 0xab5a, @@ -8563,6 +8813,8 @@ static const OnigCodePoint CR_LC[] = { 0x105bb, 0x105bc, 0x10c80, 0x10cb2, 0x10cc0, 0x10cf2, + 0x10d50, 0x10d65, + 0x10d70, 0x10d85, 0x118a0, 0x118df, 0x16e40, 0x16e7f, 0x1d400, 0x1d454, @@ -8603,7 +8855,7 @@ static const OnigCodePoint CR_LC[] = { /* 'Ll': General Category */ static const OnigCodePoint CR_Ll[] = { - 658, + 662, 0x0061, 0x007a, 0x00b5, 0x00b5, 0x00df, 0x00f6, @@ -8878,6 +9130,7 @@ static const OnigCodePoint CR_Ll[] = { 0x10fd, 0x10ff, 0x13f8, 0x13fd, 0x1c80, 0x1c88, + 0x1c8a, 0x1c8a, 0x1d00, 0x1d2b, 0x1d6b, 0x1d77, 0x1d79, 0x1d9a, @@ -9208,11 +9461,13 @@ static const OnigCodePoint CR_Ll[] = { 0xa7c3, 0xa7c3, 0xa7c8, 0xa7c8, 0xa7ca, 0xa7ca, + 0xa7cd, 0xa7cd, 0xa7d1, 0xa7d1, 0xa7d3, 0xa7d3, 0xa7d5, 0xa7d5, 0xa7d7, 0xa7d7, 0xa7d9, 0xa7d9, + 0xa7db, 0xa7db, 0xa7f6, 0xa7f6, 0xa7fa, 0xa7fa, 0xab30, 0xab5a, @@ -9228,6 +9483,7 @@ static const OnigCodePoint CR_Ll[] = { 0x105b3, 0x105b9, 0x105bb, 0x105bc, 0x10cc0, 0x10cf2, + 0x10d70, 0x10d85, 0x118c0, 0x118df, 0x16e60, 0x16e7f, 0x1d41a, 0x1d433, @@ -9266,7 +9522,7 @@ static const OnigCodePoint CR_Ll[] = { /* 'Lm': General Category */ static const OnigCodePoint CR_Lm[] = { - 71, + 75, 0x02b0, 0x02c1, 0x02c6, 0x02d1, 0x02e0, 0x02e4, @@ -9327,7 +9583,11 @@ static const OnigCodePoint CR_Lm[] = { 0x10780, 0x10785, 0x10787, 0x107b0, 0x107b2, 0x107ba, + 0x10d4e, 0x10d4e, + 0x10d6f, 0x10d6f, 0x16b40, 0x16b43, + 0x16d40, 0x16d42, + 0x16d6b, 0x16d6c, 0x16f93, 0x16f9f, 0x16fe0, 0x16fe1, 0x16fe3, 0x16fe3, @@ -9342,7 +9602,7 @@ static const OnigCodePoint CR_Lm[] = { /* 'Lo': General Category */ static const OnigCodePoint CR_Lo[] = { - 510, + 528, 0x00aa, 0x00aa, 0x00ba, 0x00ba, 0x01bb, 0x01bb, @@ -9652,6 +9912,7 @@ static const OnigCodePoint CR_Lo[] = { 0x10450, 0x1049d, 0x10500, 0x10527, 0x10530, 0x10563, + 0x105c0, 0x105f3, 0x10600, 0x10736, 0x10740, 0x10755, 0x10760, 0x10767, @@ -9683,8 +9944,11 @@ static const OnigCodePoint CR_Lo[] = { 0x10b80, 0x10b91, 0x10c00, 0x10c48, 0x10d00, 0x10d23, + 0x10d4a, 0x10d4d, + 0x10d4f, 0x10d4f, 0x10e80, 0x10ea9, 0x10eb0, 0x10eb1, + 0x10ec2, 0x10ec4, 0x10f00, 0x10f1c, 0x10f27, 0x10f27, 0x10f30, 0x10f45, @@ -9723,6 +9987,13 @@ static const OnigCodePoint CR_Lo[] = { 0x1133d, 0x1133d, 0x11350, 0x11350, 0x1135d, 0x11361, + 0x11380, 0x11389, + 0x1138b, 0x1138b, + 0x1138e, 0x1138e, + 0x11390, 0x113b5, + 0x113b7, 0x113b7, + 0x113d1, 0x113d1, + 0x113d3, 0x113d3, 0x11400, 0x11434, 0x11447, 0x1144a, 0x1145f, 0x11461, @@ -9756,6 +10027,7 @@ static const OnigCodePoint CR_Lo[] = { 0x11a5c, 0x11a89, 0x11a9d, 0x11a9d, 0x11ab0, 0x11af8, + 0x11bc0, 0x11be0, 0x11c00, 0x11c08, 0x11c0a, 0x11c2e, 0x11c40, 0x11c40, @@ -9778,7 +10050,9 @@ static const OnigCodePoint CR_Lo[] = { 0x12f90, 0x12ff0, 0x13000, 0x1342f, 0x13441, 0x13446, + 0x13460, 0x143fa, 0x14400, 0x14646, + 0x16100, 0x1611d, 0x16800, 0x16a38, 0x16a40, 0x16a5e, 0x16a70, 0x16abe, @@ -9786,11 +10060,12 @@ static const OnigCodePoint CR_Lo[] = { 0x16b00, 0x16b2f, 0x16b63, 0x16b77, 0x16b7d, 0x16b8f, + 0x16d43, 0x16d6a, 0x16f00, 0x16f4a, 0x16f50, 0x16f50, 0x17000, 0x187f7, 0x18800, 0x18cd5, - 0x18d00, 0x18d08, + 0x18cff, 0x18d08, 0x1b000, 0x1b122, 0x1b132, 0x1b132, 0x1b150, 0x1b152, @@ -9807,6 +10082,8 @@ static const OnigCodePoint CR_Lo[] = { 0x1e290, 0x1e2ad, 0x1e2c0, 0x1e2eb, 0x1e4d0, 0x1e4ea, + 0x1e5d0, 0x1e5ed, + 0x1e5f0, 0x1e5f0, 0x1e7e0, 0x1e7e6, 0x1e7e8, 0x1e7eb, 0x1e7ed, 0x1e7ee, @@ -9850,6 +10127,7 @@ static const OnigCodePoint CR_Lo[] = { 0x2b740, 0x2b81d, 0x2b820, 0x2cea1, 0x2ceb0, 0x2ebe0, + 0x2ebf0, 0x2ee5d, 0x2f800, 0x2fa1d, 0x30000, 0x3134a, 0x31350, 0x323af, @@ -9872,7 +10150,7 @@ static const OnigCodePoint CR_Lt[] = { /* 'Lu': General Category */ static const OnigCodePoint CR_Lu[] = { - 646, + 651, 0x0041, 0x005a, 0x00c0, 0x00d6, 0x00d8, 0x00de, @@ -10149,6 +10427,7 @@ static const OnigCodePoint CR_Lu[] = { 0x10c7, 0x10c7, 0x10cd, 0x10cd, 0x13a0, 0x13f5, + 0x1c89, 0x1c89, 0x1c90, 0x1cba, 0x1cbd, 0x1cbf, 0x1e00, 0x1e00, @@ -10473,9 +10752,12 @@ static const OnigCodePoint CR_Lu[] = { 0xa7c2, 0xa7c2, 0xa7c4, 0xa7c7, 0xa7c9, 0xa7c9, + 0xa7cb, 0xa7cc, 0xa7d0, 0xa7d0, 0xa7d6, 0xa7d6, 0xa7d8, 0xa7d8, + 0xa7da, 0xa7da, + 0xa7dc, 0xa7dc, 0xa7f5, 0xa7f5, 0xff21, 0xff3a, 0x10400, 0x10427, @@ -10485,6 +10767,7 @@ static const OnigCodePoint CR_Lu[] = { 0x1058c, 0x10592, 0x10594, 0x10595, 0x10c80, 0x10cb2, + 0x10d50, 0x10d65, 0x118a0, 0x118bf, 0x16e40, 0x16e5f, 0x1d400, 0x1d419, @@ -10523,7 +10806,7 @@ static const OnigCodePoint CR_Lu[] = { /* 'M': Major Category */ static const OnigCodePoint CR_M[] = { - 310, + 321, 0x0300, 0x036f, 0x0483, 0x0489, 0x0591, 0x05bd, @@ -10548,7 +10831,7 @@ static const OnigCodePoint CR_M[] = { 0x0825, 0x0827, 0x0829, 0x082d, 0x0859, 0x085b, - 0x0898, 0x089f, + 0x0897, 0x089f, 0x08ca, 0x08e1, 0x08e3, 0x0903, 0x093a, 0x093c, @@ -10724,8 +11007,9 @@ static const OnigCodePoint CR_M[] = { 0x10a3f, 0x10a3f, 0x10ae5, 0x10ae6, 0x10d24, 0x10d27, + 0x10d69, 0x10d6d, 0x10eab, 0x10eac, - 0x10efd, 0x10eff, + 0x10efc, 0x10eff, 0x10f46, 0x10f50, 0x10f82, 0x10f85, 0x11000, 0x11002, @@ -10756,6 +11040,13 @@ static const OnigCodePoint CR_M[] = { 0x11362, 0x11363, 0x11366, 0x1136c, 0x11370, 0x11374, + 0x113b8, 0x113c0, + 0x113c2, 0x113c2, + 0x113c5, 0x113c5, + 0x113c7, 0x113ca, + 0x113cc, 0x113d0, + 0x113d2, 0x113d2, + 0x113e1, 0x113e2, 0x11435, 0x11446, 0x1145e, 0x1145e, 0x114b0, 0x114c3, @@ -10797,8 +11088,10 @@ static const OnigCodePoint CR_M[] = { 0x11f03, 0x11f03, 0x11f34, 0x11f3a, 0x11f3e, 0x11f42, + 0x11f5a, 0x11f5a, 0x13440, 0x13440, 0x13447, 0x13455, + 0x1611e, 0x1612f, 0x16af0, 0x16af4, 0x16b30, 0x16b36, 0x16f4f, 0x16f4f, @@ -10831,6 +11124,7 @@ static const OnigCodePoint CR_M[] = { 0x1e2ae, 0x1e2ae, 0x1e2ec, 0x1e2ef, 0x1e4ec, 0x1e4ef, + 0x1e5ee, 0x1e5ef, 0x1e8d0, 0x1e8d6, 0x1e944, 0x1e94a, 0xe0100, 0xe01ef, @@ -10838,7 +11132,7 @@ static const OnigCodePoint CR_M[] = { /* 'Mc': General Category */ static const OnigCodePoint CR_Mc[] = { - 182, + 190, 0x0903, 0x0903, 0x093b, 0x093b, 0x093e, 0x0940, @@ -10973,6 +11267,12 @@ static const OnigCodePoint CR_Mc[] = { 0x1134b, 0x1134d, 0x11357, 0x11357, 0x11362, 0x11363, + 0x113b8, 0x113ba, + 0x113c2, 0x113c2, + 0x113c5, 0x113c5, + 0x113c7, 0x113ca, + 0x113cc, 0x113cd, + 0x113cf, 0x113cf, 0x11435, 0x11437, 0x11440, 0x11441, 0x11445, 0x11445, @@ -10989,6 +11289,7 @@ static const OnigCodePoint CR_Mc[] = { 0x116ac, 0x116ac, 0x116ae, 0x116af, 0x116b6, 0x116b6, + 0x1171e, 0x1171e, 0x11720, 0x11721, 0x11726, 0x11726, 0x1182c, 0x1182e, @@ -11017,6 +11318,7 @@ static const OnigCodePoint CR_Mc[] = { 0x11f34, 0x11f35, 0x11f3e, 0x11f3f, 0x11f41, 0x11f41, + 0x1612a, 0x1612c, 0x16f51, 0x16f87, 0x16ff0, 0x16ff1, 0x1d165, 0x1d166, @@ -11035,7 +11337,7 @@ static const OnigCodePoint CR_Me[] = { /* 'Mn': General Category */ static const OnigCodePoint CR_Mn[] = { - 346, + 357, 0x0300, 0x036f, 0x0483, 0x0487, 0x0591, 0x05bd, @@ -11060,7 +11362,7 @@ static const OnigCodePoint CR_Mn[] = { 0x0825, 0x0827, 0x0829, 0x082d, 0x0859, 0x085b, - 0x0898, 0x089f, + 0x0897, 0x089f, 0x08ca, 0x08e1, 0x08e3, 0x0902, 0x093a, 0x093a, @@ -11258,8 +11560,9 @@ static const OnigCodePoint CR_Mn[] = { 0x10a3f, 0x10a3f, 0x10ae5, 0x10ae6, 0x10d24, 0x10d27, + 0x10d69, 0x10d6d, 0x10eab, 0x10eac, - 0x10efd, 0x10eff, + 0x10efc, 0x10eff, 0x10f46, 0x10f50, 0x10f82, 0x10f85, 0x11001, 0x11001, @@ -11290,6 +11593,11 @@ static const OnigCodePoint CR_Mn[] = { 0x11340, 0x11340, 0x11366, 0x1136c, 0x11370, 0x11374, + 0x113bb, 0x113c0, + 0x113ce, 0x113ce, + 0x113d0, 0x113d0, + 0x113d2, 0x113d2, + 0x113e1, 0x113e2, 0x11438, 0x1143f, 0x11442, 0x11444, 0x11446, 0x11446, @@ -11309,7 +11617,8 @@ static const OnigCodePoint CR_Mn[] = { 0x116ad, 0x116ad, 0x116b0, 0x116b5, 0x116b7, 0x116b7, - 0x1171d, 0x1171f, + 0x1171d, 0x1171d, + 0x1171f, 0x1171f, 0x11722, 0x11725, 0x11727, 0x1172b, 0x1182f, 0x11837, @@ -11348,8 +11657,11 @@ static const OnigCodePoint CR_Mn[] = { 0x11f36, 0x11f3a, 0x11f40, 0x11f40, 0x11f42, 0x11f42, + 0x11f5a, 0x11f5a, 0x13440, 0x13440, 0x13447, 0x13455, + 0x1611e, 0x16129, + 0x1612d, 0x1612f, 0x16af0, 0x16af4, 0x16b30, 0x16b36, 0x16f4f, 0x16f4f, @@ -11379,6 +11691,7 @@ static const OnigCodePoint CR_Mn[] = { 0x1e2ae, 0x1e2ae, 0x1e2ec, 0x1e2ef, 0x1e4ec, 0x1e4ef, + 0x1e5ee, 0x1e5ef, 0x1e8d0, 0x1e8d6, 0x1e944, 0x1e94a, 0xe0100, 0xe01ef, @@ -11386,7 +11699,7 @@ static const OnigCodePoint CR_Mn[] = { /* 'N': Major Category */ static const OnigCodePoint CR_N[] = { - 137, + 144, 0x0030, 0x0039, 0x00b2, 0x00b3, 0x00b9, 0x00b9, @@ -11480,6 +11793,7 @@ static const OnigCodePoint CR_N[] = { 0x10ba9, 0x10baf, 0x10cfa, 0x10cff, 0x10d30, 0x10d39, + 0x10d40, 0x10d49, 0x10e60, 0x10e7e, 0x10f1d, 0x10f26, 0x10f51, 0x10f54, @@ -11494,20 +11808,25 @@ static const OnigCodePoint CR_N[] = { 0x114d0, 0x114d9, 0x11650, 0x11659, 0x116c0, 0x116c9, + 0x116d0, 0x116e3, 0x11730, 0x1173b, 0x118e0, 0x118f2, 0x11950, 0x11959, + 0x11bf0, 0x11bf9, 0x11c50, 0x11c6c, 0x11d50, 0x11d59, 0x11da0, 0x11da9, 0x11f50, 0x11f59, 0x11fc0, 0x11fd4, 0x12400, 0x1246e, + 0x16130, 0x16139, 0x16a60, 0x16a69, 0x16ac0, 0x16ac9, 0x16b50, 0x16b59, 0x16b5b, 0x16b61, + 0x16d70, 0x16d79, 0x16e80, 0x16e96, + 0x1ccf0, 0x1ccf9, 0x1d2c0, 0x1d2d3, 0x1d2e0, 0x1d2f3, 0x1d360, 0x1d378, @@ -11515,6 +11834,7 @@ static const OnigCodePoint CR_N[] = { 0x1e140, 0x1e149, 0x1e2f0, 0x1e2f9, 0x1e4f0, 0x1e4f9, + 0x1e5f1, 0x1e5fa, 0x1e8c7, 0x1e8cf, 0x1e950, 0x1e959, 0x1ec71, 0x1ecab, @@ -11639,7 +11959,7 @@ static const OnigCodePoint CR_Pc[] = { /* 'Pd': General Category */ static const OnigCodePoint CR_Pd[] = { - 19, + 20, 0x002d, 0x002d, 0x058a, 0x058a, 0x05be, 0x05be, @@ -11658,6 +11978,7 @@ static const OnigCodePoint CR_Pd[] = { 0xfe58, 0xfe58, 0xfe63, 0xfe63, 0xff0d, 0xff0d, + 0x10d6e, 0x10d6e, 0x10ead, 0x10ead, }; /* CR_Pd */ @@ -11775,7 +12096,7 @@ static const OnigCodePoint CR_Pi[] = { /* 'Po': General Category */ static const OnigCodePoint CR_Po[] = { - 187, + 193, 0x0021, 0x0023, 0x0025, 0x0027, 0x002a, 0x002a, @@ -11835,8 +12156,9 @@ static const OnigCodePoint CR_Po[] = { 0x1a1e, 0x1a1f, 0x1aa0, 0x1aa6, 0x1aa8, 0x1aad, + 0x1b4e, 0x1b4f, 0x1b5a, 0x1b60, - 0x1b7d, 0x1b7e, + 0x1b7d, 0x1b7f, 0x1bfc, 0x1bff, 0x1c3b, 0x1c3f, 0x1c7e, 0x1c7f, @@ -11931,6 +12253,8 @@ static const OnigCodePoint CR_Po[] = { 0x111dd, 0x111df, 0x11238, 0x1123d, 0x112a9, 0x112a9, + 0x113d4, 0x113d5, + 0x113d7, 0x113d8, 0x1144b, 0x1144f, 0x1145a, 0x1145b, 0x1145d, 0x1145d, @@ -11947,6 +12271,7 @@ static const OnigCodePoint CR_Po[] = { 0x11a9a, 0x11a9c, 0x11a9e, 0x11aa2, 0x11b00, 0x11b09, + 0x11be1, 0x11be1, 0x11c41, 0x11c45, 0x11c70, 0x11c71, 0x11ef7, 0x11ef8, @@ -11958,10 +12283,12 @@ static const OnigCodePoint CR_Po[] = { 0x16af5, 0x16af5, 0x16b37, 0x16b3b, 0x16b44, 0x16b44, + 0x16d6d, 0x16d6f, 0x16e97, 0x16e9a, 0x16fe2, 0x16fe2, 0x1bc9f, 0x1bc9f, 0x1da87, 0x1da8b, + 0x1e5ff, 0x1e5ff, 0x1e95e, 0x1e95f, }; /* CR_Po */ @@ -12051,7 +12378,7 @@ static const OnigCodePoint CR_Ps[] = { /* 'S': Major Category */ static const OnigCodePoint CR_S[] = { - 232, + 236, 0x0024, 0x0024, 0x002b, 0x002b, 0x003c, 0x003e, @@ -12142,7 +12469,7 @@ static const OnigCodePoint CR_S[] = { 0x218a, 0x218b, 0x2190, 0x2307, 0x230c, 0x2328, - 0x232b, 0x2426, + 0x232b, 0x2429, 0x2440, 0x244a, 0x249c, 0x24e9, 0x2500, 0x2767, @@ -12159,7 +12486,7 @@ static const OnigCodePoint CR_S[] = { 0x2e80, 0x2e99, 0x2e9b, 0x2ef3, 0x2f00, 0x2fd5, - 0x2ff0, 0x2ffb, + 0x2ff0, 0x2fff, 0x3004, 0x3004, 0x3012, 0x3013, 0x3020, 0x3020, @@ -12168,7 +12495,8 @@ static const OnigCodePoint CR_S[] = { 0x309b, 0x309c, 0x3190, 0x3191, 0x3196, 0x319f, - 0x31c0, 0x31e3, + 0x31c0, 0x31e5, + 0x31ef, 0x31ef, 0x3200, 0x321e, 0x322a, 0x3247, 0x3250, 0x3250, @@ -12211,11 +12539,14 @@ static const OnigCodePoint CR_S[] = { 0x101d0, 0x101fc, 0x10877, 0x10878, 0x10ac8, 0x10ac8, + 0x10d8e, 0x10d8f, 0x1173f, 0x1173f, 0x11fd5, 0x11ff1, 0x16b3c, 0x16b3f, 0x16b45, 0x16b45, 0x1bc9c, 0x1bc9c, + 0x1cc00, 0x1ccef, + 0x1cd00, 0x1ceb3, 0x1cf50, 0x1cfc3, 0x1d000, 0x1d0f5, 0x1d100, 0x1d126, @@ -12272,18 +12603,18 @@ static const OnigCodePoint CR_S[] = { 0x1f850, 0x1f859, 0x1f860, 0x1f887, 0x1f890, 0x1f8ad, - 0x1f8b0, 0x1f8b1, + 0x1f8b0, 0x1f8bb, + 0x1f8c0, 0x1f8c1, 0x1f900, 0x1fa53, 0x1fa60, 0x1fa6d, 0x1fa70, 0x1fa7c, - 0x1fa80, 0x1fa88, - 0x1fa90, 0x1fabd, - 0x1fabf, 0x1fac5, - 0x1face, 0x1fadb, - 0x1fae0, 0x1fae8, + 0x1fa80, 0x1fa89, + 0x1fa8f, 0x1fac6, + 0x1face, 0x1fadc, + 0x1fadf, 0x1fae9, 0x1faf0, 0x1faf8, 0x1fb00, 0x1fb92, - 0x1fb94, 0x1fbca, + 0x1fb94, 0x1fbef, }; /* CR_S */ /* 'Sc': General Category */ @@ -12350,7 +12681,7 @@ static const OnigCodePoint CR_Sk[] = { /* 'Sm': General Category */ static const OnigCodePoint CR_Sm[] = { - 64, + 65, 0x002b, 0x002b, 0x003c, 0x003e, 0x007c, 0x007c, @@ -12404,6 +12735,7 @@ static const OnigCodePoint CR_Sm[] = { 0xff5e, 0xff5e, 0xffe2, 0xffe2, 0xffe9, 0xffec, + 0x10d8e, 0x10d8f, 0x1d6c1, 0x1d6c1, 0x1d6db, 0x1d6db, 0x1d6fb, 0x1d6fb, @@ -12419,7 +12751,7 @@ static const OnigCodePoint CR_Sm[] = { /* 'So': General Category */ static const OnigCodePoint CR_So[] = { - 184, + 187, 0x00a6, 0x00a6, 0x00a9, 0x00a9, 0x00ae, 0x00ae, @@ -12486,7 +12818,7 @@ static const OnigCodePoint CR_So[] = { 0x232b, 0x237b, 0x237d, 0x239a, 0x23b4, 0x23db, - 0x23e2, 0x2426, + 0x23e2, 0x2429, 0x2440, 0x244a, 0x249c, 0x24e9, 0x2500, 0x25b6, @@ -12506,7 +12838,7 @@ static const OnigCodePoint CR_So[] = { 0x2e80, 0x2e99, 0x2e9b, 0x2ef3, 0x2f00, 0x2fd5, - 0x2ff0, 0x2ffb, + 0x2ff0, 0x2fff, 0x3004, 0x3004, 0x3012, 0x3013, 0x3020, 0x3020, @@ -12514,7 +12846,8 @@ static const OnigCodePoint CR_So[] = { 0x303e, 0x303f, 0x3190, 0x3191, 0x3196, 0x319f, - 0x31c0, 0x31e3, + 0x31c0, 0x31e5, + 0x31ef, 0x31ef, 0x3200, 0x321e, 0x322a, 0x3247, 0x3250, 0x3250, @@ -12548,6 +12881,8 @@ static const OnigCodePoint CR_So[] = { 0x16b3c, 0x16b3f, 0x16b45, 0x16b45, 0x1bc9c, 0x1bc9c, + 0x1cc00, 0x1ccef, + 0x1cd00, 0x1ceb3, 0x1cf50, 0x1cfc3, 0x1d000, 0x1d0f5, 0x1d100, 0x1d126, @@ -12592,18 +12927,18 @@ static const OnigCodePoint CR_So[] = { 0x1f850, 0x1f859, 0x1f860, 0x1f887, 0x1f890, 0x1f8ad, - 0x1f8b0, 0x1f8b1, + 0x1f8b0, 0x1f8bb, + 0x1f8c0, 0x1f8c1, 0x1f900, 0x1fa53, 0x1fa60, 0x1fa6d, 0x1fa70, 0x1fa7c, - 0x1fa80, 0x1fa88, - 0x1fa90, 0x1fabd, - 0x1fabf, 0x1fac5, - 0x1face, 0x1fadb, - 0x1fae0, 0x1fae8, + 0x1fa80, 0x1fa89, + 0x1fa8f, 0x1fac6, + 0x1face, 0x1fadc, + 0x1fadf, 0x1fae9, 0x1faf0, 0x1faf8, 0x1fb00, 0x1fb92, - 0x1fb94, 0x1fbca, + 0x1fb94, 0x1fbef, }; /* CR_So */ /* 'Z': Major Category */ @@ -12645,7 +12980,7 @@ static const OnigCodePoint CR_Zs[] = { /* 'Math': Derived Property */ static const OnigCodePoint CR_Math[] = { - 138, + 139, 0x002b, 0x002b, 0x003c, 0x003e, 0x005e, 0x005e, @@ -12729,6 +13064,7 @@ static const OnigCodePoint CR_Math[] = { 0xff5e, 0xff5e, 0xffe2, 0xffe2, 0xffe9, 0xffec, + 0x10d8e, 0x10d8f, 0x1d400, 0x1d454, 0x1d456, 0x1d49c, 0x1d49e, 0x1d49f, @@ -12797,7 +13133,7 @@ static const OnigCodePoint CR_Math[] = { /* 'Cased': Derived Property */ static const OnigCodePoint CR_Cased[] = { - 157, + 159, 0x0041, 0x005a, 0x0061, 0x007a, 0x00aa, 0x00aa, @@ -12832,7 +13168,7 @@ static const OnigCodePoint CR_Cased[] = { 0x10fc, 0x10ff, 0x13a0, 0x13f5, 0x13f8, 0x13fd, - 0x1c80, 0x1c88, + 0x1c80, 0x1c8a, 0x1c90, 0x1cba, 0x1cbd, 0x1cbf, 0x1d00, 0x1dbf, @@ -12885,10 +13221,10 @@ static const OnigCodePoint CR_Cased[] = { 0xa680, 0xa69d, 0xa722, 0xa787, 0xa78b, 0xa78e, - 0xa790, 0xa7ca, + 0xa790, 0xa7cd, 0xa7d0, 0xa7d1, 0xa7d3, 0xa7d3, - 0xa7d5, 0xa7d9, + 0xa7d5, 0xa7dc, 0xa7f2, 0xa7f6, 0xa7f8, 0xa7fa, 0xab30, 0xab5a, @@ -12915,6 +13251,8 @@ static const OnigCodePoint CR_Cased[] = { 0x107b2, 0x107ba, 0x10c80, 0x10cb2, 0x10cc0, 0x10cf2, + 0x10d50, 0x10d65, + 0x10d70, 0x10d85, 0x118a0, 0x118df, 0x16e40, 0x16e7f, 0x1d400, 0x1d454, @@ -12959,7 +13297,7 @@ static const OnigCodePoint CR_Cased[] = { /* 'Case_Ignorable': Derived Property */ static const OnigCodePoint CR_Case_Ignorable[] = { - 437, + 452, 0x0027, 0x0027, 0x002e, 0x002e, 0x003a, 0x003a, @@ -13004,7 +13342,7 @@ static const OnigCodePoint CR_Case_Ignorable[] = { 0x0859, 0x085b, 0x0888, 0x0888, 0x0890, 0x0891, - 0x0898, 0x089f, + 0x0897, 0x089f, 0x08c9, 0x0902, 0x093a, 0x093a, 0x093c, 0x093c, @@ -13261,8 +13599,11 @@ static const OnigCodePoint CR_Case_Ignorable[] = { 0x10a3f, 0x10a3f, 0x10ae5, 0x10ae6, 0x10d24, 0x10d27, + 0x10d4e, 0x10d4e, + 0x10d69, 0x10d6d, + 0x10d6f, 0x10d6f, 0x10eab, 0x10eac, - 0x10efd, 0x10eff, + 0x10efc, 0x10eff, 0x10f46, 0x10f50, 0x10f82, 0x10f85, 0x11001, 0x11001, @@ -13295,6 +13636,11 @@ static const OnigCodePoint CR_Case_Ignorable[] = { 0x11340, 0x11340, 0x11366, 0x1136c, 0x11370, 0x11374, + 0x113bb, 0x113c0, + 0x113ce, 0x113ce, + 0x113d0, 0x113d0, + 0x113d2, 0x113d2, + 0x113e1, 0x113e2, 0x11438, 0x1143f, 0x11442, 0x11444, 0x11446, 0x11446, @@ -13314,7 +13660,8 @@ static const OnigCodePoint CR_Case_Ignorable[] = { 0x116ad, 0x116ad, 0x116b0, 0x116b5, 0x116b7, 0x116b7, - 0x1171d, 0x1171f, + 0x1171d, 0x1171d, + 0x1171f, 0x1171f, 0x11722, 0x11725, 0x11727, 0x1172b, 0x1182f, 0x11837, @@ -13353,11 +13700,16 @@ static const OnigCodePoint CR_Case_Ignorable[] = { 0x11f36, 0x11f3a, 0x11f40, 0x11f40, 0x11f42, 0x11f42, + 0x11f5a, 0x11f5a, 0x13430, 0x13440, 0x13447, 0x13455, + 0x1611e, 0x16129, + 0x1612d, 0x1612f, 0x16af0, 0x16af4, 0x16b30, 0x16b36, 0x16b40, 0x16b43, + 0x16d40, 0x16d42, + 0x16d6b, 0x16d6c, 0x16f4f, 0x16f4f, 0x16f8f, 0x16f9f, 0x16fe0, 0x16fe1, @@ -13391,6 +13743,7 @@ static const OnigCodePoint CR_Case_Ignorable[] = { 0x1e2ae, 0x1e2ae, 0x1e2ec, 0x1e2ef, 0x1e4eb, 0x1e4ef, + 0x1e5ee, 0x1e5ef, 0x1e8d0, 0x1e8d6, 0x1e944, 0x1e94b, 0x1f3fb, 0x1f3ff, @@ -13401,7 +13754,7 @@ static const OnigCodePoint CR_Case_Ignorable[] = { /* 'Changes_When_Lowercased': Derived Property */ static const OnigCodePoint CR_Changes_When_Lowercased[] = { - 609, + 614, 0x0041, 0x005a, 0x00c0, 0x00d6, 0x00d8, 0x00de, @@ -13677,6 +14030,7 @@ static const OnigCodePoint CR_Changes_When_Lowercased[] = { 0x10c7, 0x10c7, 0x10cd, 0x10cd, 0x13a0, 0x13f5, + 0x1c89, 0x1c89, 0x1c90, 0x1cba, 0x1cbd, 0x1cbf, 0x1e00, 0x1e00, @@ -13996,9 +14350,12 @@ static const OnigCodePoint CR_Changes_When_Lowercased[] = { 0xa7c2, 0xa7c2, 0xa7c4, 0xa7c7, 0xa7c9, 0xa7c9, + 0xa7cb, 0xa7cc, 0xa7d0, 0xa7d0, 0xa7d6, 0xa7d6, 0xa7d8, 0xa7d8, + 0xa7da, 0xa7da, + 0xa7dc, 0xa7dc, 0xa7f5, 0xa7f5, 0xff21, 0xff3a, 0x10400, 0x10427, @@ -14008,6 +14365,7 @@ static const OnigCodePoint CR_Changes_When_Lowercased[] = { 0x1058c, 0x10592, 0x10594, 0x10595, 0x10c80, 0x10cb2, + 0x10d50, 0x10d65, 0x118a0, 0x118bf, 0x16e40, 0x16e5f, 0x1e900, 0x1e921, @@ -14015,7 +14373,7 @@ static const OnigCodePoint CR_Changes_When_Lowercased[] = { /* 'Changes_When_Uppercased': Derived Property */ static const OnigCodePoint CR_Changes_When_Uppercased[] = { - 627, + 630, 0x0061, 0x007a, 0x00b5, 0x00b5, 0x00df, 0x00f6, @@ -14088,7 +14446,7 @@ static const OnigCodePoint CR_Changes_When_Uppercased[] = { 0x018c, 0x018c, 0x0192, 0x0192, 0x0195, 0x0195, - 0x0199, 0x019a, + 0x0199, 0x019b, 0x019e, 0x019e, 0x01a1, 0x01a1, 0x01a3, 0x01a3, @@ -14164,8 +14522,7 @@ static const OnigCodePoint CR_Changes_When_Uppercased[] = { 0x0259, 0x0259, 0x025b, 0x025c, 0x0260, 0x0261, - 0x0263, 0x0263, - 0x0265, 0x0266, + 0x0263, 0x0266, 0x0268, 0x026c, 0x026f, 0x026f, 0x0271, 0x0272, @@ -14305,6 +14662,7 @@ static const OnigCodePoint CR_Changes_When_Uppercased[] = { 0x10fd, 0x10ff, 0x13f8, 0x13fd, 0x1c80, 0x1c88, + 0x1c8a, 0x1c8a, 0x1d79, 0x1d79, 0x1d7d, 0x1d7d, 0x1d8e, 0x1d8e, @@ -14624,9 +14982,11 @@ static const OnigCodePoint CR_Changes_When_Uppercased[] = { 0xa7c3, 0xa7c3, 0xa7c8, 0xa7c8, 0xa7ca, 0xa7ca, + 0xa7cd, 0xa7cd, 0xa7d1, 0xa7d1, 0xa7d7, 0xa7d7, 0xa7d9, 0xa7d9, + 0xa7db, 0xa7db, 0xa7f6, 0xa7f6, 0xab53, 0xab53, 0xab70, 0xabbf, @@ -14640,6 +15000,7 @@ static const OnigCodePoint CR_Changes_When_Uppercased[] = { 0x105b3, 0x105b9, 0x105bb, 0x105bc, 0x10cc0, 0x10cf2, + 0x10d70, 0x10d85, 0x118c0, 0x118df, 0x16e60, 0x16e7f, 0x1e922, 0x1e943, @@ -14647,7 +15008,7 @@ static const OnigCodePoint CR_Changes_When_Uppercased[] = { /* 'Changes_When_Titlecased': Derived Property */ static const OnigCodePoint CR_Changes_When_Titlecased[] = { - 626, + 629, 0x0061, 0x007a, 0x00b5, 0x00b5, 0x00df, 0x00f6, @@ -14720,7 +15081,7 @@ static const OnigCodePoint CR_Changes_When_Titlecased[] = { 0x018c, 0x018c, 0x0192, 0x0192, 0x0195, 0x0195, - 0x0199, 0x019a, + 0x0199, 0x019b, 0x019e, 0x019e, 0x01a1, 0x01a1, 0x01a3, 0x01a3, @@ -14797,8 +15158,7 @@ static const OnigCodePoint CR_Changes_When_Titlecased[] = { 0x0259, 0x0259, 0x025b, 0x025c, 0x0260, 0x0261, - 0x0263, 0x0263, - 0x0265, 0x0266, + 0x0263, 0x0266, 0x0268, 0x026c, 0x026f, 0x026f, 0x0271, 0x0272, @@ -14936,6 +15296,7 @@ static const OnigCodePoint CR_Changes_When_Titlecased[] = { 0x0561, 0x0587, 0x13f8, 0x13fd, 0x1c80, 0x1c88, + 0x1c8a, 0x1c8a, 0x1d79, 0x1d79, 0x1d7d, 0x1d7d, 0x1d8e, 0x1d8e, @@ -15255,9 +15616,11 @@ static const OnigCodePoint CR_Changes_When_Titlecased[] = { 0xa7c3, 0xa7c3, 0xa7c8, 0xa7c8, 0xa7ca, 0xa7ca, + 0xa7cd, 0xa7cd, 0xa7d1, 0xa7d1, 0xa7d7, 0xa7d7, 0xa7d9, 0xa7d9, + 0xa7db, 0xa7db, 0xa7f6, 0xa7f6, 0xab53, 0xab53, 0xab70, 0xabbf, @@ -15271,6 +15634,7 @@ static const OnigCodePoint CR_Changes_When_Titlecased[] = { 0x105b3, 0x105b9, 0x105bb, 0x105bc, 0x10cc0, 0x10cf2, + 0x10d70, 0x10d85, 0x118c0, 0x118df, 0x16e60, 0x16e7f, 0x1e922, 0x1e943, @@ -15278,7 +15642,7 @@ static const OnigCodePoint CR_Changes_When_Titlecased[] = { /* 'Changes_When_Casefolded': Derived Property */ static const OnigCodePoint CR_Changes_When_Casefolded[] = { - 622, + 626, 0x0041, 0x005a, 0x00b5, 0x00b5, 0x00c0, 0x00d6, @@ -15561,7 +15925,7 @@ static const OnigCodePoint CR_Changes_When_Casefolded[] = { 0x10c7, 0x10c7, 0x10cd, 0x10cd, 0x13f8, 0x13fd, - 0x1c80, 0x1c88, + 0x1c80, 0x1c89, 0x1c90, 0x1cba, 0x1cbd, 0x1cbf, 0x1e00, 0x1e00, @@ -15883,9 +16247,12 @@ static const OnigCodePoint CR_Changes_When_Casefolded[] = { 0xa7c2, 0xa7c2, 0xa7c4, 0xa7c7, 0xa7c9, 0xa7c9, + 0xa7cb, 0xa7cc, 0xa7d0, 0xa7d0, 0xa7d6, 0xa7d6, 0xa7d8, 0xa7d8, + 0xa7da, 0xa7da, + 0xa7dc, 0xa7dc, 0xa7f5, 0xa7f5, 0xab70, 0xabbf, 0xfb00, 0xfb06, @@ -15898,6 +16265,7 @@ static const OnigCodePoint CR_Changes_When_Casefolded[] = { 0x1058c, 0x10592, 0x10594, 0x10595, 0x10c80, 0x10cb2, + 0x10d50, 0x10d65, 0x118a0, 0x118bf, 0x16e40, 0x16e5f, 0x1e900, 0x1e921, @@ -15913,8 +16281,7 @@ static const OnigCodePoint CR_Changes_When_Casemapped[] = { 0x00d8, 0x00f6, 0x00f8, 0x0137, 0x0139, 0x018c, - 0x018e, 0x019a, - 0x019c, 0x01a9, + 0x018e, 0x01a9, 0x01ac, 0x01b9, 0x01bc, 0x01bd, 0x01bf, 0x01bf, @@ -15925,8 +16292,7 @@ static const OnigCodePoint CR_Changes_When_Casemapped[] = { 0x0259, 0x0259, 0x025b, 0x025c, 0x0260, 0x0261, - 0x0263, 0x0263, - 0x0265, 0x0266, + 0x0263, 0x0266, 0x0268, 0x026c, 0x026f, 0x026f, 0x0271, 0x0272, @@ -15960,7 +16326,7 @@ static const OnigCodePoint CR_Changes_When_Casemapped[] = { 0x10fd, 0x10ff, 0x13a0, 0x13f5, 0x13f8, 0x13fd, - 0x1c80, 0x1c88, + 0x1c80, 0x1c8a, 0x1c90, 0x1cba, 0x1cbd, 0x1cbf, 0x1d79, 0x1d79, @@ -16011,9 +16377,9 @@ static const OnigCodePoint CR_Changes_When_Casemapped[] = { 0xa78b, 0xa78d, 0xa790, 0xa794, 0xa796, 0xa7ae, - 0xa7b0, 0xa7ca, + 0xa7b0, 0xa7cd, 0xa7d0, 0xa7d1, - 0xa7d6, 0xa7d9, + 0xa7d6, 0xa7dc, 0xa7f5, 0xa7f6, 0xab53, 0xab53, 0xab70, 0xabbf, @@ -16034,6 +16400,8 @@ static const OnigCodePoint CR_Changes_When_Casemapped[] = { 0x105bb, 0x105bc, 0x10c80, 0x10cb2, 0x10cc0, 0x10cf2, + 0x10d50, 0x10d65, + 0x10d70, 0x10d85, 0x118a0, 0x118df, 0x16e40, 0x16e7f, 0x1e900, 0x1e943, @@ -16041,7 +16409,7 @@ static const OnigCodePoint CR_Changes_When_Casemapped[] = { /* 'ID_Start': Derived Property */ static const OnigCodePoint CR_ID_Start[] = { - 659, + 677, 0x0041, 0x005a, 0x0061, 0x007a, 0x00aa, 0x00aa, @@ -16266,7 +16634,7 @@ static const OnigCodePoint CR_ID_Start[] = { 0x1c00, 0x1c23, 0x1c4d, 0x1c4f, 0x1c5a, 0x1c7d, - 0x1c80, 0x1c88, + 0x1c80, 0x1c8a, 0x1c90, 0x1cba, 0x1cbd, 0x1cbf, 0x1ce9, 0x1cec, @@ -16349,10 +16717,10 @@ static const OnigCodePoint CR_ID_Start[] = { 0xa6a0, 0xa6ef, 0xa717, 0xa71f, 0xa722, 0xa788, - 0xa78b, 0xa7ca, + 0xa78b, 0xa7cd, 0xa7d0, 0xa7d1, 0xa7d3, 0xa7d3, - 0xa7d5, 0xa7d9, + 0xa7d5, 0xa7dc, 0xa7f2, 0xa801, 0xa803, 0xa805, 0xa807, 0xa80a, @@ -16450,6 +16818,7 @@ static const OnigCodePoint CR_ID_Start[] = { 0x105a3, 0x105b1, 0x105b3, 0x105b9, 0x105bb, 0x105bc, + 0x105c0, 0x105f3, 0x10600, 0x10736, 0x10740, 0x10755, 0x10760, 0x10767, @@ -16486,8 +16855,11 @@ static const OnigCodePoint CR_ID_Start[] = { 0x10c80, 0x10cb2, 0x10cc0, 0x10cf2, 0x10d00, 0x10d23, + 0x10d4a, 0x10d65, + 0x10d6f, 0x10d85, 0x10e80, 0x10ea9, 0x10eb0, 0x10eb1, + 0x10ec2, 0x10ec4, 0x10f00, 0x10f1c, 0x10f27, 0x10f27, 0x10f30, 0x10f45, @@ -16526,6 +16898,13 @@ static const OnigCodePoint CR_ID_Start[] = { 0x1133d, 0x1133d, 0x11350, 0x11350, 0x1135d, 0x11361, + 0x11380, 0x11389, + 0x1138b, 0x1138b, + 0x1138e, 0x1138e, + 0x11390, 0x113b5, + 0x113b7, 0x113b7, + 0x113d1, 0x113d1, + 0x113d3, 0x113d3, 0x11400, 0x11434, 0x11447, 0x1144a, 0x1145f, 0x11461, @@ -16560,6 +16939,7 @@ static const OnigCodePoint CR_ID_Start[] = { 0x11a5c, 0x11a89, 0x11a9d, 0x11a9d, 0x11ab0, 0x11af8, + 0x11bc0, 0x11be0, 0x11c00, 0x11c08, 0x11c0a, 0x11c2e, 0x11c40, 0x11c40, @@ -16583,7 +16963,9 @@ static const OnigCodePoint CR_ID_Start[] = { 0x12f90, 0x12ff0, 0x13000, 0x1342f, 0x13441, 0x13446, + 0x13460, 0x143fa, 0x14400, 0x14646, + 0x16100, 0x1611d, 0x16800, 0x16a38, 0x16a40, 0x16a5e, 0x16a70, 0x16abe, @@ -16592,6 +16974,7 @@ static const OnigCodePoint CR_ID_Start[] = { 0x16b40, 0x16b43, 0x16b63, 0x16b77, 0x16b7d, 0x16b8f, + 0x16d40, 0x16d6c, 0x16e40, 0x16e7f, 0x16f00, 0x16f4a, 0x16f50, 0x16f50, @@ -16600,7 +16983,7 @@ static const OnigCodePoint CR_ID_Start[] = { 0x16fe3, 0x16fe3, 0x17000, 0x187f7, 0x18800, 0x18cd5, - 0x18d00, 0x18d08, + 0x18cff, 0x18d08, 0x1aff0, 0x1aff3, 0x1aff5, 0x1affb, 0x1affd, 0x1affe, @@ -16653,6 +17036,8 @@ static const OnigCodePoint CR_ID_Start[] = { 0x1e290, 0x1e2ad, 0x1e2c0, 0x1e2eb, 0x1e4d0, 0x1e4eb, + 0x1e5d0, 0x1e5ed, + 0x1e5f0, 0x1e5f0, 0x1e7e0, 0x1e7e6, 0x1e7e8, 0x1e7eb, 0x1e7ed, 0x1e7ee, @@ -16698,6 +17083,7 @@ static const OnigCodePoint CR_ID_Start[] = { 0x2b740, 0x2b81d, 0x2b820, 0x2cea1, 0x2ceb0, 0x2ebe0, + 0x2ebf0, 0x2ee5d, 0x2f800, 0x2fa1d, 0x30000, 0x3134a, 0x31350, 0x323af, @@ -16705,7 +17091,7 @@ static const OnigCodePoint CR_ID_Start[] = { /* 'ID_Continue': Derived Property */ static const OnigCodePoint CR_ID_Continue[] = { - 768, + 793, 0x0030, 0x0039, 0x0041, 0x005a, 0x005f, 0x005f, @@ -16759,7 +17145,7 @@ static const OnigCodePoint CR_ID_Continue[] = { 0x0860, 0x086a, 0x0870, 0x0887, 0x0889, 0x088e, - 0x0898, 0x08e1, + 0x0897, 0x08e1, 0x08e3, 0x0963, 0x0966, 0x096f, 0x0971, 0x0983, @@ -16982,7 +17368,7 @@ static const OnigCodePoint CR_ID_Continue[] = { 0x1c00, 0x1c37, 0x1c40, 0x1c49, 0x1c4d, 0x1c7d, - 0x1c80, 0x1c88, + 0x1c80, 0x1c8a, 0x1c90, 0x1cba, 0x1cbd, 0x1cbf, 0x1cd0, 0x1cd2, @@ -17006,6 +17392,7 @@ static const OnigCodePoint CR_ID_Continue[] = { 0x1fe0, 0x1fec, 0x1ff2, 0x1ff4, 0x1ff6, 0x1ffc, + 0x200c, 0x200d, 0x203f, 0x2040, 0x2054, 0x2054, 0x2071, 0x2071, @@ -17050,8 +17437,7 @@ static const OnigCodePoint CR_ID_Continue[] = { 0x3038, 0x303c, 0x3041, 0x3096, 0x3099, 0x309f, - 0x30a1, 0x30fa, - 0x30fc, 0x30ff, + 0x30a1, 0x30ff, 0x3105, 0x312f, 0x3131, 0x318e, 0x31a0, 0x31bf, @@ -17066,10 +17452,10 @@ static const OnigCodePoint CR_ID_Continue[] = { 0xa67f, 0xa6f1, 0xa717, 0xa71f, 0xa722, 0xa788, - 0xa78b, 0xa7ca, + 0xa78b, 0xa7cd, 0xa7d0, 0xa7d1, 0xa7d3, 0xa7d3, - 0xa7d5, 0xa7d9, + 0xa7d5, 0xa7dc, 0xa7f2, 0xa827, 0xa82c, 0xa82c, 0xa840, 0xa873, @@ -17129,7 +17515,7 @@ static const OnigCodePoint CR_ID_Continue[] = { 0xff21, 0xff3a, 0xff3f, 0xff3f, 0xff41, 0xff5a, - 0xff66, 0xffbe, + 0xff65, 0xffbe, 0xffc2, 0xffc7, 0xffca, 0xffcf, 0xffd2, 0xffd7, @@ -17167,6 +17553,7 @@ static const OnigCodePoint CR_ID_Continue[] = { 0x105a3, 0x105b1, 0x105b3, 0x105b9, 0x105bb, 0x105bc, + 0x105c0, 0x105f3, 0x10600, 0x10736, 0x10740, 0x10755, 0x10760, 0x10767, @@ -17207,10 +17594,14 @@ static const OnigCodePoint CR_ID_Continue[] = { 0x10cc0, 0x10cf2, 0x10d00, 0x10d27, 0x10d30, 0x10d39, + 0x10d40, 0x10d65, + 0x10d69, 0x10d6d, + 0x10d6f, 0x10d85, 0x10e80, 0x10ea9, 0x10eab, 0x10eac, 0x10eb0, 0x10eb1, - 0x10efd, 0x10f1c, + 0x10ec2, 0x10ec4, + 0x10efc, 0x10f1c, 0x10f27, 0x10f27, 0x10f30, 0x10f50, 0x10f70, 0x10f85, @@ -17256,6 +17647,16 @@ static const OnigCodePoint CR_ID_Continue[] = { 0x1135d, 0x11363, 0x11366, 0x1136c, 0x11370, 0x11374, + 0x11380, 0x11389, + 0x1138b, 0x1138b, + 0x1138e, 0x1138e, + 0x11390, 0x113b5, + 0x113b7, 0x113c0, + 0x113c2, 0x113c2, + 0x113c5, 0x113c5, + 0x113c7, 0x113ca, + 0x113cc, 0x113d3, + 0x113e1, 0x113e2, 0x11400, 0x1144a, 0x11450, 0x11459, 0x1145e, 0x11461, @@ -17270,6 +17671,7 @@ static const OnigCodePoint CR_ID_Continue[] = { 0x11650, 0x11659, 0x11680, 0x116b8, 0x116c0, 0x116c9, + 0x116d0, 0x116e3, 0x11700, 0x1171a, 0x1171d, 0x1172b, 0x11730, 0x11739, @@ -17293,6 +17695,8 @@ static const OnigCodePoint CR_ID_Continue[] = { 0x11a50, 0x11a99, 0x11a9d, 0x11a9d, 0x11ab0, 0x11af8, + 0x11bc0, 0x11be0, + 0x11bf0, 0x11bf9, 0x11c00, 0x11c08, 0x11c0a, 0x11c36, 0x11c38, 0x11c40, @@ -17317,7 +17721,7 @@ static const OnigCodePoint CR_ID_Continue[] = { 0x11f00, 0x11f10, 0x11f12, 0x11f3a, 0x11f3e, 0x11f42, - 0x11f50, 0x11f59, + 0x11f50, 0x11f5a, 0x11fb0, 0x11fb0, 0x12000, 0x12399, 0x12400, 0x1246e, @@ -17325,7 +17729,9 @@ static const OnigCodePoint CR_ID_Continue[] = { 0x12f90, 0x12ff0, 0x13000, 0x1342f, 0x13440, 0x13455, + 0x13460, 0x143fa, 0x14400, 0x14646, + 0x16100, 0x16139, 0x16800, 0x16a38, 0x16a40, 0x16a5e, 0x16a60, 0x16a69, @@ -17338,6 +17744,8 @@ static const OnigCodePoint CR_ID_Continue[] = { 0x16b50, 0x16b59, 0x16b63, 0x16b77, 0x16b7d, 0x16b8f, + 0x16d40, 0x16d6c, + 0x16d70, 0x16d79, 0x16e40, 0x16e7f, 0x16f00, 0x16f4a, 0x16f4f, 0x16f87, @@ -17347,7 +17755,7 @@ static const OnigCodePoint CR_ID_Continue[] = { 0x16ff0, 0x16ff1, 0x17000, 0x187f7, 0x18800, 0x18cd5, - 0x18d00, 0x18d08, + 0x18cff, 0x18d08, 0x1aff0, 0x1aff3, 0x1aff5, 0x1affb, 0x1affd, 0x1affe, @@ -17362,6 +17770,7 @@ static const OnigCodePoint CR_ID_Continue[] = { 0x1bc80, 0x1bc88, 0x1bc90, 0x1bc99, 0x1bc9d, 0x1bc9e, + 0x1ccf0, 0x1ccf9, 0x1cf00, 0x1cf2d, 0x1cf30, 0x1cf46, 0x1d165, 0x1d169, @@ -17423,6 +17832,7 @@ static const OnigCodePoint CR_ID_Continue[] = { 0x1e290, 0x1e2ae, 0x1e2c0, 0x1e2f9, 0x1e4d0, 0x1e4f9, + 0x1e5d0, 0x1e5fa, 0x1e7e0, 0x1e7e6, 0x1e7e8, 0x1e7eb, 0x1e7ed, 0x1e7ee, @@ -17470,6 +17880,7 @@ static const OnigCodePoint CR_ID_Continue[] = { 0x2b740, 0x2b81d, 0x2b820, 0x2cea1, 0x2ceb0, 0x2ebe0, + 0x2ebf0, 0x2ee5d, 0x2f800, 0x2fa1d, 0x30000, 0x3134a, 0x31350, 0x323af, @@ -17478,7 +17889,7 @@ static const OnigCodePoint CR_ID_Continue[] = { /* 'XID_Start': Derived Property */ static const OnigCodePoint CR_XID_Start[] = { - 666, + 684, 0x0041, 0x005a, 0x0061, 0x007a, 0x00aa, 0x00aa, @@ -17703,7 +18114,7 @@ static const OnigCodePoint CR_XID_Start[] = { 0x1c00, 0x1c23, 0x1c4d, 0x1c4f, 0x1c5a, 0x1c7d, - 0x1c80, 0x1c88, + 0x1c80, 0x1c8a, 0x1c90, 0x1cba, 0x1cbd, 0x1cbf, 0x1ce9, 0x1cec, @@ -17786,10 +18197,10 @@ static const OnigCodePoint CR_XID_Start[] = { 0xa6a0, 0xa6ef, 0xa717, 0xa71f, 0xa722, 0xa788, - 0xa78b, 0xa7ca, + 0xa78b, 0xa7cd, 0xa7d0, 0xa7d1, 0xa7d3, 0xa7d3, - 0xa7d5, 0xa7d9, + 0xa7d5, 0xa7dc, 0xa7f2, 0xa801, 0xa803, 0xa805, 0xa807, 0xa80a, @@ -17894,6 +18305,7 @@ static const OnigCodePoint CR_XID_Start[] = { 0x105a3, 0x105b1, 0x105b3, 0x105b9, 0x105bb, 0x105bc, + 0x105c0, 0x105f3, 0x10600, 0x10736, 0x10740, 0x10755, 0x10760, 0x10767, @@ -17930,8 +18342,11 @@ static const OnigCodePoint CR_XID_Start[] = { 0x10c80, 0x10cb2, 0x10cc0, 0x10cf2, 0x10d00, 0x10d23, + 0x10d4a, 0x10d65, + 0x10d6f, 0x10d85, 0x10e80, 0x10ea9, 0x10eb0, 0x10eb1, + 0x10ec2, 0x10ec4, 0x10f00, 0x10f1c, 0x10f27, 0x10f27, 0x10f30, 0x10f45, @@ -17970,6 +18385,13 @@ static const OnigCodePoint CR_XID_Start[] = { 0x1133d, 0x1133d, 0x11350, 0x11350, 0x1135d, 0x11361, + 0x11380, 0x11389, + 0x1138b, 0x1138b, + 0x1138e, 0x1138e, + 0x11390, 0x113b5, + 0x113b7, 0x113b7, + 0x113d1, 0x113d1, + 0x113d3, 0x113d3, 0x11400, 0x11434, 0x11447, 0x1144a, 0x1145f, 0x11461, @@ -18004,6 +18426,7 @@ static const OnigCodePoint CR_XID_Start[] = { 0x11a5c, 0x11a89, 0x11a9d, 0x11a9d, 0x11ab0, 0x11af8, + 0x11bc0, 0x11be0, 0x11c00, 0x11c08, 0x11c0a, 0x11c2e, 0x11c40, 0x11c40, @@ -18027,7 +18450,9 @@ static const OnigCodePoint CR_XID_Start[] = { 0x12f90, 0x12ff0, 0x13000, 0x1342f, 0x13441, 0x13446, + 0x13460, 0x143fa, 0x14400, 0x14646, + 0x16100, 0x1611d, 0x16800, 0x16a38, 0x16a40, 0x16a5e, 0x16a70, 0x16abe, @@ -18036,6 +18461,7 @@ static const OnigCodePoint CR_XID_Start[] = { 0x16b40, 0x16b43, 0x16b63, 0x16b77, 0x16b7d, 0x16b8f, + 0x16d40, 0x16d6c, 0x16e40, 0x16e7f, 0x16f00, 0x16f4a, 0x16f50, 0x16f50, @@ -18044,7 +18470,7 @@ static const OnigCodePoint CR_XID_Start[] = { 0x16fe3, 0x16fe3, 0x17000, 0x187f7, 0x18800, 0x18cd5, - 0x18d00, 0x18d08, + 0x18cff, 0x18d08, 0x1aff0, 0x1aff3, 0x1aff5, 0x1affb, 0x1affd, 0x1affe, @@ -18097,6 +18523,8 @@ static const OnigCodePoint CR_XID_Start[] = { 0x1e290, 0x1e2ad, 0x1e2c0, 0x1e2eb, 0x1e4d0, 0x1e4eb, + 0x1e5d0, 0x1e5ed, + 0x1e5f0, 0x1e5f0, 0x1e7e0, 0x1e7e6, 0x1e7e8, 0x1e7eb, 0x1e7ed, 0x1e7ee, @@ -18142,6 +18570,7 @@ static const OnigCodePoint CR_XID_Start[] = { 0x2b740, 0x2b81d, 0x2b820, 0x2cea1, 0x2ceb0, 0x2ebe0, + 0x2ebf0, 0x2ee5d, 0x2f800, 0x2fa1d, 0x30000, 0x3134a, 0x31350, 0x323af, @@ -18149,7 +18578,7 @@ static const OnigCodePoint CR_XID_Start[] = { /* 'XID_Continue': Derived Property */ static const OnigCodePoint CR_XID_Continue[] = { - 775, + 800, 0x0030, 0x0039, 0x0041, 0x005a, 0x005f, 0x005f, @@ -18203,7 +18632,7 @@ static const OnigCodePoint CR_XID_Continue[] = { 0x0860, 0x086a, 0x0870, 0x0887, 0x0889, 0x088e, - 0x0898, 0x08e1, + 0x0897, 0x08e1, 0x08e3, 0x0963, 0x0966, 0x096f, 0x0971, 0x0983, @@ -18426,7 +18855,7 @@ static const OnigCodePoint CR_XID_Continue[] = { 0x1c00, 0x1c37, 0x1c40, 0x1c49, 0x1c4d, 0x1c7d, - 0x1c80, 0x1c88, + 0x1c80, 0x1c8a, 0x1c90, 0x1cba, 0x1cbd, 0x1cbf, 0x1cd0, 0x1cd2, @@ -18450,6 +18879,7 @@ static const OnigCodePoint CR_XID_Continue[] = { 0x1fe0, 0x1fec, 0x1ff2, 0x1ff4, 0x1ff6, 0x1ffc, + 0x200c, 0x200d, 0x203f, 0x2040, 0x2054, 0x2054, 0x2071, 0x2071, @@ -18495,8 +18925,7 @@ static const OnigCodePoint CR_XID_Continue[] = { 0x3041, 0x3096, 0x3099, 0x309a, 0x309d, 0x309f, - 0x30a1, 0x30fa, - 0x30fc, 0x30ff, + 0x30a1, 0x30ff, 0x3105, 0x312f, 0x3131, 0x318e, 0x31a0, 0x31bf, @@ -18511,10 +18940,10 @@ static const OnigCodePoint CR_XID_Continue[] = { 0xa67f, 0xa6f1, 0xa717, 0xa71f, 0xa722, 0xa788, - 0xa78b, 0xa7ca, + 0xa78b, 0xa7cd, 0xa7d0, 0xa7d1, 0xa7d3, 0xa7d3, - 0xa7d5, 0xa7d9, + 0xa7d5, 0xa7dc, 0xa7f2, 0xa827, 0xa82c, 0xa82c, 0xa840, 0xa873, @@ -18580,7 +19009,7 @@ static const OnigCodePoint CR_XID_Continue[] = { 0xff21, 0xff3a, 0xff3f, 0xff3f, 0xff41, 0xff5a, - 0xff66, 0xffbe, + 0xff65, 0xffbe, 0xffc2, 0xffc7, 0xffca, 0xffcf, 0xffd2, 0xffd7, @@ -18618,6 +19047,7 @@ static const OnigCodePoint CR_XID_Continue[] = { 0x105a3, 0x105b1, 0x105b3, 0x105b9, 0x105bb, 0x105bc, + 0x105c0, 0x105f3, 0x10600, 0x10736, 0x10740, 0x10755, 0x10760, 0x10767, @@ -18658,10 +19088,14 @@ static const OnigCodePoint CR_XID_Continue[] = { 0x10cc0, 0x10cf2, 0x10d00, 0x10d27, 0x10d30, 0x10d39, + 0x10d40, 0x10d65, + 0x10d69, 0x10d6d, + 0x10d6f, 0x10d85, 0x10e80, 0x10ea9, 0x10eab, 0x10eac, 0x10eb0, 0x10eb1, - 0x10efd, 0x10f1c, + 0x10ec2, 0x10ec4, + 0x10efc, 0x10f1c, 0x10f27, 0x10f27, 0x10f30, 0x10f50, 0x10f70, 0x10f85, @@ -18707,6 +19141,16 @@ static const OnigCodePoint CR_XID_Continue[] = { 0x1135d, 0x11363, 0x11366, 0x1136c, 0x11370, 0x11374, + 0x11380, 0x11389, + 0x1138b, 0x1138b, + 0x1138e, 0x1138e, + 0x11390, 0x113b5, + 0x113b7, 0x113c0, + 0x113c2, 0x113c2, + 0x113c5, 0x113c5, + 0x113c7, 0x113ca, + 0x113cc, 0x113d3, + 0x113e1, 0x113e2, 0x11400, 0x1144a, 0x11450, 0x11459, 0x1145e, 0x11461, @@ -18721,6 +19165,7 @@ static const OnigCodePoint CR_XID_Continue[] = { 0x11650, 0x11659, 0x11680, 0x116b8, 0x116c0, 0x116c9, + 0x116d0, 0x116e3, 0x11700, 0x1171a, 0x1171d, 0x1172b, 0x11730, 0x11739, @@ -18744,6 +19189,8 @@ static const OnigCodePoint CR_XID_Continue[] = { 0x11a50, 0x11a99, 0x11a9d, 0x11a9d, 0x11ab0, 0x11af8, + 0x11bc0, 0x11be0, + 0x11bf0, 0x11bf9, 0x11c00, 0x11c08, 0x11c0a, 0x11c36, 0x11c38, 0x11c40, @@ -18768,7 +19215,7 @@ static const OnigCodePoint CR_XID_Continue[] = { 0x11f00, 0x11f10, 0x11f12, 0x11f3a, 0x11f3e, 0x11f42, - 0x11f50, 0x11f59, + 0x11f50, 0x11f5a, 0x11fb0, 0x11fb0, 0x12000, 0x12399, 0x12400, 0x1246e, @@ -18776,7 +19223,9 @@ static const OnigCodePoint CR_XID_Continue[] = { 0x12f90, 0x12ff0, 0x13000, 0x1342f, 0x13440, 0x13455, + 0x13460, 0x143fa, 0x14400, 0x14646, + 0x16100, 0x16139, 0x16800, 0x16a38, 0x16a40, 0x16a5e, 0x16a60, 0x16a69, @@ -18789,6 +19238,8 @@ static const OnigCodePoint CR_XID_Continue[] = { 0x16b50, 0x16b59, 0x16b63, 0x16b77, 0x16b7d, 0x16b8f, + 0x16d40, 0x16d6c, + 0x16d70, 0x16d79, 0x16e40, 0x16e7f, 0x16f00, 0x16f4a, 0x16f4f, 0x16f87, @@ -18798,7 +19249,7 @@ static const OnigCodePoint CR_XID_Continue[] = { 0x16ff0, 0x16ff1, 0x17000, 0x187f7, 0x18800, 0x18cd5, - 0x18d00, 0x18d08, + 0x18cff, 0x18d08, 0x1aff0, 0x1aff3, 0x1aff5, 0x1affb, 0x1affd, 0x1affe, @@ -18813,6 +19264,7 @@ static const OnigCodePoint CR_XID_Continue[] = { 0x1bc80, 0x1bc88, 0x1bc90, 0x1bc99, 0x1bc9d, 0x1bc9e, + 0x1ccf0, 0x1ccf9, 0x1cf00, 0x1cf2d, 0x1cf30, 0x1cf46, 0x1d165, 0x1d169, @@ -18874,6 +19326,7 @@ static const OnigCodePoint CR_XID_Continue[] = { 0x1e290, 0x1e2ae, 0x1e2c0, 0x1e2f9, 0x1e4d0, 0x1e4f9, + 0x1e5d0, 0x1e5fa, 0x1e7e0, 0x1e7e6, 0x1e7e8, 0x1e7eb, 0x1e7ed, 0x1e7ee, @@ -18921,6 +19374,7 @@ static const OnigCodePoint CR_XID_Continue[] = { 0x2b740, 0x2b81d, 0x2b820, 0x2cea1, 0x2ceb0, 0x2ebe0, + 0x2ebf0, 0x2ee5d, 0x2f800, 0x2fa1d, 0x30000, 0x3134a, 0x31350, 0x323af, @@ -18951,7 +19405,7 @@ static const OnigCodePoint CR_Default_Ignorable_Code_Point[] = { /* 'Grapheme_Extend': Derived Property */ static const OnigCodePoint CR_Grapheme_Extend[] = { - 363, + 375, 0x0300, 0x036f, 0x0483, 0x0489, 0x0591, 0x05bd, @@ -18976,7 +19430,7 @@ static const OnigCodePoint CR_Grapheme_Extend[] = { 0x0825, 0x0827, 0x0829, 0x082d, 0x0859, 0x085b, - 0x0898, 0x089f, + 0x0897, 0x089f, 0x08ca, 0x08e1, 0x08e3, 0x0902, 0x093a, 0x093a, @@ -19030,10 +19484,10 @@ static const OnigCodePoint CR_Grapheme_Extend[] = { 0x0c62, 0x0c63, 0x0c81, 0x0c81, 0x0cbc, 0x0cbc, - 0x0cbf, 0x0cbf, + 0x0cbf, 0x0cc0, 0x0cc2, 0x0cc2, - 0x0cc6, 0x0cc6, - 0x0ccc, 0x0ccd, + 0x0cc6, 0x0cc8, + 0x0cca, 0x0ccd, 0x0cd5, 0x0cd6, 0x0ce2, 0x0ce3, 0x0d00, 0x0d01, @@ -19077,8 +19531,8 @@ static const OnigCodePoint CR_Grapheme_Extend[] = { 0x108d, 0x108d, 0x109d, 0x109d, 0x135d, 0x135f, - 0x1712, 0x1714, - 0x1732, 0x1733, + 0x1712, 0x1715, + 0x1732, 0x1734, 0x1752, 0x1753, 0x1772, 0x1773, 0x17b4, 0x17b5, @@ -19105,18 +19559,16 @@ static const OnigCodePoint CR_Grapheme_Extend[] = { 0x1a7f, 0x1a7f, 0x1ab0, 0x1ace, 0x1b00, 0x1b03, - 0x1b34, 0x1b3a, - 0x1b3c, 0x1b3c, - 0x1b42, 0x1b42, + 0x1b34, 0x1b3d, + 0x1b42, 0x1b44, 0x1b6b, 0x1b73, 0x1b80, 0x1b81, 0x1ba2, 0x1ba5, - 0x1ba8, 0x1ba9, - 0x1bab, 0x1bad, + 0x1ba8, 0x1bad, 0x1be6, 0x1be6, 0x1be8, 0x1be9, 0x1bed, 0x1bed, - 0x1bef, 0x1bf1, + 0x1bef, 0x1bf3, 0x1c2c, 0x1c33, 0x1c36, 0x1c37, 0x1cd0, 0x1cd2, @@ -19147,10 +19599,12 @@ static const OnigCodePoint CR_Grapheme_Extend[] = { 0xa8ff, 0xa8ff, 0xa926, 0xa92d, 0xa947, 0xa951, + 0xa953, 0xa953, 0xa980, 0xa982, 0xa9b3, 0xa9b3, 0xa9b6, 0xa9b9, 0xa9bc, 0xa9bd, + 0xa9c0, 0xa9c0, 0xa9e5, 0xa9e5, 0xaa29, 0xaa2e, 0xaa31, 0xaa32, @@ -19182,8 +19636,9 @@ static const OnigCodePoint CR_Grapheme_Extend[] = { 0x10a3f, 0x10a3f, 0x10ae5, 0x10ae6, 0x10d24, 0x10d27, + 0x10d69, 0x10d6d, 0x10eab, 0x10eac, - 0x10efd, 0x10eff, + 0x10efc, 0x10eff, 0x10f46, 0x10f50, 0x10f82, 0x10f85, 0x11001, 0x11001, @@ -19200,11 +19655,11 @@ static const OnigCodePoint CR_Grapheme_Extend[] = { 0x11173, 0x11173, 0x11180, 0x11181, 0x111b6, 0x111be, + 0x111c0, 0x111c0, 0x111c9, 0x111cc, 0x111cf, 0x111cf, 0x1122f, 0x11231, - 0x11234, 0x11234, - 0x11236, 0x11237, + 0x11234, 0x11237, 0x1123e, 0x1123e, 0x11241, 0x11241, 0x112df, 0x112df, @@ -19213,9 +19668,18 @@ static const OnigCodePoint CR_Grapheme_Extend[] = { 0x1133b, 0x1133c, 0x1133e, 0x1133e, 0x11340, 0x11340, + 0x1134d, 0x1134d, 0x11357, 0x11357, 0x11366, 0x1136c, 0x11370, 0x11374, + 0x113b8, 0x113b8, + 0x113bb, 0x113c0, + 0x113c2, 0x113c2, + 0x113c5, 0x113c5, + 0x113c7, 0x113c9, + 0x113ce, 0x113d0, + 0x113d2, 0x113d2, + 0x113e1, 0x113e2, 0x11438, 0x1143f, 0x11442, 0x11444, 0x11446, 0x11446, @@ -19236,16 +19700,15 @@ static const OnigCodePoint CR_Grapheme_Extend[] = { 0x1163f, 0x11640, 0x116ab, 0x116ab, 0x116ad, 0x116ad, - 0x116b0, 0x116b5, - 0x116b7, 0x116b7, - 0x1171d, 0x1171f, + 0x116b0, 0x116b7, + 0x1171d, 0x1171d, + 0x1171f, 0x1171f, 0x11722, 0x11725, 0x11727, 0x1172b, 0x1182f, 0x11837, 0x11839, 0x1183a, 0x11930, 0x11930, - 0x1193b, 0x1193c, - 0x1193e, 0x1193e, + 0x1193b, 0x1193e, 0x11943, 0x11943, 0x119d4, 0x119d7, 0x119da, 0x119db, @@ -19276,21 +19739,23 @@ static const OnigCodePoint CR_Grapheme_Extend[] = { 0x11ef3, 0x11ef4, 0x11f00, 0x11f01, 0x11f36, 0x11f3a, - 0x11f40, 0x11f40, - 0x11f42, 0x11f42, + 0x11f40, 0x11f42, + 0x11f5a, 0x11f5a, 0x13440, 0x13440, 0x13447, 0x13455, + 0x1611e, 0x16129, + 0x1612d, 0x1612f, 0x16af0, 0x16af4, 0x16b30, 0x16b36, 0x16f4f, 0x16f4f, 0x16f8f, 0x16f92, 0x16fe4, 0x16fe4, + 0x16ff0, 0x16ff1, 0x1bc9d, 0x1bc9e, 0x1cf00, 0x1cf2d, 0x1cf30, 0x1cf46, - 0x1d165, 0x1d165, - 0x1d167, 0x1d169, - 0x1d16e, 0x1d172, + 0x1d165, 0x1d169, + 0x1d16d, 0x1d172, 0x1d17b, 0x1d182, 0x1d185, 0x1d18b, 0x1d1aa, 0x1d1ad, @@ -19311,6 +19776,7 @@ static const OnigCodePoint CR_Grapheme_Extend[] = { 0x1e2ae, 0x1e2ae, 0x1e2ec, 0x1e2ef, 0x1e4ec, 0x1e4ef, + 0x1e5ee, 0x1e5ef, 0x1e8d0, 0x1e8d6, 0x1e944, 0x1e94a, 0xe0020, 0xe007f, @@ -19319,7 +19785,7 @@ static const OnigCodePoint CR_Grapheme_Extend[] = { /* 'Grapheme_Base': Derived Property */ static const OnigCodePoint CR_Grapheme_Base[] = { - 875, + 894, 0x0020, 0x007e, 0x00a0, 0x00ac, 0x00ae, 0x02ff, @@ -19462,10 +19928,8 @@ static const OnigCodePoint CR_Grapheme_Base[] = { 0x0caa, 0x0cb3, 0x0cb5, 0x0cb9, 0x0cbd, 0x0cbe, - 0x0cc0, 0x0cc1, + 0x0cc1, 0x0cc1, 0x0cc3, 0x0cc4, - 0x0cc7, 0x0cc8, - 0x0cca, 0x0ccb, 0x0cdd, 0x0cde, 0x0ce0, 0x0ce1, 0x0ce6, 0x0cef, @@ -19556,9 +20020,8 @@ static const OnigCodePoint CR_Grapheme_Base[] = { 0x1400, 0x169c, 0x16a0, 0x16f8, 0x1700, 0x1711, - 0x1715, 0x1715, 0x171f, 0x1731, - 0x1734, 0x1736, + 0x1735, 0x1736, 0x1740, 0x1751, 0x1760, 0x176c, 0x176e, 0x1770, @@ -19598,23 +20061,20 @@ static const OnigCodePoint CR_Grapheme_Base[] = { 0x1a90, 0x1a99, 0x1aa0, 0x1aad, 0x1b04, 0x1b33, - 0x1b3b, 0x1b3b, - 0x1b3d, 0x1b41, - 0x1b43, 0x1b4c, - 0x1b50, 0x1b6a, - 0x1b74, 0x1b7e, + 0x1b3e, 0x1b41, + 0x1b45, 0x1b4c, + 0x1b4e, 0x1b6a, + 0x1b74, 0x1b7f, 0x1b82, 0x1ba1, 0x1ba6, 0x1ba7, - 0x1baa, 0x1baa, 0x1bae, 0x1be5, 0x1be7, 0x1be7, 0x1bea, 0x1bec, 0x1bee, 0x1bee, - 0x1bf2, 0x1bf3, 0x1bfc, 0x1c2b, 0x1c34, 0x1c35, 0x1c3b, 0x1c49, - 0x1c4d, 0x1c88, + 0x1c4d, 0x1c8a, 0x1c90, 0x1cba, 0x1cbd, 0x1cc7, 0x1cd3, 0x1cd3, @@ -19648,7 +20108,7 @@ static const OnigCodePoint CR_Grapheme_Base[] = { 0x2090, 0x209c, 0x20a0, 0x20c0, 0x2100, 0x218b, - 0x2190, 0x2426, + 0x2190, 0x2429, 0x2440, 0x244a, 0x2460, 0x2b73, 0x2b76, 0x2b95, @@ -19672,15 +20132,14 @@ static const OnigCodePoint CR_Grapheme_Base[] = { 0x2e80, 0x2e99, 0x2e9b, 0x2ef3, 0x2f00, 0x2fd5, - 0x2ff0, 0x2ffb, - 0x3000, 0x3029, + 0x2ff0, 0x3029, 0x3030, 0x303f, 0x3041, 0x3096, 0x309b, 0x30ff, 0x3105, 0x312f, 0x3131, 0x318e, - 0x3190, 0x31e3, - 0x31f0, 0x321e, + 0x3190, 0x31e5, + 0x31ef, 0x321e, 0x3220, 0xa48c, 0xa490, 0xa4c6, 0xa4d0, 0xa62b, @@ -19689,10 +20148,10 @@ static const OnigCodePoint CR_Grapheme_Base[] = { 0xa67e, 0xa69d, 0xa6a0, 0xa6ef, 0xa6f2, 0xa6f7, - 0xa700, 0xa7ca, + 0xa700, 0xa7cd, 0xa7d0, 0xa7d1, 0xa7d3, 0xa7d3, - 0xa7d5, 0xa7d9, + 0xa7d5, 0xa7dc, 0xa7f2, 0xa801, 0xa803, 0xa805, 0xa807, 0xa80a, @@ -19705,12 +20164,13 @@ static const OnigCodePoint CR_Grapheme_Base[] = { 0xa8f2, 0xa8fe, 0xa900, 0xa925, 0xa92e, 0xa946, - 0xa952, 0xa953, + 0xa952, 0xa952, 0xa95f, 0xa97c, 0xa983, 0xa9b2, 0xa9b4, 0xa9b5, 0xa9ba, 0xa9bb, - 0xa9be, 0xa9cd, + 0xa9be, 0xa9bf, + 0xa9c1, 0xa9cd, 0xa9cf, 0xa9d9, 0xa9de, 0xa9e4, 0xa9e6, 0xa9fe, @@ -19809,6 +20269,7 @@ static const OnigCodePoint CR_Grapheme_Base[] = { 0x105a3, 0x105b1, 0x105b3, 0x105b9, 0x105bb, 0x105bc, + 0x105c0, 0x105f3, 0x10600, 0x10736, 0x10740, 0x10755, 0x10760, 0x10767, @@ -19850,10 +20311,14 @@ static const OnigCodePoint CR_Grapheme_Base[] = { 0x10cc0, 0x10cf2, 0x10cfa, 0x10d23, 0x10d30, 0x10d39, + 0x10d40, 0x10d65, + 0x10d6e, 0x10d85, + 0x10d8e, 0x10d8f, 0x10e60, 0x10e7e, 0x10e80, 0x10ea9, 0x10ead, 0x10ead, 0x10eb0, 0x10eb1, + 0x10ec2, 0x10ec4, 0x10f00, 0x10f27, 0x10f30, 0x10f45, 0x10f51, 0x10f59, @@ -19879,14 +20344,14 @@ static const OnigCodePoint CR_Grapheme_Base[] = { 0x11150, 0x11172, 0x11174, 0x11176, 0x11182, 0x111b5, - 0x111bf, 0x111c8, + 0x111bf, 0x111bf, + 0x111c1, 0x111c8, 0x111cd, 0x111ce, 0x111d0, 0x111df, 0x111e1, 0x111f4, 0x11200, 0x11211, 0x11213, 0x1122e, 0x11232, 0x11233, - 0x11235, 0x11235, 0x11238, 0x1123d, 0x1123f, 0x11240, 0x11280, 0x11286, @@ -19908,9 +20373,20 @@ static const OnigCodePoint CR_Grapheme_Base[] = { 0x1133f, 0x1133f, 0x11341, 0x11344, 0x11347, 0x11348, - 0x1134b, 0x1134d, + 0x1134b, 0x1134c, 0x11350, 0x11350, 0x1135d, 0x11363, + 0x11380, 0x11389, + 0x1138b, 0x1138b, + 0x1138e, 0x1138e, + 0x11390, 0x113b5, + 0x113b7, 0x113b7, + 0x113b9, 0x113ba, + 0x113ca, 0x113ca, + 0x113cc, 0x113cd, + 0x113d1, 0x113d1, + 0x113d3, 0x113d5, + 0x113d7, 0x113d8, 0x11400, 0x11437, 0x11440, 0x11441, 0x11445, 0x11445, @@ -19939,10 +20415,11 @@ static const OnigCodePoint CR_Grapheme_Base[] = { 0x11680, 0x116aa, 0x116ac, 0x116ac, 0x116ae, 0x116af, - 0x116b6, 0x116b6, 0x116b8, 0x116b9, 0x116c0, 0x116c9, + 0x116d0, 0x116e3, 0x11700, 0x1171a, + 0x1171e, 0x1171e, 0x11720, 0x11721, 0x11726, 0x11726, 0x11730, 0x11746, @@ -19957,7 +20434,6 @@ static const OnigCodePoint CR_Grapheme_Base[] = { 0x11918, 0x1192f, 0x11931, 0x11935, 0x11937, 0x11938, - 0x1193d, 0x1193d, 0x1193f, 0x11942, 0x11944, 0x11946, 0x11950, 0x11959, @@ -19976,6 +20452,8 @@ static const OnigCodePoint CR_Grapheme_Base[] = { 0x11a9a, 0x11aa2, 0x11ab0, 0x11af8, 0x11b00, 0x11b09, + 0x11bc0, 0x11be1, + 0x11bf0, 0x11bf9, 0x11c00, 0x11c08, 0x11c0a, 0x11c2f, 0x11c3e, 0x11c3e, @@ -20002,7 +20480,6 @@ static const OnigCodePoint CR_Grapheme_Base[] = { 0x11f02, 0x11f10, 0x11f12, 0x11f35, 0x11f3e, 0x11f3f, - 0x11f41, 0x11f41, 0x11f43, 0x11f59, 0x11fb0, 0x11fb0, 0x11fc0, 0x11ff1, @@ -20013,7 +20490,11 @@ static const OnigCodePoint CR_Grapheme_Base[] = { 0x12f90, 0x12ff2, 0x13000, 0x1342f, 0x13441, 0x13446, + 0x13460, 0x143fa, 0x14400, 0x14646, + 0x16100, 0x1611d, + 0x1612a, 0x1612c, + 0x16130, 0x16139, 0x16800, 0x16a38, 0x16a40, 0x16a5e, 0x16a60, 0x16a69, @@ -20027,15 +20508,15 @@ static const OnigCodePoint CR_Grapheme_Base[] = { 0x16b5b, 0x16b61, 0x16b63, 0x16b77, 0x16b7d, 0x16b8f, + 0x16d40, 0x16d79, 0x16e40, 0x16e9a, 0x16f00, 0x16f4a, 0x16f50, 0x16f87, 0x16f93, 0x16f9f, 0x16fe0, 0x16fe3, - 0x16ff0, 0x16ff1, 0x17000, 0x187f7, 0x18800, 0x18cd5, - 0x18d00, 0x18d08, + 0x18cff, 0x18d08, 0x1aff0, 0x1aff3, 0x1aff5, 0x1affb, 0x1affd, 0x1affe, @@ -20051,12 +20532,13 @@ static const OnigCodePoint CR_Grapheme_Base[] = { 0x1bc90, 0x1bc99, 0x1bc9c, 0x1bc9c, 0x1bc9f, 0x1bc9f, + 0x1cc00, 0x1ccf9, + 0x1cd00, 0x1ceb3, 0x1cf50, 0x1cfc3, 0x1d000, 0x1d0f5, 0x1d100, 0x1d126, 0x1d129, 0x1d164, - 0x1d166, 0x1d166, - 0x1d16a, 0x1d16d, + 0x1d16a, 0x1d16c, 0x1d183, 0x1d184, 0x1d18c, 0x1d1a9, 0x1d1ae, 0x1d1ea, @@ -20104,6 +20586,9 @@ static const OnigCodePoint CR_Grapheme_Base[] = { 0x1e2ff, 0x1e2ff, 0x1e4d0, 0x1e4eb, 0x1e4f0, 0x1e4f9, + 0x1e5d0, 0x1e5ed, + 0x1e5f0, 0x1e5fa, + 0x1e5ff, 0x1e5ff, 0x1e7e0, 0x1e7e6, 0x1e7e8, 0x1e7eb, 0x1e7ed, 0x1e7ee, @@ -20174,24 +20659,24 @@ static const OnigCodePoint CR_Grapheme_Base[] = { 0x1f850, 0x1f859, 0x1f860, 0x1f887, 0x1f890, 0x1f8ad, - 0x1f8b0, 0x1f8b1, + 0x1f8b0, 0x1f8bb, + 0x1f8c0, 0x1f8c1, 0x1f900, 0x1fa53, 0x1fa60, 0x1fa6d, 0x1fa70, 0x1fa7c, - 0x1fa80, 0x1fa88, - 0x1fa90, 0x1fabd, - 0x1fabf, 0x1fac5, - 0x1face, 0x1fadb, - 0x1fae0, 0x1fae8, + 0x1fa80, 0x1fa89, + 0x1fa8f, 0x1fac6, + 0x1face, 0x1fadc, + 0x1fadf, 0x1fae9, 0x1faf0, 0x1faf8, 0x1fb00, 0x1fb92, - 0x1fb94, 0x1fbca, - 0x1fbf0, 0x1fbf9, + 0x1fb94, 0x1fbf9, 0x20000, 0x2a6df, 0x2a700, 0x2b739, 0x2b740, 0x2b81d, 0x2b820, 0x2cea1, 0x2ceb0, 0x2ebe0, + 0x2ebf0, 0x2ee5d, 0x2f800, 0x2fa1d, 0x30000, 0x3134a, 0x31350, 0x323af, @@ -20199,7 +20684,7 @@ static const OnigCodePoint CR_Grapheme_Base[] = { /* 'Grapheme_Link': Derived Property */ static const OnigCodePoint CR_Grapheme_Link[] = { - 56, + 58, 0x094d, 0x094d, 0x09cd, 0x09cd, 0x0a4d, 0x0a4d, @@ -20240,6 +20725,7 @@ static const OnigCodePoint CR_Grapheme_Link[] = { 0x11235, 0x11235, 0x112ea, 0x112ea, 0x1134d, 0x1134d, + 0x113ce, 0x113d0, 0x11442, 0x11442, 0x114c2, 0x114c2, 0x115bf, 0x115bf, @@ -20256,279 +20742,699 @@ static const OnigCodePoint CR_Grapheme_Link[] = { 0x11d44, 0x11d45, 0x11d97, 0x11d97, 0x11f41, 0x11f42, + 0x1612f, 0x1612f, }; /* CR_Grapheme_Link */ -/* 'Common': Script */ -static const OnigCodePoint CR_Common[] = { - 173, - 0x0000, 0x0040, - 0x005b, 0x0060, - 0x007b, 0x00a9, - 0x00ab, 0x00b9, - 0x00bb, 0x00bf, - 0x00d7, 0x00d7, - 0x00f7, 0x00f7, - 0x02b9, 0x02df, - 0x02e5, 0x02e9, - 0x02ec, 0x02ff, - 0x0374, 0x0374, - 0x037e, 0x037e, - 0x0385, 0x0385, - 0x0387, 0x0387, - 0x0605, 0x0605, - 0x060c, 0x060c, - 0x061b, 0x061b, - 0x061f, 0x061f, - 0x0640, 0x0640, - 0x06dd, 0x06dd, - 0x08e2, 0x08e2, - 0x0964, 0x0965, - 0x0e3f, 0x0e3f, - 0x0fd5, 0x0fd8, - 0x10fb, 0x10fb, - 0x16eb, 0x16ed, - 0x1735, 0x1736, - 0x1802, 0x1803, - 0x1805, 0x1805, - 0x1cd3, 0x1cd3, - 0x1ce1, 0x1ce1, - 0x1ce9, 0x1cec, - 0x1cee, 0x1cf3, - 0x1cf5, 0x1cf7, - 0x1cfa, 0x1cfa, - 0x2000, 0x200b, - 0x200e, 0x2064, - 0x2066, 0x2070, - 0x2074, 0x207e, - 0x2080, 0x208e, - 0x20a0, 0x20c0, - 0x2100, 0x2125, - 0x2127, 0x2129, - 0x212c, 0x2131, - 0x2133, 0x214d, - 0x214f, 0x215f, - 0x2189, 0x218b, - 0x2190, 0x2426, - 0x2440, 0x244a, - 0x2460, 0x27ff, - 0x2900, 0x2b73, - 0x2b76, 0x2b95, - 0x2b97, 0x2bff, - 0x2e00, 0x2e5d, - 0x2ff0, 0x2ffb, - 0x3000, 0x3004, - 0x3006, 0x3006, - 0x3008, 0x3020, - 0x3030, 0x3037, - 0x303c, 0x303f, - 0x309b, 0x309c, - 0x30a0, 0x30a0, - 0x30fb, 0x30fc, - 0x3190, 0x319f, - 0x31c0, 0x31e3, - 0x3220, 0x325f, - 0x327f, 0x32cf, - 0x32ff, 0x32ff, - 0x3358, 0x33ff, - 0x4dc0, 0x4dff, - 0xa700, 0xa721, - 0xa788, 0xa78a, - 0xa830, 0xa839, - 0xa92e, 0xa92e, - 0xa9cf, 0xa9cf, - 0xab5b, 0xab5b, - 0xab6a, 0xab6b, - 0xfd3e, 0xfd3f, - 0xfe10, 0xfe19, - 0xfe30, 0xfe52, - 0xfe54, 0xfe66, - 0xfe68, 0xfe6b, - 0xfeff, 0xfeff, - 0xff01, 0xff20, - 0xff3b, 0xff40, - 0xff5b, 0xff65, - 0xff70, 0xff70, - 0xff9e, 0xff9f, - 0xffe0, 0xffe6, - 0xffe8, 0xffee, - 0xfff9, 0xfffd, - 0x10100, 0x10102, - 0x10107, 0x10133, - 0x10137, 0x1013f, - 0x10190, 0x1019c, - 0x101d0, 0x101fc, - 0x102e1, 0x102fb, - 0x1bca0, 0x1bca3, - 0x1cf50, 0x1cfc3, - 0x1d000, 0x1d0f5, - 0x1d100, 0x1d126, - 0x1d129, 0x1d166, - 0x1d16a, 0x1d17a, - 0x1d183, 0x1d184, - 0x1d18c, 0x1d1a9, - 0x1d1ae, 0x1d1ea, - 0x1d2c0, 0x1d2d3, - 0x1d2e0, 0x1d2f3, - 0x1d300, 0x1d356, - 0x1d360, 0x1d378, - 0x1d400, 0x1d454, - 0x1d456, 0x1d49c, - 0x1d49e, 0x1d49f, - 0x1d4a2, 0x1d4a2, - 0x1d4a5, 0x1d4a6, - 0x1d4a9, 0x1d4ac, - 0x1d4ae, 0x1d4b9, - 0x1d4bb, 0x1d4bb, - 0x1d4bd, 0x1d4c3, - 0x1d4c5, 0x1d505, - 0x1d507, 0x1d50a, - 0x1d50d, 0x1d514, - 0x1d516, 0x1d51c, - 0x1d51e, 0x1d539, - 0x1d53b, 0x1d53e, - 0x1d540, 0x1d544, - 0x1d546, 0x1d546, - 0x1d54a, 0x1d550, - 0x1d552, 0x1d6a5, - 0x1d6a8, 0x1d7cb, - 0x1d7ce, 0x1d7ff, - 0x1ec71, 0x1ecb4, - 0x1ed01, 0x1ed3d, - 0x1f000, 0x1f02b, - 0x1f030, 0x1f093, - 0x1f0a0, 0x1f0ae, - 0x1f0b1, 0x1f0bf, - 0x1f0c1, 0x1f0cf, - 0x1f0d1, 0x1f0f5, - 0x1f100, 0x1f1ad, - 0x1f1e6, 0x1f1ff, - 0x1f201, 0x1f202, - 0x1f210, 0x1f23b, - 0x1f240, 0x1f248, - 0x1f250, 0x1f251, - 0x1f260, 0x1f265, - 0x1f300, 0x1f6d7, - 0x1f6dc, 0x1f6ec, - 0x1f6f0, 0x1f6fc, - 0x1f700, 0x1f776, - 0x1f77b, 0x1f7d9, - 0x1f7e0, 0x1f7eb, - 0x1f7f0, 0x1f7f0, - 0x1f800, 0x1f80b, - 0x1f810, 0x1f847, - 0x1f850, 0x1f859, - 0x1f860, 0x1f887, - 0x1f890, 0x1f8ad, - 0x1f8b0, 0x1f8b1, - 0x1f900, 0x1fa53, - 0x1fa60, 0x1fa6d, - 0x1fa70, 0x1fa7c, - 0x1fa80, 0x1fa88, - 0x1fa90, 0x1fabd, - 0x1fabf, 0x1fac5, - 0x1face, 0x1fadb, - 0x1fae0, 0x1fae8, - 0x1faf0, 0x1faf8, - 0x1fb00, 0x1fb92, - 0x1fb94, 0x1fbca, - 0x1fbf0, 0x1fbf9, - 0xe0001, 0xe0001, - 0xe0020, 0xe007f, -}; /* CR_Common */ - -/* 'Latin': Script */ -static const OnigCodePoint CR_Latin[] = { - 39, - 0x0041, 0x005a, - 0x0061, 0x007a, - 0x00aa, 0x00aa, - 0x00ba, 0x00ba, - 0x00c0, 0x00d6, - 0x00d8, 0x00f6, - 0x00f8, 0x02b8, - 0x02e0, 0x02e4, - 0x1d00, 0x1d25, - 0x1d2c, 0x1d5c, - 0x1d62, 0x1d65, - 0x1d6b, 0x1d77, - 0x1d79, 0x1dbe, - 0x1e00, 0x1eff, - 0x2071, 0x2071, - 0x207f, 0x207f, - 0x2090, 0x209c, - 0x212a, 0x212b, - 0x2132, 0x2132, - 0x214e, 0x214e, - 0x2160, 0x2188, - 0x2c60, 0x2c7f, - 0xa722, 0xa787, - 0xa78b, 0xa7ca, - 0xa7d0, 0xa7d1, - 0xa7d3, 0xa7d3, - 0xa7d5, 0xa7d9, - 0xa7f2, 0xa7ff, - 0xab30, 0xab5a, - 0xab5c, 0xab64, - 0xab66, 0xab69, - 0xfb00, 0xfb06, - 0xff21, 0xff3a, - 0xff41, 0xff5a, - 0x10780, 0x10785, - 0x10787, 0x107b0, - 0x107b2, 0x107ba, - 0x1df00, 0x1df1e, - 0x1df25, 0x1df2a, -}; /* CR_Latin */ - -/* 'Greek': Script */ -static const OnigCodePoint CR_Greek[] = { - 36, - 0x0370, 0x0373, - 0x0375, 0x0377, - 0x037a, 0x037d, - 0x037f, 0x037f, - 0x0384, 0x0384, - 0x0386, 0x0386, - 0x0388, 0x038a, - 0x038c, 0x038c, - 0x038e, 0x03a1, - 0x03a3, 0x03e1, - 0x03f0, 0x03ff, - 0x1d26, 0x1d2a, - 0x1d5d, 0x1d61, - 0x1d66, 0x1d6a, - 0x1dbf, 0x1dbf, - 0x1f00, 0x1f15, - 0x1f18, 0x1f1d, - 0x1f20, 0x1f45, - 0x1f48, 0x1f4d, - 0x1f50, 0x1f57, - 0x1f59, 0x1f59, - 0x1f5b, 0x1f5b, - 0x1f5d, 0x1f5d, - 0x1f5f, 0x1f7d, - 0x1f80, 0x1fb4, - 0x1fb6, 0x1fc4, - 0x1fc6, 0x1fd3, - 0x1fd6, 0x1fdb, - 0x1fdd, 0x1fef, - 0x1ff2, 0x1ff4, - 0x1ff6, 0x1ffe, - 0x2126, 0x2126, - 0xab65, 0xab65, - 0x10140, 0x1018e, - 0x101a0, 0x101a0, - 0x1d200, 0x1d245, -}; /* CR_Greek */ +/* 'InCB_Linker': Derived Property */ +static const OnigCodePoint CR_InCB_Linker[] = { + 6, + 0x094d, 0x094d, + 0x09cd, 0x09cd, + 0x0acd, 0x0acd, + 0x0b4d, 0x0b4d, + 0x0c4d, 0x0c4d, + 0x0d4d, 0x0d4d, +}; /* CR_InCB_Linker */ + +/* 'InCB_Consonant': Derived Property */ +static const OnigCodePoint CR_InCB_Consonant[] = { + 26, + 0x0915, 0x0939, + 0x0958, 0x095f, + 0x0978, 0x097f, + 0x0995, 0x09a8, + 0x09aa, 0x09b0, + 0x09b2, 0x09b2, + 0x09b6, 0x09b9, + 0x09dc, 0x09dd, + 0x09df, 0x09df, + 0x09f0, 0x09f1, + 0x0a95, 0x0aa8, + 0x0aaa, 0x0ab0, + 0x0ab2, 0x0ab3, + 0x0ab5, 0x0ab9, + 0x0af9, 0x0af9, + 0x0b15, 0x0b28, + 0x0b2a, 0x0b30, + 0x0b32, 0x0b33, + 0x0b35, 0x0b39, + 0x0b5c, 0x0b5d, + 0x0b5f, 0x0b5f, + 0x0b71, 0x0b71, + 0x0c15, 0x0c28, + 0x0c2a, 0x0c39, + 0x0c58, 0x0c5a, + 0x0d15, 0x0d3a, +}; /* CR_InCB_Consonant */ -/* 'Cyrillic': Script */ -static const OnigCodePoint CR_Cyrillic[] = { - 10, - 0x0400, 0x0484, - 0x0487, 0x052f, - 0x1c80, 0x1c88, - 0x1d2b, 0x1d2b, - 0x1d78, 0x1d78, +/* 'InCB_Extend': Derived Property */ +static const OnigCodePoint CR_InCB_Extend[] = { + 371, + 0x0300, 0x036f, + 0x0483, 0x0489, + 0x0591, 0x05bd, + 0x05bf, 0x05bf, + 0x05c1, 0x05c2, + 0x05c4, 0x05c5, + 0x05c7, 0x05c7, + 0x0610, 0x061a, + 0x064b, 0x065f, + 0x0670, 0x0670, + 0x06d6, 0x06dc, + 0x06df, 0x06e4, + 0x06e7, 0x06e8, + 0x06ea, 0x06ed, + 0x0711, 0x0711, + 0x0730, 0x074a, + 0x07a6, 0x07b0, + 0x07eb, 0x07f3, + 0x07fd, 0x07fd, + 0x0816, 0x0819, + 0x081b, 0x0823, + 0x0825, 0x0827, + 0x0829, 0x082d, + 0x0859, 0x085b, + 0x0897, 0x089f, + 0x08ca, 0x08e1, + 0x08e3, 0x0902, + 0x093a, 0x093a, + 0x093c, 0x093c, + 0x0941, 0x0948, + 0x0951, 0x0957, + 0x0962, 0x0963, + 0x0981, 0x0981, + 0x09bc, 0x09bc, + 0x09be, 0x09be, + 0x09c1, 0x09c4, + 0x09d7, 0x09d7, + 0x09e2, 0x09e3, + 0x09fe, 0x09fe, + 0x0a01, 0x0a02, + 0x0a3c, 0x0a3c, + 0x0a41, 0x0a42, + 0x0a47, 0x0a48, + 0x0a4b, 0x0a4d, + 0x0a51, 0x0a51, + 0x0a70, 0x0a71, + 0x0a75, 0x0a75, + 0x0a81, 0x0a82, + 0x0abc, 0x0abc, + 0x0ac1, 0x0ac5, + 0x0ac7, 0x0ac8, + 0x0ae2, 0x0ae3, + 0x0afa, 0x0aff, + 0x0b01, 0x0b01, + 0x0b3c, 0x0b3c, + 0x0b3e, 0x0b3f, + 0x0b41, 0x0b44, + 0x0b55, 0x0b57, + 0x0b62, 0x0b63, + 0x0b82, 0x0b82, + 0x0bbe, 0x0bbe, + 0x0bc0, 0x0bc0, + 0x0bcd, 0x0bcd, + 0x0bd7, 0x0bd7, + 0x0c00, 0x0c00, + 0x0c04, 0x0c04, + 0x0c3c, 0x0c3c, + 0x0c3e, 0x0c40, + 0x0c46, 0x0c48, + 0x0c4a, 0x0c4c, + 0x0c55, 0x0c56, + 0x0c62, 0x0c63, + 0x0c81, 0x0c81, + 0x0cbc, 0x0cbc, + 0x0cbf, 0x0cc0, + 0x0cc2, 0x0cc2, + 0x0cc6, 0x0cc8, + 0x0cca, 0x0ccd, + 0x0cd5, 0x0cd6, + 0x0ce2, 0x0ce3, + 0x0d00, 0x0d01, + 0x0d3b, 0x0d3c, + 0x0d3e, 0x0d3e, + 0x0d41, 0x0d44, + 0x0d57, 0x0d57, + 0x0d62, 0x0d63, + 0x0d81, 0x0d81, + 0x0dca, 0x0dca, + 0x0dcf, 0x0dcf, + 0x0dd2, 0x0dd4, + 0x0dd6, 0x0dd6, + 0x0ddf, 0x0ddf, + 0x0e31, 0x0e31, + 0x0e34, 0x0e3a, + 0x0e47, 0x0e4e, + 0x0eb1, 0x0eb1, + 0x0eb4, 0x0ebc, + 0x0ec8, 0x0ece, + 0x0f18, 0x0f19, + 0x0f35, 0x0f35, + 0x0f37, 0x0f37, + 0x0f39, 0x0f39, + 0x0f71, 0x0f7e, + 0x0f80, 0x0f84, + 0x0f86, 0x0f87, + 0x0f8d, 0x0f97, + 0x0f99, 0x0fbc, + 0x0fc6, 0x0fc6, + 0x102d, 0x1030, + 0x1032, 0x1037, + 0x1039, 0x103a, + 0x103d, 0x103e, + 0x1058, 0x1059, + 0x105e, 0x1060, + 0x1071, 0x1074, + 0x1082, 0x1082, + 0x1085, 0x1086, + 0x108d, 0x108d, + 0x109d, 0x109d, + 0x135d, 0x135f, + 0x1712, 0x1715, + 0x1732, 0x1734, + 0x1752, 0x1753, + 0x1772, 0x1773, + 0x17b4, 0x17b5, + 0x17b7, 0x17bd, + 0x17c6, 0x17c6, + 0x17c9, 0x17d3, + 0x17dd, 0x17dd, + 0x180b, 0x180d, + 0x180f, 0x180f, + 0x1885, 0x1886, + 0x18a9, 0x18a9, + 0x1920, 0x1922, + 0x1927, 0x1928, + 0x1932, 0x1932, + 0x1939, 0x193b, + 0x1a17, 0x1a18, + 0x1a1b, 0x1a1b, + 0x1a56, 0x1a56, + 0x1a58, 0x1a5e, + 0x1a60, 0x1a60, + 0x1a62, 0x1a62, + 0x1a65, 0x1a6c, + 0x1a73, 0x1a7c, + 0x1a7f, 0x1a7f, + 0x1ab0, 0x1ace, + 0x1b00, 0x1b03, + 0x1b34, 0x1b3d, + 0x1b42, 0x1b44, + 0x1b6b, 0x1b73, + 0x1b80, 0x1b81, + 0x1ba2, 0x1ba5, + 0x1ba8, 0x1bad, + 0x1be6, 0x1be6, + 0x1be8, 0x1be9, + 0x1bed, 0x1bed, + 0x1bef, 0x1bf3, + 0x1c2c, 0x1c33, + 0x1c36, 0x1c37, + 0x1cd0, 0x1cd2, + 0x1cd4, 0x1ce0, + 0x1ce2, 0x1ce8, + 0x1ced, 0x1ced, + 0x1cf4, 0x1cf4, + 0x1cf8, 0x1cf9, + 0x1dc0, 0x1dff, + 0x200d, 0x200d, + 0x20d0, 0x20f0, + 0x2cef, 0x2cf1, + 0x2d7f, 0x2d7f, + 0x2de0, 0x2dff, + 0x302a, 0x302f, + 0x3099, 0x309a, + 0xa66f, 0xa672, + 0xa674, 0xa67d, + 0xa69e, 0xa69f, + 0xa6f0, 0xa6f1, + 0xa802, 0xa802, + 0xa806, 0xa806, + 0xa80b, 0xa80b, + 0xa825, 0xa826, + 0xa82c, 0xa82c, + 0xa8c4, 0xa8c5, + 0xa8e0, 0xa8f1, + 0xa8ff, 0xa8ff, + 0xa926, 0xa92d, + 0xa947, 0xa951, + 0xa953, 0xa953, + 0xa980, 0xa982, + 0xa9b3, 0xa9b3, + 0xa9b6, 0xa9b9, + 0xa9bc, 0xa9bd, + 0xa9c0, 0xa9c0, + 0xa9e5, 0xa9e5, + 0xaa29, 0xaa2e, + 0xaa31, 0xaa32, + 0xaa35, 0xaa36, + 0xaa43, 0xaa43, + 0xaa4c, 0xaa4c, + 0xaa7c, 0xaa7c, + 0xaab0, 0xaab0, + 0xaab2, 0xaab4, + 0xaab7, 0xaab8, + 0xaabe, 0xaabf, + 0xaac1, 0xaac1, + 0xaaec, 0xaaed, + 0xaaf6, 0xaaf6, + 0xabe5, 0xabe5, + 0xabe8, 0xabe8, + 0xabed, 0xabed, + 0xfb1e, 0xfb1e, + 0xfe00, 0xfe0f, + 0xfe20, 0xfe2f, + 0xff9e, 0xff9f, + 0x101fd, 0x101fd, + 0x102e0, 0x102e0, + 0x10376, 0x1037a, + 0x10a01, 0x10a03, + 0x10a05, 0x10a06, + 0x10a0c, 0x10a0f, + 0x10a38, 0x10a3a, + 0x10a3f, 0x10a3f, + 0x10ae5, 0x10ae6, + 0x10d24, 0x10d27, + 0x10d69, 0x10d6d, + 0x10eab, 0x10eac, + 0x10efc, 0x10eff, + 0x10f46, 0x10f50, + 0x10f82, 0x10f85, + 0x11001, 0x11001, + 0x11038, 0x11046, + 0x11070, 0x11070, + 0x11073, 0x11074, + 0x1107f, 0x11081, + 0x110b3, 0x110b6, + 0x110b9, 0x110ba, + 0x110c2, 0x110c2, + 0x11100, 0x11102, + 0x11127, 0x1112b, + 0x1112d, 0x11134, + 0x11173, 0x11173, + 0x11180, 0x11181, + 0x111b6, 0x111be, + 0x111c0, 0x111c0, + 0x111c9, 0x111cc, + 0x111cf, 0x111cf, + 0x1122f, 0x11231, + 0x11234, 0x11237, + 0x1123e, 0x1123e, + 0x11241, 0x11241, + 0x112df, 0x112df, + 0x112e3, 0x112ea, + 0x11300, 0x11301, + 0x1133b, 0x1133c, + 0x1133e, 0x1133e, + 0x11340, 0x11340, + 0x1134d, 0x1134d, + 0x11357, 0x11357, + 0x11366, 0x1136c, + 0x11370, 0x11374, + 0x113b8, 0x113b8, + 0x113bb, 0x113c0, + 0x113c2, 0x113c2, + 0x113c5, 0x113c5, + 0x113c7, 0x113c9, + 0x113ce, 0x113d0, + 0x113d2, 0x113d2, + 0x113e1, 0x113e2, + 0x11438, 0x1143f, + 0x11442, 0x11444, + 0x11446, 0x11446, + 0x1145e, 0x1145e, + 0x114b0, 0x114b0, + 0x114b3, 0x114b8, + 0x114ba, 0x114ba, + 0x114bd, 0x114bd, + 0x114bf, 0x114c0, + 0x114c2, 0x114c3, + 0x115af, 0x115af, + 0x115b2, 0x115b5, + 0x115bc, 0x115bd, + 0x115bf, 0x115c0, + 0x115dc, 0x115dd, + 0x11633, 0x1163a, + 0x1163d, 0x1163d, + 0x1163f, 0x11640, + 0x116ab, 0x116ab, + 0x116ad, 0x116ad, + 0x116b0, 0x116b7, + 0x1171d, 0x1171d, + 0x1171f, 0x1171f, + 0x11722, 0x11725, + 0x11727, 0x1172b, + 0x1182f, 0x11837, + 0x11839, 0x1183a, + 0x11930, 0x11930, + 0x1193b, 0x1193e, + 0x11943, 0x11943, + 0x119d4, 0x119d7, + 0x119da, 0x119db, + 0x119e0, 0x119e0, + 0x11a01, 0x11a0a, + 0x11a33, 0x11a38, + 0x11a3b, 0x11a3e, + 0x11a47, 0x11a47, + 0x11a51, 0x11a56, + 0x11a59, 0x11a5b, + 0x11a8a, 0x11a96, + 0x11a98, 0x11a99, + 0x11c30, 0x11c36, + 0x11c38, 0x11c3d, + 0x11c3f, 0x11c3f, + 0x11c92, 0x11ca7, + 0x11caa, 0x11cb0, + 0x11cb2, 0x11cb3, + 0x11cb5, 0x11cb6, + 0x11d31, 0x11d36, + 0x11d3a, 0x11d3a, + 0x11d3c, 0x11d3d, + 0x11d3f, 0x11d45, + 0x11d47, 0x11d47, + 0x11d90, 0x11d91, + 0x11d95, 0x11d95, + 0x11d97, 0x11d97, + 0x11ef3, 0x11ef4, + 0x11f00, 0x11f01, + 0x11f36, 0x11f3a, + 0x11f40, 0x11f42, + 0x11f5a, 0x11f5a, + 0x13440, 0x13440, + 0x13447, 0x13455, + 0x1611e, 0x16129, + 0x1612d, 0x1612f, + 0x16af0, 0x16af4, + 0x16b30, 0x16b36, + 0x16f4f, 0x16f4f, + 0x16f8f, 0x16f92, + 0x16fe4, 0x16fe4, + 0x16ff0, 0x16ff1, + 0x1bc9d, 0x1bc9e, + 0x1cf00, 0x1cf2d, + 0x1cf30, 0x1cf46, + 0x1d165, 0x1d169, + 0x1d16d, 0x1d172, + 0x1d17b, 0x1d182, + 0x1d185, 0x1d18b, + 0x1d1aa, 0x1d1ad, + 0x1d242, 0x1d244, + 0x1da00, 0x1da36, + 0x1da3b, 0x1da6c, + 0x1da75, 0x1da75, + 0x1da84, 0x1da84, + 0x1da9b, 0x1da9f, + 0x1daa1, 0x1daaf, + 0x1e000, 0x1e006, + 0x1e008, 0x1e018, + 0x1e01b, 0x1e021, + 0x1e023, 0x1e024, + 0x1e026, 0x1e02a, + 0x1e08f, 0x1e08f, + 0x1e130, 0x1e136, + 0x1e2ae, 0x1e2ae, + 0x1e2ec, 0x1e2ef, + 0x1e4ec, 0x1e4ef, + 0x1e5ee, 0x1e5ef, + 0x1e8d0, 0x1e8d6, + 0x1e944, 0x1e94a, + 0x1f3fb, 0x1f3ff, + 0xe0020, 0xe007f, + 0xe0100, 0xe01ef, +}; /* CR_InCB_Extend */ + +/* 'Common': Script */ +static const OnigCodePoint CR_Common[] = { + 174, + 0x0000, 0x0040, + 0x005b, 0x0060, + 0x007b, 0x00a9, + 0x00ab, 0x00b9, + 0x00bb, 0x00bf, + 0x00d7, 0x00d7, + 0x00f7, 0x00f7, + 0x02b9, 0x02df, + 0x02e5, 0x02e9, + 0x02ec, 0x02ff, + 0x0374, 0x0374, + 0x037e, 0x037e, + 0x0385, 0x0385, + 0x0387, 0x0387, + 0x0605, 0x0605, + 0x060c, 0x060c, + 0x061b, 0x061b, + 0x061f, 0x061f, + 0x0640, 0x0640, + 0x06dd, 0x06dd, + 0x08e2, 0x08e2, + 0x0964, 0x0965, + 0x0e3f, 0x0e3f, + 0x0fd5, 0x0fd8, + 0x10fb, 0x10fb, + 0x16eb, 0x16ed, + 0x1735, 0x1736, + 0x1802, 0x1803, + 0x1805, 0x1805, + 0x1cd3, 0x1cd3, + 0x1ce1, 0x1ce1, + 0x1ce9, 0x1cec, + 0x1cee, 0x1cf3, + 0x1cf5, 0x1cf7, + 0x1cfa, 0x1cfa, + 0x2000, 0x200b, + 0x200e, 0x2064, + 0x2066, 0x2070, + 0x2074, 0x207e, + 0x2080, 0x208e, + 0x20a0, 0x20c0, + 0x2100, 0x2125, + 0x2127, 0x2129, + 0x212c, 0x2131, + 0x2133, 0x214d, + 0x214f, 0x215f, + 0x2189, 0x218b, + 0x2190, 0x2429, + 0x2440, 0x244a, + 0x2460, 0x27ff, + 0x2900, 0x2b73, + 0x2b76, 0x2b95, + 0x2b97, 0x2bff, + 0x2e00, 0x2e5d, + 0x2ff0, 0x3004, + 0x3006, 0x3006, + 0x3008, 0x3020, + 0x3030, 0x3037, + 0x303c, 0x303f, + 0x309b, 0x309c, + 0x30a0, 0x30a0, + 0x30fb, 0x30fc, + 0x3190, 0x319f, + 0x31c0, 0x31e5, + 0x31ef, 0x31ef, + 0x3220, 0x325f, + 0x327f, 0x32cf, + 0x32ff, 0x32ff, + 0x3358, 0x33ff, + 0x4dc0, 0x4dff, + 0xa700, 0xa721, + 0xa788, 0xa78a, + 0xa830, 0xa839, + 0xa92e, 0xa92e, + 0xa9cf, 0xa9cf, + 0xab5b, 0xab5b, + 0xab6a, 0xab6b, + 0xfd3e, 0xfd3f, + 0xfe10, 0xfe19, + 0xfe30, 0xfe52, + 0xfe54, 0xfe66, + 0xfe68, 0xfe6b, + 0xfeff, 0xfeff, + 0xff01, 0xff20, + 0xff3b, 0xff40, + 0xff5b, 0xff65, + 0xff70, 0xff70, + 0xff9e, 0xff9f, + 0xffe0, 0xffe6, + 0xffe8, 0xffee, + 0xfff9, 0xfffd, + 0x10100, 0x10102, + 0x10107, 0x10133, + 0x10137, 0x1013f, + 0x10190, 0x1019c, + 0x101d0, 0x101fc, + 0x102e1, 0x102fb, + 0x1bca0, 0x1bca3, + 0x1cc00, 0x1ccf9, + 0x1cd00, 0x1ceb3, + 0x1cf50, 0x1cfc3, + 0x1d000, 0x1d0f5, + 0x1d100, 0x1d126, + 0x1d129, 0x1d166, + 0x1d16a, 0x1d17a, + 0x1d183, 0x1d184, + 0x1d18c, 0x1d1a9, + 0x1d1ae, 0x1d1ea, + 0x1d2c0, 0x1d2d3, + 0x1d2e0, 0x1d2f3, + 0x1d300, 0x1d356, + 0x1d360, 0x1d378, + 0x1d400, 0x1d454, + 0x1d456, 0x1d49c, + 0x1d49e, 0x1d49f, + 0x1d4a2, 0x1d4a2, + 0x1d4a5, 0x1d4a6, + 0x1d4a9, 0x1d4ac, + 0x1d4ae, 0x1d4b9, + 0x1d4bb, 0x1d4bb, + 0x1d4bd, 0x1d4c3, + 0x1d4c5, 0x1d505, + 0x1d507, 0x1d50a, + 0x1d50d, 0x1d514, + 0x1d516, 0x1d51c, + 0x1d51e, 0x1d539, + 0x1d53b, 0x1d53e, + 0x1d540, 0x1d544, + 0x1d546, 0x1d546, + 0x1d54a, 0x1d550, + 0x1d552, 0x1d6a5, + 0x1d6a8, 0x1d7cb, + 0x1d7ce, 0x1d7ff, + 0x1ec71, 0x1ecb4, + 0x1ed01, 0x1ed3d, + 0x1f000, 0x1f02b, + 0x1f030, 0x1f093, + 0x1f0a0, 0x1f0ae, + 0x1f0b1, 0x1f0bf, + 0x1f0c1, 0x1f0cf, + 0x1f0d1, 0x1f0f5, + 0x1f100, 0x1f1ad, + 0x1f1e6, 0x1f1ff, + 0x1f201, 0x1f202, + 0x1f210, 0x1f23b, + 0x1f240, 0x1f248, + 0x1f250, 0x1f251, + 0x1f260, 0x1f265, + 0x1f300, 0x1f6d7, + 0x1f6dc, 0x1f6ec, + 0x1f6f0, 0x1f6fc, + 0x1f700, 0x1f776, + 0x1f77b, 0x1f7d9, + 0x1f7e0, 0x1f7eb, + 0x1f7f0, 0x1f7f0, + 0x1f800, 0x1f80b, + 0x1f810, 0x1f847, + 0x1f850, 0x1f859, + 0x1f860, 0x1f887, + 0x1f890, 0x1f8ad, + 0x1f8b0, 0x1f8bb, + 0x1f8c0, 0x1f8c1, + 0x1f900, 0x1fa53, + 0x1fa60, 0x1fa6d, + 0x1fa70, 0x1fa7c, + 0x1fa80, 0x1fa89, + 0x1fa8f, 0x1fac6, + 0x1face, 0x1fadc, + 0x1fadf, 0x1fae9, + 0x1faf0, 0x1faf8, + 0x1fb00, 0x1fb92, + 0x1fb94, 0x1fbf9, + 0xe0001, 0xe0001, + 0xe0020, 0xe007f, +}; /* CR_Common */ + +/* 'Latin': Script */ +static const OnigCodePoint CR_Latin[] = { + 39, + 0x0041, 0x005a, + 0x0061, 0x007a, + 0x00aa, 0x00aa, + 0x00ba, 0x00ba, + 0x00c0, 0x00d6, + 0x00d8, 0x00f6, + 0x00f8, 0x02b8, + 0x02e0, 0x02e4, + 0x1d00, 0x1d25, + 0x1d2c, 0x1d5c, + 0x1d62, 0x1d65, + 0x1d6b, 0x1d77, + 0x1d79, 0x1dbe, + 0x1e00, 0x1eff, + 0x2071, 0x2071, + 0x207f, 0x207f, + 0x2090, 0x209c, + 0x212a, 0x212b, + 0x2132, 0x2132, + 0x214e, 0x214e, + 0x2160, 0x2188, + 0x2c60, 0x2c7f, + 0xa722, 0xa787, + 0xa78b, 0xa7cd, + 0xa7d0, 0xa7d1, + 0xa7d3, 0xa7d3, + 0xa7d5, 0xa7dc, + 0xa7f2, 0xa7ff, + 0xab30, 0xab5a, + 0xab5c, 0xab64, + 0xab66, 0xab69, + 0xfb00, 0xfb06, + 0xff21, 0xff3a, + 0xff41, 0xff5a, + 0x10780, 0x10785, + 0x10787, 0x107b0, + 0x107b2, 0x107ba, + 0x1df00, 0x1df1e, + 0x1df25, 0x1df2a, +}; /* CR_Latin */ + +/* 'Greek': Script */ +static const OnigCodePoint CR_Greek[] = { + 36, + 0x0370, 0x0373, + 0x0375, 0x0377, + 0x037a, 0x037d, + 0x037f, 0x037f, + 0x0384, 0x0384, + 0x0386, 0x0386, + 0x0388, 0x038a, + 0x038c, 0x038c, + 0x038e, 0x03a1, + 0x03a3, 0x03e1, + 0x03f0, 0x03ff, + 0x1d26, 0x1d2a, + 0x1d5d, 0x1d61, + 0x1d66, 0x1d6a, + 0x1dbf, 0x1dbf, + 0x1f00, 0x1f15, + 0x1f18, 0x1f1d, + 0x1f20, 0x1f45, + 0x1f48, 0x1f4d, + 0x1f50, 0x1f57, + 0x1f59, 0x1f59, + 0x1f5b, 0x1f5b, + 0x1f5d, 0x1f5d, + 0x1f5f, 0x1f7d, + 0x1f80, 0x1fb4, + 0x1fb6, 0x1fc4, + 0x1fc6, 0x1fd3, + 0x1fd6, 0x1fdb, + 0x1fdd, 0x1fef, + 0x1ff2, 0x1ff4, + 0x1ff6, 0x1ffe, + 0x2126, 0x2126, + 0xab65, 0xab65, + 0x10140, 0x1018e, + 0x101a0, 0x101a0, + 0x1d200, 0x1d245, +}; /* CR_Greek */ + +/* 'Cyrillic': Script */ +static const OnigCodePoint CR_Cyrillic[] = { + 10, + 0x0400, 0x0484, + 0x0487, 0x052f, + 0x1c80, 0x1c8a, + 0x1d2b, 0x1d2b, + 0x1d78, 0x1d78, 0x2de0, 0x2dff, 0xa640, 0xa69f, 0xfe2e, 0xfe2f, @@ -20561,7 +21467,7 @@ static const OnigCodePoint CR_Hebrew[] = { /* 'Arabic': Script */ static const OnigCodePoint CR_Arabic[] = { - 58, + 59, 0x0600, 0x0604, 0x0606, 0x060b, 0x060d, 0x061a, @@ -20574,7 +21480,7 @@ static const OnigCodePoint CR_Arabic[] = { 0x0750, 0x077f, 0x0870, 0x088e, 0x0890, 0x0891, - 0x0898, 0x08e1, + 0x0897, 0x08e1, 0x08e3, 0x08ff, 0xfb50, 0xfbc2, 0xfbd3, 0xfd3d, @@ -20585,7 +21491,8 @@ static const OnigCodePoint CR_Arabic[] = { 0xfe70, 0xfe74, 0xfe76, 0xfefc, 0x10e60, 0x10e7e, - 0x10efd, 0x10eff, + 0x10ec2, 0x10ec4, + 0x10efc, 0x10eff, 0x1ee00, 0x1ee03, 0x1ee05, 0x1ee1f, 0x1ee21, 0x1ee22, @@ -20851,10 +21758,11 @@ static const OnigCodePoint CR_Tibetan[] = { /* 'Myanmar': Script */ static const OnigCodePoint CR_Myanmar[] = { - 3, + 4, 0x1000, 0x109f, 0xa9e0, 0xa9fe, 0xaa60, 0xaa7f, + 0x116d0, 0x116e3, }; /* CR_Myanmar */ /* 'Georgian': Script */ @@ -21021,7 +21929,7 @@ static const OnigCodePoint CR_Bopomofo[] = { /* 'Han': Script */ static const OnigCodePoint CR_Han[] = { - 21, + 22, 0x2e80, 0x2e99, 0x2e9b, 0x2ef3, 0x2f00, 0x2fd5, @@ -21040,6 +21948,7 @@ static const OnigCodePoint CR_Han[] = { 0x2b740, 0x2b81d, 0x2b820, 0x2cea1, 0x2ceb0, 0x2ebe0, + 0x2ebf0, 0x2ee5d, 0x2f800, 0x2fa1d, 0x30000, 0x3134a, 0x31350, 0x323af, @@ -21271,7 +22180,7 @@ static const OnigCodePoint CR_Kharoshthi[] = { static const OnigCodePoint CR_Balinese[] = { 2, 0x1b00, 0x1b4c, - 0x1b50, 0x1b7e, + 0x1b4e, 0x1b7f, }; /* CR_Balinese */ /* 'Cuneiform': Script */ @@ -21405,8 +22314,9 @@ static const OnigCodePoint CR_Avestan[] = { /* 'Egyptian_Hieroglyphs': Script */ static const OnigCodePoint CR_Egyptian_Hieroglyphs[] = { - 1, + 2, 0x13000, 0x13455, + 0x13460, 0x143fa, }; /* CR_Egyptian_Hieroglyphs */ /* 'Samaritan': Script */ @@ -21960,9 +22870,10 @@ static const OnigCodePoint CR_Dives_Akuru[] = { /* 'Khitan_Small_Script': Script */ static const OnigCodePoint CR_Khitan_Small_Script[] = { - 2, + 3, 0x16fe4, 0x16fe4, 0x18b00, 0x18cd5, + 0x18cff, 0x18cff, }; /* CR_Khitan_Small_Script */ /* 'Yezidi': Script */ @@ -22016,7 +22927,7 @@ static const OnigCodePoint CR_Kawi[] = { 3, 0x11f00, 0x11f10, 0x11f12, 0x11f3a, - 0x11f3e, 0x11f59, + 0x11f3e, 0x11f5a, }; /* CR_Kawi */ /* 'Nag_Mundari': Script */ @@ -22025,6 +22936,62 @@ static const OnigCodePoint CR_Nag_Mundari[] = { 0x1e4d0, 0x1e4f9, }; /* CR_Nag_Mundari */ +/* 'Garay': Script */ +static const OnigCodePoint CR_Garay[] = { + 3, + 0x10d40, 0x10d65, + 0x10d69, 0x10d85, + 0x10d8e, 0x10d8f, +}; /* CR_Garay */ + +/* 'Gurung_Khema': Script */ +static const OnigCodePoint CR_Gurung_Khema[] = { + 1, + 0x16100, 0x16139, +}; /* CR_Gurung_Khema */ + +/* 'Kirat_Rai': Script */ +static const OnigCodePoint CR_Kirat_Rai[] = { + 1, + 0x16d40, 0x16d79, +}; /* CR_Kirat_Rai */ + +/* 'Ol_Onal': Script */ +static const OnigCodePoint CR_Ol_Onal[] = { + 2, + 0x1e5d0, 0x1e5fa, + 0x1e5ff, 0x1e5ff, +}; /* CR_Ol_Onal */ + +/* 'Sunuwar': Script */ +static const OnigCodePoint CR_Sunuwar[] = { + 2, + 0x11bc0, 0x11be1, + 0x11bf0, 0x11bf9, +}; /* CR_Sunuwar */ + +/* 'Todhri': Script */ +static const OnigCodePoint CR_Todhri[] = { + 1, + 0x105c0, 0x105f3, +}; /* CR_Todhri */ + +/* 'Tulu_Tigalari': Script */ +static const OnigCodePoint CR_Tulu_Tigalari[] = { + 11, + 0x11380, 0x11389, + 0x1138b, 0x1138b, + 0x1138e, 0x1138e, + 0x11390, 0x113b5, + 0x113b7, 0x113c0, + 0x113c2, 0x113c2, + 0x113c5, 0x113c5, + 0x113c7, 0x113ca, + 0x113cc, 0x113d5, + 0x113d7, 0x113d8, + 0x113e1, 0x113e2, +}; /* CR_Tulu_Tigalari */ + /* 'White_Space': Binary Property */ #define CR_White_Space CR_Space @@ -22045,7 +23012,7 @@ static const OnigCodePoint CR_Join_Control[] = { /* 'Dash': Binary Property */ static const OnigCodePoint CR_Dash[] = { - 23, + 24, 0x002d, 0x002d, 0x058a, 0x058a, 0x05be, 0x05be, @@ -22068,6 +23035,7 @@ static const OnigCodePoint CR_Dash[] = { 0xfe58, 0xfe58, 0xfe63, 0xfe63, 0xff0d, 0xff0d, + 0x10d6e, 0x10d6e, 0x10ead, 0x10ead, }; /* CR_Dash */ @@ -22106,7 +23074,7 @@ static const OnigCodePoint CR_Quotation_Mark[] = { /* 'Terminal_Punctuation': Binary Property */ static const OnigCodePoint CR_Terminal_Punctuation[] = { - 108, + 116, 0x0021, 0x0021, 0x002c, 0x002c, 0x002e, 0x002e, @@ -22123,7 +23091,8 @@ static const OnigCodePoint CR_Terminal_Punctuation[] = { 0x0700, 0x070a, 0x070c, 0x070c, 0x07f8, 0x07f9, - 0x0830, 0x083e, + 0x0830, 0x0835, + 0x0837, 0x083e, 0x085e, 0x085e, 0x0964, 0x0965, 0x0e5a, 0x0e5b, @@ -22140,13 +23109,16 @@ static const OnigCodePoint CR_Terminal_Punctuation[] = { 0x1808, 0x1809, 0x1944, 0x1945, 0x1aa8, 0x1aab, + 0x1b4e, 0x1b4f, 0x1b5a, 0x1b5b, 0x1b5d, 0x1b5f, - 0x1b7d, 0x1b7e, + 0x1b7d, 0x1b7f, 0x1c3b, 0x1c3f, 0x1c7e, 0x1c7f, + 0x2024, 0x2024, 0x203c, 0x203d, 0x2047, 0x2049, + 0x2cf9, 0x2cfb, 0x2e2e, 0x2e2e, 0x2e3c, 0x2e3c, 0x2e41, 0x2e41, @@ -22165,6 +23137,8 @@ static const OnigCodePoint CR_Terminal_Punctuation[] = { 0xaadf, 0xaadf, 0xaaf0, 0xaaf1, 0xabeb, 0xabeb, + 0xfe12, 0xfe12, + 0xfe15, 0xfe16, 0xfe50, 0xfe52, 0xfe54, 0xfe57, 0xff01, 0xff01, @@ -22192,6 +23166,7 @@ static const OnigCodePoint CR_Terminal_Punctuation[] = { 0x111de, 0x111df, 0x11238, 0x1123c, 0x112a9, 0x112a9, + 0x113d4, 0x113d5, 0x1144b, 0x1144d, 0x1145a, 0x1145b, 0x115c2, 0x115c5, @@ -22212,6 +23187,7 @@ static const OnigCodePoint CR_Terminal_Punctuation[] = { 0x16af5, 0x16af5, 0x16b37, 0x16b39, 0x16b44, 0x16b44, + 0x16d6e, 0x16d6f, 0x16e97, 0x16e98, 0x1bc9f, 0x1bc9f, 0x1da87, 0x1da8a, @@ -22372,8 +23348,9 @@ static const OnigCodePoint CR_Hex_Digit[] = { /* 'Other_Alphabetic': Binary Property */ static const OnigCodePoint CR_Other_Alphabetic[] = { - 240, + 250, 0x0345, 0x0345, + 0x0363, 0x036f, 0x05b0, 0x05bd, 0x05bf, 0x05bf, 0x05c1, 0x05c2, @@ -22394,6 +23371,7 @@ static const OnigCodePoint CR_Other_Alphabetic[] = { 0x081b, 0x0823, 0x0825, 0x0827, 0x0829, 0x082c, + 0x0897, 0x0897, 0x08d4, 0x08df, 0x08e3, 0x08e9, 0x08f0, 0x0903, @@ -22498,7 +23476,7 @@ static const OnigCodePoint CR_Other_Alphabetic[] = { 0x1bac, 0x1bad, 0x1be7, 0x1bf1, 0x1c24, 0x1c36, - 0x1de7, 0x1df4, + 0x1dd3, 0x1df4, 0x24b6, 0x24e9, 0x2de0, 0x2dff, 0xa674, 0xa67b, @@ -22532,7 +23510,9 @@ static const OnigCodePoint CR_Other_Alphabetic[] = { 0x10a05, 0x10a06, 0x10a0c, 0x10a0f, 0x10d24, 0x10d27, + 0x10d69, 0x10d69, 0x10eab, 0x10eac, + 0x10efc, 0x10efc, 0x11000, 0x11002, 0x11038, 0x11045, 0x11073, 0x11074, @@ -22556,6 +23536,11 @@ static const OnigCodePoint CR_Other_Alphabetic[] = { 0x1134b, 0x1134c, 0x11357, 0x11357, 0x11362, 0x11363, + 0x113b8, 0x113c0, + 0x113c2, 0x113c2, + 0x113c5, 0x113c5, + 0x113c7, 0x113ca, + 0x113cc, 0x113cd, 0x11435, 0x11441, 0x11443, 0x11445, 0x114b0, 0x114c1, @@ -22598,6 +23583,7 @@ static const OnigCodePoint CR_Other_Alphabetic[] = { 0x11f03, 0x11f03, 0x11f34, 0x11f3a, 0x11f3e, 0x11f40, + 0x1611e, 0x1612e, 0x16f4f, 0x16f4f, 0x16f51, 0x16f87, 0x16f8f, 0x16f92, @@ -22617,7 +23603,7 @@ static const OnigCodePoint CR_Other_Alphabetic[] = { /* 'Ideographic': Binary Property */ static const OnigCodePoint CR_Ideographic[] = { - 20, + 21, 0x3006, 0x3007, 0x3021, 0x3029, 0x3038, 0x303a, @@ -22628,13 +23614,14 @@ static const OnigCodePoint CR_Ideographic[] = { 0x16fe4, 0x16fe4, 0x17000, 0x187f7, 0x18800, 0x18cd5, - 0x18d00, 0x18d08, + 0x18cff, 0x18d08, 0x1b170, 0x1b2fb, 0x20000, 0x2a6df, 0x2a700, 0x2b739, 0x2b740, 0x2b81d, 0x2b820, 0x2cea1, 0x2ceb0, 0x2ebe0, + 0x2ebf0, 0x2ee5d, 0x2f800, 0x2fa1d, 0x30000, 0x3134a, 0x31350, 0x323af, @@ -22642,7 +23629,7 @@ static const OnigCodePoint CR_Ideographic[] = { /* 'Diacritic': Binary Property */ static const OnigCodePoint CR_Diacritic[] = { - 195, + 214, 0x005e, 0x005e, 0x0060, 0x0060, 0x00a8, 0x00a8, @@ -22696,6 +23683,7 @@ static const OnigCodePoint CR_Diacritic[] = { 0x0d3b, 0x0d3c, 0x0d4d, 0x0d4d, 0x0dca, 0x0dca, + 0x0e3a, 0x0e3a, 0x0e47, 0x0e4c, 0x0e4e, 0x0e4e, 0x0eba, 0x0eba, @@ -22717,9 +23705,11 @@ static const OnigCodePoint CR_Diacritic[] = { 0x109a, 0x109b, 0x135d, 0x135f, 0x1714, 0x1715, + 0x1734, 0x1734, 0x17c9, 0x17d3, 0x17dd, 0x17dd, 0x1939, 0x193b, + 0x1a60, 0x1a60, 0x1a75, 0x1a7c, 0x1a7f, 0x1a7f, 0x1ab0, 0x1abe, @@ -22728,6 +23718,8 @@ static const OnigCodePoint CR_Diacritic[] = { 0x1b44, 0x1b44, 0x1b6b, 0x1b73, 0x1baa, 0x1bab, + 0x1be6, 0x1be6, + 0x1bf2, 0x1bf3, 0x1c36, 0x1c37, 0x1c78, 0x1c7d, 0x1cd0, 0x1ce8, @@ -22756,6 +23748,8 @@ static const OnigCodePoint CR_Diacritic[] = { 0xa700, 0xa721, 0xa788, 0xa78a, 0xa7f8, 0xa7f9, + 0xa806, 0xa806, + 0xa82c, 0xa82c, 0xa8c4, 0xa8c4, 0xa8e0, 0xa8f1, 0xa92b, 0xa92e, @@ -22780,8 +23774,12 @@ static const OnigCodePoint CR_Diacritic[] = { 0x10780, 0x10785, 0x10787, 0x107b0, 0x107b2, 0x107ba, + 0x10a38, 0x10a3a, + 0x10a3f, 0x10a3f, 0x10ae5, 0x10ae6, 0x10d22, 0x10d27, + 0x10d4e, 0x10d4e, + 0x10d69, 0x10d6d, 0x10efd, 0x10eff, 0x10f46, 0x10f50, 0x10f82, 0x10f85, @@ -22794,10 +23792,13 @@ static const OnigCodePoint CR_Diacritic[] = { 0x111ca, 0x111cc, 0x11235, 0x11236, 0x112e9, 0x112ea, - 0x1133c, 0x1133c, + 0x1133b, 0x1133c, 0x1134d, 0x1134d, 0x11366, 0x1136c, 0x11370, 0x11374, + 0x113ce, 0x113d0, + 0x113d2, 0x113d3, + 0x113e1, 0x113e2, 0x11442, 0x11442, 0x11446, 0x11446, 0x114c2, 0x114c3, @@ -22816,9 +23817,13 @@ static const OnigCodePoint CR_Diacritic[] = { 0x11d42, 0x11d42, 0x11d44, 0x11d45, 0x11d97, 0x11d97, + 0x11f41, 0x11f42, + 0x11f5a, 0x11f5a, 0x13447, 0x13455, + 0x1612f, 0x1612f, 0x16af0, 0x16af4, 0x16b30, 0x16b36, + 0x16d6b, 0x16d6c, 0x16f8f, 0x16f9f, 0x16ff0, 0x16ff1, 0x1aff0, 0x1aff3, @@ -22835,6 +23840,7 @@ static const OnigCodePoint CR_Diacritic[] = { 0x1e130, 0x1e136, 0x1e2ae, 0x1e2ae, 0x1e2ec, 0x1e2ef, + 0x1e5ee, 0x1e5ef, 0x1e8d0, 0x1e8d6, 0x1e944, 0x1e946, 0x1e948, 0x1e94a, @@ -22842,11 +23848,13 @@ static const OnigCodePoint CR_Diacritic[] = { /* 'Extender': Binary Property */ static const OnigCodePoint CR_Extender[] = { - 33, + 41, 0x00b7, 0x00b7, 0x02d0, 0x02d1, 0x0640, 0x0640, 0x07fa, 0x07fa, + 0x0a71, 0x0a71, + 0x0afb, 0x0afb, 0x0b55, 0x0b55, 0x0e46, 0x0e46, 0x0ec6, 0x0ec6, @@ -22868,13 +23876,19 @@ static const OnigCodePoint CR_Extender[] = { 0xaaf3, 0xaaf4, 0xff70, 0xff70, 0x10781, 0x10782, + 0x10d4e, 0x10d4e, + 0x10d6a, 0x10d6a, + 0x10d6f, 0x10d6f, + 0x11237, 0x11237, 0x1135d, 0x1135d, + 0x113d2, 0x113d3, 0x115c6, 0x115c8, 0x11a98, 0x11a98, 0x16b42, 0x16b43, 0x16fe0, 0x16fe1, 0x16fe3, 0x16fe3, 0x1e13c, 0x1e13d, + 0x1e5ef, 0x1e5ef, 0x1e944, 0x1e946, }; /* CR_Extender */ @@ -22946,39 +23960,64 @@ static const OnigCodePoint CR_Noncharacter_Code_Point[] = { /* 'Other_Grapheme_Extend': Binary Property */ static const OnigCodePoint CR_Other_Grapheme_Extend[] = { - 25, + 49, 0x09be, 0x09be, 0x09d7, 0x09d7, 0x0b3e, 0x0b3e, 0x0b57, 0x0b57, 0x0bbe, 0x0bbe, 0x0bd7, 0x0bd7, + 0x0cc0, 0x0cc0, 0x0cc2, 0x0cc2, + 0x0cc7, 0x0cc8, + 0x0cca, 0x0ccb, 0x0cd5, 0x0cd6, 0x0d3e, 0x0d3e, 0x0d57, 0x0d57, 0x0dcf, 0x0dcf, 0x0ddf, 0x0ddf, + 0x1715, 0x1715, + 0x1734, 0x1734, 0x1b35, 0x1b35, + 0x1b3b, 0x1b3b, + 0x1b3d, 0x1b3d, + 0x1b43, 0x1b44, + 0x1baa, 0x1baa, + 0x1bf2, 0x1bf3, 0x200c, 0x200c, 0x302e, 0x302f, + 0xa953, 0xa953, + 0xa9c0, 0xa9c0, 0xff9e, 0xff9f, + 0x111c0, 0x111c0, + 0x11235, 0x11235, 0x1133e, 0x1133e, + 0x1134d, 0x1134d, 0x11357, 0x11357, + 0x113b8, 0x113b8, + 0x113c2, 0x113c2, + 0x113c5, 0x113c5, + 0x113c7, 0x113c9, + 0x113cf, 0x113cf, 0x114b0, 0x114b0, 0x114bd, 0x114bd, 0x115af, 0x115af, + 0x116b6, 0x116b6, 0x11930, 0x11930, - 0x1d165, 0x1d165, - 0x1d16e, 0x1d172, + 0x1193d, 0x1193d, + 0x11f41, 0x11f41, + 0x16ff0, 0x16ff1, + 0x1d165, 0x1d166, + 0x1d16d, 0x1d172, 0xe0020, 0xe007f, }; /* CR_Other_Grapheme_Extend */ /* 'IDS_Binary_Operator': Binary Property */ static const OnigCodePoint CR_IDS_Binary_Operator[] = { - 2, + 3, 0x2ff0, 0x2ff1, - 0x2ff4, 0x2ffb, + 0x2ff4, 0x2ffd, + 0x31ef, 0x31ef, }; /* CR_IDS_Binary_Operator */ /* 'IDS_Trinary_Operator': Binary Property */ @@ -22987,6 +24026,12 @@ static const OnigCodePoint CR_IDS_Trinary_Operator[] = { 0x2ff2, 0x2ff3, }; /* CR_IDS_Trinary_Operator */ +/* 'IDS_Unary_Operator': Binary Property */ +static const OnigCodePoint CR_IDS_Unary_Operator[] = { + 1, + 0x2ffe, 0x2fff, +}; /* CR_IDS_Unary_Operator */ + /* 'Radical': Binary Property */ static const OnigCodePoint CR_Radical[] = { 3, @@ -22997,7 +24042,7 @@ static const OnigCodePoint CR_Radical[] = { /* 'Unified_Ideograph': Binary Property */ static const OnigCodePoint CR_Unified_Ideograph[] = { - 16, + 17, 0x3400, 0x4dbf, 0x4e00, 0x9fff, 0xfa0e, 0xfa0f, @@ -23012,6 +24057,7 @@ static const OnigCodePoint CR_Unified_Ideograph[] = { 0x2b740, 0x2b81d, 0x2b820, 0x2cea1, 0x2ceb0, 0x2ebe0, + 0x2ebf0, 0x2ee5d, 0x30000, 0x3134a, 0x31350, 0x323af, }; /* CR_Unified_Ideograph */ @@ -23107,16 +24153,60 @@ static const OnigCodePoint CR_Other_ID_Start[] = { /* 'Other_ID_Continue': Binary Property */ static const OnigCodePoint CR_Other_ID_Continue[] = { - 4, + 7, 0x00b7, 0x00b7, 0x0387, 0x0387, 0x1369, 0x1371, 0x19da, 0x19da, + 0x200c, 0x200d, + 0x30fb, 0x30fb, + 0xff65, 0xff65, }; /* CR_Other_ID_Continue */ +/* 'ID_Compat_Math_Continue': Binary Property */ +static const OnigCodePoint CR_ID_Compat_Math_Continue[] = { + 18, + 0x00b2, 0x00b3, + 0x00b9, 0x00b9, + 0x2070, 0x2070, + 0x2074, 0x207e, + 0x2080, 0x208e, + 0x2202, 0x2202, + 0x2207, 0x2207, + 0x221e, 0x221e, + 0x1d6c1, 0x1d6c1, + 0x1d6db, 0x1d6db, + 0x1d6fb, 0x1d6fb, + 0x1d715, 0x1d715, + 0x1d735, 0x1d735, + 0x1d74f, 0x1d74f, + 0x1d76f, 0x1d76f, + 0x1d789, 0x1d789, + 0x1d7a9, 0x1d7a9, + 0x1d7c3, 0x1d7c3, +}; /* CR_ID_Compat_Math_Continue */ + +/* 'ID_Compat_Math_Start': Binary Property */ +static const OnigCodePoint CR_ID_Compat_Math_Start[] = { + 13, + 0x2202, 0x2202, + 0x2207, 0x2207, + 0x221e, 0x221e, + 0x1d6c1, 0x1d6c1, + 0x1d6db, 0x1d6db, + 0x1d6fb, 0x1d6fb, + 0x1d715, 0x1d715, + 0x1d735, 0x1d735, + 0x1d74f, 0x1d74f, + 0x1d76f, 0x1d76f, + 0x1d789, 0x1d789, + 0x1d7a9, 0x1d7a9, + 0x1d7c3, 0x1d7c3, +}; /* CR_ID_Compat_Math_Start */ + /* 'Sentence_Terminal': Binary Property */ static const OnigCodePoint CR_Sentence_Terminal[] = { - 80, + 88, 0x0021, 0x0021, 0x002e, 0x002e, 0x003f, 0x003f, @@ -23134,17 +24224,21 @@ static const OnigCodePoint CR_Sentence_Terminal[] = { 0x1367, 0x1368, 0x166e, 0x166e, 0x1735, 0x1736, + 0x17d4, 0x17d5, 0x1803, 0x1803, 0x1809, 0x1809, 0x1944, 0x1945, 0x1aa8, 0x1aab, + 0x1b4e, 0x1b4f, 0x1b5a, 0x1b5b, 0x1b5e, 0x1b5f, - 0x1b7d, 0x1b7e, + 0x1b7d, 0x1b7f, 0x1c3b, 0x1c3c, 0x1c7e, 0x1c7f, + 0x2024, 0x2024, 0x203c, 0x203d, 0x2047, 0x2049, + 0x2cf9, 0x2cfb, 0x2e2e, 0x2e2e, 0x2e3c, 0x2e3c, 0x2e53, 0x2e54, @@ -23160,6 +24254,8 @@ static const OnigCodePoint CR_Sentence_Terminal[] = { 0xaa5d, 0xaa5f, 0xaaf0, 0xaaf1, 0xabeb, 0xabeb, + 0xfe12, 0xfe12, + 0xfe15, 0xfe16, 0xfe52, 0xfe52, 0xfe56, 0xfe57, 0xff01, 0xff01, @@ -23178,6 +24274,7 @@ static const OnigCodePoint CR_Sentence_Terminal[] = { 0x11238, 0x11239, 0x1123b, 0x1123c, 0x112a9, 0x112a9, + 0x113d4, 0x113d5, 0x1144b, 0x1144c, 0x115c2, 0x115c3, 0x115c9, 0x115d7, @@ -23194,6 +24291,7 @@ static const OnigCodePoint CR_Sentence_Terminal[] = { 0x16af5, 0x16af5, 0x16b37, 0x16b38, 0x16b44, 0x16b44, + 0x16d6e, 0x16d6f, 0x16e98, 0x16e98, 0x1bc9f, 0x1bc9f, 0x1da88, 0x1da88, @@ -23269,9 +24367,23 @@ static const OnigCodePoint CR_Regional_Indicator[] = { 0x1f1e6, 0x1f1ff, }; /* CR_Regional_Indicator */ +/* 'Modifier_Combining_Mark': Binary Property */ +static const OnigCodePoint CR_Modifier_Combining_Mark[] = { + 9, + 0x0654, 0x0655, + 0x0658, 0x0658, + 0x06dc, 0x06dc, + 0x06e3, 0x06e3, + 0x06e7, 0x06e8, + 0x08ca, 0x08cb, + 0x08cd, 0x08cf, + 0x08d3, 0x08d3, + 0x08f3, 0x08f3, +}; /* CR_Modifier_Combining_Mark */ + /* 'Emoji': Emoji */ static const OnigCodePoint CR_Emoji[] = { - 151, + 150, 0x0023, 0x0023, 0x002a, 0x002a, 0x0030, 0x0039, @@ -23417,17 +24529,16 @@ static const OnigCodePoint CR_Emoji[] = { 0x1f93c, 0x1f945, 0x1f947, 0x1f9ff, 0x1fa70, 0x1fa7c, - 0x1fa80, 0x1fa88, - 0x1fa90, 0x1fabd, - 0x1fabf, 0x1fac5, - 0x1face, 0x1fadb, - 0x1fae0, 0x1fae8, + 0x1fa80, 0x1fa89, + 0x1fa8f, 0x1fac6, + 0x1face, 0x1fadc, + 0x1fadf, 0x1fae9, 0x1faf0, 0x1faf8, }; /* CR_Emoji */ /* 'Emoji_Presentation': Emoji */ static const OnigCodePoint CR_Emoji_Presentation[] = { - 81, + 80, 0x231a, 0x231b, 0x23e9, 0x23ec, 0x23f0, 0x23f0, @@ -23503,11 +24614,10 @@ static const OnigCodePoint CR_Emoji_Presentation[] = { 0x1f93c, 0x1f945, 0x1f947, 0x1f9ff, 0x1fa70, 0x1fa7c, - 0x1fa80, 0x1fa88, - 0x1fa90, 0x1fabd, - 0x1fabf, 0x1fac5, - 0x1face, 0x1fadb, - 0x1fae0, 0x1fae8, + 0x1fa80, 0x1fa89, + 0x1fa8f, 0x1fac6, + 0x1face, 0x1fadc, + 0x1fadf, 0x1fae9, 0x1faf0, 0x1faf8, }; /* CR_Emoji_Presentation */ @@ -23662,7 +24772,7 @@ static const OnigCodePoint CR_Extended_Pictographic[] = { /* 'Unknown': Script */ static const OnigCodePoint CR_Unknown[] = { - 705, + 729, 0x0378, 0x0379, 0x0380, 0x0383, 0x038b, 0x038b, @@ -23685,7 +24795,7 @@ static const OnigCodePoint CR_Unknown[] = { 0x085f, 0x085f, 0x086b, 0x086f, 0x088f, 0x088f, - 0x0892, 0x0897, + 0x0892, 0x0896, 0x0984, 0x0984, 0x098d, 0x098e, 0x0991, 0x0992, @@ -23877,12 +24987,11 @@ static const OnigCodePoint CR_Unknown[] = { 0x1a9a, 0x1a9f, 0x1aae, 0x1aaf, 0x1acf, 0x1aff, - 0x1b4d, 0x1b4f, - 0x1b7f, 0x1b7f, + 0x1b4d, 0x1b4d, 0x1bf4, 0x1bfb, 0x1c38, 0x1c3a, 0x1c4a, 0x1c4c, - 0x1c89, 0x1c8f, + 0x1c8b, 0x1c8f, 0x1cbb, 0x1cbc, 0x1cc8, 0x1ccf, 0x1cfb, 0x1cff, @@ -23909,7 +25018,7 @@ static const OnigCodePoint CR_Unknown[] = { 0x20c1, 0x20cf, 0x20f1, 0x20ff, 0x218c, 0x218f, - 0x2427, 0x243f, + 0x242a, 0x243f, 0x244b, 0x245f, 0x2b74, 0x2b75, 0x2b96, 0x2b96, @@ -23932,22 +25041,21 @@ static const OnigCodePoint CR_Unknown[] = { 0x2e9a, 0x2e9a, 0x2ef4, 0x2eff, 0x2fd6, 0x2fef, - 0x2ffc, 0x2fff, 0x3040, 0x3040, 0x3097, 0x3098, 0x3100, 0x3104, 0x3130, 0x3130, 0x318f, 0x318f, - 0x31e4, 0x31ef, + 0x31e6, 0x31ee, 0x321f, 0x321f, 0xa48d, 0xa48f, 0xa4c7, 0xa4cf, 0xa62c, 0xa63f, 0xa6f8, 0xa6ff, - 0xa7cb, 0xa7cf, + 0xa7ce, 0xa7cf, 0xa7d2, 0xa7d2, 0xa7d4, 0xa7d4, - 0xa7da, 0xa7f1, + 0xa7dd, 0xa7f1, 0xa82d, 0xa82f, 0xa83a, 0xa83f, 0xa878, 0xa87f, @@ -24037,7 +25145,8 @@ static const OnigCodePoint CR_Unknown[] = { 0x105a2, 0x105a2, 0x105b2, 0x105b2, 0x105ba, 0x105ba, - 0x105bd, 0x105ff, + 0x105bd, 0x105bf, + 0x105f4, 0x105ff, 0x10737, 0x1073f, 0x10756, 0x1075f, 0x10768, 0x1077f, @@ -24080,11 +25189,15 @@ static const OnigCodePoint CR_Unknown[] = { 0x10cb3, 0x10cbf, 0x10cf3, 0x10cf9, 0x10d28, 0x10d2f, - 0x10d3a, 0x10e5f, + 0x10d3a, 0x10d3f, + 0x10d66, 0x10d68, + 0x10d86, 0x10d8d, + 0x10d90, 0x10e5f, 0x10e7f, 0x10e7f, 0x10eaa, 0x10eaa, 0x10eae, 0x10eaf, - 0x10eb2, 0x10efc, + 0x10eb2, 0x10ec1, + 0x10ec5, 0x10efb, 0x10f28, 0x10f2f, 0x10f5a, 0x10f6f, 0x10f8a, 0x10faf, @@ -24124,7 +25237,18 @@ static const OnigCodePoint CR_Unknown[] = { 0x11358, 0x1135c, 0x11364, 0x11365, 0x1136d, 0x1136f, - 0x11375, 0x113ff, + 0x11375, 0x1137f, + 0x1138a, 0x1138a, + 0x1138c, 0x1138d, + 0x1138f, 0x1138f, + 0x113b6, 0x113b6, + 0x113c1, 0x113c1, + 0x113c3, 0x113c4, + 0x113c6, 0x113c6, + 0x113cb, 0x113cb, + 0x113d6, 0x113d6, + 0x113d9, 0x113e0, + 0x113e3, 0x113ff, 0x1145c, 0x1145c, 0x11462, 0x1147f, 0x114c8, 0x114cf, @@ -24135,7 +25259,8 @@ static const OnigCodePoint CR_Unknown[] = { 0x1165a, 0x1165f, 0x1166d, 0x1167f, 0x116ba, 0x116bf, - 0x116ca, 0x116ff, + 0x116ca, 0x116cf, + 0x116e4, 0x116ff, 0x1171b, 0x1171c, 0x1172c, 0x1172f, 0x11747, 0x117ff, @@ -24155,7 +25280,9 @@ static const OnigCodePoint CR_Unknown[] = { 0x11a48, 0x11a4f, 0x11aa3, 0x11aaf, 0x11af9, 0x11aff, - 0x11b0a, 0x11bff, + 0x11b0a, 0x11bbf, + 0x11be2, 0x11bef, + 0x11bfa, 0x11bff, 0x11c09, 0x11c09, 0x11c37, 0x11c37, 0x11c46, 0x11c4f, @@ -24179,7 +25306,7 @@ static const OnigCodePoint CR_Unknown[] = { 0x11ef9, 0x11eff, 0x11f11, 0x11f11, 0x11f3b, 0x11f3d, - 0x11f5a, 0x11faf, + 0x11f5b, 0x11faf, 0x11fb1, 0x11fbf, 0x11ff2, 0x11ffe, 0x1239a, 0x123ff, @@ -24187,8 +25314,10 @@ static const OnigCodePoint CR_Unknown[] = { 0x12475, 0x1247f, 0x12544, 0x12f8f, 0x12ff3, 0x12fff, - 0x13456, 0x143ff, - 0x14647, 0x167ff, + 0x13456, 0x1345f, + 0x143fb, 0x143ff, + 0x14647, 0x160ff, + 0x1613a, 0x167ff, 0x16a39, 0x16a3f, 0x16a5f, 0x16a5f, 0x16a6a, 0x16a6d, @@ -24200,7 +25329,8 @@ static const OnigCodePoint CR_Unknown[] = { 0x16b5a, 0x16b5a, 0x16b62, 0x16b62, 0x16b78, 0x16b7c, - 0x16b90, 0x16e3f, + 0x16b90, 0x16d3f, + 0x16d7a, 0x16e3f, 0x16e9b, 0x16eff, 0x16f4b, 0x16f4e, 0x16f88, 0x16f8e, @@ -24208,7 +25338,7 @@ static const OnigCodePoint CR_Unknown[] = { 0x16fe5, 0x16fef, 0x16ff2, 0x16fff, 0x187f8, 0x187ff, - 0x18cd6, 0x18cff, + 0x18cd6, 0x18cfe, 0x18d09, 0x1afef, 0x1aff4, 0x1aff4, 0x1affc, 0x1affc, @@ -24223,7 +25353,9 @@ static const OnigCodePoint CR_Unknown[] = { 0x1bc7d, 0x1bc7f, 0x1bc89, 0x1bc8f, 0x1bc9a, 0x1bc9b, - 0x1bca4, 0x1ceff, + 0x1bca4, 0x1cbff, + 0x1ccfa, 0x1ccff, + 0x1ceb4, 0x1ceff, 0x1cf2e, 0x1cf2f, 0x1cf47, 0x1cf4f, 0x1cfc4, 0x1cfff, @@ -24274,7 +25406,9 @@ static const OnigCodePoint CR_Unknown[] = { 0x1e2af, 0x1e2bf, 0x1e2fa, 0x1e2fe, 0x1e300, 0x1e4cf, - 0x1e4fa, 0x1e7df, + 0x1e4fa, 0x1e5cf, + 0x1e5fb, 0x1e5fe, + 0x1e600, 0x1e7df, 0x1e7e7, 0x1e7e7, 0x1e7ec, 0x1e7ec, 0x1e7ef, 0x1e7ef, @@ -24344,24 +25478,24 @@ static const OnigCodePoint CR_Unknown[] = { 0x1f85a, 0x1f85f, 0x1f888, 0x1f88f, 0x1f8ae, 0x1f8af, - 0x1f8b2, 0x1f8ff, + 0x1f8bc, 0x1f8bf, + 0x1f8c2, 0x1f8ff, 0x1fa54, 0x1fa5f, 0x1fa6e, 0x1fa6f, 0x1fa7d, 0x1fa7f, - 0x1fa89, 0x1fa8f, - 0x1fabe, 0x1fabe, - 0x1fac6, 0x1facd, - 0x1fadc, 0x1fadf, - 0x1fae9, 0x1faef, + 0x1fa8a, 0x1fa8e, + 0x1fac7, 0x1facd, + 0x1fadd, 0x1fade, + 0x1faea, 0x1faef, 0x1faf9, 0x1faff, 0x1fb93, 0x1fb93, - 0x1fbcb, 0x1fbef, 0x1fbfa, 0x1ffff, 0x2a6e0, 0x2a6ff, 0x2b73a, 0x2b73f, 0x2b81e, 0x2b81f, 0x2cea2, 0x2ceaf, - 0x2ebe1, 0x2f7ff, + 0x2ebe1, 0x2ebef, + 0x2ee5e, 0x2f7ff, 0x2fa1e, 0x2ffff, 0x3134b, 0x3134f, 0x323b0, 0xe0000, @@ -24370,10 +25504,303 @@ static const OnigCodePoint CR_Unknown[] = { 0xe01f0, 0x10ffff, }; /* CR_Unknown */ -#ifdef USE_UNICODE_AGE_PROPERTIES -/* 'Age_1_1': Derived Age 1.1 */ -static const OnigCodePoint CR_Age_1_1[] = { - 288, +#ifdef USE_UNICODE_AGE_PROPERTIES +/* 'Age_1_1': Derived Age 1.1 */ +static const OnigCodePoint CR_Age_1_1[] = { + 288, + 0x0000, 0x01f5, + 0x01fa, 0x0217, + 0x0250, 0x02a8, + 0x02b0, 0x02de, + 0x02e0, 0x02e9, + 0x0300, 0x0345, + 0x0360, 0x0361, + 0x0374, 0x0375, + 0x037a, 0x037a, + 0x037e, 0x037e, + 0x0384, 0x038a, + 0x038c, 0x038c, + 0x038e, 0x03a1, + 0x03a3, 0x03ce, + 0x03d0, 0x03d6, + 0x03da, 0x03da, + 0x03dc, 0x03dc, + 0x03de, 0x03de, + 0x03e0, 0x03e0, + 0x03e2, 0x03f3, + 0x0401, 0x040c, + 0x040e, 0x044f, + 0x0451, 0x045c, + 0x045e, 0x0486, + 0x0490, 0x04c4, + 0x04c7, 0x04c8, + 0x04cb, 0x04cc, + 0x04d0, 0x04eb, + 0x04ee, 0x04f5, + 0x04f8, 0x04f9, + 0x0531, 0x0556, + 0x0559, 0x055f, + 0x0561, 0x0587, + 0x0589, 0x0589, + 0x05b0, 0x05b9, + 0x05bb, 0x05c3, + 0x05d0, 0x05ea, + 0x05f0, 0x05f4, + 0x060c, 0x060c, + 0x061b, 0x061b, + 0x061f, 0x061f, + 0x0621, 0x063a, + 0x0640, 0x0652, + 0x0660, 0x066d, + 0x0670, 0x06b7, + 0x06ba, 0x06be, + 0x06c0, 0x06ce, + 0x06d0, 0x06ed, + 0x06f0, 0x06f9, + 0x0901, 0x0903, + 0x0905, 0x0939, + 0x093c, 0x094d, + 0x0950, 0x0954, + 0x0958, 0x0970, + 0x0981, 0x0983, + 0x0985, 0x098c, + 0x098f, 0x0990, + 0x0993, 0x09a8, + 0x09aa, 0x09b0, + 0x09b2, 0x09b2, + 0x09b6, 0x09b9, + 0x09bc, 0x09bc, + 0x09be, 0x09c4, + 0x09c7, 0x09c8, + 0x09cb, 0x09cd, + 0x09d7, 0x09d7, + 0x09dc, 0x09dd, + 0x09df, 0x09e3, + 0x09e6, 0x09fa, + 0x0a02, 0x0a02, + 0x0a05, 0x0a0a, + 0x0a0f, 0x0a10, + 0x0a13, 0x0a28, + 0x0a2a, 0x0a30, + 0x0a32, 0x0a33, + 0x0a35, 0x0a36, + 0x0a38, 0x0a39, + 0x0a3c, 0x0a3c, + 0x0a3e, 0x0a42, + 0x0a47, 0x0a48, + 0x0a4b, 0x0a4d, + 0x0a59, 0x0a5c, + 0x0a5e, 0x0a5e, + 0x0a66, 0x0a74, + 0x0a81, 0x0a83, + 0x0a85, 0x0a8b, + 0x0a8d, 0x0a8d, + 0x0a8f, 0x0a91, + 0x0a93, 0x0aa8, + 0x0aaa, 0x0ab0, + 0x0ab2, 0x0ab3, + 0x0ab5, 0x0ab9, + 0x0abc, 0x0ac5, + 0x0ac7, 0x0ac9, + 0x0acb, 0x0acd, + 0x0ad0, 0x0ad0, + 0x0ae0, 0x0ae0, + 0x0ae6, 0x0aef, + 0x0b01, 0x0b03, + 0x0b05, 0x0b0c, + 0x0b0f, 0x0b10, + 0x0b13, 0x0b28, + 0x0b2a, 0x0b30, + 0x0b32, 0x0b33, + 0x0b36, 0x0b39, + 0x0b3c, 0x0b43, + 0x0b47, 0x0b48, + 0x0b4b, 0x0b4d, + 0x0b56, 0x0b57, + 0x0b5c, 0x0b5d, + 0x0b5f, 0x0b61, + 0x0b66, 0x0b70, + 0x0b82, 0x0b83, + 0x0b85, 0x0b8a, + 0x0b8e, 0x0b90, + 0x0b92, 0x0b95, + 0x0b99, 0x0b9a, + 0x0b9c, 0x0b9c, + 0x0b9e, 0x0b9f, + 0x0ba3, 0x0ba4, + 0x0ba8, 0x0baa, + 0x0bae, 0x0bb5, + 0x0bb7, 0x0bb9, + 0x0bbe, 0x0bc2, + 0x0bc6, 0x0bc8, + 0x0bca, 0x0bcd, + 0x0bd7, 0x0bd7, + 0x0be7, 0x0bf2, + 0x0c01, 0x0c03, + 0x0c05, 0x0c0c, + 0x0c0e, 0x0c10, + 0x0c12, 0x0c28, + 0x0c2a, 0x0c33, + 0x0c35, 0x0c39, + 0x0c3e, 0x0c44, + 0x0c46, 0x0c48, + 0x0c4a, 0x0c4d, + 0x0c55, 0x0c56, + 0x0c60, 0x0c61, + 0x0c66, 0x0c6f, + 0x0c82, 0x0c83, + 0x0c85, 0x0c8c, + 0x0c8e, 0x0c90, + 0x0c92, 0x0ca8, + 0x0caa, 0x0cb3, + 0x0cb5, 0x0cb9, + 0x0cbe, 0x0cc4, + 0x0cc6, 0x0cc8, + 0x0cca, 0x0ccd, + 0x0cd5, 0x0cd6, + 0x0cde, 0x0cde, + 0x0ce0, 0x0ce1, + 0x0ce6, 0x0cef, + 0x0d02, 0x0d03, + 0x0d05, 0x0d0c, + 0x0d0e, 0x0d10, + 0x0d12, 0x0d28, + 0x0d2a, 0x0d39, + 0x0d3e, 0x0d43, + 0x0d46, 0x0d48, + 0x0d4a, 0x0d4d, + 0x0d57, 0x0d57, + 0x0d60, 0x0d61, + 0x0d66, 0x0d6f, + 0x0e01, 0x0e3a, + 0x0e3f, 0x0e5b, + 0x0e81, 0x0e82, + 0x0e84, 0x0e84, + 0x0e87, 0x0e88, + 0x0e8a, 0x0e8a, + 0x0e8d, 0x0e8d, + 0x0e94, 0x0e97, + 0x0e99, 0x0e9f, + 0x0ea1, 0x0ea3, + 0x0ea5, 0x0ea5, + 0x0ea7, 0x0ea7, + 0x0eaa, 0x0eab, + 0x0ead, 0x0eb9, + 0x0ebb, 0x0ebd, + 0x0ec0, 0x0ec4, + 0x0ec6, 0x0ec6, + 0x0ec8, 0x0ecd, + 0x0ed0, 0x0ed9, + 0x0edc, 0x0edd, + 0x10a0, 0x10c5, + 0x10d0, 0x10f6, + 0x10fb, 0x10fb, + 0x1100, 0x1159, + 0x115f, 0x11a2, + 0x11a8, 0x11f9, + 0x1e00, 0x1e9a, + 0x1ea0, 0x1ef9, + 0x1f00, 0x1f15, + 0x1f18, 0x1f1d, + 0x1f20, 0x1f45, + 0x1f48, 0x1f4d, + 0x1f50, 0x1f57, + 0x1f59, 0x1f59, + 0x1f5b, 0x1f5b, + 0x1f5d, 0x1f5d, + 0x1f5f, 0x1f7d, + 0x1f80, 0x1fb4, + 0x1fb6, 0x1fc4, + 0x1fc6, 0x1fd3, + 0x1fd6, 0x1fdb, + 0x1fdd, 0x1fef, + 0x1ff2, 0x1ff4, + 0x1ff6, 0x1ffe, + 0x2000, 0x202e, + 0x2030, 0x2046, + 0x206a, 0x2070, + 0x2074, 0x208e, + 0x20a0, 0x20aa, + 0x20d0, 0x20e1, + 0x2100, 0x2138, + 0x2153, 0x2182, + 0x2190, 0x21ea, + 0x2200, 0x22f1, + 0x2300, 0x2300, + 0x2302, 0x237a, + 0x2400, 0x2424, + 0x2440, 0x244a, + 0x2460, 0x24ea, + 0x2500, 0x2595, + 0x25a0, 0x25ef, + 0x2600, 0x2613, + 0x261a, 0x266f, + 0x2701, 0x2704, + 0x2706, 0x2709, + 0x270c, 0x2727, + 0x2729, 0x274b, + 0x274d, 0x274d, + 0x274f, 0x2752, + 0x2756, 0x2756, + 0x2758, 0x275e, + 0x2761, 0x2767, + 0x2776, 0x2794, + 0x2798, 0x27af, + 0x27b1, 0x27be, + 0x3000, 0x3037, + 0x303f, 0x303f, + 0x3041, 0x3094, + 0x3099, 0x309e, + 0x30a1, 0x30fe, + 0x3105, 0x312c, + 0x3131, 0x318e, + 0x3190, 0x319f, + 0x3200, 0x321c, + 0x3220, 0x3243, + 0x3260, 0x327b, + 0x327f, 0x32b0, + 0x32c0, 0x32cb, + 0x32d0, 0x32fe, + 0x3300, 0x3376, + 0x337b, 0x33dd, + 0x33e0, 0x33fe, + 0x4e00, 0x9fa5, + 0xe000, 0xfa2d, + 0xfb00, 0xfb06, + 0xfb13, 0xfb17, + 0xfb1e, 0xfb36, + 0xfb38, 0xfb3c, + 0xfb3e, 0xfb3e, + 0xfb40, 0xfb41, + 0xfb43, 0xfb44, + 0xfb46, 0xfbb1, + 0xfbd3, 0xfd3f, + 0xfd50, 0xfd8f, + 0xfd92, 0xfdc7, + 0xfdf0, 0xfdfb, + 0xfe20, 0xfe23, + 0xfe30, 0xfe44, + 0xfe49, 0xfe52, + 0xfe54, 0xfe66, + 0xfe68, 0xfe6b, + 0xfe70, 0xfe72, + 0xfe74, 0xfe74, + 0xfe76, 0xfefc, + 0xfeff, 0xfeff, + 0xff01, 0xff5e, + 0xff61, 0xffbe, + 0xffc2, 0xffc7, + 0xffca, 0xffcf, + 0xffd2, 0xffd7, + 0xffda, 0xffdc, + 0xffe0, 0xffe6, + 0xffe8, 0xffee, + 0xfffd, 0xffff, +}; /* CR_Age_1_1 */ + +/* 'Age_2_0': Derived Age 2.0 */ +static const OnigCodePoint CR_Age_2_0[] = { + 312, 0x0000, 0x01f5, 0x01fa, 0x0217, 0x0250, 0x02a8, @@ -24408,8 +25835,326 @@ static const OnigCodePoint CR_Age_1_1[] = { 0x0559, 0x055f, 0x0561, 0x0587, 0x0589, 0x0589, - 0x05b0, 0x05b9, - 0x05bb, 0x05c3, + 0x0591, 0x05a1, + 0x05a3, 0x05b9, + 0x05bb, 0x05c4, + 0x05d0, 0x05ea, + 0x05f0, 0x05f4, + 0x060c, 0x060c, + 0x061b, 0x061b, + 0x061f, 0x061f, + 0x0621, 0x063a, + 0x0640, 0x0652, + 0x0660, 0x066d, + 0x0670, 0x06b7, + 0x06ba, 0x06be, + 0x06c0, 0x06ce, + 0x06d0, 0x06ed, + 0x06f0, 0x06f9, + 0x0901, 0x0903, + 0x0905, 0x0939, + 0x093c, 0x094d, + 0x0950, 0x0954, + 0x0958, 0x0970, + 0x0981, 0x0983, + 0x0985, 0x098c, + 0x098f, 0x0990, + 0x0993, 0x09a8, + 0x09aa, 0x09b0, + 0x09b2, 0x09b2, + 0x09b6, 0x09b9, + 0x09bc, 0x09bc, + 0x09be, 0x09c4, + 0x09c7, 0x09c8, + 0x09cb, 0x09cd, + 0x09d7, 0x09d7, + 0x09dc, 0x09dd, + 0x09df, 0x09e3, + 0x09e6, 0x09fa, + 0x0a02, 0x0a02, + 0x0a05, 0x0a0a, + 0x0a0f, 0x0a10, + 0x0a13, 0x0a28, + 0x0a2a, 0x0a30, + 0x0a32, 0x0a33, + 0x0a35, 0x0a36, + 0x0a38, 0x0a39, + 0x0a3c, 0x0a3c, + 0x0a3e, 0x0a42, + 0x0a47, 0x0a48, + 0x0a4b, 0x0a4d, + 0x0a59, 0x0a5c, + 0x0a5e, 0x0a5e, + 0x0a66, 0x0a74, + 0x0a81, 0x0a83, + 0x0a85, 0x0a8b, + 0x0a8d, 0x0a8d, + 0x0a8f, 0x0a91, + 0x0a93, 0x0aa8, + 0x0aaa, 0x0ab0, + 0x0ab2, 0x0ab3, + 0x0ab5, 0x0ab9, + 0x0abc, 0x0ac5, + 0x0ac7, 0x0ac9, + 0x0acb, 0x0acd, + 0x0ad0, 0x0ad0, + 0x0ae0, 0x0ae0, + 0x0ae6, 0x0aef, + 0x0b01, 0x0b03, + 0x0b05, 0x0b0c, + 0x0b0f, 0x0b10, + 0x0b13, 0x0b28, + 0x0b2a, 0x0b30, + 0x0b32, 0x0b33, + 0x0b36, 0x0b39, + 0x0b3c, 0x0b43, + 0x0b47, 0x0b48, + 0x0b4b, 0x0b4d, + 0x0b56, 0x0b57, + 0x0b5c, 0x0b5d, + 0x0b5f, 0x0b61, + 0x0b66, 0x0b70, + 0x0b82, 0x0b83, + 0x0b85, 0x0b8a, + 0x0b8e, 0x0b90, + 0x0b92, 0x0b95, + 0x0b99, 0x0b9a, + 0x0b9c, 0x0b9c, + 0x0b9e, 0x0b9f, + 0x0ba3, 0x0ba4, + 0x0ba8, 0x0baa, + 0x0bae, 0x0bb5, + 0x0bb7, 0x0bb9, + 0x0bbe, 0x0bc2, + 0x0bc6, 0x0bc8, + 0x0bca, 0x0bcd, + 0x0bd7, 0x0bd7, + 0x0be7, 0x0bf2, + 0x0c01, 0x0c03, + 0x0c05, 0x0c0c, + 0x0c0e, 0x0c10, + 0x0c12, 0x0c28, + 0x0c2a, 0x0c33, + 0x0c35, 0x0c39, + 0x0c3e, 0x0c44, + 0x0c46, 0x0c48, + 0x0c4a, 0x0c4d, + 0x0c55, 0x0c56, + 0x0c60, 0x0c61, + 0x0c66, 0x0c6f, + 0x0c82, 0x0c83, + 0x0c85, 0x0c8c, + 0x0c8e, 0x0c90, + 0x0c92, 0x0ca8, + 0x0caa, 0x0cb3, + 0x0cb5, 0x0cb9, + 0x0cbe, 0x0cc4, + 0x0cc6, 0x0cc8, + 0x0cca, 0x0ccd, + 0x0cd5, 0x0cd6, + 0x0cde, 0x0cde, + 0x0ce0, 0x0ce1, + 0x0ce6, 0x0cef, + 0x0d02, 0x0d03, + 0x0d05, 0x0d0c, + 0x0d0e, 0x0d10, + 0x0d12, 0x0d28, + 0x0d2a, 0x0d39, + 0x0d3e, 0x0d43, + 0x0d46, 0x0d48, + 0x0d4a, 0x0d4d, + 0x0d57, 0x0d57, + 0x0d60, 0x0d61, + 0x0d66, 0x0d6f, + 0x0e01, 0x0e3a, + 0x0e3f, 0x0e5b, + 0x0e81, 0x0e82, + 0x0e84, 0x0e84, + 0x0e87, 0x0e88, + 0x0e8a, 0x0e8a, + 0x0e8d, 0x0e8d, + 0x0e94, 0x0e97, + 0x0e99, 0x0e9f, + 0x0ea1, 0x0ea3, + 0x0ea5, 0x0ea5, + 0x0ea7, 0x0ea7, + 0x0eaa, 0x0eab, + 0x0ead, 0x0eb9, + 0x0ebb, 0x0ebd, + 0x0ec0, 0x0ec4, + 0x0ec6, 0x0ec6, + 0x0ec8, 0x0ecd, + 0x0ed0, 0x0ed9, + 0x0edc, 0x0edd, + 0x0f00, 0x0f47, + 0x0f49, 0x0f69, + 0x0f71, 0x0f8b, + 0x0f90, 0x0f95, + 0x0f97, 0x0f97, + 0x0f99, 0x0fad, + 0x0fb1, 0x0fb7, + 0x0fb9, 0x0fb9, + 0x10a0, 0x10c5, + 0x10d0, 0x10f6, + 0x10fb, 0x10fb, + 0x1100, 0x1159, + 0x115f, 0x11a2, + 0x11a8, 0x11f9, + 0x1e00, 0x1e9b, + 0x1ea0, 0x1ef9, + 0x1f00, 0x1f15, + 0x1f18, 0x1f1d, + 0x1f20, 0x1f45, + 0x1f48, 0x1f4d, + 0x1f50, 0x1f57, + 0x1f59, 0x1f59, + 0x1f5b, 0x1f5b, + 0x1f5d, 0x1f5d, + 0x1f5f, 0x1f7d, + 0x1f80, 0x1fb4, + 0x1fb6, 0x1fc4, + 0x1fc6, 0x1fd3, + 0x1fd6, 0x1fdb, + 0x1fdd, 0x1fef, + 0x1ff2, 0x1ff4, + 0x1ff6, 0x1ffe, + 0x2000, 0x202e, + 0x2030, 0x2046, + 0x206a, 0x2070, + 0x2074, 0x208e, + 0x20a0, 0x20ab, + 0x20d0, 0x20e1, + 0x2100, 0x2138, + 0x2153, 0x2182, + 0x2190, 0x21ea, + 0x2200, 0x22f1, + 0x2300, 0x2300, + 0x2302, 0x237a, + 0x2400, 0x2424, + 0x2440, 0x244a, + 0x2460, 0x24ea, + 0x2500, 0x2595, + 0x25a0, 0x25ef, + 0x2600, 0x2613, + 0x261a, 0x266f, + 0x2701, 0x2704, + 0x2706, 0x2709, + 0x270c, 0x2727, + 0x2729, 0x274b, + 0x274d, 0x274d, + 0x274f, 0x2752, + 0x2756, 0x2756, + 0x2758, 0x275e, + 0x2761, 0x2767, + 0x2776, 0x2794, + 0x2798, 0x27af, + 0x27b1, 0x27be, + 0x3000, 0x3037, + 0x303f, 0x303f, + 0x3041, 0x3094, + 0x3099, 0x309e, + 0x30a1, 0x30fe, + 0x3105, 0x312c, + 0x3131, 0x318e, + 0x3190, 0x319f, + 0x3200, 0x321c, + 0x3220, 0x3243, + 0x3260, 0x327b, + 0x327f, 0x32b0, + 0x32c0, 0x32cb, + 0x32d0, 0x32fe, + 0x3300, 0x3376, + 0x337b, 0x33dd, + 0x33e0, 0x33fe, + 0x4e00, 0x9fa5, + 0xac00, 0xd7a3, + 0xd800, 0xfa2d, + 0xfb00, 0xfb06, + 0xfb13, 0xfb17, + 0xfb1e, 0xfb36, + 0xfb38, 0xfb3c, + 0xfb3e, 0xfb3e, + 0xfb40, 0xfb41, + 0xfb43, 0xfb44, + 0xfb46, 0xfbb1, + 0xfbd3, 0xfd3f, + 0xfd50, 0xfd8f, + 0xfd92, 0xfdc7, + 0xfdf0, 0xfdfb, + 0xfe20, 0xfe23, + 0xfe30, 0xfe44, + 0xfe49, 0xfe52, + 0xfe54, 0xfe66, + 0xfe68, 0xfe6b, + 0xfe70, 0xfe72, + 0xfe74, 0xfe74, + 0xfe76, 0xfefc, + 0xfeff, 0xfeff, + 0xff01, 0xff5e, + 0xff61, 0xffbe, + 0xffc2, 0xffc7, + 0xffca, 0xffcf, + 0xffd2, 0xffd7, + 0xffda, 0xffdc, + 0xffe0, 0xffe6, + 0xffe8, 0xffee, + 0xfffd, 0xffff, + 0x1fffe, 0x1ffff, + 0x2fffe, 0x2ffff, + 0x3fffe, 0x3ffff, + 0x4fffe, 0x4ffff, + 0x5fffe, 0x5ffff, + 0x6fffe, 0x6ffff, + 0x7fffe, 0x7ffff, + 0x8fffe, 0x8ffff, + 0x9fffe, 0x9ffff, + 0xafffe, 0xaffff, + 0xbfffe, 0xbffff, + 0xcfffe, 0xcffff, + 0xdfffe, 0xdffff, + 0xefffe, 0x10ffff, +}; /* CR_Age_2_0 */ + +/* 'Age_2_1': Derived Age 2.1 */ +static const OnigCodePoint CR_Age_2_1[] = { + 312, + 0x0000, 0x01f5, + 0x01fa, 0x0217, + 0x0250, 0x02a8, + 0x02b0, 0x02de, + 0x02e0, 0x02e9, + 0x0300, 0x0345, + 0x0360, 0x0361, + 0x0374, 0x0375, + 0x037a, 0x037a, + 0x037e, 0x037e, + 0x0384, 0x038a, + 0x038c, 0x038c, + 0x038e, 0x03a1, + 0x03a3, 0x03ce, + 0x03d0, 0x03d6, + 0x03da, 0x03da, + 0x03dc, 0x03dc, + 0x03de, 0x03de, + 0x03e0, 0x03e0, + 0x03e2, 0x03f3, + 0x0401, 0x040c, + 0x040e, 0x044f, + 0x0451, 0x045c, + 0x045e, 0x0486, + 0x0490, 0x04c4, + 0x04c7, 0x04c8, + 0x04cb, 0x04cc, + 0x04d0, 0x04eb, + 0x04ee, 0x04f5, + 0x04f8, 0x04f9, + 0x0531, 0x0556, + 0x0559, 0x055f, + 0x0561, 0x0587, + 0x0589, 0x0589, + 0x0591, 0x05a1, + 0x05a3, 0x05b9, + 0x05bb, 0x05c4, 0x05d0, 0x05ea, 0x05f0, 0x05f4, 0x060c, 0x060c, @@ -24558,13 +26303,21 @@ static const OnigCodePoint CR_Age_1_1[] = { 0x0ec8, 0x0ecd, 0x0ed0, 0x0ed9, 0x0edc, 0x0edd, + 0x0f00, 0x0f47, + 0x0f49, 0x0f69, + 0x0f71, 0x0f8b, + 0x0f90, 0x0f95, + 0x0f97, 0x0f97, + 0x0f99, 0x0fad, + 0x0fb1, 0x0fb7, + 0x0fb9, 0x0fb9, 0x10a0, 0x10c5, 0x10d0, 0x10f6, 0x10fb, 0x10fb, 0x1100, 0x1159, 0x115f, 0x11a2, 0x11a8, 0x11f9, - 0x1e00, 0x1e9a, + 0x1e00, 0x1e9b, 0x1ea0, 0x1ef9, 0x1f00, 0x1f15, 0x1f18, 0x1f1d, @@ -24586,7 +26339,7 @@ static const OnigCodePoint CR_Age_1_1[] = { 0x2030, 0x2046, 0x206a, 0x2070, 0x2074, 0x208e, - 0x20a0, 0x20aa, + 0x20a0, 0x20ac, 0x20d0, 0x20e1, 0x2100, 0x2138, 0x2153, 0x2182, @@ -24631,7 +26384,8 @@ static const OnigCodePoint CR_Age_1_1[] = { 0x337b, 0x33dd, 0x33e0, 0x33fe, 0x4e00, 0x9fa5, - 0xe000, 0xfa2d, + 0xac00, 0xd7a3, + 0xd800, 0xfa2d, 0xfb00, 0xfb06, 0xfb13, 0xfb17, 0xfb1e, 0xfb36, @@ -24661,19 +26415,32 @@ static const OnigCodePoint CR_Age_1_1[] = { 0xffda, 0xffdc, 0xffe0, 0xffe6, 0xffe8, 0xffee, - 0xfffd, 0xffff, -}; /* CR_Age_1_1 */ + 0xfffc, 0xffff, + 0x1fffe, 0x1ffff, + 0x2fffe, 0x2ffff, + 0x3fffe, 0x3ffff, + 0x4fffe, 0x4ffff, + 0x5fffe, 0x5ffff, + 0x6fffe, 0x6ffff, + 0x7fffe, 0x7ffff, + 0x8fffe, 0x8ffff, + 0x9fffe, 0x9ffff, + 0xafffe, 0xaffff, + 0xbfffe, 0xbffff, + 0xcfffe, 0xcffff, + 0xdfffe, 0xdffff, + 0xefffe, 0x10ffff, +}; /* CR_Age_2_1 */ -/* 'Age_2_0': Derived Age 2.0 */ -static const OnigCodePoint CR_Age_2_0[] = { - 312, - 0x0000, 0x01f5, - 0x01fa, 0x0217, - 0x0250, 0x02a8, - 0x02b0, 0x02de, - 0x02e0, 0x02e9, - 0x0300, 0x0345, - 0x0360, 0x0361, +/* 'Age_3_0': Derived Age 3.0 */ +static const OnigCodePoint CR_Age_3_0[] = { + 369, + 0x0000, 0x021f, + 0x0222, 0x0233, + 0x0250, 0x02ad, + 0x02b0, 0x02ee, + 0x0300, 0x034e, + 0x0360, 0x0362, 0x0374, 0x0375, 0x037a, 0x037a, 0x037e, 0x037e, @@ -24681,26 +26448,19 @@ static const OnigCodePoint CR_Age_2_0[] = { 0x038c, 0x038c, 0x038e, 0x03a1, 0x03a3, 0x03ce, - 0x03d0, 0x03d6, - 0x03da, 0x03da, - 0x03dc, 0x03dc, - 0x03de, 0x03de, - 0x03e0, 0x03e0, - 0x03e2, 0x03f3, - 0x0401, 0x040c, - 0x040e, 0x044f, - 0x0451, 0x045c, - 0x045e, 0x0486, - 0x0490, 0x04c4, + 0x03d0, 0x03d7, + 0x03da, 0x03f3, + 0x0400, 0x0486, + 0x0488, 0x0489, + 0x048c, 0x04c4, 0x04c7, 0x04c8, 0x04cb, 0x04cc, - 0x04d0, 0x04eb, - 0x04ee, 0x04f5, + 0x04d0, 0x04f5, 0x04f8, 0x04f9, 0x0531, 0x0556, 0x0559, 0x055f, 0x0561, 0x0587, - 0x0589, 0x0589, + 0x0589, 0x058a, 0x0591, 0x05a1, 0x05a3, 0x05b9, 0x05bb, 0x05c4, @@ -24710,13 +26470,14 @@ static const OnigCodePoint CR_Age_2_0[] = { 0x061b, 0x061b, 0x061f, 0x061f, 0x0621, 0x063a, - 0x0640, 0x0652, + 0x0640, 0x0655, 0x0660, 0x066d, - 0x0670, 0x06b7, - 0x06ba, 0x06be, - 0x06c0, 0x06ce, - 0x06d0, 0x06ed, - 0x06f0, 0x06f9, + 0x0670, 0x06ed, + 0x06f0, 0x06fe, + 0x0700, 0x070d, + 0x070f, 0x072c, + 0x0730, 0x074a, + 0x0780, 0x07b0, 0x0901, 0x0903, 0x0905, 0x0939, 0x093c, 0x094d, @@ -24832,6 +26593,17 @@ static const OnigCodePoint CR_Age_2_0[] = { 0x0d57, 0x0d57, 0x0d60, 0x0d61, 0x0d66, 0x0d6f, + 0x0d82, 0x0d83, + 0x0d85, 0x0d96, + 0x0d9a, 0x0db1, + 0x0db3, 0x0dbb, + 0x0dbd, 0x0dbd, + 0x0dc0, 0x0dc6, + 0x0dca, 0x0dca, + 0x0dcf, 0x0dd4, + 0x0dd6, 0x0dd6, + 0x0dd8, 0x0ddf, + 0x0df2, 0x0df4, 0x0e01, 0x0e3a, 0x0e3f, 0x0e5b, 0x0e81, 0x0e82, @@ -24853,19 +26625,60 @@ static const OnigCodePoint CR_Age_2_0[] = { 0x0ed0, 0x0ed9, 0x0edc, 0x0edd, 0x0f00, 0x0f47, - 0x0f49, 0x0f69, + 0x0f49, 0x0f6a, 0x0f71, 0x0f8b, - 0x0f90, 0x0f95, - 0x0f97, 0x0f97, - 0x0f99, 0x0fad, - 0x0fb1, 0x0fb7, - 0x0fb9, 0x0fb9, + 0x0f90, 0x0f97, + 0x0f99, 0x0fbc, + 0x0fbe, 0x0fcc, + 0x0fcf, 0x0fcf, + 0x1000, 0x1021, + 0x1023, 0x1027, + 0x1029, 0x102a, + 0x102c, 0x1032, + 0x1036, 0x1039, + 0x1040, 0x1059, 0x10a0, 0x10c5, 0x10d0, 0x10f6, 0x10fb, 0x10fb, 0x1100, 0x1159, 0x115f, 0x11a2, 0x11a8, 0x11f9, + 0x1200, 0x1206, + 0x1208, 0x1246, + 0x1248, 0x1248, + 0x124a, 0x124d, + 0x1250, 0x1256, + 0x1258, 0x1258, + 0x125a, 0x125d, + 0x1260, 0x1286, + 0x1288, 0x1288, + 0x128a, 0x128d, + 0x1290, 0x12ae, + 0x12b0, 0x12b0, + 0x12b2, 0x12b5, + 0x12b8, 0x12be, + 0x12c0, 0x12c0, + 0x12c2, 0x12c5, + 0x12c8, 0x12ce, + 0x12d0, 0x12d6, + 0x12d8, 0x12ee, + 0x12f0, 0x130e, + 0x1310, 0x1310, + 0x1312, 0x1315, + 0x1318, 0x131e, + 0x1320, 0x1346, + 0x1348, 0x135a, + 0x1361, 0x137c, + 0x13a0, 0x13f4, + 0x1401, 0x1676, + 0x1680, 0x169c, + 0x16a0, 0x16f0, + 0x1780, 0x17dc, + 0x17e0, 0x17e9, + 0x1800, 0x180e, + 0x1810, 0x1819, + 0x1820, 0x1877, + 0x1880, 0x18a9, 0x1e00, 0x1e9b, 0x1ea0, 0x1ef9, 0x1f00, 0x1f15, @@ -24884,25 +26697,25 @@ static const OnigCodePoint CR_Age_2_0[] = { 0x1fdd, 0x1fef, 0x1ff2, 0x1ff4, 0x1ff6, 0x1ffe, - 0x2000, 0x202e, - 0x2030, 0x2046, + 0x2000, 0x2046, + 0x2048, 0x204d, 0x206a, 0x2070, 0x2074, 0x208e, - 0x20a0, 0x20ab, - 0x20d0, 0x20e1, - 0x2100, 0x2138, - 0x2153, 0x2182, - 0x2190, 0x21ea, + 0x20a0, 0x20af, + 0x20d0, 0x20e3, + 0x2100, 0x213a, + 0x2153, 0x2183, + 0x2190, 0x21f3, 0x2200, 0x22f1, - 0x2300, 0x2300, - 0x2302, 0x237a, - 0x2400, 0x2424, + 0x2300, 0x237b, + 0x237d, 0x239a, + 0x2400, 0x2426, 0x2440, 0x244a, 0x2460, 0x24ea, 0x2500, 0x2595, - 0x25a0, 0x25ef, + 0x25a0, 0x25f7, 0x2600, 0x2613, - 0x261a, 0x266f, + 0x2619, 0x2671, 0x2701, 0x2704, 0x2706, 0x2709, 0x270c, 0x2727, @@ -24915,14 +26728,19 @@ static const OnigCodePoint CR_Age_2_0[] = { 0x2776, 0x2794, 0x2798, 0x27af, 0x27b1, 0x27be, - 0x3000, 0x3037, - 0x303f, 0x303f, + 0x2800, 0x28ff, + 0x2e80, 0x2e99, + 0x2e9b, 0x2ef3, + 0x2f00, 0x2fd5, + 0x2ff0, 0x2ffb, + 0x3000, 0x303a, + 0x303e, 0x303f, 0x3041, 0x3094, 0x3099, 0x309e, 0x30a1, 0x30fe, 0x3105, 0x312c, 0x3131, 0x318e, - 0x3190, 0x319f, + 0x3190, 0x31b7, 0x3200, 0x321c, 0x3220, 0x3243, 0x3260, 0x327b, @@ -24932,12 +26750,19 @@ static const OnigCodePoint CR_Age_2_0[] = { 0x3300, 0x3376, 0x337b, 0x33dd, 0x33e0, 0x33fe, + 0x3400, 0x4db5, 0x4e00, 0x9fa5, + 0xa000, 0xa48c, + 0xa490, 0xa4a1, + 0xa4a4, 0xa4b3, + 0xa4b5, 0xa4c0, + 0xa4c2, 0xa4c4, + 0xa4c6, 0xa4c6, 0xac00, 0xd7a3, 0xd800, 0xfa2d, 0xfb00, 0xfb06, 0xfb13, 0xfb17, - 0xfb1e, 0xfb36, + 0xfb1d, 0xfb36, 0xfb38, 0xfb3c, 0xfb3e, 0xfb3e, 0xfb40, 0xfb41, @@ -24964,7 +26789,7 @@ static const OnigCodePoint CR_Age_2_0[] = { 0xffda, 0xffdc, 0xffe0, 0xffe6, 0xffe8, 0xffee, - 0xfffd, 0xffff, + 0xfff9, 0xffff, 0x1fffe, 0x1ffff, 0x2fffe, 0x2ffff, 0x3fffe, 0x3ffff, @@ -24979,18 +26804,17 @@ static const OnigCodePoint CR_Age_2_0[] = { 0xcfffe, 0xcffff, 0xdfffe, 0xdffff, 0xefffe, 0x10ffff, -}; /* CR_Age_2_0 */ +}; /* CR_Age_3_0 */ -/* 'Age_2_1': Derived Age 2.1 */ -static const OnigCodePoint CR_Age_2_1[] = { - 312, - 0x0000, 0x01f5, - 0x01fa, 0x0217, - 0x0250, 0x02a8, - 0x02b0, 0x02de, - 0x02e0, 0x02e9, - 0x0300, 0x0345, - 0x0360, 0x0361, +/* 'Age_3_1': Derived Age 3.1 */ +static const OnigCodePoint CR_Age_3_1[] = { + 402, + 0x0000, 0x021f, + 0x0222, 0x0233, + 0x0250, 0x02ad, + 0x02b0, 0x02ee, + 0x0300, 0x034e, + 0x0360, 0x0362, 0x0374, 0x0375, 0x037a, 0x037a, 0x037e, 0x037e, @@ -24998,26 +26822,19 @@ static const OnigCodePoint CR_Age_2_1[] = { 0x038c, 0x038c, 0x038e, 0x03a1, 0x03a3, 0x03ce, - 0x03d0, 0x03d6, - 0x03da, 0x03da, - 0x03dc, 0x03dc, - 0x03de, 0x03de, - 0x03e0, 0x03e0, - 0x03e2, 0x03f3, - 0x0401, 0x040c, - 0x040e, 0x044f, - 0x0451, 0x045c, - 0x045e, 0x0486, - 0x0490, 0x04c4, + 0x03d0, 0x03d7, + 0x03da, 0x03f5, + 0x0400, 0x0486, + 0x0488, 0x0489, + 0x048c, 0x04c4, 0x04c7, 0x04c8, 0x04cb, 0x04cc, - 0x04d0, 0x04eb, - 0x04ee, 0x04f5, + 0x04d0, 0x04f5, 0x04f8, 0x04f9, 0x0531, 0x0556, 0x0559, 0x055f, 0x0561, 0x0587, - 0x0589, 0x0589, + 0x0589, 0x058a, 0x0591, 0x05a1, 0x05a3, 0x05b9, 0x05bb, 0x05c4, @@ -25027,13 +26844,14 @@ static const OnigCodePoint CR_Age_2_1[] = { 0x061b, 0x061b, 0x061f, 0x061f, 0x0621, 0x063a, - 0x0640, 0x0652, + 0x0640, 0x0655, 0x0660, 0x066d, - 0x0670, 0x06b7, - 0x06ba, 0x06be, - 0x06c0, 0x06ce, - 0x06d0, 0x06ed, - 0x06f0, 0x06f9, + 0x0670, 0x06ed, + 0x06f0, 0x06fe, + 0x0700, 0x070d, + 0x070f, 0x072c, + 0x0730, 0x074a, + 0x0780, 0x07b0, 0x0901, 0x0903, 0x0905, 0x0939, 0x093c, 0x094d, @@ -25149,6 +26967,17 @@ static const OnigCodePoint CR_Age_2_1[] = { 0x0d57, 0x0d57, 0x0d60, 0x0d61, 0x0d66, 0x0d6f, + 0x0d82, 0x0d83, + 0x0d85, 0x0d96, + 0x0d9a, 0x0db1, + 0x0db3, 0x0dbb, + 0x0dbd, 0x0dbd, + 0x0dc0, 0x0dc6, + 0x0dca, 0x0dca, + 0x0dcf, 0x0dd4, + 0x0dd6, 0x0dd6, + 0x0dd8, 0x0ddf, + 0x0df2, 0x0df4, 0x0e01, 0x0e3a, 0x0e3f, 0x0e5b, 0x0e81, 0x0e82, @@ -25170,19 +26999,60 @@ static const OnigCodePoint CR_Age_2_1[] = { 0x0ed0, 0x0ed9, 0x0edc, 0x0edd, 0x0f00, 0x0f47, - 0x0f49, 0x0f69, + 0x0f49, 0x0f6a, 0x0f71, 0x0f8b, - 0x0f90, 0x0f95, - 0x0f97, 0x0f97, - 0x0f99, 0x0fad, - 0x0fb1, 0x0fb7, - 0x0fb9, 0x0fb9, + 0x0f90, 0x0f97, + 0x0f99, 0x0fbc, + 0x0fbe, 0x0fcc, + 0x0fcf, 0x0fcf, + 0x1000, 0x1021, + 0x1023, 0x1027, + 0x1029, 0x102a, + 0x102c, 0x1032, + 0x1036, 0x1039, + 0x1040, 0x1059, 0x10a0, 0x10c5, 0x10d0, 0x10f6, 0x10fb, 0x10fb, 0x1100, 0x1159, 0x115f, 0x11a2, 0x11a8, 0x11f9, + 0x1200, 0x1206, + 0x1208, 0x1246, + 0x1248, 0x1248, + 0x124a, 0x124d, + 0x1250, 0x1256, + 0x1258, 0x1258, + 0x125a, 0x125d, + 0x1260, 0x1286, + 0x1288, 0x1288, + 0x128a, 0x128d, + 0x1290, 0x12ae, + 0x12b0, 0x12b0, + 0x12b2, 0x12b5, + 0x12b8, 0x12be, + 0x12c0, 0x12c0, + 0x12c2, 0x12c5, + 0x12c8, 0x12ce, + 0x12d0, 0x12d6, + 0x12d8, 0x12ee, + 0x12f0, 0x130e, + 0x1310, 0x1310, + 0x1312, 0x1315, + 0x1318, 0x131e, + 0x1320, 0x1346, + 0x1348, 0x135a, + 0x1361, 0x137c, + 0x13a0, 0x13f4, + 0x1401, 0x1676, + 0x1680, 0x169c, + 0x16a0, 0x16f0, + 0x1780, 0x17dc, + 0x17e0, 0x17e9, + 0x1800, 0x180e, + 0x1810, 0x1819, + 0x1820, 0x1877, + 0x1880, 0x18a9, 0x1e00, 0x1e9b, 0x1ea0, 0x1ef9, 0x1f00, 0x1f15, @@ -25201,25 +27071,25 @@ static const OnigCodePoint CR_Age_2_1[] = { 0x1fdd, 0x1fef, 0x1ff2, 0x1ff4, 0x1ff6, 0x1ffe, - 0x2000, 0x202e, - 0x2030, 0x2046, + 0x2000, 0x2046, + 0x2048, 0x204d, 0x206a, 0x2070, 0x2074, 0x208e, - 0x20a0, 0x20ac, - 0x20d0, 0x20e1, - 0x2100, 0x2138, - 0x2153, 0x2182, - 0x2190, 0x21ea, + 0x20a0, 0x20af, + 0x20d0, 0x20e3, + 0x2100, 0x213a, + 0x2153, 0x2183, + 0x2190, 0x21f3, 0x2200, 0x22f1, - 0x2300, 0x2300, - 0x2302, 0x237a, - 0x2400, 0x2424, + 0x2300, 0x237b, + 0x237d, 0x239a, + 0x2400, 0x2426, 0x2440, 0x244a, 0x2460, 0x24ea, 0x2500, 0x2595, - 0x25a0, 0x25ef, + 0x25a0, 0x25f7, 0x2600, 0x2613, - 0x261a, 0x266f, + 0x2619, 0x2671, 0x2701, 0x2704, 0x2706, 0x2709, 0x270c, 0x2727, @@ -25232,14 +27102,19 @@ static const OnigCodePoint CR_Age_2_1[] = { 0x2776, 0x2794, 0x2798, 0x27af, 0x27b1, 0x27be, - 0x3000, 0x3037, - 0x303f, 0x303f, + 0x2800, 0x28ff, + 0x2e80, 0x2e99, + 0x2e9b, 0x2ef3, + 0x2f00, 0x2fd5, + 0x2ff0, 0x2ffb, + 0x3000, 0x303a, + 0x303e, 0x303f, 0x3041, 0x3094, 0x3099, 0x309e, 0x30a1, 0x30fe, 0x3105, 0x312c, 0x3131, 0x318e, - 0x3190, 0x319f, + 0x3190, 0x31b7, 0x3200, 0x321c, 0x3220, 0x3243, 0x3260, 0x327b, @@ -25249,12 +27124,19 @@ static const OnigCodePoint CR_Age_2_1[] = { 0x3300, 0x3376, 0x337b, 0x33dd, 0x33e0, 0x33fe, + 0x3400, 0x4db5, 0x4e00, 0x9fa5, + 0xa000, 0xa48c, + 0xa490, 0xa4a1, + 0xa4a4, 0xa4b3, + 0xa4b5, 0xa4c0, + 0xa4c2, 0xa4c4, + 0xa4c6, 0xa4c6, 0xac00, 0xd7a3, 0xd800, 0xfa2d, 0xfb00, 0xfb06, 0xfb13, 0xfb17, - 0xfb1e, 0xfb36, + 0xfb1d, 0xfb36, 0xfb38, 0xfb3c, 0xfb3e, 0xfb3e, 0xfb40, 0xfb41, @@ -25263,7 +27145,7 @@ static const OnigCodePoint CR_Age_2_1[] = { 0xfbd3, 0xfd3f, 0xfd50, 0xfd8f, 0xfd92, 0xfdc7, - 0xfdf0, 0xfdfb, + 0xfdd0, 0xfdfb, 0xfe20, 0xfe23, 0xfe30, 0xfe44, 0xfe49, 0xfe52, @@ -25281,8 +27163,39 @@ static const OnigCodePoint CR_Age_2_1[] = { 0xffda, 0xffdc, 0xffe0, 0xffe6, 0xffe8, 0xffee, - 0xfffc, 0xffff, - 0x1fffe, 0x1ffff, + 0xfff9, 0xffff, + 0x10300, 0x1031e, + 0x10320, 0x10323, + 0x10330, 0x1034a, + 0x10400, 0x10425, + 0x10428, 0x1044d, + 0x1d000, 0x1d0f5, + 0x1d100, 0x1d126, + 0x1d12a, 0x1d1dd, + 0x1d400, 0x1d454, + 0x1d456, 0x1d49c, + 0x1d49e, 0x1d49f, + 0x1d4a2, 0x1d4a2, + 0x1d4a5, 0x1d4a6, + 0x1d4a9, 0x1d4ac, + 0x1d4ae, 0x1d4b9, + 0x1d4bb, 0x1d4bb, + 0x1d4bd, 0x1d4c0, + 0x1d4c2, 0x1d4c3, + 0x1d4c5, 0x1d505, + 0x1d507, 0x1d50a, + 0x1d50d, 0x1d514, + 0x1d516, 0x1d51c, + 0x1d51e, 0x1d539, + 0x1d53b, 0x1d53e, + 0x1d540, 0x1d544, + 0x1d546, 0x1d546, + 0x1d54a, 0x1d550, + 0x1d552, 0x1d6a3, + 0x1d6a8, 0x1d7c9, + 0x1d7ce, 0x1d7ff, + 0x1fffe, 0x2a6d6, + 0x2f800, 0x2fa1d, 0x2fffe, 0x2ffff, 0x3fffe, 0x3ffff, 0x4fffe, 0x4ffff, @@ -25295,18 +27208,20 @@ static const OnigCodePoint CR_Age_2_1[] = { 0xbfffe, 0xbffff, 0xcfffe, 0xcffff, 0xdfffe, 0xdffff, + 0xe0001, 0xe0001, + 0xe0020, 0xe007f, 0xefffe, 0x10ffff, -}; /* CR_Age_2_1 */ +}; /* CR_Age_3_1 */ -/* 'Age_3_0': Derived Age 3.0 */ -static const OnigCodePoint CR_Age_3_0[] = { - 369, - 0x0000, 0x021f, +/* 'Age_3_2': Derived Age 3.2 */ +static const OnigCodePoint CR_Age_3_2[] = { + 397, + 0x0000, 0x0220, 0x0222, 0x0233, 0x0250, 0x02ad, 0x02b0, 0x02ee, - 0x0300, 0x034e, - 0x0360, 0x0362, + 0x0300, 0x034f, + 0x0360, 0x036f, 0x0374, 0x0375, 0x037a, 0x037a, 0x037e, 0x037e, @@ -25314,15 +27229,12 @@ static const OnigCodePoint CR_Age_3_0[] = { 0x038c, 0x038c, 0x038e, 0x03a1, 0x03a3, 0x03ce, - 0x03d0, 0x03d7, - 0x03da, 0x03f3, + 0x03d0, 0x03f6, 0x0400, 0x0486, - 0x0488, 0x0489, - 0x048c, 0x04c4, - 0x04c7, 0x04c8, - 0x04cb, 0x04cc, + 0x0488, 0x04ce, 0x04d0, 0x04f5, 0x04f8, 0x04f9, + 0x0500, 0x050f, 0x0531, 0x0556, 0x0559, 0x055f, 0x0561, 0x0587, @@ -25337,13 +27249,12 @@ static const OnigCodePoint CR_Age_3_0[] = { 0x061f, 0x061f, 0x0621, 0x063a, 0x0640, 0x0655, - 0x0660, 0x066d, - 0x0670, 0x06ed, + 0x0660, 0x06ed, 0x06f0, 0x06fe, 0x0700, 0x070d, 0x070f, 0x072c, 0x0730, 0x074a, - 0x0780, 0x07b0, + 0x0780, 0x07b1, 0x0901, 0x0903, 0x0905, 0x0939, 0x093c, 0x094d, @@ -25504,7 +27415,7 @@ static const OnigCodePoint CR_Age_3_0[] = { 0x1036, 0x1039, 0x1040, 0x1059, 0x10a0, 0x10c5, - 0x10d0, 0x10f6, + 0x10d0, 0x10f8, 0x10fb, 0x10fb, 0x1100, 0x1159, 0x115f, 0x11a2, @@ -25539,6 +27450,13 @@ static const OnigCodePoint CR_Age_3_0[] = { 0x1401, 0x1676, 0x1680, 0x169c, 0x16a0, 0x16f0, + 0x1700, 0x170c, + 0x170e, 0x1714, + 0x1720, 0x1736, + 0x1740, 0x1753, + 0x1760, 0x176c, + 0x176e, 0x1770, + 0x1772, 0x1773, 0x1780, 0x17dc, 0x17e0, 0x17e9, 0x1800, 0x180e, @@ -25563,25 +27481,24 @@ static const OnigCodePoint CR_Age_3_0[] = { 0x1fdd, 0x1fef, 0x1ff2, 0x1ff4, 0x1ff6, 0x1ffe, - 0x2000, 0x2046, - 0x2048, 0x204d, - 0x206a, 0x2070, + 0x2000, 0x2052, + 0x2057, 0x2057, + 0x205f, 0x2063, + 0x206a, 0x2071, 0x2074, 0x208e, - 0x20a0, 0x20af, - 0x20d0, 0x20e3, + 0x20a0, 0x20b1, + 0x20d0, 0x20ea, 0x2100, 0x213a, + 0x213d, 0x214b, 0x2153, 0x2183, - 0x2190, 0x21f3, - 0x2200, 0x22f1, - 0x2300, 0x237b, - 0x237d, 0x239a, + 0x2190, 0x23ce, 0x2400, 0x2426, 0x2440, 0x244a, - 0x2460, 0x24ea, - 0x2500, 0x2595, - 0x25a0, 0x25f7, - 0x2600, 0x2613, - 0x2619, 0x2671, + 0x2460, 0x24fe, + 0x2500, 0x2613, + 0x2616, 0x2617, + 0x2619, 0x267d, + 0x2680, 0x2689, 0x2701, 0x2704, 0x2706, 0x2709, 0x270c, 0x2727, @@ -25590,28 +27507,25 @@ static const OnigCodePoint CR_Age_3_0[] = { 0x274f, 0x2752, 0x2756, 0x2756, 0x2758, 0x275e, - 0x2761, 0x2767, - 0x2776, 0x2794, + 0x2761, 0x2794, 0x2798, 0x27af, 0x27b1, 0x27be, - 0x2800, 0x28ff, + 0x27d0, 0x27eb, + 0x27f0, 0x2aff, 0x2e80, 0x2e99, 0x2e9b, 0x2ef3, 0x2f00, 0x2fd5, 0x2ff0, 0x2ffb, - 0x3000, 0x303a, - 0x303e, 0x303f, - 0x3041, 0x3094, - 0x3099, 0x309e, - 0x30a1, 0x30fe, + 0x3000, 0x303f, + 0x3041, 0x3096, + 0x3099, 0x30ff, 0x3105, 0x312c, 0x3131, 0x318e, 0x3190, 0x31b7, - 0x3200, 0x321c, + 0x31f0, 0x321c, 0x3220, 0x3243, - 0x3260, 0x327b, - 0x327f, 0x32b0, - 0x32c0, 0x32cb, + 0x3251, 0x327b, + 0x327f, 0x32cb, 0x32d0, 0x32fe, 0x3300, 0x3376, 0x337b, 0x33dd, @@ -25619,13 +27533,10 @@ static const OnigCodePoint CR_Age_3_0[] = { 0x3400, 0x4db5, 0x4e00, 0x9fa5, 0xa000, 0xa48c, - 0xa490, 0xa4a1, - 0xa4a4, 0xa4b3, - 0xa4b5, 0xa4c0, - 0xa4c2, 0xa4c4, - 0xa4c6, 0xa4c6, + 0xa490, 0xa4c6, 0xac00, 0xd7a3, 0xd800, 0xfa2d, + 0xfa30, 0xfa6a, 0xfb00, 0xfb06, 0xfb13, 0xfb17, 0xfb1d, 0xfb36, @@ -25637,18 +27548,17 @@ static const OnigCodePoint CR_Age_3_0[] = { 0xfbd3, 0xfd3f, 0xfd50, 0xfd8f, 0xfd92, 0xfdc7, - 0xfdf0, 0xfdfb, + 0xfdd0, 0xfdfc, + 0xfe00, 0xfe0f, 0xfe20, 0xfe23, - 0xfe30, 0xfe44, + 0xfe30, 0xfe46, 0xfe49, 0xfe52, 0xfe54, 0xfe66, 0xfe68, 0xfe6b, - 0xfe70, 0xfe72, - 0xfe74, 0xfe74, + 0xfe70, 0xfe74, 0xfe76, 0xfefc, 0xfeff, 0xfeff, - 0xff01, 0xff5e, - 0xff61, 0xffbe, + 0xff01, 0xffbe, 0xffc2, 0xffc7, 0xffca, 0xffcf, 0xffd2, 0xffd7, @@ -25656,7 +27566,38 @@ static const OnigCodePoint CR_Age_3_0[] = { 0xffe0, 0xffe6, 0xffe8, 0xffee, 0xfff9, 0xffff, - 0x1fffe, 0x1ffff, + 0x10300, 0x1031e, + 0x10320, 0x10323, + 0x10330, 0x1034a, + 0x10400, 0x10425, + 0x10428, 0x1044d, + 0x1d000, 0x1d0f5, + 0x1d100, 0x1d126, + 0x1d12a, 0x1d1dd, + 0x1d400, 0x1d454, + 0x1d456, 0x1d49c, + 0x1d49e, 0x1d49f, + 0x1d4a2, 0x1d4a2, + 0x1d4a5, 0x1d4a6, + 0x1d4a9, 0x1d4ac, + 0x1d4ae, 0x1d4b9, + 0x1d4bb, 0x1d4bb, + 0x1d4bd, 0x1d4c0, + 0x1d4c2, 0x1d4c3, + 0x1d4c5, 0x1d505, + 0x1d507, 0x1d50a, + 0x1d50d, 0x1d514, + 0x1d516, 0x1d51c, + 0x1d51e, 0x1d539, + 0x1d53b, 0x1d53e, + 0x1d540, 0x1d544, + 0x1d546, 0x1d546, + 0x1d54a, 0x1d550, + 0x1d552, 0x1d6a3, + 0x1d6a8, 0x1d7c9, + 0x1d7ce, 0x1d7ff, + 0x1fffe, 0x2a6d6, + 0x2f800, 0x2fa1d, 0x2fffe, 0x2ffff, 0x3fffe, 0x3ffff, 0x4fffe, 0x4ffff, @@ -25669,18 +27610,17 @@ static const OnigCodePoint CR_Age_3_0[] = { 0xbfffe, 0xbffff, 0xcfffe, 0xcffff, 0xdfffe, 0xdffff, + 0xe0001, 0xe0001, + 0xe0020, 0xe007f, 0xefffe, 0x10ffff, -}; /* CR_Age_3_0 */ +}; /* CR_Age_3_2 */ -/* 'Age_3_1': Derived Age 3.1 */ -static const OnigCodePoint CR_Age_3_1[] = { - 402, - 0x0000, 0x021f, - 0x0222, 0x0233, - 0x0250, 0x02ad, - 0x02b0, 0x02ee, - 0x0300, 0x034e, - 0x0360, 0x0362, +/* 'Age_4_0': Derived Age 4.0 */ +static const OnigCodePoint CR_Age_4_0[] = { + 412, + 0x0000, 0x0236, + 0x0250, 0x0357, + 0x035d, 0x036f, 0x0374, 0x0375, 0x037a, 0x037a, 0x037e, 0x037e, @@ -25688,15 +27628,12 @@ static const OnigCodePoint CR_Age_3_1[] = { 0x038c, 0x038c, 0x038e, 0x03a1, 0x03a3, 0x03ce, - 0x03d0, 0x03d7, - 0x03da, 0x03f5, + 0x03d0, 0x03fb, 0x0400, 0x0486, - 0x0488, 0x0489, - 0x048c, 0x04c4, - 0x04c7, 0x04c8, - 0x04cb, 0x04cc, + 0x0488, 0x04ce, 0x04d0, 0x04f5, 0x04f8, 0x04f9, + 0x0500, 0x050f, 0x0531, 0x0556, 0x0559, 0x055f, 0x0561, 0x0587, @@ -25706,20 +27643,17 @@ static const OnigCodePoint CR_Age_3_1[] = { 0x05bb, 0x05c4, 0x05d0, 0x05ea, 0x05f0, 0x05f4, - 0x060c, 0x060c, + 0x0600, 0x0603, + 0x060c, 0x0615, 0x061b, 0x061b, 0x061f, 0x061f, 0x0621, 0x063a, - 0x0640, 0x0655, - 0x0660, 0x066d, - 0x0670, 0x06ed, - 0x06f0, 0x06fe, - 0x0700, 0x070d, - 0x070f, 0x072c, - 0x0730, 0x074a, - 0x0780, 0x07b0, - 0x0901, 0x0903, - 0x0905, 0x0939, + 0x0640, 0x0658, + 0x0660, 0x070d, + 0x070f, 0x074a, + 0x074d, 0x074f, + 0x0780, 0x07b1, + 0x0901, 0x0939, 0x093c, 0x094d, 0x0950, 0x0954, 0x0958, 0x0970, @@ -25730,15 +27664,14 @@ static const OnigCodePoint CR_Age_3_1[] = { 0x09aa, 0x09b0, 0x09b2, 0x09b2, 0x09b6, 0x09b9, - 0x09bc, 0x09bc, - 0x09be, 0x09c4, + 0x09bc, 0x09c4, 0x09c7, 0x09c8, 0x09cb, 0x09cd, 0x09d7, 0x09d7, 0x09dc, 0x09dd, 0x09df, 0x09e3, 0x09e6, 0x09fa, - 0x0a02, 0x0a02, + 0x0a01, 0x0a03, 0x0a05, 0x0a0a, 0x0a0f, 0x0a10, 0x0a13, 0x0a28, @@ -25754,8 +27687,7 @@ static const OnigCodePoint CR_Age_3_1[] = { 0x0a5e, 0x0a5e, 0x0a66, 0x0a74, 0x0a81, 0x0a83, - 0x0a85, 0x0a8b, - 0x0a8d, 0x0a8d, + 0x0a85, 0x0a8d, 0x0a8f, 0x0a91, 0x0a93, 0x0aa8, 0x0aaa, 0x0ab0, @@ -25765,22 +27697,23 @@ static const OnigCodePoint CR_Age_3_1[] = { 0x0ac7, 0x0ac9, 0x0acb, 0x0acd, 0x0ad0, 0x0ad0, - 0x0ae0, 0x0ae0, + 0x0ae0, 0x0ae3, 0x0ae6, 0x0aef, + 0x0af1, 0x0af1, 0x0b01, 0x0b03, 0x0b05, 0x0b0c, 0x0b0f, 0x0b10, 0x0b13, 0x0b28, 0x0b2a, 0x0b30, 0x0b32, 0x0b33, - 0x0b36, 0x0b39, + 0x0b35, 0x0b39, 0x0b3c, 0x0b43, 0x0b47, 0x0b48, 0x0b4b, 0x0b4d, 0x0b56, 0x0b57, 0x0b5c, 0x0b5d, 0x0b5f, 0x0b61, - 0x0b66, 0x0b70, + 0x0b66, 0x0b71, 0x0b82, 0x0b83, 0x0b85, 0x0b8a, 0x0b8e, 0x0b90, @@ -25796,7 +27729,7 @@ static const OnigCodePoint CR_Age_3_1[] = { 0x0bc6, 0x0bc8, 0x0bca, 0x0bcd, 0x0bd7, 0x0bd7, - 0x0be7, 0x0bf2, + 0x0be7, 0x0bfa, 0x0c01, 0x0c03, 0x0c05, 0x0c0c, 0x0c0e, 0x0c10, @@ -25815,7 +27748,7 @@ static const OnigCodePoint CR_Age_3_1[] = { 0x0c92, 0x0ca8, 0x0caa, 0x0cb3, 0x0cb5, 0x0cb9, - 0x0cbe, 0x0cc4, + 0x0cbc, 0x0cc4, 0x0cc6, 0x0cc8, 0x0cca, 0x0ccd, 0x0cd5, 0x0cd6, @@ -25878,7 +27811,7 @@ static const OnigCodePoint CR_Age_3_1[] = { 0x1036, 0x1039, 0x1040, 0x1059, 0x10a0, 0x10c5, - 0x10d0, 0x10f6, + 0x10d0, 0x10f8, 0x10fb, 0x10fb, 0x1100, 0x1159, 0x115f, 0x11a2, @@ -25913,12 +27846,28 @@ static const OnigCodePoint CR_Age_3_1[] = { 0x1401, 0x1676, 0x1680, 0x169c, 0x16a0, 0x16f0, - 0x1780, 0x17dc, + 0x1700, 0x170c, + 0x170e, 0x1714, + 0x1720, 0x1736, + 0x1740, 0x1753, + 0x1760, 0x176c, + 0x176e, 0x1770, + 0x1772, 0x1773, + 0x1780, 0x17dd, 0x17e0, 0x17e9, + 0x17f0, 0x17f9, 0x1800, 0x180e, 0x1810, 0x1819, 0x1820, 0x1877, 0x1880, 0x18a9, + 0x1900, 0x191c, + 0x1920, 0x192b, + 0x1930, 0x193b, + 0x1940, 0x1940, + 0x1944, 0x196d, + 0x1970, 0x1974, + 0x19e0, 0x19ff, + 0x1d00, 0x1d6b, 0x1e00, 0x1e9b, 0x1ea0, 0x1ef9, 0x1f00, 0x1f15, @@ -25937,25 +27886,23 @@ static const OnigCodePoint CR_Age_3_1[] = { 0x1fdd, 0x1fef, 0x1ff2, 0x1ff4, 0x1ff6, 0x1ffe, - 0x2000, 0x2046, - 0x2048, 0x204d, - 0x206a, 0x2070, + 0x2000, 0x2054, + 0x2057, 0x2057, + 0x205f, 0x2063, + 0x206a, 0x2071, 0x2074, 0x208e, - 0x20a0, 0x20af, - 0x20d0, 0x20e3, - 0x2100, 0x213a, + 0x20a0, 0x20b1, + 0x20d0, 0x20ea, + 0x2100, 0x213b, + 0x213d, 0x214b, 0x2153, 0x2183, - 0x2190, 0x21f3, - 0x2200, 0x22f1, - 0x2300, 0x237b, - 0x237d, 0x239a, + 0x2190, 0x23d0, 0x2400, 0x2426, 0x2440, 0x244a, - 0x2460, 0x24ea, - 0x2500, 0x2595, - 0x25a0, 0x25f7, - 0x2600, 0x2613, - 0x2619, 0x2671, + 0x2460, 0x2617, + 0x2619, 0x267d, + 0x2680, 0x2691, + 0x26a0, 0x26a1, 0x2701, 0x2704, 0x2706, 0x2709, 0x270c, 0x2727, @@ -25964,42 +27911,32 @@ static const OnigCodePoint CR_Age_3_1[] = { 0x274f, 0x2752, 0x2756, 0x2756, 0x2758, 0x275e, - 0x2761, 0x2767, - 0x2776, 0x2794, + 0x2761, 0x2794, 0x2798, 0x27af, 0x27b1, 0x27be, - 0x2800, 0x28ff, + 0x27d0, 0x27eb, + 0x27f0, 0x2b0d, 0x2e80, 0x2e99, 0x2e9b, 0x2ef3, 0x2f00, 0x2fd5, 0x2ff0, 0x2ffb, - 0x3000, 0x303a, - 0x303e, 0x303f, - 0x3041, 0x3094, - 0x3099, 0x309e, - 0x30a1, 0x30fe, + 0x3000, 0x303f, + 0x3041, 0x3096, + 0x3099, 0x30ff, 0x3105, 0x312c, 0x3131, 0x318e, 0x3190, 0x31b7, - 0x3200, 0x321c, + 0x31f0, 0x321e, 0x3220, 0x3243, - 0x3260, 0x327b, - 0x327f, 0x32b0, - 0x32c0, 0x32cb, - 0x32d0, 0x32fe, - 0x3300, 0x3376, - 0x337b, 0x33dd, - 0x33e0, 0x33fe, - 0x3400, 0x4db5, - 0x4e00, 0x9fa5, + 0x3250, 0x327d, + 0x327f, 0x32fe, + 0x3300, 0x4db5, + 0x4dc0, 0x9fa5, 0xa000, 0xa48c, - 0xa490, 0xa4a1, - 0xa4a4, 0xa4b3, - 0xa4b5, 0xa4c0, - 0xa4c2, 0xa4c4, - 0xa4c6, 0xa4c6, + 0xa490, 0xa4c6, 0xac00, 0xd7a3, 0xd800, 0xfa2d, + 0xfa30, 0xfa6a, 0xfb00, 0xfb06, 0xfb13, 0xfb17, 0xfb1d, 0xfb36, @@ -26011,33 +27948,49 @@ static const OnigCodePoint CR_Age_3_1[] = { 0xfbd3, 0xfd3f, 0xfd50, 0xfd8f, 0xfd92, 0xfdc7, - 0xfdd0, 0xfdfb, + 0xfdd0, 0xfdfd, + 0xfe00, 0xfe0f, 0xfe20, 0xfe23, - 0xfe30, 0xfe44, - 0xfe49, 0xfe52, + 0xfe30, 0xfe52, 0xfe54, 0xfe66, 0xfe68, 0xfe6b, - 0xfe70, 0xfe72, - 0xfe74, 0xfe74, + 0xfe70, 0xfe74, 0xfe76, 0xfefc, 0xfeff, 0xfeff, - 0xff01, 0xff5e, - 0xff61, 0xffbe, + 0xff01, 0xffbe, 0xffc2, 0xffc7, 0xffca, 0xffcf, 0xffd2, 0xffd7, 0xffda, 0xffdc, 0xffe0, 0xffe6, 0xffe8, 0xffee, - 0xfff9, 0xffff, + 0xfff9, 0x1000b, + 0x1000d, 0x10026, + 0x10028, 0x1003a, + 0x1003c, 0x1003d, + 0x1003f, 0x1004d, + 0x10050, 0x1005d, + 0x10080, 0x100fa, + 0x10100, 0x10102, + 0x10107, 0x10133, + 0x10137, 0x1013f, 0x10300, 0x1031e, 0x10320, 0x10323, 0x10330, 0x1034a, - 0x10400, 0x10425, - 0x10428, 0x1044d, + 0x10380, 0x1039d, + 0x1039f, 0x1039f, + 0x10400, 0x1049d, + 0x104a0, 0x104a9, + 0x10800, 0x10805, + 0x10808, 0x10808, + 0x1080a, 0x10835, + 0x10837, 0x10838, + 0x1083c, 0x1083c, + 0x1083f, 0x1083f, 0x1d000, 0x1d0f5, 0x1d100, 0x1d126, 0x1d12a, 0x1d1dd, + 0x1d300, 0x1d356, 0x1d400, 0x1d454, 0x1d456, 0x1d49c, 0x1d49e, 0x1d49f, @@ -26046,8 +27999,7 @@ static const OnigCodePoint CR_Age_3_1[] = { 0x1d4a9, 0x1d4ac, 0x1d4ae, 0x1d4b9, 0x1d4bb, 0x1d4bb, - 0x1d4bd, 0x1d4c0, - 0x1d4c2, 0x1d4c3, + 0x1d4bd, 0x1d4c3, 0x1d4c5, 0x1d505, 0x1d507, 0x1d50a, 0x1d50d, 0x1d514, @@ -26076,18 +28028,15 @@ static const OnigCodePoint CR_Age_3_1[] = { 0xdfffe, 0xdffff, 0xe0001, 0xe0001, 0xe0020, 0xe007f, + 0xe0100, 0xe01ef, 0xefffe, 0x10ffff, -}; /* CR_Age_3_1 */ +}; /* CR_Age_4_0 */ -/* 'Age_3_2': Derived Age 3.2 */ -static const OnigCodePoint CR_Age_3_2[] = { - 397, - 0x0000, 0x0220, - 0x0222, 0x0233, - 0x0250, 0x02ad, - 0x02b0, 0x02ee, - 0x0300, 0x034f, - 0x0360, 0x036f, +/* 'Age_4_1': Derived Age 4.1 */ +static const OnigCodePoint CR_Age_4_1[] = { + 430, + 0x0000, 0x0241, + 0x0250, 0x036f, 0x0374, 0x0375, 0x037a, 0x037a, 0x037e, 0x037e, @@ -26095,37 +28044,33 @@ static const OnigCodePoint CR_Age_3_2[] = { 0x038c, 0x038c, 0x038e, 0x03a1, 0x03a3, 0x03ce, - 0x03d0, 0x03f6, - 0x0400, 0x0486, + 0x03d0, 0x0486, 0x0488, 0x04ce, - 0x04d0, 0x04f5, - 0x04f8, 0x04f9, + 0x04d0, 0x04f9, 0x0500, 0x050f, 0x0531, 0x0556, 0x0559, 0x055f, 0x0561, 0x0587, 0x0589, 0x058a, - 0x0591, 0x05a1, - 0x05a3, 0x05b9, - 0x05bb, 0x05c4, + 0x0591, 0x05b9, + 0x05bb, 0x05c7, 0x05d0, 0x05ea, 0x05f0, 0x05f4, - 0x060c, 0x060c, + 0x0600, 0x0603, + 0x060b, 0x0615, 0x061b, 0x061b, - 0x061f, 0x061f, + 0x061e, 0x061f, 0x0621, 0x063a, - 0x0640, 0x0655, - 0x0660, 0x06ed, - 0x06f0, 0x06fe, - 0x0700, 0x070d, - 0x070f, 0x072c, - 0x0730, 0x074a, + 0x0640, 0x065e, + 0x0660, 0x070d, + 0x070f, 0x074a, + 0x074d, 0x076d, 0x0780, 0x07b1, - 0x0901, 0x0903, - 0x0905, 0x0939, + 0x0901, 0x0939, 0x093c, 0x094d, 0x0950, 0x0954, 0x0958, 0x0970, + 0x097d, 0x097d, 0x0981, 0x0983, 0x0985, 0x098c, 0x098f, 0x0990, @@ -26133,15 +28078,14 @@ static const OnigCodePoint CR_Age_3_2[] = { 0x09aa, 0x09b0, 0x09b2, 0x09b2, 0x09b6, 0x09b9, - 0x09bc, 0x09bc, - 0x09be, 0x09c4, + 0x09bc, 0x09c4, 0x09c7, 0x09c8, - 0x09cb, 0x09cd, + 0x09cb, 0x09ce, 0x09d7, 0x09d7, 0x09dc, 0x09dd, 0x09df, 0x09e3, 0x09e6, 0x09fa, - 0x0a02, 0x0a02, + 0x0a01, 0x0a03, 0x0a05, 0x0a0a, 0x0a0f, 0x0a10, 0x0a13, 0x0a28, @@ -26157,8 +28101,7 @@ static const OnigCodePoint CR_Age_3_2[] = { 0x0a5e, 0x0a5e, 0x0a66, 0x0a74, 0x0a81, 0x0a83, - 0x0a85, 0x0a8b, - 0x0a8d, 0x0a8d, + 0x0a85, 0x0a8d, 0x0a8f, 0x0a91, 0x0a93, 0x0aa8, 0x0aaa, 0x0ab0, @@ -26168,22 +28111,23 @@ static const OnigCodePoint CR_Age_3_2[] = { 0x0ac7, 0x0ac9, 0x0acb, 0x0acd, 0x0ad0, 0x0ad0, - 0x0ae0, 0x0ae0, + 0x0ae0, 0x0ae3, 0x0ae6, 0x0aef, + 0x0af1, 0x0af1, 0x0b01, 0x0b03, 0x0b05, 0x0b0c, 0x0b0f, 0x0b10, 0x0b13, 0x0b28, 0x0b2a, 0x0b30, 0x0b32, 0x0b33, - 0x0b36, 0x0b39, + 0x0b35, 0x0b39, 0x0b3c, 0x0b43, 0x0b47, 0x0b48, 0x0b4b, 0x0b4d, 0x0b56, 0x0b57, 0x0b5c, 0x0b5d, 0x0b5f, 0x0b61, - 0x0b66, 0x0b70, + 0x0b66, 0x0b71, 0x0b82, 0x0b83, 0x0b85, 0x0b8a, 0x0b8e, 0x0b90, @@ -26193,13 +28137,12 @@ static const OnigCodePoint CR_Age_3_2[] = { 0x0b9e, 0x0b9f, 0x0ba3, 0x0ba4, 0x0ba8, 0x0baa, - 0x0bae, 0x0bb5, - 0x0bb7, 0x0bb9, + 0x0bae, 0x0bb9, 0x0bbe, 0x0bc2, 0x0bc6, 0x0bc8, 0x0bca, 0x0bcd, 0x0bd7, 0x0bd7, - 0x0be7, 0x0bf2, + 0x0be6, 0x0bfa, 0x0c01, 0x0c03, 0x0c05, 0x0c0c, 0x0c0e, 0x0c10, @@ -26218,7 +28161,7 @@ static const OnigCodePoint CR_Age_3_2[] = { 0x0c92, 0x0ca8, 0x0caa, 0x0cb3, 0x0cb5, 0x0cb9, - 0x0cbe, 0x0cc4, + 0x0cbc, 0x0cc4, 0x0cc6, 0x0cc8, 0x0cca, 0x0ccd, 0x0cd5, 0x0cd6, @@ -26273,7 +28216,7 @@ static const OnigCodePoint CR_Age_3_2[] = { 0x0f90, 0x0f97, 0x0f99, 0x0fbc, 0x0fbe, 0x0fcc, - 0x0fcf, 0x0fcf, + 0x0fcf, 0x0fd1, 0x1000, 0x1021, 0x1023, 0x1027, 0x1029, 0x102a, @@ -26281,37 +28224,28 @@ static const OnigCodePoint CR_Age_3_2[] = { 0x1036, 0x1039, 0x1040, 0x1059, 0x10a0, 0x10c5, - 0x10d0, 0x10f8, - 0x10fb, 0x10fb, + 0x10d0, 0x10fc, 0x1100, 0x1159, 0x115f, 0x11a2, 0x11a8, 0x11f9, - 0x1200, 0x1206, - 0x1208, 0x1246, - 0x1248, 0x1248, + 0x1200, 0x1248, 0x124a, 0x124d, 0x1250, 0x1256, 0x1258, 0x1258, 0x125a, 0x125d, - 0x1260, 0x1286, - 0x1288, 0x1288, + 0x1260, 0x1288, 0x128a, 0x128d, - 0x1290, 0x12ae, - 0x12b0, 0x12b0, + 0x1290, 0x12b0, 0x12b2, 0x12b5, 0x12b8, 0x12be, 0x12c0, 0x12c0, 0x12c2, 0x12c5, - 0x12c8, 0x12ce, - 0x12d0, 0x12d6, - 0x12d8, 0x12ee, - 0x12f0, 0x130e, - 0x1310, 0x1310, + 0x12c8, 0x12d6, + 0x12d8, 0x1310, 0x1312, 0x1315, - 0x1318, 0x131e, - 0x1320, 0x1346, - 0x1348, 0x135a, - 0x1361, 0x137c, + 0x1318, 0x135a, + 0x135f, 0x137c, + 0x1380, 0x1399, 0x13a0, 0x13f4, 0x1401, 0x1676, 0x1680, 0x169c, @@ -26323,12 +28257,25 @@ static const OnigCodePoint CR_Age_3_2[] = { 0x1760, 0x176c, 0x176e, 0x1770, 0x1772, 0x1773, - 0x1780, 0x17dc, + 0x1780, 0x17dd, 0x17e0, 0x17e9, + 0x17f0, 0x17f9, 0x1800, 0x180e, 0x1810, 0x1819, 0x1820, 0x1877, 0x1880, 0x18a9, + 0x1900, 0x191c, + 0x1920, 0x192b, + 0x1930, 0x193b, + 0x1940, 0x1940, + 0x1944, 0x196d, + 0x1970, 0x1974, + 0x1980, 0x19a9, + 0x19b0, 0x19c9, + 0x19d0, 0x19d9, + 0x19de, 0x1a1b, + 0x1a1e, 0x1a1f, + 0x1d00, 0x1dc3, 0x1e00, 0x1e9b, 0x1ea0, 0x1ef9, 0x1f00, 0x1f15, @@ -26347,24 +28294,19 @@ static const OnigCodePoint CR_Age_3_2[] = { 0x1fdd, 0x1fef, 0x1ff2, 0x1ff4, 0x1ff6, 0x1ffe, - 0x2000, 0x2052, - 0x2057, 0x2057, - 0x205f, 0x2063, + 0x2000, 0x2063, 0x206a, 0x2071, 0x2074, 0x208e, - 0x20a0, 0x20b1, - 0x20d0, 0x20ea, - 0x2100, 0x213a, - 0x213d, 0x214b, + 0x2090, 0x2094, + 0x20a0, 0x20b5, + 0x20d0, 0x20eb, + 0x2100, 0x214c, 0x2153, 0x2183, - 0x2190, 0x23ce, + 0x2190, 0x23db, 0x2400, 0x2426, 0x2440, 0x244a, - 0x2460, 0x24fe, - 0x2500, 0x2613, - 0x2616, 0x2617, - 0x2619, 0x267d, - 0x2680, 0x2689, + 0x2460, 0x269c, + 0x26a0, 0x26b1, 0x2701, 0x2704, 0x2706, 0x2709, 0x270c, 0x2727, @@ -26376,8 +28318,26 @@ static const OnigCodePoint CR_Age_3_2[] = { 0x2761, 0x2794, 0x2798, 0x27af, 0x27b1, 0x27be, + 0x27c0, 0x27c6, 0x27d0, 0x27eb, - 0x27f0, 0x2aff, + 0x27f0, 0x2b13, + 0x2c00, 0x2c2e, + 0x2c30, 0x2c5e, + 0x2c80, 0x2cea, + 0x2cf9, 0x2d25, + 0x2d30, 0x2d65, + 0x2d6f, 0x2d6f, + 0x2d80, 0x2d96, + 0x2da0, 0x2da6, + 0x2da8, 0x2dae, + 0x2db0, 0x2db6, + 0x2db8, 0x2dbe, + 0x2dc0, 0x2dc6, + 0x2dc8, 0x2dce, + 0x2dd0, 0x2dd6, + 0x2dd8, 0x2dde, + 0x2e00, 0x2e17, + 0x2e1c, 0x2e1d, 0x2e80, 0x2e99, 0x2e9b, 0x2ef3, 0x2f00, 0x2fd5, @@ -26388,21 +28348,20 @@ static const OnigCodePoint CR_Age_3_2[] = { 0x3105, 0x312c, 0x3131, 0x318e, 0x3190, 0x31b7, - 0x31f0, 0x321c, + 0x31c0, 0x31cf, + 0x31f0, 0x321e, 0x3220, 0x3243, - 0x3251, 0x327b, - 0x327f, 0x32cb, - 0x32d0, 0x32fe, - 0x3300, 0x3376, - 0x337b, 0x33dd, - 0x33e0, 0x33fe, - 0x3400, 0x4db5, - 0x4e00, 0x9fa5, + 0x3250, 0x32fe, + 0x3300, 0x4db5, + 0x4dc0, 0x9fbb, 0xa000, 0xa48c, 0xa490, 0xa4c6, + 0xa700, 0xa716, + 0xa800, 0xa82b, 0xac00, 0xd7a3, 0xd800, 0xfa2d, 0xfa30, 0xfa6a, + 0xfa70, 0xfad9, 0xfb00, 0xfb06, 0xfb13, 0xfb17, 0xfb1d, 0xfb36, @@ -26414,11 +28373,10 @@ static const OnigCodePoint CR_Age_3_2[] = { 0xfbd3, 0xfd3f, 0xfd50, 0xfd8f, 0xfd92, 0xfdc7, - 0xfdd0, 0xfdfc, - 0xfe00, 0xfe0f, + 0xfdd0, 0xfdfd, + 0xfe00, 0xfe19, 0xfe20, 0xfe23, - 0xfe30, 0xfe46, - 0xfe49, 0xfe52, + 0xfe30, 0xfe52, 0xfe54, 0xfe66, 0xfe68, 0xfe6b, 0xfe70, 0xfe74, @@ -26431,15 +28389,43 @@ static const OnigCodePoint CR_Age_3_2[] = { 0xffda, 0xffdc, 0xffe0, 0xffe6, 0xffe8, 0xffee, - 0xfff9, 0xffff, + 0xfff9, 0x1000b, + 0x1000d, 0x10026, + 0x10028, 0x1003a, + 0x1003c, 0x1003d, + 0x1003f, 0x1004d, + 0x10050, 0x1005d, + 0x10080, 0x100fa, + 0x10100, 0x10102, + 0x10107, 0x10133, + 0x10137, 0x1018a, 0x10300, 0x1031e, 0x10320, 0x10323, 0x10330, 0x1034a, - 0x10400, 0x10425, - 0x10428, 0x1044d, + 0x10380, 0x1039d, + 0x1039f, 0x103c3, + 0x103c8, 0x103d5, + 0x10400, 0x1049d, + 0x104a0, 0x104a9, + 0x10800, 0x10805, + 0x10808, 0x10808, + 0x1080a, 0x10835, + 0x10837, 0x10838, + 0x1083c, 0x1083c, + 0x1083f, 0x1083f, + 0x10a00, 0x10a03, + 0x10a05, 0x10a06, + 0x10a0c, 0x10a13, + 0x10a15, 0x10a17, + 0x10a19, 0x10a33, + 0x10a38, 0x10a3a, + 0x10a3f, 0x10a47, + 0x10a50, 0x10a58, 0x1d000, 0x1d0f5, 0x1d100, 0x1d126, 0x1d12a, 0x1d1dd, + 0x1d200, 0x1d245, + 0x1d300, 0x1d356, 0x1d400, 0x1d454, 0x1d456, 0x1d49c, 0x1d49e, 0x1d49f, @@ -26448,8 +28434,7 @@ static const OnigCodePoint CR_Age_3_2[] = { 0x1d4a9, 0x1d4ac, 0x1d4ae, 0x1d4b9, 0x1d4bb, 0x1d4bb, - 0x1d4bd, 0x1d4c0, - 0x1d4c2, 0x1d4c3, + 0x1d4bd, 0x1d4c3, 0x1d4c5, 0x1d505, 0x1d507, 0x1d50a, 0x1d50d, 0x1d514, @@ -26459,7 +28444,7 @@ static const OnigCodePoint CR_Age_3_2[] = { 0x1d540, 0x1d544, 0x1d546, 0x1d546, 0x1d54a, 0x1d550, - 0x1d552, 0x1d6a3, + 0x1d552, 0x1d6a5, 0x1d6a8, 0x1d7c9, 0x1d7ce, 0x1d7ff, 0x1fffe, 0x2a6d6, @@ -26478,51 +28463,45 @@ static const OnigCodePoint CR_Age_3_2[] = { 0xdfffe, 0xdffff, 0xe0001, 0xe0001, 0xe0020, 0xe007f, + 0xe0100, 0xe01ef, 0xefffe, 0x10ffff, -}; /* CR_Age_3_2 */ +}; /* CR_Age_4_1 */ -/* 'Age_4_0': Derived Age 4.0 */ -static const OnigCodePoint CR_Age_4_0[] = { - 412, - 0x0000, 0x0236, - 0x0250, 0x0357, - 0x035d, 0x036f, +/* 'Age_5_0': Derived Age 5.0 */ +static const OnigCodePoint CR_Age_5_0[] = { + 440, + 0x0000, 0x036f, 0x0374, 0x0375, - 0x037a, 0x037a, - 0x037e, 0x037e, + 0x037a, 0x037e, 0x0384, 0x038a, 0x038c, 0x038c, 0x038e, 0x03a1, 0x03a3, 0x03ce, - 0x03d0, 0x03fb, - 0x0400, 0x0486, - 0x0488, 0x04ce, - 0x04d0, 0x04f5, - 0x04f8, 0x04f9, - 0x0500, 0x050f, + 0x03d0, 0x0486, + 0x0488, 0x0513, 0x0531, 0x0556, 0x0559, 0x055f, 0x0561, 0x0587, 0x0589, 0x058a, - 0x0591, 0x05a1, - 0x05a3, 0x05b9, - 0x05bb, 0x05c4, + 0x0591, 0x05c7, 0x05d0, 0x05ea, 0x05f0, 0x05f4, 0x0600, 0x0603, - 0x060c, 0x0615, + 0x060b, 0x0615, 0x061b, 0x061b, - 0x061f, 0x061f, + 0x061e, 0x061f, 0x0621, 0x063a, - 0x0640, 0x0658, + 0x0640, 0x065e, 0x0660, 0x070d, 0x070f, 0x074a, - 0x074d, 0x074f, + 0x074d, 0x076d, 0x0780, 0x07b1, + 0x07c0, 0x07fa, 0x0901, 0x0939, 0x093c, 0x094d, 0x0950, 0x0954, 0x0958, 0x0970, + 0x097b, 0x097f, 0x0981, 0x0983, 0x0985, 0x098c, 0x098f, 0x0990, @@ -26532,7 +28511,7 @@ static const OnigCodePoint CR_Age_4_0[] = { 0x09b6, 0x09b9, 0x09bc, 0x09c4, 0x09c7, 0x09c8, - 0x09cb, 0x09cd, + 0x09cb, 0x09ce, 0x09d7, 0x09d7, 0x09dc, 0x09dd, 0x09df, 0x09e3, @@ -26589,13 +28568,12 @@ static const OnigCodePoint CR_Age_4_0[] = { 0x0b9e, 0x0b9f, 0x0ba3, 0x0ba4, 0x0ba8, 0x0baa, - 0x0bae, 0x0bb5, - 0x0bb7, 0x0bb9, + 0x0bae, 0x0bb9, 0x0bbe, 0x0bc2, 0x0bc6, 0x0bc8, 0x0bca, 0x0bcd, 0x0bd7, 0x0bd7, - 0x0be7, 0x0bfa, + 0x0be6, 0x0bfa, 0x0c01, 0x0c03, 0x0c05, 0x0c0c, 0x0c0e, 0x0c10, @@ -26619,8 +28597,9 @@ static const OnigCodePoint CR_Age_4_0[] = { 0x0cca, 0x0ccd, 0x0cd5, 0x0cd6, 0x0cde, 0x0cde, - 0x0ce0, 0x0ce1, + 0x0ce0, 0x0ce3, 0x0ce6, 0x0cef, + 0x0cf1, 0x0cf2, 0x0d02, 0x0d03, 0x0d05, 0x0d0c, 0x0d0e, 0x0d10, @@ -26669,7 +28648,7 @@ static const OnigCodePoint CR_Age_4_0[] = { 0x0f90, 0x0f97, 0x0f99, 0x0fbc, 0x0fbe, 0x0fcc, - 0x0fcf, 0x0fcf, + 0x0fcf, 0x0fd1, 0x1000, 0x1021, 0x1023, 0x1027, 0x1029, 0x102a, @@ -26677,37 +28656,28 @@ static const OnigCodePoint CR_Age_4_0[] = { 0x1036, 0x1039, 0x1040, 0x1059, 0x10a0, 0x10c5, - 0x10d0, 0x10f8, - 0x10fb, 0x10fb, + 0x10d0, 0x10fc, 0x1100, 0x1159, 0x115f, 0x11a2, 0x11a8, 0x11f9, - 0x1200, 0x1206, - 0x1208, 0x1246, - 0x1248, 0x1248, + 0x1200, 0x1248, 0x124a, 0x124d, 0x1250, 0x1256, 0x1258, 0x1258, 0x125a, 0x125d, - 0x1260, 0x1286, - 0x1288, 0x1288, + 0x1260, 0x1288, 0x128a, 0x128d, - 0x1290, 0x12ae, - 0x12b0, 0x12b0, + 0x1290, 0x12b0, 0x12b2, 0x12b5, 0x12b8, 0x12be, 0x12c0, 0x12c0, 0x12c2, 0x12c5, - 0x12c8, 0x12ce, - 0x12d0, 0x12d6, - 0x12d8, 0x12ee, - 0x12f0, 0x130e, - 0x1310, 0x1310, + 0x12c8, 0x12d6, + 0x12d8, 0x1310, 0x1312, 0x1315, - 0x1318, 0x131e, - 0x1320, 0x1346, - 0x1348, 0x135a, - 0x1361, 0x137c, + 0x1318, 0x135a, + 0x135f, 0x137c, + 0x1380, 0x1399, 0x13a0, 0x13f4, 0x1401, 0x1676, 0x1680, 0x169c, @@ -26732,9 +28702,15 @@ static const OnigCodePoint CR_Age_4_0[] = { 0x1940, 0x1940, 0x1944, 0x196d, 0x1970, 0x1974, - 0x19e0, 0x19ff, - 0x1d00, 0x1d6b, - 0x1e00, 0x1e9b, + 0x1980, 0x19a9, + 0x19b0, 0x19c9, + 0x19d0, 0x19d9, + 0x19de, 0x1a1b, + 0x1a1e, 0x1a1f, + 0x1b00, 0x1b4b, + 0x1b50, 0x1b7c, + 0x1d00, 0x1dca, + 0x1dfe, 0x1e9b, 0x1ea0, 0x1ef9, 0x1f00, 0x1f15, 0x1f18, 0x1f1d, @@ -26752,23 +28728,19 @@ static const OnigCodePoint CR_Age_4_0[] = { 0x1fdd, 0x1fef, 0x1ff2, 0x1ff4, 0x1ff6, 0x1ffe, - 0x2000, 0x2054, - 0x2057, 0x2057, - 0x205f, 0x2063, + 0x2000, 0x2063, 0x206a, 0x2071, 0x2074, 0x208e, - 0x20a0, 0x20b1, - 0x20d0, 0x20ea, - 0x2100, 0x213b, - 0x213d, 0x214b, - 0x2153, 0x2183, - 0x2190, 0x23d0, + 0x2090, 0x2094, + 0x20a0, 0x20b5, + 0x20d0, 0x20ef, + 0x2100, 0x214e, + 0x2153, 0x2184, + 0x2190, 0x23e7, 0x2400, 0x2426, 0x2440, 0x244a, - 0x2460, 0x2617, - 0x2619, 0x267d, - 0x2680, 0x2691, - 0x26a0, 0x26a1, + 0x2460, 0x269c, + 0x26a0, 0x26b2, 0x2701, 0x2704, 0x2706, 0x2709, 0x270c, 0x2727, @@ -26780,8 +28752,29 @@ static const OnigCodePoint CR_Age_4_0[] = { 0x2761, 0x2794, 0x2798, 0x27af, 0x27b1, 0x27be, + 0x27c0, 0x27ca, 0x27d0, 0x27eb, - 0x27f0, 0x2b0d, + 0x27f0, 0x2b1a, + 0x2b20, 0x2b23, + 0x2c00, 0x2c2e, + 0x2c30, 0x2c5e, + 0x2c60, 0x2c6c, + 0x2c74, 0x2c77, + 0x2c80, 0x2cea, + 0x2cf9, 0x2d25, + 0x2d30, 0x2d65, + 0x2d6f, 0x2d6f, + 0x2d80, 0x2d96, + 0x2da0, 0x2da6, + 0x2da8, 0x2dae, + 0x2db0, 0x2db6, + 0x2db8, 0x2dbe, + 0x2dc0, 0x2dc6, + 0x2dc8, 0x2dce, + 0x2dd0, 0x2dd6, + 0x2dd8, 0x2dde, + 0x2e00, 0x2e17, + 0x2e1c, 0x2e1d, 0x2e80, 0x2e99, 0x2e9b, 0x2ef3, 0x2f00, 0x2fd5, @@ -26792,17 +28785,22 @@ static const OnigCodePoint CR_Age_4_0[] = { 0x3105, 0x312c, 0x3131, 0x318e, 0x3190, 0x31b7, + 0x31c0, 0x31cf, 0x31f0, 0x321e, 0x3220, 0x3243, - 0x3250, 0x327d, - 0x327f, 0x32fe, + 0x3250, 0x32fe, 0x3300, 0x4db5, - 0x4dc0, 0x9fa5, + 0x4dc0, 0x9fbb, 0xa000, 0xa48c, 0xa490, 0xa4c6, + 0xa700, 0xa71a, + 0xa720, 0xa721, + 0xa800, 0xa82b, + 0xa840, 0xa877, 0xac00, 0xd7a3, 0xd800, 0xfa2d, 0xfa30, 0xfa6a, + 0xfa70, 0xfad9, 0xfb00, 0xfb06, 0xfb13, 0xfb17, 0xfb1d, 0xfb36, @@ -26815,7 +28813,7 @@ static const OnigCodePoint CR_Age_4_0[] = { 0xfd50, 0xfd8f, 0xfd92, 0xfdc7, 0xfdd0, 0xfdfd, - 0xfe00, 0xfe0f, + 0xfe00, 0xfe19, 0xfe20, 0xfe23, 0xfe30, 0xfe52, 0xfe54, 0xfe66, @@ -26839,12 +28837,13 @@ static const OnigCodePoint CR_Age_4_0[] = { 0x10080, 0x100fa, 0x10100, 0x10102, 0x10107, 0x10133, - 0x10137, 0x1013f, + 0x10137, 0x1018a, 0x10300, 0x1031e, 0x10320, 0x10323, 0x10330, 0x1034a, 0x10380, 0x1039d, - 0x1039f, 0x1039f, + 0x1039f, 0x103c3, + 0x103c8, 0x103d5, 0x10400, 0x1049d, 0x104a0, 0x104a9, 0x10800, 0x10805, @@ -26853,10 +28852,25 @@ static const OnigCodePoint CR_Age_4_0[] = { 0x10837, 0x10838, 0x1083c, 0x1083c, 0x1083f, 0x1083f, + 0x10900, 0x10919, + 0x1091f, 0x1091f, + 0x10a00, 0x10a03, + 0x10a05, 0x10a06, + 0x10a0c, 0x10a13, + 0x10a15, 0x10a17, + 0x10a19, 0x10a33, + 0x10a38, 0x10a3a, + 0x10a3f, 0x10a47, + 0x10a50, 0x10a58, + 0x12000, 0x1236e, + 0x12400, 0x12462, + 0x12470, 0x12473, 0x1d000, 0x1d0f5, 0x1d100, 0x1d126, 0x1d12a, 0x1d1dd, + 0x1d200, 0x1d245, 0x1d300, 0x1d356, + 0x1d360, 0x1d371, 0x1d400, 0x1d454, 0x1d456, 0x1d49c, 0x1d49e, 0x1d49f, @@ -26875,8 +28889,8 @@ static const OnigCodePoint CR_Age_4_0[] = { 0x1d540, 0x1d544, 0x1d546, 0x1d546, 0x1d54a, 0x1d550, - 0x1d552, 0x1d6a3, - 0x1d6a8, 0x1d7c9, + 0x1d552, 0x1d6a5, + 0x1d6a8, 0x1d7cb, 0x1d7ce, 0x1d7ff, 0x1fffe, 0x2a6d6, 0x2f800, 0x2fa1d, @@ -26896,47 +28910,37 @@ static const OnigCodePoint CR_Age_4_0[] = { 0xe0020, 0xe007f, 0xe0100, 0xe01ef, 0xefffe, 0x10ffff, -}; /* CR_Age_4_0 */ +}; /* CR_Age_5_0 */ -/* 'Age_4_1': Derived Age 4.1 */ -static const OnigCodePoint CR_Age_4_1[] = { - 430, - 0x0000, 0x0241, - 0x0250, 0x036f, - 0x0374, 0x0375, - 0x037a, 0x037a, - 0x037e, 0x037e, +/* 'Age_5_1': Derived Age 5.1 */ +static const OnigCodePoint CR_Age_5_1[] = { + 455, + 0x0000, 0x0377, + 0x037a, 0x037e, 0x0384, 0x038a, 0x038c, 0x038c, 0x038e, 0x03a1, - 0x03a3, 0x03ce, - 0x03d0, 0x0486, - 0x0488, 0x04ce, - 0x04d0, 0x04f9, - 0x0500, 0x050f, + 0x03a3, 0x0523, 0x0531, 0x0556, 0x0559, 0x055f, 0x0561, 0x0587, 0x0589, 0x058a, - 0x0591, 0x05b9, - 0x05bb, 0x05c7, + 0x0591, 0x05c7, 0x05d0, 0x05ea, 0x05f0, 0x05f4, 0x0600, 0x0603, - 0x060b, 0x0615, - 0x061b, 0x061b, + 0x0606, 0x061b, 0x061e, 0x061f, - 0x0621, 0x063a, - 0x0640, 0x065e, + 0x0621, 0x065e, 0x0660, 0x070d, 0x070f, 0x074a, - 0x074d, 0x076d, - 0x0780, 0x07b1, + 0x074d, 0x07b1, + 0x07c0, 0x07fa, 0x0901, 0x0939, 0x093c, 0x094d, 0x0950, 0x0954, - 0x0958, 0x0970, - 0x097d, 0x097d, + 0x0958, 0x0972, + 0x097b, 0x097f, 0x0981, 0x0983, 0x0985, 0x098c, 0x098f, 0x0990, @@ -26963,9 +28967,10 @@ static const OnigCodePoint CR_Age_4_1[] = { 0x0a3e, 0x0a42, 0x0a47, 0x0a48, 0x0a4b, 0x0a4d, + 0x0a51, 0x0a51, 0x0a59, 0x0a5c, 0x0a5e, 0x0a5e, - 0x0a66, 0x0a74, + 0x0a66, 0x0a75, 0x0a81, 0x0a83, 0x0a85, 0x0a8d, 0x0a8f, 0x0a91, @@ -26987,12 +28992,12 @@ static const OnigCodePoint CR_Age_4_1[] = { 0x0b2a, 0x0b30, 0x0b32, 0x0b33, 0x0b35, 0x0b39, - 0x0b3c, 0x0b43, + 0x0b3c, 0x0b44, 0x0b47, 0x0b48, 0x0b4b, 0x0b4d, 0x0b56, 0x0b57, 0x0b5c, 0x0b5d, - 0x0b5f, 0x0b61, + 0x0b5f, 0x0b63, 0x0b66, 0x0b71, 0x0b82, 0x0b83, 0x0b85, 0x0b8a, @@ -27007,6 +29012,7 @@ static const OnigCodePoint CR_Age_4_1[] = { 0x0bbe, 0x0bc2, 0x0bc6, 0x0bc8, 0x0bca, 0x0bcd, + 0x0bd0, 0x0bd0, 0x0bd7, 0x0bd7, 0x0be6, 0x0bfa, 0x0c01, 0x0c03, @@ -27015,12 +29021,14 @@ static const OnigCodePoint CR_Age_4_1[] = { 0x0c12, 0x0c28, 0x0c2a, 0x0c33, 0x0c35, 0x0c39, - 0x0c3e, 0x0c44, + 0x0c3d, 0x0c44, 0x0c46, 0x0c48, 0x0c4a, 0x0c4d, 0x0c55, 0x0c56, - 0x0c60, 0x0c61, + 0x0c58, 0x0c59, + 0x0c60, 0x0c63, 0x0c66, 0x0c6f, + 0x0c78, 0x0c7f, 0x0c82, 0x0c83, 0x0c85, 0x0c8c, 0x0c8e, 0x0c90, @@ -27032,19 +29040,21 @@ static const OnigCodePoint CR_Age_4_1[] = { 0x0cca, 0x0ccd, 0x0cd5, 0x0cd6, 0x0cde, 0x0cde, - 0x0ce0, 0x0ce1, + 0x0ce0, 0x0ce3, 0x0ce6, 0x0cef, + 0x0cf1, 0x0cf2, 0x0d02, 0x0d03, 0x0d05, 0x0d0c, 0x0d0e, 0x0d10, 0x0d12, 0x0d28, 0x0d2a, 0x0d39, - 0x0d3e, 0x0d43, + 0x0d3d, 0x0d44, 0x0d46, 0x0d48, 0x0d4a, 0x0d4d, 0x0d57, 0x0d57, - 0x0d60, 0x0d61, - 0x0d66, 0x0d6f, + 0x0d60, 0x0d63, + 0x0d66, 0x0d75, + 0x0d79, 0x0d7f, 0x0d82, 0x0d83, 0x0d85, 0x0d96, 0x0d9a, 0x0db1, @@ -27077,19 +29087,14 @@ static const OnigCodePoint CR_Age_4_1[] = { 0x0ed0, 0x0ed9, 0x0edc, 0x0edd, 0x0f00, 0x0f47, - 0x0f49, 0x0f6a, + 0x0f49, 0x0f6c, 0x0f71, 0x0f8b, 0x0f90, 0x0f97, 0x0f99, 0x0fbc, 0x0fbe, 0x0fcc, - 0x0fcf, 0x0fd1, - 0x1000, 0x1021, - 0x1023, 0x1027, - 0x1029, 0x102a, - 0x102c, 0x1032, - 0x1036, 0x1039, - 0x1040, 0x1059, - 0x10a0, 0x10c5, + 0x0fce, 0x0fd4, + 0x1000, 0x1099, + 0x109e, 0x10c5, 0x10d0, 0x10fc, 0x1100, 0x1159, 0x115f, 0x11a2, @@ -27129,7 +29134,7 @@ static const OnigCodePoint CR_Age_4_1[] = { 0x1800, 0x180e, 0x1810, 0x1819, 0x1820, 0x1877, - 0x1880, 0x18a9, + 0x1880, 0x18aa, 0x1900, 0x191c, 0x1920, 0x192b, 0x1930, 0x193b, @@ -27141,10 +29146,15 @@ static const OnigCodePoint CR_Age_4_1[] = { 0x19d0, 0x19d9, 0x19de, 0x1a1b, 0x1a1e, 0x1a1f, - 0x1d00, 0x1dc3, - 0x1e00, 0x1e9b, - 0x1ea0, 0x1ef9, - 0x1f00, 0x1f15, + 0x1b00, 0x1b4b, + 0x1b50, 0x1b7c, + 0x1b80, 0x1baa, + 0x1bae, 0x1bb9, + 0x1c00, 0x1c37, + 0x1c3b, 0x1c49, + 0x1c4d, 0x1c7f, + 0x1d00, 0x1de6, + 0x1dfe, 0x1f15, 0x1f18, 0x1f1d, 0x1f20, 0x1f45, 0x1f48, 0x1f4d, @@ -27160,19 +29170,20 @@ static const OnigCodePoint CR_Age_4_1[] = { 0x1fdd, 0x1fef, 0x1ff2, 0x1ff4, 0x1ff6, 0x1ffe, - 0x2000, 0x2063, + 0x2000, 0x2064, 0x206a, 0x2071, 0x2074, 0x208e, 0x2090, 0x2094, 0x20a0, 0x20b5, - 0x20d0, 0x20eb, - 0x2100, 0x214c, - 0x2153, 0x2183, - 0x2190, 0x23db, + 0x20d0, 0x20f0, + 0x2100, 0x214f, + 0x2153, 0x2188, + 0x2190, 0x23e7, 0x2400, 0x2426, 0x2440, 0x244a, - 0x2460, 0x269c, - 0x26a0, 0x26b1, + 0x2460, 0x269d, + 0x26a0, 0x26bc, + 0x26c0, 0x26c3, 0x2701, 0x2704, 0x2706, 0x2709, 0x270c, 0x2727, @@ -27184,11 +29195,14 @@ static const OnigCodePoint CR_Age_4_1[] = { 0x2761, 0x2794, 0x2798, 0x27af, 0x27b1, 0x27be, - 0x27c0, 0x27c6, - 0x27d0, 0x27eb, - 0x27f0, 0x2b13, + 0x27c0, 0x27ca, + 0x27cc, 0x27cc, + 0x27d0, 0x2b4c, + 0x2b50, 0x2b54, 0x2c00, 0x2c2e, 0x2c30, 0x2c5e, + 0x2c60, 0x2c6f, + 0x2c71, 0x2c7d, 0x2c80, 0x2cea, 0x2cf9, 0x2d25, 0x2d30, 0x2d65, @@ -27202,8 +29216,7 @@ static const OnigCodePoint CR_Age_4_1[] = { 0x2dc8, 0x2dce, 0x2dd0, 0x2dd6, 0x2dd8, 0x2dde, - 0x2e00, 0x2e17, - 0x2e1c, 0x2e1d, + 0x2de0, 0x2e30, 0x2e80, 0x2e99, 0x2e9b, 0x2ef3, 0x2f00, 0x2fd5, @@ -27211,19 +29224,32 @@ static const OnigCodePoint CR_Age_4_1[] = { 0x3000, 0x303f, 0x3041, 0x3096, 0x3099, 0x30ff, - 0x3105, 0x312c, + 0x3105, 0x312d, 0x3131, 0x318e, 0x3190, 0x31b7, - 0x31c0, 0x31cf, + 0x31c0, 0x31e3, 0x31f0, 0x321e, 0x3220, 0x3243, 0x3250, 0x32fe, 0x3300, 0x4db5, - 0x4dc0, 0x9fbb, + 0x4dc0, 0x9fc3, 0xa000, 0xa48c, 0xa490, 0xa4c6, - 0xa700, 0xa716, - 0xa800, 0xa82b, + 0xa500, 0xa62b, + 0xa640, 0xa65f, + 0xa662, 0xa673, + 0xa67c, 0xa697, + 0xa700, 0xa78c, + 0xa7fb, 0xa82b, + 0xa840, 0xa877, + 0xa880, 0xa8c4, + 0xa8ce, 0xa8d9, + 0xa900, 0xa953, + 0xa95f, 0xa95f, + 0xaa00, 0xaa36, + 0xaa40, 0xaa4d, + 0xaa50, 0xaa59, + 0xaa5c, 0xaa5f, 0xac00, 0xd7a3, 0xd800, 0xfa2d, 0xfa30, 0xfa6a, @@ -27241,7 +29267,7 @@ static const OnigCodePoint CR_Age_4_1[] = { 0xfd92, 0xfdc7, 0xfdd0, 0xfdfd, 0xfe00, 0xfe19, - 0xfe20, 0xfe23, + 0xfe20, 0xfe26, 0xfe30, 0xfe52, 0xfe54, 0xfe66, 0xfe68, 0xfe6b, @@ -27265,6 +29291,10 @@ static const OnigCodePoint CR_Age_4_1[] = { 0x10100, 0x10102, 0x10107, 0x10133, 0x10137, 0x1018a, + 0x10190, 0x1019b, + 0x101d0, 0x101fd, + 0x10280, 0x1029c, + 0x102a0, 0x102d0, 0x10300, 0x1031e, 0x10320, 0x10323, 0x10330, 0x1034a, @@ -27279,6 +29309,9 @@ static const OnigCodePoint CR_Age_4_1[] = { 0x10837, 0x10838, 0x1083c, 0x1083c, 0x1083f, 0x1083f, + 0x10900, 0x10919, + 0x1091f, 0x10939, + 0x1093f, 0x1093f, 0x10a00, 0x10a03, 0x10a05, 0x10a06, 0x10a0c, 0x10a13, @@ -27287,11 +29320,15 @@ static const OnigCodePoint CR_Age_4_1[] = { 0x10a38, 0x10a3a, 0x10a3f, 0x10a47, 0x10a50, 0x10a58, + 0x12000, 0x1236e, + 0x12400, 0x12462, + 0x12470, 0x12473, 0x1d000, 0x1d0f5, 0x1d100, 0x1d126, - 0x1d12a, 0x1d1dd, + 0x1d129, 0x1d1dd, 0x1d200, 0x1d245, 0x1d300, 0x1d356, + 0x1d360, 0x1d371, 0x1d400, 0x1d454, 0x1d456, 0x1d49c, 0x1d49e, 0x1d49f, @@ -27311,8 +29348,10 @@ static const OnigCodePoint CR_Age_4_1[] = { 0x1d546, 0x1d546, 0x1d54a, 0x1d550, 0x1d552, 0x1d6a5, - 0x1d6a8, 0x1d7c9, + 0x1d6a8, 0x1d7cb, 0x1d7ce, 0x1d7ff, + 0x1f000, 0x1f02b, + 0x1f030, 0x1f093, 0x1fffe, 0x2a6d6, 0x2f800, 0x2fa1d, 0x2fffe, 0x2ffff, @@ -27331,20 +29370,17 @@ static const OnigCodePoint CR_Age_4_1[] = { 0xe0020, 0xe007f, 0xe0100, 0xe01ef, 0xefffe, 0x10ffff, -}; /* CR_Age_4_1 */ +}; /* CR_Age_5_1 */ -/* 'Age_5_0': Derived Age 5.0 */ -static const OnigCodePoint CR_Age_5_0[] = { - 440, - 0x0000, 0x036f, - 0x0374, 0x0375, +/* 'Age_5_2': Derived Age 5.2 */ +static const OnigCodePoint CR_Age_5_2[] = { + 495, + 0x0000, 0x0377, 0x037a, 0x037e, 0x0384, 0x038a, 0x038c, 0x038c, 0x038e, 0x03a1, - 0x03a3, 0x03ce, - 0x03d0, 0x0486, - 0x0488, 0x0513, + 0x03a3, 0x0525, 0x0531, 0x0556, 0x0559, 0x055f, 0x0561, 0x0587, @@ -27353,21 +29389,20 @@ static const OnigCodePoint CR_Age_5_0[] = { 0x05d0, 0x05ea, 0x05f0, 0x05f4, 0x0600, 0x0603, - 0x060b, 0x0615, - 0x061b, 0x061b, + 0x0606, 0x061b, 0x061e, 0x061f, - 0x0621, 0x063a, - 0x0640, 0x065e, + 0x0621, 0x065e, 0x0660, 0x070d, 0x070f, 0x074a, - 0x074d, 0x076d, - 0x0780, 0x07b1, + 0x074d, 0x07b1, 0x07c0, 0x07fa, - 0x0901, 0x0939, - 0x093c, 0x094d, - 0x0950, 0x0954, - 0x0958, 0x0970, - 0x097b, 0x097f, + 0x0800, 0x082d, + 0x0830, 0x083e, + 0x0900, 0x0939, + 0x093c, 0x094e, + 0x0950, 0x0955, + 0x0958, 0x0972, + 0x0979, 0x097f, 0x0981, 0x0983, 0x0985, 0x098c, 0x098f, 0x0990, @@ -27381,7 +29416,7 @@ static const OnigCodePoint CR_Age_5_0[] = { 0x09d7, 0x09d7, 0x09dc, 0x09dd, 0x09df, 0x09e3, - 0x09e6, 0x09fa, + 0x09e6, 0x09fb, 0x0a01, 0x0a03, 0x0a05, 0x0a0a, 0x0a0f, 0x0a10, @@ -27394,9 +29429,10 @@ static const OnigCodePoint CR_Age_5_0[] = { 0x0a3e, 0x0a42, 0x0a47, 0x0a48, 0x0a4b, 0x0a4d, + 0x0a51, 0x0a51, 0x0a59, 0x0a5c, 0x0a5e, 0x0a5e, - 0x0a66, 0x0a74, + 0x0a66, 0x0a75, 0x0a81, 0x0a83, 0x0a85, 0x0a8d, 0x0a8f, 0x0a91, @@ -27418,12 +29454,12 @@ static const OnigCodePoint CR_Age_5_0[] = { 0x0b2a, 0x0b30, 0x0b32, 0x0b33, 0x0b35, 0x0b39, - 0x0b3c, 0x0b43, + 0x0b3c, 0x0b44, 0x0b47, 0x0b48, 0x0b4b, 0x0b4d, 0x0b56, 0x0b57, 0x0b5c, 0x0b5d, - 0x0b5f, 0x0b61, + 0x0b5f, 0x0b63, 0x0b66, 0x0b71, 0x0b82, 0x0b83, 0x0b85, 0x0b8a, @@ -27438,6 +29474,7 @@ static const OnigCodePoint CR_Age_5_0[] = { 0x0bbe, 0x0bc2, 0x0bc6, 0x0bc8, 0x0bca, 0x0bcd, + 0x0bd0, 0x0bd0, 0x0bd7, 0x0bd7, 0x0be6, 0x0bfa, 0x0c01, 0x0c03, @@ -27446,12 +29483,14 @@ static const OnigCodePoint CR_Age_5_0[] = { 0x0c12, 0x0c28, 0x0c2a, 0x0c33, 0x0c35, 0x0c39, - 0x0c3e, 0x0c44, + 0x0c3d, 0x0c44, 0x0c46, 0x0c48, 0x0c4a, 0x0c4d, 0x0c55, 0x0c56, - 0x0c60, 0x0c61, + 0x0c58, 0x0c59, + 0x0c60, 0x0c63, 0x0c66, 0x0c6f, + 0x0c78, 0x0c7f, 0x0c82, 0x0c83, 0x0c85, 0x0c8c, 0x0c8e, 0x0c90, @@ -27471,12 +29510,13 @@ static const OnigCodePoint CR_Age_5_0[] = { 0x0d0e, 0x0d10, 0x0d12, 0x0d28, 0x0d2a, 0x0d39, - 0x0d3e, 0x0d43, + 0x0d3d, 0x0d44, 0x0d46, 0x0d48, 0x0d4a, 0x0d4d, 0x0d57, 0x0d57, - 0x0d60, 0x0d61, - 0x0d66, 0x0d6f, + 0x0d60, 0x0d63, + 0x0d66, 0x0d75, + 0x0d79, 0x0d7f, 0x0d82, 0x0d83, 0x0d85, 0x0d96, 0x0d9a, 0x0db1, @@ -27509,24 +29549,15 @@ static const OnigCodePoint CR_Age_5_0[] = { 0x0ed0, 0x0ed9, 0x0edc, 0x0edd, 0x0f00, 0x0f47, - 0x0f49, 0x0f6a, + 0x0f49, 0x0f6c, 0x0f71, 0x0f8b, 0x0f90, 0x0f97, 0x0f99, 0x0fbc, 0x0fbe, 0x0fcc, - 0x0fcf, 0x0fd1, - 0x1000, 0x1021, - 0x1023, 0x1027, - 0x1029, 0x102a, - 0x102c, 0x1032, - 0x1036, 0x1039, - 0x1040, 0x1059, - 0x10a0, 0x10c5, + 0x0fce, 0x0fd8, + 0x1000, 0x10c5, 0x10d0, 0x10fc, - 0x1100, 0x1159, - 0x115f, 0x11a2, - 0x11a8, 0x11f9, - 0x1200, 0x1248, + 0x1100, 0x1248, 0x124a, 0x124d, 0x1250, 0x1256, 0x1258, 0x1258, @@ -27545,8 +29576,7 @@ static const OnigCodePoint CR_Age_5_0[] = { 0x135f, 0x137c, 0x1380, 0x1399, 0x13a0, 0x13f4, - 0x1401, 0x1676, - 0x1680, 0x169c, + 0x1400, 0x169c, 0x16a0, 0x16f0, 0x1700, 0x170c, 0x170e, 0x1714, @@ -27561,24 +29591,33 @@ static const OnigCodePoint CR_Age_5_0[] = { 0x1800, 0x180e, 0x1810, 0x1819, 0x1820, 0x1877, - 0x1880, 0x18a9, + 0x1880, 0x18aa, + 0x18b0, 0x18f5, 0x1900, 0x191c, 0x1920, 0x192b, 0x1930, 0x193b, 0x1940, 0x1940, 0x1944, 0x196d, 0x1970, 0x1974, - 0x1980, 0x19a9, + 0x1980, 0x19ab, 0x19b0, 0x19c9, - 0x19d0, 0x19d9, + 0x19d0, 0x19da, 0x19de, 0x1a1b, - 0x1a1e, 0x1a1f, + 0x1a1e, 0x1a5e, + 0x1a60, 0x1a7c, + 0x1a7f, 0x1a89, + 0x1a90, 0x1a99, + 0x1aa0, 0x1aad, 0x1b00, 0x1b4b, 0x1b50, 0x1b7c, - 0x1d00, 0x1dca, - 0x1dfe, 0x1e9b, - 0x1ea0, 0x1ef9, - 0x1f00, 0x1f15, + 0x1b80, 0x1baa, + 0x1bae, 0x1bb9, + 0x1c00, 0x1c37, + 0x1c3b, 0x1c49, + 0x1c4d, 0x1c7f, + 0x1cd0, 0x1cf2, + 0x1d00, 0x1de6, + 0x1dfd, 0x1f15, 0x1f18, 0x1f1d, 0x1f20, 0x1f45, 0x1f48, 0x1f4d, @@ -27594,39 +29633,37 @@ static const OnigCodePoint CR_Age_5_0[] = { 0x1fdd, 0x1fef, 0x1ff2, 0x1ff4, 0x1ff6, 0x1ffe, - 0x2000, 0x2063, + 0x2000, 0x2064, 0x206a, 0x2071, 0x2074, 0x208e, 0x2090, 0x2094, - 0x20a0, 0x20b5, - 0x20d0, 0x20ef, - 0x2100, 0x214e, - 0x2153, 0x2184, - 0x2190, 0x23e7, + 0x20a0, 0x20b8, + 0x20d0, 0x20f0, + 0x2100, 0x2189, + 0x2190, 0x23e8, 0x2400, 0x2426, 0x2440, 0x244a, - 0x2460, 0x269c, - 0x26a0, 0x26b2, + 0x2460, 0x26cd, + 0x26cf, 0x26e1, + 0x26e3, 0x26e3, + 0x26e8, 0x26ff, 0x2701, 0x2704, 0x2706, 0x2709, 0x270c, 0x2727, 0x2729, 0x274b, 0x274d, 0x274d, 0x274f, 0x2752, - 0x2756, 0x2756, - 0x2758, 0x275e, + 0x2756, 0x275e, 0x2761, 0x2794, 0x2798, 0x27af, 0x27b1, 0x27be, 0x27c0, 0x27ca, - 0x27d0, 0x27eb, - 0x27f0, 0x2b1a, - 0x2b20, 0x2b23, + 0x27cc, 0x27cc, + 0x27d0, 0x2b4c, + 0x2b50, 0x2b59, 0x2c00, 0x2c2e, 0x2c30, 0x2c5e, - 0x2c60, 0x2c6c, - 0x2c74, 0x2c77, - 0x2c80, 0x2cea, + 0x2c60, 0x2cf1, 0x2cf9, 0x2d25, 0x2d30, 0x2d65, 0x2d6f, 0x2d6f, @@ -27639,8 +29676,7 @@ static const OnigCodePoint CR_Age_5_0[] = { 0x2dc8, 0x2dce, 0x2dd0, 0x2dd6, 0x2dd8, 0x2dde, - 0x2e00, 0x2e17, - 0x2e1c, 0x2e1d, + 0x2de0, 0x2e31, 0x2e80, 0x2e99, 0x2e9b, 0x2ef3, 0x2f00, 0x2fd5, @@ -27648,24 +29684,46 @@ static const OnigCodePoint CR_Age_5_0[] = { 0x3000, 0x303f, 0x3041, 0x3096, 0x3099, 0x30ff, - 0x3105, 0x312c, + 0x3105, 0x312d, 0x3131, 0x318e, 0x3190, 0x31b7, - 0x31c0, 0x31cf, + 0x31c0, 0x31e3, 0x31f0, 0x321e, - 0x3220, 0x3243, - 0x3250, 0x32fe, + 0x3220, 0x32fe, 0x3300, 0x4db5, - 0x4dc0, 0x9fbb, + 0x4dc0, 0x9fcb, 0xa000, 0xa48c, 0xa490, 0xa4c6, - 0xa700, 0xa71a, - 0xa720, 0xa721, - 0xa800, 0xa82b, + 0xa4d0, 0xa62b, + 0xa640, 0xa65f, + 0xa662, 0xa673, + 0xa67c, 0xa697, + 0xa6a0, 0xa6f7, + 0xa700, 0xa78c, + 0xa7fb, 0xa82b, + 0xa830, 0xa839, 0xa840, 0xa877, + 0xa880, 0xa8c4, + 0xa8ce, 0xa8d9, + 0xa8e0, 0xa8fb, + 0xa900, 0xa953, + 0xa95f, 0xa97c, + 0xa980, 0xa9cd, + 0xa9cf, 0xa9d9, + 0xa9de, 0xa9df, + 0xaa00, 0xaa36, + 0xaa40, 0xaa4d, + 0xaa50, 0xaa59, + 0xaa5c, 0xaa7b, + 0xaa80, 0xaac2, + 0xaadb, 0xaadf, + 0xabc0, 0xabed, + 0xabf0, 0xabf9, 0xac00, 0xd7a3, + 0xd7b0, 0xd7c6, + 0xd7cb, 0xd7fb, 0xd800, 0xfa2d, - 0xfa30, 0xfa6a, + 0xfa30, 0xfa6d, 0xfa70, 0xfad9, 0xfb00, 0xfb06, 0xfb13, 0xfb17, @@ -27680,7 +29738,7 @@ static const OnigCodePoint CR_Age_5_0[] = { 0xfd92, 0xfdc7, 0xfdd0, 0xfdfd, 0xfe00, 0xfe19, - 0xfe20, 0xfe23, + 0xfe20, 0xfe26, 0xfe30, 0xfe52, 0xfe54, 0xfe66, 0xfe68, 0xfe6b, @@ -27704,6 +29762,10 @@ static const OnigCodePoint CR_Age_5_0[] = { 0x10100, 0x10102, 0x10107, 0x10133, 0x10137, 0x1018a, + 0x10190, 0x1019b, + 0x101d0, 0x101fd, + 0x10280, 0x1029c, + 0x102a0, 0x102d0, 0x10300, 0x1031e, 0x10320, 0x10323, 0x10330, 0x1034a, @@ -27717,9 +29779,11 @@ static const OnigCodePoint CR_Age_5_0[] = { 0x1080a, 0x10835, 0x10837, 0x10838, 0x1083c, 0x1083c, - 0x1083f, 0x1083f, - 0x10900, 0x10919, - 0x1091f, 0x1091f, + 0x1083f, 0x10855, + 0x10857, 0x1085f, + 0x10900, 0x1091b, + 0x1091f, 0x10939, + 0x1093f, 0x1093f, 0x10a00, 0x10a03, 0x10a05, 0x10a06, 0x10a0c, 0x10a13, @@ -27728,12 +29792,21 @@ static const OnigCodePoint CR_Age_5_0[] = { 0x10a38, 0x10a3a, 0x10a3f, 0x10a47, 0x10a50, 0x10a58, + 0x10a60, 0x10a7f, + 0x10b00, 0x10b35, + 0x10b39, 0x10b55, + 0x10b58, 0x10b72, + 0x10b78, 0x10b7f, + 0x10c00, 0x10c48, + 0x10e60, 0x10e7e, + 0x11080, 0x110c1, 0x12000, 0x1236e, 0x12400, 0x12462, 0x12470, 0x12473, + 0x13000, 0x1342e, 0x1d000, 0x1d0f5, 0x1d100, 0x1d126, - 0x1d12a, 0x1d1dd, + 0x1d129, 0x1d1dd, 0x1d200, 0x1d245, 0x1d300, 0x1d356, 0x1d360, 0x1d371, @@ -27758,7 +29831,28 @@ static const OnigCodePoint CR_Age_5_0[] = { 0x1d552, 0x1d6a5, 0x1d6a8, 0x1d7cb, 0x1d7ce, 0x1d7ff, + 0x1f000, 0x1f02b, + 0x1f030, 0x1f093, + 0x1f100, 0x1f10a, + 0x1f110, 0x1f12e, + 0x1f131, 0x1f131, + 0x1f13d, 0x1f13d, + 0x1f13f, 0x1f13f, + 0x1f142, 0x1f142, + 0x1f146, 0x1f146, + 0x1f14a, 0x1f14e, + 0x1f157, 0x1f157, + 0x1f15f, 0x1f15f, + 0x1f179, 0x1f179, + 0x1f17b, 0x1f17c, + 0x1f17f, 0x1f17f, + 0x1f18a, 0x1f18d, + 0x1f190, 0x1f190, + 0x1f200, 0x1f200, + 0x1f210, 0x1f231, + 0x1f240, 0x1f248, 0x1fffe, 0x2a6d6, + 0x2a700, 0x2b734, 0x2f800, 0x2fa1d, 0x2fffe, 0x2ffff, 0x3fffe, 0x3ffff, @@ -27776,17 +29870,17 @@ static const OnigCodePoint CR_Age_5_0[] = { 0xe0020, 0xe007f, 0xe0100, 0xe01ef, 0xefffe, 0x10ffff, -}; /* CR_Age_5_0 */ +}; /* CR_Age_5_2 */ -/* 'Age_5_1': Derived Age 5.1 */ -static const OnigCodePoint CR_Age_5_1[] = { - 455, +/* 'Age_6_0': Derived Age 6.0 */ +static const OnigCodePoint CR_Age_6_0[] = { + 511, 0x0000, 0x0377, 0x037a, 0x037e, 0x0384, 0x038a, 0x038c, 0x038c, 0x038e, 0x03a1, - 0x03a3, 0x0523, + 0x03a3, 0x0527, 0x0531, 0x0556, 0x0559, 0x055f, 0x0561, 0x0587, @@ -27796,17 +29890,16 @@ static const OnigCodePoint CR_Age_5_1[] = { 0x05f0, 0x05f4, 0x0600, 0x0603, 0x0606, 0x061b, - 0x061e, 0x061f, - 0x0621, 0x065e, - 0x0660, 0x070d, + 0x061e, 0x070d, 0x070f, 0x074a, 0x074d, 0x07b1, 0x07c0, 0x07fa, - 0x0901, 0x0939, - 0x093c, 0x094d, - 0x0950, 0x0954, - 0x0958, 0x0972, - 0x097b, 0x097f, + 0x0800, 0x082d, + 0x0830, 0x083e, + 0x0840, 0x085b, + 0x085e, 0x085e, + 0x0900, 0x0977, + 0x0979, 0x097f, 0x0981, 0x0983, 0x0985, 0x098c, 0x098f, 0x0990, @@ -27820,7 +29913,7 @@ static const OnigCodePoint CR_Age_5_1[] = { 0x09d7, 0x09d7, 0x09dc, 0x09dd, 0x09df, 0x09e3, - 0x09e6, 0x09fa, + 0x09e6, 0x09fb, 0x0a01, 0x0a03, 0x0a05, 0x0a0a, 0x0a0f, 0x0a10, @@ -27864,7 +29957,7 @@ static const OnigCodePoint CR_Age_5_1[] = { 0x0b56, 0x0b57, 0x0b5c, 0x0b5d, 0x0b5f, 0x0b63, - 0x0b66, 0x0b71, + 0x0b66, 0x0b77, 0x0b82, 0x0b83, 0x0b85, 0x0b8a, 0x0b8e, 0x0b90, @@ -27912,11 +30005,10 @@ static const OnigCodePoint CR_Age_5_1[] = { 0x0d02, 0x0d03, 0x0d05, 0x0d0c, 0x0d0e, 0x0d10, - 0x0d12, 0x0d28, - 0x0d2a, 0x0d39, + 0x0d12, 0x0d3a, 0x0d3d, 0x0d44, 0x0d46, 0x0d48, - 0x0d4a, 0x0d4d, + 0x0d4a, 0x0d4e, 0x0d57, 0x0d57, 0x0d60, 0x0d63, 0x0d66, 0x0d75, @@ -27954,18 +30046,13 @@ static const OnigCodePoint CR_Age_5_1[] = { 0x0edc, 0x0edd, 0x0f00, 0x0f47, 0x0f49, 0x0f6c, - 0x0f71, 0x0f8b, - 0x0f90, 0x0f97, + 0x0f71, 0x0f97, 0x0f99, 0x0fbc, 0x0fbe, 0x0fcc, - 0x0fce, 0x0fd4, - 0x1000, 0x1099, - 0x109e, 0x10c5, + 0x0fce, 0x0fda, + 0x1000, 0x10c5, 0x10d0, 0x10fc, - 0x1100, 0x1159, - 0x115f, 0x11a2, - 0x11a8, 0x11f9, - 0x1200, 0x1248, + 0x1100, 0x1248, 0x124a, 0x124d, 0x1250, 0x1256, 0x1258, 0x1258, @@ -27981,11 +30068,10 @@ static const OnigCodePoint CR_Age_5_1[] = { 0x12d8, 0x1310, 0x1312, 0x1315, 0x1318, 0x135a, - 0x135f, 0x137c, + 0x135d, 0x137c, 0x1380, 0x1399, 0x13a0, 0x13f4, - 0x1401, 0x1676, - 0x1680, 0x169c, + 0x1400, 0x169c, 0x16a0, 0x16f0, 0x1700, 0x170c, 0x170e, 0x1714, @@ -28001,26 +30087,33 @@ static const OnigCodePoint CR_Age_5_1[] = { 0x1810, 0x1819, 0x1820, 0x1877, 0x1880, 0x18aa, + 0x18b0, 0x18f5, 0x1900, 0x191c, 0x1920, 0x192b, 0x1930, 0x193b, 0x1940, 0x1940, 0x1944, 0x196d, 0x1970, 0x1974, - 0x1980, 0x19a9, + 0x1980, 0x19ab, 0x19b0, 0x19c9, - 0x19d0, 0x19d9, + 0x19d0, 0x19da, 0x19de, 0x1a1b, - 0x1a1e, 0x1a1f, + 0x1a1e, 0x1a5e, + 0x1a60, 0x1a7c, + 0x1a7f, 0x1a89, + 0x1a90, 0x1a99, + 0x1aa0, 0x1aad, 0x1b00, 0x1b4b, 0x1b50, 0x1b7c, 0x1b80, 0x1baa, 0x1bae, 0x1bb9, - 0x1c00, 0x1c37, + 0x1bc0, 0x1bf3, + 0x1bfc, 0x1c37, 0x1c3b, 0x1c49, 0x1c4d, 0x1c7f, + 0x1cd0, 0x1cf2, 0x1d00, 0x1de6, - 0x1dfe, 0x1f15, + 0x1dfc, 0x1f15, 0x1f18, 0x1f1d, 0x1f20, 0x1f45, 0x1f48, 0x1f4d, @@ -28039,41 +30132,25 @@ static const OnigCodePoint CR_Age_5_1[] = { 0x2000, 0x2064, 0x206a, 0x2071, 0x2074, 0x208e, - 0x2090, 0x2094, - 0x20a0, 0x20b5, + 0x2090, 0x209c, + 0x20a0, 0x20b9, 0x20d0, 0x20f0, - 0x2100, 0x214f, - 0x2153, 0x2188, - 0x2190, 0x23e7, + 0x2100, 0x2189, + 0x2190, 0x23f3, 0x2400, 0x2426, 0x2440, 0x244a, - 0x2460, 0x269d, - 0x26a0, 0x26bc, - 0x26c0, 0x26c3, - 0x2701, 0x2704, - 0x2706, 0x2709, - 0x270c, 0x2727, - 0x2729, 0x274b, - 0x274d, 0x274d, - 0x274f, 0x2752, - 0x2756, 0x2756, - 0x2758, 0x275e, - 0x2761, 0x2794, - 0x2798, 0x27af, - 0x27b1, 0x27be, - 0x27c0, 0x27ca, + 0x2460, 0x26ff, + 0x2701, 0x27ca, 0x27cc, 0x27cc, - 0x27d0, 0x2b4c, - 0x2b50, 0x2b54, + 0x27ce, 0x2b4c, + 0x2b50, 0x2b59, 0x2c00, 0x2c2e, 0x2c30, 0x2c5e, - 0x2c60, 0x2c6f, - 0x2c71, 0x2c7d, - 0x2c80, 0x2cea, + 0x2c60, 0x2cf1, 0x2cf9, 0x2d25, 0x2d30, 0x2d65, - 0x2d6f, 0x2d6f, - 0x2d80, 0x2d96, + 0x2d6f, 0x2d70, + 0x2d7f, 0x2d96, 0x2da0, 0x2da6, 0x2da8, 0x2dae, 0x2db0, 0x2db6, @@ -28082,7 +30159,7 @@ static const OnigCodePoint CR_Age_5_1[] = { 0x2dc8, 0x2dce, 0x2dd0, 0x2dd6, 0x2dd8, 0x2dde, - 0x2de0, 0x2e30, + 0x2de0, 0x2e31, 0x2e80, 0x2e99, 0x2e9b, 0x2ef3, 0x2f00, 0x2fd5, @@ -28092,33 +30169,50 @@ static const OnigCodePoint CR_Age_5_1[] = { 0x3099, 0x30ff, 0x3105, 0x312d, 0x3131, 0x318e, - 0x3190, 0x31b7, + 0x3190, 0x31ba, 0x31c0, 0x31e3, 0x31f0, 0x321e, - 0x3220, 0x3243, - 0x3250, 0x32fe, + 0x3220, 0x32fe, 0x3300, 0x4db5, - 0x4dc0, 0x9fc3, + 0x4dc0, 0x9fcb, 0xa000, 0xa48c, 0xa490, 0xa4c6, - 0xa500, 0xa62b, - 0xa640, 0xa65f, - 0xa662, 0xa673, + 0xa4d0, 0xa62b, + 0xa640, 0xa673, 0xa67c, 0xa697, - 0xa700, 0xa78c, - 0xa7fb, 0xa82b, + 0xa6a0, 0xa6f7, + 0xa700, 0xa78e, + 0xa790, 0xa791, + 0xa7a0, 0xa7a9, + 0xa7fa, 0xa82b, + 0xa830, 0xa839, 0xa840, 0xa877, 0xa880, 0xa8c4, 0xa8ce, 0xa8d9, + 0xa8e0, 0xa8fb, 0xa900, 0xa953, - 0xa95f, 0xa95f, + 0xa95f, 0xa97c, + 0xa980, 0xa9cd, + 0xa9cf, 0xa9d9, + 0xa9de, 0xa9df, 0xaa00, 0xaa36, 0xaa40, 0xaa4d, 0xaa50, 0xaa59, - 0xaa5c, 0xaa5f, + 0xaa5c, 0xaa7b, + 0xaa80, 0xaac2, + 0xaadb, 0xaadf, + 0xab01, 0xab06, + 0xab09, 0xab0e, + 0xab11, 0xab16, + 0xab20, 0xab26, + 0xab28, 0xab2e, + 0xabc0, 0xabed, + 0xabf0, 0xabf9, 0xac00, 0xd7a3, + 0xd7b0, 0xd7c6, + 0xd7cb, 0xd7fb, 0xd800, 0xfa2d, - 0xfa30, 0xfa6a, + 0xfa30, 0xfa6d, 0xfa70, 0xfad9, 0xfb00, 0xfb06, 0xfb13, 0xfb17, @@ -28127,7 +30221,7 @@ static const OnigCodePoint CR_Age_5_1[] = { 0xfb3e, 0xfb3e, 0xfb40, 0xfb41, 0xfb43, 0xfb44, - 0xfb46, 0xfbb1, + 0xfb46, 0xfbc1, 0xfbd3, 0xfd3f, 0xfd50, 0xfd8f, 0xfd92, 0xfdc7, @@ -28174,8 +30268,9 @@ static const OnigCodePoint CR_Age_5_1[] = { 0x1080a, 0x10835, 0x10837, 0x10838, 0x1083c, 0x1083c, - 0x1083f, 0x1083f, - 0x10900, 0x10919, + 0x1083f, 0x10855, + 0x10857, 0x1085f, + 0x10900, 0x1091b, 0x1091f, 0x10939, 0x1093f, 0x1093f, 0x10a00, 0x10a03, @@ -28186,9 +30281,22 @@ static const OnigCodePoint CR_Age_5_1[] = { 0x10a38, 0x10a3a, 0x10a3f, 0x10a47, 0x10a50, 0x10a58, + 0x10a60, 0x10a7f, + 0x10b00, 0x10b35, + 0x10b39, 0x10b55, + 0x10b58, 0x10b72, + 0x10b78, 0x10b7f, + 0x10c00, 0x10c48, + 0x10e60, 0x10e7e, + 0x11000, 0x1104d, + 0x11052, 0x1106f, + 0x11080, 0x110c1, 0x12000, 0x1236e, 0x12400, 0x12462, 0x12470, 0x12473, + 0x13000, 0x1342e, + 0x16800, 0x16a38, + 0x1b000, 0x1b001, 0x1d000, 0x1d0f5, 0x1d100, 0x1d126, 0x1d129, 0x1d1dd, @@ -28218,7 +30326,49 @@ static const OnigCodePoint CR_Age_5_1[] = { 0x1d7ce, 0x1d7ff, 0x1f000, 0x1f02b, 0x1f030, 0x1f093, + 0x1f0a0, 0x1f0ae, + 0x1f0b1, 0x1f0be, + 0x1f0c1, 0x1f0cf, + 0x1f0d1, 0x1f0df, + 0x1f100, 0x1f10a, + 0x1f110, 0x1f12e, + 0x1f130, 0x1f169, + 0x1f170, 0x1f19a, + 0x1f1e6, 0x1f202, + 0x1f210, 0x1f23a, + 0x1f240, 0x1f248, + 0x1f250, 0x1f251, + 0x1f300, 0x1f320, + 0x1f330, 0x1f335, + 0x1f337, 0x1f37c, + 0x1f380, 0x1f393, + 0x1f3a0, 0x1f3c4, + 0x1f3c6, 0x1f3ca, + 0x1f3e0, 0x1f3f0, + 0x1f400, 0x1f43e, + 0x1f440, 0x1f440, + 0x1f442, 0x1f4f7, + 0x1f4f9, 0x1f4fc, + 0x1f500, 0x1f53d, + 0x1f550, 0x1f567, + 0x1f5fb, 0x1f5ff, + 0x1f601, 0x1f610, + 0x1f612, 0x1f614, + 0x1f616, 0x1f616, + 0x1f618, 0x1f618, + 0x1f61a, 0x1f61a, + 0x1f61c, 0x1f61e, + 0x1f620, 0x1f625, + 0x1f628, 0x1f62b, + 0x1f62d, 0x1f62d, + 0x1f630, 0x1f633, + 0x1f635, 0x1f640, + 0x1f645, 0x1f64f, + 0x1f680, 0x1f6c5, + 0x1f700, 0x1f773, 0x1fffe, 0x2a6d6, + 0x2a700, 0x2b734, + 0x2b740, 0x2b81d, 0x2f800, 0x2fa1d, 0x2fffe, 0x2ffff, 0x3fffe, 0x3ffff, @@ -28236,38 +30386,39 @@ static const OnigCodePoint CR_Age_5_1[] = { 0xe0020, 0xe007f, 0xe0100, 0xe01ef, 0xefffe, 0x10ffff, -}; /* CR_Age_5_1 */ +}; /* CR_Age_6_0 */ -/* 'Age_5_2': Derived Age 5.2 */ -static const OnigCodePoint CR_Age_5_2[] = { - 495, +/* 'Age_6_1': Derived Age 6.1 */ +static const OnigCodePoint CR_Age_6_1[] = { + 549, 0x0000, 0x0377, 0x037a, 0x037e, 0x0384, 0x038a, 0x038c, 0x038c, 0x038e, 0x03a1, - 0x03a3, 0x0525, + 0x03a3, 0x0527, 0x0531, 0x0556, 0x0559, 0x055f, 0x0561, 0x0587, 0x0589, 0x058a, + 0x058f, 0x058f, 0x0591, 0x05c7, 0x05d0, 0x05ea, 0x05f0, 0x05f4, - 0x0600, 0x0603, + 0x0600, 0x0604, 0x0606, 0x061b, - 0x061e, 0x061f, - 0x0621, 0x065e, - 0x0660, 0x070d, + 0x061e, 0x070d, 0x070f, 0x074a, 0x074d, 0x07b1, 0x07c0, 0x07fa, 0x0800, 0x082d, 0x0830, 0x083e, - 0x0900, 0x0939, - 0x093c, 0x094e, - 0x0950, 0x0955, - 0x0958, 0x0972, + 0x0840, 0x085b, + 0x085e, 0x085e, + 0x08a0, 0x08a0, + 0x08a2, 0x08ac, + 0x08e4, 0x08fe, + 0x0900, 0x0977, 0x0979, 0x097f, 0x0981, 0x0983, 0x0985, 0x098c, @@ -28311,8 +30462,7 @@ static const OnigCodePoint CR_Age_5_2[] = { 0x0acb, 0x0acd, 0x0ad0, 0x0ad0, 0x0ae0, 0x0ae3, - 0x0ae6, 0x0aef, - 0x0af1, 0x0af1, + 0x0ae6, 0x0af1, 0x0b01, 0x0b03, 0x0b05, 0x0b0c, 0x0b0f, 0x0b10, @@ -28326,7 +30476,7 @@ static const OnigCodePoint CR_Age_5_2[] = { 0x0b56, 0x0b57, 0x0b5c, 0x0b5d, 0x0b5f, 0x0b63, - 0x0b66, 0x0b71, + 0x0b66, 0x0b77, 0x0b82, 0x0b83, 0x0b85, 0x0b8a, 0x0b8e, 0x0b90, @@ -28374,11 +30524,10 @@ static const OnigCodePoint CR_Age_5_2[] = { 0x0d02, 0x0d03, 0x0d05, 0x0d0c, 0x0d0e, 0x0d10, - 0x0d12, 0x0d28, - 0x0d2a, 0x0d39, + 0x0d12, 0x0d3a, 0x0d3d, 0x0d44, 0x0d46, 0x0d48, - 0x0d4a, 0x0d4d, + 0x0d4a, 0x0d4e, 0x0d57, 0x0d57, 0x0d60, 0x0d63, 0x0d66, 0x0d75, @@ -28413,17 +30562,17 @@ static const OnigCodePoint CR_Age_5_2[] = { 0x0ec6, 0x0ec6, 0x0ec8, 0x0ecd, 0x0ed0, 0x0ed9, - 0x0edc, 0x0edd, + 0x0edc, 0x0edf, 0x0f00, 0x0f47, 0x0f49, 0x0f6c, - 0x0f71, 0x0f8b, - 0x0f90, 0x0f97, + 0x0f71, 0x0f97, 0x0f99, 0x0fbc, 0x0fbe, 0x0fcc, - 0x0fce, 0x0fd8, + 0x0fce, 0x0fda, 0x1000, 0x10c5, - 0x10d0, 0x10fc, - 0x1100, 0x1248, + 0x10c7, 0x10c7, + 0x10cd, 0x10cd, + 0x10d0, 0x1248, 0x124a, 0x124d, 0x1250, 0x1256, 0x1258, 0x1258, @@ -28439,7 +30588,7 @@ static const OnigCodePoint CR_Age_5_2[] = { 0x12d8, 0x1310, 0x1312, 0x1315, 0x1318, 0x135a, - 0x135f, 0x137c, + 0x135d, 0x137c, 0x1380, 0x1399, 0x13a0, 0x13f4, 0x1400, 0x169c, @@ -28476,14 +30625,14 @@ static const OnigCodePoint CR_Age_5_2[] = { 0x1aa0, 0x1aad, 0x1b00, 0x1b4b, 0x1b50, 0x1b7c, - 0x1b80, 0x1baa, - 0x1bae, 0x1bb9, - 0x1c00, 0x1c37, + 0x1b80, 0x1bf3, + 0x1bfc, 0x1c37, 0x1c3b, 0x1c49, 0x1c4d, 0x1c7f, - 0x1cd0, 0x1cf2, + 0x1cc0, 0x1cc7, + 0x1cd0, 0x1cf6, 0x1d00, 0x1de6, - 0x1dfd, 0x1f15, + 0x1dfc, 0x1f15, 0x1f18, 0x1f1d, 0x1f20, 0x1f45, 0x1f48, 0x1f4d, @@ -28502,38 +30651,25 @@ static const OnigCodePoint CR_Age_5_2[] = { 0x2000, 0x2064, 0x206a, 0x2071, 0x2074, 0x208e, - 0x2090, 0x2094, - 0x20a0, 0x20b8, + 0x2090, 0x209c, + 0x20a0, 0x20b9, 0x20d0, 0x20f0, 0x2100, 0x2189, - 0x2190, 0x23e8, + 0x2190, 0x23f3, 0x2400, 0x2426, 0x2440, 0x244a, - 0x2460, 0x26cd, - 0x26cf, 0x26e1, - 0x26e3, 0x26e3, - 0x26e8, 0x26ff, - 0x2701, 0x2704, - 0x2706, 0x2709, - 0x270c, 0x2727, - 0x2729, 0x274b, - 0x274d, 0x274d, - 0x274f, 0x2752, - 0x2756, 0x275e, - 0x2761, 0x2794, - 0x2798, 0x27af, - 0x27b1, 0x27be, - 0x27c0, 0x27ca, - 0x27cc, 0x27cc, - 0x27d0, 0x2b4c, + 0x2460, 0x26ff, + 0x2701, 0x2b4c, 0x2b50, 0x2b59, 0x2c00, 0x2c2e, 0x2c30, 0x2c5e, - 0x2c60, 0x2cf1, + 0x2c60, 0x2cf3, 0x2cf9, 0x2d25, - 0x2d30, 0x2d65, - 0x2d6f, 0x2d6f, - 0x2d80, 0x2d96, + 0x2d27, 0x2d27, + 0x2d2d, 0x2d2d, + 0x2d30, 0x2d67, + 0x2d6f, 0x2d70, + 0x2d7f, 0x2d96, 0x2da0, 0x2da6, 0x2da8, 0x2dae, 0x2db0, 0x2db6, @@ -28542,7 +30678,7 @@ static const OnigCodePoint CR_Age_5_2[] = { 0x2dc8, 0x2dce, 0x2dd0, 0x2dd6, 0x2dd8, 0x2dde, - 0x2de0, 0x2e31, + 0x2de0, 0x2e3b, 0x2e80, 0x2e99, 0x2e9b, 0x2ef3, 0x2f00, 0x2fd5, @@ -28552,21 +30688,21 @@ static const OnigCodePoint CR_Age_5_2[] = { 0x3099, 0x30ff, 0x3105, 0x312d, 0x3131, 0x318e, - 0x3190, 0x31b7, + 0x3190, 0x31ba, 0x31c0, 0x31e3, 0x31f0, 0x321e, 0x3220, 0x32fe, 0x3300, 0x4db5, - 0x4dc0, 0x9fcb, + 0x4dc0, 0x9fcc, 0xa000, 0xa48c, 0xa490, 0xa4c6, 0xa4d0, 0xa62b, - 0xa640, 0xa65f, - 0xa662, 0xa673, - 0xa67c, 0xa697, - 0xa6a0, 0xa6f7, - 0xa700, 0xa78c, - 0xa7fb, 0xa82b, + 0xa640, 0xa697, + 0xa69f, 0xa6f7, + 0xa700, 0xa78e, + 0xa790, 0xa793, + 0xa7a0, 0xa7aa, + 0xa7f8, 0xa82b, 0xa830, 0xa839, 0xa840, 0xa877, 0xa880, 0xa8c4, @@ -28582,14 +30718,18 @@ static const OnigCodePoint CR_Age_5_2[] = { 0xaa50, 0xaa59, 0xaa5c, 0xaa7b, 0xaa80, 0xaac2, - 0xaadb, 0xaadf, + 0xaadb, 0xaaf6, + 0xab01, 0xab06, + 0xab09, 0xab0e, + 0xab11, 0xab16, + 0xab20, 0xab26, + 0xab28, 0xab2e, 0xabc0, 0xabed, 0xabf0, 0xabf9, 0xac00, 0xd7a3, 0xd7b0, 0xd7c6, 0xd7cb, 0xd7fb, - 0xd800, 0xfa2d, - 0xfa30, 0xfa6d, + 0xd800, 0xfa6d, 0xfa70, 0xfad9, 0xfb00, 0xfb06, 0xfb13, 0xfb17, @@ -28598,7 +30738,7 @@ static const OnigCodePoint CR_Age_5_2[] = { 0xfb3e, 0xfb3e, 0xfb40, 0xfb41, 0xfb43, 0xfb44, - 0xfb46, 0xfbb1, + 0xfb46, 0xfbc1, 0xfbd3, 0xfd3f, 0xfd50, 0xfd8f, 0xfd92, 0xfdc7, @@ -28650,6 +30790,8 @@ static const OnigCodePoint CR_Age_5_2[] = { 0x10900, 0x1091b, 0x1091f, 0x10939, 0x1093f, 0x1093f, + 0x10980, 0x109b7, + 0x109be, 0x109bf, 0x10a00, 0x10a03, 0x10a05, 0x10a06, 0x10a0c, 0x10a13, @@ -28665,11 +30807,26 @@ static const OnigCodePoint CR_Age_5_2[] = { 0x10b78, 0x10b7f, 0x10c00, 0x10c48, 0x10e60, 0x10e7e, + 0x11000, 0x1104d, + 0x11052, 0x1106f, 0x11080, 0x110c1, + 0x110d0, 0x110e8, + 0x110f0, 0x110f9, + 0x11100, 0x11134, + 0x11136, 0x11143, + 0x11180, 0x111c8, + 0x111d0, 0x111d9, + 0x11680, 0x116b7, + 0x116c0, 0x116c9, 0x12000, 0x1236e, 0x12400, 0x12462, 0x12470, 0x12473, 0x13000, 0x1342e, + 0x16800, 0x16a38, + 0x16f00, 0x16f44, + 0x16f50, 0x16f7e, + 0x16f8f, 0x16f9f, + 0x1b000, 0x1b001, 0x1d000, 0x1d0f5, 0x1d100, 0x1d126, 0x1d129, 0x1d1dd, @@ -28697,28 +30854,75 @@ static const OnigCodePoint CR_Age_5_2[] = { 0x1d552, 0x1d6a5, 0x1d6a8, 0x1d7cb, 0x1d7ce, 0x1d7ff, + 0x1ee00, 0x1ee03, + 0x1ee05, 0x1ee1f, + 0x1ee21, 0x1ee22, + 0x1ee24, 0x1ee24, + 0x1ee27, 0x1ee27, + 0x1ee29, 0x1ee32, + 0x1ee34, 0x1ee37, + 0x1ee39, 0x1ee39, + 0x1ee3b, 0x1ee3b, + 0x1ee42, 0x1ee42, + 0x1ee47, 0x1ee47, + 0x1ee49, 0x1ee49, + 0x1ee4b, 0x1ee4b, + 0x1ee4d, 0x1ee4f, + 0x1ee51, 0x1ee52, + 0x1ee54, 0x1ee54, + 0x1ee57, 0x1ee57, + 0x1ee59, 0x1ee59, + 0x1ee5b, 0x1ee5b, + 0x1ee5d, 0x1ee5d, + 0x1ee5f, 0x1ee5f, + 0x1ee61, 0x1ee62, + 0x1ee64, 0x1ee64, + 0x1ee67, 0x1ee6a, + 0x1ee6c, 0x1ee72, + 0x1ee74, 0x1ee77, + 0x1ee79, 0x1ee7c, + 0x1ee7e, 0x1ee7e, + 0x1ee80, 0x1ee89, + 0x1ee8b, 0x1ee9b, + 0x1eea1, 0x1eea3, + 0x1eea5, 0x1eea9, + 0x1eeab, 0x1eebb, + 0x1eef0, 0x1eef1, 0x1f000, 0x1f02b, 0x1f030, 0x1f093, + 0x1f0a0, 0x1f0ae, + 0x1f0b1, 0x1f0be, + 0x1f0c1, 0x1f0cf, + 0x1f0d1, 0x1f0df, 0x1f100, 0x1f10a, 0x1f110, 0x1f12e, - 0x1f131, 0x1f131, - 0x1f13d, 0x1f13d, - 0x1f13f, 0x1f13f, - 0x1f142, 0x1f142, - 0x1f146, 0x1f146, - 0x1f14a, 0x1f14e, - 0x1f157, 0x1f157, - 0x1f15f, 0x1f15f, - 0x1f179, 0x1f179, - 0x1f17b, 0x1f17c, - 0x1f17f, 0x1f17f, - 0x1f18a, 0x1f18d, - 0x1f190, 0x1f190, - 0x1f200, 0x1f200, - 0x1f210, 0x1f231, + 0x1f130, 0x1f16b, + 0x1f170, 0x1f19a, + 0x1f1e6, 0x1f202, + 0x1f210, 0x1f23a, 0x1f240, 0x1f248, + 0x1f250, 0x1f251, + 0x1f300, 0x1f320, + 0x1f330, 0x1f335, + 0x1f337, 0x1f37c, + 0x1f380, 0x1f393, + 0x1f3a0, 0x1f3c4, + 0x1f3c6, 0x1f3ca, + 0x1f3e0, 0x1f3f0, + 0x1f400, 0x1f43e, + 0x1f440, 0x1f440, + 0x1f442, 0x1f4f7, + 0x1f4f9, 0x1f4fc, + 0x1f500, 0x1f53d, + 0x1f540, 0x1f543, + 0x1f550, 0x1f567, + 0x1f5fb, 0x1f640, + 0x1f645, 0x1f64f, + 0x1f680, 0x1f6c5, + 0x1f700, 0x1f773, 0x1fffe, 0x2a6d6, 0x2a700, 0x2b734, + 0x2b740, 0x2b81d, 0x2f800, 0x2fa1d, 0x2fffe, 0x2ffff, 0x3fffe, 0x3ffff, @@ -28736,11 +30940,11 @@ static const OnigCodePoint CR_Age_5_2[] = { 0xe0020, 0xe007f, 0xe0100, 0xe01ef, 0xefffe, 0x10ffff, -}; /* CR_Age_5_2 */ +}; /* CR_Age_6_1 */ -/* 'Age_6_0': Derived Age 6.0 */ -static const OnigCodePoint CR_Age_6_0[] = { - 511, +/* 'Age_6_2': Derived Age 6.2 */ +static const OnigCodePoint CR_Age_6_2[] = { + 549, 0x0000, 0x0377, 0x037a, 0x037e, 0x0384, 0x038a, @@ -28751,10 +30955,11 @@ static const OnigCodePoint CR_Age_6_0[] = { 0x0559, 0x055f, 0x0561, 0x0587, 0x0589, 0x058a, + 0x058f, 0x058f, 0x0591, 0x05c7, 0x05d0, 0x05ea, 0x05f0, 0x05f4, - 0x0600, 0x0603, + 0x0600, 0x0604, 0x0606, 0x061b, 0x061e, 0x070d, 0x070f, 0x074a, @@ -28764,6 +30969,9 @@ static const OnigCodePoint CR_Age_6_0[] = { 0x0830, 0x083e, 0x0840, 0x085b, 0x085e, 0x085e, + 0x08a0, 0x08a0, + 0x08a2, 0x08ac, + 0x08e4, 0x08fe, 0x0900, 0x0977, 0x0979, 0x097f, 0x0981, 0x0983, @@ -28808,8 +31016,7 @@ static const OnigCodePoint CR_Age_6_0[] = { 0x0acb, 0x0acd, 0x0ad0, 0x0ad0, 0x0ae0, 0x0ae3, - 0x0ae6, 0x0aef, - 0x0af1, 0x0af1, + 0x0ae6, 0x0af1, 0x0b01, 0x0b03, 0x0b05, 0x0b0c, 0x0b0f, 0x0b10, @@ -28909,7 +31116,7 @@ static const OnigCodePoint CR_Age_6_0[] = { 0x0ec6, 0x0ec6, 0x0ec8, 0x0ecd, 0x0ed0, 0x0ed9, - 0x0edc, 0x0edd, + 0x0edc, 0x0edf, 0x0f00, 0x0f47, 0x0f49, 0x0f6c, 0x0f71, 0x0f97, @@ -28917,8 +31124,9 @@ static const OnigCodePoint CR_Age_6_0[] = { 0x0fbe, 0x0fcc, 0x0fce, 0x0fda, 0x1000, 0x10c5, - 0x10d0, 0x10fc, - 0x1100, 0x1248, + 0x10c7, 0x10c7, + 0x10cd, 0x10cd, + 0x10d0, 0x1248, 0x124a, 0x124d, 0x1250, 0x1256, 0x1258, 0x1258, @@ -28971,13 +31179,12 @@ static const OnigCodePoint CR_Age_6_0[] = { 0x1aa0, 0x1aad, 0x1b00, 0x1b4b, 0x1b50, 0x1b7c, - 0x1b80, 0x1baa, - 0x1bae, 0x1bb9, - 0x1bc0, 0x1bf3, + 0x1b80, 0x1bf3, 0x1bfc, 0x1c37, 0x1c3b, 0x1c49, 0x1c4d, 0x1c7f, - 0x1cd0, 0x1cf2, + 0x1cc0, 0x1cc7, + 0x1cd0, 0x1cf6, 0x1d00, 0x1de6, 0x1dfc, 0x1f15, 0x1f18, 0x1f1d, @@ -28999,22 +31206,22 @@ static const OnigCodePoint CR_Age_6_0[] = { 0x206a, 0x2071, 0x2074, 0x208e, 0x2090, 0x209c, - 0x20a0, 0x20b9, + 0x20a0, 0x20ba, 0x20d0, 0x20f0, 0x2100, 0x2189, 0x2190, 0x23f3, 0x2400, 0x2426, 0x2440, 0x244a, 0x2460, 0x26ff, - 0x2701, 0x27ca, - 0x27cc, 0x27cc, - 0x27ce, 0x2b4c, + 0x2701, 0x2b4c, 0x2b50, 0x2b59, 0x2c00, 0x2c2e, 0x2c30, 0x2c5e, - 0x2c60, 0x2cf1, + 0x2c60, 0x2cf3, 0x2cf9, 0x2d25, - 0x2d30, 0x2d65, + 0x2d27, 0x2d27, + 0x2d2d, 0x2d2d, + 0x2d30, 0x2d67, 0x2d6f, 0x2d70, 0x2d7f, 0x2d96, 0x2da0, 0x2da6, @@ -29025,7 +31232,7 @@ static const OnigCodePoint CR_Age_6_0[] = { 0x2dc8, 0x2dce, 0x2dd0, 0x2dd6, 0x2dd8, 0x2dde, - 0x2de0, 0x2e31, + 0x2de0, 0x2e3b, 0x2e80, 0x2e99, 0x2e9b, 0x2ef3, 0x2f00, 0x2fd5, @@ -29040,17 +31247,16 @@ static const OnigCodePoint CR_Age_6_0[] = { 0x31f0, 0x321e, 0x3220, 0x32fe, 0x3300, 0x4db5, - 0x4dc0, 0x9fcb, + 0x4dc0, 0x9fcc, 0xa000, 0xa48c, 0xa490, 0xa4c6, 0xa4d0, 0xa62b, - 0xa640, 0xa673, - 0xa67c, 0xa697, - 0xa6a0, 0xa6f7, + 0xa640, 0xa697, + 0xa69f, 0xa6f7, 0xa700, 0xa78e, - 0xa790, 0xa791, - 0xa7a0, 0xa7a9, - 0xa7fa, 0xa82b, + 0xa790, 0xa793, + 0xa7a0, 0xa7aa, + 0xa7f8, 0xa82b, 0xa830, 0xa839, 0xa840, 0xa877, 0xa880, 0xa8c4, @@ -29066,7 +31272,7 @@ static const OnigCodePoint CR_Age_6_0[] = { 0xaa50, 0xaa59, 0xaa5c, 0xaa7b, 0xaa80, 0xaac2, - 0xaadb, 0xaadf, + 0xaadb, 0xaaf6, 0xab01, 0xab06, 0xab09, 0xab0e, 0xab11, 0xab16, @@ -29077,8 +31283,7 @@ static const OnigCodePoint CR_Age_6_0[] = { 0xac00, 0xd7a3, 0xd7b0, 0xd7c6, 0xd7cb, 0xd7fb, - 0xd800, 0xfa2d, - 0xfa30, 0xfa6d, + 0xd800, 0xfa6d, 0xfa70, 0xfad9, 0xfb00, 0xfb06, 0xfb13, 0xfb17, @@ -29139,6 +31344,8 @@ static const OnigCodePoint CR_Age_6_0[] = { 0x10900, 0x1091b, 0x1091f, 0x10939, 0x1093f, 0x1093f, + 0x10980, 0x109b7, + 0x109be, 0x109bf, 0x10a00, 0x10a03, 0x10a05, 0x10a06, 0x10a0c, 0x10a13, @@ -29157,11 +31364,22 @@ static const OnigCodePoint CR_Age_6_0[] = { 0x11000, 0x1104d, 0x11052, 0x1106f, 0x11080, 0x110c1, + 0x110d0, 0x110e8, + 0x110f0, 0x110f9, + 0x11100, 0x11134, + 0x11136, 0x11143, + 0x11180, 0x111c8, + 0x111d0, 0x111d9, + 0x11680, 0x116b7, + 0x116c0, 0x116c9, 0x12000, 0x1236e, 0x12400, 0x12462, 0x12470, 0x12473, 0x13000, 0x1342e, 0x16800, 0x16a38, + 0x16f00, 0x16f44, + 0x16f50, 0x16f7e, + 0x16f8f, 0x16f9f, 0x1b000, 0x1b001, 0x1d000, 0x1d0f5, 0x1d100, 0x1d126, @@ -29190,6 +31408,40 @@ static const OnigCodePoint CR_Age_6_0[] = { 0x1d552, 0x1d6a5, 0x1d6a8, 0x1d7cb, 0x1d7ce, 0x1d7ff, + 0x1ee00, 0x1ee03, + 0x1ee05, 0x1ee1f, + 0x1ee21, 0x1ee22, + 0x1ee24, 0x1ee24, + 0x1ee27, 0x1ee27, + 0x1ee29, 0x1ee32, + 0x1ee34, 0x1ee37, + 0x1ee39, 0x1ee39, + 0x1ee3b, 0x1ee3b, + 0x1ee42, 0x1ee42, + 0x1ee47, 0x1ee47, + 0x1ee49, 0x1ee49, + 0x1ee4b, 0x1ee4b, + 0x1ee4d, 0x1ee4f, + 0x1ee51, 0x1ee52, + 0x1ee54, 0x1ee54, + 0x1ee57, 0x1ee57, + 0x1ee59, 0x1ee59, + 0x1ee5b, 0x1ee5b, + 0x1ee5d, 0x1ee5d, + 0x1ee5f, 0x1ee5f, + 0x1ee61, 0x1ee62, + 0x1ee64, 0x1ee64, + 0x1ee67, 0x1ee6a, + 0x1ee6c, 0x1ee72, + 0x1ee74, 0x1ee77, + 0x1ee79, 0x1ee7c, + 0x1ee7e, 0x1ee7e, + 0x1ee80, 0x1ee89, + 0x1ee8b, 0x1ee9b, + 0x1eea1, 0x1eea3, + 0x1eea5, 0x1eea9, + 0x1eeab, 0x1eebb, + 0x1eef0, 0x1eef1, 0x1f000, 0x1f02b, 0x1f030, 0x1f093, 0x1f0a0, 0x1f0ae, @@ -29198,7 +31450,7 @@ static const OnigCodePoint CR_Age_6_0[] = { 0x1f0d1, 0x1f0df, 0x1f100, 0x1f10a, 0x1f110, 0x1f12e, - 0x1f130, 0x1f169, + 0x1f130, 0x1f16b, 0x1f170, 0x1f19a, 0x1f1e6, 0x1f202, 0x1f210, 0x1f23a, @@ -29216,19 +31468,9 @@ static const OnigCodePoint CR_Age_6_0[] = { 0x1f442, 0x1f4f7, 0x1f4f9, 0x1f4fc, 0x1f500, 0x1f53d, + 0x1f540, 0x1f543, 0x1f550, 0x1f567, - 0x1f5fb, 0x1f5ff, - 0x1f601, 0x1f610, - 0x1f612, 0x1f614, - 0x1f616, 0x1f616, - 0x1f618, 0x1f618, - 0x1f61a, 0x1f61a, - 0x1f61c, 0x1f61e, - 0x1f620, 0x1f625, - 0x1f628, 0x1f62b, - 0x1f62d, 0x1f62d, - 0x1f630, 0x1f633, - 0x1f635, 0x1f640, + 0x1f5fb, 0x1f640, 0x1f645, 0x1f64f, 0x1f680, 0x1f6c5, 0x1f700, 0x1f773, @@ -29252,10 +31494,10 @@ static const OnigCodePoint CR_Age_6_0[] = { 0xe0020, 0xe007f, 0xe0100, 0xe01ef, 0xefffe, 0x10ffff, -}; /* CR_Age_6_0 */ +}; /* CR_Age_6_2 */ -/* 'Age_6_1': Derived Age 6.1 */ -static const OnigCodePoint CR_Age_6_1[] = { +/* 'Age_6_3': Derived Age 6.3 */ +static const OnigCodePoint CR_Age_6_3[] = { 549, 0x0000, 0x0377, 0x037a, 0x037e, @@ -29272,7 +31514,7 @@ static const OnigCodePoint CR_Age_6_1[] = { 0x05d0, 0x05ea, 0x05f0, 0x05f4, 0x0600, 0x0604, - 0x0606, 0x061b, + 0x0606, 0x061c, 0x061e, 0x070d, 0x070f, 0x074a, 0x074d, 0x07b1, @@ -29515,10 +31757,10 @@ static const OnigCodePoint CR_Age_6_1[] = { 0x1ff2, 0x1ff4, 0x1ff6, 0x1ffe, 0x2000, 0x2064, - 0x206a, 0x2071, + 0x2066, 0x2071, 0x2074, 0x208e, 0x2090, 0x209c, - 0x20a0, 0x20b9, + 0x20a0, 0x20ba, 0x20d0, 0x20f0, 0x2100, 0x2189, 0x2190, 0x23f3, @@ -29806,27 +32048,26 @@ static const OnigCodePoint CR_Age_6_1[] = { 0xe0020, 0xe007f, 0xe0100, 0xe01ef, 0xefffe, 0x10ffff, -}; /* CR_Age_6_1 */ +}; /* CR_Age_6_3 */ -/* 'Age_6_2': Derived Age 6.2 */ -static const OnigCodePoint CR_Age_6_2[] = { - 549, +/* 'Age_7_0': Derived Age 7.0 */ +static const OnigCodePoint CR_Age_7_0[] = { + 610, 0x0000, 0x0377, - 0x037a, 0x037e, + 0x037a, 0x037f, 0x0384, 0x038a, 0x038c, 0x038c, 0x038e, 0x03a1, - 0x03a3, 0x0527, + 0x03a3, 0x052f, 0x0531, 0x0556, 0x0559, 0x055f, 0x0561, 0x0587, 0x0589, 0x058a, - 0x058f, 0x058f, + 0x058d, 0x058f, 0x0591, 0x05c7, 0x05d0, 0x05ea, 0x05f0, 0x05f4, - 0x0600, 0x0604, - 0x0606, 0x061b, + 0x0600, 0x061c, 0x061e, 0x070d, 0x070f, 0x074a, 0x074d, 0x07b1, @@ -29835,12 +32076,8 @@ static const OnigCodePoint CR_Age_6_2[] = { 0x0830, 0x083e, 0x0840, 0x085b, 0x085e, 0x085e, - 0x08a0, 0x08a0, - 0x08a2, 0x08ac, - 0x08e4, 0x08fe, - 0x0900, 0x0977, - 0x0979, 0x097f, - 0x0981, 0x0983, + 0x08a0, 0x08b2, + 0x08e4, 0x0983, 0x0985, 0x098c, 0x098f, 0x0990, 0x0993, 0x09a8, @@ -29913,12 +32150,11 @@ static const OnigCodePoint CR_Age_6_2[] = { 0x0bd0, 0x0bd0, 0x0bd7, 0x0bd7, 0x0be6, 0x0bfa, - 0x0c01, 0x0c03, + 0x0c00, 0x0c03, 0x0c05, 0x0c0c, 0x0c0e, 0x0c10, 0x0c12, 0x0c28, - 0x0c2a, 0x0c33, - 0x0c35, 0x0c39, + 0x0c2a, 0x0c39, 0x0c3d, 0x0c44, 0x0c46, 0x0c48, 0x0c4a, 0x0c4d, @@ -29927,7 +32163,7 @@ static const OnigCodePoint CR_Age_6_2[] = { 0x0c60, 0x0c63, 0x0c66, 0x0c6f, 0x0c78, 0x0c7f, - 0x0c82, 0x0c83, + 0x0c81, 0x0c83, 0x0c85, 0x0c8c, 0x0c8e, 0x0c90, 0x0c92, 0x0ca8, @@ -29941,7 +32177,7 @@ static const OnigCodePoint CR_Age_6_2[] = { 0x0ce0, 0x0ce3, 0x0ce6, 0x0cef, 0x0cf1, 0x0cf2, - 0x0d02, 0x0d03, + 0x0d01, 0x0d03, 0x0d05, 0x0d0c, 0x0d0e, 0x0d10, 0x0d12, 0x0d3a, @@ -29962,6 +32198,7 @@ static const OnigCodePoint CR_Age_6_2[] = { 0x0dcf, 0x0dd4, 0x0dd6, 0x0dd6, 0x0dd8, 0x0ddf, + 0x0de6, 0x0def, 0x0df2, 0x0df4, 0x0e01, 0x0e3a, 0x0e3f, 0x0e5b, @@ -30012,7 +32249,7 @@ static const OnigCodePoint CR_Age_6_2[] = { 0x1380, 0x1399, 0x13a0, 0x13f4, 0x1400, 0x169c, - 0x16a0, 0x16f0, + 0x16a0, 0x16f8, 0x1700, 0x170c, 0x170e, 0x1714, 0x1720, 0x1736, @@ -30028,7 +32265,7 @@ static const OnigCodePoint CR_Age_6_2[] = { 0x1820, 0x1877, 0x1880, 0x18aa, 0x18b0, 0x18f5, - 0x1900, 0x191c, + 0x1900, 0x191e, 0x1920, 0x192b, 0x1930, 0x193b, 0x1940, 0x1940, @@ -30043,6 +32280,7 @@ static const OnigCodePoint CR_Age_6_2[] = { 0x1a7f, 0x1a89, 0x1a90, 0x1a99, 0x1aa0, 0x1aad, + 0x1ab0, 0x1abe, 0x1b00, 0x1b4b, 0x1b50, 0x1b7c, 0x1b80, 0x1bf3, @@ -30051,7 +32289,8 @@ static const OnigCodePoint CR_Age_6_2[] = { 0x1c4d, 0x1c7f, 0x1cc0, 0x1cc7, 0x1cd0, 0x1cf6, - 0x1d00, 0x1de6, + 0x1cf8, 0x1cf9, + 0x1d00, 0x1df5, 0x1dfc, 0x1f15, 0x1f18, 0x1f1d, 0x1f20, 0x1f45, @@ -30069,18 +32308,20 @@ static const OnigCodePoint CR_Age_6_2[] = { 0x1ff2, 0x1ff4, 0x1ff6, 0x1ffe, 0x2000, 0x2064, - 0x206a, 0x2071, + 0x2066, 0x2071, 0x2074, 0x208e, 0x2090, 0x209c, - 0x20a0, 0x20ba, + 0x20a0, 0x20bd, 0x20d0, 0x20f0, 0x2100, 0x2189, - 0x2190, 0x23f3, + 0x2190, 0x23fa, 0x2400, 0x2426, 0x2440, 0x244a, - 0x2460, 0x26ff, - 0x2701, 0x2b4c, - 0x2b50, 0x2b59, + 0x2460, 0x2b73, + 0x2b76, 0x2b95, + 0x2b98, 0x2bb9, + 0x2bbd, 0x2bc8, + 0x2bca, 0x2bd1, 0x2c00, 0x2c2e, 0x2c30, 0x2c5e, 0x2c60, 0x2cf3, @@ -30098,7 +32339,7 @@ static const OnigCodePoint CR_Age_6_2[] = { 0x2dc8, 0x2dce, 0x2dd0, 0x2dd6, 0x2dd8, 0x2dde, - 0x2de0, 0x2e3b, + 0x2de0, 0x2e42, 0x2e80, 0x2e99, 0x2e9b, 0x2ef3, 0x2f00, 0x2fd5, @@ -30117,12 +32358,12 @@ static const OnigCodePoint CR_Age_6_2[] = { 0xa000, 0xa48c, 0xa490, 0xa4c6, 0xa4d0, 0xa62b, - 0xa640, 0xa697, + 0xa640, 0xa69d, 0xa69f, 0xa6f7, 0xa700, 0xa78e, - 0xa790, 0xa793, - 0xa7a0, 0xa7aa, - 0xa7f8, 0xa82b, + 0xa790, 0xa7ad, + 0xa7b0, 0xa7b1, + 0xa7f7, 0xa82b, 0xa830, 0xa839, 0xa840, 0xa877, 0xa880, 0xa8c4, @@ -30132,18 +32373,19 @@ static const OnigCodePoint CR_Age_6_2[] = { 0xa95f, 0xa97c, 0xa980, 0xa9cd, 0xa9cf, 0xa9d9, - 0xa9de, 0xa9df, + 0xa9de, 0xa9fe, 0xaa00, 0xaa36, 0xaa40, 0xaa4d, 0xaa50, 0xaa59, - 0xaa5c, 0xaa7b, - 0xaa80, 0xaac2, + 0xaa5c, 0xaac2, 0xaadb, 0xaaf6, 0xab01, 0xab06, 0xab09, 0xab0e, 0xab11, 0xab16, 0xab20, 0xab26, 0xab28, 0xab2e, + 0xab30, 0xab5f, + 0xab64, 0xab65, 0xabc0, 0xabed, 0xabf0, 0xabf9, 0xac00, 0xd7a3, @@ -30164,7 +32406,7 @@ static const OnigCodePoint CR_Age_6_2[] = { 0xfd92, 0xfdc7, 0xfdd0, 0xfdfd, 0xfe00, 0xfe19, - 0xfe20, 0xfe26, + 0xfe20, 0xfe2d, 0xfe30, 0xfe52, 0xfe54, 0xfe66, 0xfe68, 0xfe6b, @@ -30187,26 +32429,35 @@ static const OnigCodePoint CR_Age_6_2[] = { 0x10080, 0x100fa, 0x10100, 0x10102, 0x10107, 0x10133, - 0x10137, 0x1018a, + 0x10137, 0x1018c, 0x10190, 0x1019b, + 0x101a0, 0x101a0, 0x101d0, 0x101fd, 0x10280, 0x1029c, 0x102a0, 0x102d0, - 0x10300, 0x1031e, - 0x10320, 0x10323, + 0x102e0, 0x102fb, + 0x10300, 0x10323, 0x10330, 0x1034a, + 0x10350, 0x1037a, 0x10380, 0x1039d, 0x1039f, 0x103c3, 0x103c8, 0x103d5, 0x10400, 0x1049d, 0x104a0, 0x104a9, + 0x10500, 0x10527, + 0x10530, 0x10563, + 0x1056f, 0x1056f, + 0x10600, 0x10736, + 0x10740, 0x10755, + 0x10760, 0x10767, 0x10800, 0x10805, 0x10808, 0x10808, 0x1080a, 0x10835, 0x10837, 0x10838, 0x1083c, 0x1083c, 0x1083f, 0x10855, - 0x10857, 0x1085f, + 0x10857, 0x1089e, + 0x108a7, 0x108af, 0x10900, 0x1091b, 0x1091f, 0x10939, 0x1093f, 0x1093f, @@ -30220,33 +32471,82 @@ static const OnigCodePoint CR_Age_6_2[] = { 0x10a38, 0x10a3a, 0x10a3f, 0x10a47, 0x10a50, 0x10a58, - 0x10a60, 0x10a7f, + 0x10a60, 0x10a9f, + 0x10ac0, 0x10ae6, + 0x10aeb, 0x10af6, 0x10b00, 0x10b35, 0x10b39, 0x10b55, 0x10b58, 0x10b72, - 0x10b78, 0x10b7f, + 0x10b78, 0x10b91, + 0x10b99, 0x10b9c, + 0x10ba9, 0x10baf, 0x10c00, 0x10c48, 0x10e60, 0x10e7e, 0x11000, 0x1104d, 0x11052, 0x1106f, - 0x11080, 0x110c1, + 0x1107f, 0x110c1, 0x110d0, 0x110e8, 0x110f0, 0x110f9, 0x11100, 0x11134, 0x11136, 0x11143, + 0x11150, 0x11176, 0x11180, 0x111c8, - 0x111d0, 0x111d9, + 0x111cd, 0x111cd, + 0x111d0, 0x111da, + 0x111e1, 0x111f4, + 0x11200, 0x11211, + 0x11213, 0x1123d, + 0x112b0, 0x112ea, + 0x112f0, 0x112f9, + 0x11301, 0x11303, + 0x11305, 0x1130c, + 0x1130f, 0x11310, + 0x11313, 0x11328, + 0x1132a, 0x11330, + 0x11332, 0x11333, + 0x11335, 0x11339, + 0x1133c, 0x11344, + 0x11347, 0x11348, + 0x1134b, 0x1134d, + 0x11357, 0x11357, + 0x1135d, 0x11363, + 0x11366, 0x1136c, + 0x11370, 0x11374, + 0x11480, 0x114c7, + 0x114d0, 0x114d9, + 0x11580, 0x115b5, + 0x115b8, 0x115c9, + 0x11600, 0x11644, + 0x11650, 0x11659, 0x11680, 0x116b7, 0x116c0, 0x116c9, - 0x12000, 0x1236e, - 0x12400, 0x12462, - 0x12470, 0x12473, + 0x118a0, 0x118f2, + 0x118ff, 0x118ff, + 0x11ac0, 0x11af8, + 0x12000, 0x12398, + 0x12400, 0x1246e, + 0x12470, 0x12474, 0x13000, 0x1342e, 0x16800, 0x16a38, + 0x16a40, 0x16a5e, + 0x16a60, 0x16a69, + 0x16a6e, 0x16a6f, + 0x16ad0, 0x16aed, + 0x16af0, 0x16af5, + 0x16b00, 0x16b45, + 0x16b50, 0x16b59, + 0x16b5b, 0x16b61, + 0x16b63, 0x16b77, + 0x16b7d, 0x16b8f, 0x16f00, 0x16f44, 0x16f50, 0x16f7e, 0x16f8f, 0x16f9f, 0x1b000, 0x1b001, + 0x1bc00, 0x1bc6a, + 0x1bc70, 0x1bc7c, + 0x1bc80, 0x1bc88, + 0x1bc90, 0x1bc99, + 0x1bc9c, 0x1bca3, 0x1d000, 0x1d0f5, 0x1d100, 0x1d126, 0x1d129, 0x1d1dd, @@ -30274,6 +32574,8 @@ static const OnigCodePoint CR_Age_6_2[] = { 0x1d552, 0x1d6a5, 0x1d6a8, 0x1d7cb, 0x1d7ce, 0x1d7ff, + 0x1e800, 0x1e8c4, + 0x1e8c7, 0x1e8d6, 0x1ee00, 0x1ee03, 0x1ee05, 0x1ee1f, 0x1ee21, 0x1ee22, @@ -30311,10 +32613,10 @@ static const OnigCodePoint CR_Age_6_2[] = { 0x1f000, 0x1f02b, 0x1f030, 0x1f093, 0x1f0a0, 0x1f0ae, - 0x1f0b1, 0x1f0be, + 0x1f0b1, 0x1f0bf, 0x1f0c1, 0x1f0cf, - 0x1f0d1, 0x1f0df, - 0x1f100, 0x1f10a, + 0x1f0d1, 0x1f0f5, + 0x1f100, 0x1f10c, 0x1f110, 0x1f12e, 0x1f130, 0x1f16b, 0x1f170, 0x1f19a, @@ -30322,24 +32624,25 @@ static const OnigCodePoint CR_Age_6_2[] = { 0x1f210, 0x1f23a, 0x1f240, 0x1f248, 0x1f250, 0x1f251, - 0x1f300, 0x1f320, - 0x1f330, 0x1f335, - 0x1f337, 0x1f37c, - 0x1f380, 0x1f393, - 0x1f3a0, 0x1f3c4, - 0x1f3c6, 0x1f3ca, - 0x1f3e0, 0x1f3f0, - 0x1f400, 0x1f43e, - 0x1f440, 0x1f440, - 0x1f442, 0x1f4f7, - 0x1f4f9, 0x1f4fc, - 0x1f500, 0x1f53d, - 0x1f540, 0x1f543, - 0x1f550, 0x1f567, - 0x1f5fb, 0x1f640, - 0x1f645, 0x1f64f, - 0x1f680, 0x1f6c5, + 0x1f300, 0x1f32c, + 0x1f330, 0x1f37d, + 0x1f380, 0x1f3ce, + 0x1f3d4, 0x1f3f7, + 0x1f400, 0x1f4fe, + 0x1f500, 0x1f54a, + 0x1f550, 0x1f579, + 0x1f57b, 0x1f5a3, + 0x1f5a5, 0x1f642, + 0x1f645, 0x1f6cf, + 0x1f6e0, 0x1f6ec, + 0x1f6f0, 0x1f6f3, 0x1f700, 0x1f773, + 0x1f780, 0x1f7d4, + 0x1f800, 0x1f80b, + 0x1f810, 0x1f847, + 0x1f850, 0x1f859, + 0x1f860, 0x1f887, + 0x1f890, 0x1f8ad, 0x1fffe, 0x2a6d6, 0x2a700, 0x2b734, 0x2b740, 0x2b81d, @@ -30360,27 +32663,26 @@ static const OnigCodePoint CR_Age_6_2[] = { 0xe0020, 0xe007f, 0xe0100, 0xe01ef, 0xefffe, 0x10ffff, -}; /* CR_Age_6_2 */ +}; /* CR_Age_7_0 */ -/* 'Age_6_3': Derived Age 6.3 */ -static const OnigCodePoint CR_Age_6_3[] = { - 549, +/* 'Age_8_0': Derived Age 8.0 */ +static const OnigCodePoint CR_Age_8_0[] = { + 623, 0x0000, 0x0377, - 0x037a, 0x037e, + 0x037a, 0x037f, 0x0384, 0x038a, 0x038c, 0x038c, 0x038e, 0x03a1, - 0x03a3, 0x0527, + 0x03a3, 0x052f, 0x0531, 0x0556, 0x0559, 0x055f, 0x0561, 0x0587, 0x0589, 0x058a, - 0x058f, 0x058f, + 0x058d, 0x058f, 0x0591, 0x05c7, 0x05d0, 0x05ea, 0x05f0, 0x05f4, - 0x0600, 0x0604, - 0x0606, 0x061c, + 0x0600, 0x061c, 0x061e, 0x070d, 0x070f, 0x074a, 0x074d, 0x07b1, @@ -30389,12 +32691,8 @@ static const OnigCodePoint CR_Age_6_3[] = { 0x0830, 0x083e, 0x0840, 0x085b, 0x085e, 0x085e, - 0x08a0, 0x08a0, - 0x08a2, 0x08ac, - 0x08e4, 0x08fe, - 0x0900, 0x0977, - 0x0979, 0x097f, - 0x0981, 0x0983, + 0x08a0, 0x08b4, + 0x08e3, 0x0983, 0x0985, 0x098c, 0x098f, 0x0990, 0x0993, 0x09a8, @@ -30437,6 +32735,7 @@ static const OnigCodePoint CR_Age_6_3[] = { 0x0ad0, 0x0ad0, 0x0ae0, 0x0ae3, 0x0ae6, 0x0af1, + 0x0af9, 0x0af9, 0x0b01, 0x0b03, 0x0b05, 0x0b0c, 0x0b0f, 0x0b10, @@ -30467,21 +32766,20 @@ static const OnigCodePoint CR_Age_6_3[] = { 0x0bd0, 0x0bd0, 0x0bd7, 0x0bd7, 0x0be6, 0x0bfa, - 0x0c01, 0x0c03, + 0x0c00, 0x0c03, 0x0c05, 0x0c0c, 0x0c0e, 0x0c10, 0x0c12, 0x0c28, - 0x0c2a, 0x0c33, - 0x0c35, 0x0c39, + 0x0c2a, 0x0c39, 0x0c3d, 0x0c44, 0x0c46, 0x0c48, 0x0c4a, 0x0c4d, 0x0c55, 0x0c56, - 0x0c58, 0x0c59, + 0x0c58, 0x0c5a, 0x0c60, 0x0c63, 0x0c66, 0x0c6f, 0x0c78, 0x0c7f, - 0x0c82, 0x0c83, + 0x0c81, 0x0c83, 0x0c85, 0x0c8c, 0x0c8e, 0x0c90, 0x0c92, 0x0ca8, @@ -30495,7 +32793,7 @@ static const OnigCodePoint CR_Age_6_3[] = { 0x0ce0, 0x0ce3, 0x0ce6, 0x0cef, 0x0cf1, 0x0cf2, - 0x0d02, 0x0d03, + 0x0d01, 0x0d03, 0x0d05, 0x0d0c, 0x0d0e, 0x0d10, 0x0d12, 0x0d3a, @@ -30503,7 +32801,7 @@ static const OnigCodePoint CR_Age_6_3[] = { 0x0d46, 0x0d48, 0x0d4a, 0x0d4e, 0x0d57, 0x0d57, - 0x0d60, 0x0d63, + 0x0d5f, 0x0d63, 0x0d66, 0x0d75, 0x0d79, 0x0d7f, 0x0d82, 0x0d83, @@ -30516,6 +32814,7 @@ static const OnigCodePoint CR_Age_6_3[] = { 0x0dcf, 0x0dd4, 0x0dd6, 0x0dd6, 0x0dd8, 0x0ddf, + 0x0de6, 0x0def, 0x0df2, 0x0df4, 0x0e01, 0x0e3a, 0x0e3f, 0x0e5b, @@ -30564,9 +32863,10 @@ static const OnigCodePoint CR_Age_6_3[] = { 0x1318, 0x135a, 0x135d, 0x137c, 0x1380, 0x1399, - 0x13a0, 0x13f4, + 0x13a0, 0x13f5, + 0x13f8, 0x13fd, 0x1400, 0x169c, - 0x16a0, 0x16f0, + 0x16a0, 0x16f8, 0x1700, 0x170c, 0x170e, 0x1714, 0x1720, 0x1736, @@ -30582,7 +32882,7 @@ static const OnigCodePoint CR_Age_6_3[] = { 0x1820, 0x1877, 0x1880, 0x18aa, 0x18b0, 0x18f5, - 0x1900, 0x191c, + 0x1900, 0x191e, 0x1920, 0x192b, 0x1930, 0x193b, 0x1940, 0x1940, @@ -30597,6 +32897,7 @@ static const OnigCodePoint CR_Age_6_3[] = { 0x1a7f, 0x1a89, 0x1a90, 0x1a99, 0x1aa0, 0x1aad, + 0x1ab0, 0x1abe, 0x1b00, 0x1b4b, 0x1b50, 0x1b7c, 0x1b80, 0x1bf3, @@ -30605,7 +32906,8 @@ static const OnigCodePoint CR_Age_6_3[] = { 0x1c4d, 0x1c7f, 0x1cc0, 0x1cc7, 0x1cd0, 0x1cf6, - 0x1d00, 0x1de6, + 0x1cf8, 0x1cf9, + 0x1d00, 0x1df5, 0x1dfc, 0x1f15, 0x1f18, 0x1f1d, 0x1f20, 0x1f45, @@ -30626,15 +32928,18 @@ static const OnigCodePoint CR_Age_6_3[] = { 0x2066, 0x2071, 0x2074, 0x208e, 0x2090, 0x209c, - 0x20a0, 0x20ba, + 0x20a0, 0x20be, 0x20d0, 0x20f0, - 0x2100, 0x2189, - 0x2190, 0x23f3, + 0x2100, 0x218b, + 0x2190, 0x23fa, 0x2400, 0x2426, 0x2440, 0x244a, - 0x2460, 0x26ff, - 0x2701, 0x2b4c, - 0x2b50, 0x2b59, + 0x2460, 0x2b73, + 0x2b76, 0x2b95, + 0x2b98, 0x2bb9, + 0x2bbd, 0x2bc8, + 0x2bca, 0x2bd1, + 0x2bec, 0x2bef, 0x2c00, 0x2c2e, 0x2c30, 0x2c5e, 0x2c60, 0x2cf3, @@ -30652,7 +32957,7 @@ static const OnigCodePoint CR_Age_6_3[] = { 0x2dc8, 0x2dce, 0x2dd0, 0x2dd6, 0x2dd8, 0x2dde, - 0x2de0, 0x2e3b, + 0x2de0, 0x2e42, 0x2e80, 0x2e99, 0x2e9b, 0x2ef3, 0x2f00, 0x2fd5, @@ -30667,38 +32972,36 @@ static const OnigCodePoint CR_Age_6_3[] = { 0x31f0, 0x321e, 0x3220, 0x32fe, 0x3300, 0x4db5, - 0x4dc0, 0x9fcc, + 0x4dc0, 0x9fd5, 0xa000, 0xa48c, 0xa490, 0xa4c6, 0xa4d0, 0xa62b, - 0xa640, 0xa697, - 0xa69f, 0xa6f7, - 0xa700, 0xa78e, - 0xa790, 0xa793, - 0xa7a0, 0xa7aa, - 0xa7f8, 0xa82b, + 0xa640, 0xa6f7, + 0xa700, 0xa7ad, + 0xa7b0, 0xa7b7, + 0xa7f7, 0xa82b, 0xa830, 0xa839, 0xa840, 0xa877, 0xa880, 0xa8c4, 0xa8ce, 0xa8d9, - 0xa8e0, 0xa8fb, + 0xa8e0, 0xa8fd, 0xa900, 0xa953, 0xa95f, 0xa97c, 0xa980, 0xa9cd, 0xa9cf, 0xa9d9, - 0xa9de, 0xa9df, + 0xa9de, 0xa9fe, 0xaa00, 0xaa36, 0xaa40, 0xaa4d, 0xaa50, 0xaa59, - 0xaa5c, 0xaa7b, - 0xaa80, 0xaac2, + 0xaa5c, 0xaac2, 0xaadb, 0xaaf6, 0xab01, 0xab06, 0xab09, 0xab0e, 0xab11, 0xab16, 0xab20, 0xab26, 0xab28, 0xab2e, - 0xabc0, 0xabed, + 0xab30, 0xab65, + 0xab70, 0xabed, 0xabf0, 0xabf9, 0xac00, 0xd7a3, 0xd7b0, 0xd7c6, @@ -30718,8 +33021,7 @@ static const OnigCodePoint CR_Age_6_3[] = { 0xfd92, 0xfdc7, 0xfdd0, 0xfdfd, 0xfe00, 0xfe19, - 0xfe20, 0xfe26, - 0xfe30, 0xfe52, + 0xfe20, 0xfe52, 0xfe54, 0xfe66, 0xfe68, 0xfe6b, 0xfe70, 0xfe74, @@ -30741,32 +33043,43 @@ static const OnigCodePoint CR_Age_6_3[] = { 0x10080, 0x100fa, 0x10100, 0x10102, 0x10107, 0x10133, - 0x10137, 0x1018a, + 0x10137, 0x1018c, 0x10190, 0x1019b, + 0x101a0, 0x101a0, 0x101d0, 0x101fd, 0x10280, 0x1029c, 0x102a0, 0x102d0, - 0x10300, 0x1031e, - 0x10320, 0x10323, + 0x102e0, 0x102fb, + 0x10300, 0x10323, 0x10330, 0x1034a, + 0x10350, 0x1037a, 0x10380, 0x1039d, 0x1039f, 0x103c3, 0x103c8, 0x103d5, 0x10400, 0x1049d, 0x104a0, 0x104a9, + 0x10500, 0x10527, + 0x10530, 0x10563, + 0x1056f, 0x1056f, + 0x10600, 0x10736, + 0x10740, 0x10755, + 0x10760, 0x10767, 0x10800, 0x10805, 0x10808, 0x10808, 0x1080a, 0x10835, 0x10837, 0x10838, 0x1083c, 0x1083c, 0x1083f, 0x10855, - 0x10857, 0x1085f, - 0x10900, 0x1091b, + 0x10857, 0x1089e, + 0x108a7, 0x108af, + 0x108e0, 0x108f2, + 0x108f4, 0x108f5, + 0x108fb, 0x1091b, 0x1091f, 0x10939, 0x1093f, 0x1093f, 0x10980, 0x109b7, - 0x109be, 0x109bf, - 0x10a00, 0x10a03, + 0x109bc, 0x109cf, + 0x109d2, 0x10a03, 0x10a05, 0x10a06, 0x10a0c, 0x10a13, 0x10a15, 0x10a17, @@ -30774,36 +33087,98 @@ static const OnigCodePoint CR_Age_6_3[] = { 0x10a38, 0x10a3a, 0x10a3f, 0x10a47, 0x10a50, 0x10a58, - 0x10a60, 0x10a7f, + 0x10a60, 0x10a9f, + 0x10ac0, 0x10ae6, + 0x10aeb, 0x10af6, 0x10b00, 0x10b35, 0x10b39, 0x10b55, 0x10b58, 0x10b72, - 0x10b78, 0x10b7f, + 0x10b78, 0x10b91, + 0x10b99, 0x10b9c, + 0x10ba9, 0x10baf, 0x10c00, 0x10c48, + 0x10c80, 0x10cb2, + 0x10cc0, 0x10cf2, + 0x10cfa, 0x10cff, 0x10e60, 0x10e7e, 0x11000, 0x1104d, 0x11052, 0x1106f, - 0x11080, 0x110c1, + 0x1107f, 0x110c1, 0x110d0, 0x110e8, 0x110f0, 0x110f9, 0x11100, 0x11134, 0x11136, 0x11143, - 0x11180, 0x111c8, - 0x111d0, 0x111d9, + 0x11150, 0x11176, + 0x11180, 0x111cd, + 0x111d0, 0x111df, + 0x111e1, 0x111f4, + 0x11200, 0x11211, + 0x11213, 0x1123d, + 0x11280, 0x11286, + 0x11288, 0x11288, + 0x1128a, 0x1128d, + 0x1128f, 0x1129d, + 0x1129f, 0x112a9, + 0x112b0, 0x112ea, + 0x112f0, 0x112f9, + 0x11300, 0x11303, + 0x11305, 0x1130c, + 0x1130f, 0x11310, + 0x11313, 0x11328, + 0x1132a, 0x11330, + 0x11332, 0x11333, + 0x11335, 0x11339, + 0x1133c, 0x11344, + 0x11347, 0x11348, + 0x1134b, 0x1134d, + 0x11350, 0x11350, + 0x11357, 0x11357, + 0x1135d, 0x11363, + 0x11366, 0x1136c, + 0x11370, 0x11374, + 0x11480, 0x114c7, + 0x114d0, 0x114d9, + 0x11580, 0x115b5, + 0x115b8, 0x115dd, + 0x11600, 0x11644, + 0x11650, 0x11659, 0x11680, 0x116b7, 0x116c0, 0x116c9, - 0x12000, 0x1236e, - 0x12400, 0x12462, - 0x12470, 0x12473, + 0x11700, 0x11719, + 0x1171d, 0x1172b, + 0x11730, 0x1173f, + 0x118a0, 0x118f2, + 0x118ff, 0x118ff, + 0x11ac0, 0x11af8, + 0x12000, 0x12399, + 0x12400, 0x1246e, + 0x12470, 0x12474, + 0x12480, 0x12543, 0x13000, 0x1342e, + 0x14400, 0x14646, 0x16800, 0x16a38, + 0x16a40, 0x16a5e, + 0x16a60, 0x16a69, + 0x16a6e, 0x16a6f, + 0x16ad0, 0x16aed, + 0x16af0, 0x16af5, + 0x16b00, 0x16b45, + 0x16b50, 0x16b59, + 0x16b5b, 0x16b61, + 0x16b63, 0x16b77, + 0x16b7d, 0x16b8f, 0x16f00, 0x16f44, 0x16f50, 0x16f7e, 0x16f8f, 0x16f9f, 0x1b000, 0x1b001, + 0x1bc00, 0x1bc6a, + 0x1bc70, 0x1bc7c, + 0x1bc80, 0x1bc88, + 0x1bc90, 0x1bc99, + 0x1bc9c, 0x1bca3, 0x1d000, 0x1d0f5, 0x1d100, 0x1d126, - 0x1d129, 0x1d1dd, + 0x1d129, 0x1d1e8, 0x1d200, 0x1d245, 0x1d300, 0x1d356, 0x1d360, 0x1d371, @@ -30827,7 +33202,11 @@ static const OnigCodePoint CR_Age_6_3[] = { 0x1d54a, 0x1d550, 0x1d552, 0x1d6a5, 0x1d6a8, 0x1d7cb, - 0x1d7ce, 0x1d7ff, + 0x1d7ce, 0x1da8b, + 0x1da9b, 0x1da9f, + 0x1daa1, 0x1daaf, + 0x1e800, 0x1e8c4, + 0x1e8c7, 0x1e8d6, 0x1ee00, 0x1ee03, 0x1ee05, 0x1ee1f, 0x1ee21, 0x1ee22, @@ -30865,10 +33244,10 @@ static const OnigCodePoint CR_Age_6_3[] = { 0x1f000, 0x1f02b, 0x1f030, 0x1f093, 0x1f0a0, 0x1f0ae, - 0x1f0b1, 0x1f0be, + 0x1f0b1, 0x1f0bf, 0x1f0c1, 0x1f0cf, - 0x1f0d1, 0x1f0df, - 0x1f100, 0x1f10a, + 0x1f0d1, 0x1f0f5, + 0x1f100, 0x1f10c, 0x1f110, 0x1f12e, 0x1f130, 0x1f16b, 0x1f170, 0x1f19a, @@ -30876,27 +33255,25 @@ static const OnigCodePoint CR_Age_6_3[] = { 0x1f210, 0x1f23a, 0x1f240, 0x1f248, 0x1f250, 0x1f251, - 0x1f300, 0x1f320, - 0x1f330, 0x1f335, - 0x1f337, 0x1f37c, - 0x1f380, 0x1f393, - 0x1f3a0, 0x1f3c4, - 0x1f3c6, 0x1f3ca, - 0x1f3e0, 0x1f3f0, - 0x1f400, 0x1f43e, - 0x1f440, 0x1f440, - 0x1f442, 0x1f4f7, - 0x1f4f9, 0x1f4fc, - 0x1f500, 0x1f53d, - 0x1f540, 0x1f543, - 0x1f550, 0x1f567, - 0x1f5fb, 0x1f640, - 0x1f645, 0x1f64f, - 0x1f680, 0x1f6c5, + 0x1f300, 0x1f579, + 0x1f57b, 0x1f5a3, + 0x1f5a5, 0x1f6d0, + 0x1f6e0, 0x1f6ec, + 0x1f6f0, 0x1f6f3, 0x1f700, 0x1f773, + 0x1f780, 0x1f7d4, + 0x1f800, 0x1f80b, + 0x1f810, 0x1f847, + 0x1f850, 0x1f859, + 0x1f860, 0x1f887, + 0x1f890, 0x1f8ad, + 0x1f910, 0x1f918, + 0x1f980, 0x1f984, + 0x1f9c0, 0x1f9c0, 0x1fffe, 0x2a6d6, 0x2a700, 0x2b734, 0x2b740, 0x2b81d, + 0x2b820, 0x2cea1, 0x2f800, 0x2fa1d, 0x2fffe, 0x2ffff, 0x3fffe, 0x3ffff, @@ -30914,11 +33291,11 @@ static const OnigCodePoint CR_Age_6_3[] = { 0xe0020, 0xe007f, 0xe0100, 0xe01ef, 0xefffe, 0x10ffff, -}; /* CR_Age_6_3 */ +}; /* CR_Age_8_0 */ -/* 'Age_7_0': Derived Age 7.0 */ -static const OnigCodePoint CR_Age_7_0[] = { - 610, +/* 'Age_9_0': Derived Age 9.0 */ +static const OnigCodePoint CR_Age_9_0[] = { + 648, 0x0000, 0x0377, 0x037a, 0x037f, 0x0384, 0x038a, @@ -30942,8 +33319,9 @@ static const OnigCodePoint CR_Age_7_0[] = { 0x0830, 0x083e, 0x0840, 0x085b, 0x085e, 0x085e, - 0x08a0, 0x08b2, - 0x08e4, 0x0983, + 0x08a0, 0x08b4, + 0x08b6, 0x08bd, + 0x08d4, 0x0983, 0x0985, 0x098c, 0x098f, 0x0990, 0x0993, 0x09a8, @@ -30986,6 +33364,7 @@ static const OnigCodePoint CR_Age_7_0[] = { 0x0ad0, 0x0ad0, 0x0ae0, 0x0ae3, 0x0ae6, 0x0af1, + 0x0af9, 0x0af9, 0x0b01, 0x0b03, 0x0b05, 0x0b0c, 0x0b0f, 0x0b10, @@ -31025,11 +33404,10 @@ static const OnigCodePoint CR_Age_7_0[] = { 0x0c46, 0x0c48, 0x0c4a, 0x0c4d, 0x0c55, 0x0c56, - 0x0c58, 0x0c59, + 0x0c58, 0x0c5a, 0x0c60, 0x0c63, 0x0c66, 0x0c6f, - 0x0c78, 0x0c7f, - 0x0c81, 0x0c83, + 0x0c78, 0x0c83, 0x0c85, 0x0c8c, 0x0c8e, 0x0c90, 0x0c92, 0x0ca8, @@ -31049,11 +33427,9 @@ static const OnigCodePoint CR_Age_7_0[] = { 0x0d12, 0x0d3a, 0x0d3d, 0x0d44, 0x0d46, 0x0d48, - 0x0d4a, 0x0d4e, - 0x0d57, 0x0d57, - 0x0d60, 0x0d63, - 0x0d66, 0x0d75, - 0x0d79, 0x0d7f, + 0x0d4a, 0x0d4f, + 0x0d54, 0x0d63, + 0x0d66, 0x0d7f, 0x0d82, 0x0d83, 0x0d85, 0x0d96, 0x0d9a, 0x0db1, @@ -31113,7 +33489,8 @@ static const OnigCodePoint CR_Age_7_0[] = { 0x1318, 0x135a, 0x135d, 0x137c, 0x1380, 0x1399, - 0x13a0, 0x13f4, + 0x13a0, 0x13f5, + 0x13f8, 0x13fd, 0x1400, 0x169c, 0x16a0, 0x16f8, 0x1700, 0x170c, @@ -31152,12 +33529,12 @@ static const OnigCodePoint CR_Age_7_0[] = { 0x1b80, 0x1bf3, 0x1bfc, 0x1c37, 0x1c3b, 0x1c49, - 0x1c4d, 0x1c7f, + 0x1c4d, 0x1c88, 0x1cc0, 0x1cc7, 0x1cd0, 0x1cf6, 0x1cf8, 0x1cf9, 0x1d00, 0x1df5, - 0x1dfc, 0x1f15, + 0x1dfb, 0x1f15, 0x1f18, 0x1f1d, 0x1f20, 0x1f45, 0x1f48, 0x1f4d, @@ -31177,10 +33554,10 @@ static const OnigCodePoint CR_Age_7_0[] = { 0x2066, 0x2071, 0x2074, 0x208e, 0x2090, 0x209c, - 0x20a0, 0x20bd, + 0x20a0, 0x20be, 0x20d0, 0x20f0, - 0x2100, 0x2189, - 0x2190, 0x23fa, + 0x2100, 0x218b, + 0x2190, 0x23fe, 0x2400, 0x2426, 0x2440, 0x244a, 0x2460, 0x2b73, @@ -31188,6 +33565,7 @@ static const OnigCodePoint CR_Age_7_0[] = { 0x2b98, 0x2bb9, 0x2bbd, 0x2bc8, 0x2bca, 0x2bd1, + 0x2bec, 0x2bef, 0x2c00, 0x2c2e, 0x2c30, 0x2c5e, 0x2c60, 0x2cf3, @@ -31205,7 +33583,7 @@ static const OnigCodePoint CR_Age_7_0[] = { 0x2dc8, 0x2dce, 0x2dd0, 0x2dd6, 0x2dd8, 0x2dde, - 0x2de0, 0x2e42, + 0x2de0, 0x2e44, 0x2e80, 0x2e99, 0x2e9b, 0x2ef3, 0x2f00, 0x2fd5, @@ -31220,21 +33598,19 @@ static const OnigCodePoint CR_Age_7_0[] = { 0x31f0, 0x321e, 0x3220, 0x32fe, 0x3300, 0x4db5, - 0x4dc0, 0x9fcc, + 0x4dc0, 0x9fd5, 0xa000, 0xa48c, 0xa490, 0xa4c6, 0xa4d0, 0xa62b, - 0xa640, 0xa69d, - 0xa69f, 0xa6f7, - 0xa700, 0xa78e, - 0xa790, 0xa7ad, - 0xa7b0, 0xa7b1, + 0xa640, 0xa6f7, + 0xa700, 0xa7ae, + 0xa7b0, 0xa7b7, 0xa7f7, 0xa82b, 0xa830, 0xa839, 0xa840, 0xa877, - 0xa880, 0xa8c4, + 0xa880, 0xa8c5, 0xa8ce, 0xa8d9, - 0xa8e0, 0xa8fb, + 0xa8e0, 0xa8fd, 0xa900, 0xa953, 0xa95f, 0xa97c, 0xa980, 0xa9cd, @@ -31250,9 +33626,8 @@ static const OnigCodePoint CR_Age_7_0[] = { 0xab11, 0xab16, 0xab20, 0xab26, 0xab28, 0xab2e, - 0xab30, 0xab5f, - 0xab64, 0xab65, - 0xabc0, 0xabed, + 0xab30, 0xab65, + 0xab70, 0xabed, 0xabf0, 0xabf9, 0xac00, 0xd7a3, 0xd7b0, 0xd7c6, @@ -31272,8 +33647,7 @@ static const OnigCodePoint CR_Age_7_0[] = { 0xfd92, 0xfdc7, 0xfdd0, 0xfdfd, 0xfe00, 0xfe19, - 0xfe20, 0xfe2d, - 0xfe30, 0xfe52, + 0xfe20, 0xfe52, 0xfe54, 0xfe66, 0xfe68, 0xfe6b, 0xfe70, 0xfe74, @@ -31295,7 +33669,7 @@ static const OnigCodePoint CR_Age_7_0[] = { 0x10080, 0x100fa, 0x10100, 0x10102, 0x10107, 0x10133, - 0x10137, 0x1018c, + 0x10137, 0x1018e, 0x10190, 0x1019b, 0x101a0, 0x101a0, 0x101d0, 0x101fd, @@ -31310,6 +33684,8 @@ static const OnigCodePoint CR_Age_7_0[] = { 0x103c8, 0x103d5, 0x10400, 0x1049d, 0x104a0, 0x104a9, + 0x104b0, 0x104d3, + 0x104d8, 0x104fb, 0x10500, 0x10527, 0x10530, 0x10563, 0x1056f, 0x1056f, @@ -31324,12 +33700,14 @@ static const OnigCodePoint CR_Age_7_0[] = { 0x1083f, 0x10855, 0x10857, 0x1089e, 0x108a7, 0x108af, - 0x10900, 0x1091b, + 0x108e0, 0x108f2, + 0x108f4, 0x108f5, + 0x108fb, 0x1091b, 0x1091f, 0x10939, 0x1093f, 0x1093f, 0x10980, 0x109b7, - 0x109be, 0x109bf, - 0x10a00, 0x10a03, + 0x109bc, 0x109cf, + 0x109d2, 0x10a03, 0x10a05, 0x10a06, 0x10a0c, 0x10a13, 0x10a15, 0x10a17, @@ -31347,6 +33725,9 @@ static const OnigCodePoint CR_Age_7_0[] = { 0x10b99, 0x10b9c, 0x10ba9, 0x10baf, 0x10c00, 0x10c48, + 0x10c80, 0x10cb2, + 0x10cc0, 0x10cf2, + 0x10cfa, 0x10cff, 0x10e60, 0x10e7e, 0x11000, 0x1104d, 0x11052, 0x1106f, @@ -31356,15 +33737,19 @@ static const OnigCodePoint CR_Age_7_0[] = { 0x11100, 0x11134, 0x11136, 0x11143, 0x11150, 0x11176, - 0x11180, 0x111c8, - 0x111cd, 0x111cd, - 0x111d0, 0x111da, + 0x11180, 0x111cd, + 0x111d0, 0x111df, 0x111e1, 0x111f4, 0x11200, 0x11211, - 0x11213, 0x1123d, + 0x11213, 0x1123e, + 0x11280, 0x11286, + 0x11288, 0x11288, + 0x1128a, 0x1128d, + 0x1128f, 0x1129d, + 0x1129f, 0x112a9, 0x112b0, 0x112ea, 0x112f0, 0x112f9, - 0x11301, 0x11303, + 0x11300, 0x11303, 0x11305, 0x1130c, 0x1130f, 0x11310, 0x11313, 0x11328, @@ -31374,25 +33759,42 @@ static const OnigCodePoint CR_Age_7_0[] = { 0x1133c, 0x11344, 0x11347, 0x11348, 0x1134b, 0x1134d, + 0x11350, 0x11350, 0x11357, 0x11357, 0x1135d, 0x11363, 0x11366, 0x1136c, 0x11370, 0x11374, + 0x11400, 0x11459, + 0x1145b, 0x1145b, + 0x1145d, 0x1145d, 0x11480, 0x114c7, 0x114d0, 0x114d9, 0x11580, 0x115b5, - 0x115b8, 0x115c9, + 0x115b8, 0x115dd, 0x11600, 0x11644, 0x11650, 0x11659, + 0x11660, 0x1166c, 0x11680, 0x116b7, 0x116c0, 0x116c9, + 0x11700, 0x11719, + 0x1171d, 0x1172b, + 0x11730, 0x1173f, 0x118a0, 0x118f2, 0x118ff, 0x118ff, 0x11ac0, 0x11af8, - 0x12000, 0x12398, + 0x11c00, 0x11c08, + 0x11c0a, 0x11c36, + 0x11c38, 0x11c45, + 0x11c50, 0x11c6c, + 0x11c70, 0x11c8f, + 0x11c92, 0x11ca7, + 0x11ca9, 0x11cb6, + 0x12000, 0x12399, 0x12400, 0x1246e, 0x12470, 0x12474, + 0x12480, 0x12543, 0x13000, 0x1342e, + 0x14400, 0x14646, 0x16800, 0x16a38, 0x16a40, 0x16a5e, 0x16a60, 0x16a69, @@ -31407,6 +33809,9 @@ static const OnigCodePoint CR_Age_7_0[] = { 0x16f00, 0x16f44, 0x16f50, 0x16f7e, 0x16f8f, 0x16f9f, + 0x16fe0, 0x16fe0, + 0x17000, 0x187ec, + 0x18800, 0x18af2, 0x1b000, 0x1b001, 0x1bc00, 0x1bc6a, 0x1bc70, 0x1bc7c, @@ -31415,7 +33820,7 @@ static const OnigCodePoint CR_Age_7_0[] = { 0x1bc9c, 0x1bca3, 0x1d000, 0x1d0f5, 0x1d100, 0x1d126, - 0x1d129, 0x1d1dd, + 0x1d129, 0x1d1e8, 0x1d200, 0x1d245, 0x1d300, 0x1d356, 0x1d360, 0x1d371, @@ -31439,9 +33844,19 @@ static const OnigCodePoint CR_Age_7_0[] = { 0x1d54a, 0x1d550, 0x1d552, 0x1d6a5, 0x1d6a8, 0x1d7cb, - 0x1d7ce, 0x1d7ff, + 0x1d7ce, 0x1da8b, + 0x1da9b, 0x1da9f, + 0x1daa1, 0x1daaf, + 0x1e000, 0x1e006, + 0x1e008, 0x1e018, + 0x1e01b, 0x1e021, + 0x1e023, 0x1e024, + 0x1e026, 0x1e02a, 0x1e800, 0x1e8c4, 0x1e8c7, 0x1e8d6, + 0x1e900, 0x1e94a, + 0x1e950, 0x1e959, + 0x1e95e, 0x1e95f, 0x1ee00, 0x1ee03, 0x1ee05, 0x1ee1f, 0x1ee21, 0x1ee22, @@ -31485,23 +33900,14 @@ static const OnigCodePoint CR_Age_7_0[] = { 0x1f100, 0x1f10c, 0x1f110, 0x1f12e, 0x1f130, 0x1f16b, - 0x1f170, 0x1f19a, + 0x1f170, 0x1f1ac, 0x1f1e6, 0x1f202, - 0x1f210, 0x1f23a, + 0x1f210, 0x1f23b, 0x1f240, 0x1f248, 0x1f250, 0x1f251, - 0x1f300, 0x1f32c, - 0x1f330, 0x1f37d, - 0x1f380, 0x1f3ce, - 0x1f3d4, 0x1f3f7, - 0x1f400, 0x1f4fe, - 0x1f500, 0x1f54a, - 0x1f550, 0x1f579, - 0x1f57b, 0x1f5a3, - 0x1f5a5, 0x1f642, - 0x1f645, 0x1f6cf, + 0x1f300, 0x1f6d2, 0x1f6e0, 0x1f6ec, - 0x1f6f0, 0x1f6f3, + 0x1f6f0, 0x1f6f6, 0x1f700, 0x1f773, 0x1f780, 0x1f7d4, 0x1f800, 0x1f80b, @@ -31509,9 +33915,18 @@ static const OnigCodePoint CR_Age_7_0[] = { 0x1f850, 0x1f859, 0x1f860, 0x1f887, 0x1f890, 0x1f8ad, + 0x1f910, 0x1f91e, + 0x1f920, 0x1f927, + 0x1f930, 0x1f930, + 0x1f933, 0x1f93e, + 0x1f940, 0x1f94b, + 0x1f950, 0x1f95e, + 0x1f980, 0x1f991, + 0x1f9c0, 0x1f9c0, 0x1fffe, 0x2a6d6, 0x2a700, 0x2b734, 0x2b740, 0x2b81d, + 0x2b820, 0x2cea1, 0x2f800, 0x2fa1d, 0x2fffe, 0x2ffff, 0x3fffe, 0x3ffff, @@ -31529,11 +33944,11 @@ static const OnigCodePoint CR_Age_7_0[] = { 0xe0020, 0xe007f, 0xe0100, 0xe01ef, 0xefffe, 0x10ffff, -}; /* CR_Age_7_0 */ +}; /* CR_Age_9_0 */ -/* 'Age_8_0': Derived Age 8.0 */ -static const OnigCodePoint CR_Age_8_0[] = { - 623, +/* 'Age_10_0': Derived Age 10.0 */ +static const OnigCodePoint CR_Age_10_0[] = { + 659, 0x0000, 0x0377, 0x037a, 0x037f, 0x0384, 0x038a, @@ -31557,8 +33972,10 @@ static const OnigCodePoint CR_Age_8_0[] = { 0x0830, 0x083e, 0x0840, 0x085b, 0x085e, 0x085e, + 0x0860, 0x086a, 0x08a0, 0x08b4, - 0x08e3, 0x0983, + 0x08b6, 0x08bd, + 0x08d4, 0x0983, 0x0985, 0x098c, 0x098f, 0x0990, 0x0993, 0x09a8, @@ -31571,7 +33988,7 @@ static const OnigCodePoint CR_Age_8_0[] = { 0x09d7, 0x09d7, 0x09dc, 0x09dd, 0x09df, 0x09e3, - 0x09e6, 0x09fb, + 0x09e6, 0x09fd, 0x0a01, 0x0a03, 0x0a05, 0x0a0a, 0x0a0f, 0x0a10, @@ -31601,7 +34018,7 @@ static const OnigCodePoint CR_Age_8_0[] = { 0x0ad0, 0x0ad0, 0x0ae0, 0x0ae3, 0x0ae6, 0x0af1, - 0x0af9, 0x0af9, + 0x0af9, 0x0aff, 0x0b01, 0x0b03, 0x0b05, 0x0b0c, 0x0b0f, 0x0b10, @@ -31644,8 +34061,7 @@ static const OnigCodePoint CR_Age_8_0[] = { 0x0c58, 0x0c5a, 0x0c60, 0x0c63, 0x0c66, 0x0c6f, - 0x0c78, 0x0c7f, - 0x0c81, 0x0c83, + 0x0c78, 0x0c83, 0x0c85, 0x0c8c, 0x0c8e, 0x0c90, 0x0c92, 0x0ca8, @@ -31659,17 +34075,14 @@ static const OnigCodePoint CR_Age_8_0[] = { 0x0ce0, 0x0ce3, 0x0ce6, 0x0cef, 0x0cf1, 0x0cf2, - 0x0d01, 0x0d03, + 0x0d00, 0x0d03, 0x0d05, 0x0d0c, 0x0d0e, 0x0d10, - 0x0d12, 0x0d3a, - 0x0d3d, 0x0d44, + 0x0d12, 0x0d44, 0x0d46, 0x0d48, - 0x0d4a, 0x0d4e, - 0x0d57, 0x0d57, - 0x0d5f, 0x0d63, - 0x0d66, 0x0d75, - 0x0d79, 0x0d7f, + 0x0d4a, 0x0d4f, + 0x0d54, 0x0d63, + 0x0d66, 0x0d7f, 0x0d82, 0x0d83, 0x0d85, 0x0d96, 0x0d9a, 0x0db1, @@ -31769,12 +34182,11 @@ static const OnigCodePoint CR_Age_8_0[] = { 0x1b80, 0x1bf3, 0x1bfc, 0x1c37, 0x1c3b, 0x1c49, - 0x1c4d, 0x1c7f, + 0x1c4d, 0x1c88, 0x1cc0, 0x1cc7, - 0x1cd0, 0x1cf6, - 0x1cf8, 0x1cf9, - 0x1d00, 0x1df5, - 0x1dfc, 0x1f15, + 0x1cd0, 0x1cf9, + 0x1d00, 0x1df9, + 0x1dfb, 0x1f15, 0x1f18, 0x1f1d, 0x1f20, 0x1f45, 0x1f48, 0x1f4d, @@ -31794,17 +34206,16 @@ static const OnigCodePoint CR_Age_8_0[] = { 0x2066, 0x2071, 0x2074, 0x208e, 0x2090, 0x209c, - 0x20a0, 0x20be, + 0x20a0, 0x20bf, 0x20d0, 0x20f0, 0x2100, 0x218b, - 0x2190, 0x23fa, - 0x2400, 0x2426, + 0x2190, 0x2426, 0x2440, 0x244a, 0x2460, 0x2b73, 0x2b76, 0x2b95, 0x2b98, 0x2bb9, 0x2bbd, 0x2bc8, - 0x2bca, 0x2bd1, + 0x2bca, 0x2bd2, 0x2bec, 0x2bef, 0x2c00, 0x2c2e, 0x2c30, 0x2c5e, @@ -31823,7 +34234,7 @@ static const OnigCodePoint CR_Age_8_0[] = { 0x2dc8, 0x2dce, 0x2dd0, 0x2dd6, 0x2dd8, 0x2dde, - 0x2de0, 0x2e42, + 0x2de0, 0x2e49, 0x2e80, 0x2e99, 0x2e9b, 0x2ef3, 0x2f00, 0x2fd5, @@ -31831,24 +34242,24 @@ static const OnigCodePoint CR_Age_8_0[] = { 0x3000, 0x303f, 0x3041, 0x3096, 0x3099, 0x30ff, - 0x3105, 0x312d, + 0x3105, 0x312e, 0x3131, 0x318e, 0x3190, 0x31ba, 0x31c0, 0x31e3, 0x31f0, 0x321e, 0x3220, 0x32fe, 0x3300, 0x4db5, - 0x4dc0, 0x9fd5, + 0x4dc0, 0x9fea, 0xa000, 0xa48c, 0xa490, 0xa4c6, 0xa4d0, 0xa62b, 0xa640, 0xa6f7, - 0xa700, 0xa7ad, + 0xa700, 0xa7ae, 0xa7b0, 0xa7b7, 0xa7f7, 0xa82b, 0xa830, 0xa839, 0xa840, 0xa877, - 0xa880, 0xa8c4, + 0xa880, 0xa8c5, 0xa8ce, 0xa8d9, 0xa8e0, 0xa8fd, 0xa900, 0xa953, @@ -31909,7 +34320,7 @@ static const OnigCodePoint CR_Age_8_0[] = { 0x10080, 0x100fa, 0x10100, 0x10102, 0x10107, 0x10133, - 0x10137, 0x1018c, + 0x10137, 0x1018e, 0x10190, 0x1019b, 0x101a0, 0x101a0, 0x101d0, 0x101fd, @@ -31917,13 +34328,15 @@ static const OnigCodePoint CR_Age_8_0[] = { 0x102a0, 0x102d0, 0x102e0, 0x102fb, 0x10300, 0x10323, - 0x10330, 0x1034a, + 0x1032d, 0x1034a, 0x10350, 0x1037a, 0x10380, 0x1039d, 0x1039f, 0x103c3, 0x103c8, 0x103d5, 0x10400, 0x1049d, 0x104a0, 0x104a9, + 0x104b0, 0x104d3, + 0x104d8, 0x104fb, 0x10500, 0x10527, 0x10530, 0x10563, 0x1056f, 0x1056f, @@ -31979,7 +34392,7 @@ static const OnigCodePoint CR_Age_8_0[] = { 0x111d0, 0x111df, 0x111e1, 0x111f4, 0x11200, 0x11211, - 0x11213, 0x1123d, + 0x11213, 0x1123e, 0x11280, 0x11286, 0x11288, 0x11288, 0x1128a, 0x1128d, @@ -32002,12 +34415,16 @@ static const OnigCodePoint CR_Age_8_0[] = { 0x1135d, 0x11363, 0x11366, 0x1136c, 0x11370, 0x11374, + 0x11400, 0x11459, + 0x1145b, 0x1145b, + 0x1145d, 0x1145d, 0x11480, 0x114c7, 0x114d0, 0x114d9, 0x11580, 0x115b5, 0x115b8, 0x115dd, 0x11600, 0x11644, 0x11650, 0x11659, + 0x11660, 0x1166c, 0x11680, 0x116b7, 0x116c0, 0x116c9, 0x11700, 0x11719, @@ -32015,7 +34432,25 @@ static const OnigCodePoint CR_Age_8_0[] = { 0x11730, 0x1173f, 0x118a0, 0x118f2, 0x118ff, 0x118ff, + 0x11a00, 0x11a47, + 0x11a50, 0x11a83, + 0x11a86, 0x11a9c, + 0x11a9e, 0x11aa2, 0x11ac0, 0x11af8, + 0x11c00, 0x11c08, + 0x11c0a, 0x11c36, + 0x11c38, 0x11c45, + 0x11c50, 0x11c6c, + 0x11c70, 0x11c8f, + 0x11c92, 0x11ca7, + 0x11ca9, 0x11cb6, + 0x11d00, 0x11d06, + 0x11d08, 0x11d09, + 0x11d0b, 0x11d36, + 0x11d3a, 0x11d3a, + 0x11d3c, 0x11d3d, + 0x11d3f, 0x11d47, + 0x11d50, 0x11d59, 0x12000, 0x12399, 0x12400, 0x1246e, 0x12470, 0x12474, @@ -32036,7 +34471,11 @@ static const OnigCodePoint CR_Age_8_0[] = { 0x16f00, 0x16f44, 0x16f50, 0x16f7e, 0x16f8f, 0x16f9f, - 0x1b000, 0x1b001, + 0x16fe0, 0x16fe1, + 0x17000, 0x187ec, + 0x18800, 0x18af2, + 0x1b000, 0x1b11e, + 0x1b170, 0x1b2fb, 0x1bc00, 0x1bc6a, 0x1bc70, 0x1bc7c, 0x1bc80, 0x1bc88, @@ -32071,8 +34510,16 @@ static const OnigCodePoint CR_Age_8_0[] = { 0x1d7ce, 0x1da8b, 0x1da9b, 0x1da9f, 0x1daa1, 0x1daaf, + 0x1e000, 0x1e006, + 0x1e008, 0x1e018, + 0x1e01b, 0x1e021, + 0x1e023, 0x1e024, + 0x1e026, 0x1e02a, 0x1e800, 0x1e8c4, 0x1e8c7, 0x1e8d6, + 0x1e900, 0x1e94a, + 0x1e950, 0x1e959, + 0x1e95e, 0x1e95f, 0x1ee00, 0x1ee03, 0x1ee05, 0x1ee1f, 0x1ee21, 0x1ee22, @@ -32116,16 +34563,15 @@ static const OnigCodePoint CR_Age_8_0[] = { 0x1f100, 0x1f10c, 0x1f110, 0x1f12e, 0x1f130, 0x1f16b, - 0x1f170, 0x1f19a, + 0x1f170, 0x1f1ac, 0x1f1e6, 0x1f202, - 0x1f210, 0x1f23a, + 0x1f210, 0x1f23b, 0x1f240, 0x1f248, 0x1f250, 0x1f251, - 0x1f300, 0x1f579, - 0x1f57b, 0x1f5a3, - 0x1f5a5, 0x1f6d0, + 0x1f260, 0x1f265, + 0x1f300, 0x1f6d4, 0x1f6e0, 0x1f6ec, - 0x1f6f0, 0x1f6f3, + 0x1f6f0, 0x1f6f8, 0x1f700, 0x1f773, 0x1f780, 0x1f7d4, 0x1f800, 0x1f80b, @@ -32133,13 +34579,18 @@ static const OnigCodePoint CR_Age_8_0[] = { 0x1f850, 0x1f859, 0x1f860, 0x1f887, 0x1f890, 0x1f8ad, - 0x1f910, 0x1f918, - 0x1f980, 0x1f984, + 0x1f900, 0x1f90b, + 0x1f910, 0x1f93e, + 0x1f940, 0x1f94c, + 0x1f950, 0x1f96b, + 0x1f980, 0x1f997, 0x1f9c0, 0x1f9c0, + 0x1f9d0, 0x1f9e6, 0x1fffe, 0x2a6d6, 0x2a700, 0x2b734, 0x2b740, 0x2b81d, 0x2b820, 0x2cea1, + 0x2ceb0, 0x2ebe0, 0x2f800, 0x2fa1d, 0x2fffe, 0x2ffff, 0x3fffe, 0x3ffff, @@ -32157,11 +34608,11 @@ static const OnigCodePoint CR_Age_8_0[] = { 0xe0020, 0xe007f, 0xe0100, 0xe01ef, 0xefffe, 0x10ffff, -}; /* CR_Age_8_0 */ +}; /* CR_Age_10_0 */ -/* 'Age_9_0': Derived Age 9.0 */ -static const OnigCodePoint CR_Age_9_0[] = { - 648, +/* 'Age_11_0': Derived Age 11.0 */ +static const OnigCodePoint CR_Age_11_0[] = { + 668, 0x0000, 0x0377, 0x037a, 0x037f, 0x0384, 0x038a, @@ -32169,25 +34620,24 @@ static const OnigCodePoint CR_Age_9_0[] = { 0x038e, 0x03a1, 0x03a3, 0x052f, 0x0531, 0x0556, - 0x0559, 0x055f, - 0x0561, 0x0587, - 0x0589, 0x058a, + 0x0559, 0x058a, 0x058d, 0x058f, 0x0591, 0x05c7, 0x05d0, 0x05ea, - 0x05f0, 0x05f4, + 0x05ef, 0x05f4, 0x0600, 0x061c, 0x061e, 0x070d, 0x070f, 0x074a, 0x074d, 0x07b1, 0x07c0, 0x07fa, - 0x0800, 0x082d, + 0x07fd, 0x082d, 0x0830, 0x083e, 0x0840, 0x085b, 0x085e, 0x085e, + 0x0860, 0x086a, 0x08a0, 0x08b4, 0x08b6, 0x08bd, - 0x08d4, 0x0983, + 0x08d3, 0x0983, 0x0985, 0x098c, 0x098f, 0x0990, 0x0993, 0x09a8, @@ -32200,7 +34650,7 @@ static const OnigCodePoint CR_Age_9_0[] = { 0x09d7, 0x09d7, 0x09dc, 0x09dd, 0x09df, 0x09e3, - 0x09e6, 0x09fb, + 0x09e6, 0x09fe, 0x0a01, 0x0a03, 0x0a05, 0x0a0a, 0x0a0f, 0x0a10, @@ -32216,7 +34666,7 @@ static const OnigCodePoint CR_Age_9_0[] = { 0x0a51, 0x0a51, 0x0a59, 0x0a5c, 0x0a5e, 0x0a5e, - 0x0a66, 0x0a75, + 0x0a66, 0x0a76, 0x0a81, 0x0a83, 0x0a85, 0x0a8d, 0x0a8f, 0x0a91, @@ -32230,7 +34680,7 @@ static const OnigCodePoint CR_Age_9_0[] = { 0x0ad0, 0x0ad0, 0x0ae0, 0x0ae3, 0x0ae6, 0x0af1, - 0x0af9, 0x0af9, + 0x0af9, 0x0aff, 0x0b01, 0x0b03, 0x0b05, 0x0b0c, 0x0b0f, 0x0b10, @@ -32261,8 +34711,7 @@ static const OnigCodePoint CR_Age_9_0[] = { 0x0bd0, 0x0bd0, 0x0bd7, 0x0bd7, 0x0be6, 0x0bfa, - 0x0c00, 0x0c03, - 0x0c05, 0x0c0c, + 0x0c00, 0x0c0c, 0x0c0e, 0x0c10, 0x0c12, 0x0c28, 0x0c2a, 0x0c39, @@ -32273,8 +34722,7 @@ static const OnigCodePoint CR_Age_9_0[] = { 0x0c58, 0x0c5a, 0x0c60, 0x0c63, 0x0c66, 0x0c6f, - 0x0c78, 0x0c83, - 0x0c85, 0x0c8c, + 0x0c78, 0x0c8c, 0x0c8e, 0x0c90, 0x0c92, 0x0ca8, 0x0caa, 0x0cb3, @@ -32287,11 +34735,10 @@ static const OnigCodePoint CR_Age_9_0[] = { 0x0ce0, 0x0ce3, 0x0ce6, 0x0cef, 0x0cf1, 0x0cf2, - 0x0d01, 0x0d03, + 0x0d00, 0x0d03, 0x0d05, 0x0d0c, 0x0d0e, 0x0d10, - 0x0d12, 0x0d3a, - 0x0d3d, 0x0d44, + 0x0d12, 0x0d44, 0x0d46, 0x0d48, 0x0d4a, 0x0d4f, 0x0d54, 0x0d63, @@ -32371,7 +34818,7 @@ static const OnigCodePoint CR_Age_9_0[] = { 0x17f0, 0x17f9, 0x1800, 0x180e, 0x1810, 0x1819, - 0x1820, 0x1877, + 0x1820, 0x1878, 0x1880, 0x18aa, 0x18b0, 0x18f5, 0x1900, 0x191e, @@ -32396,10 +34843,10 @@ static const OnigCodePoint CR_Age_9_0[] = { 0x1bfc, 0x1c37, 0x1c3b, 0x1c49, 0x1c4d, 0x1c88, - 0x1cc0, 0x1cc7, - 0x1cd0, 0x1cf6, - 0x1cf8, 0x1cf9, - 0x1d00, 0x1df5, + 0x1c90, 0x1cba, + 0x1cbd, 0x1cc7, + 0x1cd0, 0x1cf9, + 0x1d00, 0x1df9, 0x1dfb, 0x1f15, 0x1f18, 0x1f1d, 0x1f20, 0x1f45, @@ -32420,18 +34867,15 @@ static const OnigCodePoint CR_Age_9_0[] = { 0x2066, 0x2071, 0x2074, 0x208e, 0x2090, 0x209c, - 0x20a0, 0x20be, + 0x20a0, 0x20bf, 0x20d0, 0x20f0, 0x2100, 0x218b, - 0x2190, 0x23fe, - 0x2400, 0x2426, + 0x2190, 0x2426, 0x2440, 0x244a, 0x2460, 0x2b73, 0x2b76, 0x2b95, - 0x2b98, 0x2bb9, - 0x2bbd, 0x2bc8, - 0x2bca, 0x2bd1, - 0x2bec, 0x2bef, + 0x2b98, 0x2bc8, + 0x2bca, 0x2bfe, 0x2c00, 0x2c2e, 0x2c30, 0x2c5e, 0x2c60, 0x2cf3, @@ -32449,7 +34893,7 @@ static const OnigCodePoint CR_Age_9_0[] = { 0x2dc8, 0x2dce, 0x2dd0, 0x2dd6, 0x2dd8, 0x2dde, - 0x2de0, 0x2e44, + 0x2de0, 0x2e4e, 0x2e80, 0x2e99, 0x2e9b, 0x2ef3, 0x2f00, 0x2fd5, @@ -32457,27 +34901,25 @@ static const OnigCodePoint CR_Age_9_0[] = { 0x3000, 0x303f, 0x3041, 0x3096, 0x3099, 0x30ff, - 0x3105, 0x312d, + 0x3105, 0x312f, 0x3131, 0x318e, 0x3190, 0x31ba, 0x31c0, 0x31e3, 0x31f0, 0x321e, 0x3220, 0x32fe, 0x3300, 0x4db5, - 0x4dc0, 0x9fd5, + 0x4dc0, 0x9fef, 0xa000, 0xa48c, 0xa490, 0xa4c6, 0xa4d0, 0xa62b, 0xa640, 0xa6f7, - 0xa700, 0xa7ae, - 0xa7b0, 0xa7b7, + 0xa700, 0xa7b9, 0xa7f7, 0xa82b, 0xa830, 0xa839, 0xa840, 0xa877, 0xa880, 0xa8c5, 0xa8ce, 0xa8d9, - 0xa8e0, 0xa8fd, - 0xa900, 0xa953, + 0xa8e0, 0xa953, 0xa95f, 0xa97c, 0xa980, 0xa9cd, 0xa9cf, 0xa9d9, @@ -32543,7 +34985,7 @@ static const OnigCodePoint CR_Age_9_0[] = { 0x102a0, 0x102d0, 0x102e0, 0x102fb, 0x10300, 0x10323, - 0x10330, 0x1034a, + 0x1032d, 0x1034a, 0x10350, 0x1037a, 0x10380, 0x1039d, 0x1039f, 0x103c3, @@ -32577,9 +35019,9 @@ static const OnigCodePoint CR_Age_9_0[] = { 0x10a05, 0x10a06, 0x10a0c, 0x10a13, 0x10a15, 0x10a17, - 0x10a19, 0x10a33, + 0x10a19, 0x10a35, 0x10a38, 0x10a3a, - 0x10a3f, 0x10a47, + 0x10a3f, 0x10a48, 0x10a50, 0x10a58, 0x10a60, 0x10a9f, 0x10ac0, 0x10ae6, @@ -32593,15 +35035,19 @@ static const OnigCodePoint CR_Age_9_0[] = { 0x10c00, 0x10c48, 0x10c80, 0x10cb2, 0x10cc0, 0x10cf2, - 0x10cfa, 0x10cff, + 0x10cfa, 0x10d27, + 0x10d30, 0x10d39, 0x10e60, 0x10e7e, + 0x10f00, 0x10f27, + 0x10f30, 0x10f59, 0x11000, 0x1104d, 0x11052, 0x1106f, 0x1107f, 0x110c1, + 0x110cd, 0x110cd, 0x110d0, 0x110e8, 0x110f0, 0x110f9, 0x11100, 0x11134, - 0x11136, 0x11143, + 0x11136, 0x11146, 0x11150, 0x11176, 0x11180, 0x111cd, 0x111d0, 0x111df, @@ -32622,7 +35068,7 @@ static const OnigCodePoint CR_Age_9_0[] = { 0x1132a, 0x11330, 0x11332, 0x11333, 0x11335, 0x11339, - 0x1133c, 0x11344, + 0x1133b, 0x11344, 0x11347, 0x11348, 0x1134b, 0x1134d, 0x11350, 0x11350, @@ -32632,7 +35078,7 @@ static const OnigCodePoint CR_Age_9_0[] = { 0x11370, 0x11374, 0x11400, 0x11459, 0x1145b, 0x1145b, - 0x1145d, 0x1145d, + 0x1145d, 0x1145e, 0x11480, 0x114c7, 0x114d0, 0x114d9, 0x11580, 0x115b5, @@ -32642,11 +35088,15 @@ static const OnigCodePoint CR_Age_9_0[] = { 0x11660, 0x1166c, 0x11680, 0x116b7, 0x116c0, 0x116c9, - 0x11700, 0x11719, + 0x11700, 0x1171a, 0x1171d, 0x1172b, 0x11730, 0x1173f, + 0x11800, 0x1183b, 0x118a0, 0x118f2, 0x118ff, 0x118ff, + 0x11a00, 0x11a47, + 0x11a50, 0x11a83, + 0x11a86, 0x11aa2, 0x11ac0, 0x11af8, 0x11c00, 0x11c08, 0x11c0a, 0x11c36, @@ -32655,6 +35105,20 @@ static const OnigCodePoint CR_Age_9_0[] = { 0x11c70, 0x11c8f, 0x11c92, 0x11ca7, 0x11ca9, 0x11cb6, + 0x11d00, 0x11d06, + 0x11d08, 0x11d09, + 0x11d0b, 0x11d36, + 0x11d3a, 0x11d3a, + 0x11d3c, 0x11d3d, + 0x11d3f, 0x11d47, + 0x11d50, 0x11d59, + 0x11d60, 0x11d65, + 0x11d67, 0x11d68, + 0x11d6a, 0x11d8e, + 0x11d90, 0x11d91, + 0x11d93, 0x11d98, + 0x11da0, 0x11da9, + 0x11ee0, 0x11ef8, 0x12000, 0x12399, 0x12400, 0x1246e, 0x12470, 0x12474, @@ -32672,13 +35136,15 @@ static const OnigCodePoint CR_Age_9_0[] = { 0x16b5b, 0x16b61, 0x16b63, 0x16b77, 0x16b7d, 0x16b8f, + 0x16e40, 0x16e9a, 0x16f00, 0x16f44, 0x16f50, 0x16f7e, 0x16f8f, 0x16f9f, - 0x16fe0, 0x16fe0, - 0x17000, 0x187ec, + 0x16fe0, 0x16fe1, + 0x17000, 0x187f1, 0x18800, 0x18af2, - 0x1b000, 0x1b001, + 0x1b000, 0x1b11e, + 0x1b170, 0x1b2fb, 0x1bc00, 0x1bc6a, 0x1bc70, 0x1bc7c, 0x1bc80, 0x1bc88, @@ -32688,8 +35154,9 @@ static const OnigCodePoint CR_Age_9_0[] = { 0x1d100, 0x1d126, 0x1d129, 0x1d1e8, 0x1d200, 0x1d245, + 0x1d2e0, 0x1d2f3, 0x1d300, 0x1d356, - 0x1d360, 0x1d371, + 0x1d360, 0x1d378, 0x1d400, 0x1d454, 0x1d456, 0x1d49c, 0x1d49e, 0x1d49f, @@ -32723,6 +35190,7 @@ static const OnigCodePoint CR_Age_9_0[] = { 0x1e900, 0x1e94a, 0x1e950, 0x1e959, 0x1e95e, 0x1e95f, + 0x1ec71, 0x1ecb4, 0x1ee00, 0x1ee03, 0x1ee05, 0x1ee1f, 0x1ee21, 0x1ee22, @@ -32764,35 +35232,38 @@ static const OnigCodePoint CR_Age_9_0[] = { 0x1f0c1, 0x1f0cf, 0x1f0d1, 0x1f0f5, 0x1f100, 0x1f10c, - 0x1f110, 0x1f12e, - 0x1f130, 0x1f16b, + 0x1f110, 0x1f16b, 0x1f170, 0x1f1ac, 0x1f1e6, 0x1f202, 0x1f210, 0x1f23b, 0x1f240, 0x1f248, 0x1f250, 0x1f251, - 0x1f300, 0x1f6d2, + 0x1f260, 0x1f265, + 0x1f300, 0x1f6d4, 0x1f6e0, 0x1f6ec, - 0x1f6f0, 0x1f6f6, + 0x1f6f0, 0x1f6f9, 0x1f700, 0x1f773, - 0x1f780, 0x1f7d4, + 0x1f780, 0x1f7d8, 0x1f800, 0x1f80b, 0x1f810, 0x1f847, 0x1f850, 0x1f859, 0x1f860, 0x1f887, 0x1f890, 0x1f8ad, - 0x1f910, 0x1f91e, - 0x1f920, 0x1f927, - 0x1f930, 0x1f930, - 0x1f933, 0x1f93e, - 0x1f940, 0x1f94b, - 0x1f950, 0x1f95e, - 0x1f980, 0x1f991, - 0x1f9c0, 0x1f9c0, + 0x1f900, 0x1f90b, + 0x1f910, 0x1f93e, + 0x1f940, 0x1f970, + 0x1f973, 0x1f976, + 0x1f97a, 0x1f97a, + 0x1f97c, 0x1f9a2, + 0x1f9b0, 0x1f9b9, + 0x1f9c0, 0x1f9c2, + 0x1f9d0, 0x1f9ff, + 0x1fa60, 0x1fa6d, 0x1fffe, 0x2a6d6, 0x2a700, 0x2b734, 0x2b740, 0x2b81d, 0x2b820, 0x2cea1, + 0x2ceb0, 0x2ebe0, 0x2f800, 0x2fa1d, 0x2fffe, 0x2ffff, 0x3fffe, 0x3ffff, @@ -32810,11 +35281,11 @@ static const OnigCodePoint CR_Age_9_0[] = { 0xe0020, 0xe007f, 0xe0100, 0xe01ef, 0xefffe, 0x10ffff, -}; /* CR_Age_9_0 */ +}; /* CR_Age_11_0 */ -/* 'Age_10_0': Derived Age 10.0 */ -static const OnigCodePoint CR_Age_10_0[] = { - 659, +/* 'Age_12_0': Derived Age 12.0 */ +static const OnigCodePoint CR_Age_12_0[] = { + 677, 0x0000, 0x0377, 0x037a, 0x037f, 0x0384, 0x038a, @@ -32822,26 +35293,24 @@ static const OnigCodePoint CR_Age_10_0[] = { 0x038e, 0x03a1, 0x03a3, 0x052f, 0x0531, 0x0556, - 0x0559, 0x055f, - 0x0561, 0x0587, - 0x0589, 0x058a, + 0x0559, 0x058a, 0x058d, 0x058f, 0x0591, 0x05c7, 0x05d0, 0x05ea, - 0x05f0, 0x05f4, + 0x05ef, 0x05f4, 0x0600, 0x061c, 0x061e, 0x070d, 0x070f, 0x074a, 0x074d, 0x07b1, 0x07c0, 0x07fa, - 0x0800, 0x082d, + 0x07fd, 0x082d, 0x0830, 0x083e, 0x0840, 0x085b, 0x085e, 0x085e, 0x0860, 0x086a, 0x08a0, 0x08b4, 0x08b6, 0x08bd, - 0x08d4, 0x0983, + 0x08d3, 0x0983, 0x0985, 0x098c, 0x098f, 0x0990, 0x0993, 0x09a8, @@ -32854,7 +35323,7 @@ static const OnigCodePoint CR_Age_10_0[] = { 0x09d7, 0x09d7, 0x09dc, 0x09dd, 0x09df, 0x09e3, - 0x09e6, 0x09fd, + 0x09e6, 0x09fe, 0x0a01, 0x0a03, 0x0a05, 0x0a0a, 0x0a0f, 0x0a10, @@ -32870,7 +35339,7 @@ static const OnigCodePoint CR_Age_10_0[] = { 0x0a51, 0x0a51, 0x0a59, 0x0a5c, 0x0a5e, 0x0a5e, - 0x0a66, 0x0a75, + 0x0a66, 0x0a76, 0x0a81, 0x0a83, 0x0a85, 0x0a8d, 0x0a8f, 0x0a91, @@ -32915,8 +35384,7 @@ static const OnigCodePoint CR_Age_10_0[] = { 0x0bd0, 0x0bd0, 0x0bd7, 0x0bd7, 0x0be6, 0x0bfa, - 0x0c00, 0x0c03, - 0x0c05, 0x0c0c, + 0x0c00, 0x0c0c, 0x0c0e, 0x0c10, 0x0c12, 0x0c28, 0x0c2a, 0x0c39, @@ -32927,8 +35395,7 @@ static const OnigCodePoint CR_Age_10_0[] = { 0x0c58, 0x0c5a, 0x0c60, 0x0c63, 0x0c66, 0x0c6f, - 0x0c78, 0x0c83, - 0x0c85, 0x0c8c, + 0x0c77, 0x0c8c, 0x0c8e, 0x0c90, 0x0c92, 0x0ca8, 0x0caa, 0x0cb3, @@ -32965,17 +35432,10 @@ static const OnigCodePoint CR_Age_10_0[] = { 0x0e3f, 0x0e5b, 0x0e81, 0x0e82, 0x0e84, 0x0e84, - 0x0e87, 0x0e88, - 0x0e8a, 0x0e8a, - 0x0e8d, 0x0e8d, - 0x0e94, 0x0e97, - 0x0e99, 0x0e9f, - 0x0ea1, 0x0ea3, + 0x0e86, 0x0e8a, + 0x0e8c, 0x0ea3, 0x0ea5, 0x0ea5, - 0x0ea7, 0x0ea7, - 0x0eaa, 0x0eab, - 0x0ead, 0x0eb9, - 0x0ebb, 0x0ebd, + 0x0ea7, 0x0ebd, 0x0ec0, 0x0ec4, 0x0ec6, 0x0ec6, 0x0ec8, 0x0ecd, @@ -33024,7 +35484,7 @@ static const OnigCodePoint CR_Age_10_0[] = { 0x17f0, 0x17f9, 0x1800, 0x180e, 0x1810, 0x1819, - 0x1820, 0x1877, + 0x1820, 0x1878, 0x1880, 0x18aa, 0x18b0, 0x18f5, 0x1900, 0x191e, @@ -33049,8 +35509,9 @@ static const OnigCodePoint CR_Age_10_0[] = { 0x1bfc, 0x1c37, 0x1c3b, 0x1c49, 0x1c4d, 0x1c88, - 0x1cc0, 0x1cc7, - 0x1cd0, 0x1cf9, + 0x1c90, 0x1cba, + 0x1cbd, 0x1cc7, + 0x1cd0, 0x1cfa, 0x1d00, 0x1df9, 0x1dfb, 0x1f15, 0x1f18, 0x1f1d, @@ -33079,11 +35540,7 @@ static const OnigCodePoint CR_Age_10_0[] = { 0x2440, 0x244a, 0x2460, 0x2b73, 0x2b76, 0x2b95, - 0x2b98, 0x2bb9, - 0x2bbd, 0x2bc8, - 0x2bca, 0x2bd2, - 0x2bec, 0x2bef, - 0x2c00, 0x2c2e, + 0x2b98, 0x2c2e, 0x2c30, 0x2c5e, 0x2c60, 0x2cf3, 0x2cf9, 0x2d25, @@ -33100,7 +35557,7 @@ static const OnigCodePoint CR_Age_10_0[] = { 0x2dc8, 0x2dce, 0x2dd0, 0x2dd6, 0x2dd8, 0x2dde, - 0x2de0, 0x2e49, + 0x2de0, 0x2e4f, 0x2e80, 0x2e99, 0x2e9b, 0x2ef3, 0x2f00, 0x2fd5, @@ -33108,27 +35565,26 @@ static const OnigCodePoint CR_Age_10_0[] = { 0x3000, 0x303f, 0x3041, 0x3096, 0x3099, 0x30ff, - 0x3105, 0x312e, + 0x3105, 0x312f, 0x3131, 0x318e, 0x3190, 0x31ba, 0x31c0, 0x31e3, 0x31f0, 0x321e, 0x3220, 0x32fe, 0x3300, 0x4db5, - 0x4dc0, 0x9fea, + 0x4dc0, 0x9fef, 0xa000, 0xa48c, 0xa490, 0xa4c6, 0xa4d0, 0xa62b, 0xa640, 0xa6f7, - 0xa700, 0xa7ae, - 0xa7b0, 0xa7b7, + 0xa700, 0xa7bf, + 0xa7c2, 0xa7c6, 0xa7f7, 0xa82b, 0xa830, 0xa839, 0xa840, 0xa877, 0xa880, 0xa8c5, 0xa8ce, 0xa8d9, - 0xa8e0, 0xa8fd, - 0xa900, 0xa953, + 0xa8e0, 0xa953, 0xa95f, 0xa97c, 0xa980, 0xa9cd, 0xa9cf, 0xa9d9, @@ -33143,7 +35599,7 @@ static const OnigCodePoint CR_Age_10_0[] = { 0xab11, 0xab16, 0xab20, 0xab26, 0xab28, 0xab2e, - 0xab30, 0xab65, + 0xab30, 0xab67, 0xab70, 0xabed, 0xabf0, 0xabf9, 0xac00, 0xd7a3, @@ -33228,9 +35684,9 @@ static const OnigCodePoint CR_Age_10_0[] = { 0x10a05, 0x10a06, 0x10a0c, 0x10a13, 0x10a15, 0x10a17, - 0x10a19, 0x10a33, + 0x10a19, 0x10a35, 0x10a38, 0x10a3a, - 0x10a3f, 0x10a47, + 0x10a3f, 0x10a48, 0x10a50, 0x10a58, 0x10a60, 0x10a9f, 0x10ac0, 0x10ae6, @@ -33244,15 +35700,20 @@ static const OnigCodePoint CR_Age_10_0[] = { 0x10c00, 0x10c48, 0x10c80, 0x10cb2, 0x10cc0, 0x10cf2, - 0x10cfa, 0x10cff, + 0x10cfa, 0x10d27, + 0x10d30, 0x10d39, 0x10e60, 0x10e7e, + 0x10f00, 0x10f27, + 0x10f30, 0x10f59, + 0x10fe0, 0x10ff6, 0x11000, 0x1104d, 0x11052, 0x1106f, 0x1107f, 0x110c1, + 0x110cd, 0x110cd, 0x110d0, 0x110e8, 0x110f0, 0x110f9, 0x11100, 0x11134, - 0x11136, 0x11143, + 0x11136, 0x11146, 0x11150, 0x11176, 0x11180, 0x111cd, 0x111d0, 0x111df, @@ -33273,7 +35734,7 @@ static const OnigCodePoint CR_Age_10_0[] = { 0x1132a, 0x11330, 0x11332, 0x11333, 0x11335, 0x11339, - 0x1133c, 0x11344, + 0x1133b, 0x11344, 0x11347, 0x11348, 0x1134b, 0x1134d, 0x11350, 0x11350, @@ -33283,7 +35744,7 @@ static const OnigCodePoint CR_Age_10_0[] = { 0x11370, 0x11374, 0x11400, 0x11459, 0x1145b, 0x1145b, - 0x1145d, 0x1145d, + 0x1145d, 0x1145f, 0x11480, 0x114c7, 0x114d0, 0x114d9, 0x11580, 0x115b5, @@ -33291,17 +35752,19 @@ static const OnigCodePoint CR_Age_10_0[] = { 0x11600, 0x11644, 0x11650, 0x11659, 0x11660, 0x1166c, - 0x11680, 0x116b7, + 0x11680, 0x116b8, 0x116c0, 0x116c9, - 0x11700, 0x11719, + 0x11700, 0x1171a, 0x1171d, 0x1172b, 0x11730, 0x1173f, + 0x11800, 0x1183b, 0x118a0, 0x118f2, 0x118ff, 0x118ff, + 0x119a0, 0x119a7, + 0x119aa, 0x119d7, + 0x119da, 0x119e4, 0x11a00, 0x11a47, - 0x11a50, 0x11a83, - 0x11a86, 0x11a9c, - 0x11a9e, 0x11aa2, + 0x11a50, 0x11aa2, 0x11ac0, 0x11af8, 0x11c00, 0x11c08, 0x11c0a, 0x11c36, @@ -33317,11 +35780,20 @@ static const OnigCodePoint CR_Age_10_0[] = { 0x11d3c, 0x11d3d, 0x11d3f, 0x11d47, 0x11d50, 0x11d59, - 0x12000, 0x12399, + 0x11d60, 0x11d65, + 0x11d67, 0x11d68, + 0x11d6a, 0x11d8e, + 0x11d90, 0x11d91, + 0x11d93, 0x11d98, + 0x11da0, 0x11da9, + 0x11ee0, 0x11ef8, + 0x11fc0, 0x11ff1, + 0x11fff, 0x12399, 0x12400, 0x1246e, 0x12470, 0x12474, 0x12480, 0x12543, 0x13000, 0x1342e, + 0x13430, 0x13438, 0x14400, 0x14646, 0x16800, 0x16a38, 0x16a40, 0x16a5e, @@ -33334,13 +35806,16 @@ static const OnigCodePoint CR_Age_10_0[] = { 0x16b5b, 0x16b61, 0x16b63, 0x16b77, 0x16b7d, 0x16b8f, - 0x16f00, 0x16f44, - 0x16f50, 0x16f7e, + 0x16e40, 0x16e9a, + 0x16f00, 0x16f4a, + 0x16f4f, 0x16f87, 0x16f8f, 0x16f9f, - 0x16fe0, 0x16fe1, - 0x17000, 0x187ec, + 0x16fe0, 0x16fe3, + 0x17000, 0x187f7, 0x18800, 0x18af2, 0x1b000, 0x1b11e, + 0x1b150, 0x1b152, + 0x1b164, 0x1b167, 0x1b170, 0x1b2fb, 0x1bc00, 0x1bc6a, 0x1bc70, 0x1bc7c, @@ -33351,8 +35826,9 @@ static const OnigCodePoint CR_Age_10_0[] = { 0x1d100, 0x1d126, 0x1d129, 0x1d1e8, 0x1d200, 0x1d245, + 0x1d2e0, 0x1d2f3, 0x1d300, 0x1d356, - 0x1d360, 0x1d371, + 0x1d360, 0x1d378, 0x1d400, 0x1d454, 0x1d456, 0x1d49c, 0x1d49e, 0x1d49f, @@ -33381,11 +35857,19 @@ static const OnigCodePoint CR_Age_10_0[] = { 0x1e01b, 0x1e021, 0x1e023, 0x1e024, 0x1e026, 0x1e02a, + 0x1e100, 0x1e12c, + 0x1e130, 0x1e13d, + 0x1e140, 0x1e149, + 0x1e14e, 0x1e14f, + 0x1e2c0, 0x1e2f9, + 0x1e2ff, 0x1e2ff, 0x1e800, 0x1e8c4, 0x1e8c7, 0x1e8d6, - 0x1e900, 0x1e94a, + 0x1e900, 0x1e94b, 0x1e950, 0x1e959, 0x1e95e, 0x1e95f, + 0x1ec71, 0x1ecb4, + 0x1ed01, 0x1ed3d, 0x1ee00, 0x1ee03, 0x1ee05, 0x1ee1f, 0x1ee21, 0x1ee22, @@ -33427,31 +35911,36 @@ static const OnigCodePoint CR_Age_10_0[] = { 0x1f0c1, 0x1f0cf, 0x1f0d1, 0x1f0f5, 0x1f100, 0x1f10c, - 0x1f110, 0x1f12e, - 0x1f130, 0x1f16b, + 0x1f110, 0x1f16c, 0x1f170, 0x1f1ac, 0x1f1e6, 0x1f202, 0x1f210, 0x1f23b, 0x1f240, 0x1f248, 0x1f250, 0x1f251, 0x1f260, 0x1f265, - 0x1f300, 0x1f6d4, + 0x1f300, 0x1f6d5, 0x1f6e0, 0x1f6ec, - 0x1f6f0, 0x1f6f8, + 0x1f6f0, 0x1f6fa, 0x1f700, 0x1f773, - 0x1f780, 0x1f7d4, + 0x1f780, 0x1f7d8, + 0x1f7e0, 0x1f7eb, 0x1f800, 0x1f80b, 0x1f810, 0x1f847, 0x1f850, 0x1f859, 0x1f860, 0x1f887, 0x1f890, 0x1f8ad, 0x1f900, 0x1f90b, - 0x1f910, 0x1f93e, - 0x1f940, 0x1f94c, - 0x1f950, 0x1f96b, - 0x1f980, 0x1f997, - 0x1f9c0, 0x1f9c0, - 0x1f9d0, 0x1f9e6, + 0x1f90d, 0x1f971, + 0x1f973, 0x1f976, + 0x1f97a, 0x1f9a2, + 0x1f9a5, 0x1f9aa, + 0x1f9ae, 0x1f9ca, + 0x1f9cd, 0x1fa53, + 0x1fa60, 0x1fa6d, + 0x1fa70, 0x1fa73, + 0x1fa78, 0x1fa7a, + 0x1fa80, 0x1fa82, + 0x1fa90, 0x1fa95, 0x1fffe, 0x2a6d6, 0x2a700, 0x2b734, 0x2b740, 0x2b81d, @@ -33474,11 +35963,11 @@ static const OnigCodePoint CR_Age_10_0[] = { 0xe0020, 0xe007f, 0xe0100, 0xe01ef, 0xefffe, 0x10ffff, -}; /* CR_Age_10_0 */ +}; /* CR_Age_12_0 */ -/* 'Age_11_0': Derived Age 11.0 */ -static const OnigCodePoint CR_Age_11_0[] = { - 668, +/* 'Age_12_1': Derived Age 12.1 */ +static const OnigCodePoint CR_Age_12_1[] = { + 676, 0x0000, 0x0377, 0x037a, 0x037f, 0x0384, 0x038a, @@ -33588,7 +36077,7 @@ static const OnigCodePoint CR_Age_11_0[] = { 0x0c58, 0x0c5a, 0x0c60, 0x0c63, 0x0c66, 0x0c6f, - 0x0c78, 0x0c8c, + 0x0c77, 0x0c8c, 0x0c8e, 0x0c90, 0x0c92, 0x0ca8, 0x0caa, 0x0cb3, @@ -33625,17 +36114,10 @@ static const OnigCodePoint CR_Age_11_0[] = { 0x0e3f, 0x0e5b, 0x0e81, 0x0e82, 0x0e84, 0x0e84, - 0x0e87, 0x0e88, - 0x0e8a, 0x0e8a, - 0x0e8d, 0x0e8d, - 0x0e94, 0x0e97, - 0x0e99, 0x0e9f, - 0x0ea1, 0x0ea3, + 0x0e86, 0x0e8a, + 0x0e8c, 0x0ea3, 0x0ea5, 0x0ea5, - 0x0ea7, 0x0ea7, - 0x0eaa, 0x0eab, - 0x0ead, 0x0eb9, - 0x0ebb, 0x0ebd, + 0x0ea7, 0x0ebd, 0x0ec0, 0x0ec4, 0x0ec6, 0x0ec6, 0x0ec8, 0x0ecd, @@ -33711,7 +36193,7 @@ static const OnigCodePoint CR_Age_11_0[] = { 0x1c4d, 0x1c88, 0x1c90, 0x1cba, 0x1cbd, 0x1cc7, - 0x1cd0, 0x1cf9, + 0x1cd0, 0x1cfa, 0x1d00, 0x1df9, 0x1dfb, 0x1f15, 0x1f18, 0x1f1d, @@ -33740,9 +36222,7 @@ static const OnigCodePoint CR_Age_11_0[] = { 0x2440, 0x244a, 0x2460, 0x2b73, 0x2b76, 0x2b95, - 0x2b98, 0x2bc8, - 0x2bca, 0x2bfe, - 0x2c00, 0x2c2e, + 0x2b98, 0x2c2e, 0x2c30, 0x2c5e, 0x2c60, 0x2cf3, 0x2cf9, 0x2d25, @@ -33759,7 +36239,7 @@ static const OnigCodePoint CR_Age_11_0[] = { 0x2dc8, 0x2dce, 0x2dd0, 0x2dd6, 0x2dd8, 0x2dde, - 0x2de0, 0x2e4e, + 0x2de0, 0x2e4f, 0x2e80, 0x2e99, 0x2e9b, 0x2ef3, 0x2f00, 0x2fd5, @@ -33772,14 +36252,14 @@ static const OnigCodePoint CR_Age_11_0[] = { 0x3190, 0x31ba, 0x31c0, 0x31e3, 0x31f0, 0x321e, - 0x3220, 0x32fe, - 0x3300, 0x4db5, + 0x3220, 0x4db5, 0x4dc0, 0x9fef, 0xa000, 0xa48c, 0xa490, 0xa4c6, 0xa4d0, 0xa62b, 0xa640, 0xa6f7, - 0xa700, 0xa7b9, + 0xa700, 0xa7bf, + 0xa7c2, 0xa7c6, 0xa7f7, 0xa82b, 0xa830, 0xa839, 0xa840, 0xa877, @@ -33800,7 +36280,7 @@ static const OnigCodePoint CR_Age_11_0[] = { 0xab11, 0xab16, 0xab20, 0xab26, 0xab28, 0xab2e, - 0xab30, 0xab65, + 0xab30, 0xab67, 0xab70, 0xabed, 0xabf0, 0xabf9, 0xac00, 0xd7a3, @@ -33906,6 +36386,7 @@ static const OnigCodePoint CR_Age_11_0[] = { 0x10e60, 0x10e7e, 0x10f00, 0x10f27, 0x10f30, 0x10f59, + 0x10fe0, 0x10ff6, 0x11000, 0x1104d, 0x11052, 0x1106f, 0x1107f, 0x110c1, @@ -33944,7 +36425,7 @@ static const OnigCodePoint CR_Age_11_0[] = { 0x11370, 0x11374, 0x11400, 0x11459, 0x1145b, 0x1145b, - 0x1145d, 0x1145e, + 0x1145d, 0x1145f, 0x11480, 0x114c7, 0x114d0, 0x114d9, 0x11580, 0x115b5, @@ -33952,7 +36433,7 @@ static const OnigCodePoint CR_Age_11_0[] = { 0x11600, 0x11644, 0x11650, 0x11659, 0x11660, 0x1166c, - 0x11680, 0x116b7, + 0x11680, 0x116b8, 0x116c0, 0x116c9, 0x11700, 0x1171a, 0x1171d, 0x1172b, @@ -33960,9 +36441,11 @@ static const OnigCodePoint CR_Age_11_0[] = { 0x11800, 0x1183b, 0x118a0, 0x118f2, 0x118ff, 0x118ff, + 0x119a0, 0x119a7, + 0x119aa, 0x119d7, + 0x119da, 0x119e4, 0x11a00, 0x11a47, - 0x11a50, 0x11a83, - 0x11a86, 0x11aa2, + 0x11a50, 0x11aa2, 0x11ac0, 0x11af8, 0x11c00, 0x11c08, 0x11c0a, 0x11c36, @@ -33985,11 +36468,13 @@ static const OnigCodePoint CR_Age_11_0[] = { 0x11d93, 0x11d98, 0x11da0, 0x11da9, 0x11ee0, 0x11ef8, - 0x12000, 0x12399, + 0x11fc0, 0x11ff1, + 0x11fff, 0x12399, 0x12400, 0x1246e, 0x12470, 0x12474, 0x12480, 0x12543, 0x13000, 0x1342e, + 0x13430, 0x13438, 0x14400, 0x14646, 0x16800, 0x16a38, 0x16a40, 0x16a5e, @@ -34003,13 +36488,15 @@ static const OnigCodePoint CR_Age_11_0[] = { 0x16b63, 0x16b77, 0x16b7d, 0x16b8f, 0x16e40, 0x16e9a, - 0x16f00, 0x16f44, - 0x16f50, 0x16f7e, + 0x16f00, 0x16f4a, + 0x16f4f, 0x16f87, 0x16f8f, 0x16f9f, - 0x16fe0, 0x16fe1, - 0x17000, 0x187f1, + 0x16fe0, 0x16fe3, + 0x17000, 0x187f7, 0x18800, 0x18af2, 0x1b000, 0x1b11e, + 0x1b150, 0x1b152, + 0x1b164, 0x1b167, 0x1b170, 0x1b2fb, 0x1bc00, 0x1bc6a, 0x1bc70, 0x1bc7c, @@ -34051,12 +36538,19 @@ static const OnigCodePoint CR_Age_11_0[] = { 0x1e01b, 0x1e021, 0x1e023, 0x1e024, 0x1e026, 0x1e02a, + 0x1e100, 0x1e12c, + 0x1e130, 0x1e13d, + 0x1e140, 0x1e149, + 0x1e14e, 0x1e14f, + 0x1e2c0, 0x1e2f9, + 0x1e2ff, 0x1e2ff, 0x1e800, 0x1e8c4, 0x1e8c7, 0x1e8d6, - 0x1e900, 0x1e94a, + 0x1e900, 0x1e94b, 0x1e950, 0x1e959, 0x1e95e, 0x1e95f, 0x1ec71, 0x1ecb4, + 0x1ed01, 0x1ed3d, 0x1ee00, 0x1ee03, 0x1ee05, 0x1ee1f, 0x1ee21, 0x1ee22, @@ -34098,33 +36592,36 @@ static const OnigCodePoint CR_Age_11_0[] = { 0x1f0c1, 0x1f0cf, 0x1f0d1, 0x1f0f5, 0x1f100, 0x1f10c, - 0x1f110, 0x1f16b, + 0x1f110, 0x1f16c, 0x1f170, 0x1f1ac, 0x1f1e6, 0x1f202, 0x1f210, 0x1f23b, 0x1f240, 0x1f248, 0x1f250, 0x1f251, 0x1f260, 0x1f265, - 0x1f300, 0x1f6d4, + 0x1f300, 0x1f6d5, 0x1f6e0, 0x1f6ec, - 0x1f6f0, 0x1f6f9, + 0x1f6f0, 0x1f6fa, 0x1f700, 0x1f773, 0x1f780, 0x1f7d8, + 0x1f7e0, 0x1f7eb, 0x1f800, 0x1f80b, 0x1f810, 0x1f847, 0x1f850, 0x1f859, 0x1f860, 0x1f887, 0x1f890, 0x1f8ad, 0x1f900, 0x1f90b, - 0x1f910, 0x1f93e, - 0x1f940, 0x1f970, + 0x1f90d, 0x1f971, 0x1f973, 0x1f976, - 0x1f97a, 0x1f97a, - 0x1f97c, 0x1f9a2, - 0x1f9b0, 0x1f9b9, - 0x1f9c0, 0x1f9c2, - 0x1f9d0, 0x1f9ff, + 0x1f97a, 0x1f9a2, + 0x1f9a5, 0x1f9aa, + 0x1f9ae, 0x1f9ca, + 0x1f9cd, 0x1fa53, 0x1fa60, 0x1fa6d, + 0x1fa70, 0x1fa73, + 0x1fa78, 0x1fa7a, + 0x1fa80, 0x1fa82, + 0x1fa90, 0x1fa95, 0x1fffe, 0x2a6d6, 0x2a700, 0x2b734, 0x2b740, 0x2b81d, @@ -34147,11 +36644,11 @@ static const OnigCodePoint CR_Age_11_0[] = { 0xe0020, 0xe007f, 0xe0100, 0xe01ef, 0xefffe, 0x10ffff, -}; /* CR_Age_11_0 */ +}; /* CR_Age_12_1 */ -/* 'Age_12_0': Derived Age 12.0 */ -static const OnigCodePoint CR_Age_12_0[] = { - 677, +/* 'Age_13_0': Derived Age 13.0 */ +static const OnigCodePoint CR_Age_13_0[] = { + 686, 0x0000, 0x0377, 0x037a, 0x037f, 0x0384, 0x038a, @@ -34175,7 +36672,7 @@ static const OnigCodePoint CR_Age_12_0[] = { 0x085e, 0x085e, 0x0860, 0x086a, 0x08a0, 0x08b4, - 0x08b6, 0x08bd, + 0x08b6, 0x08c7, 0x08d3, 0x0983, 0x0985, 0x098c, 0x098f, 0x0990, @@ -34230,7 +36727,7 @@ static const OnigCodePoint CR_Age_12_0[] = { 0x0b3c, 0x0b44, 0x0b47, 0x0b48, 0x0b4b, 0x0b4d, - 0x0b56, 0x0b57, + 0x0b55, 0x0b57, 0x0b5c, 0x0b5d, 0x0b5f, 0x0b63, 0x0b66, 0x0b77, @@ -34274,15 +36771,14 @@ static const OnigCodePoint CR_Age_12_0[] = { 0x0ce0, 0x0ce3, 0x0ce6, 0x0cef, 0x0cf1, 0x0cf2, - 0x0d00, 0x0d03, - 0x0d05, 0x0d0c, + 0x0d00, 0x0d0c, 0x0d0e, 0x0d10, 0x0d12, 0x0d44, 0x0d46, 0x0d48, 0x0d4a, 0x0d4f, 0x0d54, 0x0d63, 0x0d66, 0x0d7f, - 0x0d82, 0x0d83, + 0x0d81, 0x0d83, 0x0d85, 0x0d96, 0x0d9a, 0x0db1, 0x0db3, 0x0dbb, @@ -34368,7 +36864,7 @@ static const OnigCodePoint CR_Age_12_0[] = { 0x1a7f, 0x1a89, 0x1a90, 0x1a99, 0x1aa0, 0x1aad, - 0x1ab0, 0x1abe, + 0x1ab0, 0x1ac0, 0x1b00, 0x1b4b, 0x1b50, 0x1b7c, 0x1b80, 0x1bf3, @@ -34406,7 +36902,7 @@ static const OnigCodePoint CR_Age_12_0[] = { 0x2440, 0x244a, 0x2460, 0x2b73, 0x2b76, 0x2b95, - 0x2b98, 0x2c2e, + 0x2b97, 0x2c2e, 0x2c30, 0x2c5e, 0x2c60, 0x2cf3, 0x2cf9, 0x2d25, @@ -34423,7 +36919,7 @@ static const OnigCodePoint CR_Age_12_0[] = { 0x2dc8, 0x2dce, 0x2dd0, 0x2dd6, 0x2dd8, 0x2dde, - 0x2de0, 0x2e4f, + 0x2de0, 0x2e52, 0x2e80, 0x2e99, 0x2e9b, 0x2ef3, 0x2f00, 0x2fd5, @@ -34433,19 +36929,16 @@ static const OnigCodePoint CR_Age_12_0[] = { 0x3099, 0x30ff, 0x3105, 0x312f, 0x3131, 0x318e, - 0x3190, 0x31ba, - 0x31c0, 0x31e3, + 0x3190, 0x31e3, 0x31f0, 0x321e, - 0x3220, 0x32fe, - 0x3300, 0x4db5, - 0x4dc0, 0x9fef, + 0x3220, 0x9ffc, 0xa000, 0xa48c, 0xa490, 0xa4c6, 0xa4d0, 0xa62b, 0xa640, 0xa6f7, 0xa700, 0xa7bf, - 0xa7c2, 0xa7c6, - 0xa7f7, 0xa82b, + 0xa7c2, 0xa7ca, + 0xa7f5, 0xa82c, 0xa830, 0xa839, 0xa840, 0xa877, 0xa880, 0xa8c5, @@ -34465,7 +36958,7 @@ static const OnigCodePoint CR_Age_12_0[] = { 0xab11, 0xab16, 0xab20, 0xab26, 0xab28, 0xab2e, - 0xab30, 0xab67, + 0xab30, 0xab6b, 0xab70, 0xabed, 0xabf0, 0xabf9, 0xac00, 0xd7a3, @@ -34509,7 +37002,7 @@ static const OnigCodePoint CR_Age_12_0[] = { 0x10100, 0x10102, 0x10107, 0x10133, 0x10137, 0x1018e, - 0x10190, 0x1019b, + 0x10190, 0x1019c, 0x101a0, 0x101a0, 0x101d0, 0x101fd, 0x10280, 0x1029c, @@ -34569,8 +37062,12 @@ static const OnigCodePoint CR_Age_12_0[] = { 0x10cfa, 0x10d27, 0x10d30, 0x10d39, 0x10e60, 0x10e7e, + 0x10e80, 0x10ea9, + 0x10eab, 0x10ead, + 0x10eb0, 0x10eb1, 0x10f00, 0x10f27, 0x10f30, 0x10f59, + 0x10fb0, 0x10fcb, 0x10fe0, 0x10ff6, 0x11000, 0x1104d, 0x11052, 0x1106f, @@ -34579,10 +37076,9 @@ static const OnigCodePoint CR_Age_12_0[] = { 0x110d0, 0x110e8, 0x110f0, 0x110f9, 0x11100, 0x11134, - 0x11136, 0x11146, + 0x11136, 0x11147, 0x11150, 0x11176, - 0x11180, 0x111cd, - 0x111d0, 0x111df, + 0x11180, 0x111df, 0x111e1, 0x111f4, 0x11200, 0x11211, 0x11213, 0x1123e, @@ -34608,9 +37104,8 @@ static const OnigCodePoint CR_Age_12_0[] = { 0x1135d, 0x11363, 0x11366, 0x1136c, 0x11370, 0x11374, - 0x11400, 0x11459, - 0x1145b, 0x1145b, - 0x1145d, 0x1145f, + 0x11400, 0x1145b, + 0x1145d, 0x11461, 0x11480, 0x114c7, 0x114d0, 0x114d9, 0x11580, 0x115b5, @@ -34625,7 +37120,14 @@ static const OnigCodePoint CR_Age_12_0[] = { 0x11730, 0x1173f, 0x11800, 0x1183b, 0x118a0, 0x118f2, - 0x118ff, 0x118ff, + 0x118ff, 0x11906, + 0x11909, 0x11909, + 0x1190c, 0x11913, + 0x11915, 0x11916, + 0x11918, 0x11935, + 0x11937, 0x11938, + 0x1193b, 0x11946, + 0x11950, 0x11959, 0x119a0, 0x119a7, 0x119aa, 0x119d7, 0x119da, 0x119e4, @@ -34653,6 +37155,7 @@ static const OnigCodePoint CR_Age_12_0[] = { 0x11d93, 0x11d98, 0x11da0, 0x11da9, 0x11ee0, 0x11ef8, + 0x11fb0, 0x11fb0, 0x11fc0, 0x11ff1, 0x11fff, 0x12399, 0x12400, 0x1246e, @@ -34676,9 +37179,11 @@ static const OnigCodePoint CR_Age_12_0[] = { 0x16f00, 0x16f4a, 0x16f4f, 0x16f87, 0x16f8f, 0x16f9f, - 0x16fe0, 0x16fe3, + 0x16fe0, 0x16fe4, + 0x16ff0, 0x16ff1, 0x17000, 0x187f7, - 0x18800, 0x18af2, + 0x18800, 0x18cd5, + 0x18d00, 0x18d08, 0x1b000, 0x1b11e, 0x1b150, 0x1b152, 0x1b164, 0x1b167, @@ -34776,17 +37281,15 @@ static const OnigCodePoint CR_Age_12_0[] = { 0x1f0b1, 0x1f0bf, 0x1f0c1, 0x1f0cf, 0x1f0d1, 0x1f0f5, - 0x1f100, 0x1f10c, - 0x1f110, 0x1f16c, - 0x1f170, 0x1f1ac, + 0x1f100, 0x1f1ad, 0x1f1e6, 0x1f202, 0x1f210, 0x1f23b, 0x1f240, 0x1f248, 0x1f250, 0x1f251, 0x1f260, 0x1f265, - 0x1f300, 0x1f6d5, + 0x1f300, 0x1f6d7, 0x1f6e0, 0x1f6ec, - 0x1f6f0, 0x1f6fa, + 0x1f6f0, 0x1f6fc, 0x1f700, 0x1f773, 0x1f780, 0x1f7d8, 0x1f7e0, 0x1f7eb, @@ -34795,25 +37298,28 @@ static const OnigCodePoint CR_Age_12_0[] = { 0x1f850, 0x1f859, 0x1f860, 0x1f887, 0x1f890, 0x1f8ad, - 0x1f900, 0x1f90b, - 0x1f90d, 0x1f971, - 0x1f973, 0x1f976, - 0x1f97a, 0x1f9a2, - 0x1f9a5, 0x1f9aa, - 0x1f9ae, 0x1f9ca, + 0x1f8b0, 0x1f8b1, + 0x1f900, 0x1f978, + 0x1f97a, 0x1f9cb, 0x1f9cd, 0x1fa53, 0x1fa60, 0x1fa6d, - 0x1fa70, 0x1fa73, + 0x1fa70, 0x1fa74, 0x1fa78, 0x1fa7a, - 0x1fa80, 0x1fa82, - 0x1fa90, 0x1fa95, - 0x1fffe, 0x2a6d6, + 0x1fa80, 0x1fa86, + 0x1fa90, 0x1faa8, + 0x1fab0, 0x1fab6, + 0x1fac0, 0x1fac2, + 0x1fad0, 0x1fad6, + 0x1fb00, 0x1fb92, + 0x1fb94, 0x1fbca, + 0x1fbf0, 0x1fbf9, + 0x1fffe, 0x2a6dd, 0x2a700, 0x2b734, 0x2b740, 0x2b81d, 0x2b820, 0x2cea1, 0x2ceb0, 0x2ebe0, 0x2f800, 0x2fa1d, - 0x2fffe, 0x2ffff, + 0x2fffe, 0x3134a, 0x3fffe, 0x3ffff, 0x4fffe, 0x4ffff, 0x5fffe, 0x5ffff, @@ -34829,11 +37335,11 @@ static const OnigCodePoint CR_Age_12_0[] = { 0xe0020, 0xe007f, 0xe0100, 0xe01ef, 0xefffe, 0x10ffff, -}; /* CR_Age_12_0 */ +}; /* CR_Age_13_0 */ -/* 'Age_12_1': Derived Age 12.1 */ -static const OnigCodePoint CR_Age_12_1[] = { - 676, +/* 'Age_14_0': Derived Age 14.0 */ +static const OnigCodePoint CR_Age_14_0[] = { + 706, 0x0000, 0x0377, 0x037a, 0x037f, 0x0384, 0x038a, @@ -34846,8 +37352,7 @@ static const OnigCodePoint CR_Age_12_1[] = { 0x0591, 0x05c7, 0x05d0, 0x05ea, 0x05ef, 0x05f4, - 0x0600, 0x061c, - 0x061e, 0x070d, + 0x0600, 0x070d, 0x070f, 0x074a, 0x074d, 0x07b1, 0x07c0, 0x07fa, @@ -34856,9 +37361,9 @@ static const OnigCodePoint CR_Age_12_1[] = { 0x0840, 0x085b, 0x085e, 0x085e, 0x0860, 0x086a, - 0x08a0, 0x08b4, - 0x08b6, 0x08bd, - 0x08d3, 0x0983, + 0x0870, 0x088e, + 0x0890, 0x0891, + 0x0898, 0x0983, 0x0985, 0x098c, 0x098f, 0x0990, 0x0993, 0x09a8, @@ -34912,7 +37417,7 @@ static const OnigCodePoint CR_Age_12_1[] = { 0x0b3c, 0x0b44, 0x0b47, 0x0b48, 0x0b4b, 0x0b4d, - 0x0b56, 0x0b57, + 0x0b55, 0x0b57, 0x0b5c, 0x0b5d, 0x0b5f, 0x0b63, 0x0b66, 0x0b77, @@ -34936,11 +37441,12 @@ static const OnigCodePoint CR_Age_12_1[] = { 0x0c0e, 0x0c10, 0x0c12, 0x0c28, 0x0c2a, 0x0c39, - 0x0c3d, 0x0c44, + 0x0c3c, 0x0c44, 0x0c46, 0x0c48, 0x0c4a, 0x0c4d, 0x0c55, 0x0c56, 0x0c58, 0x0c5a, + 0x0c5d, 0x0c5d, 0x0c60, 0x0c63, 0x0c66, 0x0c6f, 0x0c77, 0x0c8c, @@ -34952,19 +37458,18 @@ static const OnigCodePoint CR_Age_12_1[] = { 0x0cc6, 0x0cc8, 0x0cca, 0x0ccd, 0x0cd5, 0x0cd6, - 0x0cde, 0x0cde, + 0x0cdd, 0x0cde, 0x0ce0, 0x0ce3, 0x0ce6, 0x0cef, 0x0cf1, 0x0cf2, - 0x0d00, 0x0d03, - 0x0d05, 0x0d0c, + 0x0d00, 0x0d0c, 0x0d0e, 0x0d10, 0x0d12, 0x0d44, 0x0d46, 0x0d48, 0x0d4a, 0x0d4f, 0x0d54, 0x0d63, 0x0d66, 0x0d7f, - 0x0d82, 0x0d83, + 0x0d81, 0x0d83, 0x0d85, 0x0d96, 0x0d9a, 0x0db1, 0x0db3, 0x0dbb, @@ -35020,9 +37525,8 @@ static const OnigCodePoint CR_Age_12_1[] = { 0x13f8, 0x13fd, 0x1400, 0x169c, 0x16a0, 0x16f8, - 0x1700, 0x170c, - 0x170e, 0x1714, - 0x1720, 0x1736, + 0x1700, 0x1715, + 0x171f, 0x1736, 0x1740, 0x1753, 0x1760, 0x176c, 0x176e, 0x1770, @@ -35030,8 +37534,7 @@ static const OnigCodePoint CR_Age_12_1[] = { 0x1780, 0x17dd, 0x17e0, 0x17e9, 0x17f0, 0x17f9, - 0x1800, 0x180e, - 0x1810, 0x1819, + 0x1800, 0x1819, 0x1820, 0x1878, 0x1880, 0x18aa, 0x18b0, 0x18f5, @@ -35050,9 +37553,9 @@ static const OnigCodePoint CR_Age_12_1[] = { 0x1a7f, 0x1a89, 0x1a90, 0x1a99, 0x1aa0, 0x1aad, - 0x1ab0, 0x1abe, - 0x1b00, 0x1b4b, - 0x1b50, 0x1b7c, + 0x1ab0, 0x1ace, + 0x1b00, 0x1b4c, + 0x1b50, 0x1b7e, 0x1b80, 0x1bf3, 0x1bfc, 0x1c37, 0x1c3b, 0x1c49, @@ -35060,8 +37563,7 @@ static const OnigCodePoint CR_Age_12_1[] = { 0x1c90, 0x1cba, 0x1cbd, 0x1cc7, 0x1cd0, 0x1cfa, - 0x1d00, 0x1df9, - 0x1dfb, 0x1f15, + 0x1d00, 0x1f15, 0x1f18, 0x1f1d, 0x1f20, 0x1f45, 0x1f48, 0x1f4d, @@ -35081,16 +37583,14 @@ static const OnigCodePoint CR_Age_12_1[] = { 0x2066, 0x2071, 0x2074, 0x208e, 0x2090, 0x209c, - 0x20a0, 0x20bf, + 0x20a0, 0x20c0, 0x20d0, 0x20f0, 0x2100, 0x218b, 0x2190, 0x2426, 0x2440, 0x244a, 0x2460, 0x2b73, 0x2b76, 0x2b95, - 0x2b98, 0x2c2e, - 0x2c30, 0x2c5e, - 0x2c60, 0x2cf3, + 0x2b97, 0x2cf3, 0x2cf9, 0x2d25, 0x2d27, 0x2d27, 0x2d2d, 0x2d2d, @@ -35105,7 +37605,7 @@ static const OnigCodePoint CR_Age_12_1[] = { 0x2dc8, 0x2dce, 0x2dd0, 0x2dd6, 0x2dd8, 0x2dde, - 0x2de0, 0x2e4f, + 0x2de0, 0x2e5d, 0x2e80, 0x2e99, 0x2e9b, 0x2ef3, 0x2f00, 0x2fd5, @@ -35115,18 +37615,17 @@ static const OnigCodePoint CR_Age_12_1[] = { 0x3099, 0x30ff, 0x3105, 0x312f, 0x3131, 0x318e, - 0x3190, 0x31ba, - 0x31c0, 0x31e3, + 0x3190, 0x31e3, 0x31f0, 0x321e, - 0x3220, 0x4db5, - 0x4dc0, 0x9fef, - 0xa000, 0xa48c, + 0x3220, 0xa48c, 0xa490, 0xa4c6, 0xa4d0, 0xa62b, 0xa640, 0xa6f7, - 0xa700, 0xa7bf, - 0xa7c2, 0xa7c6, - 0xa7f7, 0xa82b, + 0xa700, 0xa7ca, + 0xa7d0, 0xa7d1, + 0xa7d3, 0xa7d3, + 0xa7d5, 0xa7d9, + 0xa7f2, 0xa82c, 0xa830, 0xa839, 0xa840, 0xa877, 0xa880, 0xa8c5, @@ -35146,7 +37645,7 @@ static const OnigCodePoint CR_Age_12_1[] = { 0xab11, 0xab16, 0xab20, 0xab26, 0xab28, 0xab2e, - 0xab30, 0xab67, + 0xab30, 0xab6b, 0xab70, 0xabed, 0xabf0, 0xabf9, 0xac00, 0xd7a3, @@ -35161,12 +37660,10 @@ static const OnigCodePoint CR_Age_12_1[] = { 0xfb3e, 0xfb3e, 0xfb40, 0xfb41, 0xfb43, 0xfb44, - 0xfb46, 0xfbc1, - 0xfbd3, 0xfd3f, - 0xfd50, 0xfd8f, + 0xfb46, 0xfbc2, + 0xfbd3, 0xfd8f, 0xfd92, 0xfdc7, - 0xfdd0, 0xfdfd, - 0xfe00, 0xfe19, + 0xfdcf, 0xfe19, 0xfe20, 0xfe52, 0xfe54, 0xfe66, 0xfe68, 0xfe6b, @@ -35190,7 +37687,7 @@ static const OnigCodePoint CR_Age_12_1[] = { 0x10100, 0x10102, 0x10107, 0x10133, 0x10137, 0x1018e, - 0x10190, 0x1019b, + 0x10190, 0x1019c, 0x101a0, 0x101a0, 0x101d0, 0x101fd, 0x10280, 0x1029c, @@ -35208,10 +37705,20 @@ static const OnigCodePoint CR_Age_12_1[] = { 0x104d8, 0x104fb, 0x10500, 0x10527, 0x10530, 0x10563, - 0x1056f, 0x1056f, + 0x1056f, 0x1057a, + 0x1057c, 0x1058a, + 0x1058c, 0x10592, + 0x10594, 0x10595, + 0x10597, 0x105a1, + 0x105a3, 0x105b1, + 0x105b3, 0x105b9, + 0x105bb, 0x105bc, 0x10600, 0x10736, 0x10740, 0x10755, 0x10760, 0x10767, + 0x10780, 0x10785, + 0x10787, 0x107b0, + 0x107b2, 0x107ba, 0x10800, 0x10805, 0x10808, 0x10808, 0x1080a, 0x10835, @@ -35250,20 +37757,24 @@ static const OnigCodePoint CR_Age_12_1[] = { 0x10cfa, 0x10d27, 0x10d30, 0x10d39, 0x10e60, 0x10e7e, + 0x10e80, 0x10ea9, + 0x10eab, 0x10ead, + 0x10eb0, 0x10eb1, 0x10f00, 0x10f27, 0x10f30, 0x10f59, + 0x10f70, 0x10f89, + 0x10fb0, 0x10fcb, 0x10fe0, 0x10ff6, 0x11000, 0x1104d, - 0x11052, 0x1106f, - 0x1107f, 0x110c1, + 0x11052, 0x11075, + 0x1107f, 0x110c2, 0x110cd, 0x110cd, 0x110d0, 0x110e8, 0x110f0, 0x110f9, 0x11100, 0x11134, - 0x11136, 0x11146, + 0x11136, 0x11147, 0x11150, 0x11176, - 0x11180, 0x111cd, - 0x111d0, 0x111df, + 0x11180, 0x111df, 0x111e1, 0x111f4, 0x11200, 0x11211, 0x11213, 0x1123e, @@ -35289,9 +37800,8 @@ static const OnigCodePoint CR_Age_12_1[] = { 0x1135d, 0x11363, 0x11366, 0x1136c, 0x11370, 0x11374, - 0x11400, 0x11459, - 0x1145b, 0x1145b, - 0x1145d, 0x1145f, + 0x11400, 0x1145b, + 0x1145d, 0x11461, 0x11480, 0x114c7, 0x114d0, 0x114d9, 0x11580, 0x115b5, @@ -35299,20 +37809,27 @@ static const OnigCodePoint CR_Age_12_1[] = { 0x11600, 0x11644, 0x11650, 0x11659, 0x11660, 0x1166c, - 0x11680, 0x116b8, + 0x11680, 0x116b9, 0x116c0, 0x116c9, 0x11700, 0x1171a, 0x1171d, 0x1172b, - 0x11730, 0x1173f, + 0x11730, 0x11746, 0x11800, 0x1183b, 0x118a0, 0x118f2, - 0x118ff, 0x118ff, + 0x118ff, 0x11906, + 0x11909, 0x11909, + 0x1190c, 0x11913, + 0x11915, 0x11916, + 0x11918, 0x11935, + 0x11937, 0x11938, + 0x1193b, 0x11946, + 0x11950, 0x11959, 0x119a0, 0x119a7, 0x119aa, 0x119d7, 0x119da, 0x119e4, 0x11a00, 0x11a47, 0x11a50, 0x11aa2, - 0x11ac0, 0x11af8, + 0x11ab0, 0x11af8, 0x11c00, 0x11c08, 0x11c0a, 0x11c36, 0x11c38, 0x11c45, @@ -35334,18 +37851,21 @@ static const OnigCodePoint CR_Age_12_1[] = { 0x11d93, 0x11d98, 0x11da0, 0x11da9, 0x11ee0, 0x11ef8, + 0x11fb0, 0x11fb0, 0x11fc0, 0x11ff1, 0x11fff, 0x12399, 0x12400, 0x1246e, 0x12470, 0x12474, 0x12480, 0x12543, + 0x12f90, 0x12ff2, 0x13000, 0x1342e, 0x13430, 0x13438, 0x14400, 0x14646, 0x16800, 0x16a38, 0x16a40, 0x16a5e, 0x16a60, 0x16a69, - 0x16a6e, 0x16a6f, + 0x16a6e, 0x16abe, + 0x16ac0, 0x16ac9, 0x16ad0, 0x16aed, 0x16af0, 0x16af5, 0x16b00, 0x16b45, @@ -35357,10 +37877,15 @@ static const OnigCodePoint CR_Age_12_1[] = { 0x16f00, 0x16f4a, 0x16f4f, 0x16f87, 0x16f8f, 0x16f9f, - 0x16fe0, 0x16fe3, + 0x16fe0, 0x16fe4, + 0x16ff0, 0x16ff1, 0x17000, 0x187f7, - 0x18800, 0x18af2, - 0x1b000, 0x1b11e, + 0x18800, 0x18cd5, + 0x18d00, 0x18d08, + 0x1aff0, 0x1aff3, + 0x1aff5, 0x1affb, + 0x1affd, 0x1affe, + 0x1b000, 0x1b122, 0x1b150, 0x1b152, 0x1b164, 0x1b167, 0x1b170, 0x1b2fb, @@ -35369,9 +37894,12 @@ static const OnigCodePoint CR_Age_12_1[] = { 0x1bc80, 0x1bc88, 0x1bc90, 0x1bc99, 0x1bc9c, 0x1bca3, + 0x1cf00, 0x1cf2d, + 0x1cf30, 0x1cf46, + 0x1cf50, 0x1cfc3, 0x1d000, 0x1d0f5, 0x1d100, 0x1d126, - 0x1d129, 0x1d1e8, + 0x1d129, 0x1d1ea, 0x1d200, 0x1d245, 0x1d2e0, 0x1d2f3, 0x1d300, 0x1d356, @@ -35399,6 +37927,7 @@ static const OnigCodePoint CR_Age_12_1[] = { 0x1d7ce, 0x1da8b, 0x1da9b, 0x1da9f, 0x1daa1, 0x1daaf, + 0x1df00, 0x1df1e, 0x1e000, 0x1e006, 0x1e008, 0x1e018, 0x1e01b, 0x1e021, @@ -35408,8 +37937,13 @@ static const OnigCodePoint CR_Age_12_1[] = { 0x1e130, 0x1e13d, 0x1e140, 0x1e149, 0x1e14e, 0x1e14f, + 0x1e290, 0x1e2ae, 0x1e2c0, 0x1e2f9, 0x1e2ff, 0x1e2ff, + 0x1e7e0, 0x1e7e6, + 0x1e7e8, 0x1e7eb, + 0x1e7ed, 0x1e7ee, + 0x1e7f0, 0x1e7fe, 0x1e800, 0x1e8c4, 0x1e8c7, 0x1e8d6, 0x1e900, 0x1e94b, @@ -35457,44 +37991,46 @@ static const OnigCodePoint CR_Age_12_1[] = { 0x1f0b1, 0x1f0bf, 0x1f0c1, 0x1f0cf, 0x1f0d1, 0x1f0f5, - 0x1f100, 0x1f10c, - 0x1f110, 0x1f16c, - 0x1f170, 0x1f1ac, + 0x1f100, 0x1f1ad, 0x1f1e6, 0x1f202, 0x1f210, 0x1f23b, 0x1f240, 0x1f248, 0x1f250, 0x1f251, 0x1f260, 0x1f265, - 0x1f300, 0x1f6d5, - 0x1f6e0, 0x1f6ec, - 0x1f6f0, 0x1f6fa, + 0x1f300, 0x1f6d7, + 0x1f6dd, 0x1f6ec, + 0x1f6f0, 0x1f6fc, 0x1f700, 0x1f773, 0x1f780, 0x1f7d8, 0x1f7e0, 0x1f7eb, + 0x1f7f0, 0x1f7f0, 0x1f800, 0x1f80b, 0x1f810, 0x1f847, 0x1f850, 0x1f859, 0x1f860, 0x1f887, 0x1f890, 0x1f8ad, - 0x1f900, 0x1f90b, - 0x1f90d, 0x1f971, - 0x1f973, 0x1f976, - 0x1f97a, 0x1f9a2, - 0x1f9a5, 0x1f9aa, - 0x1f9ae, 0x1f9ca, - 0x1f9cd, 0x1fa53, + 0x1f8b0, 0x1f8b1, + 0x1f900, 0x1fa53, 0x1fa60, 0x1fa6d, - 0x1fa70, 0x1fa73, - 0x1fa78, 0x1fa7a, - 0x1fa80, 0x1fa82, - 0x1fa90, 0x1fa95, - 0x1fffe, 0x2a6d6, - 0x2a700, 0x2b734, + 0x1fa70, 0x1fa74, + 0x1fa78, 0x1fa7c, + 0x1fa80, 0x1fa86, + 0x1fa90, 0x1faac, + 0x1fab0, 0x1faba, + 0x1fac0, 0x1fac5, + 0x1fad0, 0x1fad9, + 0x1fae0, 0x1fae7, + 0x1faf0, 0x1faf6, + 0x1fb00, 0x1fb92, + 0x1fb94, 0x1fbca, + 0x1fbf0, 0x1fbf9, + 0x1fffe, 0x2a6df, + 0x2a700, 0x2b738, 0x2b740, 0x2b81d, 0x2b820, 0x2cea1, 0x2ceb0, 0x2ebe0, 0x2f800, 0x2fa1d, - 0x2fffe, 0x2ffff, + 0x2fffe, 0x3134a, 0x3fffe, 0x3ffff, 0x4fffe, 0x4ffff, 0x5fffe, 0x5ffff, @@ -35510,11 +38046,11 @@ static const OnigCodePoint CR_Age_12_1[] = { 0xe0020, 0xe007f, 0xe0100, 0xe01ef, 0xefffe, 0x10ffff, -}; /* CR_Age_12_1 */ +}; /* CR_Age_14_0 */ -/* 'Age_13_0': Derived Age 13.0 */ -static const OnigCodePoint CR_Age_13_0[] = { - 686, +/* 'Age_15_0': Derived Age 15.0 */ +static const OnigCodePoint CR_Age_15_0[] = { + 715, 0x0000, 0x0377, 0x037a, 0x037f, 0x0384, 0x038a, @@ -35527,8 +38063,7 @@ static const OnigCodePoint CR_Age_13_0[] = { 0x0591, 0x05c7, 0x05d0, 0x05ea, 0x05ef, 0x05f4, - 0x0600, 0x061c, - 0x061e, 0x070d, + 0x0600, 0x070d, 0x070f, 0x074a, 0x074d, 0x07b1, 0x07c0, 0x07fa, @@ -35537,9 +38072,9 @@ static const OnigCodePoint CR_Age_13_0[] = { 0x0840, 0x085b, 0x085e, 0x085e, 0x0860, 0x086a, - 0x08a0, 0x08b4, - 0x08b6, 0x08c7, - 0x08d3, 0x0983, + 0x0870, 0x088e, + 0x0890, 0x0891, + 0x0898, 0x0983, 0x0985, 0x098c, 0x098f, 0x0990, 0x0993, 0x09a8, @@ -35617,11 +38152,12 @@ static const OnigCodePoint CR_Age_13_0[] = { 0x0c0e, 0x0c10, 0x0c12, 0x0c28, 0x0c2a, 0x0c39, - 0x0c3d, 0x0c44, + 0x0c3c, 0x0c44, 0x0c46, 0x0c48, 0x0c4a, 0x0c4d, 0x0c55, 0x0c56, 0x0c58, 0x0c5a, + 0x0c5d, 0x0c5d, 0x0c60, 0x0c63, 0x0c66, 0x0c6f, 0x0c77, 0x0c8c, @@ -35633,10 +38169,10 @@ static const OnigCodePoint CR_Age_13_0[] = { 0x0cc6, 0x0cc8, 0x0cca, 0x0ccd, 0x0cd5, 0x0cd6, - 0x0cde, 0x0cde, + 0x0cdd, 0x0cde, 0x0ce0, 0x0ce3, 0x0ce6, 0x0cef, - 0x0cf1, 0x0cf2, + 0x0cf1, 0x0cf3, 0x0d00, 0x0d0c, 0x0d0e, 0x0d10, 0x0d12, 0x0d44, @@ -35666,7 +38202,7 @@ static const OnigCodePoint CR_Age_13_0[] = { 0x0ea7, 0x0ebd, 0x0ec0, 0x0ec4, 0x0ec6, 0x0ec6, - 0x0ec8, 0x0ecd, + 0x0ec8, 0x0ece, 0x0ed0, 0x0ed9, 0x0edc, 0x0edf, 0x0f00, 0x0f47, @@ -35700,9 +38236,8 @@ static const OnigCodePoint CR_Age_13_0[] = { 0x13f8, 0x13fd, 0x1400, 0x169c, 0x16a0, 0x16f8, - 0x1700, 0x170c, - 0x170e, 0x1714, - 0x1720, 0x1736, + 0x1700, 0x1715, + 0x171f, 0x1736, 0x1740, 0x1753, 0x1760, 0x176c, 0x176e, 0x1770, @@ -35710,8 +38245,7 @@ static const OnigCodePoint CR_Age_13_0[] = { 0x1780, 0x17dd, 0x17e0, 0x17e9, 0x17f0, 0x17f9, - 0x1800, 0x180e, - 0x1810, 0x1819, + 0x1800, 0x1819, 0x1820, 0x1878, 0x1880, 0x18aa, 0x18b0, 0x18f5, @@ -35730,9 +38264,9 @@ static const OnigCodePoint CR_Age_13_0[] = { 0x1a7f, 0x1a89, 0x1a90, 0x1a99, 0x1aa0, 0x1aad, - 0x1ab0, 0x1ac0, - 0x1b00, 0x1b4b, - 0x1b50, 0x1b7c, + 0x1ab0, 0x1ace, + 0x1b00, 0x1b4c, + 0x1b50, 0x1b7e, 0x1b80, 0x1bf3, 0x1bfc, 0x1c37, 0x1c3b, 0x1c49, @@ -35740,8 +38274,7 @@ static const OnigCodePoint CR_Age_13_0[] = { 0x1c90, 0x1cba, 0x1cbd, 0x1cc7, 0x1cd0, 0x1cfa, - 0x1d00, 0x1df9, - 0x1dfb, 0x1f15, + 0x1d00, 0x1f15, 0x1f18, 0x1f1d, 0x1f20, 0x1f45, 0x1f48, 0x1f4d, @@ -35761,16 +38294,14 @@ static const OnigCodePoint CR_Age_13_0[] = { 0x2066, 0x2071, 0x2074, 0x208e, 0x2090, 0x209c, - 0x20a0, 0x20bf, + 0x20a0, 0x20c0, 0x20d0, 0x20f0, 0x2100, 0x218b, 0x2190, 0x2426, 0x2440, 0x244a, 0x2460, 0x2b73, 0x2b76, 0x2b95, - 0x2b97, 0x2c2e, - 0x2c30, 0x2c5e, - 0x2c60, 0x2cf3, + 0x2b97, 0x2cf3, 0x2cf9, 0x2d25, 0x2d27, 0x2d27, 0x2d2d, 0x2d2d, @@ -35785,7 +38316,7 @@ static const OnigCodePoint CR_Age_13_0[] = { 0x2dc8, 0x2dce, 0x2dd0, 0x2dd6, 0x2dd8, 0x2dde, - 0x2de0, 0x2e52, + 0x2de0, 0x2e5d, 0x2e80, 0x2e99, 0x2e9b, 0x2ef3, 0x2f00, 0x2fd5, @@ -35797,14 +38328,15 @@ static const OnigCodePoint CR_Age_13_0[] = { 0x3131, 0x318e, 0x3190, 0x31e3, 0x31f0, 0x321e, - 0x3220, 0x9ffc, - 0xa000, 0xa48c, + 0x3220, 0xa48c, 0xa490, 0xa4c6, 0xa4d0, 0xa62b, 0xa640, 0xa6f7, - 0xa700, 0xa7bf, - 0xa7c2, 0xa7ca, - 0xa7f5, 0xa82c, + 0xa700, 0xa7ca, + 0xa7d0, 0xa7d1, + 0xa7d3, 0xa7d3, + 0xa7d5, 0xa7d9, + 0xa7f2, 0xa82c, 0xa830, 0xa839, 0xa840, 0xa877, 0xa880, 0xa8c5, @@ -35839,12 +38371,10 @@ static const OnigCodePoint CR_Age_13_0[] = { 0xfb3e, 0xfb3e, 0xfb40, 0xfb41, 0xfb43, 0xfb44, - 0xfb46, 0xfbc1, - 0xfbd3, 0xfd3f, - 0xfd50, 0xfd8f, + 0xfb46, 0xfbc2, + 0xfbd3, 0xfd8f, 0xfd92, 0xfdc7, - 0xfdd0, 0xfdfd, - 0xfe00, 0xfe19, + 0xfdcf, 0xfe19, 0xfe20, 0xfe52, 0xfe54, 0xfe66, 0xfe68, 0xfe6b, @@ -35886,10 +38416,20 @@ static const OnigCodePoint CR_Age_13_0[] = { 0x104d8, 0x104fb, 0x10500, 0x10527, 0x10530, 0x10563, - 0x1056f, 0x1056f, + 0x1056f, 0x1057a, + 0x1057c, 0x1058a, + 0x1058c, 0x10592, + 0x10594, 0x10595, + 0x10597, 0x105a1, + 0x105a3, 0x105b1, + 0x105b3, 0x105b9, + 0x105bb, 0x105bc, 0x10600, 0x10736, 0x10740, 0x10755, 0x10760, 0x10767, + 0x10780, 0x10785, + 0x10787, 0x107b0, + 0x107b2, 0x107ba, 0x10800, 0x10805, 0x10808, 0x10808, 0x1080a, 0x10835, @@ -35931,13 +38471,14 @@ static const OnigCodePoint CR_Age_13_0[] = { 0x10e80, 0x10ea9, 0x10eab, 0x10ead, 0x10eb0, 0x10eb1, - 0x10f00, 0x10f27, + 0x10efd, 0x10f27, 0x10f30, 0x10f59, + 0x10f70, 0x10f89, 0x10fb0, 0x10fcb, 0x10fe0, 0x10ff6, 0x11000, 0x1104d, - 0x11052, 0x1106f, - 0x1107f, 0x110c1, + 0x11052, 0x11075, + 0x1107f, 0x110c2, 0x110cd, 0x110cd, 0x110d0, 0x110e8, 0x110f0, 0x110f9, @@ -35947,7 +38488,7 @@ static const OnigCodePoint CR_Age_13_0[] = { 0x11180, 0x111df, 0x111e1, 0x111f4, 0x11200, 0x11211, - 0x11213, 0x1123e, + 0x11213, 0x11241, 0x11280, 0x11286, 0x11288, 0x11288, 0x1128a, 0x1128d, @@ -35979,11 +38520,11 @@ static const OnigCodePoint CR_Age_13_0[] = { 0x11600, 0x11644, 0x11650, 0x11659, 0x11660, 0x1166c, - 0x11680, 0x116b8, + 0x11680, 0x116b9, 0x116c0, 0x116c9, 0x11700, 0x1171a, 0x1171d, 0x1172b, - 0x11730, 0x1173f, + 0x11730, 0x11746, 0x11800, 0x1183b, 0x118a0, 0x118f2, 0x118ff, 0x11906, @@ -35999,7 +38540,8 @@ static const OnigCodePoint CR_Age_13_0[] = { 0x119da, 0x119e4, 0x11a00, 0x11a47, 0x11a50, 0x11aa2, - 0x11ac0, 0x11af8, + 0x11ab0, 0x11af8, + 0x11b00, 0x11b09, 0x11c00, 0x11c08, 0x11c0a, 0x11c36, 0x11c38, 0x11c45, @@ -36021,19 +38563,23 @@ static const OnigCodePoint CR_Age_13_0[] = { 0x11d93, 0x11d98, 0x11da0, 0x11da9, 0x11ee0, 0x11ef8, + 0x11f00, 0x11f10, + 0x11f12, 0x11f3a, + 0x11f3e, 0x11f59, 0x11fb0, 0x11fb0, 0x11fc0, 0x11ff1, 0x11fff, 0x12399, 0x12400, 0x1246e, 0x12470, 0x12474, 0x12480, 0x12543, - 0x13000, 0x1342e, - 0x13430, 0x13438, + 0x12f90, 0x12ff2, + 0x13000, 0x13455, 0x14400, 0x14646, 0x16800, 0x16a38, 0x16a40, 0x16a5e, 0x16a60, 0x16a69, - 0x16a6e, 0x16a6f, + 0x16a6e, 0x16abe, + 0x16ac0, 0x16ac9, 0x16ad0, 0x16aed, 0x16af0, 0x16af5, 0x16b00, 0x16b45, @@ -36050,8 +38596,13 @@ static const OnigCodePoint CR_Age_13_0[] = { 0x17000, 0x187f7, 0x18800, 0x18cd5, 0x18d00, 0x18d08, - 0x1b000, 0x1b11e, + 0x1aff0, 0x1aff3, + 0x1aff5, 0x1affb, + 0x1affd, 0x1affe, + 0x1b000, 0x1b122, + 0x1b132, 0x1b132, 0x1b150, 0x1b152, + 0x1b155, 0x1b155, 0x1b164, 0x1b167, 0x1b170, 0x1b2fb, 0x1bc00, 0x1bc6a, @@ -36059,10 +38610,14 @@ static const OnigCodePoint CR_Age_13_0[] = { 0x1bc80, 0x1bc88, 0x1bc90, 0x1bc99, 0x1bc9c, 0x1bca3, + 0x1cf00, 0x1cf2d, + 0x1cf30, 0x1cf46, + 0x1cf50, 0x1cfc3, 0x1d000, 0x1d0f5, 0x1d100, 0x1d126, - 0x1d129, 0x1d1e8, + 0x1d129, 0x1d1ea, 0x1d200, 0x1d245, + 0x1d2c0, 0x1d2d3, 0x1d2e0, 0x1d2f3, 0x1d300, 0x1d356, 0x1d360, 0x1d378, @@ -36089,17 +38644,27 @@ static const OnigCodePoint CR_Age_13_0[] = { 0x1d7ce, 0x1da8b, 0x1da9b, 0x1da9f, 0x1daa1, 0x1daaf, + 0x1df00, 0x1df1e, + 0x1df25, 0x1df2a, 0x1e000, 0x1e006, 0x1e008, 0x1e018, 0x1e01b, 0x1e021, 0x1e023, 0x1e024, 0x1e026, 0x1e02a, + 0x1e030, 0x1e06d, + 0x1e08f, 0x1e08f, 0x1e100, 0x1e12c, 0x1e130, 0x1e13d, 0x1e140, 0x1e149, 0x1e14e, 0x1e14f, + 0x1e290, 0x1e2ae, 0x1e2c0, 0x1e2f9, 0x1e2ff, 0x1e2ff, + 0x1e4d0, 0x1e4f9, + 0x1e7e0, 0x1e7e6, + 0x1e7e8, 0x1e7eb, + 0x1e7ed, 0x1e7ee, + 0x1e7f0, 0x1e7fe, 0x1e800, 0x1e8c4, 0x1e8c7, 0x1e8d6, 0x1e900, 0x1e94b, @@ -36154,38 +38719,38 @@ static const OnigCodePoint CR_Age_13_0[] = { 0x1f250, 0x1f251, 0x1f260, 0x1f265, 0x1f300, 0x1f6d7, - 0x1f6e0, 0x1f6ec, + 0x1f6dc, 0x1f6ec, 0x1f6f0, 0x1f6fc, - 0x1f700, 0x1f773, - 0x1f780, 0x1f7d8, + 0x1f700, 0x1f776, + 0x1f77b, 0x1f7d9, 0x1f7e0, 0x1f7eb, + 0x1f7f0, 0x1f7f0, 0x1f800, 0x1f80b, 0x1f810, 0x1f847, 0x1f850, 0x1f859, 0x1f860, 0x1f887, 0x1f890, 0x1f8ad, 0x1f8b0, 0x1f8b1, - 0x1f900, 0x1f978, - 0x1f97a, 0x1f9cb, - 0x1f9cd, 0x1fa53, + 0x1f900, 0x1fa53, 0x1fa60, 0x1fa6d, - 0x1fa70, 0x1fa74, - 0x1fa78, 0x1fa7a, - 0x1fa80, 0x1fa86, - 0x1fa90, 0x1faa8, - 0x1fab0, 0x1fab6, - 0x1fac0, 0x1fac2, - 0x1fad0, 0x1fad6, + 0x1fa70, 0x1fa7c, + 0x1fa80, 0x1fa88, + 0x1fa90, 0x1fabd, + 0x1fabf, 0x1fac5, + 0x1face, 0x1fadb, + 0x1fae0, 0x1fae8, + 0x1faf0, 0x1faf8, 0x1fb00, 0x1fb92, 0x1fb94, 0x1fbca, 0x1fbf0, 0x1fbf9, - 0x1fffe, 0x2a6dd, - 0x2a700, 0x2b734, + 0x1fffe, 0x2a6df, + 0x2a700, 0x2b739, 0x2b740, 0x2b81d, 0x2b820, 0x2cea1, 0x2ceb0, 0x2ebe0, 0x2f800, 0x2fa1d, 0x2fffe, 0x3134a, + 0x31350, 0x323af, 0x3fffe, 0x3ffff, 0x4fffe, 0x4ffff, 0x5fffe, 0x5ffff, @@ -36201,11 +38766,11 @@ static const OnigCodePoint CR_Age_13_0[] = { 0xe0020, 0xe007f, 0xe0100, 0xe01ef, 0xefffe, 0x10ffff, -}; /* CR_Age_13_0 */ +}; /* CR_Age_15_0 */ -/* 'Age_14_0': Derived Age 14.0 */ -static const OnigCodePoint CR_Age_14_0[] = { - 706, +/* 'Age_15_1': Derived Age 15.1 */ +static const OnigCodePoint CR_Age_15_1[] = { + 715, 0x0000, 0x0377, 0x037a, 0x037f, 0x0384, 0x038a, @@ -36327,7 +38892,7 @@ static const OnigCodePoint CR_Age_14_0[] = { 0x0cdd, 0x0cde, 0x0ce0, 0x0ce3, 0x0ce6, 0x0cef, - 0x0cf1, 0x0cf2, + 0x0cf1, 0x0cf3, 0x0d00, 0x0d0c, 0x0d0e, 0x0d10, 0x0d12, 0x0d44, @@ -36357,7 +38922,7 @@ static const OnigCodePoint CR_Age_14_0[] = { 0x0ea7, 0x0ebd, 0x0ec0, 0x0ec4, 0x0ec6, 0x0ec6, - 0x0ec8, 0x0ecd, + 0x0ec8, 0x0ece, 0x0ed0, 0x0ed9, 0x0edc, 0x0edf, 0x0f00, 0x0f47, @@ -36475,14 +39040,13 @@ static const OnigCodePoint CR_Age_14_0[] = { 0x2e80, 0x2e99, 0x2e9b, 0x2ef3, 0x2f00, 0x2fd5, - 0x2ff0, 0x2ffb, - 0x3000, 0x303f, + 0x2ff0, 0x303f, 0x3041, 0x3096, 0x3099, 0x30ff, 0x3105, 0x312f, 0x3131, 0x318e, 0x3190, 0x31e3, - 0x31f0, 0x321e, + 0x31ef, 0x321e, 0x3220, 0xa48c, 0xa490, 0xa4c6, 0xa4d0, 0xa62b, @@ -36626,7 +39190,7 @@ static const OnigCodePoint CR_Age_14_0[] = { 0x10e80, 0x10ea9, 0x10eab, 0x10ead, 0x10eb0, 0x10eb1, - 0x10f00, 0x10f27, + 0x10efd, 0x10f27, 0x10f30, 0x10f59, 0x10f70, 0x10f89, 0x10fb0, 0x10fcb, @@ -36643,7 +39207,7 @@ static const OnigCodePoint CR_Age_14_0[] = { 0x11180, 0x111df, 0x111e1, 0x111f4, 0x11200, 0x11211, - 0x11213, 0x1123e, + 0x11213, 0x11241, 0x11280, 0x11286, 0x11288, 0x11288, 0x1128a, 0x1128d, @@ -36696,6 +39260,7 @@ static const OnigCodePoint CR_Age_14_0[] = { 0x11a00, 0x11a47, 0x11a50, 0x11aa2, 0x11ab0, 0x11af8, + 0x11b00, 0x11b09, 0x11c00, 0x11c08, 0x11c0a, 0x11c36, 0x11c38, 0x11c45, @@ -36717,6 +39282,9 @@ static const OnigCodePoint CR_Age_14_0[] = { 0x11d93, 0x11d98, 0x11da0, 0x11da9, 0x11ee0, 0x11ef8, + 0x11f00, 0x11f10, + 0x11f12, 0x11f3a, + 0x11f3e, 0x11f59, 0x11fb0, 0x11fb0, 0x11fc0, 0x11ff1, 0x11fff, 0x12399, @@ -36724,8 +39292,7 @@ static const OnigCodePoint CR_Age_14_0[] = { 0x12470, 0x12474, 0x12480, 0x12543, 0x12f90, 0x12ff2, - 0x13000, 0x1342e, - 0x13430, 0x13438, + 0x13000, 0x13455, 0x14400, 0x14646, 0x16800, 0x16a38, 0x16a40, 0x16a5e, @@ -36752,7 +39319,9 @@ static const OnigCodePoint CR_Age_14_0[] = { 0x1aff5, 0x1affb, 0x1affd, 0x1affe, 0x1b000, 0x1b122, + 0x1b132, 0x1b132, 0x1b150, 0x1b152, + 0x1b155, 0x1b155, 0x1b164, 0x1b167, 0x1b170, 0x1b2fb, 0x1bc00, 0x1bc6a, @@ -36767,6 +39336,7 @@ static const OnigCodePoint CR_Age_14_0[] = { 0x1d100, 0x1d126, 0x1d129, 0x1d1ea, 0x1d200, 0x1d245, + 0x1d2c0, 0x1d2d3, 0x1d2e0, 0x1d2f3, 0x1d300, 0x1d356, 0x1d360, 0x1d378, @@ -36794,11 +39364,14 @@ static const OnigCodePoint CR_Age_14_0[] = { 0x1da9b, 0x1da9f, 0x1daa1, 0x1daaf, 0x1df00, 0x1df1e, + 0x1df25, 0x1df2a, 0x1e000, 0x1e006, 0x1e008, 0x1e018, 0x1e01b, 0x1e021, 0x1e023, 0x1e024, 0x1e026, 0x1e02a, + 0x1e030, 0x1e06d, + 0x1e08f, 0x1e08f, 0x1e100, 0x1e12c, 0x1e130, 0x1e13d, 0x1e140, 0x1e149, @@ -36806,6 +39379,7 @@ static const OnigCodePoint CR_Age_14_0[] = { 0x1e290, 0x1e2ae, 0x1e2c0, 0x1e2f9, 0x1e2ff, 0x1e2ff, + 0x1e4d0, 0x1e4f9, 0x1e7e0, 0x1e7e6, 0x1e7e8, 0x1e7eb, 0x1e7ed, 0x1e7ee, @@ -36864,10 +39438,10 @@ static const OnigCodePoint CR_Age_14_0[] = { 0x1f250, 0x1f251, 0x1f260, 0x1f265, 0x1f300, 0x1f6d7, - 0x1f6dd, 0x1f6ec, + 0x1f6dc, 0x1f6ec, 0x1f6f0, 0x1f6fc, - 0x1f700, 0x1f773, - 0x1f780, 0x1f7d8, + 0x1f700, 0x1f776, + 0x1f77b, 0x1f7d9, 0x1f7e0, 0x1f7eb, 0x1f7f0, 0x1f7f0, 0x1f800, 0x1f80b, @@ -36878,25 +39452,25 @@ static const OnigCodePoint CR_Age_14_0[] = { 0x1f8b0, 0x1f8b1, 0x1f900, 0x1fa53, 0x1fa60, 0x1fa6d, - 0x1fa70, 0x1fa74, - 0x1fa78, 0x1fa7c, - 0x1fa80, 0x1fa86, - 0x1fa90, 0x1faac, - 0x1fab0, 0x1faba, - 0x1fac0, 0x1fac5, - 0x1fad0, 0x1fad9, - 0x1fae0, 0x1fae7, - 0x1faf0, 0x1faf6, + 0x1fa70, 0x1fa7c, + 0x1fa80, 0x1fa88, + 0x1fa90, 0x1fabd, + 0x1fabf, 0x1fac5, + 0x1face, 0x1fadb, + 0x1fae0, 0x1fae8, + 0x1faf0, 0x1faf8, 0x1fb00, 0x1fb92, 0x1fb94, 0x1fbca, 0x1fbf0, 0x1fbf9, 0x1fffe, 0x2a6df, - 0x2a700, 0x2b738, + 0x2a700, 0x2b739, 0x2b740, 0x2b81d, 0x2b820, 0x2cea1, 0x2ceb0, 0x2ebe0, + 0x2ebf0, 0x2ee5d, 0x2f800, 0x2fa1d, 0x2fffe, 0x3134a, + 0x31350, 0x323af, 0x3fffe, 0x3ffff, 0x4fffe, 0x4ffff, 0x5fffe, 0x5ffff, @@ -36912,11 +39486,11 @@ static const OnigCodePoint CR_Age_14_0[] = { 0xe0020, 0xe007f, 0xe0100, 0xe01ef, 0xefffe, 0x10ffff, -}; /* CR_Age_14_0 */ +}; /* CR_Age_15_1 */ -/* 'Age_15_0': Derived Age 15.0 */ -static const OnigCodePoint CR_Age_15_0[] = { - 715, +/* 'Age_16_0': Derived Age 16.0 */ +static const OnigCodePoint CR_Age_16_0[] = { + 739, 0x0000, 0x0377, 0x037a, 0x037f, 0x0384, 0x038a, @@ -36940,7 +39514,7 @@ static const OnigCodePoint CR_Age_15_0[] = { 0x0860, 0x086a, 0x0870, 0x088e, 0x0890, 0x0891, - 0x0898, 0x0983, + 0x0897, 0x0983, 0x0985, 0x098c, 0x098f, 0x0990, 0x0993, 0x09a8, @@ -37132,11 +39706,10 @@ static const OnigCodePoint CR_Age_15_0[] = { 0x1aa0, 0x1aad, 0x1ab0, 0x1ace, 0x1b00, 0x1b4c, - 0x1b50, 0x1b7e, - 0x1b80, 0x1bf3, + 0x1b4e, 0x1bf3, 0x1bfc, 0x1c37, 0x1c3b, 0x1c49, - 0x1c4d, 0x1c88, + 0x1c4d, 0x1c8a, 0x1c90, 0x1cba, 0x1cbd, 0x1cc7, 0x1cd0, 0x1cfa, @@ -37163,7 +39736,7 @@ static const OnigCodePoint CR_Age_15_0[] = { 0x20a0, 0x20c0, 0x20d0, 0x20f0, 0x2100, 0x218b, - 0x2190, 0x2426, + 0x2190, 0x2429, 0x2440, 0x244a, 0x2460, 0x2b73, 0x2b76, 0x2b95, @@ -37186,22 +39759,21 @@ static const OnigCodePoint CR_Age_15_0[] = { 0x2e80, 0x2e99, 0x2e9b, 0x2ef3, 0x2f00, 0x2fd5, - 0x2ff0, 0x2ffb, - 0x3000, 0x303f, + 0x2ff0, 0x303f, 0x3041, 0x3096, 0x3099, 0x30ff, 0x3105, 0x312f, 0x3131, 0x318e, - 0x3190, 0x31e3, - 0x31f0, 0x321e, + 0x3190, 0x31e5, + 0x31ef, 0x321e, 0x3220, 0xa48c, 0xa490, 0xa4c6, 0xa4d0, 0xa62b, 0xa640, 0xa6f7, - 0xa700, 0xa7ca, + 0xa700, 0xa7cd, 0xa7d0, 0xa7d1, 0xa7d3, 0xa7d3, - 0xa7d5, 0xa7d9, + 0xa7d5, 0xa7dc, 0xa7f2, 0xa82c, 0xa830, 0xa839, 0xa840, 0xa877, @@ -37290,6 +39862,7 @@ static const OnigCodePoint CR_Age_15_0[] = { 0x105a3, 0x105b1, 0x105b3, 0x105b9, 0x105bb, 0x105bc, + 0x105c0, 0x105f3, 0x10600, 0x10736, 0x10740, 0x10755, 0x10760, 0x10767, @@ -37333,11 +39906,15 @@ static const OnigCodePoint CR_Age_15_0[] = { 0x10cc0, 0x10cf2, 0x10cfa, 0x10d27, 0x10d30, 0x10d39, + 0x10d40, 0x10d65, + 0x10d69, 0x10d85, + 0x10d8e, 0x10d8f, 0x10e60, 0x10e7e, 0x10e80, 0x10ea9, 0x10eab, 0x10ead, 0x10eb0, 0x10eb1, - 0x10efd, 0x10f27, + 0x10ec2, 0x10ec4, + 0x10efc, 0x10f27, 0x10f30, 0x10f59, 0x10f70, 0x10f89, 0x10fb0, 0x10fcb, @@ -37377,6 +39954,17 @@ static const OnigCodePoint CR_Age_15_0[] = { 0x1135d, 0x11363, 0x11366, 0x1136c, 0x11370, 0x11374, + 0x11380, 0x11389, + 0x1138b, 0x1138b, + 0x1138e, 0x1138e, + 0x11390, 0x113b5, + 0x113b7, 0x113c0, + 0x113c2, 0x113c2, + 0x113c5, 0x113c5, + 0x113c7, 0x113ca, + 0x113cc, 0x113d5, + 0x113d7, 0x113d8, + 0x113e1, 0x113e2, 0x11400, 0x1145b, 0x1145d, 0x11461, 0x11480, 0x114c7, @@ -37388,6 +39976,7 @@ static const OnigCodePoint CR_Age_15_0[] = { 0x11660, 0x1166c, 0x11680, 0x116b9, 0x116c0, 0x116c9, + 0x116d0, 0x116e3, 0x11700, 0x1171a, 0x1171d, 0x1172b, 0x11730, 0x11746, @@ -37408,6 +39997,8 @@ static const OnigCodePoint CR_Age_15_0[] = { 0x11a50, 0x11aa2, 0x11ab0, 0x11af8, 0x11b00, 0x11b09, + 0x11bc0, 0x11be1, + 0x11bf0, 0x11bf9, 0x11c00, 0x11c08, 0x11c0a, 0x11c36, 0x11c38, 0x11c45, @@ -37431,7 +40022,7 @@ static const OnigCodePoint CR_Age_15_0[] = { 0x11ee0, 0x11ef8, 0x11f00, 0x11f10, 0x11f12, 0x11f3a, - 0x11f3e, 0x11f59, + 0x11f3e, 0x11f5a, 0x11fb0, 0x11fb0, 0x11fc0, 0x11ff1, 0x11fff, 0x12399, @@ -37440,7 +40031,9 @@ static const OnigCodePoint CR_Age_15_0[] = { 0x12480, 0x12543, 0x12f90, 0x12ff2, 0x13000, 0x13455, + 0x13460, 0x143fa, 0x14400, 0x14646, + 0x16100, 0x16139, 0x16800, 0x16a38, 0x16a40, 0x16a5e, 0x16a60, 0x16a69, @@ -37453,6 +40046,7 @@ static const OnigCodePoint CR_Age_15_0[] = { 0x16b5b, 0x16b61, 0x16b63, 0x16b77, 0x16b7d, 0x16b8f, + 0x16d40, 0x16d79, 0x16e40, 0x16e9a, 0x16f00, 0x16f4a, 0x16f4f, 0x16f87, @@ -37461,7 +40055,7 @@ static const OnigCodePoint CR_Age_15_0[] = { 0x16ff0, 0x16ff1, 0x17000, 0x187f7, 0x18800, 0x18cd5, - 0x18d00, 0x18d08, + 0x18cff, 0x18d08, 0x1aff0, 0x1aff3, 0x1aff5, 0x1affb, 0x1affd, 0x1affe, @@ -37476,6 +40070,8 @@ static const OnigCodePoint CR_Age_15_0[] = { 0x1bc80, 0x1bc88, 0x1bc90, 0x1bc99, 0x1bc9c, 0x1bca3, + 0x1cc00, 0x1ccf9, + 0x1cd00, 0x1ceb3, 0x1cf00, 0x1cf2d, 0x1cf30, 0x1cf46, 0x1cf50, 0x1cfc3, @@ -37527,6 +40123,8 @@ static const OnigCodePoint CR_Age_15_0[] = { 0x1e2c0, 0x1e2f9, 0x1e2ff, 0x1e2ff, 0x1e4d0, 0x1e4f9, + 0x1e5d0, 0x1e5fa, + 0x1e5ff, 0x1e5ff, 0x1e7e0, 0x1e7e6, 0x1e7e8, 0x1e7eb, 0x1e7ed, 0x1e7ee, @@ -37596,24 +40194,24 @@ static const OnigCodePoint CR_Age_15_0[] = { 0x1f850, 0x1f859, 0x1f860, 0x1f887, 0x1f890, 0x1f8ad, - 0x1f8b0, 0x1f8b1, + 0x1f8b0, 0x1f8bb, + 0x1f8c0, 0x1f8c1, 0x1f900, 0x1fa53, 0x1fa60, 0x1fa6d, 0x1fa70, 0x1fa7c, - 0x1fa80, 0x1fa88, - 0x1fa90, 0x1fabd, - 0x1fabf, 0x1fac5, - 0x1face, 0x1fadb, - 0x1fae0, 0x1fae8, + 0x1fa80, 0x1fa89, + 0x1fa8f, 0x1fac6, + 0x1face, 0x1fadc, + 0x1fadf, 0x1fae9, 0x1faf0, 0x1faf8, 0x1fb00, 0x1fb92, - 0x1fb94, 0x1fbca, - 0x1fbf0, 0x1fbf9, + 0x1fb94, 0x1fbf9, 0x1fffe, 0x2a6df, 0x2a700, 0x2b739, 0x2b740, 0x2b81d, 0x2b820, 0x2cea1, 0x2ceb0, 0x2ebe0, + 0x2ebf0, 0x2ee5d, 0x2f800, 0x2fa1d, 0x2fffe, 0x3134a, 0x31350, 0x323af, @@ -37632,12 +40230,12 @@ static const OnigCodePoint CR_Age_15_0[] = { 0xe0020, 0xe007f, 0xe0100, 0xe01ef, 0xefffe, 0x10ffff, -}; /* CR_Age_15_0 */ +}; /* CR_Age_16_0 */ #endif /* USE_UNICODE_AGE_PROPERTIES */ /* 'Grapheme_Cluster_Break_Prepend': Grapheme_Cluster_Break=Prepend */ static const OnigCodePoint CR_Grapheme_Cluster_Break_Prepend[] = { - 15, + 16, 0x0600, 0x0605, 0x06dd, 0x06dd, 0x070f, 0x070f, @@ -37647,6 +40245,7 @@ static const OnigCodePoint CR_Grapheme_Cluster_Break_Prepend[] = { 0x110bd, 0x110bd, 0x110cd, 0x110cd, 0x111c2, 0x111c3, + 0x113d1, 0x113d1, 0x1193f, 0x1193f, 0x11941, 0x11941, 0x11a3a, 0x11a3a, @@ -37690,7 +40289,7 @@ static const OnigCodePoint CR_Grapheme_Cluster_Break_Control[] = { /* 'Grapheme_Cluster_Break_Extend': Grapheme_Cluster_Break=Extend */ static const OnigCodePoint CR_Grapheme_Cluster_Break_Extend[] = { - 364, + 376, 0x0300, 0x036f, 0x0483, 0x0489, 0x0591, 0x05bd, @@ -37715,7 +40314,7 @@ static const OnigCodePoint CR_Grapheme_Cluster_Break_Extend[] = { 0x0825, 0x0827, 0x0829, 0x082d, 0x0859, 0x085b, - 0x0898, 0x089f, + 0x0897, 0x089f, 0x08ca, 0x08e1, 0x08e3, 0x0902, 0x093a, 0x093a, @@ -37769,10 +40368,10 @@ static const OnigCodePoint CR_Grapheme_Cluster_Break_Extend[] = { 0x0c62, 0x0c63, 0x0c81, 0x0c81, 0x0cbc, 0x0cbc, - 0x0cbf, 0x0cbf, + 0x0cbf, 0x0cc0, 0x0cc2, 0x0cc2, - 0x0cc6, 0x0cc6, - 0x0ccc, 0x0ccd, + 0x0cc6, 0x0cc8, + 0x0cca, 0x0ccd, 0x0cd5, 0x0cd6, 0x0ce2, 0x0ce3, 0x0d00, 0x0d01, @@ -37816,8 +40415,8 @@ static const OnigCodePoint CR_Grapheme_Cluster_Break_Extend[] = { 0x108d, 0x108d, 0x109d, 0x109d, 0x135d, 0x135f, - 0x1712, 0x1714, - 0x1732, 0x1733, + 0x1712, 0x1715, + 0x1732, 0x1734, 0x1752, 0x1753, 0x1772, 0x1773, 0x17b4, 0x17b5, @@ -37844,18 +40443,16 @@ static const OnigCodePoint CR_Grapheme_Cluster_Break_Extend[] = { 0x1a7f, 0x1a7f, 0x1ab0, 0x1ace, 0x1b00, 0x1b03, - 0x1b34, 0x1b3a, - 0x1b3c, 0x1b3c, - 0x1b42, 0x1b42, + 0x1b34, 0x1b3d, + 0x1b42, 0x1b44, 0x1b6b, 0x1b73, 0x1b80, 0x1b81, 0x1ba2, 0x1ba5, - 0x1ba8, 0x1ba9, - 0x1bab, 0x1bad, + 0x1ba8, 0x1bad, 0x1be6, 0x1be6, 0x1be8, 0x1be9, 0x1bed, 0x1bed, - 0x1bef, 0x1bf1, + 0x1bef, 0x1bf3, 0x1c2c, 0x1c33, 0x1c36, 0x1c37, 0x1cd0, 0x1cd2, @@ -37886,10 +40483,12 @@ static const OnigCodePoint CR_Grapheme_Cluster_Break_Extend[] = { 0xa8ff, 0xa8ff, 0xa926, 0xa92d, 0xa947, 0xa951, + 0xa953, 0xa953, 0xa980, 0xa982, 0xa9b3, 0xa9b3, 0xa9b6, 0xa9b9, 0xa9bc, 0xa9bd, + 0xa9c0, 0xa9c0, 0xa9e5, 0xa9e5, 0xaa29, 0xaa2e, 0xaa31, 0xaa32, @@ -37921,8 +40520,9 @@ static const OnigCodePoint CR_Grapheme_Cluster_Break_Extend[] = { 0x10a3f, 0x10a3f, 0x10ae5, 0x10ae6, 0x10d24, 0x10d27, + 0x10d69, 0x10d6d, 0x10eab, 0x10eac, - 0x10efd, 0x10eff, + 0x10efc, 0x10eff, 0x10f46, 0x10f50, 0x10f82, 0x10f85, 0x11001, 0x11001, @@ -37939,11 +40539,11 @@ static const OnigCodePoint CR_Grapheme_Cluster_Break_Extend[] = { 0x11173, 0x11173, 0x11180, 0x11181, 0x111b6, 0x111be, + 0x111c0, 0x111c0, 0x111c9, 0x111cc, 0x111cf, 0x111cf, 0x1122f, 0x11231, - 0x11234, 0x11234, - 0x11236, 0x11237, + 0x11234, 0x11237, 0x1123e, 0x1123e, 0x11241, 0x11241, 0x112df, 0x112df, @@ -37952,9 +40552,18 @@ static const OnigCodePoint CR_Grapheme_Cluster_Break_Extend[] = { 0x1133b, 0x1133c, 0x1133e, 0x1133e, 0x11340, 0x11340, + 0x1134d, 0x1134d, 0x11357, 0x11357, 0x11366, 0x1136c, 0x11370, 0x11374, + 0x113b8, 0x113b8, + 0x113bb, 0x113c0, + 0x113c2, 0x113c2, + 0x113c5, 0x113c5, + 0x113c7, 0x113c9, + 0x113ce, 0x113d0, + 0x113d2, 0x113d2, + 0x113e1, 0x113e2, 0x11438, 0x1143f, 0x11442, 0x11444, 0x11446, 0x11446, @@ -37975,16 +40584,15 @@ static const OnigCodePoint CR_Grapheme_Cluster_Break_Extend[] = { 0x1163f, 0x11640, 0x116ab, 0x116ab, 0x116ad, 0x116ad, - 0x116b0, 0x116b5, - 0x116b7, 0x116b7, - 0x1171d, 0x1171f, + 0x116b0, 0x116b7, + 0x1171d, 0x1171d, + 0x1171f, 0x1171f, 0x11722, 0x11725, 0x11727, 0x1172b, 0x1182f, 0x11837, 0x11839, 0x1183a, 0x11930, 0x11930, - 0x1193b, 0x1193c, - 0x1193e, 0x1193e, + 0x1193b, 0x1193e, 0x11943, 0x11943, 0x119d4, 0x119d7, 0x119da, 0x119db, @@ -38015,21 +40623,23 @@ static const OnigCodePoint CR_Grapheme_Cluster_Break_Extend[] = { 0x11ef3, 0x11ef4, 0x11f00, 0x11f01, 0x11f36, 0x11f3a, - 0x11f40, 0x11f40, - 0x11f42, 0x11f42, + 0x11f40, 0x11f42, + 0x11f5a, 0x11f5a, 0x13440, 0x13440, 0x13447, 0x13455, + 0x1611e, 0x16129, + 0x1612d, 0x1612f, 0x16af0, 0x16af4, 0x16b30, 0x16b36, 0x16f4f, 0x16f4f, 0x16f8f, 0x16f92, 0x16fe4, 0x16fe4, + 0x16ff0, 0x16ff1, 0x1bc9d, 0x1bc9e, 0x1cf00, 0x1cf2d, 0x1cf30, 0x1cf46, - 0x1d165, 0x1d165, - 0x1d167, 0x1d169, - 0x1d16e, 0x1d172, + 0x1d165, 0x1d169, + 0x1d16d, 0x1d172, 0x1d17b, 0x1d182, 0x1d185, 0x1d18b, 0x1d1aa, 0x1d1ad, @@ -38050,6 +40660,7 @@ static const OnigCodePoint CR_Grapheme_Cluster_Break_Extend[] = { 0x1e2ae, 0x1e2ae, 0x1e2ec, 0x1e2ef, 0x1e4ec, 0x1e4ef, + 0x1e5ee, 0x1e5ef, 0x1e8d0, 0x1e8d6, 0x1e944, 0x1e94a, 0x1f3fb, 0x1f3ff, @@ -38062,7 +40673,7 @@ static const OnigCodePoint CR_Grapheme_Cluster_Break_Extend[] = { /* 'Grapheme_Cluster_Break_SpacingMark': Grapheme_Cluster_Break=SpacingMark */ static const OnigCodePoint CR_Grapheme_Cluster_Break_SpacingMark[] = { - 165, + 155, 0x0903, 0x0903, 0x093b, 0x093b, 0x093e, 0x0940, @@ -38090,10 +40701,8 @@ static const OnigCodePoint CR_Grapheme_Cluster_Break_SpacingMark[] = { 0x0c41, 0x0c44, 0x0c82, 0x0c83, 0x0cbe, 0x0cbe, - 0x0cc0, 0x0cc1, + 0x0cc1, 0x0cc1, 0x0cc3, 0x0cc4, - 0x0cc7, 0x0cc8, - 0x0cca, 0x0ccb, 0x0cf3, 0x0cf3, 0x0d02, 0x0d03, 0x0d3f, 0x0d40, @@ -38111,8 +40720,6 @@ static const OnigCodePoint CR_Grapheme_Cluster_Break_SpacingMark[] = { 0x103b, 0x103c, 0x1056, 0x1057, 0x1084, 0x1084, - 0x1715, 0x1715, - 0x1734, 0x1734, 0x17b6, 0x17b6, 0x17be, 0x17c5, 0x17c7, 0x17c8, @@ -38125,17 +40732,13 @@ static const OnigCodePoint CR_Grapheme_Cluster_Break_SpacingMark[] = { 0x1a57, 0x1a57, 0x1a6d, 0x1a72, 0x1b04, 0x1b04, - 0x1b3b, 0x1b3b, - 0x1b3d, 0x1b41, - 0x1b43, 0x1b44, + 0x1b3e, 0x1b41, 0x1b82, 0x1b82, 0x1ba1, 0x1ba1, 0x1ba6, 0x1ba7, - 0x1baa, 0x1baa, 0x1be7, 0x1be7, 0x1bea, 0x1bec, 0x1bee, 0x1bee, - 0x1bf2, 0x1bf3, 0x1c24, 0x1c2b, 0x1c34, 0x1c35, 0x1ce1, 0x1ce1, @@ -38144,11 +40747,11 @@ static const OnigCodePoint CR_Grapheme_Cluster_Break_SpacingMark[] = { 0xa827, 0xa827, 0xa880, 0xa881, 0xa8b4, 0xa8c3, - 0xa952, 0xa953, + 0xa952, 0xa952, 0xa983, 0xa983, 0xa9b4, 0xa9b5, 0xa9ba, 0xa9bb, - 0xa9be, 0xa9c0, + 0xa9be, 0xa9bf, 0xaa2f, 0xaa30, 0xaa33, 0xaa34, 0xaa4d, 0xaa4d, @@ -38168,18 +40771,20 @@ static const OnigCodePoint CR_Grapheme_Cluster_Break_SpacingMark[] = { 0x11145, 0x11146, 0x11182, 0x11182, 0x111b3, 0x111b5, - 0x111bf, 0x111c0, + 0x111bf, 0x111bf, 0x111ce, 0x111ce, 0x1122c, 0x1122e, 0x11232, 0x11233, - 0x11235, 0x11235, 0x112e0, 0x112e2, 0x11302, 0x11303, 0x1133f, 0x1133f, 0x11341, 0x11344, 0x11347, 0x11348, - 0x1134b, 0x1134d, + 0x1134b, 0x1134c, 0x11362, 0x11363, + 0x113b9, 0x113ba, + 0x113ca, 0x113ca, + 0x113cc, 0x113cd, 0x11435, 0x11437, 0x11440, 0x11441, 0x11445, 0x11445, @@ -38196,13 +40801,12 @@ static const OnigCodePoint CR_Grapheme_Cluster_Break_SpacingMark[] = { 0x1163e, 0x1163e, 0x116ac, 0x116ac, 0x116ae, 0x116af, - 0x116b6, 0x116b6, + 0x1171e, 0x1171e, 0x11726, 0x11726, 0x1182c, 0x1182e, 0x11838, 0x11838, 0x11931, 0x11935, 0x11937, 0x11938, - 0x1193d, 0x1193d, 0x11940, 0x11940, 0x11942, 0x11942, 0x119d1, 0x119d3, @@ -38223,11 +40827,8 @@ static const OnigCodePoint CR_Grapheme_Cluster_Break_SpacingMark[] = { 0x11f03, 0x11f03, 0x11f34, 0x11f35, 0x11f3e, 0x11f3f, - 0x11f41, 0x11f41, + 0x1612a, 0x1612c, 0x16f51, 0x16f87, - 0x16ff0, 0x16ff1, - 0x1d166, 0x1d166, - 0x1d16d, 0x1d16d, }; /* CR_Grapheme_Cluster_Break_SpacingMark */ /* 'Grapheme_Cluster_Break_L': Grapheme_Cluster_Break=L */ @@ -38239,9 +40840,11 @@ static const OnigCodePoint CR_Grapheme_Cluster_Break_L[] = { /* 'Grapheme_Cluster_Break_V': Grapheme_Cluster_Break=V */ static const OnigCodePoint CR_Grapheme_Cluster_Break_V[] = { - 2, + 4, 0x1160, 0x11a7, 0xd7b0, 0xd7c6, + 0x16d63, 0x16d63, + 0x16d67, 0x16d6a, }; /* CR_Grapheme_Cluster_Break_V */ /* 'Grapheme_Cluster_Break_T': Grapheme_Cluster_Break=T */ @@ -40160,6 +42763,12 @@ static const OnigCodePoint CR_In_Vithkuqi[] = { 0x10570, 0x105bf, }; /* CR_In_Vithkuqi */ +/* 'In_Todhri': Block */ +static const OnigCodePoint CR_In_Todhri[] = { + 1, + 0x105c0, 0x105ff, +}; /* CR_In_Todhri */ + /* 'In_Linear_A': Block */ static const OnigCodePoint CR_In_Linear_A[] = { 1, @@ -40280,6 +42889,12 @@ static const OnigCodePoint CR_In_Hanifi_Rohingya[] = { 0x10d00, 0x10d3f, }; /* CR_In_Hanifi_Rohingya */ +/* 'In_Garay': Block */ +static const OnigCodePoint CR_In_Garay[] = { + 1, + 0x10d40, 0x10d8f, +}; /* CR_In_Garay */ + /* 'In_Rumi_Numeral_Symbols': Block */ static const OnigCodePoint CR_In_Rumi_Numeral_Symbols[] = { 1, @@ -40391,6 +43006,12 @@ static const OnigCodePoint CR_In_Grantha[] = { 0x11300, 0x1137f, }; /* CR_In_Grantha */ +/* 'In_Tulu_Tigalari': Block */ +static const OnigCodePoint CR_In_Tulu_Tigalari[] = { + 1, + 0x11380, 0x113ff, +}; /* CR_In_Tulu_Tigalari */ + /* 'In_Newa': Block */ static const OnigCodePoint CR_In_Newa[] = { 1, @@ -40427,6 +43048,12 @@ static const OnigCodePoint CR_In_Takri[] = { 0x11680, 0x116cf, }; /* CR_In_Takri */ +/* 'In_Myanmar_Extended_C': Block */ +static const OnigCodePoint CR_In_Myanmar_Extended_C[] = { + 1, + 0x116d0, 0x116ff, +}; /* CR_In_Myanmar_Extended_C */ + /* 'In_Ahom': Block */ static const OnigCodePoint CR_In_Ahom[] = { 1, @@ -40487,6 +43114,12 @@ static const OnigCodePoint CR_In_Devanagari_Extended_A[] = { 0x11b00, 0x11b5f, }; /* CR_In_Devanagari_Extended_A */ +/* 'In_Sunuwar': Block */ +static const OnigCodePoint CR_In_Sunuwar[] = { + 1, + 0x11bc0, 0x11bff, +}; /* CR_In_Sunuwar */ + /* 'In_Bhaiksuki': Block */ static const OnigCodePoint CR_In_Bhaiksuki[] = { 1, @@ -40571,12 +43204,24 @@ static const OnigCodePoint CR_In_Egyptian_Hieroglyph_Format_Controls[] = { 0x13430, 0x1345f, }; /* CR_In_Egyptian_Hieroglyph_Format_Controls */ +/* 'In_Egyptian_Hieroglyphs_Extended_A': Block */ +static const OnigCodePoint CR_In_Egyptian_Hieroglyphs_Extended_A[] = { + 1, + 0x13460, 0x143ff, +}; /* CR_In_Egyptian_Hieroglyphs_Extended_A */ + /* 'In_Anatolian_Hieroglyphs': Block */ static const OnigCodePoint CR_In_Anatolian_Hieroglyphs[] = { 1, 0x14400, 0x1467f, }; /* CR_In_Anatolian_Hieroglyphs */ +/* 'In_Gurung_Khema': Block */ +static const OnigCodePoint CR_In_Gurung_Khema[] = { + 1, + 0x16100, 0x1613f, +}; /* CR_In_Gurung_Khema */ + /* 'In_Bamum_Supplement': Block */ static const OnigCodePoint CR_In_Bamum_Supplement[] = { 1, @@ -40607,6 +43252,12 @@ static const OnigCodePoint CR_In_Pahawh_Hmong[] = { 0x16b00, 0x16b8f, }; /* CR_In_Pahawh_Hmong */ +/* 'In_Kirat_Rai': Block */ +static const OnigCodePoint CR_In_Kirat_Rai[] = { + 1, + 0x16d40, 0x16d7f, +}; /* CR_In_Kirat_Rai */ + /* 'In_Medefaidrin': Block */ static const OnigCodePoint CR_In_Medefaidrin[] = { 1, @@ -40691,6 +43342,12 @@ static const OnigCodePoint CR_In_Shorthand_Format_Controls[] = { 0x1bca0, 0x1bcaf, }; /* CR_In_Shorthand_Format_Controls */ +/* 'In_Symbols_for_Legacy_Computing_Supplement': Block */ +static const OnigCodePoint CR_In_Symbols_for_Legacy_Computing_Supplement[] = { + 1, + 0x1cc00, 0x1cebf, +}; /* CR_In_Symbols_for_Legacy_Computing_Supplement */ + /* 'In_Znamenny_Musical_Notation': Block */ static const OnigCodePoint CR_In_Znamenny_Musical_Notation[] = { 1, @@ -40793,6 +43450,12 @@ static const OnigCodePoint CR_In_Nag_Mundari[] = { 0x1e4d0, 0x1e4ff, }; /* CR_In_Nag_Mundari */ +/* 'In_Ol_Onal': Block */ +static const OnigCodePoint CR_In_Ol_Onal[] = { + 1, + 0x1e5d0, 0x1e5ff, +}; /* CR_In_Ol_Onal */ + /* 'In_Ethiopic_Extended_B': Block */ static const OnigCodePoint CR_In_Ethiopic_Extended_B[] = { 1, @@ -40955,6 +43618,12 @@ static const OnigCodePoint CR_In_CJK_Unified_Ideographs_Extension_F[] = { 0x2ceb0, 0x2ebef, }; /* CR_In_CJK_Unified_Ideographs_Extension_F */ +/* 'In_CJK_Unified_Ideographs_Extension_I': Block */ +static const OnigCodePoint CR_In_CJK_Unified_Ideographs_Extension_I[] = { + 1, + 0x2ebf0, 0x2ee5f, +}; /* CR_In_CJK_Unified_Ideographs_Extension_I */ + /* 'In_CJK_Compatibility_Ideographs_Supplement': Block */ static const OnigCodePoint CR_In_CJK_Compatibility_Ideographs_Supplement[] = { 1, @@ -41003,34 +43672,33 @@ static const OnigCodePoint CR_In_No_Block[] = { 0x2fe0, 0x2fef, 0x10200, 0x1027f, 0x103e0, 0x103ff, - 0x105c0, 0x105ff, 0x107c0, 0x107ff, 0x108b0, 0x108df, 0x10940, 0x1097f, 0x10aa0, 0x10abf, 0x10bb0, 0x10bff, 0x10c50, 0x10c7f, - 0x10d40, 0x10e5f, + 0x10d90, 0x10e5f, 0x11250, 0x1127f, - 0x11380, 0x113ff, 0x114e0, 0x1157f, - 0x116d0, 0x116ff, 0x11750, 0x117ff, 0x11850, 0x1189f, 0x11960, 0x1199f, - 0x11b60, 0x11bff, + 0x11b60, 0x11bbf, 0x11cc0, 0x11cff, 0x11db0, 0x11edf, 0x11f60, 0x11faf, 0x12550, 0x12f8f, - 0x13460, 0x143ff, - 0x14680, 0x167ff, - 0x16b90, 0x16e3f, + 0x14680, 0x160ff, + 0x16140, 0x167ff, + 0x16b90, 0x16d3f, + 0x16d80, 0x16e3f, 0x16ea0, 0x16eff, 0x16fa0, 0x16fdf, 0x18d80, 0x1afef, 0x1b300, 0x1bbff, - 0x1bcb0, 0x1ceff, + 0x1bcb0, 0x1cbff, + 0x1cec0, 0x1ceff, 0x1cfd0, 0x1cfff, 0x1d250, 0x1d2bf, 0x1d380, 0x1d3ff, @@ -41038,7 +43706,8 @@ static const OnigCodePoint CR_In_No_Block[] = { 0x1e090, 0x1e0ff, 0x1e150, 0x1e28f, 0x1e300, 0x1e4cf, - 0x1e500, 0x1e7df, + 0x1e500, 0x1e5cf, + 0x1e600, 0x1e7df, 0x1e8e0, 0x1e8ff, 0x1e960, 0x1ec6f, 0x1ecc0, 0x1ecff, @@ -41046,7 +43715,7 @@ static const OnigCodePoint CR_In_No_Block[] = { 0x1ef00, 0x1efff, 0x1fc00, 0x1ffff, 0x2a6e0, 0x2a6ff, - 0x2ebf0, 0x2f7ff, + 0x2ee60, 0x2f7ff, 0x2fa20, 0x2ffff, 0x323b0, 0xdffff, 0xe0080, 0xe00ff, @@ -41131,6 +43800,9 @@ static const OnigCodePoint* const CodeRanges[] = { CR_Grapheme_Extend, CR_Grapheme_Base, CR_Grapheme_Link, + CR_InCB_Linker, + CR_InCB_Consonant, + CR_InCB_Extend, CR_Common, CR_Latin, CR_Greek, @@ -41294,6 +43966,13 @@ static const OnigCodePoint* const CodeRanges[] = { CR_Vithkuqi, CR_Kawi, CR_Nag_Mundari, + CR_Garay, + CR_Gurung_Khema, + CR_Kirat_Rai, + CR_Ol_Onal, + CR_Sunuwar, + CR_Todhri, + CR_Tulu_Tigalari, CR_White_Space, CR_Bidi_Control, CR_Join_Control, @@ -41314,6 +43993,7 @@ static const OnigCodePoint* const CodeRanges[] = { CR_Other_Grapheme_Extend, CR_IDS_Binary_Operator, CR_IDS_Trinary_Operator, + CR_IDS_Unary_Operator, CR_Radical, CR_Unified_Ideograph, CR_Other_Default_Ignorable_Code_Point, @@ -41322,12 +44002,15 @@ static const OnigCodePoint* const CodeRanges[] = { CR_Logical_Order_Exception, CR_Other_ID_Start, CR_Other_ID_Continue, + CR_ID_Compat_Math_Continue, + CR_ID_Compat_Math_Start, CR_Sentence_Terminal, CR_Variation_Selector, CR_Pattern_White_Space, CR_Pattern_Syntax, CR_Prepended_Concatenation_Mark, CR_Regional_Indicator, + CR_Modifier_Combining_Mark, CR_Emoji, CR_Emoji_Presentation, CR_Emoji_Modifier, @@ -41361,6 +44044,8 @@ static const OnigCodePoint* const CodeRanges[] = { CR_Age_13_0, CR_Age_14_0, CR_Age_15_0, + CR_Age_15_1, + CR_Age_16_0, #endif /* USE_UNICODE_AGE_PROPERTIES */ CR_Grapheme_Cluster_Break_Prepend, CR_Grapheme_Cluster_Break_CR, @@ -41560,6 +44245,7 @@ static const OnigCodePoint* const CodeRanges[] = { CR_In_Elbasan, CR_In_Caucasian_Albanian, CR_In_Vithkuqi, + CR_In_Todhri, CR_In_Linear_A, CR_In_Latin_Extended_F, CR_In_Cypriot_Syllabary, @@ -41582,6 +44268,7 @@ static const OnigCodePoint* const CodeRanges[] = { CR_In_Old_Turkic, CR_In_Old_Hungarian, CR_In_Hanifi_Rohingya, + CR_In_Garay, CR_In_Rumi_Numeral_Symbols, CR_In_Yezidi, CR_In_Arabic_Extended_C, @@ -41601,12 +44288,14 @@ static const OnigCodePoint* const CodeRanges[] = { CR_In_Multani, CR_In_Khudawadi, CR_In_Grantha, + CR_In_Tulu_Tigalari, CR_In_Newa, CR_In_Tirhuta, CR_In_Siddham, CR_In_Modi, CR_In_Mongolian_Supplement, CR_In_Takri, + CR_In_Myanmar_Extended_C, CR_In_Ahom, CR_In_Dogra, CR_In_Warang_Citi, @@ -41617,6 +44306,7 @@ static const OnigCodePoint* const CodeRanges[] = { CR_In_Unified_Canadian_Aboriginal_Syllabics_Extended_A, CR_In_Pau_Cin_Hau, CR_In_Devanagari_Extended_A, + CR_In_Sunuwar, CR_In_Bhaiksuki, CR_In_Marchen, CR_In_Masaram_Gondi, @@ -41631,12 +44321,15 @@ static const OnigCodePoint* const CodeRanges[] = { CR_In_Cypro_Minoan, CR_In_Egyptian_Hieroglyphs, CR_In_Egyptian_Hieroglyph_Format_Controls, + CR_In_Egyptian_Hieroglyphs_Extended_A, CR_In_Anatolian_Hieroglyphs, + CR_In_Gurung_Khema, CR_In_Bamum_Supplement, CR_In_Mro, CR_In_Tangsa, CR_In_Bassa_Vah, CR_In_Pahawh_Hmong, + CR_In_Kirat_Rai, CR_In_Medefaidrin, CR_In_Miao, CR_In_Ideographic_Symbols_and_Punctuation, @@ -41651,6 +44344,7 @@ static const OnigCodePoint* const CodeRanges[] = { CR_In_Nushu, CR_In_Duployan, CR_In_Shorthand_Format_Controls, + CR_In_Symbols_for_Legacy_Computing_Supplement, CR_In_Znamenny_Musical_Notation, CR_In_Byzantine_Musical_Symbols, CR_In_Musical_Symbols, @@ -41668,6 +44362,7 @@ static const OnigCodePoint* const CodeRanges[] = { CR_In_Toto, CR_In_Wancho, CR_In_Nag_Mundari, + CR_In_Ol_Onal, CR_In_Ethiopic_Extended_B, CR_In_Mende_Kikakui, CR_In_Adlam, @@ -41695,6 +44390,7 @@ static const OnigCodePoint* const CodeRanges[] = { CR_In_CJK_Unified_Ideographs_Extension_D, CR_In_CJK_Unified_Ideographs_Extension_E, CR_In_CJK_Unified_Ideographs_Extension_F, + CR_In_CJK_Unified_Ideographs_Extension_I, CR_In_CJK_Compatibility_Ideographs_Supplement, CR_In_CJK_Unified_Ideographs_Extension_G, CR_In_CJK_Unified_Ideographs_Extension_H, @@ -41722,15 +44418,15 @@ static const struct uniname2ctype_struct *uniname2ctype_p(register const char *s /* maximum key range = 15, duplicates = 0 */ #else /* USE_UNICODE_PROPERTIES */ #ifndef USE_UNICODE_AGE_PROPERTIES -#define TOTAL_KEYWORDS 866 +#define TOTAL_KEYWORDS 900 #else /* USE_UNICODE_AGE_PROPERTIES */ -#define TOTAL_KEYWORDS 891 +#define TOTAL_KEYWORDS 927 #endif /* USE_UNICODE_AGE_PROPERTIES */ #define MIN_WORD_LENGTH 1 #define MAX_WORD_LENGTH 45 -#define MIN_HASH_VALUE 11 -#define MAX_HASH_VALUE 6098 -/* maximum key range = 6088, duplicates = 0 */ +#define MIN_HASH_VALUE 12 +#define MAX_HASH_VALUE 6807 +/* maximum key range = 6796, duplicates = 0 */ #endif /* USE_UNICODE_PROPERTIES */ #ifdef __GNUC__ @@ -41764,24 +44460,24 @@ uniname2ctype_hash (register const char *str, register size_t len) 2, 1, 1, 21, 1, 7, 4, 6, 21, 1, 4, 21, 21, 21, 21, 21, 21, 21 #else /* USE_UNICODE_PROPERTIES */ - 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099, - 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099, - 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099, - 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099, + 6808, 6808, 6808, 6808, 6808, 6808, 6808, 6808, 6808, 6808, + 6808, 6808, 6808, 6808, 6808, 6808, 6808, 6808, 6808, 6808, + 6808, 6808, 6808, 6808, 6808, 6808, 6808, 6808, 6808, 6808, + 6808, 6808, 6808, 6808, 6808, 6808, 6808, 6808, 6808, 6808, #ifndef USE_UNICODE_AGE_PROPERTIES - 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099, - 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099, + 6808, 6808, 6808, 6808, 6808, 6808, 6808, 6808, 6808, 6808, + 6808, 6808, 6808, 6808, 6808, 6808, 6808, 6808, 6808, 6808, #else /* USE_UNICODE_AGE_PROPERTIES */ - 6099, 6099, 6099, 6099, 6099, 6099, 12, 6099, 3, 1, - 4, 8, 32, 26, 14, 17, 10, 7, 6099, 6099, + 6808, 6808, 6808, 6808, 6808, 6808, 7, 6808, 2, 1, + 4, 42, 27, 21, 6, 10, 9, 2, 6808, 6808, #endif /* USE_UNICODE_AGE_PROPERTIES */ - 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099, - 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099, - 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099, 6099, - 6099, 6099, 6099, 6099, 6099, 6099, 6099, 1, 1425, 113, - 437, 37, 1086, 1071, 1051, 4, 1984, 9, 500, 88, - 8, 18, 1371, 1287, 54, 203, 310, 619, 1958, 603, - 275, 1624, 44, 1, 22, 6099, 6099, 6099, 6099, 6099 + 6808, 1, 6808, 6808, 6808, 6808, 6808, 6808, 6808, 6808, + 6808, 6808, 6808, 6808, 6808, 6808, 6808, 6808, 6808, 6808, + 6808, 6808, 6808, 6808, 6808, 6808, 6808, 6808, 6808, 6808, + 6808, 6808, 6808, 6808, 6808, 6808, 6808, 1, 1475, 140, + 423, 30, 1736, 1065, 1241, 5, 907, 6, 795, 96, + 3, 10, 1388, 543, 48, 197, 370, 502, 1709, 2040, + 816, 2019, 52, 5, 12, 6808, 6808, 6808, 6808, 6808 #endif /* USE_UNICODE_PROPERTIES */ }; #ifndef USE_UNICODE_PROPERTIES @@ -41845,917 +44541,943 @@ struct uniname2ctype_pool_t char uniname2ctype_pool_str19[sizeof("digit")]; char uniname2ctype_pool_str20[sizeof("blank")]; #else /* USE_UNICODE_PROPERTIES */ - char uniname2ctype_pool_str11[sizeof("yi")]; - char uniname2ctype_pool_str17[sizeof("yiii")]; - char uniname2ctype_pool_str22[sizeof("lana")]; - char uniname2ctype_pool_str25[sizeof("lina")]; - char uniname2ctype_pool_str33[sizeof("maka")]; - char uniname2ctype_pool_str35[sizeof("mani")]; - char uniname2ctype_pool_str36[sizeof("mn")]; - char uniname2ctype_pool_str45[sizeof("miao")]; - char uniname2ctype_pool_str46[sizeof("lo")]; - char uniname2ctype_pool_str47[sizeof("ci")]; - char uniname2ctype_pool_str48[sizeof("lao")]; - char uniname2ctype_pool_str49[sizeof("laoo")]; - char uniname2ctype_pool_str52[sizeof("inkannada")]; - char uniname2ctype_pool_str55[sizeof("cn")]; - char uniname2ctype_pool_str64[sizeof("pi")]; - char uniname2ctype_pool_str66[sizeof("innko")]; - char uniname2ctype_pool_str67[sizeof("z")]; - char uniname2ctype_pool_str71[sizeof("gran")]; - char uniname2ctype_pool_str75[sizeof("co")]; - char uniname2ctype_pool_str83[sizeof("lineara")]; - char uniname2ctype_pool_str86[sizeof("mark")]; - char uniname2ctype_pool_str90[sizeof("yezi")]; - char uniname2ctype_pool_str92[sizeof("po")]; - char uniname2ctype_pool_str94[sizeof("me")]; - char uniname2ctype_pool_str100[sizeof("cari")]; - char uniname2ctype_pool_str101[sizeof("inkharoshthi")]; - char uniname2ctype_pool_str102[sizeof("kana")]; - char uniname2ctype_pool_str103[sizeof("loe")]; + char uniname2ctype_pool_str12[sizeof("lana")]; + char uniname2ctype_pool_str16[sizeof("lina")]; + char uniname2ctype_pool_str17[sizeof("yi")]; + char uniname2ctype_pool_str18[sizeof("mn")]; + char uniname2ctype_pool_str22[sizeof("maka")]; + char uniname2ctype_pool_str23[sizeof("mani")]; + char uniname2ctype_pool_str24[sizeof("yiii")]; + char uniname2ctype_pool_str25[sizeof("lo")]; + char uniname2ctype_pool_str27[sizeof("lao")]; + char uniname2ctype_pool_str28[sizeof("laoo")]; + char uniname2ctype_pool_str30[sizeof("miao")]; + char uniname2ctype_pool_str31[sizeof("inkannada")]; + char uniname2ctype_pool_str37[sizeof("innko")]; + char uniname2ctype_pool_str38[sizeof("cn")]; + char uniname2ctype_pool_str42[sizeof("ci")]; + char uniname2ctype_pool_str52[sizeof("co")]; + char uniname2ctype_pool_str59[sizeof("gara")]; + char uniname2ctype_pool_str60[sizeof("pi")]; + char uniname2ctype_pool_str61[sizeof("gran")]; + char uniname2ctype_pool_str65[sizeof("z")]; + char uniname2ctype_pool_str68[sizeof("lineara")]; + char uniname2ctype_pool_str69[sizeof("mark")]; + char uniname2ctype_pool_str70[sizeof("po")]; + char uniname2ctype_pool_str72[sizeof("me")]; + char uniname2ctype_pool_str76[sizeof("loe")]; + char uniname2ctype_pool_str79[sizeof("inkiratrai")]; + char uniname2ctype_pool_str81[sizeof("mro")]; + char uniname2ctype_pool_str82[sizeof("mroo")]; + char uniname2ctype_pool_str86[sizeof("inkharoshthi")]; + char uniname2ctype_pool_str88[sizeof("cari")]; + char uniname2ctype_pool_str92[sizeof("carian")]; + char uniname2ctype_pool_str93[sizeof("grek")]; + char uniname2ctype_pool_str96[sizeof("yezi")]; + char uniname2ctype_pool_str97[sizeof("geor")]; + char uniname2ctype_pool_str100[sizeof("greek")]; + char uniname2ctype_pool_str101[sizeof("mendekikakui")]; + char uniname2ctype_pool_str102[sizeof("mero")]; + char uniname2ctype_pool_str105[sizeof("kana")]; char uniname2ctype_pool_str107[sizeof("m")]; - char uniname2ctype_pool_str108[sizeof("grek")]; - char uniname2ctype_pool_str111[sizeof("mro")]; - char uniname2ctype_pool_str112[sizeof("mroo")]; - char uniname2ctype_pool_str115[sizeof("carian")]; - char uniname2ctype_pool_str117[sizeof("geor")]; - char uniname2ctype_pool_str118[sizeof("greek")]; - char uniname2ctype_pool_str122[sizeof("gonm")]; - char uniname2ctype_pool_str129[sizeof("mendekikakui")]; - char uniname2ctype_pool_str130[sizeof("pe")]; - char uniname2ctype_pool_str131[sizeof("mero")]; - char uniname2ctype_pool_str134[sizeof("inosmanya")]; - char uniname2ctype_pool_str139[sizeof("cakm")]; - char uniname2ctype_pool_str145[sizeof("inmanichaean")]; - char uniname2ctype_pool_str146[sizeof("inmro")]; - char uniname2ctype_pool_str148[sizeof("inmiao")]; - char uniname2ctype_pool_str149[sizeof("inchakma")]; - char uniname2ctype_pool_str151[sizeof("c")]; - char uniname2ctype_pool_str152[sizeof("mandaic")]; - char uniname2ctype_pool_str153[sizeof("meeteimayek")]; - char uniname2ctype_pool_str158[sizeof("zzzz")]; - char uniname2ctype_pool_str161[sizeof("inarmenian")]; - char uniname2ctype_pool_str177[sizeof("inmyanmar")]; - char uniname2ctype_pool_str178[sizeof("inmakasar")]; - char uniname2ctype_pool_str183[sizeof("common")]; - char uniname2ctype_pool_str186[sizeof("lm")]; - char uniname2ctype_pool_str190[sizeof("marc")]; - char uniname2ctype_pool_str203[sizeof("inrunic")]; - char uniname2ctype_pool_str204[sizeof("incarian")]; - char uniname2ctype_pool_str210[sizeof("inideographicsymbolsandpunctuation")]; - char uniname2ctype_pool_str212[sizeof("inkhmer")]; - char uniname2ctype_pool_str213[sizeof("qaai")]; + char uniname2ctype_pool_str110[sizeof("pe")]; + char uniname2ctype_pool_str118[sizeof("gonm")]; + char uniname2ctype_pool_str122[sizeof("meeteimayek")]; + char uniname2ctype_pool_str126[sizeof("inosmanya")]; + char uniname2ctype_pool_str130[sizeof("inmro")]; + char uniname2ctype_pool_str131[sizeof("inmanichaean")]; + char uniname2ctype_pool_str132[sizeof("inmiao")]; + char uniname2ctype_pool_str137[sizeof("cakm")]; + char uniname2ctype_pool_str149[sizeof("inarmenian")]; + char uniname2ctype_pool_str154[sizeof("krai")]; + char uniname2ctype_pool_str158[sizeof("common")]; + char uniname2ctype_pool_str165[sizeof("inchakma")]; + char uniname2ctype_pool_str166[sizeof("inmyanmar")]; + char uniname2ctype_pool_str167[sizeof("mandaic")]; + char uniname2ctype_pool_str169[sizeof("inmakasar")]; + char uniname2ctype_pool_str171[sizeof("c")]; + char uniname2ctype_pool_str172[sizeof("zzzz")]; + char uniname2ctype_pool_str192[sizeof("inideographicsymbolsandpunctuation")]; + char uniname2ctype_pool_str196[sizeof("inkhmer")]; + char uniname2ctype_pool_str197[sizeof("lm")]; + char uniname2ctype_pool_str203[sizeof("marc")]; + char uniname2ctype_pool_str208[sizeof("qaai")]; + char uniname2ctype_pool_str211[sizeof("combiningmark")]; + char uniname2ctype_pool_str212[sizeof("inrunic")]; + char uniname2ctype_pool_str213[sizeof("incarian")]; char uniname2ctype_pool_str218[sizeof("inahom")]; - char uniname2ctype_pool_str226[sizeof("merc")]; - char uniname2ctype_pool_str230[sizeof("inchorasmian")]; - char uniname2ctype_pool_str231[sizeof("combiningmark")]; - char uniname2ctype_pool_str236[sizeof("lc")]; - char uniname2ctype_pool_str237[sizeof("perm")]; - char uniname2ctype_pool_str246[sizeof("mc")]; - char uniname2ctype_pool_str250[sizeof("connectorpunctuation")]; - char uniname2ctype_pool_str253[sizeof("cans")]; - char uniname2ctype_pool_str260[sizeof("incuneiformnumbersandpunctuation")]; - char uniname2ctype_pool_str263[sizeof("armi")]; - char uniname2ctype_pool_str265[sizeof("cc")]; - char uniname2ctype_pool_str267[sizeof("armn")]; - char uniname2ctype_pool_str268[sizeof("incherokee")]; - char uniname2ctype_pool_str270[sizeof("prependedconcatenationmark")]; - char uniname2ctype_pool_str274[sizeof("incuneiform")]; - char uniname2ctype_pool_str275[sizeof("inavestan")]; - char uniname2ctype_pool_str281[sizeof("inipaextensions")]; - char uniname2ctype_pool_str282[sizeof("pc")]; - char uniname2ctype_pool_str283[sizeof("armenian")]; - char uniname2ctype_pool_str285[sizeof("insharada")]; - char uniname2ctype_pool_str287[sizeof("vai")]; - char uniname2ctype_pool_str288[sizeof("vaii")]; - char uniname2ctype_pool_str289[sizeof("inmarchen")]; - char uniname2ctype_pool_str293[sizeof("makasar")]; - char uniname2ctype_pool_str297[sizeof("masaramgondi")]; - char uniname2ctype_pool_str301[sizeof("inarrows")]; - char uniname2ctype_pool_str311[sizeof("incyrillic")]; - char uniname2ctype_pool_str313[sizeof("incham")]; - char uniname2ctype_pool_str315[sizeof("qmark")]; - char uniname2ctype_pool_str320[sizeof("ri")]; - char uniname2ctype_pool_str322[sizeof("qaac")]; - char uniname2ctype_pool_str328[sizeof("insamaritan")]; - char uniname2ctype_pool_str331[sizeof("latn")]; - char uniname2ctype_pool_str335[sizeof("inmasaramgondi")]; - char uniname2ctype_pool_str338[sizeof("inthaana")]; - char uniname2ctype_pool_str340[sizeof("latin")]; - char uniname2ctype_pool_str342[sizeof("inthai")]; - char uniname2ctype_pool_str345[sizeof("lineseparator")]; - char uniname2ctype_pool_str346[sizeof("pcm")]; - char uniname2ctype_pool_str348[sizeof("inkatakana")]; - char uniname2ctype_pool_str352[sizeof("inkaithi")]; - char uniname2ctype_pool_str362[sizeof("inscriptionalparthian")]; - char uniname2ctype_pool_str366[sizeof("initialpunctuation")]; - char uniname2ctype_pool_str373[sizeof("mtei")]; - char uniname2ctype_pool_str381[sizeof("inzanabazarsquare")]; - char uniname2ctype_pool_str386[sizeof("inkhmersymbols")]; - char uniname2ctype_pool_str399[sizeof("insyriac")]; - char uniname2ctype_pool_str401[sizeof("intakri")]; - char uniname2ctype_pool_str404[sizeof("arabic")]; - char uniname2ctype_pool_str418[sizeof("katakana")]; - char uniname2ctype_pool_str426[sizeof("prti")]; - char uniname2ctype_pool_str430[sizeof("zs")]; - char uniname2ctype_pool_str442[sizeof("ascii")]; - char uniname2ctype_pool_str445[sizeof("cs")]; - char uniname2ctype_pool_str462[sizeof("ps")]; - char uniname2ctype_pool_str468[sizeof("mand")]; - char uniname2ctype_pool_str470[sizeof("privateuse")]; - char uniname2ctype_pool_str475[sizeof("inruminumeralsymbols")]; - char uniname2ctype_pool_str480[sizeof("inmyanmarextendeda")]; - char uniname2ctype_pool_str481[sizeof("modi")]; - char uniname2ctype_pool_str486[sizeof("incjkcompatibilityforms")]; - char uniname2ctype_pool_str488[sizeof("inkanaextendeda")]; - char uniname2ctype_pool_str491[sizeof("incjkcompatibilityideographs")]; - char uniname2ctype_pool_str500[sizeof("brai")]; - char uniname2ctype_pool_str504[sizeof("mend")]; - char uniname2ctype_pool_str505[sizeof("ideo")]; - char uniname2ctype_pool_str506[sizeof("letter")]; - char uniname2ctype_pool_str509[sizeof("l")]; - char uniname2ctype_pool_str511[sizeof("inmeeteimayek")]; - char uniname2ctype_pool_str520[sizeof("inideographicdescriptioncharacters")]; - char uniname2ctype_pool_str533[sizeof("yezidi")]; - char uniname2ctype_pool_str538[sizeof("knda")]; - char uniname2ctype_pool_str541[sizeof("innandinagari")]; - char uniname2ctype_pool_str543[sizeof("kannada")]; - char uniname2ctype_pool_str556[sizeof("inmodi")]; - char uniname2ctype_pool_str558[sizeof("inlao")]; - char uniname2ctype_pool_str559[sizeof("xidcontinue")]; - char uniname2ctype_pool_str560[sizeof("inoldnortharabian")]; - char uniname2ctype_pool_str565[sizeof("intransportandmapsymbols")]; - char uniname2ctype_pool_str566[sizeof("letternumber")]; - char uniname2ctype_pool_str568[sizeof("gothic")]; - char uniname2ctype_pool_str572[sizeof("inlineara")]; - char uniname2ctype_pool_str577[sizeof("inmendekikakui")]; - char uniname2ctype_pool_str579[sizeof("mongolian")]; - char uniname2ctype_pool_str582[sizeof("inmiscellaneousmathematicalsymbolsa")]; + char uniname2ctype_pool_str224[sizeof("prependedconcatenationmark")]; + char uniname2ctype_pool_str225[sizeof("inchorasmian")]; + char uniname2ctype_pool_str226[sizeof("perm")]; + char uniname2ctype_pool_str232[sizeof("merc")]; + char uniname2ctype_pool_str235[sizeof("cans")]; + char uniname2ctype_pool_str240[sizeof("connectorpunctuation")]; + char uniname2ctype_pool_str249[sizeof("inavestan")]; + char uniname2ctype_pool_str250[sizeof("incuneiformnumbersandpunctuation")]; + char uniname2ctype_pool_str262[sizeof("inipaextensions")]; + char uniname2ctype_pool_str265[sizeof("insharada")]; + char uniname2ctype_pool_str267[sizeof("incherokee")]; + char uniname2ctype_pool_str270[sizeof("makasar")]; + char uniname2ctype_pool_str273[sizeof("inarrows")]; + char uniname2ctype_pool_str279[sizeof("masaramgondi")]; + char uniname2ctype_pool_str285[sizeof("lc")]; + char uniname2ctype_pool_str289[sizeof("incuneiform")]; + char uniname2ctype_pool_str291[sizeof("armn")]; + char uniname2ctype_pool_str292[sizeof("mc")]; + char uniname2ctype_pool_str293[sizeof("armi")]; + char uniname2ctype_pool_str303[sizeof("armenian")]; + char uniname2ctype_pool_str305[sizeof("inmarchen")]; + char uniname2ctype_pool_str309[sizeof("lineseparator")]; + char uniname2ctype_pool_str311[sizeof("qmark")]; + char uniname2ctype_pool_str312[sizeof("cc")]; + char uniname2ctype_pool_str317[sizeof("insamaritan")]; + char uniname2ctype_pool_str325[sizeof("inmasaramgondi")]; + char uniname2ctype_pool_str330[sizeof("pc")]; + char uniname2ctype_pool_str332[sizeof("inscriptionalparthian")]; + char uniname2ctype_pool_str343[sizeof("qaac")]; + char uniname2ctype_pool_str345[sizeof("mcm")]; + char uniname2ctype_pool_str348[sizeof("incham")]; + char uniname2ctype_pool_str352[sizeof("incyrillic")]; + char uniname2ctype_pool_str357[sizeof("inzanabazarsquare")]; + char uniname2ctype_pool_str362[sizeof("inkhmersymbols")]; + char uniname2ctype_pool_str381[sizeof("latn")]; + char uniname2ctype_pool_str382[sizeof("ri")]; + char uniname2ctype_pool_str383[sizeof("pcm")]; + char uniname2ctype_pool_str385[sizeof("latin")]; + char uniname2ctype_pool_str390[sizeof("inthaana")]; + char uniname2ctype_pool_str396[sizeof("inthai")]; + char uniname2ctype_pool_str397[sizeof("inkatakana")]; + char uniname2ctype_pool_str403[sizeof("inkaithi")]; + char uniname2ctype_pool_str407[sizeof("insyriac")]; + char uniname2ctype_pool_str408[sizeof("zs")]; + char uniname2ctype_pool_str416[sizeof("initialpunctuation")]; + char uniname2ctype_pool_str419[sizeof("mtei")]; + char uniname2ctype_pool_str426[sizeof("cs")]; + char uniname2ctype_pool_str441[sizeof("mand")]; + char uniname2ctype_pool_str444[sizeof("ps")]; + char uniname2ctype_pool_str445[sizeof("intakri")]; + char uniname2ctype_pool_str452[sizeof("modi")]; + char uniname2ctype_pool_str458[sizeof("inkanaextendeda")]; + char uniname2ctype_pool_str470[sizeof("mend")]; + char uniname2ctype_pool_str472[sizeof("inruminumeralsymbols")]; + char uniname2ctype_pool_str473[sizeof("ideo")]; + char uniname2ctype_pool_str475[sizeof("prti")]; + char uniname2ctype_pool_str480[sizeof("arabic")]; + char uniname2ctype_pool_str481[sizeof("brai")]; + char uniname2ctype_pool_str483[sizeof("katakana")]; + char uniname2ctype_pool_str487[sizeof("inideographicdescriptioncharacters")]; + char uniname2ctype_pool_str492[sizeof("ascii")]; + char uniname2ctype_pool_str504[sizeof("innandinagari")]; + char uniname2ctype_pool_str512[sizeof("privateuse")]; + char uniname2ctype_pool_str514[sizeof("inoldnortharabian")]; + char uniname2ctype_pool_str516[sizeof("sk")]; + char uniname2ctype_pool_str524[sizeof("so")]; + char uniname2ctype_pool_str525[sizeof("incjkcompatibilityforms")]; + char uniname2ctype_pool_str526[sizeof("yezidi")]; + char uniname2ctype_pool_str527[sizeof("knda")]; + char uniname2ctype_pool_str528[sizeof("inmyanmarextendeda")]; + char uniname2ctype_pool_str530[sizeof("incjkcompatibilityideographs")]; + char uniname2ctype_pool_str532[sizeof("kannada")]; + char uniname2ctype_pool_str534[sizeof("xidcontinue")]; + char uniname2ctype_pool_str535[sizeof("letter")]; + char uniname2ctype_pool_str544[sizeof("inmodi")]; + char uniname2ctype_pool_str554[sizeof("inmeeteimayek")]; + char uniname2ctype_pool_str556[sizeof("inmendekikakui")]; + char uniname2ctype_pool_str561[sizeof("onao")]; + char uniname2ctype_pool_str565[sizeof("sora")]; + char uniname2ctype_pool_str579[sizeof("inmedefaidrin")]; + char uniname2ctype_pool_str580[sizeof("kiratrai")]; char uniname2ctype_pool_str583[sizeof("inspecials")]; - char uniname2ctype_pool_str590[sizeof("grlink")]; - char uniname2ctype_pool_str594[sizeof("brahmi")]; - char uniname2ctype_pool_str596[sizeof("inemoticons")]; - char uniname2ctype_pool_str597[sizeof("kali")]; - char uniname2ctype_pool_str600[sizeof("inolditalic")]; - char uniname2ctype_pool_str602[sizeof("xidc")]; - char uniname2ctype_pool_str604[sizeof("inmedefaidrin")]; - char uniname2ctype_pool_str605[sizeof("inchesssymbols")]; - char uniname2ctype_pool_str608[sizeof("incjkcompatibilityideographssupplement")]; - char uniname2ctype_pool_str609[sizeof("kits")]; - char uniname2ctype_pool_str614[sizeof("inadlam")]; - char uniname2ctype_pool_str624[sizeof("psalterpahlavi")]; - char uniname2ctype_pool_str625[sizeof("incommonindicnumberforms")]; - char uniname2ctype_pool_str630[sizeof("lt")]; - char uniname2ctype_pool_str636[sizeof("innewa")]; - char uniname2ctype_pool_str639[sizeof("sk")]; - char uniname2ctype_pool_str642[sizeof("control")]; - char uniname2ctype_pool_str643[sizeof("inkawi")]; - char uniname2ctype_pool_str645[sizeof("inancientsymbols")]; - char uniname2ctype_pool_str647[sizeof("palm")]; - char uniname2ctype_pool_str650[sizeof("inlycian")]; - char uniname2ctype_pool_str657[sizeof("so")]; - char uniname2ctype_pool_str660[sizeof("patternwhitespace")]; - char uniname2ctype_pool_str672[sizeof("inmandaic")]; - char uniname2ctype_pool_str675[sizeof("idc")]; - char uniname2ctype_pool_str678[sizeof("meroiticcursive")]; - char uniname2ctype_pool_str679[sizeof("intoto")]; - char uniname2ctype_pool_str683[sizeof("vs")]; - char uniname2ctype_pool_str692[sizeof("xids")]; - char uniname2ctype_pool_str695[sizeof("inwarangciti")]; - char uniname2ctype_pool_str696[sizeof("sora")]; - char uniname2ctype_pool_str697[sizeof("inopticalcharacterrecognition")]; - char uniname2ctype_pool_str700[sizeof("kawi")]; - char uniname2ctype_pool_str703[sizeof("inoldsogdian")]; - char uniname2ctype_pool_str705[sizeof("inmalayalam")]; - char uniname2ctype_pool_str707[sizeof("bamum")]; - char uniname2ctype_pool_str708[sizeof("inkanasupplement")]; - char uniname2ctype_pool_str713[sizeof("insundanese")]; - char uniname2ctype_pool_str720[sizeof("grext")]; - char uniname2ctype_pool_str737[sizeof("print")]; - char uniname2ctype_pool_str738[sizeof("intaitham")]; - char uniname2ctype_pool_str742[sizeof("lower")]; - char uniname2ctype_pool_str745[sizeof("patternsyntax")]; - char uniname2ctype_pool_str753[sizeof("joinc")]; - char uniname2ctype_pool_str755[sizeof("inoldsoutharabian")]; - char uniname2ctype_pool_str760[sizeof("incjkstrokes")]; - char uniname2ctype_pool_str761[sizeof("batk")]; - char uniname2ctype_pool_str766[sizeof("samr")]; - char uniname2ctype_pool_str767[sizeof("inwancho")]; - char uniname2ctype_pool_str771[sizeof("batak")]; - char uniname2ctype_pool_str776[sizeof("patws")]; - char uniname2ctype_pool_str783[sizeof("samaritan")]; - char uniname2ctype_pool_str787[sizeof("idsbinaryoperator")]; - char uniname2ctype_pool_str791[sizeof("pauc")]; - char uniname2ctype_pool_str794[sizeof("insmallkanaextension")]; - char uniname2ctype_pool_str797[sizeof("sm")]; - char uniname2ctype_pool_str799[sizeof("indominotiles")]; - char uniname2ctype_pool_str802[sizeof("alnum")]; - char uniname2ctype_pool_str803[sizeof("inznamennymusicalnotation")]; - char uniname2ctype_pool_str809[sizeof("insylotinagri")]; - char uniname2ctype_pool_str814[sizeof("inugaritic")]; - char uniname2ctype_pool_str818[sizeof("incontrolpictures")]; - char uniname2ctype_pool_str821[sizeof("inlinearbideograms")]; - char uniname2ctype_pool_str822[sizeof("inmusicalsymbols")]; - char uniname2ctype_pool_str823[sizeof("s")]; - char uniname2ctype_pool_str824[sizeof("ital")]; - char uniname2ctype_pool_str825[sizeof("inmodifiertoneletters")]; - char uniname2ctype_pool_str828[sizeof("inancientgreekmusicalnotation")]; - char uniname2ctype_pool_str838[sizeof("lisu")]; - char uniname2ctype_pool_str842[sizeof("lowercase")]; - char uniname2ctype_pool_str845[sizeof("cwcm")]; - char uniname2ctype_pool_str847[sizeof("sc")]; - char uniname2ctype_pool_str848[sizeof("bass")]; - char uniname2ctype_pool_str855[sizeof("ids")]; - char uniname2ctype_pool_str857[sizeof("inlatinextendeda")]; - char uniname2ctype_pool_str875[sizeof("intaile")]; - char uniname2ctype_pool_str886[sizeof("inmiscellaneoussymbols")]; - char uniname2ctype_pool_str895[sizeof("inmiscellaneoussymbolsandarrows")]; - char uniname2ctype_pool_str898[sizeof("incaucasianalbanian")]; - char uniname2ctype_pool_str900[sizeof("inmiscellaneoussymbolsandpictographs")]; - char uniname2ctype_pool_str906[sizeof("inoldturkic")]; - char uniname2ctype_pool_str907[sizeof("insaurashtra")]; - char uniname2ctype_pool_str920[sizeof("incyrillicextendeda")]; - char uniname2ctype_pool_str924[sizeof("idcontinue")]; - char uniname2ctype_pool_str925[sizeof("intaixuanjingsymbols")]; - char uniname2ctype_pool_str926[sizeof("intamil")]; - char uniname2ctype_pool_str928[sizeof("inmultani")]; - char uniname2ctype_pool_str929[sizeof("inlatinextendede")]; - char uniname2ctype_pool_str930[sizeof("pd")]; - char uniname2ctype_pool_str946[sizeof("bali")]; - char uniname2ctype_pool_str961[sizeof("blank")]; - char uniname2ctype_pool_str963[sizeof("idst")]; - char uniname2ctype_pool_str974[sizeof("inlydian")]; - char uniname2ctype_pool_str986[sizeof("innewtailue")]; - char uniname2ctype_pool_str994[sizeof("bengali")]; - char uniname2ctype_pool_str995[sizeof("runr")]; - char uniname2ctype_pool_str1010[sizeof("ll")]; - char uniname2ctype_pool_str1013[sizeof("indeseret")]; - char uniname2ctype_pool_str1015[sizeof("inancientgreeknumbers")]; - char uniname2ctype_pool_str1021[sizeof("idstart")]; - char uniname2ctype_pool_str1024[sizeof("zl")]; - char uniname2ctype_pool_str1025[sizeof("inmeeteimayekextensions")]; - char uniname2ctype_pool_str1028[sizeof("balinese")]; - char uniname2ctype_pool_str1032[sizeof("incyrillicextendedc")]; - char uniname2ctype_pool_str1035[sizeof("inspacingmodifierletters")]; - char uniname2ctype_pool_str1036[sizeof("inearlydynasticcuneiform")]; - char uniname2ctype_pool_str1049[sizeof("plrd")]; - char uniname2ctype_pool_str1067[sizeof("canadianaboriginal")]; - char uniname2ctype_pool_str1072[sizeof("sind")]; - char uniname2ctype_pool_str1081[sizeof("inlatinextendedc")]; - char uniname2ctype_pool_str1085[sizeof("uideo")]; - char uniname2ctype_pool_str1087[sizeof("incountingrodnumerals")]; - char uniname2ctype_pool_str1089[sizeof("zinh")]; - char uniname2ctype_pool_str1095[sizeof("dia")]; - char uniname2ctype_pool_str1096[sizeof("di")]; - char uniname2ctype_pool_str1097[sizeof("inkhudawadi")]; - char uniname2ctype_pool_str1102[sizeof("inhanifirohingya")]; - char uniname2ctype_pool_str1104[sizeof("diak")]; - char uniname2ctype_pool_str1105[sizeof("gong")]; - char uniname2ctype_pool_str1107[sizeof("ingrantha")]; - char uniname2ctype_pool_str1109[sizeof("bidic")]; - char uniname2ctype_pool_str1114[sizeof("xidstart")]; - char uniname2ctype_pool_str1115[sizeof("xdigit")]; - char uniname2ctype_pool_str1119[sizeof("mong")]; - char uniname2ctype_pool_str1120[sizeof("cased")]; - char uniname2ctype_pool_str1134[sizeof("inhiragana")]; - char uniname2ctype_pool_str1140[sizeof("sinhala")]; - char uniname2ctype_pool_str1142[sizeof("adlm")]; - char uniname2ctype_pool_str1145[sizeof("xsux")]; - char uniname2ctype_pool_str1146[sizeof("glagolitic")]; - char uniname2ctype_pool_str1147[sizeof("sterm")]; - char uniname2ctype_pool_str1149[sizeof("bamu")]; - char uniname2ctype_pool_str1150[sizeof("georgian")]; - char uniname2ctype_pool_str1151[sizeof("inosage")]; - char uniname2ctype_pool_str1152[sizeof("gunjalagondi")]; - char uniname2ctype_pool_str1153[sizeof("phoenician")]; - char uniname2ctype_pool_str1156[sizeof("inolduyghur")]; - char uniname2ctype_pool_str1157[sizeof("multani")]; - char uniname2ctype_pool_str1158[sizeof("kaithi")]; - char uniname2ctype_pool_str1164[sizeof("joincontrol")]; - char uniname2ctype_pool_str1168[sizeof("runic")]; - char uniname2ctype_pool_str1170[sizeof("ingeneralpunctuation")]; - char uniname2ctype_pool_str1171[sizeof("inmahajani")]; - char uniname2ctype_pool_str1174[sizeof("incyrillicsupplement")]; - char uniname2ctype_pool_str1175[sizeof("lowercaseletter")]; - char uniname2ctype_pool_str1176[sizeof("marchen")]; - char uniname2ctype_pool_str1177[sizeof("graphemelink")]; - char uniname2ctype_pool_str1178[sizeof("ingeorgian")]; - char uniname2ctype_pool_str1180[sizeof("khojki")]; - char uniname2ctype_pool_str1181[sizeof("cham")]; - char uniname2ctype_pool_str1182[sizeof("inogham")]; - char uniname2ctype_pool_str1183[sizeof("cher")]; - char uniname2ctype_pool_str1185[sizeof("chakma")]; - char uniname2ctype_pool_str1186[sizeof("inkaktoviknumerals")]; - char uniname2ctype_pool_str1190[sizeof("emoji")]; - char uniname2ctype_pool_str1191[sizeof("insiddham")]; - char uniname2ctype_pool_str1197[sizeof("cherokee")]; - char uniname2ctype_pool_str1198[sizeof("khar")]; - char uniname2ctype_pool_str1203[sizeof("inmongolian")]; - char uniname2ctype_pool_str1204[sizeof("innagmundari")]; - char uniname2ctype_pool_str1207[sizeof("incherokeesupplement")]; - char uniname2ctype_pool_str1209[sizeof("manichaean")]; - char uniname2ctype_pool_str1212[sizeof("inolchiki")]; - char uniname2ctype_pool_str1223[sizeof("inkhitansmallscript")]; - char uniname2ctype_pool_str1227[sizeof("quotationmark")]; - char uniname2ctype_pool_str1229[sizeof("vithkuqi")]; - char uniname2ctype_pool_str1230[sizeof("variationselector")]; - char uniname2ctype_pool_str1231[sizeof("adlam")]; - char uniname2ctype_pool_str1232[sizeof("inethiopic")]; - char uniname2ctype_pool_str1233[sizeof("graphemebase")]; -#ifdef USE_UNICODE_AGE_PROPERTIES - char uniname2ctype_pool_str1234[sizeof("age=11.0")]; - char uniname2ctype_pool_str1235[sizeof("age=12.1")]; - char uniname2ctype_pool_str1236[sizeof("age=10.0")]; - char uniname2ctype_pool_str1237[sizeof("age=12.0")]; - char uniname2ctype_pool_str1241[sizeof("age=13.0")]; - char uniname2ctype_pool_str1242[sizeof("age=1.1")]; -#endif /* USE_UNICODE_AGE_PROPERTIES */ - char uniname2ctype_pool_str1243[sizeof("casedletter")]; - char uniname2ctype_pool_str1244[sizeof("ingurmukhi")]; -#ifdef USE_UNICODE_AGE_PROPERTIES - char uniname2ctype_pool_str1245[sizeof("age=2.1")]; -#endif /* USE_UNICODE_AGE_PROPERTIES */ - char uniname2ctype_pool_str1246[sizeof("incjkunifiedideographsextensiona")]; -#ifdef USE_UNICODE_AGE_PROPERTIES - char uniname2ctype_pool_str1247[sizeof("age=2.0")]; -#endif /* USE_UNICODE_AGE_PROPERTIES */ - char uniname2ctype_pool_str1248[sizeof("lu")]; -#ifdef USE_UNICODE_AGE_PROPERTIES - char uniname2ctype_pool_str1249[sizeof("age=3.1")]; - char uniname2ctype_pool_str1250[sizeof("age=9.0")]; - char uniname2ctype_pool_str1251[sizeof("age=3.0")]; - char uniname2ctype_pool_str1252[sizeof("age=3.2")]; - char uniname2ctype_pool_str1253[sizeof("age=8.0")]; -#endif /* USE_UNICODE_AGE_PROPERTIES */ - char uniname2ctype_pool_str1254[sizeof("intamilsupplement")]; -#ifdef USE_UNICODE_AGE_PROPERTIES - char uniname2ctype_pool_str1255[sizeof("age=6.1")]; -#endif /* USE_UNICODE_AGE_PROPERTIES */ - char uniname2ctype_pool_str1256[sizeof("unknown")]; + char uniname2ctype_pool_str584[sizeof("brahmi")]; + char uniname2ctype_pool_str589[sizeof("letternumber")]; + char uniname2ctype_pool_str597[sizeof("inchesssymbols")]; + char uniname2ctype_pool_str598[sizeof("inolditalic")]; + char uniname2ctype_pool_str603[sizeof("oriya")]; + char uniname2ctype_pool_str604[sizeof("inmiscellaneousmathematicalsymbolsa")]; + char uniname2ctype_pool_str606[sizeof("intransportandmapsymbols")]; + char uniname2ctype_pool_str614[sizeof("incb=extend")]; + char uniname2ctype_pool_str624[sizeof("xidc")]; + char uniname2ctype_pool_str627[sizeof("inemoticons")]; + char uniname2ctype_pool_str651[sizeof("samr")]; + char uniname2ctype_pool_str657[sizeof("inoldsogdian")]; + char uniname2ctype_pool_str661[sizeof("inancientsymbols")]; + char uniname2ctype_pool_str663[sizeof("incommonindicnumberforms")]; + char uniname2ctype_pool_str664[sizeof("samaritan")]; + char uniname2ctype_pool_str666[sizeof("psalterpahlavi")]; + char uniname2ctype_pool_str667[sizeof("inmyanmarextendedc")]; + char uniname2ctype_pool_str672[sizeof("kits")]; + char uniname2ctype_pool_str673[sizeof("insundanese")]; + char uniname2ctype_pool_str675[sizeof("incb=consonant")]; + char uniname2ctype_pool_str676[sizeof("gothic")]; + char uniname2ctype_pool_str680[sizeof("inmandaic")]; + char uniname2ctype_pool_str681[sizeof("xids")]; + char uniname2ctype_pool_str689[sizeof("inznamennymusicalnotation")]; + char uniname2ctype_pool_str695[sizeof("pauc")]; + char uniname2ctype_pool_str696[sizeof("sm")]; + char uniname2ctype_pool_str700[sizeof("s")]; + char uniname2ctype_pool_str705[sizeof("meroiticcursive")]; + char uniname2ctype_pool_str708[sizeof("inoldsoutharabian")]; + char uniname2ctype_pool_str710[sizeof("inugaritic")]; + char uniname2ctype_pool_str711[sizeof("lisu")]; + char uniname2ctype_pool_str712[sizeof("idc")]; + char uniname2ctype_pool_str713[sizeof("incjkcompatibilityideographssupplement")]; + char uniname2ctype_pool_str714[sizeof("patternwhitespace")]; + char uniname2ctype_pool_str717[sizeof("bamum")]; + char uniname2ctype_pool_str719[sizeof("inancientgreekmusicalnotation")]; + char uniname2ctype_pool_str739[sizeof("idsbinaryoperator")]; + char uniname2ctype_pool_str745[sizeof("lt")]; + char uniname2ctype_pool_str758[sizeof("incjkstrokes")]; + char uniname2ctype_pool_str768[sizeof("insunuwar")]; + char uniname2ctype_pool_str770[sizeof("insaurashtra")]; + char uniname2ctype_pool_str773[sizeof("indominotiles")]; + char uniname2ctype_pool_str775[sizeof("intoto")]; + char uniname2ctype_pool_str784[sizeof("sc")]; + char uniname2ctype_pool_str790[sizeof("idsunaryoperator")]; + char uniname2ctype_pool_str791[sizeof("inmodifiertoneletters")]; + char uniname2ctype_pool_str797[sizeof("inopticalcharacterrecognition")]; + char uniname2ctype_pool_str799[sizeof("l")]; + char uniname2ctype_pool_str804[sizeof("batk")]; + char uniname2ctype_pool_str805[sizeof("inkanasupplement")]; + char uniname2ctype_pool_str806[sizeof("osage")]; + char uniname2ctype_pool_str811[sizeof("batak")]; + char uniname2ctype_pool_str813[sizeof("inmusicalsymbols")]; + char uniname2ctype_pool_str817[sizeof("incaucasianalbanian")]; + char uniname2ctype_pool_str818[sizeof("patws")]; + char uniname2ctype_pool_str822[sizeof("bass")]; + char uniname2ctype_pool_str826[sizeof("ids")]; + char uniname2ctype_pool_str828[sizeof("grext")]; + char uniname2ctype_pool_str829[sizeof("inlao")]; + char uniname2ctype_pool_str830[sizeof("vai")]; + char uniname2ctype_pool_str831[sizeof("vaii")]; + char uniname2ctype_pool_str835[sizeof("inolonal")]; + char uniname2ctype_pool_str840[sizeof("mongolian")]; + char uniname2ctype_pool_str841[sizeof("osma")]; + char uniname2ctype_pool_str846[sizeof("print")]; + char uniname2ctype_pool_str847[sizeof("inlineara")]; + char uniname2ctype_pool_str859[sizeof("intaitham")]; + char uniname2ctype_pool_str869[sizeof("grlink")]; + char uniname2ctype_pool_str888[sizeof("inmiscellaneoussymbols")]; + char uniname2ctype_pool_str896[sizeof("pd")]; + char uniname2ctype_pool_str897[sizeof("inmiscellaneoussymbolsandarrows")]; + char uniname2ctype_pool_str901[sizeof("kali")]; + char uniname2ctype_pool_str902[sizeof("inmiscellaneoussymbolsandpictographs")]; + char uniname2ctype_pool_str903[sizeof("control")]; + char uniname2ctype_pool_str905[sizeof("inancientgreeknumbers")]; + char uniname2ctype_pool_str906[sizeof("incontrolpictures")]; + char uniname2ctype_pool_str909[sizeof("inadlam")]; + char uniname2ctype_pool_str917[sizeof("han")]; + char uniname2ctype_pool_str920[sizeof("hani")]; + char uniname2ctype_pool_str925[sizeof("hano")]; + char uniname2ctype_pool_str927[sizeof("runr")]; + char uniname2ctype_pool_str937[sizeof("sind")]; + char uniname2ctype_pool_str941[sizeof("hanunoo")]; + char uniname2ctype_pool_str944[sizeof("palm")]; + char uniname2ctype_pool_str945[sizeof("inkhojki")]; + char uniname2ctype_pool_str956[sizeof("inkhudawadi")]; + char uniname2ctype_pool_str960[sizeof("inlycian")]; + char uniname2ctype_pool_str963[sizeof("inoldturkic")]; + char uniname2ctype_pool_str965[sizeof("hira")]; + char uniname2ctype_pool_str978[sizeof("incountingrodnumerals")]; + char uniname2ctype_pool_str979[sizeof("odi")]; + char uniname2ctype_pool_str982[sizeof("idcontinue")]; + char uniname2ctype_pool_str1000[sizeof("idst")]; + char uniname2ctype_pool_str1003[sizeof("inolduyghur")]; + char uniname2ctype_pool_str1004[sizeof("incb=linker")]; + char uniname2ctype_pool_str1008[sizeof("inmalayalam")]; + char uniname2ctype_pool_str1009[sizeof("lu")]; + char uniname2ctype_pool_str1021[sizeof("inspacingmodifierletters")]; + char uniname2ctype_pool_str1026[sizeof("bamu")]; + char uniname2ctype_pool_str1038[sizeof("indeseret")]; + char uniname2ctype_pool_str1050[sizeof("sundanese")]; + char uniname2ctype_pool_str1052[sizeof("idstart")]; + char uniname2ctype_pool_str1057[sizeof("saur")]; + char uniname2ctype_pool_str1058[sizeof("insmallkanaextension")]; + char uniname2ctype_pool_str1061[sizeof("guru")]; + char uniname2ctype_pool_str1070[sizeof("paucinhau")]; + char uniname2ctype_pool_str1076[sizeof("gurmukhi")]; + char uniname2ctype_pool_str1077[sizeof("insylotinagri")]; + char uniname2ctype_pool_str1079[sizeof("cased")]; + char uniname2ctype_pool_str1083[sizeof("inlinearbideograms")]; + char uniname2ctype_pool_str1087[sizeof("gong")]; + char uniname2ctype_pool_str1088[sizeof("ingrantha")]; + char uniname2ctype_pool_str1092[sizeof("mong")]; + char uniname2ctype_pool_str1095[sizeof("joinc")]; + char uniname2ctype_pool_str1099[sizeof("sterm")]; + char uniname2ctype_pool_str1109[sizeof("inkaktoviknumerals")]; + char uniname2ctype_pool_str1113[sizeof("limbu")]; + char uniname2ctype_pool_str1115[sizeof("oidc")]; + char uniname2ctype_pool_str1122[sizeof("inosage")]; + char uniname2ctype_pool_str1123[sizeof("incjkunifiedideographsextensiona")]; + char uniname2ctype_pool_str1124[sizeof("incyrillicsupplement")]; + char uniname2ctype_pool_str1125[sizeof("inmeeteimayekextensions")]; + char uniname2ctype_pool_str1126[sizeof("georgian")]; + char uniname2ctype_pool_str1127[sizeof("incjkunifiedideographsextensioni")]; + char uniname2ctype_pool_str1132[sizeof("idsu")]; + char uniname2ctype_pool_str1134[sizeof("ingeneralpunctuation")]; + char uniname2ctype_pool_str1135[sizeof("alnum")]; + char uniname2ctype_pool_str1136[sizeof("bidic")]; + char uniname2ctype_pool_str1145[sizeof("ingeorgian")]; + char uniname2ctype_pool_str1147[sizeof("quotationmark")]; + char uniname2ctype_pool_str1149[sizeof("incherokeesupplement")]; + char uniname2ctype_pool_str1152[sizeof("incjkunifiedideographsextensione")]; + char uniname2ctype_pool_str1157[sizeof("insiddham")]; + char uniname2ctype_pool_str1160[sizeof("runic")]; + char uniname2ctype_pool_str1172[sizeof("oids")]; + char uniname2ctype_pool_str1176[sizeof("ital")]; + char uniname2ctype_pool_str1186[sizeof("emoji")]; + char uniname2ctype_pool_str1187[sizeof("inmongolian")]; + char uniname2ctype_pool_str1195[sizeof("innagmundari")]; + char uniname2ctype_pool_str1200[sizeof("inlatinextendeda")]; + char uniname2ctype_pool_str1212[sizeof("vs")]; + char uniname2ctype_pool_str1214[sizeof("saurashtra")]; + char uniname2ctype_pool_str1216[sizeof("intaile")]; + char uniname2ctype_pool_str1228[sizeof("bali")]; + char uniname2ctype_pool_str1229[sizeof("xidstart")]; + char uniname2ctype_pool_str1231[sizeof("xdigit")]; + char uniname2ctype_pool_str1233[sizeof("ingurmukhi")]; + char uniname2ctype_pool_str1236[sizeof("blank")]; + char uniname2ctype_pool_str1243[sizeof("inlydian")]; #ifdef USE_UNICODE_AGE_PROPERTIES + char uniname2ctype_pool_str1247[sizeof("age=11.0")]; + char uniname2ctype_pool_str1248[sizeof("age=10.0")]; + char uniname2ctype_pool_str1249[sizeof("age=12.1")]; + char uniname2ctype_pool_str1250[sizeof("age=12.0")]; + char uniname2ctype_pool_str1251[sizeof("age=1.1")]; + char uniname2ctype_pool_str1252[sizeof("age=16.0")]; + char uniname2ctype_pool_str1253[sizeof("age=9.0")]; + char uniname2ctype_pool_str1254[sizeof("age=2.1")]; + char uniname2ctype_pool_str1255[sizeof("age=2.0")]; + char uniname2ctype_pool_str1256[sizeof("age=6.1")]; char uniname2ctype_pool_str1257[sizeof("age=6.0")]; - char uniname2ctype_pool_str1258[sizeof("age=6.2")]; - char uniname2ctype_pool_str1259[sizeof("age=15.0")]; - char uniname2ctype_pool_str1260[sizeof("age=7.0")]; - char uniname2ctype_pool_str1262[sizeof("age=6.3")]; #endif /* USE_UNICODE_AGE_PROPERTIES */ - char uniname2ctype_pool_str1263[sizeof("cwt")]; + char uniname2ctype_pool_str1258[sizeof("inlatinextendede")]; #ifdef USE_UNICODE_AGE_PROPERTIES - char uniname2ctype_pool_str1265[sizeof("age=14.0")]; + char uniname2ctype_pool_str1259[sizeof("age=6.2")]; + char uniname2ctype_pool_str1260[sizeof("age=8.0")]; + char uniname2ctype_pool_str1261[sizeof("age=7.0")]; #endif /* USE_UNICODE_AGE_PROPERTIES */ - char uniname2ctype_pool_str1266[sizeof("unassigned")]; + char uniname2ctype_pool_str1262[sizeof("incjkunifiedideographsextensionc")]; + char uniname2ctype_pool_str1264[sizeof("bengali")]; + char uniname2ctype_pool_str1265[sizeof("zinh")]; #ifdef USE_UNICODE_AGE_PROPERTIES - char uniname2ctype_pool_str1267[sizeof("age=5.1")]; - char uniname2ctype_pool_str1269[sizeof("age=5.0")]; - char uniname2ctype_pool_str1270[sizeof("age=5.2")]; + char uniname2ctype_pool_str1266[sizeof("age=15.1")]; + char uniname2ctype_pool_str1267[sizeof("age=15.0")]; + char uniname2ctype_pool_str1271[sizeof("age=5.1")]; + char uniname2ctype_pool_str1272[sizeof("age=5.0")]; + char uniname2ctype_pool_str1273[sizeof("age=14.0")]; + char uniname2ctype_pool_str1274[sizeof("age=5.2")]; + char uniname2ctype_pool_str1277[sizeof("age=4.1")]; + char uniname2ctype_pool_str1278[sizeof("age=4.0")]; #endif /* USE_UNICODE_AGE_PROPERTIES */ - char uniname2ctype_pool_str1271[sizeof("diacritic")]; + char uniname2ctype_pool_str1281[sizeof("inhanifirohingya")]; + char uniname2ctype_pool_str1282[sizeof("intamil")]; + char uniname2ctype_pool_str1284[sizeof("inmultani")]; #ifdef USE_UNICODE_AGE_PROPERTIES - char uniname2ctype_pool_str1273[sizeof("age=4.1")]; + char uniname2ctype_pool_str1288[sizeof("age=13.0")]; #endif /* USE_UNICODE_AGE_PROPERTIES */ - char uniname2ctype_pool_str1274[sizeof("ahom")]; + char uniname2ctype_pool_str1290[sizeof("balinese")]; + char uniname2ctype_pool_str1291[sizeof("hatran")]; #ifdef USE_UNICODE_AGE_PROPERTIES - char uniname2ctype_pool_str1275[sizeof("age=4.0")]; + char uniname2ctype_pool_str1292[sizeof("age=3.1")]; + char uniname2ctype_pool_str1293[sizeof("age=3.0")]; + char uniname2ctype_pool_str1295[sizeof("age=3.2")]; + char uniname2ctype_pool_str1297[sizeof("age=6.3")]; #endif /* USE_UNICODE_AGE_PROPERTIES */ - char uniname2ctype_pool_str1282[sizeof("incjkunifiedideographsextensione")]; - char uniname2ctype_pool_str1285[sizeof("khmr")]; - char uniname2ctype_pool_str1289[sizeof("insinhala")]; - char uniname2ctype_pool_str1292[sizeof("inmiscellaneoustechnical")]; - char uniname2ctype_pool_str1297[sizeof("saur")]; - char uniname2ctype_pool_str1300[sizeof("guru")]; - char uniname2ctype_pool_str1301[sizeof("sundanese")]; - char uniname2ctype_pool_str1306[sizeof("punct")]; - char uniname2ctype_pool_str1314[sizeof("paucinhau")]; - char uniname2ctype_pool_str1317[sizeof("gurmukhi")]; - char uniname2ctype_pool_str1328[sizeof("chorasmian")]; - char uniname2ctype_pool_str1331[sizeof("logicalorderexception")]; - char uniname2ctype_pool_str1340[sizeof("khmer")]; - char uniname2ctype_pool_str1343[sizeof("limbu")]; - char uniname2ctype_pool_str1349[sizeof("chrs")]; - char uniname2ctype_pool_str1352[sizeof("oriya")]; - char uniname2ctype_pool_str1354[sizeof("inscriptionalpahlavi")]; - char uniname2ctype_pool_str1356[sizeof("incyrillicextendedd")]; - char uniname2ctype_pool_str1358[sizeof("incjkunifiedideographsextensionc")]; - char uniname2ctype_pool_str1360[sizeof("cntrl")]; - char uniname2ctype_pool_str1365[sizeof("inlatinextendedadditional")]; - char uniname2ctype_pool_str1367[sizeof("insorasompeng")]; - char uniname2ctype_pool_str1369[sizeof("radical")]; - char uniname2ctype_pool_str1373[sizeof("emojimodifier")]; - char uniname2ctype_pool_str1375[sizeof("kharoshthi")]; - char uniname2ctype_pool_str1380[sizeof("n")]; - char uniname2ctype_pool_str1384[sizeof("math")]; - char uniname2ctype_pool_str1387[sizeof("goth")]; - char uniname2ctype_pool_str1392[sizeof("phnx")]; - char uniname2ctype_pool_str1400[sizeof("anatolianhieroglyphs")]; - char uniname2ctype_pool_str1401[sizeof("inenclosedalphanumerics")]; - char uniname2ctype_pool_str1407[sizeof("nandinagari")]; - char uniname2ctype_pool_str1409[sizeof("no")]; - char uniname2ctype_pool_str1415[sizeof("intangsa")]; - char uniname2ctype_pool_str1419[sizeof("nko")]; - char uniname2ctype_pool_str1420[sizeof("nkoo")]; - char uniname2ctype_pool_str1422[sizeof("ingreekandcoptic")]; - char uniname2ctype_pool_str1426[sizeof("p")]; - char uniname2ctype_pool_str1428[sizeof("grantha")]; - char uniname2ctype_pool_str1429[sizeof("decimalnumber")]; - char uniname2ctype_pool_str1438[sizeof("incjkunifiedideographs")]; - char uniname2ctype_pool_str1442[sizeof("intirhuta")]; - char uniname2ctype_pool_str1448[sizeof("inhatran")]; - char uniname2ctype_pool_str1449[sizeof("linb")]; - char uniname2ctype_pool_str1451[sizeof("mult")]; - char uniname2ctype_pool_str1454[sizeof("saurashtra")]; - char uniname2ctype_pool_str1457[sizeof("kthi")]; - char uniname2ctype_pool_str1460[sizeof("zanb")]; - char uniname2ctype_pool_str1462[sizeof("inbhaiksuki")]; - char uniname2ctype_pool_str1470[sizeof("innabataean")]; - char uniname2ctype_pool_str1471[sizeof("inphoenician")]; - char uniname2ctype_pool_str1474[sizeof("xpeo")]; - char uniname2ctype_pool_str1475[sizeof("inkanbun")]; - char uniname2ctype_pool_str1476[sizeof("inmeroitichieroglyphs")]; - char uniname2ctype_pool_str1480[sizeof("ahex")]; - char uniname2ctype_pool_str1489[sizeof("enclosingmark")]; - char uniname2ctype_pool_str1495[sizeof("sd")]; - char uniname2ctype_pool_str1497[sizeof("inelbasan")]; - char uniname2ctype_pool_str1499[sizeof("inenclosedideographicsupplement")]; - char uniname2ctype_pool_str1501[sizeof("sidd")]; - char uniname2ctype_pool_str1507[sizeof("linearb")]; - char uniname2ctype_pool_str1508[sizeof("cpmn")]; - char uniname2ctype_pool_str1517[sizeof("inenclosedalphanumericsupplement")]; - char uniname2ctype_pool_str1520[sizeof("bidicontrol")]; - char uniname2ctype_pool_str1524[sizeof("inphaistosdisc")]; - char uniname2ctype_pool_str1529[sizeof("limb")]; - char uniname2ctype_pool_str1531[sizeof("inkangxiradicals")]; - char uniname2ctype_pool_str1533[sizeof("lepc")]; - char uniname2ctype_pool_str1536[sizeof("braille")]; - char uniname2ctype_pool_str1537[sizeof("regionalindicator")]; - char uniname2ctype_pool_str1542[sizeof("inlowsurrogates")]; - char uniname2ctype_pool_str1547[sizeof("brah")]; - char uniname2ctype_pool_str1549[sizeof("inoldhungarian")]; - char uniname2ctype_pool_str1557[sizeof("beng")]; - char uniname2ctype_pool_str1563[sizeof("emojimodifierbase")]; - char uniname2ctype_pool_str1565[sizeof("inarabic")]; - char uniname2ctype_pool_str1570[sizeof("osage")]; - char uniname2ctype_pool_str1572[sizeof("inherited")]; - char uniname2ctype_pool_str1577[sizeof("incyprominoan")]; - char uniname2ctype_pool_str1580[sizeof("glag")]; - char uniname2ctype_pool_str1582[sizeof("medf")]; - char uniname2ctype_pool_str1583[sizeof("osma")]; - char uniname2ctype_pool_str1587[sizeof("indogra")]; - char uniname2ctype_pool_str1597[sizeof("arab")]; - char uniname2ctype_pool_str1598[sizeof("medefaidrin")]; - char uniname2ctype_pool_str1607[sizeof("inshorthandformatcontrols")]; - char uniname2ctype_pool_str1613[sizeof("phli")]; - char uniname2ctype_pool_str1617[sizeof("inimperialaramaic")]; - char uniname2ctype_pool_str1618[sizeof("emod")]; - char uniname2ctype_pool_str1622[sizeof("ingreekextended")]; - char uniname2ctype_pool_str1623[sizeof("inanatolianhieroglyphs")]; - char uniname2ctype_pool_str1629[sizeof("punctuation")]; - char uniname2ctype_pool_str1635[sizeof("graphemeextend")]; - char uniname2ctype_pool_str1643[sizeof("cwl")]; - char uniname2ctype_pool_str1644[sizeof("vith")]; - char uniname2ctype_pool_str1654[sizeof("ingeometricshapes")]; - char uniname2ctype_pool_str1655[sizeof("emojicomponent")]; - char uniname2ctype_pool_str1657[sizeof("dsrt")]; - char uniname2ctype_pool_str1662[sizeof("coptic")]; - char uniname2ctype_pool_str1664[sizeof("inkayahli")]; - char uniname2ctype_pool_str1671[sizeof("inoriya")]; - char uniname2ctype_pool_str1675[sizeof("inarabicpresentationformsa")]; - char uniname2ctype_pool_str1677[sizeof("inbasiclatin")]; - char uniname2ctype_pool_str1682[sizeof("incjkunifiedideographsextensiond")]; - char uniname2ctype_pool_str1684[sizeof("wara")]; - char uniname2ctype_pool_str1686[sizeof("sinh")]; - char uniname2ctype_pool_str1687[sizeof("sund")]; - char uniname2ctype_pool_str1691[sizeof("shavian")]; - char uniname2ctype_pool_str1699[sizeof("insundanesesupplement")]; - char uniname2ctype_pool_str1701[sizeof("inyezidi")]; - char uniname2ctype_pool_str1704[sizeof("bhks")]; - char uniname2ctype_pool_str1714[sizeof("bhaiksuki")]; - char uniname2ctype_pool_str1722[sizeof("inhanunoo")]; - char uniname2ctype_pool_str1724[sizeof("intangut")]; - char uniname2ctype_pool_str1728[sizeof("sogdian")]; - char uniname2ctype_pool_str1729[sizeof("inlatinextendedd")]; - char uniname2ctype_pool_str1730[sizeof("sogo")]; - char uniname2ctype_pool_str1731[sizeof("insinhalaarchaicnumbers")]; - char uniname2ctype_pool_str1732[sizeof("ideographic")]; - char uniname2ctype_pool_str1733[sizeof("ugar")]; - char uniname2ctype_pool_str1734[sizeof("deseret")]; - char uniname2ctype_pool_str1735[sizeof("odi")]; - char uniname2ctype_pool_str1740[sizeof("copt")]; - char uniname2ctype_pool_str1742[sizeof("imperialaramaic")]; - char uniname2ctype_pool_str1745[sizeof("insogdian")]; - char uniname2ctype_pool_str1746[sizeof("indingbats")]; - char uniname2ctype_pool_str1750[sizeof("format")]; - char uniname2ctype_pool_str1752[sizeof("ininscriptionalpahlavi")]; - char uniname2ctype_pool_str1753[sizeof("lyci")]; - char uniname2ctype_pool_str1757[sizeof("ininscriptionalparthian")]; - char uniname2ctype_pool_str1766[sizeof("grbase")]; - char uniname2ctype_pool_str1768[sizeof("lycian")]; - char uniname2ctype_pool_str1769[sizeof("inbatak")]; - char uniname2ctype_pool_str1776[sizeof("cprt")]; - char uniname2ctype_pool_str1781[sizeof("inunifiedcanadianaboriginalsyllabicsextendeda")]; - char uniname2ctype_pool_str1788[sizeof("mymr")]; - char uniname2ctype_pool_str1793[sizeof("myanmar")]; - char uniname2ctype_pool_str1806[sizeof("intibetan")]; - char uniname2ctype_pool_str1810[sizeof("intags")]; - char uniname2ctype_pool_str1811[sizeof("asciihexdigit")]; - char uniname2ctype_pool_str1813[sizeof("sentenceterminal")]; - char uniname2ctype_pool_str1821[sizeof("nand")]; - char uniname2ctype_pool_str1828[sizeof("inblockelements")]; - char uniname2ctype_pool_str1838[sizeof("inornamentaldingbats")]; - char uniname2ctype_pool_str1841[sizeof("inethiopicextendeda")]; - char uniname2ctype_pool_str1842[sizeof("innumberforms")]; - char uniname2ctype_pool_str1843[sizeof("cwcf")]; - char uniname2ctype_pool_str1845[sizeof("oidc")]; - char uniname2ctype_pool_str1848[sizeof("bopo")]; - char uniname2ctype_pool_str1851[sizeof("cuneiform")]; - char uniname2ctype_pool_str1866[sizeof("caseignorable")]; - char uniname2ctype_pool_str1871[sizeof("inoldpersian")]; - char uniname2ctype_pool_str1881[sizeof("cwu")]; - char uniname2ctype_pool_str1888[sizeof("inelymaic")]; - char uniname2ctype_pool_str1889[sizeof("insoyombo")]; - char uniname2ctype_pool_str1896[sizeof("ingeometricshapesextended")]; - char uniname2ctype_pool_str1902[sizeof("incjkcompatibility")]; - char uniname2ctype_pool_str1904[sizeof("inmyanmarextendedb")]; - char uniname2ctype_pool_str1905[sizeof("innushu")]; - char uniname2ctype_pool_str1912[sizeof("inkanaextendedb")]; - char uniname2ctype_pool_str1913[sizeof("olck")]; - char uniname2ctype_pool_str1916[sizeof("inbyzantinemusicalsymbols")]; - char uniname2ctype_pool_str1924[sizeof("olchiki")]; - char uniname2ctype_pool_str1929[sizeof("inkatakanaphoneticextensions")]; - char uniname2ctype_pool_str1932[sizeof("incoptic")]; - char uniname2ctype_pool_str1935[sizeof("oids")]; - char uniname2ctype_pool_str1936[sizeof("inarabicextendeda")]; - char uniname2ctype_pool_str1941[sizeof("modifierletter")]; - char uniname2ctype_pool_str1950[sizeof("incjksymbolsandpunctuation")]; - char uniname2ctype_pool_str1956[sizeof("olower")]; - char uniname2ctype_pool_str1958[sizeof("bopomofo")]; - char uniname2ctype_pool_str1964[sizeof("inlisu")]; - char uniname2ctype_pool_str1967[sizeof("inoldpermic")]; - char uniname2ctype_pool_str1968[sizeof("innoblock")]; - char uniname2ctype_pool_str1969[sizeof("ext")]; - char uniname2ctype_pool_str1974[sizeof("inunifiedcanadianaboriginalsyllabics")]; - char uniname2ctype_pool_str1981[sizeof("takri")]; - char uniname2ctype_pool_str1985[sizeof("inbraillepatterns")]; - char uniname2ctype_pool_str1988[sizeof("invai")]; - char uniname2ctype_pool_str1991[sizeof("alpha")]; - char uniname2ctype_pool_str1993[sizeof("inbalinese")]; - char uniname2ctype_pool_str1994[sizeof("sorasompeng")]; - char uniname2ctype_pool_str1996[sizeof("closepunctuation")]; - char uniname2ctype_pool_str2001[sizeof("hani")]; - char uniname2ctype_pool_str2002[sizeof("inmayannumerals")]; - char uniname2ctype_pool_str2004[sizeof("han")]; - char uniname2ctype_pool_str2006[sizeof("inmiscellaneousmathematicalsymbolsb")]; - char uniname2ctype_pool_str2010[sizeof("inlepcha")]; - char uniname2ctype_pool_str2011[sizeof("patsyn")]; - char uniname2ctype_pool_str2012[sizeof("inlisusupplement")]; - char uniname2ctype_pool_str2014[sizeof("insyriacsupplement")]; - char uniname2ctype_pool_str2015[sizeof("hano")]; - char uniname2ctype_pool_str2016[sizeof("newa")]; - char uniname2ctype_pool_str2023[sizeof("spacingmark")]; - char uniname2ctype_pool_str2024[sizeof("inpalmyrene")]; - char uniname2ctype_pool_str2026[sizeof("takr")]; - char uniname2ctype_pool_str2033[sizeof("xposixpunct")]; - char uniname2ctype_pool_str2040[sizeof("inkhojki")]; - char uniname2ctype_pool_str2042[sizeof("taile")]; - char uniname2ctype_pool_str2043[sizeof("assigned")]; - char uniname2ctype_pool_str2044[sizeof("hanunoo")]; - char uniname2ctype_pool_str2047[sizeof("hira")]; - char uniname2ctype_pool_str2048[sizeof("inarabicextendedc")]; - char uniname2ctype_pool_str2062[sizeof("newtailue")]; - char uniname2ctype_pool_str2070[sizeof("space")]; - char uniname2ctype_pool_str2073[sizeof("intelugu")]; - char uniname2ctype_pool_str2077[sizeof("lydi")]; - char uniname2ctype_pool_str2078[sizeof("idsb")]; - char uniname2ctype_pool_str2090[sizeof("extpict")]; - char uniname2ctype_pool_str2092[sizeof("lydian")]; - char uniname2ctype_pool_str2095[sizeof("inethiopicsupplement")]; - char uniname2ctype_pool_str2103[sizeof("sarb")]; - char uniname2ctype_pool_str2110[sizeof("ugaritic")]; - char uniname2ctype_pool_str2114[sizeof("inyiradicals")]; - char uniname2ctype_pool_str2115[sizeof("inphoneticextensions")]; - char uniname2ctype_pool_str2117[sizeof("sharada")]; - char uniname2ctype_pool_str2128[sizeof("zanabazarsquare")]; - char uniname2ctype_pool_str2135[sizeof("bugi")]; - char uniname2ctype_pool_str2137[sizeof("word")]; - char uniname2ctype_pool_str2141[sizeof("term")]; - char uniname2ctype_pool_str2145[sizeof("separator")]; - char uniname2ctype_pool_str2146[sizeof("ingeorgiansupplement")]; - char uniname2ctype_pool_str2149[sizeof("sogd")]; - char uniname2ctype_pool_str2163[sizeof("extender")]; - char uniname2ctype_pool_str2165[sizeof("shrd")]; - char uniname2ctype_pool_str2166[sizeof("graph")]; - char uniname2ctype_pool_str2174[sizeof("tnsa")]; - char uniname2ctype_pool_str2178[sizeof("tangsa")]; - char uniname2ctype_pool_str2181[sizeof("phag")]; - char uniname2ctype_pool_str2182[sizeof("dogra")]; - char uniname2ctype_pool_str2195[sizeof("inhanguljamo")]; - char uniname2ctype_pool_str2196[sizeof("inshavian")]; - char uniname2ctype_pool_str2207[sizeof("siddham")]; - char uniname2ctype_pool_str2211[sizeof("cf")]; - char uniname2ctype_pool_str2216[sizeof("inunifiedcanadianaboriginalsyllabicsextended")]; - char uniname2ctype_pool_str2217[sizeof("buginese")]; - char uniname2ctype_pool_str2218[sizeof("inmongoliansupplement")]; - char uniname2ctype_pool_str2219[sizeof("cyrl")]; - char uniname2ctype_pool_str2224[sizeof("inhanguljamoextendeda")]; - char uniname2ctype_pool_str2228[sizeof("pf")]; - char uniname2ctype_pool_str2229[sizeof("number")]; - char uniname2ctype_pool_str2232[sizeof("inphoneticextensionssupplement")]; - char uniname2ctype_pool_str2233[sizeof("dogr")]; - char uniname2ctype_pool_str2234[sizeof("mlym")]; - char uniname2ctype_pool_str2235[sizeof("incopticepactnumbers")]; - char uniname2ctype_pool_str2241[sizeof("malayalam")]; - char uniname2ctype_pool_str2244[sizeof("inbamum")]; - char uniname2ctype_pool_str2247[sizeof("nd")]; - char uniname2ctype_pool_str2248[sizeof("insuttonsignwriting")]; - char uniname2ctype_pool_str2276[sizeof("inethiopicextended")]; - char uniname2ctype_pool_str2278[sizeof("shaw")]; - char uniname2ctype_pool_str2279[sizeof("palmyrene")]; - char uniname2ctype_pool_str2283[sizeof("soyo")]; - char uniname2ctype_pool_str2296[sizeof("incjkunifiedideographsextensionh")]; - char uniname2ctype_pool_str2305[sizeof("sgnw")]; - char uniname2ctype_pool_str2308[sizeof("toto")]; - char uniname2ctype_pool_str2312[sizeof("caucasianalbanian")]; - char uniname2ctype_pool_str2315[sizeof("inmathematicalalphanumericsymbols")]; - char uniname2ctype_pool_str2316[sizeof("incjkunifiedideographsextensiong")]; - char uniname2ctype_pool_str2318[sizeof("hatran")]; - char uniname2ctype_pool_str2321[sizeof("taiviet")]; - char uniname2ctype_pool_str2323[sizeof("meroitichieroglyphs")]; - char uniname2ctype_pool_str2327[sizeof("ingeorgianextended")]; - char uniname2ctype_pool_str2331[sizeof("incjkunifiedideographsextensionf")]; - char uniname2ctype_pool_str2333[sizeof("oldpersian")]; - char uniname2ctype_pool_str2343[sizeof("induployan")]; - char uniname2ctype_pool_str2344[sizeof("incyrillicextendedb")]; - char uniname2ctype_pool_str2345[sizeof("dash")]; - char uniname2ctype_pool_str2353[sizeof("hatr")]; - char uniname2ctype_pool_str2361[sizeof("innyiakengpuachuehmong")]; - char uniname2ctype_pool_str2364[sizeof("incombiningdiacriticalmarks")]; - char uniname2ctype_pool_str2373[sizeof("nl")]; - char uniname2ctype_pool_str2374[sizeof("incombiningdiacriticalmarksforsymbols")]; - char uniname2ctype_pool_str2375[sizeof("khudawadi")]; - char uniname2ctype_pool_str2397[sizeof("incjkradicalssupplement")]; - char uniname2ctype_pool_str2398[sizeof("inglagolitic")]; - char uniname2ctype_pool_str2405[sizeof("orkh")]; - char uniname2ctype_pool_str2414[sizeof("syrc")]; - char uniname2ctype_pool_str2427[sizeof("surrogate")]; - char uniname2ctype_pool_str2433[sizeof("indevanagari")]; - char uniname2ctype_pool_str2434[sizeof("avestan")]; - char uniname2ctype_pool_str2437[sizeof("oldpermic")]; - char uniname2ctype_pool_str2440[sizeof("ethi")]; - char uniname2ctype_pool_str2451[sizeof("ogam")]; - char uniname2ctype_pool_str2454[sizeof("rohg")]; - char uniname2ctype_pool_str2460[sizeof("idstrinaryoperator")]; - char uniname2ctype_pool_str2464[sizeof("java")]; - char uniname2ctype_pool_str2470[sizeof("inphagspa")]; - char uniname2ctype_pool_str2475[sizeof("lepcha")]; - char uniname2ctype_pool_str2476[sizeof("indevanagariextendeda")]; - char uniname2ctype_pool_str2478[sizeof("intifinagh")]; - char uniname2ctype_pool_str2479[sizeof("intagalog")]; - char uniname2ctype_pool_str2481[sizeof("incombiningdiacriticalmarkssupplement")]; - char uniname2ctype_pool_str2500[sizeof("tale")]; - char uniname2ctype_pool_str2506[sizeof("inbrahmi")]; - char uniname2ctype_pool_str2511[sizeof("terminalpunctuation")]; - char uniname2ctype_pool_str2513[sizeof("insymbolsandpictographsextendeda")]; - char uniname2ctype_pool_str2530[sizeof("syriac")]; - char uniname2ctype_pool_str2534[sizeof("inbengali")]; - char uniname2ctype_pool_str2535[sizeof("nagm")]; - char uniname2ctype_pool_str2545[sizeof("extendedpictographic")]; - char uniname2ctype_pool_str2548[sizeof("buhd")]; - char uniname2ctype_pool_str2549[sizeof("javanese")]; - char uniname2ctype_pool_str2551[sizeof("taml")]; - char uniname2ctype_pool_str2564[sizeof("inbuginese")]; - char uniname2ctype_pool_str2567[sizeof("inlatin1supplement")]; - char uniname2ctype_pool_str2570[sizeof("ingothic")]; - char uniname2ctype_pool_str2572[sizeof("invariationselectors")]; - char uniname2ctype_pool_str2574[sizeof("hex")]; - char uniname2ctype_pool_str2575[sizeof("inverticalforms")]; - char uniname2ctype_pool_str2576[sizeof("ebase")]; - char uniname2ctype_pool_str2582[sizeof("incurrencysymbols")]; - char uniname2ctype_pool_str2588[sizeof("avst")]; - char uniname2ctype_pool_str2602[sizeof("osge")]; - char uniname2ctype_pool_str2606[sizeof("incombiningdiacriticalmarksextended")]; - char uniname2ctype_pool_str2608[sizeof("intaiviet")]; - char uniname2ctype_pool_str2609[sizeof("spaceseparator")]; - char uniname2ctype_pool_str2625[sizeof("softdotted")]; - char uniname2ctype_pool_str2648[sizeof("nchar")]; - char uniname2ctype_pool_str2652[sizeof("invedicextensions")]; - char uniname2ctype_pool_str2656[sizeof("inlimbu")]; - char uniname2ctype_pool_str2657[sizeof("olditalic")]; - char uniname2ctype_pool_str2665[sizeof("gujr")]; - char uniname2ctype_pool_str2666[sizeof("mathsymbol")]; - char uniname2ctype_pool_str2670[sizeof("incjkunifiedideographsextensionb")]; - char uniname2ctype_pool_str2674[sizeof("gujarati")]; - char uniname2ctype_pool_str2688[sizeof("phagspa")]; - char uniname2ctype_pool_str2689[sizeof("invariationselectorssupplement")]; - char uniname2ctype_pool_str2694[sizeof("currencysymbol")]; - char uniname2ctype_pool_str2705[sizeof("inlinearbsyllabary")]; - char uniname2ctype_pool_str2726[sizeof("wancho")]; - char uniname2ctype_pool_str2750[sizeof("inpaucinhau")]; - char uniname2ctype_pool_str2761[sizeof("other")]; - char uniname2ctype_pool_str2762[sizeof("otheridcontinue")]; - char uniname2ctype_pool_str2765[sizeof("sylo")]; - char uniname2ctype_pool_str2766[sizeof("zp")]; - char uniname2ctype_pool_str2769[sizeof("inaegeannumbers")]; - char uniname2ctype_pool_str2772[sizeof("warangciti")]; - char uniname2ctype_pool_str2775[sizeof("othernumber")]; - char uniname2ctype_pool_str2786[sizeof("digit")]; - char uniname2ctype_pool_str2793[sizeof("nonspacingmark")]; - char uniname2ctype_pool_str2801[sizeof("titlecaseletter")]; - char uniname2ctype_pool_str2808[sizeof("inmeroiticcursive")]; - char uniname2ctype_pool_str2810[sizeof("wcho")]; - char uniname2ctype_pool_str2816[sizeof("graphemeclusterbreak=spacingmark")]; - char uniname2ctype_pool_str2821[sizeof("inletterlikesymbols")]; - char uniname2ctype_pool_str2830[sizeof("inottomansiyaqnumbers")]; - char uniname2ctype_pool_str2834[sizeof("intagbanwa")]; - char uniname2ctype_pool_str2836[sizeof("cyrillic")]; - char uniname2ctype_pool_str2847[sizeof("oalpha")]; - char uniname2ctype_pool_str2852[sizeof("graphemeclusterbreak=cr")]; - char uniname2ctype_pool_str2855[sizeof("narb")]; - char uniname2ctype_pool_str2856[sizeof("changeswhencasemapped")]; - char uniname2ctype_pool_str2859[sizeof("inbopomofo")]; - char uniname2ctype_pool_str2867[sizeof("graphemeclusterbreak=regionalindicator")]; - char uniname2ctype_pool_str2868[sizeof("otheralphabetic")]; - char uniname2ctype_pool_str2871[sizeof("noncharactercodepoint")]; - char uniname2ctype_pool_str2879[sizeof("oldhungarian")]; - char uniname2ctype_pool_str2886[sizeof("insymbolsforlegacycomputing")]; - char uniname2ctype_pool_str2902[sizeof("insmallformvariants")]; - char uniname2ctype_pool_str2904[sizeof("inhangulsyllables")]; - char uniname2ctype_pool_str2905[sizeof("emojipresentation")]; - char uniname2ctype_pool_str2907[sizeof("epres")]; - char uniname2ctype_pool_str2909[sizeof("inbassavah")]; - char uniname2ctype_pool_str2911[sizeof("indevanagariextended")]; - char uniname2ctype_pool_str2941[sizeof("inbuhid")]; - char uniname2ctype_pool_str2953[sizeof("tirhuta")]; - char uniname2ctype_pool_str2964[sizeof("inpsalterpahlavi")]; - char uniname2ctype_pool_str2966[sizeof("whitespace")]; - char uniname2ctype_pool_str2967[sizeof("finalpunctuation")]; - char uniname2ctype_pool_str2970[sizeof("orya")]; - char uniname2ctype_pool_str2980[sizeof("phlp")]; - char uniname2ctype_pool_str2984[sizeof("inbamumsupplement")]; - char uniname2ctype_pool_str2986[sizeof("buhid")]; - char uniname2ctype_pool_str2987[sizeof("paragraphseparator")]; - char uniname2ctype_pool_str2988[sizeof("inalphabeticpresentationforms")]; - char uniname2ctype_pool_str2997[sizeof("inlatinextendedg")]; - char uniname2ctype_pool_str3001[sizeof("elba")]; - char uniname2ctype_pool_str3002[sizeof("changeswhentitlecased")]; - char uniname2ctype_pool_str3005[sizeof("incombininghalfmarks")]; - char uniname2ctype_pool_str3006[sizeof("intangutcomponents")]; - char uniname2ctype_pool_str3015[sizeof("thaa")]; - char uniname2ctype_pool_str3018[sizeof("thai")]; - char uniname2ctype_pool_str3019[sizeof("oldturkic")]; - char uniname2ctype_pool_str3026[sizeof("thaana")]; - char uniname2ctype_pool_str3027[sizeof("inlatinextendedf")]; - char uniname2ctype_pool_str3035[sizeof("ougr")]; - char uniname2ctype_pool_str3042[sizeof("tang")]; - char uniname2ctype_pool_str3045[sizeof("inarabicmathematicalalphabeticsymbols")]; - char uniname2ctype_pool_str3048[sizeof("tagbanwa")]; - char uniname2ctype_pool_str3052[sizeof("tamil")]; - char uniname2ctype_pool_str3053[sizeof("khitansmallscript")]; - char uniname2ctype_pool_str3058[sizeof("mahj")]; - char uniname2ctype_pool_str3067[sizeof("mahajani")]; - char uniname2ctype_pool_str3068[sizeof("hang")]; - char uniname2ctype_pool_str3071[sizeof("tirh")]; - char uniname2ctype_pool_str3072[sizeof("sylotinagri")]; - char uniname2ctype_pool_str3082[sizeof("talu")]; - char uniname2ctype_pool_str3084[sizeof("nagmundari")]; - char uniname2ctype_pool_str3086[sizeof("deva")]; - char uniname2ctype_pool_str3087[sizeof("ingujarati")]; - char uniname2ctype_pool_str3091[sizeof("deprecated")]; - char uniname2ctype_pool_str3099[sizeof("inarabicpresentationformsb")]; - char uniname2ctype_pool_str3104[sizeof("devanagari")]; - char uniname2ctype_pool_str3106[sizeof("ingunjalagondi")]; - char uniname2ctype_pool_str3107[sizeof("graphemeclusterbreak=t")]; - char uniname2ctype_pool_str3109[sizeof("graphemeclusterbreak=lvt")]; - char uniname2ctype_pool_str3110[sizeof("taitham")]; - char uniname2ctype_pool_str3111[sizeof("nbat")]; - char uniname2ctype_pool_str3118[sizeof("telu")]; - char uniname2ctype_pool_str3123[sizeof("hiragana")]; - char uniname2ctype_pool_str3125[sizeof("nabataean")]; - char uniname2ctype_pool_str3135[sizeof("inrejang")]; - char uniname2ctype_pool_str3142[sizeof("intangutsupplement")]; - char uniname2ctype_pool_str3145[sizeof("khoj")]; - char uniname2ctype_pool_str3155[sizeof("hmng")]; - char uniname2ctype_pool_str3157[sizeof("cyprominoan")]; - char uniname2ctype_pool_str3158[sizeof("inhebrew")]; - char uniname2ctype_pool_str3176[sizeof("inmathematicaloperators")]; - char uniname2ctype_pool_str3180[sizeof("inarabicsupplement")]; - char uniname2ctype_pool_str3193[sizeof("inenclosedcjklettersandmonths")]; - char uniname2ctype_pool_str3209[sizeof("changeswhenlowercased")]; - char uniname2ctype_pool_str3212[sizeof("tangut")]; - char uniname2ctype_pool_str3215[sizeof("elbasan")]; - char uniname2ctype_pool_str3218[sizeof("osmanya")]; - char uniname2ctype_pool_str3237[sizeof("insuperscriptsandsubscripts")]; - char uniname2ctype_pool_str3239[sizeof("graphemeclusterbreak=extend")]; - char uniname2ctype_pool_str3240[sizeof("graphemeclusterbreak=prepend")]; - char uniname2ctype_pool_str3248[sizeof("nshu")]; - char uniname2ctype_pool_str3254[sizeof("otherlowercase")]; - char uniname2ctype_pool_str3265[sizeof("inethiopicextendedb")]; - char uniname2ctype_pool_str3267[sizeof("otherletter")]; - char uniname2ctype_pool_str3275[sizeof("kayahli")]; - char uniname2ctype_pool_str3284[sizeof("inplayingcards")]; - char uniname2ctype_pool_str3287[sizeof("elym")]; - char uniname2ctype_pool_str3297[sizeof("graphemeclusterbreak=l")]; - char uniname2ctype_pool_str3303[sizeof("graphemeclusterbreak=control")]; - char uniname2ctype_pool_str3313[sizeof("ogrext")]; - char uniname2ctype_pool_str3320[sizeof("elymaic")]; - char uniname2ctype_pool_str3328[sizeof("changeswhenuppercased")]; - char uniname2ctype_pool_str3329[sizeof("inalchemicalsymbols")]; - char uniname2ctype_pool_str3331[sizeof("oldsogdian")]; - char uniname2ctype_pool_str3338[sizeof("otheridstart")]; - char uniname2ctype_pool_str3348[sizeof("insupplementalarrowsa")]; - char uniname2ctype_pool_str3350[sizeof("invithkuqi")]; - char uniname2ctype_pool_str3355[sizeof("symbol")]; - char uniname2ctype_pool_str3360[sizeof("inarabicextendedb")]; - char uniname2ctype_pool_str3371[sizeof("cypriot")]; - char uniname2ctype_pool_str3372[sizeof("any")]; - char uniname2ctype_pool_str3373[sizeof("otheruppercase")]; - char uniname2ctype_pool_str3377[sizeof("rjng")]; - char uniname2ctype_pool_str3391[sizeof("wspace")]; - char uniname2ctype_pool_str3396[sizeof("inindicsiyaqnumbers")]; - char uniname2ctype_pool_str3405[sizeof("inprivateusearea")]; - char uniname2ctype_pool_str3416[sizeof("othersymbol")]; - char uniname2ctype_pool_str3428[sizeof("oupper")]; - char uniname2ctype_pool_str3433[sizeof("signwriting")]; - char uniname2ctype_pool_str3436[sizeof("nushu")]; - char uniname2ctype_pool_str3455[sizeof("hmnp")]; - char uniname2ctype_pool_str3458[sizeof("upper")]; - char uniname2ctype_pool_str3460[sizeof("insupplementalarrowsc")]; - char uniname2ctype_pool_str3483[sizeof("omath")]; - char uniname2ctype_pool_str3502[sizeof("modifiersymbol")]; - char uniname2ctype_pool_str3504[sizeof("hebr")]; - char uniname2ctype_pool_str3505[sizeof("inhalfwidthandfullwidthforms")]; - char uniname2ctype_pool_str3511[sizeof("insupplementalmathematicaloperators")]; - char uniname2ctype_pool_str3532[sizeof("inpahawhhmong")]; - char uniname2ctype_pool_str3533[sizeof("alphabetic")]; - char uniname2ctype_pool_str3558[sizeof("uppercase")]; - char uniname2ctype_pool_str3580[sizeof("dupl")]; - char uniname2ctype_pool_str3590[sizeof("ogham")]; - char uniname2ctype_pool_str3613[sizeof("dashpunctuation")]; - char uniname2ctype_pool_str3618[sizeof("hangul")]; - char uniname2ctype_pool_str3648[sizeof("inhanguljamoextendedb")]; - char uniname2ctype_pool_str3659[sizeof("bassavah")]; - char uniname2ctype_pool_str3664[sizeof("aghb")]; - char uniname2ctype_pool_str3686[sizeof("hung")]; - char uniname2ctype_pool_str3689[sizeof("hexdigit")]; - char uniname2ctype_pool_str3698[sizeof("incypriotsyllabary")]; - char uniname2ctype_pool_str3699[sizeof("indivesakuru")]; - char uniname2ctype_pool_str3701[sizeof("tibt")]; - char uniname2ctype_pool_str3705[sizeof("inlatinextendedb")]; - char uniname2ctype_pool_str3710[sizeof("hluw")]; - char uniname2ctype_pool_str3713[sizeof("tibetan")]; - char uniname2ctype_pool_str3721[sizeof("inyisyllables")]; - char uniname2ctype_pool_str3744[sizeof("oldnortharabian")]; - char uniname2ctype_pool_str3754[sizeof("defaultignorablecodepoint")]; - char uniname2ctype_pool_str3766[sizeof("inhighprivateusesurrogates")]; - char uniname2ctype_pool_str3799[sizeof("soyombo")]; - char uniname2ctype_pool_str3807[sizeof("otherdefaultignorablecodepoint")]; - char uniname2ctype_pool_str3842[sizeof("pahawhhmong")]; - char uniname2ctype_pool_str3845[sizeof("unifiedideograph")]; - char uniname2ctype_pool_str3850[sizeof("othermath")]; - char uniname2ctype_pool_str3854[sizeof("changeswhencasefolded")]; - char uniname2ctype_pool_str3857[sizeof("inmahjongtiles")]; - char uniname2ctype_pool_str3868[sizeof("dep")]; - char uniname2ctype_pool_str3881[sizeof("divesakuru")]; - char uniname2ctype_pool_str3884[sizeof("graphemeclusterbreak=lf")]; - char uniname2ctype_pool_str3891[sizeof("uppercaseletter")]; - char uniname2ctype_pool_str3924[sizeof("insupplementalpunctuation")]; - char uniname2ctype_pool_str3942[sizeof("ethiopic")]; - char uniname2ctype_pool_str3944[sizeof("inyijinghexagramsymbols")]; - char uniname2ctype_pool_str3949[sizeof("ecomp")]; - char uniname2ctype_pool_str3976[sizeof("inglagoliticsupplement")]; - char uniname2ctype_pool_str3998[sizeof("inbopomofoextended")]; - char uniname2ctype_pool_str4007[sizeof("injavanese")]; - char uniname2ctype_pool_str4106[sizeof("otherpunctuation")]; - char uniname2ctype_pool_str4116[sizeof("tifinagh")]; - char uniname2ctype_pool_str4127[sizeof("tfng")]; - char uniname2ctype_pool_str4169[sizeof("hanifirohingya")]; - char uniname2ctype_pool_str4231[sizeof("tavt")]; - char uniname2ctype_pool_str4308[sizeof("inboxdrawing")]; - char uniname2ctype_pool_str4309[sizeof("oldsoutharabian")]; - char uniname2ctype_pool_str4348[sizeof("inegyptianhieroglyphs")]; - char uniname2ctype_pool_str4361[sizeof("inegyptianhieroglyphformatcontrols")]; - char uniname2ctype_pool_str4459[sizeof("tagb")]; - char uniname2ctype_pool_str4487[sizeof("rejang")]; - char uniname2ctype_pool_str4604[sizeof("tglg")]; - char uniname2ctype_pool_str4626[sizeof("tagalog")]; - char uniname2ctype_pool_str4627[sizeof("othergraphemeextend")]; - char uniname2ctype_pool_str4674[sizeof("insupplementaryprivateuseareaa")]; - char uniname2ctype_pool_str4683[sizeof("inhighsurrogates")]; - char uniname2ctype_pool_str4695[sizeof("hebrew")]; - char uniname2ctype_pool_str4734[sizeof("duployan")]; - char uniname2ctype_pool_str4755[sizeof("graphemeclusterbreak=v")]; - char uniname2ctype_pool_str4756[sizeof("graphemeclusterbreak=lv")]; - char uniname2ctype_pool_str4772[sizeof("insupplementalarrowsb")]; - char uniname2ctype_pool_str4783[sizeof("graphemeclusterbreak=zwj")]; - char uniname2ctype_pool_str4810[sizeof("telugu")]; - char uniname2ctype_pool_str4898[sizeof("zyyy")]; - char uniname2ctype_pool_str4982[sizeof("olduyghur")]; - char uniname2ctype_pool_str4986[sizeof("inhangulcompatibilityjamo")]; - char uniname2ctype_pool_str5018[sizeof("openpunctuation")]; - char uniname2ctype_pool_str5038[sizeof("hyphen")]; - char uniname2ctype_pool_str5134[sizeof("insupplementalsymbolsandpictographs")]; - char uniname2ctype_pool_str5141[sizeof("egyp")]; - char uniname2ctype_pool_str5300[sizeof("nyiakengpuachuehmong")]; - char uniname2ctype_pool_str5980[sizeof("egyptianhieroglyphs")]; - char uniname2ctype_pool_str6098[sizeof("insupplementaryprivateuseareab")]; + char uniname2ctype_pool_str1298[sizeof("punct")]; + char uniname2ctype_pool_str1309[sizeof("incjkunifiedideographs")]; + char uniname2ctype_pool_str1310[sizeof("inhiragana")]; + char uniname2ctype_pool_str1314[sizeof("sinhala")]; + char uniname2ctype_pool_str1318[sizeof("plrd")]; + char uniname2ctype_pool_str1320[sizeof("phoenician")]; + char uniname2ctype_pool_str1321[sizeof("logicalorderexception")]; + char uniname2ctype_pool_str1323[sizeof("multani")]; + char uniname2ctype_pool_str1326[sizeof("canadianaboriginal")]; + char uniname2ctype_pool_str1327[sizeof("patternsyntax")]; + char uniname2ctype_pool_str1328[sizeof("gunjalagondi")]; + char uniname2ctype_pool_str1330[sizeof("hatr")]; + char uniname2ctype_pool_str1336[sizeof("insorasompeng")]; + char uniname2ctype_pool_str1339[sizeof("inearlydynasticcuneiform")]; + char uniname2ctype_pool_str1340[sizeof("marchen")]; + char uniname2ctype_pool_str1349[sizeof("graphemelink")]; + char uniname2ctype_pool_str1350[sizeof("sd")]; + char uniname2ctype_pool_str1353[sizeof("cher")]; + char uniname2ctype_pool_str1355[sizeof("cherokee")]; + char uniname2ctype_pool_str1357[sizeof("sidd")]; + char uniname2ctype_pool_str1359[sizeof("kaithi")]; + char uniname2ctype_pool_str1362[sizeof("inmahajani")]; + char uniname2ctype_pool_str1363[sizeof("emojimodifier")]; + char uniname2ctype_pool_str1364[sizeof("inogham")]; + char uniname2ctype_pool_str1369[sizeof("khojki")]; + char uniname2ctype_pool_str1372[sizeof("cham")]; + char uniname2ctype_pool_str1376[sizeof("chakma")]; + char uniname2ctype_pool_str1390[sizeof("khar")]; + char uniname2ctype_pool_str1392[sizeof("n")]; + char uniname2ctype_pool_str1397[sizeof("graphemebase")]; + char uniname2ctype_pool_str1408[sizeof("manichaean")]; + char uniname2ctype_pool_str1410[sizeof("no")]; + char uniname2ctype_pool_str1414[sizeof("inolchiki")]; + char uniname2ctype_pool_str1416[sizeof("nandinagari")]; + char uniname2ctype_pool_str1417[sizeof("nko")]; + char uniname2ctype_pool_str1418[sizeof("nkoo")]; + char uniname2ctype_pool_str1434[sizeof("sund")]; + char uniname2ctype_pool_str1435[sizeof("inethiopic")]; + char uniname2ctype_pool_str1437[sizeof("p")]; + char uniname2ctype_pool_str1439[sizeof("punctuation")]; + char uniname2ctype_pool_str1440[sizeof("ingreekandcoptic")]; + char uniname2ctype_pool_str1451[sizeof("inmeroitichieroglyphs")]; + char uniname2ctype_pool_str1455[sizeof("inphoenician")]; + char uniname2ctype_pool_str1456[sizeof("intangsa")]; + char uniname2ctype_pool_str1458[sizeof("adlm")]; + char uniname2ctype_pool_str1460[sizeof("insinhala")]; + char uniname2ctype_pool_str1461[sizeof("incyrillicextendeda")]; + char uniname2ctype_pool_str1466[sizeof("gujr")]; + char uniname2ctype_pool_str1476[sizeof("gujarati")]; + char uniname2ctype_pool_str1478[sizeof("inlatinextendedc")]; + char uniname2ctype_pool_str1480[sizeof("olower")]; + char uniname2ctype_pool_str1482[sizeof("enclosingmark")]; + char uniname2ctype_pool_str1484[sizeof("xpeo")]; + char uniname2ctype_pool_str1485[sizeof("khmr")]; + char uniname2ctype_pool_str1488[sizeof("olck")]; + char uniname2ctype_pool_str1490[sizeof("linb")]; + char uniname2ctype_pool_str1491[sizeof("ahom")]; + char uniname2ctype_pool_str1492[sizeof("chorasmian")]; + char uniname2ctype_pool_str1495[sizeof("zanb")]; + char uniname2ctype_pool_str1498[sizeof("inkangxiradicals")]; + char uniname2ctype_pool_str1501[sizeof("olchiki")]; + char uniname2ctype_pool_str1502[sizeof("innabataean")]; + char uniname2ctype_pool_str1504[sizeof("inkanbun")]; + char uniname2ctype_pool_str1505[sizeof("casedletter")]; + char uniname2ctype_pool_str1506[sizeof("inbhaiksuki")]; + char uniname2ctype_pool_str1513[sizeof("sunu")]; + char uniname2ctype_pool_str1516[sizeof("intaixuanjingsymbols")]; + char uniname2ctype_pool_str1520[sizeof("chrs")]; + char uniname2ctype_pool_str1521[sizeof("cpmn")]; + char uniname2ctype_pool_str1525[sizeof("beng")]; + char uniname2ctype_pool_str1526[sizeof("inscriptionalpahlavi")]; + char uniname2ctype_pool_str1527[sizeof("inelbasan")]; + char uniname2ctype_pool_str1534[sizeof("khmer")]; + char uniname2ctype_pool_str1542[sizeof("linearb")]; + char uniname2ctype_pool_str1545[sizeof("incjkunifiedideographsextensiond")]; + char uniname2ctype_pool_str1546[sizeof("emojimodifierbase")]; + char uniname2ctype_pool_str1553[sizeof("indogra")]; + char uniname2ctype_pool_str1555[sizeof("adlam")]; + char uniname2ctype_pool_str1558[sizeof("regionalindicator")]; + char uniname2ctype_pool_str1560[sizeof("kharoshthi")]; + char uniname2ctype_pool_str1562[sizeof("inphaistosdisc")]; + char uniname2ctype_pool_str1565[sizeof("lepc")]; + char uniname2ctype_pool_str1571[sizeof("xsux")]; + char uniname2ctype_pool_str1575[sizeof("ingreekextended")]; + char uniname2ctype_pool_str1583[sizeof("limb")]; + char uniname2ctype_pool_str1591[sizeof("sogo")]; + char uniname2ctype_pool_str1593[sizeof("sogdian")]; + char uniname2ctype_pool_str1595[sizeof("ll")]; + char uniname2ctype_pool_str1598[sizeof("emod")]; + char uniname2ctype_pool_str1600[sizeof("incyrillicextendedc")]; + char uniname2ctype_pool_str1602[sizeof("incyprominoan")]; + char uniname2ctype_pool_str1604[sizeof("zl")]; + char uniname2ctype_pool_str1621[sizeof("ingeometricshapes")]; + char uniname2ctype_pool_str1622[sizeof("inkhitansmallscript")]; + char uniname2ctype_pool_str1626[sizeof("math")]; + char uniname2ctype_pool_str1630[sizeof("goth")]; + char uniname2ctype_pool_str1634[sizeof("inarabic")]; + char uniname2ctype_pool_str1635[sizeof("gurungkhema")]; + char uniname2ctype_pool_str1642[sizeof("inimperialaramaic")]; + char uniname2ctype_pool_str1661[sizeof("inmiscellaneoustechnical")]; + char uniname2ctype_pool_str1665[sizeof("intamilsupplement")]; + char uniname2ctype_pool_str1668[sizeof("arab")]; + char uniname2ctype_pool_str1673[sizeof("grantha")]; + char uniname2ctype_pool_str1678[sizeof("intirhuta")]; + char uniname2ctype_pool_str1679[sizeof("inhatran")]; + char uniname2ctype_pool_str1681[sizeof("mult")]; + char uniname2ctype_pool_str1696[sizeof("intulutigalari")]; + char uniname2ctype_pool_str1704[sizeof("inbasiclatin")]; + char uniname2ctype_pool_str1705[sizeof("inoldhungarian")]; + char uniname2ctype_pool_str1706[sizeof("insogdian")]; + char uniname2ctype_pool_str1707[sizeof("indingbats")]; + char uniname2ctype_pool_str1709[sizeof("ogam")]; + char uniname2ctype_pool_str1711[sizeof("inarabicpresentationformsa")]; + char uniname2ctype_pool_str1712[sizeof("vithkuqi")]; + char uniname2ctype_pool_str1716[sizeof("kthi")]; + char uniname2ctype_pool_str1717[sizeof("brah")]; + char uniname2ctype_pool_str1719[sizeof("coptic")]; + char uniname2ctype_pool_str1723[sizeof("ideographic")]; + char uniname2ctype_pool_str1730[sizeof("emojicomponent")]; + char uniname2ctype_pool_str1731[sizeof("takri")]; + char uniname2ctype_pool_str1733[sizeof("invai")]; + char uniname2ctype_pool_str1734[sizeof("ingurungkhema")]; + char uniname2ctype_pool_str1735[sizeof("inherited")]; + char uniname2ctype_pool_str1737[sizeof("radical")]; + char uniname2ctype_pool_str1746[sizeof("dia")]; + char uniname2ctype_pool_str1748[sizeof("di")]; + char uniname2ctype_pool_str1752[sizeof("diak")]; + char uniname2ctype_pool_str1755[sizeof("sinh")]; + char uniname2ctype_pool_str1756[sizeof("glagolitic")]; + char uniname2ctype_pool_str1758[sizeof("gukh")]; + char uniname2ctype_pool_str1760[sizeof("shavian")]; + char uniname2ctype_pool_str1766[sizeof("joincontrol")]; + char uniname2ctype_pool_str1768[sizeof("takr")]; + char uniname2ctype_pool_str1774[sizeof("inhanunoo")]; + char uniname2ctype_pool_str1775[sizeof("ininscriptionalparthian")]; + char uniname2ctype_pool_str1776[sizeof("ininscriptionalpahlavi")]; + char uniname2ctype_pool_str1780[sizeof("taile")]; + char uniname2ctype_pool_str1791[sizeof("grbase")]; + char uniname2ctype_pool_str1792[sizeof("graphemeextend")]; + char uniname2ctype_pool_str1794[sizeof("imperialaramaic")]; + char uniname2ctype_pool_str1802[sizeof("copt")]; + char uniname2ctype_pool_str1807[sizeof("bidicontrol")]; + char uniname2ctype_pool_str1819[sizeof("nand")]; + char uniname2ctype_pool_str1825[sizeof("intangut")]; + char uniname2ctype_pool_str1835[sizeof("bopo")]; + char uniname2ctype_pool_str1839[sizeof("osge")]; + char uniname2ctype_pool_str1840[sizeof("cprt")]; + char uniname2ctype_pool_str1842[sizeof("orkh")]; + char uniname2ctype_pool_str1843[sizeof("sorasompeng")]; + char uniname2ctype_pool_str1844[sizeof("intags")]; + char uniname2ctype_pool_str1846[sizeof("inenclosedideographicsupplement")]; + char uniname2ctype_pool_str1848[sizeof("inoldpersian")]; + char uniname2ctype_pool_str1851[sizeof("inanatolianhieroglyphs")]; + char uniname2ctype_pool_str1852[sizeof("oldpersian")]; + char uniname2ctype_pool_str1855[sizeof("ingeometricshapesextended")]; + char uniname2ctype_pool_str1868[sizeof("inbatak")]; + char uniname2ctype_pool_str1870[sizeof("glag")]; + char uniname2ctype_pool_str1871[sizeof("bhks")]; + char uniname2ctype_pool_str1876[sizeof("inblockelements")]; + char uniname2ctype_pool_str1882[sizeof("bhaiksuki")]; + char uniname2ctype_pool_str1883[sizeof("incyrillicextendedd")]; + char uniname2ctype_pool_str1887[sizeof("term")]; + char uniname2ctype_pool_str1889[sizeof("innumberforms")]; + char uniname2ctype_pool_str1896[sizeof("intibetan")]; + char uniname2ctype_pool_str1914[sizeof("tnsa")]; + char uniname2ctype_pool_str1916[sizeof("spacingmark")]; + char uniname2ctype_pool_str1918[sizeof("tangsa")]; + char uniname2ctype_pool_str1928[sizeof("inshavian")]; + char uniname2ctype_pool_str1932[sizeof("inkanaextendedb")]; + char uniname2ctype_pool_str1944[sizeof("diacritic")]; + char uniname2ctype_pool_str1945[sizeof("bopomofo")]; + char uniname2ctype_pool_str1950[sizeof("insinhalaarchaicnumbers")]; + char uniname2ctype_pool_str1956[sizeof("space")]; + char uniname2ctype_pool_str1957[sizeof("inarabicextendeda")]; + char uniname2ctype_pool_str1959[sizeof("innushu")]; + char uniname2ctype_pool_str1966[sizeof("incjksymbolsandpunctuation")]; + char uniname2ctype_pool_str1980[sizeof("hang")]; + char uniname2ctype_pool_str1981[sizeof("inoldpermic")]; + char uniname2ctype_pool_str1988[sizeof("oldpermic")]; + char uniname2ctype_pool_str1991[sizeof("anatolianhieroglyphs")]; + char uniname2ctype_pool_str1992[sizeof("inenclosedalphanumerics")]; + char uniname2ctype_pool_str1995[sizeof("inbyzantinemusicalsymbols")]; + char uniname2ctype_pool_str1997[sizeof("ingujarati")]; + char uniname2ctype_pool_str1998[sizeof("cntrl")]; + char uniname2ctype_pool_str1999[sizeof("bugi")]; + char uniname2ctype_pool_str2002[sizeof("inmyanmarextendedb")]; + char uniname2ctype_pool_str2003[sizeof("inlatinextendedadditional")]; + char uniname2ctype_pool_str2004[sizeof("sogd")]; + char uniname2ctype_pool_str2006[sizeof("ingunjalagondi")]; + char uniname2ctype_pool_str2011[sizeof("inlisu")]; + char uniname2ctype_pool_str2015[sizeof("insundanesesupplement")]; + char uniname2ctype_pool_str2026[sizeof("separator")]; + char uniname2ctype_pool_str2030[sizeof("sarb")]; + char uniname2ctype_pool_str2033[sizeof("assigned")]; + char uniname2ctype_pool_str2035[sizeof("hiragana")]; + char uniname2ctype_pool_str2038[sizeof("inrejang")]; + char uniname2ctype_pool_str2039[sizeof("zanabazarsquare")]; + char uniname2ctype_pool_str2044[sizeof("inlatinextendedd")]; + char uniname2ctype_pool_str2046[sizeof("format")]; + char uniname2ctype_pool_str2049[sizeof("inkayahli")]; + char uniname2ctype_pool_str2051[sizeof("inoriya")]; + char uniname2ctype_pool_str2054[sizeof("ingeorgiansupplement")]; + char uniname2ctype_pool_str2055[sizeof("incoptic")]; + char uniname2ctype_pool_str2056[sizeof("intodhri")]; + char uniname2ctype_pool_str2060[sizeof("innewa")]; + char uniname2ctype_pool_str2061[sizeof("buginese")]; + char uniname2ctype_pool_str2065[sizeof("insyriacsupplement")]; + char uniname2ctype_pool_str2071[sizeof("inkawi")]; + char uniname2ctype_pool_str2073[sizeof("wara")]; + char uniname2ctype_pool_str2075[sizeof("hmng")]; + char uniname2ctype_pool_str2077[sizeof("inbraillepatterns")]; + char uniname2ctype_pool_str2078[sizeof("inmiscellaneousmathematicalsymbolsb")]; + char uniname2ctype_pool_str2093[sizeof("phli")]; + char uniname2ctype_pool_str2094[sizeof("decimalnumber")]; + char uniname2ctype_pool_str2096[sizeof("inarabicextendedc")]; + char uniname2ctype_pool_str2098[sizeof("inyezidi")]; + char uniname2ctype_pool_str2099[sizeof("braille")]; + char uniname2ctype_pool_str2100[sizeof("inornamentaldingbats")]; + char uniname2ctype_pool_str2103[sizeof("toto")]; + char uniname2ctype_pool_str2105[sizeof("idsb")]; + char uniname2ctype_pool_str2106[sizeof("variationselector")]; + char uniname2ctype_pool_str2109[sizeof("innyiakengpuachuehmong")]; + char uniname2ctype_pool_str2111[sizeof("asciihexdigit")]; + char uniname2ctype_pool_str2112[sizeof("phnx")]; + char uniname2ctype_pool_str2118[sizeof("number")]; + char uniname2ctype_pool_str2120[sizeof("inwarangciti")]; + char uniname2ctype_pool_str2127[sizeof("taiviet")]; + char uniname2ctype_pool_str2136[sizeof("caseignorable")]; + char uniname2ctype_pool_str2146[sizeof("kawi")]; + char uniname2ctype_pool_str2154[sizeof("lower")]; + char uniname2ctype_pool_str2162[sizeof("ougr")]; + char uniname2ctype_pool_str2163[sizeof("mahj")]; + char uniname2ctype_pool_str2164[sizeof("indevanagari")]; + char uniname2ctype_pool_str2166[sizeof("surrogate")]; + char uniname2ctype_pool_str2171[sizeof("lyci")]; + char uniname2ctype_pool_str2173[sizeof("mahajani")]; + char uniname2ctype_pool_str2174[sizeof("inenclosedalphanumericsupplement")]; + char uniname2ctype_pool_str2175[sizeof("lycian")]; + char uniname2ctype_pool_str2176[sizeof("sharada")]; + char uniname2ctype_pool_str2177[sizeof("mymr")]; + char uniname2ctype_pool_str2182[sizeof("myanmar")]; + char uniname2ctype_pool_str2185[sizeof("inbamum")]; + char uniname2ctype_pool_str2186[sizeof("intelugu")]; + char uniname2ctype_pool_str2187[sizeof("incjkunifiedideographsextensiong")]; + char uniname2ctype_pool_str2194[sizeof("todr")]; + char uniname2ctype_pool_str2199[sizeof("indevanagariextendeda")]; + char uniname2ctype_pool_str2203[sizeof("medf")]; + char uniname2ctype_pool_str2206[sizeof("todhri")]; + char uniname2ctype_pool_str2207[sizeof("inethiopicsupplement")]; + char uniname2ctype_pool_str2210[sizeof("inwancho")]; + char uniname2ctype_pool_str2214[sizeof("medefaidrin")]; + char uniname2ctype_pool_str2218[sizeof("shrd")]; + char uniname2ctype_pool_str2222[sizeof("inkatakanaphoneticextensions")]; + char uniname2ctype_pool_str2223[sizeof("inshorthandformatcontrols")]; + char uniname2ctype_pool_str2227[sizeof("caucasianalbanian")]; + char uniname2ctype_pool_str2231[sizeof("ahex")]; + char uniname2ctype_pool_str2233[sizeof("insymbolsforlegacycomputingsupplement")]; + char uniname2ctype_pool_str2236[sizeof("nd")]; + char uniname2ctype_pool_str2254[sizeof("insoyombo")]; + char uniname2ctype_pool_str2255[sizeof("other")]; + char uniname2ctype_pool_str2257[sizeof("otheridcontinue")]; + char uniname2ctype_pool_str2258[sizeof("khoj")]; + char uniname2ctype_pool_str2260[sizeof("avestan")]; + char uniname2ctype_pool_str2264[sizeof("othernumber")]; + char uniname2ctype_pool_str2270[sizeof("sentenceterminal")]; + char uniname2ctype_pool_str2275[sizeof("siddham")]; + char uniname2ctype_pool_str2276[sizeof("closepunctuation")]; + char uniname2ctype_pool_str2280[sizeof("lowercase")]; + char uniname2ctype_pool_str2281[sizeof("olditalic")]; + char uniname2ctype_pool_str2284[sizeof("oldhungarian")]; + char uniname2ctype_pool_str2289[sizeof("inlisusupplement")]; + char uniname2ctype_pool_str2297[sizeof("innoblock")]; + char uniname2ctype_pool_str2302[sizeof("inunifiedcanadianaboriginalsyllabicsextendeda")]; + char uniname2ctype_pool_str2303[sizeof("inelymaic")]; + char uniname2ctype_pool_str2310[sizeof("cwcm")]; + char uniname2ctype_pool_str2324[sizeof("inbalinese")]; + char uniname2ctype_pool_str2325[sizeof("invariationselectors")]; + char uniname2ctype_pool_str2327[sizeof("terminalpunctuation")]; + char uniname2ctype_pool_str2329[sizeof("inpalmyrene")]; + char uniname2ctype_pool_str2330[sizeof("alpha")]; + char uniname2ctype_pool_str2341[sizeof("inlepcha")]; + char uniname2ctype_pool_str2342[sizeof("incjkcompatibility")]; + char uniname2ctype_pool_str2349[sizeof("rjng")]; + char uniname2ctype_pool_str2350[sizeof("inhanguljamo")]; + char uniname2ctype_pool_str2355[sizeof("dsrt")]; + char uniname2ctype_pool_str2358[sizeof("inverticalforms")]; + char uniname2ctype_pool_str2359[sizeof("phag")]; + char uniname2ctype_pool_str2360[sizeof("incopticepactnumbers")]; + char uniname2ctype_pool_str2363[sizeof("incjkunifiedideographsextensionh")]; + char uniname2ctype_pool_str2366[sizeof("invedicextensions")]; + char uniname2ctype_pool_str2380[sizeof("inhanguljamoextendeda")]; + char uniname2ctype_pool_str2381[sizeof("cuneiform")]; + char uniname2ctype_pool_str2385[sizeof("inmayannumerals")]; + char uniname2ctype_pool_str2388[sizeof("otheralphabetic")]; + char uniname2ctype_pool_str2398[sizeof("hmnp")]; + char uniname2ctype_pool_str2403[sizeof("insuttonsignwriting")]; + char uniname2ctype_pool_str2415[sizeof("incombiningdiacriticalmarks")]; + char uniname2ctype_pool_str2418[sizeof("deseret")]; + char uniname2ctype_pool_str2420[sizeof("avst")]; + char uniname2ctype_pool_str2421[sizeof("inmeroiticcursive")]; + char uniname2ctype_pool_str2425[sizeof("incombiningdiacriticalmarksforsymbols")]; + char uniname2ctype_pool_str2432[sizeof("inglagolitic")]; + char uniname2ctype_pool_str2436[sizeof("vith")]; + char uniname2ctype_pool_str2450[sizeof("patsyn")]; + char uniname2ctype_pool_str2454[sizeof("lydi")]; + char uniname2ctype_pool_str2458[sizeof("lydian")]; + char uniname2ctype_pool_str2460[sizeof("oldturkic")]; + char uniname2ctype_pool_str2463[sizeof("innewtailue")]; + char uniname2ctype_pool_str2464[sizeof("hebr")]; + char uniname2ctype_pool_str2472[sizeof("intaiviet")]; + char uniname2ctype_pool_str2473[sizeof("inphagspa")]; + char uniname2ctype_pool_str2477[sizeof("inenclosedcjklettersandmonths")]; + char uniname2ctype_pool_str2481[sizeof("hung")]; + char uniname2ctype_pool_str2483[sizeof("inyiradicals")]; + char uniname2ctype_pool_str2489[sizeof("inunifiedcanadianaboriginalsyllabics")]; + char uniname2ctype_pool_str2493[sizeof("uideo")]; + char uniname2ctype_pool_str2503[sizeof("idstrinaryoperator")]; + char uniname2ctype_pool_str2504[sizeof("word")]; + char uniname2ctype_pool_str2508[sizeof("invariationselectorssupplement")]; + char uniname2ctype_pool_str2510[sizeof("java")]; + char uniname2ctype_pool_str2519[sizeof("intagalog")]; + char uniname2ctype_pool_str2539[sizeof("tale")]; + char uniname2ctype_pool_str2541[sizeof("graph")]; + char uniname2ctype_pool_str2544[sizeof("inethiopicextendeda")]; + char uniname2ctype_pool_str2545[sizeof("soyo")]; + char uniname2ctype_pool_str2550[sizeof("spaceseparator")]; + char uniname2ctype_pool_str2552[sizeof("inpaucinhau")]; + char uniname2ctype_pool_str2554[sizeof("nagm")]; + char uniname2ctype_pool_str2556[sizeof("inmongoliansupplement")]; + char uniname2ctype_pool_str2565[sizeof("oupper")]; + char uniname2ctype_pool_str2566[sizeof("inbengali")]; + char uniname2ctype_pool_str2572[sizeof("hex")]; + char uniname2ctype_pool_str2576[sizeof("javanese")]; + char uniname2ctype_pool_str2588[sizeof("oalpha")]; + char uniname2ctype_pool_str2593[sizeof("buhd")]; + char uniname2ctype_pool_str2594[sizeof("inbuginese")]; + char uniname2ctype_pool_str2597[sizeof("incjkunifiedideographsextensionb")]; + char uniname2ctype_pool_str2598[sizeof("incombiningdiacriticalmarkssupplement")]; + char uniname2ctype_pool_str2603[sizeof("insymbolsandpictographsextendeda")]; + char uniname2ctype_pool_str2605[sizeof("taml")]; + char uniname2ctype_pool_str2606[sizeof("ebase")]; + char uniname2ctype_pool_str2615[sizeof("orya")]; + char uniname2ctype_pool_str2616[sizeof("modifierletter")]; + char uniname2ctype_pool_str2620[sizeof("indevanagariextended")]; + char uniname2ctype_pool_str2624[sizeof("ext")]; + char uniname2ctype_pool_str2628[sizeof("induployan")]; + char uniname2ctype_pool_str2640[sizeof("inphoneticextensions")]; + char uniname2ctype_pool_str2642[sizeof("tirhuta")]; + char uniname2ctype_pool_str2649[sizeof("incombiningdiacriticalmarksextended")]; + char uniname2ctype_pool_str2652[sizeof("xposixpunct")]; + char uniname2ctype_pool_str2666[sizeof("injavanese")]; + char uniname2ctype_pool_str2670[sizeof("lepcha")]; + char uniname2ctype_pool_str2674[sizeof("lowercaseletter")]; + char uniname2ctype_pool_str2676[sizeof("inindicsiyaqnumbers")]; + char uniname2ctype_pool_str2679[sizeof("unassigned")]; + char uniname2ctype_pool_str2685[sizeof("ethi")]; + char uniname2ctype_pool_str2687[sizeof("titlecaseletter")]; + char uniname2ctype_pool_str2690[sizeof("rohg")]; + char uniname2ctype_pool_str2713[sizeof("syrc")]; + char uniname2ctype_pool_str2723[sizeof("inunifiedcanadianaboriginalsyllabicsextended")]; + char uniname2ctype_pool_str2733[sizeof("extender")]; + char uniname2ctype_pool_str2739[sizeof("inbrahmi")]; + char uniname2ctype_pool_str2746[sizeof("meroitichieroglyphs")]; + char uniname2ctype_pool_str2749[sizeof("otheruppercase")]; + char uniname2ctype_pool_str2773[sizeof("extpict")]; + char uniname2ctype_pool_str2779[sizeof("incjkradicalssupplement")]; + char uniname2ctype_pool_str2782[sizeof("tang")]; + char uniname2ctype_pool_str2788[sizeof("tagbanwa")]; + char uniname2ctype_pool_str2790[sizeof("zp")]; + char uniname2ctype_pool_str2792[sizeof("inaegeannumbers")]; + char uniname2ctype_pool_str2811[sizeof("nonspacingmark")]; + char uniname2ctype_pool_str2812[sizeof("ingeorgianextended")]; + char uniname2ctype_pool_str2813[sizeof("cwt")]; + char uniname2ctype_pool_str2818[sizeof("dogra")]; + char uniname2ctype_pool_str2823[sizeof("inphoneticextensionssupplement")]; + char uniname2ctype_pool_str2833[sizeof("ingothic")]; + char uniname2ctype_pool_str2849[sizeof("oldsogdian")]; + char uniname2ctype_pool_str2856[sizeof("syriac")]; + char uniname2ctype_pool_str2858[sizeof("incjkunifiedideographsextensionf")]; + char uniname2ctype_pool_str2863[sizeof("dogr")]; + char uniname2ctype_pool_str2866[sizeof("osmanya")]; + char uniname2ctype_pool_str2870[sizeof("nchar")]; + char uniname2ctype_pool_str2881[sizeof("inmathematicalalphanumericsymbols")]; + char uniname2ctype_pool_str2883[sizeof("phagspa")]; + char uniname2ctype_pool_str2884[sizeof("inlimbu")]; + char uniname2ctype_pool_str2896[sizeof("cyrl")]; + char uniname2ctype_pool_str2897[sizeof("currencysymbol")]; + char uniname2ctype_pool_str2900[sizeof("epres")]; + char uniname2ctype_pool_str2902[sizeof("inbopomofo")]; + char uniname2ctype_pool_str2916[sizeof("narb")]; + char uniname2ctype_pool_str2918[sizeof("insymbolsforlegacycomputing")]; + char uniname2ctype_pool_str2924[sizeof("mlym")]; + char uniname2ctype_pool_str2928[sizeof("insmallformvariants")]; + char uniname2ctype_pool_str2930[sizeof("intagbanwa")]; + char uniname2ctype_pool_str2931[sizeof("malayalam")]; + char uniname2ctype_pool_str2935[sizeof("incyrillicextendedb")]; + char uniname2ctype_pool_str2945[sizeof("olonal")]; + char uniname2ctype_pool_str2950[sizeof("palmyrene")]; + char uniname2ctype_pool_str2956[sizeof("thaa")]; + char uniname2ctype_pool_str2959[sizeof("otheridstart")]; + char uniname2ctype_pool_str2960[sizeof("thai")]; + char uniname2ctype_pool_str2961[sizeof("tangut")]; + char uniname2ctype_pool_str2962[sizeof("thaana")]; + char uniname2ctype_pool_str2964[sizeof("emojipresentation")]; + char uniname2ctype_pool_str2965[sizeof("inethiopicextended")]; + char uniname2ctype_pool_str2974[sizeof("nagmundari")]; + char uniname2ctype_pool_str2980[sizeof("nl")]; + char uniname2ctype_pool_str2985[sizeof("inlatin1supplement")]; + char uniname2ctype_pool_str3007[sizeof("tirh")]; + char uniname2ctype_pool_str3009[sizeof("hangul")]; + char uniname2ctype_pool_str3011[sizeof("talu")]; + char uniname2ctype_pool_str3017[sizeof("buhid")]; + char uniname2ctype_pool_str3034[sizeof("paragraphseparator")]; + char uniname2ctype_pool_str3035[sizeof("graphemeclusterbreak=spacingmark")]; + char uniname2ctype_pool_str3040[sizeof("telu")]; + char uniname2ctype_pool_str3042[sizeof("otherlowercase")]; + char uniname2ctype_pool_str3046[sizeof("ogham")]; + char uniname2ctype_pool_str3047[sizeof("changeswhencasemapped")]; + char uniname2ctype_pool_str3053[sizeof("intangutcomponents")]; + char uniname2ctype_pool_str3056[sizeof("otherletter")]; + char uniname2ctype_pool_str3060[sizeof("taitham")]; + char uniname2ctype_pool_str3068[sizeof("graphemeclusterbreak=cr")]; + char uniname2ctype_pool_str3077[sizeof("cwu")]; + char uniname2ctype_pool_str3083[sizeof("graphemeclusterbreak=regionalindicator")]; + char uniname2ctype_pool_str3096[sizeof("nushu")]; + char uniname2ctype_pool_str3103[sizeof("sunuwar")]; + char uniname2ctype_pool_str3112[sizeof("noncharactercodepoint")]; + char uniname2ctype_pool_str3114[sizeof("softdotted")]; + char uniname2ctype_pool_str3127[sizeof("omath")]; + char uniname2ctype_pool_str3129[sizeof("inbassavah")]; + char uniname2ctype_pool_str3138[sizeof("inottomansiyaqnumbers")]; + char uniname2ctype_pool_str3149[sizeof("ingaray")]; + char uniname2ctype_pool_str3151[sizeof("warangciti")]; + char uniname2ctype_pool_str3158[sizeof("ugar")]; + char uniname2ctype_pool_str3159[sizeof("inprivateusearea")]; + char uniname2ctype_pool_str3160[sizeof("inbuhid")]; + char uniname2ctype_pool_str3179[sizeof("dash")]; + char uniname2ctype_pool_str3185[sizeof("inarabicpresentationformsb")]; + char uniname2ctype_pool_str3187[sizeof("indivesakuru")]; + char uniname2ctype_pool_str3201[sizeof("hexdigit")]; + char uniname2ctype_pool_str3202[sizeof("inalphabeticpresentationforms")]; + char uniname2ctype_pool_str3205[sizeof("othersymbol")]; + char uniname2ctype_pool_str3208[sizeof("extendedpictographic")]; + char uniname2ctype_pool_str3211[sizeof("changeswhentitlecased")]; + char uniname2ctype_pool_str3218[sizeof("ogrext")]; + char uniname2ctype_pool_str3238[sizeof("nbat")]; + char uniname2ctype_pool_str3239[sizeof("insuperscriptsandsubscripts")]; + char uniname2ctype_pool_str3247[sizeof("nabataean")]; + char uniname2ctype_pool_str3253[sizeof("intangutsupplement")]; + char uniname2ctype_pool_str3254[sizeof("inlowsurrogates")]; + char uniname2ctype_pool_str3257[sizeof("inyijinghexagramsymbols")]; + char uniname2ctype_pool_str3259[sizeof("inmahjongtiles")]; + char uniname2ctype_pool_str3265[sizeof("inletterlikesymbols")]; + char uniname2ctype_pool_str3267[sizeof("inbamumsupplement")]; + char uniname2ctype_pool_str3273[sizeof("incurrencysymbols")]; + char uniname2ctype_pool_str3274[sizeof("incombininghalfmarks")]; + char uniname2ctype_pool_str3290[sizeof("wancho")]; + char uniname2ctype_pool_str3292[sizeof("inarabicsupplement")]; + char uniname2ctype_pool_str3312[sizeof("oldnortharabian")]; + char uniname2ctype_pool_str3318[sizeof("khitansmallscript")]; + char uniname2ctype_pool_str3328[sizeof("inlatinextendedg")]; + char uniname2ctype_pool_str3330[sizeof("sylo")]; + char uniname2ctype_pool_str3331[sizeof("inarabicmathematicalalphabeticsymbols")]; + char uniname2ctype_pool_str3332[sizeof("nshu")]; + char uniname2ctype_pool_str3340[sizeof("elba")]; + char uniname2ctype_pool_str3344[sizeof("invithkuqi")]; + char uniname2ctype_pool_str3357[sizeof("inhangulsyllables")]; + char uniname2ctype_pool_str3361[sizeof("changeswhenuppercased")]; + char uniname2ctype_pool_str3371[sizeof("intifinagh")]; + char uniname2ctype_pool_str3389[sizeof("graphemeclusterbreak=t")]; + char uniname2ctype_pool_str3391[sizeof("graphemeclusterbreak=lvt")]; + char uniname2ctype_pool_str3401[sizeof("tamil")]; + char uniname2ctype_pool_str3402[sizeof("mathsymbol")]; + char uniname2ctype_pool_str3403[sizeof("tulutigalari")]; + char uniname2ctype_pool_str3405[sizeof("otherdefaultignorablecodepoint")]; + char uniname2ctype_pool_str3414[sizeof("wcho")]; + char uniname2ctype_pool_str3422[sizeof("insupplementalarrowsa")]; + char uniname2ctype_pool_str3431[sizeof("inarabicextendedb")]; + char uniname2ctype_pool_str3446[sizeof("rejang")]; + char uniname2ctype_pool_str3447[sizeof("graphemeclusterbreak=extend")]; + char uniname2ctype_pool_str3448[sizeof("graphemeclusterbreak=prepend")]; + char uniname2ctype_pool_str3455[sizeof("finalpunctuation")]; + char uniname2ctype_pool_str3460[sizeof("inpsalterpahlavi")]; + char uniname2ctype_pool_str3463[sizeof("newa")]; + char uniname2ctype_pool_str3464[sizeof("inmathematicaloperators")]; + char uniname2ctype_pool_str3476[sizeof("phlp")]; + char uniname2ctype_pool_str3480[sizeof("deva")]; + char uniname2ctype_pool_str3494[sizeof("devanagari")]; + char uniname2ctype_pool_str3503[sizeof("newtailue")]; + char uniname2ctype_pool_str3504[sizeof("cf")]; + char uniname2ctype_pool_str3522[sizeof("pf")]; + char uniname2ctype_pool_str3532[sizeof("whitespace")]; + char uniname2ctype_pool_str3543[sizeof("elbasan")]; + char uniname2ctype_pool_str3548[sizeof("othermath")]; + char uniname2ctype_pool_str3551[sizeof("digit")]; + char uniname2ctype_pool_str3557[sizeof("cyprominoan")]; + char uniname2ctype_pool_str3561[sizeof("insupplementalarrowsc")]; + char uniname2ctype_pool_str3563[sizeof("tibt")]; + char uniname2ctype_pool_str3570[sizeof("tibetan")]; + char uniname2ctype_pool_str3580[sizeof("bassavah")]; + char uniname2ctype_pool_str3585[sizeof("insupplementalmathematicaloperators")]; + char uniname2ctype_pool_str3613[sizeof("otherpunctuation")]; + char uniname2ctype_pool_str3614[sizeof("sgnw")]; + char uniname2ctype_pool_str3629[sizeof("ugaritic")]; + char uniname2ctype_pool_str3650[sizeof("tutg")]; + char uniname2ctype_pool_str3654[sizeof("changeswhenlowercased")]; + char uniname2ctype_pool_str3663[sizeof("cwl")]; + char uniname2ctype_pool_str3670[sizeof("inlinearbsyllabary")]; + char uniname2ctype_pool_str3676[sizeof("inplayingcards")]; + char uniname2ctype_pool_str3689[sizeof("modifiercombiningmark")]; + char uniname2ctype_pool_str3707[sizeof("sylotinagri")]; + char uniname2ctype_pool_str3714[sizeof("idcompatmathcontinue")]; + char uniname2ctype_pool_str3720[sizeof("inpahawhhmong")]; + char uniname2ctype_pool_str3729[sizeof("idcompatmathstart")]; + char uniname2ctype_pool_str3732[sizeof("hanifirohingya")]; + char uniname2ctype_pool_str3757[sizeof("deprecated")]; + char uniname2ctype_pool_str3766[sizeof("oldsoutharabian")]; + char uniname2ctype_pool_str3788[sizeof("shaw")]; + char uniname2ctype_pool_str3793[sizeof("tavt")]; + char uniname2ctype_pool_str3810[sizeof("wspace")]; + char uniname2ctype_pool_str3814[sizeof("graphemeclusterbreak=l")]; + char uniname2ctype_pool_str3820[sizeof("graphemeclusterbreak=control")]; + char uniname2ctype_pool_str3829[sizeof("cypriot")]; + char uniname2ctype_pool_str3835[sizeof("cyrillic")]; + char uniname2ctype_pool_str3854[sizeof("inhanguljamoextendedb")]; + char uniname2ctype_pool_str3877[sizeof("inalchemicalsymbols")]; + char uniname2ctype_pool_str3882[sizeof("insupplementalpunctuation")]; + char uniname2ctype_pool_str3894[sizeof("khudawadi")]; + char uniname2ctype_pool_str3925[sizeof("aghb")]; + char uniname2ctype_pool_str3928[sizeof("graphemeclusterbreak=zwj")]; + char uniname2ctype_pool_str3949[sizeof("alphabetic")]; + char uniname2ctype_pool_str3950[sizeof("cwcf")]; + char uniname2ctype_pool_str3979[sizeof("elym")]; + char uniname2ctype_pool_str3996[sizeof("ecomp")]; + char uniname2ctype_pool_str4018[sizeof("inethiopicextendedb")]; + char uniname2ctype_pool_str4032[sizeof("elymaic")]; + char uniname2ctype_pool_str4060[sizeof("inglagoliticsupplement")]; + char uniname2ctype_pool_str4097[sizeof("garay")]; + char uniname2ctype_pool_str4109[sizeof("unknown")]; + char uniname2ctype_pool_str4119[sizeof("soyombo")]; + char uniname2ctype_pool_str4148[sizeof("inlatinextendedb")]; + char uniname2ctype_pool_str4160[sizeof("divesakuru")]; + char uniname2ctype_pool_str4164[sizeof("kayahli")]; + char uniname2ctype_pool_str4175[sizeof("othergraphemeextend")]; + char uniname2ctype_pool_str4179[sizeof("inhighprivateusesurrogates")]; + char uniname2ctype_pool_str4184[sizeof("any")]; + char uniname2ctype_pool_str4212[sizeof("dashpunctuation")]; + char uniname2ctype_pool_str4222[sizeof("ethiopic")]; + char uniname2ctype_pool_str4223[sizeof("symbol")]; + char uniname2ctype_pool_str4239[sizeof("openpunctuation")]; + char uniname2ctype_pool_str4248[sizeof("hluw")]; + char uniname2ctype_pool_str4254[sizeof("tagb")]; + char uniname2ctype_pool_str4356[sizeof("hyphen")]; + char uniname2ctype_pool_str4418[sizeof("incypriotsyllabary")]; + char uniname2ctype_pool_str4425[sizeof("dupl")]; + char uniname2ctype_pool_str4468[sizeof("modifiersymbol")]; + char uniname2ctype_pool_str4484[sizeof("inyisyllables")]; + char uniname2ctype_pool_str4509[sizeof("inhalfwidthandfullwidthforms")]; + char uniname2ctype_pool_str4517[sizeof("tfng")]; + char uniname2ctype_pool_str4545[sizeof("dep")]; + char uniname2ctype_pool_str4547[sizeof("inegyptianhieroglyphsextendeda")]; + char uniname2ctype_pool_str4562[sizeof("inbopomofoextended")]; + char uniname2ctype_pool_str4609[sizeof("telugu")]; + char uniname2ctype_pool_str4638[sizeof("tglg")]; + char uniname2ctype_pool_str4652[sizeof("tagalog")]; + char uniname2ctype_pool_str4670[sizeof("inlatinextendedf")]; + char uniname2ctype_pool_str4687[sizeof("changeswhencasefolded")]; + char uniname2ctype_pool_str4703[sizeof("tifinagh")]; + char uniname2ctype_pool_str4728[sizeof("graphemeclusterbreak=v")]; + char uniname2ctype_pool_str4729[sizeof("graphemeclusterbreak=lv")]; + char uniname2ctype_pool_str4734[sizeof("inegyptianhieroglyphs")]; + char uniname2ctype_pool_str4736[sizeof("signwriting")]; + char uniname2ctype_pool_str4747[sizeof("inegyptianhieroglyphformatcontrols")]; + char uniname2ctype_pool_str4756[sizeof("graphemeclusterbreak=lf")]; + char uniname2ctype_pool_str4771[sizeof("insupplementaryprivateuseareaa")]; + char uniname2ctype_pool_str4821[sizeof("inhebrew")]; + char uniname2ctype_pool_str4865[sizeof("inboxdrawing")]; + char uniname2ctype_pool_str4896[sizeof("insupplementalarrowsb")]; + char uniname2ctype_pool_str4902[sizeof("olduyghur")]; + char uniname2ctype_pool_str4917[sizeof("upper")]; + char uniname2ctype_pool_str5031[sizeof("inhighsurrogates")]; + char uniname2ctype_pool_str5043[sizeof("uppercase")]; + char uniname2ctype_pool_str5216[sizeof("inhangulcompatibilityjamo")]; + char uniname2ctype_pool_str5272[sizeof("defaultignorablecodepoint")]; + char uniname2ctype_pool_str5437[sizeof("uppercaseletter")]; + char uniname2ctype_pool_str5541[sizeof("egyp")]; + char uniname2ctype_pool_str5603[sizeof("insupplementalsymbolsandpictographs")]; + char uniname2ctype_pool_str5646[sizeof("unifiedideograph")]; + char uniname2ctype_pool_str5647[sizeof("pahawhhmong")]; + char uniname2ctype_pool_str5666[sizeof("duployan")]; + char uniname2ctype_pool_str5914[sizeof("nyiakengpuachuehmong")]; + char uniname2ctype_pool_str6073[sizeof("zyyy")]; + char uniname2ctype_pool_str6245[sizeof("insupplementaryprivateuseareab")]; + char uniname2ctype_pool_str6528[sizeof("hebrew")]; + char uniname2ctype_pool_str6807[sizeof("egyptianhieroglyphs")]; #endif /* USE_UNICODE_PROPERTIES */ }; static const struct uniname2ctype_pool_t uniname2ctype_pool_contents = @@ -42763,943 +45485,968 @@ static const struct uniname2ctype_pool_t uniname2ctype_pool_contents = #ifndef USE_UNICODE_PROPERTIES "word", #else /* USE_UNICODE_PROPERTIES */ - "yi", - "yiii", "lana", "lina", + "yi", + "mn", "maka", "mani", - "mn", - "miao", + "yiii", "lo", - "ci", "lao", "laoo", + "miao", "inkannada", + "innko", "cn", + "ci", + "co", + "gara", "pi", - "innko", - "z", "gran", - "co", + "z", "lineara", "mark", - "yezi", "po", "me", - "cari", - "inkharoshthi", - "kana", "loe", - "m", - "grek", + "inkiratrai", "mro", "mroo", + "inkharoshthi", + "cari", "carian", + "grek", + "yezi", "geor", "greek", - "gonm", "mendekikakui", - "pe", "mero", + "kana", + "m", + "pe", + "gonm", + "meeteimayek", "inosmanya", - "cakm", - "inmanichaean", "inmro", + "inmanichaean", "inmiao", - "inchakma", - "c", - "mandaic", - "meeteimayek", - "zzzz", + "cakm", "inarmenian", + "krai", + "common", + "inchakma", "inmyanmar", + "mandaic", "inmakasar", - "common", + "c", + "zzzz", + "inideographicsymbolsandpunctuation", + "inkhmer", "lm", "marc", + "qaai", + "combiningmark", "inrunic", "incarian", - "inideographicsymbolsandpunctuation", - "inkhmer", - "qaai", "inahom", - "merc", + "prependedconcatenationmark", "inchorasmian", - "combiningmark", - "lc", "perm", - "mc", - "connectorpunctuation", + "merc", "cans", - "incuneiformnumbersandpunctuation", - "armi", - "cc", - "armn", - "incherokee", - "prependedconcatenationmark", - "incuneiform", + "connectorpunctuation", "inavestan", + "incuneiformnumbersandpunctuation", "inipaextensions", - "pc", - "armenian", "insharada", - "vai", - "vaii", - "inmarchen", + "incherokee", "makasar", - "masaramgondi", "inarrows", - "incyrillic", - "incham", + "masaramgondi", + "lc", + "incuneiform", + "armn", + "mc", + "armi", + "armenian", + "inmarchen", + "lineseparator", "qmark", - "ri", - "qaac", + "cc", "insamaritan", - "latn", "inmasaramgondi", - "inthaana", + "pc", + "inscriptionalparthian", + "qaac", + "mcm", + "incham", + "incyrillic", + "inzanabazarsquare", + "inkhmersymbols", + "latn", + "ri", + "pcm", "latin", + "inthaana", "inthai", - "lineseparator", - "pcm", "inkatakana", "inkaithi", - "inscriptionalparthian", - "initialpunctuation", - "mtei", - "inzanabazarsquare", - "inkhmersymbols", "insyriac", - "intakri", - "arabic", - "katakana", - "prti", "zs", - "ascii", + "initialpunctuation", + "mtei", "cs", - "ps", "mand", - "privateuse", - "inruminumeralsymbols", - "inmyanmarextendeda", + "ps", + "intakri", "modi", - "incjkcompatibilityforms", "inkanaextendeda", - "incjkcompatibilityideographs", - "brai", "mend", + "inruminumeralsymbols", "ideo", - "letter", - "l", - "inmeeteimayek", + "prti", + "arabic", + "brai", + "katakana", "inideographicdescriptioncharacters", + "ascii", + "innandinagari", + "privateuse", + "inoldnortharabian", + "sk", + "so", + "incjkcompatibilityforms", "yezidi", "knda", - "innandinagari", + "inmyanmarextendeda", + "incjkcompatibilityideographs", "kannada", - "inmodi", - "inlao", "xidcontinue", - "inoldnortharabian", - "intransportandmapsymbols", - "letternumber", - "gothic", - "inlineara", + "letter", + "inmodi", + "inmeeteimayek", "inmendekikakui", - "mongolian", - "inmiscellaneousmathematicalsymbolsa", + "onao", + "sora", + "inmedefaidrin", + "kiratrai", "inspecials", - "grlink", "brahmi", - "inemoticons", - "kali", + "letternumber", + "inchesssymbols", "inolditalic", + "oriya", + "inmiscellaneousmathematicalsymbolsa", + "intransportandmapsymbols", + "incb=extend", "xidc", - "inmedefaidrin", - "inchesssymbols", - "incjkcompatibilityideographssupplement", - "kits", - "inadlam", - "psalterpahlavi", - "incommonindicnumberforms", - "lt", - "innewa", - "sk", - "control", - "inkawi", + "inemoticons", + "samr", + "inoldsogdian", "inancientsymbols", - "palm", - "inlycian", - "so", - "patternwhitespace", + "incommonindicnumberforms", + "samaritan", + "psalterpahlavi", + "inmyanmarextendedc", + "kits", + "insundanese", + "incb=consonant", + "gothic", "inmandaic", - "idc", - "meroiticcursive", - "intoto", - "vs", "xids", - "inwarangciti", - "sora", - "inopticalcharacterrecognition", - "kawi", - "inoldsogdian", - "inmalayalam", - "bamum", - "inkanasupplement", - "insundanese", - "grext", -#endif /* USE_UNICODE_PROPERTIES */ - "print", -#ifndef USE_UNICODE_PROPERTIES - "punct", - "alpha", -#else /* USE_UNICODE_PROPERTIES */ - "intaitham", - "lower", - "patternsyntax", - "joinc", - "inoldsoutharabian", - "incjkstrokes", - "batk", - "samr", - "inwancho", - "batak", - "patws", - "samaritan", - "idsbinaryoperator", + "inznamennymusicalnotation", "pauc", - "insmallkanaextension", "sm", - "indominotiles", -#endif /* USE_UNICODE_PROPERTIES */ - "alnum", -#ifdef USE_UNICODE_PROPERTIES - "inznamennymusicalnotation", - "insylotinagri", - "inugaritic", - "incontrolpictures", - "inlinearbideograms", - "inmusicalsymbols", "s", - "ital", - "inmodifiertoneletters", - "inancientgreekmusicalnotation", + "meroiticcursive", + "inoldsoutharabian", + "inugaritic", "lisu", - "lowercase", - "cwcm", + "idc", + "incjkcompatibilityideographssupplement", + "patternwhitespace", + "bamum", + "inancientgreekmusicalnotation", + "idsbinaryoperator", + "lt", + "incjkstrokes", + "insunuwar", + "insaurashtra", + "indominotiles", + "intoto", "sc", + "idsunaryoperator", + "inmodifiertoneletters", + "inopticalcharacterrecognition", + "l", + "batk", + "inkanasupplement", + "osage", + "batak", + "inmusicalsymbols", + "incaucasianalbanian", + "patws", "bass", "ids", - "inlatinextendeda", - "intaile", + "grext", + "inlao", + "vai", + "vaii", + "inolonal", + "mongolian", + "osma", +#endif /* USE_UNICODE_PROPERTIES */ + "print", +#ifndef USE_UNICODE_PROPERTIES + "punct", + "alpha", +#else /* USE_UNICODE_PROPERTIES */ + "inlineara", + "intaitham", + "grlink", "inmiscellaneoussymbols", + "pd", "inmiscellaneoussymbolsandarrows", - "incaucasianalbanian", + "kali", "inmiscellaneoussymbolsandpictographs", + "control", + "inancientgreeknumbers", + "incontrolpictures", + "inadlam", + "han", + "hani", + "hano", + "runr", + "sind", + "hanunoo", + "palm", + "inkhojki", + "inkhudawadi", + "inlycian", "inoldturkic", - "insaurashtra", - "incyrillicextendeda", + "hira", + "incountingrodnumerals", + "odi", "idcontinue", - "intaixuanjingsymbols", - "intamil", - "inmultani", - "inlatinextendede", - "pd", - "bali", - "blank", "idst", - "inlydian", - "innewtailue", - "bengali", - "runr", - "ll", + "inolduyghur", + "incb=linker", + "inmalayalam", + "lu", + "inspacingmodifierletters", + "bamu", "indeseret", - "inancientgreeknumbers", + "sundanese", "idstart", - "zl", - "inmeeteimayekextensions", - "balinese", - "incyrillicextendedc", - "inspacingmodifierletters", - "inearlydynasticcuneiform", - "plrd", - "canadianaboriginal", - "sind", - "inlatinextendedc", - "uideo", - "incountingrodnumerals", - "zinh", - "dia", - "di", - "inkhudawadi", - "inhanifirohingya", - "diak", + "saur", + "insmallkanaextension", + "guru", + "paucinhau", + "gurmukhi", + "insylotinagri", + "cased", + "inlinearbideograms", "gong", "ingrantha", - "bidic", - "xidstart", -#endif /* USE_UNICODE_PROPERTIES */ - "xdigit", -#ifndef USE_UNICODE_PROPERTIES - "upper", - "ascii", -#else /* USE_UNICODE_PROPERTIES */ "mong", - "cased", - "inhiragana", - "sinhala", - "adlm", - "xsux", - "glagolitic", + "joinc", "sterm", - "bamu", - "georgian", + "inkaktoviknumerals", + "limbu", + "oidc", "inosage", - "gunjalagondi", - "phoenician", - "inolduyghur", - "multani", - "kaithi", - "joincontrol", - "runic", - "ingeneralpunctuation", - "inmahajani", + "incjkunifiedideographsextensiona", "incyrillicsupplement", - "lowercaseletter", - "marchen", - "graphemelink", + "inmeeteimayekextensions", + "georgian", + "incjkunifiedideographsextensioni", + "idsu", + "ingeneralpunctuation", +#endif /* USE_UNICODE_PROPERTIES */ + "alnum", +#ifdef USE_UNICODE_PROPERTIES + "bidic", "ingeorgian", - "khojki", - "cham", - "inogham", - "cher", - "chakma", - "inkaktoviknumerals", - "emoji", + "quotationmark", + "incherokeesupplement", + "incjkunifiedideographsextensione", "insiddham", - "cherokee", - "khar", + "runic", + "oids", + "ital", + "emoji", "inmongolian", "innagmundari", - "incherokeesupplement", - "manichaean", - "inolchiki", - "inkhitansmallscript", - "quotationmark", - "vithkuqi", - "variationselector", - "adlam", - "inethiopic", - "graphemebase", + "inlatinextendeda", + "vs", + "saurashtra", + "intaile", + "bali", + "xidstart", +#endif /* USE_UNICODE_PROPERTIES */ + "xdigit", +#ifndef USE_UNICODE_PROPERTIES + "upper", + "ascii", + "cntrl", +#else /* USE_UNICODE_PROPERTIES */ + "ingurmukhi", + "blank", + "inlydian", #ifdef USE_UNICODE_AGE_PROPERTIES "age=11.0", - "age=12.1", "age=10.0", + "age=12.1", "age=12.0", - "age=13.0", "age=1.1", -#endif /* USE_UNICODE_AGE_PROPERTIES */ - "casedletter", - "ingurmukhi", -#ifdef USE_UNICODE_AGE_PROPERTIES + "age=16.0", + "age=9.0", "age=2.1", -#endif /* USE_UNICODE_AGE_PROPERTIES */ - "incjkunifiedideographsextensiona", -#ifdef USE_UNICODE_AGE_PROPERTIES "age=2.0", -#endif /* USE_UNICODE_AGE_PROPERTIES */ - "lu", -#ifdef USE_UNICODE_AGE_PROPERTIES - "age=3.1", - "age=9.0", - "age=3.0", - "age=3.2", - "age=8.0", -#endif /* USE_UNICODE_AGE_PROPERTIES */ - "intamilsupplement", -#ifdef USE_UNICODE_AGE_PROPERTIES "age=6.1", + "age=6.0", #endif /* USE_UNICODE_AGE_PROPERTIES */ - "unknown", + "inlatinextendede", #ifdef USE_UNICODE_AGE_PROPERTIES - "age=6.0", "age=6.2", - "age=15.0", + "age=8.0", "age=7.0", - "age=6.3", -#endif /* USE_UNICODE_AGE_PROPERTIES */ - "cwt", -#ifdef USE_UNICODE_AGE_PROPERTIES - "age=14.0", #endif /* USE_UNICODE_AGE_PROPERTIES */ - "unassigned", + "incjkunifiedideographsextensionc", + "bengali", + "zinh", #ifdef USE_UNICODE_AGE_PROPERTIES + "age=15.1", + "age=15.0", "age=5.1", "age=5.0", + "age=14.0", "age=5.2", + "age=4.1", + "age=4.0", #endif /* USE_UNICODE_AGE_PROPERTIES */ - "diacritic", + "inhanifirohingya", + "intamil", + "inmultani", #ifdef USE_UNICODE_AGE_PROPERTIES - "age=4.1", + "age=13.0", #endif /* USE_UNICODE_AGE_PROPERTIES */ - "ahom", + "balinese", + "hatran", #ifdef USE_UNICODE_AGE_PROPERTIES - "age=4.0", + "age=3.1", + "age=3.0", + "age=3.2", + "age=6.3", #endif /* USE_UNICODE_AGE_PROPERTIES */ - "incjkunifiedideographsextensione", - "khmr", - "insinhala", - "inmiscellaneoustechnical", - "saur", - "guru", - "sundanese", "punct", - "paucinhau", - "gurmukhi", - "chorasmian", + "incjkunifiedideographs", + "inhiragana", + "sinhala", + "plrd", + "phoenician", "logicalorderexception", - "khmer", - "limbu", - "chrs", - "oriya", - "inscriptionalpahlavi", - "incyrillicextendedd", - "incjkunifiedideographsextensionc", -#endif /* USE_UNICODE_PROPERTIES */ - "cntrl", -#ifndef USE_UNICODE_PROPERTIES - "space", -#else /* USE_UNICODE_PROPERTIES */ - "inlatinextendedadditional", + "multani", + "canadianaboriginal", + "patternsyntax", + "gunjalagondi", + "hatr", "insorasompeng", - "radical", + "inearlydynasticcuneiform", + "marchen", + "graphemelink", + "sd", + "cher", + "cherokee", + "sidd", + "kaithi", + "inmahajani", "emojimodifier", - "kharoshthi", + "inogham", + "khojki", + "cham", + "chakma", + "khar", "n", - "math", - "goth", - "phnx", - "anatolianhieroglyphs", - "inenclosedalphanumerics", - "nandinagari", + "graphemebase", + "manichaean", "no", - "intangsa", + "inolchiki", + "nandinagari", "nko", "nkoo", - "ingreekandcoptic", + "sund", + "inethiopic", "p", - "grantha", - "decimalnumber", - "incjkunifiedideographs", - "intirhuta", - "inhatran", + "punctuation", + "ingreekandcoptic", + "inmeroitichieroglyphs", + "inphoenician", + "intangsa", + "adlm", + "insinhala", + "incyrillicextendeda", + "gujr", + "gujarati", + "inlatinextendedc", + "olower", + "enclosingmark", + "xpeo", + "khmr", + "olck", "linb", - "mult", - "saurashtra", - "kthi", + "ahom", + "chorasmian", "zanb", - "inbhaiksuki", + "inkangxiradicals", + "olchiki", "innabataean", - "inphoenician", - "xpeo", "inkanbun", - "inmeroitichieroglyphs", - "ahex", - "enclosingmark", - "sd", - "inelbasan", - "inenclosedideographicsupplement", - "sidd", - "linearb", + "casedletter", + "inbhaiksuki", + "sunu", + "intaixuanjingsymbols", + "chrs", "cpmn", - "inenclosedalphanumericsupplement", - "bidicontrol", - "inphaistosdisc", - "limb", - "inkangxiradicals", - "lepc", - "braille", - "regionalindicator", - "inlowsurrogates", - "brah", - "inoldhungarian", "beng", + "inscriptionalpahlavi", + "inelbasan", + "khmer", + "linearb", + "incjkunifiedideographsextensiond", "emojimodifierbase", - "inarabic", - "osage", - "inherited", - "incyprominoan", - "glag", - "medf", - "osma", "indogra", - "arab", - "medefaidrin", - "inshorthandformatcontrols", - "phli", - "inimperialaramaic", - "emod", + "adlam", + "regionalindicator", + "kharoshthi", + "inphaistosdisc", + "lepc", + "xsux", "ingreekextended", - "inanatolianhieroglyphs", - "punctuation", - "graphemeextend", - "cwl", - "vith", + "limb", + "sogo", + "sogdian", + "ll", + "emod", + "incyrillicextendedc", + "incyprominoan", + "zl", "ingeometricshapes", - "emojicomponent", - "dsrt", - "coptic", - "inkayahli", - "inoriya", - "inarabicpresentationformsa", + "inkhitansmallscript", + "math", + "goth", + "inarabic", + "gurungkhema", + "inimperialaramaic", + "inmiscellaneoustechnical", + "intamilsupplement", + "arab", + "grantha", + "intirhuta", + "inhatran", + "mult", + "intulutigalari", "inbasiclatin", - "incjkunifiedideographsextensiond", - "wara", + "inoldhungarian", + "insogdian", + "indingbats", + "ogam", + "inarabicpresentationformsa", + "vithkuqi", + "kthi", + "brah", + "coptic", + "ideographic", + "emojicomponent", + "takri", + "invai", + "ingurungkhema", + "inherited", + "radical", + "dia", + "di", + "diak", "sinh", - "sund", + "glagolitic", + "gukh", "shavian", - "insundanesesupplement", - "inyezidi", - "bhks", - "bhaiksuki", + "joincontrol", + "takr", "inhanunoo", - "intangut", - "sogdian", - "inlatinextendedd", - "sogo", - "insinhalaarchaicnumbers", - "ideographic", - "ugar", - "deseret", - "odi", - "copt", - "imperialaramaic", - "insogdian", - "indingbats", - "format", - "ininscriptionalpahlavi", - "lyci", "ininscriptionalparthian", + "ininscriptionalpahlavi", + "taile", "grbase", - "lycian", - "inbatak", - "cprt", - "inunifiedcanadianaboriginalsyllabicsextendeda", - "mymr", - "myanmar", - "intibetan", - "intags", - "asciihexdigit", - "sentenceterminal", + "graphemeextend", + "imperialaramaic", + "copt", + "bidicontrol", "nand", - "inblockelements", - "inornamentaldingbats", - "inethiopicextendeda", - "innumberforms", - "cwcf", - "oidc", + "intangut", "bopo", - "cuneiform", - "caseignorable", + "osge", + "cprt", + "orkh", + "sorasompeng", + "intags", + "inenclosedideographicsupplement", "inoldpersian", - "cwu", - "inelymaic", - "insoyombo", + "inanatolianhieroglyphs", + "oldpersian", "ingeometricshapesextended", - "incjkcompatibility", - "inmyanmarextendedb", - "innushu", - "inkanaextendedb", - "olck", - "inbyzantinemusicalsymbols", - "olchiki", - "inkatakanaphoneticextensions", - "incoptic", - "oids", - "inarabicextendeda", - "modifierletter", - "incjksymbolsandpunctuation", - "olower", - "bopomofo", - "inlisu", - "inoldpermic", - "innoblock", - "ext", - "inunifiedcanadianaboriginalsyllabics", - "takri", - "inbraillepatterns", - "invai", - "alpha", - "inbalinese", - "sorasompeng", - "closepunctuation", - "hani", - "inmayannumerals", - "han", - "inmiscellaneousmathematicalsymbolsb", - "inlepcha", - "patsyn", - "inlisusupplement", - "insyriacsupplement", - "hano", - "newa", + "inbatak", + "glag", + "bhks", + "inblockelements", + "bhaiksuki", + "incyrillicextendedd", + "term", + "innumberforms", + "intibetan", + "tnsa", "spacingmark", - "inpalmyrene", - "takr", + "tangsa", + "inshavian", + "inkanaextendedb", + "diacritic", + "bopomofo", + "insinhalaarchaicnumbers", #endif /* USE_UNICODE_PROPERTIES */ - "xposixpunct", + "space", #ifndef USE_UNICODE_PROPERTIES - "lower", + "xposixpunct", #else /* USE_UNICODE_PROPERTIES */ - "inkhojki", - "taile", - "assigned", - "hanunoo", - "hira", - "inarabicextendedc", - "newtailue", - "space", - "intelugu", - "lydi", - "idsb", - "extpict", - "lydian", - "inethiopicsupplement", - "sarb", - "ugaritic", - "inyiradicals", - "inphoneticextensions", - "sharada", - "zanabazarsquare", + "inarabicextendeda", + "innushu", + "incjksymbolsandpunctuation", + "hang", + "inoldpermic", + "oldpermic", + "anatolianhieroglyphs", + "inenclosedalphanumerics", + "inbyzantinemusicalsymbols", + "ingujarati", + "cntrl", "bugi", - "word", - "term", + "inmyanmarextendedb", + "inlatinextendedadditional", + "sogd", + "ingunjalagondi", + "inlisu", + "insundanesesupplement", "separator", + "sarb", + "assigned", + "hiragana", + "inrejang", + "zanabazarsquare", + "inlatinextendedd", + "format", + "inkayahli", + "inoriya", "ingeorgiansupplement", - "sogd", - "extender", - "shrd", -#endif /* USE_UNICODE_PROPERTIES */ - "graph", -#ifdef USE_UNICODE_PROPERTIES - "tnsa", - "tangsa", - "phag", - "dogra", - "inhanguljamo", - "inshavian", - "siddham", - "cf", - "inunifiedcanadianaboriginalsyllabicsextended", + "incoptic", + "intodhri", + "innewa", "buginese", - "inmongoliansupplement", - "cyrl", - "inhanguljamoextendeda", - "pf", + "insyriacsupplement", + "inkawi", + "wara", + "hmng", + "inbraillepatterns", + "inmiscellaneousmathematicalsymbolsb", + "phli", + "decimalnumber", + "inarabicextendedc", + "inyezidi", + "braille", + "inornamentaldingbats", + "toto", + "idsb", + "variationselector", + "innyiakengpuachuehmong", + "asciihexdigit", + "phnx", "number", - "inphoneticextensionssupplement", - "dogr", - "mlym", - "incopticepactnumbers", - "malayalam", + "inwarangciti", + "taiviet", + "caseignorable", + "kawi", +#endif /* USE_UNICODE_PROPERTIES */ + "lower", +#ifdef USE_UNICODE_PROPERTIES + "ougr", + "mahj", + "indevanagari", + "surrogate", + "lyci", + "mahajani", + "inenclosedalphanumericsupplement", + "lycian", + "sharada", + "mymr", + "myanmar", "inbamum", + "intelugu", + "incjkunifiedideographsextensiong", + "todr", + "indevanagariextendeda", + "medf", + "todhri", + "inethiopicsupplement", + "inwancho", + "medefaidrin", + "shrd", + "inkatakanaphoneticextensions", + "inshorthandformatcontrols", + "caucasianalbanian", + "ahex", + "insymbolsforlegacycomputingsupplement", "nd", - "insuttonsignwriting", - "inethiopicextended", - "shaw", - "palmyrene", - "soyo", + "insoyombo", + "other", + "otheridcontinue", + "khoj", + "avestan", + "othernumber", + "sentenceterminal", + "siddham", + "closepunctuation", + "lowercase", + "olditalic", + "oldhungarian", + "inlisusupplement", + "innoblock", + "inunifiedcanadianaboriginalsyllabicsextendeda", + "inelymaic", + "cwcm", + "inbalinese", + "invariationselectors", + "terminalpunctuation", + "inpalmyrene", + "alpha", + "inlepcha", + "incjkcompatibility", + "rjng", + "inhanguljamo", + "dsrt", + "inverticalforms", + "phag", + "incopticepactnumbers", "incjkunifiedideographsextensionh", - "sgnw", - "toto", - "caucasianalbanian", - "inmathematicalalphanumericsymbols", - "incjkunifiedideographsextensiong", - "hatran", - "taiviet", - "meroitichieroglyphs", - "ingeorgianextended", - "incjkunifiedideographsextensionf", - "oldpersian", - "induployan", - "incyrillicextendedb", - "dash", - "hatr", - "innyiakengpuachuehmong", + "invedicextensions", + "inhanguljamoextendeda", + "cuneiform", + "inmayannumerals", + "otheralphabetic", + "hmnp", + "insuttonsignwriting", "incombiningdiacriticalmarks", - "nl", + "deseret", + "avst", + "inmeroiticcursive", "incombiningdiacriticalmarksforsymbols", - "khudawadi", - "incjkradicalssupplement", "inglagolitic", - "orkh", - "syrc", - "surrogate", - "indevanagari", - "avestan", - "oldpermic", - "ethi", - "ogam", - "rohg", + "vith", + "patsyn", + "lydi", + "lydian", + "oldturkic", + "innewtailue", + "hebr", + "intaiviet", + "inphagspa", + "inenclosedcjklettersandmonths", + "hung", + "inyiradicals", + "inunifiedcanadianaboriginalsyllabics", + "uideo", "idstrinaryoperator", + "word", + "invariationselectorssupplement", "java", - "inphagspa", - "lepcha", - "indevanagariextendeda", - "intifinagh", "intagalog", - "incombiningdiacriticalmarkssupplement", "tale", - "inbrahmi", - "terminalpunctuation", - "insymbolsandpictographsextendeda", - "syriac", - "inbengali", +#endif /* USE_UNICODE_PROPERTIES */ + "graph", +#ifdef USE_UNICODE_PROPERTIES + "inethiopicextendeda", + "soyo", + "spaceseparator", + "inpaucinhau", "nagm", - "extendedpictographic", - "buhd", + "inmongoliansupplement", + "oupper", + "inbengali", + "hex", "javanese", - "taml", + "oalpha", + "buhd", "inbuginese", - "inlatin1supplement", - "ingothic", - "invariationselectors", - "hex", - "inverticalforms", + "incjkunifiedideographsextensionb", + "incombiningdiacriticalmarkssupplement", + "insymbolsandpictographsextendeda", + "taml", "ebase", - "incurrencysymbols", - "avst", - "osge", + "orya", + "modifierletter", + "indevanagariextended", + "ext", + "induployan", + "inphoneticextensions", + "tirhuta", "incombiningdiacriticalmarksextended", - "intaiviet", - "spaceseparator", - "softdotted", - "nchar", - "invedicextensions", - "inlimbu", - "olditalic", - "gujr", - "mathsymbol", - "incjkunifiedideographsextensionb", - "gujarati", - "phagspa", - "invariationselectorssupplement", - "currencysymbol", - "inlinearbsyllabary", - "wancho", - "inpaucinhau", - "other", - "otheridcontinue", - "sylo", + "xposixpunct", + "injavanese", + "lepcha", + "lowercaseletter", + "inindicsiyaqnumbers", + "unassigned", + "ethi", + "titlecaseletter", + "rohg", + "syrc", + "inunifiedcanadianaboriginalsyllabicsextended", + "extender", + "inbrahmi", + "meroitichieroglyphs", + "otheruppercase", + "extpict", + "incjkradicalssupplement", + "tang", + "tagbanwa", "zp", "inaegeannumbers", - "warangciti", - "othernumber", -#endif /* USE_UNICODE_PROPERTIES */ - "digit", -#ifndef USE_UNICODE_PROPERTIES - "blank" -#else /* USE_UNICODE_PROPERTIES */ "nonspacingmark", - "titlecaseletter", - "inmeroiticcursive", - "wcho", - "graphemeclusterbreak=spacingmark", - "inletterlikesymbols", - "inottomansiyaqnumbers", - "intagbanwa", - "cyrillic", - "oalpha", - "graphemeclusterbreak=cr", - "narb", - "changeswhencasemapped", + "ingeorgianextended", + "cwt", + "dogra", + "inphoneticextensionssupplement", + "ingothic", + "oldsogdian", + "syriac", + "incjkunifiedideographsextensionf", + "dogr", + "osmanya", + "nchar", + "inmathematicalalphanumericsymbols", + "phagspa", + "inlimbu", + "cyrl", + "currencysymbol", + "epres", "inbopomofo", - "graphemeclusterbreak=regionalindicator", - "otheralphabetic", - "noncharactercodepoint", - "oldhungarian", + "narb", "insymbolsforlegacycomputing", + "mlym", "insmallformvariants", - "inhangulsyllables", - "emojipresentation", - "epres", - "inbassavah", - "indevanagariextended", - "inbuhid", - "tirhuta", - "inpsalterpahlavi", - "whitespace", - "finalpunctuation", - "orya", - "phlp", - "inbamumsupplement", - "buhid", - "paragraphseparator", - "inalphabeticpresentationforms", - "inlatinextendedg", - "elba", - "changeswhentitlecased", - "incombininghalfmarks", - "intangutcomponents", + "intagbanwa", + "malayalam", + "incyrillicextendedb", + "olonal", + "palmyrene", "thaa", + "otheridstart", "thai", - "oldturkic", + "tangut", "thaana", - "inlatinextendedf", - "ougr", - "tang", - "inarabicmathematicalalphabeticsymbols", - "tagbanwa", - "tamil", - "khitansmallscript", - "mahj", - "mahajani", - "hang", + "emojipresentation", + "inethiopicextended", + "nagmundari", + "nl", + "inlatin1supplement", "tirh", - "sylotinagri", + "hangul", "talu", - "nagmundari", - "deva", - "ingujarati", - "deprecated", - "inarabicpresentationformsb", - "devanagari", - "ingunjalagondi", - "graphemeclusterbreak=t", - "graphemeclusterbreak=lvt", + "buhid", + "paragraphseparator", + "graphemeclusterbreak=spacingmark", + "telu", + "otherlowercase", + "ogham", + "changeswhencasemapped", + "intangutcomponents", + "otherletter", "taitham", + "graphemeclusterbreak=cr", + "cwu", + "graphemeclusterbreak=regionalindicator", + "nushu", + "sunuwar", + "noncharactercodepoint", + "softdotted", + "omath", + "inbassavah", + "inottomansiyaqnumbers", + "ingaray", + "warangciti", + "ugar", + "inprivateusearea", + "inbuhid", + "dash", + "inarabicpresentationformsb", + "indivesakuru", + "hexdigit", + "inalphabeticpresentationforms", + "othersymbol", + "extendedpictographic", + "changeswhentitlecased", + "ogrext", "nbat", - "telu", - "hiragana", + "insuperscriptsandsubscripts", "nabataean", - "inrejang", "intangutsupplement", - "khoj", - "hmng", - "cyprominoan", - "inhebrew", - "inmathematicaloperators", + "inlowsurrogates", + "inyijinghexagramsymbols", + "inmahjongtiles", + "inletterlikesymbols", + "inbamumsupplement", + "incurrencysymbols", + "incombininghalfmarks", + "wancho", "inarabicsupplement", - "inenclosedcjklettersandmonths", - "changeswhenlowercased", - "tangut", - "elbasan", - "osmanya", - "insuperscriptsandsubscripts", - "graphemeclusterbreak=extend", - "graphemeclusterbreak=prepend", + "oldnortharabian", + "khitansmallscript", + "inlatinextendedg", + "sylo", + "inarabicmathematicalalphabeticsymbols", "nshu", - "otherlowercase", - "inethiopicextendedb", - "otherletter", - "kayahli", - "inplayingcards", - "elym", - "graphemeclusterbreak=l", - "graphemeclusterbreak=control", - "ogrext", - "elymaic", + "elba", + "invithkuqi", + "inhangulsyllables", "changeswhenuppercased", - "inalchemicalsymbols", - "oldsogdian", - "otheridstart", + "intifinagh", + "graphemeclusterbreak=t", + "graphemeclusterbreak=lvt", + "tamil", + "mathsymbol", + "tulutigalari", + "otherdefaultignorablecodepoint", + "wcho", "insupplementalarrowsa", - "invithkuqi", - "symbol", "inarabicextendedb", - "cypriot", - "any", - "otheruppercase", - "rjng", - "wspace", - "inindicsiyaqnumbers", - "inprivateusearea", - "othersymbol", - "oupper", - "signwriting", - "nushu", - "hmnp", - "upper", + "rejang", + "graphemeclusterbreak=extend", + "graphemeclusterbreak=prepend", + "finalpunctuation", + "inpsalterpahlavi", + "newa", + "inmathematicaloperators", + "phlp", + "deva", + "devanagari", + "newtailue", + "cf", + "pf", + "whitespace", + "elbasan", + "othermath", +#endif /* USE_UNICODE_PROPERTIES */ + "digit", +#ifndef USE_UNICODE_PROPERTIES + "blank" +#else /* USE_UNICODE_PROPERTIES */ + "cyprominoan", "insupplementalarrowsc", - "omath", - "modifiersymbol", - "hebr", - "inhalfwidthandfullwidthforms", + "tibt", + "tibetan", + "bassavah", "insupplementalmathematicaloperators", + "otherpunctuation", + "sgnw", + "ugaritic", + "tutg", + "changeswhenlowercased", + "cwl", + "inlinearbsyllabary", + "inplayingcards", + "modifiercombiningmark", + "sylotinagri", + "idcompatmathcontinue", "inpahawhhmong", - "alphabetic", - "uppercase", - "dupl", - "ogham", - "dashpunctuation", - "hangul", + "idcompatmathstart", + "hanifirohingya", + "deprecated", + "oldsoutharabian", + "shaw", + "tavt", + "wspace", + "graphemeclusterbreak=l", + "graphemeclusterbreak=control", + "cypriot", + "cyrillic", "inhanguljamoextendedb", - "bassavah", + "inalchemicalsymbols", + "insupplementalpunctuation", + "khudawadi", "aghb", - "hung", - "hexdigit", - "incypriotsyllabary", - "indivesakuru", - "tibt", + "graphemeclusterbreak=zwj", + "alphabetic", + "cwcf", + "elym", + "ecomp", + "inethiopicextendedb", + "elymaic", + "inglagoliticsupplement", + "garay", + "unknown", + "soyombo", "inlatinextendedb", + "divesakuru", + "kayahli", + "othergraphemeextend", + "inhighprivateusesurrogates", + "any", + "dashpunctuation", + "ethiopic", + "symbol", + "openpunctuation", "hluw", - "tibetan", + "tagb", + "hyphen", + "incypriotsyllabary", + "dupl", + "modifiersymbol", "inyisyllables", - "oldnortharabian", - "defaultignorablecodepoint", - "inhighprivateusesurrogates", - "soyombo", - "otherdefaultignorablecodepoint", - "pahawhhmong", - "unifiedideograph", - "othermath", - "changeswhencasefolded", - "inmahjongtiles", + "inhalfwidthandfullwidthforms", + "tfng", "dep", - "divesakuru", - "graphemeclusterbreak=lf", - "uppercaseletter", - "insupplementalpunctuation", - "ethiopic", - "inyijinghexagramsymbols", - "ecomp", - "inglagoliticsupplement", + "inegyptianhieroglyphsextendeda", "inbopomofoextended", - "injavanese", - "otherpunctuation", - "tifinagh", - "tfng", - "hanifirohingya", - "tavt", - "inboxdrawing", - "oldsoutharabian", - "inegyptianhieroglyphs", - "inegyptianhieroglyphformatcontrols", - "tagb", - "rejang", + "telugu", "tglg", "tagalog", - "othergraphemeextend", - "insupplementaryprivateuseareaa", - "inhighsurrogates", - "hebrew", - "duployan", + "inlatinextendedf", + "changeswhencasefolded", + "tifinagh", "graphemeclusterbreak=v", "graphemeclusterbreak=lv", + "inegyptianhieroglyphs", + "signwriting", + "inegyptianhieroglyphformatcontrols", + "graphemeclusterbreak=lf", + "insupplementaryprivateuseareaa", + "inhebrew", + "inboxdrawing", "insupplementalarrowsb", - "graphemeclusterbreak=zwj", - "telugu", - "zyyy", "olduyghur", + "upper", + "inhighsurrogates", + "uppercase", "inhangulcompatibilityjamo", - "openpunctuation", - "hyphen", - "insupplementalsymbolsandpictographs", + "defaultignorablecodepoint", + "uppercaseletter", "egyp", + "insupplementalsymbolsandpictographs", + "unifiedideograph", + "pahawhhmong", + "duployan", "nyiakengpuachuehmong", - "egyptianhieroglyphs", - "insupplementaryprivateuseareab" + "zyyy", + "insupplementaryprivateuseareab", + "hebrew", + "egyptianhieroglyphs" #endif /* USE_UNICODE_PROPERTIES */ }; #define uniname2ctype_pool ((const char *) &uniname2ctype_pool_contents) @@ -43710,1672 +46457,1812 @@ uniname2ctype_p (register const char *str, register size_t len) { #ifdef USE_UNICODE_PROPERTIES {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, - {uniname2ctype_offset(str11), 111}, - {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str17), 111}, - {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str22), 152}, - {-1}, {-1}, - {uniname2ctype_offset(str25), 184}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str33), 218}, - {-1}, - {uniname2ctype_offset(str35), 186}, - {uniname2ctype_offset(str36), 34}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str45), 173}, - {uniname2ctype_offset(str46), 28}, - {uniname2ctype_offset(str47), 61}, - {uniname2ctype_offset(str48), 95}, - {uniname2ctype_offset(str49), 95}, - {-1}, {-1}, - {uniname2ctype_offset(str52), 346}, - {-1}, {-1}, - {uniname2ctype_offset(str55), 21}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str64), 44}, - {-1}, - {uniname2ctype_offset(str66), 333}, - {uniname2ctype_offset(str67), 52}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str71), 181}, + {uniname2ctype_offset(str12), 155}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str75), 22}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str83), 184}, - {-1}, {-1}, - {uniname2ctype_offset(str86), 31}, + {uniname2ctype_offset(str16), 187}, + {uniname2ctype_offset(str17), 114}, + {uniname2ctype_offset(str18), 34}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str90), 230}, + {uniname2ctype_offset(str22), 221}, + {uniname2ctype_offset(str23), 189}, + {uniname2ctype_offset(str24), 114}, + {uniname2ctype_offset(str25), 28}, {-1}, - {uniname2ctype_offset(str92), 45}, + {uniname2ctype_offset(str27), 98}, + {uniname2ctype_offset(str28), 98}, {-1}, - {uniname2ctype_offset(str94), 33}, + {uniname2ctype_offset(str30), 176}, + {uniname2ctype_offset(str31), 362}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str100), 149}, - {uniname2ctype_offset(str101), 513}, - {uniname2ctype_offset(str102), 108}, - {uniname2ctype_offset(str103), 263}, + {uniname2ctype_offset(str37), 349}, + {uniname2ctype_offset(str38), 21}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str107), 31}, - {uniname2ctype_offset(str108), 77}, - {-1}, {-1}, - {uniname2ctype_offset(str111), 189}, - {uniname2ctype_offset(str112), 189}, + {uniname2ctype_offset(str42), 61}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str52), 22}, +#endif /* USE_UNICODE_PROPERTIES */ + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, +#ifndef USE_UNICODE_PROPERTIES + {uniname2ctype_offset(str6), 12}, + {uniname2ctype_offset(str7), 7}, + {uniname2ctype_offset(str8), 15}, + {uniname2ctype_offset(str9), 1}, + {uniname2ctype_offset(str10), 13}, + {uniname2ctype_offset(str11), 11}, + {uniname2ctype_offset(str12), 10}, + {uniname2ctype_offset(str13), 14}, + {uniname2ctype_offset(str14), 3}, + {uniname2ctype_offset(str15), 9}, + {uniname2ctype_offset(str16), 8}, + {uniname2ctype_offset(str17), 6}, + {uniname2ctype_offset(str18), 5}, + {uniname2ctype_offset(str19), 4}, + {uniname2ctype_offset(str20), 2} +#else /* USE_UNICODE_PROPERTIES */ + {uniname2ctype_offset(str59), 241}, + {uniname2ctype_offset(str60), 44}, + {uniname2ctype_offset(str61), 184}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str65), 52}, {-1}, {-1}, - {uniname2ctype_offset(str115), 149}, + {uniname2ctype_offset(str68), 187}, + {uniname2ctype_offset(str69), 31}, + {uniname2ctype_offset(str70), 45}, {-1}, - {uniname2ctype_offset(str117), 98}, - {uniname2ctype_offset(str118), 77}, + {uniname2ctype_offset(str72), 33}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str122), 212}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str129), 187}, - {uniname2ctype_offset(str130), 42}, - {uniname2ctype_offset(str131), 172}, + {uniname2ctype_offset(str76), 274}, {-1}, {-1}, - {uniname2ctype_offset(str134), 497}, - {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str139), 170}, - {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str145), 516}, - {uniname2ctype_offset(str146), 575}, + {uniname2ctype_offset(str79), 602}, {-1}, - {uniname2ctype_offset(str148), 580}, - {uniname2ctype_offset(str149), 535}, + {uniname2ctype_offset(str81), 192}, + {uniname2ctype_offset(str82), 192}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str86), 530}, {-1}, - {uniname2ctype_offset(str151), 18}, - {uniname2ctype_offset(str152), 169}, - {uniname2ctype_offset(str153), 160}, - {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str158), 278}, + {uniname2ctype_offset(str88), 152}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str92), 152}, + {uniname2ctype_offset(str93), 80}, {-1}, {-1}, - {uniname2ctype_offset(str161), 327}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str177), 352}, - {uniname2ctype_offset(str178), 563}, - {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str183), 75}, + {uniname2ctype_offset(str96), 233}, + {uniname2ctype_offset(str97), 101}, {-1}, {-1}, - {uniname2ctype_offset(str186), 27}, - {-1}, {-1}, {-1}, - {uniname2ctype_offset(str190), 208}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, - {uniname2ctype_offset(str203), 360}, - {uniname2ctype_offset(str204), 488}, - {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str210), 581}, + {uniname2ctype_offset(str100), 80}, + {uniname2ctype_offset(str101), 190}, + {uniname2ctype_offset(str102), 175}, + {-1}, {-1}, + {uniname2ctype_offset(str105), 111}, {-1}, - {uniname2ctype_offset(str212), 365}, - {uniname2ctype_offset(str213), 115}, - {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str218), 549}, + {uniname2ctype_offset(str107), 31}, + {-1}, {-1}, + {uniname2ctype_offset(str110), 42}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str226), 171}, + {uniname2ctype_offset(str118), 215}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str230), 530}, - {uniname2ctype_offset(str231), 31}, - {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str236), 25}, - {uniname2ctype_offset(str237), 194}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str246), 32}, + {uniname2ctype_offset(str122), 163}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str250), 40}, + {uniname2ctype_offset(str126), 513}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str130), 598}, + {uniname2ctype_offset(str131), 533}, + {uniname2ctype_offset(str132), 604}, + {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str137), 173}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str253), 102}, + {uniname2ctype_offset(str149), 343}, + {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str154), 243}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str158), 78}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str260), 568}, - {-1}, {-1}, - {uniname2ctype_offset(str263), 161}, + {uniname2ctype_offset(str165), 553}, + {uniname2ctype_offset(str166), 368}, + {uniname2ctype_offset(str167), 172}, {-1}, - {uniname2ctype_offset(str265), 19}, + {uniname2ctype_offset(str169), 584}, {-1}, - {uniname2ctype_offset(str267), 79}, - {uniname2ctype_offset(str268), 357}, + {uniname2ctype_offset(str171), 18}, + {uniname2ctype_offset(str172), 292}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str270), 270}, + {uniname2ctype_offset(str192), 605}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str274), 567}, - {uniname2ctype_offset(str275), 517}, + {uniname2ctype_offset(str196), 381}, + {uniname2ctype_offset(str197), 27}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str281), 321}, - {uniname2ctype_offset(str282), 40}, - {uniname2ctype_offset(str283), 79}, - {-1}, - {uniname2ctype_offset(str285), 537}, - {-1}, - {uniname2ctype_offset(str287), 144}, - {uniname2ctype_offset(str288), 144}, - {uniname2ctype_offset(str289), 560}, - {-1}, {-1}, {-1}, - {uniname2ctype_offset(str293), 218}, - {-1}, {-1}, {-1}, - {uniname2ctype_offset(str297), 212}, - {-1}, {-1}, {-1}, - {uniname2ctype_offset(str301), 395}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str311), 325}, - {-1}, - {uniname2ctype_offset(str313), 456}, - {-1}, - {uniname2ctype_offset(str315), 243}, + {uniname2ctype_offset(str203), 211}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str320), 271}, - {-1}, - {uniname2ctype_offset(str322), 129}, + {uniname2ctype_offset(str208), 118}, + {-1}, {-1}, + {uniname2ctype_offset(str211), 31}, + {uniname2ctype_offset(str212), 376}, + {uniname2ctype_offset(str213), 504}, + {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str218), 569}, + {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str224), 283}, + {uniname2ctype_offset(str225), 548}, + {uniname2ctype_offset(str226), 197}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str328), 334}, + {uniname2ctype_offset(str232), 174}, {-1}, {-1}, - {uniname2ctype_offset(str331), 76}, - {-1}, {-1}, {-1}, - {uniname2ctype_offset(str335), 561}, + {uniname2ctype_offset(str235), 105}, + {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str240), 40}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str249), 534}, + {uniname2ctype_offset(str250), 589}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str338), 332}, - {-1}, - {uniname2ctype_offset(str340), 76}, - {-1}, - {uniname2ctype_offset(str342), 349}, + {uniname2ctype_offset(str262), 337}, {-1}, {-1}, - {uniname2ctype_offset(str345), 53}, - {uniname2ctype_offset(str346), 270}, + {uniname2ctype_offset(str265), 555}, {-1}, - {uniname2ctype_offset(str348), 426}, + {uniname2ctype_offset(str267), 373}, + {-1}, {-1}, + {uniname2ctype_offset(str270), 221}, + {-1}, {-1}, + {uniname2ctype_offset(str273), 411}, + {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str279), 215}, + {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str285), 25}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str352), 533}, + {uniname2ctype_offset(str289), 588}, + {-1}, + {uniname2ctype_offset(str291), 82}, + {uniname2ctype_offset(str292), 32}, + {uniname2ctype_offset(str293), 164}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str362), 163}, + {uniname2ctype_offset(str303), 82}, + {-1}, + {uniname2ctype_offset(str305), 581}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str366), 44}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str373), 160}, + {uniname2ctype_offset(str309), 53}, + {-1}, + {uniname2ctype_offset(str311), 253}, + {uniname2ctype_offset(str312), 19}, + {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str317), 350}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str381), 554}, + {uniname2ctype_offset(str325), 582}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str386), 371}, + {uniname2ctype_offset(str330), 40}, + {-1}, + {uniname2ctype_offset(str332), 166}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, - {uniname2ctype_offset(str399), 330}, {-1}, - {uniname2ctype_offset(str401), 548}, + {uniname2ctype_offset(str343), 132}, + {-1}, + {uniname2ctype_offset(str345), 285}, {-1}, {-1}, - {uniname2ctype_offset(str404), 81}, + {uniname2ctype_offset(str348), 472}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str352), 341}, + {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str357), 574}, + {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str362), 387}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str381), 79}, + {uniname2ctype_offset(str382), 284}, + {uniname2ctype_offset(str383), 283}, + {-1}, + {uniname2ctype_offset(str385), 79}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str418), 108}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str426), 163}, + {uniname2ctype_offset(str390), 348}, + {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str396), 365}, + {uniname2ctype_offset(str397), 442}, + {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str403), 551}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str430), 55}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, - {uniname2ctype_offset(str442), 14}, + {uniname2ctype_offset(str407), 346}, + {uniname2ctype_offset(str408), 55}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str416), 44}, {-1}, {-1}, - {uniname2ctype_offset(str445), 23}, + {uniname2ctype_offset(str419), 163}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str426), 23}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str462), 46}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str468), 169}, + {uniname2ctype_offset(str441), 172}, + {-1}, {-1}, + {uniname2ctype_offset(str444), 46}, + {uniname2ctype_offset(str445), 567}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str452), 191}, + {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str458), 612}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, + {uniname2ctype_offset(str470), 190}, {-1}, - {uniname2ctype_offset(str470), 22}, - {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str475), 524}, - {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str480), 457}, - {uniname2ctype_offset(str481), 188}, + {uniname2ctype_offset(str472), 542}, + {uniname2ctype_offset(str473), 259}, + {-1}, + {uniname2ctype_offset(str475), 166}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str486), 476}, + {uniname2ctype_offset(str480), 84}, + {uniname2ctype_offset(str481), 130}, {-1}, - {uniname2ctype_offset(str488), 588}, - {-1}, {-1}, - {uniname2ctype_offset(str491), 470}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str500), 127}, + {uniname2ctype_offset(str483), 111}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str504), 187}, - {uniname2ctype_offset(str505), 249}, - {uniname2ctype_offset(str506), 24}, + {uniname2ctype_offset(str487), 439}, + {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str492), 14}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str509), 24}, + {uniname2ctype_offset(str504), 573}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str512), 22}, + {-1}, + {uniname2ctype_offset(str514), 532}, + {-1}, + {uniname2ctype_offset(str516), 49}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str524), 51}, + {uniname2ctype_offset(str525), 492}, + {uniname2ctype_offset(str526), 233}, + {uniname2ctype_offset(str527), 94}, + {uniname2ctype_offset(str528), 473}, + {-1}, + {uniname2ctype_offset(str530), 486}, {-1}, - {uniname2ctype_offset(str511), 463}, + {uniname2ctype_offset(str532), 94}, + {-1}, + {uniname2ctype_offset(str534), 70}, + {uniname2ctype_offset(str535), 24}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str520), 423}, + {uniname2ctype_offset(str544), 565}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str554), 479}, + {-1}, + {uniname2ctype_offset(str556), 637}, + {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str561), 244}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str533), 230}, + {uniname2ctype_offset(str565), 178}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str538), 91}, + {uniname2ctype_offset(str579), 603}, + {uniname2ctype_offset(str580), 243}, {-1}, {-1}, - {uniname2ctype_offset(str541), 553}, + {uniname2ctype_offset(str583), 496}, + {uniname2ctype_offset(str584), 171}, + {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str589), 37}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str597), 655}, + {uniname2ctype_offset(str598), 506}, + {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str603), 91}, + {uniname2ctype_offset(str604), 422}, {-1}, - {uniname2ctype_offset(str543), 91}, + {uniname2ctype_offset(str606), 650}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str614), 77}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str624), 70}, + {-1}, {-1}, + {uniname2ctype_offset(str627), 648}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str651), 159}, + {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str657), 545}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str556), 546}, + {uniname2ctype_offset(str661), 501}, + {-1}, + {uniname2ctype_offset(str663), 463}, + {uniname2ctype_offset(str664), 159}, {-1}, - {uniname2ctype_offset(str558), 350}, - {uniname2ctype_offset(str559), 70}, - {uniname2ctype_offset(str560), 515}, + {uniname2ctype_offset(str666), 198}, + {uniname2ctype_offset(str667), 568}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str565), 624}, - {uniname2ctype_offset(str566), 37}, + {uniname2ctype_offset(str672), 232}, + {uniname2ctype_offset(str673), 392}, {-1}, - {uniname2ctype_offset(str568), 113}, + {uniname2ctype_offset(str675), 76}, + {uniname2ctype_offset(str676), 116}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str572), 502}, + {uniname2ctype_offset(str680), 351}, + {uniname2ctype_offset(str681), 69}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str689), 618}, + {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str695), 196}, + {uniname2ctype_offset(str696), 50}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str700), 47}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str577), 611}, + {uniname2ctype_offset(str705), 174}, + {-1}, {-1}, + {uniname2ctype_offset(str708), 531}, {-1}, - {uniname2ctype_offset(str579), 106}, + {uniname2ctype_offset(str710), 509}, + {uniname2ctype_offset(str711), 160}, + {uniname2ctype_offset(str712), 68}, + {uniname2ctype_offset(str713), 664}, + {uniname2ctype_offset(str714), 281}, {-1}, {-1}, - {uniname2ctype_offset(str582), 406}, - {uniname2ctype_offset(str583), 480}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str590), 74}, + {uniname2ctype_offset(str717), 161}, + {-1}, + {uniname2ctype_offset(str719), 621}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, + {uniname2ctype_offset(str739), 266}, + {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str745), 29}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str594), 168}, + {uniname2ctype_offset(str758), 447}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str768), 579}, {-1}, - {uniname2ctype_offset(str596), 622}, - {uniname2ctype_offset(str597), 146}, + {uniname2ctype_offset(str770), 465}, {-1}, {-1}, - {uniname2ctype_offset(str600), 490}, + {uniname2ctype_offset(str773), 643}, {-1}, - {uniname2ctype_offset(str602), 70}, + {uniname2ctype_offset(str775), 632}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str784), 48}, + {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str790), 268}, + {uniname2ctype_offset(str791), 460}, + {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str797), 415}, {-1}, - {uniname2ctype_offset(str604), 579}, - {uniname2ctype_offset(str605), 629}, - {-1}, {-1}, - {uniname2ctype_offset(str608), 637}, - {uniname2ctype_offset(str609), 229}, + {uniname2ctype_offset(str799), 24}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str614), 612}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str624), 195}, - {uniname2ctype_offset(str625), 447}, + {uniname2ctype_offset(str804), 170}, + {uniname2ctype_offset(str805), 611}, + {uniname2ctype_offset(str806), 213}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str630), 29}, - {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str636), 543}, - {-1}, {-1}, - {uniname2ctype_offset(str639), 49}, - {-1}, {-1}, - {uniname2ctype_offset(str642), 19}, - {uniname2ctype_offset(str643), 564}, + {uniname2ctype_offset(str811), 170}, {-1}, - {uniname2ctype_offset(str645), 485}, + {uniname2ctype_offset(str813), 620}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str817), 516}, + {uniname2ctype_offset(str818), 281}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str822), 181}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str826), 67}, {-1}, - {uniname2ctype_offset(str647), 192}, - {-1}, {-1}, - {uniname2ctype_offset(str650), 487}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str657), 51}, - {-1}, {-1}, - {uniname2ctype_offset(str660), 268}, + {uniname2ctype_offset(str828), 72}, + {uniname2ctype_offset(str829), 366}, + {uniname2ctype_offset(str830), 147}, + {uniname2ctype_offset(str831), 147}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str835), 635}, + {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str840), 109}, + {uniname2ctype_offset(str841), 128}, + {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str846), 7}, + {uniname2ctype_offset(str847), 519}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str672), 335}, - {-1}, {-1}, - {uniname2ctype_offset(str675), 68}, - {-1}, {-1}, - {uniname2ctype_offset(str678), 171}, - {uniname2ctype_offset(str679), 607}, + {uniname2ctype_offset(str859), 389}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str869), 74}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str888), 420}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str896), 41}, + {uniname2ctype_offset(str897), 428}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str683), 267}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str692), 69}, - {-1}, {-1}, - {uniname2ctype_offset(str695), 551}, - {uniname2ctype_offset(str696), 175}, - {uniname2ctype_offset(str697), 399}, + {uniname2ctype_offset(str901), 149}, + {uniname2ctype_offset(str902), 647}, + {uniname2ctype_offset(str903), 19}, + {-1}, + {uniname2ctype_offset(str905), 500}, + {uniname2ctype_offset(str906), 414}, {-1}, {-1}, - {uniname2ctype_offset(str700), 236}, + {uniname2ctype_offset(str909), 638}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str917), 113}, {-1}, {-1}, - {uniname2ctype_offset(str703), 527}, - {-1}, - {uniname2ctype_offset(str705), 347}, - {-1}, - {uniname2ctype_offset(str707), 158}, - {uniname2ctype_offset(str708), 587}, + {uniname2ctype_offset(str920), 113}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str713), 376}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str720), 72}, + {uniname2ctype_offset(str925), 120}, + {-1}, + {uniname2ctype_offset(str927), 107}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str737), 7}, - {uniname2ctype_offset(str738), 373}, + {uniname2ctype_offset(str937), 200}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str742), 6}, + {uniname2ctype_offset(str941), 120}, {-1}, {-1}, - {uniname2ctype_offset(str745), 269}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str753), 240}, + {uniname2ctype_offset(str944), 195}, + {uniname2ctype_offset(str945), 557}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str755), 514}, - {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str760), 431}, - {uniname2ctype_offset(str761), 167}, - {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str766), 156}, - {uniname2ctype_offset(str767), 608}, + {uniname2ctype_offset(str956), 559}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str771), 167}, - {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str776), 268}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str783), 156}, + {uniname2ctype_offset(str960), 503}, + {-1}, {-1}, + {uniname2ctype_offset(str963), 538}, + {-1}, + {uniname2ctype_offset(str965), 110}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str787), 256}, + {uniname2ctype_offset(str978), 625}, + {uniname2ctype_offset(str979), 271}, + {-1}, {-1}, + {uniname2ctype_offset(str982), 68}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1000), 267}, + {-1}, {-1}, + {uniname2ctype_offset(str1003), 547}, + {uniname2ctype_offset(str1004), 75}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str791), 193}, + {uniname2ctype_offset(str1008), 363}, + {uniname2ctype_offset(str1009), 30}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, + {uniname2ctype_offset(str1021), 338}, + {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1026), 161}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str794), 589}, + {uniname2ctype_offset(str1038), 511}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str797), 50}, + {uniname2ctype_offset(str1050), 144}, {-1}, - {uniname2ctype_offset(str799), 617}, + {uniname2ctype_offset(str1052), 67}, + {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1057), 148}, + {uniname2ctype_offset(str1058), 613}, {-1}, {-1}, - {uniname2ctype_offset(str802), 13}, - {uniname2ctype_offset(str803), 593}, + {uniname2ctype_offset(str1061), 89}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1070), 196}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str809), 446}, - {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str814), 493}, + {uniname2ctype_offset(str1076), 89}, + {uniname2ctype_offset(str1077), 462}, + {-1}, + {uniname2ctype_offset(str1079), 60}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str818), 398}, - {-1}, {-1}, - {uniname2ctype_offset(str821), 482}, - {uniname2ctype_offset(str822), 595}, - {uniname2ctype_offset(str823), 47}, - {uniname2ctype_offset(str824), 112}, - {uniname2ctype_offset(str825), 444}, + {uniname2ctype_offset(str1083), 498}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1087), 220}, + {uniname2ctype_offset(str1088), 560}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1092), 109}, {-1}, {-1}, - {uniname2ctype_offset(str828), 596}, + {uniname2ctype_offset(str1095), 250}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1099), 279}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str838), 157}, + {uniname2ctype_offset(str1109), 622}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str842), 58}, - {-1}, {-1}, - {uniname2ctype_offset(str845), 66}, + {uniname2ctype_offset(str1113), 123}, {-1}, - {uniname2ctype_offset(str847), 48}, - {uniname2ctype_offset(str848), 178}, + {uniname2ctype_offset(str1115), 276}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str855), 67}, + {uniname2ctype_offset(str1122), 514}, + {uniname2ctype_offset(str1123), 451}, + {uniname2ctype_offset(str1124), 342}, + {uniname2ctype_offset(str1125), 475}, + {uniname2ctype_offset(str1126), 101}, + {uniname2ctype_offset(str1127), 663}, + {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1132), 268}, {-1}, - {uniname2ctype_offset(str857), 319}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1134), 405}, + {uniname2ctype_offset(str1135), 13}, + {uniname2ctype_offset(str1136), 249}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str875), 369}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1145), 369}, {-1}, - {uniname2ctype_offset(str886), 404}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str895), 412}, - {-1}, {-1}, - {uniname2ctype_offset(str898), 500}, + {uniname2ctype_offset(str1147), 253}, {-1}, - {uniname2ctype_offset(str900), 621}, - {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str906), 521}, - {uniname2ctype_offset(str907), 449}, + {uniname2ctype_offset(str1149), 478}, + {-1}, {-1}, + {uniname2ctype_offset(str1152), 661}, + {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1157), 564}, + {-1}, {-1}, + {uniname2ctype_offset(str1160), 107}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, + {uniname2ctype_offset(str1172), 275}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str920), 419}, - {-1}, {-1}, {-1}, - {uniname2ctype_offset(str924), 68}, - {uniname2ctype_offset(str925), 599}, - {uniname2ctype_offset(str926), 344}, - {-1}, - {uniname2ctype_offset(str928), 540}, - {uniname2ctype_offset(str929), 461}, - {uniname2ctype_offset(str930), 41}, + {uniname2ctype_offset(str1176), 115}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str946), 136}, + {uniname2ctype_offset(str1186), 286}, + {uniname2ctype_offset(str1187), 382}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1195), 634}, + {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1200), 335}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str961), 2}, + {-1}, {-1}, + {uniname2ctype_offset(str1212), 280}, {-1}, - {uniname2ctype_offset(str963), 257}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1214), 148}, {-1}, - {uniname2ctype_offset(str974), 510}, + {uniname2ctype_offset(str1216), 385}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str986), 370}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str994), 85}, - {uniname2ctype_offset(str995), 104}, + {uniname2ctype_offset(str1228), 139}, + {uniname2ctype_offset(str1229), 69}, + {-1}, + {uniname2ctype_offset(str1231), 11}, + {-1}, + {uniname2ctype_offset(str1233), 357}, + {-1}, {-1}, + {uniname2ctype_offset(str1236), 2}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1243), 527}, +#ifndef USE_UNICODE_AGE_PROPERTIES {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1010), 26}, - {-1}, {-1}, - {uniname2ctype_offset(str1013), 495}, + {uniname2ctype_offset(str1258), 477}, +#endif /* USE_UNICODE_AGE_PROPERTIES */ + {-1}, {-1}, {-1}, +#ifdef USE_UNICODE_AGE_PROPERTIES + {uniname2ctype_offset(str1247), 312}, + {uniname2ctype_offset(str1248), 311}, + {uniname2ctype_offset(str1249), 314}, + {uniname2ctype_offset(str1250), 313}, + {uniname2ctype_offset(str1251), 293}, + {uniname2ctype_offset(str1252), 319}, + {uniname2ctype_offset(str1253), 310}, + {uniname2ctype_offset(str1254), 295}, + {uniname2ctype_offset(str1255), 294}, + {uniname2ctype_offset(str1256), 305}, + {uniname2ctype_offset(str1257), 304}, + {uniname2ctype_offset(str1258), 477}, + {uniname2ctype_offset(str1259), 306}, + {uniname2ctype_offset(str1260), 309}, + {uniname2ctype_offset(str1261), 308}, +#endif /* USE_UNICODE_AGE_PROPERTIES */ + {uniname2ctype_offset(str1262), 659}, {-1}, - {uniname2ctype_offset(str1015), 484}, - {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1021), 67}, + {uniname2ctype_offset(str1264), 88}, + {uniname2ctype_offset(str1265), 118}, +#ifndef USE_UNICODE_AGE_PROPERTIES + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, +#else /* USE_UNICODE_AGE_PROPERTIES */ + {uniname2ctype_offset(str1266), 318}, + {uniname2ctype_offset(str1267), 317}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1271), 302}, + {uniname2ctype_offset(str1272), 301}, + {uniname2ctype_offset(str1273), 316}, + {uniname2ctype_offset(str1274), 303}, {-1}, {-1}, - {uniname2ctype_offset(str1024), 53}, - {uniname2ctype_offset(str1025), 459}, + {uniname2ctype_offset(str1277), 300}, + {uniname2ctype_offset(str1278), 299}, {-1}, {-1}, - {uniname2ctype_offset(str1028), 136}, +#endif /* USE_UNICODE_AGE_PROPERTIES */ + {uniname2ctype_offset(str1281), 540}, + {uniname2ctype_offset(str1282), 360}, + {-1}, + {uniname2ctype_offset(str1284), 558}, +#ifndef USE_UNICODE_AGE_PROPERTIES + {-1}, {-1}, {-1}, {-1}, {-1}, +#else /* USE_UNICODE_AGE_PROPERTIES */ {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1032), 380}, - {-1}, {-1}, - {uniname2ctype_offset(str1035), 322}, - {uniname2ctype_offset(str1036), 569}, + {uniname2ctype_offset(str1288), 315}, + {-1}, +#endif /* USE_UNICODE_AGE_PROPERTIES */ + {uniname2ctype_offset(str1290), 139}, + {uniname2ctype_offset(str1291), 205}, +#ifndef USE_UNICODE_AGE_PROPERTIES + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, +#else /* USE_UNICODE_AGE_PROPERTIES */ + {uniname2ctype_offset(str1292), 297}, + {uniname2ctype_offset(str1293), 296}, + {-1}, + {uniname2ctype_offset(str1295), 298}, + {-1}, + {uniname2ctype_offset(str1297), 307}, +#endif /* USE_UNICODE_AGE_PROPERTIES */ + {uniname2ctype_offset(str1298), 15}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, + {uniname2ctype_offset(str1309), 453}, + {uniname2ctype_offset(str1310), 441}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1049), 173}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1067), 102}, - {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1072), 197}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1081), 414}, + {uniname2ctype_offset(str1314), 96}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1085), 259}, + {uniname2ctype_offset(str1318), 176}, {-1}, - {uniname2ctype_offset(str1087), 600}, + {uniname2ctype_offset(str1320), 141}, + {uniname2ctype_offset(str1321), 274}, + {-1}, + {uniname2ctype_offset(str1323), 206}, + {-1}, {-1}, + {uniname2ctype_offset(str1326), 105}, + {uniname2ctype_offset(str1327), 282}, + {uniname2ctype_offset(str1328), 220}, {-1}, - {uniname2ctype_offset(str1089), 115}, + {uniname2ctype_offset(str1330), 205}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1095), 250}, - {uniname2ctype_offset(str1096), 71}, - {uniname2ctype_offset(str1097), 541}, - {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1102), 523}, + {uniname2ctype_offset(str1336), 552}, + {-1}, {-1}, + {uniname2ctype_offset(str1339), 590}, + {uniname2ctype_offset(str1340), 211}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1349), 74}, + {uniname2ctype_offset(str1350), 273}, + {-1}, {-1}, + {uniname2ctype_offset(str1353), 104}, {-1}, - {uniname2ctype_offset(str1104), 228}, - {uniname2ctype_offset(str1105), 217}, + {uniname2ctype_offset(str1355), 104}, {-1}, - {uniname2ctype_offset(str1107), 542}, + {uniname2ctype_offset(str1357), 199}, {-1}, - {uniname2ctype_offset(str1109), 239}, + {uniname2ctype_offset(str1359), 169}, + {-1}, {-1}, + {uniname2ctype_offset(str1362), 554}, + {uniname2ctype_offset(str1363), 288}, + {uniname2ctype_offset(str1364), 375}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1114), 69}, - {uniname2ctype_offset(str1115), 11}, + {uniname2ctype_offset(str1369), 186}, + {-1}, {-1}, + {uniname2ctype_offset(str1372), 154}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1119), 106}, - {uniname2ctype_offset(str1120), 60}, + {uniname2ctype_offset(str1376), 173}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1134), 425}, - {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1140), 93}, + {uniname2ctype_offset(str1390), 138}, {-1}, - {uniname2ctype_offset(str1142), 206}, - {-1}, {-1}, - {uniname2ctype_offset(str1145), 137}, - {uniname2ctype_offset(str1146), 131}, - {uniname2ctype_offset(str1147), 266}, + {uniname2ctype_offset(str1392), 35}, + {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1397), 73}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1149), 158}, - {uniname2ctype_offset(str1150), 98}, - {uniname2ctype_offset(str1151), 498}, - {uniname2ctype_offset(str1152), 217}, - {uniname2ctype_offset(str1153), 138}, - {-1}, {-1}, - {uniname2ctype_offset(str1156), 529}, - {uniname2ctype_offset(str1157), 203}, - {uniname2ctype_offset(str1158), 166}, - {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1164), 240}, + {uniname2ctype_offset(str1408), 189}, + {-1}, + {uniname2ctype_offset(str1410), 38}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1168), 104}, + {uniname2ctype_offset(str1414), 395}, {-1}, - {uniname2ctype_offset(str1170), 389}, - {uniname2ctype_offset(str1171), 536}, - {-1}, {-1}, - {uniname2ctype_offset(str1174), 326}, - {uniname2ctype_offset(str1175), 26}, - {uniname2ctype_offset(str1176), 208}, - {uniname2ctype_offset(str1177), 74}, - {uniname2ctype_offset(str1178), 353}, + {uniname2ctype_offset(str1416), 227}, + {uniname2ctype_offset(str1417), 143}, + {uniname2ctype_offset(str1418), 143}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1434), 144}, + {uniname2ctype_offset(str1435), 371}, + {-1}, + {uniname2ctype_offset(str1437), 39}, {-1}, - {uniname2ctype_offset(str1180), 183}, - {uniname2ctype_offset(str1181), 151}, - {uniname2ctype_offset(str1182), 359}, - {uniname2ctype_offset(str1183), 101}, + {uniname2ctype_offset(str1439), 39}, + {uniname2ctype_offset(str1440), 340}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1185), 170}, - {uniname2ctype_offset(str1186), 597}, + {uniname2ctype_offset(str1451), 528}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1190), 272}, - {uniname2ctype_offset(str1191), 545}, - {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1197), 101}, - {uniname2ctype_offset(str1198), 135}, + {uniname2ctype_offset(str1455), 526}, + {uniname2ctype_offset(str1456), 599}, + {-1}, + {uniname2ctype_offset(str1458), 209}, + {-1}, + {uniname2ctype_offset(str1460), 364}, + {uniname2ctype_offset(str1461), 435}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1203), 366}, - {uniname2ctype_offset(str1204), 609}, + {uniname2ctype_offset(str1466), 90}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1476), 90}, + {-1}, + {uniname2ctype_offset(str1478), 430}, + {-1}, + {uniname2ctype_offset(str1480), 262}, + {-1}, + {uniname2ctype_offset(str1482), 33}, + {-1}, + {uniname2ctype_offset(str1484), 137}, + {uniname2ctype_offset(str1485), 108}, {-1}, {-1}, - {uniname2ctype_offset(str1207), 462}, + {uniname2ctype_offset(str1488), 146}, {-1}, - {uniname2ctype_offset(str1209), 186}, + {uniname2ctype_offset(str1490), 125}, + {uniname2ctype_offset(str1491), 203}, + {uniname2ctype_offset(str1492), 230}, {-1}, {-1}, - {uniname2ctype_offset(str1212), 379}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1495), 218}, + {-1}, {-1}, + {uniname2ctype_offset(str1498), 438}, + {-1}, {-1}, + {uniname2ctype_offset(str1501), 146}, + {uniname2ctype_offset(str1502), 524}, {-1}, - {uniname2ctype_offset(str1223), 584}, + {uniname2ctype_offset(str1504), 445}, + {uniname2ctype_offset(str1505), 25}, + {uniname2ctype_offset(str1506), 580}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1513), 245}, + {-1}, {-1}, + {uniname2ctype_offset(str1516), 624}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1227), 243}, - {-1}, - {uniname2ctype_offset(str1229), 235}, - {uniname2ctype_offset(str1230), 267}, - {uniname2ctype_offset(str1231), 206}, - {uniname2ctype_offset(str1232), 355}, - {uniname2ctype_offset(str1233), 73}, -#ifndef USE_UNICODE_AGE_PROPERTIES - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -#else /* USE_UNICODE_AGE_PROPERTIES */ - {uniname2ctype_offset(str1234), 298}, - {uniname2ctype_offset(str1235), 300}, - {uniname2ctype_offset(str1236), 297}, - {uniname2ctype_offset(str1237), 299}, + {uniname2ctype_offset(str1520), 230}, + {uniname2ctype_offset(str1521), 234}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1241), 301}, - {uniname2ctype_offset(str1242), 279}, -#endif /* USE_UNICODE_AGE_PROPERTIES */ - {uniname2ctype_offset(str1243), 25}, - {uniname2ctype_offset(str1244), 341}, -#ifndef USE_UNICODE_AGE_PROPERTIES + {uniname2ctype_offset(str1525), 88}, + {uniname2ctype_offset(str1526), 167}, + {uniname2ctype_offset(str1527), 515}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1534), 108}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1542), 125}, + {-1}, {-1}, + {uniname2ctype_offset(str1545), 660}, + {uniname2ctype_offset(str1546), 289}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1553), 570}, {-1}, -#else /* USE_UNICODE_AGE_PROPERTIES */ - {uniname2ctype_offset(str1245), 281}, -#endif /* USE_UNICODE_AGE_PROPERTIES */ - {uniname2ctype_offset(str1246), 435}, -#ifndef USE_UNICODE_AGE_PROPERTIES + {uniname2ctype_offset(str1555), 209}, + {-1}, {-1}, + {uniname2ctype_offset(str1558), 284}, {-1}, -#else /* USE_UNICODE_AGE_PROPERTIES */ - {uniname2ctype_offset(str1247), 280}, -#endif /* USE_UNICODE_AGE_PROPERTIES */ - {uniname2ctype_offset(str1248), 30}, -#ifndef USE_UNICODE_AGE_PROPERTIES + {uniname2ctype_offset(str1560), 138}, + {-1}, + {uniname2ctype_offset(str1562), 502}, + {-1}, {-1}, + {uniname2ctype_offset(str1565), 145}, {-1}, {-1}, {-1}, {-1}, {-1}, -#else /* USE_UNICODE_AGE_PROPERTIES */ - {uniname2ctype_offset(str1249), 283}, - {uniname2ctype_offset(str1250), 296}, - {uniname2ctype_offset(str1251), 282}, - {uniname2ctype_offset(str1252), 284}, - {uniname2ctype_offset(str1253), 295}, -#endif /* USE_UNICODE_AGE_PROPERTIES */ - {uniname2ctype_offset(str1254), 566}, -#ifndef USE_UNICODE_AGE_PROPERTIES + {uniname2ctype_offset(str1571), 140}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1575), 404}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1583), 123}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1591), 225}, {-1}, -#else /* USE_UNICODE_AGE_PROPERTIES */ - {uniname2ctype_offset(str1255), 291}, -#endif /* USE_UNICODE_AGE_PROPERTIES */ - {uniname2ctype_offset(str1256), 278}, -#ifndef USE_UNICODE_AGE_PROPERTIES - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -#else /* USE_UNICODE_AGE_PROPERTIES */ - {uniname2ctype_offset(str1257), 290}, - {uniname2ctype_offset(str1258), 292}, - {uniname2ctype_offset(str1259), 303}, - {uniname2ctype_offset(str1260), 294}, + {uniname2ctype_offset(str1593), 224}, {-1}, - {uniname2ctype_offset(str1262), 293}, -#endif /* USE_UNICODE_AGE_PROPERTIES */ - {uniname2ctype_offset(str1263), 64}, -#ifndef USE_UNICODE_AGE_PROPERTIES + {uniname2ctype_offset(str1595), 26}, {-1}, {-1}, -#else /* USE_UNICODE_AGE_PROPERTIES */ + {uniname2ctype_offset(str1598), 288}, {-1}, - {uniname2ctype_offset(str1265), 302}, -#endif /* USE_UNICODE_AGE_PROPERTIES */ - {uniname2ctype_offset(str1266), 21}, -#ifndef USE_UNICODE_AGE_PROPERTIES - {-1}, {-1}, {-1}, {-1}, -#else /* USE_UNICODE_AGE_PROPERTIES */ - {uniname2ctype_offset(str1267), 288}, + {uniname2ctype_offset(str1600), 396}, {-1}, - {uniname2ctype_offset(str1269), 287}, - {uniname2ctype_offset(str1270), 289}, -#endif /* USE_UNICODE_AGE_PROPERTIES */ - {uniname2ctype_offset(str1271), 250}, -#ifndef USE_UNICODE_AGE_PROPERTIES - {-1}, {-1}, -#else /* USE_UNICODE_AGE_PROPERTIES */ + {uniname2ctype_offset(str1602), 591}, {-1}, - {uniname2ctype_offset(str1273), 286}, -#endif /* USE_UNICODE_AGE_PROPERTIES */ - {uniname2ctype_offset(str1274), 200}, -#ifndef USE_UNICODE_AGE_PROPERTIES + {uniname2ctype_offset(str1604), 53}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -#else /* USE_UNICODE_AGE_PROPERTIES */ - {uniname2ctype_offset(str1275), 285}, + {uniname2ctype_offset(str1621), 419}, + {uniname2ctype_offset(str1622), 608}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1626), 56}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1630), 116}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1634), 345}, + {uniname2ctype_offset(str1635), 242}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -#endif /* USE_UNICODE_AGE_PROPERTIES */ - {uniname2ctype_offset(str1282), 635}, - {-1}, {-1}, - {uniname2ctype_offset(str1285), 105}, + {uniname2ctype_offset(str1642), 522}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1661), 413}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1289), 348}, + {uniname2ctype_offset(str1665), 587}, {-1}, {-1}, - {uniname2ctype_offset(str1292), 397}, + {uniname2ctype_offset(str1668), 84}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1297), 145}, - {-1}, {-1}, - {uniname2ctype_offset(str1300), 86}, - {uniname2ctype_offset(str1301), 141}, + {uniname2ctype_offset(str1673), 184}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1306), 15}, + {uniname2ctype_offset(str1678), 563}, + {uniname2ctype_offset(str1679), 525}, + {-1}, + {uniname2ctype_offset(str1681), 206}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1696), 561}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1314), 193}, + {uniname2ctype_offset(str1704), 333}, + {uniname2ctype_offset(str1705), 539}, + {uniname2ctype_offset(str1706), 546}, + {uniname2ctype_offset(str1707), 421}, + {-1}, + {uniname2ctype_offset(str1709), 106}, + {-1}, + {uniname2ctype_offset(str1711), 488}, + {uniname2ctype_offset(str1712), 238}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1716), 169}, + {uniname2ctype_offset(str1717), 171}, + {-1}, + {uniname2ctype_offset(str1719), 132}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1723), 259}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1730), 290}, + {uniname2ctype_offset(str1731), 179}, + {-1}, + {uniname2ctype_offset(str1733), 457}, + {uniname2ctype_offset(str1734), 596}, + {uniname2ctype_offset(str1735), 118}, + {-1}, + {uniname2ctype_offset(str1737), 269}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1746), 260}, + {-1}, + {uniname2ctype_offset(str1748), 71}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1752), 231}, {-1}, {-1}, - {uniname2ctype_offset(str1317), 86}, + {uniname2ctype_offset(str1755), 96}, + {uniname2ctype_offset(str1756), 134}, + {-1}, + {uniname2ctype_offset(str1758), 242}, + {-1}, + {uniname2ctype_offset(str1760), 127}, + {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1766), 250}, + {-1}, + {uniname2ctype_offset(str1768), 179}, + {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1774), 378}, + {uniname2ctype_offset(str1775), 535}, + {uniname2ctype_offset(str1776), 536}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1780), 124}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1328), 227}, - {-1}, {-1}, - {uniname2ctype_offset(str1331), 263}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1340), 105}, + {uniname2ctype_offset(str1791), 73}, + {uniname2ctype_offset(str1792), 72}, + {-1}, + {uniname2ctype_offset(str1794), 164}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1802), 132}, + {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1807), 249}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1343), 120}, + {uniname2ctype_offset(str1819), 227}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1349), 227}, - {-1}, {-1}, - {uniname2ctype_offset(str1352), 88}, + {uniname2ctype_offset(str1825), 606}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1835), 112}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1839), 213}, + {uniname2ctype_offset(str1840), 129}, {-1}, - {uniname2ctype_offset(str1354), 164}, + {uniname2ctype_offset(str1842), 168}, + {uniname2ctype_offset(str1843), 178}, + {uniname2ctype_offset(str1844), 667}, {-1}, - {uniname2ctype_offset(str1356), 605}, + {uniname2ctype_offset(str1846), 646}, {-1}, - {uniname2ctype_offset(str1358), 633}, + {uniname2ctype_offset(str1848), 510}, + {-1}, {-1}, + {uniname2ctype_offset(str1851), 595}, + {uniname2ctype_offset(str1852), 137}, + {-1}, {-1}, + {uniname2ctype_offset(str1855), 652}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1868), 393}, {-1}, - {uniname2ctype_offset(str1360), 3}, + {uniname2ctype_offset(str1870), 134}, + {uniname2ctype_offset(str1871), 210}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1365), 387}, + {uniname2ctype_offset(str1876), 418}, + {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1882), 210}, + {uniname2ctype_offset(str1883), 630}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1887), 254}, {-1}, - {uniname2ctype_offset(str1367), 534}, + {uniname2ctype_offset(str1889), 410}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1896), 367}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1914), 236}, {-1}, - {uniname2ctype_offset(str1369), 258}, - {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1373), 274}, + {uniname2ctype_offset(str1916), 32}, {-1}, - {uniname2ctype_offset(str1375), 135}, - {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1380), 35}, + {uniname2ctype_offset(str1918), 236}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1928), 512}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1384), 56}, + {uniname2ctype_offset(str1932), 610}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1387), 113}, + {uniname2ctype_offset(str1944), 260}, + {uniname2ctype_offset(str1945), 112}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1392), 138}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1400), 201}, - {uniname2ctype_offset(str1401), 400}, + {uniname2ctype_offset(str1950), 556}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1407), 224}, + {uniname2ctype_offset(str1956), 9}, + {uniname2ctype_offset(str1957), 354}, {-1}, - {uniname2ctype_offset(str1409), 38}, - {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1415), 576}, - {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1419), 140}, - {uniname2ctype_offset(str1420), 140}, + {uniname2ctype_offset(str1959), 614}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1966), 440}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1980), 102}, + {uniname2ctype_offset(str1981), 508}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str1988), 197}, + {-1}, {-1}, + {uniname2ctype_offset(str1991), 204}, + {uniname2ctype_offset(str1992), 416}, + {-1}, {-1}, + {uniname2ctype_offset(str1995), 619}, {-1}, - {uniname2ctype_offset(str1422), 324}, - {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1426), 39}, + {uniname2ctype_offset(str1997), 358}, + {uniname2ctype_offset(str1998), 3}, + {uniname2ctype_offset(str1999), 131}, + {-1}, {-1}, + {uniname2ctype_offset(str2002), 471}, + {uniname2ctype_offset(str2003), 403}, + {uniname2ctype_offset(str2004), 224}, {-1}, - {uniname2ctype_offset(str1428), 181}, - {uniname2ctype_offset(str1429), 36}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1438), 437}, + {uniname2ctype_offset(str2006), 583}, + {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2011), 456}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1442), 544}, - {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1448), 508}, - {uniname2ctype_offset(str1449), 122}, + {uniname2ctype_offset(str2015), 398}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1451), 203}, + {uniname2ctype_offset(str2026), 52}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2030), 165}, {-1}, {-1}, - {uniname2ctype_offset(str1454), 145}, + {uniname2ctype_offset(str2033), 17}, + {-1}, + {uniname2ctype_offset(str2035), 110}, {-1}, {-1}, - {uniname2ctype_offset(str1457), 166}, + {uniname2ctype_offset(str2038), 468}, + {uniname2ctype_offset(str2039), 218}, + {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2044), 461}, + {-1}, + {uniname2ctype_offset(str2046), 20}, {-1}, {-1}, - {uniname2ctype_offset(str1460), 215}, + {uniname2ctype_offset(str2049), 467}, {-1}, - {uniname2ctype_offset(str1462), 559}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1470), 507}, - {uniname2ctype_offset(str1471), 509}, + {uniname2ctype_offset(str2051), 359}, {-1}, {-1}, - {uniname2ctype_offset(str1474), 134}, - {uniname2ctype_offset(str1475), 429}, - {uniname2ctype_offset(str1476), 511}, + {uniname2ctype_offset(str2054), 432}, + {uniname2ctype_offset(str2055), 431}, + {uniname2ctype_offset(str2056), 518}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1480), 247}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1489), 33}, + {uniname2ctype_offset(str2060), 562}, + {uniname2ctype_offset(str2061), 131}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2065), 352}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1495), 262}, + {uniname2ctype_offset(str2071), 585}, {-1}, - {uniname2ctype_offset(str1497), 499}, + {uniname2ctype_offset(str2073), 202}, {-1}, - {uniname2ctype_offset(str1499), 620}, + {uniname2ctype_offset(str2075), 185}, {-1}, - {uniname2ctype_offset(str1501), 196}, + {uniname2ctype_offset(str2077), 424}, + {uniname2ctype_offset(str2078), 426}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1507), 122}, - {uniname2ctype_offset(str1508), 231}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1517), 619}, - {-1}, {-1}, - {uniname2ctype_offset(str1520), 239}, - {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1524), 486}, - {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1529), 120}, + {uniname2ctype_offset(str2093), 167}, + {uniname2ctype_offset(str2094), 36}, {-1}, - {uniname2ctype_offset(str1531), 422}, + {uniname2ctype_offset(str2096), 544}, {-1}, - {uniname2ctype_offset(str1533), 142}, + {uniname2ctype_offset(str2098), 543}, + {uniname2ctype_offset(str2099), 130}, + {uniname2ctype_offset(str2100), 649}, {-1}, {-1}, - {uniname2ctype_offset(str1536), 127}, - {uniname2ctype_offset(str1537), 271}, - {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1542), 468}, - {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1547), 168}, + {uniname2ctype_offset(str2103), 237}, {-1}, - {uniname2ctype_offset(str1549), 522}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1557), 85}, + {uniname2ctype_offset(str2105), 266}, + {uniname2ctype_offset(str2106), 280}, + {-1}, {-1}, + {uniname2ctype_offset(str2109), 631}, + {-1}, + {uniname2ctype_offset(str2111), 257}, + {uniname2ctype_offset(str2112), 141}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1563), 275}, + {uniname2ctype_offset(str2118), 35}, + {-1}, + {uniname2ctype_offset(str2120), 571}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2127), 156}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2136), 61}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2146), 239}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2154), 6}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2162), 235}, + {uniname2ctype_offset(str2163), 188}, + {uniname2ctype_offset(str2164), 355}, {-1}, - {uniname2ctype_offset(str1565), 329}, + {uniname2ctype_offset(str2166), 23}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1570), 210}, + {uniname2ctype_offset(str2171), 151}, {-1}, - {uniname2ctype_offset(str1572), 115}, + {uniname2ctype_offset(str2173), 188}, + {uniname2ctype_offset(str2174), 645}, + {uniname2ctype_offset(str2175), 151}, + {uniname2ctype_offset(str2176), 177}, + {uniname2ctype_offset(str2177), 100}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1577), 570}, + {uniname2ctype_offset(str2182), 100}, {-1}, {-1}, - {uniname2ctype_offset(str1580), 131}, - {-1}, - {uniname2ctype_offset(str1582), 219}, - {uniname2ctype_offset(str1583), 125}, + {uniname2ctype_offset(str2185), 459}, + {uniname2ctype_offset(str2186), 361}, + {uniname2ctype_offset(str2187), 665}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2194), 246}, + {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2199), 578}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1587), 550}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1597), 81}, - {uniname2ctype_offset(str1598), 219}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1607), 592}, - {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1613), 164}, + {uniname2ctype_offset(str2203), 222}, + {-1}, {-1}, + {uniname2ctype_offset(str2206), 246}, + {uniname2ctype_offset(str2207), 372}, + {-1}, {-1}, + {uniname2ctype_offset(str2210), 633}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1617), 505}, - {uniname2ctype_offset(str1618), 274}, + {uniname2ctype_offset(str2214), 222}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1622), 388}, - {uniname2ctype_offset(str1623), 573}, - {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1629), 39}, - {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1635), 72}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1643), 62}, - {uniname2ctype_offset(str1644), 235}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1654), 403}, - {uniname2ctype_offset(str1655), 276}, - {-1}, - {uniname2ctype_offset(str1657), 114}, - {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1662), 129}, - {-1}, - {uniname2ctype_offset(str1664), 451}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1671), 343}, + {uniname2ctype_offset(str2218), 177}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1675), 472}, - {-1}, - {uniname2ctype_offset(str1677), 317}, - {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1682), 634}, - {-1}, - {uniname2ctype_offset(str1684), 199}, - {-1}, - {uniname2ctype_offset(str1686), 93}, - {uniname2ctype_offset(str1687), 141}, + {uniname2ctype_offset(str2222), 448}, + {uniname2ctype_offset(str2223), 616}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1691), 124}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1699), 382}, + {uniname2ctype_offset(str2227), 180}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2231), 257}, {-1}, - {uniname2ctype_offset(str1701), 525}, + {uniname2ctype_offset(str2233), 617}, {-1}, {-1}, - {uniname2ctype_offset(str1704), 207}, + {uniname2ctype_offset(str2236), 36}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1714), 207}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1722), 362}, - {-1}, - {uniname2ctype_offset(str1724), 582}, - {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1728), 221}, - {uniname2ctype_offset(str1729), 445}, - {uniname2ctype_offset(str1730), 222}, - {uniname2ctype_offset(str1731), 538}, - {uniname2ctype_offset(str1732), 249}, - {uniname2ctype_offset(str1733), 123}, - {uniname2ctype_offset(str1734), 114}, - {uniname2ctype_offset(str1735), 260}, - {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1740), 129}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2254), 575}, + {uniname2ctype_offset(str2255), 18}, {-1}, - {uniname2ctype_offset(str1742), 161}, - {-1}, {-1}, - {uniname2ctype_offset(str1745), 528}, - {uniname2ctype_offset(str1746), 405}, - {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1750), 20}, + {uniname2ctype_offset(str2257), 276}, + {uniname2ctype_offset(str2258), 186}, {-1}, - {uniname2ctype_offset(str1752), 519}, - {uniname2ctype_offset(str1753), 148}, + {uniname2ctype_offset(str2260), 157}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1757), 518}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1766), 73}, - {-1}, - {uniname2ctype_offset(str1768), 148}, - {uniname2ctype_offset(str1769), 377}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1776), 126}, - {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1781), 556}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1788), 97}, + {uniname2ctype_offset(str2264), 38}, + {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2270), 279}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1793), 97}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1806), 351}, + {uniname2ctype_offset(str2275), 199}, + {uniname2ctype_offset(str2276), 42}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1810), 640}, - {uniname2ctype_offset(str1811), 247}, - {-1}, - {uniname2ctype_offset(str1813), 266}, + {uniname2ctype_offset(str2280), 58}, + {uniname2ctype_offset(str2281), 115}, + {-1}, {-1}, + {uniname2ctype_offset(str2284), 207}, + {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2289), 586}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1821), 224}, + {uniname2ctype_offset(str2297), 671}, + {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2302), 576}, + {uniname2ctype_offset(str2303), 549}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1828), 402}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1838), 623}, - {-1}, {-1}, - {uniname2ctype_offset(str1841), 460}, - {uniname2ctype_offset(str1842), 394}, - {uniname2ctype_offset(str1843), 65}, - {-1}, - {uniname2ctype_offset(str1845), 265}, - {-1}, {-1}, - {uniname2ctype_offset(str1848), 109}, - {-1}, {-1}, - {uniname2ctype_offset(str1851), 137}, + {uniname2ctype_offset(str2310), 66}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1866), 61}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1871), 494}, + {uniname2ctype_offset(str2324), 391}, + {uniname2ctype_offset(str2325), 489}, + {-1}, + {uniname2ctype_offset(str2327), 254}, + {-1}, + {uniname2ctype_offset(str2329), 523}, + {uniname2ctype_offset(str2330), 1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1881), 63}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1888), 531}, - {uniname2ctype_offset(str1889), 555}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1896), 626}, - {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1902), 434}, {-1}, - {uniname2ctype_offset(str1904), 455}, - {uniname2ctype_offset(str1905), 590}, + {uniname2ctype_offset(str2341), 394}, + {uniname2ctype_offset(str2342), 450}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1912), 586}, - {uniname2ctype_offset(str1913), 143}, - {-1}, {-1}, - {uniname2ctype_offset(str1916), 594}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1924), 143}, + {uniname2ctype_offset(str2349), 150}, + {uniname2ctype_offset(str2350), 370}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1929), 432}, + {uniname2ctype_offset(str2355), 117}, {-1}, {-1}, - {uniname2ctype_offset(str1932), 415}, + {uniname2ctype_offset(str2358), 490}, + {uniname2ctype_offset(str2359), 142}, + {uniname2ctype_offset(str2360), 505}, {-1}, {-1}, - {uniname2ctype_offset(str1935), 264}, - {uniname2ctype_offset(str1936), 338}, - {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1941), 27}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1950), 424}, - {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1956), 252}, - {-1}, - {uniname2ctype_offset(str1958), 109}, - {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1964), 440}, + {uniname2ctype_offset(str2363), 666}, {-1}, {-1}, - {uniname2ctype_offset(str1967), 492}, - {uniname2ctype_offset(str1968), 644}, - {uniname2ctype_offset(str1969), 251}, + {uniname2ctype_offset(str2366), 399}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1974), 358}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1981), 176}, + {uniname2ctype_offset(str2380), 469}, + {uniname2ctype_offset(str2381), 140}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str1985), 408}, + {uniname2ctype_offset(str2385), 623}, {-1}, {-1}, - {uniname2ctype_offset(str1988), 441}, - {-1}, {-1}, - {uniname2ctype_offset(str1991), 1}, - {-1}, - {uniname2ctype_offset(str1993), 375}, - {uniname2ctype_offset(str1994), 175}, - {-1}, - {uniname2ctype_offset(str1996), 42}, + {uniname2ctype_offset(str2388), 258}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2398), 228}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2001), 110}, - {uniname2ctype_offset(str2002), 598}, - {-1}, - {uniname2ctype_offset(str2004), 110}, + {uniname2ctype_offset(str2403), 627}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, + {uniname2ctype_offset(str2415), 339}, + {-1}, {-1}, + {uniname2ctype_offset(str2418), 117}, {-1}, - {uniname2ctype_offset(str2006), 410}, + {uniname2ctype_offset(str2420), 157}, + {uniname2ctype_offset(str2421), 529}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2010), 378}, - {uniname2ctype_offset(str2011), 269}, - {uniname2ctype_offset(str2012), 565}, - {-1}, - {uniname2ctype_offset(str2014), 336}, - {uniname2ctype_offset(str2015), 117}, - {uniname2ctype_offset(str2016), 209}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2023), 32}, - {uniname2ctype_offset(str2024), 506}, - {-1}, - {uniname2ctype_offset(str2026), 176}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2033), 8}, + {uniname2ctype_offset(str2425), 408}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2040), 539}, - {-1}, - {uniname2ctype_offset(str2042), 121}, - {uniname2ctype_offset(str2043), 17}, - {uniname2ctype_offset(str2044), 117}, - {-1}, {-1}, - {uniname2ctype_offset(str2047), 107}, - {uniname2ctype_offset(str2048), 526}, + {uniname2ctype_offset(str2432), 429}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2436), 238}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2062), 130}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2070), 9}, - {-1}, {-1}, - {uniname2ctype_offset(str2073), 345}, + {uniname2ctype_offset(str2450), 282}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2077), 150}, - {uniname2ctype_offset(str2078), 256}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, - {uniname2ctype_offset(str2090), 277}, + {uniname2ctype_offset(str2454), 153}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2458), 153}, {-1}, - {uniname2ctype_offset(str2092), 150}, + {uniname2ctype_offset(str2460), 168}, {-1}, {-1}, - {uniname2ctype_offset(str2095), 356}, + {uniname2ctype_offset(str2463), 386}, + {uniname2ctype_offset(str2464), 83}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2103), 162}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2110), 123}, - {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2114), 439}, - {uniname2ctype_offset(str2115), 384}, - {-1}, - {uniname2ctype_offset(str2117), 174}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, - {uniname2ctype_offset(str2128), 215}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2135), 128}, - {-1}, - {uniname2ctype_offset(str2137), 12}, + {uniname2ctype_offset(str2472), 474}, + {uniname2ctype_offset(str2473), 464}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2141), 244}, + {uniname2ctype_offset(str2477), 449}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2145), 52}, - {uniname2ctype_offset(str2146), 416}, - {-1}, {-1}, - {uniname2ctype_offset(str2149), 221}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2163), 251}, + {uniname2ctype_offset(str2481), 207}, {-1}, - {uniname2ctype_offset(str2165), 174}, - {uniname2ctype_offset(str2166), 5}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2174), 233}, + {uniname2ctype_offset(str2483), 455}, + {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2489), 374}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2178), 233}, - {-1}, {-1}, - {uniname2ctype_offset(str2181), 139}, - {uniname2ctype_offset(str2182), 216}, + {uniname2ctype_offset(str2493), 270}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2503), 267}, + {uniname2ctype_offset(str2504), 12}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2195), 354}, - {uniname2ctype_offset(str2196), 496}, + {uniname2ctype_offset(str2508), 668}, + {-1}, + {uniname2ctype_offset(str2510), 162}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2519), 377}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2207), 196}, - {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2211), 20}, - {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2216), 367}, - {uniname2ctype_offset(str2217), 128}, - {uniname2ctype_offset(str2218), 547}, - {uniname2ctype_offset(str2219), 78}, - {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2224), 453}, - {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2228), 43}, - {uniname2ctype_offset(str2229), 35}, + {uniname2ctype_offset(str2539), 124}, + {-1}, + {uniname2ctype_offset(str2541), 5}, {-1}, {-1}, - {uniname2ctype_offset(str2232), 385}, - {uniname2ctype_offset(str2233), 216}, - {uniname2ctype_offset(str2234), 92}, - {uniname2ctype_offset(str2235), 489}, + {uniname2ctype_offset(str2544), 476}, + {uniname2ctype_offset(str2545), 217}, + {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2550), 55}, + {-1}, + {uniname2ctype_offset(str2552), 577}, + {-1}, + {uniname2ctype_offset(str2554), 240}, + {-1}, + {uniname2ctype_offset(str2556), 566}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2565), 263}, + {uniname2ctype_offset(str2566), 356}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2241), 92}, + {uniname2ctype_offset(str2572), 256}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2576), 162}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2244), 443}, + {uniname2ctype_offset(str2588), 258}, + {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2593), 121}, + {uniname2ctype_offset(str2594), 388}, {-1}, {-1}, - {uniname2ctype_offset(str2247), 36}, - {uniname2ctype_offset(str2248), 602}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2276), 418}, + {uniname2ctype_offset(str2597), 658}, + {uniname2ctype_offset(str2598), 402}, + {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2603), 656}, {-1}, - {uniname2ctype_offset(str2278), 124}, - {uniname2ctype_offset(str2279), 192}, + {uniname2ctype_offset(str2605), 92}, + {uniname2ctype_offset(str2606), 289}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2615), 91}, + {uniname2ctype_offset(str2616), 27}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2283), 214}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2620), 466}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2296), 639}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2305), 205}, - {-1}, {-1}, - {uniname2ctype_offset(str2308), 234}, + {uniname2ctype_offset(str2624), 261}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2312), 177}, + {uniname2ctype_offset(str2628), 615}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2315), 601}, - {uniname2ctype_offset(str2316), 638}, + {uniname2ctype_offset(str2640), 400}, {-1}, - {uniname2ctype_offset(str2318), 202}, + {uniname2ctype_offset(str2642), 201}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2649), 390}, {-1}, {-1}, - {uniname2ctype_offset(str2321), 153}, - {-1}, - {uniname2ctype_offset(str2323), 172}, + {uniname2ctype_offset(str2652), 8}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2666), 470}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2327), 381}, + {uniname2ctype_offset(str2670), 145}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2331), 636}, + {uniname2ctype_offset(str2674), 26}, {-1}, - {uniname2ctype_offset(str2333), 134}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2343), 591}, - {uniname2ctype_offset(str2344), 442}, - {uniname2ctype_offset(str2345), 241}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2353), 202}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2361), 606}, + {uniname2ctype_offset(str2676), 639}, {-1}, {-1}, - {uniname2ctype_offset(str2364), 323}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2373), 37}, - {uniname2ctype_offset(str2374), 392}, - {uniname2ctype_offset(str2375), 197}, + {uniname2ctype_offset(str2679), 21}, + {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2685), 103}, + {-1}, + {uniname2ctype_offset(str2687), 29}, + {-1}, {-1}, + {uniname2ctype_offset(str2690), 223}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2397), 421}, - {uniname2ctype_offset(str2398), 413}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2405), 165}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2414), 82}, + {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2713), 85}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2427), 23}, + {uniname2ctype_offset(str2723), 383}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2733), 261}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2433), 339}, - {uniname2ctype_offset(str2434), 154}, - {-1}, {-1}, - {uniname2ctype_offset(str2437), 194}, + {uniname2ctype_offset(str2739), 550}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2746), 175}, {-1}, {-1}, - {uniname2ctype_offset(str2440), 100}, + {uniname2ctype_offset(str2749), 263}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, - {uniname2ctype_offset(str2451), 103}, - {-1}, {-1}, - {uniname2ctype_offset(str2454), 220}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2460), 257}, - {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2464), 159}, + {uniname2ctype_offset(str2773), 291}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2470), 448}, - {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2475), 142}, - {uniname2ctype_offset(str2476), 558}, + {uniname2ctype_offset(str2779), 437}, + {-1}, {-1}, + {uniname2ctype_offset(str2782), 214}, + {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2788), 122}, {-1}, - {uniname2ctype_offset(str2478), 417}, - {uniname2ctype_offset(str2479), 361}, + {uniname2ctype_offset(str2790), 54}, {-1}, - {uniname2ctype_offset(str2481), 386}, + {uniname2ctype_offset(str2792), 499}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2500), 121}, - {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2506), 532}, + {uniname2ctype_offset(str2811), 34}, + {uniname2ctype_offset(str2812), 397}, + {uniname2ctype_offset(str2813), 64}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2511), 244}, - {-1}, - {uniname2ctype_offset(str2513), 630}, + {uniname2ctype_offset(str2818), 219}, + {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2823), 401}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2530), 82}, - {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2534), 340}, - {uniname2ctype_offset(str2535), 237}, + {uniname2ctype_offset(str2833), 507}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2545), 277}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2849), 225}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2856), 85}, + {-1}, + {uniname2ctype_offset(str2858), 662}, + {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2863), 219}, {-1}, {-1}, - {uniname2ctype_offset(str2548), 118}, - {uniname2ctype_offset(str2549), 159}, + {uniname2ctype_offset(str2866), 128}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2870), 264}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, + {uniname2ctype_offset(str2881), 626}, {-1}, - {uniname2ctype_offset(str2551), 89}, + {uniname2ctype_offset(str2883), 142}, + {uniname2ctype_offset(str2884), 384}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2564), 372}, {-1}, {-1}, - {uniname2ctype_offset(str2567), 318}, + {uniname2ctype_offset(str2896), 81}, + {uniname2ctype_offset(str2897), 48}, {-1}, {-1}, - {uniname2ctype_offset(str2570), 491}, + {uniname2ctype_offset(str2900), 287}, {-1}, - {uniname2ctype_offset(str2572), 473}, + {uniname2ctype_offset(str2902), 443}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2916), 193}, {-1}, - {uniname2ctype_offset(str2574), 246}, - {uniname2ctype_offset(str2575), 474}, - {uniname2ctype_offset(str2576), 275}, - {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2582), 391}, + {uniname2ctype_offset(str2918), 657}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2588), 154}, + {uniname2ctype_offset(str2924), 95}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2928), 493}, + {-1}, + {uniname2ctype_offset(str2930), 380}, + {uniname2ctype_offset(str2931), 95}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2935), 458}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2945), 244}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2602), 210}, - {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2606), 374}, + {uniname2ctype_offset(str2950), 195}, + {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2956), 86}, + {-1}, {-1}, + {uniname2ctype_offset(str2959), 275}, + {uniname2ctype_offset(str2960), 97}, + {uniname2ctype_offset(str2961), 214}, + {uniname2ctype_offset(str2962), 86}, {-1}, - {uniname2ctype_offset(str2608), 458}, - {uniname2ctype_offset(str2609), 55}, + {uniname2ctype_offset(str2964), 287}, + {uniname2ctype_offset(str2965), 434}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2974), 240}, + {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2980), 37}, + {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str2985), 334}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2625), 262}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3007), 201}, + {-1}, + {uniname2ctype_offset(str3009), 102}, + {-1}, + {uniname2ctype_offset(str3011), 133}, + {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3017), 121}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3034), 54}, + {uniname2ctype_offset(str3035), 326}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2648), 254}, + {uniname2ctype_offset(str3040), 93}, + {-1}, + {uniname2ctype_offset(str3042), 262}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2652), 383}, + {uniname2ctype_offset(str3046), 106}, + {uniname2ctype_offset(str3047), 66}, + {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3053), 607}, + {-1}, {-1}, + {uniname2ctype_offset(str3056), 28}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2656), 368}, - {uniname2ctype_offset(str2657), 112}, + {uniname2ctype_offset(str3060), 155}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2665), 87}, - {uniname2ctype_offset(str2666), 50}, - {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2670), 632}, - {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2674), 87}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2688), 139}, - {uniname2ctype_offset(str2689), 641}, - {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2694), 48}, + {uniname2ctype_offset(str3068), 321}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3077), 63}, + {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3083), 325}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3096), 216}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3103), 245}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3112), 264}, {-1}, - {uniname2ctype_offset(str2705), 481}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, - {uniname2ctype_offset(str2726), 226}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2750), 557}, + {uniname2ctype_offset(str3114), 273}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3127), 255}, {-1}, - {uniname2ctype_offset(str2761), 18}, - {uniname2ctype_offset(str2762), 265}, - {-1}, {-1}, - {uniname2ctype_offset(str2765), 133}, - {uniname2ctype_offset(str2766), 54}, - {-1}, {-1}, - {uniname2ctype_offset(str2769), 483}, - {-1}, {-1}, - {uniname2ctype_offset(str2772), 199}, - {-1}, {-1}, - {uniname2ctype_offset(str2775), 38}, + {uniname2ctype_offset(str3129), 600}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3138), 640}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2786), 4}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2793), 34}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2801), 29}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2808), 512}, + {uniname2ctype_offset(str3149), 541}, {-1}, - {uniname2ctype_offset(str2810), 226}, + {uniname2ctype_offset(str3151), 202}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3158), 126}, + {uniname2ctype_offset(str3159), 485}, + {uniname2ctype_offset(str3160), 379}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3179), 251}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2816), 310}, - {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2821), 393}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2830), 614}, - {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2834), 364}, + {uniname2ctype_offset(str3185), 494}, {-1}, - {uniname2ctype_offset(str2836), 78}, + {uniname2ctype_offset(str3187), 572}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, - {uniname2ctype_offset(str2847), 248}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2852), 305}, + {uniname2ctype_offset(str3201), 256}, + {uniname2ctype_offset(str3202), 487}, {-1}, {-1}, - {uniname2ctype_offset(str2855), 190}, - {uniname2ctype_offset(str2856), 66}, + {uniname2ctype_offset(str3205), 51}, {-1}, {-1}, - {uniname2ctype_offset(str2859), 427}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2867), 309}, - {uniname2ctype_offset(str2868), 248}, + {uniname2ctype_offset(str3208), 291}, {-1}, {-1}, - {uniname2ctype_offset(str2871), 254}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2879), 204}, + {uniname2ctype_offset(str3211), 64}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2886), 631}, + {uniname2ctype_offset(str3218), 265}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2902), 477}, {-1}, - {uniname2ctype_offset(str2904), 464}, - {uniname2ctype_offset(str2905), 273}, + {uniname2ctype_offset(str3238), 194}, + {uniname2ctype_offset(str3239), 406}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3247), 194}, + {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3253), 609}, + {uniname2ctype_offset(str3254), 484}, + {-1}, {-1}, + {uniname2ctype_offset(str3257), 452}, {-1}, - {uniname2ctype_offset(str2907), 273}, + {uniname2ctype_offset(str3259), 642}, + {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3265), 409}, {-1}, - {uniname2ctype_offset(str2909), 577}, + {uniname2ctype_offset(str3267), 597}, + {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3273), 407}, + {uniname2ctype_offset(str3274), 491}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3290), 229}, {-1}, - {uniname2ctype_offset(str2911), 450}, + {uniname2ctype_offset(str3292), 347}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, + {uniname2ctype_offset(str3312), 193}, + {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3318), 232}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, - {uniname2ctype_offset(str2941), 363}, + {uniname2ctype_offset(str3328), 628}, + {-1}, + {uniname2ctype_offset(str3330), 136}, + {uniname2ctype_offset(str3331), 641}, + {uniname2ctype_offset(str3332), 216}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3340), 183}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3344), 517}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, - {uniname2ctype_offset(str2953), 198}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3357), 480}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3361), 63}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3371), 433}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3389), 329}, {-1}, - {uniname2ctype_offset(str2964), 520}, - {-1}, - {uniname2ctype_offset(str2966), 238}, - {uniname2ctype_offset(str2967), 43}, - {-1}, {-1}, - {uniname2ctype_offset(str2970), 88}, + {uniname2ctype_offset(str3391), 331}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2980), 195}, - {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2984), 574}, + {uniname2ctype_offset(str3401), 92}, + {uniname2ctype_offset(str3402), 50}, + {uniname2ctype_offset(str3403), 247}, {-1}, - {uniname2ctype_offset(str2986), 118}, - {uniname2ctype_offset(str2987), 54}, - {uniname2ctype_offset(str2988), 471}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str2997), 603}, - {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3001), 180}, - {uniname2ctype_offset(str3002), 64}, - {-1}, {-1}, - {uniname2ctype_offset(str3005), 475}, - {uniname2ctype_offset(str3006), 583}, + {uniname2ctype_offset(str3405), 271}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3015), 83}, - {-1}, {-1}, - {uniname2ctype_offset(str3018), 94}, - {uniname2ctype_offset(str3019), 165}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3026), 83}, - {uniname2ctype_offset(str3027), 503}, + {uniname2ctype_offset(str3414), 229}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3035), 232}, + {uniname2ctype_offset(str3422), 423}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3431), 353}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3446), 150}, + {uniname2ctype_offset(str3447), 324}, + {uniname2ctype_offset(str3448), 320}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3042), 211}, + {uniname2ctype_offset(str3455), 43}, + {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3460), 537}, {-1}, {-1}, - {uniname2ctype_offset(str3045), 615}, + {uniname2ctype_offset(str3463), 212}, + {uniname2ctype_offset(str3464), 412}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3048), 119}, + {uniname2ctype_offset(str3476), 198}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3052), 89}, - {uniname2ctype_offset(str3053), 229}, + {uniname2ctype_offset(str3480), 87}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3058), 185}, + {uniname2ctype_offset(str3494), 87}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3067), 185}, - {uniname2ctype_offset(str3068), 99}, - {-1}, {-1}, - {uniname2ctype_offset(str3071), 198}, - {uniname2ctype_offset(str3072), 133}, + {uniname2ctype_offset(str3503), 133}, + {uniname2ctype_offset(str3504), 20}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3522), 43}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3532), 248}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3082), 130}, - {-1}, - {uniname2ctype_offset(str3084), 237}, {-1}, - {uniname2ctype_offset(str3086), 84}, - {uniname2ctype_offset(str3087), 342}, - {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3091), 261}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3099), 478}, + {uniname2ctype_offset(str3543), 183}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3104), 84}, - {-1}, - {uniname2ctype_offset(str3106), 562}, - {uniname2ctype_offset(str3107), 313}, + {uniname2ctype_offset(str3548), 255}, + {-1}, {-1}, + {uniname2ctype_offset(str3551), 4}, + {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3557), 234}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3561), 653}, {-1}, - {uniname2ctype_offset(str3109), 315}, - {uniname2ctype_offset(str3110), 152}, - {uniname2ctype_offset(str3111), 191}, + {uniname2ctype_offset(str3563), 99}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3118), 90}, + {uniname2ctype_offset(str3570), 99}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3580), 181}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3123), 107}, - {-1}, - {uniname2ctype_offset(str3125), 191}, + {uniname2ctype_offset(str3585), 427}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3135), 452}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3142), 585}, - {-1}, {-1}, - {uniname2ctype_offset(str3145), 183}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3155), 182}, - {-1}, - {uniname2ctype_offset(str3157), 231}, - {uniname2ctype_offset(str3158), 328}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3176), 396}, - {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3180), 331}, + {uniname2ctype_offset(str3613), 45}, + {uniname2ctype_offset(str3614), 208}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3629), 126}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3193), 433}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3209), 62}, - {-1}, {-1}, - {uniname2ctype_offset(str3212), 211}, - {-1}, {-1}, - {uniname2ctype_offset(str3215), 180}, {-1}, {-1}, - {uniname2ctype_offset(str3218), 125}, + {uniname2ctype_offset(str3650), 247}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3654), 62}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3663), 62}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3670), 497}, + {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3676), 644}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3689), 285}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3237), 390}, - {-1}, - {uniname2ctype_offset(str3239), 308}, - {uniname2ctype_offset(str3240), 304}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3248), 213}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3707), 136}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3714), 277}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3254), 252}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, - {uniname2ctype_offset(str3265), 610}, - {-1}, - {uniname2ctype_offset(str3267), 28}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3275), 146}, + {uniname2ctype_offset(str3720), 601}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3284), 618}, + {uniname2ctype_offset(str3729), 278}, {-1}, {-1}, - {uniname2ctype_offset(str3287), 223}, + {uniname2ctype_offset(str3732), 223}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3297), 311}, - {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3303), 307}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3313), 255}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3320), 223}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3328), 63}, - {uniname2ctype_offset(str3329), 625}, - {-1}, - {uniname2ctype_offset(str3331), 222}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3338), 264}, + {uniname2ctype_offset(str3757), 272}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3766), 165}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3348), 407}, - {-1}, - {uniname2ctype_offset(str3350), 501}, - {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3355), 47}, - {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3360), 337}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, - {uniname2ctype_offset(str3371), 126}, - {uniname2ctype_offset(str3372), 16}, - {uniname2ctype_offset(str3373), 253}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3377), 147}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3391), 238}, + {uniname2ctype_offset(str3788), 127}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3396), 613}, + {uniname2ctype_offset(str3793), 156}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3810), 248}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3814), 327}, + {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3820), 323}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3405), 469}, + {uniname2ctype_offset(str3829), 129}, + {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3835), 81}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, - {uniname2ctype_offset(str3416), 51}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, - {uniname2ctype_offset(str3428), 253}, + {uniname2ctype_offset(str3854), 481}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3877), 651}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3433), 205}, + {uniname2ctype_offset(str3882), 436}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3436), 213}, + {uniname2ctype_offset(str3894), 200}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3455), 225}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3925), 180}, {-1}, {-1}, - {uniname2ctype_offset(str3458), 10}, - {-1}, - {uniname2ctype_offset(str3460), 627}, + {uniname2ctype_offset(str3928), 332}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3483), 245}, + {-1}, {-1}, + {uniname2ctype_offset(str3949), 57}, + {uniname2ctype_offset(str3950), 65}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3502), 49}, {-1}, - {uniname2ctype_offset(str3504), 80}, - {uniname2ctype_offset(str3505), 479}, - {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3511), 411}, + {uniname2ctype_offset(str3979), 226}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str3996), 290}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, - {uniname2ctype_offset(str3532), 578}, - {uniname2ctype_offset(str3533), 57}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str4018), 636}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3558), 59}, + {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str4032), 226}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3580), 179}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3590), 103}, + {uniname2ctype_offset(str4060), 629}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3613), 41}, - {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3618), 99}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str4097), 241}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3648), 465}, + {uniname2ctype_offset(str4109), 292}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, - {uniname2ctype_offset(str3659), 178}, - {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3664), 177}, + {uniname2ctype_offset(str4119), 217}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3686), 204}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, + {uniname2ctype_offset(str4148), 336}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3689), 246}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3698), 504}, - {uniname2ctype_offset(str3699), 552}, + {uniname2ctype_offset(str4160), 231}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str4164), 149}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3701), 96}, + {uniname2ctype_offset(str4175), 265}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3705), 320}, + {uniname2ctype_offset(str4179), 483}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3710), 201}, - {-1}, {-1}, - {uniname2ctype_offset(str3713), 96}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3721), 438}, + {uniname2ctype_offset(str4184), 16}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str4212), 41}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str4222), 103}, + {uniname2ctype_offset(str4223), 47}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str4239), 46}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str4248), 204}, + {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str4254), 122}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3744), 190}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3754), 71}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3766), 467}, + {uniname2ctype_offset(str4356), 252}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3799), 214}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3807), 260}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3842), 182}, - {-1}, {-1}, - {uniname2ctype_offset(str3845), 259}, - {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3850), 245}, - {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3854), 65}, - {-1}, {-1}, - {uniname2ctype_offset(str3857), 616}, + {uniname2ctype_offset(str4418), 521}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str4425), 182}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, - {uniname2ctype_offset(str3868), 261}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3881), 228}, - {-1}, {-1}, - {uniname2ctype_offset(str3884), 306}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3891), 30}, + {uniname2ctype_offset(str4468), 49}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str4484), 454}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3924), 420}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str4509), 495}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str4517), 135}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3942), 100}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str4545), 272}, {-1}, - {uniname2ctype_offset(str3944), 436}, - {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3949), 276}, + {uniname2ctype_offset(str4547), 594}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str4562), 446}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3976), 604}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, - {uniname2ctype_offset(str3998), 430}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str4007), 454}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, + {uniname2ctype_offset(str4609), 93}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, + {uniname2ctype_offset(str4638), 119}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str4652), 119}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str4670), 520}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str4687), 65}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str4703), 135}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str4106), 45}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str4116), 132}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str4728), 328}, + {uniname2ctype_offset(str4729), 330}, + {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str4734), 592}, + {-1}, + {uniname2ctype_offset(str4736), 208}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str4127), 132}, + {uniname2ctype_offset(str4747), 593}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str4756), 322}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str4771), 669}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str4169), 220}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str4821), 344}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str4231), 153}, + {uniname2ctype_offset(str4865), 417}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str4896), 425}, + {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str4902), 235}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str4917), 10}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, @@ -45384,18 +48271,15 @@ uniname2ctype_p (register const char *str, register size_t len) {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str4308), 401}, - {uniname2ctype_offset(str4309), 162}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str5031), 482}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str4348), 571}, + {uniname2ctype_offset(str5043), 59}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, - {uniname2ctype_offset(str4361), 572}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, @@ -45406,64 +48290,48 @@ uniname2ctype_p (register const char *str, register size_t len) {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str4459), 119}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str4487), 147}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, + {uniname2ctype_offset(str5216), 444}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, + {uniname2ctype_offset(str5272), 71}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str4604), 116}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, - {uniname2ctype_offset(str4626), 116}, - {uniname2ctype_offset(str4627), 255}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, - {uniname2ctype_offset(str4674), 642}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str4683), 466}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, - {uniname2ctype_offset(str4695), 80}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, - {uniname2ctype_offset(str4734), 179}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str4755), 312}, - {uniname2ctype_offset(str4756), 314}, + {uniname2ctype_offset(str5437), 30}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str4772), 409}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, - {uniname2ctype_offset(str4783), 316}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str4810), 90}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, @@ -45471,32 +48339,31 @@ uniname2ctype_p (register const char *str, register size_t len) {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str5541), 158}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str4898), 75}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str5603), 654}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str5646), 270}, + {uniname2ctype_offset(str5647), 185}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, - {uniname2ctype_offset(str4982), 232}, - {-1}, {-1}, {-1}, - {uniname2ctype_offset(str4986), 428}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str5666), 182}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str5018), 46}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, - {uniname2ctype_offset(str5038), 242}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, @@ -45507,28 +48374,6 @@ uniname2ctype_p (register const char *str, register size_t len) {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str5134), 628}, -#endif /* USE_UNICODE_PROPERTIES */ - {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -#ifndef USE_UNICODE_PROPERTIES - {uniname2ctype_offset(str6), 12}, - {uniname2ctype_offset(str7), 7}, - {uniname2ctype_offset(str8), 15}, - {uniname2ctype_offset(str9), 1}, - {uniname2ctype_offset(str10), 13}, - {uniname2ctype_offset(str11), 11}, - {uniname2ctype_offset(str12), 10}, - {uniname2ctype_offset(str13), 14}, - {uniname2ctype_offset(str14), 3}, - {uniname2ctype_offset(str15), 9}, - {uniname2ctype_offset(str16), 8}, - {uniname2ctype_offset(str17), 6}, - {uniname2ctype_offset(str18), 5}, - {uniname2ctype_offset(str19), 4}, - {uniname2ctype_offset(str20), 2} -#else /* USE_UNICODE_PROPERTIES */ - {uniname2ctype_offset(str5141), 155}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, @@ -45541,13 +48386,13 @@ uniname2ctype_p (register const char *str, register size_t len) {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str5914), 228}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str5300), 225}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, @@ -45560,6 +48405,9 @@ uniname2ctype_p (register const char *str, register size_t len) {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str6073), 78}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, @@ -45578,6 +48426,7 @@ uniname2ctype_p (register const char *str, register size_t len) {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str6245), 670}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, @@ -45609,6 +48458,8 @@ uniname2ctype_p (register const char *str, register size_t len) {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, + {uniname2ctype_offset(str6528), 83}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, @@ -45623,8 +48474,6 @@ uniname2ctype_p (register const char *str, register size_t len) {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str5980), 155}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, @@ -45638,7 +48487,11 @@ uniname2ctype_p (register const char *str, register size_t len) {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, - {uniname2ctype_offset(str6098), 643} + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, + {uniname2ctype_offset(str6807), 158} #endif /* USE_UNICODE_PROPERTIES */ }; @@ -45669,22 +48522,22 @@ uniname2ctype(const UChar *name, unsigned int len) return -1; } #if defined ONIG_UNICODE_VERSION_STRING && !( \ - ONIG_UNICODE_VERSION_MAJOR == 15 && \ + ONIG_UNICODE_VERSION_MAJOR == 16 && \ ONIG_UNICODE_VERSION_MINOR == 0 && \ ONIG_UNICODE_VERSION_TEENY == 0 && \ 1) # error ONIG_UNICODE_VERSION_STRING mismatch #endif -#define ONIG_UNICODE_VERSION_STRING "15.0.0" -#define ONIG_UNICODE_VERSION_MAJOR 15 +#define ONIG_UNICODE_VERSION_STRING "16.0.0" +#define ONIG_UNICODE_VERSION_MAJOR 16 #define ONIG_UNICODE_VERSION_MINOR 0 #define ONIG_UNICODE_VERSION_TEENY 0 #if defined ONIG_UNICODE_EMOJI_VERSION_STRING && !( \ - ONIG_UNICODE_EMOJI_VERSION_MAJOR == 15 && \ + ONIG_UNICODE_EMOJI_VERSION_MAJOR == 16 && \ ONIG_UNICODE_EMOJI_VERSION_MINOR == 0 && \ 1) # error ONIG_UNICODE_EMOJI_VERSION_STRING mismatch #endif -#define ONIG_UNICODE_EMOJI_VERSION_STRING "15.0" -#define ONIG_UNICODE_EMOJI_VERSION_MAJOR 15 +#define ONIG_UNICODE_EMOJI_VERSION_STRING "16.0" +#define ONIG_UNICODE_EMOJI_VERSION_MAJOR 16 #define ONIG_UNICODE_EMOJI_VERSION_MINOR 0 diff --git a/encoding.c b/encoding.c index 8bfab731770fdb..6fbb739bb631b7 100644 --- a/encoding.c +++ b/encoding.c @@ -24,6 +24,7 @@ #include "internal/string.h" #include "internal/vm.h" #include "regenc.h" +#include "ruby/atomic.h" #include "ruby/encoding.h" #include "ruby/util.h" #include "ruby_assert.h" @@ -60,6 +61,7 @@ VALUE rb_cEncoding; static VALUE rb_encoding_list; struct rb_encoding_entry { + rb_atomic_t loaded; const char *name; rb_encoding *enc; rb_encoding *base; @@ -71,19 +73,33 @@ static struct enc_table { st_table *names; } global_enc_table; +static int +enc_names_free_i(st_data_t name, st_data_t idx, st_data_t args) +{ + ruby_xfree((void *)name); + return ST_DELETE; +} + +void +rb_free_global_enc_table(void) +{ + for (size_t i = 0; i < ENCODING_LIST_CAPA; i++) { + xfree((void *)global_enc_table.list[i].enc); + } + + st_foreach(global_enc_table.names, enc_names_free_i, (st_data_t)0); + st_free_table(global_enc_table.names); +} + static rb_encoding *global_enc_ascii, *global_enc_utf_8, *global_enc_us_ascii; -#define GLOBAL_ENC_TABLE_ENTER(enc_table) struct enc_table *enc_table = &global_enc_table; RB_VM_LOCK_ENTER() -#define GLOBAL_ENC_TABLE_LEAVE() RB_VM_LOCK_LEAVE() -#define GLOBAL_ENC_TABLE_EVAL(enc_table, expr) do { \ - GLOBAL_ENC_TABLE_ENTER(enc_table); \ - { \ - expr; \ - } \ - GLOBAL_ENC_TABLE_LEAVE(); \ -} while (0) +#define GLOBAL_ENC_TABLE_LOCKING(tbl) \ + for (struct enc_table *tbl = &global_enc_table, **locking = &tbl; \ + locking; \ + locking = NULL) \ + RB_VM_LOCKING() #define ENC_DUMMY_FLAG (1<<24) @@ -330,6 +346,8 @@ enc_table_expand(struct enc_table *enc_table, int newsize) static int enc_register_at(struct enc_table *enc_table, int index, const char *name, rb_encoding *base_encoding) { + ASSERT_vm_locking(); + struct rb_encoding_entry *ent = &enc_table->list[index]; rb_raw_encoding *encoding; @@ -344,6 +362,7 @@ enc_register_at(struct enc_table *enc_table, int index, const char *name, rb_enc if (!encoding) { encoding = xmalloc(sizeof(rb_encoding)); } + if (base_encoding) { *encoding = *base_encoding; } @@ -356,12 +375,18 @@ enc_register_at(struct enc_table *enc_table, int index, const char *name, rb_enc st_insert(enc_table->names, (st_data_t)name, (st_data_t)index); enc_list_update(index, encoding); + + // max_enc_len is used to mark a fully loaded encoding. + RUBY_ATOMIC_SET(ent->loaded, encoding->max_enc_len); + return index; } static int enc_register(struct enc_table *enc_table, const char *name, rb_encoding *encoding) { + ASSERT_vm_locking(); + int index = enc_table->count; enc_table->count = enc_table_expand(enc_table, index + 1); @@ -391,8 +416,7 @@ rb_enc_register(const char *name, rb_encoding *encoding) { int index; - GLOBAL_ENC_TABLE_ENTER(enc_table); - { + GLOBAL_ENC_TABLE_LOCKING(enc_table) { index = enc_registered(enc_table, name); if (index >= 0) { @@ -412,13 +436,13 @@ rb_enc_register(const char *name, rb_encoding *encoding) set_encoding_const(name, rb_enc_from_index(index)); } } - GLOBAL_ENC_TABLE_LEAVE(); return index; } int enc_registered(struct enc_table *enc_table, const char *name) { + ASSERT_vm_locking(); st_data_t idx = 0; if (!name) return -1; @@ -432,15 +456,13 @@ enc_registered(struct enc_table *enc_table, const char *name) void rb_encdb_declare(const char *name) { - GLOBAL_ENC_TABLE_ENTER(enc_table); - { + GLOBAL_ENC_TABLE_LOCKING(enc_table) { int idx = enc_registered(enc_table, name); if (idx < 0) { idx = enc_register(enc_table, name, 0); } set_encoding_const(name, rb_enc_from_index(idx)); } - GLOBAL_ENC_TABLE_LEAVE(); } static void @@ -472,13 +494,11 @@ set_base_encoding(struct enc_table *enc_table, int index, rb_encoding *base) void rb_enc_set_base(const char *name, const char *orig) { - GLOBAL_ENC_TABLE_ENTER(enc_table); - { + GLOBAL_ENC_TABLE_LOCKING(enc_table) { int idx = enc_registered(enc_table, name); int origidx = enc_registered(enc_table, orig); set_base_encoding(enc_table, idx, rb_enc_from_index(origidx)); } - GLOBAL_ENC_TABLE_LEAVE(); } /* for encdb.h @@ -529,8 +549,7 @@ rb_encdb_replicate(const char *name, const char *orig) { int r; - GLOBAL_ENC_TABLE_ENTER(enc_table); - { + GLOBAL_ENC_TABLE_LOCKING(enc_table) { int origidx = enc_registered(enc_table, orig); int idx = enc_registered(enc_table, name); @@ -539,7 +558,6 @@ rb_encdb_replicate(const char *name, const char *orig) } r = enc_replicate_with_index(enc_table, name, rb_enc_from_index(origidx), idx); } - GLOBAL_ENC_TABLE_LEAVE(); return r; } @@ -549,13 +567,11 @@ rb_define_dummy_encoding(const char *name) { int index; - GLOBAL_ENC_TABLE_ENTER(enc_table); - { + GLOBAL_ENC_TABLE_LOCKING(enc_table) { index = enc_replicate(enc_table, name, rb_ascii8bit_encoding()); rb_encoding *enc = enc_table->list[index].enc; ENC_SET_DUMMY((rb_raw_encoding *)enc); } - GLOBAL_ENC_TABLE_LEAVE(); return index; } @@ -565,15 +581,13 @@ rb_encdb_dummy(const char *name) { int index; - GLOBAL_ENC_TABLE_ENTER(enc_table); - { + GLOBAL_ENC_TABLE_LOCKING(enc_table) { index = enc_replicate_with_index(enc_table, name, rb_ascii8bit_encoding(), enc_registered(enc_table, name)); rb_encoding *enc = enc_table->list[index].enc; ENC_SET_DUMMY((rb_raw_encoding *)enc); } - GLOBAL_ENC_TABLE_LEAVE(); return index; } @@ -635,6 +649,7 @@ enc_dup_name(st_data_t name) static int enc_alias_internal(struct enc_table *enc_table, const char *alias, int idx) { + ASSERT_vm_locking(); return st_insert2(enc_table->names, (st_data_t)alias, (st_data_t)idx, enc_dup_name); } @@ -653,8 +668,7 @@ rb_enc_alias(const char *alias, const char *orig) { int idx, r; - GLOBAL_ENC_TABLE_ENTER(enc_table); - { + GLOBAL_ENC_TABLE_LOCKING(enc_table) { enc_check_addable(enc_table, alias); if ((idx = rb_enc_find_index(orig)) < 0) { r = -1; @@ -663,7 +677,6 @@ rb_enc_alias(const char *alias, const char *orig) r = enc_alias(enc_table, alias, idx); } } - GLOBAL_ENC_TABLE_LEAVE(); return r; } @@ -673,8 +686,7 @@ rb_encdb_alias(const char *alias, const char *orig) { int r; - GLOBAL_ENC_TABLE_ENTER(enc_table); - { + GLOBAL_ENC_TABLE_LOCKING(enc_table) { int idx = enc_registered(enc_table, orig); if (idx < 0) { @@ -682,7 +694,6 @@ rb_encdb_alias(const char *alias, const char *orig) } r = enc_alias(enc_table, alias, idx); } - GLOBAL_ENC_TABLE_LEAVE(); return r; } @@ -690,6 +701,7 @@ rb_encdb_alias(const char *alias, const char *orig) static void rb_enc_init(struct enc_table *enc_table) { + ASSERT_vm_locking(); enc_table_expand(enc_table, ENCODING_COUNT + 1); if (!enc_table->names) { enc_table->names = st_init_strcasetable_with_size(ENCODING_LIST_CAPA); @@ -749,8 +761,7 @@ load_encoding(const char *name) ruby_debug = debug; rb_set_errinfo(errinfo); - GLOBAL_ENC_TABLE_ENTER(enc_table); - { + GLOBAL_ENC_TABLE_LOCKING(enc_table) { if (loaded < 0 || 1 < loaded) { idx = -1; } @@ -761,51 +772,74 @@ load_encoding(const char *name) idx = -1; } } - GLOBAL_ENC_TABLE_LEAVE(); return idx; } static int -enc_autoload_body(struct enc_table *enc_table, rb_encoding *enc) +enc_autoload_body(rb_encoding *enc) { - rb_encoding *base = enc_table->list[ENC_TO_ENCINDEX(enc)].base; + rb_encoding *base; + int i = 0; + + GLOBAL_ENC_TABLE_LOCKING(enc_table) { + base = enc_table->list[ENC_TO_ENCINDEX(enc)].base; + if (base) { + do { + if (i >= enc_table->count) { + i = -1; + break; + } + } while (enc_table->list[i].enc != base && (++i, 1)); + } + } + + if (i == -1) return -1; if (base) { - int i = 0; - do { - if (i >= enc_table->count) return -1; - } while (enc_table->list[i].enc != base && (++i, 1)); if (rb_enc_autoload_p(base)) { if (rb_enc_autoload(base) < 0) return -1; } i = enc->ruby_encoding_index; - enc_register_at(enc_table, i & ENC_INDEX_MASK, rb_enc_name(enc), base); + + GLOBAL_ENC_TABLE_LOCKING(enc_table) { + enc_register_at(enc_table, i & ENC_INDEX_MASK, rb_enc_name(enc), base); + } + ((rb_raw_encoding *)enc)->ruby_encoding_index = i; i &= ENC_INDEX_MASK; return i; } - else { - return -2; - } + + return -2; } int rb_enc_autoload(rb_encoding *enc) { - int i; - GLOBAL_ENC_TABLE_EVAL(enc_table, i = enc_autoload_body(enc_table, enc)); + int i = enc_autoload_body(enc); if (i == -2) { i = load_encoding(rb_enc_name(enc)); } return i; } +bool +rb_enc_autoload_p(rb_encoding *enc) +{ + int idx = ENC_TO_ENCINDEX(enc); + RUBY_ASSERT(rb_enc_from_index(idx) == enc); + return !RUBY_ATOMIC_LOAD(global_enc_table.list[idx].loaded); +} + /* Return encoding index or UNSPECIFIED_ENCODING from encoding name */ int rb_enc_find_index(const char *name) { - int i = enc_registered(&global_enc_table, name); + int i; + GLOBAL_ENC_TABLE_LOCKING(enc_table) { + i = enc_registered(enc_table, name); + } rb_encoding *enc; if (i < 0) { @@ -949,6 +983,21 @@ enc_set_index(VALUE obj, int idx) rb_ivar_set(obj, rb_id_encoding(), INT2NUM(idx)); } +void +rb_enc_raw_set(VALUE obj, rb_encoding *enc) +{ + RUBY_ASSERT(enc_capable(obj)); + + int idx = enc ? ENC_TO_ENCINDEX(enc) : 0; + + if (idx < ENCODING_INLINE_MAX) { + ENCODING_SET_INLINED(obj, idx); + return; + } + ENCODING_SET_INLINED(obj, ENCODING_INLINE_MAX); + rb_ivar_set(obj, rb_id_encoding(), INT2NUM(idx)); +} + void rb_enc_set_index(VALUE obj, int idx) { @@ -997,13 +1046,22 @@ rb_enc_get(VALUE obj) return rb_enc_from_index(rb_enc_get_index(obj)); } +const char * +rb_enc_inspect_name(rb_encoding *enc) +{ + if (enc == global_enc_ascii) { + return "BINARY (ASCII-8BIT)"; + } + return enc->name; +} + static rb_encoding* rb_encoding_check(rb_encoding* enc, VALUE str1, VALUE str2) { if (!enc) rb_raise(rb_eEncCompatError, "incompatible character encodings: %s and %s", - rb_enc_name(rb_enc_get(str1)), - rb_enc_name(rb_enc_get(str2))); + rb_enc_inspect_name(rb_enc_get(str1)), + rb_enc_inspect_name(rb_enc_get(str2))); return enc; } @@ -1026,6 +1084,13 @@ rb_enc_check(VALUE str1, VALUE str2) static rb_encoding* enc_compatible_latter(VALUE str1, VALUE str2, int idx1, int idx2) { + if (idx1 < 0 || idx2 < 0) + return 0; + + if (idx1 == idx2) { + return rb_enc_from_index(idx1); + } + int isstr1, isstr2; rb_encoding *enc1 = rb_enc_from_index(idx1); rb_encoding *enc2 = rb_enc_from_index(idx2); @@ -1084,15 +1149,7 @@ enc_compatible_str(VALUE str1, VALUE str2) int idx1 = enc_get_index_str(str1); int idx2 = enc_get_index_str(str2); - if (idx1 < 0 || idx2 < 0) - return 0; - - if (idx1 == idx2) { - return rb_enc_from_index(idx1); - } - else { - return enc_compatible_latter(str1, str2, idx1, idx2); - } + return enc_compatible_latter(str1, str2, idx1, idx2); } rb_encoding* @@ -1101,13 +1158,6 @@ rb_enc_compatible(VALUE str1, VALUE str2) int idx1 = rb_enc_get_index(str1); int idx2 = rb_enc_get_index(str2); - if (idx1 < 0 || idx2 < 0) - return 0; - - if (idx1 == idx2) { - return rb_enc_from_index(idx1); - } - return enc_compatible_latter(str1, str2, idx1, idx2); } @@ -1245,9 +1295,10 @@ enc_inspect(VALUE self) if (!(enc = DATA_PTR(self)) || rb_enc_from_index(rb_enc_to_index(enc)) != enc) { rb_raise(rb_eTypeError, "broken Encoding"); } + return rb_enc_sprintf(rb_usascii_encoding(), "#<%"PRIsVALUE":%s%s%s>", rb_obj_class(self), - rb_enc_name(enc), + rb_enc_inspect_name(enc), (ENC_DUMMY_P(enc) ? " (dummy)" : ""), rb_enc_autoload_p(enc) ? " (autoload)" : ""); } @@ -1273,7 +1324,7 @@ enc_names_i(st_data_t name, st_data_t idx, st_data_t args) VALUE *arg = (VALUE *)args; if ((int)idx == (int)arg[0]) { - VALUE str = rb_fstring_cstr((char *)name); + VALUE str = rb_interned_str_cstr((char *)name); rb_ary_push(arg[1], str); } return ST_CONTINUE; @@ -1469,16 +1520,16 @@ rb_locale_encindex(void) if (idx < 0) idx = ENCINDEX_UTF_8; - if (enc_registered(&global_enc_table, "locale") < 0) { + GLOBAL_ENC_TABLE_LOCKING(enc_table) { + if (enc_registered(enc_table, "locale") < 0) { # if defined _WIN32 - void Init_w32_codepage(void); - Init_w32_codepage(); + void Init_w32_codepage(void); + Init_w32_codepage(); # endif - GLOBAL_ENC_TABLE_ENTER(enc_table); - { - enc_alias_internal(enc_table, "locale", idx); + GLOBAL_ENC_TABLE_LOCKING(enc_table) { + enc_alias_internal(enc_table, "locale", idx); + } } - GLOBAL_ENC_TABLE_LEAVE(); } return idx; @@ -1493,7 +1544,10 @@ rb_locale_encoding(void) int rb_filesystem_encindex(void) { - int idx = enc_registered(&global_enc_table, "filesystem"); + int idx; + GLOBAL_ENC_TABLE_LOCKING(enc_table) { + idx = enc_registered(enc_table, "filesystem"); + } if (idx < 0) idx = ENCINDEX_ASCII_8BIT; return idx; } @@ -1520,12 +1574,18 @@ enc_set_default_encoding(struct default_encoding *def, VALUE encoding, const cha /* Already set */ overridden = TRUE; - GLOBAL_ENC_TABLE_ENTER(enc_table); - { + GLOBAL_ENC_TABLE_LOCKING(enc_table) { if (NIL_P(encoding)) { def->index = -1; def->enc = 0; - st_insert(enc_table->names, (st_data_t)strdup(name), + char *name_dup = strdup(name); + + st_data_t existing_name = (st_data_t)name_dup; + if (st_delete(enc_table->names, &existing_name, NULL)) { + xfree((void *)existing_name); + } + + st_insert(enc_table->names, (st_data_t)name_dup, (st_data_t)UNSPECIFIED_ENCODING); } else { @@ -1538,7 +1598,6 @@ enc_set_default_encoding(struct default_encoding *def, VALUE encoding, const cha enc_alias_internal(enc_table, "filesystem", Init_enc_set_filesystem_encoding()); } } - GLOBAL_ENC_TABLE_LEAVE(); return overridden; } @@ -1763,7 +1822,7 @@ static int rb_enc_name_list_i(st_data_t name, st_data_t idx, st_data_t arg) { VALUE ary = (VALUE)arg; - VALUE str = rb_fstring_cstr((char *)name); + VALUE str = rb_interned_str_cstr((char *)name); rb_ary_push(ary, str); return ST_CONTINUE; } @@ -1808,7 +1867,7 @@ rb_enc_aliases_enc_i(st_data_t name, st_data_t orig, st_data_t arg) str = rb_fstring_cstr(rb_enc_name(enc)); rb_ary_store(ary, idx, str); } - key = rb_fstring_cstr((char *)name); + key = rb_interned_str_cstr((char *)name); rb_hash_aset(aliases, key, str); return ST_CONTINUE; } @@ -1902,7 +1961,7 @@ Init_Encoding(void) list = rb_encoding_list = rb_ary_new2(ENCODING_LIST_CAPA); RBASIC_CLEAR_CLASS(list); - rb_gc_register_mark_object(list); + rb_vm_register_global_object(list); for (i = 0; i < enc_table->count; ++i) { rb_ary_push(list, enc_new(enc_table->list[i].enc)); @@ -1911,6 +1970,17 @@ Init_Encoding(void) rb_marshal_define_compat(rb_cEncoding, Qnil, 0, enc_m_loader); } +void +Init_unicode_version(void) +{ + extern const char onigenc_unicode_version_string[]; + + VALUE str = rb_usascii_str_new_static(onigenc_unicode_version_string, + strlen(onigenc_unicode_version_string)); + OBJ_FREEZE(str); + rb_define_const(rb_cEncoding, "UNICODE_VERSION", str); +} + void Init_encodings(void) { diff --git a/enum.c b/enum.c index 355170cc3ecb68..cbf74df484bbcd 100644 --- a/enum.c +++ b/enum.c @@ -322,16 +322,33 @@ enum_count(int argc, VALUE *argv, VALUE obj) return imemo_count_value(memo); } +NORETURN(static void found(VALUE i, VALUE memop)); +static void +found(VALUE i, VALUE memop) +{ + struct MEMO *memo = MEMO_CAST(memop); + MEMO_V1_SET(memo, i); + memo->u3.cnt = 1; + rb_iter_break(); +} + +static VALUE +find_i_fast(RB_BLOCK_CALL_FUNC_ARGLIST(i, memop)) +{ + if (RTEST(rb_yield_values2(argc, argv))) { + ENUM_WANT_SVALUE(); + found(i, memop); + } + return Qnil; +} + static VALUE find_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memop)) { ENUM_WANT_SVALUE(); if (RTEST(enum_yield(argc, i))) { - struct MEMO *memo = MEMO_CAST(memop); - MEMO_V1_SET(memo, i); - memo->u3.cnt = 1; - rb_iter_break(); + found(i, memop); } return Qnil; } @@ -366,7 +383,10 @@ enum_find(int argc, VALUE *argv, VALUE obj) if_none = rb_check_arity(argc, 0, 1) ? argv[0] : Qnil; RETURN_ENUMERATOR(obj, argc, argv); memo = MEMO_NEW(Qundef, 0, 0); - rb_block_call(obj, id_each, 0, 0, find_i, (VALUE)memo); + if (rb_block_pair_yield_optimizable()) + rb_block_call2(obj, id_each, 0, 0, find_i_fast, (VALUE)memo, RB_BLOCK_NO_USE_PACKED_ARGS); + else + rb_block_call2(obj, id_each, 0, 0, find_i, (VALUE)memo, RB_BLOCK_NO_USE_PACKED_ARGS); if (memo->u3.cnt) { return memo->v1; } @@ -870,134 +890,151 @@ ary_inject_op(VALUE ary, VALUE init, VALUE op) /* * call-seq: - * inject(symbol) -> object - * inject(initial_operand, symbol) -> object - * inject {|memo, operand| ... } -> object - * inject(initial_operand) {|memo, operand| ... } -> object - * - * Returns an object formed from operands via either: + * inject(symbol) -> object + * inject(initial_value, symbol) -> object + * inject {|memo, value| ... } -> object + * inject(initial_value) {|memo, value| ... } -> object + * + * Returns the result of applying a reducer to an initial value and + * the first element of the Enumerable. It then takes the result and applies the + * function to it and the second element of the collection, and so on. The + * return value is the result returned by the final call to the function. * - * - A method named by +symbol+. - * - A block to which each operand is passed. - * - * With method-name argument +symbol+, - * combines operands using the method: - * - * # Sum, without initial_operand. - * (1..4).inject(:+) # => 10 - * # Sum, with initial_operand. - * (1..4).inject(10, :+) # => 20 + * You can think of * - * With a block, passes each operand to the block: - * - * # Sum of squares, without initial_operand. - * (1..4).inject {|sum, n| sum + n*n } # => 30 - * # Sum of squares, with initial_operand. - * (1..4).inject(2) {|sum, n| sum + n*n } # => 32 + * [ a, b, c, d ].inject(i) { |r, v| fn(r, v) } * - * Operands + * as being * - * If argument +initial_operand+ is not given, - * the operands for +inject+ are simply the elements of +self+. - * Example calls and their operands: + * fn(fn(fn(fn(i, a), b), c), d) * - * - (1..4).inject(:+):: [1, 2, 3, 4]. - * - (1...4).inject(:+):: [1, 2, 3]. - * - ('a'..'d').inject(:+):: ['a', 'b', 'c', 'd']. - * - ('a'...'d').inject(:+):: ['a', 'b', 'c']. + * In a way the +inject+ function _injects_ the function + * between the elements of the enumerable. * - * Examples with first operand (which is self.first) of various types: + * +inject+ is aliased as +reduce+. You use it when you want to + * _reduce_ a collection to a single value. * - * # Integer. - * (1..4).inject(:+) # => 10 - * # Float. - * [1.0, 2, 3, 4].inject(:+) # => 10.0 - * # Character. - * ('a'..'d').inject(:+) # => "abcd" - * # Complex. - * [Complex(1, 2), 3, 4].inject(:+) # => (8+2i) + * The Calling Sequences * - * If argument +initial_operand+ is given, - * the operands for +inject+ are that value plus the elements of +self+. - * Example calls their operands: + * Let's start with the most verbose: + * + * enum.inject(initial_value) do |result, next_value| + * # do something with +result+ and +next_value+ + * # the value returned by the block becomes the + * # value passed in to the next iteration + * # as +result+ + * end * - * - (1..4).inject(10, :+):: [10, 1, 2, 3, 4]. - * - (1...4).inject(10, :+):: [10, 1, 2, 3]. - * - ('a'..'d').inject('e', :+):: ['e', 'a', 'b', 'c', 'd']. - * - ('a'...'d').inject('e', :+):: ['e', 'a', 'b', 'c']. + * For example: * - * Examples with +initial_operand+ of various types: + * product = [ 2, 3, 4 ].inject(1) do |result, next_value| + * result * next_value + * end + * product #=> 24 * - * # Integer. - * (1..4).inject(2, :+) # => 12 - * # Float. - * (1..4).inject(2.0, :+) # => 12.0 - * # String. - * ('a'..'d').inject('foo', :+) # => "fooabcd" - * # Array. - * %w[a b c].inject(['x'], :push) # => ["x", "a", "b", "c"] - * # Complex. - * (1..4).inject(Complex(2, 2), :+) # => (12+2i) + * When this runs, the block is first called with +1+ (the initial value) and + * +2+ (the first element of the array). The block returns 1*2, so on + * the next iteration the block is called with +2+ (the previous result) and + * +3+. The block returns +6+, and is called one last time with +6+ and +4+. + * The result of the block, +24+ becomes the value returned by +inject+. This + * code returns the product of the elements in the enumerable. * - * Combination by Given \Method + * First Shortcut: Default Initial value * - * If the method-name argument +symbol+ is given, - * the operands are combined by that method: + * In the case of the previous example, the initial value, +1+, wasn't really + * necessary: the calculation of the product of a list of numbers is self-contained. * - * - The first and second operands are combined. - * - That result is combined with the third operand. - * - That result is combined with the fourth operand. - * - And so on. + * In these circumstances, you can omit the +initial_value+ parameter. +inject+ + * will then initially call the block with the first element of the collection + * as the +result+ parameter and the second element as the +next_value+. * - * The return value from +inject+ is the result of the last combination. + * [ 2, 3, 4 ].inject do |result, next_value| + * result * next_value + * end * - * This call to +inject+ computes the sum of the operands: + * This shortcut is convenient, but can only be used when the block produces a result + * which can be passed back to it as a first parameter. * - * (1..4).inject(:+) # => 10 + * Here's an example where that's not the case: it returns a hash where the keys are words + * and the values are the number of occurrences of that word in the enumerable. * - * Examples with various methods: + * freqs = File.read("README.md") + * .scan(/\w{2,}/) + * .reduce(Hash.new(0)) do |counts, word| + * counts[word] += 1 + * counts + * end + * freqs #=> {"Actions"=>4, + * "Status"=>5, + * "MinGW"=>3, + * "https"=>27, + * "github"=>10, + * "com"=>15, ... * - * # Integer addition. - * (1..4).inject(:+) # => 10 - * # Integer multiplication. - * (1..4).inject(:*) # => 24 - * # Character range concatenation. - * ('a'..'d').inject('', :+) # => "abcd" - * # String array concatenation. - * %w[foo bar baz].inject('', :+) # => "foobarbaz" - * # Hash update. - * h = [{foo: 0, bar: 1}, {baz: 2}, {bat: 3}].inject(:update) - * h # => {:foo=>0, :bar=>1, :baz=>2, :bat=>3} - * # Hash conversion to nested arrays. - * h = {foo: 0, bar: 1}.inject([], :push) - * h # => [[:foo, 0], [:bar, 1]] + * Note that the last line of the block is just the word +counts+. This ensures the + * return value of the block is the result that's being calculated. * - * Combination by Given Block + * Second Shortcut: a Reducer function * - * If a block is given, the operands are passed to the block: + * A reducer function is a function that takes a partial result and the next value, + * returning the next partial result. The block that is given to +inject+ is a reducer. * - * - The first call passes the first and second operands. - * - The second call passes the result of the first call, - * along with the third operand. - * - The third call passes the result of the second call, - * along with the fourth operand. - * - And so on. + * You can also write a reducer as a function and pass the name of that function + * (as a symbol) to +inject+. However, for this to work, the function * - * The return value from +inject+ is the return value from the last block call. - * - * This call to +inject+ gives a block - * that writes the memo and element, and also sums the elements: + * 1. Must be defined on the type of the result value + * 2. Must accept a single parameter, the next value in the collection, and + * 3. Must return an updated result which will also implement the function. * - * (1..4).inject do |memo, element| - * p "Memo: #{memo}; element: #{element}" - * memo + element - * end # => 10 + * Here's an example that adds elements to a string. The two calls invoke the functions + * String#concat and String#+ on the result so far, passing it the next value. * - * Output: + * s = [ "cat", " ", "dog" ].inject("", :concat) + * s #=> "cat dog" + * s = [ "cat", " ", "dog" ].inject("The result is:", :+) + * s #=> "The result is: cat dog" + * + * Here's a more complex example when the result object maintains + * state of a different type to the enumerable elements. + * + * class Turtle + * + * def initialize + * @x = @y = 0 + * end + * + * def move(dir) + * case dir + * when "n" then @y += 1 + * when "s" then @y -= 1 + * when "e" then @x += 1 + * when "w" then @x -= 1 + * end + * self + * end + * end + * + * position = "nnneesw".chars.reduce(Turtle.new, :move) + * position #=>> # * - * "Memo: 1; element: 2" - * "Memo: 3; element: 3" - * "Memo: 6; element: 4" + * Third Shortcut: Reducer With no Initial Value + * + * If your reducer returns a value that it can accept as a parameter, then you + * don't have to pass in an initial value. Here :* is the name of the + * _times_ function: + * + * product = [ 2, 3, 4 ].inject(:*) + * product # => 24 + * + * String concatenation again: + * + * s = [ "cat", " ", "dog" ].inject(:+) + * s #=> "cat dog" + * + * And an example that converts a hash to an array of two-element subarrays. + * + * nested = {foo: 0, bar: 1}.inject([], :push) + * nested # => [[:foo, 0], [:bar, 1]] * * */ @@ -1178,14 +1215,15 @@ tally_up(st_data_t *group, st_data_t *value, st_data_t arg, int existing) RB_OBJ_WRITTEN(hash, Qundef, tally); } *value = (st_data_t)tally; - if (!SPECIAL_CONST_P(*group)) RB_OBJ_WRITTEN(hash, Qundef, *group); return ST_CONTINUE; } static VALUE rb_enum_tally_up(VALUE hash, VALUE group) { - rb_hash_stlike_update(hash, group, tally_up, (st_data_t)hash); + if (!rb_hash_stlike_update(hash, group, tally_up, (st_data_t)hash)) { + RB_OBJ_WRITTEN(hash, Qundef, group); + } return hash; } @@ -1199,29 +1237,47 @@ tally_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, hash)) /* * call-seq: - * tally -> new_hash - * tally(hash) -> hash + * tally(hash = {}) -> hash * - * Returns a hash containing the counts of equal elements: + * When argument +hash+ is not given, + * returns a new hash whose keys are the distinct elements in +self+; + * each integer value is the count of occurrences of each element: * - * - Each key is an element of +self+. - * - Each value is the number elements equal to that key. + * %w[a b c b c a c b].tally # => {"a"=>2, "b"=>3, "c"=>3} * - * With no argument: + * When argument +hash+ is given, + * returns +hash+, possibly augmented; for each element +ele+ in +self+: * - * %w[a b c b c a c b].tally # => {"a"=>2, "b"=>3, "c"=>3} + * - Adds it as a key with a zero value if that key does not already exist: + * + * hash[ele] = 0 unless hash.include?(ele) + * + * - Increments the value of key +ele+: + * + * hash[ele] += 1 + * + * This is useful for accumulating tallies across multiple enumerables: + * + * h = {} # => {} + * %w[a c d b c a].tally(h) # => {"a"=>2, "c"=>2, "d"=>1, "b"=>1} + * %w[b a z].tally(h) # => {"a"=>3, "c"=>2, "d"=>1, "b"=>2, "z"=>1} + * %w[b a m].tally(h) # => {"a"=>4, "c"=>2, "d"=>1, "b"=>3, "z"=>1, "m"=>1} + * + * The key to be added or found for an element depends on the class of +self+; + * see {Enumerable in Ruby Classes}[rdoc-ref:Enumerable@Enumerable+in+Ruby+Classes]. * - * With a hash argument, that hash is used for the tally (instead of a new hash), - * and is returned; - * this may be useful for accumulating tallies across multiple enumerables: + * Examples: + * + * - Array (and certain array-like classes): + * the key is the element (as above). + * - Hash (and certain hash-like classes): + * the key is the 2-element array formed from the key-value pair: * - * hash = {} - * hash = %w[a c d b c a].tally(hash) - * hash # => {"a"=>2, "c"=>2, "d"=>1, "b"=>1} - * hash = %w[b a z].tally(hash) - * hash # => {"a"=>3, "c"=>2, "d"=>1, "b"=>2, "z"=>1} - * hash = %w[b a m].tally(hash) - * hash # => {"a"=>4, "c"=>2, "d"=>1, "b"=>3, "z"=>1, "m"=> 1} + * h = {} # => {} + * {foo: 'a', bar: 'b'}.tally(h) # => {[:foo, "a"]=>1, [:bar, "b"]=>1} + * {foo: 'c', bar: 'd'}.tally(h) # => {[:foo, "a"]=>1, [:bar, "b"]=>1, [:foo, "c"]=>1, [:bar, "d"]=>1} + * {foo: 'a', bar: 'b'}.tally(h) # => {[:foo, "a"]=>2, [:bar, "b"]=>2, [:foo, "c"]=>1, [:bar, "d"]=>1} + * {foo: 'c', bar: 'd'}.tally(h) # => {[:foo, "a"]=>2, [:bar, "b"]=>2, [:foo, "c"]=>2, [:bar, "d"]=>2} * */ @@ -1304,7 +1360,7 @@ enum_first(int argc, VALUE *argv, VALUE obj) * The ordering of equal elements is indeterminate and may be unstable. * * With no block given, the sort compares - * using the elements' own method <=>: + * using the elements' own method #<=>: * * %w[b c a d].sort # => ["a", "b", "c", "d"] * {foo: 0, bar: 1, baz: 2}.sort # => [[:bar, 1], [:baz, 2], [:foo, 0]] @@ -1707,6 +1763,9 @@ enum_sort_by(VALUE obj) #define ENUMFUNC(name) argc ? name##_eqq : rb_block_given_p() ? name##_iter_i : name##_i +#define ENUM_BLOCK_CALL(name) \ + rb_block_call2(obj, id_each, 0, 0, ENUMFUNC(name), (VALUE)memo, rb_block_given_p() && rb_block_pair_yield_optimizable() ? RB_BLOCK_NO_USE_PACKED_ARGS : 0); + #define MEMO_ENUM_NEW(v1) (rb_check_arity(argc, 0, 1), MEMO_NEW((v1), (argc ? *argv : 0), 0)) #define DEFINE_ENUMFUNCS(name) \ @@ -1800,7 +1859,7 @@ enum_all(int argc, VALUE *argv, VALUE obj) { struct MEMO *memo = MEMO_ENUM_NEW(Qtrue); WARN_UNUSED_BLOCK(argc); - rb_block_call(obj, id_each, 0, 0, ENUMFUNC(all), (VALUE)memo); + ENUM_BLOCK_CALL(all); return memo->v1; } @@ -1862,7 +1921,7 @@ enum_any(int argc, VALUE *argv, VALUE obj) { struct MEMO *memo = MEMO_ENUM_NEW(Qfalse); WARN_UNUSED_BLOCK(argc); - rb_block_call(obj, id_each, 0, 0, ENUMFUNC(any), (VALUE)memo); + ENUM_BLOCK_CALL(any); return memo->v1; } @@ -2151,7 +2210,7 @@ enum_one(int argc, VALUE *argv, VALUE obj) VALUE result; WARN_UNUSED_BLOCK(argc); - rb_block_call(obj, id_each, 0, 0, ENUMFUNC(one), (VALUE)memo); + ENUM_BLOCK_CALL(one); result = memo->v1; if (UNDEF_P(result)) return Qfalse; return result; @@ -2212,7 +2271,7 @@ enum_none(int argc, VALUE *argv, VALUE obj) struct MEMO *memo = MEMO_ENUM_NEW(Qtrue); WARN_UNUSED_BLOCK(argc); - rb_block_call(obj, id_each, 0, 0, ENUMFUNC(none), (VALUE)memo); + ENUM_BLOCK_CALL(none); return memo->v1; } @@ -2270,7 +2329,7 @@ min_ii(RB_BLOCK_CALL_FUNC_ARGLIST(i, args)) * The ordering of equal elements is indeterminate and may be unstable. * * With no argument and no block, returns the minimum element, - * using the elements' own method <=> for comparison: + * using the elements' own method #<=> for comparison: * * (1..4).min # => 1 * (-4..-1).min # => -4 @@ -2392,7 +2451,7 @@ max_ii(RB_BLOCK_CALL_FUNC_ARGLIST(i, args)) * The ordering of equal elements is indeterminate and may be unstable. * * With no argument and no block, returns the maximum element, - * using the elements' own method <=> for comparison: + * using the elements' own method #<=> for comparison: * * (1..4).max # => 4 * (-4..-1).max # => -1 @@ -2581,7 +2640,7 @@ minmax_ii(RB_BLOCK_CALL_FUNC_ARGLIST(i, _memo)) * The ordering of equal elements is indeterminate and may be unstable. * * With no argument and no block, returns the minimum and maximum elements, - * using the elements' own method <=> for comparison: + * using the elements' own method #<=> for comparison: * * (1..4).minmax # => [1, 4] * (-4..-1).minmax # => [-4, -1] @@ -2927,13 +2986,12 @@ enum_member(VALUE obj, VALUE val) } static VALUE -each_with_index_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memo)) +each_with_index_i(RB_BLOCK_CALL_FUNC_ARGLIST(_, index)) { - struct MEMO *m = MEMO_CAST(memo); - VALUE n = imemo_count_value(m); + struct vm_ifunc *ifunc = rb_current_ifunc(); + ifunc->data = (const void *)rb_int_succ(index); - imemo_count_up(m); - return rb_yield_values(2, rb_enum_values_pack(argc, argv), n); + return rb_yield_values(2, rb_enum_values_pack(argc, argv), index); } /* @@ -2941,7 +2999,8 @@ each_with_index_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memo)) * each_with_index(*args) {|element, i| ..... } -> self * each_with_index(*args) -> enumerator * - * With a block given, calls the block with each element and its index; + * Invoke self.each with *args. + * With a block given, the block receives each element and its index; * returns +self+: * * h = {} @@ -2966,12 +3025,9 @@ each_with_index_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, memo)) static VALUE enum_each_with_index(int argc, VALUE *argv, VALUE obj) { - struct MEMO *memo; - RETURN_SIZED_ENUMERATOR(obj, argc, argv, enum_size); - memo = MEMO_NEW(0, 0, 0); - rb_block_call(obj, id_each, argc, argv, each_with_index_i, (VALUE)memo); + rb_block_call(obj, id_each, argc, argv, each_with_index_i, INT2FIX(0)); return obj; } @@ -3649,6 +3705,17 @@ drop_while_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, args)) * * With no block given, returns an Enumerator. * + * e = (1..4).drop_while + * p e #=> # + * i = e.next; p i; e.feed(i < 3) #=> 1 + * i = e.next; p i; e.feed(i < 3) #=> 2 + * i = e.next; p i; e.feed(i < 3) #=> 3 + * begin + * e.next + * rescue StopIteration + * p $!.result #=> [3, 4] + * end + * */ static VALUE @@ -3858,7 +3925,7 @@ chunk_i(RB_BLOCK_CALL_FUNC_ARGLIST(yielder, enumerator)) * e.next # => [2, [6, 7, 8]] * e.next # => [3, [9, 10]] * - * \Method +chunk+ is especially useful for an enumerable that is already sorted. + * Method +chunk+ is especially useful for an enumerable that is already sorted. * This example counts words for each initial letter in a large array of words: * * # Get sorted words from a web page. @@ -4538,7 +4605,7 @@ struct enum_sum_memo { static void sum_iter_normalize_memo(struct enum_sum_memo *memo) { - assert(FIXABLE(memo->n)); + RUBY_ASSERT(FIXABLE(memo->n)); memo->v = rb_fix_plus(LONG2FIX(memo->n), memo->v); memo->n = 0; @@ -4640,7 +4707,7 @@ sum_iter_Kahan_Babuska(VALUE i, struct enum_sum_memo *memo) static void sum_iter(VALUE i, struct enum_sum_memo *memo) { - assert(memo != NULL); + RUBY_ASSERT(memo != NULL); if (memo->block_given) { i = rb_yield(i); } @@ -4650,7 +4717,7 @@ sum_iter(VALUE i, struct enum_sum_memo *memo) } else switch (TYPE(memo->v)) { default: sum_iter_some_value(i, memo); return; - case T_FLOAT: sum_iter_Kahan_Babuska(i, memo); return; + case T_FLOAT: case T_FIXNUM: case T_BIGNUM: case T_RATIONAL: @@ -4691,8 +4758,8 @@ hash_sum_i(VALUE key, VALUE value, VALUE arg) static void hash_sum(VALUE hash, struct enum_sum_memo *memo) { - assert(RB_TYPE_P(hash, T_HASH)); - assert(memo != NULL); + RUBY_ASSERT(RB_TYPE_P(hash, T_HASH)); + RUBY_ASSERT(memo != NULL); rb_hash_foreach(hash, hash_sum_i, (VALUE)memo); } @@ -4885,7 +4952,7 @@ enum_compact(VALUE obj) /* * == What's Here * - * \Module \Enumerable provides methods that are useful to a collection class for: + * Module \Enumerable provides methods that are useful to a collection class for: * * - {Querying}[rdoc-ref:Enumerable@Methods+for+Querying] * - {Fetching}[rdoc-ref:Enumerable@Methods+for+Fetching] @@ -4898,7 +4965,7 @@ enum_compact(VALUE obj) * * These methods return information about the \Enumerable other than the elements themselves: * - * - #include?, #member?: Returns +true+ if self == object, +false+ otherwise. + * - #member? (aliased as #include?): Returns +true+ if self == object, +false+ otherwise. * - #all?: Returns +true+ if all elements meet a specified criterion; +false+ otherwise. * - #any?: Returns +true+ if any element meets a specified criterion; +false+ otherwise. * - #none?: Returns +true+ if no element meets a specified criterion; +false+ otherwise. @@ -4913,7 +4980,7 @@ enum_compact(VALUE obj) * * Leading, trailing, or all elements: * - * - #entries, #to_a: Returns all elements. + * - #to_a (aliased as #entries): Returns all elements. * - #first: Returns the first element or leading elements. * - #take: Returns a specified number of leading elements. * - #drop: Returns a specified number of trailing elements. @@ -4923,9 +4990,9 @@ enum_compact(VALUE obj) * Minimum and maximum value elements: * * - #min: Returns the elements whose values are smallest among the elements, - * as determined by <=> or a given block. + * as determined by #<=> or a given block. * - #max: Returns the elements whose values are largest among the elements, - * as determined by <=> or a given block. + * as determined by #<=> or a given block. * - #minmax: Returns a 2-element Array containing the smallest and largest elements. * - #min_by: Returns the smallest element, as determined by the given block. * - #max_by: Returns the largest element, as determined by the given block. @@ -4936,11 +5003,11 @@ enum_compact(VALUE obj) * - #group_by: Returns a Hash that partitions the elements into groups. * - #partition: Returns elements partitioned into two new Arrays, as determined by the given block. * - #slice_after: Returns a new Enumerator whose entries are a partition of +self+, - based either on a given +object+ or a given block. + * based either on a given +object+ or a given block. * - #slice_before: Returns a new Enumerator whose entries are a partition of +self+, - based either on a given +object+ or a given block. + * based either on a given +object+ or a given block. * - #slice_when: Returns a new Enumerator whose entries are a partition of +self+ - based on the given block. + * based on the given block. * - #chunk: Returns elements organized into chunks as specified by the given block. * - #chunk_while: Returns elements organized into chunks as specified by the given block. * @@ -4948,8 +5015,8 @@ enum_compact(VALUE obj) * * These methods return elements that meet a specified criterion: * - * - #find, #detect: Returns an element selected by the block. - * - #find_all, #filter, #select: Returns elements selected by the block. + * - #find (aliased as #detect): Returns an element selected by the block. + * - #find_all (aliased as #filter, #select): Returns elements selected by the block. * - #find_index: Returns the index of an element selected by a given object or block. * - #reject: Returns elements not rejected by the block. * - #uniq: Returns elements that are not duplicates. @@ -4958,7 +5025,7 @@ enum_compact(VALUE obj) * * These methods return elements in sorted order: * - * - #sort: Returns the elements, sorted by <=> or the given block. + * - #sort: Returns the elements, sorted by #<=> or the given block. * - #sort_by: Returns the elements, sorted by the given block. * * === Methods for Iterating @@ -4974,14 +5041,14 @@ enum_compact(VALUE obj) * * === Other Methods * - * - #map, #collect: Returns objects returned by the block. + * - #collect (aliased as #map): Returns objects returned by the block. * - #filter_map: Returns truthy objects returned by the block. - * - #flat_map, #collect_concat: Returns flattened objects returned by the block. + * - #flat_map (aliased as #collect_concat): Returns flattened objects returned by the block. * - #grep: Returns elements selected by a given object * or objects returned by a given block. - * - #grep_v: Returns elements selected by a given object + * - #grep_v: Returns elements not selected by a given object * or objects returned by a given block. - * - #reduce, #inject: Returns the object formed by combining all elements. + * - #inject (aliased as #reduce): Returns the object formed by combining all elements. * - #sum: Returns the sum of the elements, using method +. * - #zip: Combines each element with elements from other enumerables; * returns the n-tuples or calls the block with each. @@ -5053,6 +5120,82 @@ enum_compact(VALUE obj) * For some methods, though, the usage would not make sense, * and so it is not shown. Example: #tally would find exactly one of each Hash entry. * + * == Extended Methods + * + * A Enumerable class may define extended methods. This section describes the standard + * behavior of extension methods for reference purposes. + * + * === #size + * + * \Enumerator has a #size method. + * It uses the size function argument passed to +Enumerator.new+. + * + * e = Enumerator.new(-> { 3 }) {|y| p y; y.yield :a; y.yield :b; y.yield :c; :z } + * p e.size #=> 3 + * p e.next #=> :a + * p e.next #=> :b + * p e.next #=> :c + * begin + * e.next + * rescue StopIteration + * p $!.result #=> :z + * end + * + * The result of the size function should represent the number of iterations + * (i.e., the number of times Enumerator::Yielder#yield is called). + * In the above example, the block calls #yield three times, and + * the size function, +-> { 3 }+, returns 3 accordingly. + * The result of the size function can be an integer, +Float::INFINITY+, + * or +nil+. + * An integer means the exact number of times #yield will be called, + * as shown above. + * +Float::INFINITY+ indicates an infinite number of #yield calls. + * +nil+ means the number of #yield calls is difficult or impossible to + * determine. + * + * Many iteration methods return an \Enumerator object with an + * appropriate size function if no block is given. + * + * Examples: + * + * ["a", "b", "c"].each.size #=> 3 + * {a: "x", b: "y", c: "z"}.each.size #=> 3 + * (0..20).to_a.permutation.size #=> 51090942171709440000 + * loop.size #=> Float::INFINITY + * (1..100).drop_while.size #=> nil # size depends on the block's behavior + * STDIN.each.size #=> nil # cannot be computed without consuming input + * File.open("/etc/resolv.conf").each.size #=> nil # cannot be computed without reading the file + * + * The behavior of #size for Range-based enumerators depends on the #begin element: + * + * - If the #begin element is an Integer, the #size method returns an Integer or +Float::INFINITY+. + * - If the #begin element is an object with a #succ method (other than Integer), #size returns +nil+. + * (Computing the size would require repeatedly calling #succ, which may be too slow.) + * - If the #begin element does not have a #succ method, #size raises a TypeError. + * + * Examples: + * + * (10..42).each.size #=> 33 + * (10..42.9).each.size #=> 33 (the #end element may be a non-integer numeric) + * (10..).each.size #=> Float::INFINITY + * ("a".."z").each.size #=> nil + * ("a"..).each.size #=> nil + * (1.0..9.0).each.size # raises TypeError (Float does not have #succ) + * (..10).each.size # raises TypeError (beginless range has nil as its #begin) + * + * The \Enumerable module itself does not define a #size method. + * A class that includes \Enumerable may define its own #size method. + * It is recommended that such a #size method be consistent with + * Enumerator#size. + * + * Array and Hash implement #size and return values consistent with + * Enumerator#size. + * IO and Dir do not define #size, which is also consistent because the + * corresponding enumerator's size function returns +nil+. + * + * However, it is not strictly required for a class's #size method to match Enumerator#size. + * For example, File#size returns the number of bytes in the file, not the number of lines. + * */ void diff --git a/enumerator.c b/enumerator.c index 252333f303ea22..b91b2eb940d445 100644 --- a/enumerator.c +++ b/enumerator.c @@ -85,12 +85,16 @@ * puts e.next # => 3 * puts e.next # raises StopIteration * - * +next+, +next_values+, +peek+ and +peek_values+ are the only methods - * which use external iteration (and Array#zip(Enumerable-not-Array) which uses +next+). + * +next+, +next_values+, +peek+, and +peek_values+ are the only methods + * which use external iteration (and Array#zip(Enumerable-not-Array) which uses +next+ internally). * * These methods do not affect other internal enumeration methods, * unless the underlying iteration method itself has side-effect, e.g. IO#each_line. * + * FrozenError will be raised if these methods are called against a frozen enumerator. + * Since +rewind+ and +feed+ also change state for external iteration, + * these methods may raise FrozenError too. + * * External iteration differs *significantly* from internal iteration * due to using a Fiber: * - The Fiber adds some overhead compared to internal enumeration. @@ -158,10 +162,9 @@ */ VALUE rb_cEnumerator; static VALUE rb_cLazy; -static ID id_rewind, id_new, id_to_enum, id_each_entry; +static ID id_rewind, id_to_enum, id_each_entry; static ID id_next, id_result, id_receiver, id_arguments, id_memo, id_method, id_force; -static ID id_begin, id_end, id_step, id_exclude_end; -static VALUE sym_each, sym_cycle, sym_yield; +static VALUE sym_each, sym_yield; static VALUE lazy_use_super_method; @@ -191,17 +194,18 @@ struct enumerator { int kw_splat; }; -RUBY_REFERENCES_START(enumerator_refs) - REF_EDGE(enumerator, obj), - REF_EDGE(enumerator, args), - REF_EDGE(enumerator, fib), - REF_EDGE(enumerator, dst), - REF_EDGE(enumerator, lookahead), - REF_EDGE(enumerator, feedvalue), - REF_EDGE(enumerator, stop_exc), - REF_EDGE(enumerator, size), - REF_EDGE(enumerator, procs), -RUBY_REFERENCES_END +RUBY_REFERENCES(enumerator_refs) = { + RUBY_REF_EDGE(struct enumerator, obj), + RUBY_REF_EDGE(struct enumerator, args), + RUBY_REF_EDGE(struct enumerator, fib), + RUBY_REF_EDGE(struct enumerator, dst), + RUBY_REF_EDGE(struct enumerator, lookahead), + RUBY_REF_EDGE(struct enumerator, feedvalue), + RUBY_REF_EDGE(struct enumerator, stop_exc), + RUBY_REF_EDGE(struct enumerator, size), + RUBY_REF_EDGE(struct enumerator, procs), + RUBY_REF_END +}; static VALUE rb_cGenerator, rb_cYielder, rb_cEnumProducer; @@ -252,23 +256,15 @@ struct enum_product { VALUE rb_cArithSeq; -#define enumerator_free RUBY_TYPED_DEFAULT_FREE - -static size_t -enumerator_memsize(const void *p) -{ - return sizeof(struct enumerator); -} - static const rb_data_type_t enumerator_data_type = { "enumerator", { - REFS_LIST_PTR(enumerator_refs), - enumerator_free, - enumerator_memsize, + RUBY_REFS_LIST_PTR(enumerator_refs), + RUBY_TYPED_DEFAULT_FREE, + NULL, // Nothing allocated externally, so don't need a memsize function NULL, }, - 0, NULL, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_DECL_MARKING + 0, NULL, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_DECL_MARKING | RUBY_TYPED_EMBEDDABLE }; static struct enumerator * @@ -299,22 +295,15 @@ proc_entry_compact(void *p) ptr->memo = rb_gc_location(ptr->memo); } -#define proc_entry_free RUBY_TYPED_DEFAULT_FREE - -static size_t -proc_entry_memsize(const void *p) -{ - return p ? sizeof(struct proc_entry) : 0; -} - static const rb_data_type_t proc_entry_data_type = { "proc_entry", { proc_entry_mark, - proc_entry_free, - proc_entry_memsize, + RUBY_TYPED_DEFAULT_FREE, + NULL, // Nothing allocated externally, so don't need a memsize function proc_entry_compact, }, + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_EMBEDDABLE }; static struct proc_entry * @@ -399,7 +388,7 @@ obj_to_enum(int argc, VALUE *argv, VALUE obj) } enumerator = rb_enumeratorize_with_size(obj, meth, argc, argv, 0); if (rb_block_given_p()) { - enumerator_ptr(enumerator)->size = rb_block_proc(); + RB_OBJ_WRITE(enumerator, &enumerator_ptr(enumerator)->size, rb_block_proc()); } return enumerator; } @@ -428,15 +417,15 @@ enumerator_init(VALUE enum_obj, VALUE obj, VALUE meth, int argc, const VALUE *ar rb_raise(rb_eArgError, "unallocated enumerator"); } - ptr->obj = obj; + RB_OBJ_WRITE(enum_obj, &ptr->obj, obj); ptr->meth = rb_to_id(meth); - if (argc) ptr->args = rb_ary_new4(argc, argv); + if (argc) RB_OBJ_WRITE(enum_obj, &ptr->args, rb_ary_new4(argc, argv)); ptr->fib = 0; ptr->dst = Qnil; ptr->lookahead = Qundef; ptr->feedvalue = Qundef; ptr->stop_exc = Qfalse; - ptr->size = size; + RB_OBJ_WRITE(enum_obj, &ptr->size, size); ptr->size_fn = size_fn; ptr->kw_splat = kw_splat; @@ -515,13 +504,13 @@ enumerator_init_copy(VALUE obj, VALUE orig) rb_raise(rb_eArgError, "unallocated enumerator"); } - ptr1->obj = ptr0->obj; + RB_OBJ_WRITE(obj, &ptr1->obj, ptr0->obj); ptr1->meth = ptr0->meth; - ptr1->args = ptr0->args; + RB_OBJ_WRITE(obj, &ptr1->args, ptr0->args); ptr1->fib = 0; ptr1->lookahead = Qundef; ptr1->feedvalue = Qundef; - ptr1->size = ptr0->size; + RB_OBJ_WRITE(obj, &ptr1->size, ptr0->size); ptr1->size_fn = ptr0->size_fn; return obj; @@ -569,11 +558,17 @@ enumerator_block_call(VALUE obj, rb_block_call_func *func, VALUE arg) const struct enumerator *e = enumerator_ptr(obj); ID meth = e->meth; - if (e->args) { - argc = RARRAY_LENINT(e->args); - argv = RARRAY_CONST_PTR(e->args); + VALUE args = e->args; + if (args) { + argc = RARRAY_LENINT(args); + argv = RARRAY_CONST_PTR(args); } - return rb_block_call_kw(e->obj, meth, argc, argv, func, arg, e->kw_splat); + + VALUE ret = rb_block_call_kw(e->obj, meth, argc, argv, func, arg, e->kw_splat); + + RB_GC_GUARD(args); + + return ret; } /* @@ -630,7 +625,7 @@ enumerator_each(int argc, VALUE *argv, VALUE obj) else { args = rb_ary_new4(argc, argv); } - e->args = args; + RB_OBJ_WRITE(obj, &e->args, args); e->size = Qnil; e->size_fn = 0; } @@ -771,7 +766,7 @@ next_i(RB_BLOCK_CALL_FUNC_ARGLIST(_, obj)) VALUE result; result = rb_block_call(obj, id_each, 0, 0, next_ii, obj); - e->stop_exc = rb_exc_new2(rb_eStopIteration, "iteration reached an end"); + RB_OBJ_WRITE(obj, &e->stop_exc, rb_exc_new2(rb_eStopIteration, "iteration reached an end")); rb_ivar_set(e->stop_exc, id_result, result); return rb_fiber_yield(1, &nil); } @@ -780,8 +775,8 @@ static void next_init(VALUE obj, struct enumerator *e) { VALUE curr = rb_fiber_current(); - e->dst = curr; - e->fib = rb_fiber_new(next_i, obj); + RB_OBJ_WRITE(obj, &e->dst, curr); + RB_OBJ_WRITE(obj, &e->fib, rb_fiber_new(next_i, obj)); e->lookahead = Qundef; } @@ -869,6 +864,8 @@ enumerator_next_values(VALUE obj) struct enumerator *e = enumerator_ptr(obj); VALUE vs; + rb_check_frozen(obj); + if (!UNDEF_P(e->lookahead)) { vs = e->lookahead; e->lookahead = Qundef; @@ -930,9 +927,12 @@ enumerator_peek_values(VALUE obj) { struct enumerator *e = enumerator_ptr(obj); + rb_check_frozen(obj); + if (UNDEF_P(e->lookahead)) { - e->lookahead = get_next_values(obj, e); + RB_OBJ_WRITE(obj, &e->lookahead, get_next_values(obj, e)); } + return e->lookahead; } @@ -1054,10 +1054,12 @@ enumerator_feed(VALUE obj, VALUE v) { struct enumerator *e = enumerator_ptr(obj); + rb_check_frozen(obj); + if (!UNDEF_P(e->feedvalue)) { rb_raise(rb_eTypeError, "feed value already set"); } - e->feedvalue = v; + RB_OBJ_WRITE(obj, &e->feedvalue, v); return Qnil; } @@ -1076,6 +1078,8 @@ enumerator_rewind(VALUE obj) { struct enumerator *e = enumerator_ptr(obj); + rb_check_frozen(obj); + rb_check_funcall(e->obj, id_rewind, 0, 0); e->fib = 0; @@ -1289,23 +1293,15 @@ yielder_compact(void *p) ptr->proc = rb_gc_location(ptr->proc); } -#define yielder_free RUBY_TYPED_DEFAULT_FREE - -static size_t -yielder_memsize(const void *p) -{ - return sizeof(struct yielder); -} - static const rb_data_type_t yielder_data_type = { "yielder", { yielder_mark, - yielder_free, - yielder_memsize, + RUBY_TYPED_DEFAULT_FREE, + NULL, yielder_compact, }, - 0, 0, RUBY_TYPED_FREE_IMMEDIATELY + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_EMBEDDABLE }; static struct yielder * @@ -1344,7 +1340,7 @@ yielder_init(VALUE obj, VALUE proc) rb_raise(rb_eArgError, "unallocated yielder"); } - ptr->proc = proc; + RB_OBJ_WRITE(obj, &ptr->proc, proc); return obj; } @@ -1429,23 +1425,15 @@ generator_compact(void *p) ptr->obj = rb_gc_location(ptr->obj); } -#define generator_free RUBY_TYPED_DEFAULT_FREE - -static size_t -generator_memsize(const void *p) -{ - return sizeof(struct generator); -} - static const rb_data_type_t generator_data_type = { "generator", { generator_mark, - generator_free, - generator_memsize, + RUBY_TYPED_DEFAULT_FREE, + NULL, generator_compact, }, - 0, 0, RUBY_TYPED_FREE_IMMEDIATELY + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_EMBEDDABLE }; static struct generator * @@ -1485,7 +1473,7 @@ generator_init(VALUE obj, VALUE proc) rb_raise(rb_eArgError, "unallocated generator"); } - ptr->proc = proc; + RB_OBJ_WRITE(obj, &ptr->proc, proc); return obj; } @@ -1533,7 +1521,7 @@ generator_init_copy(VALUE obj, VALUE orig) rb_raise(rb_eArgError, "unallocated generator"); } - ptr1->proc = ptr0->proc; + RB_OBJ_WRITE(obj, &ptr1->proc, ptr0->proc); return obj; } @@ -1700,7 +1688,7 @@ lazy_generator_init(VALUE enumerator, VALUE procs) lazy_init_block, rb_ary_new3(2, obj, procs)); gen_ptr = generator_ptr(generator); - gen_ptr->obj = obj; + RB_OBJ_WRITE(generator, &gen_ptr->obj, obj); return generator; } @@ -1885,10 +1873,10 @@ lazy_add_method(VALUE obj, int argc, VALUE *argv, VALUE args, VALUE memo, VALUE entry_obj = TypedData_Make_Struct(rb_cObject, struct proc_entry, &proc_entry_data_type, entry); if (rb_block_given_p()) { - entry->proc = rb_block_proc(); + RB_OBJ_WRITE(entry_obj, &entry->proc, rb_block_proc()); } entry->fn = fn; - entry->memo = args; + RB_OBJ_WRITE(entry_obj, &entry->memo, args); lazy_set_args(entry_obj, memo); @@ -1897,9 +1885,9 @@ lazy_add_method(VALUE obj, int argc, VALUE *argv, VALUE args, VALUE memo, rb_ary_push(new_procs, entry_obj); new_obj = enumerator_init_copy(enumerator_allocate(rb_cLazy), obj); - new_e = DATA_PTR(new_obj); - new_e->obj = new_generator; - new_e->procs = new_procs; + new_e = RTYPEDDATA_GET_DATA(new_obj); + RB_OBJ_WRITE(new_obj, &new_e->obj, new_generator); + RB_OBJ_WRITE(new_obj, &new_e->procs, new_procs); if (argc > 0) { new_e->meth = rb_to_id(*argv++); @@ -1908,7 +1896,9 @@ lazy_add_method(VALUE obj, int argc, VALUE *argv, VALUE args, VALUE memo, else { new_e->meth = id_each; } - new_e->args = rb_ary_new4(argc, argv); + + RB_OBJ_WRITE(new_obj, &new_e->args, rb_ary_new4(argc, argv)); + return new_obj; } @@ -1994,7 +1984,7 @@ lazy_to_enum(int argc, VALUE *argv, VALUE self) } lazy = lazy_to_enum_i(self, meth, argc, argv, 0, rb_keyword_given_p()); if (rb_block_given_p()) { - enumerator_ptr(lazy)->size = rb_block_proc(); + RB_OBJ_WRITE(lazy, &enumerator_ptr(lazy)->size, rb_block_proc()); } return lazy; } @@ -2409,7 +2399,6 @@ lazy_zip_func(VALUE proc_entry, struct MEMO *result, VALUE memos, long memo_inde rb_ary_push(ary, v); } LAZY_MEMO_SET_VALUE(result, ary); - LAZY_MEMO_SET_PACKED(result); return result; } @@ -2954,7 +2943,7 @@ static const rb_data_type_t producer_data_type = { producer_memsize, producer_compact, }, - 0, 0, RUBY_TYPED_FREE_IMMEDIATELY + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_EMBEDDABLE }; static struct producer * @@ -2994,8 +2983,8 @@ producer_init(VALUE obj, VALUE init, VALUE proc) rb_raise(rb_eArgError, "unallocated producer"); } - ptr->init = init; - ptr->proc = proc; + RB_OBJ_WRITE(obj, &ptr->init, init); + RB_OBJ_WRITE(obj, &ptr->proc, proc); return obj; } @@ -3190,7 +3179,7 @@ enum_chain_initialize(VALUE obj, VALUE enums) if (!ptr) rb_raise(rb_eArgError, "unallocated chain"); - ptr->enums = rb_obj_freeze(enums); + ptr->enums = rb_ary_freeze(enums); ptr->pos = -1; return obj; @@ -3518,7 +3507,7 @@ enum_product_initialize(int argc, VALUE *argv, VALUE obj) if (!ptr) rb_raise(rb_eArgError, "unallocated product"); - ptr->enums = rb_obj_freeze(enums); + ptr->enums = rb_ary_freeze(enums); return obj; } @@ -3545,10 +3534,19 @@ static VALUE enum_product_total_size(VALUE enums) { VALUE total = INT2FIX(1); + VALUE sizes = rb_ary_hidden_new(RARRAY_LEN(enums)); long i; for (i = 0; i < RARRAY_LEN(enums); i++) { VALUE size = enum_size(RARRAY_AREF(enums, i)); + if (size == INT2FIX(0)) { + rb_ary_resize(sizes, 0); + return size; + } + rb_ary_push(sizes, size); + } + for (i = 0; i < RARRAY_LEN(sizes); i++) { + VALUE size = RARRAY_AREF(sizes, i); if (NIL_P(size) || (RB_TYPE_P(size, T_FLOAT) && isinf(NUM2DBL(size)))) { return size; @@ -3749,6 +3747,55 @@ enumerator_s_product(int argc, VALUE *argv, VALUE klass) return obj; } +struct arith_seq { + struct enumerator enumerator; + VALUE begin; + VALUE end; + VALUE step; + bool exclude_end; +}; + +RUBY_REFERENCES(arith_seq_refs) = { + RUBY_REF_EDGE(struct enumerator, obj), + RUBY_REF_EDGE(struct enumerator, args), + RUBY_REF_EDGE(struct enumerator, fib), + RUBY_REF_EDGE(struct enumerator, dst), + RUBY_REF_EDGE(struct enumerator, lookahead), + RUBY_REF_EDGE(struct enumerator, feedvalue), + RUBY_REF_EDGE(struct enumerator, stop_exc), + RUBY_REF_EDGE(struct enumerator, size), + RUBY_REF_EDGE(struct enumerator, procs), + + RUBY_REF_EDGE(struct arith_seq, begin), + RUBY_REF_EDGE(struct arith_seq, end), + RUBY_REF_EDGE(struct arith_seq, step), + RUBY_REF_END +}; + +static const rb_data_type_t arith_seq_data_type = { + "arithmetic_sequence", + { + RUBY_REFS_LIST_PTR(arith_seq_refs), + RUBY_TYPED_DEFAULT_FREE, + NULL, // Nothing allocated externally, so don't need a memsize function + NULL, + }, + .parent = &enumerator_data_type, + .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_DECL_MARKING | RUBY_TYPED_EMBEDDABLE +}; + +static VALUE +arith_seq_allocate(VALUE klass) +{ + struct arith_seq *ptr; + VALUE enum_obj; + + enum_obj = TypedData_Make_Struct(klass, struct arith_seq, &arith_seq_data_type, ptr); + ptr->enumerator.obj = Qundef; + + return enum_obj; +} + /* * Document-class: Enumerator::ArithmeticSequence * @@ -3766,12 +3813,16 @@ rb_arith_seq_new(VALUE obj, VALUE meth, int argc, VALUE const *argv, rb_enumerator_size_func *size_fn, VALUE beg, VALUE end, VALUE step, int excl) { - VALUE aseq = enumerator_init(enumerator_allocate(rb_cArithSeq), + VALUE aseq = enumerator_init(arith_seq_allocate(rb_cArithSeq), obj, meth, argc, argv, size_fn, Qnil, rb_keyword_given_p()); - rb_ivar_set(aseq, id_begin, beg); - rb_ivar_set(aseq, id_end, end); - rb_ivar_set(aseq, id_step, step); - rb_ivar_set(aseq, id_exclude_end, RBOOL(excl)); + struct arith_seq *ptr; + TypedData_Get_Struct(aseq, struct arith_seq, &enumerator_data_type, ptr); + + RB_OBJ_WRITE(aseq, &ptr->begin, beg); + RB_OBJ_WRITE(aseq, &ptr->end, end); + RB_OBJ_WRITE(aseq, &ptr->step, step); + ptr->exclude_end = excl; + return aseq; } @@ -3784,7 +3835,9 @@ rb_arith_seq_new(VALUE obj, VALUE meth, int argc, VALUE const *argv, static inline VALUE arith_seq_begin(VALUE self) { - return rb_ivar_get(self, id_begin); + struct arith_seq *ptr; + TypedData_Get_Struct(self, struct arith_seq, &enumerator_data_type, ptr); + return ptr->begin; } /* @@ -3795,7 +3848,9 @@ arith_seq_begin(VALUE self) static inline VALUE arith_seq_end(VALUE self) { - return rb_ivar_get(self, id_end); + struct arith_seq *ptr; + TypedData_Get_Struct(self, struct arith_seq, &enumerator_data_type, ptr); + return ptr->end; } /* @@ -3807,7 +3862,9 @@ arith_seq_end(VALUE self) static inline VALUE arith_seq_step(VALUE self) { - return rb_ivar_get(self, id_step); + struct arith_seq *ptr; + TypedData_Get_Struct(self, struct arith_seq, &enumerator_data_type, ptr); + return ptr->step; } /* @@ -3818,13 +3875,17 @@ arith_seq_step(VALUE self) static inline VALUE arith_seq_exclude_end(VALUE self) { - return rb_ivar_get(self, id_exclude_end); + struct arith_seq *ptr; + TypedData_Get_Struct(self, struct arith_seq, &enumerator_data_type, ptr); + return RBOOL(ptr->exclude_end); } static inline int arith_seq_exclude_end_p(VALUE self) { - return RTEST(arith_seq_exclude_end(self)); + struct arith_seq *ptr; + TypedData_Get_Struct(self, struct arith_seq, &enumerator_data_type, ptr); + return ptr->exclude_end; } int @@ -4571,7 +4632,7 @@ InitVM_Enumerator(void) rb_hash_aset(lazy_use_super_method, sym("uniq"), sym("_enumerable_uniq")); rb_hash_aset(lazy_use_super_method, sym("with_index"), sym("_enumerable_with_index")); rb_obj_freeze(lazy_use_super_method); - rb_gc_register_mark_object(lazy_use_super_method); + rb_vm_register_global_object(lazy_use_super_method); #if 0 /* for RDoc */ rb_define_method(rb_cLazy, "to_a", lazy_to_a, 0); @@ -4665,7 +4726,6 @@ void Init_Enumerator(void) { id_rewind = rb_intern_const("rewind"); - id_new = rb_intern_const("new"); id_next = rb_intern_const("next"); id_result = rb_intern_const("result"); id_receiver = rb_intern_const("receiver"); @@ -4675,12 +4735,7 @@ Init_Enumerator(void) id_force = rb_intern_const("force"); id_to_enum = rb_intern_const("to_enum"); id_each_entry = rb_intern_const("each_entry"); - id_begin = rb_intern_const("begin"); - id_end = rb_intern_const("end"); - id_step = rb_intern_const("step"); - id_exclude_end = rb_intern_const("exclude_end"); sym_each = ID2SYM(id_each); - sym_cycle = ID2SYM(rb_intern_const("cycle")); sym_yield = ID2SYM(rb_intern_const("yield")); InitVM(Enumerator); diff --git a/error.c b/error.c index 13a6e3a5e28a11..d3aeec54d8b97c 100644 --- a/error.c +++ b/error.c @@ -23,25 +23,33 @@ # include #endif +#ifdef HAVE_SYS_WAIT_H +# include +#endif + #if defined __APPLE__ # include #endif #include "internal.h" +#include "internal/class.h" #include "internal/error.h" #include "internal/eval.h" #include "internal/hash.h" #include "internal/io.h" #include "internal/load.h" #include "internal/object.h" +#include "internal/process.h" #include "internal/string.h" #include "internal/symbol.h" #include "internal/thread.h" #include "internal/variable.h" #include "ruby/encoding.h" #include "ruby/st.h" +#include "ruby/util.h" #include "ruby_assert.h" #include "vm_core.h" +#include "yjit.h" #include "builtin.h" @@ -78,6 +86,7 @@ static ID id_category; static ID id_deprecated; static ID id_experimental; static ID id_performance; +static ID id_strict_unused_block; static VALUE sym_category; static VALUE sym_highlight; static struct { @@ -205,12 +214,10 @@ rb_warning_category_enabled_p(rb_warning_category_t category) * deprecation warnings * * assignment of non-nil value to $, and $; * * keyword arguments - * * proc/lambda without block * etc. * * +:experimental+ :: * experimental features - * * Pattern matching * * +:performance+ :: * performance hints @@ -245,6 +252,26 @@ rb_warning_s_aset(VALUE mod, VALUE category, VALUE flag) return flag; } +/* + * call-seq: + * categories -> array + * + * Returns a list of the supported category symbols. + */ + +static VALUE +rb_warning_s_categories(VALUE mod) +{ + st_index_t num = warning_categories.id2enum->num_entries; + ID *ids = ALLOCA_N(ID, num); + num = st_keys(warning_categories.id2enum, ids, num); + VALUE ary = rb_ary_new_capa(num); + for (st_index_t i = 0; i < num; ++i) { + rb_ary_push(ary, ID2SYM(ids[i])); + } + return rb_ary_freeze(ary); +} + /* * call-seq: * warn(msg, category: nil) -> nil @@ -286,11 +313,11 @@ rb_warning_s_warn(int argc, VALUE *argv, VALUE mod) * * Changing the behavior of Warning.warn is useful to customize how warnings are * handled by Ruby, for instance by filtering some warnings, and/or outputting - * warnings somewhere other than $stderr. + * warnings somewhere other than $stderr. * * If you want to change the behavior of Warning.warn you should use - * +Warning.extend(MyNewModuleWithWarnMethod)+ and you can use `super` - * to get the default behavior of printing the warning to $stderr. + * Warning.extend(MyNewModuleWithWarnMethod) and you can use +super+ + * to get the default behavior of printing the warning to $stderr. * * Example: * module MyWarningFilter @@ -307,7 +334,7 @@ rb_warning_s_warn(int argc, VALUE *argv, VALUE mod) * You should never redefine Warning#warn (the instance method), as that will * then no longer provide a way to use the default behavior. * - * The +warning+ gem provides convenient ways to customize Warning.warn. + * The warning[https://rubygems.org/gems/warning] gem provides convenient ways to customize Warning.warn. */ static VALUE @@ -359,18 +386,28 @@ warn_vsprintf(rb_encoding *enc, const char *file, int line, const char *fmt, va_ return rb_str_cat2(str, "\n"); } -#define with_warn_vsprintf(file, line, fmt) \ +#define with_warn_vsprintf(enc, file, line, fmt) \ VALUE str; \ va_list args; \ va_start(args, fmt); \ - str = warn_vsprintf(NULL, file, line, fmt, args); \ + str = warn_vsprintf(enc, file, line, fmt, args); \ va_end(args); void rb_compile_warn(const char *file, int line, const char *fmt, ...) { if (!NIL_P(ruby_verbose)) { - with_warn_vsprintf(file, line, fmt) { + with_warn_vsprintf(NULL, file, line, fmt) { + rb_write_warning_str(str); + } + } +} + +void +rb_enc_compile_warn(rb_encoding *enc, const char *file, int line, const char *fmt, ...) +{ + if (!NIL_P(ruby_verbose)) { + with_warn_vsprintf(enc, file, line, fmt) { rb_write_warning_str(str); } } @@ -381,7 +418,18 @@ void rb_compile_warning(const char *file, int line, const char *fmt, ...) { if (RTEST(ruby_verbose)) { - with_warn_vsprintf(file, line, fmt) { + with_warn_vsprintf(NULL, file, line, fmt) { + rb_write_warning_str(str); + } + } +} + +/* rb_enc_compile_warning() reports only in verbose mode */ +void +rb_enc_compile_warning(rb_encoding *enc, const char *file, int line, const char *fmt, ...) +{ + if (RTEST(ruby_verbose)) { + with_warn_vsprintf(enc, file, line, fmt) { rb_write_warning_str(str); } } @@ -391,7 +439,7 @@ void rb_category_compile_warn(rb_warning_category_t category, const char *file, int line, const char *fmt, ...) { if (!NIL_P(ruby_verbose)) { - with_warn_vsprintf(file, line, fmt) { + with_warn_vsprintf(NULL, file, line, fmt) { rb_warn_category(str, rb_warning_category_to_name(category)); } } @@ -427,7 +475,7 @@ rb_warn(const char *fmt, ...) void rb_category_warn(rb_warning_category_t category, const char *fmt, ...) { - if (!NIL_P(ruby_verbose)) { + if (!NIL_P(ruby_verbose) && rb_warning_category_enabled_p(category)) { with_warning_string(mesg, 0, fmt) { rb_warn_category(mesg, rb_warning_category_to_name(category)); } @@ -459,7 +507,7 @@ rb_warning(const char *fmt, ...) void rb_category_warning(rb_warning_category_t category, const char *fmt, ...) { - if (RTEST(ruby_verbose)) { + if (RTEST(ruby_verbose) && rb_warning_category_enabled_p(category)) { with_warning_string(mesg, 0, fmt) { rb_warn_category(mesg, rb_warning_category_to_name(category)); } @@ -527,6 +575,18 @@ rb_warn_deprecated_to_remove(const char *removal, const char *fmt, const char *s } } +void +rb_warn_reserved_name(const char *coming, const char *fmt, ...) +{ + if (!deprecation_warning_enabled()) return; + + with_warning_string_from(mesg, 0, fmt, fmt) { + rb_str_set_len(mesg, RSTRING_LEN(mesg) - 1); + rb_str_catf(mesg, " is reserved for Ruby %s\n", coming); + rb_warn_category(mesg, ID2SYM(id_deprecated)); + } +} + static inline int end_with_asciichar(VALUE str, int c) { @@ -623,18 +683,239 @@ rb_bug_reporter_add(void (*func)(FILE *, void *), void *data) return 1; } +/* returns true if x can not be used as file name */ +static bool +path_sep_p(char x) +{ +#if defined __CYGWIN__ || defined DOSISH +# define PATH_SEP_ENCODING 1 + // Assume that "/" is only the first byte in any encoding. + if (x == ':') return true; // drive letter or ADS + if (x == '\\') return true; +#endif + return x == '/'; +} + +struct path_string { + const char *ptr; + size_t len; +}; + +static const char PATHSEP_REPLACE = '!'; + +static char * +append_pathname(char *p, const char *pe, VALUE str) +{ +#ifdef PATH_SEP_ENCODING + rb_encoding *enc = rb_enc_get(str); +#endif + const char *s = RSTRING_PTR(str); + const char *const se = s + RSTRING_LEN(str); + char c; + + --pe; // for terminator + + while (p < pe && s < se && (c = *s) != '\0') { + if (c == '.') { + if (s == se || !*s) break; // chomp "." basename + if (path_sep_p(s[1])) goto skipsep; // skip "./" + } + else if (path_sep_p(c)) { + // squeeze successive separators + *p++ = PATHSEP_REPLACE; + skipsep: + while (++s < se && path_sep_p(*s)); + continue; + } + const char *const ss = s; + while (p < pe && s < se && *s && !path_sep_p(*s)) { +#ifdef PATH_SEP_ENCODING + int n = rb_enc_mbclen(s, se, enc); +#else + const int n = 1; +#endif + p += n; + s += n; + } + if (s > ss) memcpy(p - (s - ss), ss, s - ss); + } + + return p; +} + +static char * +append_basename(char *p, const char *pe, struct path_string *path, VALUE str) +{ + if (!path->ptr) { +#ifdef PATH_SEP_ENCODING + rb_encoding *enc = rb_enc_get(str); +#endif + const char *const b = RSTRING_PTR(str), *const e = RSTRING_END(str), *p = e; + + while (p > b) { + if (path_sep_p(p[-1])) { +#ifdef PATH_SEP_ENCODING + const char *t = rb_enc_prev_char(b, p, e, enc); + if (t == p-1) break; + p = t; +#else + break; +#endif + } + else { + --p; + } + } + + path->ptr = p; + path->len = e - p; + } + size_t n = path->len; + if (p + n > pe) n = pe - p; + memcpy(p, path->ptr, n); + return p + n; +} + +static void +finish_report(FILE *out, rb_pid_t pid) +{ + if (out != stdout && out != stderr) fclose(out); +#ifdef HAVE_WORKING_FORK + if (pid > 0) waitpid(pid, NULL, 0); +#endif +} + +struct report_expansion { + struct path_string exe, script; + rb_pid_t pid; + time_t time; +}; + +/* + * Open a bug report file to write. The `RUBY_CRASH_REPORT` + * environment variable can be set to define a template that is used + * to name bug report files. The template can contain % specifiers + * which are substituted by the following values when a bug report + * file is created: + * + * %% A single % character. + * %e The base name of the executable filename. + * %E Pathname of executable, with slashes ('/') replaced by + * exclamation marks ('!'). + * %f Similar to %e with the main script filename. + * %F Similar to %E with the main script filename. + * %p PID of dumped process in decimal. + * %t Time of dump, expressed as seconds since the Epoch, + * 1970-01-01 00:00:00 +0000 (UTC). + * %NNN Octal char code, upto 3 digits. + */ +static char * +expand_report_argument(const char **input_template, struct report_expansion *values, + char *buf, size_t size, bool word) +{ + char *p = buf; + char *end = buf + size; + const char *template = *input_template; + bool store = true; + + if (p >= end-1 || !*template) return NULL; + do { + char c = *template++; + if (word && ISSPACE(c)) break; + if (!store) continue; + if (c == '%') { + size_t n; + switch (c = *template++) { + case 'e': + p = append_basename(p, end, &values->exe, rb_argv0); + continue; + case 'E': + p = append_pathname(p, end, rb_argv0); + continue; + case 'f': + p = append_basename(p, end, &values->script, GET_VM()->orig_progname); + continue; + case 'F': + p = append_pathname(p, end, GET_VM()->orig_progname); + continue; + case 'p': + if (!values->pid) values->pid = getpid(); + snprintf(p, end-p, "%" PRI_PIDT_PREFIX "d", values->pid); + p += strlen(p); + continue; + case 't': + if (!values->time) values->time = time(NULL); + snprintf(p, end-p, "%" PRI_TIMET_PREFIX "d", values->time); + p += strlen(p); + continue; + default: + if (c >= '0' && c <= '7') { + c = (unsigned char)ruby_scan_oct(template-1, 3, &n); + template += n - 1; + if (!c) store = false; + } + break; + } + } + if (p < end-1) *p++ = c; + } while (*template); + *input_template = template; + *p = '\0'; + return ++p; +} + +FILE *ruby_popen_writer(char *const *argv, rb_pid_t *pid); + +static FILE * +open_report_path(const char *template, char *buf, size_t size, rb_pid_t *pid) +{ + struct report_expansion values = {{0}}; + + if (!template) return NULL; + if (0) fprintf(stderr, "RUBY_CRASH_REPORT=%s\n", buf); + if (*template == '|') { + char *argv[16], *bufend = buf + size, *p; + int argc; + template++; + for (argc = 0; argc < numberof(argv) - 1; ++argc) { + while (*template && ISSPACE(*template)) template++; + p = expand_report_argument(&template, &values, buf, bufend-buf, true); + if (!p) break; + argv[argc] = buf; + buf = p; + } + argv[argc] = NULL; + if (!p) return ruby_popen_writer(argv, pid); + } + else if (*template) { + expand_report_argument(&template, &values, buf, size, false); + return fopen(buf, "w"); + } + return NULL; +} + +static const char *crash_report; + /* SIGSEGV handler might have a very small stack. Thus we need to use it carefully. */ #define REPORT_BUG_BUFSIZ 256 static FILE * -bug_report_file(const char *file, int line) +bug_report_file(const char *file, int line, rb_pid_t *pid) { char buf[REPORT_BUG_BUFSIZ]; - FILE *out = stderr; + const char *report = crash_report; + if (!report) report = getenv("RUBY_CRASH_REPORT"); + FILE *out = open_report_path(report, buf, sizeof(buf), pid); int len = err_position_0(buf, sizeof(buf), file, line); - if ((ssize_t)fwrite(buf, 1, len, out) == (ssize_t)len || - (ssize_t)fwrite(buf, 1, len, (out = stdout)) == (ssize_t)len) { - return out; + if (out) { + if ((ssize_t)fwrite(buf, 1, len, out) == (ssize_t)len) return out; + fclose(out); + } + if ((ssize_t)fwrite(buf, 1, len, stderr) == (ssize_t)len) { + return stderr; + } + if ((ssize_t)fwrite(buf, 1, len, stdout) == (ssize_t)len) { + return stdout; } return NULL; @@ -741,7 +1022,7 @@ bug_report_begin_valist(FILE *out, const char *fmt, va_list args) } while (0) static void -bug_report_end(FILE *out) +bug_report_end(FILE *out, rb_pid_t pid) { /* call additional bug reporters */ { @@ -752,26 +1033,45 @@ bug_report_end(FILE *out) } } postscript_dump(out); + finish_report(out, pid); } #define report_bug(file, line, fmt, ctx) do { \ - FILE *out = bug_report_file(file, line); \ + rb_pid_t pid = -1; \ + FILE *out = bug_report_file(file, line, &pid); \ if (out) { \ bug_report_begin(out, fmt); \ - rb_vm_bugreport(ctx); \ - bug_report_end(out); \ + rb_vm_bugreport(ctx, out); \ + bug_report_end(out, pid); \ } \ } while (0) \ #define report_bug_valist(file, line, fmt, ctx, args) do { \ - FILE *out = bug_report_file(file, line); \ + rb_pid_t pid = -1; \ + FILE *out = bug_report_file(file, line, &pid); \ if (out) { \ bug_report_begin_valist(out, fmt, args); \ - rb_vm_bugreport(ctx); \ - bug_report_end(out); \ + rb_vm_bugreport(ctx, out); \ + bug_report_end(out, pid); \ } \ } while (0) \ +void +ruby_set_crash_report(const char *template) +{ + crash_report = template; +#if RUBY_DEBUG + rb_pid_t pid = -1; + char buf[REPORT_BUG_BUFSIZ]; + FILE *out = open_report_path(template, buf, sizeof(buf), &pid); + if (out) { + time_t t = time(NULL); + fprintf(out, "ruby_test_bug_report: %s", ctime(&t)); + finish_report(out, pid); + } +#endif +} + NORETURN(static void die(void)); static void die(void) @@ -784,8 +1084,8 @@ die(void) } RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 1, 0) -void -rb_bug_without_die(const char *fmt, va_list args) +static void +rb_bug_without_die_internal(const char *fmt, va_list args) { const char *file = NULL; int line = 0; @@ -797,12 +1097,22 @@ rb_bug_without_die(const char *fmt, va_list args) report_bug_valist(file, line, fmt, NULL, args); } +RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 1, 0) +void +rb_bug_without_die(const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + rb_bug_without_die_internal(fmt, args); + va_end(args); +} + void rb_bug(const char *fmt, ...) { va_list args; va_start(args, fmt); - rb_bug_without_die(fmt, args); + rb_bug_without_die_internal(fmt, args); va_end(args); die(); } @@ -821,6 +1131,7 @@ rb_bug_for_fatal_signal(ruby_sighandler_t default_sighandler, int sig, const voi if (default_sighandler) default_sighandler(sig); + ruby_default_signal(sig); die(); } @@ -877,13 +1188,34 @@ rb_report_bug_valist(VALUE file, int line, const char *fmt, va_list args) void rb_assert_failure(const char *file, int line, const char *name, const char *expr) { - FILE *out = stderr; - fprintf(out, "Assertion Failed: %s:%d:", file, line); - if (name) fprintf(out, "%s:", name); - fprintf(out, "%s\n%s\n\n", expr, rb_dynamic_description); - preface_dump(out); - rb_vm_bugreport(NULL); - bug_report_end(out); + rb_assert_failure_detail(file, line, name, expr, NULL); +} + +void +rb_assert_failure_detail(const char *file, int line, const char *name, const char *expr, + const char *fmt, ...) +{ + rb_pid_t pid = -1; + FILE *out = bug_report_file(file, line, &pid); + if (out) { + fputs("Assertion Failed: ", out); + if (name) fprintf(out, "%s:", name); + fputs(expr, out); + + if (fmt && *fmt) { + va_list args; + va_start(args, fmt); + fputs(": ", out); + vfprintf(out, fmt, args); + va_end(args); + } + fprintf(out, "\n%s\n\n", rb_dynamic_description); + + preface_dump(out); + rb_vm_bugreport(NULL, out); + bug_report_end(out, pid); + } + die(); } @@ -1077,7 +1409,7 @@ rb_check_typeddata(VALUE obj, const rb_data_type_t *data_type) actual = rb_str_new_cstr(name); /* or rb_fstring_cstr? not sure... */ } else { - return DATA_PTR(obj); + return RTYPEDDATA_GET_DATA(obj); } const char *expected = data_type->wrap_struct_name; @@ -1148,6 +1480,7 @@ rb_exc_new_cstr(VALUE etype, const char *s) VALUE rb_exc_new_str(VALUE etype, VALUE str) { + rb_yjit_lazy_push_frame(GET_EC()->cfp->pc); StringValue(str); return rb_class_new_instance(1, &str, etype); } @@ -1162,12 +1495,23 @@ exc_init(VALUE exc, VALUE mesg) } /* - * call-seq: - * Exception.new(msg = nil) -> exception - * Exception.exception(msg = nil) -> exception + * call-seq: + * Exception.new(message = nil) -> exception + * + * Returns a new exception object. + * + * The given +message+ should be + * a {string-convertible object}[rdoc-ref:implicit_conversion.rdoc@String-Convertible+Objects]; + * see method #message; + * if not given, the message is the class name of the new instance + * (which may be the name of a subclass): + * + * Examples: + * + * Exception.new # => # + * LoadError.new # => # # Subclass of Exception. + * Exception.new('Boom') # => # * - * Construct a new Exception object, optionally passing in - * a message. */ static VALUE @@ -1183,12 +1527,24 @@ exc_initialize(int argc, VALUE *argv, VALUE exc) * Document-method: exception * * call-seq: - * exc.exception([string]) -> an_exception or exc + * exception(message = nil) -> self or new_exception + * + * Returns an exception object of the same class as +self+; + * useful for creating a similar exception, but with a different message. * - * With no argument, or if the argument is the same as the receiver, - * return the receiver. Otherwise, create a new - * exception object of the same class as the receiver, but with a - * message equal to string.to_str. + * With +message+ +nil+, returns +self+: + * + * x0 = StandardError.new('Boom') # => # + * x1 = x0.exception # => # + * x0.__id__ == x1.__id__ # => true + * + * With {string-convertible object}[rdoc-ref:implicit_conversion.rdoc@String-Convertible+Objects] + * +message+ (even the same as the original message), + * returns a new exception object whose class is the same as +self+, + * and whose message is the given +message+: + * + * x1 = x0.exception('Boom') # => # + * x0..equal?(x1) # => false * */ @@ -1207,10 +1563,15 @@ exc_exception(int argc, VALUE *argv, VALUE self) /* * call-seq: - * exception.to_s -> string + * to_s -> string + * + * Returns a string representation of +self+: + * + * x = RuntimeError.new('Boom') + * x.to_s # => "Boom" + * x = RuntimeError.new + * x.to_s # => "RuntimeError" * - * Returns exception's message (or the name of the exception if - * no message is set). */ static VALUE @@ -1250,10 +1611,10 @@ rb_get_detailed_message(VALUE exc, VALUE opt) } /* - * call-seq: - * Exception.to_tty? -> true or false + * call-seq: + * Exception.to_tty? -> true or false * - * Returns +true+ if exception messages will be sent to a tty. + * Returns +true+ if exception messages will be sent to a terminal device. */ static VALUE exc_s_to_tty_p(VALUE self) @@ -1313,20 +1674,51 @@ check_order_keyword(VALUE opt) /* * call-seq: - * exception.full_message(highlight: bool, order: [:top or :bottom]) -> string + * full_message(highlight: true, order: :top) -> string * - * Returns formatted string of _exception_. - * The returned string is formatted using the same format that Ruby uses - * when printing an uncaught exceptions to stderr. + * Returns an enhanced message string: * - * If _highlight_ is +true+ the default error handler will send the - * messages to a tty. + * - Includes the exception class name. + * - If the value of keyword +highlight+ is true (not +nil+ or +false+), + * includes bolding ANSI codes (see below) to enhance the appearance of the message. + * - Includes the {backtrace}[rdoc-ref:exceptions.md@Backtraces]: * - * _order_ must be either of +:top+ or +:bottom+, and places the error - * message and the innermost backtrace come at the top or the bottom. + * - If the value of keyword +order+ is +:top+ (the default), + * lists the error message and the innermost backtrace entry first. + * - If the value of keyword +order+ is +:bottom+, + * lists the error message the the innermost entry last. * - * The default values of these options depend on $stderr - * and its +tty?+ at the timing of a call. + * Example: + * + * def baz + * begin + * 1 / 0 + * rescue => x + * pp x.message + * pp x.full_message(highlight: false).split("\n") + * pp x.full_message.split("\n") + * end + * end + * def bar; baz; end + * def foo; bar; end + * foo + * + * Output: + * + * "divided by 0" + * ["t.rb:3:in 'Integer#/': divided by 0 (ZeroDivisionError)", + * "\tfrom t.rb:3:in 'Object#baz'", + * "\tfrom t.rb:10:in 'Object#bar'", + * "\tfrom t.rb:11:in 'Object#foo'", + * "\tfrom t.rb:12:in '
'"] + * ["t.rb:3:in 'Integer#/': \e[1mdivided by 0 (\e[1;4mZeroDivisionError\e[m\e[1m)\e[m", + * "\tfrom t.rb:3:in 'Object#baz'", + * "\tfrom t.rb:10:in 'Object#bar'", + * "\tfrom t.rb:11:in 'Object#foo'", + * "\tfrom t.rb:12:in '
'"] + * + * An overriding method should be careful with ANSI code enhancements; + * see {Messages}[rdoc-ref:exceptions.md@Messages]. */ static VALUE @@ -1355,10 +1747,11 @@ exc_full_message(int argc, VALUE *argv, VALUE exc) /* * call-seq: - * exception.message -> string + * message -> string + * + * Returns #to_s. * - * Returns the result of invoking exception.to_s. - * Normally this returns the exception's message or name. + * See {Messages}[rdoc-ref:exceptions.md@Messages]. */ static VALUE @@ -1369,42 +1762,47 @@ exc_message(VALUE exc) /* * call-seq: - * exception.detailed_message(highlight: bool, **opt) -> string + * detailed_message(highlight: false, **kwargs) -> string + * + * Returns the message string with enhancements: + * + * - Includes the exception class name in the first line. + * - If the value of keyword +highlight+ is +true+, + * includes bolding and underlining ANSI codes (see below) + * to enhance the appearance of the message. * - * Processes a string returned by #message. + * Examples: * - * It may add the class name of the exception to the end of the first line. - * Also, when +highlight+ keyword is true, it adds ANSI escape sequences to - * make the message bold. + * begin + * 1 / 0 + * rescue => x + * p x.message + * p x.detailed_message # Class name added. + * p x.detailed_message(highlight: true) # Class name, bolding, and underlining added. + * end * - * If you override this method, it must be tolerant for unknown keyword - * arguments. All keyword arguments passed to #full_message are delegated - * to this method. + * Output: * - * This method is overridden by did_you_mean and error_highlight to add - * their information. + * "divided by 0" + * "divided by 0 (ZeroDivisionError)" + * "\e[1mdivided by 0 (\e[1;4mZeroDivisionError\e[m\e[1m)\e[m" * - * A user-defined exception class can also define their own - * +detailed_message+ method to add supplemental information. - * When +highlight+ is true, it can return a string containing escape - * sequences, but use widely-supported ones. It is recommended to limit - * the following codes: + * This method is overridden by some gems in the Ruby standard library to add information: * - * - Reset (+\e[0m+) - * - Bold (+\e[1m+) - * - Underline (+\e[4m+) - * - Foreground color except white and black - * - Red (+\e[31m+) - * - Green (+\e[32m+) - * - Yellow (+\e[33m+) - * - Blue (+\e[34m+) - * - Magenta (+\e[35m+) - * - Cyan (+\e[36m+) + * - DidYouMean::Correctable#detailed_message. + * - ErrorHighlight::CoreExt#detailed_message. + * - SyntaxSuggest#detailed_message. * - * Use escape sequences carefully even if +highlight+ is true. - * Do not use escape sequences to express essential information; - * the message should be readable even if all escape sequences are - * ignored. + * An overriding method must be tolerant of passed keyword arguments, + * which may include (but may not be limited to): + * + * - +:highlight+. + * - +:did_you_mean+. + * - +:error_highlight+. + * - +:syntax_suggest+. + * + * An overriding method should also be careful with ANSI code enhancements; + * see {Messages}[rdoc-ref:exceptions.md@Messages]. */ static VALUE @@ -1416,16 +1814,22 @@ exc_detailed_message(int argc, VALUE *argv, VALUE exc) VALUE highlight = check_highlight_keyword(opt, 0); - extern VALUE rb_decorate_message(const VALUE eclass, const VALUE emesg, int highlight); + extern VALUE rb_decorate_message(const VALUE eclass, VALUE emesg, int highlight); return rb_decorate_message(CLASS_OF(exc), rb_get_message(exc), RTEST(highlight)); } /* * call-seq: - * exception.inspect -> string + * inspect -> string + * + * Returns a string representation of +self+: + * + * x = RuntimeError.new('Boom') + * x.inspect # => "#" + * x = RuntimeError.new + * x.inspect # => "#" * - * Return this exception's class name and message. */ static VALUE @@ -1458,38 +1862,36 @@ exc_inspect(VALUE exc) /* * call-seq: - * exception.backtrace -> array or nil + * backtrace -> array or nil * - * Returns any backtrace associated with the exception. The backtrace - * is an array of strings, each containing either ``filename:lineNo: in - * `method''' or ``filename:lineNo.'' + * Returns the backtrace (the list of code locations that led to the exception), + * as an array of strings. * - * def a - * raise "boom" - * end + * Example (assuming the code is stored in the file named t.rb): * - * def b - * a() - * end - * - * begin - * b() - * rescue => detail - * print detail.backtrace.join("\n") - * end + * def division(numerator, denominator) + * numerator / denominator + * end * - * produces: + * begin + * division(1, 0) + * rescue => ex + * p ex.backtrace + * # ["t.rb:2:in 'Integer#/'", "t.rb:2:in 'Object#division'", "t.rb:6:in '
'"] + * loc = ex.backtrace.first + * p loc.class + * # String + * end * - * prog.rb:2:in `a' - * prog.rb:6:in `b' - * prog.rb:10 + * The value returned by this method migth be adjusted when raising (see Kernel#raise), + * or during intermediate handling by #set_backtrace. * - * In the case no backtrace has been set, +nil+ is returned + * See also #backtrace_locations that provide the same value, as structured objects. + * (Note though that two values might not be consistent with each other when + * backtraces are manually adjusted.) * - * ex = StandardError.new - * ex.backtrace - * #=> nil -*/ + * see {Backtraces}[rdoc-ref:exceptions.md@Backtraces]. + */ static VALUE exc_backtrace(VALUE exc) @@ -1531,13 +1933,41 @@ rb_get_backtrace(VALUE exc) /* * call-seq: - * exception.backtrace_locations -> array or nil + * backtrace_locations -> array or nil + * + * Returns the backtrace (the list of code locations that led to the exception), + * as an array of Thread::Backtrace::Location instances. + * + * Example (assuming the code is stored in the file named t.rb): + * + * def division(numerator, denominator) + * numerator / denominator + * end + * + * begin + * division(1, 0) + * rescue => ex + * p ex.backtrace_locations + * # ["t.rb:2:in 'Integer#/'", "t.rb:2:in 'Object#division'", "t.rb:6:in '
'"] + * loc = ex.backtrace_locations.first + * p loc.class + * # Thread::Backtrace::Location + * p loc.path + * # "t.rb" + * p loc.lineno + * # 2 + * p loc.label + * # "Integer#/" + * end * - * Returns any backtrace associated with the exception. This method is - * similar to Exception#backtrace, but the backtrace is an array of - * Thread::Backtrace::Location. + * The value returned by this method might be adjusted when raising (see Kernel#raise), + * or during intermediate handling by #set_backtrace. * - * This method is not affected by Exception#set_backtrace(). + * See also #backtrace that provide the same value as an array of strings. + * (Note though that two values might not be consistent with each other when + * backtraces are manually adjusted.) + * + * See {Backtraces}[rdoc-ref:exceptions.md@Backtraces]. */ static VALUE exc_backtrace_locations(VALUE exc) @@ -1555,7 +1985,7 @@ static VALUE rb_check_backtrace(VALUE bt) { long i; - static const char err[] = "backtrace must be Array of String"; + static const char err[] = "backtrace must be an Array of String or an Array of Thread::Backtrace::Location"; if (!NIL_P(bt)) { if (RB_TYPE_P(bt, T_STRING)) return rb_ary_new3(1, bt); @@ -1575,18 +2005,118 @@ rb_check_backtrace(VALUE bt) /* * call-seq: - * exc.set_backtrace(backtrace) -> array + * set_backtrace(value) -> value + * + * Sets the backtrace value for +self+; returns the given +value+. + * + * The +value+ might be: + * + * - an array of Thread::Backtrace::Location; + * - an array of String instances; + * - a single String instance; or + * - +nil+. + * + * Using array of Thread::Backtrace::Location is the most consistent + * option: it sets both #backtrace and #backtrace_locations. It should be + * preferred when possible. The suitable array of locations can be obtained + * from Kernel#caller_locations, copied from another error, or just set to + * the adjusted result of the current error's #backtrace_locations: * - * Sets the backtrace information associated with +exc+. The +backtrace+ must - * be an array of String objects or a single String in the format described - * in Exception#backtrace. + * require 'json' + * + * def parse_payload(text) + * JSON.parse(text) # test.rb, line 4 + * rescue JSON::ParserError => ex + * ex.set_backtrace(ex.backtrace_locations[2...]) + * raise + * end + * + * parse_payload('{"wrong: "json"') + * # test.rb:4:in 'Object#parse_payload': unexpected token at '{"wrong: "json"' (JSON::ParserError) + * # + * # An error points to the body of parse_payload method, + * # hiding the parts of the backtrace related to the internals + * # of the "json" library + * + * # The error has both #backtace and #backtrace_locations set + * # consistently: + * begin + * parse_payload('{"wrong: "json"') + * rescue => ex + * p ex.backtrace + * # ["test.rb:4:in 'Object#parse_payload'", "test.rb:20:in '
'"] + * p ex.backtrace_locations + * # ["test.rb:4:in 'Object#parse_payload'", "test.rb:20:in '
'"] + * end * + * When the desired stack of locations is not available and should + * be constructed from scratch, an array of strings or a singular + * string can be used. In this case, only #backtrace is affected: + * + * def parse_payload(text) + * JSON.parse(text) + * rescue JSON::ParserError => ex + * ex.set_backtrace(["dsl.rb:34", "framework.rb:1"]) + * # The error have the new value in #backtrace: + * p ex.backtrace + * # ["dsl.rb:34", "framework.rb:1"] + * + * # but the original one in #backtrace_locations + * p ex.backtrace_locations + * # [".../json/common.rb:221:in 'JSON::Ext::Parser.parse'", ...] + * end + * + * parse_payload('{"wrong: "json"') + * + * Calling #set_backtrace with +nil+ clears up #backtrace but doesn't affect + * #backtrace_locations: + * + * def parse_payload(text) + * JSON.parse(text) + * rescue JSON::ParserError => ex + * ex.set_backtrace(nil) + * p ex.backtrace + * # nil + * p ex.backtrace_locations + * # [".../json/common.rb:221:in 'JSON::Ext::Parser.parse'", ...] + * end + * + * parse_payload('{"wrong: "json"') + * + * On reraising of such an exception, both #backtrace and #backtrace_locations + * is set to the place of reraising: + * + * def parse_payload(text) + * JSON.parse(text) + * rescue JSON::ParserError => ex + * ex.set_backtrace(nil) + * raise # test.rb, line 7 + * end + * + * begin + * parse_payload('{"wrong: "json"') + * rescue => ex + * p ex.backtrace + * # ["test.rb:7:in 'Object#parse_payload'", "test.rb:11:in '
'"] + * p ex.backtrace_locations + * # ["test.rb:7:in 'Object#parse_payload'", "test.rb:11:in '
'"] + * end + * + * See {Backtraces}[rdoc-ref:exceptions.md@Backtraces]. */ static VALUE exc_set_backtrace(VALUE exc, VALUE bt) { - return rb_ivar_set(exc, id_bt, rb_check_backtrace(bt)); + VALUE btobj = rb_location_ary_to_backtrace(bt); + if (RTEST(btobj)) { + rb_ivar_set(exc, id_bt, btobj); + rb_ivar_set(exc, id_bt_locations, btobj); + return bt; + } + else { + return rb_ivar_set(exc, id_bt, rb_check_backtrace(bt)); + } } VALUE @@ -1596,12 +2126,35 @@ rb_exc_set_backtrace(VALUE exc, VALUE bt) } /* - * call-seq: - * exception.cause -> an_exception or nil + * call-seq: + * cause -> exception or nil + * + * Returns the previous value of global variable $!, + * which may be +nil+ + * (see {Global Variables}[rdoc-ref:exceptions.md@Global+Variables]): + * + * begin + * raise('Boom 0') + * rescue => x0 + * puts "Exception: #{x0}; $!: #{$!}; cause: #{x0.cause.inspect}." + * begin + * raise('Boom 1') + * rescue => x1 + * puts "Exception: #{x1}; $!: #{$!}; cause: #{x1.cause}." + * begin + * raise('Boom 2') + * rescue => x2 + * puts "Exception: #{x2}; $!: #{$!}; cause: #{x2.cause}." + * end + * end + * end + * + * Output: + * + * Exception: Boom 0; $!: Boom 0; cause: nil. + * Exception: Boom 1; $!: Boom 1; cause: Boom 0. + * Exception: Boom 2; $!: Boom 2; cause: Boom 1. * - * Returns the previous exception ($!) at the time this exception was raised. - * This is useful for wrapping exceptions and retaining the original exception - * information. */ static VALUE @@ -1618,11 +2171,11 @@ try_convert_to_exception(VALUE obj) /* * call-seq: - * exc == obj -> true or false + * self == object -> true or false + * + * Returns whether +object+ is the same class as +self+ + * and its #message and #backtrace are equal to those of +self+. * - * Equality---If obj is not an Exception, returns - * false. Otherwise, returns true if exc and - * obj share same class, messages, and backtrace. */ static VALUE @@ -1957,50 +2510,50 @@ rb_nomethod_err_new(VALUE mesg, VALUE recv, VALUE method, VALUE args, int priv) return nometh_err_init_attr(exc, args, priv); } -/* :nodoc: */ -enum { - NAME_ERR_MESG__MESG, - NAME_ERR_MESG__RECV, - NAME_ERR_MESG__NAME, - NAME_ERR_MESG_COUNT -}; +typedef struct name_error_message_struct { + VALUE mesg; + VALUE recv; + VALUE name; +} name_error_message_t; static void name_err_mesg_mark(void *p) { - VALUE *ptr = p; - rb_gc_mark_locations(ptr, ptr+NAME_ERR_MESG_COUNT); + name_error_message_t *ptr = (name_error_message_t *)p; + rb_gc_mark_movable(ptr->mesg); + rb_gc_mark_movable(ptr->recv); + rb_gc_mark_movable(ptr->name); } -#define name_err_mesg_free RUBY_TYPED_DEFAULT_FREE - -static size_t -name_err_mesg_memsize(const void *p) +static void +name_err_mesg_update(void *p) { - return NAME_ERR_MESG_COUNT * sizeof(VALUE); + name_error_message_t *ptr = (name_error_message_t *)p; + ptr->mesg = rb_gc_location(ptr->mesg); + ptr->recv = rb_gc_location(ptr->recv); + ptr->name = rb_gc_location(ptr->name); } static const rb_data_type_t name_err_mesg_data_type = { "name_err_mesg", { name_err_mesg_mark, - name_err_mesg_free, - name_err_mesg_memsize, + RUBY_TYPED_DEFAULT_FREE, + NULL, // No external memory to report, + name_err_mesg_update, }, - 0, 0, RUBY_TYPED_FREE_IMMEDIATELY + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_EMBEDDABLE }; /* :nodoc: */ static VALUE -rb_name_err_mesg_init(VALUE klass, VALUE mesg, VALUE recv, VALUE method) +rb_name_err_mesg_init(VALUE klass, VALUE mesg, VALUE recv, VALUE name) { - VALUE result = TypedData_Wrap_Struct(klass, &name_err_mesg_data_type, 0); - VALUE *ptr = ALLOC_N(VALUE, NAME_ERR_MESG_COUNT); - - ptr[NAME_ERR_MESG__MESG] = mesg; - ptr[NAME_ERR_MESG__RECV] = recv; - ptr[NAME_ERR_MESG__NAME] = method; - RTYPEDDATA_DATA(result) = ptr; + name_error_message_t *message; + VALUE result = TypedData_Make_Struct(klass, name_error_message_t, &name_err_mesg_data_type, message); + RB_OBJ_WRITE(result, &message->mesg, mesg); + RB_OBJ_WRITE(result, &message->recv, recv); + RB_OBJ_WRITE(result, &message->name, name); return result; } @@ -2022,14 +2575,16 @@ name_err_mesg_alloc(VALUE klass) static VALUE name_err_mesg_init_copy(VALUE obj1, VALUE obj2) { - VALUE *ptr1, *ptr2; - if (obj1 == obj2) return obj1; rb_obj_init_copy(obj1, obj2); - TypedData_Get_Struct(obj1, VALUE, &name_err_mesg_data_type, ptr1); - TypedData_Get_Struct(obj2, VALUE, &name_err_mesg_data_type, ptr2); - MEMCPY(ptr1, ptr2, VALUE, NAME_ERR_MESG_COUNT); + name_error_message_t *ptr1, *ptr2; + TypedData_Get_Struct(obj1, name_error_message_t, &name_err_mesg_data_type, ptr1); + TypedData_Get_Struct(obj2, name_error_message_t, &name_err_mesg_data_type, ptr2); + + RB_OBJ_WRITE(obj1, &ptr1->mesg, ptr2->mesg); + RB_OBJ_WRITE(obj1, &ptr1->recv, ptr2->recv); + RB_OBJ_WRITE(obj1, &ptr1->name, ptr2->name); return obj1; } @@ -2037,19 +2592,18 @@ name_err_mesg_init_copy(VALUE obj1, VALUE obj2) static VALUE name_err_mesg_equal(VALUE obj1, VALUE obj2) { - VALUE *ptr1, *ptr2; - int i; - if (obj1 == obj2) return Qtrue; + if (rb_obj_class(obj2) != rb_cNameErrorMesg) return Qfalse; - TypedData_Get_Struct(obj1, VALUE, &name_err_mesg_data_type, ptr1); - TypedData_Get_Struct(obj2, VALUE, &name_err_mesg_data_type, ptr2); - for (i=0; imesg, ptr2->mesg)) return Qfalse; + if (!rb_equal(ptr1->recv, ptr2->recv)) return Qfalse; + if (!rb_equal(ptr1->name, ptr2->name)) return Qfalse; return Qtrue; } @@ -2068,10 +2622,10 @@ name_err_mesg_receiver_name(VALUE obj) static VALUE name_err_mesg_to_str(VALUE obj) { - VALUE *ptr, mesg; - TypedData_Get_Struct(obj, VALUE, &name_err_mesg_data_type, ptr); + name_error_message_t *ptr; + TypedData_Get_Struct(obj, name_error_message_t, &name_err_mesg_data_type, ptr); - mesg = ptr[NAME_ERR_MESG__MESG]; + VALUE mesg = ptr->mesg; if (NIL_P(mesg)) return Qnil; else { struct RString s_str, c_str, d_str; @@ -2081,7 +2635,7 @@ name_err_mesg_to_str(VALUE obj) #define FAKE_CSTR(v, str) rb_setup_fake_str((v), (str), rb_strlen_lit(str), usascii) c = s = FAKE_CSTR(&s_str, ""); - obj = ptr[NAME_ERR_MESG__RECV]; + obj = ptr->recv; switch (obj) { case Qnil: c = d = FAKE_CSTR(&d_str, "nil"); @@ -2124,7 +2678,7 @@ name_err_mesg_to_str(VALUE obj) VALUE klass; object: klass = CLASS_OF(obj); - if (RB_TYPE_P(klass, T_CLASS) && FL_TEST(klass, FL_SINGLETON)) { + if (RB_TYPE_P(klass, T_CLASS) && RCLASS_SINGLETON_P(klass)) { s = FAKE_CSTR(&s_str, ""); if (obj == rb_vm_top_self()) { c = FAKE_CSTR(&c_str, "main"); @@ -2152,7 +2706,7 @@ name_err_mesg_to_str(VALUE obj) c = c2; break; } - args[0] = rb_obj_as_string(ptr[NAME_ERR_MESG__NAME]); + args[0] = rb_obj_as_string(ptr->name); args[1] = d; args[2] = s; args[3] = c; @@ -2185,17 +2739,17 @@ name_err_mesg_load(VALUE klass, VALUE str) static VALUE name_err_receiver(VALUE self) { - VALUE *ptr, recv, mesg; - - recv = rb_ivar_lookup(self, id_recv, Qundef); + VALUE recv = rb_ivar_lookup(self, id_recv, Qundef); if (!UNDEF_P(recv)) return recv; - mesg = rb_attr_get(self, id_mesg); + VALUE mesg = rb_attr_get(self, id_mesg); if (!rb_typeddata_is_kind_of(mesg, &name_err_mesg_data_type)) { rb_raise(rb_eArgError, "no receiver is available"); } - ptr = DATA_PTR(mesg); - return ptr[NAME_ERR_MESG__RECV]; + + name_error_message_t *ptr; + TypedData_Get_Struct(mesg, name_error_message_t, &name_err_mesg_data_type, ptr); + return ptr->recv; } /* @@ -2405,8 +2959,18 @@ syntax_error_with_path(VALUE exc, VALUE path, VALUE *mesg, rb_encoding *enc) rb_ivar_set(exc, id_i_path, path); } else { - if (rb_attr_get(exc, id_i_path) != path) { - rb_raise(rb_eArgError, "SyntaxError#path changed"); + VALUE old_path = rb_attr_get(exc, id_i_path); + if (old_path != path) { + if (rb_str_equal(path, old_path)) { + rb_raise(rb_eArgError, "SyntaxError#path changed: %+"PRIsVALUE" (%p->%p)", + old_path, (void *)old_path, (void *)path); + } + else { + rb_raise(rb_eArgError, "SyntaxError#path changed: %+"PRIsVALUE"(%s%s)->%+"PRIsVALUE"(%s)", + old_path, rb_enc_name(rb_enc_get(old_path)), + (FL_TEST(old_path, RSTRING_FSTR) ? ":FSTR" : ""), + path, rb_enc_name(rb_enc_get(path))); + } } VALUE s = *mesg = rb_attr_get(exc, idMesg); if (RSTRING_LEN(s) > 0 && *(RSTRING_END(s)-1) != '\n') @@ -2418,67 +2982,105 @@ syntax_error_with_path(VALUE exc, VALUE path, VALUE *mesg, rb_encoding *enc) /* * Document-module: Errno * - * Ruby exception objects are subclasses of Exception. However, - * operating systems typically report errors using plain - * integers. Module Errno is created dynamically to map these - * operating system errors to Ruby classes, with each error number - * generating its own subclass of SystemCallError. As the subclass - * is created in module Errno, its name will start - * Errno::. + * When an operating system encounters an error, + * it typically reports the error as an integer error code: + * + * $ ls nosuch.txt + * ls: cannot access 'nosuch.txt': No such file or directory + * $ echo $? # Code for last error. + * 2 + * + * When the Ruby interpreter interacts with the operating system + * and receives such an error code (e.g., +2+), + * it maps the code to a particular Ruby exception class (e.g., +Errno::ENOENT+): + * + * File.open('nosuch.txt') + * # => No such file or directory @ rb_sysopen - nosuch.txt (Errno::ENOENT) + * + * Each such class is: * - * The names of the Errno:: classes depend on the - * environment in which Ruby runs. On a typical Unix or Windows - * platform, there are Errno classes such as Errno::EACCES, - * Errno::EAGAIN, Errno::EINTR, and so on. + * - A nested class in this module, +Errno+. + * - A subclass of class SystemCallError. + * - Associated with an error code. * - * The integer operating system error number corresponding to a - * particular error is available as the class constant - * Errno::error::Errno. + * Thus: * - * Errno::EACCES::Errno #=> 13 - * Errno::EAGAIN::Errno #=> 11 - * Errno::EINTR::Errno #=> 4 + * Errno::ENOENT.superclass # => SystemCallError + * Errno::ENOENT::Errno # => 2 * - * The full list of operating system errors on your particular platform - * are available as the constants of Errno. + * The names of nested classes are returned by method +Errno.constants+: * - * Errno.constants #=> :E2BIG, :EACCES, :EADDRINUSE, :EADDRNOTAVAIL, ... + * Errno.constants.size # => 158 + * Errno.constants.sort.take(5) # => [:E2BIG, :EACCES, :EADDRINUSE, :EADDRNOTAVAIL, :EADV] + * + * As seen above, the error code associated with each class + * is available as the value of a constant; + * the value for a particular class may vary among operating systems. + * If the class is not needed for the particular operating system, + * the value is zero: + * + * Errno::ENOENT::Errno # => 2 + * Errno::ENOTCAPABLE::Errno # => 0 + * + * Each class in Errno can be created with optional messages: + * + * Errno::EPIPE.new # => # + * Errno::EPIPE.new("foo") # => # + * Errno::EPIPE.new("foo", "here") # => # + * + * See SystemCallError.new. */ static st_table *syserr_tbl; -static VALUE -set_syserr(int n, const char *name) +void +rb_free_warning(void) { - st_data_t error; + st_free_table(warning_categories.id2enum); + st_free_table(warning_categories.enum2id); + st_free_table(syserr_tbl); +} - if (!st_lookup(syserr_tbl, n, &error)) { - error = rb_define_class_under(rb_mErrno, name, rb_eSystemCallError); +static VALUE +setup_syserr(int n, const char *name) +{ + VALUE error = rb_define_class_under(rb_mErrno, name, rb_eSystemCallError); - /* capture nonblock errnos for WaitReadable/WaitWritable subclasses */ - switch (n) { - case EAGAIN: - rb_eEAGAIN = error; + /* capture nonblock errnos for WaitReadable/WaitWritable subclasses */ + switch (n) { + case EAGAIN: + rb_eEAGAIN = error; #if defined(EWOULDBLOCK) && EWOULDBLOCK != EAGAIN - break; - case EWOULDBLOCK: + break; + case EWOULDBLOCK: #endif - rb_eEWOULDBLOCK = error; - break; - case EINPROGRESS: - rb_eEINPROGRESS = error; - break; - } + rb_eEWOULDBLOCK = error; + break; + case EINPROGRESS: + rb_eEINPROGRESS = error; + break; + } - rb_define_const(error, "Errno", INT2NUM(n)); - st_add_direct(syserr_tbl, n, error); + rb_define_const(error, "Errno", INT2NUM(n)); + st_add_direct(syserr_tbl, n, (st_data_t)error); + return error; +} + +static VALUE +set_syserr(int n, const char *name) +{ + st_data_t error; + + if (!st_lookup(syserr_tbl, n, &error)) { + return setup_syserr(n, name); } else { - rb_define_const(rb_mErrno, name, error); + VALUE errclass = (VALUE)error; + rb_define_const(rb_mErrno, name, errclass); + return errclass; } - return error; } static VALUE @@ -2487,22 +3089,43 @@ get_syserr(int n) st_data_t error; if (!st_lookup(syserr_tbl, n, &error)) { - char name[8]; /* some Windows' errno have 5 digits. */ + char name[DECIMAL_SIZE_OF(n) + sizeof("E-")]; snprintf(name, sizeof(name), "E%03d", n); - error = set_syserr(n, name); + return setup_syserr(n, name); } - return error; + return (VALUE)error; } /* * call-seq: - * SystemCallError.new(msg, errno) -> system_call_error_subclass + * SystemCallError.new(msg, errno = nil, func = nil) -> system_call_error_subclass * * If _errno_ corresponds to a known system error code, constructs the * appropriate Errno class for that error, otherwise constructs a * generic SystemCallError object. The error number is subsequently * available via the #errno method. + * + * If only numeric object is given, it is treated as an Integer _errno_, + * and _msg_ is omitted, otherwise the first argument _msg_ is used as + * the additional error message. + * + * SystemCallError.new(Errno::EPIPE::Errno) + * #=> # + * + * SystemCallError.new("foo") + * #=> # + * + * SystemCallError.new("foo", Errno::EPIPE::Errno) + * #=> # + * + * If _func_ is not +nil+, it is appended to the message with " @ ". + * + * SystemCallError.new("foo", Errno::EPIPE::Errno, "here") + * #=> # + * + * A subclass of SystemCallError can also be instantiated via the + * +new+ method of the subclass. See Errno. */ static VALUE @@ -2806,7 +3429,7 @@ syserr_eqq(VALUE self, VALUE exc) * * raises the exception: * - * NoMethodError: undefined method `to_ary' for "hello":String + * NoMethodError: undefined method `to_ary' for an instance of String */ /* @@ -2879,7 +3502,7 @@ syserr_eqq(VALUE self, VALUE exc) /* * Document-class: fatal * - * fatal is an Exception that is raised when Ruby has encountered a fatal + * +fatal+ is an Exception that is raised when Ruby has encountered a fatal * error and must exit. */ @@ -2891,62 +3514,26 @@ syserr_eqq(VALUE self, VALUE exc) /* * Document-class: Exception * - * \Class Exception and its subclasses are used to communicate between - * Kernel#raise and +rescue+ statements in begin ... end blocks. - * - * An Exception object carries information about an exception: - * - Its type (the exception's class). - * - An optional descriptive message. - * - Optional backtrace information. + * Class +Exception+ and its subclasses are used to indicate that an error + * or other problem has occurred, + * and may need to be handled. + * See {Exceptions}[rdoc-ref:exceptions.md]. * - * Some built-in subclasses of Exception have additional methods: e.g., NameError#name. + * An +Exception+ object carries certain information: * - * == Defaults + * - The type (the exception's class), + * commonly StandardError, RuntimeError, or a subclass of one or the other; + * see {Built-In Exception Class Hierarchy}[rdoc-ref:Exception@Built-In+Exception+Class+Hierarchy]. + * - An optional descriptive message; + * see methods ::new, #message. + * - Optional backtrace information; + * see methods #backtrace, #backtrace_locations, #set_backtrace. + * - An optional cause; + * see method #cause. * - * Two Ruby statements have default exception classes: - * - +raise+: defaults to RuntimeError. - * - +rescue+: defaults to StandardError. + * == Built-In \Exception Class Hierarchy * - * == Global Variables - * - * When an exception has been raised but not yet handled (in +rescue+, - * +ensure+, +at_exit+ and +END+ blocks), two global variables are set: - * - $! contains the current exception. - * - $@ contains its backtrace. - * - * == Custom Exceptions - * - * To provide additional or alternate information, - * a program may create custom exception classes - * that derive from the built-in exception classes. - * - * A good practice is for a library to create a single "generic" exception class - * (typically a subclass of StandardError or RuntimeError) - * and have its other exception classes derive from that class. - * This allows the user to rescue the generic exception, thus catching all exceptions - * the library may raise even if future versions of the library add new - * exception subclasses. - * - * For example: - * - * class MyLibrary - * class Error < ::StandardError - * end - * - * class WidgetError < Error - * end - * - * class FrobError < Error - * end - * - * end - * - * To handle both MyLibrary::WidgetError and MyLibrary::FrobError the library - * user can rescue MyLibrary::Error. - * - * == Built-In Exception Classes - * - * The built-in subclasses of Exception are: + * The hierarchy of built-in subclasses of class +Exception+: * * * NoMemoryError * * ScriptError @@ -2976,13 +3563,14 @@ syserr_eqq(VALUE self, VALUE exc) * * RuntimeError * * FrozenError * * SystemCallError - * * Errno::* + * * Errno (and its subclasses, representing system errors) * * ThreadError * * TypeError * * ZeroDivisionError * * SystemExit * * SystemStackError - * * fatal + * * {fatal}[rdoc-ref:fatal] + * */ static VALUE @@ -3002,9 +3590,9 @@ exception_dumper(VALUE exc) } static int -ivar_copy_i(st_data_t key, st_data_t val, st_data_t exc) +ivar_copy_i(ID key, VALUE val, st_data_t exc) { - rb_ivar_set((VALUE) exc, (ID) key, (VALUE) val); + rb_ivar_set((VALUE)exc, key, val); return ST_CONTINUE; } @@ -3081,11 +3669,11 @@ Init_Exception(void) * and will render `idPath` as an attribute name without this trick */ ID path = idPath; - /* the path failed to parse */ + /* the path that failed to parse */ rb_attr(rb_eSyntaxError, path, TRUE, FALSE, FALSE); rb_eLoadError = rb_define_class("LoadError", rb_eScriptError); - /* the path failed to load */ + /* the path that failed to load */ rb_attr(rb_eLoadError, path, TRUE, FALSE, FALSE); rb_eNotImpError = rb_define_class("NotImplementedError", rb_eScriptError); @@ -3132,6 +3720,7 @@ Init_Exception(void) rb_mWarning = rb_define_module("Warning"); rb_define_singleton_method(rb_mWarning, "[]", rb_warning_s_aref, 1); rb_define_singleton_method(rb_mWarning, "[]=", rb_warning_s_aset, 2); + rb_define_singleton_method(rb_mWarning, "categories", rb_warning_s_categories, 0); rb_define_method(rb_mWarning, "warn", rb_warning_s_warn, -1); rb_extend_object(rb_mWarning, rb_mWarning); @@ -3157,6 +3746,7 @@ Init_Exception(void) id_deprecated = rb_intern_const("deprecated"); id_experimental = rb_intern_const("experimental"); id_performance = rb_intern_const("performance"); + id_strict_unused_block = rb_intern_const("strict_unused_block"); id_top = rb_intern_const("top"); id_bottom = rb_intern_const("bottom"); id_iseq = rb_make_internal_id(); @@ -3169,12 +3759,14 @@ Init_Exception(void) st_add_direct(warning_categories.id2enum, id_deprecated, RB_WARN_CATEGORY_DEPRECATED); st_add_direct(warning_categories.id2enum, id_experimental, RB_WARN_CATEGORY_EXPERIMENTAL); st_add_direct(warning_categories.id2enum, id_performance, RB_WARN_CATEGORY_PERFORMANCE); + st_add_direct(warning_categories.id2enum, id_strict_unused_block, RB_WARN_CATEGORY_STRICT_UNUSED_BLOCK); warning_categories.enum2id = rb_init_identtable(); st_add_direct(warning_categories.enum2id, RB_WARN_CATEGORY_NONE, 0); st_add_direct(warning_categories.enum2id, RB_WARN_CATEGORY_DEPRECATED, id_deprecated); st_add_direct(warning_categories.enum2id, RB_WARN_CATEGORY_EXPERIMENTAL, id_experimental); st_add_direct(warning_categories.enum2id, RB_WARN_CATEGORY_PERFORMANCE, id_performance); + st_add_direct(warning_categories.enum2id, RB_WARN_CATEGORY_STRICT_UNUSED_BLOCK, id_strict_unused_block); } void @@ -3197,12 +3789,13 @@ rb_vraise(VALUE exc, const char *fmt, va_list ap) } void -rb_raise(VALUE exc, const char *fmt, ...) +rb_raise(VALUE exc_class, const char *fmt, ...) { va_list args; va_start(args, fmt); - rb_vraise(exc, fmt, args); + VALUE exc = rb_exc_new3(exc_class, rb_vsprintf(fmt, args)); va_end(args); + rb_exc_raise(exc); } NORETURN(static void raise_loaderror(VALUE path, VALUE mesg)); @@ -3257,7 +3850,7 @@ rb_fatal(const char *fmt, ...) /* The thread has no GVL. Object allocation impossible (cant run GC), * thus no message can be printed out. */ fprintf(stderr, "[FATAL] rb_fatal() outside of GVL\n"); - rb_print_backtrace(); + rb_print_backtrace(stderr); die(); } @@ -3546,11 +4139,25 @@ inspect_frozen_obj(VALUE obj, VALUE mesg, int recur) return mesg; } +static VALUE +get_created_info(VALUE obj, int *pline) +{ + VALUE info = rb_attr_get(obj, id_debug_created_info); + + if (NIL_P(info)) return Qnil; + + VALUE path = rb_ary_entry(info, 0); + VALUE line = rb_ary_entry(info, 1); + if (NIL_P(path)) return Qnil; + *pline = NUM2INT(line); + return StringValue(path); +} + void rb_error_frozen_object(VALUE frozen_obj) { - VALUE debug_info; - const ID created_info = id_debug_created_info; + rb_yjit_lazy_push_frame(GET_EC()->cfp->pc); + VALUE mesg = rb_sprintf("can't modify frozen %"PRIsVALUE": ", CLASS_OF(frozen_obj)); VALUE exc = rb_exc_new_str(rb_eFrozenError, mesg); @@ -3558,36 +4165,81 @@ rb_error_frozen_object(VALUE frozen_obj) rb_ivar_set(exc, id_recv, frozen_obj); rb_exec_recursive(inspect_frozen_obj, frozen_obj, mesg); - if (!NIL_P(debug_info = rb_attr_get(frozen_obj, created_info))) { - VALUE path = rb_ary_entry(debug_info, 0); - VALUE line = rb_ary_entry(debug_info, 1); - - rb_str_catf(mesg, ", created at %"PRIsVALUE":%"PRIsVALUE, path, line); + int created_line; + VALUE created_path = get_created_info(frozen_obj, &created_line); + if (!NIL_P(created_path)) { + rb_str_catf(mesg, ", created at %"PRIsVALUE":%d", created_path, created_line); } rb_exc_raise(exc); } +void +rb_warn_unchilled_literal(VALUE obj) +{ + rb_warning_category_t category = RB_WARN_CATEGORY_DEPRECATED; + if (!NIL_P(ruby_verbose) && rb_warning_category_enabled_p(category)) { + int line; + VALUE file = rb_source_location(&line); + VALUE mesg = NIL_P(file) ? rb_str_new(0, 0) : rb_str_dup(file); + + if (!NIL_P(file)) { + if (line) rb_str_catf(mesg, ":%d", line); + rb_str_cat2(mesg, ": "); + } + rb_str_cat2(mesg, "warning: literal string will be frozen in the future"); + + VALUE str = obj; + if (STR_SHARED_P(str)) { + str = RSTRING(obj)->as.heap.aux.shared; + } + VALUE created = get_created_info(str, &line); + if (NIL_P(created)) { + rb_str_cat2(mesg, " (run with --debug-frozen-string-literal for more information)\n"); + } + else { + rb_str_cat2(mesg, "\n"); + rb_str_append(mesg, created); + if (line) rb_str_catf(mesg, ":%d", line); + rb_str_cat2(mesg, ": info: the string was created here\n"); + } + rb_warn_category(mesg, rb_warning_category_to_name(category)); + } +} + +void +rb_warn_unchilled_symbol_to_s(VALUE obj) +{ + rb_category_warn( + RB_WARN_CATEGORY_DEPRECATED, + "string returned by :%s.to_s will be frozen in the future", RSTRING_PTR(obj) + ); +} + #undef rb_check_frozen void rb_check_frozen(VALUE obj) { - rb_check_frozen_internal(obj); + rb_check_frozen_inline(obj); } void rb_check_copyable(VALUE obj, VALUE orig) { if (!FL_ABLE(obj)) return; - rb_check_frozen_internal(obj); + rb_check_frozen(obj); if (!FL_ABLE(orig)) return; } void Init_syserr(void) { - rb_eNOERROR = set_syserr(0, "NOERROR"); + rb_eNOERROR = setup_syserr(0, "NOERROR"); +#if 0 + /* No error */ + rb_define_const(rb_mErrno, "NOERROR", rb_eNOERROR); +#endif #define defined_error(name, num) set_syserr((num), (name)); -#define undefined_error(name) set_syserr(0, (name)); +#define undefined_error(name) rb_define_const(rb_mErrno, (name), rb_eNOERROR); #include "known_errors.inc" #undef defined_error #undef undefined_error diff --git a/eval.c b/eval.c index 844c537cc41d06..74f31db5c02259 100644 --- a/eval.c +++ b/eval.c @@ -32,7 +32,6 @@ #include "internal/variable.h" #include "ruby/fiber/scheduler.h" #include "iseq.h" -#include "rjit.h" #include "probes.h" #include "probes_helper.h" #include "ruby/vm.h" @@ -70,8 +69,6 @@ ruby_setup(void) if (GET_VM()) return 0; - ruby_init_stack((void *)&state); - /* * Disable THP early before mallocs happen because we want this to * affect as many future pages as possible for CoW-friendliness @@ -80,9 +77,10 @@ ruby_setup(void) prctl(PR_SET_THP_DISABLE, 1, 0, 0, 0); #endif Init_BareVM(); - Init_heap(); rb_vm_encoded_insn_data_table_init(); + Init_enable_namespace(); Init_vm_objects(); + Init_fstring_table(); EC_PUSH_TAG(GET_EC()); if ((state = EC_EXEC_TAG()) == TAG_NONE) { @@ -115,10 +113,9 @@ ruby_options(int argc, char **argv) enum ruby_tag_type state; void *volatile iseq = 0; - ruby_init_stack((void *)&iseq); EC_PUSH_TAG(ec); if ((state = EC_EXEC_TAG()) == TAG_NONE) { - SAVE_ROOT_JMPBUF(GET_THREAD(), iseq = ruby_process_options(argc, argv)); + iseq = ruby_process_options(argc, argv); } else { rb_ec_clear_current_thread_trace_func(ec); @@ -165,7 +162,7 @@ rb_ec_finalize(rb_execution_context_t *ec) { ruby_sig_finalize(); ec->errinfo = Qnil; - rb_objspace_call_finalizer(rb_ec_vm_ptr(ec)->objspace); + rb_objspace_call_finalizer(); } void @@ -200,16 +197,15 @@ rb_ec_cleanup(rb_execution_context_t *ec, enum ruby_tag_type ex) EC_PUSH_TAG(ec); if ((state = EC_EXEC_TAG()) == TAG_NONE) { - SAVE_ROOT_JMPBUF(th, { RUBY_VM_CHECK_INTS(ec); }); + RUBY_VM_CHECK_INTS(ec); step_0: step++; save_error = ec->errinfo; if (THROW_DATA_P(ec->errinfo)) ec->errinfo = Qnil; - ruby_init_stack(&message); /* exits with failure but silently when an exception raised * here */ - SAVE_ROOT_JMPBUF(th, rb_ec_teardown(ec)); + rb_ec_teardown(ec); step_1: step++; VALUE err = ec->errinfo; @@ -227,7 +223,7 @@ rb_ec_cleanup(rb_execution_context_t *ec, enum ruby_tag_type ex) mode1 = exiting_split(err, (mode0 & EXITING_WITH_STATUS) ? NULL : &sysex, &signaled); if (mode1 & EXITING_WITH_MESSAGE) { buf = rb_str_new(NULL, 0); - SAVE_ROOT_JMPBUF(th, rb_ec_error_print_detailed(ec, err, buf, Qundef)); + rb_ec_error_print_detailed(ec, err, buf, Qundef); message = buf; } } @@ -236,7 +232,7 @@ rb_ec_cleanup(rb_execution_context_t *ec, enum ruby_tag_type ex) /* protect from Thread#raise */ th->status = THREAD_KILLED; - SAVE_ROOT_JMPBUF(th, rb_ractor_terminate_all()); + rb_ractor_terminate_all(); step_3: step++; if (!NIL_P(buf = message)) { @@ -283,10 +279,7 @@ rb_ec_exec_node(rb_execution_context_t *ec, void *n) EC_PUSH_TAG(ec); if ((state = EC_EXEC_TAG()) == TAG_NONE) { - rb_thread_t *const th = rb_ec_thread_ptr(ec); - SAVE_ROOT_JMPBUF(th, { - rb_iseq_eval_main(iseq); - }); + rb_iseq_eval_main(iseq); } EC_POP_TAG(); return state; @@ -324,14 +317,12 @@ ruby_run_node(void *n) rb_ec_cleanup(ec, (NIL_P(ec->errinfo) ? TAG_NONE : TAG_RAISE)); return status; } - ruby_init_stack((void *)&status); return rb_ec_cleanup(ec, rb_ec_exec_node(ec, n)); } int ruby_exec_node(void *n) { - ruby_init_stack((void *)&n); return rb_ec_exec_node(GET_EC(), n); } @@ -419,11 +410,11 @@ rb_mod_s_constants(int argc, VALUE *argv, VALUE mod) return rb_const_list(data); } -/*! - * Asserts that \a klass is not a frozen class. - * \param[in] klass a \c Module object - * \exception RuntimeError if \a klass is not a class or frozen. - * \ingroup class +/** + * Asserts that `klass` is not a frozen class. + * @param[in] klass a `Module` object + * @exception RuntimeError if `klass` is not a class or frozen. + * @ingroup class */ void rb_class_modify_check(VALUE klass) @@ -432,12 +423,13 @@ rb_class_modify_check(VALUE klass) Check_Type(klass, T_CLASS); } if (RB_TYPE_P(klass, T_MODULE)) { - rb_module_set_initialized(klass); + // TODO: shouldn't this only happen in a few places? + rb_class_set_initialized(klass); } if (OBJ_FROZEN(klass)) { const char *desc; - if (FL_TEST(klass, FL_SINGLETON)) { + if (RCLASS_SINGLETON_P(klass)) { desc = "object"; klass = RCLASS_ATTACHED_OBJECT(klass); if (!SPECIAL_CONST_P(klass)) { @@ -472,7 +464,7 @@ rb_class_modify_check(VALUE klass) } } -NORETURN(static void rb_longjmp(rb_execution_context_t *, int, volatile VALUE, VALUE)); +NORETURN(static void rb_longjmp(rb_execution_context_t *, enum ruby_tag_type, volatile VALUE, VALUE)); static VALUE get_errinfo(void); #define get_ec_errinfo(ec) rb_ec_get_errinfo(ec) @@ -539,10 +531,14 @@ exc_setup_message(const rb_execution_context_t *ec, VALUE mesg, VALUE *cause) rb_exc_check_circular_cause(*cause); #else VALUE c = *cause; - while (!NIL_P(c = rb_attr_get(c, id_cause))) { + while (!NIL_P(c)) { if (c == mesg) { rb_raise(rb_eArgError, "circular causes"); } + if (THROW_DATA_P(c)) { + break; + } + c = rb_attr_get(c, id_cause); } #endif } @@ -550,7 +546,7 @@ exc_setup_message(const rb_execution_context_t *ec, VALUE mesg, VALUE *cause) } static void -setup_exception(rb_execution_context_t *ec, int tag, volatile VALUE mesg, VALUE cause) +setup_exception(rb_execution_context_t *ec, enum ruby_tag_type tag, volatile VALUE mesg, VALUE cause) { VALUE e; int line; @@ -598,15 +594,15 @@ setup_exception(rb_execution_context_t *ec, int tag, volatile VALUE mesg, VALUE e = rb_obj_as_string(mesg); ec->errinfo = mesg; if (file && line) { - e = rb_sprintf("Exception `%"PRIsVALUE"' at %s:%d - %"PRIsVALUE"\n", + e = rb_sprintf("Exception '%"PRIsVALUE"' at %s:%d - %"PRIsVALUE"\n", rb_obj_class(mesg), file, line, e); } else if (file) { - e = rb_sprintf("Exception `%"PRIsVALUE"' at %s - %"PRIsVALUE"\n", + e = rb_sprintf("Exception '%"PRIsVALUE"' at %s - %"PRIsVALUE"\n", rb_obj_class(mesg), file, e); } else { - e = rb_sprintf("Exception `%"PRIsVALUE"' - %"PRIsVALUE"\n", + e = rb_sprintf("Exception '%"PRIsVALUE"' - %"PRIsVALUE"\n", rb_obj_class(mesg), e); } warn_print_str(e); @@ -654,7 +650,7 @@ rb_ec_setup_exception(const rb_execution_context_t *ec, VALUE mesg, VALUE cause) } static void -rb_longjmp(rb_execution_context_t *ec, int tag, volatile VALUE mesg, VALUE cause) +rb_longjmp(rb_execution_context_t *ec, enum ruby_tag_type tag, volatile VALUE mesg, VALUE cause) { mesg = exc_setup_message(ec, mesg, &cause); setup_exception(ec, tag, mesg, cause); @@ -664,10 +660,10 @@ rb_longjmp(rb_execution_context_t *ec, int tag, volatile VALUE mesg, VALUE cause static VALUE make_exception(int argc, const VALUE *argv, int isstr); -NORETURN(static void rb_exc_exception(VALUE mesg, int tag, VALUE cause)); +NORETURN(static void rb_exc_exception(VALUE mesg, enum ruby_tag_type tag, VALUE cause)); static void -rb_exc_exception(VALUE mesg, int tag, VALUE cause) +rb_exc_exception(VALUE mesg, enum ruby_tag_type tag, VALUE cause) { if (!NIL_P(mesg)) { mesg = make_exception(1, &mesg, FALSE); @@ -675,12 +671,12 @@ rb_exc_exception(VALUE mesg, int tag, VALUE cause) rb_longjmp(GET_EC(), tag, mesg, cause); } -/*! +/** * Raises an exception in the current thread. - * \param[in] mesg an Exception class or an \c Exception object. - * \exception always raises an instance of the given exception class or - * the given \c Exception object. - * \ingroup exception + * @param[in] mesg an Exception class or an `Exception` object. + * @exception always raises an instance of the given exception class or + * the given `Exception` object. + * @ingroup exception */ void rb_exc_raise(VALUE mesg) @@ -756,31 +752,112 @@ rb_f_raise(int argc, VALUE *argv) /* * call-seq: - * raise - * raise(string, cause: $!) - * raise(exception [, string [, array]], cause: $!) - * fail - * fail(string, cause: $!) - * fail(exception [, string [, array]], cause: $!) - * - * With no arguments, raises the exception in $! or raises - * a RuntimeError if $! is +nil+. With a single +String+ - * argument, raises a +RuntimeError+ with the string as a message. Otherwise, - * the first parameter should be an +Exception+ class (or another - * object that returns an +Exception+ object when sent an +exception+ - * message). The optional second parameter sets the message associated with - * the exception (accessible via Exception#message), and the third parameter - * is an array of callback information (accessible via Exception#backtrace). - * The +cause+ of the generated exception (accessible via Exception#cause) - * is automatically set to the "current" exception ($!), if any. - * An alternative value, either an +Exception+ object or +nil+, can be - * specified via the +:cause+ argument. - * - * Exceptions are caught by the +rescue+ clause of - * begin...end blocks. - * - * raise "Failed to create socket" - * raise ArgumentError, "No parameters", caller + * raise(exception, message = exception.to_s, backtrace = nil, cause: $!) + * raise(message = nil, cause: $!) + * + * Raises an exception; + * see {Exceptions}[rdoc-ref:exceptions.md]. + * + * Argument +exception+ sets the class of the new exception; + * it should be class Exception or one of its subclasses + * (most commonly, RuntimeError or StandardError), + * or an instance of one of those classes: + * + * begin + * raise(StandardError) + * rescue => x + * p x.class + * end + * # => StandardError + * + * Argument +message+ sets the stored message in the new exception, + * which may be retrieved by method Exception#message; + * the message must be + * a {string-convertible object}[rdoc-ref:implicit_conversion.rdoc@String-Convertible+Objects] + * or +nil+: + * + * begin + * raise(StandardError, 'Boom') + * rescue => x + * p x.message + * end + * # => "Boom" + * + * If argument +message+ is not given, + * the message is the exception class name. + * + * See {Messages}[rdoc-ref:exceptions.md@Messages]. + * + * Argument +backtrace+ might be used to modify the backtrace of the new exception, + * as reported by Exception#backtrace and Exception#backtrace_locations; + * the backtrace must be an array of Thread::Backtrace::Location, an array of + * strings, a single string, or +nil+. + * + * Using the array of Thread::Backtrace::Location instances is the most consistent option + * and should be preferred when possible. The necessary value might be obtained + * from #caller_locations, or copied from Exception#backtrace_locations of another + * error: + * + * begin + * do_some_work() + * rescue ZeroDivisionError => ex + * raise(LogicalError, "You have an error in your math", ex.backtrace_locations) + * end + * + * The ways, both Exception#backtrace and Exception#backtrace_locations of the + * raised error are set to the same backtrace. + * + * When the desired stack of locations is not available and should + * be constructed from scratch, an array of strings or a singular + * string can be used. In this case, only Exception#backtrace is set: + * + * begin + * raise(StandardError, 'Boom', %w[dsl.rb:3 framework.rb:1]) + * rescue => ex + * p ex.backtrace + * # => ["dsl.rb:3", "framework.rb:1"] + * p ex.backtrace_locations + * # => nil + * end + * + * If argument +backtrace+ is not given, + * the backtrace is set according to an array of Thread::Backtrace::Location objects, + * as derived from the call stack. + * + * See {Backtraces}[rdoc-ref:exceptions.md@Backtraces]. + * + * Keyword argument +cause+ sets the stored cause in the new exception, + * which may be retrieved by method Exception#cause; + * the cause must be an exception object (Exception or one of its subclasses), + * or +nil+: + * + * begin + * raise(StandardError, cause: RuntimeError.new) + * rescue => x + * p x.cause + * end + * # => # + * + * If keyword argument +cause+ is not given, + * the cause is the value of $!. + * + * See {Cause}[rdoc-ref:exceptions.md@Cause]. + * + * In the alternate calling sequence, + * where argument +exception+ _not_ given, + * raises a new exception of the class given by $!, + * or of class RuntimeError if $! is +nil+: + * + * begin + * raise + * rescue => x + * p x + * end + * # => RuntimeError + * + * With argument +exception+ not given, + * argument +message+ and keyword argument +cause+ may be given, + * but argument +backtrace+ may not be given. */ static VALUE @@ -980,7 +1057,7 @@ rb_protect(VALUE (* proc) (VALUE), VALUE data, int *pstate) EC_PUSH_TAG(ec); if ((state = EC_EXEC_TAG()) == TAG_NONE) { - SAVE_ROOT_JMPBUF(rb_ec_thread_ptr(ec), result = (*proc) (data)); + result = (*proc)(data); } else { rb_vm_rewind_cfp(ec, cfp); @@ -994,16 +1071,10 @@ rb_protect(VALUE (* proc) (VALUE), VALUE data, int *pstate) VALUE rb_ensure(VALUE (*b_proc)(VALUE), VALUE data1, VALUE (*e_proc)(VALUE), VALUE data2) { - int state; + enum ruby_tag_type state; volatile VALUE result = Qnil; VALUE errinfo; rb_execution_context_t * volatile ec = GET_EC(); - rb_ensure_list_t ensure_list; - ensure_list.entry.marker = 0; - ensure_list.entry.e_proc = e_proc; - ensure_list.entry.data2 = data2; - ensure_list.next = ec->ensure_list; - ec->ensure_list = &ensure_list; EC_PUSH_TAG(ec); if ((state = EC_EXEC_TAG()) == TAG_NONE) { result = (*b_proc) (data1); @@ -1013,8 +1084,7 @@ rb_ensure(VALUE (*b_proc)(VALUE), VALUE data1, VALUE (*e_proc)(VALUE), VALUE dat if (!NIL_P(errinfo) && !RB_TYPE_P(errinfo, T_OBJECT)) { ec->errinfo = Qnil; } - ec->ensure_list=ensure_list.next; - (*ensure_list.entry.e_proc)(ensure_list.entry.data2); + (*e_proc)(data2); ec->errinfo = errinfo; if (state) EC_JUMP_TAG(ec, state); @@ -1128,6 +1198,8 @@ rb_mod_append_features(VALUE module, VALUE include) return module; } +static VALUE refinement_import_methods(int argc, VALUE *argv, VALUE refinement); + /* * call-seq: * include(module, ...) -> self @@ -1281,16 +1353,10 @@ rb_using_refinement(rb_cref_t *cref, VALUE klass, VALUE module) } superclass = refinement_superclass(superclass); c = iclass = rb_include_class_new(module, superclass); - RB_OBJ_WRITE(c, &RCLASS_REFINED_CLASS(c), klass); + RCLASS_SET_REFINED_CLASS(c, klass); - RCLASS_M_TBL(c) = RCLASS_M_TBL(module); + RCLASS_WRITE_M_TBL(c, RCLASS_M_TBL(module)); - module = RCLASS_SUPER(module); - while (module && module != klass) { - c = RCLASS_SET_SUPER(c, rb_include_class_new(module, RCLASS_SUPER(c))); - RB_OBJ_WRITE(c, &RCLASS_REFINED_CLASS(c), klass); - module = RCLASS_SUPER(module); - } rb_hash_aset(CREF_REFINEMENTS(cref), klass, iclass); } @@ -1344,11 +1410,24 @@ rb_using_module(const rb_cref_t *cref, VALUE module) rb_clear_all_refinement_method_cache(); } +void +rb_vm_using_module(VALUE module) +{ + rb_using_module(rb_vm_cref_replace_with_duplicated_cref(), module); +} + /* * call-seq: - * target -> class + * target -> class_or_module * * Return the class or module refined by the receiver. + * + * module M + * refine String do + * end + * end + * + * M.refinements[0].target # => String */ VALUE rb_refinement_module_get_refined_class(VALUE module) @@ -1359,19 +1438,6 @@ rb_refinement_module_get_refined_class(VALUE module) return rb_attr_get(module, id_refined_class); } -/* - * call-seq: - * refined_class -> class - * - * Return the class refined by the receiver. - */ -static VALUE -rb_refinement_refined_class(VALUE module) -{ - rb_warn_deprecated_to_remove("3.4", "Refinement#refined_class", "Refinement#target"); - return rb_refinement_module_get_refined_class(module); -} - static void add_activated_refinement(VALUE activated_refinements, VALUE klass, VALUE refinement) @@ -1390,43 +1456,24 @@ add_activated_refinement(VALUE activated_refinements, } superclass = refinement_superclass(superclass); c = iclass = rb_include_class_new(refinement, superclass); - RB_OBJ_WRITE(c, &RCLASS_REFINED_CLASS(c), klass); + RCLASS_SET_REFINED_CLASS(c, klass); refinement = RCLASS_SUPER(refinement); while (refinement && refinement != klass) { - c = RCLASS_SET_SUPER(c, rb_include_class_new(refinement, RCLASS_SUPER(c))); - RB_OBJ_WRITE(c, &RCLASS_REFINED_CLASS(c), klass); + c = rb_class_set_super(c, rb_include_class_new(refinement, RCLASS_SUPER(c))); + RCLASS_SET_REFINED_CLASS(c, klass); refinement = RCLASS_SUPER(refinement); } rb_hash_aset(activated_refinements, klass, iclass); } -/* - * call-seq: - * refine(mod) { block } -> module - * - * Refine mod in the receiver. - * - * Returns a module, where refined methods are defined. - */ - -static VALUE -rb_mod_refine(VALUE module, VALUE klass) +void +rb_refinement_setup(struct rb_refinements_data *data, VALUE module, VALUE klass) { VALUE refinement; ID id_refinements, id_activated_refinements, id_refined_class, id_defined_at; VALUE refinements, activated_refinements; - rb_thread_t *th = GET_THREAD(); - VALUE block_handler = rb_vm_frame_block_handler(th->ec->cfp); - if (block_handler == VM_BLOCK_HANDLER_NONE) { - rb_raise(rb_eArgError, "no block given"); - } - if (vm_block_handler_type(block_handler) != block_handler_type_iseq) { - rb_raise(rb_eArgError, "can't pass a Proc as a block to Module#refine"); - } - - ensure_class_or_module(klass); CONST_ID(id_refinements, "__refinements__"); refinements = rb_attr_get(module, id_refinements); if (NIL_P(refinements)) { @@ -1444,7 +1491,7 @@ rb_mod_refine(VALUE module, VALUE klass) if (NIL_P(refinement)) { VALUE superclass = refinement_superclass(klass); refinement = rb_refinement_new(); - RCLASS_SET_SUPER(refinement, superclass); + rb_class_set_super(refinement, superclass); RUBY_ASSERT(BUILTIN_TYPE(refinement) == T_MODULE); FL_SET(refinement, RMODULE_IS_REFINEMENT); CONST_ID(id_refined_class, "__refined_class__"); @@ -1454,8 +1501,41 @@ rb_mod_refine(VALUE module, VALUE klass) rb_hash_aset(refinements, klass, refinement); add_activated_refinement(activated_refinements, klass, refinement); } - rb_yield_refine_block(refinement, activated_refinements); - return refinement; + + data->refinement = refinement; + data->refinements = activated_refinements; +} + +/* + * call-seq: + * refine(mod) { block } -> module + * + * Refine mod in the receiver. + * + * Returns a module, where refined methods are defined. + */ + +static VALUE +rb_mod_refine(VALUE module, VALUE klass) +{ + /* module is the receiver of #refine, klass is a module to be refined (`mod` in the doc) */ + rb_thread_t *th = GET_THREAD(); + VALUE block_handler = rb_vm_frame_block_handler(th->ec->cfp); + struct rb_refinements_data data; + + if (block_handler == VM_BLOCK_HANDLER_NONE) { + rb_raise(rb_eArgError, "no block given"); + } + if (vm_block_handler_type(block_handler) != block_handler_type_iseq) { + rb_raise(rb_eArgError, "can't pass a Proc as a block to Module#refine"); + } + + ensure_class_or_module(klass); + + rb_refinement_setup(&data, module, klass); + + rb_yield_refine_block(data.refinement, data.refinements); + return data.refinement; } static void @@ -1501,7 +1581,7 @@ mod_using(VALUE self, VALUE module) * call-seq: * refinements -> array * - * Returns an array of modules defined within the receiver. + * Returns an array of +Refinement+ defined within the receiver. * * module A * refine Integer do @@ -1788,6 +1868,16 @@ rb_obj_extend(int argc, VALUE *argv, VALUE obj) return obj; } +VALUE +rb_top_main_class(const char *method) +{ + VALUE klass = GET_THREAD()->top_wrapper; + + if (!klass) return rb_cObject; + rb_warning("main.%s in the wrapped load is effective only in wrapper module", method); + return klass; +} + /* * call-seq: * include(module, ...) -> self @@ -1800,13 +1890,7 @@ rb_obj_extend(int argc, VALUE *argv, VALUE obj) static VALUE top_include(int argc, VALUE *argv, VALUE self) { - rb_thread_t *th = GET_THREAD(); - - if (th->top_wrapper) { - rb_warning("main.include in the wrapped load is effective only in wrapper module"); - return rb_mod_include(argc, argv, th->top_wrapper); - } - return rb_mod_include(argc, argv, rb_cObject); + return rb_mod_include(argc, argv, rb_top_main_class("include")); } /* @@ -1820,7 +1904,7 @@ top_include(int argc, VALUE *argv, VALUE self) static VALUE top_using(VALUE self, VALUE module) { - const rb_cref_t *cref = CREF_NEXT(rb_vm_cref());; + const rb_cref_t *cref = CREF_NEXT(rb_vm_cref()); rb_control_frame_t *prev_cfp = previous_frame(GET_EC()); rb_thread_t *th = GET_THREAD(); @@ -2013,7 +2097,7 @@ f_global_variables(VALUE _) * +Proc+ object) or block is executed whenever the variable * is assigned. The block or +Proc+ object receives the * variable's new value as a parameter. Also see - * Kernel::untrace_var. + * #untrace_var. * * trace_var :$_, proc {|v| puts "$_ is now '#{v}'" } * $_ = "hello" @@ -2081,7 +2165,6 @@ Init_eval(void) rb_undef_method(rb_cClass, "refine"); rb_define_private_method(rb_cRefinement, "import_methods", refinement_import_methods, -1); rb_define_method(rb_cRefinement, "target", rb_refinement_module_get_refined_class, 0); - rb_define_method(rb_cRefinement, "refined_class", rb_refinement_refined_class, 0); rb_undef_method(rb_cRefinement, "append_features"); rb_undef_method(rb_cRefinement, "prepend_features"); rb_undef_method(rb_cRefinement, "extend_object"); @@ -2110,3 +2193,21 @@ Init_eval(void) id_signo = rb_intern_const("signo"); id_status = rb_intern_const("status"); } + +int +rb_errno(void) +{ + return *rb_orig_errno_ptr(); +} + +void +rb_errno_set(int e) +{ + *rb_orig_errno_ptr() = e; +} + +int * +rb_errno_ptr(void) +{ + return rb_orig_errno_ptr(); +} diff --git a/eval_error.c b/eval_error.c index bdce295f6ec5b3..f3d05a1043fea7 100644 --- a/eval_error.c +++ b/eval_error.c @@ -47,7 +47,7 @@ error_pos_str(void) return rb_sprintf("%"PRIsVALUE": ", sourcefile); } else if ((caller_name = rb_frame_callee()) != 0) { - return rb_sprintf("%"PRIsVALUE":%d:in `%"PRIsVALUE"': ", + return rb_sprintf("%"PRIsVALUE":%d:in '%"PRIsVALUE"': ", sourcefile, sourceline, rb_id2str(caller_name)); } @@ -125,7 +125,7 @@ print_errinfo(const VALUE eclass, const VALUE errat, const VALUE emesg, const VA } VALUE -rb_decorate_message(const VALUE eclass, const VALUE emesg, int highlight) +rb_decorate_message(const VALUE eclass, VALUE emesg, int highlight) { const char *einfo = ""; long elen = 0; @@ -210,6 +210,8 @@ rb_decorate_message(const VALUE eclass, const VALUE emesg, int highlight) } } + RB_GC_GUARD(emesg); + return str; } @@ -390,7 +392,7 @@ rb_ec_error_print(rb_execution_context_t *volatile ec, volatile VALUE errinfo) rb_ec_error_print_detailed(ec, errinfo, Qnil, Qundef); } -#define undef_mesg_for(v, k) rb_fstring_lit("undefined"v" method `%1$s' for "k" `%2$s'") +#define undef_mesg_for(v, k) rb_fstring_lit("undefined"v" method '%1$s' for "k" '%2$s'") #define undef_mesg(v) ( \ is_mod ? \ undef_mesg_for(v, "module") : \ @@ -418,7 +420,7 @@ rb_print_undef_str(VALUE klass, VALUE name) rb_name_err_raise_str(undef_mesg(""), klass, name); } -#define inaccessible_mesg_for(v, k) rb_fstring_lit("method `%1$s' for "k" `%2$s' is "v) +#define inaccessible_mesg_for(v, k) rb_fstring_lit("method '%1$s' for "k" '%2$s' is "v) #define inaccessible_mesg(v) ( \ is_mod ? \ inaccessible_mesg_for(v, "module") : \ diff --git a/eval_intern.h b/eval_intern.h index 778b63e0ea61bd..2c244aa5e09b40 100644 --- a/eval_intern.h +++ b/eval_intern.h @@ -95,14 +95,6 @@ extern int select_large_fdset(int, fd_set *, fd_set *, fd_set *, struct timeval #include - -#define SAVE_ROOT_JMPBUF(th, stmt) do \ - if (true) { \ - stmt; \ - } \ - else if (th) { /* suppress unused-variable warning */ \ - } while (0) - #define EC_PUSH_TAG(ec) do { \ rb_execution_context_t * const _ec = (ec); \ struct rb_vm_tag _tag; \ @@ -110,9 +102,11 @@ extern int select_large_fdset(int, fd_set *, fd_set *, fd_set *, struct timeval _tag.tag = Qundef; \ _tag.prev = _ec->tag; \ _tag.lock_rec = rb_ec_vm_lock_rec(_ec); \ + rb_vm_tag_jmpbuf_init(&_tag.buf); \ #define EC_POP_TAG() \ _ec->tag = _tag.prev; \ + rb_vm_tag_jmpbuf_deinit(&_tag.buf); \ } while (0) #define EC_TMPPOP_TAG() \ @@ -151,7 +145,8 @@ rb_ec_tag_state(const rb_execution_context_t *ec) enum ruby_tag_type state = tag->state; tag->state = TAG_NONE; rb_ec_vm_lock_rec_check(ec, tag->lock_rec); - RBIMPL_ASSUME(state != TAG_NONE); + RBIMPL_ASSUME(state > TAG_NONE); + RBIMPL_ASSUME(state <= TAG_FATAL); return state; } @@ -159,9 +154,9 @@ NORETURN(static inline void rb_ec_tag_jump(const rb_execution_context_t *ec, enu static inline void rb_ec_tag_jump(const rb_execution_context_t *ec, enum ruby_tag_type st) { - RUBY_ASSERT(st != TAG_NONE); + RUBY_ASSERT(st > TAG_NONE && st <= TAG_FATAL, ": Invalid tag jump: %d", (int)st); ec->tag->state = st; - ruby_longjmp(ec->tag->buf, 1); + ruby_longjmp(RB_VM_TAG_JMPBUF_GET(ec->tag->buf), 1); } /* @@ -169,7 +164,7 @@ rb_ec_tag_jump(const rb_execution_context_t *ec, enum ruby_tag_type st) [ISO/IEC 9899:1999] 7.13.1.1 */ #define EC_EXEC_TAG() \ - (UNLIKELY(ruby_setjmp(_tag.buf)) ? rb_ec_tag_state(VAR_FROM_MEMORY(_ec)) : (EC_REPUSH_TAG(), 0)) + (UNLIKELY(ruby_setjmp(RB_VM_TAG_JMPBUF_GET(_tag.buf))) ? rb_ec_tag_state(VAR_FROM_MEMORY(_ec)) : (EC_REPUSH_TAG(), 0)) #define EC_JUMP_TAG(ec, st) rb_ec_tag_jump(ec, st) @@ -295,16 +290,19 @@ NORETURN(void rb_print_undef(VALUE, ID, rb_method_visibility_t)); NORETURN(void rb_print_undef_str(VALUE, VALUE)); NORETURN(void rb_print_inaccessible(VALUE, ID, rb_method_visibility_t)); NORETURN(void rb_vm_localjump_error(const char *,VALUE, int)); -NORETURN(void rb_vm_jump_tag_but_local_jump(int)); +NORETURN(void rb_vm_jump_tag_but_local_jump(enum ruby_tag_type)); -VALUE rb_vm_make_jump_tag_but_local_jump(int state, VALUE val); +VALUE rb_vm_make_jump_tag_but_local_jump(enum ruby_tag_type state, VALUE val); rb_cref_t *rb_vm_cref(void); rb_cref_t *rb_vm_cref_replace_with_duplicated_cref(void); VALUE rb_vm_call_cfunc(VALUE recv, VALUE (*func)(VALUE), VALUE arg, VALUE block_handler, VALUE filename); +VALUE rb_vm_call_cfunc2(VALUE recv, VALUE (*func)(VALUE, VALUE), VALUE arg1, VALUE arg2, VALUE block_handler, VALUE filename); void rb_vm_set_progname(VALUE filename); VALUE rb_vm_cbase(void); /* vm_backtrace.c */ +#define RUBY_BACKTRACE_START 0 +#define RUBY_ALL_BACKTRACE_LINES -1 VALUE rb_ec_backtrace_object(const rb_execution_context_t *ec); VALUE rb_ec_backtrace_str_ary(const rb_execution_context_t *ec, long lev, long n); VALUE rb_ec_backtrace_location_ary(const rb_execution_context_t *ec, long lev, long n, bool skip_internal); @@ -326,16 +324,4 @@ rb_char_next(const char *p) # endif #endif -#if defined DOSISH || defined __CYGWIN__ -static inline void -translit_char(char *p, int from, int to) -{ - while (*p) { - if ((unsigned char)*p == from) - *p = to; - p = CharNext(p); - } -} -#endif - #endif /* RUBY_EVAL_INTERN_H */ diff --git a/eval_jump.c b/eval_jump.c index e8e74f4e70050a..7593a35e360152 100644 --- a/eval_jump.c +++ b/eval_jump.c @@ -112,21 +112,21 @@ rb_ec_exec_end_proc(rb_execution_context_t * ec) { enum ruby_tag_type state; volatile VALUE errinfo = ec->errinfo; - - EC_PUSH_TAG(ec); - if ((state = EC_EXEC_TAG()) == TAG_NONE) { - again: - exec_end_procs_chain(&ephemeral_end_procs, &ec->errinfo); - exec_end_procs_chain(&end_procs, &ec->errinfo); - } - else { - EC_TMPPOP_TAG(); - error_handle(ec, ec->errinfo, state); - if (!NIL_P(ec->errinfo)) errinfo = ec->errinfo; - EC_REPUSH_TAG(); - goto again; + volatile bool finished = false; + + while (!finished) { + EC_PUSH_TAG(ec); + if ((state = EC_EXEC_TAG()) == TAG_NONE) { + exec_end_procs_chain(&ephemeral_end_procs, &ec->errinfo); + exec_end_procs_chain(&end_procs, &ec->errinfo); + finished = true; + } + EC_POP_TAG(); + if (state != TAG_NONE) { + error_handle(ec, ec->errinfo, state); + if (!NIL_P(ec->errinfo)) errinfo = ec->errinfo; + } } - EC_POP_TAG(); ec->errinfo = errinfo; } diff --git a/ext/-test-/RUBY_ALIGNOF/depend b/ext/-test-/RUBY_ALIGNOF/depend index 3011b637e5366e..103d20b33c8de5 100644 --- a/ext/-test-/RUBY_ALIGNOF/depend +++ b/ext/-test-/RUBY_ALIGNOF/depend @@ -128,6 +128,7 @@ c.o: $(hdrdir)/ruby/internal/intern/re.h c.o: $(hdrdir)/ruby/internal/intern/ruby.h c.o: $(hdrdir)/ruby/internal/intern/select.h c.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +c.o: $(hdrdir)/ruby/internal/intern/set.h c.o: $(hdrdir)/ruby/internal/intern/signal.h c.o: $(hdrdir)/ruby/internal/intern/sprintf.h c.o: $(hdrdir)/ruby/internal/intern/string.h @@ -147,6 +148,7 @@ c.o: $(hdrdir)/ruby/internal/special_consts.h c.o: $(hdrdir)/ruby/internal/static_assert.h c.o: $(hdrdir)/ruby/internal/stdalign.h c.o: $(hdrdir)/ruby/internal/stdbool.h +c.o: $(hdrdir)/ruby/internal/stdckdint.h c.o: $(hdrdir)/ruby/internal/symbol.h c.o: $(hdrdir)/ruby/internal/value.h c.o: $(hdrdir)/ruby/internal/value_type.h diff --git a/ext/-test-/abi/depend b/ext/-test-/abi/depend new file mode 100644 index 00000000000000..716a7b13568470 --- /dev/null +++ b/ext/-test-/abi/depend @@ -0,0 +1,3 @@ +# AUTOGENERATED DEPENDENCIES START +abi.o: abi.c +# AUTOGENERATED DEPENDENCIES END diff --git a/ext/-test-/arith_seq/beg_len_step/depend b/ext/-test-/arith_seq/beg_len_step/depend index dc807eaa992ae4..098c8ff1f0f0fb 100644 --- a/ext/-test-/arith_seq/beg_len_step/depend +++ b/ext/-test-/arith_seq/beg_len_step/depend @@ -127,6 +127,7 @@ beg_len_step.o: $(hdrdir)/ruby/internal/intern/re.h beg_len_step.o: $(hdrdir)/ruby/internal/intern/ruby.h beg_len_step.o: $(hdrdir)/ruby/internal/intern/select.h beg_len_step.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +beg_len_step.o: $(hdrdir)/ruby/internal/intern/set.h beg_len_step.o: $(hdrdir)/ruby/internal/intern/signal.h beg_len_step.o: $(hdrdir)/ruby/internal/intern/sprintf.h beg_len_step.o: $(hdrdir)/ruby/internal/intern/string.h @@ -146,6 +147,7 @@ beg_len_step.o: $(hdrdir)/ruby/internal/special_consts.h beg_len_step.o: $(hdrdir)/ruby/internal/static_assert.h beg_len_step.o: $(hdrdir)/ruby/internal/stdalign.h beg_len_step.o: $(hdrdir)/ruby/internal/stdbool.h +beg_len_step.o: $(hdrdir)/ruby/internal/stdckdint.h beg_len_step.o: $(hdrdir)/ruby/internal/symbol.h beg_len_step.o: $(hdrdir)/ruby/internal/value.h beg_len_step.o: $(hdrdir)/ruby/internal/value_type.h diff --git a/ext/-test-/arith_seq/extract/depend b/ext/-test-/arith_seq/extract/depend index 231736b277ddf6..5c07cea4b4b1dd 100644 --- a/ext/-test-/arith_seq/extract/depend +++ b/ext/-test-/arith_seq/extract/depend @@ -127,6 +127,7 @@ extract.o: $(hdrdir)/ruby/internal/intern/re.h extract.o: $(hdrdir)/ruby/internal/intern/ruby.h extract.o: $(hdrdir)/ruby/internal/intern/select.h extract.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +extract.o: $(hdrdir)/ruby/internal/intern/set.h extract.o: $(hdrdir)/ruby/internal/intern/signal.h extract.o: $(hdrdir)/ruby/internal/intern/sprintf.h extract.o: $(hdrdir)/ruby/internal/intern/string.h @@ -146,6 +147,7 @@ extract.o: $(hdrdir)/ruby/internal/special_consts.h extract.o: $(hdrdir)/ruby/internal/static_assert.h extract.o: $(hdrdir)/ruby/internal/stdalign.h extract.o: $(hdrdir)/ruby/internal/stdbool.h +extract.o: $(hdrdir)/ruby/internal/stdckdint.h extract.o: $(hdrdir)/ruby/internal/symbol.h extract.o: $(hdrdir)/ruby/internal/value.h extract.o: $(hdrdir)/ruby/internal/value_type.h diff --git a/ext/-test-/array/concat/depend b/ext/-test-/array/concat/depend index d66e7a540f311e..8edf45465f707d 100644 --- a/ext/-test-/array/concat/depend +++ b/ext/-test-/array/concat/depend @@ -128,6 +128,7 @@ to_ary_concat.o: $(hdrdir)/ruby/internal/intern/re.h to_ary_concat.o: $(hdrdir)/ruby/internal/intern/ruby.h to_ary_concat.o: $(hdrdir)/ruby/internal/intern/select.h to_ary_concat.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +to_ary_concat.o: $(hdrdir)/ruby/internal/intern/set.h to_ary_concat.o: $(hdrdir)/ruby/internal/intern/signal.h to_ary_concat.o: $(hdrdir)/ruby/internal/intern/sprintf.h to_ary_concat.o: $(hdrdir)/ruby/internal/intern/string.h @@ -147,6 +148,7 @@ to_ary_concat.o: $(hdrdir)/ruby/internal/special_consts.h to_ary_concat.o: $(hdrdir)/ruby/internal/static_assert.h to_ary_concat.o: $(hdrdir)/ruby/internal/stdalign.h to_ary_concat.o: $(hdrdir)/ruby/internal/stdbool.h +to_ary_concat.o: $(hdrdir)/ruby/internal/stdckdint.h to_ary_concat.o: $(hdrdir)/ruby/internal/symbol.h to_ary_concat.o: $(hdrdir)/ruby/internal/value.h to_ary_concat.o: $(hdrdir)/ruby/internal/value_type.h diff --git a/ext/-test-/array/resize/depend b/ext/-test-/array/resize/depend index a9c02b3db2cddd..e6a228b43d779c 100644 --- a/ext/-test-/array/resize/depend +++ b/ext/-test-/array/resize/depend @@ -127,6 +127,7 @@ resize.o: $(hdrdir)/ruby/internal/intern/re.h resize.o: $(hdrdir)/ruby/internal/intern/ruby.h resize.o: $(hdrdir)/ruby/internal/intern/select.h resize.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +resize.o: $(hdrdir)/ruby/internal/intern/set.h resize.o: $(hdrdir)/ruby/internal/intern/signal.h resize.o: $(hdrdir)/ruby/internal/intern/sprintf.h resize.o: $(hdrdir)/ruby/internal/intern/string.h @@ -146,6 +147,7 @@ resize.o: $(hdrdir)/ruby/internal/special_consts.h resize.o: $(hdrdir)/ruby/internal/static_assert.h resize.o: $(hdrdir)/ruby/internal/stdalign.h resize.o: $(hdrdir)/ruby/internal/stdbool.h +resize.o: $(hdrdir)/ruby/internal/stdckdint.h resize.o: $(hdrdir)/ruby/internal/symbol.h resize.o: $(hdrdir)/ruby/internal/value.h resize.o: $(hdrdir)/ruby/internal/value_type.h diff --git a/ext/-test-/asan/asan.c b/ext/-test-/asan/asan.c new file mode 100644 index 00000000000000..45b6253fdac8c8 --- /dev/null +++ b/ext/-test-/asan/asan.c @@ -0,0 +1,24 @@ +#include "ruby/ruby.h" + +static VALUE +asan_enabled_p(VALUE self) +{ +#if defined(__has_feature) + /* clang uses __has_feature for determining asan */ + return __has_feature(address_sanitizer) ? Qtrue : Qfalse; +#elif defined(__SANITIZE_ADDRESS__) + /* GCC sets __SANITIZE_ADDRESS__ for determining asan */ + return Qtrue; +#else + return Qfalse; +#endif +} + +void +Init_asan(void) +{ + VALUE m = rb_define_module("Test"); + VALUE c = rb_define_class_under(m, "ASAN", rb_cObject); + rb_define_singleton_method(c, "enabled?", asan_enabled_p, 0); +} + diff --git a/ext/-test-/asan/depend b/ext/-test-/asan/depend new file mode 100644 index 00000000000000..93cdc739ec63b7 --- /dev/null +++ b/ext/-test-/asan/depend @@ -0,0 +1,162 @@ +# AUTOGENERATED DEPENDENCIES START +asan.o: $(RUBY_EXTCONF_H) +asan.o: $(arch_hdrdir)/ruby/config.h +asan.o: $(hdrdir)/ruby/assert.h +asan.o: $(hdrdir)/ruby/backward.h +asan.o: $(hdrdir)/ruby/backward/2/assume.h +asan.o: $(hdrdir)/ruby/backward/2/attributes.h +asan.o: $(hdrdir)/ruby/backward/2/bool.h +asan.o: $(hdrdir)/ruby/backward/2/inttypes.h +asan.o: $(hdrdir)/ruby/backward/2/limits.h +asan.o: $(hdrdir)/ruby/backward/2/long_long.h +asan.o: $(hdrdir)/ruby/backward/2/stdalign.h +asan.o: $(hdrdir)/ruby/backward/2/stdarg.h +asan.o: $(hdrdir)/ruby/defines.h +asan.o: $(hdrdir)/ruby/intern.h +asan.o: $(hdrdir)/ruby/internal/abi.h +asan.o: $(hdrdir)/ruby/internal/anyargs.h +asan.o: $(hdrdir)/ruby/internal/arithmetic.h +asan.o: $(hdrdir)/ruby/internal/arithmetic/char.h +asan.o: $(hdrdir)/ruby/internal/arithmetic/double.h +asan.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +asan.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +asan.o: $(hdrdir)/ruby/internal/arithmetic/int.h +asan.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +asan.o: $(hdrdir)/ruby/internal/arithmetic/long.h +asan.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +asan.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +asan.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +asan.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +asan.o: $(hdrdir)/ruby/internal/arithmetic/short.h +asan.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +asan.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +asan.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +asan.o: $(hdrdir)/ruby/internal/assume.h +asan.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +asan.o: $(hdrdir)/ruby/internal/attr/artificial.h +asan.o: $(hdrdir)/ruby/internal/attr/cold.h +asan.o: $(hdrdir)/ruby/internal/attr/const.h +asan.o: $(hdrdir)/ruby/internal/attr/constexpr.h +asan.o: $(hdrdir)/ruby/internal/attr/deprecated.h +asan.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +asan.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +asan.o: $(hdrdir)/ruby/internal/attr/error.h +asan.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +asan.o: $(hdrdir)/ruby/internal/attr/forceinline.h +asan.o: $(hdrdir)/ruby/internal/attr/format.h +asan.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +asan.o: $(hdrdir)/ruby/internal/attr/noalias.h +asan.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +asan.o: $(hdrdir)/ruby/internal/attr/noexcept.h +asan.o: $(hdrdir)/ruby/internal/attr/noinline.h +asan.o: $(hdrdir)/ruby/internal/attr/nonnull.h +asan.o: $(hdrdir)/ruby/internal/attr/noreturn.h +asan.o: $(hdrdir)/ruby/internal/attr/packed_struct.h +asan.o: $(hdrdir)/ruby/internal/attr/pure.h +asan.o: $(hdrdir)/ruby/internal/attr/restrict.h +asan.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +asan.o: $(hdrdir)/ruby/internal/attr/warning.h +asan.o: $(hdrdir)/ruby/internal/attr/weakref.h +asan.o: $(hdrdir)/ruby/internal/cast.h +asan.o: $(hdrdir)/ruby/internal/compiler_is.h +asan.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +asan.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +asan.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +asan.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +asan.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +asan.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +asan.o: $(hdrdir)/ruby/internal/compiler_since.h +asan.o: $(hdrdir)/ruby/internal/config.h +asan.o: $(hdrdir)/ruby/internal/constant_p.h +asan.o: $(hdrdir)/ruby/internal/core.h +asan.o: $(hdrdir)/ruby/internal/core/rarray.h +asan.o: $(hdrdir)/ruby/internal/core/rbasic.h +asan.o: $(hdrdir)/ruby/internal/core/rbignum.h +asan.o: $(hdrdir)/ruby/internal/core/rclass.h +asan.o: $(hdrdir)/ruby/internal/core/rdata.h +asan.o: $(hdrdir)/ruby/internal/core/rfile.h +asan.o: $(hdrdir)/ruby/internal/core/rhash.h +asan.o: $(hdrdir)/ruby/internal/core/robject.h +asan.o: $(hdrdir)/ruby/internal/core/rregexp.h +asan.o: $(hdrdir)/ruby/internal/core/rstring.h +asan.o: $(hdrdir)/ruby/internal/core/rstruct.h +asan.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +asan.o: $(hdrdir)/ruby/internal/ctype.h +asan.o: $(hdrdir)/ruby/internal/dllexport.h +asan.o: $(hdrdir)/ruby/internal/dosish.h +asan.o: $(hdrdir)/ruby/internal/error.h +asan.o: $(hdrdir)/ruby/internal/eval.h +asan.o: $(hdrdir)/ruby/internal/event.h +asan.o: $(hdrdir)/ruby/internal/fl_type.h +asan.o: $(hdrdir)/ruby/internal/gc.h +asan.o: $(hdrdir)/ruby/internal/glob.h +asan.o: $(hdrdir)/ruby/internal/globals.h +asan.o: $(hdrdir)/ruby/internal/has/attribute.h +asan.o: $(hdrdir)/ruby/internal/has/builtin.h +asan.o: $(hdrdir)/ruby/internal/has/c_attribute.h +asan.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +asan.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +asan.o: $(hdrdir)/ruby/internal/has/extension.h +asan.o: $(hdrdir)/ruby/internal/has/feature.h +asan.o: $(hdrdir)/ruby/internal/has/warning.h +asan.o: $(hdrdir)/ruby/internal/intern/array.h +asan.o: $(hdrdir)/ruby/internal/intern/bignum.h +asan.o: $(hdrdir)/ruby/internal/intern/class.h +asan.o: $(hdrdir)/ruby/internal/intern/compar.h +asan.o: $(hdrdir)/ruby/internal/intern/complex.h +asan.o: $(hdrdir)/ruby/internal/intern/cont.h +asan.o: $(hdrdir)/ruby/internal/intern/dir.h +asan.o: $(hdrdir)/ruby/internal/intern/enum.h +asan.o: $(hdrdir)/ruby/internal/intern/enumerator.h +asan.o: $(hdrdir)/ruby/internal/intern/error.h +asan.o: $(hdrdir)/ruby/internal/intern/eval.h +asan.o: $(hdrdir)/ruby/internal/intern/file.h +asan.o: $(hdrdir)/ruby/internal/intern/hash.h +asan.o: $(hdrdir)/ruby/internal/intern/io.h +asan.o: $(hdrdir)/ruby/internal/intern/load.h +asan.o: $(hdrdir)/ruby/internal/intern/marshal.h +asan.o: $(hdrdir)/ruby/internal/intern/numeric.h +asan.o: $(hdrdir)/ruby/internal/intern/object.h +asan.o: $(hdrdir)/ruby/internal/intern/parse.h +asan.o: $(hdrdir)/ruby/internal/intern/proc.h +asan.o: $(hdrdir)/ruby/internal/intern/process.h +asan.o: $(hdrdir)/ruby/internal/intern/random.h +asan.o: $(hdrdir)/ruby/internal/intern/range.h +asan.o: $(hdrdir)/ruby/internal/intern/rational.h +asan.o: $(hdrdir)/ruby/internal/intern/re.h +asan.o: $(hdrdir)/ruby/internal/intern/ruby.h +asan.o: $(hdrdir)/ruby/internal/intern/select.h +asan.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +asan.o: $(hdrdir)/ruby/internal/intern/set.h +asan.o: $(hdrdir)/ruby/internal/intern/signal.h +asan.o: $(hdrdir)/ruby/internal/intern/sprintf.h +asan.o: $(hdrdir)/ruby/internal/intern/string.h +asan.o: $(hdrdir)/ruby/internal/intern/struct.h +asan.o: $(hdrdir)/ruby/internal/intern/thread.h +asan.o: $(hdrdir)/ruby/internal/intern/time.h +asan.o: $(hdrdir)/ruby/internal/intern/variable.h +asan.o: $(hdrdir)/ruby/internal/intern/vm.h +asan.o: $(hdrdir)/ruby/internal/interpreter.h +asan.o: $(hdrdir)/ruby/internal/iterator.h +asan.o: $(hdrdir)/ruby/internal/memory.h +asan.o: $(hdrdir)/ruby/internal/method.h +asan.o: $(hdrdir)/ruby/internal/module.h +asan.o: $(hdrdir)/ruby/internal/newobj.h +asan.o: $(hdrdir)/ruby/internal/scan_args.h +asan.o: $(hdrdir)/ruby/internal/special_consts.h +asan.o: $(hdrdir)/ruby/internal/static_assert.h +asan.o: $(hdrdir)/ruby/internal/stdalign.h +asan.o: $(hdrdir)/ruby/internal/stdbool.h +asan.o: $(hdrdir)/ruby/internal/stdckdint.h +asan.o: $(hdrdir)/ruby/internal/symbol.h +asan.o: $(hdrdir)/ruby/internal/value.h +asan.o: $(hdrdir)/ruby/internal/value_type.h +asan.o: $(hdrdir)/ruby/internal/variable.h +asan.o: $(hdrdir)/ruby/internal/warning_push.h +asan.o: $(hdrdir)/ruby/internal/xmalloc.h +asan.o: $(hdrdir)/ruby/missing.h +asan.o: $(hdrdir)/ruby/ruby.h +asan.o: $(hdrdir)/ruby/st.h +asan.o: $(hdrdir)/ruby/subst.h +asan.o: asan.c +# AUTOGENERATED DEPENDENCIES END diff --git a/ext/-test-/asan/extconf.rb b/ext/-test-/asan/extconf.rb new file mode 100644 index 00000000000000..ec02742b8145e4 --- /dev/null +++ b/ext/-test-/asan/extconf.rb @@ -0,0 +1,2 @@ +require 'mkmf' +create_makefile('-test-/asan') diff --git a/ext/-test-/bignum/depend b/ext/-test-/bignum/depend index d4392bb6a12996..049f0c7b520970 100644 --- a/ext/-test-/bignum/depend +++ b/ext/-test-/bignum/depend @@ -127,6 +127,7 @@ big2str.o: $(hdrdir)/ruby/internal/intern/re.h big2str.o: $(hdrdir)/ruby/internal/intern/ruby.h big2str.o: $(hdrdir)/ruby/internal/intern/select.h big2str.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +big2str.o: $(hdrdir)/ruby/internal/intern/set.h big2str.o: $(hdrdir)/ruby/internal/intern/signal.h big2str.o: $(hdrdir)/ruby/internal/intern/sprintf.h big2str.o: $(hdrdir)/ruby/internal/intern/string.h @@ -146,6 +147,7 @@ big2str.o: $(hdrdir)/ruby/internal/special_consts.h big2str.o: $(hdrdir)/ruby/internal/static_assert.h big2str.o: $(hdrdir)/ruby/internal/stdalign.h big2str.o: $(hdrdir)/ruby/internal/stdbool.h +big2str.o: $(hdrdir)/ruby/internal/stdckdint.h big2str.o: $(hdrdir)/ruby/internal/symbol.h big2str.o: $(hdrdir)/ruby/internal/value.h big2str.o: $(hdrdir)/ruby/internal/value_type.h @@ -286,6 +288,7 @@ bigzero.o: $(hdrdir)/ruby/internal/intern/re.h bigzero.o: $(hdrdir)/ruby/internal/intern/ruby.h bigzero.o: $(hdrdir)/ruby/internal/intern/select.h bigzero.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +bigzero.o: $(hdrdir)/ruby/internal/intern/set.h bigzero.o: $(hdrdir)/ruby/internal/intern/signal.h bigzero.o: $(hdrdir)/ruby/internal/intern/sprintf.h bigzero.o: $(hdrdir)/ruby/internal/intern/string.h @@ -305,6 +308,7 @@ bigzero.o: $(hdrdir)/ruby/internal/special_consts.h bigzero.o: $(hdrdir)/ruby/internal/static_assert.h bigzero.o: $(hdrdir)/ruby/internal/stdalign.h bigzero.o: $(hdrdir)/ruby/internal/stdbool.h +bigzero.o: $(hdrdir)/ruby/internal/stdckdint.h bigzero.o: $(hdrdir)/ruby/internal/symbol.h bigzero.o: $(hdrdir)/ruby/internal/value.h bigzero.o: $(hdrdir)/ruby/internal/value_type.h @@ -445,6 +449,7 @@ div.o: $(hdrdir)/ruby/internal/intern/re.h div.o: $(hdrdir)/ruby/internal/intern/ruby.h div.o: $(hdrdir)/ruby/internal/intern/select.h div.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +div.o: $(hdrdir)/ruby/internal/intern/set.h div.o: $(hdrdir)/ruby/internal/intern/signal.h div.o: $(hdrdir)/ruby/internal/intern/sprintf.h div.o: $(hdrdir)/ruby/internal/intern/string.h @@ -464,6 +469,7 @@ div.o: $(hdrdir)/ruby/internal/special_consts.h div.o: $(hdrdir)/ruby/internal/static_assert.h div.o: $(hdrdir)/ruby/internal/stdalign.h div.o: $(hdrdir)/ruby/internal/stdbool.h +div.o: $(hdrdir)/ruby/internal/stdckdint.h div.o: $(hdrdir)/ruby/internal/symbol.h div.o: $(hdrdir)/ruby/internal/value.h div.o: $(hdrdir)/ruby/internal/value_type.h @@ -605,6 +611,7 @@ init.o: $(hdrdir)/ruby/internal/intern/re.h init.o: $(hdrdir)/ruby/internal/intern/ruby.h init.o: $(hdrdir)/ruby/internal/intern/select.h init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +init.o: $(hdrdir)/ruby/internal/intern/set.h init.o: $(hdrdir)/ruby/internal/intern/signal.h init.o: $(hdrdir)/ruby/internal/intern/sprintf.h init.o: $(hdrdir)/ruby/internal/intern/string.h @@ -624,6 +631,7 @@ init.o: $(hdrdir)/ruby/internal/special_consts.h init.o: $(hdrdir)/ruby/internal/static_assert.h init.o: $(hdrdir)/ruby/internal/stdalign.h init.o: $(hdrdir)/ruby/internal/stdbool.h +init.o: $(hdrdir)/ruby/internal/stdckdint.h init.o: $(hdrdir)/ruby/internal/symbol.h init.o: $(hdrdir)/ruby/internal/value.h init.o: $(hdrdir)/ruby/internal/value_type.h @@ -763,6 +771,7 @@ intpack.o: $(hdrdir)/ruby/internal/intern/re.h intpack.o: $(hdrdir)/ruby/internal/intern/ruby.h intpack.o: $(hdrdir)/ruby/internal/intern/select.h intpack.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +intpack.o: $(hdrdir)/ruby/internal/intern/set.h intpack.o: $(hdrdir)/ruby/internal/intern/signal.h intpack.o: $(hdrdir)/ruby/internal/intern/sprintf.h intpack.o: $(hdrdir)/ruby/internal/intern/string.h @@ -782,6 +791,7 @@ intpack.o: $(hdrdir)/ruby/internal/special_consts.h intpack.o: $(hdrdir)/ruby/internal/static_assert.h intpack.o: $(hdrdir)/ruby/internal/stdalign.h intpack.o: $(hdrdir)/ruby/internal/stdbool.h +intpack.o: $(hdrdir)/ruby/internal/stdckdint.h intpack.o: $(hdrdir)/ruby/internal/symbol.h intpack.o: $(hdrdir)/ruby/internal/value.h intpack.o: $(hdrdir)/ruby/internal/value_type.h @@ -922,6 +932,7 @@ mul.o: $(hdrdir)/ruby/internal/intern/re.h mul.o: $(hdrdir)/ruby/internal/intern/ruby.h mul.o: $(hdrdir)/ruby/internal/intern/select.h mul.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +mul.o: $(hdrdir)/ruby/internal/intern/set.h mul.o: $(hdrdir)/ruby/internal/intern/signal.h mul.o: $(hdrdir)/ruby/internal/intern/sprintf.h mul.o: $(hdrdir)/ruby/internal/intern/string.h @@ -941,6 +952,7 @@ mul.o: $(hdrdir)/ruby/internal/special_consts.h mul.o: $(hdrdir)/ruby/internal/static_assert.h mul.o: $(hdrdir)/ruby/internal/stdalign.h mul.o: $(hdrdir)/ruby/internal/stdbool.h +mul.o: $(hdrdir)/ruby/internal/stdckdint.h mul.o: $(hdrdir)/ruby/internal/symbol.h mul.o: $(hdrdir)/ruby/internal/value.h mul.o: $(hdrdir)/ruby/internal/value_type.h @@ -1081,6 +1093,7 @@ str2big.o: $(hdrdir)/ruby/internal/intern/re.h str2big.o: $(hdrdir)/ruby/internal/intern/ruby.h str2big.o: $(hdrdir)/ruby/internal/intern/select.h str2big.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +str2big.o: $(hdrdir)/ruby/internal/intern/set.h str2big.o: $(hdrdir)/ruby/internal/intern/signal.h str2big.o: $(hdrdir)/ruby/internal/intern/sprintf.h str2big.o: $(hdrdir)/ruby/internal/intern/string.h @@ -1100,6 +1113,7 @@ str2big.o: $(hdrdir)/ruby/internal/special_consts.h str2big.o: $(hdrdir)/ruby/internal/static_assert.h str2big.o: $(hdrdir)/ruby/internal/stdalign.h str2big.o: $(hdrdir)/ruby/internal/stdbool.h +str2big.o: $(hdrdir)/ruby/internal/stdckdint.h str2big.o: $(hdrdir)/ruby/internal/symbol.h str2big.o: $(hdrdir)/ruby/internal/value.h str2big.o: $(hdrdir)/ruby/internal/value_type.h diff --git a/ext/-test-/bug-14834/bug-14384.c b/ext/-test-/bug-14834/bug-14384.c deleted file mode 100644 index 3a16a2d222c832..00000000000000 --- a/ext/-test-/bug-14834/bug-14384.c +++ /dev/null @@ -1,39 +0,0 @@ -#include -#include - -#ifndef MAYBE_UNUSED -# define MAYBE_UNUSED(x) x -#endif - -static NOINLINE(VALUE f(VALUE)); -static NOINLINE(void g(VALUE, void*)); -extern NOINLINE(void Init_bug_14384(void)); - -void -Init_bug_14834(void) -{ - VALUE q = rb_define_module("Bug"); - rb_define_module_function(q, "bug_14834", f, 0); -} - -VALUE -f(VALUE q) -{ - int w[] = { 0, 1024 }; - VALUE e = rb_tracepoint_new(Qnil, RUBY_INTERNAL_EVENT_NEWOBJ, g, w); - - rb_tracepoint_enable(e); - return rb_ensure(rb_yield, q, rb_tracepoint_disable, e); -} - -void -g(MAYBE_UNUSED(VALUE q), void* w) -{ - const int *e = (const int *)w; - const int r = *e++; - const int t = *e++; - VALUE *y = ALLOCA_N(VALUE, t); - int *u = ALLOCA_N(int, t); - - rb_profile_frames(r, t, y, u); -} diff --git a/ext/-test-/bug-14834/bug-14834.c b/ext/-test-/bug-14834/bug-14834.c new file mode 100644 index 00000000000000..af2070d303ff38 --- /dev/null +++ b/ext/-test-/bug-14834/bug-14834.c @@ -0,0 +1,39 @@ +#include +#include + +#ifndef MAYBE_UNUSED +# define MAYBE_UNUSED(x) x +#endif + +static NOINLINE(VALUE f(VALUE)); +static NOINLINE(void g(VALUE, void*)); +extern NOINLINE(void Init_bug_14834(void)); + +void +Init_bug_14834(void) +{ + VALUE q = rb_define_module("Bug"); + rb_define_module_function(q, "bug_14834", f, 0); +} + +VALUE +f(VALUE q) +{ + int w[] = { 0, 1024 }; + VALUE e = rb_tracepoint_new(Qnil, RUBY_INTERNAL_EVENT_NEWOBJ, g, w); + + rb_tracepoint_enable(e); + return rb_ensure(rb_yield, q, rb_tracepoint_disable, e); +} + +void +g(MAYBE_UNUSED(VALUE q), void* w) +{ + const int *e = (const int *)w; + const int r = *e++; + const int t = *e++; + VALUE *y = ALLOCA_N(VALUE, t); + int *u = ALLOCA_N(int, t); + + rb_profile_frames(r, t, y, u); +} diff --git a/ext/-test-/bug-14834/depend b/ext/-test-/bug-14834/depend index bf26a571aaab86..f83939d559f63c 100644 --- a/ext/-test-/bug-14834/depend +++ b/ext/-test-/bug-14834/depend @@ -1,161 +1,163 @@ # AUTOGENERATED DEPENDENCIES START -bug-14384.o: $(RUBY_EXTCONF_H) -bug-14384.o: $(arch_hdrdir)/ruby/config.h -bug-14384.o: $(hdrdir)/ruby/assert.h -bug-14384.o: $(hdrdir)/ruby/backward.h -bug-14384.o: $(hdrdir)/ruby/backward/2/assume.h -bug-14384.o: $(hdrdir)/ruby/backward/2/attributes.h -bug-14384.o: $(hdrdir)/ruby/backward/2/bool.h -bug-14384.o: $(hdrdir)/ruby/backward/2/inttypes.h -bug-14384.o: $(hdrdir)/ruby/backward/2/limits.h -bug-14384.o: $(hdrdir)/ruby/backward/2/long_long.h -bug-14384.o: $(hdrdir)/ruby/backward/2/stdalign.h -bug-14384.o: $(hdrdir)/ruby/backward/2/stdarg.h -bug-14384.o: $(hdrdir)/ruby/debug.h -bug-14384.o: $(hdrdir)/ruby/defines.h -bug-14384.o: $(hdrdir)/ruby/intern.h -bug-14384.o: $(hdrdir)/ruby/internal/abi.h -bug-14384.o: $(hdrdir)/ruby/internal/anyargs.h -bug-14384.o: $(hdrdir)/ruby/internal/arithmetic.h -bug-14384.o: $(hdrdir)/ruby/internal/arithmetic/char.h -bug-14384.o: $(hdrdir)/ruby/internal/arithmetic/double.h -bug-14384.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h -bug-14384.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h -bug-14384.o: $(hdrdir)/ruby/internal/arithmetic/int.h -bug-14384.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h -bug-14384.o: $(hdrdir)/ruby/internal/arithmetic/long.h -bug-14384.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h -bug-14384.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h -bug-14384.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h -bug-14384.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h -bug-14384.o: $(hdrdir)/ruby/internal/arithmetic/short.h -bug-14384.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h -bug-14384.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h -bug-14384.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h -bug-14384.o: $(hdrdir)/ruby/internal/assume.h -bug-14384.o: $(hdrdir)/ruby/internal/attr/alloc_size.h -bug-14384.o: $(hdrdir)/ruby/internal/attr/artificial.h -bug-14384.o: $(hdrdir)/ruby/internal/attr/cold.h -bug-14384.o: $(hdrdir)/ruby/internal/attr/const.h -bug-14384.o: $(hdrdir)/ruby/internal/attr/constexpr.h -bug-14384.o: $(hdrdir)/ruby/internal/attr/deprecated.h -bug-14384.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h -bug-14384.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h -bug-14384.o: $(hdrdir)/ruby/internal/attr/error.h -bug-14384.o: $(hdrdir)/ruby/internal/attr/flag_enum.h -bug-14384.o: $(hdrdir)/ruby/internal/attr/forceinline.h -bug-14384.o: $(hdrdir)/ruby/internal/attr/format.h -bug-14384.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h -bug-14384.o: $(hdrdir)/ruby/internal/attr/noalias.h -bug-14384.o: $(hdrdir)/ruby/internal/attr/nodiscard.h -bug-14384.o: $(hdrdir)/ruby/internal/attr/noexcept.h -bug-14384.o: $(hdrdir)/ruby/internal/attr/noinline.h -bug-14384.o: $(hdrdir)/ruby/internal/attr/nonnull.h -bug-14384.o: $(hdrdir)/ruby/internal/attr/noreturn.h -bug-14384.o: $(hdrdir)/ruby/internal/attr/packed_struct.h -bug-14384.o: $(hdrdir)/ruby/internal/attr/pure.h -bug-14384.o: $(hdrdir)/ruby/internal/attr/restrict.h -bug-14384.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h -bug-14384.o: $(hdrdir)/ruby/internal/attr/warning.h -bug-14384.o: $(hdrdir)/ruby/internal/attr/weakref.h -bug-14384.o: $(hdrdir)/ruby/internal/cast.h -bug-14384.o: $(hdrdir)/ruby/internal/compiler_is.h -bug-14384.o: $(hdrdir)/ruby/internal/compiler_is/apple.h -bug-14384.o: $(hdrdir)/ruby/internal/compiler_is/clang.h -bug-14384.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h -bug-14384.o: $(hdrdir)/ruby/internal/compiler_is/intel.h -bug-14384.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h -bug-14384.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h -bug-14384.o: $(hdrdir)/ruby/internal/compiler_since.h -bug-14384.o: $(hdrdir)/ruby/internal/config.h -bug-14384.o: $(hdrdir)/ruby/internal/constant_p.h -bug-14384.o: $(hdrdir)/ruby/internal/core.h -bug-14384.o: $(hdrdir)/ruby/internal/core/rarray.h -bug-14384.o: $(hdrdir)/ruby/internal/core/rbasic.h -bug-14384.o: $(hdrdir)/ruby/internal/core/rbignum.h -bug-14384.o: $(hdrdir)/ruby/internal/core/rclass.h -bug-14384.o: $(hdrdir)/ruby/internal/core/rdata.h -bug-14384.o: $(hdrdir)/ruby/internal/core/rfile.h -bug-14384.o: $(hdrdir)/ruby/internal/core/rhash.h -bug-14384.o: $(hdrdir)/ruby/internal/core/robject.h -bug-14384.o: $(hdrdir)/ruby/internal/core/rregexp.h -bug-14384.o: $(hdrdir)/ruby/internal/core/rstring.h -bug-14384.o: $(hdrdir)/ruby/internal/core/rstruct.h -bug-14384.o: $(hdrdir)/ruby/internal/core/rtypeddata.h -bug-14384.o: $(hdrdir)/ruby/internal/ctype.h -bug-14384.o: $(hdrdir)/ruby/internal/dllexport.h -bug-14384.o: $(hdrdir)/ruby/internal/dosish.h -bug-14384.o: $(hdrdir)/ruby/internal/error.h -bug-14384.o: $(hdrdir)/ruby/internal/eval.h -bug-14384.o: $(hdrdir)/ruby/internal/event.h -bug-14384.o: $(hdrdir)/ruby/internal/fl_type.h -bug-14384.o: $(hdrdir)/ruby/internal/gc.h -bug-14384.o: $(hdrdir)/ruby/internal/glob.h -bug-14384.o: $(hdrdir)/ruby/internal/globals.h -bug-14384.o: $(hdrdir)/ruby/internal/has/attribute.h -bug-14384.o: $(hdrdir)/ruby/internal/has/builtin.h -bug-14384.o: $(hdrdir)/ruby/internal/has/c_attribute.h -bug-14384.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h -bug-14384.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h -bug-14384.o: $(hdrdir)/ruby/internal/has/extension.h -bug-14384.o: $(hdrdir)/ruby/internal/has/feature.h -bug-14384.o: $(hdrdir)/ruby/internal/has/warning.h -bug-14384.o: $(hdrdir)/ruby/internal/intern/array.h -bug-14384.o: $(hdrdir)/ruby/internal/intern/bignum.h -bug-14384.o: $(hdrdir)/ruby/internal/intern/class.h -bug-14384.o: $(hdrdir)/ruby/internal/intern/compar.h -bug-14384.o: $(hdrdir)/ruby/internal/intern/complex.h -bug-14384.o: $(hdrdir)/ruby/internal/intern/cont.h -bug-14384.o: $(hdrdir)/ruby/internal/intern/dir.h -bug-14384.o: $(hdrdir)/ruby/internal/intern/enum.h -bug-14384.o: $(hdrdir)/ruby/internal/intern/enumerator.h -bug-14384.o: $(hdrdir)/ruby/internal/intern/error.h -bug-14384.o: $(hdrdir)/ruby/internal/intern/eval.h -bug-14384.o: $(hdrdir)/ruby/internal/intern/file.h -bug-14384.o: $(hdrdir)/ruby/internal/intern/hash.h -bug-14384.o: $(hdrdir)/ruby/internal/intern/io.h -bug-14384.o: $(hdrdir)/ruby/internal/intern/load.h -bug-14384.o: $(hdrdir)/ruby/internal/intern/marshal.h -bug-14384.o: $(hdrdir)/ruby/internal/intern/numeric.h -bug-14384.o: $(hdrdir)/ruby/internal/intern/object.h -bug-14384.o: $(hdrdir)/ruby/internal/intern/parse.h -bug-14384.o: $(hdrdir)/ruby/internal/intern/proc.h -bug-14384.o: $(hdrdir)/ruby/internal/intern/process.h -bug-14384.o: $(hdrdir)/ruby/internal/intern/random.h -bug-14384.o: $(hdrdir)/ruby/internal/intern/range.h -bug-14384.o: $(hdrdir)/ruby/internal/intern/rational.h -bug-14384.o: $(hdrdir)/ruby/internal/intern/re.h -bug-14384.o: $(hdrdir)/ruby/internal/intern/ruby.h -bug-14384.o: $(hdrdir)/ruby/internal/intern/select.h -bug-14384.o: $(hdrdir)/ruby/internal/intern/select/largesize.h -bug-14384.o: $(hdrdir)/ruby/internal/intern/signal.h -bug-14384.o: $(hdrdir)/ruby/internal/intern/sprintf.h -bug-14384.o: $(hdrdir)/ruby/internal/intern/string.h -bug-14384.o: $(hdrdir)/ruby/internal/intern/struct.h -bug-14384.o: $(hdrdir)/ruby/internal/intern/thread.h -bug-14384.o: $(hdrdir)/ruby/internal/intern/time.h -bug-14384.o: $(hdrdir)/ruby/internal/intern/variable.h -bug-14384.o: $(hdrdir)/ruby/internal/intern/vm.h -bug-14384.o: $(hdrdir)/ruby/internal/interpreter.h -bug-14384.o: $(hdrdir)/ruby/internal/iterator.h -bug-14384.o: $(hdrdir)/ruby/internal/memory.h -bug-14384.o: $(hdrdir)/ruby/internal/method.h -bug-14384.o: $(hdrdir)/ruby/internal/module.h -bug-14384.o: $(hdrdir)/ruby/internal/newobj.h -bug-14384.o: $(hdrdir)/ruby/internal/scan_args.h -bug-14384.o: $(hdrdir)/ruby/internal/special_consts.h -bug-14384.o: $(hdrdir)/ruby/internal/static_assert.h -bug-14384.o: $(hdrdir)/ruby/internal/stdalign.h -bug-14384.o: $(hdrdir)/ruby/internal/stdbool.h -bug-14384.o: $(hdrdir)/ruby/internal/symbol.h -bug-14384.o: $(hdrdir)/ruby/internal/value.h -bug-14384.o: $(hdrdir)/ruby/internal/value_type.h -bug-14384.o: $(hdrdir)/ruby/internal/variable.h -bug-14384.o: $(hdrdir)/ruby/internal/warning_push.h -bug-14384.o: $(hdrdir)/ruby/internal/xmalloc.h -bug-14384.o: $(hdrdir)/ruby/missing.h -bug-14384.o: $(hdrdir)/ruby/ruby.h -bug-14384.o: $(hdrdir)/ruby/st.h -bug-14384.o: $(hdrdir)/ruby/subst.h -bug-14384.o: bug-14384.c +bug-14834.o: $(RUBY_EXTCONF_H) +bug-14834.o: $(arch_hdrdir)/ruby/config.h +bug-14834.o: $(hdrdir)/ruby/assert.h +bug-14834.o: $(hdrdir)/ruby/backward.h +bug-14834.o: $(hdrdir)/ruby/backward/2/assume.h +bug-14834.o: $(hdrdir)/ruby/backward/2/attributes.h +bug-14834.o: $(hdrdir)/ruby/backward/2/bool.h +bug-14834.o: $(hdrdir)/ruby/backward/2/inttypes.h +bug-14834.o: $(hdrdir)/ruby/backward/2/limits.h +bug-14834.o: $(hdrdir)/ruby/backward/2/long_long.h +bug-14834.o: $(hdrdir)/ruby/backward/2/stdalign.h +bug-14834.o: $(hdrdir)/ruby/backward/2/stdarg.h +bug-14834.o: $(hdrdir)/ruby/debug.h +bug-14834.o: $(hdrdir)/ruby/defines.h +bug-14834.o: $(hdrdir)/ruby/intern.h +bug-14834.o: $(hdrdir)/ruby/internal/abi.h +bug-14834.o: $(hdrdir)/ruby/internal/anyargs.h +bug-14834.o: $(hdrdir)/ruby/internal/arithmetic.h +bug-14834.o: $(hdrdir)/ruby/internal/arithmetic/char.h +bug-14834.o: $(hdrdir)/ruby/internal/arithmetic/double.h +bug-14834.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +bug-14834.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +bug-14834.o: $(hdrdir)/ruby/internal/arithmetic/int.h +bug-14834.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +bug-14834.o: $(hdrdir)/ruby/internal/arithmetic/long.h +bug-14834.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +bug-14834.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +bug-14834.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +bug-14834.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +bug-14834.o: $(hdrdir)/ruby/internal/arithmetic/short.h +bug-14834.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +bug-14834.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +bug-14834.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +bug-14834.o: $(hdrdir)/ruby/internal/assume.h +bug-14834.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +bug-14834.o: $(hdrdir)/ruby/internal/attr/artificial.h +bug-14834.o: $(hdrdir)/ruby/internal/attr/cold.h +bug-14834.o: $(hdrdir)/ruby/internal/attr/const.h +bug-14834.o: $(hdrdir)/ruby/internal/attr/constexpr.h +bug-14834.o: $(hdrdir)/ruby/internal/attr/deprecated.h +bug-14834.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +bug-14834.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +bug-14834.o: $(hdrdir)/ruby/internal/attr/error.h +bug-14834.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +bug-14834.o: $(hdrdir)/ruby/internal/attr/forceinline.h +bug-14834.o: $(hdrdir)/ruby/internal/attr/format.h +bug-14834.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +bug-14834.o: $(hdrdir)/ruby/internal/attr/noalias.h +bug-14834.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +bug-14834.o: $(hdrdir)/ruby/internal/attr/noexcept.h +bug-14834.o: $(hdrdir)/ruby/internal/attr/noinline.h +bug-14834.o: $(hdrdir)/ruby/internal/attr/nonnull.h +bug-14834.o: $(hdrdir)/ruby/internal/attr/noreturn.h +bug-14834.o: $(hdrdir)/ruby/internal/attr/packed_struct.h +bug-14834.o: $(hdrdir)/ruby/internal/attr/pure.h +bug-14834.o: $(hdrdir)/ruby/internal/attr/restrict.h +bug-14834.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +bug-14834.o: $(hdrdir)/ruby/internal/attr/warning.h +bug-14834.o: $(hdrdir)/ruby/internal/attr/weakref.h +bug-14834.o: $(hdrdir)/ruby/internal/cast.h +bug-14834.o: $(hdrdir)/ruby/internal/compiler_is.h +bug-14834.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +bug-14834.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +bug-14834.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +bug-14834.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +bug-14834.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +bug-14834.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +bug-14834.o: $(hdrdir)/ruby/internal/compiler_since.h +bug-14834.o: $(hdrdir)/ruby/internal/config.h +bug-14834.o: $(hdrdir)/ruby/internal/constant_p.h +bug-14834.o: $(hdrdir)/ruby/internal/core.h +bug-14834.o: $(hdrdir)/ruby/internal/core/rarray.h +bug-14834.o: $(hdrdir)/ruby/internal/core/rbasic.h +bug-14834.o: $(hdrdir)/ruby/internal/core/rbignum.h +bug-14834.o: $(hdrdir)/ruby/internal/core/rclass.h +bug-14834.o: $(hdrdir)/ruby/internal/core/rdata.h +bug-14834.o: $(hdrdir)/ruby/internal/core/rfile.h +bug-14834.o: $(hdrdir)/ruby/internal/core/rhash.h +bug-14834.o: $(hdrdir)/ruby/internal/core/robject.h +bug-14834.o: $(hdrdir)/ruby/internal/core/rregexp.h +bug-14834.o: $(hdrdir)/ruby/internal/core/rstring.h +bug-14834.o: $(hdrdir)/ruby/internal/core/rstruct.h +bug-14834.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +bug-14834.o: $(hdrdir)/ruby/internal/ctype.h +bug-14834.o: $(hdrdir)/ruby/internal/dllexport.h +bug-14834.o: $(hdrdir)/ruby/internal/dosish.h +bug-14834.o: $(hdrdir)/ruby/internal/error.h +bug-14834.o: $(hdrdir)/ruby/internal/eval.h +bug-14834.o: $(hdrdir)/ruby/internal/event.h +bug-14834.o: $(hdrdir)/ruby/internal/fl_type.h +bug-14834.o: $(hdrdir)/ruby/internal/gc.h +bug-14834.o: $(hdrdir)/ruby/internal/glob.h +bug-14834.o: $(hdrdir)/ruby/internal/globals.h +bug-14834.o: $(hdrdir)/ruby/internal/has/attribute.h +bug-14834.o: $(hdrdir)/ruby/internal/has/builtin.h +bug-14834.o: $(hdrdir)/ruby/internal/has/c_attribute.h +bug-14834.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +bug-14834.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +bug-14834.o: $(hdrdir)/ruby/internal/has/extension.h +bug-14834.o: $(hdrdir)/ruby/internal/has/feature.h +bug-14834.o: $(hdrdir)/ruby/internal/has/warning.h +bug-14834.o: $(hdrdir)/ruby/internal/intern/array.h +bug-14834.o: $(hdrdir)/ruby/internal/intern/bignum.h +bug-14834.o: $(hdrdir)/ruby/internal/intern/class.h +bug-14834.o: $(hdrdir)/ruby/internal/intern/compar.h +bug-14834.o: $(hdrdir)/ruby/internal/intern/complex.h +bug-14834.o: $(hdrdir)/ruby/internal/intern/cont.h +bug-14834.o: $(hdrdir)/ruby/internal/intern/dir.h +bug-14834.o: $(hdrdir)/ruby/internal/intern/enum.h +bug-14834.o: $(hdrdir)/ruby/internal/intern/enumerator.h +bug-14834.o: $(hdrdir)/ruby/internal/intern/error.h +bug-14834.o: $(hdrdir)/ruby/internal/intern/eval.h +bug-14834.o: $(hdrdir)/ruby/internal/intern/file.h +bug-14834.o: $(hdrdir)/ruby/internal/intern/hash.h +bug-14834.o: $(hdrdir)/ruby/internal/intern/io.h +bug-14834.o: $(hdrdir)/ruby/internal/intern/load.h +bug-14834.o: $(hdrdir)/ruby/internal/intern/marshal.h +bug-14834.o: $(hdrdir)/ruby/internal/intern/numeric.h +bug-14834.o: $(hdrdir)/ruby/internal/intern/object.h +bug-14834.o: $(hdrdir)/ruby/internal/intern/parse.h +bug-14834.o: $(hdrdir)/ruby/internal/intern/proc.h +bug-14834.o: $(hdrdir)/ruby/internal/intern/process.h +bug-14834.o: $(hdrdir)/ruby/internal/intern/random.h +bug-14834.o: $(hdrdir)/ruby/internal/intern/range.h +bug-14834.o: $(hdrdir)/ruby/internal/intern/rational.h +bug-14834.o: $(hdrdir)/ruby/internal/intern/re.h +bug-14834.o: $(hdrdir)/ruby/internal/intern/ruby.h +bug-14834.o: $(hdrdir)/ruby/internal/intern/select.h +bug-14834.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +bug-14834.o: $(hdrdir)/ruby/internal/intern/set.h +bug-14834.o: $(hdrdir)/ruby/internal/intern/signal.h +bug-14834.o: $(hdrdir)/ruby/internal/intern/sprintf.h +bug-14834.o: $(hdrdir)/ruby/internal/intern/string.h +bug-14834.o: $(hdrdir)/ruby/internal/intern/struct.h +bug-14834.o: $(hdrdir)/ruby/internal/intern/thread.h +bug-14834.o: $(hdrdir)/ruby/internal/intern/time.h +bug-14834.o: $(hdrdir)/ruby/internal/intern/variable.h +bug-14834.o: $(hdrdir)/ruby/internal/intern/vm.h +bug-14834.o: $(hdrdir)/ruby/internal/interpreter.h +bug-14834.o: $(hdrdir)/ruby/internal/iterator.h +bug-14834.o: $(hdrdir)/ruby/internal/memory.h +bug-14834.o: $(hdrdir)/ruby/internal/method.h +bug-14834.o: $(hdrdir)/ruby/internal/module.h +bug-14834.o: $(hdrdir)/ruby/internal/newobj.h +bug-14834.o: $(hdrdir)/ruby/internal/scan_args.h +bug-14834.o: $(hdrdir)/ruby/internal/special_consts.h +bug-14834.o: $(hdrdir)/ruby/internal/static_assert.h +bug-14834.o: $(hdrdir)/ruby/internal/stdalign.h +bug-14834.o: $(hdrdir)/ruby/internal/stdbool.h +bug-14834.o: $(hdrdir)/ruby/internal/stdckdint.h +bug-14834.o: $(hdrdir)/ruby/internal/symbol.h +bug-14834.o: $(hdrdir)/ruby/internal/value.h +bug-14834.o: $(hdrdir)/ruby/internal/value_type.h +bug-14834.o: $(hdrdir)/ruby/internal/variable.h +bug-14834.o: $(hdrdir)/ruby/internal/warning_push.h +bug-14834.o: $(hdrdir)/ruby/internal/xmalloc.h +bug-14834.o: $(hdrdir)/ruby/missing.h +bug-14834.o: $(hdrdir)/ruby/ruby.h +bug-14834.o: $(hdrdir)/ruby/st.h +bug-14834.o: $(hdrdir)/ruby/subst.h +bug-14834.o: bug-14834.c # AUTOGENERATED DEPENDENCIES END diff --git a/ext/-test-/bug-3571/depend b/ext/-test-/bug-3571/depend index 9105093b0d39b1..69c970b6f25703 100644 --- a/ext/-test-/bug-3571/depend +++ b/ext/-test-/bug-3571/depend @@ -128,6 +128,7 @@ bug.o: $(hdrdir)/ruby/internal/intern/re.h bug.o: $(hdrdir)/ruby/internal/intern/ruby.h bug.o: $(hdrdir)/ruby/internal/intern/select.h bug.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +bug.o: $(hdrdir)/ruby/internal/intern/set.h bug.o: $(hdrdir)/ruby/internal/intern/signal.h bug.o: $(hdrdir)/ruby/internal/intern/sprintf.h bug.o: $(hdrdir)/ruby/internal/intern/string.h @@ -147,6 +148,7 @@ bug.o: $(hdrdir)/ruby/internal/special_consts.h bug.o: $(hdrdir)/ruby/internal/static_assert.h bug.o: $(hdrdir)/ruby/internal/stdalign.h bug.o: $(hdrdir)/ruby/internal/stdbool.h +bug.o: $(hdrdir)/ruby/internal/stdckdint.h bug.o: $(hdrdir)/ruby/internal/symbol.h bug.o: $(hdrdir)/ruby/internal/value.h bug.o: $(hdrdir)/ruby/internal/value_type.h diff --git a/ext/-test-/bug-5832/depend b/ext/-test-/bug-5832/depend index 9105093b0d39b1..69c970b6f25703 100644 --- a/ext/-test-/bug-5832/depend +++ b/ext/-test-/bug-5832/depend @@ -128,6 +128,7 @@ bug.o: $(hdrdir)/ruby/internal/intern/re.h bug.o: $(hdrdir)/ruby/internal/intern/ruby.h bug.o: $(hdrdir)/ruby/internal/intern/select.h bug.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +bug.o: $(hdrdir)/ruby/internal/intern/set.h bug.o: $(hdrdir)/ruby/internal/intern/signal.h bug.o: $(hdrdir)/ruby/internal/intern/sprintf.h bug.o: $(hdrdir)/ruby/internal/intern/string.h @@ -147,6 +148,7 @@ bug.o: $(hdrdir)/ruby/internal/special_consts.h bug.o: $(hdrdir)/ruby/internal/static_assert.h bug.o: $(hdrdir)/ruby/internal/stdalign.h bug.o: $(hdrdir)/ruby/internal/stdbool.h +bug.o: $(hdrdir)/ruby/internal/stdckdint.h bug.o: $(hdrdir)/ruby/internal/symbol.h bug.o: $(hdrdir)/ruby/internal/value.h bug.o: $(hdrdir)/ruby/internal/value_type.h diff --git a/ext/-test-/bug_reporter/depend b/ext/-test-/bug_reporter/depend index 20882708d1ba13..e9993c3295505e 100644 --- a/ext/-test-/bug_reporter/depend +++ b/ext/-test-/bug_reporter/depend @@ -128,6 +128,7 @@ bug_reporter.o: $(hdrdir)/ruby/internal/intern/re.h bug_reporter.o: $(hdrdir)/ruby/internal/intern/ruby.h bug_reporter.o: $(hdrdir)/ruby/internal/intern/select.h bug_reporter.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +bug_reporter.o: $(hdrdir)/ruby/internal/intern/set.h bug_reporter.o: $(hdrdir)/ruby/internal/intern/signal.h bug_reporter.o: $(hdrdir)/ruby/internal/intern/sprintf.h bug_reporter.o: $(hdrdir)/ruby/internal/intern/string.h @@ -147,6 +148,7 @@ bug_reporter.o: $(hdrdir)/ruby/internal/special_consts.h bug_reporter.o: $(hdrdir)/ruby/internal/static_assert.h bug_reporter.o: $(hdrdir)/ruby/internal/stdalign.h bug_reporter.o: $(hdrdir)/ruby/internal/stdbool.h +bug_reporter.o: $(hdrdir)/ruby/internal/stdckdint.h bug_reporter.o: $(hdrdir)/ruby/internal/symbol.h bug_reporter.o: $(hdrdir)/ruby/internal/value.h bug_reporter.o: $(hdrdir)/ruby/internal/value_type.h diff --git a/ext/-test-/class/depend b/ext/-test-/class/depend index 0a805f815e15ba..557206cefb41f4 100644 --- a/ext/-test-/class/depend +++ b/ext/-test-/class/depend @@ -127,6 +127,7 @@ class2name.o: $(hdrdir)/ruby/internal/intern/re.h class2name.o: $(hdrdir)/ruby/internal/intern/ruby.h class2name.o: $(hdrdir)/ruby/internal/intern/select.h class2name.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +class2name.o: $(hdrdir)/ruby/internal/intern/set.h class2name.o: $(hdrdir)/ruby/internal/intern/signal.h class2name.o: $(hdrdir)/ruby/internal/intern/sprintf.h class2name.o: $(hdrdir)/ruby/internal/intern/string.h @@ -146,6 +147,7 @@ class2name.o: $(hdrdir)/ruby/internal/special_consts.h class2name.o: $(hdrdir)/ruby/internal/static_assert.h class2name.o: $(hdrdir)/ruby/internal/stdalign.h class2name.o: $(hdrdir)/ruby/internal/stdbool.h +class2name.o: $(hdrdir)/ruby/internal/stdckdint.h class2name.o: $(hdrdir)/ruby/internal/symbol.h class2name.o: $(hdrdir)/ruby/internal/value.h class2name.o: $(hdrdir)/ruby/internal/value_type.h @@ -286,6 +288,7 @@ init.o: $(hdrdir)/ruby/internal/intern/re.h init.o: $(hdrdir)/ruby/internal/intern/ruby.h init.o: $(hdrdir)/ruby/internal/intern/select.h init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +init.o: $(hdrdir)/ruby/internal/intern/set.h init.o: $(hdrdir)/ruby/internal/intern/signal.h init.o: $(hdrdir)/ruby/internal/intern/sprintf.h init.o: $(hdrdir)/ruby/internal/intern/string.h @@ -305,6 +308,7 @@ init.o: $(hdrdir)/ruby/internal/special_consts.h init.o: $(hdrdir)/ruby/internal/static_assert.h init.o: $(hdrdir)/ruby/internal/stdalign.h init.o: $(hdrdir)/ruby/internal/stdbool.h +init.o: $(hdrdir)/ruby/internal/stdckdint.h init.o: $(hdrdir)/ruby/internal/symbol.h init.o: $(hdrdir)/ruby/internal/value.h init.o: $(hdrdir)/ruby/internal/value_type.h diff --git a/ext/-test-/class/init.c b/ext/-test-/class/init.c index ed715c1942492c..108ff7525cef85 100644 --- a/ext/-test-/class/init.c +++ b/ext/-test-/class/init.c @@ -7,5 +7,6 @@ Init_class(void) { VALUE mBug = rb_define_module("Bug"); VALUE mod = rb_define_module_under(mBug, "Class"); + rb_define_class_under(mod, "TestClassDefinedInC", rb_cObject); TEST_INIT_FUNCS(init); } diff --git a/ext/-test-/debug/depend b/ext/-test-/debug/depend index 5feeea6d989dd1..4ae0378ef2072d 100644 --- a/ext/-test-/debug/depend +++ b/ext/-test-/debug/depend @@ -128,6 +128,7 @@ init.o: $(hdrdir)/ruby/internal/intern/re.h init.o: $(hdrdir)/ruby/internal/intern/ruby.h init.o: $(hdrdir)/ruby/internal/intern/select.h init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +init.o: $(hdrdir)/ruby/internal/intern/set.h init.o: $(hdrdir)/ruby/internal/intern/signal.h init.o: $(hdrdir)/ruby/internal/intern/sprintf.h init.o: $(hdrdir)/ruby/internal/intern/string.h @@ -147,6 +148,7 @@ init.o: $(hdrdir)/ruby/internal/special_consts.h init.o: $(hdrdir)/ruby/internal/static_assert.h init.o: $(hdrdir)/ruby/internal/stdalign.h init.o: $(hdrdir)/ruby/internal/stdbool.h +init.o: $(hdrdir)/ruby/internal/stdckdint.h init.o: $(hdrdir)/ruby/internal/symbol.h init.o: $(hdrdir)/ruby/internal/value.h init.o: $(hdrdir)/ruby/internal/value_type.h @@ -287,6 +289,7 @@ inspector.o: $(hdrdir)/ruby/internal/intern/re.h inspector.o: $(hdrdir)/ruby/internal/intern/ruby.h inspector.o: $(hdrdir)/ruby/internal/intern/select.h inspector.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +inspector.o: $(hdrdir)/ruby/internal/intern/set.h inspector.o: $(hdrdir)/ruby/internal/intern/signal.h inspector.o: $(hdrdir)/ruby/internal/intern/sprintf.h inspector.o: $(hdrdir)/ruby/internal/intern/string.h @@ -306,6 +309,7 @@ inspector.o: $(hdrdir)/ruby/internal/special_consts.h inspector.o: $(hdrdir)/ruby/internal/static_assert.h inspector.o: $(hdrdir)/ruby/internal/stdalign.h inspector.o: $(hdrdir)/ruby/internal/stdbool.h +inspector.o: $(hdrdir)/ruby/internal/stdckdint.h inspector.o: $(hdrdir)/ruby/internal/symbol.h inspector.o: $(hdrdir)/ruby/internal/value.h inspector.o: $(hdrdir)/ruby/internal/value_type.h @@ -446,6 +450,7 @@ profile_frames.o: $(hdrdir)/ruby/internal/intern/re.h profile_frames.o: $(hdrdir)/ruby/internal/intern/ruby.h profile_frames.o: $(hdrdir)/ruby/internal/intern/select.h profile_frames.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +profile_frames.o: $(hdrdir)/ruby/internal/intern/set.h profile_frames.o: $(hdrdir)/ruby/internal/intern/signal.h profile_frames.o: $(hdrdir)/ruby/internal/intern/sprintf.h profile_frames.o: $(hdrdir)/ruby/internal/intern/string.h @@ -465,6 +470,7 @@ profile_frames.o: $(hdrdir)/ruby/internal/special_consts.h profile_frames.o: $(hdrdir)/ruby/internal/static_assert.h profile_frames.o: $(hdrdir)/ruby/internal/stdalign.h profile_frames.o: $(hdrdir)/ruby/internal/stdbool.h +profile_frames.o: $(hdrdir)/ruby/internal/stdckdint.h profile_frames.o: $(hdrdir)/ruby/internal/symbol.h profile_frames.o: $(hdrdir)/ruby/internal/value.h profile_frames.o: $(hdrdir)/ruby/internal/value_type.h diff --git a/ext/-test-/debug/profile_frames.c b/ext/-test-/debug/profile_frames.c index d2bba7d1834e1b..f9a77a5a780f18 100644 --- a/ext/-test-/debug/profile_frames.c +++ b/ext/-test-/debug/profile_frames.c @@ -37,8 +37,29 @@ profile_frames(VALUE self, VALUE start_v, VALUE num_v) return result; } +static VALUE +profile_thread_frames(VALUE self, VALUE thread, VALUE start_v, VALUE num_v) +{ + int i, collected_size; + int start = NUM2INT(start_v); + int buff_size = NUM2INT(num_v); + VALUE buff[MAX_BUF_SIZE]; + int lines[MAX_BUF_SIZE]; + VALUE result = rb_ary_new(); + + if (buff_size > MAX_BUF_SIZE) rb_raise(rb_eRuntimeError, "too long buff_size"); + + collected_size = rb_profile_thread_frames(thread, start, buff_size, buff, lines); + for (i=0; iobj, data->fname); + return Qnil; +} + +static VALUE +call_ensure(VALUE _) +{ + VALUE v = rb_iv_get(rb_mEnsureAndCallcc, "@ensure_called"); + int called = FIX2INT(v) + 1; + rb_iv_set(rb_mEnsureAndCallcc, "@ensure_called", INT2FIX(called)); + return Qnil; +} + +static VALUE +require_with_ensure(VALUE self, VALUE fname) +{ + struct require_data data = { + .obj = self, + .fname = fname + }; + return rb_ensure(call_require, (VALUE)&data, call_ensure, Qnil); +} + +static VALUE +ensure_called(VALUE self) +{ + return rb_iv_get(rb_mEnsureAndCallcc, "@ensure_called"); +} + +static VALUE +reset(VALUE self) +{ + rb_iv_set(rb_mEnsureAndCallcc, "@ensure_called", INT2FIX(0)); + return Qnil; +} + +void +Init_ensure_and_callcc(void) +{ + rb_mEnsureAndCallcc = rb_define_module("EnsureAndCallcc"); + rb_iv_set(rb_mEnsureAndCallcc, "@ensure_called", INT2FIX(0)); + rb_define_singleton_method(rb_mEnsureAndCallcc, "reset", reset, 0); + rb_define_singleton_method(rb_mEnsureAndCallcc, "ensure_called", ensure_called, 0); + rb_define_singleton_method(rb_mEnsureAndCallcc, "require_with_ensure", require_with_ensure, 1); +} diff --git a/ext/-test-/ensure_and_callcc/extconf.rb b/ext/-test-/ensure_and_callcc/extconf.rb new file mode 100644 index 00000000000000..123b80b8d02470 --- /dev/null +++ b/ext/-test-/ensure_and_callcc/extconf.rb @@ -0,0 +1,5 @@ +# frozen_string_literal: false +require "mkmf" + +require_relative "../auto_ext.rb" +auto_ext(inc: true) diff --git a/ext/-test-/enumerator_kw/depend b/ext/-test-/enumerator_kw/depend index 49ea4954213bae..b6d2f0a9989788 100644 --- a/ext/-test-/enumerator_kw/depend +++ b/ext/-test-/enumerator_kw/depend @@ -128,6 +128,7 @@ enumerator_kw.o: $(hdrdir)/ruby/internal/intern/re.h enumerator_kw.o: $(hdrdir)/ruby/internal/intern/ruby.h enumerator_kw.o: $(hdrdir)/ruby/internal/intern/select.h enumerator_kw.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +enumerator_kw.o: $(hdrdir)/ruby/internal/intern/set.h enumerator_kw.o: $(hdrdir)/ruby/internal/intern/signal.h enumerator_kw.o: $(hdrdir)/ruby/internal/intern/sprintf.h enumerator_kw.o: $(hdrdir)/ruby/internal/intern/string.h @@ -147,6 +148,7 @@ enumerator_kw.o: $(hdrdir)/ruby/internal/special_consts.h enumerator_kw.o: $(hdrdir)/ruby/internal/static_assert.h enumerator_kw.o: $(hdrdir)/ruby/internal/stdalign.h enumerator_kw.o: $(hdrdir)/ruby/internal/stdbool.h +enumerator_kw.o: $(hdrdir)/ruby/internal/stdckdint.h enumerator_kw.o: $(hdrdir)/ruby/internal/symbol.h enumerator_kw.o: $(hdrdir)/ruby/internal/value.h enumerator_kw.o: $(hdrdir)/ruby/internal/value_type.h diff --git a/ext/-test-/eval/depend b/ext/-test-/eval/depend new file mode 100644 index 00000000000000..03a1c7d7ef9bee --- /dev/null +++ b/ext/-test-/eval/depend @@ -0,0 +1,162 @@ +# AUTOGENERATED DEPENDENCIES START +eval.o: $(RUBY_EXTCONF_H) +eval.o: $(arch_hdrdir)/ruby/config.h +eval.o: $(hdrdir)/ruby/assert.h +eval.o: $(hdrdir)/ruby/backward.h +eval.o: $(hdrdir)/ruby/backward/2/assume.h +eval.o: $(hdrdir)/ruby/backward/2/attributes.h +eval.o: $(hdrdir)/ruby/backward/2/bool.h +eval.o: $(hdrdir)/ruby/backward/2/inttypes.h +eval.o: $(hdrdir)/ruby/backward/2/limits.h +eval.o: $(hdrdir)/ruby/backward/2/long_long.h +eval.o: $(hdrdir)/ruby/backward/2/stdalign.h +eval.o: $(hdrdir)/ruby/backward/2/stdarg.h +eval.o: $(hdrdir)/ruby/defines.h +eval.o: $(hdrdir)/ruby/intern.h +eval.o: $(hdrdir)/ruby/internal/abi.h +eval.o: $(hdrdir)/ruby/internal/anyargs.h +eval.o: $(hdrdir)/ruby/internal/arithmetic.h +eval.o: $(hdrdir)/ruby/internal/arithmetic/char.h +eval.o: $(hdrdir)/ruby/internal/arithmetic/double.h +eval.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +eval.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +eval.o: $(hdrdir)/ruby/internal/arithmetic/int.h +eval.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +eval.o: $(hdrdir)/ruby/internal/arithmetic/long.h +eval.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +eval.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +eval.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +eval.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +eval.o: $(hdrdir)/ruby/internal/arithmetic/short.h +eval.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +eval.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +eval.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +eval.o: $(hdrdir)/ruby/internal/assume.h +eval.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +eval.o: $(hdrdir)/ruby/internal/attr/artificial.h +eval.o: $(hdrdir)/ruby/internal/attr/cold.h +eval.o: $(hdrdir)/ruby/internal/attr/const.h +eval.o: $(hdrdir)/ruby/internal/attr/constexpr.h +eval.o: $(hdrdir)/ruby/internal/attr/deprecated.h +eval.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +eval.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +eval.o: $(hdrdir)/ruby/internal/attr/error.h +eval.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +eval.o: $(hdrdir)/ruby/internal/attr/forceinline.h +eval.o: $(hdrdir)/ruby/internal/attr/format.h +eval.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +eval.o: $(hdrdir)/ruby/internal/attr/noalias.h +eval.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +eval.o: $(hdrdir)/ruby/internal/attr/noexcept.h +eval.o: $(hdrdir)/ruby/internal/attr/noinline.h +eval.o: $(hdrdir)/ruby/internal/attr/nonnull.h +eval.o: $(hdrdir)/ruby/internal/attr/noreturn.h +eval.o: $(hdrdir)/ruby/internal/attr/packed_struct.h +eval.o: $(hdrdir)/ruby/internal/attr/pure.h +eval.o: $(hdrdir)/ruby/internal/attr/restrict.h +eval.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +eval.o: $(hdrdir)/ruby/internal/attr/warning.h +eval.o: $(hdrdir)/ruby/internal/attr/weakref.h +eval.o: $(hdrdir)/ruby/internal/cast.h +eval.o: $(hdrdir)/ruby/internal/compiler_is.h +eval.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +eval.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +eval.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +eval.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +eval.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +eval.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +eval.o: $(hdrdir)/ruby/internal/compiler_since.h +eval.o: $(hdrdir)/ruby/internal/config.h +eval.o: $(hdrdir)/ruby/internal/constant_p.h +eval.o: $(hdrdir)/ruby/internal/core.h +eval.o: $(hdrdir)/ruby/internal/core/rarray.h +eval.o: $(hdrdir)/ruby/internal/core/rbasic.h +eval.o: $(hdrdir)/ruby/internal/core/rbignum.h +eval.o: $(hdrdir)/ruby/internal/core/rclass.h +eval.o: $(hdrdir)/ruby/internal/core/rdata.h +eval.o: $(hdrdir)/ruby/internal/core/rfile.h +eval.o: $(hdrdir)/ruby/internal/core/rhash.h +eval.o: $(hdrdir)/ruby/internal/core/robject.h +eval.o: $(hdrdir)/ruby/internal/core/rregexp.h +eval.o: $(hdrdir)/ruby/internal/core/rstring.h +eval.o: $(hdrdir)/ruby/internal/core/rstruct.h +eval.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +eval.o: $(hdrdir)/ruby/internal/ctype.h +eval.o: $(hdrdir)/ruby/internal/dllexport.h +eval.o: $(hdrdir)/ruby/internal/dosish.h +eval.o: $(hdrdir)/ruby/internal/error.h +eval.o: $(hdrdir)/ruby/internal/eval.h +eval.o: $(hdrdir)/ruby/internal/event.h +eval.o: $(hdrdir)/ruby/internal/fl_type.h +eval.o: $(hdrdir)/ruby/internal/gc.h +eval.o: $(hdrdir)/ruby/internal/glob.h +eval.o: $(hdrdir)/ruby/internal/globals.h +eval.o: $(hdrdir)/ruby/internal/has/attribute.h +eval.o: $(hdrdir)/ruby/internal/has/builtin.h +eval.o: $(hdrdir)/ruby/internal/has/c_attribute.h +eval.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +eval.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +eval.o: $(hdrdir)/ruby/internal/has/extension.h +eval.o: $(hdrdir)/ruby/internal/has/feature.h +eval.o: $(hdrdir)/ruby/internal/has/warning.h +eval.o: $(hdrdir)/ruby/internal/intern/array.h +eval.o: $(hdrdir)/ruby/internal/intern/bignum.h +eval.o: $(hdrdir)/ruby/internal/intern/class.h +eval.o: $(hdrdir)/ruby/internal/intern/compar.h +eval.o: $(hdrdir)/ruby/internal/intern/complex.h +eval.o: $(hdrdir)/ruby/internal/intern/cont.h +eval.o: $(hdrdir)/ruby/internal/intern/dir.h +eval.o: $(hdrdir)/ruby/internal/intern/enum.h +eval.o: $(hdrdir)/ruby/internal/intern/enumerator.h +eval.o: $(hdrdir)/ruby/internal/intern/error.h +eval.o: $(hdrdir)/ruby/internal/intern/eval.h +eval.o: $(hdrdir)/ruby/internal/intern/file.h +eval.o: $(hdrdir)/ruby/internal/intern/hash.h +eval.o: $(hdrdir)/ruby/internal/intern/io.h +eval.o: $(hdrdir)/ruby/internal/intern/load.h +eval.o: $(hdrdir)/ruby/internal/intern/marshal.h +eval.o: $(hdrdir)/ruby/internal/intern/numeric.h +eval.o: $(hdrdir)/ruby/internal/intern/object.h +eval.o: $(hdrdir)/ruby/internal/intern/parse.h +eval.o: $(hdrdir)/ruby/internal/intern/proc.h +eval.o: $(hdrdir)/ruby/internal/intern/process.h +eval.o: $(hdrdir)/ruby/internal/intern/random.h +eval.o: $(hdrdir)/ruby/internal/intern/range.h +eval.o: $(hdrdir)/ruby/internal/intern/rational.h +eval.o: $(hdrdir)/ruby/internal/intern/re.h +eval.o: $(hdrdir)/ruby/internal/intern/ruby.h +eval.o: $(hdrdir)/ruby/internal/intern/select.h +eval.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +eval.o: $(hdrdir)/ruby/internal/intern/set.h +eval.o: $(hdrdir)/ruby/internal/intern/signal.h +eval.o: $(hdrdir)/ruby/internal/intern/sprintf.h +eval.o: $(hdrdir)/ruby/internal/intern/string.h +eval.o: $(hdrdir)/ruby/internal/intern/struct.h +eval.o: $(hdrdir)/ruby/internal/intern/thread.h +eval.o: $(hdrdir)/ruby/internal/intern/time.h +eval.o: $(hdrdir)/ruby/internal/intern/variable.h +eval.o: $(hdrdir)/ruby/internal/intern/vm.h +eval.o: $(hdrdir)/ruby/internal/interpreter.h +eval.o: $(hdrdir)/ruby/internal/iterator.h +eval.o: $(hdrdir)/ruby/internal/memory.h +eval.o: $(hdrdir)/ruby/internal/method.h +eval.o: $(hdrdir)/ruby/internal/module.h +eval.o: $(hdrdir)/ruby/internal/newobj.h +eval.o: $(hdrdir)/ruby/internal/scan_args.h +eval.o: $(hdrdir)/ruby/internal/special_consts.h +eval.o: $(hdrdir)/ruby/internal/static_assert.h +eval.o: $(hdrdir)/ruby/internal/stdalign.h +eval.o: $(hdrdir)/ruby/internal/stdbool.h +eval.o: $(hdrdir)/ruby/internal/stdckdint.h +eval.o: $(hdrdir)/ruby/internal/symbol.h +eval.o: $(hdrdir)/ruby/internal/value.h +eval.o: $(hdrdir)/ruby/internal/value_type.h +eval.o: $(hdrdir)/ruby/internal/variable.h +eval.o: $(hdrdir)/ruby/internal/warning_push.h +eval.o: $(hdrdir)/ruby/internal/xmalloc.h +eval.o: $(hdrdir)/ruby/missing.h +eval.o: $(hdrdir)/ruby/ruby.h +eval.o: $(hdrdir)/ruby/st.h +eval.o: $(hdrdir)/ruby/subst.h +eval.o: eval.c +# AUTOGENERATED DEPENDENCIES END diff --git a/ext/-test-/exception/depend b/ext/-test-/exception/depend index 818b4c79dfca25..690e5ad3776231 100644 --- a/ext/-test-/exception/depend +++ b/ext/-test-/exception/depend @@ -127,6 +127,7 @@ dataerror.o: $(hdrdir)/ruby/internal/intern/re.h dataerror.o: $(hdrdir)/ruby/internal/intern/ruby.h dataerror.o: $(hdrdir)/ruby/internal/intern/select.h dataerror.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +dataerror.o: $(hdrdir)/ruby/internal/intern/set.h dataerror.o: $(hdrdir)/ruby/internal/intern/signal.h dataerror.o: $(hdrdir)/ruby/internal/intern/sprintf.h dataerror.o: $(hdrdir)/ruby/internal/intern/string.h @@ -146,6 +147,7 @@ dataerror.o: $(hdrdir)/ruby/internal/special_consts.h dataerror.o: $(hdrdir)/ruby/internal/static_assert.h dataerror.o: $(hdrdir)/ruby/internal/stdalign.h dataerror.o: $(hdrdir)/ruby/internal/stdbool.h +dataerror.o: $(hdrdir)/ruby/internal/stdckdint.h dataerror.o: $(hdrdir)/ruby/internal/symbol.h dataerror.o: $(hdrdir)/ruby/internal/value.h dataerror.o: $(hdrdir)/ruby/internal/value_type.h @@ -296,6 +298,7 @@ enc_raise.o: $(hdrdir)/ruby/internal/intern/re.h enc_raise.o: $(hdrdir)/ruby/internal/intern/ruby.h enc_raise.o: $(hdrdir)/ruby/internal/intern/select.h enc_raise.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +enc_raise.o: $(hdrdir)/ruby/internal/intern/set.h enc_raise.o: $(hdrdir)/ruby/internal/intern/signal.h enc_raise.o: $(hdrdir)/ruby/internal/intern/sprintf.h enc_raise.o: $(hdrdir)/ruby/internal/intern/string.h @@ -315,6 +318,7 @@ enc_raise.o: $(hdrdir)/ruby/internal/special_consts.h enc_raise.o: $(hdrdir)/ruby/internal/static_assert.h enc_raise.o: $(hdrdir)/ruby/internal/stdalign.h enc_raise.o: $(hdrdir)/ruby/internal/stdbool.h +enc_raise.o: $(hdrdir)/ruby/internal/stdckdint.h enc_raise.o: $(hdrdir)/ruby/internal/symbol.h enc_raise.o: $(hdrdir)/ruby/internal/value.h enc_raise.o: $(hdrdir)/ruby/internal/value_type.h @@ -457,6 +461,7 @@ ensured.o: $(hdrdir)/ruby/internal/intern/re.h ensured.o: $(hdrdir)/ruby/internal/intern/ruby.h ensured.o: $(hdrdir)/ruby/internal/intern/select.h ensured.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +ensured.o: $(hdrdir)/ruby/internal/intern/set.h ensured.o: $(hdrdir)/ruby/internal/intern/signal.h ensured.o: $(hdrdir)/ruby/internal/intern/sprintf.h ensured.o: $(hdrdir)/ruby/internal/intern/string.h @@ -476,6 +481,7 @@ ensured.o: $(hdrdir)/ruby/internal/special_consts.h ensured.o: $(hdrdir)/ruby/internal/static_assert.h ensured.o: $(hdrdir)/ruby/internal/stdalign.h ensured.o: $(hdrdir)/ruby/internal/stdbool.h +ensured.o: $(hdrdir)/ruby/internal/stdckdint.h ensured.o: $(hdrdir)/ruby/internal/symbol.h ensured.o: $(hdrdir)/ruby/internal/value.h ensured.o: $(hdrdir)/ruby/internal/value_type.h @@ -616,6 +622,7 @@ init.o: $(hdrdir)/ruby/internal/intern/re.h init.o: $(hdrdir)/ruby/internal/intern/ruby.h init.o: $(hdrdir)/ruby/internal/intern/select.h init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +init.o: $(hdrdir)/ruby/internal/intern/set.h init.o: $(hdrdir)/ruby/internal/intern/signal.h init.o: $(hdrdir)/ruby/internal/intern/sprintf.h init.o: $(hdrdir)/ruby/internal/intern/string.h @@ -635,6 +642,7 @@ init.o: $(hdrdir)/ruby/internal/special_consts.h init.o: $(hdrdir)/ruby/internal/static_assert.h init.o: $(hdrdir)/ruby/internal/stdalign.h init.o: $(hdrdir)/ruby/internal/stdbool.h +init.o: $(hdrdir)/ruby/internal/stdckdint.h init.o: $(hdrdir)/ruby/internal/symbol.h init.o: $(hdrdir)/ruby/internal/value.h init.o: $(hdrdir)/ruby/internal/value_type.h diff --git a/ext/-test-/fatal/depend b/ext/-test-/fatal/depend index 730a72e52a4180..306bc9099c2dbd 100644 --- a/ext/-test-/fatal/depend +++ b/ext/-test-/fatal/depend @@ -1,4 +1,327 @@ # AUTOGENERATED DEPENDENCIES START + +init.o: $(RUBY_EXTCONF_H) +init.o: $(arch_hdrdir)/ruby/config.h +init.o: $(hdrdir)/ruby.h +init.o: $(hdrdir)/ruby/assert.h +init.o: $(hdrdir)/ruby/backward.h +init.o: $(hdrdir)/ruby/backward/2/assume.h +init.o: $(hdrdir)/ruby/backward/2/attributes.h +init.o: $(hdrdir)/ruby/backward/2/bool.h +init.o: $(hdrdir)/ruby/backward/2/inttypes.h +init.o: $(hdrdir)/ruby/backward/2/limits.h +init.o: $(hdrdir)/ruby/backward/2/long_long.h +init.o: $(hdrdir)/ruby/backward/2/stdalign.h +init.o: $(hdrdir)/ruby/backward/2/stdarg.h +init.o: $(hdrdir)/ruby/defines.h +init.o: $(hdrdir)/ruby/intern.h +init.o: $(hdrdir)/ruby/internal/abi.h +init.o: $(hdrdir)/ruby/internal/anyargs.h +init.o: $(hdrdir)/ruby/internal/arithmetic.h +init.o: $(hdrdir)/ruby/internal/arithmetic/char.h +init.o: $(hdrdir)/ruby/internal/arithmetic/double.h +init.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +init.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +init.o: $(hdrdir)/ruby/internal/arithmetic/int.h +init.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +init.o: $(hdrdir)/ruby/internal/arithmetic/long.h +init.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +init.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +init.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +init.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +init.o: $(hdrdir)/ruby/internal/arithmetic/short.h +init.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +init.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +init.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +init.o: $(hdrdir)/ruby/internal/assume.h +init.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +init.o: $(hdrdir)/ruby/internal/attr/artificial.h +init.o: $(hdrdir)/ruby/internal/attr/cold.h +init.o: $(hdrdir)/ruby/internal/attr/const.h +init.o: $(hdrdir)/ruby/internal/attr/constexpr.h +init.o: $(hdrdir)/ruby/internal/attr/deprecated.h +init.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +init.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +init.o: $(hdrdir)/ruby/internal/attr/error.h +init.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +init.o: $(hdrdir)/ruby/internal/attr/forceinline.h +init.o: $(hdrdir)/ruby/internal/attr/format.h +init.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +init.o: $(hdrdir)/ruby/internal/attr/noalias.h +init.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +init.o: $(hdrdir)/ruby/internal/attr/noexcept.h +init.o: $(hdrdir)/ruby/internal/attr/noinline.h +init.o: $(hdrdir)/ruby/internal/attr/nonnull.h +init.o: $(hdrdir)/ruby/internal/attr/noreturn.h +init.o: $(hdrdir)/ruby/internal/attr/packed_struct.h +init.o: $(hdrdir)/ruby/internal/attr/pure.h +init.o: $(hdrdir)/ruby/internal/attr/restrict.h +init.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +init.o: $(hdrdir)/ruby/internal/attr/warning.h +init.o: $(hdrdir)/ruby/internal/attr/weakref.h +init.o: $(hdrdir)/ruby/internal/cast.h +init.o: $(hdrdir)/ruby/internal/compiler_is.h +init.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +init.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +init.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +init.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +init.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +init.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +init.o: $(hdrdir)/ruby/internal/compiler_since.h +init.o: $(hdrdir)/ruby/internal/config.h +init.o: $(hdrdir)/ruby/internal/constant_p.h +init.o: $(hdrdir)/ruby/internal/core.h +init.o: $(hdrdir)/ruby/internal/core/rarray.h +init.o: $(hdrdir)/ruby/internal/core/rbasic.h +init.o: $(hdrdir)/ruby/internal/core/rbignum.h +init.o: $(hdrdir)/ruby/internal/core/rclass.h +init.o: $(hdrdir)/ruby/internal/core/rdata.h +init.o: $(hdrdir)/ruby/internal/core/rfile.h +init.o: $(hdrdir)/ruby/internal/core/rhash.h +init.o: $(hdrdir)/ruby/internal/core/robject.h +init.o: $(hdrdir)/ruby/internal/core/rregexp.h +init.o: $(hdrdir)/ruby/internal/core/rstring.h +init.o: $(hdrdir)/ruby/internal/core/rstruct.h +init.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +init.o: $(hdrdir)/ruby/internal/ctype.h +init.o: $(hdrdir)/ruby/internal/dllexport.h +init.o: $(hdrdir)/ruby/internal/dosish.h +init.o: $(hdrdir)/ruby/internal/error.h +init.o: $(hdrdir)/ruby/internal/eval.h +init.o: $(hdrdir)/ruby/internal/event.h +init.o: $(hdrdir)/ruby/internal/fl_type.h +init.o: $(hdrdir)/ruby/internal/gc.h +init.o: $(hdrdir)/ruby/internal/glob.h +init.o: $(hdrdir)/ruby/internal/globals.h +init.o: $(hdrdir)/ruby/internal/has/attribute.h +init.o: $(hdrdir)/ruby/internal/has/builtin.h +init.o: $(hdrdir)/ruby/internal/has/c_attribute.h +init.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +init.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +init.o: $(hdrdir)/ruby/internal/has/extension.h +init.o: $(hdrdir)/ruby/internal/has/feature.h +init.o: $(hdrdir)/ruby/internal/has/warning.h +init.o: $(hdrdir)/ruby/internal/intern/array.h +init.o: $(hdrdir)/ruby/internal/intern/bignum.h +init.o: $(hdrdir)/ruby/internal/intern/class.h +init.o: $(hdrdir)/ruby/internal/intern/compar.h +init.o: $(hdrdir)/ruby/internal/intern/complex.h +init.o: $(hdrdir)/ruby/internal/intern/cont.h +init.o: $(hdrdir)/ruby/internal/intern/dir.h +init.o: $(hdrdir)/ruby/internal/intern/enum.h +init.o: $(hdrdir)/ruby/internal/intern/enumerator.h +init.o: $(hdrdir)/ruby/internal/intern/error.h +init.o: $(hdrdir)/ruby/internal/intern/eval.h +init.o: $(hdrdir)/ruby/internal/intern/file.h +init.o: $(hdrdir)/ruby/internal/intern/hash.h +init.o: $(hdrdir)/ruby/internal/intern/io.h +init.o: $(hdrdir)/ruby/internal/intern/load.h +init.o: $(hdrdir)/ruby/internal/intern/marshal.h +init.o: $(hdrdir)/ruby/internal/intern/numeric.h +init.o: $(hdrdir)/ruby/internal/intern/object.h +init.o: $(hdrdir)/ruby/internal/intern/parse.h +init.o: $(hdrdir)/ruby/internal/intern/proc.h +init.o: $(hdrdir)/ruby/internal/intern/process.h +init.o: $(hdrdir)/ruby/internal/intern/random.h +init.o: $(hdrdir)/ruby/internal/intern/range.h +init.o: $(hdrdir)/ruby/internal/intern/rational.h +init.o: $(hdrdir)/ruby/internal/intern/re.h +init.o: $(hdrdir)/ruby/internal/intern/ruby.h +init.o: $(hdrdir)/ruby/internal/intern/select.h +init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +init.o: $(hdrdir)/ruby/internal/intern/set.h +init.o: $(hdrdir)/ruby/internal/intern/signal.h +init.o: $(hdrdir)/ruby/internal/intern/sprintf.h +init.o: $(hdrdir)/ruby/internal/intern/string.h +init.o: $(hdrdir)/ruby/internal/intern/struct.h +init.o: $(hdrdir)/ruby/internal/intern/thread.h +init.o: $(hdrdir)/ruby/internal/intern/time.h +init.o: $(hdrdir)/ruby/internal/intern/variable.h +init.o: $(hdrdir)/ruby/internal/intern/vm.h +init.o: $(hdrdir)/ruby/internal/interpreter.h +init.o: $(hdrdir)/ruby/internal/iterator.h +init.o: $(hdrdir)/ruby/internal/memory.h +init.o: $(hdrdir)/ruby/internal/method.h +init.o: $(hdrdir)/ruby/internal/module.h +init.o: $(hdrdir)/ruby/internal/newobj.h +init.o: $(hdrdir)/ruby/internal/scan_args.h +init.o: $(hdrdir)/ruby/internal/special_consts.h +init.o: $(hdrdir)/ruby/internal/static_assert.h +init.o: $(hdrdir)/ruby/internal/stdalign.h +init.o: $(hdrdir)/ruby/internal/stdbool.h +init.o: $(hdrdir)/ruby/internal/stdckdint.h +init.o: $(hdrdir)/ruby/internal/symbol.h +init.o: $(hdrdir)/ruby/internal/value.h +init.o: $(hdrdir)/ruby/internal/value_type.h +init.o: $(hdrdir)/ruby/internal/variable.h +init.o: $(hdrdir)/ruby/internal/warning_push.h +init.o: $(hdrdir)/ruby/internal/xmalloc.h +init.o: $(hdrdir)/ruby/missing.h +init.o: $(hdrdir)/ruby/ruby.h +init.o: $(hdrdir)/ruby/st.h +init.o: $(hdrdir)/ruby/subst.h +init.o: init.c +invalid.o: $(RUBY_EXTCONF_H) +invalid.o: $(arch_hdrdir)/ruby/config.h +invalid.o: $(hdrdir)/ruby.h +invalid.o: $(hdrdir)/ruby/assert.h +invalid.o: $(hdrdir)/ruby/backward.h +invalid.o: $(hdrdir)/ruby/backward/2/assume.h +invalid.o: $(hdrdir)/ruby/backward/2/attributes.h +invalid.o: $(hdrdir)/ruby/backward/2/bool.h +invalid.o: $(hdrdir)/ruby/backward/2/inttypes.h +invalid.o: $(hdrdir)/ruby/backward/2/limits.h +invalid.o: $(hdrdir)/ruby/backward/2/long_long.h +invalid.o: $(hdrdir)/ruby/backward/2/stdalign.h +invalid.o: $(hdrdir)/ruby/backward/2/stdarg.h +invalid.o: $(hdrdir)/ruby/defines.h +invalid.o: $(hdrdir)/ruby/intern.h +invalid.o: $(hdrdir)/ruby/internal/abi.h +invalid.o: $(hdrdir)/ruby/internal/anyargs.h +invalid.o: $(hdrdir)/ruby/internal/arithmetic.h +invalid.o: $(hdrdir)/ruby/internal/arithmetic/char.h +invalid.o: $(hdrdir)/ruby/internal/arithmetic/double.h +invalid.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +invalid.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +invalid.o: $(hdrdir)/ruby/internal/arithmetic/int.h +invalid.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +invalid.o: $(hdrdir)/ruby/internal/arithmetic/long.h +invalid.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +invalid.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +invalid.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +invalid.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +invalid.o: $(hdrdir)/ruby/internal/arithmetic/short.h +invalid.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +invalid.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +invalid.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +invalid.o: $(hdrdir)/ruby/internal/assume.h +invalid.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +invalid.o: $(hdrdir)/ruby/internal/attr/artificial.h +invalid.o: $(hdrdir)/ruby/internal/attr/cold.h +invalid.o: $(hdrdir)/ruby/internal/attr/const.h +invalid.o: $(hdrdir)/ruby/internal/attr/constexpr.h +invalid.o: $(hdrdir)/ruby/internal/attr/deprecated.h +invalid.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +invalid.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +invalid.o: $(hdrdir)/ruby/internal/attr/error.h +invalid.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +invalid.o: $(hdrdir)/ruby/internal/attr/forceinline.h +invalid.o: $(hdrdir)/ruby/internal/attr/format.h +invalid.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +invalid.o: $(hdrdir)/ruby/internal/attr/noalias.h +invalid.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +invalid.o: $(hdrdir)/ruby/internal/attr/noexcept.h +invalid.o: $(hdrdir)/ruby/internal/attr/noinline.h +invalid.o: $(hdrdir)/ruby/internal/attr/nonnull.h +invalid.o: $(hdrdir)/ruby/internal/attr/noreturn.h +invalid.o: $(hdrdir)/ruby/internal/attr/packed_struct.h +invalid.o: $(hdrdir)/ruby/internal/attr/pure.h +invalid.o: $(hdrdir)/ruby/internal/attr/restrict.h +invalid.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +invalid.o: $(hdrdir)/ruby/internal/attr/warning.h +invalid.o: $(hdrdir)/ruby/internal/attr/weakref.h +invalid.o: $(hdrdir)/ruby/internal/cast.h +invalid.o: $(hdrdir)/ruby/internal/compiler_is.h +invalid.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +invalid.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +invalid.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +invalid.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +invalid.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +invalid.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +invalid.o: $(hdrdir)/ruby/internal/compiler_since.h +invalid.o: $(hdrdir)/ruby/internal/config.h +invalid.o: $(hdrdir)/ruby/internal/constant_p.h +invalid.o: $(hdrdir)/ruby/internal/core.h +invalid.o: $(hdrdir)/ruby/internal/core/rarray.h +invalid.o: $(hdrdir)/ruby/internal/core/rbasic.h +invalid.o: $(hdrdir)/ruby/internal/core/rbignum.h +invalid.o: $(hdrdir)/ruby/internal/core/rclass.h +invalid.o: $(hdrdir)/ruby/internal/core/rdata.h +invalid.o: $(hdrdir)/ruby/internal/core/rfile.h +invalid.o: $(hdrdir)/ruby/internal/core/rhash.h +invalid.o: $(hdrdir)/ruby/internal/core/robject.h +invalid.o: $(hdrdir)/ruby/internal/core/rregexp.h +invalid.o: $(hdrdir)/ruby/internal/core/rstring.h +invalid.o: $(hdrdir)/ruby/internal/core/rstruct.h +invalid.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +invalid.o: $(hdrdir)/ruby/internal/ctype.h +invalid.o: $(hdrdir)/ruby/internal/dllexport.h +invalid.o: $(hdrdir)/ruby/internal/dosish.h +invalid.o: $(hdrdir)/ruby/internal/error.h +invalid.o: $(hdrdir)/ruby/internal/eval.h +invalid.o: $(hdrdir)/ruby/internal/event.h +invalid.o: $(hdrdir)/ruby/internal/fl_type.h +invalid.o: $(hdrdir)/ruby/internal/gc.h +invalid.o: $(hdrdir)/ruby/internal/glob.h +invalid.o: $(hdrdir)/ruby/internal/globals.h +invalid.o: $(hdrdir)/ruby/internal/has/attribute.h +invalid.o: $(hdrdir)/ruby/internal/has/builtin.h +invalid.o: $(hdrdir)/ruby/internal/has/c_attribute.h +invalid.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +invalid.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +invalid.o: $(hdrdir)/ruby/internal/has/extension.h +invalid.o: $(hdrdir)/ruby/internal/has/feature.h +invalid.o: $(hdrdir)/ruby/internal/has/warning.h +invalid.o: $(hdrdir)/ruby/internal/intern/array.h +invalid.o: $(hdrdir)/ruby/internal/intern/bignum.h +invalid.o: $(hdrdir)/ruby/internal/intern/class.h +invalid.o: $(hdrdir)/ruby/internal/intern/compar.h +invalid.o: $(hdrdir)/ruby/internal/intern/complex.h +invalid.o: $(hdrdir)/ruby/internal/intern/cont.h +invalid.o: $(hdrdir)/ruby/internal/intern/dir.h +invalid.o: $(hdrdir)/ruby/internal/intern/enum.h +invalid.o: $(hdrdir)/ruby/internal/intern/enumerator.h +invalid.o: $(hdrdir)/ruby/internal/intern/error.h +invalid.o: $(hdrdir)/ruby/internal/intern/eval.h +invalid.o: $(hdrdir)/ruby/internal/intern/file.h +invalid.o: $(hdrdir)/ruby/internal/intern/hash.h +invalid.o: $(hdrdir)/ruby/internal/intern/io.h +invalid.o: $(hdrdir)/ruby/internal/intern/load.h +invalid.o: $(hdrdir)/ruby/internal/intern/marshal.h +invalid.o: $(hdrdir)/ruby/internal/intern/numeric.h +invalid.o: $(hdrdir)/ruby/internal/intern/object.h +invalid.o: $(hdrdir)/ruby/internal/intern/parse.h +invalid.o: $(hdrdir)/ruby/internal/intern/proc.h +invalid.o: $(hdrdir)/ruby/internal/intern/process.h +invalid.o: $(hdrdir)/ruby/internal/intern/random.h +invalid.o: $(hdrdir)/ruby/internal/intern/range.h +invalid.o: $(hdrdir)/ruby/internal/intern/rational.h +invalid.o: $(hdrdir)/ruby/internal/intern/re.h +invalid.o: $(hdrdir)/ruby/internal/intern/ruby.h +invalid.o: $(hdrdir)/ruby/internal/intern/select.h +invalid.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +invalid.o: $(hdrdir)/ruby/internal/intern/set.h +invalid.o: $(hdrdir)/ruby/internal/intern/signal.h +invalid.o: $(hdrdir)/ruby/internal/intern/sprintf.h +invalid.o: $(hdrdir)/ruby/internal/intern/string.h +invalid.o: $(hdrdir)/ruby/internal/intern/struct.h +invalid.o: $(hdrdir)/ruby/internal/intern/thread.h +invalid.o: $(hdrdir)/ruby/internal/intern/time.h +invalid.o: $(hdrdir)/ruby/internal/intern/variable.h +invalid.o: $(hdrdir)/ruby/internal/intern/vm.h +invalid.o: $(hdrdir)/ruby/internal/interpreter.h +invalid.o: $(hdrdir)/ruby/internal/iterator.h +invalid.o: $(hdrdir)/ruby/internal/memory.h +invalid.o: $(hdrdir)/ruby/internal/method.h +invalid.o: $(hdrdir)/ruby/internal/module.h +invalid.o: $(hdrdir)/ruby/internal/newobj.h +invalid.o: $(hdrdir)/ruby/internal/scan_args.h +invalid.o: $(hdrdir)/ruby/internal/special_consts.h +invalid.o: $(hdrdir)/ruby/internal/static_assert.h +invalid.o: $(hdrdir)/ruby/internal/stdalign.h +invalid.o: $(hdrdir)/ruby/internal/stdbool.h +invalid.o: $(hdrdir)/ruby/internal/stdckdint.h +invalid.o: $(hdrdir)/ruby/internal/symbol.h +invalid.o: $(hdrdir)/ruby/internal/value.h +invalid.o: $(hdrdir)/ruby/internal/value_type.h +invalid.o: $(hdrdir)/ruby/internal/variable.h +invalid.o: $(hdrdir)/ruby/internal/warning_push.h +invalid.o: $(hdrdir)/ruby/internal/xmalloc.h +invalid.o: $(hdrdir)/ruby/missing.h +invalid.o: $(hdrdir)/ruby/ruby.h +invalid.o: $(hdrdir)/ruby/st.h +invalid.o: $(hdrdir)/ruby/subst.h +invalid.o: invalid.c rb_fatal.o: $(RUBY_EXTCONF_H) rb_fatal.o: $(arch_hdrdir)/ruby/config.h rb_fatal.o: $(hdrdir)/ruby.h @@ -128,6 +451,7 @@ rb_fatal.o: $(hdrdir)/ruby/internal/intern/re.h rb_fatal.o: $(hdrdir)/ruby/internal/intern/ruby.h rb_fatal.o: $(hdrdir)/ruby/internal/intern/select.h rb_fatal.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +rb_fatal.o: $(hdrdir)/ruby/internal/intern/set.h rb_fatal.o: $(hdrdir)/ruby/internal/intern/signal.h rb_fatal.o: $(hdrdir)/ruby/internal/intern/sprintf.h rb_fatal.o: $(hdrdir)/ruby/internal/intern/string.h @@ -147,6 +471,7 @@ rb_fatal.o: $(hdrdir)/ruby/internal/special_consts.h rb_fatal.o: $(hdrdir)/ruby/internal/static_assert.h rb_fatal.o: $(hdrdir)/ruby/internal/stdalign.h rb_fatal.o: $(hdrdir)/ruby/internal/stdbool.h +rb_fatal.o: $(hdrdir)/ruby/internal/stdckdint.h rb_fatal.o: $(hdrdir)/ruby/internal/symbol.h rb_fatal.o: $(hdrdir)/ruby/internal/value.h rb_fatal.o: $(hdrdir)/ruby/internal/value_type.h diff --git a/ext/-test-/fatal/extconf.rb b/ext/-test-/fatal/extconf.rb index d5849c073328b5..ca51178a18b200 100644 --- a/ext/-test-/fatal/extconf.rb +++ b/ext/-test-/fatal/extconf.rb @@ -1,2 +1,3 @@ # frozen_string_literal: false -create_makefile("-test-/fatal/rb_fatal") +require_relative "../auto_ext.rb" +auto_ext diff --git a/ext/-test-/fatal/init.c b/ext/-test-/fatal/init.c new file mode 100644 index 00000000000000..3b71708789502c --- /dev/null +++ b/ext/-test-/fatal/init.c @@ -0,0 +1,10 @@ +#include "ruby.h" + +#define init(n) {void Init_##n(VALUE klass); Init_##n(klass);} + +void +Init_fatal(void) +{ + VALUE klass = rb_define_module("Bug"); + TEST_INIT_FUNCS(init); +} diff --git a/ext/-test-/fatal/invalid.c b/ext/-test-/fatal/invalid.c new file mode 100644 index 00000000000000..393465416a0f6c --- /dev/null +++ b/ext/-test-/fatal/invalid.c @@ -0,0 +1,28 @@ +#include + +#if SIZEOF_LONG == SIZEOF_VOIDP +# define NUM2PTR(x) NUM2ULONG(x) +#elif SIZEOF_LONG_LONG == SIZEOF_VOIDP +# define NUM2PTR(x) NUM2ULL(x) +#endif + +static VALUE +invalid_call(VALUE obj, VALUE address) +{ + typedef VALUE (*func_type)(VALUE); + + return (*(func_type)NUM2PTR(address))(obj); +} + +static VALUE +invalid_access(VALUE obj, VALUE address) +{ + return *(VALUE *)NUM2PTR(address) == obj ? Qtrue : Qfalse; +} + +void +Init_invalid(VALUE mBug) +{ + rb_define_singleton_method(mBug, "invalid_call", invalid_call, 1); + rb_define_singleton_method(mBug, "invalid_access", invalid_access, 1); +} diff --git a/ext/-test-/fatal/rb_fatal.c b/ext/-test-/fatal/rb_fatal.c index eedbc51f8b83d6..6c7bb89628fdd4 100644 --- a/ext/-test-/fatal/rb_fatal.c +++ b/ext/-test-/fatal/rb_fatal.c @@ -13,8 +13,7 @@ ruby_fatal(VALUE obj, VALUE msg) } void -Init_rb_fatal(void) +Init_rb_fatal(VALUE mBug) { - VALUE mBug = rb_define_module("Bug"); rb_define_singleton_method(mBug, "rb_fatal", ruby_fatal, 1); } diff --git a/ext/-test-/file/depend b/ext/-test-/file/depend index 662136f1ba069b..fe320f3d44a98f 100644 --- a/ext/-test-/file/depend +++ b/ext/-test-/file/depend @@ -137,6 +137,7 @@ fs.o: $(hdrdir)/ruby/internal/intern/re.h fs.o: $(hdrdir)/ruby/internal/intern/ruby.h fs.o: $(hdrdir)/ruby/internal/intern/select.h fs.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +fs.o: $(hdrdir)/ruby/internal/intern/set.h fs.o: $(hdrdir)/ruby/internal/intern/signal.h fs.o: $(hdrdir)/ruby/internal/intern/sprintf.h fs.o: $(hdrdir)/ruby/internal/intern/string.h @@ -156,6 +157,7 @@ fs.o: $(hdrdir)/ruby/internal/special_consts.h fs.o: $(hdrdir)/ruby/internal/static_assert.h fs.o: $(hdrdir)/ruby/internal/stdalign.h fs.o: $(hdrdir)/ruby/internal/stdbool.h +fs.o: $(hdrdir)/ruby/internal/stdckdint.h fs.o: $(hdrdir)/ruby/internal/symbol.h fs.o: $(hdrdir)/ruby/internal/value.h fs.o: $(hdrdir)/ruby/internal/value_type.h @@ -299,6 +301,7 @@ init.o: $(hdrdir)/ruby/internal/intern/re.h init.o: $(hdrdir)/ruby/internal/intern/ruby.h init.o: $(hdrdir)/ruby/internal/intern/select.h init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +init.o: $(hdrdir)/ruby/internal/intern/set.h init.o: $(hdrdir)/ruby/internal/intern/signal.h init.o: $(hdrdir)/ruby/internal/intern/sprintf.h init.o: $(hdrdir)/ruby/internal/intern/string.h @@ -318,6 +321,7 @@ init.o: $(hdrdir)/ruby/internal/special_consts.h init.o: $(hdrdir)/ruby/internal/static_assert.h init.o: $(hdrdir)/ruby/internal/stdalign.h init.o: $(hdrdir)/ruby/internal/stdbool.h +init.o: $(hdrdir)/ruby/internal/stdckdint.h init.o: $(hdrdir)/ruby/internal/symbol.h init.o: $(hdrdir)/ruby/internal/value.h init.o: $(hdrdir)/ruby/internal/value_type.h @@ -329,6 +333,179 @@ init.o: $(hdrdir)/ruby/ruby.h init.o: $(hdrdir)/ruby/st.h init.o: $(hdrdir)/ruby/subst.h init.o: init.c +newline_conv.o: $(RUBY_EXTCONF_H) +newline_conv.o: $(arch_hdrdir)/ruby/config.h +newline_conv.o: $(hdrdir)/ruby/assert.h +newline_conv.o: $(hdrdir)/ruby/backward.h +newline_conv.o: $(hdrdir)/ruby/backward/2/assume.h +newline_conv.o: $(hdrdir)/ruby/backward/2/attributes.h +newline_conv.o: $(hdrdir)/ruby/backward/2/bool.h +newline_conv.o: $(hdrdir)/ruby/backward/2/inttypes.h +newline_conv.o: $(hdrdir)/ruby/backward/2/limits.h +newline_conv.o: $(hdrdir)/ruby/backward/2/long_long.h +newline_conv.o: $(hdrdir)/ruby/backward/2/stdalign.h +newline_conv.o: $(hdrdir)/ruby/backward/2/stdarg.h +newline_conv.o: $(hdrdir)/ruby/defines.h +newline_conv.o: $(hdrdir)/ruby/encoding.h +newline_conv.o: $(hdrdir)/ruby/intern.h +newline_conv.o: $(hdrdir)/ruby/internal/abi.h +newline_conv.o: $(hdrdir)/ruby/internal/anyargs.h +newline_conv.o: $(hdrdir)/ruby/internal/arithmetic.h +newline_conv.o: $(hdrdir)/ruby/internal/arithmetic/char.h +newline_conv.o: $(hdrdir)/ruby/internal/arithmetic/double.h +newline_conv.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +newline_conv.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +newline_conv.o: $(hdrdir)/ruby/internal/arithmetic/int.h +newline_conv.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +newline_conv.o: $(hdrdir)/ruby/internal/arithmetic/long.h +newline_conv.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +newline_conv.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +newline_conv.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +newline_conv.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +newline_conv.o: $(hdrdir)/ruby/internal/arithmetic/short.h +newline_conv.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +newline_conv.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +newline_conv.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +newline_conv.o: $(hdrdir)/ruby/internal/assume.h +newline_conv.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +newline_conv.o: $(hdrdir)/ruby/internal/attr/artificial.h +newline_conv.o: $(hdrdir)/ruby/internal/attr/cold.h +newline_conv.o: $(hdrdir)/ruby/internal/attr/const.h +newline_conv.o: $(hdrdir)/ruby/internal/attr/constexpr.h +newline_conv.o: $(hdrdir)/ruby/internal/attr/deprecated.h +newline_conv.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +newline_conv.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +newline_conv.o: $(hdrdir)/ruby/internal/attr/error.h +newline_conv.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +newline_conv.o: $(hdrdir)/ruby/internal/attr/forceinline.h +newline_conv.o: $(hdrdir)/ruby/internal/attr/format.h +newline_conv.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +newline_conv.o: $(hdrdir)/ruby/internal/attr/noalias.h +newline_conv.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +newline_conv.o: $(hdrdir)/ruby/internal/attr/noexcept.h +newline_conv.o: $(hdrdir)/ruby/internal/attr/noinline.h +newline_conv.o: $(hdrdir)/ruby/internal/attr/nonnull.h +newline_conv.o: $(hdrdir)/ruby/internal/attr/noreturn.h +newline_conv.o: $(hdrdir)/ruby/internal/attr/packed_struct.h +newline_conv.o: $(hdrdir)/ruby/internal/attr/pure.h +newline_conv.o: $(hdrdir)/ruby/internal/attr/restrict.h +newline_conv.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +newline_conv.o: $(hdrdir)/ruby/internal/attr/warning.h +newline_conv.o: $(hdrdir)/ruby/internal/attr/weakref.h +newline_conv.o: $(hdrdir)/ruby/internal/cast.h +newline_conv.o: $(hdrdir)/ruby/internal/compiler_is.h +newline_conv.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +newline_conv.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +newline_conv.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +newline_conv.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +newline_conv.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +newline_conv.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +newline_conv.o: $(hdrdir)/ruby/internal/compiler_since.h +newline_conv.o: $(hdrdir)/ruby/internal/config.h +newline_conv.o: $(hdrdir)/ruby/internal/constant_p.h +newline_conv.o: $(hdrdir)/ruby/internal/core.h +newline_conv.o: $(hdrdir)/ruby/internal/core/rarray.h +newline_conv.o: $(hdrdir)/ruby/internal/core/rbasic.h +newline_conv.o: $(hdrdir)/ruby/internal/core/rbignum.h +newline_conv.o: $(hdrdir)/ruby/internal/core/rclass.h +newline_conv.o: $(hdrdir)/ruby/internal/core/rdata.h +newline_conv.o: $(hdrdir)/ruby/internal/core/rfile.h +newline_conv.o: $(hdrdir)/ruby/internal/core/rhash.h +newline_conv.o: $(hdrdir)/ruby/internal/core/robject.h +newline_conv.o: $(hdrdir)/ruby/internal/core/rregexp.h +newline_conv.o: $(hdrdir)/ruby/internal/core/rstring.h +newline_conv.o: $(hdrdir)/ruby/internal/core/rstruct.h +newline_conv.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +newline_conv.o: $(hdrdir)/ruby/internal/ctype.h +newline_conv.o: $(hdrdir)/ruby/internal/dllexport.h +newline_conv.o: $(hdrdir)/ruby/internal/dosish.h +newline_conv.o: $(hdrdir)/ruby/internal/encoding/coderange.h +newline_conv.o: $(hdrdir)/ruby/internal/encoding/ctype.h +newline_conv.o: $(hdrdir)/ruby/internal/encoding/encoding.h +newline_conv.o: $(hdrdir)/ruby/internal/encoding/pathname.h +newline_conv.o: $(hdrdir)/ruby/internal/encoding/re.h +newline_conv.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +newline_conv.o: $(hdrdir)/ruby/internal/encoding/string.h +newline_conv.o: $(hdrdir)/ruby/internal/encoding/symbol.h +newline_conv.o: $(hdrdir)/ruby/internal/encoding/transcode.h +newline_conv.o: $(hdrdir)/ruby/internal/error.h +newline_conv.o: $(hdrdir)/ruby/internal/eval.h +newline_conv.o: $(hdrdir)/ruby/internal/event.h +newline_conv.o: $(hdrdir)/ruby/internal/fl_type.h +newline_conv.o: $(hdrdir)/ruby/internal/gc.h +newline_conv.o: $(hdrdir)/ruby/internal/glob.h +newline_conv.o: $(hdrdir)/ruby/internal/globals.h +newline_conv.o: $(hdrdir)/ruby/internal/has/attribute.h +newline_conv.o: $(hdrdir)/ruby/internal/has/builtin.h +newline_conv.o: $(hdrdir)/ruby/internal/has/c_attribute.h +newline_conv.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +newline_conv.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +newline_conv.o: $(hdrdir)/ruby/internal/has/extension.h +newline_conv.o: $(hdrdir)/ruby/internal/has/feature.h +newline_conv.o: $(hdrdir)/ruby/internal/has/warning.h +newline_conv.o: $(hdrdir)/ruby/internal/intern/array.h +newline_conv.o: $(hdrdir)/ruby/internal/intern/bignum.h +newline_conv.o: $(hdrdir)/ruby/internal/intern/class.h +newline_conv.o: $(hdrdir)/ruby/internal/intern/compar.h +newline_conv.o: $(hdrdir)/ruby/internal/intern/complex.h +newline_conv.o: $(hdrdir)/ruby/internal/intern/cont.h +newline_conv.o: $(hdrdir)/ruby/internal/intern/dir.h +newline_conv.o: $(hdrdir)/ruby/internal/intern/enum.h +newline_conv.o: $(hdrdir)/ruby/internal/intern/enumerator.h +newline_conv.o: $(hdrdir)/ruby/internal/intern/error.h +newline_conv.o: $(hdrdir)/ruby/internal/intern/eval.h +newline_conv.o: $(hdrdir)/ruby/internal/intern/file.h +newline_conv.o: $(hdrdir)/ruby/internal/intern/hash.h +newline_conv.o: $(hdrdir)/ruby/internal/intern/io.h +newline_conv.o: $(hdrdir)/ruby/internal/intern/load.h +newline_conv.o: $(hdrdir)/ruby/internal/intern/marshal.h +newline_conv.o: $(hdrdir)/ruby/internal/intern/numeric.h +newline_conv.o: $(hdrdir)/ruby/internal/intern/object.h +newline_conv.o: $(hdrdir)/ruby/internal/intern/parse.h +newline_conv.o: $(hdrdir)/ruby/internal/intern/proc.h +newline_conv.o: $(hdrdir)/ruby/internal/intern/process.h +newline_conv.o: $(hdrdir)/ruby/internal/intern/random.h +newline_conv.o: $(hdrdir)/ruby/internal/intern/range.h +newline_conv.o: $(hdrdir)/ruby/internal/intern/rational.h +newline_conv.o: $(hdrdir)/ruby/internal/intern/re.h +newline_conv.o: $(hdrdir)/ruby/internal/intern/ruby.h +newline_conv.o: $(hdrdir)/ruby/internal/intern/select.h +newline_conv.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +newline_conv.o: $(hdrdir)/ruby/internal/intern/set.h +newline_conv.o: $(hdrdir)/ruby/internal/intern/signal.h +newline_conv.o: $(hdrdir)/ruby/internal/intern/sprintf.h +newline_conv.o: $(hdrdir)/ruby/internal/intern/string.h +newline_conv.o: $(hdrdir)/ruby/internal/intern/struct.h +newline_conv.o: $(hdrdir)/ruby/internal/intern/thread.h +newline_conv.o: $(hdrdir)/ruby/internal/intern/time.h +newline_conv.o: $(hdrdir)/ruby/internal/intern/variable.h +newline_conv.o: $(hdrdir)/ruby/internal/intern/vm.h +newline_conv.o: $(hdrdir)/ruby/internal/interpreter.h +newline_conv.o: $(hdrdir)/ruby/internal/iterator.h +newline_conv.o: $(hdrdir)/ruby/internal/memory.h +newline_conv.o: $(hdrdir)/ruby/internal/method.h +newline_conv.o: $(hdrdir)/ruby/internal/module.h +newline_conv.o: $(hdrdir)/ruby/internal/newobj.h +newline_conv.o: $(hdrdir)/ruby/internal/scan_args.h +newline_conv.o: $(hdrdir)/ruby/internal/special_consts.h +newline_conv.o: $(hdrdir)/ruby/internal/static_assert.h +newline_conv.o: $(hdrdir)/ruby/internal/stdalign.h +newline_conv.o: $(hdrdir)/ruby/internal/stdbool.h +newline_conv.o: $(hdrdir)/ruby/internal/stdckdint.h +newline_conv.o: $(hdrdir)/ruby/internal/symbol.h +newline_conv.o: $(hdrdir)/ruby/internal/value.h +newline_conv.o: $(hdrdir)/ruby/internal/value_type.h +newline_conv.o: $(hdrdir)/ruby/internal/variable.h +newline_conv.o: $(hdrdir)/ruby/internal/warning_push.h +newline_conv.o: $(hdrdir)/ruby/internal/xmalloc.h +newline_conv.o: $(hdrdir)/ruby/io.h +newline_conv.o: $(hdrdir)/ruby/missing.h +newline_conv.o: $(hdrdir)/ruby/onigmo.h +newline_conv.o: $(hdrdir)/ruby/oniguruma.h +newline_conv.o: $(hdrdir)/ruby/ruby.h +newline_conv.o: $(hdrdir)/ruby/st.h +newline_conv.o: $(hdrdir)/ruby/subst.h +newline_conv.o: newline_conv.c stat.o: $(RUBY_EXTCONF_H) stat.o: $(arch_hdrdir)/ruby/config.h stat.o: $(hdrdir)/ruby/assert.h @@ -467,6 +644,7 @@ stat.o: $(hdrdir)/ruby/internal/intern/re.h stat.o: $(hdrdir)/ruby/internal/intern/ruby.h stat.o: $(hdrdir)/ruby/internal/intern/select.h stat.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +stat.o: $(hdrdir)/ruby/internal/intern/set.h stat.o: $(hdrdir)/ruby/internal/intern/signal.h stat.o: $(hdrdir)/ruby/internal/intern/sprintf.h stat.o: $(hdrdir)/ruby/internal/intern/string.h @@ -486,6 +664,7 @@ stat.o: $(hdrdir)/ruby/internal/special_consts.h stat.o: $(hdrdir)/ruby/internal/static_assert.h stat.o: $(hdrdir)/ruby/internal/stdalign.h stat.o: $(hdrdir)/ruby/internal/stdbool.h +stat.o: $(hdrdir)/ruby/internal/stdckdint.h stat.o: $(hdrdir)/ruby/internal/symbol.h stat.o: $(hdrdir)/ruby/internal/value.h stat.o: $(hdrdir)/ruby/internal/value_type.h diff --git a/ext/-test-/file/newline_conv.c b/ext/-test-/file/newline_conv.c new file mode 100644 index 00000000000000..2ac5aef801ef7f --- /dev/null +++ b/ext/-test-/file/newline_conv.c @@ -0,0 +1,73 @@ +#include "ruby/ruby.h" +#include "ruby/io.h" +#include + +static VALUE +open_with_rb_file_open(VALUE self, VALUE filename, VALUE read_or_write, VALUE binary_or_text) +{ + char fmode[3] = { 0 }; + if (rb_sym2id(read_or_write) == rb_intern("read")) { + fmode[0] = 'r'; + } + else if (rb_sym2id(read_or_write) == rb_intern("write")) { + fmode[0] = 'w'; + } + else { + rb_raise(rb_eArgError, "read_or_write param must be :read or :write"); + } + + if (rb_sym2id(binary_or_text) == rb_intern("binary")) { + fmode[1] = 'b'; + } + else if (rb_sym2id(binary_or_text) == rb_intern("text")) { + + } + else { + rb_raise(rb_eArgError, "binary_or_text param must be :binary or :text"); + } + + return rb_file_open(StringValueCStr(filename), fmode); +} + +static VALUE +open_with_rb_io_fdopen(VALUE self, VALUE filename, VALUE read_or_write, VALUE binary_or_text) +{ + int omode = 0; + if (rb_sym2id(read_or_write) == rb_intern("read")) { + omode |= O_RDONLY; + } + else if (rb_sym2id(read_or_write) == rb_intern("write")) { + omode |= O_WRONLY; + } + else { + rb_raise(rb_eArgError, "read_or_write param must be :read or :write"); + } + + if (rb_sym2id(binary_or_text) == rb_intern("binary")) { +#ifdef O_BINARY + omode |= O_BINARY; +#endif + } + else if (rb_sym2id(binary_or_text) == rb_intern("text")) { + + } + else { + rb_raise(rb_eArgError, "binary_or_text param must be :binary or :text"); + } + + int fd = rb_cloexec_open(StringValueCStr(filename), omode, 0); + if (fd < 0) { + rb_raise(rb_eIOError, "failed to open the file"); + } + + rb_update_max_fd(fd); + return rb_io_fdopen(fd, omode, StringValueCStr(filename)); +} + +void +Init_newline_conv(VALUE module) +{ + VALUE newline_conv = rb_define_module_under(module, "NewlineConv"); + rb_define_module_function(newline_conv, "rb_file_open", open_with_rb_file_open, 3); + rb_define_module_function(newline_conv, "rb_io_fdopen", open_with_rb_io_fdopen, 3); +} diff --git a/ext/-test-/float/depend b/ext/-test-/float/depend index 9580a0416c4d6e..334ed33c3b2299 100644 --- a/ext/-test-/float/depend +++ b/ext/-test-/float/depend @@ -131,6 +131,7 @@ init.o: $(hdrdir)/ruby/internal/intern/re.h init.o: $(hdrdir)/ruby/internal/intern/ruby.h init.o: $(hdrdir)/ruby/internal/intern/select.h init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +init.o: $(hdrdir)/ruby/internal/intern/set.h init.o: $(hdrdir)/ruby/internal/intern/signal.h init.o: $(hdrdir)/ruby/internal/intern/sprintf.h init.o: $(hdrdir)/ruby/internal/intern/string.h @@ -150,6 +151,7 @@ init.o: $(hdrdir)/ruby/internal/special_consts.h init.o: $(hdrdir)/ruby/internal/static_assert.h init.o: $(hdrdir)/ruby/internal/stdalign.h init.o: $(hdrdir)/ruby/internal/stdbool.h +init.o: $(hdrdir)/ruby/internal/stdckdint.h init.o: $(hdrdir)/ruby/internal/symbol.h init.o: $(hdrdir)/ruby/internal/value.h init.o: $(hdrdir)/ruby/internal/value_type.h @@ -290,6 +292,7 @@ nextafter.o: $(hdrdir)/ruby/internal/intern/re.h nextafter.o: $(hdrdir)/ruby/internal/intern/ruby.h nextafter.o: $(hdrdir)/ruby/internal/intern/select.h nextafter.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +nextafter.o: $(hdrdir)/ruby/internal/intern/set.h nextafter.o: $(hdrdir)/ruby/internal/intern/signal.h nextafter.o: $(hdrdir)/ruby/internal/intern/sprintf.h nextafter.o: $(hdrdir)/ruby/internal/intern/string.h @@ -309,6 +312,7 @@ nextafter.o: $(hdrdir)/ruby/internal/special_consts.h nextafter.o: $(hdrdir)/ruby/internal/static_assert.h nextafter.o: $(hdrdir)/ruby/internal/stdalign.h nextafter.o: $(hdrdir)/ruby/internal/stdbool.h +nextafter.o: $(hdrdir)/ruby/internal/stdckdint.h nextafter.o: $(hdrdir)/ruby/internal/symbol.h nextafter.o: $(hdrdir)/ruby/internal/value.h nextafter.o: $(hdrdir)/ruby/internal/value_type.h diff --git a/ext/-test-/funcall/depend b/ext/-test-/funcall/depend index 6719e4e6760489..e54370306f47ca 100644 --- a/ext/-test-/funcall/depend +++ b/ext/-test-/funcall/depend @@ -128,6 +128,7 @@ funcall.o: $(hdrdir)/ruby/internal/intern/re.h funcall.o: $(hdrdir)/ruby/internal/intern/ruby.h funcall.o: $(hdrdir)/ruby/internal/intern/select.h funcall.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +funcall.o: $(hdrdir)/ruby/internal/intern/set.h funcall.o: $(hdrdir)/ruby/internal/intern/signal.h funcall.o: $(hdrdir)/ruby/internal/intern/sprintf.h funcall.o: $(hdrdir)/ruby/internal/intern/string.h @@ -147,6 +148,7 @@ funcall.o: $(hdrdir)/ruby/internal/special_consts.h funcall.o: $(hdrdir)/ruby/internal/static_assert.h funcall.o: $(hdrdir)/ruby/internal/stdalign.h funcall.o: $(hdrdir)/ruby/internal/stdbool.h +funcall.o: $(hdrdir)/ruby/internal/stdckdint.h funcall.o: $(hdrdir)/ruby/internal/symbol.h funcall.o: $(hdrdir)/ruby/internal/value.h funcall.o: $(hdrdir)/ruby/internal/value_type.h diff --git a/ext/-test-/gvl/call_without_gvl/depend b/ext/-test-/gvl/call_without_gvl/depend index a4987a65ca75c5..236d1e1d3b6148 100644 --- a/ext/-test-/gvl/call_without_gvl/depend +++ b/ext/-test-/gvl/call_without_gvl/depend @@ -127,6 +127,7 @@ call_without_gvl.o: $(hdrdir)/ruby/internal/intern/re.h call_without_gvl.o: $(hdrdir)/ruby/internal/intern/ruby.h call_without_gvl.o: $(hdrdir)/ruby/internal/intern/select.h call_without_gvl.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +call_without_gvl.o: $(hdrdir)/ruby/internal/intern/set.h call_without_gvl.o: $(hdrdir)/ruby/internal/intern/signal.h call_without_gvl.o: $(hdrdir)/ruby/internal/intern/sprintf.h call_without_gvl.o: $(hdrdir)/ruby/internal/intern/string.h @@ -146,6 +147,7 @@ call_without_gvl.o: $(hdrdir)/ruby/internal/special_consts.h call_without_gvl.o: $(hdrdir)/ruby/internal/static_assert.h call_without_gvl.o: $(hdrdir)/ruby/internal/stdalign.h call_without_gvl.o: $(hdrdir)/ruby/internal/stdbool.h +call_without_gvl.o: $(hdrdir)/ruby/internal/stdckdint.h call_without_gvl.o: $(hdrdir)/ruby/internal/symbol.h call_without_gvl.o: $(hdrdir)/ruby/internal/value.h call_without_gvl.o: $(hdrdir)/ruby/internal/value_type.h diff --git a/ext/-test-/hash/depend b/ext/-test-/hash/depend index 58d9a6247e6d6b..416b93f9de37b1 100644 --- a/ext/-test-/hash/depend +++ b/ext/-test-/hash/depend @@ -128,6 +128,7 @@ delete.o: $(hdrdir)/ruby/internal/intern/re.h delete.o: $(hdrdir)/ruby/internal/intern/ruby.h delete.o: $(hdrdir)/ruby/internal/intern/select.h delete.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +delete.o: $(hdrdir)/ruby/internal/intern/set.h delete.o: $(hdrdir)/ruby/internal/intern/signal.h delete.o: $(hdrdir)/ruby/internal/intern/sprintf.h delete.o: $(hdrdir)/ruby/internal/intern/string.h @@ -147,6 +148,7 @@ delete.o: $(hdrdir)/ruby/internal/special_consts.h delete.o: $(hdrdir)/ruby/internal/static_assert.h delete.o: $(hdrdir)/ruby/internal/stdalign.h delete.o: $(hdrdir)/ruby/internal/stdbool.h +delete.o: $(hdrdir)/ruby/internal/stdckdint.h delete.o: $(hdrdir)/ruby/internal/symbol.h delete.o: $(hdrdir)/ruby/internal/value.h delete.o: $(hdrdir)/ruby/internal/value_type.h @@ -287,6 +289,7 @@ init.o: $(hdrdir)/ruby/internal/intern/re.h init.o: $(hdrdir)/ruby/internal/intern/ruby.h init.o: $(hdrdir)/ruby/internal/intern/select.h init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +init.o: $(hdrdir)/ruby/internal/intern/set.h init.o: $(hdrdir)/ruby/internal/intern/signal.h init.o: $(hdrdir)/ruby/internal/intern/sprintf.h init.o: $(hdrdir)/ruby/internal/intern/string.h @@ -306,6 +309,7 @@ init.o: $(hdrdir)/ruby/internal/special_consts.h init.o: $(hdrdir)/ruby/internal/static_assert.h init.o: $(hdrdir)/ruby/internal/stdalign.h init.o: $(hdrdir)/ruby/internal/stdbool.h +init.o: $(hdrdir)/ruby/internal/stdckdint.h init.o: $(hdrdir)/ruby/internal/symbol.h init.o: $(hdrdir)/ruby/internal/value.h init.o: $(hdrdir)/ruby/internal/value_type.h diff --git a/ext/-test-/integer/depend b/ext/-test-/integer/depend index b68a68ce7344a2..0ea007e814128d 100644 --- a/ext/-test-/integer/depend +++ b/ext/-test-/integer/depend @@ -128,6 +128,7 @@ core_ext.o: $(hdrdir)/ruby/internal/intern/re.h core_ext.o: $(hdrdir)/ruby/internal/intern/ruby.h core_ext.o: $(hdrdir)/ruby/internal/intern/select.h core_ext.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +core_ext.o: $(hdrdir)/ruby/internal/intern/set.h core_ext.o: $(hdrdir)/ruby/internal/intern/signal.h core_ext.o: $(hdrdir)/ruby/internal/intern/sprintf.h core_ext.o: $(hdrdir)/ruby/internal/intern/string.h @@ -147,6 +148,7 @@ core_ext.o: $(hdrdir)/ruby/internal/special_consts.h core_ext.o: $(hdrdir)/ruby/internal/static_assert.h core_ext.o: $(hdrdir)/ruby/internal/stdalign.h core_ext.o: $(hdrdir)/ruby/internal/stdbool.h +core_ext.o: $(hdrdir)/ruby/internal/stdckdint.h core_ext.o: $(hdrdir)/ruby/internal/symbol.h core_ext.o: $(hdrdir)/ruby/internal/value.h core_ext.o: $(hdrdir)/ruby/internal/value_type.h @@ -295,6 +297,7 @@ init.o: $(hdrdir)/ruby/internal/intern/re.h init.o: $(hdrdir)/ruby/internal/intern/ruby.h init.o: $(hdrdir)/ruby/internal/intern/select.h init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +init.o: $(hdrdir)/ruby/internal/intern/set.h init.o: $(hdrdir)/ruby/internal/intern/signal.h init.o: $(hdrdir)/ruby/internal/intern/sprintf.h init.o: $(hdrdir)/ruby/internal/intern/string.h @@ -314,6 +317,7 @@ init.o: $(hdrdir)/ruby/internal/special_consts.h init.o: $(hdrdir)/ruby/internal/static_assert.h init.o: $(hdrdir)/ruby/internal/stdalign.h init.o: $(hdrdir)/ruby/internal/stdbool.h +init.o: $(hdrdir)/ruby/internal/stdckdint.h init.o: $(hdrdir)/ruby/internal/symbol.h init.o: $(hdrdir)/ruby/internal/value.h init.o: $(hdrdir)/ruby/internal/value_type.h @@ -454,6 +458,7 @@ my_integer.o: $(hdrdir)/ruby/internal/intern/re.h my_integer.o: $(hdrdir)/ruby/internal/intern/ruby.h my_integer.o: $(hdrdir)/ruby/internal/intern/select.h my_integer.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +my_integer.o: $(hdrdir)/ruby/internal/intern/set.h my_integer.o: $(hdrdir)/ruby/internal/intern/signal.h my_integer.o: $(hdrdir)/ruby/internal/intern/sprintf.h my_integer.o: $(hdrdir)/ruby/internal/intern/string.h @@ -473,6 +478,7 @@ my_integer.o: $(hdrdir)/ruby/internal/special_consts.h my_integer.o: $(hdrdir)/ruby/internal/static_assert.h my_integer.o: $(hdrdir)/ruby/internal/stdalign.h my_integer.o: $(hdrdir)/ruby/internal/stdbool.h +my_integer.o: $(hdrdir)/ruby/internal/stdckdint.h my_integer.o: $(hdrdir)/ruby/internal/symbol.h my_integer.o: $(hdrdir)/ruby/internal/value.h my_integer.o: $(hdrdir)/ruby/internal/value_type.h diff --git a/ext/-test-/integer/my_integer.c b/ext/-test-/integer/my_integer.c index d86474bd7dfd48..94f14d27651a3f 100644 --- a/ext/-test-/integer/my_integer.c +++ b/ext/-test-/integer/my_integer.c @@ -1,9 +1,13 @@ #include "ruby.h" +static const rb_data_type_t my_integer_type = { + "MyInteger", {0}, 0, 0, RUBY_TYPED_FREE_IMMEDIATELY +}; + static VALUE my_integer_s_new(VALUE klass) { - return Data_Wrap_Struct(klass, 0, 0, 0); + return TypedData_Wrap_Struct(klass, &my_integer_type, 0); } void diff --git a/ext/-test-/iseq_load/depend b/ext/-test-/iseq_load/depend index 30deb6e039ea23..9361ddb93844ce 100644 --- a/ext/-test-/iseq_load/depend +++ b/ext/-test-/iseq_load/depend @@ -128,6 +128,7 @@ iseq_load.o: $(hdrdir)/ruby/internal/intern/re.h iseq_load.o: $(hdrdir)/ruby/internal/intern/ruby.h iseq_load.o: $(hdrdir)/ruby/internal/intern/select.h iseq_load.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +iseq_load.o: $(hdrdir)/ruby/internal/intern/set.h iseq_load.o: $(hdrdir)/ruby/internal/intern/signal.h iseq_load.o: $(hdrdir)/ruby/internal/intern/sprintf.h iseq_load.o: $(hdrdir)/ruby/internal/intern/string.h @@ -147,6 +148,7 @@ iseq_load.o: $(hdrdir)/ruby/internal/special_consts.h iseq_load.o: $(hdrdir)/ruby/internal/static_assert.h iseq_load.o: $(hdrdir)/ruby/internal/stdalign.h iseq_load.o: $(hdrdir)/ruby/internal/stdbool.h +iseq_load.o: $(hdrdir)/ruby/internal/stdckdint.h iseq_load.o: $(hdrdir)/ruby/internal/symbol.h iseq_load.o: $(hdrdir)/ruby/internal/value.h iseq_load.o: $(hdrdir)/ruby/internal/value_type.h diff --git a/ext/-test-/iter/depend b/ext/-test-/iter/depend index 077a2835328083..161947382cd91b 100644 --- a/ext/-test-/iter/depend +++ b/ext/-test-/iter/depend @@ -128,6 +128,7 @@ break.o: $(hdrdir)/ruby/internal/intern/re.h break.o: $(hdrdir)/ruby/internal/intern/ruby.h break.o: $(hdrdir)/ruby/internal/intern/select.h break.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +break.o: $(hdrdir)/ruby/internal/intern/set.h break.o: $(hdrdir)/ruby/internal/intern/signal.h break.o: $(hdrdir)/ruby/internal/intern/sprintf.h break.o: $(hdrdir)/ruby/internal/intern/string.h @@ -147,6 +148,7 @@ break.o: $(hdrdir)/ruby/internal/special_consts.h break.o: $(hdrdir)/ruby/internal/static_assert.h break.o: $(hdrdir)/ruby/internal/stdalign.h break.o: $(hdrdir)/ruby/internal/stdbool.h +break.o: $(hdrdir)/ruby/internal/stdckdint.h break.o: $(hdrdir)/ruby/internal/symbol.h break.o: $(hdrdir)/ruby/internal/value.h break.o: $(hdrdir)/ruby/internal/value_type.h @@ -287,6 +289,7 @@ init.o: $(hdrdir)/ruby/internal/intern/re.h init.o: $(hdrdir)/ruby/internal/intern/ruby.h init.o: $(hdrdir)/ruby/internal/intern/select.h init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +init.o: $(hdrdir)/ruby/internal/intern/set.h init.o: $(hdrdir)/ruby/internal/intern/signal.h init.o: $(hdrdir)/ruby/internal/intern/sprintf.h init.o: $(hdrdir)/ruby/internal/intern/string.h @@ -306,6 +309,7 @@ init.o: $(hdrdir)/ruby/internal/special_consts.h init.o: $(hdrdir)/ruby/internal/static_assert.h init.o: $(hdrdir)/ruby/internal/stdalign.h init.o: $(hdrdir)/ruby/internal/stdbool.h +init.o: $(hdrdir)/ruby/internal/stdckdint.h init.o: $(hdrdir)/ruby/internal/symbol.h init.o: $(hdrdir)/ruby/internal/value.h init.o: $(hdrdir)/ruby/internal/value_type.h @@ -446,6 +450,7 @@ yield.o: $(hdrdir)/ruby/internal/intern/re.h yield.o: $(hdrdir)/ruby/internal/intern/ruby.h yield.o: $(hdrdir)/ruby/internal/intern/select.h yield.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +yield.o: $(hdrdir)/ruby/internal/intern/set.h yield.o: $(hdrdir)/ruby/internal/intern/signal.h yield.o: $(hdrdir)/ruby/internal/intern/sprintf.h yield.o: $(hdrdir)/ruby/internal/intern/string.h @@ -465,6 +470,7 @@ yield.o: $(hdrdir)/ruby/internal/special_consts.h yield.o: $(hdrdir)/ruby/internal/static_assert.h yield.o: $(hdrdir)/ruby/internal/stdalign.h yield.o: $(hdrdir)/ruby/internal/stdbool.h +yield.o: $(hdrdir)/ruby/internal/stdckdint.h yield.o: $(hdrdir)/ruby/internal/symbol.h yield.o: $(hdrdir)/ruby/internal/value.h yield.o: $(hdrdir)/ruby/internal/value_type.h diff --git a/ext/-test-/load/dot.dot/depend b/ext/-test-/load/dot.dot/depend index be835d3ea5b970..339837d1832ad7 100644 --- a/ext/-test-/load/dot.dot/depend +++ b/ext/-test-/load/dot.dot/depend @@ -128,6 +128,7 @@ dot.dot.o: $(hdrdir)/ruby/internal/intern/re.h dot.dot.o: $(hdrdir)/ruby/internal/intern/ruby.h dot.dot.o: $(hdrdir)/ruby/internal/intern/select.h dot.dot.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +dot.dot.o: $(hdrdir)/ruby/internal/intern/set.h dot.dot.o: $(hdrdir)/ruby/internal/intern/signal.h dot.dot.o: $(hdrdir)/ruby/internal/intern/sprintf.h dot.dot.o: $(hdrdir)/ruby/internal/intern/string.h @@ -147,6 +148,7 @@ dot.dot.o: $(hdrdir)/ruby/internal/special_consts.h dot.dot.o: $(hdrdir)/ruby/internal/static_assert.h dot.dot.o: $(hdrdir)/ruby/internal/stdalign.h dot.dot.o: $(hdrdir)/ruby/internal/stdbool.h +dot.dot.o: $(hdrdir)/ruby/internal/stdckdint.h dot.dot.o: $(hdrdir)/ruby/internal/symbol.h dot.dot.o: $(hdrdir)/ruby/internal/value.h dot.dot.o: $(hdrdir)/ruby/internal/value_type.h diff --git a/ext/-test-/load/protect/depend b/ext/-test-/load/protect/depend index 57cf02990115a3..c76c6f88ed9591 100644 --- a/ext/-test-/load/protect/depend +++ b/ext/-test-/load/protect/depend @@ -128,6 +128,7 @@ protect.o: $(hdrdir)/ruby/internal/intern/re.h protect.o: $(hdrdir)/ruby/internal/intern/ruby.h protect.o: $(hdrdir)/ruby/internal/intern/select.h protect.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +protect.o: $(hdrdir)/ruby/internal/intern/set.h protect.o: $(hdrdir)/ruby/internal/intern/signal.h protect.o: $(hdrdir)/ruby/internal/intern/sprintf.h protect.o: $(hdrdir)/ruby/internal/intern/string.h @@ -147,6 +148,7 @@ protect.o: $(hdrdir)/ruby/internal/special_consts.h protect.o: $(hdrdir)/ruby/internal/static_assert.h protect.o: $(hdrdir)/ruby/internal/stdalign.h protect.o: $(hdrdir)/ruby/internal/stdbool.h +protect.o: $(hdrdir)/ruby/internal/stdckdint.h protect.o: $(hdrdir)/ruby/internal/symbol.h protect.o: $(hdrdir)/ruby/internal/value.h protect.o: $(hdrdir)/ruby/internal/value_type.h diff --git a/ext/-test-/load/resolve_symbol_resolver/depend b/ext/-test-/load/resolve_symbol_resolver/depend new file mode 100644 index 00000000000000..f422898b691af7 --- /dev/null +++ b/ext/-test-/load/resolve_symbol_resolver/depend @@ -0,0 +1,163 @@ +# AUTOGENERATED DEPENDENCIES START +resolve_symbol_resolver.o: $(RUBY_EXTCONF_H) +resolve_symbol_resolver.o: $(arch_hdrdir)/ruby/config.h +resolve_symbol_resolver.o: $(hdrdir)/ruby.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/assert.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/backward.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/backward/2/assume.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/backward/2/attributes.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/backward/2/bool.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/backward/2/inttypes.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/backward/2/limits.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/backward/2/long_long.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/backward/2/stdalign.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/backward/2/stdarg.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/defines.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/intern.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/abi.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/anyargs.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/arithmetic.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/arithmetic/char.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/arithmetic/double.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/arithmetic/int.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/arithmetic/long.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/arithmetic/short.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/assume.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/attr/artificial.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/attr/cold.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/attr/const.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/attr/constexpr.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/attr/deprecated.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/attr/error.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/attr/forceinline.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/attr/format.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/attr/noalias.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/attr/noexcept.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/attr/noinline.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/attr/nonnull.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/attr/noreturn.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/attr/packed_struct.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/attr/pure.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/attr/restrict.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/attr/warning.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/attr/weakref.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/cast.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/compiler_is.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/compiler_since.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/config.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/constant_p.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/core.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/core/rarray.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/core/rbasic.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/core/rbignum.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/core/rclass.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/core/rdata.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/core/rfile.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/core/rhash.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/core/robject.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/core/rregexp.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/core/rstring.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/core/rstruct.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/ctype.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/dllexport.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/dosish.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/error.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/eval.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/event.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/fl_type.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/gc.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/glob.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/globals.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/has/attribute.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/has/builtin.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/has/c_attribute.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/has/extension.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/has/feature.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/has/warning.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/array.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/bignum.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/class.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/compar.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/complex.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/cont.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/dir.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/enum.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/enumerator.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/error.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/eval.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/file.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/hash.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/io.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/load.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/marshal.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/numeric.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/object.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/parse.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/proc.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/process.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/random.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/range.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/rational.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/re.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/ruby.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/select.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/set.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/signal.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/sprintf.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/string.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/struct.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/thread.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/time.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/variable.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/intern/vm.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/interpreter.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/iterator.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/memory.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/method.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/module.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/newobj.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/scan_args.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/special_consts.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/static_assert.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/stdalign.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/stdbool.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/stdckdint.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/symbol.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/value.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/value_type.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/variable.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/warning_push.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/internal/xmalloc.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/missing.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/ruby.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/st.h +resolve_symbol_resolver.o: $(hdrdir)/ruby/subst.h +resolve_symbol_resolver.o: resolve_symbol_resolver.c +# AUTOGENERATED DEPENDENCIES END diff --git a/ext/-test-/load/resolve_symbol_resolver/extconf.rb b/ext/-test-/load/resolve_symbol_resolver/extconf.rb new file mode 100644 index 00000000000000..2299efcfd3780f --- /dev/null +++ b/ext/-test-/load/resolve_symbol_resolver/extconf.rb @@ -0,0 +1 @@ +create_makefile('-test-/load/resolve_symbol_resolver') diff --git a/ext/-test-/load/resolve_symbol_resolver/resolve_symbol_resolver.c b/ext/-test-/load/resolve_symbol_resolver/resolve_symbol_resolver.c new file mode 100644 index 00000000000000..6cc07cc1f84b14 --- /dev/null +++ b/ext/-test-/load/resolve_symbol_resolver/resolve_symbol_resolver.c @@ -0,0 +1,56 @@ +#include +#include "ruby/internal/intern/load.h" + +typedef VALUE(*target_func)(VALUE); + +static target_func rst_any_method; + +#define resolve_func(file, name) (target_func)(uintptr_t)rb_ext_resolve_symbol(file, name) +VALUE +rsr_any_method(VALUE klass) +{ + return rst_any_method((VALUE)NULL); +} + +VALUE +rsr_try_resolve_fname(VALUE klass) +{ + target_func rst_something_missing = + resolve_func("-test-/load/resolve_symbol_missing", "rst_any_method"); + if (rst_something_missing == NULL) { + // This should be done in Init_*, so the error is LoadError + rb_raise(rb_eLoadError, "symbol not found: missing fname"); + } + return Qtrue; +} + +VALUE +rsr_try_resolve_sname(VALUE klass) +{ + target_func rst_something_missing = + resolve_func("-test-/load/resolve_symbol_target", "rst_something_missing"); + if (rst_something_missing == NULL) { + // This should be done in Init_*, so the error is LoadError + rb_raise(rb_eLoadError, "symbol not found: missing sname"); + } + return Qtrue; +} + +void +Init_resolve_symbol_resolver(void) +{ + /* + * Resolving symbols at the head of Init_ because it raises LoadError (in cases). + * If the module and methods are defined before raising LoadError, retrying `require "this.so"` will + * cause re-defining those methods (and will be warned). + */ + rst_any_method = resolve_func("-test-/load/resolve_symbol_target", "rst_any_method"); + if (rst_any_method == NULL) { + rb_raise(rb_eLoadError, "resolve_symbol_target is not loaded"); + } + + VALUE mod = rb_define_module("ResolveSymbolResolver"); + rb_define_singleton_method(mod, "any_method", rsr_any_method, 0); + rb_define_singleton_method(mod, "try_resolve_fname", rsr_try_resolve_fname, 0); + rb_define_singleton_method(mod, "try_resolve_sname", rsr_try_resolve_sname, 0); +} diff --git a/ext/-test-/load/resolve_symbol_target/depend b/ext/-test-/load/resolve_symbol_target/depend new file mode 100644 index 00000000000000..aa0b5327bee023 --- /dev/null +++ b/ext/-test-/load/resolve_symbol_target/depend @@ -0,0 +1,164 @@ +# AUTOGENERATED DEPENDENCIES START +resolve_symbol_target.o: $(RUBY_EXTCONF_H) +resolve_symbol_target.o: $(arch_hdrdir)/ruby/config.h +resolve_symbol_target.o: $(hdrdir)/ruby.h +resolve_symbol_target.o: $(hdrdir)/ruby/assert.h +resolve_symbol_target.o: $(hdrdir)/ruby/backward.h +resolve_symbol_target.o: $(hdrdir)/ruby/backward/2/assume.h +resolve_symbol_target.o: $(hdrdir)/ruby/backward/2/attributes.h +resolve_symbol_target.o: $(hdrdir)/ruby/backward/2/bool.h +resolve_symbol_target.o: $(hdrdir)/ruby/backward/2/inttypes.h +resolve_symbol_target.o: $(hdrdir)/ruby/backward/2/limits.h +resolve_symbol_target.o: $(hdrdir)/ruby/backward/2/long_long.h +resolve_symbol_target.o: $(hdrdir)/ruby/backward/2/stdalign.h +resolve_symbol_target.o: $(hdrdir)/ruby/backward/2/stdarg.h +resolve_symbol_target.o: $(hdrdir)/ruby/defines.h +resolve_symbol_target.o: $(hdrdir)/ruby/intern.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/abi.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/anyargs.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/arithmetic.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/arithmetic/char.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/arithmetic/double.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/arithmetic/int.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/arithmetic/long.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/arithmetic/short.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/assume.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/attr/artificial.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/attr/cold.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/attr/const.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/attr/constexpr.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/attr/deprecated.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/attr/error.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/attr/forceinline.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/attr/format.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/attr/noalias.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/attr/noexcept.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/attr/noinline.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/attr/nonnull.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/attr/noreturn.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/attr/packed_struct.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/attr/pure.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/attr/restrict.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/attr/warning.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/attr/weakref.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/cast.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/compiler_is.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/compiler_since.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/config.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/constant_p.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/core.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/core/rarray.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/core/rbasic.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/core/rbignum.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/core/rclass.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/core/rdata.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/core/rfile.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/core/rhash.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/core/robject.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/core/rregexp.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/core/rstring.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/core/rstruct.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/ctype.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/dllexport.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/dosish.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/error.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/eval.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/event.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/fl_type.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/gc.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/glob.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/globals.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/has/attribute.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/has/builtin.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/has/c_attribute.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/has/extension.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/has/feature.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/has/warning.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/array.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/bignum.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/class.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/compar.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/complex.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/cont.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/dir.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/enum.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/enumerator.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/error.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/eval.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/file.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/hash.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/io.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/load.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/marshal.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/numeric.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/object.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/parse.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/proc.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/process.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/random.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/range.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/rational.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/re.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/ruby.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/select.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/set.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/signal.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/sprintf.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/string.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/struct.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/thread.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/time.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/variable.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/intern/vm.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/interpreter.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/iterator.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/memory.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/method.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/module.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/newobj.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/scan_args.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/special_consts.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/static_assert.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/stdalign.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/stdbool.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/stdckdint.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/symbol.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/value.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/value_type.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/variable.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/warning_push.h +resolve_symbol_target.o: $(hdrdir)/ruby/internal/xmalloc.h +resolve_symbol_target.o: $(hdrdir)/ruby/missing.h +resolve_symbol_target.o: $(hdrdir)/ruby/ruby.h +resolve_symbol_target.o: $(hdrdir)/ruby/st.h +resolve_symbol_target.o: $(hdrdir)/ruby/subst.h +resolve_symbol_target.o: resolve_symbol_target.c +resolve_symbol_target.o: resolve_symbol_target.h +# AUTOGENERATED DEPENDENCIES END diff --git a/ext/-test-/load/resolve_symbol_target/extconf.rb b/ext/-test-/load/resolve_symbol_target/extconf.rb new file mode 100644 index 00000000000000..b5a99ca7f1ec64 --- /dev/null +++ b/ext/-test-/load/resolve_symbol_target/extconf.rb @@ -0,0 +1 @@ +create_makefile('-test-/load/resolve_symbol_target') diff --git a/ext/-test-/load/resolve_symbol_target/resolve_symbol_target.c b/ext/-test-/load/resolve_symbol_target/resolve_symbol_target.c new file mode 100644 index 00000000000000..b5bc9e8ee0a564 --- /dev/null +++ b/ext/-test-/load/resolve_symbol_target/resolve_symbol_target.c @@ -0,0 +1,15 @@ +#include +#include "resolve_symbol_target.h" + +VALUE +rst_any_method(VALUE klass) +{ + return rb_str_new_cstr("from target"); +} + +void +Init_resolve_symbol_target(void) +{ + VALUE mod = rb_define_module("ResolveSymbolTarget"); + rb_define_singleton_method(mod, "any_method", rst_any_method, 0); +} diff --git a/ext/-test-/load/resolve_symbol_target/resolve_symbol_target.h b/ext/-test-/load/resolve_symbol_target/resolve_symbol_target.h new file mode 100644 index 00000000000000..847dcb7dd336d7 --- /dev/null +++ b/ext/-test-/load/resolve_symbol_target/resolve_symbol_target.h @@ -0,0 +1,4 @@ +#include +#include "ruby/internal/dllexport.h" + +RUBY_FUNC_EXPORTED VALUE rst_any_method(VALUE); diff --git a/ext/-test-/load/stringify_symbols/depend b/ext/-test-/load/stringify_symbols/depend new file mode 100644 index 00000000000000..2d4d79a7b7a21a --- /dev/null +++ b/ext/-test-/load/stringify_symbols/depend @@ -0,0 +1,164 @@ +# AUTOGENERATED DEPENDENCIES START +stringify_symbols.o: $(RUBY_EXTCONF_H) +stringify_symbols.o: $(arch_hdrdir)/ruby/config.h +stringify_symbols.o: $(hdrdir)/ruby.h +stringify_symbols.o: $(hdrdir)/ruby/assert.h +stringify_symbols.o: $(hdrdir)/ruby/backward.h +stringify_symbols.o: $(hdrdir)/ruby/backward/2/assume.h +stringify_symbols.o: $(hdrdir)/ruby/backward/2/attributes.h +stringify_symbols.o: $(hdrdir)/ruby/backward/2/bool.h +stringify_symbols.o: $(hdrdir)/ruby/backward/2/inttypes.h +stringify_symbols.o: $(hdrdir)/ruby/backward/2/limits.h +stringify_symbols.o: $(hdrdir)/ruby/backward/2/long_long.h +stringify_symbols.o: $(hdrdir)/ruby/backward/2/stdalign.h +stringify_symbols.o: $(hdrdir)/ruby/backward/2/stdarg.h +stringify_symbols.o: $(hdrdir)/ruby/defines.h +stringify_symbols.o: $(hdrdir)/ruby/intern.h +stringify_symbols.o: $(hdrdir)/ruby/internal/abi.h +stringify_symbols.o: $(hdrdir)/ruby/internal/anyargs.h +stringify_symbols.o: $(hdrdir)/ruby/internal/arithmetic.h +stringify_symbols.o: $(hdrdir)/ruby/internal/arithmetic/char.h +stringify_symbols.o: $(hdrdir)/ruby/internal/arithmetic/double.h +stringify_symbols.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +stringify_symbols.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +stringify_symbols.o: $(hdrdir)/ruby/internal/arithmetic/int.h +stringify_symbols.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +stringify_symbols.o: $(hdrdir)/ruby/internal/arithmetic/long.h +stringify_symbols.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +stringify_symbols.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +stringify_symbols.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +stringify_symbols.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +stringify_symbols.o: $(hdrdir)/ruby/internal/arithmetic/short.h +stringify_symbols.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +stringify_symbols.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +stringify_symbols.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +stringify_symbols.o: $(hdrdir)/ruby/internal/assume.h +stringify_symbols.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +stringify_symbols.o: $(hdrdir)/ruby/internal/attr/artificial.h +stringify_symbols.o: $(hdrdir)/ruby/internal/attr/cold.h +stringify_symbols.o: $(hdrdir)/ruby/internal/attr/const.h +stringify_symbols.o: $(hdrdir)/ruby/internal/attr/constexpr.h +stringify_symbols.o: $(hdrdir)/ruby/internal/attr/deprecated.h +stringify_symbols.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +stringify_symbols.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +stringify_symbols.o: $(hdrdir)/ruby/internal/attr/error.h +stringify_symbols.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +stringify_symbols.o: $(hdrdir)/ruby/internal/attr/forceinline.h +stringify_symbols.o: $(hdrdir)/ruby/internal/attr/format.h +stringify_symbols.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +stringify_symbols.o: $(hdrdir)/ruby/internal/attr/noalias.h +stringify_symbols.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +stringify_symbols.o: $(hdrdir)/ruby/internal/attr/noexcept.h +stringify_symbols.o: $(hdrdir)/ruby/internal/attr/noinline.h +stringify_symbols.o: $(hdrdir)/ruby/internal/attr/nonnull.h +stringify_symbols.o: $(hdrdir)/ruby/internal/attr/noreturn.h +stringify_symbols.o: $(hdrdir)/ruby/internal/attr/packed_struct.h +stringify_symbols.o: $(hdrdir)/ruby/internal/attr/pure.h +stringify_symbols.o: $(hdrdir)/ruby/internal/attr/restrict.h +stringify_symbols.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +stringify_symbols.o: $(hdrdir)/ruby/internal/attr/warning.h +stringify_symbols.o: $(hdrdir)/ruby/internal/attr/weakref.h +stringify_symbols.o: $(hdrdir)/ruby/internal/cast.h +stringify_symbols.o: $(hdrdir)/ruby/internal/compiler_is.h +stringify_symbols.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +stringify_symbols.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +stringify_symbols.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +stringify_symbols.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +stringify_symbols.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +stringify_symbols.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +stringify_symbols.o: $(hdrdir)/ruby/internal/compiler_since.h +stringify_symbols.o: $(hdrdir)/ruby/internal/config.h +stringify_symbols.o: $(hdrdir)/ruby/internal/constant_p.h +stringify_symbols.o: $(hdrdir)/ruby/internal/core.h +stringify_symbols.o: $(hdrdir)/ruby/internal/core/rarray.h +stringify_symbols.o: $(hdrdir)/ruby/internal/core/rbasic.h +stringify_symbols.o: $(hdrdir)/ruby/internal/core/rbignum.h +stringify_symbols.o: $(hdrdir)/ruby/internal/core/rclass.h +stringify_symbols.o: $(hdrdir)/ruby/internal/core/rdata.h +stringify_symbols.o: $(hdrdir)/ruby/internal/core/rfile.h +stringify_symbols.o: $(hdrdir)/ruby/internal/core/rhash.h +stringify_symbols.o: $(hdrdir)/ruby/internal/core/robject.h +stringify_symbols.o: $(hdrdir)/ruby/internal/core/rregexp.h +stringify_symbols.o: $(hdrdir)/ruby/internal/core/rstring.h +stringify_symbols.o: $(hdrdir)/ruby/internal/core/rstruct.h +stringify_symbols.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +stringify_symbols.o: $(hdrdir)/ruby/internal/ctype.h +stringify_symbols.o: $(hdrdir)/ruby/internal/dllexport.h +stringify_symbols.o: $(hdrdir)/ruby/internal/dosish.h +stringify_symbols.o: $(hdrdir)/ruby/internal/error.h +stringify_symbols.o: $(hdrdir)/ruby/internal/eval.h +stringify_symbols.o: $(hdrdir)/ruby/internal/event.h +stringify_symbols.o: $(hdrdir)/ruby/internal/fl_type.h +stringify_symbols.o: $(hdrdir)/ruby/internal/gc.h +stringify_symbols.o: $(hdrdir)/ruby/internal/glob.h +stringify_symbols.o: $(hdrdir)/ruby/internal/globals.h +stringify_symbols.o: $(hdrdir)/ruby/internal/has/attribute.h +stringify_symbols.o: $(hdrdir)/ruby/internal/has/builtin.h +stringify_symbols.o: $(hdrdir)/ruby/internal/has/c_attribute.h +stringify_symbols.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +stringify_symbols.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +stringify_symbols.o: $(hdrdir)/ruby/internal/has/extension.h +stringify_symbols.o: $(hdrdir)/ruby/internal/has/feature.h +stringify_symbols.o: $(hdrdir)/ruby/internal/has/warning.h +stringify_symbols.o: $(hdrdir)/ruby/internal/intern/array.h +stringify_symbols.o: $(hdrdir)/ruby/internal/intern/bignum.h +stringify_symbols.o: $(hdrdir)/ruby/internal/intern/class.h +stringify_symbols.o: $(hdrdir)/ruby/internal/intern/compar.h +stringify_symbols.o: $(hdrdir)/ruby/internal/intern/complex.h +stringify_symbols.o: $(hdrdir)/ruby/internal/intern/cont.h +stringify_symbols.o: $(hdrdir)/ruby/internal/intern/dir.h +stringify_symbols.o: $(hdrdir)/ruby/internal/intern/enum.h +stringify_symbols.o: $(hdrdir)/ruby/internal/intern/enumerator.h +stringify_symbols.o: $(hdrdir)/ruby/internal/intern/error.h +stringify_symbols.o: $(hdrdir)/ruby/internal/intern/eval.h +stringify_symbols.o: $(hdrdir)/ruby/internal/intern/file.h +stringify_symbols.o: $(hdrdir)/ruby/internal/intern/hash.h +stringify_symbols.o: $(hdrdir)/ruby/internal/intern/io.h +stringify_symbols.o: $(hdrdir)/ruby/internal/intern/load.h +stringify_symbols.o: $(hdrdir)/ruby/internal/intern/marshal.h +stringify_symbols.o: $(hdrdir)/ruby/internal/intern/numeric.h +stringify_symbols.o: $(hdrdir)/ruby/internal/intern/object.h +stringify_symbols.o: $(hdrdir)/ruby/internal/intern/parse.h +stringify_symbols.o: $(hdrdir)/ruby/internal/intern/proc.h +stringify_symbols.o: $(hdrdir)/ruby/internal/intern/process.h +stringify_symbols.o: $(hdrdir)/ruby/internal/intern/random.h +stringify_symbols.o: $(hdrdir)/ruby/internal/intern/range.h +stringify_symbols.o: $(hdrdir)/ruby/internal/intern/rational.h +stringify_symbols.o: $(hdrdir)/ruby/internal/intern/re.h +stringify_symbols.o: $(hdrdir)/ruby/internal/intern/ruby.h +stringify_symbols.o: $(hdrdir)/ruby/internal/intern/select.h +stringify_symbols.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +stringify_symbols.o: $(hdrdir)/ruby/internal/intern/set.h +stringify_symbols.o: $(hdrdir)/ruby/internal/intern/signal.h +stringify_symbols.o: $(hdrdir)/ruby/internal/intern/sprintf.h +stringify_symbols.o: $(hdrdir)/ruby/internal/intern/string.h +stringify_symbols.o: $(hdrdir)/ruby/internal/intern/struct.h +stringify_symbols.o: $(hdrdir)/ruby/internal/intern/thread.h +stringify_symbols.o: $(hdrdir)/ruby/internal/intern/time.h +stringify_symbols.o: $(hdrdir)/ruby/internal/intern/variable.h +stringify_symbols.o: $(hdrdir)/ruby/internal/intern/vm.h +stringify_symbols.o: $(hdrdir)/ruby/internal/interpreter.h +stringify_symbols.o: $(hdrdir)/ruby/internal/iterator.h +stringify_symbols.o: $(hdrdir)/ruby/internal/memory.h +stringify_symbols.o: $(hdrdir)/ruby/internal/method.h +stringify_symbols.o: $(hdrdir)/ruby/internal/module.h +stringify_symbols.o: $(hdrdir)/ruby/internal/newobj.h +stringify_symbols.o: $(hdrdir)/ruby/internal/scan_args.h +stringify_symbols.o: $(hdrdir)/ruby/internal/special_consts.h +stringify_symbols.o: $(hdrdir)/ruby/internal/static_assert.h +stringify_symbols.o: $(hdrdir)/ruby/internal/stdalign.h +stringify_symbols.o: $(hdrdir)/ruby/internal/stdbool.h +stringify_symbols.o: $(hdrdir)/ruby/internal/stdckdint.h +stringify_symbols.o: $(hdrdir)/ruby/internal/symbol.h +stringify_symbols.o: $(hdrdir)/ruby/internal/value.h +stringify_symbols.o: $(hdrdir)/ruby/internal/value_type.h +stringify_symbols.o: $(hdrdir)/ruby/internal/variable.h +stringify_symbols.o: $(hdrdir)/ruby/internal/warning_push.h +stringify_symbols.o: $(hdrdir)/ruby/internal/xmalloc.h +stringify_symbols.o: $(hdrdir)/ruby/missing.h +stringify_symbols.o: $(hdrdir)/ruby/ruby.h +stringify_symbols.o: $(hdrdir)/ruby/st.h +stringify_symbols.o: $(hdrdir)/ruby/subst.h +stringify_symbols.o: $(hdrdir)/ruby/util.h +stringify_symbols.o: stringify_symbols.c +# AUTOGENERATED DEPENDENCIES END diff --git a/ext/-test-/load/stringify_symbols/extconf.rb b/ext/-test-/load/stringify_symbols/extconf.rb new file mode 100644 index 00000000000000..ac39c15f09c9f8 --- /dev/null +++ b/ext/-test-/load/stringify_symbols/extconf.rb @@ -0,0 +1 @@ +create_makefile('-test-/load/stringify_symbols') diff --git a/ext/-test-/load/stringify_symbols/stringify_symbols.c b/ext/-test-/load/stringify_symbols/stringify_symbols.c new file mode 100644 index 00000000000000..11a5ee3bc5514c --- /dev/null +++ b/ext/-test-/load/stringify_symbols/stringify_symbols.c @@ -0,0 +1,29 @@ +#include +#include "ruby/internal/intern/load.h" +#include "ruby/util.h" + +#if SIZEOF_INTPTR_T == SIZEOF_LONG_LONG +# define UINTPTR2NUM ULL2NUM +#elif SIZEOF_INTPTR_T == SIZEOF_LONG +# define UINTPTR2NUM ULONG2NUM +#else +# define UINTPTR2NUM UINT2NUM +#endif + +static VALUE +stringify_symbol(VALUE klass, VALUE fname, VALUE sname) +{ + void *ptr = rb_ext_resolve_symbol(StringValueCStr(fname), StringValueCStr(sname)); + if (ptr == NULL) { + return Qnil; + } + uintptr_t uintptr = (uintptr_t)ptr; + return UINTPTR2NUM(uintptr); +} + +void +Init_stringify_symbols(void) +{ + VALUE mod = rb_define_module("StringifySymbols"); + rb_define_singleton_method(mod, "stringify_symbol", stringify_symbol, 2); +} diff --git a/ext/-test-/load/stringify_target/depend b/ext/-test-/load/stringify_target/depend new file mode 100644 index 00000000000000..c66575d4e4fbc5 --- /dev/null +++ b/ext/-test-/load/stringify_target/depend @@ -0,0 +1,164 @@ +# AUTOGENERATED DEPENDENCIES START +stringify_target.o: $(RUBY_EXTCONF_H) +stringify_target.o: $(arch_hdrdir)/ruby/config.h +stringify_target.o: $(hdrdir)/ruby.h +stringify_target.o: $(hdrdir)/ruby/assert.h +stringify_target.o: $(hdrdir)/ruby/backward.h +stringify_target.o: $(hdrdir)/ruby/backward/2/assume.h +stringify_target.o: $(hdrdir)/ruby/backward/2/attributes.h +stringify_target.o: $(hdrdir)/ruby/backward/2/bool.h +stringify_target.o: $(hdrdir)/ruby/backward/2/inttypes.h +stringify_target.o: $(hdrdir)/ruby/backward/2/limits.h +stringify_target.o: $(hdrdir)/ruby/backward/2/long_long.h +stringify_target.o: $(hdrdir)/ruby/backward/2/stdalign.h +stringify_target.o: $(hdrdir)/ruby/backward/2/stdarg.h +stringify_target.o: $(hdrdir)/ruby/defines.h +stringify_target.o: $(hdrdir)/ruby/intern.h +stringify_target.o: $(hdrdir)/ruby/internal/abi.h +stringify_target.o: $(hdrdir)/ruby/internal/anyargs.h +stringify_target.o: $(hdrdir)/ruby/internal/arithmetic.h +stringify_target.o: $(hdrdir)/ruby/internal/arithmetic/char.h +stringify_target.o: $(hdrdir)/ruby/internal/arithmetic/double.h +stringify_target.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +stringify_target.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +stringify_target.o: $(hdrdir)/ruby/internal/arithmetic/int.h +stringify_target.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +stringify_target.o: $(hdrdir)/ruby/internal/arithmetic/long.h +stringify_target.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +stringify_target.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +stringify_target.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +stringify_target.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +stringify_target.o: $(hdrdir)/ruby/internal/arithmetic/short.h +stringify_target.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +stringify_target.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +stringify_target.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +stringify_target.o: $(hdrdir)/ruby/internal/assume.h +stringify_target.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +stringify_target.o: $(hdrdir)/ruby/internal/attr/artificial.h +stringify_target.o: $(hdrdir)/ruby/internal/attr/cold.h +stringify_target.o: $(hdrdir)/ruby/internal/attr/const.h +stringify_target.o: $(hdrdir)/ruby/internal/attr/constexpr.h +stringify_target.o: $(hdrdir)/ruby/internal/attr/deprecated.h +stringify_target.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +stringify_target.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +stringify_target.o: $(hdrdir)/ruby/internal/attr/error.h +stringify_target.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +stringify_target.o: $(hdrdir)/ruby/internal/attr/forceinline.h +stringify_target.o: $(hdrdir)/ruby/internal/attr/format.h +stringify_target.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +stringify_target.o: $(hdrdir)/ruby/internal/attr/noalias.h +stringify_target.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +stringify_target.o: $(hdrdir)/ruby/internal/attr/noexcept.h +stringify_target.o: $(hdrdir)/ruby/internal/attr/noinline.h +stringify_target.o: $(hdrdir)/ruby/internal/attr/nonnull.h +stringify_target.o: $(hdrdir)/ruby/internal/attr/noreturn.h +stringify_target.o: $(hdrdir)/ruby/internal/attr/packed_struct.h +stringify_target.o: $(hdrdir)/ruby/internal/attr/pure.h +stringify_target.o: $(hdrdir)/ruby/internal/attr/restrict.h +stringify_target.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +stringify_target.o: $(hdrdir)/ruby/internal/attr/warning.h +stringify_target.o: $(hdrdir)/ruby/internal/attr/weakref.h +stringify_target.o: $(hdrdir)/ruby/internal/cast.h +stringify_target.o: $(hdrdir)/ruby/internal/compiler_is.h +stringify_target.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +stringify_target.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +stringify_target.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +stringify_target.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +stringify_target.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +stringify_target.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +stringify_target.o: $(hdrdir)/ruby/internal/compiler_since.h +stringify_target.o: $(hdrdir)/ruby/internal/config.h +stringify_target.o: $(hdrdir)/ruby/internal/constant_p.h +stringify_target.o: $(hdrdir)/ruby/internal/core.h +stringify_target.o: $(hdrdir)/ruby/internal/core/rarray.h +stringify_target.o: $(hdrdir)/ruby/internal/core/rbasic.h +stringify_target.o: $(hdrdir)/ruby/internal/core/rbignum.h +stringify_target.o: $(hdrdir)/ruby/internal/core/rclass.h +stringify_target.o: $(hdrdir)/ruby/internal/core/rdata.h +stringify_target.o: $(hdrdir)/ruby/internal/core/rfile.h +stringify_target.o: $(hdrdir)/ruby/internal/core/rhash.h +stringify_target.o: $(hdrdir)/ruby/internal/core/robject.h +stringify_target.o: $(hdrdir)/ruby/internal/core/rregexp.h +stringify_target.o: $(hdrdir)/ruby/internal/core/rstring.h +stringify_target.o: $(hdrdir)/ruby/internal/core/rstruct.h +stringify_target.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +stringify_target.o: $(hdrdir)/ruby/internal/ctype.h +stringify_target.o: $(hdrdir)/ruby/internal/dllexport.h +stringify_target.o: $(hdrdir)/ruby/internal/dosish.h +stringify_target.o: $(hdrdir)/ruby/internal/error.h +stringify_target.o: $(hdrdir)/ruby/internal/eval.h +stringify_target.o: $(hdrdir)/ruby/internal/event.h +stringify_target.o: $(hdrdir)/ruby/internal/fl_type.h +stringify_target.o: $(hdrdir)/ruby/internal/gc.h +stringify_target.o: $(hdrdir)/ruby/internal/glob.h +stringify_target.o: $(hdrdir)/ruby/internal/globals.h +stringify_target.o: $(hdrdir)/ruby/internal/has/attribute.h +stringify_target.o: $(hdrdir)/ruby/internal/has/builtin.h +stringify_target.o: $(hdrdir)/ruby/internal/has/c_attribute.h +stringify_target.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +stringify_target.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +stringify_target.o: $(hdrdir)/ruby/internal/has/extension.h +stringify_target.o: $(hdrdir)/ruby/internal/has/feature.h +stringify_target.o: $(hdrdir)/ruby/internal/has/warning.h +stringify_target.o: $(hdrdir)/ruby/internal/intern/array.h +stringify_target.o: $(hdrdir)/ruby/internal/intern/bignum.h +stringify_target.o: $(hdrdir)/ruby/internal/intern/class.h +stringify_target.o: $(hdrdir)/ruby/internal/intern/compar.h +stringify_target.o: $(hdrdir)/ruby/internal/intern/complex.h +stringify_target.o: $(hdrdir)/ruby/internal/intern/cont.h +stringify_target.o: $(hdrdir)/ruby/internal/intern/dir.h +stringify_target.o: $(hdrdir)/ruby/internal/intern/enum.h +stringify_target.o: $(hdrdir)/ruby/internal/intern/enumerator.h +stringify_target.o: $(hdrdir)/ruby/internal/intern/error.h +stringify_target.o: $(hdrdir)/ruby/internal/intern/eval.h +stringify_target.o: $(hdrdir)/ruby/internal/intern/file.h +stringify_target.o: $(hdrdir)/ruby/internal/intern/hash.h +stringify_target.o: $(hdrdir)/ruby/internal/intern/io.h +stringify_target.o: $(hdrdir)/ruby/internal/intern/load.h +stringify_target.o: $(hdrdir)/ruby/internal/intern/marshal.h +stringify_target.o: $(hdrdir)/ruby/internal/intern/numeric.h +stringify_target.o: $(hdrdir)/ruby/internal/intern/object.h +stringify_target.o: $(hdrdir)/ruby/internal/intern/parse.h +stringify_target.o: $(hdrdir)/ruby/internal/intern/proc.h +stringify_target.o: $(hdrdir)/ruby/internal/intern/process.h +stringify_target.o: $(hdrdir)/ruby/internal/intern/random.h +stringify_target.o: $(hdrdir)/ruby/internal/intern/range.h +stringify_target.o: $(hdrdir)/ruby/internal/intern/rational.h +stringify_target.o: $(hdrdir)/ruby/internal/intern/re.h +stringify_target.o: $(hdrdir)/ruby/internal/intern/ruby.h +stringify_target.o: $(hdrdir)/ruby/internal/intern/select.h +stringify_target.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +stringify_target.o: $(hdrdir)/ruby/internal/intern/set.h +stringify_target.o: $(hdrdir)/ruby/internal/intern/signal.h +stringify_target.o: $(hdrdir)/ruby/internal/intern/sprintf.h +stringify_target.o: $(hdrdir)/ruby/internal/intern/string.h +stringify_target.o: $(hdrdir)/ruby/internal/intern/struct.h +stringify_target.o: $(hdrdir)/ruby/internal/intern/thread.h +stringify_target.o: $(hdrdir)/ruby/internal/intern/time.h +stringify_target.o: $(hdrdir)/ruby/internal/intern/variable.h +stringify_target.o: $(hdrdir)/ruby/internal/intern/vm.h +stringify_target.o: $(hdrdir)/ruby/internal/interpreter.h +stringify_target.o: $(hdrdir)/ruby/internal/iterator.h +stringify_target.o: $(hdrdir)/ruby/internal/memory.h +stringify_target.o: $(hdrdir)/ruby/internal/method.h +stringify_target.o: $(hdrdir)/ruby/internal/module.h +stringify_target.o: $(hdrdir)/ruby/internal/newobj.h +stringify_target.o: $(hdrdir)/ruby/internal/scan_args.h +stringify_target.o: $(hdrdir)/ruby/internal/special_consts.h +stringify_target.o: $(hdrdir)/ruby/internal/static_assert.h +stringify_target.o: $(hdrdir)/ruby/internal/stdalign.h +stringify_target.o: $(hdrdir)/ruby/internal/stdbool.h +stringify_target.o: $(hdrdir)/ruby/internal/stdckdint.h +stringify_target.o: $(hdrdir)/ruby/internal/symbol.h +stringify_target.o: $(hdrdir)/ruby/internal/value.h +stringify_target.o: $(hdrdir)/ruby/internal/value_type.h +stringify_target.o: $(hdrdir)/ruby/internal/variable.h +stringify_target.o: $(hdrdir)/ruby/internal/warning_push.h +stringify_target.o: $(hdrdir)/ruby/internal/xmalloc.h +stringify_target.o: $(hdrdir)/ruby/missing.h +stringify_target.o: $(hdrdir)/ruby/ruby.h +stringify_target.o: $(hdrdir)/ruby/st.h +stringify_target.o: $(hdrdir)/ruby/subst.h +stringify_target.o: stringify_target.c +stringify_target.o: stringify_target.h +# AUTOGENERATED DEPENDENCIES END diff --git a/ext/-test-/load/stringify_target/extconf.rb b/ext/-test-/load/stringify_target/extconf.rb new file mode 100644 index 00000000000000..4aa201cb09ef57 --- /dev/null +++ b/ext/-test-/load/stringify_target/extconf.rb @@ -0,0 +1 @@ +create_makefile('-test-/load/stringify_target') diff --git a/ext/-test-/load/stringify_target/stringify_target.c b/ext/-test-/load/stringify_target/stringify_target.c new file mode 100644 index 00000000000000..ce09b8fd77e208 --- /dev/null +++ b/ext/-test-/load/stringify_target/stringify_target.c @@ -0,0 +1,15 @@ +#include +#include "stringify_target.h" + +VALUE +stt_any_method(VALUE klass) +{ + return rb_str_new_cstr("from target"); +} + +void +Init_stringify_target(void) +{ + VALUE mod = rb_define_module("StringifyTarget"); + rb_define_singleton_method(mod, "any_method", stt_any_method, 0); +} diff --git a/ext/-test-/load/stringify_target/stringify_target.h b/ext/-test-/load/stringify_target/stringify_target.h new file mode 100644 index 00000000000000..d95fb65d7ca7e7 --- /dev/null +++ b/ext/-test-/load/stringify_target/stringify_target.h @@ -0,0 +1,4 @@ +#include +#include "ruby/internal/dllexport.h" + +RUBY_FUNC_EXPORTED VALUE stt_any_method(VALUE); diff --git a/ext/-test-/marshal/compat/depend b/ext/-test-/marshal/compat/depend index ff675ccabbc092..36b9235c230de1 100644 --- a/ext/-test-/marshal/compat/depend +++ b/ext/-test-/marshal/compat/depend @@ -128,6 +128,7 @@ usrcompat.o: $(hdrdir)/ruby/internal/intern/re.h usrcompat.o: $(hdrdir)/ruby/internal/intern/ruby.h usrcompat.o: $(hdrdir)/ruby/internal/intern/select.h usrcompat.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +usrcompat.o: $(hdrdir)/ruby/internal/intern/set.h usrcompat.o: $(hdrdir)/ruby/internal/intern/signal.h usrcompat.o: $(hdrdir)/ruby/internal/intern/sprintf.h usrcompat.o: $(hdrdir)/ruby/internal/intern/string.h @@ -147,6 +148,7 @@ usrcompat.o: $(hdrdir)/ruby/internal/special_consts.h usrcompat.o: $(hdrdir)/ruby/internal/static_assert.h usrcompat.o: $(hdrdir)/ruby/internal/stdalign.h usrcompat.o: $(hdrdir)/ruby/internal/stdbool.h +usrcompat.o: $(hdrdir)/ruby/internal/stdckdint.h usrcompat.o: $(hdrdir)/ruby/internal/symbol.h usrcompat.o: $(hdrdir)/ruby/internal/value.h usrcompat.o: $(hdrdir)/ruby/internal/value_type.h diff --git a/ext/-test-/marshal/internal_ivar/depend b/ext/-test-/marshal/internal_ivar/depend index 4fe36834d8135f..a2e093d809b941 100644 --- a/ext/-test-/marshal/internal_ivar/depend +++ b/ext/-test-/marshal/internal_ivar/depend @@ -128,6 +128,7 @@ internal_ivar.o: $(hdrdir)/ruby/internal/intern/re.h internal_ivar.o: $(hdrdir)/ruby/internal/intern/ruby.h internal_ivar.o: $(hdrdir)/ruby/internal/intern/select.h internal_ivar.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +internal_ivar.o: $(hdrdir)/ruby/internal/intern/set.h internal_ivar.o: $(hdrdir)/ruby/internal/intern/signal.h internal_ivar.o: $(hdrdir)/ruby/internal/intern/sprintf.h internal_ivar.o: $(hdrdir)/ruby/internal/intern/string.h @@ -147,6 +148,7 @@ internal_ivar.o: $(hdrdir)/ruby/internal/special_consts.h internal_ivar.o: $(hdrdir)/ruby/internal/static_assert.h internal_ivar.o: $(hdrdir)/ruby/internal/stdalign.h internal_ivar.o: $(hdrdir)/ruby/internal/stdbool.h +internal_ivar.o: $(hdrdir)/ruby/internal/stdckdint.h internal_ivar.o: $(hdrdir)/ruby/internal/symbol.h internal_ivar.o: $(hdrdir)/ruby/internal/value.h internal_ivar.o: $(hdrdir)/ruby/internal/value_type.h diff --git a/ext/-test-/marshal/internal_ivar/internal_ivar.c b/ext/-test-/marshal/internal_ivar/internal_ivar.c index b2188f737a14e3..2e2f9cb235f02e 100644 --- a/ext/-test-/marshal/internal_ivar/internal_ivar.c +++ b/ext/-test-/marshal/internal_ivar/internal_ivar.c @@ -1,13 +1,14 @@ #include -static ID id_normal_ivar, id_internal_ivar, id_encoding_short; +static ID id_normal_ivar, id_internal_ivar, id_encoding_short, id_encoding_long; static VALUE -init(VALUE self, VALUE arg1, VALUE arg2, VALUE arg3) +init(VALUE self, VALUE arg1, VALUE arg2, VALUE arg3, VALUE arg4) { rb_ivar_set(self, id_normal_ivar, arg1); rb_ivar_set(self, id_internal_ivar, arg2); rb_ivar_set(self, id_encoding_short, arg3); + rb_ivar_set(self, id_encoding_long, arg4); return self; } @@ -29,6 +30,12 @@ get_encoding_short(VALUE self) return rb_attr_get(self, id_encoding_short); } +static VALUE +get_encoding_long(VALUE self) +{ + return rb_attr_get(self, id_encoding_long); +} + void Init_internal_ivar(void) { @@ -38,8 +45,10 @@ Init_internal_ivar(void) id_normal_ivar = rb_intern_const("normal"); id_internal_ivar = rb_intern_const("K"); id_encoding_short = rb_intern_const("E"); - rb_define_method(newclass, "initialize", init, 3); + id_encoding_long = rb_intern_const("encoding"); + rb_define_method(newclass, "initialize", init, 4); rb_define_method(newclass, "normal", get_normal, 0); rb_define_method(newclass, "internal", get_internal, 0); rb_define_method(newclass, "encoding_short", get_encoding_short, 0); + rb_define_method(newclass, "encoding_long", get_encoding_long, 0); } diff --git a/ext/-test-/marshal/usr/depend b/ext/-test-/marshal/usr/depend index 1d56cc82022750..5ffb8c58de24be 100644 --- a/ext/-test-/marshal/usr/depend +++ b/ext/-test-/marshal/usr/depend @@ -128,6 +128,7 @@ usrmarshal.o: $(hdrdir)/ruby/internal/intern/re.h usrmarshal.o: $(hdrdir)/ruby/internal/intern/ruby.h usrmarshal.o: $(hdrdir)/ruby/internal/intern/select.h usrmarshal.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +usrmarshal.o: $(hdrdir)/ruby/internal/intern/set.h usrmarshal.o: $(hdrdir)/ruby/internal/intern/signal.h usrmarshal.o: $(hdrdir)/ruby/internal/intern/sprintf.h usrmarshal.o: $(hdrdir)/ruby/internal/intern/string.h @@ -147,6 +148,7 @@ usrmarshal.o: $(hdrdir)/ruby/internal/special_consts.h usrmarshal.o: $(hdrdir)/ruby/internal/static_assert.h usrmarshal.o: $(hdrdir)/ruby/internal/stdalign.h usrmarshal.o: $(hdrdir)/ruby/internal/stdbool.h +usrmarshal.o: $(hdrdir)/ruby/internal/stdckdint.h usrmarshal.o: $(hdrdir)/ruby/internal/symbol.h usrmarshal.o: $(hdrdir)/ruby/internal/value.h usrmarshal.o: $(hdrdir)/ruby/internal/value_type.h diff --git a/ext/-test-/memory_status/depend b/ext/-test-/memory_status/depend index 52e2fe8e1f2875..4dd503e1bba59c 100644 --- a/ext/-test-/memory_status/depend +++ b/ext/-test-/memory_status/depend @@ -147,6 +147,7 @@ memory_status.o: $(hdrdir)/ruby/internal/special_consts.h memory_status.o: $(hdrdir)/ruby/internal/static_assert.h memory_status.o: $(hdrdir)/ruby/internal/stdalign.h memory_status.o: $(hdrdir)/ruby/internal/stdbool.h +memory_status.o: $(hdrdir)/ruby/internal/stdckdint.h memory_status.o: $(hdrdir)/ruby/internal/symbol.h memory_status.o: $(hdrdir)/ruby/internal/value.h memory_status.o: $(hdrdir)/ruby/internal/value_type.h diff --git a/ext/-test-/memory_view/depend b/ext/-test-/memory_view/depend index c9ef06a15c5e1d..a6ffd76f459669 100644 --- a/ext/-test-/memory_view/depend +++ b/ext/-test-/memory_view/depend @@ -128,6 +128,7 @@ memory_view.o: $(hdrdir)/ruby/internal/intern/re.h memory_view.o: $(hdrdir)/ruby/internal/intern/ruby.h memory_view.o: $(hdrdir)/ruby/internal/intern/select.h memory_view.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +memory_view.o: $(hdrdir)/ruby/internal/intern/set.h memory_view.o: $(hdrdir)/ruby/internal/intern/signal.h memory_view.o: $(hdrdir)/ruby/internal/intern/sprintf.h memory_view.o: $(hdrdir)/ruby/internal/intern/string.h @@ -147,6 +148,7 @@ memory_view.o: $(hdrdir)/ruby/internal/special_consts.h memory_view.o: $(hdrdir)/ruby/internal/static_assert.h memory_view.o: $(hdrdir)/ruby/internal/stdalign.h memory_view.o: $(hdrdir)/ruby/internal/stdbool.h +memory_view.o: $(hdrdir)/ruby/internal/stdckdint.h memory_view.o: $(hdrdir)/ruby/internal/symbol.h memory_view.o: $(hdrdir)/ruby/internal/value.h memory_view.o: $(hdrdir)/ruby/internal/value_type.h diff --git a/ext/-test-/memory_view/memory_view.c b/ext/-test-/memory_view/memory_view.c index c1df0353cfc596..63f0beb81e42aa 100644 --- a/ext/-test-/memory_view/memory_view.c +++ b/ext/-test-/memory_view/memory_view.c @@ -313,8 +313,8 @@ mdview_get_memory_view(VALUE obj, rb_memory_view_t *view, int flags) static bool mdview_release_memory_view(VALUE obj, rb_memory_view_t *view) { - if (view->shape) xfree((void *)view->shape); - if (view->strides) xfree((void *)view->strides); + xfree((void *)view->shape); + xfree((void *)view->strides); return true; } diff --git a/ext/-test-/method/depend b/ext/-test-/method/depend index dbf513f48fc3ee..95745b3daea8eb 100644 --- a/ext/-test-/method/depend +++ b/ext/-test-/method/depend @@ -128,6 +128,7 @@ arity.o: $(hdrdir)/ruby/internal/intern/re.h arity.o: $(hdrdir)/ruby/internal/intern/ruby.h arity.o: $(hdrdir)/ruby/internal/intern/select.h arity.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +arity.o: $(hdrdir)/ruby/internal/intern/set.h arity.o: $(hdrdir)/ruby/internal/intern/signal.h arity.o: $(hdrdir)/ruby/internal/intern/sprintf.h arity.o: $(hdrdir)/ruby/internal/intern/string.h @@ -147,6 +148,7 @@ arity.o: $(hdrdir)/ruby/internal/special_consts.h arity.o: $(hdrdir)/ruby/internal/static_assert.h arity.o: $(hdrdir)/ruby/internal/stdalign.h arity.o: $(hdrdir)/ruby/internal/stdbool.h +arity.o: $(hdrdir)/ruby/internal/stdckdint.h arity.o: $(hdrdir)/ruby/internal/symbol.h arity.o: $(hdrdir)/ruby/internal/value.h arity.o: $(hdrdir)/ruby/internal/value_type.h @@ -287,6 +289,7 @@ init.o: $(hdrdir)/ruby/internal/intern/re.h init.o: $(hdrdir)/ruby/internal/intern/ruby.h init.o: $(hdrdir)/ruby/internal/intern/select.h init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +init.o: $(hdrdir)/ruby/internal/intern/set.h init.o: $(hdrdir)/ruby/internal/intern/signal.h init.o: $(hdrdir)/ruby/internal/intern/sprintf.h init.o: $(hdrdir)/ruby/internal/intern/string.h @@ -306,6 +309,7 @@ init.o: $(hdrdir)/ruby/internal/special_consts.h init.o: $(hdrdir)/ruby/internal/static_assert.h init.o: $(hdrdir)/ruby/internal/stdalign.h init.o: $(hdrdir)/ruby/internal/stdbool.h +init.o: $(hdrdir)/ruby/internal/stdckdint.h init.o: $(hdrdir)/ruby/internal/symbol.h init.o: $(hdrdir)/ruby/internal/value.h init.o: $(hdrdir)/ruby/internal/value_type.h diff --git a/ext/-test-/namespace/yay1/extconf.rb b/ext/-test-/namespace/yay1/extconf.rb new file mode 100644 index 00000000000000..539e99ab091b34 --- /dev/null +++ b/ext/-test-/namespace/yay1/extconf.rb @@ -0,0 +1 @@ +create_makefile('-test-/namespace/yay1') diff --git a/ext/-test-/namespace/yay1/yay1.c b/ext/-test-/namespace/yay1/yay1.c new file mode 100644 index 00000000000000..564a221c8c2be8 --- /dev/null +++ b/ext/-test-/namespace/yay1/yay1.c @@ -0,0 +1,28 @@ +#include "yay1.h" + +VALUE +yay_value(void) +{ + return rb_str_new_cstr("yay"); +} + +static VALUE +yay1_f_version(VALUE klass) +{ + return rb_str_new_cstr("1.0.0"); +} + +static VALUE +yay1_yay(VALUE klass) +{ + return yay_value(); +} + +void +Init_yay1(void) +{ + VALUE mod = rb_define_module("Yay"); + rb_define_const(mod, "VERSION", rb_str_new_cstr("1.0.0")); + rb_define_singleton_method(mod, "version", yay1_f_version, 0); + rb_define_singleton_method(mod, "yay", yay1_yay, 0); +} diff --git a/ext/-test-/namespace/yay1/yay1.def b/ext/-test-/namespace/yay1/yay1.def new file mode 100644 index 00000000000000..edbae873126604 --- /dev/null +++ b/ext/-test-/namespace/yay1/yay1.def @@ -0,0 +1,4 @@ +LIBRARY yay1 +EXPORTS + Init_yay1 + yay_value diff --git a/ext/-test-/namespace/yay1/yay1.h b/ext/-test-/namespace/yay1/yay1.h new file mode 100644 index 00000000000000..d68f8b552324b9 --- /dev/null +++ b/ext/-test-/namespace/yay1/yay1.h @@ -0,0 +1,4 @@ +#include +#include "ruby/internal/dllexport.h" + +RUBY_EXTERN VALUE yay_value(void); diff --git a/ext/-test-/namespace/yay2/extconf.rb b/ext/-test-/namespace/yay2/extconf.rb new file mode 100644 index 00000000000000..2027a42860ba6a --- /dev/null +++ b/ext/-test-/namespace/yay2/extconf.rb @@ -0,0 +1 @@ +create_makefile('-test-/namespace/yay2') diff --git a/ext/-test-/namespace/yay2/yay2.c b/ext/-test-/namespace/yay2/yay2.c new file mode 100644 index 00000000000000..b632ae8495be32 --- /dev/null +++ b/ext/-test-/namespace/yay2/yay2.c @@ -0,0 +1,28 @@ +#include "yay2.h" + +VALUE +yay_value(void) +{ + return rb_str_new_cstr("yaaay"); +} + +static VALUE +yay2_f_version(VALUE klass) +{ + return rb_str_new_cstr("2.0.0"); +} + +static VALUE +yay2_yay(VALUE klass) +{ + return yay_value(); +} + +void +Init_yay2(void) +{ + VALUE mod = rb_define_module("Yay"); + rb_define_const(mod, "VERSION", rb_str_new_cstr("2.0.0")); + rb_define_singleton_method(mod, "version", yay2_f_version, 0); + rb_define_singleton_method(mod, "yay", yay2_yay, 0); +} diff --git a/ext/-test-/namespace/yay2/yay2.def b/ext/-test-/namespace/yay2/yay2.def new file mode 100644 index 00000000000000..6bb6011f4b841d --- /dev/null +++ b/ext/-test-/namespace/yay2/yay2.def @@ -0,0 +1,4 @@ +LIBRARY yay2 +EXPORTS + Init_yay2 + yay_value diff --git a/ext/-test-/namespace/yay2/yay2.h b/ext/-test-/namespace/yay2/yay2.h new file mode 100644 index 00000000000000..d68f8b552324b9 --- /dev/null +++ b/ext/-test-/namespace/yay2/yay2.h @@ -0,0 +1,4 @@ +#include +#include "ruby/internal/dllexport.h" + +RUBY_EXTERN VALUE yay_value(void); diff --git a/ext/-test-/notimplement/depend b/ext/-test-/notimplement/depend index 9105093b0d39b1..69c970b6f25703 100644 --- a/ext/-test-/notimplement/depend +++ b/ext/-test-/notimplement/depend @@ -128,6 +128,7 @@ bug.o: $(hdrdir)/ruby/internal/intern/re.h bug.o: $(hdrdir)/ruby/internal/intern/ruby.h bug.o: $(hdrdir)/ruby/internal/intern/select.h bug.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +bug.o: $(hdrdir)/ruby/internal/intern/set.h bug.o: $(hdrdir)/ruby/internal/intern/signal.h bug.o: $(hdrdir)/ruby/internal/intern/sprintf.h bug.o: $(hdrdir)/ruby/internal/intern/string.h @@ -147,6 +148,7 @@ bug.o: $(hdrdir)/ruby/internal/special_consts.h bug.o: $(hdrdir)/ruby/internal/static_assert.h bug.o: $(hdrdir)/ruby/internal/stdalign.h bug.o: $(hdrdir)/ruby/internal/stdbool.h +bug.o: $(hdrdir)/ruby/internal/stdckdint.h bug.o: $(hdrdir)/ruby/internal/symbol.h bug.o: $(hdrdir)/ruby/internal/value.h bug.o: $(hdrdir)/ruby/internal/value_type.h diff --git a/ext/-test-/num2int/depend b/ext/-test-/num2int/depend index 4e05d1e8c1f319..75536363ac650d 100644 --- a/ext/-test-/num2int/depend +++ b/ext/-test-/num2int/depend @@ -128,6 +128,7 @@ num2int.o: $(hdrdir)/ruby/internal/intern/re.h num2int.o: $(hdrdir)/ruby/internal/intern/ruby.h num2int.o: $(hdrdir)/ruby/internal/intern/select.h num2int.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +num2int.o: $(hdrdir)/ruby/internal/intern/set.h num2int.o: $(hdrdir)/ruby/internal/intern/signal.h num2int.o: $(hdrdir)/ruby/internal/intern/sprintf.h num2int.o: $(hdrdir)/ruby/internal/intern/string.h @@ -147,6 +148,7 @@ num2int.o: $(hdrdir)/ruby/internal/special_consts.h num2int.o: $(hdrdir)/ruby/internal/static_assert.h num2int.o: $(hdrdir)/ruby/internal/stdalign.h num2int.o: $(hdrdir)/ruby/internal/stdbool.h +num2int.o: $(hdrdir)/ruby/internal/stdckdint.h num2int.o: $(hdrdir)/ruby/internal/symbol.h num2int.o: $(hdrdir)/ruby/internal/value.h num2int.o: $(hdrdir)/ruby/internal/value_type.h diff --git a/ext/-test-/path_to_class/depend b/ext/-test-/path_to_class/depend index 8fe6ee37c2e9e3..e535058e092935 100644 --- a/ext/-test-/path_to_class/depend +++ b/ext/-test-/path_to_class/depend @@ -128,6 +128,7 @@ path_to_class.o: $(hdrdir)/ruby/internal/intern/re.h path_to_class.o: $(hdrdir)/ruby/internal/intern/ruby.h path_to_class.o: $(hdrdir)/ruby/internal/intern/select.h path_to_class.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +path_to_class.o: $(hdrdir)/ruby/internal/intern/set.h path_to_class.o: $(hdrdir)/ruby/internal/intern/signal.h path_to_class.o: $(hdrdir)/ruby/internal/intern/sprintf.h path_to_class.o: $(hdrdir)/ruby/internal/intern/string.h @@ -147,6 +148,7 @@ path_to_class.o: $(hdrdir)/ruby/internal/special_consts.h path_to_class.o: $(hdrdir)/ruby/internal/static_assert.h path_to_class.o: $(hdrdir)/ruby/internal/stdalign.h path_to_class.o: $(hdrdir)/ruby/internal/stdbool.h +path_to_class.o: $(hdrdir)/ruby/internal/stdckdint.h path_to_class.o: $(hdrdir)/ruby/internal/symbol.h path_to_class.o: $(hdrdir)/ruby/internal/value.h path_to_class.o: $(hdrdir)/ruby/internal/value_type.h diff --git a/ext/-test-/popen_deadlock/depend b/ext/-test-/popen_deadlock/depend index fb58ca30e9900b..0b8932e8b8a191 100644 --- a/ext/-test-/popen_deadlock/depend +++ b/ext/-test-/popen_deadlock/depend @@ -128,6 +128,7 @@ infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/re.h infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/ruby.h infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/select.h infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/set.h infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/signal.h infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/sprintf.h infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/intern/string.h @@ -147,6 +148,7 @@ infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/special_consts.h infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/static_assert.h infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/stdalign.h infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/stdbool.h +infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/stdckdint.h infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/symbol.h infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/value.h infinite_loop_dlsym.o: $(hdrdir)/ruby/internal/value_type.h diff --git a/ext/-test-/postponed_job/depend b/ext/-test-/postponed_job/depend index e44d9d51b75e04..ff567e39215ce5 100644 --- a/ext/-test-/postponed_job/depend +++ b/ext/-test-/postponed_job/depend @@ -129,6 +129,7 @@ postponed_job.o: $(hdrdir)/ruby/internal/intern/re.h postponed_job.o: $(hdrdir)/ruby/internal/intern/ruby.h postponed_job.o: $(hdrdir)/ruby/internal/intern/select.h postponed_job.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +postponed_job.o: $(hdrdir)/ruby/internal/intern/set.h postponed_job.o: $(hdrdir)/ruby/internal/intern/signal.h postponed_job.o: $(hdrdir)/ruby/internal/intern/sprintf.h postponed_job.o: $(hdrdir)/ruby/internal/intern/string.h @@ -148,6 +149,7 @@ postponed_job.o: $(hdrdir)/ruby/internal/special_consts.h postponed_job.o: $(hdrdir)/ruby/internal/static_assert.h postponed_job.o: $(hdrdir)/ruby/internal/stdalign.h postponed_job.o: $(hdrdir)/ruby/internal/stdbool.h +postponed_job.o: $(hdrdir)/ruby/internal/stdckdint.h postponed_job.o: $(hdrdir)/ruby/internal/symbol.h postponed_job.o: $(hdrdir)/ruby/internal/value.h postponed_job.o: $(hdrdir)/ruby/internal/value_type.h diff --git a/ext/-test-/postponed_job/postponed_job.c b/ext/-test-/postponed_job/postponed_job.c index fa57bef6f5acec..9ac866ae7733ce 100644 --- a/ext/-test-/postponed_job/postponed_job.c +++ b/ext/-test-/postponed_job/postponed_job.c @@ -1,6 +1,29 @@ #include "ruby.h" #include "ruby/debug.h" +// We're testing deprecated things, don't print the compiler warnings +#if 0 + +#elif defined(_MSC_VER) +#pragma warning(disable : 4996) + +#elif defined(__INTEL_COMPILER) +#pragma warning(disable : 1786) + +#elif defined(__clang__) +#pragma clang diagnostic ignored "-Wdeprecated-declarations" + +#elif defined(__GNUC__) +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + +#elif defined(__SUNPRO_CC) +#pragma error_messages (off,symdeprecated) + +#else +// :FIXME: improve here for your compiler. + +#endif + static int counter; static void @@ -58,6 +81,22 @@ pjob_call_direct(VALUE self, VALUE obj) return self; } +static void pjob_noop_callback(void *data) { } + +static VALUE +pjob_register_one_same(VALUE self) +{ + rb_gc_start(); + int r1 = rb_postponed_job_register_one(0, pjob_noop_callback, NULL); + int r2 = rb_postponed_job_register_one(0, pjob_noop_callback, NULL); + int r3 = rb_postponed_job_register_one(0, pjob_noop_callback, NULL); + VALUE ary = rb_ary_new(); + rb_ary_push(ary, INT2FIX(r1)); + rb_ary_push(ary, INT2FIX(r2)); + rb_ary_push(ary, INT2FIX(r3)); + return ary; +} + #ifdef HAVE_PTHREAD_H #include @@ -86,6 +125,93 @@ pjob_register_in_c_thread(VALUE self, VALUE obj) } #endif +static void +pjob_preregistered_callback(void *data) +{ + VALUE ary = (VALUE)data; + Check_Type(ary, T_ARRAY); + rb_ary_push(ary, INT2FIX(counter)); +} + +static VALUE +pjob_preregister_and_call_with_sleep(VALUE self, VALUE obj) +{ + counter = 0; + rb_postponed_job_handle_t h = rb_postponed_job_preregister(0, pjob_preregistered_callback, (void *)obj); + counter++; + rb_postponed_job_trigger(h); + rb_thread_sleep(0); + counter++; + rb_postponed_job_trigger(h); + rb_thread_sleep(0); + counter++; + rb_postponed_job_trigger(h); + rb_thread_sleep(0); + return self; +} + +static VALUE +pjob_preregister_and_call_without_sleep(VALUE self, VALUE obj) +{ + counter = 0; + rb_postponed_job_handle_t h = rb_postponed_job_preregister(0, pjob_preregistered_callback, (void *)obj); + counter = 3; + rb_postponed_job_trigger(h); + rb_postponed_job_trigger(h); + rb_postponed_job_trigger(h); + return self; +} + +static VALUE +pjob_preregister_multiple_times(VALUE self) +{ + int r1 = rb_postponed_job_preregister(0, pjob_noop_callback, NULL); + int r2 = rb_postponed_job_preregister(0, pjob_noop_callback, NULL); + int r3 = rb_postponed_job_preregister(0, pjob_noop_callback, NULL); + VALUE ary = rb_ary_new(); + rb_ary_push(ary, INT2FIX(r1)); + rb_ary_push(ary, INT2FIX(r2)); + rb_ary_push(ary, INT2FIX(r3)); + return ary; + +} + +struct pjob_append_data_args { + VALUE ary; + VALUE data; +}; + +static void +pjob_append_data_callback(void *vctx) { + struct pjob_append_data_args *ctx = (struct pjob_append_data_args *)vctx; + Check_Type(ctx->ary, T_ARRAY); + rb_ary_push(ctx->ary, ctx->data); +} + +static VALUE +pjob_preregister_calls_with_last_argument(VALUE self) +{ + VALUE ary = rb_ary_new(); + + struct pjob_append_data_args arg1 = { .ary = ary, .data = INT2FIX(1) }; + struct pjob_append_data_args arg2 = { .ary = ary, .data = INT2FIX(2) }; + struct pjob_append_data_args arg3 = { .ary = ary, .data = INT2FIX(3) }; + struct pjob_append_data_args arg4 = { .ary = ary, .data = INT2FIX(4) }; + + rb_postponed_job_handle_t h; + h = rb_postponed_job_preregister(0, pjob_append_data_callback, &arg1); + rb_postponed_job_preregister(0, pjob_append_data_callback, &arg2); + rb_postponed_job_trigger(h); + rb_postponed_job_preregister(0, pjob_append_data_callback, &arg3); + rb_thread_sleep(0); // should execute with arg3 + + rb_postponed_job_preregister(0, pjob_append_data_callback, &arg4); + rb_postponed_job_trigger(h); + rb_thread_sleep(0); // should execute with arg4 + + return ary; +} + void Init_postponed_job(VALUE self) { @@ -93,8 +219,13 @@ Init_postponed_job(VALUE self) rb_define_module_function(mBug, "postponed_job_register", pjob_register, 1); rb_define_module_function(mBug, "postponed_job_register_one", pjob_register_one, 1); rb_define_module_function(mBug, "postponed_job_call_direct", pjob_call_direct, 1); + rb_define_module_function(mBug, "postponed_job_register_one_same", pjob_register_one_same, 0); #ifdef HAVE_PTHREAD_H rb_define_module_function(mBug, "postponed_job_register_in_c_thread", pjob_register_in_c_thread, 1); #endif + rb_define_module_function(mBug, "postponed_job_preregister_and_call_with_sleep", pjob_preregister_and_call_with_sleep, 1); + rb_define_module_function(mBug, "postponed_job_preregister_and_call_without_sleep", pjob_preregister_and_call_without_sleep, 1); + rb_define_module_function(mBug, "postponed_job_preregister_multiple_times", pjob_preregister_multiple_times, 0); + rb_define_module_function(mBug, "postponed_job_preregister_calls_with_last_argument", pjob_preregister_calls_with_last_argument, 0); } diff --git a/ext/-test-/printf/depend b/ext/-test-/printf/depend index b3970411033ebd..be895cf769a056 100644 --- a/ext/-test-/printf/depend +++ b/ext/-test-/printf/depend @@ -138,6 +138,7 @@ printf.o: $(hdrdir)/ruby/internal/intern/re.h printf.o: $(hdrdir)/ruby/internal/intern/ruby.h printf.o: $(hdrdir)/ruby/internal/intern/select.h printf.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +printf.o: $(hdrdir)/ruby/internal/intern/set.h printf.o: $(hdrdir)/ruby/internal/intern/signal.h printf.o: $(hdrdir)/ruby/internal/intern/sprintf.h printf.o: $(hdrdir)/ruby/internal/intern/string.h @@ -157,6 +158,7 @@ printf.o: $(hdrdir)/ruby/internal/special_consts.h printf.o: $(hdrdir)/ruby/internal/static_assert.h printf.o: $(hdrdir)/ruby/internal/stdalign.h printf.o: $(hdrdir)/ruby/internal/stdbool.h +printf.o: $(hdrdir)/ruby/internal/stdckdint.h printf.o: $(hdrdir)/ruby/internal/symbol.h printf.o: $(hdrdir)/ruby/internal/value.h printf.o: $(hdrdir)/ruby/internal/value_type.h diff --git a/ext/-test-/proc/depend b/ext/-test-/proc/depend index 7e78aa6f836cdc..97834db0a2d422 100644 --- a/ext/-test-/proc/depend +++ b/ext/-test-/proc/depend @@ -128,6 +128,7 @@ init.o: $(hdrdir)/ruby/internal/intern/re.h init.o: $(hdrdir)/ruby/internal/intern/ruby.h init.o: $(hdrdir)/ruby/internal/intern/select.h init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +init.o: $(hdrdir)/ruby/internal/intern/set.h init.o: $(hdrdir)/ruby/internal/intern/signal.h init.o: $(hdrdir)/ruby/internal/intern/sprintf.h init.o: $(hdrdir)/ruby/internal/intern/string.h @@ -147,6 +148,7 @@ init.o: $(hdrdir)/ruby/internal/special_consts.h init.o: $(hdrdir)/ruby/internal/static_assert.h init.o: $(hdrdir)/ruby/internal/stdalign.h init.o: $(hdrdir)/ruby/internal/stdbool.h +init.o: $(hdrdir)/ruby/internal/stdckdint.h init.o: $(hdrdir)/ruby/internal/symbol.h init.o: $(hdrdir)/ruby/internal/value.h init.o: $(hdrdir)/ruby/internal/value_type.h @@ -287,6 +289,7 @@ receiver.o: $(hdrdir)/ruby/internal/intern/re.h receiver.o: $(hdrdir)/ruby/internal/intern/ruby.h receiver.o: $(hdrdir)/ruby/internal/intern/select.h receiver.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +receiver.o: $(hdrdir)/ruby/internal/intern/set.h receiver.o: $(hdrdir)/ruby/internal/intern/signal.h receiver.o: $(hdrdir)/ruby/internal/intern/sprintf.h receiver.o: $(hdrdir)/ruby/internal/intern/string.h @@ -306,6 +309,7 @@ receiver.o: $(hdrdir)/ruby/internal/special_consts.h receiver.o: $(hdrdir)/ruby/internal/static_assert.h receiver.o: $(hdrdir)/ruby/internal/stdalign.h receiver.o: $(hdrdir)/ruby/internal/stdbool.h +receiver.o: $(hdrdir)/ruby/internal/stdckdint.h receiver.o: $(hdrdir)/ruby/internal/symbol.h receiver.o: $(hdrdir)/ruby/internal/value.h receiver.o: $(hdrdir)/ruby/internal/value_type.h @@ -446,6 +450,7 @@ super.o: $(hdrdir)/ruby/internal/intern/re.h super.o: $(hdrdir)/ruby/internal/intern/ruby.h super.o: $(hdrdir)/ruby/internal/intern/select.h super.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +super.o: $(hdrdir)/ruby/internal/intern/set.h super.o: $(hdrdir)/ruby/internal/intern/signal.h super.o: $(hdrdir)/ruby/internal/intern/sprintf.h super.o: $(hdrdir)/ruby/internal/intern/string.h @@ -465,6 +470,7 @@ super.o: $(hdrdir)/ruby/internal/special_consts.h super.o: $(hdrdir)/ruby/internal/static_assert.h super.o: $(hdrdir)/ruby/internal/stdalign.h super.o: $(hdrdir)/ruby/internal/stdbool.h +super.o: $(hdrdir)/ruby/internal/stdckdint.h super.o: $(hdrdir)/ruby/internal/symbol.h super.o: $(hdrdir)/ruby/internal/value.h super.o: $(hdrdir)/ruby/internal/value_type.h diff --git a/ext/-test-/public_header_warnings/extconf.rb b/ext/-test-/public_header_warnings/extconf.rb new file mode 100644 index 00000000000000..4431e09da40a69 --- /dev/null +++ b/ext/-test-/public_header_warnings/extconf.rb @@ -0,0 +1,28 @@ +# +# Under compilers with WERRORFLAG, MakeMakefile.try_compile treats warnings as errors, so we can +# use append_cflags to test whether the public header files emit warnings with certain flags turned +# on. +# +def check_append_cflags(flag, msg = nil) + msg ||= "flag #{flag} is not acceptable" + if $CFLAGS.include?(flag) + raise("flag #{flag} already present in $CFLAGS") + end + append_cflags(flag) + unless $CFLAGS.include?(flag) + system("cat mkmf.log") + raise(msg) + end +end + +if %w[gcc clang].include?(RbConfig::CONFIG['CC']) + config_string("WERRORFLAG") or raise("expected WERRORFLAG to be defined") + + # should be acceptable on all modern C compilers + check_append_cflags("-D_TEST_OK", "baseline compiler warning test failed") + + # Feature #20507: Allow compilation of C extensions with -Wconversion + check_append_cflags("-Wconversion", "-Wconversion raising warnings in public headers") +end + +create_makefile("-test-/public_header_warnings") diff --git a/ext/-test-/random/depend b/ext/-test-/random/depend index 3f9a52be446540..380c30fbe4a355 100644 --- a/ext/-test-/random/depend +++ b/ext/-test-/random/depend @@ -127,6 +127,7 @@ bad_version.o: $(hdrdir)/ruby/internal/intern/re.h bad_version.o: $(hdrdir)/ruby/internal/intern/ruby.h bad_version.o: $(hdrdir)/ruby/internal/intern/select.h bad_version.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +bad_version.o: $(hdrdir)/ruby/internal/intern/set.h bad_version.o: $(hdrdir)/ruby/internal/intern/signal.h bad_version.o: $(hdrdir)/ruby/internal/intern/sprintf.h bad_version.o: $(hdrdir)/ruby/internal/intern/string.h @@ -146,6 +147,7 @@ bad_version.o: $(hdrdir)/ruby/internal/special_consts.h bad_version.o: $(hdrdir)/ruby/internal/static_assert.h bad_version.o: $(hdrdir)/ruby/internal/stdalign.h bad_version.o: $(hdrdir)/ruby/internal/stdbool.h +bad_version.o: $(hdrdir)/ruby/internal/stdckdint.h bad_version.o: $(hdrdir)/ruby/internal/symbol.h bad_version.o: $(hdrdir)/ruby/internal/value.h bad_version.o: $(hdrdir)/ruby/internal/value_type.h @@ -287,6 +289,7 @@ init.o: $(hdrdir)/ruby/internal/intern/re.h init.o: $(hdrdir)/ruby/internal/intern/ruby.h init.o: $(hdrdir)/ruby/internal/intern/select.h init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +init.o: $(hdrdir)/ruby/internal/intern/set.h init.o: $(hdrdir)/ruby/internal/intern/signal.h init.o: $(hdrdir)/ruby/internal/intern/sprintf.h init.o: $(hdrdir)/ruby/internal/intern/string.h @@ -306,6 +309,7 @@ init.o: $(hdrdir)/ruby/internal/special_consts.h init.o: $(hdrdir)/ruby/internal/static_assert.h init.o: $(hdrdir)/ruby/internal/stdalign.h init.o: $(hdrdir)/ruby/internal/stdbool.h +init.o: $(hdrdir)/ruby/internal/stdckdint.h init.o: $(hdrdir)/ruby/internal/symbol.h init.o: $(hdrdir)/ruby/internal/value.h init.o: $(hdrdir)/ruby/internal/value_type.h @@ -445,6 +449,7 @@ loop.o: $(hdrdir)/ruby/internal/intern/re.h loop.o: $(hdrdir)/ruby/internal/intern/ruby.h loop.o: $(hdrdir)/ruby/internal/intern/select.h loop.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +loop.o: $(hdrdir)/ruby/internal/intern/set.h loop.o: $(hdrdir)/ruby/internal/intern/signal.h loop.o: $(hdrdir)/ruby/internal/intern/sprintf.h loop.o: $(hdrdir)/ruby/internal/intern/string.h @@ -464,6 +469,7 @@ loop.o: $(hdrdir)/ruby/internal/special_consts.h loop.o: $(hdrdir)/ruby/internal/static_assert.h loop.o: $(hdrdir)/ruby/internal/stdalign.h loop.o: $(hdrdir)/ruby/internal/stdbool.h +loop.o: $(hdrdir)/ruby/internal/stdckdint.h loop.o: $(hdrdir)/ruby/internal/symbol.h loop.o: $(hdrdir)/ruby/internal/value.h loop.o: $(hdrdir)/ruby/internal/value_type.h diff --git a/ext/-test-/random/loop.c b/ext/-test-/random/loop.c index b789ab1d0177d4..f79e5cfd832549 100644 --- a/ext/-test-/random/loop.c +++ b/ext/-test-/random/loop.c @@ -13,6 +13,15 @@ static const rb_random_interface_t random_loop_if = { RB_RANDOM_INTERFACE_DEFINE_WITH_REAL(loop) }; +static void +loop_free(void *ptr) +{ + rand_loop_t *r = ptr; + + xfree(r->buf); + xfree(r); +} + RB_RANDOM_DEFINE_INIT_INT32_FUNC(loop) static size_t random_loop_memsize(const void *ptr) @@ -25,7 +34,7 @@ static rb_random_data_type_t random_loop_type = { "random/loop", { rb_random_mark, - RUBY_TYPED_DEFAULT_FREE, + loop_free, random_loop_memsize, }, RB_RANDOM_PARENT, diff --git a/ext/-test-/rational/depend b/ext/-test-/rational/depend index cff2eae38d4bcf..56d6ab77d6c36a 100644 --- a/ext/-test-/rational/depend +++ b/ext/-test-/rational/depend @@ -132,6 +132,7 @@ rat.o: $(hdrdir)/ruby/internal/intern/re.h rat.o: $(hdrdir)/ruby/internal/intern/ruby.h rat.o: $(hdrdir)/ruby/internal/intern/select.h rat.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +rat.o: $(hdrdir)/ruby/internal/intern/set.h rat.o: $(hdrdir)/ruby/internal/intern/signal.h rat.o: $(hdrdir)/ruby/internal/intern/sprintf.h rat.o: $(hdrdir)/ruby/internal/intern/string.h @@ -151,6 +152,7 @@ rat.o: $(hdrdir)/ruby/internal/special_consts.h rat.o: $(hdrdir)/ruby/internal/static_assert.h rat.o: $(hdrdir)/ruby/internal/stdalign.h rat.o: $(hdrdir)/ruby/internal/stdbool.h +rat.o: $(hdrdir)/ruby/internal/stdckdint.h rat.o: $(hdrdir)/ruby/internal/symbol.h rat.o: $(hdrdir)/ruby/internal/value.h rat.o: $(hdrdir)/ruby/internal/value_type.h diff --git a/ext/-test-/rb_call_super_kw/depend b/ext/-test-/rb_call_super_kw/depend index a42ddc85acc456..bf34323ca7ddc8 100644 --- a/ext/-test-/rb_call_super_kw/depend +++ b/ext/-test-/rb_call_super_kw/depend @@ -128,6 +128,7 @@ rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/re.h rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/ruby.h rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/select.h rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/set.h rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/signal.h rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/sprintf.h rb_call_super_kw.o: $(hdrdir)/ruby/internal/intern/string.h @@ -147,6 +148,7 @@ rb_call_super_kw.o: $(hdrdir)/ruby/internal/special_consts.h rb_call_super_kw.o: $(hdrdir)/ruby/internal/static_assert.h rb_call_super_kw.o: $(hdrdir)/ruby/internal/stdalign.h rb_call_super_kw.o: $(hdrdir)/ruby/internal/stdbool.h +rb_call_super_kw.o: $(hdrdir)/ruby/internal/stdckdint.h rb_call_super_kw.o: $(hdrdir)/ruby/internal/symbol.h rb_call_super_kw.o: $(hdrdir)/ruby/internal/value.h rb_call_super_kw.o: $(hdrdir)/ruby/internal/value_type.h diff --git a/ext/-test-/recursion/depend b/ext/-test-/recursion/depend index 49377250efe760..b6487eb4dfa624 100644 --- a/ext/-test-/recursion/depend +++ b/ext/-test-/recursion/depend @@ -128,6 +128,7 @@ recursion.o: $(hdrdir)/ruby/internal/intern/re.h recursion.o: $(hdrdir)/ruby/internal/intern/ruby.h recursion.o: $(hdrdir)/ruby/internal/intern/select.h recursion.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +recursion.o: $(hdrdir)/ruby/internal/intern/set.h recursion.o: $(hdrdir)/ruby/internal/intern/signal.h recursion.o: $(hdrdir)/ruby/internal/intern/sprintf.h recursion.o: $(hdrdir)/ruby/internal/intern/string.h @@ -147,6 +148,7 @@ recursion.o: $(hdrdir)/ruby/internal/special_consts.h recursion.o: $(hdrdir)/ruby/internal/static_assert.h recursion.o: $(hdrdir)/ruby/internal/stdalign.h recursion.o: $(hdrdir)/ruby/internal/stdbool.h +recursion.o: $(hdrdir)/ruby/internal/stdckdint.h recursion.o: $(hdrdir)/ruby/internal/symbol.h recursion.o: $(hdrdir)/ruby/internal/value.h recursion.o: $(hdrdir)/ruby/internal/value_type.h diff --git a/ext/-test-/regexp/depend b/ext/-test-/regexp/depend index 484f0320dde545..5ba1b92f18898c 100644 --- a/ext/-test-/regexp/depend +++ b/ext/-test-/regexp/depend @@ -128,6 +128,7 @@ init.o: $(hdrdir)/ruby/internal/intern/re.h init.o: $(hdrdir)/ruby/internal/intern/ruby.h init.o: $(hdrdir)/ruby/internal/intern/select.h init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +init.o: $(hdrdir)/ruby/internal/intern/set.h init.o: $(hdrdir)/ruby/internal/intern/signal.h init.o: $(hdrdir)/ruby/internal/intern/sprintf.h init.o: $(hdrdir)/ruby/internal/intern/string.h @@ -147,6 +148,7 @@ init.o: $(hdrdir)/ruby/internal/special_consts.h init.o: $(hdrdir)/ruby/internal/static_assert.h init.o: $(hdrdir)/ruby/internal/stdalign.h init.o: $(hdrdir)/ruby/internal/stdbool.h +init.o: $(hdrdir)/ruby/internal/stdckdint.h init.o: $(hdrdir)/ruby/internal/symbol.h init.o: $(hdrdir)/ruby/internal/value.h init.o: $(hdrdir)/ruby/internal/value_type.h @@ -287,6 +289,7 @@ parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/re.h parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/ruby.h parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/select.h parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/set.h parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/signal.h parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/sprintf.h parse_depth_limit.o: $(hdrdir)/ruby/internal/intern/string.h @@ -306,6 +309,7 @@ parse_depth_limit.o: $(hdrdir)/ruby/internal/special_consts.h parse_depth_limit.o: $(hdrdir)/ruby/internal/static_assert.h parse_depth_limit.o: $(hdrdir)/ruby/internal/stdalign.h parse_depth_limit.o: $(hdrdir)/ruby/internal/stdbool.h +parse_depth_limit.o: $(hdrdir)/ruby/internal/stdckdint.h parse_depth_limit.o: $(hdrdir)/ruby/internal/symbol.h parse_depth_limit.o: $(hdrdir)/ruby/internal/value.h parse_depth_limit.o: $(hdrdir)/ruby/internal/value_type.h diff --git a/ext/-test-/scan_args/depend b/ext/-test-/scan_args/depend index 3bedc6a7cfca27..ca0fc1923860b0 100644 --- a/ext/-test-/scan_args/depend +++ b/ext/-test-/scan_args/depend @@ -128,6 +128,7 @@ scan_args.o: $(hdrdir)/ruby/internal/intern/re.h scan_args.o: $(hdrdir)/ruby/internal/intern/ruby.h scan_args.o: $(hdrdir)/ruby/internal/intern/select.h scan_args.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +scan_args.o: $(hdrdir)/ruby/internal/intern/set.h scan_args.o: $(hdrdir)/ruby/internal/intern/signal.h scan_args.o: $(hdrdir)/ruby/internal/intern/sprintf.h scan_args.o: $(hdrdir)/ruby/internal/intern/string.h @@ -147,6 +148,7 @@ scan_args.o: $(hdrdir)/ruby/internal/special_consts.h scan_args.o: $(hdrdir)/ruby/internal/static_assert.h scan_args.o: $(hdrdir)/ruby/internal/stdalign.h scan_args.o: $(hdrdir)/ruby/internal/stdbool.h +scan_args.o: $(hdrdir)/ruby/internal/stdckdint.h scan_args.o: $(hdrdir)/ruby/internal/symbol.h scan_args.o: $(hdrdir)/ruby/internal/value.h scan_args.o: $(hdrdir)/ruby/internal/value_type.h diff --git a/ext/-test-/st/foreach/depend b/ext/-test-/st/foreach/depend index fdfe356805fd5b..29aab2bb29511f 100644 --- a/ext/-test-/st/foreach/depend +++ b/ext/-test-/st/foreach/depend @@ -128,6 +128,7 @@ foreach.o: $(hdrdir)/ruby/internal/intern/re.h foreach.o: $(hdrdir)/ruby/internal/intern/ruby.h foreach.o: $(hdrdir)/ruby/internal/intern/select.h foreach.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +foreach.o: $(hdrdir)/ruby/internal/intern/set.h foreach.o: $(hdrdir)/ruby/internal/intern/signal.h foreach.o: $(hdrdir)/ruby/internal/intern/sprintf.h foreach.o: $(hdrdir)/ruby/internal/intern/string.h @@ -147,6 +148,7 @@ foreach.o: $(hdrdir)/ruby/internal/special_consts.h foreach.o: $(hdrdir)/ruby/internal/static_assert.h foreach.o: $(hdrdir)/ruby/internal/stdalign.h foreach.o: $(hdrdir)/ruby/internal/stdbool.h +foreach.o: $(hdrdir)/ruby/internal/stdckdint.h foreach.o: $(hdrdir)/ruby/internal/symbol.h foreach.o: $(hdrdir)/ruby/internal/value.h foreach.o: $(hdrdir)/ruby/internal/value_type.h diff --git a/ext/-test-/st/numhash/depend b/ext/-test-/st/numhash/depend index ef28c892f364e8..18320d55f56805 100644 --- a/ext/-test-/st/numhash/depend +++ b/ext/-test-/st/numhash/depend @@ -128,6 +128,7 @@ numhash.o: $(hdrdir)/ruby/internal/intern/re.h numhash.o: $(hdrdir)/ruby/internal/intern/ruby.h numhash.o: $(hdrdir)/ruby/internal/intern/select.h numhash.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +numhash.o: $(hdrdir)/ruby/internal/intern/set.h numhash.o: $(hdrdir)/ruby/internal/intern/signal.h numhash.o: $(hdrdir)/ruby/internal/intern/sprintf.h numhash.o: $(hdrdir)/ruby/internal/intern/string.h @@ -147,6 +148,7 @@ numhash.o: $(hdrdir)/ruby/internal/special_consts.h numhash.o: $(hdrdir)/ruby/internal/static_assert.h numhash.o: $(hdrdir)/ruby/internal/stdalign.h numhash.o: $(hdrdir)/ruby/internal/stdbool.h +numhash.o: $(hdrdir)/ruby/internal/stdckdint.h numhash.o: $(hdrdir)/ruby/internal/symbol.h numhash.o: $(hdrdir)/ruby/internal/value.h numhash.o: $(hdrdir)/ruby/internal/value_type.h diff --git a/ext/-test-/st/update/depend b/ext/-test-/st/update/depend index 2d5ff224a2852f..247f0efd6b39b6 100644 --- a/ext/-test-/st/update/depend +++ b/ext/-test-/st/update/depend @@ -128,6 +128,7 @@ update.o: $(hdrdir)/ruby/internal/intern/re.h update.o: $(hdrdir)/ruby/internal/intern/ruby.h update.o: $(hdrdir)/ruby/internal/intern/select.h update.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +update.o: $(hdrdir)/ruby/internal/intern/set.h update.o: $(hdrdir)/ruby/internal/intern/signal.h update.o: $(hdrdir)/ruby/internal/intern/sprintf.h update.o: $(hdrdir)/ruby/internal/intern/string.h @@ -147,6 +148,7 @@ update.o: $(hdrdir)/ruby/internal/special_consts.h update.o: $(hdrdir)/ruby/internal/static_assert.h update.o: $(hdrdir)/ruby/internal/stdalign.h update.o: $(hdrdir)/ruby/internal/stdbool.h +update.o: $(hdrdir)/ruby/internal/stdckdint.h update.o: $(hdrdir)/ruby/internal/symbol.h update.o: $(hdrdir)/ruby/internal/value.h update.o: $(hdrdir)/ruby/internal/value_type.h diff --git a/ext/-test-/stack/depend b/ext/-test-/stack/depend new file mode 100644 index 00000000000000..31571c882e6eb7 --- /dev/null +++ b/ext/-test-/stack/depend @@ -0,0 +1,178 @@ +# AUTOGENERATED DEPENDENCIES START +stack.o: $(RUBY_EXTCONF_H) +stack.o: $(arch_hdrdir)/ruby/config.h +stack.o: $(hdrdir)/ruby.h +stack.o: $(hdrdir)/ruby/assert.h +stack.o: $(hdrdir)/ruby/backward.h +stack.o: $(hdrdir)/ruby/backward/2/assume.h +stack.o: $(hdrdir)/ruby/backward/2/attributes.h +stack.o: $(hdrdir)/ruby/backward/2/bool.h +stack.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h +stack.o: $(hdrdir)/ruby/backward/2/inttypes.h +stack.o: $(hdrdir)/ruby/backward/2/limits.h +stack.o: $(hdrdir)/ruby/backward/2/long_long.h +stack.o: $(hdrdir)/ruby/backward/2/stdalign.h +stack.o: $(hdrdir)/ruby/backward/2/stdarg.h +stack.o: $(hdrdir)/ruby/defines.h +stack.o: $(hdrdir)/ruby/encoding.h +stack.o: $(hdrdir)/ruby/intern.h +stack.o: $(hdrdir)/ruby/internal/abi.h +stack.o: $(hdrdir)/ruby/internal/anyargs.h +stack.o: $(hdrdir)/ruby/internal/arithmetic.h +stack.o: $(hdrdir)/ruby/internal/arithmetic/char.h +stack.o: $(hdrdir)/ruby/internal/arithmetic/double.h +stack.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +stack.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +stack.o: $(hdrdir)/ruby/internal/arithmetic/int.h +stack.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +stack.o: $(hdrdir)/ruby/internal/arithmetic/long.h +stack.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +stack.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +stack.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +stack.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +stack.o: $(hdrdir)/ruby/internal/arithmetic/short.h +stack.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +stack.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +stack.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +stack.o: $(hdrdir)/ruby/internal/assume.h +stack.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +stack.o: $(hdrdir)/ruby/internal/attr/artificial.h +stack.o: $(hdrdir)/ruby/internal/attr/cold.h +stack.o: $(hdrdir)/ruby/internal/attr/const.h +stack.o: $(hdrdir)/ruby/internal/attr/constexpr.h +stack.o: $(hdrdir)/ruby/internal/attr/deprecated.h +stack.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +stack.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +stack.o: $(hdrdir)/ruby/internal/attr/error.h +stack.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +stack.o: $(hdrdir)/ruby/internal/attr/forceinline.h +stack.o: $(hdrdir)/ruby/internal/attr/format.h +stack.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +stack.o: $(hdrdir)/ruby/internal/attr/noalias.h +stack.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +stack.o: $(hdrdir)/ruby/internal/attr/noexcept.h +stack.o: $(hdrdir)/ruby/internal/attr/noinline.h +stack.o: $(hdrdir)/ruby/internal/attr/nonnull.h +stack.o: $(hdrdir)/ruby/internal/attr/noreturn.h +stack.o: $(hdrdir)/ruby/internal/attr/packed_struct.h +stack.o: $(hdrdir)/ruby/internal/attr/pure.h +stack.o: $(hdrdir)/ruby/internal/attr/restrict.h +stack.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +stack.o: $(hdrdir)/ruby/internal/attr/warning.h +stack.o: $(hdrdir)/ruby/internal/attr/weakref.h +stack.o: $(hdrdir)/ruby/internal/cast.h +stack.o: $(hdrdir)/ruby/internal/compiler_is.h +stack.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +stack.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +stack.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +stack.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +stack.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +stack.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +stack.o: $(hdrdir)/ruby/internal/compiler_since.h +stack.o: $(hdrdir)/ruby/internal/config.h +stack.o: $(hdrdir)/ruby/internal/constant_p.h +stack.o: $(hdrdir)/ruby/internal/core.h +stack.o: $(hdrdir)/ruby/internal/core/rarray.h +stack.o: $(hdrdir)/ruby/internal/core/rbasic.h +stack.o: $(hdrdir)/ruby/internal/core/rbignum.h +stack.o: $(hdrdir)/ruby/internal/core/rclass.h +stack.o: $(hdrdir)/ruby/internal/core/rdata.h +stack.o: $(hdrdir)/ruby/internal/core/rfile.h +stack.o: $(hdrdir)/ruby/internal/core/rhash.h +stack.o: $(hdrdir)/ruby/internal/core/robject.h +stack.o: $(hdrdir)/ruby/internal/core/rregexp.h +stack.o: $(hdrdir)/ruby/internal/core/rstring.h +stack.o: $(hdrdir)/ruby/internal/core/rstruct.h +stack.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +stack.o: $(hdrdir)/ruby/internal/ctype.h +stack.o: $(hdrdir)/ruby/internal/dllexport.h +stack.o: $(hdrdir)/ruby/internal/dosish.h +stack.o: $(hdrdir)/ruby/internal/encoding/coderange.h +stack.o: $(hdrdir)/ruby/internal/encoding/ctype.h +stack.o: $(hdrdir)/ruby/internal/encoding/encoding.h +stack.o: $(hdrdir)/ruby/internal/encoding/pathname.h +stack.o: $(hdrdir)/ruby/internal/encoding/re.h +stack.o: $(hdrdir)/ruby/internal/encoding/sprintf.h +stack.o: $(hdrdir)/ruby/internal/encoding/string.h +stack.o: $(hdrdir)/ruby/internal/encoding/symbol.h +stack.o: $(hdrdir)/ruby/internal/encoding/transcode.h +stack.o: $(hdrdir)/ruby/internal/error.h +stack.o: $(hdrdir)/ruby/internal/eval.h +stack.o: $(hdrdir)/ruby/internal/event.h +stack.o: $(hdrdir)/ruby/internal/fl_type.h +stack.o: $(hdrdir)/ruby/internal/gc.h +stack.o: $(hdrdir)/ruby/internal/glob.h +stack.o: $(hdrdir)/ruby/internal/globals.h +stack.o: $(hdrdir)/ruby/internal/has/attribute.h +stack.o: $(hdrdir)/ruby/internal/has/builtin.h +stack.o: $(hdrdir)/ruby/internal/has/c_attribute.h +stack.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +stack.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +stack.o: $(hdrdir)/ruby/internal/has/extension.h +stack.o: $(hdrdir)/ruby/internal/has/feature.h +stack.o: $(hdrdir)/ruby/internal/has/warning.h +stack.o: $(hdrdir)/ruby/internal/intern/array.h +stack.o: $(hdrdir)/ruby/internal/intern/bignum.h +stack.o: $(hdrdir)/ruby/internal/intern/class.h +stack.o: $(hdrdir)/ruby/internal/intern/compar.h +stack.o: $(hdrdir)/ruby/internal/intern/complex.h +stack.o: $(hdrdir)/ruby/internal/intern/cont.h +stack.o: $(hdrdir)/ruby/internal/intern/dir.h +stack.o: $(hdrdir)/ruby/internal/intern/enum.h +stack.o: $(hdrdir)/ruby/internal/intern/enumerator.h +stack.o: $(hdrdir)/ruby/internal/intern/error.h +stack.o: $(hdrdir)/ruby/internal/intern/eval.h +stack.o: $(hdrdir)/ruby/internal/intern/file.h +stack.o: $(hdrdir)/ruby/internal/intern/hash.h +stack.o: $(hdrdir)/ruby/internal/intern/io.h +stack.o: $(hdrdir)/ruby/internal/intern/load.h +stack.o: $(hdrdir)/ruby/internal/intern/marshal.h +stack.o: $(hdrdir)/ruby/internal/intern/numeric.h +stack.o: $(hdrdir)/ruby/internal/intern/object.h +stack.o: $(hdrdir)/ruby/internal/intern/parse.h +stack.o: $(hdrdir)/ruby/internal/intern/proc.h +stack.o: $(hdrdir)/ruby/internal/intern/process.h +stack.o: $(hdrdir)/ruby/internal/intern/random.h +stack.o: $(hdrdir)/ruby/internal/intern/range.h +stack.o: $(hdrdir)/ruby/internal/intern/rational.h +stack.o: $(hdrdir)/ruby/internal/intern/re.h +stack.o: $(hdrdir)/ruby/internal/intern/ruby.h +stack.o: $(hdrdir)/ruby/internal/intern/select.h +stack.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +stack.o: $(hdrdir)/ruby/internal/intern/set.h +stack.o: $(hdrdir)/ruby/internal/intern/signal.h +stack.o: $(hdrdir)/ruby/internal/intern/sprintf.h +stack.o: $(hdrdir)/ruby/internal/intern/string.h +stack.o: $(hdrdir)/ruby/internal/intern/struct.h +stack.o: $(hdrdir)/ruby/internal/intern/thread.h +stack.o: $(hdrdir)/ruby/internal/intern/time.h +stack.o: $(hdrdir)/ruby/internal/intern/variable.h +stack.o: $(hdrdir)/ruby/internal/intern/vm.h +stack.o: $(hdrdir)/ruby/internal/interpreter.h +stack.o: $(hdrdir)/ruby/internal/iterator.h +stack.o: $(hdrdir)/ruby/internal/memory.h +stack.o: $(hdrdir)/ruby/internal/method.h +stack.o: $(hdrdir)/ruby/internal/module.h +stack.o: $(hdrdir)/ruby/internal/newobj.h +stack.o: $(hdrdir)/ruby/internal/scan_args.h +stack.o: $(hdrdir)/ruby/internal/special_consts.h +stack.o: $(hdrdir)/ruby/internal/static_assert.h +stack.o: $(hdrdir)/ruby/internal/stdalign.h +stack.o: $(hdrdir)/ruby/internal/stdbool.h +stack.o: $(hdrdir)/ruby/internal/stdckdint.h +stack.o: $(hdrdir)/ruby/internal/symbol.h +stack.o: $(hdrdir)/ruby/internal/value.h +stack.o: $(hdrdir)/ruby/internal/value_type.h +stack.o: $(hdrdir)/ruby/internal/variable.h +stack.o: $(hdrdir)/ruby/internal/warning_push.h +stack.o: $(hdrdir)/ruby/internal/xmalloc.h +stack.o: $(hdrdir)/ruby/missing.h +stack.o: $(hdrdir)/ruby/onigmo.h +stack.o: $(hdrdir)/ruby/oniguruma.h +stack.o: $(hdrdir)/ruby/ruby.h +stack.o: $(hdrdir)/ruby/st.h +stack.o: $(hdrdir)/ruby/subst.h +stack.o: $(top_srcdir)/internal/compilers.h +stack.o: $(top_srcdir)/internal/string.h +stack.o: stack.c +# AUTOGENERATED DEPENDENCIES END diff --git a/ext/-test-/stack/extconf.rb b/ext/-test-/stack/extconf.rb new file mode 100644 index 00000000000000..d786b15db98c7f --- /dev/null +++ b/ext/-test-/stack/extconf.rb @@ -0,0 +1,3 @@ +# frozen_string_literal: false +require_relative "../auto_ext.rb" +auto_ext(inc: true) diff --git a/ext/-test-/stack/stack.c b/ext/-test-/stack/stack.c new file mode 100644 index 00000000000000..8ff32f9737b218 --- /dev/null +++ b/ext/-test-/stack/stack.c @@ -0,0 +1,35 @@ +#include "ruby.h" +#include "internal/string.h" + +static VALUE +stack_alloca_overflow(VALUE self) +{ + size_t i = 0; + + while (1) { + // Allocate and touch memory to force actual stack usage: + volatile char *stack = alloca(1024); + stack[0] = (char)i; + stack[1023] = (char)i; + i++; + } + + return Qnil; +} + +static VALUE +asan_p(VALUE klass) +{ +#if defined(__SANITIZE_ADDRESS__) || __has_feature(address_sanitizer) + return Qtrue; +#else + return Qfalse; +#endif +} + +void +Init_stack(VALUE klass) +{ + rb_define_singleton_method(rb_cThread, "alloca_overflow", stack_alloca_overflow, 0); + rb_define_singleton_method(rb_cThread, "asan?", asan_p, 0); +} diff --git a/ext/-test-/string/depend b/ext/-test-/string/depend index 26720282b2dabf..de6e775accf395 100644 --- a/ext/-test-/string/depend +++ b/ext/-test-/string/depend @@ -139,6 +139,7 @@ capacity.o: $(hdrdir)/ruby/internal/intern/re.h capacity.o: $(hdrdir)/ruby/internal/intern/ruby.h capacity.o: $(hdrdir)/ruby/internal/intern/select.h capacity.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +capacity.o: $(hdrdir)/ruby/internal/intern/set.h capacity.o: $(hdrdir)/ruby/internal/intern/signal.h capacity.o: $(hdrdir)/ruby/internal/intern/sprintf.h capacity.o: $(hdrdir)/ruby/internal/intern/string.h @@ -158,6 +159,7 @@ capacity.o: $(hdrdir)/ruby/internal/special_consts.h capacity.o: $(hdrdir)/ruby/internal/static_assert.h capacity.o: $(hdrdir)/ruby/internal/stdalign.h capacity.o: $(hdrdir)/ruby/internal/stdbool.h +capacity.o: $(hdrdir)/ruby/internal/stdckdint.h capacity.o: $(hdrdir)/ruby/internal/symbol.h capacity.o: $(hdrdir)/ruby/internal/value.h capacity.o: $(hdrdir)/ruby/internal/value_type.h @@ -173,6 +175,166 @@ capacity.o: $(hdrdir)/ruby/subst.h capacity.o: $(top_srcdir)/internal/compilers.h capacity.o: $(top_srcdir)/internal/string.h capacity.o: capacity.c +chilled.o: $(RUBY_EXTCONF_H) +chilled.o: $(arch_hdrdir)/ruby/config.h +chilled.o: $(hdrdir)/ruby.h +chilled.o: $(hdrdir)/ruby/assert.h +chilled.o: $(hdrdir)/ruby/backward.h +chilled.o: $(hdrdir)/ruby/backward/2/assume.h +chilled.o: $(hdrdir)/ruby/backward/2/attributes.h +chilled.o: $(hdrdir)/ruby/backward/2/bool.h +chilled.o: $(hdrdir)/ruby/backward/2/inttypes.h +chilled.o: $(hdrdir)/ruby/backward/2/limits.h +chilled.o: $(hdrdir)/ruby/backward/2/long_long.h +chilled.o: $(hdrdir)/ruby/backward/2/stdalign.h +chilled.o: $(hdrdir)/ruby/backward/2/stdarg.h +chilled.o: $(hdrdir)/ruby/defines.h +chilled.o: $(hdrdir)/ruby/intern.h +chilled.o: $(hdrdir)/ruby/internal/abi.h +chilled.o: $(hdrdir)/ruby/internal/anyargs.h +chilled.o: $(hdrdir)/ruby/internal/arithmetic.h +chilled.o: $(hdrdir)/ruby/internal/arithmetic/char.h +chilled.o: $(hdrdir)/ruby/internal/arithmetic/double.h +chilled.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +chilled.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +chilled.o: $(hdrdir)/ruby/internal/arithmetic/int.h +chilled.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +chilled.o: $(hdrdir)/ruby/internal/arithmetic/long.h +chilled.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +chilled.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +chilled.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +chilled.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +chilled.o: $(hdrdir)/ruby/internal/arithmetic/short.h +chilled.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +chilled.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +chilled.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +chilled.o: $(hdrdir)/ruby/internal/assume.h +chilled.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +chilled.o: $(hdrdir)/ruby/internal/attr/artificial.h +chilled.o: $(hdrdir)/ruby/internal/attr/cold.h +chilled.o: $(hdrdir)/ruby/internal/attr/const.h +chilled.o: $(hdrdir)/ruby/internal/attr/constexpr.h +chilled.o: $(hdrdir)/ruby/internal/attr/deprecated.h +chilled.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +chilled.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +chilled.o: $(hdrdir)/ruby/internal/attr/error.h +chilled.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +chilled.o: $(hdrdir)/ruby/internal/attr/forceinline.h +chilled.o: $(hdrdir)/ruby/internal/attr/format.h +chilled.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +chilled.o: $(hdrdir)/ruby/internal/attr/noalias.h +chilled.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +chilled.o: $(hdrdir)/ruby/internal/attr/noexcept.h +chilled.o: $(hdrdir)/ruby/internal/attr/noinline.h +chilled.o: $(hdrdir)/ruby/internal/attr/nonnull.h +chilled.o: $(hdrdir)/ruby/internal/attr/noreturn.h +chilled.o: $(hdrdir)/ruby/internal/attr/packed_struct.h +chilled.o: $(hdrdir)/ruby/internal/attr/pure.h +chilled.o: $(hdrdir)/ruby/internal/attr/restrict.h +chilled.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +chilled.o: $(hdrdir)/ruby/internal/attr/warning.h +chilled.o: $(hdrdir)/ruby/internal/attr/weakref.h +chilled.o: $(hdrdir)/ruby/internal/cast.h +chilled.o: $(hdrdir)/ruby/internal/compiler_is.h +chilled.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +chilled.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +chilled.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +chilled.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +chilled.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +chilled.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +chilled.o: $(hdrdir)/ruby/internal/compiler_since.h +chilled.o: $(hdrdir)/ruby/internal/config.h +chilled.o: $(hdrdir)/ruby/internal/constant_p.h +chilled.o: $(hdrdir)/ruby/internal/core.h +chilled.o: $(hdrdir)/ruby/internal/core/rarray.h +chilled.o: $(hdrdir)/ruby/internal/core/rbasic.h +chilled.o: $(hdrdir)/ruby/internal/core/rbignum.h +chilled.o: $(hdrdir)/ruby/internal/core/rclass.h +chilled.o: $(hdrdir)/ruby/internal/core/rdata.h +chilled.o: $(hdrdir)/ruby/internal/core/rfile.h +chilled.o: $(hdrdir)/ruby/internal/core/rhash.h +chilled.o: $(hdrdir)/ruby/internal/core/robject.h +chilled.o: $(hdrdir)/ruby/internal/core/rregexp.h +chilled.o: $(hdrdir)/ruby/internal/core/rstring.h +chilled.o: $(hdrdir)/ruby/internal/core/rstruct.h +chilled.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +chilled.o: $(hdrdir)/ruby/internal/ctype.h +chilled.o: $(hdrdir)/ruby/internal/dllexport.h +chilled.o: $(hdrdir)/ruby/internal/dosish.h +chilled.o: $(hdrdir)/ruby/internal/error.h +chilled.o: $(hdrdir)/ruby/internal/eval.h +chilled.o: $(hdrdir)/ruby/internal/event.h +chilled.o: $(hdrdir)/ruby/internal/fl_type.h +chilled.o: $(hdrdir)/ruby/internal/gc.h +chilled.o: $(hdrdir)/ruby/internal/glob.h +chilled.o: $(hdrdir)/ruby/internal/globals.h +chilled.o: $(hdrdir)/ruby/internal/has/attribute.h +chilled.o: $(hdrdir)/ruby/internal/has/builtin.h +chilled.o: $(hdrdir)/ruby/internal/has/c_attribute.h +chilled.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +chilled.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +chilled.o: $(hdrdir)/ruby/internal/has/extension.h +chilled.o: $(hdrdir)/ruby/internal/has/feature.h +chilled.o: $(hdrdir)/ruby/internal/has/warning.h +chilled.o: $(hdrdir)/ruby/internal/intern/array.h +chilled.o: $(hdrdir)/ruby/internal/intern/bignum.h +chilled.o: $(hdrdir)/ruby/internal/intern/class.h +chilled.o: $(hdrdir)/ruby/internal/intern/compar.h +chilled.o: $(hdrdir)/ruby/internal/intern/complex.h +chilled.o: $(hdrdir)/ruby/internal/intern/cont.h +chilled.o: $(hdrdir)/ruby/internal/intern/dir.h +chilled.o: $(hdrdir)/ruby/internal/intern/enum.h +chilled.o: $(hdrdir)/ruby/internal/intern/enumerator.h +chilled.o: $(hdrdir)/ruby/internal/intern/error.h +chilled.o: $(hdrdir)/ruby/internal/intern/eval.h +chilled.o: $(hdrdir)/ruby/internal/intern/file.h +chilled.o: $(hdrdir)/ruby/internal/intern/hash.h +chilled.o: $(hdrdir)/ruby/internal/intern/io.h +chilled.o: $(hdrdir)/ruby/internal/intern/load.h +chilled.o: $(hdrdir)/ruby/internal/intern/marshal.h +chilled.o: $(hdrdir)/ruby/internal/intern/numeric.h +chilled.o: $(hdrdir)/ruby/internal/intern/object.h +chilled.o: $(hdrdir)/ruby/internal/intern/parse.h +chilled.o: $(hdrdir)/ruby/internal/intern/proc.h +chilled.o: $(hdrdir)/ruby/internal/intern/process.h +chilled.o: $(hdrdir)/ruby/internal/intern/random.h +chilled.o: $(hdrdir)/ruby/internal/intern/range.h +chilled.o: $(hdrdir)/ruby/internal/intern/rational.h +chilled.o: $(hdrdir)/ruby/internal/intern/re.h +chilled.o: $(hdrdir)/ruby/internal/intern/ruby.h +chilled.o: $(hdrdir)/ruby/internal/intern/select.h +chilled.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +chilled.o: $(hdrdir)/ruby/internal/intern/signal.h +chilled.o: $(hdrdir)/ruby/internal/intern/sprintf.h +chilled.o: $(hdrdir)/ruby/internal/intern/string.h +chilled.o: $(hdrdir)/ruby/internal/intern/struct.h +chilled.o: $(hdrdir)/ruby/internal/intern/thread.h +chilled.o: $(hdrdir)/ruby/internal/intern/time.h +chilled.o: $(hdrdir)/ruby/internal/intern/variable.h +chilled.o: $(hdrdir)/ruby/internal/intern/vm.h +chilled.o: $(hdrdir)/ruby/internal/interpreter.h +chilled.o: $(hdrdir)/ruby/internal/iterator.h +chilled.o: $(hdrdir)/ruby/internal/memory.h +chilled.o: $(hdrdir)/ruby/internal/method.h +chilled.o: $(hdrdir)/ruby/internal/module.h +chilled.o: $(hdrdir)/ruby/internal/newobj.h +chilled.o: $(hdrdir)/ruby/internal/scan_args.h +chilled.o: $(hdrdir)/ruby/internal/special_consts.h +chilled.o: $(hdrdir)/ruby/internal/static_assert.h +chilled.o: $(hdrdir)/ruby/internal/stdalign.h +chilled.o: $(hdrdir)/ruby/internal/stdbool.h +chilled.o: $(hdrdir)/ruby/internal/stdckdint.h +chilled.o: $(hdrdir)/ruby/internal/symbol.h +chilled.o: $(hdrdir)/ruby/internal/value.h +chilled.o: $(hdrdir)/ruby/internal/value_type.h +chilled.o: $(hdrdir)/ruby/internal/variable.h +chilled.o: $(hdrdir)/ruby/internal/warning_push.h +chilled.o: $(hdrdir)/ruby/internal/xmalloc.h +chilled.o: $(hdrdir)/ruby/missing.h +chilled.o: $(hdrdir)/ruby/ruby.h +chilled.o: $(hdrdir)/ruby/st.h +chilled.o: $(hdrdir)/ruby/subst.h +chilled.o: chilled.c coderange.o: $(RUBY_EXTCONF_H) coderange.o: $(arch_hdrdir)/ruby/config.h coderange.o: $(hdrdir)/ruby/assert.h @@ -311,6 +473,7 @@ coderange.o: $(hdrdir)/ruby/internal/intern/re.h coderange.o: $(hdrdir)/ruby/internal/intern/ruby.h coderange.o: $(hdrdir)/ruby/internal/intern/select.h coderange.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +coderange.o: $(hdrdir)/ruby/internal/intern/set.h coderange.o: $(hdrdir)/ruby/internal/intern/signal.h coderange.o: $(hdrdir)/ruby/internal/intern/sprintf.h coderange.o: $(hdrdir)/ruby/internal/intern/string.h @@ -330,6 +493,7 @@ coderange.o: $(hdrdir)/ruby/internal/special_consts.h coderange.o: $(hdrdir)/ruby/internal/static_assert.h coderange.o: $(hdrdir)/ruby/internal/stdalign.h coderange.o: $(hdrdir)/ruby/internal/stdbool.h +coderange.o: $(hdrdir)/ruby/internal/stdckdint.h coderange.o: $(hdrdir)/ruby/internal/symbol.h coderange.o: $(hdrdir)/ruby/internal/value.h coderange.o: $(hdrdir)/ruby/internal/value_type.h @@ -482,6 +646,7 @@ cstr.o: $(hdrdir)/ruby/internal/intern/re.h cstr.o: $(hdrdir)/ruby/internal/intern/ruby.h cstr.o: $(hdrdir)/ruby/internal/intern/select.h cstr.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +cstr.o: $(hdrdir)/ruby/internal/intern/set.h cstr.o: $(hdrdir)/ruby/internal/intern/signal.h cstr.o: $(hdrdir)/ruby/internal/intern/sprintf.h cstr.o: $(hdrdir)/ruby/internal/intern/string.h @@ -501,6 +666,7 @@ cstr.o: $(hdrdir)/ruby/internal/special_consts.h cstr.o: $(hdrdir)/ruby/internal/static_assert.h cstr.o: $(hdrdir)/ruby/internal/stdalign.h cstr.o: $(hdrdir)/ruby/internal/stdbool.h +cstr.o: $(hdrdir)/ruby/internal/stdckdint.h cstr.o: $(hdrdir)/ruby/internal/symbol.h cstr.o: $(hdrdir)/ruby/internal/value.h cstr.o: $(hdrdir)/ruby/internal/value_type.h @@ -646,6 +812,7 @@ ellipsize.o: $(hdrdir)/ruby/internal/intern/re.h ellipsize.o: $(hdrdir)/ruby/internal/intern/ruby.h ellipsize.o: $(hdrdir)/ruby/internal/intern/select.h ellipsize.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +ellipsize.o: $(hdrdir)/ruby/internal/intern/set.h ellipsize.o: $(hdrdir)/ruby/internal/intern/signal.h ellipsize.o: $(hdrdir)/ruby/internal/intern/sprintf.h ellipsize.o: $(hdrdir)/ruby/internal/intern/string.h @@ -665,6 +832,7 @@ ellipsize.o: $(hdrdir)/ruby/internal/special_consts.h ellipsize.o: $(hdrdir)/ruby/internal/static_assert.h ellipsize.o: $(hdrdir)/ruby/internal/stdalign.h ellipsize.o: $(hdrdir)/ruby/internal/stdbool.h +ellipsize.o: $(hdrdir)/ruby/internal/stdckdint.h ellipsize.o: $(hdrdir)/ruby/internal/symbol.h ellipsize.o: $(hdrdir)/ruby/internal/value.h ellipsize.o: $(hdrdir)/ruby/internal/value_type.h @@ -815,6 +983,7 @@ enc_associate.o: $(hdrdir)/ruby/internal/intern/re.h enc_associate.o: $(hdrdir)/ruby/internal/intern/ruby.h enc_associate.o: $(hdrdir)/ruby/internal/intern/select.h enc_associate.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +enc_associate.o: $(hdrdir)/ruby/internal/intern/set.h enc_associate.o: $(hdrdir)/ruby/internal/intern/signal.h enc_associate.o: $(hdrdir)/ruby/internal/intern/sprintf.h enc_associate.o: $(hdrdir)/ruby/internal/intern/string.h @@ -834,6 +1003,7 @@ enc_associate.o: $(hdrdir)/ruby/internal/special_consts.h enc_associate.o: $(hdrdir)/ruby/internal/static_assert.h enc_associate.o: $(hdrdir)/ruby/internal/stdalign.h enc_associate.o: $(hdrdir)/ruby/internal/stdbool.h +enc_associate.o: $(hdrdir)/ruby/internal/stdckdint.h enc_associate.o: $(hdrdir)/ruby/internal/symbol.h enc_associate.o: $(hdrdir)/ruby/internal/value.h enc_associate.o: $(hdrdir)/ruby/internal/value_type.h @@ -986,6 +1156,7 @@ enc_dummy.o: $(hdrdir)/ruby/internal/intern/re.h enc_dummy.o: $(hdrdir)/ruby/internal/intern/ruby.h enc_dummy.o: $(hdrdir)/ruby/internal/intern/select.h enc_dummy.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +enc_dummy.o: $(hdrdir)/ruby/internal/intern/set.h enc_dummy.o: $(hdrdir)/ruby/internal/intern/signal.h enc_dummy.o: $(hdrdir)/ruby/internal/intern/sprintf.h enc_dummy.o: $(hdrdir)/ruby/internal/intern/string.h @@ -1005,6 +1176,7 @@ enc_dummy.o: $(hdrdir)/ruby/internal/special_consts.h enc_dummy.o: $(hdrdir)/ruby/internal/static_assert.h enc_dummy.o: $(hdrdir)/ruby/internal/stdalign.h enc_dummy.o: $(hdrdir)/ruby/internal/stdbool.h +enc_dummy.o: $(hdrdir)/ruby/internal/stdckdint.h enc_dummy.o: $(hdrdir)/ruby/internal/symbol.h enc_dummy.o: $(hdrdir)/ruby/internal/value.h enc_dummy.o: $(hdrdir)/ruby/internal/value_type.h @@ -1156,6 +1328,7 @@ enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/re.h enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/ruby.h enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/select.h enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/set.h enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/signal.h enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/sprintf.h enc_str_buf_cat.o: $(hdrdir)/ruby/internal/intern/string.h @@ -1175,6 +1348,7 @@ enc_str_buf_cat.o: $(hdrdir)/ruby/internal/special_consts.h enc_str_buf_cat.o: $(hdrdir)/ruby/internal/static_assert.h enc_str_buf_cat.o: $(hdrdir)/ruby/internal/stdalign.h enc_str_buf_cat.o: $(hdrdir)/ruby/internal/stdbool.h +enc_str_buf_cat.o: $(hdrdir)/ruby/internal/stdckdint.h enc_str_buf_cat.o: $(hdrdir)/ruby/internal/symbol.h enc_str_buf_cat.o: $(hdrdir)/ruby/internal/value.h enc_str_buf_cat.o: $(hdrdir)/ruby/internal/value_type.h @@ -1196,6 +1370,7 @@ fstring.o: $(hdrdir)/ruby/backward.h fstring.o: $(hdrdir)/ruby/backward/2/assume.h fstring.o: $(hdrdir)/ruby/backward/2/attributes.h fstring.o: $(hdrdir)/ruby/backward/2/bool.h +fstring.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h fstring.o: $(hdrdir)/ruby/backward/2/inttypes.h fstring.o: $(hdrdir)/ruby/backward/2/limits.h fstring.o: $(hdrdir)/ruby/backward/2/long_long.h @@ -1327,6 +1502,7 @@ fstring.o: $(hdrdir)/ruby/internal/intern/re.h fstring.o: $(hdrdir)/ruby/internal/intern/ruby.h fstring.o: $(hdrdir)/ruby/internal/intern/select.h fstring.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +fstring.o: $(hdrdir)/ruby/internal/intern/set.h fstring.o: $(hdrdir)/ruby/internal/intern/signal.h fstring.o: $(hdrdir)/ruby/internal/intern/sprintf.h fstring.o: $(hdrdir)/ruby/internal/intern/string.h @@ -1346,6 +1522,7 @@ fstring.o: $(hdrdir)/ruby/internal/special_consts.h fstring.o: $(hdrdir)/ruby/internal/static_assert.h fstring.o: $(hdrdir)/ruby/internal/stdalign.h fstring.o: $(hdrdir)/ruby/internal/stdbool.h +fstring.o: $(hdrdir)/ruby/internal/stdckdint.h fstring.o: $(hdrdir)/ruby/internal/symbol.h fstring.o: $(hdrdir)/ruby/internal/value.h fstring.o: $(hdrdir)/ruby/internal/value_type.h @@ -1358,6 +1535,8 @@ fstring.o: $(hdrdir)/ruby/oniguruma.h fstring.o: $(hdrdir)/ruby/ruby.h fstring.o: $(hdrdir)/ruby/st.h fstring.o: $(hdrdir)/ruby/subst.h +fstring.o: $(top_srcdir)/internal/compilers.h +fstring.o: $(top_srcdir)/internal/string.h fstring.o: fstring.c init.o: $(RUBY_EXTCONF_H) init.o: $(arch_hdrdir)/ruby/config.h @@ -1488,6 +1667,7 @@ init.o: $(hdrdir)/ruby/internal/intern/re.h init.o: $(hdrdir)/ruby/internal/intern/ruby.h init.o: $(hdrdir)/ruby/internal/intern/select.h init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +init.o: $(hdrdir)/ruby/internal/intern/set.h init.o: $(hdrdir)/ruby/internal/intern/signal.h init.o: $(hdrdir)/ruby/internal/intern/sprintf.h init.o: $(hdrdir)/ruby/internal/intern/string.h @@ -1507,6 +1687,7 @@ init.o: $(hdrdir)/ruby/internal/special_consts.h init.o: $(hdrdir)/ruby/internal/static_assert.h init.o: $(hdrdir)/ruby/internal/stdalign.h init.o: $(hdrdir)/ruby/internal/stdbool.h +init.o: $(hdrdir)/ruby/internal/stdckdint.h init.o: $(hdrdir)/ruby/internal/symbol.h init.o: $(hdrdir)/ruby/internal/value.h init.o: $(hdrdir)/ruby/internal/value_type.h @@ -1647,6 +1828,7 @@ modify.o: $(hdrdir)/ruby/internal/intern/re.h modify.o: $(hdrdir)/ruby/internal/intern/ruby.h modify.o: $(hdrdir)/ruby/internal/intern/select.h modify.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +modify.o: $(hdrdir)/ruby/internal/intern/set.h modify.o: $(hdrdir)/ruby/internal/intern/signal.h modify.o: $(hdrdir)/ruby/internal/intern/sprintf.h modify.o: $(hdrdir)/ruby/internal/intern/string.h @@ -1666,6 +1848,7 @@ modify.o: $(hdrdir)/ruby/internal/special_consts.h modify.o: $(hdrdir)/ruby/internal/static_assert.h modify.o: $(hdrdir)/ruby/internal/stdalign.h modify.o: $(hdrdir)/ruby/internal/stdbool.h +modify.o: $(hdrdir)/ruby/internal/stdckdint.h modify.o: $(hdrdir)/ruby/internal/symbol.h modify.o: $(hdrdir)/ruby/internal/value.h modify.o: $(hdrdir)/ruby/internal/value_type.h @@ -1816,6 +1999,7 @@ new.o: $(hdrdir)/ruby/internal/intern/re.h new.o: $(hdrdir)/ruby/internal/intern/ruby.h new.o: $(hdrdir)/ruby/internal/intern/select.h new.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +new.o: $(hdrdir)/ruby/internal/intern/set.h new.o: $(hdrdir)/ruby/internal/intern/signal.h new.o: $(hdrdir)/ruby/internal/intern/sprintf.h new.o: $(hdrdir)/ruby/internal/intern/string.h @@ -1835,6 +2019,7 @@ new.o: $(hdrdir)/ruby/internal/special_consts.h new.o: $(hdrdir)/ruby/internal/static_assert.h new.o: $(hdrdir)/ruby/internal/stdalign.h new.o: $(hdrdir)/ruby/internal/stdbool.h +new.o: $(hdrdir)/ruby/internal/stdckdint.h new.o: $(hdrdir)/ruby/internal/symbol.h new.o: $(hdrdir)/ruby/internal/value.h new.o: $(hdrdir)/ruby/internal/value_type.h @@ -1977,6 +2162,7 @@ nofree.o: $(hdrdir)/ruby/internal/intern/re.h nofree.o: $(hdrdir)/ruby/internal/intern/ruby.h nofree.o: $(hdrdir)/ruby/internal/intern/select.h nofree.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +nofree.o: $(hdrdir)/ruby/internal/intern/set.h nofree.o: $(hdrdir)/ruby/internal/intern/signal.h nofree.o: $(hdrdir)/ruby/internal/intern/sprintf.h nofree.o: $(hdrdir)/ruby/internal/intern/string.h @@ -1996,6 +2182,7 @@ nofree.o: $(hdrdir)/ruby/internal/special_consts.h nofree.o: $(hdrdir)/ruby/internal/static_assert.h nofree.o: $(hdrdir)/ruby/internal/stdalign.h nofree.o: $(hdrdir)/ruby/internal/stdbool.h +nofree.o: $(hdrdir)/ruby/internal/stdckdint.h nofree.o: $(hdrdir)/ruby/internal/symbol.h nofree.o: $(hdrdir)/ruby/internal/value.h nofree.o: $(hdrdir)/ruby/internal/value_type.h @@ -2145,6 +2332,7 @@ normalize.o: $(hdrdir)/ruby/internal/intern/re.h normalize.o: $(hdrdir)/ruby/internal/intern/ruby.h normalize.o: $(hdrdir)/ruby/internal/intern/select.h normalize.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +normalize.o: $(hdrdir)/ruby/internal/intern/set.h normalize.o: $(hdrdir)/ruby/internal/intern/signal.h normalize.o: $(hdrdir)/ruby/internal/intern/sprintf.h normalize.o: $(hdrdir)/ruby/internal/intern/string.h @@ -2164,6 +2352,7 @@ normalize.o: $(hdrdir)/ruby/internal/special_consts.h normalize.o: $(hdrdir)/ruby/internal/static_assert.h normalize.o: $(hdrdir)/ruby/internal/stdalign.h normalize.o: $(hdrdir)/ruby/internal/stdbool.h +normalize.o: $(hdrdir)/ruby/internal/stdckdint.h normalize.o: $(hdrdir)/ruby/internal/symbol.h normalize.o: $(hdrdir)/ruby/internal/value.h normalize.o: $(hdrdir)/ruby/internal/value_type.h @@ -2317,6 +2506,7 @@ qsort.o: $(hdrdir)/ruby/internal/intern/re.h qsort.o: $(hdrdir)/ruby/internal/intern/ruby.h qsort.o: $(hdrdir)/ruby/internal/intern/select.h qsort.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +qsort.o: $(hdrdir)/ruby/internal/intern/set.h qsort.o: $(hdrdir)/ruby/internal/intern/signal.h qsort.o: $(hdrdir)/ruby/internal/intern/sprintf.h qsort.o: $(hdrdir)/ruby/internal/intern/string.h @@ -2336,6 +2526,7 @@ qsort.o: $(hdrdir)/ruby/internal/special_consts.h qsort.o: $(hdrdir)/ruby/internal/static_assert.h qsort.o: $(hdrdir)/ruby/internal/stdalign.h qsort.o: $(hdrdir)/ruby/internal/stdbool.h +qsort.o: $(hdrdir)/ruby/internal/stdckdint.h qsort.o: $(hdrdir)/ruby/internal/symbol.h qsort.o: $(hdrdir)/ruby/internal/value.h qsort.o: $(hdrdir)/ruby/internal/value_type.h @@ -2479,6 +2670,7 @@ rb_interned_str.o: $(hdrdir)/ruby/internal/intern/re.h rb_interned_str.o: $(hdrdir)/ruby/internal/intern/ruby.h rb_interned_str.o: $(hdrdir)/ruby/internal/intern/select.h rb_interned_str.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +rb_interned_str.o: $(hdrdir)/ruby/internal/intern/set.h rb_interned_str.o: $(hdrdir)/ruby/internal/intern/signal.h rb_interned_str.o: $(hdrdir)/ruby/internal/intern/sprintf.h rb_interned_str.o: $(hdrdir)/ruby/internal/intern/string.h @@ -2498,6 +2690,7 @@ rb_interned_str.o: $(hdrdir)/ruby/internal/special_consts.h rb_interned_str.o: $(hdrdir)/ruby/internal/static_assert.h rb_interned_str.o: $(hdrdir)/ruby/internal/stdalign.h rb_interned_str.o: $(hdrdir)/ruby/internal/stdbool.h +rb_interned_str.o: $(hdrdir)/ruby/internal/stdckdint.h rb_interned_str.o: $(hdrdir)/ruby/internal/symbol.h rb_interned_str.o: $(hdrdir)/ruby/internal/value.h rb_interned_str.o: $(hdrdir)/ruby/internal/value_type.h @@ -2638,6 +2831,7 @@ rb_str_dup.o: $(hdrdir)/ruby/internal/intern/re.h rb_str_dup.o: $(hdrdir)/ruby/internal/intern/ruby.h rb_str_dup.o: $(hdrdir)/ruby/internal/intern/select.h rb_str_dup.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +rb_str_dup.o: $(hdrdir)/ruby/internal/intern/set.h rb_str_dup.o: $(hdrdir)/ruby/internal/intern/signal.h rb_str_dup.o: $(hdrdir)/ruby/internal/intern/sprintf.h rb_str_dup.o: $(hdrdir)/ruby/internal/intern/string.h @@ -2657,6 +2851,7 @@ rb_str_dup.o: $(hdrdir)/ruby/internal/special_consts.h rb_str_dup.o: $(hdrdir)/ruby/internal/static_assert.h rb_str_dup.o: $(hdrdir)/ruby/internal/stdalign.h rb_str_dup.o: $(hdrdir)/ruby/internal/stdbool.h +rb_str_dup.o: $(hdrdir)/ruby/internal/stdckdint.h rb_str_dup.o: $(hdrdir)/ruby/internal/symbol.h rb_str_dup.o: $(hdrdir)/ruby/internal/value.h rb_str_dup.o: $(hdrdir)/ruby/internal/value_type.h @@ -2797,6 +2992,7 @@ set_len.o: $(hdrdir)/ruby/internal/intern/re.h set_len.o: $(hdrdir)/ruby/internal/intern/ruby.h set_len.o: $(hdrdir)/ruby/internal/intern/select.h set_len.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +set_len.o: $(hdrdir)/ruby/internal/intern/set.h set_len.o: $(hdrdir)/ruby/internal/intern/signal.h set_len.o: $(hdrdir)/ruby/internal/intern/sprintf.h set_len.o: $(hdrdir)/ruby/internal/intern/string.h @@ -2816,6 +3012,7 @@ set_len.o: $(hdrdir)/ruby/internal/special_consts.h set_len.o: $(hdrdir)/ruby/internal/static_assert.h set_len.o: $(hdrdir)/ruby/internal/stdalign.h set_len.o: $(hdrdir)/ruby/internal/stdbool.h +set_len.o: $(hdrdir)/ruby/internal/stdckdint.h set_len.o: $(hdrdir)/ruby/internal/symbol.h set_len.o: $(hdrdir)/ruby/internal/value.h set_len.o: $(hdrdir)/ruby/internal/value_type.h diff --git a/ext/-test-/string/fstring.c b/ext/-test-/string/fstring.c index 2374319fe340b0..71c4b7f97eee44 100644 --- a/ext/-test-/string/fstring.c +++ b/ext/-test-/string/fstring.c @@ -1,30 +1,38 @@ #include "ruby.h" #include "ruby/encoding.h" - -VALUE rb_fstring(VALUE str); +#include "internal/string.h" VALUE bug_s_fstring(VALUE self, VALUE str) { - return rb_fstring(str); + return rb_str_to_interned_str(str); +} + +VALUE +bug_s_fstring_fake_str(VALUE self) +{ + static const char literal[] = "abcdefghijklmnopqrstuvwxyz"; + struct RString fake_str; + return rb_str_to_interned_str(rb_setup_fake_str(&fake_str, literal, sizeof(literal) - 1, 0)); } VALUE bug_s_rb_enc_interned_str(VALUE self, VALUE encoding) { - return rb_enc_interned_str("foo", 3, RDATA(encoding)->data); + return rb_enc_interned_str("foo", 3, NIL_P(encoding) ? NULL : RDATA(encoding)->data); } VALUE bug_s_rb_enc_str_new(VALUE self, VALUE encoding) { - return rb_enc_str_new("foo", 3, RDATA(encoding)->data); + return rb_enc_str_new("foo", 3, NIL_P(encoding) ? NULL : RDATA(encoding)->data); } void Init_string_fstring(VALUE klass) { rb_define_singleton_method(klass, "fstring", bug_s_fstring, 1); + rb_define_singleton_method(klass, "fstring_fake_str", bug_s_fstring_fake_str, 0); rb_define_singleton_method(klass, "rb_enc_interned_str", bug_s_rb_enc_interned_str, 1); rb_define_singleton_method(klass, "rb_enc_str_new", bug_s_rb_enc_str_new, 1); } diff --git a/ext/-test-/string/set_len.c b/ext/-test-/string/set_len.c index 219cea404cffe5..b55ef6f4691b89 100644 --- a/ext/-test-/string/set_len.c +++ b/ext/-test-/string/set_len.c @@ -7,8 +7,26 @@ bug_str_set_len(VALUE str, VALUE len) return str; } +static VALUE +bug_str_append(VALUE str, VALUE addendum) +{ + StringValue(addendum); + rb_str_modify_expand(str, RSTRING_LEN(addendum)); + memcpy(RSTRING_END(str), RSTRING_PTR(addendum), RSTRING_LEN(addendum)); + return str; +} + +static VALUE +bug_str_resize(VALUE str, VALUE len) +{ + rb_str_resize(str, NUM2LONG(len)); + return str; +} + void Init_string_set_len(VALUE klass) { rb_define_method(klass, "set_len", bug_str_set_len, 1); + rb_define_method(klass, "append", bug_str_append, 1); + rb_define_method(klass, "resize", bug_str_resize, 1); } diff --git a/ext/-test-/struct/depend b/ext/-test-/struct/depend index 5db943e28637f1..e2638e4cdf5115 100644 --- a/ext/-test-/struct/depend +++ b/ext/-test-/struct/depend @@ -128,6 +128,7 @@ data.o: $(hdrdir)/ruby/internal/intern/re.h data.o: $(hdrdir)/ruby/internal/intern/ruby.h data.o: $(hdrdir)/ruby/internal/intern/select.h data.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +data.o: $(hdrdir)/ruby/internal/intern/set.h data.o: $(hdrdir)/ruby/internal/intern/signal.h data.o: $(hdrdir)/ruby/internal/intern/sprintf.h data.o: $(hdrdir)/ruby/internal/intern/string.h @@ -147,6 +148,7 @@ data.o: $(hdrdir)/ruby/internal/special_consts.h data.o: $(hdrdir)/ruby/internal/static_assert.h data.o: $(hdrdir)/ruby/internal/stdalign.h data.o: $(hdrdir)/ruby/internal/stdbool.h +data.o: $(hdrdir)/ruby/internal/stdckdint.h data.o: $(hdrdir)/ruby/internal/symbol.h data.o: $(hdrdir)/ruby/internal/value.h data.o: $(hdrdir)/ruby/internal/value_type.h @@ -287,6 +289,7 @@ duplicate.o: $(hdrdir)/ruby/internal/intern/re.h duplicate.o: $(hdrdir)/ruby/internal/intern/ruby.h duplicate.o: $(hdrdir)/ruby/internal/intern/select.h duplicate.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +duplicate.o: $(hdrdir)/ruby/internal/intern/set.h duplicate.o: $(hdrdir)/ruby/internal/intern/signal.h duplicate.o: $(hdrdir)/ruby/internal/intern/sprintf.h duplicate.o: $(hdrdir)/ruby/internal/intern/string.h @@ -306,6 +309,7 @@ duplicate.o: $(hdrdir)/ruby/internal/special_consts.h duplicate.o: $(hdrdir)/ruby/internal/static_assert.h duplicate.o: $(hdrdir)/ruby/internal/stdalign.h duplicate.o: $(hdrdir)/ruby/internal/stdbool.h +duplicate.o: $(hdrdir)/ruby/internal/stdckdint.h duplicate.o: $(hdrdir)/ruby/internal/symbol.h duplicate.o: $(hdrdir)/ruby/internal/value.h duplicate.o: $(hdrdir)/ruby/internal/value_type.h @@ -446,6 +450,7 @@ init.o: $(hdrdir)/ruby/internal/intern/re.h init.o: $(hdrdir)/ruby/internal/intern/ruby.h init.o: $(hdrdir)/ruby/internal/intern/select.h init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +init.o: $(hdrdir)/ruby/internal/intern/set.h init.o: $(hdrdir)/ruby/internal/intern/signal.h init.o: $(hdrdir)/ruby/internal/intern/sprintf.h init.o: $(hdrdir)/ruby/internal/intern/string.h @@ -465,6 +470,7 @@ init.o: $(hdrdir)/ruby/internal/special_consts.h init.o: $(hdrdir)/ruby/internal/static_assert.h init.o: $(hdrdir)/ruby/internal/stdalign.h init.o: $(hdrdir)/ruby/internal/stdbool.h +init.o: $(hdrdir)/ruby/internal/stdckdint.h init.o: $(hdrdir)/ruby/internal/symbol.h init.o: $(hdrdir)/ruby/internal/value.h init.o: $(hdrdir)/ruby/internal/value_type.h @@ -605,6 +611,7 @@ len.o: $(hdrdir)/ruby/internal/intern/re.h len.o: $(hdrdir)/ruby/internal/intern/ruby.h len.o: $(hdrdir)/ruby/internal/intern/select.h len.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +len.o: $(hdrdir)/ruby/internal/intern/set.h len.o: $(hdrdir)/ruby/internal/intern/signal.h len.o: $(hdrdir)/ruby/internal/intern/sprintf.h len.o: $(hdrdir)/ruby/internal/intern/string.h @@ -624,6 +631,7 @@ len.o: $(hdrdir)/ruby/internal/special_consts.h len.o: $(hdrdir)/ruby/internal/static_assert.h len.o: $(hdrdir)/ruby/internal/stdalign.h len.o: $(hdrdir)/ruby/internal/stdbool.h +len.o: $(hdrdir)/ruby/internal/stdckdint.h len.o: $(hdrdir)/ruby/internal/symbol.h len.o: $(hdrdir)/ruby/internal/value.h len.o: $(hdrdir)/ruby/internal/value_type.h @@ -764,6 +772,7 @@ member.o: $(hdrdir)/ruby/internal/intern/re.h member.o: $(hdrdir)/ruby/internal/intern/ruby.h member.o: $(hdrdir)/ruby/internal/intern/select.h member.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +member.o: $(hdrdir)/ruby/internal/intern/set.h member.o: $(hdrdir)/ruby/internal/intern/signal.h member.o: $(hdrdir)/ruby/internal/intern/sprintf.h member.o: $(hdrdir)/ruby/internal/intern/string.h @@ -783,6 +792,7 @@ member.o: $(hdrdir)/ruby/internal/special_consts.h member.o: $(hdrdir)/ruby/internal/static_assert.h member.o: $(hdrdir)/ruby/internal/stdalign.h member.o: $(hdrdir)/ruby/internal/stdbool.h +member.o: $(hdrdir)/ruby/internal/stdckdint.h member.o: $(hdrdir)/ruby/internal/symbol.h member.o: $(hdrdir)/ruby/internal/value.h member.o: $(hdrdir)/ruby/internal/value_type.h diff --git a/ext/-test-/struct/member.c b/ext/-test-/struct/member.c index f5400fe477ba63..29ddff93e8e24a 100644 --- a/ext/-test-/struct/member.c +++ b/ext/-test-/struct/member.c @@ -6,7 +6,7 @@ bug_struct_get(VALUE obj, VALUE name) ID id = rb_check_id(&name); if (!id) { - rb_name_error_str(name, "`%"PRIsVALUE"' is not a struct member", name); + rb_name_error_str(name, "'%"PRIsVALUE"' is not a struct member", name); } return rb_struct_getmember(obj, id); } diff --git a/ext/-test-/symbol/depend b/ext/-test-/symbol/depend index dd1b5c305f85f5..b1d8e1aab6fd3c 100644 --- a/ext/-test-/symbol/depend +++ b/ext/-test-/symbol/depend @@ -128,6 +128,7 @@ init.o: $(hdrdir)/ruby/internal/intern/re.h init.o: $(hdrdir)/ruby/internal/intern/ruby.h init.o: $(hdrdir)/ruby/internal/intern/select.h init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +init.o: $(hdrdir)/ruby/internal/intern/set.h init.o: $(hdrdir)/ruby/internal/intern/signal.h init.o: $(hdrdir)/ruby/internal/intern/sprintf.h init.o: $(hdrdir)/ruby/internal/intern/string.h @@ -147,6 +148,7 @@ init.o: $(hdrdir)/ruby/internal/special_consts.h init.o: $(hdrdir)/ruby/internal/static_assert.h init.o: $(hdrdir)/ruby/internal/stdalign.h init.o: $(hdrdir)/ruby/internal/stdbool.h +init.o: $(hdrdir)/ruby/internal/stdckdint.h init.o: $(hdrdir)/ruby/internal/symbol.h init.o: $(hdrdir)/ruby/internal/value.h init.o: $(hdrdir)/ruby/internal/value_type.h @@ -287,6 +289,7 @@ type.o: $(hdrdir)/ruby/internal/intern/re.h type.o: $(hdrdir)/ruby/internal/intern/ruby.h type.o: $(hdrdir)/ruby/internal/intern/select.h type.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +type.o: $(hdrdir)/ruby/internal/intern/set.h type.o: $(hdrdir)/ruby/internal/intern/signal.h type.o: $(hdrdir)/ruby/internal/intern/sprintf.h type.o: $(hdrdir)/ruby/internal/intern/string.h @@ -306,6 +309,7 @@ type.o: $(hdrdir)/ruby/internal/special_consts.h type.o: $(hdrdir)/ruby/internal/static_assert.h type.o: $(hdrdir)/ruby/internal/stdalign.h type.o: $(hdrdir)/ruby/internal/stdbool.h +type.o: $(hdrdir)/ruby/internal/stdckdint.h type.o: $(hdrdir)/ruby/internal/symbol.h type.o: $(hdrdir)/ruby/internal/value.h type.o: $(hdrdir)/ruby/internal/value_type.h diff --git a/ext/-test-/thread/id/depend b/ext/-test-/thread/id/depend new file mode 100644 index 00000000000000..6b76b31ddcc3b7 --- /dev/null +++ b/ext/-test-/thread/id/depend @@ -0,0 +1,163 @@ +# AUTOGENERATED DEPENDENCIES START +id.o: $(RUBY_EXTCONF_H) +id.o: $(arch_hdrdir)/ruby/config.h +id.o: $(hdrdir)/ruby.h +id.o: $(hdrdir)/ruby/assert.h +id.o: $(hdrdir)/ruby/backward.h +id.o: $(hdrdir)/ruby/backward/2/assume.h +id.o: $(hdrdir)/ruby/backward/2/attributes.h +id.o: $(hdrdir)/ruby/backward/2/bool.h +id.o: $(hdrdir)/ruby/backward/2/inttypes.h +id.o: $(hdrdir)/ruby/backward/2/limits.h +id.o: $(hdrdir)/ruby/backward/2/long_long.h +id.o: $(hdrdir)/ruby/backward/2/stdalign.h +id.o: $(hdrdir)/ruby/backward/2/stdarg.h +id.o: $(hdrdir)/ruby/defines.h +id.o: $(hdrdir)/ruby/intern.h +id.o: $(hdrdir)/ruby/internal/abi.h +id.o: $(hdrdir)/ruby/internal/anyargs.h +id.o: $(hdrdir)/ruby/internal/arithmetic.h +id.o: $(hdrdir)/ruby/internal/arithmetic/char.h +id.o: $(hdrdir)/ruby/internal/arithmetic/double.h +id.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +id.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +id.o: $(hdrdir)/ruby/internal/arithmetic/int.h +id.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +id.o: $(hdrdir)/ruby/internal/arithmetic/long.h +id.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +id.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +id.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +id.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +id.o: $(hdrdir)/ruby/internal/arithmetic/short.h +id.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +id.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +id.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +id.o: $(hdrdir)/ruby/internal/assume.h +id.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +id.o: $(hdrdir)/ruby/internal/attr/artificial.h +id.o: $(hdrdir)/ruby/internal/attr/cold.h +id.o: $(hdrdir)/ruby/internal/attr/const.h +id.o: $(hdrdir)/ruby/internal/attr/constexpr.h +id.o: $(hdrdir)/ruby/internal/attr/deprecated.h +id.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +id.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +id.o: $(hdrdir)/ruby/internal/attr/error.h +id.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +id.o: $(hdrdir)/ruby/internal/attr/forceinline.h +id.o: $(hdrdir)/ruby/internal/attr/format.h +id.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +id.o: $(hdrdir)/ruby/internal/attr/noalias.h +id.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +id.o: $(hdrdir)/ruby/internal/attr/noexcept.h +id.o: $(hdrdir)/ruby/internal/attr/noinline.h +id.o: $(hdrdir)/ruby/internal/attr/nonnull.h +id.o: $(hdrdir)/ruby/internal/attr/noreturn.h +id.o: $(hdrdir)/ruby/internal/attr/packed_struct.h +id.o: $(hdrdir)/ruby/internal/attr/pure.h +id.o: $(hdrdir)/ruby/internal/attr/restrict.h +id.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +id.o: $(hdrdir)/ruby/internal/attr/warning.h +id.o: $(hdrdir)/ruby/internal/attr/weakref.h +id.o: $(hdrdir)/ruby/internal/cast.h +id.o: $(hdrdir)/ruby/internal/compiler_is.h +id.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +id.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +id.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +id.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +id.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +id.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +id.o: $(hdrdir)/ruby/internal/compiler_since.h +id.o: $(hdrdir)/ruby/internal/config.h +id.o: $(hdrdir)/ruby/internal/constant_p.h +id.o: $(hdrdir)/ruby/internal/core.h +id.o: $(hdrdir)/ruby/internal/core/rarray.h +id.o: $(hdrdir)/ruby/internal/core/rbasic.h +id.o: $(hdrdir)/ruby/internal/core/rbignum.h +id.o: $(hdrdir)/ruby/internal/core/rclass.h +id.o: $(hdrdir)/ruby/internal/core/rdata.h +id.o: $(hdrdir)/ruby/internal/core/rfile.h +id.o: $(hdrdir)/ruby/internal/core/rhash.h +id.o: $(hdrdir)/ruby/internal/core/robject.h +id.o: $(hdrdir)/ruby/internal/core/rregexp.h +id.o: $(hdrdir)/ruby/internal/core/rstring.h +id.o: $(hdrdir)/ruby/internal/core/rstruct.h +id.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +id.o: $(hdrdir)/ruby/internal/ctype.h +id.o: $(hdrdir)/ruby/internal/dllexport.h +id.o: $(hdrdir)/ruby/internal/dosish.h +id.o: $(hdrdir)/ruby/internal/error.h +id.o: $(hdrdir)/ruby/internal/eval.h +id.o: $(hdrdir)/ruby/internal/event.h +id.o: $(hdrdir)/ruby/internal/fl_type.h +id.o: $(hdrdir)/ruby/internal/gc.h +id.o: $(hdrdir)/ruby/internal/glob.h +id.o: $(hdrdir)/ruby/internal/globals.h +id.o: $(hdrdir)/ruby/internal/has/attribute.h +id.o: $(hdrdir)/ruby/internal/has/builtin.h +id.o: $(hdrdir)/ruby/internal/has/c_attribute.h +id.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +id.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +id.o: $(hdrdir)/ruby/internal/has/extension.h +id.o: $(hdrdir)/ruby/internal/has/feature.h +id.o: $(hdrdir)/ruby/internal/has/warning.h +id.o: $(hdrdir)/ruby/internal/intern/array.h +id.o: $(hdrdir)/ruby/internal/intern/bignum.h +id.o: $(hdrdir)/ruby/internal/intern/class.h +id.o: $(hdrdir)/ruby/internal/intern/compar.h +id.o: $(hdrdir)/ruby/internal/intern/complex.h +id.o: $(hdrdir)/ruby/internal/intern/cont.h +id.o: $(hdrdir)/ruby/internal/intern/dir.h +id.o: $(hdrdir)/ruby/internal/intern/enum.h +id.o: $(hdrdir)/ruby/internal/intern/enumerator.h +id.o: $(hdrdir)/ruby/internal/intern/error.h +id.o: $(hdrdir)/ruby/internal/intern/eval.h +id.o: $(hdrdir)/ruby/internal/intern/file.h +id.o: $(hdrdir)/ruby/internal/intern/hash.h +id.o: $(hdrdir)/ruby/internal/intern/io.h +id.o: $(hdrdir)/ruby/internal/intern/load.h +id.o: $(hdrdir)/ruby/internal/intern/marshal.h +id.o: $(hdrdir)/ruby/internal/intern/numeric.h +id.o: $(hdrdir)/ruby/internal/intern/object.h +id.o: $(hdrdir)/ruby/internal/intern/parse.h +id.o: $(hdrdir)/ruby/internal/intern/proc.h +id.o: $(hdrdir)/ruby/internal/intern/process.h +id.o: $(hdrdir)/ruby/internal/intern/random.h +id.o: $(hdrdir)/ruby/internal/intern/range.h +id.o: $(hdrdir)/ruby/internal/intern/rational.h +id.o: $(hdrdir)/ruby/internal/intern/re.h +id.o: $(hdrdir)/ruby/internal/intern/ruby.h +id.o: $(hdrdir)/ruby/internal/intern/select.h +id.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +id.o: $(hdrdir)/ruby/internal/intern/set.h +id.o: $(hdrdir)/ruby/internal/intern/signal.h +id.o: $(hdrdir)/ruby/internal/intern/sprintf.h +id.o: $(hdrdir)/ruby/internal/intern/string.h +id.o: $(hdrdir)/ruby/internal/intern/struct.h +id.o: $(hdrdir)/ruby/internal/intern/thread.h +id.o: $(hdrdir)/ruby/internal/intern/time.h +id.o: $(hdrdir)/ruby/internal/intern/variable.h +id.o: $(hdrdir)/ruby/internal/intern/vm.h +id.o: $(hdrdir)/ruby/internal/interpreter.h +id.o: $(hdrdir)/ruby/internal/iterator.h +id.o: $(hdrdir)/ruby/internal/memory.h +id.o: $(hdrdir)/ruby/internal/method.h +id.o: $(hdrdir)/ruby/internal/module.h +id.o: $(hdrdir)/ruby/internal/newobj.h +id.o: $(hdrdir)/ruby/internal/scan_args.h +id.o: $(hdrdir)/ruby/internal/special_consts.h +id.o: $(hdrdir)/ruby/internal/static_assert.h +id.o: $(hdrdir)/ruby/internal/stdalign.h +id.o: $(hdrdir)/ruby/internal/stdbool.h +id.o: $(hdrdir)/ruby/internal/stdckdint.h +id.o: $(hdrdir)/ruby/internal/symbol.h +id.o: $(hdrdir)/ruby/internal/value.h +id.o: $(hdrdir)/ruby/internal/value_type.h +id.o: $(hdrdir)/ruby/internal/variable.h +id.o: $(hdrdir)/ruby/internal/warning_push.h +id.o: $(hdrdir)/ruby/internal/xmalloc.h +id.o: $(hdrdir)/ruby/missing.h +id.o: $(hdrdir)/ruby/ruby.h +id.o: $(hdrdir)/ruby/st.h +id.o: $(hdrdir)/ruby/subst.h +id.o: id.c +# AUTOGENERATED DEPENDENCIES END diff --git a/ext/-test-/thread/id/extconf.rb b/ext/-test-/thread/id/extconf.rb new file mode 100644 index 00000000000000..a0ae0eff15fb2e --- /dev/null +++ b/ext/-test-/thread/id/extconf.rb @@ -0,0 +1,3 @@ +if have_func("gettid") + create_makefile("-test-/thread/id") +end diff --git a/ext/-test-/thread/id/id.c b/ext/-test-/thread/id/id.c new file mode 100644 index 00000000000000..b46a5955e21086 --- /dev/null +++ b/ext/-test-/thread/id/id.c @@ -0,0 +1,15 @@ +#include + +static VALUE +bug_gettid(VALUE self) +{ + pid_t tid = gettid(); + return PIDT2NUM(tid); +} + +void +Init_id(void) +{ + VALUE klass = rb_define_module_under(rb_define_module("Bug"), "ThreadID"); + rb_define_module_function(klass, "gettid", bug_gettid, 0); +} diff --git a/ext/-test-/thread/instrumentation/depend b/ext/-test-/thread/instrumentation/depend index b03f51870f2853..63e1c7e44fb63f 100644 --- a/ext/-test-/thread/instrumentation/depend +++ b/ext/-test-/thread/instrumentation/depend @@ -128,6 +128,7 @@ instrumentation.o: $(hdrdir)/ruby/internal/intern/re.h instrumentation.o: $(hdrdir)/ruby/internal/intern/ruby.h instrumentation.o: $(hdrdir)/ruby/internal/intern/select.h instrumentation.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +instrumentation.o: $(hdrdir)/ruby/internal/intern/set.h instrumentation.o: $(hdrdir)/ruby/internal/intern/signal.h instrumentation.o: $(hdrdir)/ruby/internal/intern/sprintf.h instrumentation.o: $(hdrdir)/ruby/internal/intern/string.h @@ -147,6 +148,7 @@ instrumentation.o: $(hdrdir)/ruby/internal/special_consts.h instrumentation.o: $(hdrdir)/ruby/internal/static_assert.h instrumentation.o: $(hdrdir)/ruby/internal/stdalign.h instrumentation.o: $(hdrdir)/ruby/internal/stdbool.h +instrumentation.o: $(hdrdir)/ruby/internal/stdckdint.h instrumentation.o: $(hdrdir)/ruby/internal/symbol.h instrumentation.o: $(hdrdir)/ruby/internal/value.h instrumentation.o: $(hdrdir)/ruby/internal/value_type.h diff --git a/ext/-test-/thread/instrumentation/instrumentation.c b/ext/-test-/thread/instrumentation/instrumentation.c index edb8738a292687..25e2902a78601b 100644 --- a/ext/-test-/thread/instrumentation/instrumentation.c +++ b/ext/-test-/thread/instrumentation/instrumentation.c @@ -2,85 +2,136 @@ #include "ruby/atomic.h" #include "ruby/thread.h" -static rb_atomic_t started_count = 0; -static rb_atomic_t ready_count = 0; -static rb_atomic_t resumed_count = 0; -static rb_atomic_t suspended_count = 0; -static rb_atomic_t exited_count = 0; - #ifndef RB_THREAD_LOCAL_SPECIFIER # define RB_THREAD_LOCAL_SPECIFIER #endif -static RB_THREAD_LOCAL_SPECIFIER unsigned int local_ready_count = 0; -static RB_THREAD_LOCAL_SPECIFIER unsigned int local_resumed_count = 0; -static RB_THREAD_LOCAL_SPECIFIER unsigned int local_suspended_count = 0; +static VALUE timeline_value = Qnil; + +struct thread_event { + VALUE thread; + rb_event_flag_t event; +}; + +#define MAX_EVENTS 1024 +static struct thread_event event_timeline[MAX_EVENTS]; +static rb_atomic_t timeline_cursor; static void -ex_callback(rb_event_flag_t event, const rb_internal_thread_event_data_t *event_data, void *user_data) +event_timeline_gc_mark(void *ptr) { + rb_atomic_t cursor; + for (cursor = 0; cursor < timeline_cursor; cursor++) { + rb_gc_mark(event_timeline[cursor].thread); + } +} + +static const rb_data_type_t event_timeline_type = { + "TestThreadInstrumentation/event_timeline", + {event_timeline_gc_mark, NULL, NULL,}, + 0, 0, + RUBY_TYPED_FREE_IMMEDIATELY, +}; + +static void +reset_timeline(void) +{ + timeline_cursor = 0; + memset(event_timeline, 0, sizeof(struct thread_event) * MAX_EVENTS); +} + +static rb_event_flag_t +find_last_event(VALUE thread) +{ + rb_atomic_t cursor = timeline_cursor; + if (cursor) { + do { + if (event_timeline[cursor].thread == thread){ + return event_timeline[cursor].event; + } + cursor--; + } while (cursor > 0); + } + return 0; +} + +static const char * +event_name(rb_event_flag_t event) { switch (event) { case RUBY_INTERNAL_THREAD_EVENT_STARTED: - RUBY_ATOMIC_INC(started_count); - break; + return "started"; case RUBY_INTERNAL_THREAD_EVENT_READY: - RUBY_ATOMIC_INC(ready_count); - local_ready_count++; - break; + return "ready"; case RUBY_INTERNAL_THREAD_EVENT_RESUMED: - RUBY_ATOMIC_INC(resumed_count); - local_resumed_count++; - break; + return "resumed"; case RUBY_INTERNAL_THREAD_EVENT_SUSPENDED: - RUBY_ATOMIC_INC(suspended_count); - local_suspended_count++; - break; + return "suspended"; case RUBY_INTERNAL_THREAD_EVENT_EXITED: - RUBY_ATOMIC_INC(exited_count); - break; + return "exited"; } + return "no-event"; } -static rb_internal_thread_event_hook_t * single_hook = NULL; - -static VALUE -thread_counters(VALUE thread) +static void +unexpected(bool strict, const char *format, VALUE thread, rb_event_flag_t last_event) { - VALUE array = rb_ary_new2(5); - rb_ary_push(array, UINT2NUM(started_count)); - rb_ary_push(array, UINT2NUM(ready_count)); - rb_ary_push(array, UINT2NUM(resumed_count)); - rb_ary_push(array, UINT2NUM(suspended_count)); - rb_ary_push(array, UINT2NUM(exited_count)); - return array; + const char *last_event_name = event_name(last_event); + if (strict) { + rb_bug(format, thread, last_event_name); + } + else { + fprintf(stderr, format, thread, last_event_name); + fprintf(stderr, "\n"); + } } -static VALUE -thread_local_counters(VALUE thread) +static void +ex_callback(rb_event_flag_t event, const rb_internal_thread_event_data_t *event_data, void *user_data) { - VALUE array = rb_ary_new2(3); - rb_ary_push(array, UINT2NUM(local_ready_count)); - rb_ary_push(array, UINT2NUM(local_resumed_count)); - rb_ary_push(array, UINT2NUM(local_suspended_count)); - return array; -} + rb_event_flag_t last_event = find_last_event(event_data->thread); + bool strict = (bool)user_data; -static VALUE -thread_reset_counters(VALUE thread) -{ - RUBY_ATOMIC_SET(started_count, 0); - RUBY_ATOMIC_SET(ready_count, 0); - RUBY_ATOMIC_SET(resumed_count, 0); - RUBY_ATOMIC_SET(suspended_count, 0); - RUBY_ATOMIC_SET(exited_count, 0); - local_ready_count = 0; - local_resumed_count = 0; - local_suspended_count = 0; - return Qtrue; + if (last_event != 0) { + switch (event) { + case RUBY_INTERNAL_THREAD_EVENT_STARTED: + unexpected(strict, "[thread=%"PRIxVALUE"] `started` event can't be preceded by `%s`", event_data->thread, last_event); + break; + case RUBY_INTERNAL_THREAD_EVENT_READY: + if (last_event != RUBY_INTERNAL_THREAD_EVENT_STARTED && last_event != RUBY_INTERNAL_THREAD_EVENT_SUSPENDED) { + unexpected(strict, "[thread=%"PRIxVALUE"] `ready` must be preceded by `started` or `suspended`, got: `%s`", event_data->thread, last_event); + } + break; + case RUBY_INTERNAL_THREAD_EVENT_RESUMED: + if (last_event != RUBY_INTERNAL_THREAD_EVENT_READY) { + unexpected(strict, "[thread=%"PRIxVALUE"] `resumed` must be preceded by `ready`, got: `%s`", event_data->thread, last_event); + } + break; + case RUBY_INTERNAL_THREAD_EVENT_SUSPENDED: + if (last_event != RUBY_INTERNAL_THREAD_EVENT_RESUMED) { + unexpected(strict, "[thread=%"PRIxVALUE"] `suspended` must be preceded by `resumed`, got: `%s`", event_data->thread, last_event); + } + break; + case RUBY_INTERNAL_THREAD_EVENT_EXITED: + if (last_event != RUBY_INTERNAL_THREAD_EVENT_RESUMED && last_event != RUBY_INTERNAL_THREAD_EVENT_SUSPENDED) { + unexpected(strict, "[thread=%"PRIxVALUE"] `exited` must be preceded by `resumed` or `suspended`, got: `%s`", event_data->thread, last_event); + } + break; + } + } + + rb_atomic_t cursor = RUBY_ATOMIC_FETCH_ADD(timeline_cursor, 1); + if (cursor >= MAX_EVENTS) { + rb_bug("TestThreadInstrumentation: ran out of event_timeline space"); + } + + event_timeline[cursor].thread = event_data->thread; + event_timeline[cursor].event = event; } +static rb_internal_thread_event_hook_t * single_hook = NULL; + static VALUE -thread_register_callback(VALUE thread) +thread_register_callback(VALUE thread, VALUE strict) { single_hook = rb_internal_thread_add_event_hook( ex_callback, @@ -89,12 +140,32 @@ thread_register_callback(VALUE thread) RUBY_INTERNAL_THREAD_EVENT_RESUMED | RUBY_INTERNAL_THREAD_EVENT_SUSPENDED | RUBY_INTERNAL_THREAD_EVENT_EXITED, - NULL + (void *)RTEST(strict) ); return Qnil; } +static VALUE +event_symbol(rb_event_flag_t event) +{ + switch (event) { + case RUBY_INTERNAL_THREAD_EVENT_STARTED: + return rb_id2sym(rb_intern("started")); + case RUBY_INTERNAL_THREAD_EVENT_READY: + return rb_id2sym(rb_intern("ready")); + case RUBY_INTERNAL_THREAD_EVENT_RESUMED: + return rb_id2sym(rb_intern("resumed")); + case RUBY_INTERNAL_THREAD_EVENT_SUSPENDED: + return rb_id2sym(rb_intern("suspended")); + case RUBY_INTERNAL_THREAD_EVENT_EXITED: + return rb_id2sym(rb_intern("exited")); + default: + rb_bug("TestThreadInstrumentation: Unexpected event"); + break; + } +} + static VALUE thread_unregister_callback(VALUE thread) { @@ -103,7 +174,18 @@ thread_unregister_callback(VALUE thread) single_hook = NULL; } - return Qnil; + VALUE events = rb_ary_new_capa(timeline_cursor); + rb_atomic_t cursor; + for (cursor = 0; cursor < timeline_cursor; cursor++) { + VALUE pair = rb_ary_new_capa(2); + rb_ary_push(pair, event_timeline[cursor].thread); + rb_ary_push(pair, event_symbol(event_timeline[cursor].event)); + rb_ary_push(events, pair); + } + + reset_timeline(); + + return events; } static VALUE @@ -127,10 +209,10 @@ Init_instrumentation(void) { VALUE mBug = rb_define_module("Bug"); VALUE klass = rb_define_module_under(mBug, "ThreadInstrumentation"); - rb_define_singleton_method(klass, "counters", thread_counters, 0); - rb_define_singleton_method(klass, "local_counters", thread_local_counters, 0); - rb_define_singleton_method(klass, "reset_counters", thread_reset_counters, 0); - rb_define_singleton_method(klass, "register_callback", thread_register_callback, 0); + rb_global_variable(&timeline_value); + timeline_value = TypedData_Wrap_Struct(0, &event_timeline_type, (void *)1); + + rb_define_singleton_method(klass, "register_callback", thread_register_callback, 1); rb_define_singleton_method(klass, "unregister_callback", thread_unregister_callback, 0); rb_define_singleton_method(klass, "register_and_unregister_callbacks", thread_register_and_unregister_callback, 0); } diff --git a/ext/-test-/thread/lock_native_thread/depend b/ext/-test-/thread/lock_native_thread/depend new file mode 100644 index 00000000000000..a32843e531494a --- /dev/null +++ b/ext/-test-/thread/lock_native_thread/depend @@ -0,0 +1,163 @@ +# AUTOGENERATED DEPENDENCIES START +lock_native_thread.o: $(RUBY_EXTCONF_H) +lock_native_thread.o: $(arch_hdrdir)/ruby/config.h +lock_native_thread.o: $(hdrdir)/ruby/assert.h +lock_native_thread.o: $(hdrdir)/ruby/backward.h +lock_native_thread.o: $(hdrdir)/ruby/backward/2/assume.h +lock_native_thread.o: $(hdrdir)/ruby/backward/2/attributes.h +lock_native_thread.o: $(hdrdir)/ruby/backward/2/bool.h +lock_native_thread.o: $(hdrdir)/ruby/backward/2/inttypes.h +lock_native_thread.o: $(hdrdir)/ruby/backward/2/limits.h +lock_native_thread.o: $(hdrdir)/ruby/backward/2/long_long.h +lock_native_thread.o: $(hdrdir)/ruby/backward/2/stdalign.h +lock_native_thread.o: $(hdrdir)/ruby/backward/2/stdarg.h +lock_native_thread.o: $(hdrdir)/ruby/defines.h +lock_native_thread.o: $(hdrdir)/ruby/intern.h +lock_native_thread.o: $(hdrdir)/ruby/internal/abi.h +lock_native_thread.o: $(hdrdir)/ruby/internal/anyargs.h +lock_native_thread.o: $(hdrdir)/ruby/internal/arithmetic.h +lock_native_thread.o: $(hdrdir)/ruby/internal/arithmetic/char.h +lock_native_thread.o: $(hdrdir)/ruby/internal/arithmetic/double.h +lock_native_thread.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h +lock_native_thread.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h +lock_native_thread.o: $(hdrdir)/ruby/internal/arithmetic/int.h +lock_native_thread.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h +lock_native_thread.o: $(hdrdir)/ruby/internal/arithmetic/long.h +lock_native_thread.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h +lock_native_thread.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h +lock_native_thread.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h +lock_native_thread.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h +lock_native_thread.o: $(hdrdir)/ruby/internal/arithmetic/short.h +lock_native_thread.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h +lock_native_thread.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h +lock_native_thread.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h +lock_native_thread.o: $(hdrdir)/ruby/internal/assume.h +lock_native_thread.o: $(hdrdir)/ruby/internal/attr/alloc_size.h +lock_native_thread.o: $(hdrdir)/ruby/internal/attr/artificial.h +lock_native_thread.o: $(hdrdir)/ruby/internal/attr/cold.h +lock_native_thread.o: $(hdrdir)/ruby/internal/attr/const.h +lock_native_thread.o: $(hdrdir)/ruby/internal/attr/constexpr.h +lock_native_thread.o: $(hdrdir)/ruby/internal/attr/deprecated.h +lock_native_thread.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h +lock_native_thread.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h +lock_native_thread.o: $(hdrdir)/ruby/internal/attr/error.h +lock_native_thread.o: $(hdrdir)/ruby/internal/attr/flag_enum.h +lock_native_thread.o: $(hdrdir)/ruby/internal/attr/forceinline.h +lock_native_thread.o: $(hdrdir)/ruby/internal/attr/format.h +lock_native_thread.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h +lock_native_thread.o: $(hdrdir)/ruby/internal/attr/noalias.h +lock_native_thread.o: $(hdrdir)/ruby/internal/attr/nodiscard.h +lock_native_thread.o: $(hdrdir)/ruby/internal/attr/noexcept.h +lock_native_thread.o: $(hdrdir)/ruby/internal/attr/noinline.h +lock_native_thread.o: $(hdrdir)/ruby/internal/attr/nonnull.h +lock_native_thread.o: $(hdrdir)/ruby/internal/attr/noreturn.h +lock_native_thread.o: $(hdrdir)/ruby/internal/attr/packed_struct.h +lock_native_thread.o: $(hdrdir)/ruby/internal/attr/pure.h +lock_native_thread.o: $(hdrdir)/ruby/internal/attr/restrict.h +lock_native_thread.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h +lock_native_thread.o: $(hdrdir)/ruby/internal/attr/warning.h +lock_native_thread.o: $(hdrdir)/ruby/internal/attr/weakref.h +lock_native_thread.o: $(hdrdir)/ruby/internal/cast.h +lock_native_thread.o: $(hdrdir)/ruby/internal/compiler_is.h +lock_native_thread.o: $(hdrdir)/ruby/internal/compiler_is/apple.h +lock_native_thread.o: $(hdrdir)/ruby/internal/compiler_is/clang.h +lock_native_thread.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h +lock_native_thread.o: $(hdrdir)/ruby/internal/compiler_is/intel.h +lock_native_thread.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h +lock_native_thread.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h +lock_native_thread.o: $(hdrdir)/ruby/internal/compiler_since.h +lock_native_thread.o: $(hdrdir)/ruby/internal/config.h +lock_native_thread.o: $(hdrdir)/ruby/internal/constant_p.h +lock_native_thread.o: $(hdrdir)/ruby/internal/core.h +lock_native_thread.o: $(hdrdir)/ruby/internal/core/rarray.h +lock_native_thread.o: $(hdrdir)/ruby/internal/core/rbasic.h +lock_native_thread.o: $(hdrdir)/ruby/internal/core/rbignum.h +lock_native_thread.o: $(hdrdir)/ruby/internal/core/rclass.h +lock_native_thread.o: $(hdrdir)/ruby/internal/core/rdata.h +lock_native_thread.o: $(hdrdir)/ruby/internal/core/rfile.h +lock_native_thread.o: $(hdrdir)/ruby/internal/core/rhash.h +lock_native_thread.o: $(hdrdir)/ruby/internal/core/robject.h +lock_native_thread.o: $(hdrdir)/ruby/internal/core/rregexp.h +lock_native_thread.o: $(hdrdir)/ruby/internal/core/rstring.h +lock_native_thread.o: $(hdrdir)/ruby/internal/core/rstruct.h +lock_native_thread.o: $(hdrdir)/ruby/internal/core/rtypeddata.h +lock_native_thread.o: $(hdrdir)/ruby/internal/ctype.h +lock_native_thread.o: $(hdrdir)/ruby/internal/dllexport.h +lock_native_thread.o: $(hdrdir)/ruby/internal/dosish.h +lock_native_thread.o: $(hdrdir)/ruby/internal/error.h +lock_native_thread.o: $(hdrdir)/ruby/internal/eval.h +lock_native_thread.o: $(hdrdir)/ruby/internal/event.h +lock_native_thread.o: $(hdrdir)/ruby/internal/fl_type.h +lock_native_thread.o: $(hdrdir)/ruby/internal/gc.h +lock_native_thread.o: $(hdrdir)/ruby/internal/glob.h +lock_native_thread.o: $(hdrdir)/ruby/internal/globals.h +lock_native_thread.o: $(hdrdir)/ruby/internal/has/attribute.h +lock_native_thread.o: $(hdrdir)/ruby/internal/has/builtin.h +lock_native_thread.o: $(hdrdir)/ruby/internal/has/c_attribute.h +lock_native_thread.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h +lock_native_thread.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h +lock_native_thread.o: $(hdrdir)/ruby/internal/has/extension.h +lock_native_thread.o: $(hdrdir)/ruby/internal/has/feature.h +lock_native_thread.o: $(hdrdir)/ruby/internal/has/warning.h +lock_native_thread.o: $(hdrdir)/ruby/internal/intern/array.h +lock_native_thread.o: $(hdrdir)/ruby/internal/intern/bignum.h +lock_native_thread.o: $(hdrdir)/ruby/internal/intern/class.h +lock_native_thread.o: $(hdrdir)/ruby/internal/intern/compar.h +lock_native_thread.o: $(hdrdir)/ruby/internal/intern/complex.h +lock_native_thread.o: $(hdrdir)/ruby/internal/intern/cont.h +lock_native_thread.o: $(hdrdir)/ruby/internal/intern/dir.h +lock_native_thread.o: $(hdrdir)/ruby/internal/intern/enum.h +lock_native_thread.o: $(hdrdir)/ruby/internal/intern/enumerator.h +lock_native_thread.o: $(hdrdir)/ruby/internal/intern/error.h +lock_native_thread.o: $(hdrdir)/ruby/internal/intern/eval.h +lock_native_thread.o: $(hdrdir)/ruby/internal/intern/file.h +lock_native_thread.o: $(hdrdir)/ruby/internal/intern/hash.h +lock_native_thread.o: $(hdrdir)/ruby/internal/intern/io.h +lock_native_thread.o: $(hdrdir)/ruby/internal/intern/load.h +lock_native_thread.o: $(hdrdir)/ruby/internal/intern/marshal.h +lock_native_thread.o: $(hdrdir)/ruby/internal/intern/numeric.h +lock_native_thread.o: $(hdrdir)/ruby/internal/intern/object.h +lock_native_thread.o: $(hdrdir)/ruby/internal/intern/parse.h +lock_native_thread.o: $(hdrdir)/ruby/internal/intern/proc.h +lock_native_thread.o: $(hdrdir)/ruby/internal/intern/process.h +lock_native_thread.o: $(hdrdir)/ruby/internal/intern/random.h +lock_native_thread.o: $(hdrdir)/ruby/internal/intern/range.h +lock_native_thread.o: $(hdrdir)/ruby/internal/intern/rational.h +lock_native_thread.o: $(hdrdir)/ruby/internal/intern/re.h +lock_native_thread.o: $(hdrdir)/ruby/internal/intern/ruby.h +lock_native_thread.o: $(hdrdir)/ruby/internal/intern/select.h +lock_native_thread.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +lock_native_thread.o: $(hdrdir)/ruby/internal/intern/set.h +lock_native_thread.o: $(hdrdir)/ruby/internal/intern/signal.h +lock_native_thread.o: $(hdrdir)/ruby/internal/intern/sprintf.h +lock_native_thread.o: $(hdrdir)/ruby/internal/intern/string.h +lock_native_thread.o: $(hdrdir)/ruby/internal/intern/struct.h +lock_native_thread.o: $(hdrdir)/ruby/internal/intern/thread.h +lock_native_thread.o: $(hdrdir)/ruby/internal/intern/time.h +lock_native_thread.o: $(hdrdir)/ruby/internal/intern/variable.h +lock_native_thread.o: $(hdrdir)/ruby/internal/intern/vm.h +lock_native_thread.o: $(hdrdir)/ruby/internal/interpreter.h +lock_native_thread.o: $(hdrdir)/ruby/internal/iterator.h +lock_native_thread.o: $(hdrdir)/ruby/internal/memory.h +lock_native_thread.o: $(hdrdir)/ruby/internal/method.h +lock_native_thread.o: $(hdrdir)/ruby/internal/module.h +lock_native_thread.o: $(hdrdir)/ruby/internal/newobj.h +lock_native_thread.o: $(hdrdir)/ruby/internal/scan_args.h +lock_native_thread.o: $(hdrdir)/ruby/internal/special_consts.h +lock_native_thread.o: $(hdrdir)/ruby/internal/static_assert.h +lock_native_thread.o: $(hdrdir)/ruby/internal/stdalign.h +lock_native_thread.o: $(hdrdir)/ruby/internal/stdbool.h +lock_native_thread.o: $(hdrdir)/ruby/internal/stdckdint.h +lock_native_thread.o: $(hdrdir)/ruby/internal/symbol.h +lock_native_thread.o: $(hdrdir)/ruby/internal/value.h +lock_native_thread.o: $(hdrdir)/ruby/internal/value_type.h +lock_native_thread.o: $(hdrdir)/ruby/internal/variable.h +lock_native_thread.o: $(hdrdir)/ruby/internal/warning_push.h +lock_native_thread.o: $(hdrdir)/ruby/internal/xmalloc.h +lock_native_thread.o: $(hdrdir)/ruby/missing.h +lock_native_thread.o: $(hdrdir)/ruby/ruby.h +lock_native_thread.o: $(hdrdir)/ruby/st.h +lock_native_thread.o: $(hdrdir)/ruby/subst.h +lock_native_thread.o: $(hdrdir)/ruby/thread.h +lock_native_thread.o: lock_native_thread.c +# AUTOGENERATED DEPENDENCIES END diff --git a/ext/-test-/thread/lock_native_thread/extconf.rb b/ext/-test-/thread/lock_native_thread/extconf.rb new file mode 100644 index 00000000000000..832bfde01afeb6 --- /dev/null +++ b/ext/-test-/thread/lock_native_thread/extconf.rb @@ -0,0 +1,2 @@ +# frozen_string_literal: false +create_makefile("-test-/thread/lock_native_thread") diff --git a/ext/-test-/thread/lock_native_thread/lock_native_thread.c b/ext/-test-/thread/lock_native_thread/lock_native_thread.c new file mode 100644 index 00000000000000..2eb75809a9a57e --- /dev/null +++ b/ext/-test-/thread/lock_native_thread/lock_native_thread.c @@ -0,0 +1,50 @@ + +#include "ruby/ruby.h" +#include "ruby/thread.h" + +#ifdef HAVE_PTHREAD_H +#include + +static pthread_key_t tls_key; + +static VALUE +get_tls(VALUE self) +{ + return (VALUE)pthread_getspecific(tls_key); +} + +static VALUE +set_tls(VALUE self, VALUE vn) +{ + pthread_setspecific(tls_key, (void *)vn); + return Qnil; +} + +static VALUE +lock_native_thread(VALUE self) +{ + return rb_thread_lock_native_thread() ? Qtrue : Qfalse; +} + +void +Init_lock_native_thread(void) +{ + int r; + + if ((r = pthread_key_create(&tls_key, NULL)) != 0) { + rb_bug("pthread_key_create() returns %d", r); + } + pthread_setspecific(tls_key, NULL); + + rb_define_method(rb_cThread, "lock_native_thread", lock_native_thread, 0); + rb_define_method(rb_cThread, "get_tls", get_tls, 0); + rb_define_method(rb_cThread, "set_tls", set_tls, 1); +} + +#else // HAVE_PTHREAD_H +void +Init_lock_native_thread(void) +{ + // do nothing +} +#endif // HAVE_PTHREAD_H diff --git a/ext/-test-/thread_fd/depend b/ext/-test-/thread_fd/depend deleted file mode 100644 index d4cc772526fdb8..00000000000000 --- a/ext/-test-/thread_fd/depend +++ /dev/null @@ -1,160 +0,0 @@ -# AUTOGENERATED DEPENDENCIES START -thread_fd.o: $(RUBY_EXTCONF_H) -thread_fd.o: $(arch_hdrdir)/ruby/config.h -thread_fd.o: $(hdrdir)/ruby/assert.h -thread_fd.o: $(hdrdir)/ruby/backward.h -thread_fd.o: $(hdrdir)/ruby/backward/2/assume.h -thread_fd.o: $(hdrdir)/ruby/backward/2/attributes.h -thread_fd.o: $(hdrdir)/ruby/backward/2/bool.h -thread_fd.o: $(hdrdir)/ruby/backward/2/inttypes.h -thread_fd.o: $(hdrdir)/ruby/backward/2/limits.h -thread_fd.o: $(hdrdir)/ruby/backward/2/long_long.h -thread_fd.o: $(hdrdir)/ruby/backward/2/stdalign.h -thread_fd.o: $(hdrdir)/ruby/backward/2/stdarg.h -thread_fd.o: $(hdrdir)/ruby/defines.h -thread_fd.o: $(hdrdir)/ruby/intern.h -thread_fd.o: $(hdrdir)/ruby/internal/abi.h -thread_fd.o: $(hdrdir)/ruby/internal/anyargs.h -thread_fd.o: $(hdrdir)/ruby/internal/arithmetic.h -thread_fd.o: $(hdrdir)/ruby/internal/arithmetic/char.h -thread_fd.o: $(hdrdir)/ruby/internal/arithmetic/double.h -thread_fd.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h -thread_fd.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h -thread_fd.o: $(hdrdir)/ruby/internal/arithmetic/int.h -thread_fd.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h -thread_fd.o: $(hdrdir)/ruby/internal/arithmetic/long.h -thread_fd.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h -thread_fd.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h -thread_fd.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h -thread_fd.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h -thread_fd.o: $(hdrdir)/ruby/internal/arithmetic/short.h -thread_fd.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h -thread_fd.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h -thread_fd.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h -thread_fd.o: $(hdrdir)/ruby/internal/assume.h -thread_fd.o: $(hdrdir)/ruby/internal/attr/alloc_size.h -thread_fd.o: $(hdrdir)/ruby/internal/attr/artificial.h -thread_fd.o: $(hdrdir)/ruby/internal/attr/cold.h -thread_fd.o: $(hdrdir)/ruby/internal/attr/const.h -thread_fd.o: $(hdrdir)/ruby/internal/attr/constexpr.h -thread_fd.o: $(hdrdir)/ruby/internal/attr/deprecated.h -thread_fd.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h -thread_fd.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h -thread_fd.o: $(hdrdir)/ruby/internal/attr/error.h -thread_fd.o: $(hdrdir)/ruby/internal/attr/flag_enum.h -thread_fd.o: $(hdrdir)/ruby/internal/attr/forceinline.h -thread_fd.o: $(hdrdir)/ruby/internal/attr/format.h -thread_fd.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h -thread_fd.o: $(hdrdir)/ruby/internal/attr/noalias.h -thread_fd.o: $(hdrdir)/ruby/internal/attr/nodiscard.h -thread_fd.o: $(hdrdir)/ruby/internal/attr/noexcept.h -thread_fd.o: $(hdrdir)/ruby/internal/attr/noinline.h -thread_fd.o: $(hdrdir)/ruby/internal/attr/nonnull.h -thread_fd.o: $(hdrdir)/ruby/internal/attr/noreturn.h -thread_fd.o: $(hdrdir)/ruby/internal/attr/packed_struct.h -thread_fd.o: $(hdrdir)/ruby/internal/attr/pure.h -thread_fd.o: $(hdrdir)/ruby/internal/attr/restrict.h -thread_fd.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h -thread_fd.o: $(hdrdir)/ruby/internal/attr/warning.h -thread_fd.o: $(hdrdir)/ruby/internal/attr/weakref.h -thread_fd.o: $(hdrdir)/ruby/internal/cast.h -thread_fd.o: $(hdrdir)/ruby/internal/compiler_is.h -thread_fd.o: $(hdrdir)/ruby/internal/compiler_is/apple.h -thread_fd.o: $(hdrdir)/ruby/internal/compiler_is/clang.h -thread_fd.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h -thread_fd.o: $(hdrdir)/ruby/internal/compiler_is/intel.h -thread_fd.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h -thread_fd.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h -thread_fd.o: $(hdrdir)/ruby/internal/compiler_since.h -thread_fd.o: $(hdrdir)/ruby/internal/config.h -thread_fd.o: $(hdrdir)/ruby/internal/constant_p.h -thread_fd.o: $(hdrdir)/ruby/internal/core.h -thread_fd.o: $(hdrdir)/ruby/internal/core/rarray.h -thread_fd.o: $(hdrdir)/ruby/internal/core/rbasic.h -thread_fd.o: $(hdrdir)/ruby/internal/core/rbignum.h -thread_fd.o: $(hdrdir)/ruby/internal/core/rclass.h -thread_fd.o: $(hdrdir)/ruby/internal/core/rdata.h -thread_fd.o: $(hdrdir)/ruby/internal/core/rfile.h -thread_fd.o: $(hdrdir)/ruby/internal/core/rhash.h -thread_fd.o: $(hdrdir)/ruby/internal/core/robject.h -thread_fd.o: $(hdrdir)/ruby/internal/core/rregexp.h -thread_fd.o: $(hdrdir)/ruby/internal/core/rstring.h -thread_fd.o: $(hdrdir)/ruby/internal/core/rstruct.h -thread_fd.o: $(hdrdir)/ruby/internal/core/rtypeddata.h -thread_fd.o: $(hdrdir)/ruby/internal/ctype.h -thread_fd.o: $(hdrdir)/ruby/internal/dllexport.h -thread_fd.o: $(hdrdir)/ruby/internal/dosish.h -thread_fd.o: $(hdrdir)/ruby/internal/error.h -thread_fd.o: $(hdrdir)/ruby/internal/eval.h -thread_fd.o: $(hdrdir)/ruby/internal/event.h -thread_fd.o: $(hdrdir)/ruby/internal/fl_type.h -thread_fd.o: $(hdrdir)/ruby/internal/gc.h -thread_fd.o: $(hdrdir)/ruby/internal/glob.h -thread_fd.o: $(hdrdir)/ruby/internal/globals.h -thread_fd.o: $(hdrdir)/ruby/internal/has/attribute.h -thread_fd.o: $(hdrdir)/ruby/internal/has/builtin.h -thread_fd.o: $(hdrdir)/ruby/internal/has/c_attribute.h -thread_fd.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h -thread_fd.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h -thread_fd.o: $(hdrdir)/ruby/internal/has/extension.h -thread_fd.o: $(hdrdir)/ruby/internal/has/feature.h -thread_fd.o: $(hdrdir)/ruby/internal/has/warning.h -thread_fd.o: $(hdrdir)/ruby/internal/intern/array.h -thread_fd.o: $(hdrdir)/ruby/internal/intern/bignum.h -thread_fd.o: $(hdrdir)/ruby/internal/intern/class.h -thread_fd.o: $(hdrdir)/ruby/internal/intern/compar.h -thread_fd.o: $(hdrdir)/ruby/internal/intern/complex.h -thread_fd.o: $(hdrdir)/ruby/internal/intern/cont.h -thread_fd.o: $(hdrdir)/ruby/internal/intern/dir.h -thread_fd.o: $(hdrdir)/ruby/internal/intern/enum.h -thread_fd.o: $(hdrdir)/ruby/internal/intern/enumerator.h -thread_fd.o: $(hdrdir)/ruby/internal/intern/error.h -thread_fd.o: $(hdrdir)/ruby/internal/intern/eval.h -thread_fd.o: $(hdrdir)/ruby/internal/intern/file.h -thread_fd.o: $(hdrdir)/ruby/internal/intern/hash.h -thread_fd.o: $(hdrdir)/ruby/internal/intern/io.h -thread_fd.o: $(hdrdir)/ruby/internal/intern/load.h -thread_fd.o: $(hdrdir)/ruby/internal/intern/marshal.h -thread_fd.o: $(hdrdir)/ruby/internal/intern/numeric.h -thread_fd.o: $(hdrdir)/ruby/internal/intern/object.h -thread_fd.o: $(hdrdir)/ruby/internal/intern/parse.h -thread_fd.o: $(hdrdir)/ruby/internal/intern/proc.h -thread_fd.o: $(hdrdir)/ruby/internal/intern/process.h -thread_fd.o: $(hdrdir)/ruby/internal/intern/random.h -thread_fd.o: $(hdrdir)/ruby/internal/intern/range.h -thread_fd.o: $(hdrdir)/ruby/internal/intern/rational.h -thread_fd.o: $(hdrdir)/ruby/internal/intern/re.h -thread_fd.o: $(hdrdir)/ruby/internal/intern/ruby.h -thread_fd.o: $(hdrdir)/ruby/internal/intern/select.h -thread_fd.o: $(hdrdir)/ruby/internal/intern/select/largesize.h -thread_fd.o: $(hdrdir)/ruby/internal/intern/signal.h -thread_fd.o: $(hdrdir)/ruby/internal/intern/sprintf.h -thread_fd.o: $(hdrdir)/ruby/internal/intern/string.h -thread_fd.o: $(hdrdir)/ruby/internal/intern/struct.h -thread_fd.o: $(hdrdir)/ruby/internal/intern/thread.h -thread_fd.o: $(hdrdir)/ruby/internal/intern/time.h -thread_fd.o: $(hdrdir)/ruby/internal/intern/variable.h -thread_fd.o: $(hdrdir)/ruby/internal/intern/vm.h -thread_fd.o: $(hdrdir)/ruby/internal/interpreter.h -thread_fd.o: $(hdrdir)/ruby/internal/iterator.h -thread_fd.o: $(hdrdir)/ruby/internal/memory.h -thread_fd.o: $(hdrdir)/ruby/internal/method.h -thread_fd.o: $(hdrdir)/ruby/internal/module.h -thread_fd.o: $(hdrdir)/ruby/internal/newobj.h -thread_fd.o: $(hdrdir)/ruby/internal/scan_args.h -thread_fd.o: $(hdrdir)/ruby/internal/special_consts.h -thread_fd.o: $(hdrdir)/ruby/internal/static_assert.h -thread_fd.o: $(hdrdir)/ruby/internal/stdalign.h -thread_fd.o: $(hdrdir)/ruby/internal/stdbool.h -thread_fd.o: $(hdrdir)/ruby/internal/symbol.h -thread_fd.o: $(hdrdir)/ruby/internal/value.h -thread_fd.o: $(hdrdir)/ruby/internal/value_type.h -thread_fd.o: $(hdrdir)/ruby/internal/variable.h -thread_fd.o: $(hdrdir)/ruby/internal/warning_push.h -thread_fd.o: $(hdrdir)/ruby/internal/xmalloc.h -thread_fd.o: $(hdrdir)/ruby/missing.h -thread_fd.o: $(hdrdir)/ruby/ruby.h -thread_fd.o: $(hdrdir)/ruby/st.h -thread_fd.o: $(hdrdir)/ruby/subst.h -thread_fd.o: thread_fd.c -# AUTOGENERATED DEPENDENCIES END diff --git a/ext/-test-/thread_fd/extconf.rb b/ext/-test-/thread_fd/extconf.rb deleted file mode 100644 index a8bbe9d1697d3f..00000000000000 --- a/ext/-test-/thread_fd/extconf.rb +++ /dev/null @@ -1,2 +0,0 @@ -# frozen_string_literal: true -create_makefile('-test-/thread_fd') diff --git a/ext/-test-/thread_fd/thread_fd.c b/ext/-test-/thread_fd/thread_fd.c deleted file mode 100644 index 042b799dc8dc24..00000000000000 --- a/ext/-test-/thread_fd/thread_fd.c +++ /dev/null @@ -1,30 +0,0 @@ -#include "ruby/ruby.h" - -static VALUE -thread_fd_close(VALUE ign, VALUE fd) -{ - rb_thread_fd_close(NUM2INT(fd)); - return Qnil; -} - -static VALUE -thread_fd_wait(VALUE ign, VALUE fd) -{ - int ret = rb_thread_wait_fd(NUM2INT(fd)); - return INT2NUM(ret); -} - -static VALUE -thread_fd_writable(VALUE ign, VALUE fd) -{ - int ret = rb_thread_fd_writable(NUM2INT(fd)); - return INT2NUM(ret); -} - -void -Init_thread_fd(void) -{ - rb_define_singleton_method(rb_cIO, "thread_fd_close", thread_fd_close, 1); - rb_define_singleton_method(rb_cIO, "thread_fd_wait", thread_fd_wait, 1); - rb_define_singleton_method(rb_cIO, "thread_fd_writable", thread_fd_writable, 1); -} diff --git a/ext/-test-/time/depend b/ext/-test-/time/depend index c015588b091525..e5b05f311358e8 100644 --- a/ext/-test-/time/depend +++ b/ext/-test-/time/depend @@ -128,6 +128,7 @@ init.o: $(hdrdir)/ruby/internal/intern/re.h init.o: $(hdrdir)/ruby/internal/intern/ruby.h init.o: $(hdrdir)/ruby/internal/intern/select.h init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +init.o: $(hdrdir)/ruby/internal/intern/set.h init.o: $(hdrdir)/ruby/internal/intern/signal.h init.o: $(hdrdir)/ruby/internal/intern/sprintf.h init.o: $(hdrdir)/ruby/internal/intern/string.h @@ -147,6 +148,7 @@ init.o: $(hdrdir)/ruby/internal/special_consts.h init.o: $(hdrdir)/ruby/internal/static_assert.h init.o: $(hdrdir)/ruby/internal/stdalign.h init.o: $(hdrdir)/ruby/internal/stdbool.h +init.o: $(hdrdir)/ruby/internal/stdckdint.h init.o: $(hdrdir)/ruby/internal/symbol.h init.o: $(hdrdir)/ruby/internal/value.h init.o: $(hdrdir)/ruby/internal/value_type.h @@ -288,6 +290,7 @@ leap_second.o: $(hdrdir)/ruby/internal/intern/re.h leap_second.o: $(hdrdir)/ruby/internal/intern/ruby.h leap_second.o: $(hdrdir)/ruby/internal/intern/select.h leap_second.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +leap_second.o: $(hdrdir)/ruby/internal/intern/set.h leap_second.o: $(hdrdir)/ruby/internal/intern/signal.h leap_second.o: $(hdrdir)/ruby/internal/intern/sprintf.h leap_second.o: $(hdrdir)/ruby/internal/intern/string.h @@ -307,6 +310,7 @@ leap_second.o: $(hdrdir)/ruby/internal/special_consts.h leap_second.o: $(hdrdir)/ruby/internal/static_assert.h leap_second.o: $(hdrdir)/ruby/internal/stdalign.h leap_second.o: $(hdrdir)/ruby/internal/stdbool.h +leap_second.o: $(hdrdir)/ruby/internal/stdckdint.h leap_second.o: $(hdrdir)/ruby/internal/symbol.h leap_second.o: $(hdrdir)/ruby/internal/value.h leap_second.o: $(hdrdir)/ruby/internal/value_type.h @@ -451,6 +455,7 @@ new.o: $(hdrdir)/ruby/internal/intern/re.h new.o: $(hdrdir)/ruby/internal/intern/ruby.h new.o: $(hdrdir)/ruby/internal/intern/select.h new.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +new.o: $(hdrdir)/ruby/internal/intern/set.h new.o: $(hdrdir)/ruby/internal/intern/signal.h new.o: $(hdrdir)/ruby/internal/intern/sprintf.h new.o: $(hdrdir)/ruby/internal/intern/string.h @@ -470,6 +475,7 @@ new.o: $(hdrdir)/ruby/internal/special_consts.h new.o: $(hdrdir)/ruby/internal/static_assert.h new.o: $(hdrdir)/ruby/internal/stdalign.h new.o: $(hdrdir)/ruby/internal/stdbool.h +new.o: $(hdrdir)/ruby/internal/stdckdint.h new.o: $(hdrdir)/ruby/internal/symbol.h new.o: $(hdrdir)/ruby/internal/value.h new.o: $(hdrdir)/ruby/internal/value_type.h diff --git a/ext/-test-/tracepoint/depend b/ext/-test-/tracepoint/depend index 396004926e6427..014ba83b16af6a 100644 --- a/ext/-test-/tracepoint/depend +++ b/ext/-test-/tracepoint/depend @@ -128,6 +128,7 @@ gc_hook.o: $(hdrdir)/ruby/internal/intern/re.h gc_hook.o: $(hdrdir)/ruby/internal/intern/ruby.h gc_hook.o: $(hdrdir)/ruby/internal/intern/select.h gc_hook.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +gc_hook.o: $(hdrdir)/ruby/internal/intern/set.h gc_hook.o: $(hdrdir)/ruby/internal/intern/signal.h gc_hook.o: $(hdrdir)/ruby/internal/intern/sprintf.h gc_hook.o: $(hdrdir)/ruby/internal/intern/string.h @@ -147,6 +148,7 @@ gc_hook.o: $(hdrdir)/ruby/internal/special_consts.h gc_hook.o: $(hdrdir)/ruby/internal/static_assert.h gc_hook.o: $(hdrdir)/ruby/internal/stdalign.h gc_hook.o: $(hdrdir)/ruby/internal/stdbool.h +gc_hook.o: $(hdrdir)/ruby/internal/stdckdint.h gc_hook.o: $(hdrdir)/ruby/internal/symbol.h gc_hook.o: $(hdrdir)/ruby/internal/value.h gc_hook.o: $(hdrdir)/ruby/internal/value_type.h @@ -287,6 +289,7 @@ tracepoint.o: $(hdrdir)/ruby/internal/intern/re.h tracepoint.o: $(hdrdir)/ruby/internal/intern/ruby.h tracepoint.o: $(hdrdir)/ruby/internal/intern/select.h tracepoint.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +tracepoint.o: $(hdrdir)/ruby/internal/intern/set.h tracepoint.o: $(hdrdir)/ruby/internal/intern/signal.h tracepoint.o: $(hdrdir)/ruby/internal/intern/sprintf.h tracepoint.o: $(hdrdir)/ruby/internal/intern/string.h @@ -306,6 +309,7 @@ tracepoint.o: $(hdrdir)/ruby/internal/special_consts.h tracepoint.o: $(hdrdir)/ruby/internal/static_assert.h tracepoint.o: $(hdrdir)/ruby/internal/stdalign.h tracepoint.o: $(hdrdir)/ruby/internal/stdbool.h +tracepoint.o: $(hdrdir)/ruby/internal/stdckdint.h tracepoint.o: $(hdrdir)/ruby/internal/symbol.h tracepoint.o: $(hdrdir)/ruby/internal/value.h tracepoint.o: $(hdrdir)/ruby/internal/value_type.h diff --git a/ext/-test-/tracepoint/gc_hook.c b/ext/-test-/tracepoint/gc_hook.c index a3f4e7f68af06f..54c06c54a5b9b7 100644 --- a/ext/-test-/tracepoint/gc_hook.c +++ b/ext/-test-/tracepoint/gc_hook.c @@ -33,7 +33,9 @@ gc_start_end_i(VALUE tpval, void *data) } if (invoking == 0) { - rb_postponed_job_register(0, invoke_proc, data); + /* will overwrite the existing handle with new data on the second and subsequent call */ + rb_postponed_job_handle_t h = rb_postponed_job_preregister(0, invoke_proc, data); + rb_postponed_job_trigger(h); } } diff --git a/ext/-test-/typeddata/depend b/ext/-test-/typeddata/depend index cbeafa800097d8..b9b4915eeed590 100644 --- a/ext/-test-/typeddata/depend +++ b/ext/-test-/typeddata/depend @@ -128,6 +128,7 @@ typeddata.o: $(hdrdir)/ruby/internal/intern/re.h typeddata.o: $(hdrdir)/ruby/internal/intern/ruby.h typeddata.o: $(hdrdir)/ruby/internal/intern/select.h typeddata.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +typeddata.o: $(hdrdir)/ruby/internal/intern/set.h typeddata.o: $(hdrdir)/ruby/internal/intern/signal.h typeddata.o: $(hdrdir)/ruby/internal/intern/sprintf.h typeddata.o: $(hdrdir)/ruby/internal/intern/string.h @@ -147,6 +148,7 @@ typeddata.o: $(hdrdir)/ruby/internal/special_consts.h typeddata.o: $(hdrdir)/ruby/internal/static_assert.h typeddata.o: $(hdrdir)/ruby/internal/stdalign.h typeddata.o: $(hdrdir)/ruby/internal/stdbool.h +typeddata.o: $(hdrdir)/ruby/internal/stdckdint.h typeddata.o: $(hdrdir)/ruby/internal/symbol.h typeddata.o: $(hdrdir)/ruby/internal/value.h typeddata.o: $(hdrdir)/ruby/internal/value_type.h diff --git a/ext/-test-/vm/depend b/ext/-test-/vm/depend index f0b3f3b1f4879a..9313f2ee36fa19 100644 --- a/ext/-test-/vm/depend +++ b/ext/-test-/vm/depend @@ -127,6 +127,7 @@ at_exit.o: $(hdrdir)/ruby/internal/intern/re.h at_exit.o: $(hdrdir)/ruby/internal/intern/ruby.h at_exit.o: $(hdrdir)/ruby/internal/intern/select.h at_exit.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +at_exit.o: $(hdrdir)/ruby/internal/intern/set.h at_exit.o: $(hdrdir)/ruby/internal/intern/signal.h at_exit.o: $(hdrdir)/ruby/internal/intern/sprintf.h at_exit.o: $(hdrdir)/ruby/internal/intern/string.h @@ -146,6 +147,7 @@ at_exit.o: $(hdrdir)/ruby/internal/special_consts.h at_exit.o: $(hdrdir)/ruby/internal/static_assert.h at_exit.o: $(hdrdir)/ruby/internal/stdalign.h at_exit.o: $(hdrdir)/ruby/internal/stdbool.h +at_exit.o: $(hdrdir)/ruby/internal/stdckdint.h at_exit.o: $(hdrdir)/ruby/internal/symbol.h at_exit.o: $(hdrdir)/ruby/internal/value.h at_exit.o: $(hdrdir)/ruby/internal/value_type.h diff --git a/ext/-test-/wait/depend b/ext/-test-/wait/depend index 2e4887559cd4ab..f793d848319cbb 100644 --- a/ext/-test-/wait/depend +++ b/ext/-test-/wait/depend @@ -137,6 +137,7 @@ wait.o: $(hdrdir)/ruby/internal/intern/re.h wait.o: $(hdrdir)/ruby/internal/intern/ruby.h wait.o: $(hdrdir)/ruby/internal/intern/select.h wait.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +wait.o: $(hdrdir)/ruby/internal/intern/set.h wait.o: $(hdrdir)/ruby/internal/intern/signal.h wait.o: $(hdrdir)/ruby/internal/intern/sprintf.h wait.o: $(hdrdir)/ruby/internal/intern/string.h @@ -156,6 +157,7 @@ wait.o: $(hdrdir)/ruby/internal/special_consts.h wait.o: $(hdrdir)/ruby/internal/static_assert.h wait.o: $(hdrdir)/ruby/internal/stdalign.h wait.o: $(hdrdir)/ruby/internal/stdbool.h +wait.o: $(hdrdir)/ruby/internal/stdckdint.h wait.o: $(hdrdir)/ruby/internal/symbol.h wait.o: $(hdrdir)/ruby/internal/value.h wait.o: $(hdrdir)/ruby/internal/value_type.h diff --git a/ext/-test-/win32/dln/extconf.rb b/ext/-test-/win32/dln/extconf.rb index d72b6a868cc513..bea52cfec36564 100644 --- a/ext/-test-/win32/dln/extconf.rb +++ b/ext/-test-/win32/dln/extconf.rb @@ -7,6 +7,7 @@ testdll = "dlntest.dll" $cleanfiles << testdll $cleanfiles << "dlntest.#{$LIBEXT}" + $cleanfiles << "libdlntest.#{$OBJEXT}" config_string('cleanobjs') {|t| $cleanfiles.concat(t.gsub(/\$\*/, 'dlntest').split)} create_makefile("-test-/win32/dln") do |m| diff --git a/ext/.document b/ext/.document index f2fa5b5ba2d6ef..0efd511a61c450 100644 --- a/ext/.document +++ b/ext/.document @@ -29,8 +29,7 @@ fiddle/pinned.c fiddle/pointer.c fiddle/handle.c fiddle/lib -io/console/console.c -io/console/lib +io/console/ io/nonblock/nonblock.c io/wait/wait.c json/generator/generator.c diff --git a/ext/bigdecimal/bigdecimal.c b/ext/bigdecimal/bigdecimal.c deleted file mode 100644 index bcfa400539ccbf..00000000000000 --- a/ext/bigdecimal/bigdecimal.c +++ /dev/null @@ -1,7725 +0,0 @@ -/* - * - * Ruby BigDecimal(Variable decimal precision) extension library. - * - * Copyright(C) 2002 by Shigeo Kobayashi(shigeo@tinyforest.gr.jp) - * - */ - -/* #define BIGDECIMAL_DEBUG 1 */ - -#include "bigdecimal.h" -#include "ruby/util.h" - -#ifndef BIGDECIMAL_DEBUG -# undef NDEBUG -# define NDEBUG -#endif -#include - -#include -#include -#include -#include -#include -#include - -#ifdef HAVE_IEEEFP_H -#include -#endif - -#include "bits.h" -#include "static_assert.h" - -#define BIGDECIMAL_VERSION "3.1.4" - -/* #define ENABLE_NUMERIC_STRING */ - -#define SIGNED_VALUE_MAX INTPTR_MAX -#define SIGNED_VALUE_MIN INTPTR_MIN -#define MUL_OVERFLOW_SIGNED_VALUE_P(a, b) MUL_OVERFLOW_SIGNED_INTEGER_P(a, b, SIGNED_VALUE_MIN, SIGNED_VALUE_MAX) - -VALUE rb_cBigDecimal; -VALUE rb_mBigMath; - -static ID id_BigDecimal_exception_mode; -static ID id_BigDecimal_rounding_mode; -static ID id_BigDecimal_precision_limit; - -static ID id_up; -static ID id_down; -static ID id_truncate; -static ID id_half_up; -static ID id_default; -static ID id_half_down; -static ID id_half_even; -static ID id_banker; -static ID id_ceiling; -static ID id_ceil; -static ID id_floor; -static ID id_to_r; -static ID id_eq; -static ID id_half; - -#define RBD_NUM_ROUNDING_MODES 11 - -static struct { - ID id; - uint8_t mode; -} rbd_rounding_modes[RBD_NUM_ROUNDING_MODES]; - -/* MACRO's to guard objects from GC by keeping them in stack */ -#ifdef RBIMPL_ATTR_MAYBE_UNUSED -#define ENTER(n) RBIMPL_ATTR_MAYBE_UNUSED() volatile VALUE vStack[n];int iStack=0 -#else -#define ENTER(n) volatile VALUE RB_UNUSED_VAR(vStack[n]);int iStack=0 -#endif -#define PUSH(x) (vStack[iStack++] = (VALUE)(x)) -#define SAVE(p) PUSH((p)->obj) -#define GUARD_OBJ(p,y) ((p)=(y), SAVE(p)) - -#define BASE_FIG BIGDECIMAL_COMPONENT_FIGURES -#define BASE BIGDECIMAL_BASE - -#define HALF_BASE (BASE/2) -#define BASE1 (BASE/10) - -#define LOG10_2 0.3010299956639812 - -#ifndef RRATIONAL_ZERO_P -# define RRATIONAL_ZERO_P(x) (FIXNUM_P(rb_rational_num(x)) && \ - FIX2LONG(rb_rational_num(x)) == 0) -#endif - -#ifndef RRATIONAL_NEGATIVE_P -# define RRATIONAL_NEGATIVE_P(x) RTEST(rb_funcall((x), '<', 1, INT2FIX(0))) -#endif - -#ifndef DECIMAL_SIZE_OF_BITS -#define DECIMAL_SIZE_OF_BITS(n) (((n) * 3010 + 9998) / 9999) -/* an approximation of ceil(n * log10(2)), upto 65536 at least */ -#endif - -#ifdef PRIsVALUE -# define RB_OBJ_CLASSNAME(obj) rb_obj_class(obj) -# define RB_OBJ_STRING(obj) (obj) -#else -# define PRIsVALUE "s" -# define RB_OBJ_CLASSNAME(obj) rb_obj_classname(obj) -# define RB_OBJ_STRING(obj) StringValueCStr(obj) -#endif - -#ifndef MAYBE_UNUSED -# define MAYBE_UNUSED(x) x -#endif - -#define BIGDECIMAL_POSITIVE_P(bd) ((bd)->sign > 0) -#define BIGDECIMAL_NEGATIVE_P(bd) ((bd)->sign < 0) - -/* - * ================== Memory allocation ============================ - */ - -#ifdef BIGDECIMAL_DEBUG -static size_t rbd_allocation_count = 0; /* Memory allocation counter */ -static inline void -atomic_allocation_count_inc(void) -{ - RUBY_ATOMIC_SIZE_INC(rbd_allocation_count); -} -static inline void -atomic_allocation_count_dec_nounderflow(void) -{ - if (rbd_allocation_count == 0) return; - RUBY_ATOMIC_SIZE_DEC(rbd_allocation_count); -} -static void -check_allocation_count_nonzero(void) -{ - if (rbd_allocation_count != 0) return; - rb_bug("[bigdecimal][rbd_free_struct] Too many memory free calls"); -} -#else -# define atomic_allocation_count_inc() /* nothing */ -# define atomic_allocation_count_dec_nounderflow() /* nothing */ -# define check_allocation_count_nonzero() /* nothing */ -#endif /* BIGDECIMAL_DEBUG */ - -PUREFUNC(static inline size_t rbd_struct_size(size_t const)); - -static inline size_t -rbd_struct_size(size_t const internal_digits) -{ - size_t const frac_len = (internal_digits == 0) ? 1 : internal_digits; - return offsetof(Real, frac) + frac_len * sizeof(DECDIG); -} - -static inline Real * -rbd_allocate_struct(size_t const internal_digits) -{ - size_t const size = rbd_struct_size(internal_digits); - Real *real = ruby_xcalloc(1, size); - atomic_allocation_count_inc(); - real->MaxPrec = internal_digits; - return real; -} - -static size_t -rbd_calculate_internal_digits(size_t const digits, bool limit_precision) -{ - size_t const len = roomof(digits, BASE_FIG); - if (limit_precision) { - size_t const prec_limit = VpGetPrecLimit(); - if (prec_limit > 0) { - /* NOTE: 2 more digits for rounding and division */ - size_t const max_len = roomof(prec_limit, BASE_FIG) + 2; - if (len > max_len) - return max_len; - } - } - - return len; -} - -static inline Real * -rbd_allocate_struct_decimal_digits(size_t const decimal_digits, bool limit_precision) -{ - size_t const internal_digits = rbd_calculate_internal_digits(decimal_digits, limit_precision); - return rbd_allocate_struct(internal_digits); -} - -static VALUE BigDecimal_wrap_struct(VALUE obj, Real *vp); - -static Real * -rbd_reallocate_struct(Real *real, size_t const internal_digits) -{ - size_t const size = rbd_struct_size(internal_digits); - VALUE obj = real ? real->obj : 0; - Real *new_real = (Real *)ruby_xrealloc(real, size); - new_real->MaxPrec = internal_digits; - if (obj) { - new_real->obj = 0; - BigDecimal_wrap_struct(obj, new_real); - } - return new_real; -} - -static void -rbd_free_struct(Real *real) -{ - if (real != NULL) { - check_allocation_count_nonzero(); - ruby_xfree(real); - atomic_allocation_count_dec_nounderflow(); - } -} - -#define NewZero rbd_allocate_struct_zero -static Real * -rbd_allocate_struct_zero(int sign, size_t const digits, bool limit_precision) -{ - Real *real = rbd_allocate_struct_decimal_digits(digits, limit_precision); - VpSetZero(real, sign); - return real; -} - -MAYBE_UNUSED(static inline Real * rbd_allocate_struct_zero_limited(int sign, size_t const digits)); -#define NewZeroLimited rbd_allocate_struct_zero_limited -static inline Real * -rbd_allocate_struct_zero_limited(int sign, size_t const digits) -{ - return rbd_allocate_struct_zero(sign, digits, true); -} - -MAYBE_UNUSED(static inline Real * rbd_allocate_struct_zero_nolimit(int sign, size_t const digits)); -#define NewZeroNolimit rbd_allocate_struct_zero_nolimit -static inline Real * -rbd_allocate_struct_zero_nolimit(int sign, size_t const digits) -{ - return rbd_allocate_struct_zero(sign, digits, false); -} - -#define NewOne rbd_allocate_struct_one -static Real * -rbd_allocate_struct_one(int sign, size_t const digits, bool limit_precision) -{ - Real *real = rbd_allocate_struct_decimal_digits(digits, limit_precision); - VpSetOne(real); - if (sign < 0) - VpSetSign(real, VP_SIGN_NEGATIVE_FINITE); - return real; -} - -MAYBE_UNUSED(static inline Real * rbd_allocate_struct_one_limited(int sign, size_t const digits)); -#define NewOneLimited rbd_allocate_struct_one_limited -static inline Real * -rbd_allocate_struct_one_limited(int sign, size_t const digits) -{ - return rbd_allocate_struct_one(sign, digits, true); -} - -MAYBE_UNUSED(static inline Real * rbd_allocate_struct_one_nolimit(int sign, size_t const digits)); -#define NewOneNolimit rbd_allocate_struct_one_nolimit -static inline Real * -rbd_allocate_struct_one_nolimit(int sign, size_t const digits) -{ - return rbd_allocate_struct_one(sign, digits, false); -} - -/* - * ================== Ruby Interface part ========================== - */ -#define DoSomeOne(x,y,f) rb_num_coerce_bin(x,y,f) - -/* - * VP routines used in BigDecimal part - */ -static unsigned short VpGetException(void); -static void VpSetException(unsigned short f); -static void VpCheckException(Real *p, bool always); -static VALUE VpCheckGetValue(Real *p); -static void VpInternalRound(Real *c, size_t ixDigit, DECDIG vPrev, DECDIG v); -static int VpLimitRound(Real *c, size_t ixDigit); -static Real *VpCopy(Real *pv, Real const* const x); -static int VPrint(FILE *fp,const char *cntl_chr,Real *a); - -/* - * **** BigDecimal part **** - */ - -static VALUE BigDecimal_nan(void); -static VALUE BigDecimal_positive_infinity(void); -static VALUE BigDecimal_negative_infinity(void); -static VALUE BigDecimal_positive_zero(void); -static VALUE BigDecimal_negative_zero(void); - -static void -BigDecimal_delete(void *pv) -{ - rbd_free_struct(pv); -} - -static size_t -BigDecimal_memsize(const void *ptr) -{ - const Real *pv = ptr; - return (sizeof(*pv) + pv->MaxPrec * sizeof(DECDIG)); -} - -#ifndef HAVE_RB_EXT_RACTOR_SAFE -# undef RUBY_TYPED_FROZEN_SHAREABLE -# define RUBY_TYPED_FROZEN_SHAREABLE 0 -#endif - -static const rb_data_type_t BigDecimal_data_type = { - "BigDecimal", - { 0, BigDecimal_delete, BigDecimal_memsize, }, -#ifdef RUBY_TYPED_FREE_IMMEDIATELY - 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_FROZEN_SHAREABLE | RUBY_TYPED_WB_PROTECTED -#endif -}; - -static Real * -rbd_allocate_struct_zero_wrap_klass(VALUE klass, int sign, size_t const digits, bool limit_precision) -{ - Real *real = rbd_allocate_struct_zero(sign, digits, limit_precision); - if (real != NULL) { - VALUE obj = TypedData_Wrap_Struct(klass, &BigDecimal_data_type, 0); - BigDecimal_wrap_struct(obj, real); - } - return real; -} - -MAYBE_UNUSED(static inline Real * rbd_allocate_struct_zero_limited_wrap(int sign, size_t const digits)); -#define NewZeroWrapLimited rbd_allocate_struct_zero_limited_wrap -static inline Real * -rbd_allocate_struct_zero_limited_wrap(int sign, size_t const digits) -{ - return rbd_allocate_struct_zero_wrap_klass(rb_cBigDecimal, sign, digits, true); -} - -MAYBE_UNUSED(static inline Real * rbd_allocate_struct_zero_nolimit_wrap(int sign, size_t const digits)); -#define NewZeroWrapNolimit rbd_allocate_struct_zero_nolimit_wrap -static inline Real * -rbd_allocate_struct_zero_nolimit_wrap(int sign, size_t const digits) -{ - return rbd_allocate_struct_zero_wrap_klass(rb_cBigDecimal, sign, digits, false); -} - -static Real * -rbd_allocate_struct_one_wrap_klass(VALUE klass, int sign, size_t const digits, bool limit_precision) -{ - Real *real = rbd_allocate_struct_one(sign, digits, limit_precision); - if (real != NULL) { - VALUE obj = TypedData_Wrap_Struct(klass, &BigDecimal_data_type, 0); - BigDecimal_wrap_struct(obj, real); - } - return real; -} - -MAYBE_UNUSED(static inline Real * rbd_allocate_struct_one_limited_wrap(int sign, size_t const digits)); -#define NewOneWrapLimited rbd_allocate_struct_one_limited_wrap -static inline Real * -rbd_allocate_struct_one_limited_wrap(int sign, size_t const digits) -{ - return rbd_allocate_struct_one_wrap_klass(rb_cBigDecimal, sign, digits, true); -} - -MAYBE_UNUSED(static inline Real * rbd_allocate_struct_one_nolimit_wrap(int sign, size_t const digits)); -#define NewOneWrapNolimit rbd_allocate_struct_one_nolimit_wrap -static inline Real * -rbd_allocate_struct_one_nolimit_wrap(int sign, size_t const digits) -{ - return rbd_allocate_struct_one_wrap_klass(rb_cBigDecimal, sign, digits, false); -} - -static inline int -is_kind_of_BigDecimal(VALUE const v) -{ - return rb_typeddata_is_kind_of(v, &BigDecimal_data_type); -} - -NORETURN(static void cannot_be_coerced_into_BigDecimal(VALUE, VALUE)); - -static void -cannot_be_coerced_into_BigDecimal(VALUE exc_class, VALUE v) -{ - VALUE str; - - if (rb_special_const_p(v)) { - str = rb_inspect(v); - } - else { - str = rb_class_name(rb_obj_class(v)); - } - - str = rb_str_cat2(rb_str_dup(str), " can't be coerced into BigDecimal"); - rb_exc_raise(rb_exc_new3(exc_class, str)); -} - -static inline VALUE BigDecimal_div2(VALUE, VALUE, VALUE); -static VALUE rb_inum_convert_to_BigDecimal(VALUE val, size_t digs, int raise_exception); -static VALUE rb_float_convert_to_BigDecimal(VALUE val, size_t digs, int raise_exception); -static VALUE rb_rational_convert_to_BigDecimal(VALUE val, size_t digs, int raise_exception); -static VALUE rb_cstr_convert_to_BigDecimal(const char *c_str, size_t digs, int raise_exception); -static VALUE rb_convert_to_BigDecimal(VALUE val, size_t digs, int raise_exception); - -static Real* -GetVpValueWithPrec(VALUE v, long prec, int must) -{ - const size_t digs = prec < 0 ? SIZE_MAX : (size_t)prec; - - switch(TYPE(v)) { - case T_FLOAT: - v = rb_float_convert_to_BigDecimal(v, digs, must); - break; - - case T_RATIONAL: - v = rb_rational_convert_to_BigDecimal(v, digs, must); - break; - - case T_DATA: - if (!is_kind_of_BigDecimal(v)) { - goto SomeOneMayDoIt; - } - break; - - case T_FIXNUM: { - char szD[128]; - snprintf(szD, 128, "%ld", FIX2LONG(v)); - v = rb_cstr_convert_to_BigDecimal(szD, VpBaseFig() * 2 + 1, must); - break; - } - -#ifdef ENABLE_NUMERIC_STRING - case T_STRING: { - const char *c_str = StringValueCStr(v); - v = rb_cstr_convert_to_BigDecimal(c_str, RSTRING_LEN(v) + VpBaseFig() + 1, must); - break; - } -#endif /* ENABLE_NUMERIC_STRING */ - - case T_BIGNUM: { - VALUE bg = rb_big2str(v, 10); - v = rb_cstr_convert_to_BigDecimal(RSTRING_PTR(bg), RSTRING_LEN(bg) + VpBaseFig() + 1, must); - RB_GC_GUARD(bg); - break; - } - - default: - goto SomeOneMayDoIt; - } - - Real *vp; - TypedData_Get_Struct(v, Real, &BigDecimal_data_type, vp); - return vp; - -SomeOneMayDoIt: - if (must) { - cannot_be_coerced_into_BigDecimal(rb_eTypeError, v); - } - return NULL; /* NULL means to coerce */ -} - -static inline Real* -GetVpValue(VALUE v, int must) -{ - return GetVpValueWithPrec(v, -1, must); -} - -/* call-seq: - * BigDecimal.double_fig -> integer - * - * Returns the number of digits a Float object is allowed to have; - * the result is system-dependent: - * - * BigDecimal.double_fig # => 16 - * - */ -static inline VALUE -BigDecimal_double_fig(VALUE self) -{ - return INT2FIX(VpDblFig()); -} - -/* call-seq: - * precs -> array - * - * Returns an Array of two Integer values that represent platform-dependent - * internal storage properties. - * - * This method is deprecated and will be removed in the future. - * Instead, use BigDecimal#n_significant_digits for obtaining the number of - * significant digits in scientific notation, and BigDecimal#precision for - * obtaining the number of digits in decimal notation. - * - */ - -static VALUE -BigDecimal_prec(VALUE self) -{ - ENTER(1); - Real *p; - VALUE obj; - - rb_category_warn(RB_WARN_CATEGORY_DEPRECATED, - "BigDecimal#precs is deprecated and will be removed in the future; " - "use BigDecimal#precision instead."); - - GUARD_OBJ(p, GetVpValue(self, 1)); - obj = rb_assoc_new(SIZET2NUM(p->Prec*VpBaseFig()), - SIZET2NUM(p->MaxPrec*VpBaseFig())); - return obj; -} - -static void -BigDecimal_count_precision_and_scale(VALUE self, ssize_t *out_precision, ssize_t *out_scale) -{ - ENTER(1); - - if (out_precision == NULL && out_scale == NULL) - return; - - Real *p; - GUARD_OBJ(p, GetVpValue(self, 1)); - if (VpIsZero(p) || !VpIsDef(p)) { - zero: - if (out_precision) *out_precision = 0; - if (out_scale) *out_scale = 0; - return; - } - - DECDIG x; - - ssize_t n = p->Prec; /* The length of frac without zeros. */ - while (n > 0 && p->frac[n-1] == 0) --n; - if (n == 0) goto zero; - - int nlz = BASE_FIG; - for (x = p->frac[0]; x > 0; x /= 10) --nlz; - - int ntz = 0; - for (x = p->frac[n-1]; x > 0 && x % 10 == 0; x /= 10) ++ntz; - - /* - * Calculate the precision and the scale - * ------------------------------------- - * - * The most significant digit is frac[0], and the least significant digit - * is frac[Prec-1]. When the exponent is zero, the decimal point is - * located just before frac[0]. - * - * When the exponent is negative, the decimal point moves to leftward. - * In this case, the precision can be calculated by - * - * precision = BASE_FIG * (-exponent + n) - ntz, - * - * and the scale is the same as precision. - * - * 0 . 0000 0000 | frac[0] ... frac[n-1] | - * |<----------| exponent == -2 | - * |---------------------------------->| precision - * |---------------------------------->| scale - * - * - * Conversely, when the exponent is positive, the decimal point moves to - * rightward. In this case, the scale equals to - * - * BASE_FIG * (n - exponent) - ntz. - * - * the precision equals to - * - * scale + BASE_FIG * exponent - nlz. - * - * | frac[0] frac[1] . frac[2] ... frac[n-1] | - * |---------------->| exponent == 2 | - * | |---------------------->| scale - * |---------------------------------------->| precision - */ - - ssize_t ex = p->exponent; - - /* Count the number of decimal digits before frac[1]. */ - ssize_t n_digits_head = BASE_FIG; - if (ex < 0) { - n_digits_head += (-ex) * BASE_FIG; /* The number of leading zeros before frac[0]. */ - ex = 0; - } - else if (ex > 0) { - /* Count the number of decimal digits without the leading zeros in - * the most significant digit in the integral part. - */ - n_digits_head -= nlz; /* Make the number of digits */ - } - - if (out_precision) { - ssize_t precision = n_digits_head; - - /* Count the number of decimal digits after frac[0]. */ - if (ex > (ssize_t)n) { - /* In this case the number is an integer with some trailing zeros. */ - precision += (ex - 1) * BASE_FIG; - } - else if (n > 0) { - precision += (n - 1) * BASE_FIG; - - if (ex < (ssize_t)n) { - precision -= ntz; - } - } - - *out_precision = precision; - } - - if (out_scale) { - ssize_t scale = 0; - - if (p->exponent < 0) { - scale = n_digits_head + (n - 1) * BASE_FIG - ntz; - } - else if (n > p->exponent) { - scale = (n - p->exponent) * BASE_FIG - ntz; - } - - *out_scale = scale; - } -} - -/* - * call-seq: - * precision -> integer - * - * Returns the number of decimal digits in +self+: - * - * BigDecimal("0").precision # => 0 - * BigDecimal("1").precision # => 1 - * BigDecimal("1.1").precision # => 2 - * BigDecimal("3.1415").precision # => 5 - * BigDecimal("-1e20").precision # => 21 - * BigDecimal("1e-20").precision # => 20 - * BigDecimal("Infinity").precision # => 0 - * BigDecimal("-Infinity").precision # => 0 - * BigDecimal("NaN").precision # => 0 - * - */ -static VALUE -BigDecimal_precision(VALUE self) -{ - ssize_t precision; - BigDecimal_count_precision_and_scale(self, &precision, NULL); - return SSIZET2NUM(precision); -} - -/* - * call-seq: - * scale -> integer - * - * Returns the number of decimal digits following the decimal digits in +self+. - * - * BigDecimal("0").scale # => 0 - * BigDecimal("1").scale # => 1 - * BigDecimal("1.1").scale # => 1 - * BigDecimal("3.1415").scale # => 4 - * BigDecimal("-1e20").precision # => 0 - * BigDecimal("1e-20").precision # => 20 - * BigDecimal("Infinity").scale # => 0 - * BigDecimal("-Infinity").scale # => 0 - * BigDecimal("NaN").scale # => 0 - */ -static VALUE -BigDecimal_scale(VALUE self) -{ - ssize_t scale; - BigDecimal_count_precision_and_scale(self, NULL, &scale); - return SSIZET2NUM(scale); -} - -/* - * call-seq: - * precision_scale -> [integer, integer] - * - * Returns a 2-length array; the first item is the result of - * BigDecimal#precision and the second one is of BigDecimal#scale. - * - * See BigDecimal#precision. - * See BigDecimal#scale. - */ -static VALUE -BigDecimal_precision_scale(VALUE self) -{ - ssize_t precision, scale; - BigDecimal_count_precision_and_scale(self, &precision, &scale); - return rb_assoc_new(SSIZET2NUM(precision), SSIZET2NUM(scale)); -} - -/* - * call-seq: - * n_significant_digits -> integer - * - * Returns the number of decimal significant digits in +self+. - * - * BigDecimal("0").n_significant_digits # => 0 - * BigDecimal("1").n_significant_digits # => 1 - * BigDecimal("1.1").n_significant_digits # => 2 - * BigDecimal("3.1415").n_significant_digits # => 5 - * BigDecimal("-1e20").n_significant_digits # => 1 - * BigDecimal("1e-20").n_significant_digits # => 1 - * BigDecimal("Infinity").n_significant_digits # => 0 - * BigDecimal("-Infinity").n_significant_digits # => 0 - * BigDecimal("NaN").n_significant_digits # => 0 - */ -static VALUE -BigDecimal_n_significant_digits(VALUE self) -{ - ENTER(1); - - Real *p; - GUARD_OBJ(p, GetVpValue(self, 1)); - if (VpIsZero(p) || !VpIsDef(p)) { - return INT2FIX(0); - } - - ssize_t n = p->Prec; /* The length of frac without trailing zeros. */ - for (n = p->Prec; n > 0 && p->frac[n-1] == 0; --n); - if (n == 0) return INT2FIX(0); - - DECDIG x; - int nlz = BASE_FIG; - for (x = p->frac[0]; x > 0; x /= 10) --nlz; - - int ntz = 0; - for (x = p->frac[n-1]; x > 0 && x % 10 == 0; x /= 10) ++ntz; - - ssize_t n_significant_digits = BASE_FIG*n - nlz - ntz; - return SSIZET2NUM(n_significant_digits); -} - -/* - * call-seq: - * hash -> integer - * - * Returns the integer hash value for +self+. - * - * Two instances of \BigDecimal have the same hash value if and only if - * they have equal: - * - * - Sign. - * - Fractional part. - * - Exponent. - * - */ -static VALUE -BigDecimal_hash(VALUE self) -{ - ENTER(1); - Real *p; - st_index_t hash; - - GUARD_OBJ(p, GetVpValue(self, 1)); - hash = (st_index_t)p->sign; - /* hash!=2: the case for 0(1),NaN(0) or +-Infinity(3) is sign itself */ - if(hash == 2 || hash == (st_index_t)-2) { - hash ^= rb_memhash(p->frac, sizeof(DECDIG)*p->Prec); - hash += p->exponent; - } - return ST2FIX(hash); -} - -/* - * call-seq: - * _dump -> string - * - * Returns a string representing the marshalling of +self+. - * See module Marshal. - * - * inf = BigDecimal('Infinity') # => Infinity - * dumped = inf._dump # => "9:Infinity" - * BigDecimal._load(dumped) # => Infinity - * - */ -static VALUE -BigDecimal_dump(int argc, VALUE *argv, VALUE self) -{ - ENTER(5); - Real *vp; - char *psz; - VALUE dummy; - volatile VALUE dump; - size_t len; - - rb_scan_args(argc, argv, "01", &dummy); - GUARD_OBJ(vp,GetVpValue(self, 1)); - dump = rb_str_new(0, VpNumOfChars(vp, "E")+50); - psz = RSTRING_PTR(dump); - snprintf(psz, RSTRING_LEN(dump), "%"PRIuSIZE":", VpMaxPrec(vp)*VpBaseFig()); - len = strlen(psz); - VpToString(vp, psz+len, RSTRING_LEN(dump)-len, 0, 0); - rb_str_resize(dump, strlen(psz)); - return dump; -} - -/* - * Internal method used to provide marshalling support. See the Marshal module. - */ -static VALUE -BigDecimal_load(VALUE self, VALUE str) -{ - ENTER(2); - Real *pv; - unsigned char *pch; - unsigned char ch; - unsigned long m=0; - - pch = (unsigned char *)StringValueCStr(str); - /* First get max prec */ - while((*pch) != (unsigned char)'\0' && (ch = *pch++) != (unsigned char)':') { - if(!ISDIGIT(ch)) { - rb_raise(rb_eTypeError, "load failed: invalid character in the marshaled string"); - } - m = m*10 + (unsigned long)(ch-'0'); - } - if (m > VpBaseFig()) m -= VpBaseFig(); - GUARD_OBJ(pv, VpNewRbClass(m, (char *)pch, self, true, true)); - m /= VpBaseFig(); - if (m && pv->MaxPrec > m) { - pv->MaxPrec = m+1; - } - return VpCheckGetValue(pv); -} - -static unsigned short -check_rounding_mode_option(VALUE const opts) -{ - VALUE mode; - char const *s; - long l; - - assert(RB_TYPE_P(opts, T_HASH)); - - if (NIL_P(opts)) - goto no_opt; - - mode = rb_hash_lookup2(opts, ID2SYM(id_half), Qundef); - if (mode == Qundef || NIL_P(mode)) - goto no_opt; - - if (SYMBOL_P(mode)) - mode = rb_sym2str(mode); - else if (!RB_TYPE_P(mode, T_STRING)) { - VALUE str_mode = rb_check_string_type(mode); - if (NIL_P(str_mode)) - goto invalid; - mode = str_mode; - } - s = RSTRING_PTR(mode); - l = RSTRING_LEN(mode); - switch (l) { - case 2: - if (strncasecmp(s, "up", 2) == 0) - return VP_ROUND_HALF_UP; - break; - case 4: - if (strncasecmp(s, "even", 4) == 0) - return VP_ROUND_HALF_EVEN; - else if (strncasecmp(s, "down", 4) == 0) - return VP_ROUND_HALF_DOWN; - break; - default: - break; - } - - invalid: - rb_raise(rb_eArgError, "invalid rounding mode (%"PRIsVALUE")", mode); - - no_opt: - return VpGetRoundMode(); -} - -static unsigned short -check_rounding_mode(VALUE const v) -{ - unsigned short sw; - ID id; - if (RB_TYPE_P(v, T_SYMBOL)) { - int i; - id = SYM2ID(v); - for (i = 0; i < RBD_NUM_ROUNDING_MODES; ++i) { - if (rbd_rounding_modes[i].id == id) { - return rbd_rounding_modes[i].mode; - } - } - rb_raise(rb_eArgError, "invalid rounding mode (%"PRIsVALUE")", v); - } - else { - sw = NUM2USHORT(v); - if (!VpIsRoundMode(sw)) { - rb_raise(rb_eArgError, "invalid rounding mode (%"PRIsVALUE")", v); - } - return sw; - } -} - -/* call-seq: - * BigDecimal.mode(mode, setting = nil) -> integer - * - * Returns an integer representing the mode settings - * for exception handling and rounding. - * - * These modes control exception handling: - * - * - \BigDecimal::EXCEPTION_NaN. - * - \BigDecimal::EXCEPTION_INFINITY. - * - \BigDecimal::EXCEPTION_UNDERFLOW. - * - \BigDecimal::EXCEPTION_OVERFLOW. - * - \BigDecimal::EXCEPTION_ZERODIVIDE. - * - \BigDecimal::EXCEPTION_ALL. - * - * Values for +setting+ for exception handling: - * - * - +true+: sets the given +mode+ to +true+. - * - +false+: sets the given +mode+ to +false+. - * - +nil+: does not modify the mode settings. - * - * You can use method BigDecimal.save_exception_mode - * to temporarily change, and then automatically restore, exception modes. - * - * For clarity, some examples below begin by setting all - * exception modes to +false+. - * - * This mode controls the way rounding is to be performed: - * - * - \BigDecimal::ROUND_MODE - * - * You can use method BigDecimal.save_rounding_mode - * to temporarily change, and then automatically restore, the rounding mode. - * - * NaNs - * - * Mode \BigDecimal::EXCEPTION_NaN controls behavior - * when a \BigDecimal NaN is created. - * - * Settings: - * - * - +false+ (default): Returns BigDecimal('NaN'). - * - +true+: Raises FloatDomainError. - * - * Examples: - * - * BigDecimal.mode(BigDecimal::EXCEPTION_ALL, false) # => 0 - * BigDecimal('NaN') # => NaN - * BigDecimal.mode(BigDecimal::EXCEPTION_NaN, true) # => 2 - * BigDecimal('NaN') # Raises FloatDomainError - * - * Infinities - * - * Mode \BigDecimal::EXCEPTION_INFINITY controls behavior - * when a \BigDecimal Infinity or -Infinity is created. - * Settings: - * - * - +false+ (default): Returns BigDecimal('Infinity') - * or BigDecimal('-Infinity'). - * - +true+: Raises FloatDomainError. - * - * Examples: - * - * BigDecimal.mode(BigDecimal::EXCEPTION_ALL, false) # => 0 - * BigDecimal('Infinity') # => Infinity - * BigDecimal('-Infinity') # => -Infinity - * BigDecimal.mode(BigDecimal::EXCEPTION_INFINITY, true) # => 1 - * BigDecimal('Infinity') # Raises FloatDomainError - * BigDecimal('-Infinity') # Raises FloatDomainError - * - * Underflow - * - * Mode \BigDecimal::EXCEPTION_UNDERFLOW controls behavior - * when a \BigDecimal underflow occurs. - * Settings: - * - * - +false+ (default): Returns BigDecimal('0') - * or BigDecimal('-Infinity'). - * - +true+: Raises FloatDomainError. - * - * Examples: - * - * BigDecimal.mode(BigDecimal::EXCEPTION_ALL, false) # => 0 - * def flow_under - * x = BigDecimal('0.1') - * 100.times { x *= x } - * end - * flow_under # => 100 - * BigDecimal.mode(BigDecimal::EXCEPTION_UNDERFLOW, true) # => 4 - * flow_under # Raises FloatDomainError - * - * Overflow - * - * Mode \BigDecimal::EXCEPTION_OVERFLOW controls behavior - * when a \BigDecimal overflow occurs. - * Settings: - * - * - +false+ (default): Returns BigDecimal('Infinity') - * or BigDecimal('-Infinity'). - * - +true+: Raises FloatDomainError. - * - * Examples: - * - * BigDecimal.mode(BigDecimal::EXCEPTION_ALL, false) # => 0 - * def flow_over - * x = BigDecimal('10') - * 100.times { x *= x } - * end - * flow_over # => 100 - * BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, true) # => 1 - * flow_over # Raises FloatDomainError - * - * Zero Division - * - * Mode \BigDecimal::EXCEPTION_ZERODIVIDE controls behavior - * when a zero-division occurs. - * Settings: - * - * - +false+ (default): Returns BigDecimal('Infinity') - * or BigDecimal('-Infinity'). - * - +true+: Raises FloatDomainError. - * - * Examples: - * - * BigDecimal.mode(BigDecimal::EXCEPTION_ALL, false) # => 0 - * one = BigDecimal('1') - * zero = BigDecimal('0') - * one / zero # => Infinity - * BigDecimal.mode(BigDecimal::EXCEPTION_ZERODIVIDE, true) # => 16 - * one / zero # Raises FloatDomainError - * - * All Exceptions - * - * Mode \BigDecimal::EXCEPTION_ALL controls all of the above: - * - * BigDecimal.mode(BigDecimal::EXCEPTION_ALL, false) # => 0 - * BigDecimal.mode(BigDecimal::EXCEPTION_ALL, true) # => 23 - * - * Rounding - * - * Mode \BigDecimal::ROUND_MODE controls the way rounding is to be performed; - * its +setting+ values are: - * - * - +ROUND_UP+: Round away from zero. - * Aliased as +:up+. - * - +ROUND_DOWN+: Round toward zero. - * Aliased as +:down+ and +:truncate+. - * - +ROUND_HALF_UP+: Round toward the nearest neighbor; - * if the neighbors are equidistant, round away from zero. - * Aliased as +:half_up+ and +:default+. - * - +ROUND_HALF_DOWN+: Round toward the nearest neighbor; - * if the neighbors are equidistant, round toward zero. - * Aliased as +:half_down+. - * - +ROUND_HALF_EVEN+ (Banker's rounding): Round toward the nearest neighbor; - * if the neighbors are equidistant, round toward the even neighbor. - * Aliased as +:half_even+ and +:banker+. - * - +ROUND_CEILING+: Round toward positive infinity. - * Aliased as +:ceiling+ and +:ceil+. - * - +ROUND_FLOOR+: Round toward negative infinity. - * Aliased as +:floor:+. - * - */ -static VALUE -BigDecimal_mode(int argc, VALUE *argv, VALUE self) -{ - VALUE which; - VALUE val; - unsigned long f,fo; - - rb_scan_args(argc, argv, "11", &which, &val); - f = (unsigned long)NUM2INT(which); - - if (f & VP_EXCEPTION_ALL) { - /* Exception mode setting */ - fo = VpGetException(); - if (val == Qnil) return INT2FIX(fo); - if (val != Qfalse && val!=Qtrue) { - rb_raise(rb_eArgError, "second argument must be true or false"); - return Qnil; /* Not reached */ - } - if (f & VP_EXCEPTION_INFINITY) { - VpSetException((unsigned short)((val == Qtrue) ? (fo | VP_EXCEPTION_INFINITY) : - (fo & (~VP_EXCEPTION_INFINITY)))); - } - fo = VpGetException(); - if (f & VP_EXCEPTION_NaN) { - VpSetException((unsigned short)((val == Qtrue) ? (fo | VP_EXCEPTION_NaN) : - (fo & (~VP_EXCEPTION_NaN)))); - } - fo = VpGetException(); - if (f & VP_EXCEPTION_UNDERFLOW) { - VpSetException((unsigned short)((val == Qtrue) ? (fo | VP_EXCEPTION_UNDERFLOW) : - (fo & (~VP_EXCEPTION_UNDERFLOW)))); - } - fo = VpGetException(); - if(f & VP_EXCEPTION_ZERODIVIDE) { - VpSetException((unsigned short)((val == Qtrue) ? (fo | VP_EXCEPTION_ZERODIVIDE) : - (fo & (~VP_EXCEPTION_ZERODIVIDE)))); - } - fo = VpGetException(); - return INT2FIX(fo); - } - if (VP_ROUND_MODE == f) { - /* Rounding mode setting */ - unsigned short sw; - fo = VpGetRoundMode(); - if (NIL_P(val)) return INT2FIX(fo); - sw = check_rounding_mode(val); - fo = VpSetRoundMode(sw); - return INT2FIX(fo); - } - rb_raise(rb_eTypeError, "first argument for BigDecimal.mode invalid"); - return Qnil; -} - -static size_t -GetAddSubPrec(Real *a, Real *b) -{ - size_t mxs; - size_t mx = a->Prec; - SIGNED_VALUE d; - - if (!VpIsDef(a) || !VpIsDef(b)) return (size_t)-1L; - if (mx < b->Prec) mx = b->Prec; - if (a->exponent != b->exponent) { - mxs = mx; - d = a->exponent - b->exponent; - if (d < 0) d = -d; - mx = mx + (size_t)d; - if (mx < mxs) { - return VpException(VP_EXCEPTION_INFINITY, "Exponent overflow", 0); - } - } - return mx; -} - -static inline SIGNED_VALUE -check_int_precision(VALUE v) -{ - SIGNED_VALUE n; -#if SIZEOF_VALUE <= SIZEOF_LONG - n = (SIGNED_VALUE)NUM2LONG(v); -#elif SIZEOF_VALUE <= SIZEOF_LONG_LONG - n = (SIGNED_VALUE)NUM2LL(v); -#else -# error SIZEOF_VALUE is too large -#endif - if (n < 0) { - rb_raise(rb_eArgError, "negative precision"); - } - return n; -} - -static VALUE -BigDecimal_wrap_struct(VALUE obj, Real *vp) -{ - assert(is_kind_of_BigDecimal(obj)); - assert(vp != NULL); - - if (vp->obj == obj && RTYPEDDATA_DATA(obj) == vp) - return obj; - - assert(RTYPEDDATA_DATA(obj) == NULL); - assert(vp->obj == 0); - - RTYPEDDATA_DATA(obj) = vp; - vp->obj = obj; - RB_OBJ_FREEZE(obj); - return obj; -} - -VP_EXPORT Real * -VpNewRbClass(size_t mx, const char *str, VALUE klass, bool strict_p, bool raise_exception) -{ - VALUE obj = TypedData_Wrap_Struct(klass, &BigDecimal_data_type, 0); - Real *pv = VpAlloc(mx, str, strict_p, raise_exception); - if (!pv) - return NULL; - BigDecimal_wrap_struct(obj, pv); - return pv; -} - -VP_EXPORT Real * -VpCreateRbObject(size_t mx, const char *str, bool raise_exception) -{ - return VpNewRbClass(mx, str, rb_cBigDecimal, true, raise_exception); -} - -static Real * -VpCopy(Real *pv, Real const* const x) -{ - assert(x != NULL); - - pv = rbd_reallocate_struct(pv, x->MaxPrec); - pv->MaxPrec = x->MaxPrec; - pv->Prec = x->Prec; - pv->exponent = x->exponent; - pv->sign = x->sign; - pv->flag = x->flag; - MEMCPY(pv->frac, x->frac, DECDIG, pv->MaxPrec); - - return pv; -} - -/* Returns True if the value is Not a Number. */ -static VALUE -BigDecimal_IsNaN(VALUE self) -{ - Real *p = GetVpValue(self, 1); - if (VpIsNaN(p)) return Qtrue; - return Qfalse; -} - -/* Returns nil, -1, or +1 depending on whether the value is finite, - * -Infinity, or +Infinity. - */ -static VALUE -BigDecimal_IsInfinite(VALUE self) -{ - Real *p = GetVpValue(self, 1); - if (VpIsPosInf(p)) return INT2FIX(1); - if (VpIsNegInf(p)) return INT2FIX(-1); - return Qnil; -} - -/* Returns True if the value is finite (not NaN or infinite). */ -static VALUE -BigDecimal_IsFinite(VALUE self) -{ - Real *p = GetVpValue(self, 1); - if (VpIsNaN(p)) return Qfalse; - if (VpIsInf(p)) return Qfalse; - return Qtrue; -} - -static void -BigDecimal_check_num(Real *p) -{ - VpCheckException(p, true); -} - -static VALUE BigDecimal_split(VALUE self); - -/* Returns the value as an Integer. - * - * If the BigDecimal is infinity or NaN, raises FloatDomainError. - */ -static VALUE -BigDecimal_to_i(VALUE self) -{ - ENTER(5); - ssize_t e, nf; - Real *p; - - GUARD_OBJ(p, GetVpValue(self, 1)); - BigDecimal_check_num(p); - - e = VpExponent10(p); - if (e <= 0) return INT2FIX(0); - nf = VpBaseFig(); - if (e <= nf) { - return LONG2NUM((long)(VpGetSign(p) * (DECDIG_DBL_SIGNED)p->frac[0])); - } - else { - VALUE a = BigDecimal_split(self); - VALUE digits = RARRAY_AREF(a, 1); - VALUE numerator = rb_funcall(digits, rb_intern("to_i"), 0); - VALUE ret; - ssize_t dpower = e - (ssize_t)RSTRING_LEN(digits); - - if (BIGDECIMAL_NEGATIVE_P(p)) { - numerator = rb_funcall(numerator, '*', 1, INT2FIX(-1)); - } - if (dpower < 0) { - ret = rb_funcall(numerator, rb_intern("div"), 1, - rb_funcall(INT2FIX(10), rb_intern("**"), 1, - INT2FIX(-dpower))); - } - else { - ret = rb_funcall(numerator, '*', 1, - rb_funcall(INT2FIX(10), rb_intern("**"), 1, - INT2FIX(dpower))); - } - if (RB_TYPE_P(ret, T_FLOAT)) { - rb_raise(rb_eFloatDomainError, "Infinity"); - } - return ret; - } -} - -/* Returns a new Float object having approximately the same value as the - * BigDecimal number. Normal accuracy limits and built-in errors of binary - * Float arithmetic apply. - */ -static VALUE -BigDecimal_to_f(VALUE self) -{ - ENTER(1); - Real *p; - double d; - SIGNED_VALUE e; - char *buf; - volatile VALUE str; - - GUARD_OBJ(p, GetVpValue(self, 1)); - if (VpVtoD(&d, &e, p) != 1) - return rb_float_new(d); - if (e > (SIGNED_VALUE)(DBL_MAX_10_EXP+BASE_FIG)) - goto overflow; - if (e < (SIGNED_VALUE)(DBL_MIN_10_EXP-BASE_FIG)) - goto underflow; - - str = rb_str_new(0, VpNumOfChars(p, "E")); - buf = RSTRING_PTR(str); - VpToString(p, buf, RSTRING_LEN(str), 0, 0); - errno = 0; - d = strtod(buf, 0); - if (errno == ERANGE) { - if (d == 0.0) goto underflow; - if (fabs(d) >= HUGE_VAL) goto overflow; - } - return rb_float_new(d); - -overflow: - VpException(VP_EXCEPTION_OVERFLOW, "BigDecimal to Float conversion", 0); - if (BIGDECIMAL_NEGATIVE_P(p)) - return rb_float_new(VpGetDoubleNegInf()); - else - return rb_float_new(VpGetDoublePosInf()); - -underflow: - VpException(VP_EXCEPTION_UNDERFLOW, "BigDecimal to Float conversion", 0); - if (BIGDECIMAL_NEGATIVE_P(p)) - return rb_float_new(-0.0); - else - return rb_float_new(0.0); -} - - -/* Converts a BigDecimal to a Rational. - */ -static VALUE -BigDecimal_to_r(VALUE self) -{ - Real *p; - ssize_t sign, power, denomi_power; - VALUE a, digits, numerator; - - p = GetVpValue(self, 1); - BigDecimal_check_num(p); - - sign = VpGetSign(p); - power = VpExponent10(p); - a = BigDecimal_split(self); - digits = RARRAY_AREF(a, 1); - denomi_power = power - RSTRING_LEN(digits); - numerator = rb_funcall(digits, rb_intern("to_i"), 0); - - if (sign < 0) { - numerator = rb_funcall(numerator, '*', 1, INT2FIX(-1)); - } - if (denomi_power < 0) { - return rb_Rational(numerator, - rb_funcall(INT2FIX(10), rb_intern("**"), 1, - INT2FIX(-denomi_power))); - } - else { - return rb_Rational1(rb_funcall(numerator, '*', 1, - rb_funcall(INT2FIX(10), rb_intern("**"), 1, - INT2FIX(denomi_power)))); - } -} - -/* The coerce method provides support for Ruby type coercion. It is not - * enabled by default. - * - * This means that binary operations like + * / or - can often be performed - * on a BigDecimal and an object of another type, if the other object can - * be coerced into a BigDecimal value. - * - * e.g. - * a = BigDecimal("1.0") - * b = a / 2.0 #=> 0.5 - * - * Note that coercing a String to a BigDecimal is not supported by default; - * it requires a special compile-time option when building Ruby. - */ -static VALUE -BigDecimal_coerce(VALUE self, VALUE other) -{ - ENTER(2); - VALUE obj; - Real *b; - - if (RB_TYPE_P(other, T_FLOAT)) { - GUARD_OBJ(b, GetVpValueWithPrec(other, 0, 1)); - obj = rb_assoc_new(VpCheckGetValue(b), self); - } - else { - if (RB_TYPE_P(other, T_RATIONAL)) { - Real* pv = DATA_PTR(self); - GUARD_OBJ(b, GetVpValueWithPrec(other, pv->Prec*VpBaseFig(), 1)); - } - else { - GUARD_OBJ(b, GetVpValue(other, 1)); - } - obj = rb_assoc_new(b->obj, self); - } - - return obj; -} - -/* - * call-seq: - * +big_decimal -> self - * - * Returns +self+: - * - * +BigDecimal(5) # => 0.5e1 - * +BigDecimal(-5) # => -0.5e1 - * - */ - -static VALUE -BigDecimal_uplus(VALUE self) -{ - return self; -} - - /* - * call-seq: - * self + value -> bigdecimal - * - * Returns the \BigDecimal sum of +self+ and +value+: - * - * b = BigDecimal('111111.111') # => 0.111111111e6 - * b + 2 # => 0.111113111e6 - * b + 2.0 # => 0.111113111e6 - * b + Rational(2, 1) # => 0.111113111e6 - * b + Complex(2, 0) # => (0.111113111e6+0i) - * - * See the {Note About Precision}[BigDecimal.html#class-BigDecimal-label-A+Note+About+Precision]. - * - */ - -static VALUE -BigDecimal_add(VALUE self, VALUE r) -{ - ENTER(5); - Real *c, *a, *b; - size_t mx; - - GUARD_OBJ(a, GetVpValue(self, 1)); - if (RB_TYPE_P(r, T_FLOAT)) { - b = GetVpValueWithPrec(r, 0, 1); - } - else if (RB_TYPE_P(r, T_RATIONAL)) { - b = GetVpValueWithPrec(r, a->Prec*VpBaseFig(), 1); - } - else { - b = GetVpValue(r, 0); - } - - if (!b) return DoSomeOne(self,r,'+'); - SAVE(b); - - if (VpIsNaN(b)) return b->obj; - if (VpIsNaN(a)) return a->obj; - - mx = GetAddSubPrec(a, b); - if (mx == (size_t)-1L) { - GUARD_OBJ(c, NewZeroWrapLimited(1, VpBaseFig() + 1)); - VpAddSub(c, a, b, 1); - } - else { - GUARD_OBJ(c, NewZeroWrapLimited(1, mx * (VpBaseFig() + 1))); - if (!mx) { - VpSetInf(c, VpGetSign(a)); - } - else { - VpAddSub(c, a, b, 1); - } - } - return VpCheckGetValue(c); -} - - /* call-seq: - * self - value -> bigdecimal - * - * Returns the \BigDecimal difference of +self+ and +value+: - * - * b = BigDecimal('333333.333') # => 0.333333333e6 - * b - 2 # => 0.333331333e6 - * b - 2.0 # => 0.333331333e6 - * b - Rational(2, 1) # => 0.333331333e6 - * b - Complex(2, 0) # => (0.333331333e6+0i) - * - * See the {Note About Precision}[BigDecimal.html#class-BigDecimal-label-A+Note+About+Precision]. - * - */ -static VALUE -BigDecimal_sub(VALUE self, VALUE r) -{ - ENTER(5); - Real *c, *a, *b; - size_t mx; - - GUARD_OBJ(a, GetVpValue(self,1)); - if (RB_TYPE_P(r, T_FLOAT)) { - b = GetVpValueWithPrec(r, 0, 1); - } - else if (RB_TYPE_P(r, T_RATIONAL)) { - b = GetVpValueWithPrec(r, a->Prec*VpBaseFig(), 1); - } - else { - b = GetVpValue(r,0); - } - - if (!b) return DoSomeOne(self,r,'-'); - SAVE(b); - - if (VpIsNaN(b)) return b->obj; - if (VpIsNaN(a)) return a->obj; - - mx = GetAddSubPrec(a,b); - if (mx == (size_t)-1L) { - GUARD_OBJ(c, NewZeroWrapLimited(1, VpBaseFig() + 1)); - VpAddSub(c, a, b, -1); - } - else { - GUARD_OBJ(c, NewZeroWrapLimited(1, mx *(VpBaseFig() + 1))); - if (!mx) { - VpSetInf(c,VpGetSign(a)); - } - else { - VpAddSub(c, a, b, -1); - } - } - return VpCheckGetValue(c); -} - -static VALUE -BigDecimalCmp(VALUE self, VALUE r,char op) -{ - ENTER(5); - SIGNED_VALUE e; - Real *a, *b=0; - GUARD_OBJ(a, GetVpValue(self, 1)); - switch (TYPE(r)) { - case T_DATA: - if (!is_kind_of_BigDecimal(r)) break; - /* fall through */ - case T_FIXNUM: - /* fall through */ - case T_BIGNUM: - GUARD_OBJ(b, GetVpValue(r, 0)); - break; - - case T_FLOAT: - GUARD_OBJ(b, GetVpValueWithPrec(r, 0, 0)); - break; - - case T_RATIONAL: - GUARD_OBJ(b, GetVpValueWithPrec(r, a->Prec*VpBaseFig(), 0)); - break; - - default: - break; - } - if (b == NULL) { - ID f = 0; - - switch (op) { - case '*': - return rb_num_coerce_cmp(self, r, rb_intern("<=>")); - - case '=': - return RTEST(rb_num_coerce_cmp(self, r, rb_intern("=="))) ? Qtrue : Qfalse; - - case 'G': - f = rb_intern(">="); - break; - - case 'L': - f = rb_intern("<="); - break; - - case '>': - /* fall through */ - case '<': - f = (ID)op; - break; - - default: - break; - } - return rb_num_coerce_relop(self, r, f); - } - SAVE(b); - e = VpComp(a, b); - if (e == 999) - return (op == '*') ? Qnil : Qfalse; - switch (op) { - case '*': - return INT2FIX(e); /* any op */ - - case '=': - if (e == 0) return Qtrue; - return Qfalse; - - case 'G': - if (e >= 0) return Qtrue; - return Qfalse; - - case '>': - if (e > 0) return Qtrue; - return Qfalse; - - case 'L': - if (e <= 0) return Qtrue; - return Qfalse; - - case '<': - if (e < 0) return Qtrue; - return Qfalse; - - default: - break; - } - - rb_bug("Undefined operation in BigDecimalCmp()"); - - UNREACHABLE; -} - -/* Returns True if the value is zero. */ -static VALUE -BigDecimal_zero(VALUE self) -{ - Real *a = GetVpValue(self, 1); - return VpIsZero(a) ? Qtrue : Qfalse; -} - -/* Returns self if the value is non-zero, nil otherwise. */ -static VALUE -BigDecimal_nonzero(VALUE self) -{ - Real *a = GetVpValue(self, 1); - return VpIsZero(a) ? Qnil : self; -} - -/* The comparison operator. - * a <=> b is 0 if a == b, 1 if a > b, -1 if a < b. - */ -static VALUE -BigDecimal_comp(VALUE self, VALUE r) -{ - return BigDecimalCmp(self, r, '*'); -} - -/* - * Tests for value equality; returns true if the values are equal. - * - * The == and === operators and the eql? method have the same implementation - * for BigDecimal. - * - * Values may be coerced to perform the comparison: - * - * BigDecimal('1.0') == 1.0 #=> true - */ -static VALUE -BigDecimal_eq(VALUE self, VALUE r) -{ - return BigDecimalCmp(self, r, '='); -} - -/* call-seq: - * self < other -> true or false - * - * Returns +true+ if +self+ is less than +other+, +false+ otherwise: - * - * b = BigDecimal('1.5') # => 0.15e1 - * b < 2 # => true - * b < 2.0 # => true - * b < Rational(2, 1) # => true - * b < 1.5 # => false - * - * Raises an exception if the comparison cannot be made. - * - */ -static VALUE -BigDecimal_lt(VALUE self, VALUE r) -{ - return BigDecimalCmp(self, r, '<'); -} - -/* call-seq: - * self <= other -> true or false - * - * Returns +true+ if +self+ is less or equal to than +other+, +false+ otherwise: - * - * b = BigDecimal('1.5') # => 0.15e1 - * b <= 2 # => true - * b <= 2.0 # => true - * b <= Rational(2, 1) # => true - * b <= 1.5 # => true - * b < 1 # => false - * - * Raises an exception if the comparison cannot be made. - * - */ -static VALUE -BigDecimal_le(VALUE self, VALUE r) -{ - return BigDecimalCmp(self, r, 'L'); -} - -/* call-seq: - * self > other -> true or false - * - * Returns +true+ if +self+ is greater than +other+, +false+ otherwise: - * - * b = BigDecimal('1.5') - * b > 1 # => true - * b > 1.0 # => true - * b > Rational(1, 1) # => true - * b > 2 # => false - * - * Raises an exception if the comparison cannot be made. - * - */ -static VALUE -BigDecimal_gt(VALUE self, VALUE r) -{ - return BigDecimalCmp(self, r, '>'); -} - -/* call-seq: - * self >= other -> true or false - * - * Returns +true+ if +self+ is greater than or equal to +other+, +false+ otherwise: - * - * b = BigDecimal('1.5') - * b >= 1 # => true - * b >= 1.0 # => true - * b >= Rational(1, 1) # => true - * b >= 1.5 # => true - * b > 2 # => false - * - * Raises an exception if the comparison cannot be made. - * - */ -static VALUE -BigDecimal_ge(VALUE self, VALUE r) -{ - return BigDecimalCmp(self, r, 'G'); -} - -/* - * call-seq: - * -self -> bigdecimal - * - * Returns the \BigDecimal negation of self: - * - * b0 = BigDecimal('1.5') - * b1 = -b0 # => -0.15e1 - * b2 = -b1 # => 0.15e1 - * - */ - -static VALUE -BigDecimal_neg(VALUE self) -{ - ENTER(5); - Real *c, *a; - GUARD_OBJ(a, GetVpValue(self, 1)); - GUARD_OBJ(c, NewZeroWrapLimited(1, a->Prec *(VpBaseFig() + 1))); - VpAsgn(c, a, -1); - return VpCheckGetValue(c); -} - -static VALUE -BigDecimal_mult(VALUE self, VALUE r) -{ - ENTER(5); - Real *c, *a, *b; - size_t mx; - - GUARD_OBJ(a, GetVpValue(self, 1)); - if (RB_TYPE_P(r, T_FLOAT)) { - b = GetVpValueWithPrec(r, 0, 1); - } - else if (RB_TYPE_P(r, T_RATIONAL)) { - b = GetVpValueWithPrec(r, a->Prec*VpBaseFig(), 1); - } - else { - b = GetVpValue(r,0); - } - - if (!b) return DoSomeOne(self, r, '*'); - SAVE(b); - - mx = a->Prec + b->Prec; - GUARD_OBJ(c, NewZeroWrapLimited(1, mx * (VpBaseFig() + 1))); - VpMult(c, a, b); - return VpCheckGetValue(c); -} - -static VALUE -BigDecimal_divide(VALUE self, VALUE r, Real **c, Real **res, Real **div) -/* For c = self.div(r): with round operation */ -{ - ENTER(5); - Real *a, *b; - ssize_t a_prec, b_prec; - size_t mx; - - TypedData_Get_Struct(self, Real, &BigDecimal_data_type, a); - SAVE(a); - - VALUE rr = r; - if (is_kind_of_BigDecimal(rr)) { - /* do nothing */ - } - else if (RB_INTEGER_TYPE_P(r)) { - rr = rb_inum_convert_to_BigDecimal(r, 0, true); - } - else if (RB_TYPE_P(r, T_FLOAT)) { - rr = rb_float_convert_to_BigDecimal(r, 0, true); - } - else if (RB_TYPE_P(r, T_RATIONAL)) { - rr = rb_rational_convert_to_BigDecimal(r, a->Prec*BASE_FIG, true); - } - - if (!is_kind_of_BigDecimal(rr)) { - return DoSomeOne(self, r, '/'); - } - - TypedData_Get_Struct(rr, Real, &BigDecimal_data_type, b); - SAVE(b); - *div = b; - - BigDecimal_count_precision_and_scale(self, &a_prec, NULL); - BigDecimal_count_precision_and_scale(rr, &b_prec, NULL); - mx = (a_prec > b_prec) ? a_prec : b_prec; - mx *= 2; - - if (2*BIGDECIMAL_DOUBLE_FIGURES > mx) - mx = 2*BIGDECIMAL_DOUBLE_FIGURES; - - GUARD_OBJ((*c), NewZeroWrapNolimit(1, mx + 2*BASE_FIG)); - GUARD_OBJ((*res), NewZeroWrapNolimit(1, (mx + 1)*2 + 2*BASE_FIG)); - VpDivd(*c, *res, a, b); - - return Qnil; -} - -static VALUE BigDecimal_DoDivmod(VALUE self, VALUE r, Real **div, Real **mod); - -/* call-seq: - * a / b -> bigdecimal - * - * Divide by the specified value. - * - * The result precision will be the precision of the larger operand, - * but its minimum is 2*Float::DIG. - * - * See BigDecimal#div. - * See BigDecimal#quo. - */ -static VALUE -BigDecimal_div(VALUE self, VALUE r) -/* For c = self/r: with round operation */ -{ - ENTER(5); - Real *c=NULL, *res=NULL, *div = NULL; - r = BigDecimal_divide(self, r, &c, &res, &div); - if (!NIL_P(r)) return r; /* coerced by other */ - SAVE(c); SAVE(res); SAVE(div); - /* a/b = c + r/b */ - /* c xxxxx - r 00000yyyyy ==> (y/b)*BASE >= HALF_BASE - */ - /* Round */ - if (VpHasVal(div)) { /* frac[0] must be zero for NaN,INF,Zero */ - VpInternalRound(c, 0, c->frac[c->Prec-1], (DECDIG)(VpBaseVal() * (DECDIG_DBL)res->frac[0] / div->frac[0])); - } - return VpCheckGetValue(c); -} - -static VALUE BigDecimal_round(int argc, VALUE *argv, VALUE self); - -/* call-seq: - * quo(value) -> bigdecimal - * quo(value, digits) -> bigdecimal - * - * Divide by the specified value. - * - * digits:: If specified and less than the number of significant digits of - * the result, the result is rounded to the given number of digits, - * according to the rounding mode indicated by BigDecimal.mode. - * - * If digits is 0 or omitted, the result is the same as for the - * / operator. - * - * See BigDecimal#/. - * See BigDecimal#div. - */ -static VALUE -BigDecimal_quo(int argc, VALUE *argv, VALUE self) -{ - VALUE value, digits, result; - SIGNED_VALUE n = -1; - - argc = rb_scan_args(argc, argv, "11", &value, &digits); - if (argc > 1) { - n = check_int_precision(digits); - } - - if (n > 0) { - result = BigDecimal_div2(self, value, digits); - } - else { - result = BigDecimal_div(self, value); - } - - return result; -} - -/* - * %: mod = a%b = a - (a.to_f/b).floor * b - * div = (a.to_f/b).floor - */ -static VALUE -BigDecimal_DoDivmod(VALUE self, VALUE r, Real **div, Real **mod) -{ - ENTER(8); - Real *c=NULL, *d=NULL, *res=NULL; - Real *a, *b; - ssize_t a_prec, b_prec; - size_t mx; - - TypedData_Get_Struct(self, Real, &BigDecimal_data_type, a); - SAVE(a); - - VALUE rr = r; - if (is_kind_of_BigDecimal(rr)) { - /* do nothing */ - } - else if (RB_INTEGER_TYPE_P(r)) { - rr = rb_inum_convert_to_BigDecimal(r, 0, true); - } - else if (RB_TYPE_P(r, T_FLOAT)) { - rr = rb_float_convert_to_BigDecimal(r, 0, true); - } - else if (RB_TYPE_P(r, T_RATIONAL)) { - rr = rb_rational_convert_to_BigDecimal(r, a->Prec*BASE_FIG, true); - } - - if (!is_kind_of_BigDecimal(rr)) { - return Qfalse; - } - - TypedData_Get_Struct(rr, Real, &BigDecimal_data_type, b); - SAVE(b); - - if (VpIsNaN(a) || VpIsNaN(b)) goto NaN; - if (VpIsInf(a) && VpIsInf(b)) goto NaN; - if (VpIsZero(b)) { - rb_raise(rb_eZeroDivError, "divided by 0"); - } - if (VpIsInf(a)) { - if (VpGetSign(a) == VpGetSign(b)) { - VALUE inf = BigDecimal_positive_infinity(); - TypedData_Get_Struct(inf, Real, &BigDecimal_data_type, *div); - } - else { - VALUE inf = BigDecimal_negative_infinity(); - TypedData_Get_Struct(inf, Real, &BigDecimal_data_type, *div); - } - VALUE nan = BigDecimal_nan(); - TypedData_Get_Struct(nan, Real, &BigDecimal_data_type, *mod); - return Qtrue; - } - if (VpIsInf(b)) { - VALUE zero = BigDecimal_positive_zero(); - TypedData_Get_Struct(zero, Real, &BigDecimal_data_type, *div); - *mod = a; - return Qtrue; - } - if (VpIsZero(a)) { - VALUE zero = BigDecimal_positive_zero(); - TypedData_Get_Struct(zero, Real, &BigDecimal_data_type, *div); - TypedData_Get_Struct(zero, Real, &BigDecimal_data_type, *mod); - return Qtrue; - } - - BigDecimal_count_precision_and_scale(self, &a_prec, NULL); - BigDecimal_count_precision_and_scale(rr, &b_prec, NULL); - - mx = (a_prec > b_prec) ? a_prec : b_prec; - mx *= 2; - - if (2*BIGDECIMAL_DOUBLE_FIGURES > mx) - mx = 2*BIGDECIMAL_DOUBLE_FIGURES; - - GUARD_OBJ(c, NewZeroWrapLimited(1, mx + 2*BASE_FIG)); - GUARD_OBJ(res, NewZeroWrapNolimit(1, mx*2 + 2*BASE_FIG)); - VpDivd(c, res, a, b); - - mx = c->Prec * BASE_FIG; - GUARD_OBJ(d, NewZeroWrapLimited(1, mx)); - VpActiveRound(d, c, VP_ROUND_DOWN, 0); - - VpMult(res, d, b); - VpAddSub(c, a, res, -1); - - if (!VpIsZero(c) && (VpGetSign(a) * VpGetSign(b) < 0)) { - /* result adjustment for negative case */ - res = rbd_reallocate_struct(res, d->MaxPrec); - res->MaxPrec = d->MaxPrec; - VpAddSub(res, d, VpOne(), -1); - GUARD_OBJ(d, NewZeroWrapLimited(1, GetAddSubPrec(c, b) * 2*BASE_FIG)); - VpAddSub(d, c, b, 1); - *div = res; - *mod = d; - } - else { - *div = d; - *mod = c; - } - return Qtrue; - - NaN: - { - VALUE nan = BigDecimal_nan(); - TypedData_Get_Struct(nan, Real, &BigDecimal_data_type, *div); - TypedData_Get_Struct(nan, Real, &BigDecimal_data_type, *mod); - } - return Qtrue; -} - -/* call-seq: - * a % b - * a.modulo(b) - * - * Returns the modulus from dividing by b. - * - * See BigDecimal#divmod. - */ -static VALUE -BigDecimal_mod(VALUE self, VALUE r) /* %: a%b = a - (a.to_f/b).floor * b */ -{ - ENTER(3); - Real *div = NULL, *mod = NULL; - - if (BigDecimal_DoDivmod(self, r, &div, &mod)) { - SAVE(div); SAVE(mod); - return VpCheckGetValue(mod); - } - return DoSomeOne(self, r, '%'); -} - -static VALUE -BigDecimal_divremain(VALUE self, VALUE r, Real **dv, Real **rv) -{ - ENTER(10); - size_t mx; - Real *a = NULL, *b = NULL, *c = NULL, *res = NULL, *d = NULL, *rr = NULL, *ff = NULL; - Real *f = NULL; - - GUARD_OBJ(a, GetVpValue(self, 1)); - if (RB_TYPE_P(r, T_FLOAT)) { - b = GetVpValueWithPrec(r, 0, 1); - } - else if (RB_TYPE_P(r, T_RATIONAL)) { - b = GetVpValueWithPrec(r, a->Prec*VpBaseFig(), 1); - } - else { - b = GetVpValue(r, 0); - } - - if (!b) return DoSomeOne(self, r, rb_intern("remainder")); - SAVE(b); - - if (VpIsPosInf(b) || VpIsNegInf(b)) { - GUARD_OBJ(*dv, NewZeroWrapLimited(1, 1)); - VpSetZero(*dv, 1); - *rv = a; - return Qnil; - } - - mx = (a->MaxPrec + b->MaxPrec) *VpBaseFig(); - GUARD_OBJ(c, NewZeroWrapLimited(1, mx)); - GUARD_OBJ(res, NewZeroWrapNolimit(1, (mx+1) * 2 + (VpBaseFig() + 1))); - GUARD_OBJ(rr, NewZeroWrapNolimit(1, (mx+1) * 2 + (VpBaseFig() + 1))); - GUARD_OBJ(ff, NewZeroWrapNolimit(1, (mx+1) * 2 + (VpBaseFig() + 1))); - - VpDivd(c, res, a, b); - - mx = c->Prec *(VpBaseFig() + 1); - - GUARD_OBJ(d, NewZeroWrapLimited(1, mx)); - GUARD_OBJ(f, NewZeroWrapLimited(1, mx)); - - VpActiveRound(d, c, VP_ROUND_DOWN, 0); /* 0: round off */ - - VpFrac(f, c); - VpMult(rr, f, b); - VpAddSub(ff, res, rr, 1); - - *dv = d; - *rv = ff; - return Qnil; -} - -/* call-seq: - * remainder(value) - * - * Returns the remainder from dividing by the value. - * - * x.remainder(y) means x-y*(x/y).truncate - */ -static VALUE -BigDecimal_remainder(VALUE self, VALUE r) /* remainder */ -{ - VALUE f; - Real *d, *rv = 0; - f = BigDecimal_divremain(self, r, &d, &rv); - if (!NIL_P(f)) return f; - return VpCheckGetValue(rv); -} - -/* call-seq: - * divmod(value) - * - * Divides by the specified value, and returns the quotient and modulus - * as BigDecimal numbers. The quotient is rounded towards negative infinity. - * - * For example: - * - * require 'bigdecimal' - * - * a = BigDecimal("42") - * b = BigDecimal("9") - * - * q, m = a.divmod(b) - * - * c = q * b + m - * - * a == c #=> true - * - * The quotient q is (a/b).floor, and the modulus is the amount that must be - * added to q * b to get a. - */ -static VALUE -BigDecimal_divmod(VALUE self, VALUE r) -{ - ENTER(5); - Real *div = NULL, *mod = NULL; - - if (BigDecimal_DoDivmod(self, r, &div, &mod)) { - SAVE(div); SAVE(mod); - return rb_assoc_new(VpCheckGetValue(div), VpCheckGetValue(mod)); - } - return DoSomeOne(self,r,rb_intern("divmod")); -} - -/* - * Do the same manner as Float#div when n is nil. - * Do the same manner as BigDecimal#quo when n is 0. - */ -static inline VALUE -BigDecimal_div2(VALUE self, VALUE b, VALUE n) -{ - ENTER(5); - SIGNED_VALUE ix; - - if (NIL_P(n)) { /* div in Float sense */ - Real *div = NULL; - Real *mod; - if (BigDecimal_DoDivmod(self, b, &div, &mod)) { - return BigDecimal_to_i(VpCheckGetValue(div)); - } - return DoSomeOne(self, b, rb_intern("div")); - } - - /* div in BigDecimal sense */ - ix = check_int_precision(n); - if (ix == 0) { - return BigDecimal_div(self, b); - } - else { - Real *res = NULL; - Real *av = NULL, *bv = NULL, *cv = NULL; - size_t mx = ix + VpBaseFig()*2; - size_t b_prec = ix; - size_t pl = VpSetPrecLimit(0); - - GUARD_OBJ(cv, NewZeroWrapLimited(1, mx + VpBaseFig())); - GUARD_OBJ(av, GetVpValue(self, 1)); - /* TODO: I want to refactor this precision control for a float value later - * by introducing an implicit conversion function instead of - * GetVpValueWithPrec. */ - if (RB_FLOAT_TYPE_P(b) && b_prec > BIGDECIMAL_DOUBLE_FIGURES) { - b_prec = BIGDECIMAL_DOUBLE_FIGURES; - } - GUARD_OBJ(bv, GetVpValueWithPrec(b, b_prec, 1)); - mx = av->Prec + bv->Prec + 2; - if (mx <= cv->MaxPrec) mx = cv->MaxPrec + 1; - GUARD_OBJ(res, NewZeroWrapNolimit(1, (mx * 2 + 2)*VpBaseFig())); - VpDivd(cv, res, av, bv); - VpSetPrecLimit(pl); - VpLeftRound(cv, VpGetRoundMode(), ix); - return VpCheckGetValue(cv); - } -} - - /* - * Document-method: BigDecimal#div - * - * call-seq: - * div(value) -> integer - * div(value, digits) -> bigdecimal or integer - * - * Divide by the specified value. - * - * digits:: If specified and less than the number of significant digits of the - * result, the result is rounded to that number of digits, according - * to BigDecimal.mode. - * - * If digits is 0, the result is the same as for the / operator - * or #quo. - * - * If digits is not specified, the result is an integer, - * by analogy with Float#div; see also BigDecimal#divmod. - * - * See BigDecimal#/. - * See BigDecimal#quo. - * - * Examples: - * - * a = BigDecimal("4") - * b = BigDecimal("3") - * - * a.div(b, 3) # => 0.133e1 - * - * a.div(b, 0) # => 0.1333333333333333333e1 - * a / b # => 0.1333333333333333333e1 - * a.quo(b) # => 0.1333333333333333333e1 - * - * a.div(b) # => 1 - */ -static VALUE -BigDecimal_div3(int argc, VALUE *argv, VALUE self) -{ - VALUE b,n; - - rb_scan_args(argc, argv, "11", &b, &n); - - return BigDecimal_div2(self, b, n); -} - - /* - * call-seq: - * add(value, ndigits) -> new_bigdecimal - * - * Returns the \BigDecimal sum of +self+ and +value+ - * with a precision of +ndigits+ decimal digits. - * - * When +ndigits+ is less than the number of significant digits - * in the sum, the sum is rounded to that number of digits, - * according to the current rounding mode; see BigDecimal.mode. - * - * Examples: - * - * # Set the rounding mode. - * BigDecimal.mode(BigDecimal::ROUND_MODE, :half_up) - * b = BigDecimal('111111.111') - * b.add(1, 0) # => 0.111112111e6 - * b.add(1, 3) # => 0.111e6 - * b.add(1, 6) # => 0.111112e6 - * b.add(1, 15) # => 0.111112111e6 - * b.add(1.0, 15) # => 0.111112111e6 - * b.add(Rational(1, 1), 15) # => 0.111112111e6 - * - */ - -static VALUE -BigDecimal_add2(VALUE self, VALUE b, VALUE n) -{ - ENTER(2); - Real *cv; - SIGNED_VALUE mx = check_int_precision(n); - if (mx == 0) return BigDecimal_add(self, b); - else { - size_t pl = VpSetPrecLimit(0); - VALUE c = BigDecimal_add(self, b); - VpSetPrecLimit(pl); - GUARD_OBJ(cv, GetVpValue(c, 1)); - VpLeftRound(cv, VpGetRoundMode(), mx); - return VpCheckGetValue(cv); - } -} - -/* call-seq: - * sub(value, digits) -> bigdecimal - * - * Subtract the specified value. - * - * e.g. - * c = a.sub(b,n) - * - * digits:: If specified and less than the number of significant digits of the - * result, the result is rounded to that number of digits, according - * to BigDecimal.mode. - * - */ -static VALUE -BigDecimal_sub2(VALUE self, VALUE b, VALUE n) -{ - ENTER(2); - Real *cv; - SIGNED_VALUE mx = check_int_precision(n); - if (mx == 0) return BigDecimal_sub(self, b); - else { - size_t pl = VpSetPrecLimit(0); - VALUE c = BigDecimal_sub(self, b); - VpSetPrecLimit(pl); - GUARD_OBJ(cv, GetVpValue(c, 1)); - VpLeftRound(cv, VpGetRoundMode(), mx); - return VpCheckGetValue(cv); - } -} - - /* - * call-seq: - * mult(other, ndigits) -> bigdecimal - * - * Returns the \BigDecimal product of +self+ and +value+ - * with a precision of +ndigits+ decimal digits. - * - * When +ndigits+ is less than the number of significant digits - * in the sum, the sum is rounded to that number of digits, - * according to the current rounding mode; see BigDecimal.mode. - * - * Examples: - * - * # Set the rounding mode. - * BigDecimal.mode(BigDecimal::ROUND_MODE, :half_up) - * b = BigDecimal('555555.555') - * b.mult(3, 0) # => 0.1666666665e7 - * b.mult(3, 3) # => 0.167e7 - * b.mult(3, 6) # => 0.166667e7 - * b.mult(3, 15) # => 0.1666666665e7 - * b.mult(3.0, 0) # => 0.1666666665e7 - * b.mult(Rational(3, 1), 0) # => 0.1666666665e7 - * b.mult(Complex(3, 0), 0) # => (0.1666666665e7+0.0i) - * - */ - -static VALUE -BigDecimal_mult2(VALUE self, VALUE b, VALUE n) -{ - ENTER(2); - Real *cv; - SIGNED_VALUE mx = check_int_precision(n); - if (mx == 0) return BigDecimal_mult(self, b); - else { - size_t pl = VpSetPrecLimit(0); - VALUE c = BigDecimal_mult(self, b); - VpSetPrecLimit(pl); - GUARD_OBJ(cv, GetVpValue(c, 1)); - VpLeftRound(cv, VpGetRoundMode(), mx); - return VpCheckGetValue(cv); - } -} - -/* - * call-seq: - * abs -> bigdecimal - * - * Returns the \BigDecimal absolute value of +self+: - * - * BigDecimal('5').abs # => 0.5e1 - * BigDecimal('-3').abs # => 0.3e1 - * - */ - -static VALUE -BigDecimal_abs(VALUE self) -{ - ENTER(5); - Real *c, *a; - size_t mx; - - GUARD_OBJ(a, GetVpValue(self, 1)); - mx = a->Prec *(VpBaseFig() + 1); - GUARD_OBJ(c, NewZeroWrapLimited(1, mx)); - VpAsgn(c, a, 1); - VpChangeSign(c, 1); - return VpCheckGetValue(c); -} - -/* call-seq: - * sqrt(n) - * - * Returns the square root of the value. - * - * Result has at least n significant digits. - */ -static VALUE -BigDecimal_sqrt(VALUE self, VALUE nFig) -{ - ENTER(5); - Real *c, *a; - size_t mx, n; - - GUARD_OBJ(a, GetVpValue(self, 1)); - mx = a->Prec * (VpBaseFig() + 1); - - n = check_int_precision(nFig); - n += VpDblFig() + VpBaseFig(); - if (mx <= n) mx = n; - GUARD_OBJ(c, NewZeroWrapLimited(1, mx)); - VpSqrt(c, a); - return VpCheckGetValue(c); -} - -/* Return the integer part of the number, as a BigDecimal. - */ -static VALUE -BigDecimal_fix(VALUE self) -{ - ENTER(5); - Real *c, *a; - size_t mx; - - GUARD_OBJ(a, GetVpValue(self, 1)); - mx = a->Prec *(VpBaseFig() + 1); - GUARD_OBJ(c, NewZeroWrapLimited(1, mx)); - VpActiveRound(c, a, VP_ROUND_DOWN, 0); /* 0: round off */ - return VpCheckGetValue(c); -} - -/* call-seq: - * round(n, mode) - * - * Round to the nearest integer (by default), returning the result as a - * BigDecimal if n is specified, or as an Integer if it isn't. - * - * BigDecimal('3.14159').round #=> 3 - * BigDecimal('8.7').round #=> 9 - * BigDecimal('-9.9').round #=> -10 - * - * BigDecimal('3.14159').round(2).class.name #=> "BigDecimal" - * BigDecimal('3.14159').round.class.name #=> "Integer" - * - * If n is specified and positive, the fractional part of the result has no - * more than that many digits. - * - * If n is specified and negative, at least that many digits to the left of the - * decimal point will be 0 in the result, and return value will be an Integer. - * - * BigDecimal('3.14159').round(3) #=> 3.142 - * BigDecimal('13345.234').round(-2) #=> 13300 - * - * The value of the optional mode argument can be used to determine how - * rounding is performed; see BigDecimal.mode. - */ -static VALUE -BigDecimal_round(int argc, VALUE *argv, VALUE self) -{ - ENTER(5); - Real *c, *a; - int iLoc = 0; - VALUE vLoc; - VALUE vRound; - int round_to_int = 0; - size_t mx, pl; - - unsigned short sw = VpGetRoundMode(); - - switch (rb_scan_args(argc, argv, "02", &vLoc, &vRound)) { - case 0: - iLoc = 0; - round_to_int = 1; - break; - case 1: - if (RB_TYPE_P(vLoc, T_HASH)) { - sw = check_rounding_mode_option(vLoc); - } - else { - iLoc = NUM2INT(vLoc); - if (iLoc < 1) round_to_int = 1; - } - break; - case 2: - iLoc = NUM2INT(vLoc); - if (RB_TYPE_P(vRound, T_HASH)) { - sw = check_rounding_mode_option(vRound); - } - else { - sw = check_rounding_mode(vRound); - } - break; - default: - break; - } - - pl = VpSetPrecLimit(0); - GUARD_OBJ(a, GetVpValue(self, 1)); - mx = a->Prec * (VpBaseFig() + 1); - GUARD_OBJ(c, NewZeroWrapLimited(1, mx)); - VpSetPrecLimit(pl); - VpActiveRound(c, a, sw, iLoc); - if (round_to_int) { - return BigDecimal_to_i(VpCheckGetValue(c)); - } - return VpCheckGetValue(c); -} - -/* call-seq: - * truncate(n) - * - * Truncate to the nearest integer (by default), returning the result as a - * BigDecimal. - * - * BigDecimal('3.14159').truncate #=> 3 - * BigDecimal('8.7').truncate #=> 8 - * BigDecimal('-9.9').truncate #=> -9 - * - * If n is specified and positive, the fractional part of the result has no - * more than that many digits. - * - * If n is specified and negative, at least that many digits to the left of the - * decimal point will be 0 in the result. - * - * BigDecimal('3.14159').truncate(3) #=> 3.141 - * BigDecimal('13345.234').truncate(-2) #=> 13300.0 - */ -static VALUE -BigDecimal_truncate(int argc, VALUE *argv, VALUE self) -{ - ENTER(5); - Real *c, *a; - int iLoc; - VALUE vLoc; - size_t mx, pl = VpSetPrecLimit(0); - - if (rb_scan_args(argc, argv, "01", &vLoc) == 0) { - iLoc = 0; - } - else { - iLoc = NUM2INT(vLoc); - } - - GUARD_OBJ(a, GetVpValue(self, 1)); - mx = a->Prec * (VpBaseFig() + 1); - GUARD_OBJ(c, NewZeroWrapLimited(1, mx)); - VpSetPrecLimit(pl); - VpActiveRound(c, a, VP_ROUND_DOWN, iLoc); /* 0: truncate */ - if (argc == 0) { - return BigDecimal_to_i(VpCheckGetValue(c)); - } - return VpCheckGetValue(c); -} - -/* Return the fractional part of the number, as a BigDecimal. - */ -static VALUE -BigDecimal_frac(VALUE self) -{ - ENTER(5); - Real *c, *a; - size_t mx; - - GUARD_OBJ(a, GetVpValue(self, 1)); - mx = a->Prec * (VpBaseFig() + 1); - GUARD_OBJ(c, NewZeroWrapLimited(1, mx)); - VpFrac(c, a); - return VpCheckGetValue(c); -} - -/* call-seq: - * floor(n) - * - * Return the largest integer less than or equal to the value, as a BigDecimal. - * - * BigDecimal('3.14159').floor #=> 3 - * BigDecimal('-9.1').floor #=> -10 - * - * If n is specified and positive, the fractional part of the result has no - * more than that many digits. - * - * If n is specified and negative, at least that - * many digits to the left of the decimal point will be 0 in the result. - * - * BigDecimal('3.14159').floor(3) #=> 3.141 - * BigDecimal('13345.234').floor(-2) #=> 13300.0 - */ -static VALUE -BigDecimal_floor(int argc, VALUE *argv, VALUE self) -{ - ENTER(5); - Real *c, *a; - int iLoc; - VALUE vLoc; - size_t mx, pl = VpSetPrecLimit(0); - - if (rb_scan_args(argc, argv, "01", &vLoc)==0) { - iLoc = 0; - } - else { - iLoc = NUM2INT(vLoc); - } - - GUARD_OBJ(a, GetVpValue(self, 1)); - mx = a->Prec * (VpBaseFig() + 1); - GUARD_OBJ(c, NewZeroWrapLimited(1, mx)); - VpSetPrecLimit(pl); - VpActiveRound(c, a, VP_ROUND_FLOOR, iLoc); -#ifdef BIGDECIMAL_DEBUG - VPrint(stderr, "floor: c=%\n", c); -#endif - if (argc == 0) { - return BigDecimal_to_i(VpCheckGetValue(c)); - } - return VpCheckGetValue(c); -} - -/* call-seq: - * ceil(n) - * - * Return the smallest integer greater than or equal to the value, as a BigDecimal. - * - * BigDecimal('3.14159').ceil #=> 4 - * BigDecimal('-9.1').ceil #=> -9 - * - * If n is specified and positive, the fractional part of the result has no - * more than that many digits. - * - * If n is specified and negative, at least that - * many digits to the left of the decimal point will be 0 in the result. - * - * BigDecimal('3.14159').ceil(3) #=> 3.142 - * BigDecimal('13345.234').ceil(-2) #=> 13400.0 - */ -static VALUE -BigDecimal_ceil(int argc, VALUE *argv, VALUE self) -{ - ENTER(5); - Real *c, *a; - int iLoc; - VALUE vLoc; - size_t mx, pl = VpSetPrecLimit(0); - - if (rb_scan_args(argc, argv, "01", &vLoc) == 0) { - iLoc = 0; - } else { - iLoc = NUM2INT(vLoc); - } - - GUARD_OBJ(a, GetVpValue(self, 1)); - mx = a->Prec * (VpBaseFig() + 1); - GUARD_OBJ(c, NewZeroWrapLimited(1, mx)); - VpSetPrecLimit(pl); - VpActiveRound(c, a, VP_ROUND_CEIL, iLoc); - if (argc == 0) { - return BigDecimal_to_i(VpCheckGetValue(c)); - } - return VpCheckGetValue(c); -} - -/* call-seq: - * to_s(s) - * - * Converts the value to a string. - * - * The default format looks like 0.xxxxEnn. - * - * The optional parameter s consists of either an integer; or an optional '+' - * or ' ', followed by an optional number, followed by an optional 'E' or 'F'. - * - * If there is a '+' at the start of s, positive values are returned with - * a leading '+'. - * - * A space at the start of s returns positive values with a leading space. - * - * If s contains a number, a space is inserted after each group of that many - * digits, starting from '.' and counting outwards. - * - * If s ends with an 'E', engineering notation (0.xxxxEnn) is used. - * - * If s ends with an 'F', conventional floating point notation is used. - * - * Examples: - * - * BigDecimal('-1234567890123.45678901234567890').to_s('5F') - * #=> '-123 45678 90123.45678 90123 45678 9' - * - * BigDecimal('1234567890123.45678901234567890').to_s('+8F') - * #=> '+12345 67890123.45678901 23456789' - * - * BigDecimal('1234567890123.45678901234567890').to_s(' F') - * #=> ' 1234567890123.4567890123456789' - */ -static VALUE -BigDecimal_to_s(int argc, VALUE *argv, VALUE self) -{ - ENTER(5); - int fmt = 0; /* 0: E format, 1: F format */ - int fPlus = 0; /* 0: default, 1: set ' ' before digits, 2: set '+' before digits. */ - Real *vp; - volatile VALUE str; - char *psz; - char ch; - size_t nc, mc = 0; - SIGNED_VALUE m; - VALUE f; - - GUARD_OBJ(vp, GetVpValue(self, 1)); - - if (rb_scan_args(argc, argv, "01", &f) == 1) { - if (RB_TYPE_P(f, T_STRING)) { - psz = StringValueCStr(f); - if (*psz == ' ') { - fPlus = 1; - psz++; - } - else if (*psz == '+') { - fPlus = 2; - psz++; - } - while ((ch = *psz++) != 0) { - if (ISSPACE(ch)) { - continue; - } - if (!ISDIGIT(ch)) { - if (ch == 'F' || ch == 'f') { - fmt = 1; /* F format */ - } - break; - } - mc = mc*10 + ch - '0'; - } - } - else { - m = NUM2INT(f); - if (m <= 0) { - rb_raise(rb_eArgError, "argument must be positive"); - } - mc = (size_t)m; - } - } - if (fmt) { - nc = VpNumOfChars(vp, "F"); - } - else { - nc = VpNumOfChars(vp, "E"); - } - if (mc > 0) { - nc += (nc + mc - 1) / mc + 1; - } - - str = rb_usascii_str_new(0, nc); - psz = RSTRING_PTR(str); - - if (fmt) { - VpToFString(vp, psz, RSTRING_LEN(str), mc, fPlus); - } - else { - VpToString (vp, psz, RSTRING_LEN(str), mc, fPlus); - } - rb_str_resize(str, strlen(psz)); - return str; -} - -/* Splits a BigDecimal number into four parts, returned as an array of values. - * - * The first value represents the sign of the BigDecimal, and is -1 or 1, or 0 - * if the BigDecimal is Not a Number. - * - * The second value is a string representing the significant digits of the - * BigDecimal, with no leading zeros. - * - * The third value is the base used for arithmetic (currently always 10) as an - * Integer. - * - * The fourth value is an Integer exponent. - * - * If the BigDecimal can be represented as 0.xxxxxx*10**n, then xxxxxx is the - * string of significant digits with no leading zeros, and n is the exponent. - * - * From these values, you can translate a BigDecimal to a float as follows: - * - * sign, significant_digits, base, exponent = a.split - * f = sign * "0.#{significant_digits}".to_f * (base ** exponent) - * - * (Note that the to_f method is provided as a more convenient way to translate - * a BigDecimal to a Float.) - */ -static VALUE -BigDecimal_split(VALUE self) -{ - ENTER(5); - Real *vp; - VALUE obj,str; - ssize_t e, s; - char *psz1; - - GUARD_OBJ(vp, GetVpValue(self, 1)); - str = rb_str_new(0, VpNumOfChars(vp, "E")); - psz1 = RSTRING_PTR(str); - VpSzMantissa(vp, psz1, RSTRING_LEN(str)); - s = 1; - if(psz1[0] == '-') { - size_t len = strlen(psz1 + 1); - - memmove(psz1, psz1 + 1, len); - psz1[len] = '\0'; - s = -1; - } - if (psz1[0] == 'N') s = 0; /* NaN */ - e = VpExponent10(vp); - obj = rb_ary_new2(4); - rb_ary_push(obj, INT2FIX(s)); - rb_ary_push(obj, str); - rb_str_resize(str, strlen(psz1)); - rb_ary_push(obj, INT2FIX(10)); - rb_ary_push(obj, SSIZET2NUM(e)); - return obj; -} - -/* Returns the exponent of the BigDecimal number, as an Integer. - * - * If the number can be represented as 0.xxxxxx*10**n where xxxxxx is a string - * of digits with no leading zeros, then n is the exponent. - */ -static VALUE -BigDecimal_exponent(VALUE self) -{ - ssize_t e = VpExponent10(GetVpValue(self, 1)); - return SSIZET2NUM(e); -} - -/* Returns a string representation of self. - * - * BigDecimal("1234.5678").inspect - * #=> "0.12345678e4" - */ -static VALUE -BigDecimal_inspect(VALUE self) -{ - ENTER(5); - Real *vp; - volatile VALUE str; - size_t nc; - - GUARD_OBJ(vp, GetVpValue(self, 1)); - nc = VpNumOfChars(vp, "E"); - - str = rb_str_new(0, nc); - VpToString(vp, RSTRING_PTR(str), RSTRING_LEN(str), 0, 0); - rb_str_resize(str, strlen(RSTRING_PTR(str))); - return str; -} - -static VALUE BigMath_s_exp(VALUE, VALUE, VALUE); -static VALUE BigMath_s_log(VALUE, VALUE, VALUE); - -#define BigMath_exp(x, n) BigMath_s_exp(rb_mBigMath, (x), (n)) -#define BigMath_log(x, n) BigMath_s_log(rb_mBigMath, (x), (n)) - -inline static int -is_integer(VALUE x) -{ - return (RB_TYPE_P(x, T_FIXNUM) || RB_TYPE_P(x, T_BIGNUM)); -} - -inline static int -is_negative(VALUE x) -{ - if (FIXNUM_P(x)) { - return FIX2LONG(x) < 0; - } - else if (RB_TYPE_P(x, T_BIGNUM)) { - return FIX2INT(rb_big_cmp(x, INT2FIX(0))) < 0; - } - else if (RB_TYPE_P(x, T_FLOAT)) { - return RFLOAT_VALUE(x) < 0.0; - } - return RTEST(rb_funcall(x, '<', 1, INT2FIX(0))); -} - -#define is_positive(x) (!is_negative(x)) - -inline static int -is_zero(VALUE x) -{ - VALUE num; - - switch (TYPE(x)) { - case T_FIXNUM: - return FIX2LONG(x) == 0; - - case T_BIGNUM: - return Qfalse; - - case T_RATIONAL: - num = rb_rational_num(x); - return FIXNUM_P(num) && FIX2LONG(num) == 0; - - default: - break; - } - - return RTEST(rb_funcall(x, id_eq, 1, INT2FIX(0))); -} - -inline static int -is_one(VALUE x) -{ - VALUE num, den; - - switch (TYPE(x)) { - case T_FIXNUM: - return FIX2LONG(x) == 1; - - case T_BIGNUM: - return Qfalse; - - case T_RATIONAL: - num = rb_rational_num(x); - den = rb_rational_den(x); - return FIXNUM_P(den) && FIX2LONG(den) == 1 && - FIXNUM_P(num) && FIX2LONG(num) == 1; - - default: - break; - } - - return RTEST(rb_funcall(x, id_eq, 1, INT2FIX(1))); -} - -inline static int -is_even(VALUE x) -{ - switch (TYPE(x)) { - case T_FIXNUM: - return (FIX2LONG(x) % 2) == 0; - - case T_BIGNUM: - { - unsigned long l; - rb_big_pack(x, &l, 1); - return l % 2 == 0; - } - - default: - break; - } - - return 0; -} - -static VALUE -bigdecimal_power_by_bigdecimal(Real const* x, Real const* exp, ssize_t const n) -{ - VALUE log_x, multiplied, y; - volatile VALUE obj = exp->obj; - - if (VpIsZero(exp)) { - return VpCheckGetValue(NewOneWrapLimited(1, n)); - } - - log_x = BigMath_log(x->obj, SSIZET2NUM(n+1)); - multiplied = BigDecimal_mult2(exp->obj, log_x, SSIZET2NUM(n+1)); - y = BigMath_exp(multiplied, SSIZET2NUM(n)); - RB_GC_GUARD(obj); - - return y; -} - -/* call-seq: - * power(n) - * power(n, prec) - * - * Returns the value raised to the power of n. - * - * Note that n must be an Integer. - * - * Also available as the operator **. - */ -static VALUE -BigDecimal_power(int argc, VALUE*argv, VALUE self) -{ - ENTER(5); - VALUE vexp, prec; - Real* exp = NULL; - Real *x, *y; - ssize_t mp, ma, n; - SIGNED_VALUE int_exp; - double d; - - rb_scan_args(argc, argv, "11", &vexp, &prec); - - GUARD_OBJ(x, GetVpValue(self, 1)); - n = NIL_P(prec) ? (ssize_t)(x->Prec*VpBaseFig()) : NUM2SSIZET(prec); - - if (VpIsNaN(x)) { - y = NewZeroWrapLimited(1, n); - VpSetNaN(y); - RB_GC_GUARD(y->obj); - return VpCheckGetValue(y); - } - - retry: - switch (TYPE(vexp)) { - case T_FIXNUM: - break; - - case T_BIGNUM: - break; - - case T_FLOAT: - d = RFLOAT_VALUE(vexp); - if (d == round(d)) { - if (FIXABLE(d)) { - vexp = LONG2FIX((long)d); - } - else { - vexp = rb_dbl2big(d); - } - goto retry; - } - if (NIL_P(prec)) { - n += BIGDECIMAL_DOUBLE_FIGURES; - } - exp = GetVpValueWithPrec(vexp, 0, 1); - break; - - case T_RATIONAL: - if (is_zero(rb_rational_num(vexp))) { - if (is_positive(vexp)) { - vexp = INT2FIX(0); - goto retry; - } - } - else if (is_one(rb_rational_den(vexp))) { - vexp = rb_rational_num(vexp); - goto retry; - } - exp = GetVpValueWithPrec(vexp, n, 1); - if (NIL_P(prec)) { - n += n; - } - break; - - case T_DATA: - if (is_kind_of_BigDecimal(vexp)) { - VALUE zero = INT2FIX(0); - VALUE rounded = BigDecimal_round(1, &zero, vexp); - if (RTEST(BigDecimal_eq(vexp, rounded))) { - vexp = BigDecimal_to_i(vexp); - goto retry; - } - if (NIL_P(prec)) { - GUARD_OBJ(y, GetVpValue(vexp, 1)); - n += y->Prec*VpBaseFig(); - } - exp = DATA_PTR(vexp); - break; - } - /* fall through */ - default: - rb_raise(rb_eTypeError, - "wrong argument type %"PRIsVALUE" (expected scalar Numeric)", - RB_OBJ_CLASSNAME(vexp)); - } - - if (VpIsZero(x)) { - if (is_negative(vexp)) { - y = NewZeroWrapNolimit(1, n); - if (BIGDECIMAL_NEGATIVE_P(x)) { - if (is_integer(vexp)) { - if (is_even(vexp)) { - /* (-0) ** (-even_integer) -> Infinity */ - VpSetPosInf(y); - } - else { - /* (-0) ** (-odd_integer) -> -Infinity */ - VpSetNegInf(y); - } - } - else { - /* (-0) ** (-non_integer) -> Infinity */ - VpSetPosInf(y); - } - } - else { - /* (+0) ** (-num) -> Infinity */ - VpSetPosInf(y); - } - RB_GC_GUARD(y->obj); - return VpCheckGetValue(y); - } - else if (is_zero(vexp)) { - return VpCheckGetValue(NewOneWrapLimited(1, n)); - } - else { - return VpCheckGetValue(NewZeroWrapLimited(1, n)); - } - } - - if (is_zero(vexp)) { - return VpCheckGetValue(NewOneWrapLimited(1, n)); - } - else if (is_one(vexp)) { - return self; - } - - if (VpIsInf(x)) { - if (is_negative(vexp)) { - if (BIGDECIMAL_NEGATIVE_P(x)) { - if (is_integer(vexp)) { - if (is_even(vexp)) { - /* (-Infinity) ** (-even_integer) -> +0 */ - return VpCheckGetValue(NewZeroWrapLimited(1, n)); - } - else { - /* (-Infinity) ** (-odd_integer) -> -0 */ - return VpCheckGetValue(NewZeroWrapLimited(-1, n)); - } - } - else { - /* (-Infinity) ** (-non_integer) -> -0 */ - return VpCheckGetValue(NewZeroWrapLimited(-1, n)); - } - } - else { - return VpCheckGetValue(NewZeroWrapLimited(1, n)); - } - } - else { - y = NewZeroWrapLimited(1, n); - if (BIGDECIMAL_NEGATIVE_P(x)) { - if (is_integer(vexp)) { - if (is_even(vexp)) { - VpSetPosInf(y); - } - else { - VpSetNegInf(y); - } - } - else { - /* TODO: support complex */ - rb_raise(rb_eMathDomainError, - "a non-integral exponent for a negative base"); - } - } - else { - VpSetPosInf(y); - } - return VpCheckGetValue(y); - } - } - - if (exp != NULL) { - return bigdecimal_power_by_bigdecimal(x, exp, n); - } - else if (RB_TYPE_P(vexp, T_BIGNUM)) { - VALUE abs_value = BigDecimal_abs(self); - if (is_one(abs_value)) { - return VpCheckGetValue(NewOneWrapLimited(1, n)); - } - else if (RTEST(rb_funcall(abs_value, '<', 1, INT2FIX(1)))) { - if (is_negative(vexp)) { - y = NewZeroWrapLimited(1, n); - VpSetInf(y, (is_even(vexp) ? 1 : -1) * VpGetSign(x)); - return VpCheckGetValue(y); - } - else if (BIGDECIMAL_NEGATIVE_P(x) && is_even(vexp)) { - return VpCheckGetValue(NewZeroWrapLimited(-1, n)); - } - else { - return VpCheckGetValue(NewZeroWrapLimited(1, n)); - } - } - else { - if (is_positive(vexp)) { - y = NewZeroWrapLimited(1, n); - VpSetInf(y, (is_even(vexp) ? 1 : -1) * VpGetSign(x)); - return VpCheckGetValue(y); - } - else if (BIGDECIMAL_NEGATIVE_P(x) && is_even(vexp)) { - return VpCheckGetValue(NewZeroWrapLimited(-1, n)); - } - else { - return VpCheckGetValue(NewZeroWrapLimited(1, n)); - } - } - } - - int_exp = FIX2LONG(vexp); - ma = int_exp; - if (ma < 0) ma = -ma; - if (ma == 0) ma = 1; - - if (VpIsDef(x)) { - mp = x->Prec * (VpBaseFig() + 1); - GUARD_OBJ(y, NewZeroWrapLimited(1, mp * (ma + 1))); - } - else { - GUARD_OBJ(y, NewZeroWrapLimited(1, 1)); - } - VpPowerByInt(y, x, int_exp); - if (!NIL_P(prec) && VpIsDef(y)) { - VpMidRound(y, VpGetRoundMode(), n); - } - return VpCheckGetValue(y); -} - -/* call-seq: - * self ** other -> bigdecimal - * - * Returns the \BigDecimal value of +self+ raised to power +other+: - * - * b = BigDecimal('3.14') - * b ** 2 # => 0.98596e1 - * b ** 2.0 # => 0.98596e1 - * b ** Rational(2, 1) # => 0.98596e1 - * - * Related: BigDecimal#power. - * - */ -static VALUE -BigDecimal_power_op(VALUE self, VALUE exp) -{ - return BigDecimal_power(1, &exp, self); -} - -/* :nodoc: - * - * private method for dup and clone the provided BigDecimal +other+ - */ -static VALUE -BigDecimal_initialize_copy(VALUE self, VALUE other) -{ - Real *pv = rb_check_typeddata(self, &BigDecimal_data_type); - Real *x = rb_check_typeddata(other, &BigDecimal_data_type); - - if (self != other) { - DATA_PTR(self) = VpCopy(pv, x); - } - return self; -} - -static VALUE -BigDecimal_clone(VALUE self) -{ - return self; -} - -#ifdef HAVE_RB_OPTS_EXCEPTION_P -int rb_opts_exception_p(VALUE opts, int default_value); -#define opts_exception_p(opts) rb_opts_exception_p((opts), 1) -#else -static int -opts_exception_p(VALUE opts) -{ - static ID kwds[1]; - VALUE exception; - if (!kwds[0]) { - kwds[0] = rb_intern_const("exception"); - } - if (!rb_get_kwargs(opts, kwds, 0, 1, &exception)) return 1; - switch (exception) { - case Qtrue: case Qfalse: - break; - default: - rb_raise(rb_eArgError, "true or false is expected as exception: %+"PRIsVALUE, - exception); - } - return exception != Qfalse; -} -#endif - -static VALUE -check_exception(VALUE bd) -{ - assert(is_kind_of_BigDecimal(bd)); - - Real *vp; - TypedData_Get_Struct(bd, Real, &BigDecimal_data_type, vp); - VpCheckGetValue(vp); /* VpCheckGetValue performs exception check */ - - return bd; -} - -static VALUE -rb_uint64_convert_to_BigDecimal(uint64_t uval, RB_UNUSED_VAR(size_t digs), int raise_exception) -{ - VALUE obj = TypedData_Wrap_Struct(rb_cBigDecimal, &BigDecimal_data_type, 0); - - Real *vp; - if (uval == 0) { - vp = rbd_allocate_struct(1); - vp->MaxPrec = 1; - vp->Prec = 1; - vp->exponent = 1; - VpSetZero(vp, 1); - vp->frac[0] = 0; - } - else if (uval < BASE) { - vp = rbd_allocate_struct(1); - vp->MaxPrec = 1; - vp->Prec = 1; - vp->exponent = 1; - VpSetSign(vp, 1); - vp->frac[0] = (DECDIG)uval; - } - else { - DECDIG buf[BIGDECIMAL_INT64_MAX_LENGTH] = {0,}; - DECDIG r = uval % BASE; - size_t len = 0, ntz = 0; - if (r == 0) { - // Count and skip trailing zeros - for (; r == 0 && uval > 0; ++ntz) { - uval /= BASE; - r = uval % BASE; - } - } - for (; uval > 0; ++len) { - // Store digits - buf[BIGDECIMAL_INT64_MAX_LENGTH - len - 1] = r; - uval /= BASE; - r = uval % BASE; - } - - const size_t exp = len + ntz; - vp = rbd_allocate_struct(len); - vp->MaxPrec = len; - vp->Prec = len; - vp->exponent = exp; - VpSetSign(vp, 1); - MEMCPY(vp->frac, buf + BIGDECIMAL_INT64_MAX_LENGTH - len, DECDIG, len); - } - - return BigDecimal_wrap_struct(obj, vp); -} - -static VALUE -rb_int64_convert_to_BigDecimal(int64_t ival, size_t digs, int raise_exception) -{ - const uint64_t uval = (ival < 0) ? (((uint64_t)-(ival+1))+1) : (uint64_t)ival; - VALUE bd = rb_uint64_convert_to_BigDecimal(uval, digs, raise_exception); - if (ival < 0) { - Real *vp; - TypedData_Get_Struct(bd, Real, &BigDecimal_data_type, vp); - VpSetSign(vp, -1); - } - return bd; -} - -static VALUE -rb_big_convert_to_BigDecimal(VALUE val, RB_UNUSED_VAR(size_t digs), int raise_exception) -{ - assert(RB_TYPE_P(val, T_BIGNUM)); - - int leading_zeros; - size_t size = rb_absint_size(val, &leading_zeros); - int sign = FIX2INT(rb_big_cmp(val, INT2FIX(0))); - if (sign < 0 && leading_zeros == 0) { - size += 1; - } - if (size <= sizeof(long)) { - if (sign < 0) { - return rb_int64_convert_to_BigDecimal(NUM2LONG(val), digs, raise_exception); - } - else { - return rb_uint64_convert_to_BigDecimal(NUM2ULONG(val), digs, raise_exception); - } - } -#if defined(SIZEOF_LONG_LONG) && SIZEOF_LONG < SIZEOF_LONG_LONG - else if (size <= sizeof(LONG_LONG)) { - if (sign < 0) { - return rb_int64_convert_to_BigDecimal(NUM2LL(val), digs, raise_exception); - } - else { - return rb_uint64_convert_to_BigDecimal(NUM2ULL(val), digs, raise_exception); - } - } -#endif - else { - VALUE str = rb_big2str(val, 10); - Real *vp = VpCreateRbObject(RSTRING_LEN(str) + BASE_FIG + 1, - RSTRING_PTR(str), true); - RB_GC_GUARD(str); - return check_exception(vp->obj); - } -} - -static VALUE -rb_inum_convert_to_BigDecimal(VALUE val, RB_UNUSED_VAR(size_t digs), int raise_exception) -{ - assert(RB_INTEGER_TYPE_P(val)); - if (FIXNUM_P(val)) { - return rb_int64_convert_to_BigDecimal(FIX2LONG(val), digs, raise_exception); - } - else { - return rb_big_convert_to_BigDecimal(val, digs, raise_exception); - } -} - -static VALUE -rb_float_convert_to_BigDecimal(VALUE val, size_t digs, int raise_exception) -{ - assert(RB_FLOAT_TYPE_P(val)); - - double d = RFLOAT_VALUE(val); - - if (isnan(d)) { - VALUE obj = BigDecimal_nan(); - return check_exception(obj); - } - else if (isinf(d)) { - VALUE obj; - if (d > 0) { - obj = BigDecimal_positive_infinity(); - } - else { - obj = BigDecimal_negative_infinity(); - } - return check_exception(obj); - } - else if (d == 0.0) { - if (1/d < 0.0) { - return BigDecimal_negative_zero(); - } - else { - return BigDecimal_positive_zero(); - } - } - - if (digs == SIZE_MAX) { - if (!raise_exception) - return Qnil; - rb_raise(rb_eArgError, - "can't omit precision for a %"PRIsVALUE".", - CLASS_OF(val)); - } - else if (digs > BIGDECIMAL_DOUBLE_FIGURES) { - if (!raise_exception) - return Qnil; - rb_raise(rb_eArgError, "precision too large."); - } - - /* Use the same logic in flo_to_s to convert a float to a decimal string */ - char buf[BIGDECIMAL_DOUBLE_FIGURES + BASE_FIG + 2 + 1]; /* sizeof(buf) == 28 in the typical case */ - int decpt, negative_p; - char *e; - const int mode = digs == 0 ? 0 : 2; - char *p = BigDecimal_dtoa(d, mode, (int)digs, &decpt, &negative_p, &e); - int len10 = (int)(e - p); - if (len10 > BIGDECIMAL_DOUBLE_FIGURES) { - /* TODO: Presumably, rounding should be done here. */ - len10 = BIGDECIMAL_DOUBLE_FIGURES; - } - memcpy(buf, p, len10); - xfree(p); - - VALUE inum; - size_t RB_UNUSED_VAR(prec) = 0; - SIGNED_VALUE exp = 0; - if (decpt > 0) { - if (decpt < len10) { - /* - * len10 |---------------| - * : |-------| frac_len10 = len10 - decpt - * decpt |-------| |--| ntz10 = BASE_FIG - frac_len10 % BASE_FIG - * : : : - * 00 dd dddd.dddd dd 00 - * prec |-----.----.----.-----| prec = exp + roomof(frac_len, BASE_FIG) - * exp |-----.----| exp = roomof(decpt, BASE_FIG) - */ - const size_t frac_len10 = len10 - decpt; - const size_t ntz10 = BASE_FIG - frac_len10 % BASE_FIG; - memset(buf + len10, '0', ntz10); - buf[len10 + ntz10] = '\0'; - inum = rb_cstr_to_inum(buf, 10, false); - - exp = roomof(decpt, BASE_FIG); - prec = exp + roomof(frac_len10, BASE_FIG); - } - else { - /* - * decpt |-----------------------| - * len10 |----------| : - * : |------------| exp10 - * : : : - * 00 dd dddd dd 00 0000 0000.0 - * : : : : - * : |--| ntz10 = exp10 % BASE_FIG - * prec |-----.----.-----| : - * : |----.----| exp10 / BASE_FIG - * exp |-----.----.-----.----.----| - */ - const size_t exp10 = decpt - len10; - const size_t ntz10 = exp10 % BASE_FIG; - - memset(buf + len10, '0', ntz10); - buf[len10 + ntz10] = '\0'; - inum = rb_cstr_to_inum(buf, 10, false); - - prec = roomof(len10 + ntz10, BASE_FIG); - exp = prec + exp10 / BASE_FIG; - } - } - else if (decpt == 0) { - /* - * len10 |------------| - * : : - * 0.dddd dddd dd 00 - * : : : - * : |--| ntz10 = prec * BASE_FIG - len10 - * prec |----.----.-----| roomof(len10, BASE_FIG) - */ - prec = roomof(len10, BASE_FIG); - const size_t ntz10 = prec * BASE_FIG - len10; - - memset(buf + len10, '0', ntz10); - buf[len10 + ntz10] = '\0'; - inum = rb_cstr_to_inum(buf, 10, false); - } - else { - /* - * len10 |---------------| - * : : - * decpt |-------| |--| ntz10 = prec * BASE_FIG - nlz10 - len10 - * : : : - * 0.0000 00 dd dddd dddd dd 00 - * : : : - * nlz10 |--| : decpt % BASE_FIG - * prec |-----.----.----.-----| roomof(decpt + len10, BASE_FIG) - exp - * exp |----| decpt / BASE_FIG - */ - decpt = -decpt; - - const size_t nlz10 = decpt % BASE_FIG; - exp = decpt / BASE_FIG; - prec = roomof(decpt + len10, BASE_FIG) - exp; - const size_t ntz10 = prec * BASE_FIG - nlz10 - len10; - - if (nlz10 > 0) { - memmove(buf + nlz10, buf, len10); - memset(buf, '0', nlz10); - } - memset(buf + nlz10 + len10, '0', ntz10); - buf[nlz10 + len10 + ntz10] = '\0'; - inum = rb_cstr_to_inum(buf, 10, false); - - exp = -exp; - } - - VALUE bd = rb_inum_convert_to_BigDecimal(inum, SIZE_MAX, raise_exception); - Real *vp; - TypedData_Get_Struct(bd, Real, &BigDecimal_data_type, vp); - assert(vp->Prec == prec); - vp->exponent = exp; - - if (negative_p) VpSetSign(vp, -1); - return bd; -} - -static VALUE -rb_rational_convert_to_BigDecimal(VALUE val, size_t digs, int raise_exception) -{ - assert(RB_TYPE_P(val, T_RATIONAL)); - - if (digs == SIZE_MAX) { - if (!raise_exception) - return Qnil; - rb_raise(rb_eArgError, - "can't omit precision for a %"PRIsVALUE".", - CLASS_OF(val)); - } - - VALUE num = rb_inum_convert_to_BigDecimal(rb_rational_num(val), 0, raise_exception); - VALUE d = BigDecimal_div2(num, rb_rational_den(val), SIZET2NUM(digs)); - return d; -} - -static VALUE -rb_cstr_convert_to_BigDecimal(const char *c_str, size_t digs, int raise_exception) -{ - if (digs == SIZE_MAX) - digs = 0; - - Real *vp = VpCreateRbObject(digs, c_str, raise_exception); - if (!vp) - return Qnil; - return VpCheckGetValue(vp); -} - -static inline VALUE -rb_str_convert_to_BigDecimal(VALUE val, size_t digs, int raise_exception) -{ - const char *c_str = StringValueCStr(val); - return rb_cstr_convert_to_BigDecimal(c_str, digs, raise_exception); -} - -static VALUE -rb_convert_to_BigDecimal(VALUE val, size_t digs, int raise_exception) -{ - switch (val) { - case Qnil: - case Qtrue: - case Qfalse: - if (raise_exception) { - const char *cname = NIL_P(val) ? "nil" : - val == Qtrue ? "true" : - val == Qfalse ? "false" : - NULL; - rb_raise(rb_eTypeError, - "can't convert %s into BigDecimal", cname); - } - return Qnil; - - default: - break; - } - - if (is_kind_of_BigDecimal(val)) { - if (digs == SIZE_MAX) - return check_exception(val); - - Real *vp; - TypedData_Get_Struct(val, Real, &BigDecimal_data_type, vp); - - VALUE copy = TypedData_Wrap_Struct(rb_cBigDecimal, &BigDecimal_data_type, 0); - vp = VpCopy(NULL, vp); - /* TODO: rounding */ - BigDecimal_wrap_struct(copy, vp); - return VpCheckGetValue(vp); - } - else if (RB_INTEGER_TYPE_P(val)) { - return rb_inum_convert_to_BigDecimal(val, digs, raise_exception); - } - else if (RB_FLOAT_TYPE_P(val)) { - return rb_float_convert_to_BigDecimal(val, digs, raise_exception); - } - else if (RB_TYPE_P(val, T_RATIONAL)) { - return rb_rational_convert_to_BigDecimal(val, digs, raise_exception); - } - else if (RB_TYPE_P(val, T_COMPLEX)) { - VALUE im = rb_complex_imag(val); - if (!is_zero(im)) { - /* TODO: handle raise_exception */ - rb_raise(rb_eArgError, - "Unable to make a BigDecimal from non-zero imaginary number"); - } - return rb_convert_to_BigDecimal(rb_complex_real(val), digs, raise_exception); - } - else if (RB_TYPE_P(val, T_STRING)) { - return rb_str_convert_to_BigDecimal(val, digs, raise_exception); - } - - /* TODO: chheck to_d */ - /* TODO: chheck to_int */ - - VALUE str = rb_check_convert_type(val, T_STRING, "String", "to_str"); - if (!RB_TYPE_P(str, T_STRING)) { - if (raise_exception) { - rb_raise(rb_eTypeError, - "can't convert %"PRIsVALUE" into BigDecimal", rb_obj_class(val)); - } - return Qnil; - } - return rb_str_convert_to_BigDecimal(str, digs, raise_exception); -} - -/* call-seq: - * BigDecimal(value, exception: true) -> bigdecimal - * BigDecimal(value, ndigits, exception: true) -> bigdecimal - * - * Returns the \BigDecimal converted from +value+ - * with a precision of +ndigits+ decimal digits. - * - * When +ndigits+ is less than the number of significant digits - * in the value, the result is rounded to that number of digits, - * according to the current rounding mode; see BigDecimal.mode. - * - * When +ndigits+ is 0, the number of digits to correctly represent a float number - * is determined automatically. - * - * Returns +value+ converted to a \BigDecimal, depending on the type of +value+: - * - * - Integer, Float, Rational, Complex, or BigDecimal: converted directly: - * - * # Integer, Complex, or BigDecimal value does not require ndigits; ignored if given. - * BigDecimal(2) # => 0.2e1 - * BigDecimal(Complex(2, 0)) # => 0.2e1 - * BigDecimal(BigDecimal(2)) # => 0.2e1 - * # Float or Rational value requires ndigits. - * BigDecimal(2.0, 0) # => 0.2e1 - * BigDecimal(Rational(2, 1), 0) # => 0.2e1 - * - * - String: converted by parsing if it contains an integer or floating-point literal; - * leading and trailing whitespace is ignored: - * - * # String does not require ndigits; ignored if given. - * BigDecimal('2') # => 0.2e1 - * BigDecimal('2.0') # => 0.2e1 - * BigDecimal('0.2e1') # => 0.2e1 - * BigDecimal(' 2.0 ') # => 0.2e1 - * - * - Other type that responds to method :to_str: - * first converted to a string, then converted to a \BigDecimal, as above. - * - * - Other type: - * - * - Raises an exception if keyword argument +exception+ is +true+. - * - Returns +nil+ if keyword argument +exception+ is +false+. - * - * Raises an exception if +value+ evaluates to a Float - * and +digits+ is larger than Float::DIG + 1. - * - */ -static VALUE -f_BigDecimal(int argc, VALUE *argv, VALUE self) -{ - VALUE val, digs_v, opts = Qnil; - argc = rb_scan_args(argc, argv, "11:", &val, &digs_v, &opts); - int exception = opts_exception_p(opts); - - size_t digs = SIZE_MAX; /* this means digs is omitted */ - if (argc > 1) { - digs_v = rb_to_int(digs_v); - if (FIXNUM_P(digs_v)) { - long n = FIX2LONG(digs_v); - if (n < 0) - goto negative_digs; - digs = (size_t)n; - } - else { - if (RBIGNUM_NEGATIVE_P(digs_v)) { - negative_digs: - if (!exception) - return Qnil; - rb_raise(rb_eArgError, "negative precision"); - } - digs = NUM2SIZET(digs_v); - } - } - - return rb_convert_to_BigDecimal(val, digs, exception); -} - -static VALUE -BigDecimal_s_interpret_loosely(VALUE klass, VALUE str) -{ - char const *c_str = StringValueCStr(str); - Real *vp = VpNewRbClass(0, c_str, klass, false, true); - if (!vp) - return Qnil; - else - return VpCheckGetValue(vp); -} - - /* call-seq: - * BigDecimal.limit(digits) - * - * Limit the number of significant digits in newly created BigDecimal - * numbers to the specified value. Rounding is performed as necessary, - * as specified by BigDecimal.mode. - * - * A limit of 0, the default, means no upper limit. - * - * The limit specified by this method takes less priority over any limit - * specified to instance methods such as ceil, floor, truncate, or round. - */ -static VALUE -BigDecimal_limit(int argc, VALUE *argv, VALUE self) -{ - VALUE nFig; - VALUE nCur = SIZET2NUM(VpGetPrecLimit()); - - if (rb_scan_args(argc, argv, "01", &nFig) == 1) { - int nf; - if (NIL_P(nFig)) return nCur; - nf = NUM2INT(nFig); - if (nf < 0) { - rb_raise(rb_eArgError, "argument must be positive"); - } - VpSetPrecLimit(nf); - } - return nCur; -} - -/* Returns the sign of the value. - * - * Returns a positive value if > 0, a negative value if < 0. - * It behaves the same with zeros - - * it returns a positive value for a positive zero (BigDecimal('0')) and - * a negative value for a negative zero (BigDecimal('-0')). - * - * The specific value returned indicates the type and sign of the BigDecimal, - * as follows: - * - * BigDecimal::SIGN_NaN:: value is Not a Number - * BigDecimal::SIGN_POSITIVE_ZERO:: value is +0 - * BigDecimal::SIGN_NEGATIVE_ZERO:: value is -0 - * BigDecimal::SIGN_POSITIVE_INFINITE:: value is +Infinity - * BigDecimal::SIGN_NEGATIVE_INFINITE:: value is -Infinity - * BigDecimal::SIGN_POSITIVE_FINITE:: value is positive - * BigDecimal::SIGN_NEGATIVE_FINITE:: value is negative - */ -static VALUE -BigDecimal_sign(VALUE self) -{ /* sign */ - int s = GetVpValue(self, 1)->sign; - return INT2FIX(s); -} - -/* - * call-seq: BigDecimal.save_exception_mode { ... } - * - * Execute the provided block, but preserve the exception mode - * - * BigDecimal.save_exception_mode do - * BigDecimal.mode(BigDecimal::EXCEPTION_OVERFLOW, false) - * BigDecimal.mode(BigDecimal::EXCEPTION_NaN, false) - * - * BigDecimal(BigDecimal('Infinity')) - * BigDecimal(BigDecimal('-Infinity')) - * BigDecimal(BigDecimal('NaN')) - * end - * - * For use with the BigDecimal::EXCEPTION_* - * - * See BigDecimal.mode - */ -static VALUE -BigDecimal_save_exception_mode(VALUE self) -{ - unsigned short const exception_mode = VpGetException(); - int state; - VALUE ret = rb_protect(rb_yield, Qnil, &state); - VpSetException(exception_mode); - if (state) rb_jump_tag(state); - return ret; -} - -/* - * call-seq: BigDecimal.save_rounding_mode { ... } - * - * Execute the provided block, but preserve the rounding mode - * - * BigDecimal.save_rounding_mode do - * BigDecimal.mode(BigDecimal::ROUND_MODE, :up) - * puts BigDecimal.mode(BigDecimal::ROUND_MODE) - * end - * - * For use with the BigDecimal::ROUND_* - * - * See BigDecimal.mode - */ -static VALUE -BigDecimal_save_rounding_mode(VALUE self) -{ - unsigned short const round_mode = VpGetRoundMode(); - int state; - VALUE ret = rb_protect(rb_yield, Qnil, &state); - VpSetRoundMode(round_mode); - if (state) rb_jump_tag(state); - return ret; -} - -/* - * call-seq: BigDecimal.save_limit { ... } - * - * Execute the provided block, but preserve the precision limit - * - * BigDecimal.limit(100) - * puts BigDecimal.limit - * BigDecimal.save_limit do - * BigDecimal.limit(200) - * puts BigDecimal.limit - * end - * puts BigDecimal.limit - * - */ -static VALUE -BigDecimal_save_limit(VALUE self) -{ - size_t const limit = VpGetPrecLimit(); - int state; - VALUE ret = rb_protect(rb_yield, Qnil, &state); - VpSetPrecLimit(limit); - if (state) rb_jump_tag(state); - return ret; -} - -/* call-seq: - * BigMath.exp(decimal, numeric) -> BigDecimal - * - * Computes the value of e (the base of natural logarithms) raised to the - * power of +decimal+, to the specified number of digits of precision. - * - * If +decimal+ is infinity, returns Infinity. - * - * If +decimal+ is NaN, returns NaN. - */ -static VALUE -BigMath_s_exp(VALUE klass, VALUE x, VALUE vprec) -{ - ssize_t prec, n, i; - Real* vx = NULL; - VALUE one, d, y; - int negative = 0; - int infinite = 0; - int nan = 0; - double flo; - - prec = NUM2SSIZET(vprec); - if (prec <= 0) { - rb_raise(rb_eArgError, "Zero or negative precision for exp"); - } - - /* TODO: the following switch statement is almost same as one in the - * BigDecimalCmp function. */ - switch (TYPE(x)) { - case T_DATA: - if (!is_kind_of_BigDecimal(x)) break; - vx = DATA_PTR(x); - negative = BIGDECIMAL_NEGATIVE_P(vx); - infinite = VpIsPosInf(vx) || VpIsNegInf(vx); - nan = VpIsNaN(vx); - break; - - case T_FIXNUM: - /* fall through */ - case T_BIGNUM: - vx = GetVpValue(x, 0); - break; - - case T_FLOAT: - flo = RFLOAT_VALUE(x); - negative = flo < 0; - infinite = isinf(flo); - nan = isnan(flo); - if (!infinite && !nan) { - vx = GetVpValueWithPrec(x, 0, 0); - } - break; - - case T_RATIONAL: - vx = GetVpValueWithPrec(x, prec, 0); - break; - - default: - break; - } - if (infinite) { - if (negative) { - return VpCheckGetValue(GetVpValueWithPrec(INT2FIX(0), prec, 1)); - } - else { - Real* vy = NewZeroWrapNolimit(1, prec); - VpSetInf(vy, VP_SIGN_POSITIVE_INFINITE); - RB_GC_GUARD(vy->obj); - return VpCheckGetValue(vy); - } - } - else if (nan) { - Real* vy = NewZeroWrapNolimit(1, prec); - VpSetNaN(vy); - RB_GC_GUARD(vy->obj); - return VpCheckGetValue(vy); - } - else if (vx == NULL) { - cannot_be_coerced_into_BigDecimal(rb_eArgError, x); - } - x = vx->obj; - - n = prec + BIGDECIMAL_DOUBLE_FIGURES; - negative = BIGDECIMAL_NEGATIVE_P(vx); - if (negative) { - VALUE x_zero = INT2NUM(1); - VALUE x_copy = f_BigDecimal(1, &x_zero, klass); - x = BigDecimal_initialize_copy(x_copy, x); - vx = DATA_PTR(x); - VpSetSign(vx, 1); - } - - one = VpCheckGetValue(NewOneWrapLimited(1, 1)); - y = one; - d = y; - i = 1; - - while (!VpIsZero((Real*)DATA_PTR(d))) { - SIGNED_VALUE const ey = VpExponent10(DATA_PTR(y)); - SIGNED_VALUE const ed = VpExponent10(DATA_PTR(d)); - ssize_t m = n - vabs(ey - ed); - - rb_thread_check_ints(); - - if (m <= 0) { - break; - } - else if ((size_t)m < BIGDECIMAL_DOUBLE_FIGURES) { - m = BIGDECIMAL_DOUBLE_FIGURES; - } - - d = BigDecimal_mult(d, x); /* d <- d * x */ - d = BigDecimal_div2(d, SSIZET2NUM(i), SSIZET2NUM(m)); /* d <- d / i */ - y = BigDecimal_add(y, d); /* y <- y + d */ - ++i; /* i <- i + 1 */ - } - - if (negative) { - return BigDecimal_div2(one, y, vprec); - } - else { - vprec = SSIZET2NUM(prec - VpExponent10(DATA_PTR(y))); - return BigDecimal_round(1, &vprec, y); - } - - RB_GC_GUARD(one); - RB_GC_GUARD(x); - RB_GC_GUARD(y); - RB_GC_GUARD(d); -} - -/* call-seq: - * BigMath.log(decimal, numeric) -> BigDecimal - * - * Computes the natural logarithm of +decimal+ to the specified number of - * digits of precision, +numeric+. - * - * If +decimal+ is zero or negative, raises Math::DomainError. - * - * If +decimal+ is positive infinity, returns Infinity. - * - * If +decimal+ is NaN, returns NaN. - */ -static VALUE -BigMath_s_log(VALUE klass, VALUE x, VALUE vprec) -{ - ssize_t prec, n, i; - SIGNED_VALUE expo; - Real* vx = NULL; - VALUE vn, one, two, w, x2, y, d; - int zero = 0; - int negative = 0; - int infinite = 0; - int nan = 0; - double flo; - long fix; - - if (!is_integer(vprec)) { - rb_raise(rb_eArgError, "precision must be an Integer"); - } - - prec = NUM2SSIZET(vprec); - if (prec <= 0) { - rb_raise(rb_eArgError, "Zero or negative precision for exp"); - } - - /* TODO: the following switch statement is almost same as one in the - * BigDecimalCmp function. */ - switch (TYPE(x)) { - case T_DATA: - if (!is_kind_of_BigDecimal(x)) break; - vx = DATA_PTR(x); - zero = VpIsZero(vx); - negative = BIGDECIMAL_NEGATIVE_P(vx); - infinite = VpIsPosInf(vx) || VpIsNegInf(vx); - nan = VpIsNaN(vx); - break; - - case T_FIXNUM: - fix = FIX2LONG(x); - zero = fix == 0; - negative = fix < 0; - goto get_vp_value; - - case T_BIGNUM: - i = FIX2INT(rb_big_cmp(x, INT2FIX(0))); - zero = i == 0; - negative = i < 0; -get_vp_value: - if (zero || negative) break; - vx = GetVpValue(x, 0); - break; - - case T_FLOAT: - flo = RFLOAT_VALUE(x); - zero = flo == 0; - negative = flo < 0; - infinite = isinf(flo); - nan = isnan(flo); - if (!zero && !negative && !infinite && !nan) { - vx = GetVpValueWithPrec(x, 0, 1); - } - break; - - case T_RATIONAL: - zero = RRATIONAL_ZERO_P(x); - negative = RRATIONAL_NEGATIVE_P(x); - if (zero || negative) break; - vx = GetVpValueWithPrec(x, prec, 1); - break; - - case T_COMPLEX: - rb_raise(rb_eMathDomainError, - "Complex argument for BigMath.log"); - - default: - break; - } - if (infinite && !negative) { - Real *vy = NewZeroWrapNolimit(1, prec); - RB_GC_GUARD(vy->obj); - VpSetInf(vy, VP_SIGN_POSITIVE_INFINITE); - return VpCheckGetValue(vy); - } - else if (nan) { - Real* vy = NewZeroWrapNolimit(1, prec); - RB_GC_GUARD(vy->obj); - VpSetNaN(vy); - return VpCheckGetValue(vy); - } - else if (zero || negative) { - rb_raise(rb_eMathDomainError, - "Zero or negative argument for log"); - } - else if (vx == NULL) { - cannot_be_coerced_into_BigDecimal(rb_eArgError, x); - } - x = VpCheckGetValue(vx); - - one = VpCheckGetValue(NewOneWrapLimited(1, 1)); - two = VpCheckGetValue(VpCreateRbObject(1, "2", true)); - - n = prec + BIGDECIMAL_DOUBLE_FIGURES; - vn = SSIZET2NUM(n); - expo = VpExponent10(vx); - if (expo < 0 || expo >= 3) { - char buf[DECIMAL_SIZE_OF_BITS(SIZEOF_VALUE * CHAR_BIT) + 4]; - snprintf(buf, sizeof(buf), "1E%"PRIdVALUE, -expo); - x = BigDecimal_mult2(x, VpCheckGetValue(VpCreateRbObject(1, buf, true)), vn); - } - else { - expo = 0; - } - w = BigDecimal_sub(x, one); - x = BigDecimal_div2(w, BigDecimal_add(x, one), vn); - x2 = BigDecimal_mult2(x, x, vn); - y = x; - d = y; - i = 1; - while (!VpIsZero((Real*)DATA_PTR(d))) { - SIGNED_VALUE const ey = VpExponent10(DATA_PTR(y)); - SIGNED_VALUE const ed = VpExponent10(DATA_PTR(d)); - ssize_t m = n - vabs(ey - ed); - if (m <= 0) { - break; - } - else if ((size_t)m < BIGDECIMAL_DOUBLE_FIGURES) { - m = BIGDECIMAL_DOUBLE_FIGURES; - } - - x = BigDecimal_mult2(x2, x, vn); - i += 2; - d = BigDecimal_div2(x, SSIZET2NUM(i), SSIZET2NUM(m)); - y = BigDecimal_add(y, d); - } - - y = BigDecimal_mult(y, two); - if (expo != 0) { - VALUE log10, vexpo, dy; - log10 = BigMath_s_log(klass, INT2FIX(10), vprec); - vexpo = VpCheckGetValue(GetVpValue(SSIZET2NUM(expo), 1)); - dy = BigDecimal_mult(log10, vexpo); - y = BigDecimal_add(y, dy); - } - - RB_GC_GUARD(one); - RB_GC_GUARD(two); - RB_GC_GUARD(vn); - RB_GC_GUARD(x2); - RB_GC_GUARD(y); - RB_GC_GUARD(d); - - return y; -} - -static VALUE BIGDECIMAL_NAN = Qnil; - -static VALUE -BigDecimal_nan(void) -{ - return BIGDECIMAL_NAN; -} - -static VALUE BIGDECIMAL_POSITIVE_INFINITY = Qnil; - -static VALUE -BigDecimal_positive_infinity(void) -{ - return BIGDECIMAL_POSITIVE_INFINITY; -} - -static VALUE BIGDECIMAL_NEGATIVE_INFINITY = Qnil; - -static VALUE -BigDecimal_negative_infinity(void) -{ - return BIGDECIMAL_NEGATIVE_INFINITY; -} - -static VALUE BIGDECIMAL_POSITIVE_ZERO = Qnil; - -static VALUE -BigDecimal_positive_zero(void) -{ - return BIGDECIMAL_POSITIVE_ZERO; -} - -static VALUE BIGDECIMAL_NEGATIVE_ZERO = Qnil; - -static VALUE -BigDecimal_negative_zero(void) -{ - return BIGDECIMAL_NEGATIVE_ZERO; -} - -/* Document-class: BigDecimal - * BigDecimal provides arbitrary-precision floating point decimal arithmetic. - * - * == Introduction - * - * Ruby provides built-in support for arbitrary precision integer arithmetic. - * - * For example: - * - * 42**13 #=> 1265437718438866624512 - * - * BigDecimal provides similar support for very large or very accurate floating - * point numbers. - * - * Decimal arithmetic is also useful for general calculation, because it - * provides the correct answers people expect--whereas normal binary floating - * point arithmetic often introduces subtle errors because of the conversion - * between base 10 and base 2. - * - * For example, try: - * - * sum = 0 - * 10_000.times do - * sum = sum + 0.0001 - * end - * print sum #=> 0.9999999999999062 - * - * and contrast with the output from: - * - * require 'bigdecimal' - * - * sum = BigDecimal("0") - * 10_000.times do - * sum = sum + BigDecimal("0.0001") - * end - * print sum #=> 0.1E1 - * - * Similarly: - * - * (BigDecimal("1.2") - BigDecimal("1.0")) == BigDecimal("0.2") #=> true - * - * (1.2 - 1.0) == 0.2 #=> false - * - * == A Note About Precision - * - * For a calculation using a \BigDecimal and another +value+, - * the precision of the result depends on the type of +value+: - * - * - If +value+ is a \Float, - * the precision is Float::DIG + 1. - * - If +value+ is a \Rational, the precision is larger than Float::DIG + 1. - * - If +value+ is a \BigDecimal, the precision is +value+'s precision in the - * internal representation, which is platform-dependent. - * - If +value+ is other object, the precision is determined by the result of +BigDecimal(value)+. - * - * == Special features of accurate decimal arithmetic - * - * Because BigDecimal is more accurate than normal binary floating point - * arithmetic, it requires some special values. - * - * === Infinity - * - * BigDecimal sometimes needs to return infinity, for example if you divide - * a value by zero. - * - * BigDecimal("1.0") / BigDecimal("0.0") #=> Infinity - * BigDecimal("-1.0") / BigDecimal("0.0") #=> -Infinity - * - * You can represent infinite numbers to BigDecimal using the strings - * 'Infinity', '+Infinity' and - * '-Infinity' (case-sensitive) - * - * === Not a Number - * - * When a computation results in an undefined value, the special value +NaN+ - * (for 'not a number') is returned. - * - * Example: - * - * BigDecimal("0.0") / BigDecimal("0.0") #=> NaN - * - * You can also create undefined values. - * - * NaN is never considered to be the same as any other value, even NaN itself: - * - * n = BigDecimal('NaN') - * n == 0.0 #=> false - * n == n #=> false - * - * === Positive and negative zero - * - * If a computation results in a value which is too small to be represented as - * a BigDecimal within the currently specified limits of precision, zero must - * be returned. - * - * If the value which is too small to be represented is negative, a BigDecimal - * value of negative zero is returned. - * - * BigDecimal("1.0") / BigDecimal("-Infinity") #=> -0.0 - * - * If the value is positive, a value of positive zero is returned. - * - * BigDecimal("1.0") / BigDecimal("Infinity") #=> 0.0 - * - * (See BigDecimal.mode for how to specify limits of precision.) - * - * Note that +-0.0+ and +0.0+ are considered to be the same for the purposes of - * comparison. - * - * Note also that in mathematics, there is no particular concept of negative - * or positive zero; true mathematical zero has no sign. - * - * == bigdecimal/util - * - * When you require +bigdecimal/util+, the #to_d method will be - * available on BigDecimal and the native Integer, Float, Rational, - * and String classes: - * - * require 'bigdecimal/util' - * - * 42.to_d # => 0.42e2 - * 0.5.to_d # => 0.5e0 - * (2/3r).to_d(3) # => 0.667e0 - * "0.5".to_d # => 0.5e0 - * - * == License - * - * Copyright (C) 2002 by Shigeo Kobayashi . - * - * BigDecimal is released under the Ruby and 2-clause BSD licenses. - * See LICENSE.txt for details. - * - * Maintained by mrkn and ruby-core members. - * - * Documented by zzak , mathew , and - * many other contributors. - */ -void -Init_bigdecimal(void) -{ -#ifdef HAVE_RB_EXT_RACTOR_SAFE - rb_ext_ractor_safe(true); -#endif - VALUE arg; - - id_BigDecimal_exception_mode = rb_intern_const("BigDecimal.exception_mode"); - id_BigDecimal_rounding_mode = rb_intern_const("BigDecimal.rounding_mode"); - id_BigDecimal_precision_limit = rb_intern_const("BigDecimal.precision_limit"); - - /* Initialize VP routines */ - VpInit(0UL); - - /* Class and method registration */ - rb_cBigDecimal = rb_define_class("BigDecimal", rb_cNumeric); - - /* Global function */ - rb_define_global_function("BigDecimal", f_BigDecimal, -1); - - /* Class methods */ - rb_undef_alloc_func(rb_cBigDecimal); - rb_undef_method(CLASS_OF(rb_cBigDecimal), "new"); - rb_define_singleton_method(rb_cBigDecimal, "interpret_loosely", BigDecimal_s_interpret_loosely, 1); - rb_define_singleton_method(rb_cBigDecimal, "mode", BigDecimal_mode, -1); - rb_define_singleton_method(rb_cBigDecimal, "limit", BigDecimal_limit, -1); - rb_define_singleton_method(rb_cBigDecimal, "double_fig", BigDecimal_double_fig, 0); - rb_define_singleton_method(rb_cBigDecimal, "_load", BigDecimal_load, 1); - - rb_define_singleton_method(rb_cBigDecimal, "save_exception_mode", BigDecimal_save_exception_mode, 0); - rb_define_singleton_method(rb_cBigDecimal, "save_rounding_mode", BigDecimal_save_rounding_mode, 0); - rb_define_singleton_method(rb_cBigDecimal, "save_limit", BigDecimal_save_limit, 0); - - /* Constants definition */ - - /* - * The version of bigdecimal library - */ - rb_define_const(rb_cBigDecimal, "VERSION", rb_str_new2(BIGDECIMAL_VERSION)); - - /* - * Base value used in internal calculations. On a 32 bit system, BASE - * is 10000, indicating that calculation is done in groups of 4 digits. - * (If it were larger, BASE**2 wouldn't fit in 32 bits, so you couldn't - * guarantee that two groups could always be multiplied together without - * overflow.) - */ - rb_define_const(rb_cBigDecimal, "BASE", INT2FIX((SIGNED_VALUE)VpBaseVal())); - - /* Exceptions */ - - /* - * 0xff: Determines whether overflow, underflow or zero divide result in - * an exception being thrown. See BigDecimal.mode. - */ - rb_define_const(rb_cBigDecimal, "EXCEPTION_ALL", INT2FIX(VP_EXCEPTION_ALL)); - - /* - * 0x02: Determines what happens when the result of a computation is not a - * number (NaN). See BigDecimal.mode. - */ - rb_define_const(rb_cBigDecimal, "EXCEPTION_NaN", INT2FIX(VP_EXCEPTION_NaN)); - - /* - * 0x01: Determines what happens when the result of a computation is - * infinity. See BigDecimal.mode. - */ - rb_define_const(rb_cBigDecimal, "EXCEPTION_INFINITY", INT2FIX(VP_EXCEPTION_INFINITY)); - - /* - * 0x04: Determines what happens when the result of a computation is an - * underflow (a result too small to be represented). See BigDecimal.mode. - */ - rb_define_const(rb_cBigDecimal, "EXCEPTION_UNDERFLOW", INT2FIX(VP_EXCEPTION_UNDERFLOW)); - - /* - * 0x01: Determines what happens when the result of a computation is an - * overflow (a result too large to be represented). See BigDecimal.mode. - */ - rb_define_const(rb_cBigDecimal, "EXCEPTION_OVERFLOW", INT2FIX(VP_EXCEPTION_OVERFLOW)); - - /* - * 0x10: Determines what happens when a division by zero is performed. - * See BigDecimal.mode. - */ - rb_define_const(rb_cBigDecimal, "EXCEPTION_ZERODIVIDE", INT2FIX(VP_EXCEPTION_ZERODIVIDE)); - - /* - * 0x100: Determines what happens when a result must be rounded in order to - * fit in the appropriate number of significant digits. See - * BigDecimal.mode. - */ - rb_define_const(rb_cBigDecimal, "ROUND_MODE", INT2FIX(VP_ROUND_MODE)); - - /* 1: Indicates that values should be rounded away from zero. See - * BigDecimal.mode. - */ - rb_define_const(rb_cBigDecimal, "ROUND_UP", INT2FIX(VP_ROUND_UP)); - - /* 2: Indicates that values should be rounded towards zero. See - * BigDecimal.mode. - */ - rb_define_const(rb_cBigDecimal, "ROUND_DOWN", INT2FIX(VP_ROUND_DOWN)); - - /* 3: Indicates that digits >= 5 should be rounded up, others rounded down. - * See BigDecimal.mode. */ - rb_define_const(rb_cBigDecimal, "ROUND_HALF_UP", INT2FIX(VP_ROUND_HALF_UP)); - - /* 4: Indicates that digits >= 6 should be rounded up, others rounded down. - * See BigDecimal.mode. - */ - rb_define_const(rb_cBigDecimal, "ROUND_HALF_DOWN", INT2FIX(VP_ROUND_HALF_DOWN)); - /* 5: Round towards +Infinity. See BigDecimal.mode. */ - rb_define_const(rb_cBigDecimal, "ROUND_CEILING", INT2FIX(VP_ROUND_CEIL)); - - /* 6: Round towards -Infinity. See BigDecimal.mode. */ - rb_define_const(rb_cBigDecimal, "ROUND_FLOOR", INT2FIX(VP_ROUND_FLOOR)); - - /* 7: Round towards the even neighbor. See BigDecimal.mode. */ - rb_define_const(rb_cBigDecimal, "ROUND_HALF_EVEN", INT2FIX(VP_ROUND_HALF_EVEN)); - - /* 0: Indicates that a value is not a number. See BigDecimal.sign. */ - rb_define_const(rb_cBigDecimal, "SIGN_NaN", INT2FIX(VP_SIGN_NaN)); - - /* 1: Indicates that a value is +0. See BigDecimal.sign. */ - rb_define_const(rb_cBigDecimal, "SIGN_POSITIVE_ZERO", INT2FIX(VP_SIGN_POSITIVE_ZERO)); - - /* -1: Indicates that a value is -0. See BigDecimal.sign. */ - rb_define_const(rb_cBigDecimal, "SIGN_NEGATIVE_ZERO", INT2FIX(VP_SIGN_NEGATIVE_ZERO)); - - /* 2: Indicates that a value is positive and finite. See BigDecimal.sign. */ - rb_define_const(rb_cBigDecimal, "SIGN_POSITIVE_FINITE", INT2FIX(VP_SIGN_POSITIVE_FINITE)); - - /* -2: Indicates that a value is negative and finite. See BigDecimal.sign. */ - rb_define_const(rb_cBigDecimal, "SIGN_NEGATIVE_FINITE", INT2FIX(VP_SIGN_NEGATIVE_FINITE)); - - /* 3: Indicates that a value is positive and infinite. See BigDecimal.sign. */ - rb_define_const(rb_cBigDecimal, "SIGN_POSITIVE_INFINITE", INT2FIX(VP_SIGN_POSITIVE_INFINITE)); - - /* -3: Indicates that a value is negative and infinite. See BigDecimal.sign. */ - rb_define_const(rb_cBigDecimal, "SIGN_NEGATIVE_INFINITE", INT2FIX(VP_SIGN_NEGATIVE_INFINITE)); - - /* Positive zero value. */ - arg = rb_str_new2("+0"); - BIGDECIMAL_POSITIVE_ZERO = f_BigDecimal(1, &arg, rb_cBigDecimal); - rb_gc_register_mark_object(BIGDECIMAL_POSITIVE_ZERO); - - /* Negative zero value. */ - arg = rb_str_new2("-0"); - BIGDECIMAL_NEGATIVE_ZERO = f_BigDecimal(1, &arg, rb_cBigDecimal); - rb_gc_register_mark_object(BIGDECIMAL_NEGATIVE_ZERO); - - /* Positive infinity value. */ - arg = rb_str_new2("+Infinity"); - BIGDECIMAL_POSITIVE_INFINITY = f_BigDecimal(1, &arg, rb_cBigDecimal); - rb_gc_register_mark_object(BIGDECIMAL_POSITIVE_INFINITY); - - /* Negative infinity value. */ - arg = rb_str_new2("-Infinity"); - BIGDECIMAL_NEGATIVE_INFINITY = f_BigDecimal(1, &arg, rb_cBigDecimal); - rb_gc_register_mark_object(BIGDECIMAL_NEGATIVE_INFINITY); - - /* 'Not a Number' value. */ - arg = rb_str_new2("NaN"); - BIGDECIMAL_NAN = f_BigDecimal(1, &arg, rb_cBigDecimal); - rb_gc_register_mark_object(BIGDECIMAL_NAN); - - /* Special value constants */ - rb_define_const(rb_cBigDecimal, "INFINITY", BIGDECIMAL_POSITIVE_INFINITY); - rb_define_const(rb_cBigDecimal, "NAN", BIGDECIMAL_NAN); - - /* instance methods */ - rb_define_method(rb_cBigDecimal, "precs", BigDecimal_prec, 0); - rb_define_method(rb_cBigDecimal, "precision", BigDecimal_precision, 0); - rb_define_method(rb_cBigDecimal, "scale", BigDecimal_scale, 0); - rb_define_method(rb_cBigDecimal, "precision_scale", BigDecimal_precision_scale, 0); - rb_define_method(rb_cBigDecimal, "n_significant_digits", BigDecimal_n_significant_digits, 0); - - rb_define_method(rb_cBigDecimal, "add", BigDecimal_add2, 2); - rb_define_method(rb_cBigDecimal, "sub", BigDecimal_sub2, 2); - rb_define_method(rb_cBigDecimal, "mult", BigDecimal_mult2, 2); - rb_define_method(rb_cBigDecimal, "div", BigDecimal_div3, -1); - rb_define_method(rb_cBigDecimal, "hash", BigDecimal_hash, 0); - rb_define_method(rb_cBigDecimal, "to_s", BigDecimal_to_s, -1); - rb_define_method(rb_cBigDecimal, "to_i", BigDecimal_to_i, 0); - rb_define_method(rb_cBigDecimal, "to_int", BigDecimal_to_i, 0); - rb_define_method(rb_cBigDecimal, "to_r", BigDecimal_to_r, 0); - rb_define_method(rb_cBigDecimal, "split", BigDecimal_split, 0); - rb_define_method(rb_cBigDecimal, "+", BigDecimal_add, 1); - rb_define_method(rb_cBigDecimal, "-", BigDecimal_sub, 1); - rb_define_method(rb_cBigDecimal, "+@", BigDecimal_uplus, 0); - rb_define_method(rb_cBigDecimal, "-@", BigDecimal_neg, 0); - rb_define_method(rb_cBigDecimal, "*", BigDecimal_mult, 1); - rb_define_method(rb_cBigDecimal, "/", BigDecimal_div, 1); - rb_define_method(rb_cBigDecimal, "quo", BigDecimal_quo, -1); - rb_define_method(rb_cBigDecimal, "%", BigDecimal_mod, 1); - rb_define_method(rb_cBigDecimal, "modulo", BigDecimal_mod, 1); - rb_define_method(rb_cBigDecimal, "remainder", BigDecimal_remainder, 1); - rb_define_method(rb_cBigDecimal, "divmod", BigDecimal_divmod, 1); - rb_define_method(rb_cBigDecimal, "clone", BigDecimal_clone, 0); - rb_define_method(rb_cBigDecimal, "dup", BigDecimal_clone, 0); - rb_define_method(rb_cBigDecimal, "to_f", BigDecimal_to_f, 0); - rb_define_method(rb_cBigDecimal, "abs", BigDecimal_abs, 0); - rb_define_method(rb_cBigDecimal, "sqrt", BigDecimal_sqrt, 1); - rb_define_method(rb_cBigDecimal, "fix", BigDecimal_fix, 0); - rb_define_method(rb_cBigDecimal, "round", BigDecimal_round, -1); - rb_define_method(rb_cBigDecimal, "frac", BigDecimal_frac, 0); - rb_define_method(rb_cBigDecimal, "floor", BigDecimal_floor, -1); - rb_define_method(rb_cBigDecimal, "ceil", BigDecimal_ceil, -1); - rb_define_method(rb_cBigDecimal, "power", BigDecimal_power, -1); - rb_define_method(rb_cBigDecimal, "**", BigDecimal_power_op, 1); - rb_define_method(rb_cBigDecimal, "<=>", BigDecimal_comp, 1); - rb_define_method(rb_cBigDecimal, "==", BigDecimal_eq, 1); - rb_define_method(rb_cBigDecimal, "===", BigDecimal_eq, 1); - rb_define_method(rb_cBigDecimal, "eql?", BigDecimal_eq, 1); - rb_define_method(rb_cBigDecimal, "<", BigDecimal_lt, 1); - rb_define_method(rb_cBigDecimal, "<=", BigDecimal_le, 1); - rb_define_method(rb_cBigDecimal, ">", BigDecimal_gt, 1); - rb_define_method(rb_cBigDecimal, ">=", BigDecimal_ge, 1); - rb_define_method(rb_cBigDecimal, "zero?", BigDecimal_zero, 0); - rb_define_method(rb_cBigDecimal, "nonzero?", BigDecimal_nonzero, 0); - rb_define_method(rb_cBigDecimal, "coerce", BigDecimal_coerce, 1); - rb_define_method(rb_cBigDecimal, "inspect", BigDecimal_inspect, 0); - rb_define_method(rb_cBigDecimal, "exponent", BigDecimal_exponent, 0); - rb_define_method(rb_cBigDecimal, "sign", BigDecimal_sign, 0); - rb_define_method(rb_cBigDecimal, "nan?", BigDecimal_IsNaN, 0); - rb_define_method(rb_cBigDecimal, "infinite?", BigDecimal_IsInfinite, 0); - rb_define_method(rb_cBigDecimal, "finite?", BigDecimal_IsFinite, 0); - rb_define_method(rb_cBigDecimal, "truncate", BigDecimal_truncate, -1); - rb_define_method(rb_cBigDecimal, "_dump", BigDecimal_dump, -1); - - rb_mBigMath = rb_define_module("BigMath"); - rb_define_singleton_method(rb_mBigMath, "exp", BigMath_s_exp, 2); - rb_define_singleton_method(rb_mBigMath, "log", BigMath_s_log, 2); - -#define ROUNDING_MODE(i, name, value) \ - id_##name = rb_intern_const(#name); \ - rbd_rounding_modes[i].id = id_##name; \ - rbd_rounding_modes[i].mode = value; - - ROUNDING_MODE(0, up, RBD_ROUND_UP); - ROUNDING_MODE(1, down, RBD_ROUND_DOWN); - ROUNDING_MODE(2, half_up, RBD_ROUND_HALF_UP); - ROUNDING_MODE(3, half_down, RBD_ROUND_HALF_DOWN); - ROUNDING_MODE(4, ceil, RBD_ROUND_CEIL); - ROUNDING_MODE(5, floor, RBD_ROUND_FLOOR); - ROUNDING_MODE(6, half_even, RBD_ROUND_HALF_EVEN); - - ROUNDING_MODE(7, default, RBD_ROUND_DEFAULT); - ROUNDING_MODE(8, truncate, RBD_ROUND_TRUNCATE); - ROUNDING_MODE(9, banker, RBD_ROUND_BANKER); - ROUNDING_MODE(10, ceiling, RBD_ROUND_CEILING); - -#undef ROUNDING_MODE - - id_to_r = rb_intern_const("to_r"); - id_eq = rb_intern_const("=="); - id_half = rb_intern_const("half"); - - (void)VPrint; /* suppress unused warning */ -} - -/* - * - * ============================================================================ - * - * vp_ routines begin from here. - * - * ============================================================================ - * - */ -#ifdef BIGDECIMAL_DEBUG -static int gfDebug = 1; /* Debug switch */ -#if 0 -static int gfCheckVal = 1; /* Value checking flag in VpNmlz() */ -#endif -#endif /* BIGDECIMAL_DEBUG */ - -static Real *VpConstOne; /* constant 1.0 */ -static Real *VpConstPt5; /* constant 0.5 */ -#define maxnr 100UL /* Maximum iterations for calculating sqrt. */ - /* used in VpSqrt() */ - -/* ETC */ -#define MemCmp(x,y,z) memcmp(x,y,z) -#define StrCmp(x,y) strcmp(x,y) - -enum op_sw { - OP_SW_ADD = 1, /* + */ - OP_SW_SUB, /* - */ - OP_SW_MULT, /* * */ - OP_SW_DIV /* / */ -}; - -static int VpIsDefOP(Real *c, Real *a, Real *b, enum op_sw sw); -static int AddExponent(Real *a, SIGNED_VALUE n); -static DECDIG VpAddAbs(Real *a,Real *b,Real *c); -static DECDIG VpSubAbs(Real *a,Real *b,Real *c); -static size_t VpSetPTR(Real *a, Real *b, Real *c, size_t *a_pos, size_t *b_pos, size_t *c_pos, DECDIG *av, DECDIG *bv); -static int VpNmlz(Real *a); -static void VpFormatSt(char *psz, size_t fFmt); -static int VpRdup(Real *m, size_t ind_m); - -#ifdef BIGDECIMAL_DEBUG -# ifdef HAVE_RB_EXT_RACTOR_SAFE -# error Need to make rewiting gnAlloc atomic -# endif -static int gnAlloc = 0; /* Memory allocation counter */ -#endif /* BIGDECIMAL_DEBUG */ - -/* - * EXCEPTION Handling. - */ - -#define bigdecimal_set_thread_local_exception_mode(mode) \ - rb_thread_local_aset( \ - rb_thread_current(), \ - id_BigDecimal_exception_mode, \ - INT2FIX((int)(mode)) \ - ) - -static unsigned short -VpGetException (void) -{ - VALUE const vmode = rb_thread_local_aref( - rb_thread_current(), - id_BigDecimal_exception_mode - ); - - if (NIL_P(vmode)) { - bigdecimal_set_thread_local_exception_mode(BIGDECIMAL_EXCEPTION_MODE_DEFAULT); - return BIGDECIMAL_EXCEPTION_MODE_DEFAULT; - } - - return NUM2USHORT(vmode); -} - -static void -VpSetException(unsigned short f) -{ - bigdecimal_set_thread_local_exception_mode(f); -} - -static void -VpCheckException(Real *p, bool always) -{ - if (VpIsNaN(p)) { - VpException(VP_EXCEPTION_NaN, "Computation results in 'NaN' (Not a Number)", always); - } - else if (VpIsPosInf(p)) { - VpException(VP_EXCEPTION_INFINITY, "Computation results in 'Infinity'", always); - } - else if (VpIsNegInf(p)) { - VpException(VP_EXCEPTION_INFINITY, "Computation results in '-Infinity'", always); - } -} - -static VALUE -VpCheckGetValue(Real *p) -{ - VpCheckException(p, false); - return p->obj; -} - -/* - * Precision limit. - */ - -#define bigdecimal_set_thread_local_precision_limit(limit) \ - rb_thread_local_aset( \ - rb_thread_current(), \ - id_BigDecimal_precision_limit, \ - SIZET2NUM(limit) \ - ) -#define BIGDECIMAL_PRECISION_LIMIT_DEFAULT ((size_t)0) - -/* These 2 functions added at v1.1.7 */ -VP_EXPORT size_t -VpGetPrecLimit(void) -{ - VALUE const vlimit = rb_thread_local_aref( - rb_thread_current(), - id_BigDecimal_precision_limit - ); - - if (NIL_P(vlimit)) { - bigdecimal_set_thread_local_precision_limit(BIGDECIMAL_PRECISION_LIMIT_DEFAULT); - return BIGDECIMAL_PRECISION_LIMIT_DEFAULT; - } - - return NUM2SIZET(vlimit); -} - -VP_EXPORT size_t -VpSetPrecLimit(size_t n) -{ - size_t const s = VpGetPrecLimit(); - bigdecimal_set_thread_local_precision_limit(n); - return s; -} - -/* - * Rounding mode. - */ - -#define bigdecimal_set_thread_local_rounding_mode(mode) \ - rb_thread_local_aset( \ - rb_thread_current(), \ - id_BigDecimal_rounding_mode, \ - INT2FIX((int)(mode)) \ - ) - -VP_EXPORT unsigned short -VpGetRoundMode(void) -{ - VALUE const vmode = rb_thread_local_aref( - rb_thread_current(), - id_BigDecimal_rounding_mode - ); - - if (NIL_P(vmode)) { - bigdecimal_set_thread_local_rounding_mode(BIGDECIMAL_ROUNDING_MODE_DEFAULT); - return BIGDECIMAL_ROUNDING_MODE_DEFAULT; - } - - return NUM2USHORT(vmode); -} - -VP_EXPORT int -VpIsRoundMode(unsigned short n) -{ - switch (n) { - case VP_ROUND_UP: - case VP_ROUND_DOWN: - case VP_ROUND_HALF_UP: - case VP_ROUND_HALF_DOWN: - case VP_ROUND_CEIL: - case VP_ROUND_FLOOR: - case VP_ROUND_HALF_EVEN: - return 1; - - default: - return 0; - } -} - -VP_EXPORT unsigned short -VpSetRoundMode(unsigned short n) -{ - if (VpIsRoundMode(n)) { - bigdecimal_set_thread_local_rounding_mode(n); - return n; - } - - return VpGetRoundMode(); -} - -/* - * 0.0 & 1.0 generator - * These gZero_..... and gOne_..... can be any name - * referenced from nowhere except Zero() and One(). - * gZero_..... and gOne_..... must have global scope - * (to let the compiler know they may be changed in outside - * (... but not actually..)). - */ -volatile const double gOne_ABCED9B4_CE73__00400511F31D = 1.0; - -static double -One(void) -{ - return gOne_ABCED9B4_CE73__00400511F31D; -} - -/* - ---------------------------------------------------------------- - Value of sign in Real structure is reserved for future use. - short sign; - ==0 : NaN - 1 : Positive zero - -1 : Negative zero - 2 : Positive number - -2 : Negative number - 3 : Positive infinite number - -3 : Negative infinite number - ---------------------------------------------------------------- -*/ - -VP_EXPORT double -VpGetDoubleNaN(void) /* Returns the value of NaN */ -{ - return nan(""); -} - -VP_EXPORT double -VpGetDoublePosInf(void) /* Returns the value of +Infinity */ -{ - return HUGE_VAL; -} - -VP_EXPORT double -VpGetDoubleNegInf(void) /* Returns the value of -Infinity */ -{ - return -HUGE_VAL; -} - -VP_EXPORT double -VpGetDoubleNegZero(void) /* Returns the value of -0 */ -{ - static double nzero = 1000.0; - if (nzero != 0.0) nzero = (One()/VpGetDoubleNegInf()); - return nzero; -} - -#if 0 /* unused */ -VP_EXPORT int -VpIsNegDoubleZero(double v) -{ - double z = VpGetDoubleNegZero(); - return MemCmp(&v,&z,sizeof(v))==0; -} -#endif - -VP_EXPORT int -VpException(unsigned short f, const char *str,int always) -{ - unsigned short const exception_mode = VpGetException(); - - if (f == VP_EXCEPTION_OP) always = 1; - - if (always || (exception_mode & f)) { - switch(f) { - /* case VP_EXCEPTION_OVERFLOW: */ - case VP_EXCEPTION_ZERODIVIDE: - case VP_EXCEPTION_INFINITY: - case VP_EXCEPTION_NaN: - case VP_EXCEPTION_UNDERFLOW: - case VP_EXCEPTION_OP: - rb_raise(rb_eFloatDomainError, "%s", str); - break; - default: - rb_fatal("%s", str); - } - } - return 0; /* 0 Means VpException() raised no exception */ -} - -/* Throw exception or returns 0,when resulting c is Inf or NaN */ -/* sw=1:+ 2:- 3:* 4:/ */ -static int -VpIsDefOP(Real *c, Real *a, Real *b, enum op_sw sw) -{ - if (VpIsNaN(a) || VpIsNaN(b)) { - /* at least a or b is NaN */ - VpSetNaN(c); - goto NaN; - } - - if (VpIsInf(a)) { - if (VpIsInf(b)) { - switch(sw) { - case OP_SW_ADD: /* + */ - if (VpGetSign(a) == VpGetSign(b)) { - VpSetInf(c, VpGetSign(a)); - goto Inf; - } - else { - VpSetNaN(c); - goto NaN; - } - case OP_SW_SUB: /* - */ - if (VpGetSign(a) != VpGetSign(b)) { - VpSetInf(c, VpGetSign(a)); - goto Inf; - } - else { - VpSetNaN(c); - goto NaN; - } - case OP_SW_MULT: /* * */ - VpSetInf(c, VpGetSign(a)*VpGetSign(b)); - goto Inf; - case OP_SW_DIV: /* / */ - VpSetNaN(c); - goto NaN; - } - VpSetNaN(c); - goto NaN; - } - /* Inf op Finite */ - switch(sw) { - case OP_SW_ADD: /* + */ - case OP_SW_SUB: /* - */ - VpSetInf(c, VpGetSign(a)); - break; - case OP_SW_MULT: /* * */ - if (VpIsZero(b)) { - VpSetNaN(c); - goto NaN; - } - VpSetInf(c, VpGetSign(a)*VpGetSign(b)); - break; - case OP_SW_DIV: /* / */ - VpSetInf(c, VpGetSign(a)*VpGetSign(b)); - } - goto Inf; - } - - if (VpIsInf(b)) { - switch(sw) { - case OP_SW_ADD: /* + */ - VpSetInf(c, VpGetSign(b)); - break; - case OP_SW_SUB: /* - */ - VpSetInf(c, -VpGetSign(b)); - break; - case OP_SW_MULT: /* * */ - if (VpIsZero(a)) { - VpSetNaN(c); - goto NaN; - } - VpSetInf(c, VpGetSign(a)*VpGetSign(b)); - break; - case OP_SW_DIV: /* / */ - VpSetZero(c, VpGetSign(a)*VpGetSign(b)); - } - goto Inf; - } - return 1; /* Results OK */ - -Inf: - if (VpIsPosInf(c)) { - return VpException(VP_EXCEPTION_INFINITY, "Computation results to 'Infinity'", 0); - } - else { - return VpException(VP_EXCEPTION_INFINITY, "Computation results to '-Infinity'", 0); - } - -NaN: - return VpException(VP_EXCEPTION_NaN, "Computation results to 'NaN'", 0); -} - -/* - ---------------------------------------------------------------- -*/ - -/* - * returns number of chars needed to represent vp in specified format. - */ -VP_EXPORT size_t -VpNumOfChars(Real *vp,const char *pszFmt) -{ - SIGNED_VALUE ex; - size_t nc; - - if (vp == NULL) return BASE_FIG*2+6; - if (!VpIsDef(vp)) return 32; /* not sure,may be OK */ - - switch(*pszFmt) { - case 'F': - nc = BASE_FIG*(vp->Prec + 1)+2; - ex = vp->exponent; - if (ex < 0) { - nc += BASE_FIG*(size_t)(-ex); - } - else { - if ((size_t)ex > vp->Prec) { - nc += BASE_FIG*((size_t)ex - vp->Prec); - } - } - break; - case 'E': - /* fall through */ - default: - nc = BASE_FIG*(vp->Prec + 2)+6; /* 3: sign + exponent chars */ - } - return nc; -} - -/* - * Initializer for Vp routines and constants used. - * [Input] - * BaseVal: Base value(assigned to BASE) for Vp calculation. - * It must be the form BaseVal=10**n.(n=1,2,3,...) - * If Base <= 0L,then the BASE will be calculated so - * that BASE is as large as possible satisfying the - * relation MaxVal <= BASE*(BASE+1). Where the value - * MaxVal is the largest value which can be represented - * by one DECDIG word in the computer used. - * - * [Returns] - * BIGDECIMAL_DOUBLE_FIGURES ... OK - */ -VP_EXPORT size_t -VpInit(DECDIG BaseVal) -{ - /* Setup +/- Inf NaN -0 */ - VpGetDoubleNegZero(); - - /* Const 1.0 */ - VpConstOne = NewOneNolimit(1, 1); - - /* Const 0.5 */ - VpConstPt5 = NewOneNolimit(1, 1); - VpConstPt5->exponent = 0; - VpConstPt5->frac[0] = 5*BASE1; - -#ifdef BIGDECIMAL_DEBUG - gnAlloc = 0; -#endif /* BIGDECIMAL_DEBUG */ - -#ifdef BIGDECIMAL_DEBUG - if (gfDebug) { - printf("VpInit: BaseVal = %"PRIuDECDIG"\n", BaseVal); - printf("\tBASE = %"PRIuDECDIG"\n", BASE); - printf("\tHALF_BASE = %"PRIuDECDIG"\n", HALF_BASE); - printf("\tBASE1 = %"PRIuDECDIG"\n", BASE1); - printf("\tBASE_FIG = %u\n", BASE_FIG); - printf("\tBIGDECIMAL_DOUBLE_FIGURES = %d\n", BIGDECIMAL_DOUBLE_FIGURES); - } -#endif /* BIGDECIMAL_DEBUG */ - - return BIGDECIMAL_DOUBLE_FIGURES; -} - -VP_EXPORT Real * -VpOne(void) -{ - return VpConstOne; -} - -/* If exponent overflows,then raise exception or returns 0 */ -static int -AddExponent(Real *a, SIGNED_VALUE n) -{ - SIGNED_VALUE e = a->exponent; - SIGNED_VALUE m = e+n; - SIGNED_VALUE eb, mb; - if (e > 0) { - if (n > 0) { - if (MUL_OVERFLOW_SIGNED_VALUE_P(m, (SIGNED_VALUE)BASE_FIG) || - MUL_OVERFLOW_SIGNED_VALUE_P(e, (SIGNED_VALUE)BASE_FIG)) - goto overflow; - mb = m*(SIGNED_VALUE)BASE_FIG; - eb = e*(SIGNED_VALUE)BASE_FIG; - if (eb - mb > 0) goto overflow; - } - } - else if (n < 0) { - if (MUL_OVERFLOW_SIGNED_VALUE_P(m, (SIGNED_VALUE)BASE_FIG) || - MUL_OVERFLOW_SIGNED_VALUE_P(e, (SIGNED_VALUE)BASE_FIG)) - goto underflow; - mb = m*(SIGNED_VALUE)BASE_FIG; - eb = e*(SIGNED_VALUE)BASE_FIG; - if (mb - eb > 0) goto underflow; - } - a->exponent = m; - return 1; - -/* Overflow/Underflow ==> Raise exception or returns 0 */ -underflow: - VpSetZero(a, VpGetSign(a)); - return VpException(VP_EXCEPTION_UNDERFLOW, "Exponent underflow", 0); - -overflow: - VpSetInf(a, VpGetSign(a)); - return VpException(VP_EXCEPTION_OVERFLOW, "Exponent overflow", 0); -} - -Real * -bigdecimal_parse_special_string(const char *str) -{ - static const struct { - const char *str; - size_t len; - int sign; - } table[] = { - { SZ_INF, sizeof(SZ_INF) - 1, VP_SIGN_POSITIVE_INFINITE }, - { SZ_PINF, sizeof(SZ_PINF) - 1, VP_SIGN_POSITIVE_INFINITE }, - { SZ_NINF, sizeof(SZ_NINF) - 1, VP_SIGN_NEGATIVE_INFINITE }, - { SZ_NaN, sizeof(SZ_NaN) - 1, VP_SIGN_NaN } - }; - static const size_t table_length = sizeof(table) / sizeof(table[0]); - size_t i; - - for (i = 0; i < table_length; ++i) { - const char *p; - if (strncmp(str, table[i].str, table[i].len) != 0) { - continue; - } - - p = str + table[i].len; - while (*p && ISSPACE(*p)) ++p; - if (*p == '\0') { - Real *vp = rbd_allocate_struct(1); - vp->MaxPrec = 1; - switch (table[i].sign) { - default: - UNREACHABLE; break; - case VP_SIGN_POSITIVE_INFINITE: - VpSetPosInf(vp); - return vp; - case VP_SIGN_NEGATIVE_INFINITE: - VpSetNegInf(vp); - return vp; - case VP_SIGN_NaN: - VpSetNaN(vp); - return vp; - } - } - } - - return NULL; -} - -/* - * Allocates variable. - * [Input] - * mx ... The number of decimal digits to be allocated, if zero then mx is determined by szVal. - * The mx will be the number of significant digits can to be stored. - * szVal ... The value assigned(char). If szVal==NULL, then zero is assumed. - * If szVal[0]=='#' then MaxPrec is not affected by the precision limit - * so that the full precision specified by szVal is allocated. - * - * [Returns] - * Pointer to the newly allocated variable, or - * NULL be returned if memory allocation is failed,or any error. - */ -VP_EXPORT Real * -VpAlloc(size_t mx, const char *szVal, int strict_p, int exc) -{ - const char *orig_szVal = szVal; - size_t i, j, ni, ipf, nf, ipe, ne, dot_seen, exp_seen, nalloc; - size_t len; - char v, *psz; - int sign=1; - Real *vp = NULL; - VALUE buf; - - if (szVal == NULL) { - return_zero: - /* necessary to be able to store */ - /* at least mx digits. */ - /* szVal==NULL ==> allocate zero value. */ - vp = rbd_allocate_struct(mx); - vp->MaxPrec = rbd_calculate_internal_digits(mx, false); /* Must false */ - VpSetZero(vp, 1); /* initialize vp to zero. */ - return vp; - } - - /* Skipping leading spaces */ - while (ISSPACE(*szVal)) szVal++; - - /* Check on Inf & NaN */ - if ((vp = bigdecimal_parse_special_string(szVal)) != NULL) { - return vp; - } - - /* Processing the leading one `#` */ - if (*szVal != '#') { - len = rbd_calculate_internal_digits(mx, true); - } - else { - len = rbd_calculate_internal_digits(mx, false); - ++szVal; - } - - /* Scanning digits */ - - /* A buffer for keeping scanned digits */ - buf = rb_str_tmp_new(strlen(szVal) + 1); - psz = RSTRING_PTR(buf); - - /* cursor: i for psz, and j for szVal */ - i = j = 0; - - /* Scanning: sign part */ - v = psz[i] = szVal[j]; - if ((v == '-') || (v == '+')) { - sign = -(v == '-'); - ++i; - ++j; - } - - /* Scanning: integer part */ - ni = 0; /* number of digits in the integer part */ - while ((v = psz[i] = szVal[j]) != '\0') { - if (!strict_p && ISSPACE(v)) { - v = psz[i] = '\0'; - break; - } - if (v == '_') { - if (ni > 0) { - v = szVal[j+1]; - if (v == '\0' || ISSPACE(v) || ISDIGIT(v)) { - ++j; - continue; - } - if (!strict_p) { - v = psz[i] = '\0'; - break; - } - } - goto invalid_value; - } - if (!ISDIGIT(v)) { - break; - } - ++ni; - ++i; - ++j; - } - - /* Scanning: fractional part */ - nf = 0; /* number of digits in the fractional part */ - ne = 0; /* number of digits in the exponential part */ - ipf = 0; /* index of the beginning of the fractional part */ - ipe = 0; /* index of the beginning of the exponential part */ - dot_seen = 0; - exp_seen = 0; - - if (v != '\0') { - /* Scanning fractional part */ - if ((psz[i] = szVal[j]) == '.') { - dot_seen = 1; - ++i; - ++j; - ipf = i; - while ((v = psz[i] = szVal[j]) != '\0') { - if (!strict_p && ISSPACE(v)) { - v = psz[i] = '\0'; - break; - } - if (v == '_') { - if (nf > 0 && ISDIGIT(szVal[j+1])) { - ++j; - continue; - } - if (!strict_p) { - v = psz[i] = '\0'; - if (nf == 0) { - dot_seen = 0; - } - break; - } - goto invalid_value; - } - if (!ISDIGIT(v)) break; - ++i; - ++j; - ++nf; - } - } - - /* Scanning exponential part */ - if (v != '\0') { - switch ((psz[i] = szVal[j])) { - case '\0': - break; - case 'e': case 'E': - case 'd': case 'D': - exp_seen = 1; - ++i; - ++j; - ipe = i; - v = psz[i] = szVal[j]; - if ((v == '-') || (v == '+')) { - ++i; - ++j; - } - while ((v = psz[i] = szVal[j]) != '\0') { - if (!strict_p && ISSPACE(v)) { - v = psz[i] = '\0'; - break; - } - if (v == '_') { - if (ne > 0 && ISDIGIT(szVal[j+1])) { - ++j; - continue; - } - if (!strict_p) { - v = psz[i] = '\0'; - if (ne == 0) { - exp_seen = 0; - } - break; - } - goto invalid_value; - } - if (!ISDIGIT(v)) break; - ++i; - ++j; - ++ne; - } - break; - default: - break; - } - } - - if (v != '\0') { - /* Scanning trailing spaces */ - while (ISSPACE(szVal[j])) ++j; - - /* Invalid character */ - if (szVal[j] && strict_p) { - goto invalid_value; - } - } - } - - psz[i] = '\0'; - - if (strict_p && (((ni == 0 || dot_seen) && nf == 0) || (exp_seen && ne == 0))) { - VALUE str; - invalid_value: - if (!strict_p) { - goto return_zero; - } - if (!exc) { - return NULL; - } - str = rb_str_new2(orig_szVal); - rb_raise(rb_eArgError, "invalid value for BigDecimal(): \"%"PRIsVALUE"\"", str); - } - - nalloc = (ni + nf + BASE_FIG - 1) / BASE_FIG + 1; /* set effective allocation */ - /* units for szVal[] */ - if (len == 0) len = 1; - nalloc = Max(nalloc, len); - len = nalloc; - vp = rbd_allocate_struct(len); - vp->MaxPrec = len; /* set max precision */ - VpSetZero(vp, sign); - VpCtoV(vp, psz, ni, psz + ipf, nf, psz + ipe, ne); - rb_str_resize(buf, 0); - return vp; -} - -/* - * Assignment(c=a). - * [Input] - * a ... RHSV - * isw ... switch for assignment. - * c = a when isw > 0 - * c = -a when isw < 0 - * if c->MaxPrec < a->Prec,then round operation - * will be performed. - * [Output] - * c ... LHSV - */ -VP_EXPORT size_t -VpAsgn(Real *c, Real *a, int isw) -{ - size_t n; - if (VpIsNaN(a)) { - VpSetNaN(c); - return 0; - } - if (VpIsInf(a)) { - VpSetInf(c, isw * VpGetSign(a)); - return 0; - } - - /* check if the RHS is zero */ - if (!VpIsZero(a)) { - c->exponent = a->exponent; /* store exponent */ - VpSetSign(c, isw * VpGetSign(a)); /* set sign */ - n = (a->Prec < c->MaxPrec) ? (a->Prec) : (c->MaxPrec); - c->Prec = n; - memcpy(c->frac, a->frac, n * sizeof(DECDIG)); - /* Needs round ? */ - if (isw != 10) { - /* Not in ActiveRound */ - if(c->Prec < a->Prec) { - VpInternalRound(c, n, (n>0) ? a->frac[n-1] : 0, a->frac[n]); - } - else { - VpLimitRound(c,0); - } - } - } - else { - /* The value of 'a' is zero. */ - VpSetZero(c, isw * VpGetSign(a)); - return 1; - } - return c->Prec * BASE_FIG; -} - -/* - * c = a + b when operation = 1 or 2 - * c = a - b when operation = -1 or -2. - * Returns number of significant digits of c - */ -VP_EXPORT size_t -VpAddSub(Real *c, Real *a, Real *b, int operation) -{ - short sw, isw; - Real *a_ptr, *b_ptr; - size_t n, na, nb, i; - DECDIG mrv; - -#ifdef BIGDECIMAL_DEBUG - if (gfDebug) { - VPrint(stdout, "VpAddSub(enter) a=% \n", a); - VPrint(stdout, " b=% \n", b); - printf(" operation=%d\n", operation); - } -#endif /* BIGDECIMAL_DEBUG */ - - if (!VpIsDefOP(c, a, b, (operation > 0) ? OP_SW_ADD : OP_SW_SUB)) return 0; /* No significant digits */ - - /* check if a or b is zero */ - if (VpIsZero(a)) { - /* a is zero,then assign b to c */ - if (!VpIsZero(b)) { - VpAsgn(c, b, operation); - } - else { - /* Both a and b are zero. */ - if (VpGetSign(a) < 0 && operation * VpGetSign(b) < 0) { - /* -0 -0 */ - VpSetZero(c, -1); - } - else { - VpSetZero(c, 1); - } - return 1; /* 0: 1 significant digits */ - } - return c->Prec * BASE_FIG; - } - if (VpIsZero(b)) { - /* b is zero,then assign a to c. */ - VpAsgn(c, a, 1); - return c->Prec*BASE_FIG; - } - - if (operation < 0) sw = -1; - else sw = 1; - - /* compare absolute value. As a result,|a_ptr|>=|b_ptr| */ - if (a->exponent > b->exponent) { - a_ptr = a; - b_ptr = b; - } /* |a|>|b| */ - else if (a->exponent < b->exponent) { - a_ptr = b; - b_ptr = a; - } /* |a|<|b| */ - else { - /* Exponent part of a and b is the same,then compare fraction */ - /* part */ - na = a->Prec; - nb = b->Prec; - n = Min(na, nb); - for (i=0; i < n; ++i) { - if (a->frac[i] > b->frac[i]) { - a_ptr = a; - b_ptr = b; - goto end_if; - } - else if (a->frac[i] < b->frac[i]) { - a_ptr = b; - b_ptr = a; - goto end_if; - } - } - if (na > nb) { - a_ptr = a; - b_ptr = b; - goto end_if; - } - else if (na < nb) { - a_ptr = b; - b_ptr = a; - goto end_if; - } - /* |a| == |b| */ - if (VpGetSign(a) + sw *VpGetSign(b) == 0) { - VpSetZero(c, 1); /* abs(a)=abs(b) and operation = '-' */ - return c->Prec * BASE_FIG; - } - a_ptr = a; - b_ptr = b; - } - -end_if: - isw = VpGetSign(a) + sw *VpGetSign(b); - /* - * isw = 0 ...( 1)+(-1),( 1)-( 1),(-1)+(1),(-1)-(-1) - * = 2 ...( 1)+( 1),( 1)-(-1) - * =-2 ...(-1)+(-1),(-1)-( 1) - * If isw==0, then c =(Sign a_ptr)(|a_ptr|-|b_ptr|) - * else c =(Sign ofisw)(|a_ptr|+|b_ptr|) - */ - if (isw) { /* addition */ - VpSetSign(c, 1); - mrv = VpAddAbs(a_ptr, b_ptr, c); - VpSetSign(c, isw / 2); - } - else { /* subtraction */ - VpSetSign(c, 1); - mrv = VpSubAbs(a_ptr, b_ptr, c); - if (a_ptr == a) { - VpSetSign(c,VpGetSign(a)); - } - else { - VpSetSign(c, VpGetSign(a_ptr) * sw); - } - } - VpInternalRound(c, 0, (c->Prec > 0) ? c->frac[c->Prec-1] : 0, mrv); - -#ifdef BIGDECIMAL_DEBUG - if (gfDebug) { - VPrint(stdout, "VpAddSub(result) c=% \n", c); - VPrint(stdout, " a=% \n", a); - VPrint(stdout, " b=% \n", b); - printf(" operation=%d\n", operation); - } -#endif /* BIGDECIMAL_DEBUG */ - return c->Prec * BASE_FIG; -} - -/* - * Addition of two values with variable precision - * a and b assuming abs(a)>abs(b). - * c = abs(a) + abs(b) ; where |a|>=|b| - */ -static DECDIG -VpAddAbs(Real *a, Real *b, Real *c) -{ - size_t word_shift; - size_t ap; - size_t bp; - size_t cp; - size_t a_pos; - size_t b_pos, b_pos_with_word_shift; - size_t c_pos; - DECDIG av, bv, carry, mrv; - -#ifdef BIGDECIMAL_DEBUG - if (gfDebug) { - VPrint(stdout, "VpAddAbs called: a = %\n", a); - VPrint(stdout, " b = %\n", b); - } -#endif /* BIGDECIMAL_DEBUG */ - - word_shift = VpSetPTR(a, b, c, &ap, &bp, &cp, &av, &bv); - a_pos = ap; - b_pos = bp; - c_pos = cp; - - if (word_shift == (size_t)-1L) return 0; /* Overflow */ - if (b_pos == (size_t)-1L) goto Assign_a; - - mrv = av + bv; /* Most right val. Used for round. */ - - /* Just assign the last few digits of b to c because a has no */ - /* corresponding digits to be added. */ - if (b_pos > 0) { - while (b_pos > 0 && b_pos + word_shift > a_pos) { - c->frac[--c_pos] = b->frac[--b_pos]; - } - } - if (b_pos == 0 && word_shift > a_pos) { - while (word_shift-- > a_pos) { - c->frac[--c_pos] = 0; - } - } - - /* Just assign the last few digits of a to c because b has no */ - /* corresponding digits to be added. */ - b_pos_with_word_shift = b_pos + word_shift; - while (a_pos > b_pos_with_word_shift) { - c->frac[--c_pos] = a->frac[--a_pos]; - } - carry = 0; /* set first carry be zero */ - - /* Now perform addition until every digits of b will be */ - /* exhausted. */ - while (b_pos > 0) { - c->frac[--c_pos] = a->frac[--a_pos] + b->frac[--b_pos] + carry; - if (c->frac[c_pos] >= BASE) { - c->frac[c_pos] -= BASE; - carry = 1; - } - else { - carry = 0; - } - } - - /* Just assign the first few digits of a with considering */ - /* the carry obtained so far because b has been exhausted. */ - while (a_pos > 0) { - c->frac[--c_pos] = a->frac[--a_pos] + carry; - if (c->frac[c_pos] >= BASE) { - c->frac[c_pos] -= BASE; - carry = 1; - } - else { - carry = 0; - } - } - if (c_pos) c->frac[c_pos - 1] += carry; - goto Exit; - -Assign_a: - VpAsgn(c, a, 1); - mrv = 0; - -Exit: - -#ifdef BIGDECIMAL_DEBUG - if (gfDebug) { - VPrint(stdout, "VpAddAbs exit: c=% \n", c); - } -#endif /* BIGDECIMAL_DEBUG */ - return mrv; -} - -/* - * c = abs(a) - abs(b) - */ -static DECDIG -VpSubAbs(Real *a, Real *b, Real *c) -{ - size_t word_shift; - size_t ap; - size_t bp; - size_t cp; - size_t a_pos; - size_t b_pos, b_pos_with_word_shift; - size_t c_pos; - DECDIG av, bv, borrow, mrv; - -#ifdef BIGDECIMAL_DEBUG - if (gfDebug) { - VPrint(stdout, "VpSubAbs called: a = %\n", a); - VPrint(stdout, " b = %\n", b); - } -#endif /* BIGDECIMAL_DEBUG */ - - word_shift = VpSetPTR(a, b, c, &ap, &bp, &cp, &av, &bv); - a_pos = ap; - b_pos = bp; - c_pos = cp; - if (word_shift == (size_t)-1L) return 0; /* Overflow */ - if (b_pos == (size_t)-1L) goto Assign_a; - - if (av >= bv) { - mrv = av - bv; - borrow = 0; - } - else { - mrv = 0; - borrow = 1; - } - - /* Just assign the values which are the BASE subtracted by */ - /* each of the last few digits of the b because the a has no */ - /* corresponding digits to be subtracted. */ - if (b_pos + word_shift > a_pos) { - while (b_pos > 0 && b_pos + word_shift > a_pos) { - c->frac[--c_pos] = BASE - b->frac[--b_pos] - borrow; - borrow = 1; - } - if (b_pos == 0) { - while (word_shift > a_pos) { - --word_shift; - c->frac[--c_pos] = BASE - borrow; - borrow = 1; - } - } - } - /* Just assign the last few digits of a to c because b has no */ - /* corresponding digits to subtract. */ - - b_pos_with_word_shift = b_pos + word_shift; - while (a_pos > b_pos_with_word_shift) { - c->frac[--c_pos] = a->frac[--a_pos]; - } - - /* Now perform subtraction until every digits of b will be */ - /* exhausted. */ - while (b_pos > 0) { - --c_pos; - if (a->frac[--a_pos] < b->frac[--b_pos] + borrow) { - c->frac[c_pos] = BASE + a->frac[a_pos] - b->frac[b_pos] - borrow; - borrow = 1; - } - else { - c->frac[c_pos] = a->frac[a_pos] - b->frac[b_pos] - borrow; - borrow = 0; - } - } - - /* Just assign the first few digits of a with considering */ - /* the borrow obtained so far because b has been exhausted. */ - while (a_pos > 0) { - --c_pos; - if (a->frac[--a_pos] < borrow) { - c->frac[c_pos] = BASE + a->frac[a_pos] - borrow; - borrow = 1; - } - else { - c->frac[c_pos] = a->frac[a_pos] - borrow; - borrow = 0; - } - } - if (c_pos) c->frac[c_pos - 1] -= borrow; - goto Exit; - -Assign_a: - VpAsgn(c, a, 1); - mrv = 0; - -Exit: -#ifdef BIGDECIMAL_DEBUG - if (gfDebug) { - VPrint(stdout, "VpSubAbs exit: c=% \n", c); - } -#endif /* BIGDECIMAL_DEBUG */ - return mrv; -} - -/* - * Note: If(av+bv)>= HALF_BASE,then 1 will be added to the least significant - * digit of c(In case of addition). - * ------------------------- figure of output ----------------------------------- - * a = xxxxxxxxxxx - * b = xxxxxxxxxx - * c =xxxxxxxxxxxxxxx - * word_shift = | | - * right_word = | | (Total digits in RHSV) - * left_word = | | (Total digits in LHSV) - * a_pos = | - * b_pos = | - * c_pos = | - */ -static size_t -VpSetPTR(Real *a, Real *b, Real *c, size_t *a_pos, size_t *b_pos, size_t *c_pos, DECDIG *av, DECDIG *bv) -{ - size_t left_word, right_word, word_shift; - - size_t const round_limit = (VpGetPrecLimit() + BASE_FIG - 1) / BASE_FIG; - - assert(a->exponent >= b->exponent); - - c->frac[0] = 0; - *av = *bv = 0; - - word_shift = (a->exponent - b->exponent); - left_word = b->Prec + word_shift; - right_word = Max(a->Prec, left_word); - left_word = c->MaxPrec - 1; /* -1 ... prepare for round up */ - - /* - * check if 'round' is needed. - */ - if (right_word > left_word) { /* round ? */ - /*--------------------------------- - * Actual size of a = xxxxxxAxx - * Actual size of b = xxxBxxxxx - * Max. size of c = xxxxxx - * Round off = |-----| - * c_pos = | - * right_word = | - * a_pos = | - */ - *c_pos = right_word = left_word + 1; /* Set resulting precision */ - /* be equal to that of c */ - if (a->Prec >= c->MaxPrec) { - /* - * a = xxxxxxAxxx - * c = xxxxxx - * a_pos = | - */ - *a_pos = left_word; - if (*a_pos <= round_limit) { - *av = a->frac[*a_pos]; /* av is 'A' shown in above. */ - } - } - else { - /* - * a = xxxxxxx - * c = xxxxxxxxxx - * a_pos = | - */ - *a_pos = a->Prec; - } - if (b->Prec + word_shift >= c->MaxPrec) { - /* - * a = xxxxxxxxx - * b = xxxxxxxBxxx - * c = xxxxxxxxxxx - * b_pos = | - */ - if (c->MaxPrec >= word_shift + 1) { - *b_pos = c->MaxPrec - word_shift - 1; - if (*b_pos + word_shift <= round_limit) { - *bv = b->frac[*b_pos]; - } - } - else { - *b_pos = -1L; - } - } - else { - /* - * a = xxxxxxxxxxxxxxxx - * b = xxxxxx - * c = xxxxxxxxxxxxx - * b_pos = | - */ - *b_pos = b->Prec; - } - } - else { /* The MaxPrec of c - 1 > The Prec of a + b */ - /* - * a = xxxxxxx - * b = xxxxxx - * c = xxxxxxxxxxx - * c_pos = | - */ - *b_pos = b->Prec; - *a_pos = a->Prec; - *c_pos = right_word + 1; - } - c->Prec = *c_pos; - c->exponent = a->exponent; - if (!AddExponent(c, 1)) return (size_t)-1L; - return word_shift; -} - -/* - * Return number of significant digits - * c = a * b , Where a = a0a1a2 ... an - * b = b0b1b2 ... bm - * c = c0c1c2 ... cl - * a0 a1 ... an * bm - * a0 a1 ... an * bm-1 - * . . . - * . . . - * a0 a1 .... an * b0 - * +_____________________________ - * c0 c1 c2 ...... cl - * nc <---| - * MaxAB |--------------------| - */ -VP_EXPORT size_t -VpMult(Real *c, Real *a, Real *b) -{ - size_t MxIndA, MxIndB, MxIndAB, MxIndC; - size_t ind_c, i, ii, nc; - size_t ind_as, ind_ae, ind_bs; - DECDIG carry; - DECDIG_DBL s; - Real *w; - -#ifdef BIGDECIMAL_DEBUG - if (gfDebug) { - VPrint(stdout, "VpMult(Enter): a=% \n", a); - VPrint(stdout, " b=% \n", b); - } -#endif /* BIGDECIMAL_DEBUG */ - - if (!VpIsDefOP(c, a, b, OP_SW_MULT)) return 0; /* No significant digit */ - - if (VpIsZero(a) || VpIsZero(b)) { - /* at least a or b is zero */ - VpSetZero(c, VpGetSign(a) * VpGetSign(b)); - return 1; /* 0: 1 significant digit */ - } - - if (VpIsOne(a)) { - VpAsgn(c, b, VpGetSign(a)); - goto Exit; - } - if (VpIsOne(b)) { - VpAsgn(c, a, VpGetSign(b)); - goto Exit; - } - if (b->Prec > a->Prec) { - /* Adjust so that digits(a)>digits(b) */ - w = a; - a = b; - b = w; - } - w = NULL; - MxIndA = a->Prec - 1; - MxIndB = b->Prec - 1; - MxIndC = c->MaxPrec - 1; - MxIndAB = a->Prec + b->Prec - 1; - - if (MxIndC < MxIndAB) { /* The Max. prec. of c < Prec(a)+Prec(b) */ - w = c; - c = NewZeroNolimit(1, (size_t)((MxIndAB + 1) * BASE_FIG)); - MxIndC = MxIndAB; - } - - /* set LHSV c info */ - - c->exponent = a->exponent; /* set exponent */ - if (!AddExponent(c, b->exponent)) { - if (w) rbd_free_struct(c); - return 0; - } - VpSetSign(c, VpGetSign(a) * VpGetSign(b)); /* set sign */ - carry = 0; - nc = ind_c = MxIndAB; - memset(c->frac, 0, (nc + 1) * sizeof(DECDIG)); /* Initialize c */ - c->Prec = nc + 1; /* set precision */ - for (nc = 0; nc < MxIndAB; ++nc, --ind_c) { - if (nc < MxIndB) { /* The left triangle of the Fig. */ - ind_as = MxIndA - nc; - ind_ae = MxIndA; - ind_bs = MxIndB; - } - else if (nc <= MxIndA) { /* The middle rectangular of the Fig. */ - ind_as = MxIndA - nc; - ind_ae = MxIndA - (nc - MxIndB); - ind_bs = MxIndB; - } - else /* if (nc > MxIndA) */ { /* The right triangle of the Fig. */ - ind_as = 0; - ind_ae = MxIndAB - nc - 1; - ind_bs = MxIndB - (nc - MxIndA); - } - - for (i = ind_as; i <= ind_ae; ++i) { - s = (DECDIG_DBL)a->frac[i] * b->frac[ind_bs--]; - carry = (DECDIG)(s / BASE); - s -= (DECDIG_DBL)carry * BASE; - c->frac[ind_c] += (DECDIG)s; - if (c->frac[ind_c] >= BASE) { - s = c->frac[ind_c] / BASE; - carry += (DECDIG)s; - c->frac[ind_c] -= (DECDIG)(s * BASE); - } - if (carry) { - ii = ind_c; - while (ii-- > 0) { - c->frac[ii] += carry; - if (c->frac[ii] >= BASE) { - carry = c->frac[ii] / BASE; - c->frac[ii] -= (carry * BASE); - } - else { - break; - } - } - } - } - } - if (w != NULL) { /* free work variable */ - VpNmlz(c); - VpAsgn(w, c, 1); - rbd_free_struct(c); - c = w; - } - else { - VpLimitRound(c,0); - } - -Exit: -#ifdef BIGDECIMAL_DEBUG - if (gfDebug) { - VPrint(stdout, "VpMult(c=a*b): c=% \n", c); - VPrint(stdout, " a=% \n", a); - VPrint(stdout, " b=% \n", b); - } -#endif /*BIGDECIMAL_DEBUG */ - return c->Prec*BASE_FIG; -} - -/* - * c = a / b, remainder = r - */ -VP_EXPORT size_t -VpDivd(Real *c, Real *r, Real *a, Real *b) -{ - size_t word_a, word_b, word_c, word_r; - size_t i, n, ind_a, ind_b, ind_c, ind_r; - size_t nLoop; - DECDIG_DBL q, b1, b1p1, b1b2, b1b2p1, r1r2; - DECDIG borrow, borrow1, borrow2; - DECDIG_DBL qb; - -#ifdef BIGDECIMAL_DEBUG - if (gfDebug) { - VPrint(stdout, " VpDivd(c=a/b) a=% \n", a); - VPrint(stdout, " b=% \n", b); - } -#endif /*BIGDECIMAL_DEBUG */ - - VpSetNaN(r); - if (!VpIsDefOP(c, a, b, OP_SW_DIV)) goto Exit; - if (VpIsZero(a) && VpIsZero(b)) { - VpSetNaN(c); - return VpException(VP_EXCEPTION_NaN, "Computation results to 'NaN'", 0); - } - if (VpIsZero(b)) { - VpSetInf(c, VpGetSign(a) * VpGetSign(b)); - return VpException(VP_EXCEPTION_ZERODIVIDE, "Divide by zero", 0); - } - if (VpIsZero(a)) { - /* numerator a is zero */ - VpSetZero(c, VpGetSign(a) * VpGetSign(b)); - VpSetZero(r, VpGetSign(a) * VpGetSign(b)); - goto Exit; - } - if (VpIsOne(b)) { - /* divide by one */ - VpAsgn(c, a, VpGetSign(b)); - VpSetZero(r, VpGetSign(a)); - goto Exit; - } - - word_a = a->Prec; - word_b = b->Prec; - word_c = c->MaxPrec; - word_r = r->MaxPrec; - - if (word_a >= word_r) goto space_error; - - ind_r = 1; - r->frac[0] = 0; - while (ind_r <= word_a) { - r->frac[ind_r] = a->frac[ind_r - 1]; - ++ind_r; - } - while (ind_r < word_r) r->frac[ind_r++] = 0; - - ind_c = 0; - while (ind_c < word_c) c->frac[ind_c++] = 0; - - /* initial procedure */ - b1 = b1p1 = b->frac[0]; - if (b->Prec <= 1) { - b1b2p1 = b1b2 = b1p1 * BASE; - } - else { - b1p1 = b1 + 1; - b1b2p1 = b1b2 = b1 * BASE + b->frac[1]; - if (b->Prec > 2) ++b1b2p1; - } - - /* */ - /* loop start */ - ind_c = word_r - 1; - nLoop = Min(word_c,ind_c); - ind_c = 1; - while (ind_c < nLoop) { - if (r->frac[ind_c] == 0) { - ++ind_c; - continue; - } - r1r2 = (DECDIG_DBL)r->frac[ind_c] * BASE + r->frac[ind_c + 1]; - if (r1r2 == b1b2) { - /* The first two word digits is the same */ - ind_b = 2; - ind_a = ind_c + 2; - while (ind_b < word_b) { - if (r->frac[ind_a] < b->frac[ind_b]) goto div_b1p1; - if (r->frac[ind_a] > b->frac[ind_b]) break; - ++ind_a; - ++ind_b; - } - /* The first few word digits of r and b is the same and */ - /* the first different word digit of w is greater than that */ - /* of b, so quotient is 1 and just subtract b from r. */ - borrow = 0; /* quotient=1, then just r-b */ - ind_b = b->Prec - 1; - ind_r = ind_c + ind_b; - if (ind_r >= word_r) goto space_error; - n = ind_b; - for (i = 0; i <= n; ++i) { - if (r->frac[ind_r] < b->frac[ind_b] + borrow) { - r->frac[ind_r] += (BASE - (b->frac[ind_b] + borrow)); - borrow = 1; - } - else { - r->frac[ind_r] = r->frac[ind_r] - b->frac[ind_b] - borrow; - borrow = 0; - } - --ind_r; - --ind_b; - } - ++c->frac[ind_c]; - goto carry; - } - /* The first two word digits is not the same, */ - /* then compare magnitude, and divide actually. */ - if (r1r2 >= b1b2p1) { - q = r1r2 / b1b2p1; /* q == (DECDIG)q */ - c->frac[ind_c] += (DECDIG)q; - ind_r = b->Prec + ind_c - 1; - goto sub_mult; - } - -div_b1p1: - if (ind_c + 1 >= word_c) goto out_side; - q = r1r2 / b1p1; /* q == (DECDIG)q */ - c->frac[ind_c + 1] += (DECDIG)q; - ind_r = b->Prec + ind_c; - -sub_mult: - borrow1 = borrow2 = 0; - ind_b = word_b - 1; - if (ind_r >= word_r) goto space_error; - n = ind_b; - for (i = 0; i <= n; ++i) { - /* now, perform r = r - q * b */ - qb = q * b->frac[ind_b]; - if (qb < BASE) borrow1 = 0; - else { - borrow1 = (DECDIG)(qb / BASE); - qb -= (DECDIG_DBL)borrow1 * BASE; /* get qb < BASE */ - } - if(r->frac[ind_r] < qb) { - r->frac[ind_r] += (DECDIG)(BASE - qb); - borrow2 = borrow2 + borrow1 + 1; - } - else { - r->frac[ind_r] -= (DECDIG)qb; - borrow2 += borrow1; - } - if (borrow2) { - if(r->frac[ind_r - 1] < borrow2) { - r->frac[ind_r - 1] += (BASE - borrow2); - borrow2 = 1; - } - else { - r->frac[ind_r - 1] -= borrow2; - borrow2 = 0; - } - } - --ind_r; - --ind_b; - } - - r->frac[ind_r] -= borrow2; -carry: - ind_r = ind_c; - while (c->frac[ind_r] >= BASE) { - c->frac[ind_r] -= BASE; - --ind_r; - ++c->frac[ind_r]; - } - } - /* End of operation, now final arrangement */ -out_side: - c->Prec = word_c; - c->exponent = a->exponent; - if (!AddExponent(c, 2)) return 0; - if (!AddExponent(c, -(b->exponent))) return 0; - - VpSetSign(c, VpGetSign(a) * VpGetSign(b)); - VpNmlz(c); /* normalize c */ - r->Prec = word_r; - r->exponent = a->exponent; - if (!AddExponent(r, 1)) return 0; - VpSetSign(r, VpGetSign(a)); - VpNmlz(r); /* normalize r(remainder) */ - goto Exit; - -space_error: -#ifdef BIGDECIMAL_DEBUG - if (gfDebug) { - printf(" word_a=%"PRIuSIZE"\n", word_a); - printf(" word_b=%"PRIuSIZE"\n", word_b); - printf(" word_c=%"PRIuSIZE"\n", word_c); - printf(" word_r=%"PRIuSIZE"\n", word_r); - printf(" ind_r =%"PRIuSIZE"\n", ind_r); - } -#endif /* BIGDECIMAL_DEBUG */ - rb_bug("ERROR(VpDivd): space for remainder too small."); - -Exit: -#ifdef BIGDECIMAL_DEBUG - if (gfDebug) { - VPrint(stdout, " VpDivd(c=a/b), c=% \n", c); - VPrint(stdout, " r=% \n", r); - } -#endif /* BIGDECIMAL_DEBUG */ - return c->Prec * BASE_FIG; -} - -/* - * Input a = 00000xxxxxxxx En(5 preceding zeros) - * Output a = xxxxxxxx En-5 - */ -static int -VpNmlz(Real *a) -{ - size_t ind_a, i; - - if (!VpIsDef(a)) goto NoVal; - if (VpIsZero(a)) goto NoVal; - - ind_a = a->Prec; - while (ind_a--) { - if (a->frac[ind_a]) { - a->Prec = ind_a + 1; - i = 0; - while (a->frac[i] == 0) ++i; /* skip the first few zeros */ - if (i) { - a->Prec -= i; - if (!AddExponent(a, -(SIGNED_VALUE)i)) return 0; - memmove(&a->frac[0], &a->frac[i], a->Prec*sizeof(DECDIG)); - } - return 1; - } - } - /* a is zero(no non-zero digit) */ - VpSetZero(a, VpGetSign(a)); - return 0; - -NoVal: - a->frac[0] = 0; - a->Prec = 1; - return 0; -} - -/* - * VpComp = 0 ... if a=b, - * Pos ... a>b, - * Neg ... asign - b->sign; - else e = a->sign; - - if (e > 0) return 1; - else if (e < 0) return -1; - else return 0; - } - if (!VpIsDef(b)) { - e = -b->sign; - if (e > 0) return 1; - else return -1; - } - /* Zero check */ - if (VpIsZero(a)) { - if (VpIsZero(b)) return 0; /* both zero */ - val = -VpGetSign(b); - goto Exit; - } - if (VpIsZero(b)) { - val = VpGetSign(a); - goto Exit; - } - - /* compare sign */ - if (VpGetSign(a) > VpGetSign(b)) { - val = 1; /* a>b */ - goto Exit; - } - if (VpGetSign(a) < VpGetSign(b)) { - val = -1; /* aexponent > b->exponent) { - val = VpGetSign(a); - goto Exit; - } - if (a->exponent < b->exponent) { - val = -VpGetSign(b); - goto Exit; - } - - /* a and b have same exponent, then compare their significand. */ - mx = (a->Prec < b->Prec) ? a->Prec : b->Prec; - ind = 0; - while (ind < mx) { - if (a->frac[ind] > b->frac[ind]) { - val = VpGetSign(a); - goto Exit; - } - if (a->frac[ind] < b->frac[ind]) { - val = -VpGetSign(b); - goto Exit; - } - ++ind; - } - if (a->Prec > b->Prec) { - val = VpGetSign(a); - } - else if (a->Prec < b->Prec) { - val = -VpGetSign(b); - } - -Exit: - if (val > 1) val = 1; - else if (val < -1) val = -1; - -#ifdef BIGDECIMAL_DEBUG - if (gfDebug) { - VPrint(stdout, " VpComp a=%\n", a); - VPrint(stdout, " b=%\n", b); - printf(" ans=%d\n", val); - } -#endif /* BIGDECIMAL_DEBUG */ - return (int)val; -} - -/* - * cntl_chr ... ASCIIZ Character, print control characters - * Available control codes: - * % ... VP variable. To print '%', use '%%'. - * \n ... new line - * \b ... backspace - * \t ... tab - * Note: % must not appear more than once - * a ... VP variable to be printed - */ -static int -VPrint(FILE *fp, const char *cntl_chr, Real *a) -{ - size_t i, j, nc, nd, ZeroSup, sep = 10; - DECDIG m, e, nn; - - j = 0; - nd = nc = 0; /* nd : number of digits in fraction part(every 10 digits, */ - /* nd<=10). */ - /* nc : number of characters printed */ - ZeroSup = 1; /* Flag not to print the leading zeros as 0.00xxxxEnn */ - while (*(cntl_chr + j)) { - if (*(cntl_chr + j) == '%' && *(cntl_chr + j + 1) != '%') { - nc = 0; - if (VpIsNaN(a)) { - fprintf(fp, SZ_NaN); - nc += 8; - } - else if (VpIsPosInf(a)) { - fprintf(fp, SZ_INF); - nc += 8; - } - else if (VpIsNegInf(a)) { - fprintf(fp, SZ_NINF); - nc += 9; - } - else if (!VpIsZero(a)) { - if (BIGDECIMAL_NEGATIVE_P(a)) { - fprintf(fp, "-"); - ++nc; - } - nc += fprintf(fp, "0."); - switch (*(cntl_chr + j + 1)) { - default: - break; - - case '0': case 'z': - ZeroSup = 0; - ++j; - sep = cntl_chr[j] == 'z' ? BIGDECIMAL_COMPONENT_FIGURES : 10; - break; - } - for (i = 0; i < a->Prec; ++i) { - m = BASE1; - e = a->frac[i]; - while (m) { - nn = e / m; - if (!ZeroSup || nn) { - nc += fprintf(fp, "%lu", (unsigned long)nn); /* The leading zero(s) */ - /* as 0.00xx will not */ - /* be printed. */ - ++nd; - ZeroSup = 0; /* Set to print succeeding zeros */ - } - if (nd >= sep) { /* print ' ' after every 10 digits */ - nd = 0; - nc += fprintf(fp, " "); - } - e = e - nn * m; - m /= 10; - } - } - nc += fprintf(fp, "E%"PRIdSIZE, VpExponent10(a)); - nc += fprintf(fp, " (%"PRIdVALUE", %"PRIuSIZE", %"PRIuSIZE")", a->exponent, a->Prec, a->MaxPrec); - } - else { - nc += fprintf(fp, "0.0"); - } - } - else { - ++nc; - if (*(cntl_chr + j) == '\\') { - switch (*(cntl_chr + j + 1)) { - case 'n': - fprintf(fp, "\n"); - ++j; - break; - case 't': - fprintf(fp, "\t"); - ++j; - break; - case 'b': - fprintf(fp, "\n"); - ++j; - break; - default: - fprintf(fp, "%c", *(cntl_chr + j)); - break; - } - } - else { - fprintf(fp, "%c", *(cntl_chr + j)); - if (*(cntl_chr + j) == '%') ++j; - } - } - j++; - } - - return (int)nc; -} - -static void -VpFormatSt(char *psz, size_t fFmt) -{ - size_t ie, i, nf = 0; - char ch; - - if (fFmt == 0) return; - - ie = strlen(psz); - for (i = 0; i < ie; ++i) { - ch = psz[i]; - if (!ch) break; - if (ISSPACE(ch) || ch=='-' || ch=='+') continue; - if (ch == '.') { nf = 0; continue; } - if (ch == 'E' || ch == 'e') break; - - if (++nf > fFmt) { - memmove(psz + i + 1, psz + i, ie - i + 1); - ++ie; - nf = 0; - psz[i] = ' '; - } - } -} - -VP_EXPORT ssize_t -VpExponent10(Real *a) -{ - ssize_t ex; - size_t n; - - if (!VpHasVal(a)) return 0; - - ex = a->exponent * (ssize_t)BASE_FIG; - n = BASE1; - while ((a->frac[0] / n) == 0) { - --ex; - n /= 10; - } - return ex; -} - -VP_EXPORT void -VpSzMantissa(Real *a, char *buf, size_t buflen) -{ - size_t i, n, ZeroSup; - DECDIG_DBL m, e, nn; - - if (VpIsNaN(a)) { - snprintf(buf, buflen, SZ_NaN); - return; - } - if (VpIsPosInf(a)) { - snprintf(buf, buflen, SZ_INF); - return; - } - if (VpIsNegInf(a)) { - snprintf(buf, buflen, SZ_NINF); - return; - } - - ZeroSup = 1; /* Flag not to print the leading zeros as 0.00xxxxEnn */ - if (!VpIsZero(a)) { - if (BIGDECIMAL_NEGATIVE_P(a)) *buf++ = '-'; - n = a->Prec; - for (i = 0; i < n; ++i) { - m = BASE1; - e = a->frac[i]; - while (m) { - nn = e / m; - if (!ZeroSup || nn) { - snprintf(buf, buflen, "%lu", (unsigned long)nn); /* The leading zero(s) */ - buf += strlen(buf); - /* as 0.00xx will be ignored. */ - ZeroSup = 0; /* Set to print succeeding zeros */ - } - e = e - nn * m; - m /= 10; - } - } - *buf = 0; - while (buf[-1] == '0') *(--buf) = 0; - } - else { - if (VpIsPosZero(a)) snprintf(buf, buflen, "0"); - else snprintf(buf, buflen, "-0"); - } -} - -VP_EXPORT int -VpToSpecialString(Real *a, char *buf, size_t buflen, int fPlus) -/* fPlus = 0: default, 1: set ' ' before digits, 2: set '+' before digits. */ -{ - if (VpIsNaN(a)) { - snprintf(buf, buflen, SZ_NaN); - return 1; - } - - if (VpIsPosInf(a)) { - if (fPlus == 1) { - *buf++ = ' '; - } - else if (fPlus == 2) { - *buf++ = '+'; - } - snprintf(buf, buflen, SZ_INF); - return 1; - } - if (VpIsNegInf(a)) { - snprintf(buf, buflen, SZ_NINF); - return 1; - } - if (VpIsZero(a)) { - if (VpIsPosZero(a)) { - if (fPlus == 1) snprintf(buf, buflen, " 0.0"); - else if (fPlus == 2) snprintf(buf, buflen, "+0.0"); - else snprintf(buf, buflen, "0.0"); - } - else snprintf(buf, buflen, "-0.0"); - return 1; - } - return 0; -} - -VP_EXPORT void -VpToString(Real *a, char *buf, size_t buflen, size_t fFmt, int fPlus) -/* fPlus = 0: default, 1: set ' ' before digits, 2: set '+' before digits. */ -{ - size_t i, n, ZeroSup; - DECDIG shift, m, e, nn; - char *p = buf; - size_t plen = buflen; - ssize_t ex; - - if (VpToSpecialString(a, buf, buflen, fPlus)) return; - - ZeroSup = 1; /* Flag not to print the leading zeros as 0.00xxxxEnn */ - -#define ADVANCE(n) do { \ - if (plen < n) goto overflow; \ - p += n; \ - plen -= n; \ -} while (0) - - if (BIGDECIMAL_NEGATIVE_P(a)) { - *p = '-'; - ADVANCE(1); - } - else if (fPlus == 1) { - *p = ' '; - ADVANCE(1); - } - else if (fPlus == 2) { - *p = '+'; - ADVANCE(1); - } - - *p = '0'; ADVANCE(1); - *p = '.'; ADVANCE(1); - - n = a->Prec; - for (i = 0; i < n; ++i) { - m = BASE1; - e = a->frac[i]; - while (m) { - nn = e / m; - if (!ZeroSup || nn) { - /* The reading zero(s) */ - size_t n = (size_t)snprintf(p, plen, "%lu", (unsigned long)nn); - if (n > plen) goto overflow; - ADVANCE(n); - /* as 0.00xx will be ignored. */ - ZeroSup = 0; /* Set to print succeeding zeros */ - } - e = e - nn * m; - m /= 10; - } - } - - ex = a->exponent * (ssize_t)BASE_FIG; - shift = BASE1; - while (a->frac[0] / shift == 0) { - --ex; - shift /= 10; - } - while (p - 1 > buf && p[-1] == '0') { - *(--p) = '\0'; - ++plen; - } - snprintf(p, plen, "e%"PRIdSIZE, ex); - if (fFmt) VpFormatSt(buf, fFmt); - - overflow: - return; -#undef ADVANCE -} - -VP_EXPORT void -VpToFString(Real *a, char *buf, size_t buflen, size_t fFmt, int fPlus) -/* fPlus = 0: default, 1: set ' ' before digits, 2: set '+' before digits. */ -{ - size_t i, n; - DECDIG m, e; - char *p = buf; - size_t plen = buflen, delim = fFmt; - ssize_t ex; - - if (VpToSpecialString(a, buf, buflen, fPlus)) return; - -#define APPEND(c, group) do { \ - if (plen < 1) goto overflow; \ - if (group && delim == 0) { \ - *p = ' '; \ - p += 1; \ - plen -= 1; \ - } \ - if (plen < 1) goto overflow; \ - *p = c; \ - p += 1; \ - plen -= 1; \ - if (group) delim = (delim + 1) % fFmt; \ -} while (0) - - - if (BIGDECIMAL_NEGATIVE_P(a)) { - APPEND('-', false); - } - else if (fPlus == 1) { - APPEND(' ', false); - } - else if (fPlus == 2) { - APPEND('+', false); - } - - n = a->Prec; - ex = a->exponent; - if (ex <= 0) { - APPEND('0', false); - APPEND('.', false); - } - while (ex < 0) { - for (i=0; i < BASE_FIG; ++i) { - APPEND('0', fFmt > 0); - } - ++ex; - } - - for (i = 0; i < n; ++i) { - m = BASE1; - e = a->frac[i]; - if (i == 0 && ex > 0) { - for (delim = 0; e / m == 0; delim++) { - m /= 10; - } - if (fFmt > 0) { - delim = 2*fFmt - (ex * BASE_FIG - delim) % fFmt; - } - } - while (m && (e || (i < n - 1) || ex > 0)) { - APPEND((char)(e / m + '0'), fFmt > 0); - e %= m; - m /= 10; - } - if (--ex == 0) { - APPEND('.', false); - delim = fFmt; - } - } - - while (ex > 0) { - for (i=0; i < BASE_FIG; ++i) { - APPEND('0', fFmt > 0); - } - if (--ex == 0) { - APPEND('.', false); - } - } - - *p = '\0'; - if (p - 1 > buf && p[-1] == '.') { - snprintf(p, plen, "0"); - } - - overflow: - return; -#undef APPEND -} - -/* - * [Output] - * a[] ... variable to be assigned the value. - * [Input] - * int_chr[] ... integer part(may include '+/-'). - * ni ... number of characters in int_chr[],not including '+/-'. - * frac[] ... fraction part. - * nf ... number of characters in frac[]. - * exp_chr[] ... exponent part(including '+/-'). - * ne ... number of characters in exp_chr[],not including '+/-'. - */ -VP_EXPORT int -VpCtoV(Real *a, const char *int_chr, size_t ni, const char *frac, size_t nf, const char *exp_chr, size_t ne) -{ - size_t i, j, ind_a, ma, mi, me; - SIGNED_VALUE e, es, eb, ef; - int sign, signe, exponent_overflow; - - /* get exponent part */ - e = 0; - ma = a->MaxPrec; - mi = ni; - me = ne; - signe = 1; - exponent_overflow = 0; - memset(a->frac, 0, ma * sizeof(DECDIG)); - if (ne > 0) { - i = 0; - if (exp_chr[0] == '-') { - signe = -1; - ++i; - ++me; - } - else if (exp_chr[0] == '+') { - ++i; - ++me; - } - while (i < me) { - if (MUL_OVERFLOW_SIGNED_VALUE_P(e, (SIGNED_VALUE)BASE_FIG)) { - es = e; - goto exp_overflow; - } - es = e * (SIGNED_VALUE)BASE_FIG; - if (MUL_OVERFLOW_SIGNED_VALUE_P(e, 10) || - SIGNED_VALUE_MAX - (exp_chr[i] - '0') < e * 10) - goto exp_overflow; - e = e * 10 + exp_chr[i] - '0'; - if (MUL_OVERFLOW_SIGNED_VALUE_P(e, (SIGNED_VALUE)BASE_FIG)) - goto exp_overflow; - if (es > (SIGNED_VALUE)(e * BASE_FIG)) { - exp_overflow: - exponent_overflow = 1; - e = es; /* keep sign */ - break; - } - ++i; - } - } - - /* get integer part */ - i = 0; - sign = 1; - if (1 /*ni >= 0*/) { - if (int_chr[0] == '-') { - sign = -1; - ++i; - ++mi; - } - else if (int_chr[0] == '+') { - ++i; - ++mi; - } - } - - e = signe * e; /* e: The value of exponent part. */ - e = e + ni; /* set actual exponent size. */ - - if (e > 0) signe = 1; - else signe = -1; - - /* Adjust the exponent so that it is the multiple of BASE_FIG. */ - j = 0; - ef = 1; - while (ef) { - if (e >= 0) eb = e; - else eb = -e; - ef = eb / (SIGNED_VALUE)BASE_FIG; - ef = eb - ef * (SIGNED_VALUE)BASE_FIG; - if (ef) { - ++j; /* Means to add one more preceding zero */ - ++e; - } - } - - eb = e / (SIGNED_VALUE)BASE_FIG; - - if (exponent_overflow) { - int zero = 1; - for ( ; i < mi && zero; i++) zero = int_chr[i] == '0'; - for (i = 0; i < nf && zero; i++) zero = frac[i] == '0'; - if (!zero && signe > 0) { - VpSetInf(a, sign); - VpException(VP_EXCEPTION_INFINITY, "exponent overflow",0); - } - else VpSetZero(a, sign); - return 1; - } - - ind_a = 0; - while (i < mi) { - a->frac[ind_a] = 0; - while (j < BASE_FIG && i < mi) { - a->frac[ind_a] = a->frac[ind_a] * 10 + int_chr[i] - '0'; - ++j; - ++i; - } - if (i < mi) { - ++ind_a; - if (ind_a >= ma) goto over_flow; - j = 0; - } - } - - /* get fraction part */ - - i = 0; - while (i < nf) { - while (j < BASE_FIG && i < nf) { - a->frac[ind_a] = a->frac[ind_a] * 10 + frac[i] - '0'; - ++j; - ++i; - } - if (i < nf) { - ++ind_a; - if (ind_a >= ma) goto over_flow; - j = 0; - } - } - goto Final; - -over_flow: - rb_warn("Conversion from String to BigDecimal overflow (last few digits discarded)."); - -Final: - if (ind_a >= ma) ind_a = ma - 1; - while (j < BASE_FIG) { - a->frac[ind_a] = a->frac[ind_a] * 10; - ++j; - } - a->Prec = ind_a + 1; - a->exponent = eb; - VpSetSign(a, sign); - VpNmlz(a); - return 1; -} - -/* - * [Input] - * *m ... Real - * [Output] - * *d ... fraction part of m(d = 0.xxxxxxx). where # of 'x's is fig. - * *e ... exponent of m. - * BIGDECIMAL_DOUBLE_FIGURES ... Number of digits in a double variable. - * - * m -> d*10**e, 0Prec); - *d = 0.0; - div = 1.; - while (ind_m < mm) { - div /= (double)BASE; - *d = *d + (double)m->frac[ind_m++] * div; - } - *e = m->exponent * (SIGNED_VALUE)BASE_FIG; - *d *= VpGetSign(m); - -Exit: -#ifdef BIGDECIMAL_DEBUG - if (gfDebug) { - VPrint(stdout, " VpVtoD: m=%\n", m); - printf(" d=%e * 10 **%ld\n", *d, *e); - printf(" BIGDECIMAL_DOUBLE_FIGURES = %d\n", BIGDECIMAL_DOUBLE_FIGURES); - } -#endif /*BIGDECIMAL_DEBUG */ - return f; -} - -/* - * m <- d - */ -VP_EXPORT void -VpDtoV(Real *m, double d) -{ - size_t ind_m, mm; - SIGNED_VALUE ne; - DECDIG i; - double val, val2; - - if (isnan(d)) { - VpSetNaN(m); - goto Exit; - } - if (isinf(d)) { - if (d > 0.0) VpSetPosInf(m); - else VpSetNegInf(m); - goto Exit; - } - - if (d == 0.0) { - VpSetZero(m, 1); - goto Exit; - } - val = (d > 0.) ? d : -d; - ne = 0; - if (val >= 1.0) { - while (val >= 1.0) { - val /= (double)BASE; - ++ne; - } - } - else { - val2 = 1.0 / (double)BASE; - while (val < val2) { - val *= (double)BASE; - --ne; - } - } - /* Now val = 0.xxxxx*BASE**ne */ - - mm = m->MaxPrec; - memset(m->frac, 0, mm * sizeof(DECDIG)); - for (ind_m = 0; val > 0.0 && ind_m < mm; ind_m++) { - val *= (double)BASE; - i = (DECDIG)val; - val -= (double)i; - m->frac[ind_m] = i; - } - if (ind_m >= mm) ind_m = mm - 1; - VpSetSign(m, (d > 0.0) ? 1 : -1); - m->Prec = ind_m + 1; - m->exponent = ne; - - VpInternalRound(m, 0, (m->Prec > 0) ? m->frac[m->Prec-1] : 0, - (DECDIG)(val*(double)BASE)); - -Exit: -#ifdef BIGDECIMAL_DEBUG - if (gfDebug) { - printf("VpDtoV d=%30.30e\n", d); - VPrint(stdout, " m=%\n", m); - } -#endif /* BIGDECIMAL_DEBUG */ - return; -} - -/* - * m <- ival - */ -#if 0 /* unused */ -VP_EXPORT void -VpItoV(Real *m, SIGNED_VALUE ival) -{ - size_t mm, ind_m; - size_t val, v1, v2, v; - int isign; - SIGNED_VALUE ne; - - if (ival == 0) { - VpSetZero(m, 1); - goto Exit; - } - isign = 1; - val = ival; - if (ival < 0) { - isign = -1; - val =(size_t)(-ival); - } - ne = 0; - ind_m = 0; - mm = m->MaxPrec; - while (ind_m < mm) { - m->frac[ind_m] = 0; - ++ind_m; - } - ind_m = 0; - while (val > 0) { - if (val) { - v1 = val; - v2 = 1; - while (v1 >= BASE) { - v1 /= BASE; - v2 *= BASE; - } - val = val - v2 * v1; - v = v1; - } - else { - v = 0; - } - m->frac[ind_m] = v; - ++ind_m; - ++ne; - } - m->Prec = ind_m - 1; - m->exponent = ne; - VpSetSign(m, isign); - VpNmlz(m); - -Exit: -#ifdef BIGDECIMAL_DEBUG - if (gfDebug) { - printf(" VpItoV i=%d\n", ival); - VPrint(stdout, " m=%\n", m); - } -#endif /* BIGDECIMAL_DEBUG */ - return; -} -#endif - -/* - * y = SQRT(x), y*y - x =>0 - */ -VP_EXPORT int -VpSqrt(Real *y, Real *x) -{ - Real *f = NULL; - Real *r = NULL; - size_t y_prec; - SIGNED_VALUE n, e; - ssize_t nr; - double val; - - /* Zero or +Infinity ? */ - if (VpIsZero(x) || VpIsPosInf(x)) { - VpAsgn(y,x,1); - goto Exit; - } - - /* Negative ? */ - if (BIGDECIMAL_NEGATIVE_P(x)) { - VpSetNaN(y); - return VpException(VP_EXCEPTION_OP, "sqrt of negative value", 0); - } - - /* NaN ? */ - if (VpIsNaN(x)) { - VpSetNaN(y); - return VpException(VP_EXCEPTION_OP, "sqrt of 'NaN'(Not a Number)", 0); - } - - /* One ? */ - if (VpIsOne(x)) { - VpSetOne(y); - goto Exit; - } - - n = (SIGNED_VALUE)y->MaxPrec; - if (x->MaxPrec > (size_t)n) n = (ssize_t)x->MaxPrec; - - /* allocate temporally variables */ - /* TODO: reconsider MaxPrec of f and r */ - f = NewOneNolimit(1, y->MaxPrec * (BASE_FIG + 2)); - r = NewOneNolimit(1, (n + n) * (BASE_FIG + 2)); - - nr = 0; - y_prec = y->MaxPrec; - - VpVtoD(&val, &e, x); /* val <- x */ - e /= (SIGNED_VALUE)BASE_FIG; - n = e / 2; - if (e - n * 2 != 0) { - val /= BASE; - n = (e + 1) / 2; - } - VpDtoV(y, sqrt(val)); /* y <- sqrt(val) */ - y->exponent += n; - n = (SIGNED_VALUE)roomof(BIGDECIMAL_DOUBLE_FIGURES, BASE_FIG); - y->MaxPrec = Min((size_t)n , y_prec); - f->MaxPrec = y->MaxPrec + 1; - n = (SIGNED_VALUE)(y_prec * BASE_FIG); - if (n < (SIGNED_VALUE)maxnr) n = (SIGNED_VALUE)maxnr; - - /* - * Perform: y_{n+1} = (y_n - x/y_n) / 2 - */ - do { - y->MaxPrec *= 2; - if (y->MaxPrec > y_prec) y->MaxPrec = y_prec; - f->MaxPrec = y->MaxPrec; - VpDivd(f, r, x, y); /* f = x/y */ - VpAddSub(r, f, y, -1); /* r = f - y */ - VpMult(f, VpConstPt5, r); /* f = 0.5*r */ - if (VpIsZero(f)) - goto converge; - VpAddSub(r, f, y, 1); /* r = y + f */ - VpAsgn(y, r, 1); /* y = r */ - } while (++nr < n); - -#ifdef BIGDECIMAL_DEBUG - if (gfDebug) { - printf("ERROR(VpSqrt): did not converge within %ld iterations.\n", nr); - } -#endif /* BIGDECIMAL_DEBUG */ - y->MaxPrec = y_prec; - -converge: - VpChangeSign(y, 1); -#ifdef BIGDECIMAL_DEBUG - if (gfDebug) { - VpMult(r, y, y); - VpAddSub(f, x, r, -1); - printf("VpSqrt: iterations = %"PRIdSIZE"\n", nr); - VPrint(stdout, " y =% \n", y); - VPrint(stdout, " x =% \n", x); - VPrint(stdout, " x-y*y = % \n", f); - } -#endif /* BIGDECIMAL_DEBUG */ - y->MaxPrec = y_prec; - -Exit: - rbd_free_struct(f); - rbd_free_struct(r); - return 1; -} - -/* - * Round relatively from the decimal point. - * f: rounding mode - * nf: digit location to round from the decimal point. - */ -VP_EXPORT int -VpMidRound(Real *y, unsigned short f, ssize_t nf) -{ - /* fracf: any positive digit under rounding position? */ - /* fracf_1further: any positive digits under one further than the rounding position? */ - /* exptoadd: number of digits needed to compensate negative nf */ - int fracf, fracf_1further; - ssize_t n,i,ix,ioffset, exptoadd; - DECDIG v, shifter; - DECDIG div; - - nf += y->exponent * (ssize_t)BASE_FIG; - exptoadd=0; - if (nf < 0) { - /* rounding position too left(large). */ - if (f != VP_ROUND_CEIL && f != VP_ROUND_FLOOR) { - VpSetZero(y, VpGetSign(y)); /* truncate everything */ - return 0; - } - exptoadd = -nf; - nf = 0; - } - - ix = nf / (ssize_t)BASE_FIG; - if ((size_t)ix >= y->Prec) return 0; /* rounding position too right(small). */ - v = y->frac[ix]; - - ioffset = nf - ix*(ssize_t)BASE_FIG; - n = (ssize_t)BASE_FIG - ioffset - 1; - for (shifter = 1, i = 0; i < n; ++i) shifter *= 10; - - /* so the representation used (in y->frac) is an array of DECDIG, where - each DECDIG contains a value between 0 and BASE-1, consisting of BASE_FIG - decimal places. - - (that numbers of decimal places are typed as ssize_t is somewhat confusing) - - nf is now position (in decimal places) of the digit from the start of - the array. - - ix is the position (in DECDIGs) of the DECDIG containing the decimal digit, - from the start of the array. - - v is the value of this DECDIG - - ioffset is the number of extra decimal places along of this decimal digit - within v. - - n is the number of decimal digits remaining within v after this decimal digit - shifter is 10**n, - - v % shifter are the remaining digits within v - v % (shifter * 10) are the digit together with the remaining digits within v - v / shifter are the digit's predecessors together with the digit - div = v / shifter / 10 is just the digit's precessors - (v / shifter) - div*10 is just the digit, which is what v ends up being reassigned to. - */ - - fracf = (v % (shifter * 10) > 0); - fracf_1further = ((v % shifter) > 0); - - v /= shifter; - div = v / 10; - v = v - div*10; - /* now v is just the digit required. - now fracf is whether the digit or any of the remaining digits within v are non-zero - now fracf_1further is whether any of the remaining digits within v are non-zero - */ - - /* now check all the remaining DECDIGs for zero-ness a whole DECDIG at a time. - if we spot any non-zeroness, that means that we found a positive digit under - rounding position, and we also found a positive digit under one further than - the rounding position, so both searches (to see if any such non-zero digit exists) - can stop */ - - for (i = ix + 1; (size_t)i < y->Prec; i++) { - if (y->frac[i] % BASE) { - fracf = fracf_1further = 1; - break; - } - } - - /* now fracf = does any positive digit exist under the rounding position? - now fracf_1further = does any positive digit exist under one further than the - rounding position? - now v = the first digit under the rounding position */ - - /* drop digits after pointed digit */ - memset(y->frac + ix + 1, 0, (y->Prec - (ix + 1)) * sizeof(DECDIG)); - - switch (f) { - case VP_ROUND_DOWN: /* Truncate */ - break; - case VP_ROUND_UP: /* Roundup */ - if (fracf) ++div; - break; - case VP_ROUND_HALF_UP: - if (v>=5) ++div; - break; - case VP_ROUND_HALF_DOWN: - if (v > 5 || (v == 5 && fracf_1further)) ++div; - break; - case VP_ROUND_CEIL: - if (fracf && BIGDECIMAL_POSITIVE_P(y)) ++div; - break; - case VP_ROUND_FLOOR: - if (fracf && BIGDECIMAL_NEGATIVE_P(y)) ++div; - break; - case VP_ROUND_HALF_EVEN: /* Banker's rounding */ - if (v > 5) ++div; - else if (v == 5) { - if (fracf_1further) { - ++div; - } - else { - if (ioffset == 0) { - /* v is the first decimal digit of its DECDIG; - need to grab the previous DECDIG if present - to check for evenness of the previous decimal - digit (which is same as that of the DECDIG since - base 10 has a factor of 2) */ - if (ix && (y->frac[ix-1] % 2)) ++div; - } - else { - if (div % 2) ++div; - } - } - } - break; - } - for (i = 0; i <= n; ++i) div *= 10; - if (div >= BASE) { - if (ix) { - y->frac[ix] = 0; - VpRdup(y, ix); - } - else { - short s = VpGetSign(y); - SIGNED_VALUE e = y->exponent; - VpSetOne(y); - VpSetSign(y, s); - y->exponent = e + 1; - } - } - else { - y->frac[ix] = div; - VpNmlz(y); - } - if (exptoadd > 0) { - y->exponent += (SIGNED_VALUE)(exptoadd / BASE_FIG); - exptoadd %= (ssize_t)BASE_FIG; - for (i = 0; i < exptoadd; i++) { - y->frac[0] *= 10; - if (y->frac[0] >= BASE) { - y->frac[0] /= BASE; - y->exponent++; - } - } - } - return 1; -} - -VP_EXPORT int -VpLeftRound(Real *y, unsigned short f, ssize_t nf) -/* - * Round from the left hand side of the digits. - */ -{ - DECDIG v; - if (!VpHasVal(y)) return 0; /* Unable to round */ - v = y->frac[0]; - nf -= VpExponent(y) * (ssize_t)BASE_FIG; - while ((v /= 10) != 0) nf--; - nf += (ssize_t)BASE_FIG-1; - return VpMidRound(y, f, nf); -} - -VP_EXPORT int -VpActiveRound(Real *y, Real *x, unsigned short f, ssize_t nf) -{ - /* First,assign whole value in truncation mode */ - if (VpAsgn(y, x, 10) <= 1) return 0; /* Zero,NaN,or Infinity */ - return VpMidRound(y, f, nf); -} - -static int -VpLimitRound(Real *c, size_t ixDigit) -{ - size_t ix = VpGetPrecLimit(); - if (!VpNmlz(c)) return -1; - if (!ix) return 0; - if (!ixDigit) ixDigit = c->Prec-1; - if ((ix + BASE_FIG - 1) / BASE_FIG > ixDigit + 1) return 0; - return VpLeftRound(c, VpGetRoundMode(), (ssize_t)ix); -} - -/* If I understand correctly, this is only ever used to round off the final decimal - digit of precision */ -static void -VpInternalRound(Real *c, size_t ixDigit, DECDIG vPrev, DECDIG v) -{ - int f = 0; - - unsigned short const rounding_mode = VpGetRoundMode(); - - if (VpLimitRound(c, ixDigit)) return; - if (!v) return; - - v /= BASE1; - switch (rounding_mode) { - case VP_ROUND_DOWN: - break; - case VP_ROUND_UP: - if (v) f = 1; - break; - case VP_ROUND_HALF_UP: - if (v >= 5) f = 1; - break; - case VP_ROUND_HALF_DOWN: - /* this is ok - because this is the last digit of precision, - the case where v == 5 and some further digits are nonzero - will never occur */ - if (v >= 6) f = 1; - break; - case VP_ROUND_CEIL: - if (v && BIGDECIMAL_POSITIVE_P(c)) f = 1; - break; - case VP_ROUND_FLOOR: - if (v && BIGDECIMAL_NEGATIVE_P(c)) f = 1; - break; - case VP_ROUND_HALF_EVEN: /* Banker's rounding */ - /* as per VP_ROUND_HALF_DOWN, because this is the last digit of precision, - there is no case to worry about where v == 5 and some further digits are nonzero */ - if (v > 5) f = 1; - else if (v == 5 && vPrev % 2) f = 1; - break; - } - if (f) { - VpRdup(c, ixDigit); - VpNmlz(c); - } -} - -/* - * Rounds up m(plus one to final digit of m). - */ -static int -VpRdup(Real *m, size_t ind_m) -{ - DECDIG carry; - - if (!ind_m) ind_m = m->Prec; - - carry = 1; - while (carry > 0 && ind_m--) { - m->frac[ind_m] += carry; - if (m->frac[ind_m] >= BASE) m->frac[ind_m] -= BASE; - else carry = 0; - } - if (carry > 0) { /* Overflow,count exponent and set fraction part be 1 */ - if (!AddExponent(m, 1)) return 0; - m->Prec = m->frac[0] = 1; - } - else { - VpNmlz(m); - } - return 1; -} - -/* - * y = x - fix(x) - */ -VP_EXPORT void -VpFrac(Real *y, Real *x) -{ - size_t my, ind_y, ind_x; - - if (!VpHasVal(x)) { - VpAsgn(y, x, 1); - goto Exit; - } - - if (x->exponent > 0 && (size_t)x->exponent >= x->Prec) { - VpSetZero(y, VpGetSign(x)); - goto Exit; - } - else if (x->exponent <= 0) { - VpAsgn(y, x, 1); - goto Exit; - } - - /* satisfy: x->exponent > 0 */ - - y->Prec = x->Prec - (size_t)x->exponent; - y->Prec = Min(y->Prec, y->MaxPrec); - y->exponent = 0; - VpSetSign(y, VpGetSign(x)); - ind_y = 0; - my = y->Prec; - ind_x = x->exponent; - while (ind_y < my) { - y->frac[ind_y] = x->frac[ind_x]; - ++ind_y; - ++ind_x; - } - VpNmlz(y); - -Exit: -#ifdef BIGDECIMAL_DEBUG - if (gfDebug) { - VPrint(stdout, "VpFrac y=%\n", y); - VPrint(stdout, " x=%\n", x); - } -#endif /* BIGDECIMAL_DEBUG */ - return; -} - -/* - * y = x ** n - */ -VP_EXPORT int -VpPowerByInt(Real *y, Real *x, SIGNED_VALUE n) -{ - size_t s, ss; - ssize_t sign; - Real *w1 = NULL; - Real *w2 = NULL; - - if (VpIsZero(x)) { - if (n == 0) { - VpSetOne(y); - goto Exit; - } - sign = VpGetSign(x); - if (n < 0) { - n = -n; - if (sign < 0) sign = (n % 2) ? -1 : 1; - VpSetInf(y, sign); - } - else { - if (sign < 0) sign = (n % 2) ? -1 : 1; - VpSetZero(y,sign); - } - goto Exit; - } - if (VpIsNaN(x)) { - VpSetNaN(y); - goto Exit; - } - if (VpIsInf(x)) { - if (n == 0) { - VpSetOne(y); - goto Exit; - } - if (n > 0) { - VpSetInf(y, (n % 2 == 0 || VpIsPosInf(x)) ? 1 : -1); - goto Exit; - } - VpSetZero(y, (n % 2 == 0 || VpIsPosInf(x)) ? 1 : -1); - goto Exit; - } - - if (x->exponent == 1 && x->Prec == 1 && x->frac[0] == 1) { - /* abs(x) = 1 */ - VpSetOne(y); - if (BIGDECIMAL_POSITIVE_P(x)) goto Exit; - if ((n % 2) == 0) goto Exit; - VpSetSign(y, -1); - goto Exit; - } - - if (n > 0) sign = 1; - else if (n < 0) { - sign = -1; - n = -n; - } - else { - VpSetOne(y); - goto Exit; - } - - /* Allocate working variables */ - /* TODO: reconsider MaxPrec of w1 and w2 */ - w1 = NewZeroNolimit(1, (y->MaxPrec + 2) * BASE_FIG); - w2 = NewZeroNolimit(1, (w1->MaxPrec * 2 + 1) * BASE_FIG); - - /* calculation start */ - - VpAsgn(y, x, 1); - --n; - while (n > 0) { - VpAsgn(w1, x, 1); - s = 1; - while (ss = s, (s += s) <= (size_t)n) { - VpMult(w2, w1, w1); - VpAsgn(w1, w2, 1); - } - n -= (SIGNED_VALUE)ss; - VpMult(w2, y, w1); - VpAsgn(y, w2, 1); - } - if (sign < 0) { - VpDivd(w1, w2, VpConstOne, y); - VpAsgn(y, w1, 1); - } - -Exit: -#ifdef BIGDECIMAL_DEBUG - if (gfDebug) { - VPrint(stdout, "VpPowerByInt y=%\n", y); - VPrint(stdout, "VpPowerByInt x=%\n", x); - printf(" n=%"PRIdVALUE"\n", n); - } -#endif /* BIGDECIMAL_DEBUG */ - rbd_free_struct(w2); - rbd_free_struct(w1); - return 1; -} - -#ifdef BIGDECIMAL_DEBUG -int -VpVarCheck(Real * v) -/* - * Checks the validity of the Real variable v. - * [Input] - * v ... Real *, variable to be checked. - * [Returns] - * 0 ... correct v. - * other ... error - */ -{ - size_t i; - - if (v->MaxPrec == 0) { - printf("ERROR(VpVarCheck): Illegal Max. Precision(=%"PRIuSIZE")\n", - v->MaxPrec); - return 1; - } - if (v->Prec == 0 || v->Prec > v->MaxPrec) { - printf("ERROR(VpVarCheck): Illegal Precision(=%"PRIuSIZE")\n", v->Prec); - printf(" Max. Prec.=%"PRIuSIZE"\n", v->MaxPrec); - return 2; - } - for (i = 0; i < v->Prec; ++i) { - if (v->frac[i] >= BASE) { - printf("ERROR(VpVarCheck): Illegal fraction\n"); - printf(" Frac[%"PRIuSIZE"]=%"PRIuDECDIG"\n", i, v->frac[i]); - printf(" Prec. =%"PRIuSIZE"\n", v->Prec); - printf(" Exp. =%"PRIdVALUE"\n", v->exponent); - printf(" BASE =%"PRIuDECDIG"\n", BASE); - return 3; - } - } - return 0; -} -#endif /* BIGDECIMAL_DEBUG */ diff --git a/ext/bigdecimal/bigdecimal.gemspec b/ext/bigdecimal/bigdecimal.gemspec deleted file mode 100644 index f9f3b456168531..00000000000000 --- a/ext/bigdecimal/bigdecimal.gemspec +++ /dev/null @@ -1,54 +0,0 @@ -# coding: utf-8 - -name = File.basename(__FILE__, '.*') -source_version = ["", "ext/#{name}/"].find do |dir| - begin - break File.foreach(File.join(__dir__, "#{dir}#{name}.c")) {|line| - break $1.sub("-", ".") if /^#define\s+#{name.upcase}_VERSION\s+"(.+)"/o =~ line - } - rescue Errno::ENOENT - end -end or raise "can't find #{name.upcase}_VERSION" - -Gem::Specification.new do |s| - s.name = name - s.version = source_version - s.authors = ["Kenta Murata", "Zachary Scott", "Shigeo Kobayashi"] - s.email = ["mrkn@mrkn.jp"] - - s.summary = "Arbitrary-precision decimal floating-point number library." - s.description = "This library provides arbitrary-precision decimal floating-point number class." - s.homepage = "https://github.com/ruby/bigdecimal" - s.licenses = ["Ruby", "BSD-2-Clause"] - - s.require_paths = %w[lib] - s.files = %w[ - bigdecimal.gemspec - lib/bigdecimal.rb - lib/bigdecimal/jacobian.rb - lib/bigdecimal/ludcmp.rb - lib/bigdecimal/math.rb - lib/bigdecimal/newton.rb - lib/bigdecimal/util.rb - sample/linear.rb - sample/nlsolve.rb - sample/pi.rb - ] - if Gem::Platform === s.platform and s.platform =~ 'java' or RUBY_ENGINE == 'jruby' - s.platform = 'java' - else - s.extensions = %w[ext/bigdecimal/extconf.rb] - s.files += %w[ - ext/bigdecimal/bigdecimal.c - ext/bigdecimal/bigdecimal.h - ext/bigdecimal/bits.h - ext/bigdecimal/feature.h - ext/bigdecimal/missing.c - ext/bigdecimal/missing.h - ext/bigdecimal/missing/dtoa.c - ext/bigdecimal/static_assert.h - ] - end - - s.required_ruby_version = Gem::Requirement.new(">= 2.5.0") -end diff --git a/ext/bigdecimal/bigdecimal.h b/ext/bigdecimal/bigdecimal.h deleted file mode 100644 index 54fed811fb6abb..00000000000000 --- a/ext/bigdecimal/bigdecimal.h +++ /dev/null @@ -1,313 +0,0 @@ -/* - * - * Ruby BigDecimal(Variable decimal precision) extension library. - * - * Copyright(C) 2002 by Shigeo Kobayashi(shigeo@tinyforest.gr.jp) - * - */ - -#ifndef RUBY_BIG_DECIMAL_H -#define RUBY_BIG_DECIMAL_H 1 - -#define RUBY_NO_OLD_COMPATIBILITY -#include "ruby/ruby.h" -#include "missing.h" - -#ifdef HAVE_FLOAT_H -# include -#endif - -#ifdef HAVE_INT64_T -# define DECDIG uint32_t -# define DECDIG_DBL uint64_t -# define DECDIG_DBL_SIGNED int64_t -# define SIZEOF_DECDIG 4 -# define PRI_DECDIG_PREFIX "" -# ifdef PRI_LL_PREFIX -# define PRI_DECDIG_DBL_PREFIX PRI_LL_PREFIX -# else -# define PRI_DECDIG_DBL_PREFIX "l" -# endif -#else -# define DECDIG uint16_t -# define DECDIG_DBL uint32_t -# define DECDIG_DBL_SIGNED int32_t -# define SIZEOF_DECDIG 2 -# define PRI_DECDIG_PREFIX "h" -# define PRI_DECDIG_DBL_PREFIX "" -#endif - -#define PRIdDECDIG PRI_DECDIG_PREFIX"d" -#define PRIiDECDIG PRI_DECDIG_PREFIX"i" -#define PRIoDECDIG PRI_DECDIG_PREFIX"o" -#define PRIuDECDIG PRI_DECDIG_PREFIX"u" -#define PRIxDECDIG PRI_DECDIG_PREFIX"x" -#define PRIXDECDIG PRI_DECDIG_PREFIX"X" - -#define PRIdDECDIG_DBL PRI_DECDIG_DBL_PREFIX"d" -#define PRIiDECDIG_DBL PRI_DECDIG_DBL_PREFIX"i" -#define PRIoDECDIG_DBL PRI_DECDIG_DBL_PREFIX"o" -#define PRIuDECDIG_DBL PRI_DECDIG_DBL_PREFIX"u" -#define PRIxDECDIG_DBL PRI_DECDIG_DBL_PREFIX"x" -#define PRIXDECDIG_DBL PRI_DECDIG_DBL_PREFIX"X" - -#if SIZEOF_DECDIG == 4 -# define BIGDECIMAL_BASE ((DECDIG)1000000000U) -# define BIGDECIMAL_COMPONENT_FIGURES 9 -/* - * The number of components required for a 64-bit integer. - * - * INT64_MAX: 9_223372036_854775807 - * UINT64_MAX: 18_446744073_709551615 - */ -# define BIGDECIMAL_INT64_MAX_LENGTH 3 - -#elif SIZEOF_DECDIG == 2 -# define BIGDECIMAL_BASE ((DECDIG)10000U) -# define BIGDECIMAL_COMPONENT_FIGURES 4 -/* - * The number of components required for a 64-bit integer. - * - * INT64_MAX: 922_3372_0368_5477_5807 - * UINT64_MAX: 1844_6744_0737_0955_1615 - */ -# define BIGDECIMAL_INT64_MAX_LENGTH 5 - -#else -# error Unknown size of DECDIG -#endif - -#define BIGDECIMAL_DOUBLE_FIGURES (1+DBL_DIG) - -#if defined(__cplusplus) -extern "C" { -#if 0 -} /* satisfy cc-mode */ -#endif -#endif - -extern VALUE rb_cBigDecimal; - -/* - * NaN & Infinity - */ -#define SZ_NaN "NaN" -#define SZ_INF "Infinity" -#define SZ_PINF "+Infinity" -#define SZ_NINF "-Infinity" - -/* - * #define VP_EXPORT other than static to let VP_ routines - * be called from outside of this module. - */ -#define VP_EXPORT static - -/* Exception mode */ -#define VP_EXCEPTION_ALL ((unsigned short)0x00FF) -#define VP_EXCEPTION_INFINITY ((unsigned short)0x0001) -#define VP_EXCEPTION_NaN ((unsigned short)0x0002) -#define VP_EXCEPTION_UNDERFLOW ((unsigned short)0x0004) -#define VP_EXCEPTION_OVERFLOW ((unsigned short)0x0001) /* 0x0008) */ -#define VP_EXCEPTION_ZERODIVIDE ((unsigned short)0x0010) - -/* Following 2 exceptions can't controlled by user */ -#define VP_EXCEPTION_OP ((unsigned short)0x0020) - -#define BIGDECIMAL_EXCEPTION_MODE_DEFAULT 0U - -/* This is used in BigDecimal#mode */ -#define VP_ROUND_MODE ((unsigned short)0x0100) - -/* Rounding mode */ -#define VP_ROUND_UP RBD_ROUND_UP -#define VP_ROUND_DOWN RBD_ROUND_DOWN -#define VP_ROUND_HALF_UP RBD_ROUND_HALF_UP -#define VP_ROUND_HALF_DOWN RBD_ROUND_HALF_DOWN -#define VP_ROUND_CEIL RBD_ROUND_CEIL -#define VP_ROUND_FLOOR RBD_ROUND_FLOOR -#define VP_ROUND_HALF_EVEN RBD_ROUND_HALF_EVEN - -enum rbd_rounding_mode { - RBD_ROUND_UP = 1, - RBD_ROUND_DOWN = 2, - RBD_ROUND_HALF_UP = 3, - RBD_ROUND_HALF_DOWN = 4, - RBD_ROUND_CEIL = 5, - RBD_ROUND_FLOOR = 6, - RBD_ROUND_HALF_EVEN = 7, - - RBD_ROUND_DEFAULT = RBD_ROUND_HALF_UP, - RBD_ROUND_TRUNCATE = RBD_ROUND_DOWN, - RBD_ROUND_BANKER = RBD_ROUND_HALF_EVEN, - RBD_ROUND_CEILING = RBD_ROUND_CEIL -}; - -#define BIGDECIMAL_ROUNDING_MODE_DEFAULT VP_ROUND_HALF_UP - -/* Sign flag */ -#define VP_SIGN_NaN 0 /* NaN */ -#define VP_SIGN_POSITIVE_ZERO 1 /* Positive zero */ -#define VP_SIGN_NEGATIVE_ZERO -1 /* Negative zero */ -#define VP_SIGN_POSITIVE_FINITE 2 /* Positive finite number */ -#define VP_SIGN_NEGATIVE_FINITE -2 /* Negative finite number */ -#define VP_SIGN_POSITIVE_INFINITE 3 /* Positive infinite number */ -#define VP_SIGN_NEGATIVE_INFINITE -3 /* Negative infinite number */ - -/* The size of fraction part array */ -#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) -#define FLEXIBLE_ARRAY_SIZE /* */ -#elif defined(__GNUC__) && !defined(__STRICT_ANSI__) -#define FLEXIBLE_ARRAY_SIZE 0 -#else -#define FLEXIBLE_ARRAY_SIZE 1 -#endif - -/* - * VP representation - * r = 0.xxxxxxxxx *BASE**exponent - */ -typedef struct { - VALUE obj; /* Back pointer(VALUE) for Ruby object. */ - size_t MaxPrec; /* Maximum precision size */ - /* This is the actual size of frac[] */ - /*(frac[0] to frac[MaxPrec] are available). */ - size_t Prec; /* Current precision size. */ - /* This indicates how much the */ - /* array frac[] is actually used. */ - SIGNED_VALUE exponent; /* Exponent part. */ - short sign; /* Attributes of the value. */ - /* - * ==0 : NaN - * 1 : Positive zero - * -1 : Negative zero - * 2 : Positive number - * -2 : Negative number - * 3 : Positive infinite number - * -3 : Negative infinite number - */ - short flag; /* Not used in vp_routines,space for user. */ - DECDIG frac[FLEXIBLE_ARRAY_SIZE]; /* Array of fraction part. */ -} Real; - -/* - * ------------------ - * EXPORTables. - * ------------------ - */ - -VP_EXPORT Real *VpNewRbClass(size_t mx, char const *str, VALUE klass, bool strict_p, bool raise_exception); - -VP_EXPORT Real *VpCreateRbObject(size_t mx, const char *str, bool raise_exception); - -#define VpBaseFig() BIGDECIMAL_COMPONENT_FIGURES -#define VpDblFig() BIGDECIMAL_DOUBLE_FIGURES -#define VpBaseVal() BIGDECIMAL_BASE - -/* Zero,Inf,NaN (isinf(),isnan() used to check) */ -VP_EXPORT double VpGetDoubleNaN(void); -VP_EXPORT double VpGetDoublePosInf(void); -VP_EXPORT double VpGetDoubleNegInf(void); -VP_EXPORT double VpGetDoubleNegZero(void); - -/* These 2 functions added at v1.1.7 */ -VP_EXPORT size_t VpGetPrecLimit(void); -VP_EXPORT size_t VpSetPrecLimit(size_t n); - -/* Round mode */ -VP_EXPORT int VpIsRoundMode(unsigned short n); -VP_EXPORT unsigned short VpGetRoundMode(void); -VP_EXPORT unsigned short VpSetRoundMode(unsigned short n); - -VP_EXPORT int VpException(unsigned short f,const char *str,int always); -#if 0 /* unused */ -VP_EXPORT int VpIsNegDoubleZero(double v); -#endif -VP_EXPORT size_t VpNumOfChars(Real *vp,const char *pszFmt); -VP_EXPORT size_t VpInit(DECDIG BaseVal); -VP_EXPORT Real *VpAlloc(size_t mx, const char *szVal, int strict_p, int exc); -VP_EXPORT size_t VpAsgn(Real *c, Real *a, int isw); -VP_EXPORT size_t VpAddSub(Real *c,Real *a,Real *b,int operation); -VP_EXPORT size_t VpMult(Real *c,Real *a,Real *b); -VP_EXPORT size_t VpDivd(Real *c,Real *r,Real *a,Real *b); -VP_EXPORT int VpComp(Real *a,Real *b); -VP_EXPORT ssize_t VpExponent10(Real *a); -VP_EXPORT void VpSzMantissa(Real *a, char *buf, size_t bufsize); -VP_EXPORT int VpToSpecialString(Real *a, char *buf, size_t bufsize, int fPlus); -VP_EXPORT void VpToString(Real *a, char *buf, size_t bufsize, size_t fFmt, int fPlus); -VP_EXPORT void VpToFString(Real *a, char *buf, size_t bufsize, size_t fFmt, int fPlus); -VP_EXPORT int VpCtoV(Real *a, const char *int_chr, size_t ni, const char *frac, size_t nf, const char *exp_chr, size_t ne); -VP_EXPORT int VpVtoD(double *d, SIGNED_VALUE *e, Real *m); -VP_EXPORT void VpDtoV(Real *m,double d); -#if 0 /* unused */ -VP_EXPORT void VpItoV(Real *m,S_INT ival); -#endif -VP_EXPORT int VpSqrt(Real *y,Real *x); -VP_EXPORT int VpActiveRound(Real *y, Real *x, unsigned short f, ssize_t il); -VP_EXPORT int VpMidRound(Real *y, unsigned short f, ssize_t nf); -VP_EXPORT int VpLeftRound(Real *y, unsigned short f, ssize_t nf); -VP_EXPORT void VpFrac(Real *y, Real *x); -VP_EXPORT int VpPowerByInt(Real *y, Real *x, SIGNED_VALUE n); -#define VpPower VpPowerByInt - -/* VP constants */ -VP_EXPORT Real *VpOne(void); - -/* - * ------------------ - * MACRO definitions. - * ------------------ - */ -#define Abs(a) (((a)>= 0)?(a):(-(a))) -#define Max(a, b) (((a)>(b))?(a):(b)) -#define Min(a, b) (((a)>(b))?(b):(a)) - -#define VpMaxPrec(a) ((a)->MaxPrec) -#define VpPrec(a) ((a)->Prec) -#define VpGetFlag(a) ((a)->flag) - -/* Sign */ - -/* VpGetSign(a) returns 1,-1 if a>0,a<0 respectively */ -#define VpGetSign(a) (((a)->sign>0)?1:(-1)) -/* Change sign of a to a>0,a<0 if s = 1,-1 respectively */ -#define VpChangeSign(a,s) {if((s)>0) (a)->sign=(short)Abs((ssize_t)(a)->sign);else (a)->sign=-(short)Abs((ssize_t)(a)->sign);} -/* Sets sign of a to a>0,a<0 if s = 1,-1 respectively */ -#define VpSetSign(a,s) {if((s)>0) (a)->sign=(short)VP_SIGN_POSITIVE_FINITE;else (a)->sign=(short)VP_SIGN_NEGATIVE_FINITE;} - -/* 1 */ -#define VpSetOne(a) {(a)->Prec=(a)->exponent=(a)->frac[0]=1;(a)->sign=VP_SIGN_POSITIVE_FINITE;} - -/* ZEROs */ -#define VpIsPosZero(a) ((a)->sign==VP_SIGN_POSITIVE_ZERO) -#define VpIsNegZero(a) ((a)->sign==VP_SIGN_NEGATIVE_ZERO) -#define VpIsZero(a) (VpIsPosZero(a) || VpIsNegZero(a)) -#define VpSetPosZero(a) ((a)->frac[0]=0,(a)->Prec=1,(a)->sign=VP_SIGN_POSITIVE_ZERO) -#define VpSetNegZero(a) ((a)->frac[0]=0,(a)->Prec=1,(a)->sign=VP_SIGN_NEGATIVE_ZERO) -#define VpSetZero(a,s) (void)(((s)>0)?VpSetPosZero(a):VpSetNegZero(a)) - -/* NaN */ -#define VpIsNaN(a) ((a)->sign==VP_SIGN_NaN) -#define VpSetNaN(a) ((a)->frac[0]=0,(a)->Prec=1,(a)->sign=VP_SIGN_NaN) - -/* Infinity */ -#define VpIsPosInf(a) ((a)->sign==VP_SIGN_POSITIVE_INFINITE) -#define VpIsNegInf(a) ((a)->sign==VP_SIGN_NEGATIVE_INFINITE) -#define VpIsInf(a) (VpIsPosInf(a) || VpIsNegInf(a)) -#define VpIsDef(a) ( !(VpIsNaN(a)||VpIsInf(a)) ) -#define VpSetPosInf(a) ((a)->frac[0]=0,(a)->Prec=1,(a)->sign=VP_SIGN_POSITIVE_INFINITE) -#define VpSetNegInf(a) ((a)->frac[0]=0,(a)->Prec=1,(a)->sign=VP_SIGN_NEGATIVE_INFINITE) -#define VpSetInf(a,s) (void)(((s)>0)?VpSetPosInf(a):VpSetNegInf(a)) -#define VpHasVal(a) (a->frac[0]) -#define VpIsOne(a) ((a->Prec==1)&&(a->frac[0]==1)&&(a->exponent==1)) -#define VpExponent(a) (a->exponent) -#ifdef BIGDECIMAL_DEBUG -int VpVarCheck(Real * v); -#endif /* BIGDECIMAL_DEBUG */ - -#if defined(__cplusplus) -#if 0 -{ /* satisfy cc-mode */ -#endif -} /* extern "C" { */ -#endif -#endif /* RUBY_BIG_DECIMAL_H */ diff --git a/ext/bigdecimal/bits.h b/ext/bigdecimal/bits.h deleted file mode 100644 index 6e1e4776e39599..00000000000000 --- a/ext/bigdecimal/bits.h +++ /dev/null @@ -1,141 +0,0 @@ -#ifndef BIGDECIMAL_BITS_H -#define BIGDECIMAL_BITS_H - -#include "feature.h" -#include "static_assert.h" - -#if defined(__x86_64__) && defined(HAVE_X86INTRIN_H) -# include /* for _lzcnt_u64, etc. */ -#elif defined(_MSC_VER) && defined(HAVE_INTRIN_H) -# include /* for the following intrinsics */ -#endif - -#if defined(_MSC_VER) && defined(__AVX2__) -# pragma intrinsic(__lzcnt) -# pragma intrinsic(__lzcnt64) -#endif - -#define numberof(array) ((int)(sizeof(array) / sizeof((array)[0]))) -#define roomof(x, y) (((x) + (y) - 1) / (y)) -#define type_roomof(x, y) roomof(sizeof(x), sizeof(y)) - -#define MUL_OVERFLOW_SIGNED_INTEGER_P(a, b, min, max) ( \ - (a) == 0 ? 0 : \ - (a) == -1 ? (b) < -(max) : \ - (a) > 0 ? \ - ((b) > 0 ? (max) / (a) < (b) : (min) / (a) > (b)) : \ - ((b) > 0 ? (min) / (a) < (b) : (max) / (a) > (b))) - -#ifdef HAVE_UINT128_T -# define bit_length(x) \ - (unsigned int) \ - (sizeof(x) <= sizeof(int32_t) ? 32 - nlz_int32((uint32_t)(x)) : \ - sizeof(x) <= sizeof(int64_t) ? 64 - nlz_int64((uint64_t)(x)) : \ - 128 - nlz_int128((uint128_t)(x))) -#else -# define bit_length(x) \ - (unsigned int) \ - (sizeof(x) <= sizeof(int32_t) ? 32 - nlz_int32((uint32_t)(x)) : \ - 64 - nlz_int64((uint64_t)(x))) -#endif - -static inline unsigned nlz_int32(uint32_t x); -static inline unsigned nlz_int64(uint64_t x); -#ifdef HAVE_UINT128_T -static inline unsigned nlz_int128(uint128_t x); -#endif - -static inline unsigned int -nlz_int32(uint32_t x) -{ -#if defined(_MSC_VER) && defined(__AVX2__) && defined(HAVE___LZCNT) - /* Note: It seems there is no such thing like __LZCNT__ predefined in MSVC. - * AMD CPUs have had this instruction for decades (since K10) but for - * Intel, Haswell is the oldest one. We need to use __AVX2__ for maximum - * safety. */ - return (unsigned int)__lzcnt(x); - -#elif defined(__x86_64__) && defined(__LZCNT__) && defined(HAVE__LZCNT_U32) - return (unsigned int)_lzcnt_u32(x); - -#elif defined(_MSC_VER) && defined(HAVE__BITSCANREVERSE) - unsigned long r; - return _BitScanReverse(&r, x) ? (31 - (int)r) : 32; - -#elif __has_builtin(__builtin_clz) - STATIC_ASSERT(sizeof_int, sizeof(int) * CHAR_BIT == 32); - return x ? (unsigned int)__builtin_clz(x) : 32; - -#else - uint32_t y; - unsigned n = 32; - y = x >> 16; if (y) {n -= 16; x = y;} - y = x >> 8; if (y) {n -= 8; x = y;} - y = x >> 4; if (y) {n -= 4; x = y;} - y = x >> 2; if (y) {n -= 2; x = y;} - y = x >> 1; if (y) {return n - 2;} - return (unsigned int)(n - x); -#endif -} - -static inline unsigned int -nlz_int64(uint64_t x) -{ -#if defined(_MSC_VER) && defined(__AVX2__) && defined(HAVE___LZCNT64) - return (unsigned int)__lzcnt64(x); - -#elif defined(__x86_64__) && defined(__LZCNT__) && defined(HAVE__LZCNT_U64) - return (unsigned int)_lzcnt_u64(x); - -#elif defined(_WIN64) && defined(_MSC_VER) && defined(HAVE__BITSCANREVERSE64) - unsigned long r; - return _BitScanReverse64(&r, x) ? (63u - (unsigned int)r) : 64; - -#elif __has_builtin(__builtin_clzl) && __has_builtin(__builtin_clzll) && !(defined(__sun) && defined(__sparc)) - if (x == 0) { - return 64; - } - else if (sizeof(long) * CHAR_BIT == 64) { - return (unsigned int)__builtin_clzl((unsigned long)x); - } - else if (sizeof(long long) * CHAR_BIT == 64) { - return (unsigned int)__builtin_clzll((unsigned long long)x); - } - else { - /* :FIXME: Is there a way to make this branch a compile-time error? */ - __builtin_unreachable(); - } - -#else - uint64_t y; - unsigned int n = 64; - y = x >> 32; if (y) {n -= 32; x = y;} - y = x >> 16; if (y) {n -= 16; x = y;} - y = x >> 8; if (y) {n -= 8; x = y;} - y = x >> 4; if (y) {n -= 4; x = y;} - y = x >> 2; if (y) {n -= 2; x = y;} - y = x >> 1; if (y) {return n - 2;} - return (unsigned int)(n - x); - -#endif -} - -#ifdef HAVE_UINT128_T -static inline unsigned int -nlz_int128(uint128_t x) -{ - uint64_t y = (uint64_t)(x >> 64); - - if (x == 0) { - return 128; - } - else if (y == 0) { - return (unsigned int)nlz_int64(x) + 64; - } - else { - return (unsigned int)nlz_int64(y); - } -} -#endif - -#endif /* BIGDECIMAL_BITS_H */ diff --git a/ext/bigdecimal/depend b/ext/bigdecimal/depend deleted file mode 100644 index a2455ebbda6cba..00000000000000 --- a/ext/bigdecimal/depend +++ /dev/null @@ -1,327 +0,0 @@ -Makefile: $(BIGDECIMAL_RB) - -# AUTOGENERATED DEPENDENCIES START -bigdecimal.o: $(RUBY_EXTCONF_H) -bigdecimal.o: $(arch_hdrdir)/ruby/config.h -bigdecimal.o: $(hdrdir)/ruby/assert.h -bigdecimal.o: $(hdrdir)/ruby/backward/2/assume.h -bigdecimal.o: $(hdrdir)/ruby/backward/2/attributes.h -bigdecimal.o: $(hdrdir)/ruby/backward/2/bool.h -bigdecimal.o: $(hdrdir)/ruby/backward/2/inttypes.h -bigdecimal.o: $(hdrdir)/ruby/backward/2/limits.h -bigdecimal.o: $(hdrdir)/ruby/backward/2/long_long.h -bigdecimal.o: $(hdrdir)/ruby/backward/2/stdalign.h -bigdecimal.o: $(hdrdir)/ruby/backward/2/stdarg.h -bigdecimal.o: $(hdrdir)/ruby/defines.h -bigdecimal.o: $(hdrdir)/ruby/intern.h -bigdecimal.o: $(hdrdir)/ruby/internal/abi.h -bigdecimal.o: $(hdrdir)/ruby/internal/anyargs.h -bigdecimal.o: $(hdrdir)/ruby/internal/arithmetic.h -bigdecimal.o: $(hdrdir)/ruby/internal/arithmetic/char.h -bigdecimal.o: $(hdrdir)/ruby/internal/arithmetic/double.h -bigdecimal.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h -bigdecimal.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h -bigdecimal.o: $(hdrdir)/ruby/internal/arithmetic/int.h -bigdecimal.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h -bigdecimal.o: $(hdrdir)/ruby/internal/arithmetic/long.h -bigdecimal.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h -bigdecimal.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h -bigdecimal.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h -bigdecimal.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h -bigdecimal.o: $(hdrdir)/ruby/internal/arithmetic/short.h -bigdecimal.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h -bigdecimal.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h -bigdecimal.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h -bigdecimal.o: $(hdrdir)/ruby/internal/assume.h -bigdecimal.o: $(hdrdir)/ruby/internal/attr/alloc_size.h -bigdecimal.o: $(hdrdir)/ruby/internal/attr/artificial.h -bigdecimal.o: $(hdrdir)/ruby/internal/attr/cold.h -bigdecimal.o: $(hdrdir)/ruby/internal/attr/const.h -bigdecimal.o: $(hdrdir)/ruby/internal/attr/constexpr.h -bigdecimal.o: $(hdrdir)/ruby/internal/attr/deprecated.h -bigdecimal.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h -bigdecimal.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h -bigdecimal.o: $(hdrdir)/ruby/internal/attr/error.h -bigdecimal.o: $(hdrdir)/ruby/internal/attr/flag_enum.h -bigdecimal.o: $(hdrdir)/ruby/internal/attr/forceinline.h -bigdecimal.o: $(hdrdir)/ruby/internal/attr/format.h -bigdecimal.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h -bigdecimal.o: $(hdrdir)/ruby/internal/attr/noalias.h -bigdecimal.o: $(hdrdir)/ruby/internal/attr/nodiscard.h -bigdecimal.o: $(hdrdir)/ruby/internal/attr/noexcept.h -bigdecimal.o: $(hdrdir)/ruby/internal/attr/noinline.h -bigdecimal.o: $(hdrdir)/ruby/internal/attr/nonnull.h -bigdecimal.o: $(hdrdir)/ruby/internal/attr/noreturn.h -bigdecimal.o: $(hdrdir)/ruby/internal/attr/packed_struct.h -bigdecimal.o: $(hdrdir)/ruby/internal/attr/pure.h -bigdecimal.o: $(hdrdir)/ruby/internal/attr/restrict.h -bigdecimal.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h -bigdecimal.o: $(hdrdir)/ruby/internal/attr/warning.h -bigdecimal.o: $(hdrdir)/ruby/internal/attr/weakref.h -bigdecimal.o: $(hdrdir)/ruby/internal/cast.h -bigdecimal.o: $(hdrdir)/ruby/internal/compiler_is.h -bigdecimal.o: $(hdrdir)/ruby/internal/compiler_is/apple.h -bigdecimal.o: $(hdrdir)/ruby/internal/compiler_is/clang.h -bigdecimal.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h -bigdecimal.o: $(hdrdir)/ruby/internal/compiler_is/intel.h -bigdecimal.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h -bigdecimal.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h -bigdecimal.o: $(hdrdir)/ruby/internal/compiler_since.h -bigdecimal.o: $(hdrdir)/ruby/internal/config.h -bigdecimal.o: $(hdrdir)/ruby/internal/constant_p.h -bigdecimal.o: $(hdrdir)/ruby/internal/core.h -bigdecimal.o: $(hdrdir)/ruby/internal/core/rarray.h -bigdecimal.o: $(hdrdir)/ruby/internal/core/rbasic.h -bigdecimal.o: $(hdrdir)/ruby/internal/core/rbignum.h -bigdecimal.o: $(hdrdir)/ruby/internal/core/rclass.h -bigdecimal.o: $(hdrdir)/ruby/internal/core/rdata.h -bigdecimal.o: $(hdrdir)/ruby/internal/core/rfile.h -bigdecimal.o: $(hdrdir)/ruby/internal/core/rhash.h -bigdecimal.o: $(hdrdir)/ruby/internal/core/robject.h -bigdecimal.o: $(hdrdir)/ruby/internal/core/rregexp.h -bigdecimal.o: $(hdrdir)/ruby/internal/core/rstring.h -bigdecimal.o: $(hdrdir)/ruby/internal/core/rstruct.h -bigdecimal.o: $(hdrdir)/ruby/internal/core/rtypeddata.h -bigdecimal.o: $(hdrdir)/ruby/internal/ctype.h -bigdecimal.o: $(hdrdir)/ruby/internal/dllexport.h -bigdecimal.o: $(hdrdir)/ruby/internal/dosish.h -bigdecimal.o: $(hdrdir)/ruby/internal/error.h -bigdecimal.o: $(hdrdir)/ruby/internal/eval.h -bigdecimal.o: $(hdrdir)/ruby/internal/event.h -bigdecimal.o: $(hdrdir)/ruby/internal/fl_type.h -bigdecimal.o: $(hdrdir)/ruby/internal/gc.h -bigdecimal.o: $(hdrdir)/ruby/internal/glob.h -bigdecimal.o: $(hdrdir)/ruby/internal/globals.h -bigdecimal.o: $(hdrdir)/ruby/internal/has/attribute.h -bigdecimal.o: $(hdrdir)/ruby/internal/has/builtin.h -bigdecimal.o: $(hdrdir)/ruby/internal/has/c_attribute.h -bigdecimal.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h -bigdecimal.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h -bigdecimal.o: $(hdrdir)/ruby/internal/has/extension.h -bigdecimal.o: $(hdrdir)/ruby/internal/has/feature.h -bigdecimal.o: $(hdrdir)/ruby/internal/has/warning.h -bigdecimal.o: $(hdrdir)/ruby/internal/intern/array.h -bigdecimal.o: $(hdrdir)/ruby/internal/intern/bignum.h -bigdecimal.o: $(hdrdir)/ruby/internal/intern/class.h -bigdecimal.o: $(hdrdir)/ruby/internal/intern/compar.h -bigdecimal.o: $(hdrdir)/ruby/internal/intern/complex.h -bigdecimal.o: $(hdrdir)/ruby/internal/intern/cont.h -bigdecimal.o: $(hdrdir)/ruby/internal/intern/dir.h -bigdecimal.o: $(hdrdir)/ruby/internal/intern/enum.h -bigdecimal.o: $(hdrdir)/ruby/internal/intern/enumerator.h -bigdecimal.o: $(hdrdir)/ruby/internal/intern/error.h -bigdecimal.o: $(hdrdir)/ruby/internal/intern/eval.h -bigdecimal.o: $(hdrdir)/ruby/internal/intern/file.h -bigdecimal.o: $(hdrdir)/ruby/internal/intern/hash.h -bigdecimal.o: $(hdrdir)/ruby/internal/intern/io.h -bigdecimal.o: $(hdrdir)/ruby/internal/intern/load.h -bigdecimal.o: $(hdrdir)/ruby/internal/intern/marshal.h -bigdecimal.o: $(hdrdir)/ruby/internal/intern/numeric.h -bigdecimal.o: $(hdrdir)/ruby/internal/intern/object.h -bigdecimal.o: $(hdrdir)/ruby/internal/intern/parse.h -bigdecimal.o: $(hdrdir)/ruby/internal/intern/proc.h -bigdecimal.o: $(hdrdir)/ruby/internal/intern/process.h -bigdecimal.o: $(hdrdir)/ruby/internal/intern/random.h -bigdecimal.o: $(hdrdir)/ruby/internal/intern/range.h -bigdecimal.o: $(hdrdir)/ruby/internal/intern/rational.h -bigdecimal.o: $(hdrdir)/ruby/internal/intern/re.h -bigdecimal.o: $(hdrdir)/ruby/internal/intern/ruby.h -bigdecimal.o: $(hdrdir)/ruby/internal/intern/select.h -bigdecimal.o: $(hdrdir)/ruby/internal/intern/select/largesize.h -bigdecimal.o: $(hdrdir)/ruby/internal/intern/signal.h -bigdecimal.o: $(hdrdir)/ruby/internal/intern/sprintf.h -bigdecimal.o: $(hdrdir)/ruby/internal/intern/string.h -bigdecimal.o: $(hdrdir)/ruby/internal/intern/struct.h -bigdecimal.o: $(hdrdir)/ruby/internal/intern/thread.h -bigdecimal.o: $(hdrdir)/ruby/internal/intern/time.h -bigdecimal.o: $(hdrdir)/ruby/internal/intern/variable.h -bigdecimal.o: $(hdrdir)/ruby/internal/intern/vm.h -bigdecimal.o: $(hdrdir)/ruby/internal/interpreter.h -bigdecimal.o: $(hdrdir)/ruby/internal/iterator.h -bigdecimal.o: $(hdrdir)/ruby/internal/memory.h -bigdecimal.o: $(hdrdir)/ruby/internal/method.h -bigdecimal.o: $(hdrdir)/ruby/internal/module.h -bigdecimal.o: $(hdrdir)/ruby/internal/newobj.h -bigdecimal.o: $(hdrdir)/ruby/internal/scan_args.h -bigdecimal.o: $(hdrdir)/ruby/internal/special_consts.h -bigdecimal.o: $(hdrdir)/ruby/internal/static_assert.h -bigdecimal.o: $(hdrdir)/ruby/internal/stdalign.h -bigdecimal.o: $(hdrdir)/ruby/internal/stdbool.h -bigdecimal.o: $(hdrdir)/ruby/internal/symbol.h -bigdecimal.o: $(hdrdir)/ruby/internal/value.h -bigdecimal.o: $(hdrdir)/ruby/internal/value_type.h -bigdecimal.o: $(hdrdir)/ruby/internal/variable.h -bigdecimal.o: $(hdrdir)/ruby/internal/warning_push.h -bigdecimal.o: $(hdrdir)/ruby/internal/xmalloc.h -bigdecimal.o: $(hdrdir)/ruby/missing.h -bigdecimal.o: $(hdrdir)/ruby/ruby.h -bigdecimal.o: $(hdrdir)/ruby/st.h -bigdecimal.o: $(hdrdir)/ruby/subst.h -bigdecimal.o: $(hdrdir)/ruby/util.h -bigdecimal.o: bigdecimal.c -bigdecimal.o: bigdecimal.h -bigdecimal.o: bits.h -bigdecimal.o: feature.h -bigdecimal.o: missing.h -bigdecimal.o: static_assert.h -missing.o: $(RUBY_EXTCONF_H) -missing.o: $(arch_hdrdir)/ruby/config.h -missing.o: $(hdrdir)/ruby/assert.h -missing.o: $(hdrdir)/ruby/atomic.h -missing.o: $(hdrdir)/ruby/backward.h -missing.o: $(hdrdir)/ruby/backward/2/assume.h -missing.o: $(hdrdir)/ruby/backward/2/attributes.h -missing.o: $(hdrdir)/ruby/backward/2/bool.h -missing.o: $(hdrdir)/ruby/backward/2/inttypes.h -missing.o: $(hdrdir)/ruby/backward/2/limits.h -missing.o: $(hdrdir)/ruby/backward/2/long_long.h -missing.o: $(hdrdir)/ruby/backward/2/stdalign.h -missing.o: $(hdrdir)/ruby/backward/2/stdarg.h -missing.o: $(hdrdir)/ruby/defines.h -missing.o: $(hdrdir)/ruby/intern.h -missing.o: $(hdrdir)/ruby/internal/abi.h -missing.o: $(hdrdir)/ruby/internal/anyargs.h -missing.o: $(hdrdir)/ruby/internal/arithmetic.h -missing.o: $(hdrdir)/ruby/internal/arithmetic/char.h -missing.o: $(hdrdir)/ruby/internal/arithmetic/double.h -missing.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h -missing.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h -missing.o: $(hdrdir)/ruby/internal/arithmetic/int.h -missing.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h -missing.o: $(hdrdir)/ruby/internal/arithmetic/long.h -missing.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h -missing.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h -missing.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h -missing.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h -missing.o: $(hdrdir)/ruby/internal/arithmetic/short.h -missing.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h -missing.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h -missing.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h -missing.o: $(hdrdir)/ruby/internal/assume.h -missing.o: $(hdrdir)/ruby/internal/attr/alloc_size.h -missing.o: $(hdrdir)/ruby/internal/attr/artificial.h -missing.o: $(hdrdir)/ruby/internal/attr/cold.h -missing.o: $(hdrdir)/ruby/internal/attr/const.h -missing.o: $(hdrdir)/ruby/internal/attr/constexpr.h -missing.o: $(hdrdir)/ruby/internal/attr/deprecated.h -missing.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h -missing.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h -missing.o: $(hdrdir)/ruby/internal/attr/error.h -missing.o: $(hdrdir)/ruby/internal/attr/flag_enum.h -missing.o: $(hdrdir)/ruby/internal/attr/forceinline.h -missing.o: $(hdrdir)/ruby/internal/attr/format.h -missing.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h -missing.o: $(hdrdir)/ruby/internal/attr/noalias.h -missing.o: $(hdrdir)/ruby/internal/attr/nodiscard.h -missing.o: $(hdrdir)/ruby/internal/attr/noexcept.h -missing.o: $(hdrdir)/ruby/internal/attr/noinline.h -missing.o: $(hdrdir)/ruby/internal/attr/nonnull.h -missing.o: $(hdrdir)/ruby/internal/attr/noreturn.h -missing.o: $(hdrdir)/ruby/internal/attr/packed_struct.h -missing.o: $(hdrdir)/ruby/internal/attr/pure.h -missing.o: $(hdrdir)/ruby/internal/attr/restrict.h -missing.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h -missing.o: $(hdrdir)/ruby/internal/attr/warning.h -missing.o: $(hdrdir)/ruby/internal/attr/weakref.h -missing.o: $(hdrdir)/ruby/internal/cast.h -missing.o: $(hdrdir)/ruby/internal/compiler_is.h -missing.o: $(hdrdir)/ruby/internal/compiler_is/apple.h -missing.o: $(hdrdir)/ruby/internal/compiler_is/clang.h -missing.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h -missing.o: $(hdrdir)/ruby/internal/compiler_is/intel.h -missing.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h -missing.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h -missing.o: $(hdrdir)/ruby/internal/compiler_since.h -missing.o: $(hdrdir)/ruby/internal/config.h -missing.o: $(hdrdir)/ruby/internal/constant_p.h -missing.o: $(hdrdir)/ruby/internal/core.h -missing.o: $(hdrdir)/ruby/internal/core/rarray.h -missing.o: $(hdrdir)/ruby/internal/core/rbasic.h -missing.o: $(hdrdir)/ruby/internal/core/rbignum.h -missing.o: $(hdrdir)/ruby/internal/core/rclass.h -missing.o: $(hdrdir)/ruby/internal/core/rdata.h -missing.o: $(hdrdir)/ruby/internal/core/rfile.h -missing.o: $(hdrdir)/ruby/internal/core/rhash.h -missing.o: $(hdrdir)/ruby/internal/core/robject.h -missing.o: $(hdrdir)/ruby/internal/core/rregexp.h -missing.o: $(hdrdir)/ruby/internal/core/rstring.h -missing.o: $(hdrdir)/ruby/internal/core/rstruct.h -missing.o: $(hdrdir)/ruby/internal/core/rtypeddata.h -missing.o: $(hdrdir)/ruby/internal/ctype.h -missing.o: $(hdrdir)/ruby/internal/dllexport.h -missing.o: $(hdrdir)/ruby/internal/dosish.h -missing.o: $(hdrdir)/ruby/internal/error.h -missing.o: $(hdrdir)/ruby/internal/eval.h -missing.o: $(hdrdir)/ruby/internal/event.h -missing.o: $(hdrdir)/ruby/internal/fl_type.h -missing.o: $(hdrdir)/ruby/internal/gc.h -missing.o: $(hdrdir)/ruby/internal/glob.h -missing.o: $(hdrdir)/ruby/internal/globals.h -missing.o: $(hdrdir)/ruby/internal/has/attribute.h -missing.o: $(hdrdir)/ruby/internal/has/builtin.h -missing.o: $(hdrdir)/ruby/internal/has/c_attribute.h -missing.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h -missing.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h -missing.o: $(hdrdir)/ruby/internal/has/extension.h -missing.o: $(hdrdir)/ruby/internal/has/feature.h -missing.o: $(hdrdir)/ruby/internal/has/warning.h -missing.o: $(hdrdir)/ruby/internal/intern/array.h -missing.o: $(hdrdir)/ruby/internal/intern/bignum.h -missing.o: $(hdrdir)/ruby/internal/intern/class.h -missing.o: $(hdrdir)/ruby/internal/intern/compar.h -missing.o: $(hdrdir)/ruby/internal/intern/complex.h -missing.o: $(hdrdir)/ruby/internal/intern/cont.h -missing.o: $(hdrdir)/ruby/internal/intern/dir.h -missing.o: $(hdrdir)/ruby/internal/intern/enum.h -missing.o: $(hdrdir)/ruby/internal/intern/enumerator.h -missing.o: $(hdrdir)/ruby/internal/intern/error.h -missing.o: $(hdrdir)/ruby/internal/intern/eval.h -missing.o: $(hdrdir)/ruby/internal/intern/file.h -missing.o: $(hdrdir)/ruby/internal/intern/hash.h -missing.o: $(hdrdir)/ruby/internal/intern/io.h -missing.o: $(hdrdir)/ruby/internal/intern/load.h -missing.o: $(hdrdir)/ruby/internal/intern/marshal.h -missing.o: $(hdrdir)/ruby/internal/intern/numeric.h -missing.o: $(hdrdir)/ruby/internal/intern/object.h -missing.o: $(hdrdir)/ruby/internal/intern/parse.h -missing.o: $(hdrdir)/ruby/internal/intern/proc.h -missing.o: $(hdrdir)/ruby/internal/intern/process.h -missing.o: $(hdrdir)/ruby/internal/intern/random.h -missing.o: $(hdrdir)/ruby/internal/intern/range.h -missing.o: $(hdrdir)/ruby/internal/intern/rational.h -missing.o: $(hdrdir)/ruby/internal/intern/re.h -missing.o: $(hdrdir)/ruby/internal/intern/ruby.h -missing.o: $(hdrdir)/ruby/internal/intern/select.h -missing.o: $(hdrdir)/ruby/internal/intern/select/largesize.h -missing.o: $(hdrdir)/ruby/internal/intern/signal.h -missing.o: $(hdrdir)/ruby/internal/intern/sprintf.h -missing.o: $(hdrdir)/ruby/internal/intern/string.h -missing.o: $(hdrdir)/ruby/internal/intern/struct.h -missing.o: $(hdrdir)/ruby/internal/intern/thread.h -missing.o: $(hdrdir)/ruby/internal/intern/time.h -missing.o: $(hdrdir)/ruby/internal/intern/variable.h -missing.o: $(hdrdir)/ruby/internal/intern/vm.h -missing.o: $(hdrdir)/ruby/internal/interpreter.h -missing.o: $(hdrdir)/ruby/internal/iterator.h -missing.o: $(hdrdir)/ruby/internal/memory.h -missing.o: $(hdrdir)/ruby/internal/method.h -missing.o: $(hdrdir)/ruby/internal/module.h -missing.o: $(hdrdir)/ruby/internal/newobj.h -missing.o: $(hdrdir)/ruby/internal/scan_args.h -missing.o: $(hdrdir)/ruby/internal/special_consts.h -missing.o: $(hdrdir)/ruby/internal/static_assert.h -missing.o: $(hdrdir)/ruby/internal/stdalign.h -missing.o: $(hdrdir)/ruby/internal/stdbool.h -missing.o: $(hdrdir)/ruby/internal/symbol.h -missing.o: $(hdrdir)/ruby/internal/value.h -missing.o: $(hdrdir)/ruby/internal/value_type.h -missing.o: $(hdrdir)/ruby/internal/variable.h -missing.o: $(hdrdir)/ruby/internal/warning_push.h -missing.o: $(hdrdir)/ruby/internal/xmalloc.h -missing.o: $(hdrdir)/ruby/missing.h -missing.o: $(hdrdir)/ruby/ruby.h -missing.o: $(hdrdir)/ruby/st.h -missing.o: $(hdrdir)/ruby/subst.h -missing.o: missing.c -missing.o: missing/dtoa.c -# AUTOGENERATED DEPENDENCIES END diff --git a/ext/bigdecimal/extconf.rb b/ext/bigdecimal/extconf.rb deleted file mode 100644 index 23904ed60e3dd9..00000000000000 --- a/ext/bigdecimal/extconf.rb +++ /dev/null @@ -1,62 +0,0 @@ -# frozen_string_literal: false -require 'mkmf' - -def have_builtin_func(name, check_expr, opt = "", &b) - checking_for checking_message(name.funcall_style, nil, opt) do - if try_compile(< -#endif - -#ifdef RBIMPL_HAS_BUILTIN -# define BIGDECIMAL_HAS_BUILTIN(...) RBIMPL_HAS_BUILTIN(__VA_ARGS__) - -#else -# /* The following section is copied from CRuby's builtin.h */ -# -# ifdef __has_builtin -# if defined(__INTEL_COMPILER) -# /* :TODO: Intel C Compiler has __has_builtin (since 19.1 maybe?), and is -# * reportedly broken. We have to skip them. However the situation can -# * change. They might improve someday. We need to revisit here later. */ -# elif defined(__GNUC__) && ! __has_builtin(__builtin_alloca) -# /* FreeBSD's defines its own *broken* version of -# * __has_builtin. Cygwin copied that content to be a victim of the -# * broken-ness. We don't take them into account. */ -# else -# define HAVE___HAS_BUILTIN 1 -# endif -# endif -# -# if defined(HAVE___HAS_BUILTIN) -# define BIGDECIMAL_HAS_BUILTIN(_) __has_builtin(_) -# -# elif defined(__GNUC__) -# define BIGDECIMAL_HAS_BUILTIN(_) BIGDECIMAL_HAS_BUILTIN_ ## _ -# if defined(__GNUC__) && (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 6)) -# define BIGDECIMAL_HAS_BUILTIN___builtin_clz 1 -# define BIGDECIMAL_HAS_BUILTIN___builtin_clzl 1 -# else -# define BIGDECIMAL_HAS_BUILTIN___builtin_clz 0 -# define BIGDECIMAL_HAS_BUILTIN___builtin_clzl 0 -# endif -# elif defined(_MSC_VER) -# define BIGDECIMAL_HAS_BUILTIN(_) 0 -# -# else -# define BIGDECIMAL_HAS_BUILTIN(_) BIGDECIMAL_HAS_BUILTIN_ ## _ -# define BIGDECIMAL_HAS_BUILTIN___builtin_clz HAVE_BUILTIN___BUILTIN_CLZ -# define BIGDECIMAL_HAS_BUILTIN___builtin_clzl HAVE_BUILTIN___BUILTIN_CLZL -# endif -#endif /* RBIMPL_HAS_BUILTIN */ - -#ifndef __has_builtin -# define __has_builtin(...) BIGDECIMAL_HAS_BUILTIN(__VA_ARGS__) -#endif - -#endif /* BIGDECIMAL_HAS_FEATURE_H */ diff --git a/ext/bigdecimal/lib/bigdecimal.rb b/ext/bigdecimal/lib/bigdecimal.rb deleted file mode 100644 index 82b3e1b7b98808..00000000000000 --- a/ext/bigdecimal/lib/bigdecimal.rb +++ /dev/null @@ -1,5 +0,0 @@ -if RUBY_ENGINE == 'jruby' - JRuby::Util.load_ext("org.jruby.ext.bigdecimal.BigDecimalLibrary") -else - require 'bigdecimal.so' -end diff --git a/ext/bigdecimal/lib/bigdecimal/jacobian.rb b/ext/bigdecimal/lib/bigdecimal/jacobian.rb deleted file mode 100644 index 4448024c74285f..00000000000000 --- a/ext/bigdecimal/lib/bigdecimal/jacobian.rb +++ /dev/null @@ -1,90 +0,0 @@ -# frozen_string_literal: false - -require 'bigdecimal' - -# require 'bigdecimal/jacobian' -# -# Provides methods to compute the Jacobian matrix of a set of equations at a -# point x. In the methods below: -# -# f is an Object which is used to compute the Jacobian matrix of the equations. -# It must provide the following methods: -# -# f.values(x):: returns the values of all functions at x -# -# f.zero:: returns 0.0 -# f.one:: returns 1.0 -# f.two:: returns 2.0 -# f.ten:: returns 10.0 -# -# f.eps:: returns the convergence criterion (epsilon value) used to determine whether two values are considered equal. If |a-b| < epsilon, the two values are considered equal. -# -# x is the point at which to compute the Jacobian. -# -# fx is f.values(x). -# -module Jacobian - module_function - - # Determines the equality of two numbers by comparing to zero, or using the epsilon value - def isEqual(a,b,zero=0.0,e=1.0e-8) - aa = a.abs - bb = b.abs - if aa == zero && bb == zero then - true - else - if ((a-b)/(aa+bb)).abs < e then - true - else - false - end - end - end - - - # Computes the derivative of +f[i]+ at +x[i]+. - # +fx+ is the value of +f+ at +x+. - def dfdxi(f,fx,x,i) - nRetry = 0 - n = x.size - xSave = x[i] - ok = 0 - ratio = f.ten*f.ten*f.ten - dx = x[i].abs/ratio - dx = fx[i].abs/ratio if isEqual(dx,f.zero,f.zero,f.eps) - dx = f.one/f.ten if isEqual(dx,f.zero,f.zero,f.eps) - until ok>0 do - deriv = [] - nRetry += 1 - if nRetry > 100 - raise "Singular Jacobian matrix. No change at x[" + i.to_s + "]" - end - dx = dx*f.two - x[i] += dx - fxNew = f.values(x) - for j in 0...n do - if !isEqual(fxNew[j],fx[j],f.zero,f.eps) then - ok += 1 - deriv <<= (fxNew[j]-fx[j])/dx - else - deriv <<= f.zero - end - end - x[i] = xSave - end - deriv - end - - # Computes the Jacobian of +f+ at +x+. +fx+ is the value of +f+ at +x+. - def jacobian(f,fx,x) - n = x.size - dfdx = Array.new(n*n) - for i in 0...n do - df = dfdxi(f,fx,x,i) - for j in 0...n do - dfdx[j*n+i] = df[j] - end - end - dfdx - end -end diff --git a/ext/bigdecimal/lib/bigdecimal/ludcmp.rb b/ext/bigdecimal/lib/bigdecimal/ludcmp.rb deleted file mode 100644 index dd265e482a3178..00000000000000 --- a/ext/bigdecimal/lib/bigdecimal/ludcmp.rb +++ /dev/null @@ -1,89 +0,0 @@ -# frozen_string_literal: false -require 'bigdecimal' - -# -# Solves a*x = b for x, using LU decomposition. -# -module LUSolve - module_function - - # Performs LU decomposition of the n by n matrix a. - def ludecomp(a,n,zero=0,one=1) - prec = BigDecimal.limit(nil) - ps = [] - scales = [] - for i in 0...n do # pick up largest(abs. val.) element in each row. - ps <<= i - nrmrow = zero - ixn = i*n - for j in 0...n do - biggst = a[ixn+j].abs - nrmrow = biggst if biggst>nrmrow - end - if nrmrow>zero then - scales <<= one.div(nrmrow,prec) - else - raise "Singular matrix" - end - end - n1 = n - 1 - for k in 0...n1 do # Gaussian elimination with partial pivoting. - biggst = zero; - for i in k...n do - size = a[ps[i]*n+k].abs*scales[ps[i]] - if size>biggst then - biggst = size - pividx = i - end - end - raise "Singular matrix" if biggst<=zero - if pividx!=k then - j = ps[k] - ps[k] = ps[pividx] - ps[pividx] = j - end - pivot = a[ps[k]*n+k] - for i in (k+1)...n do - psin = ps[i]*n - a[psin+k] = mult = a[psin+k].div(pivot,prec) - if mult!=zero then - pskn = ps[k]*n - for j in (k+1)...n do - a[psin+j] -= mult.mult(a[pskn+j],prec) - end - end - end - end - raise "Singular matrix" if a[ps[n1]*n+n1] == zero - ps - end - - # Solves a*x = b for x, using LU decomposition. - # - # a is a matrix, b is a constant vector, x is the solution vector. - # - # ps is the pivot, a vector which indicates the permutation of rows performed - # during LU decomposition. - def lusolve(a,b,ps,zero=0.0) - prec = BigDecimal.limit(nil) - n = ps.size - x = [] - for i in 0...n do - dot = zero - psin = ps[i]*n - for j in 0...i do - dot = a[psin+j].mult(x[j],prec) + dot - end - x <<= b[ps[i]] - dot - end - (n-1).downto(0) do |i| - dot = zero - psin = ps[i]*n - for j in (i+1)...n do - dot = a[psin+j].mult(x[j],prec) + dot - end - x[i] = (x[i]-dot).div(a[psin+i],prec) - end - x - end -end diff --git a/ext/bigdecimal/lib/bigdecimal/math.rb b/ext/bigdecimal/lib/bigdecimal/math.rb deleted file mode 100644 index 0b9d0648bb3e38..00000000000000 --- a/ext/bigdecimal/lib/bigdecimal/math.rb +++ /dev/null @@ -1,232 +0,0 @@ -# frozen_string_literal: false -require 'bigdecimal' - -# -#-- -# Contents: -# sqrt(x, prec) -# sin (x, prec) -# cos (x, prec) -# atan(x, prec) Note: |x|<1, x=0.9999 may not converge. -# PI (prec) -# E (prec) == exp(1.0,prec) -# -# where: -# x ... BigDecimal number to be computed. -# |x| must be small enough to get convergence. -# prec ... Number of digits to be obtained. -#++ -# -# Provides mathematical functions. -# -# Example: -# -# require "bigdecimal/math" -# -# include BigMath -# -# a = BigDecimal((PI(100)/2).to_s) -# puts sin(a,100) # => 0.99999999999999999999......e0 -# -module BigMath - module_function - - # call-seq: - # sqrt(decimal, numeric) -> BigDecimal - # - # Computes the square root of +decimal+ to the specified number of digits of - # precision, +numeric+. - # - # BigMath.sqrt(BigDecimal('2'), 16).to_s - # #=> "0.1414213562373095048801688724e1" - # - def sqrt(x, prec) - x.sqrt(prec) - end - - # call-seq: - # sin(decimal, numeric) -> BigDecimal - # - # Computes the sine of +decimal+ to the specified number of digits of - # precision, +numeric+. - # - # If +decimal+ is Infinity or NaN, returns NaN. - # - # BigMath.sin(BigMath.PI(5)/4, 5).to_s - # #=> "0.70710678118654752440082036563292800375e0" - # - def sin(x, prec) - raise ArgumentError, "Zero or negative precision for sin" if prec <= 0 - return BigDecimal("NaN") if x.infinite? || x.nan? - n = prec + BigDecimal.double_fig - one = BigDecimal("1") - two = BigDecimal("2") - x = -x if neg = x < 0 - if x > (twopi = two * BigMath.PI(prec)) - if x > 30 - x %= twopi - else - x -= twopi while x > twopi - end - end - x1 = x - x2 = x.mult(x,n) - sign = 1 - y = x - d = y - i = one - z = one - while d.nonzero? && ((m = n - (y.exponent - d.exponent).abs) > 0) - m = BigDecimal.double_fig if m < BigDecimal.double_fig - sign = -sign - x1 = x2.mult(x1,n) - i += two - z *= (i-one) * i - d = sign * x1.div(z,m) - y += d - end - neg ? -y : y - end - - # call-seq: - # cos(decimal, numeric) -> BigDecimal - # - # Computes the cosine of +decimal+ to the specified number of digits of - # precision, +numeric+. - # - # If +decimal+ is Infinity or NaN, returns NaN. - # - # BigMath.cos(BigMath.PI(4), 16).to_s - # #=> "-0.999999999999999999999999999999856613163740061349e0" - # - def cos(x, prec) - raise ArgumentError, "Zero or negative precision for cos" if prec <= 0 - return BigDecimal("NaN") if x.infinite? || x.nan? - n = prec + BigDecimal.double_fig - one = BigDecimal("1") - two = BigDecimal("2") - x = -x if x < 0 - if x > (twopi = two * BigMath.PI(prec)) - if x > 30 - x %= twopi - else - x -= twopi while x > twopi - end - end - x1 = one - x2 = x.mult(x,n) - sign = 1 - y = one - d = y - i = BigDecimal("0") - z = one - while d.nonzero? && ((m = n - (y.exponent - d.exponent).abs) > 0) - m = BigDecimal.double_fig if m < BigDecimal.double_fig - sign = -sign - x1 = x2.mult(x1,n) - i += two - z *= (i-one) * i - d = sign * x1.div(z,m) - y += d - end - y - end - - # call-seq: - # atan(decimal, numeric) -> BigDecimal - # - # Computes the arctangent of +decimal+ to the specified number of digits of - # precision, +numeric+. - # - # If +decimal+ is NaN, returns NaN. - # - # BigMath.atan(BigDecimal('-1'), 16).to_s - # #=> "-0.785398163397448309615660845819878471907514682065e0" - # - def atan(x, prec) - raise ArgumentError, "Zero or negative precision for atan" if prec <= 0 - return BigDecimal("NaN") if x.nan? - pi = PI(prec) - x = -x if neg = x < 0 - return pi.div(neg ? -2 : 2, prec) if x.infinite? - return pi / (neg ? -4 : 4) if x.round(prec) == 1 - x = BigDecimal("1").div(x, prec) if inv = x > 1 - x = (-1 + sqrt(1 + x**2, prec))/x if dbl = x > 0.5 - n = prec + BigDecimal.double_fig - y = x - d = y - t = x - r = BigDecimal("3") - x2 = x.mult(x,n) - while d.nonzero? && ((m = n - (y.exponent - d.exponent).abs) > 0) - m = BigDecimal.double_fig if m < BigDecimal.double_fig - t = -t.mult(x2,n) - d = t.div(r,m) - y += d - r += 2 - end - y *= 2 if dbl - y = pi / 2 - y if inv - y = -y if neg - y - end - - # call-seq: - # PI(numeric) -> BigDecimal - # - # Computes the value of pi to the specified number of digits of precision, - # +numeric+. - # - # BigMath.PI(10).to_s - # #=> "0.3141592653589793238462643388813853786957412e1" - # - def PI(prec) - raise ArgumentError, "Zero or negative precision for PI" if prec <= 0 - n = prec + BigDecimal.double_fig - zero = BigDecimal("0") - one = BigDecimal("1") - two = BigDecimal("2") - - m25 = BigDecimal("-0.04") - m57121 = BigDecimal("-57121") - - pi = zero - - d = one - k = one - t = BigDecimal("-80") - while d.nonzero? && ((m = n - (pi.exponent - d.exponent).abs) > 0) - m = BigDecimal.double_fig if m < BigDecimal.double_fig - t = t*m25 - d = t.div(k,m) - k = k+two - pi = pi + d - end - - d = one - k = one - t = BigDecimal("956") - while d.nonzero? && ((m = n - (pi.exponent - d.exponent).abs) > 0) - m = BigDecimal.double_fig if m < BigDecimal.double_fig - t = t.div(m57121,n) - d = t.div(k,m) - pi = pi + d - k = k+two - end - pi - end - - # call-seq: - # E(numeric) -> BigDecimal - # - # Computes e (the base of natural logarithms) to the specified number of - # digits of precision, +numeric+. - # - # BigMath.E(10).to_s - # #=> "0.271828182845904523536028752390026306410273e1" - # - def E(prec) - raise ArgumentError, "Zero or negative precision for E" if prec <= 0 - BigMath.exp(1, prec) - end -end diff --git a/ext/bigdecimal/lib/bigdecimal/newton.rb b/ext/bigdecimal/lib/bigdecimal/newton.rb deleted file mode 100644 index 85bacb7f2efbf0..00000000000000 --- a/ext/bigdecimal/lib/bigdecimal/newton.rb +++ /dev/null @@ -1,80 +0,0 @@ -# frozen_string_literal: false -require "bigdecimal/ludcmp" -require "bigdecimal/jacobian" - -# -# newton.rb -# -# Solves the nonlinear algebraic equation system f = 0 by Newton's method. -# This program is not dependent on BigDecimal. -# -# To call: -# n = nlsolve(f,x) -# where n is the number of iterations required, -# x is the initial value vector -# f is an Object which is used to compute the values of the equations to be solved. -# It must provide the following methods: -# -# f.values(x):: returns the values of all functions at x -# -# f.zero:: returns 0.0 -# f.one:: returns 1.0 -# f.two:: returns 2.0 -# f.ten:: returns 10.0 -# -# f.eps:: returns the convergence criterion (epsilon value) used to determine whether two values are considered equal. If |a-b| < epsilon, the two values are considered equal. -# -# On exit, x is the solution vector. -# -module Newton - include LUSolve - include Jacobian - module_function - - def norm(fv,zero=0.0) # :nodoc: - s = zero - n = fv.size - for i in 0...n do - s += fv[i]*fv[i] - end - s - end - - # See also Newton - def nlsolve(f,x) - nRetry = 0 - n = x.size - - f0 = f.values(x) - zero = f.zero - one = f.one - two = f.two - p5 = one/two - d = norm(f0,zero) - minfact = f.ten*f.ten*f.ten - minfact = one/minfact - e = f.eps - while d >= e do - nRetry += 1 - # Not yet converged. => Compute Jacobian matrix - dfdx = jacobian(f,f0,x) - # Solve dfdx*dx = -f0 to estimate dx - dx = lusolve(dfdx,f0,ludecomp(dfdx,n,zero,one),zero) - fact = two - xs = x.dup - begin - fact *= p5 - if fact < minfact then - raise "Failed to reduce function values." - end - for i in 0...n do - x[i] = xs[i] - dx[i]*fact - end - f0 = f.values(x) - dn = norm(f0,zero) - end while(dn>=d) - d = dn - end - nRetry - end -end diff --git a/ext/bigdecimal/lib/bigdecimal/util.rb b/ext/bigdecimal/lib/bigdecimal/util.rb deleted file mode 100644 index ad92f7cfe64eef..00000000000000 --- a/ext/bigdecimal/lib/bigdecimal/util.rb +++ /dev/null @@ -1,185 +0,0 @@ -# frozen_string_literal: false -# -#-- -# bigdecimal/util extends various native classes to provide the #to_d method, -# and provides BigDecimal#to_d and BigDecimal#to_digits. -#++ - -require 'bigdecimal' - -class Integer < Numeric - # call-seq: - # int.to_d -> bigdecimal - # - # Returns the value of +int+ as a BigDecimal. - # - # require 'bigdecimal' - # require 'bigdecimal/util' - # - # 42.to_d # => 0.42e2 - # - # See also BigDecimal::new. - # - def to_d - BigDecimal(self) - end -end - - -class Float < Numeric - # call-seq: - # float.to_d -> bigdecimal - # float.to_d(precision) -> bigdecimal - # - # Returns the value of +float+ as a BigDecimal. - # The +precision+ parameter is used to determine the number of - # significant digits for the result. When +precision+ is set to +0+, - # the number of digits to represent the float being converted is determined - # automatically. - # The default +precision+ is +0+. - # - # require 'bigdecimal' - # require 'bigdecimal/util' - # - # 0.5.to_d # => 0.5e0 - # 1.234.to_d # => 0.1234e1 - # 1.234.to_d(2) # => 0.12e1 - # - # See also BigDecimal::new. - # - def to_d(precision=0) - BigDecimal(self, precision) - end -end - - -class String - # call-seq: - # str.to_d -> bigdecimal - # - # Returns the result of interpreting leading characters in +str+ - # as a BigDecimal. - # - # require 'bigdecimal' - # require 'bigdecimal/util' - # - # "0.5".to_d # => 0.5e0 - # "123.45e1".to_d # => 0.12345e4 - # "45.67 degrees".to_d # => 0.4567e2 - # - # See also BigDecimal::new. - # - def to_d - BigDecimal.interpret_loosely(self) - end -end - - -class BigDecimal < Numeric - # call-seq: - # a.to_digits -> string - # - # Converts a BigDecimal to a String of the form "nnnnnn.mmm". - # This method is deprecated; use BigDecimal#to_s("F") instead. - # - # require 'bigdecimal/util' - # - # d = BigDecimal("3.14") - # d.to_digits # => "3.14" - # - def to_digits - if self.nan? || self.infinite? || self.zero? - self.to_s - else - i = self.to_i.to_s - _,f,_,z = self.frac.split - i + "." + ("0"*(-z)) + f - end - end - - # call-seq: - # a.to_d -> bigdecimal - # - # Returns self. - # - # require 'bigdecimal/util' - # - # d = BigDecimal("3.14") - # d.to_d # => 0.314e1 - # - def to_d - self - end -end - - -class Rational < Numeric - # call-seq: - # rat.to_d(precision) -> bigdecimal - # - # Returns the value as a BigDecimal. - # - # The required +precision+ parameter is used to determine the number of - # significant digits for the result. - # - # require 'bigdecimal' - # require 'bigdecimal/util' - # - # Rational(22, 7).to_d(3) # => 0.314e1 - # - # See also BigDecimal::new. - # - def to_d(precision) - BigDecimal(self, precision) - end -end - - -class Complex < Numeric - # call-seq: - # cmp.to_d -> bigdecimal - # cmp.to_d(precision) -> bigdecimal - # - # Returns the value as a BigDecimal. - # - # The +precision+ parameter is required for a rational complex number. - # This parameter is used to determine the number of significant digits - # for the result. - # - # require 'bigdecimal' - # require 'bigdecimal/util' - # - # Complex(0.1234567, 0).to_d(4) # => 0.1235e0 - # Complex(Rational(22, 7), 0).to_d(3) # => 0.314e1 - # - # See also BigDecimal::new. - # - def to_d(*args) - BigDecimal(self) unless self.imag.zero? # to raise eerror - - if args.length == 0 - case self.real - when Rational - BigDecimal(self.real) # to raise error - end - end - self.real.to_d(*args) - end -end - - -class NilClass - # call-seq: - # nil.to_d -> bigdecimal - # - # Returns nil represented as a BigDecimal. - # - # require 'bigdecimal' - # require 'bigdecimal/util' - # - # nil.to_d # => 0.0 - # - def to_d - BigDecimal(0) - end -end diff --git a/ext/bigdecimal/missing.c b/ext/bigdecimal/missing.c deleted file mode 100644 index 703232d92f7716..00000000000000 --- a/ext/bigdecimal/missing.c +++ /dev/null @@ -1,27 +0,0 @@ -#include - -#ifdef HAVE_RUBY_ATOMIC_H -# include -#endif - -#ifdef RUBY_ATOMIC_PTR_CAS -# define ATOMIC_PTR_CAS(var, old, new) RUBY_ATOMIC_PTR_CAS(var, old, new) -#endif - -#if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) -/* GCC warns about unknown sanitizer, which is annoying. */ -# undef NO_SANITIZE -# define NO_SANITIZE(x, y) \ - _Pragma("GCC diagnostic push") \ - _Pragma("GCC diagnostic ignored \"-Wattributes\"") \ - __attribute__((__no_sanitize__(x))) y; \ - _Pragma("GCC diagnostic pop") -#endif - -#undef strtod -#define strtod BigDecimal_strtod -#undef dtoa -#define dtoa BigDecimal_dtoa -#undef hdtoa -#define hdtoa BigDecimal_hdtoa -#include "missing/dtoa.c" diff --git a/ext/bigdecimal/missing.h b/ext/bigdecimal/missing.h deleted file mode 100644 index 325554b5f536d3..00000000000000 --- a/ext/bigdecimal/missing.h +++ /dev/null @@ -1,196 +0,0 @@ -#ifndef MISSING_H -#define MISSING_H 1 - -#if defined(__cplusplus) -extern "C" { -#if 0 -} /* satisfy cc-mode */ -#endif -#endif - -#ifdef HAVE_STDLIB_H -# include -#endif - -#ifdef HAVE_MATH_H -# include -#endif - -#ifndef RB_UNUSED_VAR -# if defined(_MSC_VER) && _MSC_VER >= 1911 -# define RB_UNUSED_VAR(x) x [[maybe_unused]] - -# elif defined(__has_cpp_attribute) && __has_cpp_attribute(maybe_unused) -# define RB_UNUSED_VAR(x) x [[maybe_unused]] - -# elif defined(__has_c_attribute) && __has_c_attribute(maybe_unused) -# define RB_UNUSED_VAR(x) x [[maybe_unused]] - -# elif defined(__GNUC__) -# define RB_UNUSED_VAR(x) x __attribute__ ((unused)) - -# else -# define RB_UNUSED_VAR(x) x -# endif -#endif /* RB_UNUSED_VAR */ - -#if defined(_MSC_VER) && _MSC_VER >= 1310 -# define HAVE___ASSUME 1 - -#elif defined(__INTEL_COMPILER) && __INTEL_COMPILER >= 1300 -# define HAVE___ASSUME 1 -#endif - -#ifndef UNREACHABLE -# if __has_builtin(__builtin_unreachable) -# define UNREACHABLE __builtin_unreachable() - -# elif defined(HAVE___ASSUME) -# define UNREACHABLE __assume(0) - -# else -# define UNREACHABLE /* unreachable */ -# endif -#endif /* UNREACHABLE */ - -/* bool */ - -#if defined(__bool_true_false_are_defined) -# /* Take that. */ - -#elif defined(HAVE_STDBOOL_H) -# include - -#else -typedef unsigned char _Bool; -# define bool _Bool -# define true ((_Bool)+1) -# define false ((_Bool)-1) -# define __bool_true_false_are_defined -#endif - -/* abs */ - -#ifndef HAVE_LABS -static inline long -labs(long const x) -{ - if (x < 0) return -x; - return x; -} -#endif - -#ifndef HAVE_LLABS -static inline LONG_LONG -llabs(LONG_LONG const x) -{ - if (x < 0) return -x; - return x; -} -#endif - -#ifdef vabs -# undef vabs -#endif -#if SIZEOF_VALUE <= SIZEOF_INT -# define vabs abs -#elif SIZEOF_VALUE <= SIZEOF_LONG -# define vabs labs -#elif SIZEOF_VALUE <= SIZEOF_LONG_LONG -# define vabs llabs -#endif - -/* finite */ - -#ifndef HAVE_FINITE -static int -finite(double) -{ - return !isnan(n) && !isinf(n); -} -#endif - -#ifndef isfinite -# ifndef HAVE_ISFINITE -# define HAVE_ISFINITE 1 -# define isfinite(x) finite(x) -# endif -#endif - -/* dtoa */ -char *BigDecimal_dtoa(double d_, int mode, int ndigits, int *decpt, int *sign, char **rve); - -/* rational */ - -#ifndef HAVE_RB_RATIONAL_NUM -static inline VALUE -rb_rational_num(VALUE rat) -{ -#ifdef RRATIONAL - return RRATIONAL(rat)->num; -#else - return rb_funcall(rat, rb_intern("numerator"), 0); -#endif -} -#endif - -#ifndef HAVE_RB_RATIONAL_DEN -static inline VALUE -rb_rational_den(VALUE rat) -{ -#ifdef RRATIONAL - return RRATIONAL(rat)->den; -#else - return rb_funcall(rat, rb_intern("denominator"), 0); -#endif -} -#endif - -/* complex */ - -#ifndef HAVE_RB_COMPLEX_REAL -static inline VALUE -rb_complex_real(VALUE cmp) -{ -#ifdef RCOMPLEX - return RCOMPLEX(cmp)->real; -#else - return rb_funcall(cmp, rb_intern("real"), 0); -#endif -} -#endif - -#ifndef HAVE_RB_COMPLEX_IMAG -static inline VALUE -rb_complex_imag(VALUE cmp) -{ -# ifdef RCOMPLEX - return RCOMPLEX(cmp)->imag; -# else - return rb_funcall(cmp, rb_intern("imag"), 0); -# endif -} -#endif - -/* st */ - -#ifndef ST2FIX -# undef RB_ST2FIX -# define RB_ST2FIX(h) LONG2FIX((long)(h)) -# define ST2FIX(h) RB_ST2FIX(h) -#endif - -/* warning */ - -#if !defined(HAVE_RB_CATEGORY_WARN) || !defined(HAVE_CONST_RB_WARN_CATEGORY_DEPRECATED) -# define rb_category_warn(category, ...) rb_warn(__VA_ARGS__) -#endif - -#if defined(__cplusplus) -#if 0 -{ /* satisfy cc-mode */ -#endif -} /* extern "C" { */ -#endif - -#endif /* MISSING_H */ diff --git a/ext/bigdecimal/missing/dtoa.c b/ext/bigdecimal/missing/dtoa.c deleted file mode 100644 index 41b0a221d14f4b..00000000000000 --- a/ext/bigdecimal/missing/dtoa.c +++ /dev/null @@ -1,3462 +0,0 @@ -/**************************************************************** - * - * The author of this software is David M. Gay. - * - * Copyright (c) 1991, 2000, 2001 by Lucent Technologies. - * - * Permission to use, copy, modify, and distribute this software for any - * purpose without fee is hereby granted, provided that this entire notice - * is included in all copies of any software which is or includes a copy - * or modification of this software and in all copies of the supporting - * documentation for such software. - * - * THIS SOFTWARE IS BEING PROVIDED "AS IS", WITHOUT ANY EXPRESS OR IMPLIED - * WARRANTY. IN PARTICULAR, NEITHER THE AUTHOR NOR LUCENT MAKES ANY - * REPRESENTATION OR WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY - * OF THIS SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. - * - ***************************************************************/ - -/* Please send bug reports to David M. Gay (dmg at acm dot org, - * with " at " changed at "@" and " dot " changed to "."). */ - -/* On a machine with IEEE extended-precision registers, it is - * necessary to specify double-precision (53-bit) rounding precision - * before invoking strtod or dtoa. If the machine uses (the equivalent - * of) Intel 80x87 arithmetic, the call - * _control87(PC_53, MCW_PC); - * does this with many compilers. Whether this or another call is - * appropriate depends on the compiler; for this to work, it may be - * necessary to #include "float.h" or another system-dependent header - * file. - */ - -/* strtod for IEEE-, VAX-, and IBM-arithmetic machines. - * - * This strtod returns a nearest machine number to the input decimal - * string (or sets errno to ERANGE). With IEEE arithmetic, ties are - * broken by the IEEE round-even rule. Otherwise ties are broken by - * biased rounding (add half and chop). - * - * Inspired loosely by William D. Clinger's paper "How to Read Floating - * Point Numbers Accurately" [Proc. ACM SIGPLAN '90, pp. 92-101]. - * - * Modifications: - * - * 1. We only require IEEE, IBM, or VAX double-precision - * arithmetic (not IEEE double-extended). - * 2. We get by with floating-point arithmetic in a case that - * Clinger missed -- when we're computing d * 10^n - * for a small integer d and the integer n is not too - * much larger than 22 (the maximum integer k for which - * we can represent 10^k exactly), we may be able to - * compute (d*10^k) * 10^(e-k) with just one roundoff. - * 3. Rather than a bit-at-a-time adjustment of the binary - * result in the hard case, we use floating-point - * arithmetic to determine the adjustment to within - * one bit; only in really hard cases do we need to - * compute a second residual. - * 4. Because of 3., we don't need a large table of powers of 10 - * for ten-to-e (just some small tables, e.g. of 10^k - * for 0 <= k <= 22). - */ - -/* - * #define IEEE_LITTLE_ENDIAN for IEEE-arithmetic machines where the least - * significant byte has the lowest address. - * #define IEEE_BIG_ENDIAN for IEEE-arithmetic machines where the most - * significant byte has the lowest address. - * #define Long int on machines with 32-bit ints and 64-bit longs. - * #define IBM for IBM mainframe-style floating-point arithmetic. - * #define VAX for VAX-style floating-point arithmetic (D_floating). - * #define No_leftright to omit left-right logic in fast floating-point - * computation of dtoa. - * #define Honor_FLT_ROUNDS if FLT_ROUNDS can assume the values 2 or 3 - * and strtod and dtoa should round accordingly. - * #define Check_FLT_ROUNDS if FLT_ROUNDS can assume the values 2 or 3 - * and Honor_FLT_ROUNDS is not #defined. - * #define RND_PRODQUOT to use rnd_prod and rnd_quot (assembly routines - * that use extended-precision instructions to compute rounded - * products and quotients) with IBM. - * #define ROUND_BIASED for IEEE-format with biased rounding. - * #define Inaccurate_Divide for IEEE-format with correctly rounded - * products but inaccurate quotients, e.g., for Intel i860. - * #define NO_LONG_LONG on machines that do not have a "long long" - * integer type (of >= 64 bits). On such machines, you can - * #define Just_16 to store 16 bits per 32-bit Long when doing - * high-precision integer arithmetic. Whether this speeds things - * up or slows things down depends on the machine and the number - * being converted. If long long is available and the name is - * something other than "long long", #define Llong to be the name, - * and if "unsigned Llong" does not work as an unsigned version of - * Llong, #define #ULLong to be the corresponding unsigned type. - * #define KR_headers for old-style C function headers. - * #define Bad_float_h if your system lacks a float.h or if it does not - * define some or all of DBL_DIG, DBL_MAX_10_EXP, DBL_MAX_EXP, - * FLT_RADIX, FLT_ROUNDS, and DBL_MAX. - * #define MALLOC your_malloc, where your_malloc(n) acts like malloc(n) - * if memory is available and otherwise does something you deem - * appropriate. If MALLOC is undefined, malloc will be invoked - * directly -- and assumed always to succeed. - * #define Omit_Private_Memory to omit logic (added Jan. 1998) for making - * memory allocations from a private pool of memory when possible. - * When used, the private pool is PRIVATE_MEM bytes long: 2304 bytes, - * unless #defined to be a different length. This default length - * suffices to get rid of MALLOC calls except for unusual cases, - * such as decimal-to-binary conversion of a very long string of - * digits. The longest string dtoa can return is about 751 bytes - * long. For conversions by strtod of strings of 800 digits and - * all dtoa conversions in single-threaded executions with 8-byte - * pointers, PRIVATE_MEM >= 7400 appears to suffice; with 4-byte - * pointers, PRIVATE_MEM >= 7112 appears adequate. - * #define INFNAN_CHECK on IEEE systems to cause strtod to check for - * Infinity and NaN (case insensitively). On some systems (e.g., - * some HP systems), it may be necessary to #define NAN_WORD0 - * appropriately -- to the most significant word of a quiet NaN. - * (On HP Series 700/800 machines, -DNAN_WORD0=0x7ff40000 works.) - * When INFNAN_CHECK is #defined and No_Hex_NaN is not #defined, - * strtod also accepts (case insensitively) strings of the form - * NaN(x), where x is a string of hexadecimal digits and spaces; - * if there is only one string of hexadecimal digits, it is taken - * for the 52 fraction bits of the resulting NaN; if there are two - * or more strings of hex digits, the first is for the high 20 bits, - * the second and subsequent for the low 32 bits, with intervening - * white space ignored; but if this results in none of the 52 - * fraction bits being on (an IEEE Infinity symbol), then NAN_WORD0 - * and NAN_WORD1 are used instead. - * #define MULTIPLE_THREADS if the system offers preemptively scheduled - * multiple threads. In this case, you must provide (or suitably - * #define) two locks, acquired by ACQUIRE_DTOA_LOCK(n) and freed - * by FREE_DTOA_LOCK(n) for n = 0 or 1. (The second lock, accessed - * in pow5mult, ensures lazy evaluation of only one copy of high - * powers of 5; omitting this lock would introduce a small - * probability of wasting memory, but would otherwise be harmless.) - * You must also invoke freedtoa(s) to free the value s returned by - * dtoa. You may do so whether or not MULTIPLE_THREADS is #defined. - * #define NO_IEEE_Scale to disable new (Feb. 1997) logic in strtod that - * avoids underflows on inputs whose result does not underflow. - * If you #define NO_IEEE_Scale on a machine that uses IEEE-format - * floating-point numbers and flushes underflows to zero rather - * than implementing gradual underflow, then you must also #define - * Sudden_Underflow. - * #define YES_ALIAS to permit aliasing certain double values with - * arrays of ULongs. This leads to slightly better code with - * some compilers and was always used prior to 19990916, but it - * is not strictly legal and can cause trouble with aggressively - * optimizing compilers (e.g., gcc 2.95.1 under -O2). - * #define USE_LOCALE to use the current locale's decimal_point value. - * #define SET_INEXACT if IEEE arithmetic is being used and extra - * computation should be done to set the inexact flag when the - * result is inexact and avoid setting inexact when the result - * is exact. In this case, dtoa.c must be compiled in - * an environment, perhaps provided by #include "dtoa.c" in a - * suitable wrapper, that defines two functions, - * int get_inexact(void); - * void clear_inexact(void); - * such that get_inexact() returns a nonzero value if the - * inexact bit is already set, and clear_inexact() sets the - * inexact bit to 0. When SET_INEXACT is #defined, strtod - * also does extra computations to set the underflow and overflow - * flags when appropriate (i.e., when the result is tiny and - * inexact or when it is a numeric value rounded to +-infinity). - * #define NO_ERRNO if strtod should not assign errno = ERANGE when - * the result overflows to +-Infinity or underflows to 0. - */ - -#ifdef WORDS_BIGENDIAN -#define IEEE_BIG_ENDIAN -#else -#define IEEE_LITTLE_ENDIAN -#endif - -#ifdef __vax__ -#define VAX -#undef IEEE_BIG_ENDIAN -#undef IEEE_LITTLE_ENDIAN -#endif - -#if defined(__arm__) && !defined(__VFP_FP__) -#define IEEE_BIG_ENDIAN -#undef IEEE_LITTLE_ENDIAN -#endif - -#undef Long -#undef ULong - -#include - -#if (INT_MAX >> 30) && !(INT_MAX >> 31) -#define Long int -#define ULong unsigned int -#elif (LONG_MAX >> 30) && !(LONG_MAX >> 31) -#define Long long int -#define ULong unsigned long int -#else -#error No 32bit integer -#endif - -#if HAVE_LONG_LONG -#define Llong LONG_LONG -#else -#define NO_LONG_LONG -#endif - -#ifdef DEBUG -#include -#define Bug(x) {fprintf(stderr, "%s\n", (x)); exit(EXIT_FAILURE);} -#endif - -#ifndef ISDIGIT -#include -#define ISDIGIT(c) isdigit(c) -#endif -#include -#include -#include - -#ifdef USE_LOCALE -#include -#endif - -#ifdef MALLOC -extern void *MALLOC(size_t); -#else -#define MALLOC xmalloc -#endif -#ifdef FREE -extern void FREE(void*); -#else -#define FREE xfree -#endif -#ifndef NO_SANITIZE -#define NO_SANITIZE(x, y) y -#endif - -#ifndef Omit_Private_Memory -#ifndef PRIVATE_MEM -#define PRIVATE_MEM 2304 -#endif -#define PRIVATE_mem ((PRIVATE_MEM+sizeof(double)-1)/sizeof(double)) -static double private_mem[PRIVATE_mem], *pmem_next = private_mem; -#endif - -#undef IEEE_Arith -#undef Avoid_Underflow -#ifdef IEEE_BIG_ENDIAN -#define IEEE_Arith -#endif -#ifdef IEEE_LITTLE_ENDIAN -#define IEEE_Arith -#endif - -#ifdef Bad_float_h - -#ifdef IEEE_Arith -#define DBL_DIG 15 -#define DBL_MAX_10_EXP 308 -#define DBL_MAX_EXP 1024 -#define FLT_RADIX 2 -#endif /*IEEE_Arith*/ - -#ifdef IBM -#define DBL_DIG 16 -#define DBL_MAX_10_EXP 75 -#define DBL_MAX_EXP 63 -#define FLT_RADIX 16 -#define DBL_MAX 7.2370055773322621e+75 -#endif - -#ifdef VAX -#define DBL_DIG 16 -#define DBL_MAX_10_EXP 38 -#define DBL_MAX_EXP 127 -#define FLT_RADIX 2 -#define DBL_MAX 1.7014118346046923e+38 -#endif - -#ifndef LONG_MAX -#define LONG_MAX 2147483647 -#endif - -#else /* ifndef Bad_float_h */ -#include -#endif /* Bad_float_h */ - -#include - -#ifdef __cplusplus -extern "C" { -#if 0 -} /* satisfy cc-mode */ -#endif -#endif - -#ifndef hexdigit -static const char hexdigit[] = "0123456789abcdef0123456789ABCDEF"; -#endif - -#if defined(IEEE_LITTLE_ENDIAN) + defined(IEEE_BIG_ENDIAN) + defined(VAX) + defined(IBM) != 1 -Exactly one of IEEE_LITTLE_ENDIAN, IEEE_BIG_ENDIAN, VAX, or IBM should be defined. -#endif - -typedef union { double d; ULong L[2]; } U; - -#ifdef YES_ALIAS -typedef double double_u; -# define dval(x) (x) -# ifdef IEEE_LITTLE_ENDIAN -# define word0(x) (((ULong *)&(x))[1]) -# define word1(x) (((ULong *)&(x))[0]) -# else -# define word0(x) (((ULong *)&(x))[0]) -# define word1(x) (((ULong *)&(x))[1]) -# endif -#else -typedef U double_u; -# ifdef IEEE_LITTLE_ENDIAN -# define word0(x) ((x).L[1]) -# define word1(x) ((x).L[0]) -# else -# define word0(x) ((x).L[0]) -# define word1(x) ((x).L[1]) -# endif -# define dval(x) ((x).d) -#endif - -/* The following definition of Storeinc is appropriate for MIPS processors. - * An alternative that might be better on some machines is - * #define Storeinc(a,b,c) (*a++ = b << 16 | c & 0xffff) - */ -#if defined(IEEE_LITTLE_ENDIAN) + defined(VAX) + defined(__arm__) -#define Storeinc(a,b,c) (((unsigned short *)(a))[1] = (unsigned short)(b), \ -((unsigned short *)(a))[0] = (unsigned short)(c), (a)++) -#else -#define Storeinc(a,b,c) (((unsigned short *)(a))[0] = (unsigned short)(b), \ -((unsigned short *)(a))[1] = (unsigned short)(c), (a)++) -#endif - -/* #define P DBL_MANT_DIG */ -/* Ten_pmax = floor(P*log(2)/log(5)) */ -/* Bletch = (highest power of 2 < DBL_MAX_10_EXP) / 16 */ -/* Quick_max = floor((P-1)*log(FLT_RADIX)/log(10) - 1) */ -/* Int_max = floor(P*log(FLT_RADIX)/log(10) - 1) */ - -#ifdef IEEE_Arith -#define Exp_shift 20 -#define Exp_shift1 20 -#define Exp_msk1 0x100000 -#define Exp_msk11 0x100000 -#define Exp_mask 0x7ff00000 -#define P 53 -#define Bias 1023 -#define Emin (-1022) -#define Exp_1 0x3ff00000 -#define Exp_11 0x3ff00000 -#define Ebits 11 -#define Frac_mask 0xfffff -#define Frac_mask1 0xfffff -#define Ten_pmax 22 -#define Bletch 0x10 -#define Bndry_mask 0xfffff -#define Bndry_mask1 0xfffff -#define LSB 1 -#define Sign_bit 0x80000000 -#define Log2P 1 -#define Tiny0 0 -#define Tiny1 1 -#define Quick_max 14 -#define Int_max 14 -#ifndef NO_IEEE_Scale -#define Avoid_Underflow -#ifdef Flush_Denorm /* debugging option */ -#undef Sudden_Underflow -#endif -#endif - -#ifndef Flt_Rounds -#ifdef FLT_ROUNDS -#define Flt_Rounds FLT_ROUNDS -#else -#define Flt_Rounds 1 -#endif -#endif /*Flt_Rounds*/ - -#ifdef Honor_FLT_ROUNDS -#define Rounding rounding -#undef Check_FLT_ROUNDS -#define Check_FLT_ROUNDS -#else -#define Rounding Flt_Rounds -#endif - -#else /* ifndef IEEE_Arith */ -#undef Check_FLT_ROUNDS -#undef Honor_FLT_ROUNDS -#undef SET_INEXACT -#undef Sudden_Underflow -#define Sudden_Underflow -#ifdef IBM -#undef Flt_Rounds -#define Flt_Rounds 0 -#define Exp_shift 24 -#define Exp_shift1 24 -#define Exp_msk1 0x1000000 -#define Exp_msk11 0x1000000 -#define Exp_mask 0x7f000000 -#define P 14 -#define Bias 65 -#define Exp_1 0x41000000 -#define Exp_11 0x41000000 -#define Ebits 8 /* exponent has 7 bits, but 8 is the right value in b2d */ -#define Frac_mask 0xffffff -#define Frac_mask1 0xffffff -#define Bletch 4 -#define Ten_pmax 22 -#define Bndry_mask 0xefffff -#define Bndry_mask1 0xffffff -#define LSB 1 -#define Sign_bit 0x80000000 -#define Log2P 4 -#define Tiny0 0x100000 -#define Tiny1 0 -#define Quick_max 14 -#define Int_max 15 -#else /* VAX */ -#undef Flt_Rounds -#define Flt_Rounds 1 -#define Exp_shift 23 -#define Exp_shift1 7 -#define Exp_msk1 0x80 -#define Exp_msk11 0x800000 -#define Exp_mask 0x7f80 -#define P 56 -#define Bias 129 -#define Exp_1 0x40800000 -#define Exp_11 0x4080 -#define Ebits 8 -#define Frac_mask 0x7fffff -#define Frac_mask1 0xffff007f -#define Ten_pmax 24 -#define Bletch 2 -#define Bndry_mask 0xffff007f -#define Bndry_mask1 0xffff007f -#define LSB 0x10000 -#define Sign_bit 0x8000 -#define Log2P 1 -#define Tiny0 0x80 -#define Tiny1 0 -#define Quick_max 15 -#define Int_max 15 -#endif /* IBM, VAX */ -#endif /* IEEE_Arith */ - -#ifndef IEEE_Arith -#define ROUND_BIASED -#endif - -#ifdef RND_PRODQUOT -#define rounded_product(a,b) ((a) = rnd_prod((a), (b))) -#define rounded_quotient(a,b) ((a) = rnd_quot((a), (b))) -extern double rnd_prod(double, double), rnd_quot(double, double); -#else -#define rounded_product(a,b) ((a) *= (b)) -#define rounded_quotient(a,b) ((a) /= (b)) -#endif - -#define Big0 (Frac_mask1 | Exp_msk1*(DBL_MAX_EXP+Bias-1)) -#define Big1 0xffffffff - -#ifndef Pack_32 -#define Pack_32 -#endif - -#define FFFFFFFF 0xffffffffUL - -#ifdef NO_LONG_LONG -#undef ULLong -#ifdef Just_16 -#undef Pack_32 -/* When Pack_32 is not defined, we store 16 bits per 32-bit Long. - * This makes some inner loops simpler and sometimes saves work - * during multiplications, but it often seems to make things slightly - * slower. Hence the default is now to store 32 bits per Long. - */ -#endif -#else /* long long available */ -#ifndef Llong -#define Llong long long -#endif -#ifndef ULLong -#define ULLong unsigned Llong -#endif -#endif /* NO_LONG_LONG */ - -#define MULTIPLE_THREADS 1 - -#ifndef MULTIPLE_THREADS -#define ACQUIRE_DTOA_LOCK(n) /*nothing*/ -#define FREE_DTOA_LOCK(n) /*nothing*/ -#else -#define ACQUIRE_DTOA_LOCK(n) /*unused right now*/ -#define FREE_DTOA_LOCK(n) /*unused right now*/ -#endif - -#ifndef ATOMIC_PTR_CAS -#define ATOMIC_PTR_CAS(var, old, new) ((var) = (new), (old)) -#endif -#ifndef LIKELY -#define LIKELY(x) (x) -#endif -#ifndef UNLIKELY -#define UNLIKELY(x) (x) -#endif -#ifndef ASSUME -#define ASSUME(x) (void)(x) -#endif - -#define Kmax 15 - -struct Bigint { - struct Bigint *next; - int k, maxwds, sign, wds; - ULong x[1]; -}; - -typedef struct Bigint Bigint; - -static Bigint *freelist[Kmax+1]; - -static Bigint * -Balloc(int k) -{ - int x; - Bigint *rv; -#ifndef Omit_Private_Memory - size_t len; -#endif - - rv = 0; - ACQUIRE_DTOA_LOCK(0); - if (k <= Kmax) { - rv = freelist[k]; - while (rv) { - Bigint *rvn = rv; - rv = ATOMIC_PTR_CAS(freelist[k], rv, rv->next); - if (LIKELY(rvn == rv)) { - ASSUME(rv); - break; - } - } - } - if (!rv) { - x = 1 << k; -#ifdef Omit_Private_Memory - rv = (Bigint *)MALLOC(sizeof(Bigint) + (x-1)*sizeof(ULong)); -#else - len = (sizeof(Bigint) + (x-1)*sizeof(ULong) + sizeof(double) - 1) - /sizeof(double); - if (k <= Kmax) { - double *pnext = pmem_next; - while (pnext - private_mem + len <= PRIVATE_mem) { - double *p = pnext; - pnext = ATOMIC_PTR_CAS(pmem_next, pnext, pnext + len); - if (LIKELY(p == pnext)) { - rv = (Bigint*)pnext; - ASSUME(rv); - break; - } - } - } - if (!rv) - rv = (Bigint*)MALLOC(len*sizeof(double)); -#endif - rv->k = k; - rv->maxwds = x; - } - FREE_DTOA_LOCK(0); - rv->sign = rv->wds = 0; - return rv; -} - -static void -Bfree(Bigint *v) -{ - Bigint *vn; - if (v) { - if (v->k > Kmax) { - FREE(v); - return; - } - ACQUIRE_DTOA_LOCK(0); - do { - vn = v->next = freelist[v->k]; - } while (UNLIKELY(ATOMIC_PTR_CAS(freelist[v->k], vn, v) != vn)); - FREE_DTOA_LOCK(0); - } -} - -#define Bcopy(x,y) memcpy((char *)&(x)->sign, (char *)&(y)->sign, \ -(y)->wds*sizeof(Long) + 2*sizeof(int)) - -static Bigint * -multadd(Bigint *b, int m, int a) /* multiply by m and add a */ -{ - int i, wds; - ULong *x; -#ifdef ULLong - ULLong carry, y; -#else - ULong carry, y; -#ifdef Pack_32 - ULong xi, z; -#endif -#endif - Bigint *b1; - - wds = b->wds; - x = b->x; - i = 0; - carry = a; - do { -#ifdef ULLong - y = *x * (ULLong)m + carry; - carry = y >> 32; - *x++ = (ULong)(y & FFFFFFFF); -#else -#ifdef Pack_32 - xi = *x; - y = (xi & 0xffff) * m + carry; - z = (xi >> 16) * m + (y >> 16); - carry = z >> 16; - *x++ = (z << 16) + (y & 0xffff); -#else - y = *x * m + carry; - carry = y >> 16; - *x++ = y & 0xffff; -#endif -#endif - } while (++i < wds); - if (carry) { - if (wds >= b->maxwds) { - b1 = Balloc(b->k+1); - Bcopy(b1, b); - Bfree(b); - b = b1; - } - b->x[wds++] = (ULong)carry; - b->wds = wds; - } - return b; -} - -static Bigint * -s2b(const char *s, int nd0, int nd, ULong y9) -{ - Bigint *b; - int i, k; - Long x, y; - - x = (nd + 8) / 9; - for (k = 0, y = 1; x > y; y <<= 1, k++) ; -#ifdef Pack_32 - b = Balloc(k); - b->x[0] = y9; - b->wds = 1; -#else - b = Balloc(k+1); - b->x[0] = y9 & 0xffff; - b->wds = (b->x[1] = y9 >> 16) ? 2 : 1; -#endif - - i = 9; - if (9 < nd0) { - s += 9; - do { - b = multadd(b, 10, *s++ - '0'); - } while (++i < nd0); - s++; - } - else - s += 10; - for (; i < nd; i++) - b = multadd(b, 10, *s++ - '0'); - return b; -} - -static int -hi0bits(register ULong x) -{ - register int k = 0; - - if (!(x & 0xffff0000)) { - k = 16; - x <<= 16; - } - if (!(x & 0xff000000)) { - k += 8; - x <<= 8; - } - if (!(x & 0xf0000000)) { - k += 4; - x <<= 4; - } - if (!(x & 0xc0000000)) { - k += 2; - x <<= 2; - } - if (!(x & 0x80000000)) { - k++; - if (!(x & 0x40000000)) - return 32; - } - return k; -} - -static int -lo0bits(ULong *y) -{ - register int k; - register ULong x = *y; - - if (x & 7) { - if (x & 1) - return 0; - if (x & 2) { - *y = x >> 1; - return 1; - } - *y = x >> 2; - return 2; - } - k = 0; - if (!(x & 0xffff)) { - k = 16; - x >>= 16; - } - if (!(x & 0xff)) { - k += 8; - x >>= 8; - } - if (!(x & 0xf)) { - k += 4; - x >>= 4; - } - if (!(x & 0x3)) { - k += 2; - x >>= 2; - } - if (!(x & 1)) { - k++; - x >>= 1; - if (!x) - return 32; - } - *y = x; - return k; -} - -static Bigint * -i2b(int i) -{ - Bigint *b; - - b = Balloc(1); - b->x[0] = i; - b->wds = 1; - return b; -} - -static Bigint * -mult(Bigint *a, Bigint *b) -{ - Bigint *c; - int k, wa, wb, wc; - ULong *x, *xa, *xae, *xb, *xbe, *xc, *xc0; - ULong y; -#ifdef ULLong - ULLong carry, z; -#else - ULong carry, z; -#ifdef Pack_32 - ULong z2; -#endif -#endif - - if (a->wds < b->wds) { - c = a; - a = b; - b = c; - } - k = a->k; - wa = a->wds; - wb = b->wds; - wc = wa + wb; - if (wc > a->maxwds) - k++; - c = Balloc(k); - for (x = c->x, xa = x + wc; x < xa; x++) - *x = 0; - xa = a->x; - xae = xa + wa; - xb = b->x; - xbe = xb + wb; - xc0 = c->x; -#ifdef ULLong - for (; xb < xbe; xc0++) { - if ((y = *xb++) != 0) { - x = xa; - xc = xc0; - carry = 0; - do { - z = *x++ * (ULLong)y + *xc + carry; - carry = z >> 32; - *xc++ = (ULong)(z & FFFFFFFF); - } while (x < xae); - *xc = (ULong)carry; - } - } -#else -#ifdef Pack_32 - for (; xb < xbe; xb++, xc0++) { - if ((y = *xb & 0xffff) != 0) { - x = xa; - xc = xc0; - carry = 0; - do { - z = (*x & 0xffff) * y + (*xc & 0xffff) + carry; - carry = z >> 16; - z2 = (*x++ >> 16) * y + (*xc >> 16) + carry; - carry = z2 >> 16; - Storeinc(xc, z2, z); - } while (x < xae); - *xc = (ULong)carry; - } - if ((y = *xb >> 16) != 0) { - x = xa; - xc = xc0; - carry = 0; - z2 = *xc; - do { - z = (*x & 0xffff) * y + (*xc >> 16) + carry; - carry = z >> 16; - Storeinc(xc, z, z2); - z2 = (*x++ >> 16) * y + (*xc & 0xffff) + carry; - carry = z2 >> 16; - } while (x < xae); - *xc = z2; - } - } -#else - for (; xb < xbe; xc0++) { - if (y = *xb++) { - x = xa; - xc = xc0; - carry = 0; - do { - z = *x++ * y + *xc + carry; - carry = z >> 16; - *xc++ = z & 0xffff; - } while (x < xae); - *xc = (ULong)carry; - } - } -#endif -#endif - for (xc0 = c->x, xc = xc0 + wc; wc > 0 && !*--xc; --wc) ; - c->wds = wc; - return c; -} - -static Bigint *p5s; - -static Bigint * -pow5mult(Bigint *b, int k) -{ - Bigint *b1, *p5, *p51; - Bigint *p5tmp; - int i; - static const int p05[3] = { 5, 25, 125 }; - - if ((i = k & 3) != 0) - b = multadd(b, p05[i-1], 0); - - if (!(k >>= 2)) - return b; - if (!(p5 = p5s)) { - /* first time */ - ACQUIRE_DTOA_LOCK(1); - if (!(p5 = p5s)) { - p5 = i2b(625); - p5->next = 0; - p5tmp = ATOMIC_PTR_CAS(p5s, NULL, p5); - if (UNLIKELY(p5tmp)) { - Bfree(p5); - p5 = p5tmp; - } - } - FREE_DTOA_LOCK(1); - } - for (;;) { - if (k & 1) { - b1 = mult(b, p5); - Bfree(b); - b = b1; - } - if (!(k >>= 1)) - break; - if (!(p51 = p5->next)) { - ACQUIRE_DTOA_LOCK(1); - if (!(p51 = p5->next)) { - p51 = mult(p5,p5); - p51->next = 0; - p5tmp = ATOMIC_PTR_CAS(p5->next, NULL, p51); - if (UNLIKELY(p5tmp)) { - Bfree(p51); - p51 = p5tmp; - } - } - FREE_DTOA_LOCK(1); - } - p5 = p51; - } - return b; -} - -static Bigint * -lshift(Bigint *b, int k) -{ - int i, k1, n, n1; - Bigint *b1; - ULong *x, *x1, *xe, z; - -#ifdef Pack_32 - n = k >> 5; -#else - n = k >> 4; -#endif - k1 = b->k; - n1 = n + b->wds + 1; - for (i = b->maxwds; n1 > i; i <<= 1) - k1++; - b1 = Balloc(k1); - x1 = b1->x; - for (i = 0; i < n; i++) - *x1++ = 0; - x = b->x; - xe = x + b->wds; -#ifdef Pack_32 - if (k &= 0x1f) { - k1 = 32 - k; - z = 0; - do { - *x1++ = *x << k | z; - z = *x++ >> k1; - } while (x < xe); - if ((*x1 = z) != 0) - ++n1; - } -#else - if (k &= 0xf) { - k1 = 16 - k; - z = 0; - do { - *x1++ = *x << k & 0xffff | z; - z = *x++ >> k1; - } while (x < xe); - if (*x1 = z) - ++n1; - } -#endif - else - do { - *x1++ = *x++; - } while (x < xe); - b1->wds = n1 - 1; - Bfree(b); - return b1; -} - -static int -cmp(Bigint *a, Bigint *b) -{ - ULong *xa, *xa0, *xb, *xb0; - int i, j; - - i = a->wds; - j = b->wds; -#ifdef DEBUG - if (i > 1 && !a->x[i-1]) - Bug("cmp called with a->x[a->wds-1] == 0"); - if (j > 1 && !b->x[j-1]) - Bug("cmp called with b->x[b->wds-1] == 0"); -#endif - if (i -= j) - return i; - xa0 = a->x; - xa = xa0 + j; - xb0 = b->x; - xb = xb0 + j; - for (;;) { - if (*--xa != *--xb) - return *xa < *xb ? -1 : 1; - if (xa <= xa0) - break; - } - return 0; -} - -NO_SANITIZE("unsigned-integer-overflow", static Bigint * diff(Bigint *a, Bigint *b)); -static Bigint * -diff(Bigint *a, Bigint *b) -{ - Bigint *c; - int i, wa, wb; - ULong *xa, *xae, *xb, *xbe, *xc; -#ifdef ULLong - ULLong borrow, y; -#else - ULong borrow, y; -#ifdef Pack_32 - ULong z; -#endif -#endif - - i = cmp(a,b); - if (!i) { - c = Balloc(0); - c->wds = 1; - c->x[0] = 0; - return c; - } - if (i < 0) { - c = a; - a = b; - b = c; - i = 1; - } - else - i = 0; - c = Balloc(a->k); - c->sign = i; - wa = a->wds; - xa = a->x; - xae = xa + wa; - wb = b->wds; - xb = b->x; - xbe = xb + wb; - xc = c->x; - borrow = 0; -#ifdef ULLong - do { - y = (ULLong)*xa++ - *xb++ - borrow; - borrow = y >> 32 & (ULong)1; - *xc++ = (ULong)(y & FFFFFFFF); - } while (xb < xbe); - while (xa < xae) { - y = *xa++ - borrow; - borrow = y >> 32 & (ULong)1; - *xc++ = (ULong)(y & FFFFFFFF); - } -#else -#ifdef Pack_32 - do { - y = (*xa & 0xffff) - (*xb & 0xffff) - borrow; - borrow = (y & 0x10000) >> 16; - z = (*xa++ >> 16) - (*xb++ >> 16) - borrow; - borrow = (z & 0x10000) >> 16; - Storeinc(xc, z, y); - } while (xb < xbe); - while (xa < xae) { - y = (*xa & 0xffff) - borrow; - borrow = (y & 0x10000) >> 16; - z = (*xa++ >> 16) - borrow; - borrow = (z & 0x10000) >> 16; - Storeinc(xc, z, y); - } -#else - do { - y = *xa++ - *xb++ - borrow; - borrow = (y & 0x10000) >> 16; - *xc++ = y & 0xffff; - } while (xb < xbe); - while (xa < xae) { - y = *xa++ - borrow; - borrow = (y & 0x10000) >> 16; - *xc++ = y & 0xffff; - } -#endif -#endif - while (!*--xc) - wa--; - c->wds = wa; - return c; -} - -static double -ulp(double x_) -{ - register Long L; - double_u x, a; - dval(x) = x_; - - L = (word0(x) & Exp_mask) - (P-1)*Exp_msk1; -#ifndef Avoid_Underflow -#ifndef Sudden_Underflow - if (L > 0) { -#endif -#endif -#ifdef IBM - L |= Exp_msk1 >> 4; -#endif - word0(a) = L; - word1(a) = 0; -#ifndef Avoid_Underflow -#ifndef Sudden_Underflow - } - else { - L = -L >> Exp_shift; - if (L < Exp_shift) { - word0(a) = 0x80000 >> L; - word1(a) = 0; - } - else { - word0(a) = 0; - L -= Exp_shift; - word1(a) = L >= 31 ? 1 : 1 << 31 - L; - } - } -#endif -#endif - return dval(a); -} - -static double -b2d(Bigint *a, int *e) -{ - ULong *xa, *xa0, w, y, z; - int k; - double_u d; -#ifdef VAX - ULong d0, d1; -#else -#define d0 word0(d) -#define d1 word1(d) -#endif - - xa0 = a->x; - xa = xa0 + a->wds; - y = *--xa; -#ifdef DEBUG - if (!y) Bug("zero y in b2d"); -#endif - k = hi0bits(y); - *e = 32 - k; -#ifdef Pack_32 - if (k < Ebits) { - d0 = Exp_1 | y >> (Ebits - k); - w = xa > xa0 ? *--xa : 0; - d1 = y << ((32-Ebits) + k) | w >> (Ebits - k); - goto ret_d; - } - z = xa > xa0 ? *--xa : 0; - if (k -= Ebits) { - d0 = Exp_1 | y << k | z >> (32 - k); - y = xa > xa0 ? *--xa : 0; - d1 = z << k | y >> (32 - k); - } - else { - d0 = Exp_1 | y; - d1 = z; - } -#else - if (k < Ebits + 16) { - z = xa > xa0 ? *--xa : 0; - d0 = Exp_1 | y << k - Ebits | z >> Ebits + 16 - k; - w = xa > xa0 ? *--xa : 0; - y = xa > xa0 ? *--xa : 0; - d1 = z << k + 16 - Ebits | w << k - Ebits | y >> 16 + Ebits - k; - goto ret_d; - } - z = xa > xa0 ? *--xa : 0; - w = xa > xa0 ? *--xa : 0; - k -= Ebits + 16; - d0 = Exp_1 | y << k + 16 | z << k | w >> 16 - k; - y = xa > xa0 ? *--xa : 0; - d1 = w << k + 16 | y << k; -#endif -ret_d: -#ifdef VAX - word0(d) = d0 >> 16 | d0 << 16; - word1(d) = d1 >> 16 | d1 << 16; -#else -#undef d0 -#undef d1 -#endif - return dval(d); -} - -static Bigint * -d2b(double d_, int *e, int *bits) -{ - double_u d; - Bigint *b; - int de, k; - ULong *x, y, z; -#ifndef Sudden_Underflow - int i; -#endif -#ifdef VAX - ULong d0, d1; -#endif - dval(d) = d_; -#ifdef VAX - d0 = word0(d) >> 16 | word0(d) << 16; - d1 = word1(d) >> 16 | word1(d) << 16; -#else -#define d0 word0(d) -#define d1 word1(d) -#endif - -#ifdef Pack_32 - b = Balloc(1); -#else - b = Balloc(2); -#endif - x = b->x; - - z = d0 & Frac_mask; - d0 &= 0x7fffffff; /* clear sign bit, which we ignore */ -#ifdef Sudden_Underflow - de = (int)(d0 >> Exp_shift); -#ifndef IBM - z |= Exp_msk11; -#endif -#else - if ((de = (int)(d0 >> Exp_shift)) != 0) - z |= Exp_msk1; -#endif -#ifdef Pack_32 - if ((y = d1) != 0) { - if ((k = lo0bits(&y)) != 0) { - x[0] = y | z << (32 - k); - z >>= k; - } - else - x[0] = y; -#ifndef Sudden_Underflow - i = -#endif - b->wds = (x[1] = z) ? 2 : 1; - } - else { -#ifdef DEBUG - if (!z) - Bug("Zero passed to d2b"); -#endif - k = lo0bits(&z); - x[0] = z; -#ifndef Sudden_Underflow - i = -#endif - b->wds = 1; - k += 32; - } -#else - if (y = d1) { - if (k = lo0bits(&y)) - if (k >= 16) { - x[0] = y | z << 32 - k & 0xffff; - x[1] = z >> k - 16 & 0xffff; - x[2] = z >> k; - i = 2; - } - else { - x[0] = y & 0xffff; - x[1] = y >> 16 | z << 16 - k & 0xffff; - x[2] = z >> k & 0xffff; - x[3] = z >> k+16; - i = 3; - } - else { - x[0] = y & 0xffff; - x[1] = y >> 16; - x[2] = z & 0xffff; - x[3] = z >> 16; - i = 3; - } - } - else { -#ifdef DEBUG - if (!z) - Bug("Zero passed to d2b"); -#endif - k = lo0bits(&z); - if (k >= 16) { - x[0] = z; - i = 0; - } - else { - x[0] = z & 0xffff; - x[1] = z >> 16; - i = 1; - } - k += 32; - } - while (!x[i]) - --i; - b->wds = i + 1; -#endif -#ifndef Sudden_Underflow - if (de) { -#endif -#ifdef IBM - *e = (de - Bias - (P-1) << 2) + k; - *bits = 4*P + 8 - k - hi0bits(word0(d) & Frac_mask); -#else - *e = de - Bias - (P-1) + k; - *bits = P - k; -#endif -#ifndef Sudden_Underflow - } - else { - *e = de - Bias - (P-1) + 1 + k; -#ifdef Pack_32 - *bits = 32*i - hi0bits(x[i-1]); -#else - *bits = (i+2)*16 - hi0bits(x[i]); -#endif - } -#endif - return b; -} -#undef d0 -#undef d1 - -static double -ratio(Bigint *a, Bigint *b) -{ - double_u da, db; - int k, ka, kb; - - dval(da) = b2d(a, &ka); - dval(db) = b2d(b, &kb); -#ifdef Pack_32 - k = ka - kb + 32*(a->wds - b->wds); -#else - k = ka - kb + 16*(a->wds - b->wds); -#endif -#ifdef IBM - if (k > 0) { - word0(da) += (k >> 2)*Exp_msk1; - if (k &= 3) - dval(da) *= 1 << k; - } - else { - k = -k; - word0(db) += (k >> 2)*Exp_msk1; - if (k &= 3) - dval(db) *= 1 << k; - } -#else - if (k > 0) - word0(da) += k*Exp_msk1; - else { - k = -k; - word0(db) += k*Exp_msk1; - } -#endif - return dval(da) / dval(db); -} - -static const double -tens[] = { - 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, - 1e10, 1e11, 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, - 1e20, 1e21, 1e22 -#ifdef VAX - , 1e23, 1e24 -#endif -}; - -static const double -#ifdef IEEE_Arith -bigtens[] = { 1e16, 1e32, 1e64, 1e128, 1e256 }; -static const double tinytens[] = { 1e-16, 1e-32, 1e-64, 1e-128, -#ifdef Avoid_Underflow - 9007199254740992.*9007199254740992.e-256 - /* = 2^106 * 1e-53 */ -#else - 1e-256 -#endif -}; -/* The factor of 2^53 in tinytens[4] helps us avoid setting the underflow */ -/* flag unnecessarily. It leads to a song and dance at the end of strtod. */ -#define Scale_Bit 0x10 -#define n_bigtens 5 -#else -#ifdef IBM -bigtens[] = { 1e16, 1e32, 1e64 }; -static const double tinytens[] = { 1e-16, 1e-32, 1e-64 }; -#define n_bigtens 3 -#else -bigtens[] = { 1e16, 1e32 }; -static const double tinytens[] = { 1e-16, 1e-32 }; -#define n_bigtens 2 -#endif -#endif - -#ifndef IEEE_Arith -#undef INFNAN_CHECK -#endif - -#ifdef INFNAN_CHECK - -#ifndef NAN_WORD0 -#define NAN_WORD0 0x7ff80000 -#endif - -#ifndef NAN_WORD1 -#define NAN_WORD1 0 -#endif - -static int -match(const char **sp, char *t) -{ - int c, d; - const char *s = *sp; - - while (d = *t++) { - if ((c = *++s) >= 'A' && c <= 'Z') - c += 'a' - 'A'; - if (c != d) - return 0; - } - *sp = s + 1; - return 1; -} - -#ifndef No_Hex_NaN -static void -hexnan(double *rvp, const char **sp) -{ - ULong c, x[2]; - const char *s; - int havedig, udx0, xshift; - - x[0] = x[1] = 0; - havedig = xshift = 0; - udx0 = 1; - s = *sp; - while (c = *(const unsigned char*)++s) { - if (c >= '0' && c <= '9') - c -= '0'; - else if (c >= 'a' && c <= 'f') - c += 10 - 'a'; - else if (c >= 'A' && c <= 'F') - c += 10 - 'A'; - else if (c <= ' ') { - if (udx0 && havedig) { - udx0 = 0; - xshift = 1; - } - continue; - } - else if (/*(*/ c == ')' && havedig) { - *sp = s + 1; - break; - } - else - return; /* invalid form: don't change *sp */ - havedig = 1; - if (xshift) { - xshift = 0; - x[0] = x[1]; - x[1] = 0; - } - if (udx0) - x[0] = (x[0] << 4) | (x[1] >> 28); - x[1] = (x[1] << 4) | c; - } - if ((x[0] &= 0xfffff) || x[1]) { - word0(*rvp) = Exp_mask | x[0]; - word1(*rvp) = x[1]; - } -} -#endif /*No_Hex_NaN*/ -#endif /* INFNAN_CHECK */ - -NO_SANITIZE("unsigned-integer-overflow", double strtod(const char *s00, char **se)); -double -strtod(const char *s00, char **se) -{ -#ifdef Avoid_Underflow - int scale; -#endif - int bb2, bb5, bbe, bd2, bd5, bbbits, bs2, c, dsign, - e, e1, esign, i, j, k, nd, nd0, nf, nz, nz0, sign; - const char *s, *s0, *s1; - double aadj, adj; - double_u aadj1, rv, rv0; - Long L; - ULong y, z; - Bigint *bb, *bb1, *bd, *bd0, *bs, *delta; -#ifdef SET_INEXACT - int inexact, oldinexact; -#endif -#ifdef Honor_FLT_ROUNDS - int rounding; -#endif -#ifdef USE_LOCALE - const char *s2; -#endif - - errno = 0; - sign = nz0 = nz = 0; - dval(rv) = 0.; - for (s = s00;;s++) - switch (*s) { - case '-': - sign = 1; - /* no break */ - case '+': - if (*++s) - goto break2; - /* no break */ - case 0: - goto ret0; - case '\t': - case '\n': - case '\v': - case '\f': - case '\r': - case ' ': - continue; - default: - goto break2; - } -break2: - if (*s == '0') { - if (s[1] == 'x' || s[1] == 'X') { - s0 = ++s; - adj = 0; - aadj = 1.0; - nd0 = -4; - - if (!*++s || !(s1 = strchr(hexdigit, *s))) goto ret0; - if (*s == '0') { - while (*++s == '0'); - s1 = strchr(hexdigit, *s); - } - if (s1 != NULL) { - do { - adj += aadj * ((s1 - hexdigit) & 15); - nd0 += 4; - aadj /= 16; - } while (*++s && (s1 = strchr(hexdigit, *s))); - } - - if (*s == '.') { - dsign = 1; - if (!*++s || !(s1 = strchr(hexdigit, *s))) goto ret0; - if (nd0 < 0) { - while (*s == '0') { - s++; - nd0 -= 4; - } - } - for (; *s && (s1 = strchr(hexdigit, *s)); ++s) { - adj += aadj * ((s1 - hexdigit) & 15); - if ((aadj /= 16) == 0.0) { - while (strchr(hexdigit, *++s)); - break; - } - } - } - else { - dsign = 0; - } - - if (*s == 'P' || *s == 'p') { - dsign = 0x2C - *++s; /* +: 2B, -: 2D */ - if (abs(dsign) == 1) s++; - else dsign = 1; - - nd = 0; - c = *s; - if (c < '0' || '9' < c) goto ret0; - do { - nd *= 10; - nd += c; - nd -= '0'; - c = *++s; - /* Float("0x0."+("0"*267)+"1fp2095") */ - if (nd + dsign * nd0 > 2095) { - while ('0' <= c && c <= '9') c = *++s; - break; - } - } while ('0' <= c && c <= '9'); - nd0 += nd * dsign; - } - else { - if (dsign) goto ret0; - } - dval(rv) = ldexp(adj, nd0); - goto ret; - } - nz0 = 1; - while (*++s == '0') ; - if (!*s) - goto ret; - } - s0 = s; - y = z = 0; - for (nd = nf = 0; (c = *s) >= '0' && c <= '9'; nd++, s++) - if (nd < 9) - y = 10*y + c - '0'; - else if (nd < DBL_DIG + 2) - z = 10*z + c - '0'; - nd0 = nd; -#ifdef USE_LOCALE - s1 = localeconv()->decimal_point; - if (c == *s1) { - c = '.'; - if (*++s1) { - s2 = s; - for (;;) { - if (*++s2 != *s1) { - c = 0; - break; - } - if (!*++s1) { - s = s2; - break; - } - } - } - } -#endif - if (c == '.') { - if (!ISDIGIT(s[1])) - goto dig_done; - c = *++s; - if (!nd) { - for (; c == '0'; c = *++s) - nz++; - if (c > '0' && c <= '9') { - s0 = s; - nf += nz; - nz = 0; - goto have_dig; - } - goto dig_done; - } - for (; c >= '0' && c <= '9'; c = *++s) { -have_dig: - nz++; - if (nd > DBL_DIG * 4) { - continue; - } - if (c -= '0') { - nf += nz; - for (i = 1; i < nz; i++) - if (nd++ < 9) - y *= 10; - else if (nd <= DBL_DIG + 2) - z *= 10; - if (nd++ < 9) - y = 10*y + c; - else if (nd <= DBL_DIG + 2) - z = 10*z + c; - nz = 0; - } - } - } -dig_done: - e = 0; - if (c == 'e' || c == 'E') { - if (!nd && !nz && !nz0) { - goto ret0; - } - s00 = s; - esign = 0; - switch (c = *++s) { - case '-': - esign = 1; - case '+': - c = *++s; - } - if (c >= '0' && c <= '9') { - while (c == '0') - c = *++s; - if (c > '0' && c <= '9') { - L = c - '0'; - s1 = s; - while ((c = *++s) >= '0' && c <= '9') - L = 10*L + c - '0'; - if (s - s1 > 8 || L > 19999) - /* Avoid confusion from exponents - * so large that e might overflow. - */ - e = 19999; /* safe for 16 bit ints */ - else - e = (int)L; - if (esign) - e = -e; - } - else - e = 0; - } - else - s = s00; - } - if (!nd) { - if (!nz && !nz0) { -#ifdef INFNAN_CHECK - /* Check for Nan and Infinity */ - switch (c) { - case 'i': - case 'I': - if (match(&s,"nf")) { - --s; - if (!match(&s,"inity")) - ++s; - word0(rv) = 0x7ff00000; - word1(rv) = 0; - goto ret; - } - break; - case 'n': - case 'N': - if (match(&s, "an")) { - word0(rv) = NAN_WORD0; - word1(rv) = NAN_WORD1; -#ifndef No_Hex_NaN - if (*s == '(') /*)*/ - hexnan(&rv, &s); -#endif - goto ret; - } - } -#endif /* INFNAN_CHECK */ -ret0: - s = s00; - sign = 0; - } - goto ret; - } - e1 = e -= nf; - - /* Now we have nd0 digits, starting at s0, followed by a - * decimal point, followed by nd-nd0 digits. The number we're - * after is the integer represented by those digits times - * 10**e */ - - if (!nd0) - nd0 = nd; - k = nd < DBL_DIG + 2 ? nd : DBL_DIG + 2; - dval(rv) = y; - if (k > 9) { -#ifdef SET_INEXACT - if (k > DBL_DIG) - oldinexact = get_inexact(); -#endif - dval(rv) = tens[k - 9] * dval(rv) + z; - } - bd0 = bb = bd = bs = delta = 0; - if (nd <= DBL_DIG -#ifndef RND_PRODQUOT -#ifndef Honor_FLT_ROUNDS - && Flt_Rounds == 1 -#endif -#endif - ) { - if (!e) - goto ret; - if (e > 0) { - if (e <= Ten_pmax) { -#ifdef VAX - goto vax_ovfl_check; -#else -#ifdef Honor_FLT_ROUNDS - /* round correctly FLT_ROUNDS = 2 or 3 */ - if (sign) { - dval(rv) = -dval(rv); - sign = 0; - } -#endif - /* rv = */ rounded_product(dval(rv), tens[e]); - goto ret; -#endif - } - i = DBL_DIG - nd; - if (e <= Ten_pmax + i) { - /* A fancier test would sometimes let us do - * this for larger i values. - */ -#ifdef Honor_FLT_ROUNDS - /* round correctly FLT_ROUNDS = 2 or 3 */ - if (sign) { - dval(rv) = -dval(rv); - sign = 0; - } -#endif - e -= i; - dval(rv) *= tens[i]; -#ifdef VAX - /* VAX exponent range is so narrow we must - * worry about overflow here... - */ -vax_ovfl_check: - word0(rv) -= P*Exp_msk1; - /* rv = */ rounded_product(dval(rv), tens[e]); - if ((word0(rv) & Exp_mask) - > Exp_msk1*(DBL_MAX_EXP+Bias-1-P)) - goto ovfl; - word0(rv) += P*Exp_msk1; -#else - /* rv = */ rounded_product(dval(rv), tens[e]); -#endif - goto ret; - } - } -#ifndef Inaccurate_Divide - else if (e >= -Ten_pmax) { -#ifdef Honor_FLT_ROUNDS - /* round correctly FLT_ROUNDS = 2 or 3 */ - if (sign) { - dval(rv) = -dval(rv); - sign = 0; - } -#endif - /* rv = */ rounded_quotient(dval(rv), tens[-e]); - goto ret; - } -#endif - } - e1 += nd - k; - -#ifdef IEEE_Arith -#ifdef SET_INEXACT - inexact = 1; - if (k <= DBL_DIG) - oldinexact = get_inexact(); -#endif -#ifdef Avoid_Underflow - scale = 0; -#endif -#ifdef Honor_FLT_ROUNDS - if ((rounding = Flt_Rounds) >= 2) { - if (sign) - rounding = rounding == 2 ? 0 : 2; - else - if (rounding != 2) - rounding = 0; - } -#endif -#endif /*IEEE_Arith*/ - - /* Get starting approximation = rv * 10**e1 */ - - if (e1 > 0) { - if ((i = e1 & 15) != 0) - dval(rv) *= tens[i]; - if (e1 &= ~15) { - if (e1 > DBL_MAX_10_EXP) { -ovfl: -#ifndef NO_ERRNO - errno = ERANGE; -#endif - /* Can't trust HUGE_VAL */ -#ifdef IEEE_Arith -#ifdef Honor_FLT_ROUNDS - switch (rounding) { - case 0: /* toward 0 */ - case 3: /* toward -infinity */ - word0(rv) = Big0; - word1(rv) = Big1; - break; - default: - word0(rv) = Exp_mask; - word1(rv) = 0; - } -#else /*Honor_FLT_ROUNDS*/ - word0(rv) = Exp_mask; - word1(rv) = 0; -#endif /*Honor_FLT_ROUNDS*/ -#ifdef SET_INEXACT - /* set overflow bit */ - dval(rv0) = 1e300; - dval(rv0) *= dval(rv0); -#endif -#else /*IEEE_Arith*/ - word0(rv) = Big0; - word1(rv) = Big1; -#endif /*IEEE_Arith*/ - if (bd0) - goto retfree; - goto ret; - } - e1 >>= 4; - for (j = 0; e1 > 1; j++, e1 >>= 1) - if (e1 & 1) - dval(rv) *= bigtens[j]; - /* The last multiplication could overflow. */ - word0(rv) -= P*Exp_msk1; - dval(rv) *= bigtens[j]; - if ((z = word0(rv) & Exp_mask) - > Exp_msk1*(DBL_MAX_EXP+Bias-P)) - goto ovfl; - if (z > Exp_msk1*(DBL_MAX_EXP+Bias-1-P)) { - /* set to largest number */ - /* (Can't trust DBL_MAX) */ - word0(rv) = Big0; - word1(rv) = Big1; - } - else - word0(rv) += P*Exp_msk1; - } - } - else if (e1 < 0) { - e1 = -e1; - if ((i = e1 & 15) != 0) - dval(rv) /= tens[i]; - if (e1 >>= 4) { - if (e1 >= 1 << n_bigtens) - goto undfl; -#ifdef Avoid_Underflow - if (e1 & Scale_Bit) - scale = 2*P; - for (j = 0; e1 > 0; j++, e1 >>= 1) - if (e1 & 1) - dval(rv) *= tinytens[j]; - if (scale && (j = 2*P + 1 - ((word0(rv) & Exp_mask) - >> Exp_shift)) > 0) { - /* scaled rv is denormal; zap j low bits */ - if (j >= 32) { - word1(rv) = 0; - if (j >= 53) - word0(rv) = (P+2)*Exp_msk1; - else - word0(rv) &= 0xffffffff << (j-32); - } - else - word1(rv) &= 0xffffffff << j; - } -#else - for (j = 0; e1 > 1; j++, e1 >>= 1) - if (e1 & 1) - dval(rv) *= tinytens[j]; - /* The last multiplication could underflow. */ - dval(rv0) = dval(rv); - dval(rv) *= tinytens[j]; - if (!dval(rv)) { - dval(rv) = 2.*dval(rv0); - dval(rv) *= tinytens[j]; -#endif - if (!dval(rv)) { -undfl: - dval(rv) = 0.; -#ifndef NO_ERRNO - errno = ERANGE; -#endif - if (bd0) - goto retfree; - goto ret; - } -#ifndef Avoid_Underflow - word0(rv) = Tiny0; - word1(rv) = Tiny1; - /* The refinement below will clean - * this approximation up. - */ - } -#endif - } - } - - /* Now the hard part -- adjusting rv to the correct value.*/ - - /* Put digits into bd: true value = bd * 10^e */ - - bd0 = s2b(s0, nd0, nd, y); - - for (;;) { - bd = Balloc(bd0->k); - Bcopy(bd, bd0); - bb = d2b(dval(rv), &bbe, &bbbits); /* rv = bb * 2^bbe */ - bs = i2b(1); - - if (e >= 0) { - bb2 = bb5 = 0; - bd2 = bd5 = e; - } - else { - bb2 = bb5 = -e; - bd2 = bd5 = 0; - } - if (bbe >= 0) - bb2 += bbe; - else - bd2 -= bbe; - bs2 = bb2; -#ifdef Honor_FLT_ROUNDS - if (rounding != 1) - bs2++; -#endif -#ifdef Avoid_Underflow - j = bbe - scale; - i = j + bbbits - 1; /* logb(rv) */ - if (i < Emin) /* denormal */ - j += P - Emin; - else - j = P + 1 - bbbits; -#else /*Avoid_Underflow*/ -#ifdef Sudden_Underflow -#ifdef IBM - j = 1 + 4*P - 3 - bbbits + ((bbe + bbbits - 1) & 3); -#else - j = P + 1 - bbbits; -#endif -#else /*Sudden_Underflow*/ - j = bbe; - i = j + bbbits - 1; /* logb(rv) */ - if (i < Emin) /* denormal */ - j += P - Emin; - else - j = P + 1 - bbbits; -#endif /*Sudden_Underflow*/ -#endif /*Avoid_Underflow*/ - bb2 += j; - bd2 += j; -#ifdef Avoid_Underflow - bd2 += scale; -#endif - i = bb2 < bd2 ? bb2 : bd2; - if (i > bs2) - i = bs2; - if (i > 0) { - bb2 -= i; - bd2 -= i; - bs2 -= i; - } - if (bb5 > 0) { - bs = pow5mult(bs, bb5); - bb1 = mult(bs, bb); - Bfree(bb); - bb = bb1; - } - if (bb2 > 0) - bb = lshift(bb, bb2); - if (bd5 > 0) - bd = pow5mult(bd, bd5); - if (bd2 > 0) - bd = lshift(bd, bd2); - if (bs2 > 0) - bs = lshift(bs, bs2); - delta = diff(bb, bd); - dsign = delta->sign; - delta->sign = 0; - i = cmp(delta, bs); -#ifdef Honor_FLT_ROUNDS - if (rounding != 1) { - if (i < 0) { - /* Error is less than an ulp */ - if (!delta->x[0] && delta->wds <= 1) { - /* exact */ -#ifdef SET_INEXACT - inexact = 0; -#endif - break; - } - if (rounding) { - if (dsign) { - adj = 1.; - goto apply_adj; - } - } - else if (!dsign) { - adj = -1.; - if (!word1(rv) - && !(word0(rv) & Frac_mask)) { - y = word0(rv) & Exp_mask; -#ifdef Avoid_Underflow - if (!scale || y > 2*P*Exp_msk1) -#else - if (y) -#endif - { - delta = lshift(delta,Log2P); - if (cmp(delta, bs) <= 0) - adj = -0.5; - } - } -apply_adj: -#ifdef Avoid_Underflow - if (scale && (y = word0(rv) & Exp_mask) - <= 2*P*Exp_msk1) - word0(adj) += (2*P+1)*Exp_msk1 - y; -#else -#ifdef Sudden_Underflow - if ((word0(rv) & Exp_mask) <= - P*Exp_msk1) { - word0(rv) += P*Exp_msk1; - dval(rv) += adj*ulp(dval(rv)); - word0(rv) -= P*Exp_msk1; - } - else -#endif /*Sudden_Underflow*/ -#endif /*Avoid_Underflow*/ - dval(rv) += adj*ulp(dval(rv)); - } - break; - } - adj = ratio(delta, bs); - if (adj < 1.) - adj = 1.; - if (adj <= 0x7ffffffe) { - /* adj = rounding ? ceil(adj) : floor(adj); */ - y = adj; - if (y != adj) { - if (!((rounding>>1) ^ dsign)) - y++; - adj = y; - } - } -#ifdef Avoid_Underflow - if (scale && (y = word0(rv) & Exp_mask) <= 2*P*Exp_msk1) - word0(adj) += (2*P+1)*Exp_msk1 - y; -#else -#ifdef Sudden_Underflow - if ((word0(rv) & Exp_mask) <= P*Exp_msk1) { - word0(rv) += P*Exp_msk1; - adj *= ulp(dval(rv)); - if (dsign) - dval(rv) += adj; - else - dval(rv) -= adj; - word0(rv) -= P*Exp_msk1; - goto cont; - } -#endif /*Sudden_Underflow*/ -#endif /*Avoid_Underflow*/ - adj *= ulp(dval(rv)); - if (dsign) - dval(rv) += adj; - else - dval(rv) -= adj; - goto cont; - } -#endif /*Honor_FLT_ROUNDS*/ - - if (i < 0) { - /* Error is less than half an ulp -- check for - * special case of mantissa a power of two. - */ - if (dsign || word1(rv) || word0(rv) & Bndry_mask -#ifdef IEEE_Arith -#ifdef Avoid_Underflow - || (word0(rv) & Exp_mask) <= (2*P+1)*Exp_msk1 -#else - || (word0(rv) & Exp_mask) <= Exp_msk1 -#endif -#endif - ) { -#ifdef SET_INEXACT - if (!delta->x[0] && delta->wds <= 1) - inexact = 0; -#endif - break; - } - if (!delta->x[0] && delta->wds <= 1) { - /* exact result */ -#ifdef SET_INEXACT - inexact = 0; -#endif - break; - } - delta = lshift(delta,Log2P); - if (cmp(delta, bs) > 0) - goto drop_down; - break; - } - if (i == 0) { - /* exactly half-way between */ - if (dsign) { - if ((word0(rv) & Bndry_mask1) == Bndry_mask1 - && word1(rv) == ( -#ifdef Avoid_Underflow - (scale && (y = word0(rv) & Exp_mask) <= 2*P*Exp_msk1) - ? (0xffffffff & (0xffffffff << (2*P+1-(y>>Exp_shift)))) : -#endif - 0xffffffff)) { - /*boundary case -- increment exponent*/ - word0(rv) = (word0(rv) & Exp_mask) - + Exp_msk1 -#ifdef IBM - | Exp_msk1 >> 4 -#endif - ; - word1(rv) = 0; -#ifdef Avoid_Underflow - dsign = 0; -#endif - break; - } - } - else if (!(word0(rv) & Bndry_mask) && !word1(rv)) { -drop_down: - /* boundary case -- decrement exponent */ -#ifdef Sudden_Underflow /*{{*/ - L = word0(rv) & Exp_mask; -#ifdef IBM - if (L < Exp_msk1) -#else -#ifdef Avoid_Underflow - if (L <= (scale ? (2*P+1)*Exp_msk1 : Exp_msk1)) -#else - if (L <= Exp_msk1) -#endif /*Avoid_Underflow*/ -#endif /*IBM*/ - goto undfl; - L -= Exp_msk1; -#else /*Sudden_Underflow}{*/ -#ifdef Avoid_Underflow - if (scale) { - L = word0(rv) & Exp_mask; - if (L <= (2*P+1)*Exp_msk1) { - if (L > (P+2)*Exp_msk1) - /* round even ==> */ - /* accept rv */ - break; - /* rv = smallest denormal */ - goto undfl; - } - } -#endif /*Avoid_Underflow*/ - L = (word0(rv) & Exp_mask) - Exp_msk1; -#endif /*Sudden_Underflow}}*/ - word0(rv) = L | Bndry_mask1; - word1(rv) = 0xffffffff; -#ifdef IBM - goto cont; -#else - break; -#endif - } -#ifndef ROUND_BIASED - if (!(word1(rv) & LSB)) - break; -#endif - if (dsign) - dval(rv) += ulp(dval(rv)); -#ifndef ROUND_BIASED - else { - dval(rv) -= ulp(dval(rv)); -#ifndef Sudden_Underflow - if (!dval(rv)) - goto undfl; -#endif - } -#ifdef Avoid_Underflow - dsign = 1 - dsign; -#endif -#endif - break; - } - if ((aadj = ratio(delta, bs)) <= 2.) { - if (dsign) - aadj = dval(aadj1) = 1.; - else if (word1(rv) || word0(rv) & Bndry_mask) { -#ifndef Sudden_Underflow - if (word1(rv) == Tiny1 && !word0(rv)) - goto undfl; -#endif - aadj = 1.; - dval(aadj1) = -1.; - } - else { - /* special case -- power of FLT_RADIX to be */ - /* rounded down... */ - - if (aadj < 2./FLT_RADIX) - aadj = 1./FLT_RADIX; - else - aadj *= 0.5; - dval(aadj1) = -aadj; - } - } - else { - aadj *= 0.5; - dval(aadj1) = dsign ? aadj : -aadj; -#ifdef Check_FLT_ROUNDS - switch (Rounding) { - case 2: /* towards +infinity */ - dval(aadj1) -= 0.5; - break; - case 0: /* towards 0 */ - case 3: /* towards -infinity */ - dval(aadj1) += 0.5; - } -#else - if (Flt_Rounds == 0) - dval(aadj1) += 0.5; -#endif /*Check_FLT_ROUNDS*/ - } - y = word0(rv) & Exp_mask; - - /* Check for overflow */ - - if (y == Exp_msk1*(DBL_MAX_EXP+Bias-1)) { - dval(rv0) = dval(rv); - word0(rv) -= P*Exp_msk1; - adj = dval(aadj1) * ulp(dval(rv)); - dval(rv) += adj; - if ((word0(rv) & Exp_mask) >= - Exp_msk1*(DBL_MAX_EXP+Bias-P)) { - if (word0(rv0) == Big0 && word1(rv0) == Big1) - goto ovfl; - word0(rv) = Big0; - word1(rv) = Big1; - goto cont; - } - else - word0(rv) += P*Exp_msk1; - } - else { -#ifdef Avoid_Underflow - if (scale && y <= 2*P*Exp_msk1) { - if (aadj <= 0x7fffffff) { - if ((z = (int)aadj) <= 0) - z = 1; - aadj = z; - dval(aadj1) = dsign ? aadj : -aadj; - } - word0(aadj1) += (2*P+1)*Exp_msk1 - y; - } - adj = dval(aadj1) * ulp(dval(rv)); - dval(rv) += adj; -#else -#ifdef Sudden_Underflow - if ((word0(rv) & Exp_mask) <= P*Exp_msk1) { - dval(rv0) = dval(rv); - word0(rv) += P*Exp_msk1; - adj = dval(aadj1) * ulp(dval(rv)); - dval(rv) += adj; -#ifdef IBM - if ((word0(rv) & Exp_mask) < P*Exp_msk1) -#else - if ((word0(rv) & Exp_mask) <= P*Exp_msk1) -#endif - { - if (word0(rv0) == Tiny0 && word1(rv0) == Tiny1) - goto undfl; - word0(rv) = Tiny0; - word1(rv) = Tiny1; - goto cont; - } - else - word0(rv) -= P*Exp_msk1; - } - else { - adj = dval(aadj1) * ulp(dval(rv)); - dval(rv) += adj; - } -#else /*Sudden_Underflow*/ - /* Compute adj so that the IEEE rounding rules will - * correctly round rv + adj in some half-way cases. - * If rv * ulp(rv) is denormalized (i.e., - * y <= (P-1)*Exp_msk1), we must adjust aadj to avoid - * trouble from bits lost to denormalization; - * example: 1.2e-307 . - */ - if (y <= (P-1)*Exp_msk1 && aadj > 1.) { - dval(aadj1) = (double)(int)(aadj + 0.5); - if (!dsign) - dval(aadj1) = -dval(aadj1); - } - adj = dval(aadj1) * ulp(dval(rv)); - dval(rv) += adj; -#endif /*Sudden_Underflow*/ -#endif /*Avoid_Underflow*/ - } - z = word0(rv) & Exp_mask; -#ifndef SET_INEXACT -#ifdef Avoid_Underflow - if (!scale) -#endif - if (y == z) { - /* Can we stop now? */ - L = (Long)aadj; - aadj -= L; - /* The tolerances below are conservative. */ - if (dsign || word1(rv) || word0(rv) & Bndry_mask) { - if (aadj < .4999999 || aadj > .5000001) - break; - } - else if (aadj < .4999999/FLT_RADIX) - break; - } -#endif -cont: - Bfree(bb); - Bfree(bd); - Bfree(bs); - Bfree(delta); - } -#ifdef SET_INEXACT - if (inexact) { - if (!oldinexact) { - word0(rv0) = Exp_1 + (70 << Exp_shift); - word1(rv0) = 0; - dval(rv0) += 1.; - } - } - else if (!oldinexact) - clear_inexact(); -#endif -#ifdef Avoid_Underflow - if (scale) { - word0(rv0) = Exp_1 - 2*P*Exp_msk1; - word1(rv0) = 0; - dval(rv) *= dval(rv0); -#ifndef NO_ERRNO - /* try to avoid the bug of testing an 8087 register value */ - if (word0(rv) == 0 && word1(rv) == 0) - errno = ERANGE; -#endif - } -#endif /* Avoid_Underflow */ -#ifdef SET_INEXACT - if (inexact && !(word0(rv) & Exp_mask)) { - /* set underflow bit */ - dval(rv0) = 1e-300; - dval(rv0) *= dval(rv0); - } -#endif -retfree: - Bfree(bb); - Bfree(bd); - Bfree(bs); - Bfree(bd0); - Bfree(delta); -ret: - if (se) - *se = (char *)s; - return sign ? -dval(rv) : dval(rv); -} - -NO_SANITIZE("unsigned-integer-overflow", static int quorem(Bigint *b, Bigint *S)); -static int -quorem(Bigint *b, Bigint *S) -{ - int n; - ULong *bx, *bxe, q, *sx, *sxe; -#ifdef ULLong - ULLong borrow, carry, y, ys; -#else - ULong borrow, carry, y, ys; -#ifdef Pack_32 - ULong si, z, zs; -#endif -#endif - - n = S->wds; -#ifdef DEBUG - /*debug*/ if (b->wds > n) - /*debug*/ Bug("oversize b in quorem"); -#endif - if (b->wds < n) - return 0; - sx = S->x; - sxe = sx + --n; - bx = b->x; - bxe = bx + n; - q = *bxe / (*sxe + 1); /* ensure q <= true quotient */ -#ifdef DEBUG - /*debug*/ if (q > 9) - /*debug*/ Bug("oversized quotient in quorem"); -#endif - if (q) { - borrow = 0; - carry = 0; - do { -#ifdef ULLong - ys = *sx++ * (ULLong)q + carry; - carry = ys >> 32; - y = *bx - (ys & FFFFFFFF) - borrow; - borrow = y >> 32 & (ULong)1; - *bx++ = (ULong)(y & FFFFFFFF); -#else -#ifdef Pack_32 - si = *sx++; - ys = (si & 0xffff) * q + carry; - zs = (si >> 16) * q + (ys >> 16); - carry = zs >> 16; - y = (*bx & 0xffff) - (ys & 0xffff) - borrow; - borrow = (y & 0x10000) >> 16; - z = (*bx >> 16) - (zs & 0xffff) - borrow; - borrow = (z & 0x10000) >> 16; - Storeinc(bx, z, y); -#else - ys = *sx++ * q + carry; - carry = ys >> 16; - y = *bx - (ys & 0xffff) - borrow; - borrow = (y & 0x10000) >> 16; - *bx++ = y & 0xffff; -#endif -#endif - } while (sx <= sxe); - if (!*bxe) { - bx = b->x; - while (--bxe > bx && !*bxe) - --n; - b->wds = n; - } - } - if (cmp(b, S) >= 0) { - q++; - borrow = 0; - carry = 0; - bx = b->x; - sx = S->x; - do { -#ifdef ULLong - ys = *sx++ + carry; - carry = ys >> 32; - y = *bx - (ys & FFFFFFFF) - borrow; - borrow = y >> 32 & (ULong)1; - *bx++ = (ULong)(y & FFFFFFFF); -#else -#ifdef Pack_32 - si = *sx++; - ys = (si & 0xffff) + carry; - zs = (si >> 16) + (ys >> 16); - carry = zs >> 16; - y = (*bx & 0xffff) - (ys & 0xffff) - borrow; - borrow = (y & 0x10000) >> 16; - z = (*bx >> 16) - (zs & 0xffff) - borrow; - borrow = (z & 0x10000) >> 16; - Storeinc(bx, z, y); -#else - ys = *sx++ + carry; - carry = ys >> 16; - y = *bx - (ys & 0xffff) - borrow; - borrow = (y & 0x10000) >> 16; - *bx++ = y & 0xffff; -#endif -#endif - } while (sx <= sxe); - bx = b->x; - bxe = bx + n; - if (!*bxe) { - while (--bxe > bx && !*bxe) - --n; - b->wds = n; - } - } - return q; -} - -#ifndef MULTIPLE_THREADS -static char *dtoa_result; -#endif - -#ifndef MULTIPLE_THREADS -static char * -rv_alloc(int i) -{ - return dtoa_result = MALLOC(i); -} -#else -#define rv_alloc(i) MALLOC(i) -#endif - -static char * -nrv_alloc(const char *s, char **rve, size_t n) -{ - char *rv, *t; - - t = rv = rv_alloc(n); - while ((*t = *s++) != 0) t++; - if (rve) - *rve = t; - return rv; -} - -#define rv_strdup(s, rve) nrv_alloc((s), (rve), strlen(s)+1) - -#ifndef MULTIPLE_THREADS -/* freedtoa(s) must be used to free values s returned by dtoa - * when MULTIPLE_THREADS is #defined. It should be used in all cases, - * but for consistency with earlier versions of dtoa, it is optional - * when MULTIPLE_THREADS is not defined. - */ - -static void -freedtoa(char *s) -{ - FREE(s); -} -#endif - -static const char INFSTR[] = "Infinity"; -static const char NANSTR[] = "NaN"; -static const char ZEROSTR[] = "0"; - -/* dtoa for IEEE arithmetic (dmg): convert double to ASCII string. - * - * Inspired by "How to Print Floating-Point Numbers Accurately" by - * Guy L. Steele, Jr. and Jon L. White [Proc. ACM SIGPLAN '90, pp. 112-126]. - * - * Modifications: - * 1. Rather than iterating, we use a simple numeric overestimate - * to determine k = floor(log10(d)). We scale relevant - * quantities using O(log2(k)) rather than O(k) multiplications. - * 2. For some modes > 2 (corresponding to ecvt and fcvt), we don't - * try to generate digits strictly left to right. Instead, we - * compute with fewer bits and propagate the carry if necessary - * when rounding the final digit up. This is often faster. - * 3. Under the assumption that input will be rounded nearest, - * mode 0 renders 1e23 as 1e23 rather than 9.999999999999999e22. - * That is, we allow equality in stopping tests when the - * round-nearest rule will give the same floating-point value - * as would satisfaction of the stopping test with strict - * inequality. - * 4. We remove common factors of powers of 2 from relevant - * quantities. - * 5. When converting floating-point integers less than 1e16, - * we use floating-point arithmetic rather than resorting - * to multiple-precision integers. - * 6. When asked to produce fewer than 15 digits, we first try - * to get by with floating-point arithmetic; we resort to - * multiple-precision integer arithmetic only if we cannot - * guarantee that the floating-point calculation has given - * the correctly rounded result. For k requested digits and - * "uniformly" distributed input, the probability is - * something like 10^(k-15) that we must resort to the Long - * calculation. - */ - -char * -dtoa(double d_, int mode, int ndigits, int *decpt, int *sign, char **rve) -{ - /* Arguments ndigits, decpt, sign are similar to those - of ecvt and fcvt; trailing zeros are suppressed from - the returned string. If not null, *rve is set to point - to the end of the return value. If d is +-Infinity or NaN, - then *decpt is set to 9999. - - mode: - 0 ==> shortest string that yields d when read in - and rounded to nearest. - 1 ==> like 0, but with Steele & White stopping rule; - e.g. with IEEE P754 arithmetic , mode 0 gives - 1e23 whereas mode 1 gives 9.999999999999999e22. - 2 ==> max(1,ndigits) significant digits. This gives a - return value similar to that of ecvt, except - that trailing zeros are suppressed. - 3 ==> through ndigits past the decimal point. This - gives a return value similar to that from fcvt, - except that trailing zeros are suppressed, and - ndigits can be negative. - 4,5 ==> similar to 2 and 3, respectively, but (in - round-nearest mode) with the tests of mode 0 to - possibly return a shorter string that rounds to d. - With IEEE arithmetic and compilation with - -DHonor_FLT_ROUNDS, modes 4 and 5 behave the same - as modes 2 and 3 when FLT_ROUNDS != 1. - 6-9 ==> Debugging modes similar to mode - 4: don't try - fast floating-point estimate (if applicable). - - Values of mode other than 0-9 are treated as mode 0. - - Sufficient space is allocated to the return value - to hold the suppressed trailing zeros. - */ - - int bbits, b2, b5, be, dig, i, ieps, ilim, ilim0, ilim1, - j, j1, k, k0, k_check, leftright, m2, m5, s2, s5, - spec_case, try_quick, half = 0; - Long L; -#ifndef Sudden_Underflow - int denorm; - ULong x; -#endif - Bigint *b, *b1, *delta, *mlo = 0, *mhi = 0, *S; - double ds; - double_u d, d2, eps; - char *s, *s0; -#ifdef Honor_FLT_ROUNDS - int rounding; -#endif -#ifdef SET_INEXACT - int inexact, oldinexact; -#endif - - dval(d) = d_; - -#ifndef MULTIPLE_THREADS - if (dtoa_result) { - freedtoa(dtoa_result); - dtoa_result = 0; - } -#endif - - if (word0(d) & Sign_bit) { - /* set sign for everything, including 0's and NaNs */ - *sign = 1; - word0(d) &= ~Sign_bit; /* clear sign bit */ - } - else - *sign = 0; - -#if defined(IEEE_Arith) + defined(VAX) -#ifdef IEEE_Arith - if ((word0(d) & Exp_mask) == Exp_mask) -#else - if (word0(d) == 0x8000) -#endif - { - /* Infinity or NaN */ - *decpt = 9999; -#ifdef IEEE_Arith - if (!word1(d) && !(word0(d) & 0xfffff)) - return rv_strdup(INFSTR, rve); -#endif - return rv_strdup(NANSTR, rve); - } -#endif -#ifdef IBM - dval(d) += 0; /* normalize */ -#endif - if (!dval(d)) { - *decpt = 1; - return rv_strdup(ZEROSTR, rve); - } - -#ifdef SET_INEXACT - try_quick = oldinexact = get_inexact(); - inexact = 1; -#endif -#ifdef Honor_FLT_ROUNDS - if ((rounding = Flt_Rounds) >= 2) { - if (*sign) - rounding = rounding == 2 ? 0 : 2; - else - if (rounding != 2) - rounding = 0; - } -#endif - - b = d2b(dval(d), &be, &bbits); -#ifdef Sudden_Underflow - i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1)); -#else - if ((i = (int)(word0(d) >> Exp_shift1 & (Exp_mask>>Exp_shift1))) != 0) { -#endif - dval(d2) = dval(d); - word0(d2) &= Frac_mask1; - word0(d2) |= Exp_11; -#ifdef IBM - if (j = 11 - hi0bits(word0(d2) & Frac_mask)) - dval(d2) /= 1 << j; -#endif - - /* log(x) ~=~ log(1.5) + (x-1.5)/1.5 - * log10(x) = log(x) / log(10) - * ~=~ log(1.5)/log(10) + (x-1.5)/(1.5*log(10)) - * log10(d) = (i-Bias)*log(2)/log(10) + log10(d2) - * - * This suggests computing an approximation k to log10(d) by - * - * k = (i - Bias)*0.301029995663981 - * + ( (d2-1.5)*0.289529654602168 + 0.176091259055681 ); - * - * We want k to be too large rather than too small. - * The error in the first-order Taylor series approximation - * is in our favor, so we just round up the constant enough - * to compensate for any error in the multiplication of - * (i - Bias) by 0.301029995663981; since |i - Bias| <= 1077, - * and 1077 * 0.30103 * 2^-52 ~=~ 7.2e-14, - * adding 1e-13 to the constant term more than suffices. - * Hence we adjust the constant term to 0.1760912590558. - * (We could get a more accurate k by invoking log10, - * but this is probably not worthwhile.) - */ - - i -= Bias; -#ifdef IBM - i <<= 2; - i += j; -#endif -#ifndef Sudden_Underflow - denorm = 0; - } - else { - /* d is denormalized */ - - i = bbits + be + (Bias + (P-1) - 1); - x = i > 32 ? word0(d) << (64 - i) | word1(d) >> (i - 32) - : word1(d) << (32 - i); - dval(d2) = x; - word0(d2) -= 31*Exp_msk1; /* adjust exponent */ - i -= (Bias + (P-1) - 1) + 1; - denorm = 1; - } -#endif - ds = (dval(d2)-1.5)*0.289529654602168 + 0.1760912590558 + i*0.301029995663981; - k = (int)ds; - if (ds < 0. && ds != k) - k--; /* want k = floor(ds) */ - k_check = 1; - if (k >= 0 && k <= Ten_pmax) { - if (dval(d) < tens[k]) - k--; - k_check = 0; - } - j = bbits - i - 1; - if (j >= 0) { - b2 = 0; - s2 = j; - } - else { - b2 = -j; - s2 = 0; - } - if (k >= 0) { - b5 = 0; - s5 = k; - s2 += k; - } - else { - b2 -= k; - b5 = -k; - s5 = 0; - } - if (mode < 0 || mode > 9) - mode = 0; - -#ifndef SET_INEXACT -#ifdef Check_FLT_ROUNDS - try_quick = Rounding == 1; -#else - try_quick = 1; -#endif -#endif /*SET_INEXACT*/ - - if (mode > 5) { - mode -= 4; - try_quick = 0; - } - leftright = 1; - ilim = ilim1 = -1; - switch (mode) { - case 0: - case 1: - i = 18; - ndigits = 0; - break; - case 2: - leftright = 0; - /* no break */ - case 4: - if (ndigits <= 0) - ndigits = 1; - ilim = ilim1 = i = ndigits; - break; - case 3: - leftright = 0; - /* no break */ - case 5: - i = ndigits + k + 1; - ilim = i; - ilim1 = i - 1; - if (i <= 0) - i = 1; - } - s = s0 = rv_alloc(i+1); - -#ifdef Honor_FLT_ROUNDS - if (mode > 1 && rounding != 1) - leftright = 0; -#endif - - if (ilim >= 0 && ilim <= Quick_max && try_quick) { - - /* Try to get by with floating-point arithmetic. */ - - i = 0; - dval(d2) = dval(d); - k0 = k; - ilim0 = ilim; - ieps = 2; /* conservative */ - if (k > 0) { - ds = tens[k&0xf]; - j = k >> 4; - if (j & Bletch) { - /* prevent overflows */ - j &= Bletch - 1; - dval(d) /= bigtens[n_bigtens-1]; - ieps++; - } - for (; j; j >>= 1, i++) - if (j & 1) { - ieps++; - ds *= bigtens[i]; - } - dval(d) /= ds; - } - else if ((j1 = -k) != 0) { - dval(d) *= tens[j1 & 0xf]; - for (j = j1 >> 4; j; j >>= 1, i++) - if (j & 1) { - ieps++; - dval(d) *= bigtens[i]; - } - } - if (k_check && dval(d) < 1. && ilim > 0) { - if (ilim1 <= 0) - goto fast_failed; - ilim = ilim1; - k--; - dval(d) *= 10.; - ieps++; - } - dval(eps) = ieps*dval(d) + 7.; - word0(eps) -= (P-1)*Exp_msk1; - if (ilim == 0) { - S = mhi = 0; - dval(d) -= 5.; - if (dval(d) > dval(eps)) - goto one_digit; - if (dval(d) < -dval(eps)) - goto no_digits; - goto fast_failed; - } -#ifndef No_leftright - if (leftright) { - /* Use Steele & White method of only - * generating digits needed. - */ - dval(eps) = 0.5/tens[ilim-1] - dval(eps); - for (i = 0;;) { - L = (int)dval(d); - dval(d) -= L; - *s++ = '0' + (int)L; - if (dval(d) < dval(eps)) - goto ret1; - if (1. - dval(d) < dval(eps)) - goto bump_up; - if (++i >= ilim) - break; - dval(eps) *= 10.; - dval(d) *= 10.; - } - } - else { -#endif - /* Generate ilim digits, then fix them up. */ - dval(eps) *= tens[ilim-1]; - for (i = 1;; i++, dval(d) *= 10.) { - L = (Long)(dval(d)); - if (!(dval(d) -= L)) - ilim = i; - *s++ = '0' + (int)L; - if (i == ilim) { - if (dval(d) > 0.5 + dval(eps)) - goto bump_up; - else if (dval(d) < 0.5 - dval(eps)) { - while (*--s == '0') ; - s++; - goto ret1; - } - half = 1; - if ((*(s-1) - '0') & 1) { - goto bump_up; - } - break; - } - } -#ifndef No_leftright - } -#endif -fast_failed: - s = s0; - dval(d) = dval(d2); - k = k0; - ilim = ilim0; - } - - /* Do we have a "small" integer? */ - - if (be >= 0 && k <= Int_max) { - /* Yes. */ - ds = tens[k]; - if (ndigits < 0 && ilim <= 0) { - S = mhi = 0; - if (ilim < 0 || dval(d) <= 5*ds) - goto no_digits; - goto one_digit; - } - for (i = 1;; i++, dval(d) *= 10.) { - L = (Long)(dval(d) / ds); - dval(d) -= L*ds; -#ifdef Check_FLT_ROUNDS - /* If FLT_ROUNDS == 2, L will usually be high by 1 */ - if (dval(d) < 0) { - L--; - dval(d) += ds; - } -#endif - *s++ = '0' + (int)L; - if (!dval(d)) { -#ifdef SET_INEXACT - inexact = 0; -#endif - break; - } - if (i == ilim) { -#ifdef Honor_FLT_ROUNDS - if (mode > 1) - switch (rounding) { - case 0: goto ret1; - case 2: goto bump_up; - } -#endif - dval(d) += dval(d); - if (dval(d) > ds || (dval(d) == ds && (L & 1))) { -bump_up: - while (*--s == '9') - if (s == s0) { - k++; - *s = '0'; - break; - } - ++*s++; - } - break; - } - } - goto ret1; - } - - m2 = b2; - m5 = b5; - if (leftright) { - i = -#ifndef Sudden_Underflow - denorm ? be + (Bias + (P-1) - 1 + 1) : -#endif -#ifdef IBM - 1 + 4*P - 3 - bbits + ((bbits + be - 1) & 3); -#else - 1 + P - bbits; -#endif - b2 += i; - s2 += i; - mhi = i2b(1); - } - if (m2 > 0 && s2 > 0) { - i = m2 < s2 ? m2 : s2; - b2 -= i; - m2 -= i; - s2 -= i; - } - if (b5 > 0) { - if (leftright) { - if (m5 > 0) { - mhi = pow5mult(mhi, m5); - b1 = mult(mhi, b); - Bfree(b); - b = b1; - } - if ((j = b5 - m5) != 0) - b = pow5mult(b, j); - } - else - b = pow5mult(b, b5); - } - S = i2b(1); - if (s5 > 0) - S = pow5mult(S, s5); - - /* Check for special case that d is a normalized power of 2. */ - - spec_case = 0; - if ((mode < 2 || leftright) -#ifdef Honor_FLT_ROUNDS - && rounding == 1 -#endif - ) { - if (!word1(d) && !(word0(d) & Bndry_mask) -#ifndef Sudden_Underflow - && word0(d) & (Exp_mask & ~Exp_msk1) -#endif - ) { - /* The special case */ - b2 += Log2P; - s2 += Log2P; - spec_case = 1; - } - } - - /* Arrange for convenient computation of quotients: - * shift left if necessary so divisor has 4 leading 0 bits. - * - * Perhaps we should just compute leading 28 bits of S once - * and for all and pass them and a shift to quorem, so it - * can do shifts and ors to compute the numerator for q. - */ -#ifdef Pack_32 - if ((i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0x1f) != 0) - i = 32 - i; -#else - if ((i = ((s5 ? 32 - hi0bits(S->x[S->wds-1]) : 1) + s2) & 0xf) != 0) - i = 16 - i; -#endif - if (i > 4) { - i -= 4; - b2 += i; - m2 += i; - s2 += i; - } - else if (i < 4) { - i += 28; - b2 += i; - m2 += i; - s2 += i; - } - if (b2 > 0) - b = lshift(b, b2); - if (s2 > 0) - S = lshift(S, s2); - if (k_check) { - if (cmp(b,S) < 0) { - k--; - b = multadd(b, 10, 0); /* we botched the k estimate */ - if (leftright) - mhi = multadd(mhi, 10, 0); - ilim = ilim1; - } - } - if (ilim <= 0 && (mode == 3 || mode == 5)) { - if (ilim < 0 || cmp(b,S = multadd(S,5,0)) <= 0) { - /* no digits, fcvt style */ -no_digits: - k = -1 - ndigits; - goto ret; - } -one_digit: - *s++ = '1'; - k++; - goto ret; - } - if (leftright) { - if (m2 > 0) - mhi = lshift(mhi, m2); - - /* Compute mlo -- check for special case - * that d is a normalized power of 2. - */ - - mlo = mhi; - if (spec_case) { - mhi = Balloc(mhi->k); - Bcopy(mhi, mlo); - mhi = lshift(mhi, Log2P); - } - - for (i = 1;;i++) { - dig = quorem(b,S) + '0'; - /* Do we yet have the shortest decimal string - * that will round to d? - */ - j = cmp(b, mlo); - delta = diff(S, mhi); - j1 = delta->sign ? 1 : cmp(b, delta); - Bfree(delta); -#ifndef ROUND_BIASED - if (j1 == 0 && mode != 1 && !(word1(d) & 1) -#ifdef Honor_FLT_ROUNDS - && rounding >= 1 -#endif - ) { - if (dig == '9') - goto round_9_up; - if (j > 0) - dig++; -#ifdef SET_INEXACT - else if (!b->x[0] && b->wds <= 1) - inexact = 0; -#endif - *s++ = dig; - goto ret; - } -#endif - if (j < 0 || (j == 0 && mode != 1 -#ifndef ROUND_BIASED - && !(word1(d) & 1) -#endif - )) { - if (!b->x[0] && b->wds <= 1) { -#ifdef SET_INEXACT - inexact = 0; -#endif - goto accept_dig; - } -#ifdef Honor_FLT_ROUNDS - if (mode > 1) - switch (rounding) { - case 0: goto accept_dig; - case 2: goto keep_dig; - } -#endif /*Honor_FLT_ROUNDS*/ - if (j1 > 0) { - b = lshift(b, 1); - j1 = cmp(b, S); - if ((j1 > 0 || (j1 == 0 && (dig & 1))) && dig++ == '9') - goto round_9_up; - } -accept_dig: - *s++ = dig; - goto ret; - } - if (j1 > 0) { -#ifdef Honor_FLT_ROUNDS - if (!rounding) - goto accept_dig; -#endif - if (dig == '9') { /* possible if i == 1 */ -round_9_up: - *s++ = '9'; - goto roundoff; - } - *s++ = dig + 1; - goto ret; - } -#ifdef Honor_FLT_ROUNDS -keep_dig: -#endif - *s++ = dig; - if (i == ilim) - break; - b = multadd(b, 10, 0); - if (mlo == mhi) - mlo = mhi = multadd(mhi, 10, 0); - else { - mlo = multadd(mlo, 10, 0); - mhi = multadd(mhi, 10, 0); - } - } - } - else - for (i = 1;; i++) { - *s++ = dig = quorem(b,S) + '0'; - if (!b->x[0] && b->wds <= 1) { -#ifdef SET_INEXACT - inexact = 0; -#endif - goto ret; - } - if (i >= ilim) - break; - b = multadd(b, 10, 0); - } - - /* Round off last digit */ - -#ifdef Honor_FLT_ROUNDS - switch (rounding) { - case 0: goto trimzeros; - case 2: goto roundoff; - } -#endif - b = lshift(b, 1); - j = cmp(b, S); - if (j > 0 || (j == 0 && (dig & 1))) { - roundoff: - while (*--s == '9') - if (s == s0) { - k++; - *s++ = '1'; - goto ret; - } - if (!half || (*s - '0') & 1) - ++*s; - } - else { - while (*--s == '0') ; - } - s++; -ret: - Bfree(S); - if (mhi) { - if (mlo && mlo != mhi) - Bfree(mlo); - Bfree(mhi); - } -ret1: -#ifdef SET_INEXACT - if (inexact) { - if (!oldinexact) { - word0(d) = Exp_1 + (70 << Exp_shift); - word1(d) = 0; - dval(d) += 1.; - } - } - else if (!oldinexact) - clear_inexact(); -#endif - Bfree(b); - *s = 0; - *decpt = k + 1; - if (rve) - *rve = s; - return s0; -} - -/*- - * Copyright (c) 2004-2008 David Schultz - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. 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. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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. - */ - -#define DBL_MANH_SIZE 20 -#define DBL_MANL_SIZE 32 -#define DBL_ADJ (DBL_MAX_EXP - 2) -#define SIGFIGS ((DBL_MANT_DIG + 3) / 4 + 1) -#define dexp_get(u) ((int)(word0(u) >> Exp_shift) & ~Exp_msk1) -#define dexp_set(u,v) (word0(u) = (((int)(word0(u)) & ~Exp_mask) | ((v) << Exp_shift))) -#define dmanh_get(u) ((uint32_t)(word0(u) & Frac_mask)) -#define dmanl_get(u) ((uint32_t)word1(u)) - - -/* - * This procedure converts a double-precision number in IEEE format - * into a string of hexadecimal digits and an exponent of 2. Its - * behavior is bug-for-bug compatible with dtoa() in mode 2, with the - * following exceptions: - * - * - An ndigits < 0 causes it to use as many digits as necessary to - * represent the number exactly. - * - The additional xdigs argument should point to either the string - * "0123456789ABCDEF" or the string "0123456789abcdef", depending on - * which case is desired. - * - This routine does not repeat dtoa's mistake of setting decpt - * to 9999 in the case of an infinity or NaN. INT_MAX is used - * for this purpose instead. - * - * Note that the C99 standard does not specify what the leading digit - * should be for non-zero numbers. For instance, 0x1.3p3 is the same - * as 0x2.6p2 is the same as 0x4.cp3. This implementation always makes - * the leading digit a 1. This ensures that the exponent printed is the - * actual base-2 exponent, i.e., ilogb(d). - * - * Inputs: d, xdigs, ndigits - * Outputs: decpt, sign, rve - */ -char * -hdtoa(double d, const char *xdigs, int ndigits, int *decpt, int *sign, char **rve) -{ - U u; - char *s, *s0; - int bufsize; - uint32_t manh, manl; - - u.d = d; - if (word0(u) & Sign_bit) { - /* set sign for everything, including 0's and NaNs */ - *sign = 1; - word0(u) &= ~Sign_bit; /* clear sign bit */ - } - else - *sign = 0; - - if (isinf(d)) { /* FP_INFINITE */ - *decpt = INT_MAX; - return rv_strdup(INFSTR, rve); - } - else if (isnan(d)) { /* FP_NAN */ - *decpt = INT_MAX; - return rv_strdup(NANSTR, rve); - } - else if (d == 0.0) { /* FP_ZERO */ - *decpt = 1; - return rv_strdup(ZEROSTR, rve); - } - else if (dexp_get(u)) { /* FP_NORMAL */ - *decpt = dexp_get(u) - DBL_ADJ; - } - else { /* FP_SUBNORMAL */ - u.d *= 5.363123171977039e+154 /* 0x1p514 */; - *decpt = dexp_get(u) - (514 + DBL_ADJ); - } - - if (ndigits == 0) /* dtoa() compatibility */ - ndigits = 1; - - /* - * If ndigits < 0, we are expected to auto-size, so we allocate - * enough space for all the digits. - */ - bufsize = (ndigits > 0) ? ndigits : SIGFIGS; - s0 = rv_alloc(bufsize+1); - - /* Round to the desired number of digits. */ - if (SIGFIGS > ndigits && ndigits > 0) { - float redux = 1.0f; - int offset = 4 * ndigits + DBL_MAX_EXP - 4 - DBL_MANT_DIG; - dexp_set(u, offset); - u.d += redux; - u.d -= redux; - *decpt += dexp_get(u) - offset; - } - - manh = dmanh_get(u); - manl = dmanl_get(u); - *s0 = '1'; - for (s = s0 + 1; s < s0 + bufsize; s++) { - *s = xdigs[(manh >> (DBL_MANH_SIZE - 4)) & 0xf]; - manh = (manh << 4) | (manl >> (DBL_MANL_SIZE - 4)); - manl <<= 4; - } - - /* If ndigits < 0, we are expected to auto-size the precision. */ - if (ndigits < 0) { - for (ndigits = SIGFIGS; s0[ndigits - 1] == '0'; ndigits--) - ; - } - - s = s0 + ndigits; - *s = '\0'; - if (rve != NULL) - *rve = s; - return (s0); -} - -#ifdef __cplusplus -#if 0 -{ /* satisfy cc-mode */ -#endif -} -#endif diff --git a/ext/bigdecimal/sample/linear.rb b/ext/bigdecimal/sample/linear.rb deleted file mode 100644 index 516c2473be8fce..00000000000000 --- a/ext/bigdecimal/sample/linear.rb +++ /dev/null @@ -1,74 +0,0 @@ -#!/usr/local/bin/ruby -# frozen_string_literal: false - -# -# linear.rb -# -# Solves linear equation system(A*x = b) by LU decomposition method. -# where A is a coefficient matrix,x is an answer vector,b is a constant vector. -# -# USAGE: -# ruby linear.rb [input file solved] -# - -# :stopdoc: -require "bigdecimal" -require "bigdecimal/ludcmp" - -# -# NOTE: -# Change following BigDecimal.limit() if needed. -BigDecimal.limit(100) -# - -include LUSolve -def rd_order(na) - printf("Number of equations ?") if(na <= 0) - n = ARGF.gets().to_i -end - -na = ARGV.size -zero = BigDecimal("0.0") -one = BigDecimal("1.0") - -while (n=rd_order(na))>0 - a = [] - as= [] - b = [] - if na <= 0 - # Read data from console. - printf("\nEnter coefficient matrix element A[i,j]\n") - for i in 0...n do - for j in 0...n do - printf("A[%d,%d]? ",i,j); s = ARGF.gets - a << BigDecimal(s) - as << BigDecimal(s) - end - printf("Contatant vector element b[%d] ? ",i) - b << BigDecimal(ARGF.gets) - end - else - # Read data from specified file. - printf("Coefficient matrix and constant vector.\n") - for i in 0...n do - s = ARGF.gets - printf("%d) %s",i,s) - s = s.split - for j in 0...n do - a << BigDecimal(s[j]) - as << BigDecimal(s[j]) - end - b << BigDecimal(s[n]) - end - end - x = lusolve(a,b,ludecomp(a,n,zero,one),zero) - printf("Answer(x[i] & (A*x-b)[i]) follows\n") - for i in 0...n do - printf("x[%d]=%s ",i,x[i].to_s) - s = zero - for j in 0...n do - s = s + as[i*n+j]*x[j] - end - printf(" & %s\n",(s-b[i]).to_s) - end -end diff --git a/ext/bigdecimal/sample/nlsolve.rb b/ext/bigdecimal/sample/nlsolve.rb deleted file mode 100644 index c2227dac739ba7..00000000000000 --- a/ext/bigdecimal/sample/nlsolve.rb +++ /dev/null @@ -1,40 +0,0 @@ -#!/usr/local/bin/ruby -# frozen_string_literal: false - -# -# nlsolve.rb -# An example for solving nonlinear algebraic equation system. -# - -require "bigdecimal" -require "bigdecimal/newton" -include Newton - -class Function # :nodoc: all - def initialize() - @zero = BigDecimal("0.0") - @one = BigDecimal("1.0") - @two = BigDecimal("2.0") - @ten = BigDecimal("10.0") - @eps = BigDecimal("1.0e-16") - end - def zero;@zero;end - def one ;@one ;end - def two ;@two ;end - def ten ;@ten ;end - def eps ;@eps ;end - def values(x) # <= defines functions solved - f = [] - f1 = x[0]*x[0] + x[1]*x[1] - @two # f1 = x**2 + y**2 - 2 => 0 - f2 = x[0] - x[1] # f2 = x - y => 0 - f <<= f1 - f <<= f2 - f - end -end - -f = BigDecimal.limit(100) -f = Function.new -x = [f.zero,f.zero] # Initial values -n = nlsolve(f,x) -p x diff --git a/ext/bigdecimal/sample/pi.rb b/ext/bigdecimal/sample/pi.rb deleted file mode 100644 index ea9663896c2a21..00000000000000 --- a/ext/bigdecimal/sample/pi.rb +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/local/bin/ruby -# frozen_string_literal: false - -# -# pi.rb -# -# Calculates 3.1415.... (the number of times that a circle's diameter -# will fit around the circle) using J. Machin's formula. -# - -require "bigdecimal" -require "bigdecimal/math.rb" - -include BigMath - -if ARGV.size == 1 - print "PI("+ARGV[0]+"):\n" - p PI(ARGV[0].to_i) -else - print "TRY: ruby pi.rb 1000 \n" -end diff --git a/ext/bigdecimal/static_assert.h b/ext/bigdecimal/static_assert.h deleted file mode 100644 index 9295729bf6a61c..00000000000000 --- a/ext/bigdecimal/static_assert.h +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef BIGDECIMAL_STATIC_ASSERT_H -#define BIGDECIMAL_STATIC_ASSERT_H - -#include "feature.h" - -#ifdef HAVE_RUBY_INTERNAL_STATIC_ASSERT_H -# include -#endif - -#ifdef RBIMPL_STATIC_ASSERT -# define STATIC_ASSERT RBIMPL_STATIC_ASSERT -#endif - -#ifndef STATIC_ASSERT -# /* The following section is copied from CRuby's static_assert.h */ - -# if defined(__cplusplus) && defined(__cpp_static_assert) -# /* https://isocpp.org/std/standing-documents/sd-6-sg10-feature-test-recommendations */ -# define BIGDECIMAL_STATIC_ASSERT0 static_assert - -# elif defined(__cplusplus) && defined(_MSC_VER) && _MSC_VER >= 1600 -# define BIGDECIMAL_STATIC_ASSERT0 static_assert - -# elif defined(__INTEL_CXX11_MODE__) -# define BIGDECIMAL_STATIC_ASSERT0 static_assert - -# elif defined(__cplusplus) && __cplusplus >= 201103L -# define BIGDECIMAL_STATIC_ASSERT0 static_assert - -# elif defined(__cplusplus) && __has_extension(cxx_static_assert) -# define BIGDECIMAL_STATIC_ASSERT0 __extension__ static_assert - -# elif defined(__STDC_VERSION__) && __has_extension(c_static_assert) -# define BIGDECIMAL_STATIC_ASSERT0 __extension__ _Static_assert - -# elif defined(__STDC_VERSION__) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) -# define BIGDECIMAL_STATIC_ASSERT0 __extension__ _Static_assert -#endif - -# if defined(__DOXYGEN__) -# define STATIC_ASSERT static_assert - -# elif defined(BIGDECIMAL_STATIC_ASSERT0) -# define STATIC_ASSERT(name, expr) \ - BIGDECIMAL_STATIC_ASSERT0(expr, #name ": " #expr) - -# else -# define STATIC_ASSERT(name, expr) \ - typedef int static_assert_ ## name ## _check[1 - 2 * !(expr)] -# endif -#endif /* STATIC_ASSERT */ - - -#endif /* BIGDECIMAL_STATIC_ASSERT_H */ diff --git a/ext/cgi/escape/depend b/ext/cgi/escape/depend index 37304a24f4b5bf..05b59bfdea351d 100644 --- a/ext/cgi/escape/depend +++ b/ext/cgi/escape/depend @@ -138,6 +138,7 @@ escape.o: $(hdrdir)/ruby/internal/intern/re.h escape.o: $(hdrdir)/ruby/internal/intern/ruby.h escape.o: $(hdrdir)/ruby/internal/intern/select.h escape.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +escape.o: $(hdrdir)/ruby/internal/intern/set.h escape.o: $(hdrdir)/ruby/internal/intern/signal.h escape.o: $(hdrdir)/ruby/internal/intern/sprintf.h escape.o: $(hdrdir)/ruby/internal/intern/string.h @@ -157,6 +158,7 @@ escape.o: $(hdrdir)/ruby/internal/special_consts.h escape.o: $(hdrdir)/ruby/internal/static_assert.h escape.o: $(hdrdir)/ruby/internal/stdalign.h escape.o: $(hdrdir)/ruby/internal/stdbool.h +escape.o: $(hdrdir)/ruby/internal/stdckdint.h escape.o: $(hdrdir)/ruby/internal/symbol.h escape.o: $(hdrdir)/ruby/internal/value.h escape.o: $(hdrdir)/ruby/internal/value_type.h diff --git a/ext/cgi/escape/escape.c b/ext/cgi/escape/escape.c index c5b76de596efb5..6b00bc37c1753f 100644 --- a/ext/cgi/escape/escape.c +++ b/ext/cgi/escape/escape.c @@ -8,7 +8,7 @@ RUBY_EXTERN const signed char ruby_digit36_to_number_table[]; #define upper_hexdigits (ruby_hexdigits+16) #define char_to_number(c) ruby_digit36_to_number_table[(unsigned char)(c)] -static VALUE rb_cCGI, rb_mUtil, rb_mEscape; +static VALUE rb_cCGI, rb_mEscape, rb_mEscapeExt; static ID id_accept_charset; #define HTML_ESCAPE_MAX_LEN 6 @@ -83,7 +83,7 @@ optimized_unescape_html(VALUE str) unsigned long charlimit = (strcasecmp(rb_enc_name(enc), "UTF-8") == 0 ? UNICODE_MAX : strcasecmp(rb_enc_name(enc), "ISO-8859-1") == 0 ? 256 : 128); - long i, len, beg = 0; + long i, j, len, beg = 0; size_t clen, plen; int overflow; const char *cstr; @@ -100,6 +100,7 @@ optimized_unescape_html(VALUE str) plen = i - beg; if (++i >= len) break; c = (unsigned char)cstr[i]; + j = i; #define MATCH(s) (len - i >= (int)rb_strlen_lit(s) && \ memcmp(&cstr[i], s, rb_strlen_lit(s)) == 0 && \ (i += rb_strlen_lit(s) - 1, 1)) @@ -112,28 +113,40 @@ optimized_unescape_html(VALUE str) else if (MATCH("mp;")) { c = '&'; } - else continue; + else { + i = j; + continue; + } break; case 'q': ++i; if (MATCH("uot;")) { c = '"'; } - else continue; + else { + i = j; + continue; + } break; case 'g': ++i; if (MATCH("t;")) { c = '>'; } - else continue; + else { + i = j; + continue; + } break; case 'l': ++i; if (MATCH("t;")) { c = '<'; } - else continue; + else { + i = j; + continue; + } break; case '#': if (len - ++i >= 2 && ISDIGIT(cstr[i])) { @@ -142,9 +155,15 @@ optimized_unescape_html(VALUE str) else if ((cstr[i] == 'x' || cstr[i] == 'X') && len - ++i >= 2 && ISXDIGIT(cstr[i])) { cc = ruby_scan_digits(&cstr[i], len-i, 16, &clen, &overflow); } - else continue; + else { + i = j; + continue; + } i += clen; - if (overflow || cc >= charlimit || cstr[i] != ';') continue; + if (overflow || cc >= charlimit || cstr[i] != ';') { + i = j; + continue; + } if (!dest) { dest = rb_str_buf_new(len); } @@ -452,15 +471,17 @@ Init_escape(void) void InitVM_escape(void) { - rb_cCGI = rb_define_class("CGI", rb_cObject); - rb_mEscape = rb_define_module_under(rb_cCGI, "Escape"); - rb_mUtil = rb_define_module_under(rb_cCGI, "Util"); - rb_define_method(rb_mEscape, "escapeHTML", cgiesc_escape_html, 1); - rb_define_method(rb_mEscape, "unescapeHTML", cgiesc_unescape_html, 1); - rb_define_method(rb_mEscape, "escapeURIComponent", cgiesc_escape_uri_component, 1); - rb_define_method(rb_mEscape, "unescapeURIComponent", cgiesc_unescape_uri_component, -1); - rb_define_method(rb_mEscape, "escape", cgiesc_escape, 1); - rb_define_method(rb_mEscape, "unescape", cgiesc_unescape, -1); - rb_prepend_module(rb_mUtil, rb_mEscape); - rb_extend_object(rb_cCGI, rb_mEscape); + rb_cCGI = rb_define_class("CGI", rb_cObject); + rb_mEscapeExt = rb_define_module_under(rb_cCGI, "EscapeExt"); + rb_mEscape = rb_define_module_under(rb_cCGI, "Escape"); + rb_define_method(rb_mEscapeExt, "escapeHTML", cgiesc_escape_html, 1); + rb_define_method(rb_mEscapeExt, "unescapeHTML", cgiesc_unescape_html, 1); + rb_define_method(rb_mEscapeExt, "escapeURIComponent", cgiesc_escape_uri_component, 1); + rb_define_alias(rb_mEscapeExt, "escape_uri_component", "escapeURIComponent"); + rb_define_method(rb_mEscapeExt, "unescapeURIComponent", cgiesc_unescape_uri_component, -1); + rb_define_alias(rb_mEscapeExt, "unescape_uri_component", "unescapeURIComponent"); + rb_define_method(rb_mEscapeExt, "escape", cgiesc_escape, 1); + rb_define_method(rb_mEscapeExt, "unescape", cgiesc_unescape, -1); + rb_prepend_module(rb_mEscape, rb_mEscapeExt); + rb_extend_object(rb_cCGI, rb_mEscapeExt); } diff --git a/ext/continuation/depend b/ext/continuation/depend index f0333d7fe6377a..b395d3d4d7a1bb 100644 --- a/ext/continuation/depend +++ b/ext/continuation/depend @@ -127,6 +127,7 @@ continuation.o: $(hdrdir)/ruby/internal/intern/re.h continuation.o: $(hdrdir)/ruby/internal/intern/ruby.h continuation.o: $(hdrdir)/ruby/internal/intern/select.h continuation.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +continuation.o: $(hdrdir)/ruby/internal/intern/set.h continuation.o: $(hdrdir)/ruby/internal/intern/signal.h continuation.o: $(hdrdir)/ruby/internal/intern/sprintf.h continuation.o: $(hdrdir)/ruby/internal/intern/string.h @@ -146,6 +147,7 @@ continuation.o: $(hdrdir)/ruby/internal/special_consts.h continuation.o: $(hdrdir)/ruby/internal/static_assert.h continuation.o: $(hdrdir)/ruby/internal/stdalign.h continuation.o: $(hdrdir)/ruby/internal/stdbool.h +continuation.o: $(hdrdir)/ruby/internal/stdckdint.h continuation.o: $(hdrdir)/ruby/internal/symbol.h continuation.o: $(hdrdir)/ruby/internal/value.h continuation.o: $(hdrdir)/ruby/internal/value_type.h diff --git a/ext/coverage/coverage.c b/ext/coverage/coverage.c index a3381901ee4ad1..1519b559cdafc1 100644 --- a/ext/coverage/coverage.c +++ b/ext/coverage/coverage.c @@ -243,8 +243,8 @@ method_coverage_i(void *vstart, void *vend, size_t stride, void *data) VALUE ncoverages = *(VALUE*)data, v; for (v = (VALUE)vstart; v != (VALUE)vend; v += stride) { - void *poisoned = asan_poisoned_object_p(v); - asan_unpoison_object(v, false); + void *poisoned = rb_asan_poisoned_object_p(v); + rb_asan_unpoison_object(v, false); if (RB_TYPE_P(v, T_IMEMO) && imemo_type(v) == imemo_ment) { const rb_method_entry_t *me = (rb_method_entry_t *) v; @@ -287,7 +287,7 @@ method_coverage_i(void *vstart, void *vend, size_t stride, void *data) } if (poisoned) { - asan_poison_object(v); + rb_asan_poison_object(v); } } return 0; @@ -353,7 +353,8 @@ rb_coverage_peek_result(VALUE klass) rb_raise(rb_eRuntimeError, "coverage measurement is not enabled"); } OBJ_WB_UNPROTECT(coverages); - st_foreach(RHASH_TBL_RAW(coverages), coverage_peek_result_i, ncoverages); + + rb_hash_foreach(coverages, coverage_peek_result_i, ncoverages); if (current_mode & COVERAGE_TARGET_METHODS) { rb_objspace_each_objects(method_coverage_i, &ncoverages); diff --git a/ext/coverage/depend b/ext/coverage/depend index 0a6c61d5c64658..e042bac7c4dc8b 100644 --- a/ext/coverage/depend +++ b/ext/coverage/depend @@ -140,6 +140,7 @@ coverage.o: $(hdrdir)/ruby/internal/intern/re.h coverage.o: $(hdrdir)/ruby/internal/intern/ruby.h coverage.o: $(hdrdir)/ruby/internal/intern/select.h coverage.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +coverage.o: $(hdrdir)/ruby/internal/intern/set.h coverage.o: $(hdrdir)/ruby/internal/intern/signal.h coverage.o: $(hdrdir)/ruby/internal/intern/sprintf.h coverage.o: $(hdrdir)/ruby/internal/intern/string.h @@ -159,6 +160,7 @@ coverage.o: $(hdrdir)/ruby/internal/special_consts.h coverage.o: $(hdrdir)/ruby/internal/static_assert.h coverage.o: $(hdrdir)/ruby/internal/stdalign.h coverage.o: $(hdrdir)/ruby/internal/stdbool.h +coverage.o: $(hdrdir)/ruby/internal/stdckdint.h coverage.o: $(hdrdir)/ruby/internal/symbol.h coverage.o: $(hdrdir)/ruby/internal/value.h coverage.o: $(hdrdir)/ruby/internal/value_type.h @@ -185,8 +187,10 @@ coverage.o: $(top_srcdir)/internal/compilers.h coverage.o: $(top_srcdir)/internal/gc.h coverage.o: $(top_srcdir)/internal/hash.h coverage.o: $(top_srcdir)/internal/imemo.h +coverage.o: $(top_srcdir)/internal/namespace.h coverage.o: $(top_srcdir)/internal/sanitizers.h coverage.o: $(top_srcdir)/internal/serial.h +coverage.o: $(top_srcdir)/internal/set_table.h coverage.o: $(top_srcdir)/internal/static_assert.h coverage.o: $(top_srcdir)/internal/thread.h coverage.o: $(top_srcdir)/internal/variable.h diff --git a/ext/date/date.gemspec b/ext/date/date.gemspec index 660353ebc5963b..cb439bd0a56e9b 100644 --- a/ext/date/date.gemspec +++ b/ext/date/date.gemspec @@ -7,8 +7,8 @@ end Gem::Specification.new do |s| s.name = "date" s.version = version - s.summary = "A subclass of Object includes Comparable module for handling dates." - s.description = "A subclass of Object includes Comparable module for handling dates." + s.summary = "The official date library for Ruby." + s.description = "The official date library for Ruby." if Gem::Platform === s.platform and s.platform =~ 'java' or RUBY_ENGINE == 'jruby' s.platform = 'java' @@ -17,7 +17,7 @@ Gem::Specification.new do |s| s.require_path = %w{lib} s.files = [ - "README.md", + "README.md", "COPYING", "BSDL", "lib/date.rb", "ext/date/date_core.c", "ext/date/date_parse.c", "ext/date/date_strftime.c", "ext/date/date_strptime.c", "ext/date/date_tmx.h", "ext/date/extconf.rb", "ext/date/prereq.mk", "ext/date/zonetab.h", "ext/date/zonetab.list" @@ -31,4 +31,6 @@ Gem::Specification.new do |s| s.email = [nil] s.homepage = "https://github.com/ruby/date" s.licenses = ["Ruby", "BSD-2-Clause"] + + s.metadata["changelog_uri"] = s.homepage + "/releases" end diff --git a/ext/date/date_core.c b/ext/date/date_core.c index f2baf4fcea813d..dbee067f6baa8e 100644 --- a/ext/date/date_core.c +++ b/ext/date/date_core.c @@ -57,7 +57,7 @@ static VALUE sym_hour, sym_min, sym_sec, sym_sec_fraction, sym_zone; #define f_add3(x,y,z) f_add(f_add(x, y), z) #define f_sub3(x,y,z) f_sub(f_sub(x, y), z) -#define f_frozen_ary(...) rb_obj_freeze(rb_ary_new3(__VA_ARGS__)) +#define f_frozen_ary(...) rb_ary_freeze(rb_ary_new3(__VA_ARGS__)) static VALUE date_initialize(int argc, VALUE *argv, VALUE self); static VALUE datetime_initialize(int argc, VALUE *argv, VALUE self); @@ -248,6 +248,11 @@ f_negative_p(VALUE x) #define date_sg_t double #endif +#define JULIAN_EPOCH_DATE "-4712-01-01" +#define JULIAN_EPOCH_DATETIME JULIAN_EPOCH_DATE "T00:00:00+00:00" +#define JULIAN_EPOCH_DATETIME_RFC3339 "Mon, 1 Jan -4712 00:00:00 +0000" +#define JULIAN_EPOCH_DATETIME_HTTPDATE "Mon, 01 Jan -4712 00:00:00 GMT" + /* A set of nth, jd, df and sf denote ajd + 1/2. Each ajd begin at * noon of GMT (assume equal to UTC). However, this begins at * midnight. @@ -1594,7 +1599,7 @@ m_ajd(union DateData *x) if (simple_dat_p(x)) { r = m_real_jd(x); - if (FIXNUM_P(r) && FIX2LONG(r) <= (FIXNUM_MAX / 2)) { + if (FIXNUM_P(r) && FIX2LONG(r) <= (FIXNUM_MAX / 2) && FIX2LONG(r) >= (FIXNUM_MIN + 1) / 2) { long ir = FIX2LONG(r); ir = ir * 2 - 1; return rb_rational_new2(LONG2FIX(ir), INT2FIX(2)); @@ -2493,7 +2498,7 @@ date_s__valid_jd_p(int argc, VALUE *argv, VALUE klass) * * Date.valid_jd?(2451944) # => true * - * See argument {start}[rdoc-ref:calendars.rdoc@Argument+start]. + * See argument {start}[rdoc-ref:date/calendars.rdoc@Argument+start]. * * Related: Date.jd. */ @@ -2587,7 +2592,7 @@ date_s__valid_civil_p(int argc, VALUE *argv, VALUE klass) * Date.valid_date?(2001, 2, 29) # => false * Date.valid_date?(2001, 2, -1) # => true * - * See argument {start}[rdoc-ref:calendars.rdoc@Argument+start]. + * See argument {start}[rdoc-ref:date/calendars.rdoc@Argument+start]. * * Related: Date.jd, Date.new. */ @@ -2675,7 +2680,7 @@ date_s__valid_ordinal_p(int argc, VALUE *argv, VALUE klass) * Date.valid_ordinal?(2001, 34) # => true * Date.valid_ordinal?(2001, 366) # => false * - * See argument {start}[rdoc-ref:calendars.rdoc@Argument+start]. + * See argument {start}[rdoc-ref:date/calendars.rdoc@Argument+start]. * * Related: Date.jd, Date.ordinal. */ @@ -2765,7 +2770,7 @@ date_s__valid_commercial_p(int argc, VALUE *argv, VALUE klass) * * See Date.commercial. * - * See argument {start}[rdoc-ref:calendars.rdoc@Argument+start]. + * See argument {start}[rdoc-ref:date/calendars.rdoc@Argument+start]. * * Related: Date.jd, Date.commercial. */ @@ -3345,7 +3350,7 @@ static VALUE d_lite_plus(VALUE, VALUE); * * Date.jd(Date::ITALY - 1).julian? # => true * - * See argument {start}[rdoc-ref:calendars.rdoc@Argument+start]. + * See argument {start}[rdoc-ref:date/calendars.rdoc@Argument+start]. * * Related: Date.new. */ @@ -3410,7 +3415,7 @@ date_s_jd(int argc, VALUE *argv, VALUE klass) * * Raises an exception if +yday+ is zero or out of range. * - * See argument {start}[rdoc-ref:calendars.rdoc@Argument+start]. + * See argument {start}[rdoc-ref:date/calendars.rdoc@Argument+start]. * * Related: Date.jd, Date.new. */ @@ -3487,7 +3492,7 @@ date_s_civil(int argc, VALUE *argv, VALUE klass) * where +n+ is the number of days in the month; * when the argument is negative, counts backward from the end of the month. * - * See argument {start}[rdoc-ref:calendars.rdoc@Argument+start]. + * See argument {start}[rdoc-ref:date/calendars.rdoc@Argument+start]. * * Related: Date.jd. */ @@ -3593,7 +3598,7 @@ date_initialize(int argc, VALUE *argv, VALUE self) * Date.commercial(2020, 1, 1).to_s # => "2019-12-30" Date.commercial(2020, 1, 7).to_s # => "2020-01-05" * - * See argument {start}[rdoc-ref:calendars.rdoc@Argument+start]. + * See argument {start}[rdoc-ref:date/calendars.rdoc@Argument+start]. * * Related: Date.jd, Date.new, Date.ordinal. */ @@ -3778,7 +3783,7 @@ static void set_sg(union DateData *, double); * * Date.today.to_s # => "2022-07-06" * - * See argument {start}[rdoc-ref:calendars.rdoc@Argument+start]. + * See argument {start}[rdoc-ref:date/calendars.rdoc@Argument+start]. * */ static VALUE @@ -3873,7 +3878,6 @@ static VALUE rt_complete_frags(VALUE klass, VALUE hash) { static VALUE tab = Qnil; - int g; long e; VALUE k, a, d; @@ -3970,9 +3974,13 @@ rt_complete_frags(VALUE klass, VALUE hash) rb_gc_register_mark_object(tab); } + k = Qnil; + { - long i, eno = 0, idx = 0; + long i, eno = 0; + VALUE t = Qnil; + e = 0; for (i = 0; i < RARRAY_LEN(tab); i++) { VALUE x, a; @@ -3987,23 +3995,20 @@ rt_complete_frags(VALUE klass, VALUE hash) n++; if (n > eno) { eno = n; - idx = i; + t = x; } } } - if (eno == 0) - g = 0; - else { - g = 1; - k = RARRAY_AREF(RARRAY_AREF(tab, idx), 0); - a = RARRAY_AREF(RARRAY_AREF(tab, idx), 1); - e = eno; + if (eno > 0) { + k = RARRAY_AREF(t, 0); + a = RARRAY_AREF(t, 1); } + e = eno; } d = Qnil; - if (g && !NIL_P(k) && (RARRAY_LEN(a) - e)) { + if (!NIL_P(k) && (RARRAY_LEN(a) > e)) { if (k == sym("ordinal")) { if (NIL_P(ref_hash("year"))) { if (NIL_P(d)) @@ -4090,7 +4095,7 @@ rt_complete_frags(VALUE klass, VALUE hash) } } - if (g && k == sym("time")) { + if (k == sym("time")) { if (f_le_p(klass, cDateTime)) { if (NIL_P(d)) d = date_s_today(0, (VALUE *)0, cDate); @@ -4410,7 +4415,7 @@ date_s__strptime(int argc, VALUE *argv, VALUE klass) * {Formats for Dates and Times}[rdoc-ref:strftime_formatting.rdoc]. * (Unlike Date.strftime, does not support flags and width.) * - * See argument {start}[rdoc-ref:calendars.rdoc@Argument+start]. + * See argument {start}[rdoc-ref:date/calendars.rdoc@Argument+start]. * * See also {strptime(3)}[https://man7.org/linux/man-pages/man3/strptime.3.html]. * @@ -4425,7 +4430,7 @@ date_s_strptime(int argc, VALUE *argv, VALUE klass) switch (argc) { case 0: - str = rb_str_new2("-4712-01-01"); + str = rb_str_new2(JULIAN_EPOCH_DATE); case 1: fmt = rb_str_new2("%F"); case 2: @@ -4464,12 +4469,6 @@ check_limit(VALUE str, VALUE opt) { size_t slen, limit; if (NIL_P(str)) return; - if (SYMBOL_P(str)) { - rb_category_warn(RB_WARN_CATEGORY_DEPRECATED, - "The ability to parse Symbol is an unintentional bug and is deprecated"); - str = rb_sym2str(str); - } - StringValue(str); slen = RSTRING_LEN(str); limit = get_limit(opt); @@ -4484,8 +4483,7 @@ date_s__parse_internal(int argc, VALUE *argv, VALUE klass) { VALUE vstr, vcomp, hash, opt; - rb_scan_args(argc, argv, "11:", &vstr, &vcomp, &opt); - if (!NIL_P(opt)) argc--; + argc = rb_scan_args(argc, argv, "11:", &vstr, &vcomp, &opt); check_limit(vstr, opt); StringValue(vstr); if (!rb_enc_str_asciicompat_p(vstr)) @@ -4562,7 +4560,7 @@ date_s__parse(int argc, VALUE *argv, VALUE klass) * * See: * - * - Argument {start}[rdoc-ref:calendars.rdoc@Argument+start]. + * - Argument {start}[rdoc-ref:date/calendars.rdoc@Argument+start]. * - Argument {limit}[rdoc-ref:Date@Argument+limit]. * * Related: Date._parse (returns a hash). @@ -4572,12 +4570,11 @@ date_s_parse(int argc, VALUE *argv, VALUE klass) { VALUE str, comp, sg, opt; - rb_scan_args(argc, argv, "03:", &str, &comp, &sg, &opt); - if (!NIL_P(opt)) argc--; + argc = rb_scan_args(argc, argv, "03:", &str, &comp, &sg, &opt); switch (argc) { case 0: - str = rb_str_new2("-4712-01-01"); + str = rb_str_new2(JULIAN_EPOCH_DATE); case 1: comp = Qtrue; case 2: @@ -4642,7 +4639,7 @@ date_s__iso8601(int argc, VALUE *argv, VALUE klass) * * See: * - * - Argument {start}[rdoc-ref:calendars.rdoc@Argument+start]. + * - Argument {start}[rdoc-ref:date/calendars.rdoc@Argument+start]. * - Argument {limit}[rdoc-ref:Date@Argument+limit]. * * Related: Date._iso8601 (returns a hash). @@ -4652,12 +4649,11 @@ date_s_iso8601(int argc, VALUE *argv, VALUE klass) { VALUE str, sg, opt; - rb_scan_args(argc, argv, "02:", &str, &sg, &opt); - if (!NIL_P(opt)) argc--; + argc = rb_scan_args(argc, argv, "02:", &str, &sg, &opt); switch (argc) { case 0: - str = rb_str_new2("-4712-01-01"); + str = rb_str_new2(JULIAN_EPOCH_DATE); case 1: sg = INT2FIX(DEFAULT_SG); } @@ -4713,7 +4709,7 @@ date_s__rfc3339(int argc, VALUE *argv, VALUE klass) * * See: * - * - Argument {start}[rdoc-ref:calendars.rdoc@Argument+start]. + * - Argument {start}[rdoc-ref:date/calendars.rdoc@Argument+start]. * - Argument {limit}[rdoc-ref:Date@Argument+limit]. * * Related: Date._rfc3339 (returns a hash). @@ -4723,12 +4719,11 @@ date_s_rfc3339(int argc, VALUE *argv, VALUE klass) { VALUE str, sg, opt; - rb_scan_args(argc, argv, "02:", &str, &sg, &opt); - if (!NIL_P(opt)) argc--; + argc = rb_scan_args(argc, argv, "02:", &str, &sg, &opt); switch (argc) { case 0: - str = rb_str_new2("-4712-01-01T00:00:00+00:00"); + str = rb_str_new2(JULIAN_EPOCH_DATETIME); case 1: sg = INT2FIX(DEFAULT_SG); } @@ -4782,7 +4777,7 @@ date_s__xmlschema(int argc, VALUE *argv, VALUE klass) * * See: * - * - Argument {start}[rdoc-ref:calendars.rdoc@Argument+start]. + * - Argument {start}[rdoc-ref:date/calendars.rdoc@Argument+start]. * - Argument {limit}[rdoc-ref:Date@Argument+limit]. * * Related: Date._xmlschema (returns a hash). @@ -4792,12 +4787,11 @@ date_s_xmlschema(int argc, VALUE *argv, VALUE klass) { VALUE str, sg, opt; - rb_scan_args(argc, argv, "02:", &str, &sg, &opt); - if (!NIL_P(opt)) argc--; + argc = rb_scan_args(argc, argv, "02:", &str, &sg, &opt); switch (argc) { case 0: - str = rb_str_new2("-4712-01-01"); + str = rb_str_new2(JULIAN_EPOCH_DATE); case 1: sg = INT2FIX(DEFAULT_SG); } @@ -4853,7 +4847,7 @@ date_s__rfc2822(int argc, VALUE *argv, VALUE klass) * * See: * - * - Argument {start}[rdoc-ref:calendars.rdoc@Argument+start]. + * - Argument {start}[rdoc-ref:date/calendars.rdoc@Argument+start]. * - Argument {limit}[rdoc-ref:Date@Argument+limit]. * * Related: Date._rfc2822 (returns a hash). @@ -4863,11 +4857,11 @@ date_s_rfc2822(int argc, VALUE *argv, VALUE klass) { VALUE str, sg, opt; - rb_scan_args(argc, argv, "02:", &str, &sg, &opt); + argc = rb_scan_args(argc, argv, "02:", &str, &sg, &opt); switch (argc) { case 0: - str = rb_str_new2("Mon, 1 Jan -4712 00:00:00 +0000"); + str = rb_str_new2(JULIAN_EPOCH_DATETIME_RFC3339); case 1: sg = INT2FIX(DEFAULT_SG); } @@ -4921,7 +4915,7 @@ date_s__httpdate(int argc, VALUE *argv, VALUE klass) * * See: * - * - Argument {start}[rdoc-ref:calendars.rdoc@Argument+start]. + * - Argument {start}[rdoc-ref:date/calendars.rdoc@Argument+start]. * - Argument {limit}[rdoc-ref:Date@Argument+limit]. * * Related: Date._httpdate (returns a hash). @@ -4931,11 +4925,11 @@ date_s_httpdate(int argc, VALUE *argv, VALUE klass) { VALUE str, sg, opt; - rb_scan_args(argc, argv, "02:", &str, &sg, &opt); + argc = rb_scan_args(argc, argv, "02:", &str, &sg, &opt); switch (argc) { case 0: - str = rb_str_new2("Mon, 01 Jan -4712 00:00:00 GMT"); + str = rb_str_new2(JULIAN_EPOCH_DATETIME_HTTPDATE); case 1: sg = INT2FIX(DEFAULT_SG); } @@ -4993,7 +4987,7 @@ date_s__jisx0301(int argc, VALUE *argv, VALUE klass) * * See: * - * - Argument {start}[rdoc-ref:calendars.rdoc@Argument+start]. + * - Argument {start}[rdoc-ref:date/calendars.rdoc@Argument+start]. * - Argument {limit}[rdoc-ref:Date@Argument+limit]. * * Related: Date._jisx0301 (returns a hash). @@ -5003,12 +4997,11 @@ date_s_jisx0301(int argc, VALUE *argv, VALUE klass) { VALUE str, sg, opt; - rb_scan_args(argc, argv, "02:", &str, &sg, &opt); - if (!NIL_P(opt)) argc--; + argc = rb_scan_args(argc, argv, "02:", &str, &sg, &opt); switch (argc) { case 0: - str = rb_str_new2("-4712-01-01"); + str = rb_str_new2(JULIAN_EPOCH_DATE); case 1: sg = INT2FIX(DEFAULT_SG); } @@ -5752,7 +5745,7 @@ d_lite_leap_p(VALUE self) * Date.new(2001, 2, 3, Date::GREGORIAN).start # => -Infinity * Date.new(2001, 2, 3, Date::JULIAN).start # => Infinity * - * See argument {start}[rdoc-ref:calendars.rdoc@Argument+start]. + * See argument {start}[rdoc-ref:date/calendars.rdoc@Argument+start]. * */ static VALUE @@ -5827,7 +5820,7 @@ dup_obj_with_new_start(VALUE obj, double sg) * d1 = d0.new_start(Date::JULIAN) * d1.julian? # => true * - * See argument {start}[rdoc-ref:calendars.rdoc@Argument+start]. + * See argument {start}[rdoc-ref:date/calendars.rdoc@Argument+start]. * */ static VALUE @@ -6332,9 +6325,11 @@ minus_dd(VALUE self, VALUE other) * call-seq: * d - other -> date or rational * - * Returns the difference between the two dates if the other is a date - * object. If the other is a numeric value, returns a date object - * pointing +other+ days before self. If the other is a fractional number, + * If the other is a date object, returns a Rational + * whose value is the difference between the two dates in days. + * If the other is a numeric value, returns a date object + * pointing +other+ days before self. + * If the other is a fractional number, * assumes its precision is at most nanosecond. * * Date.new(2001,2,3) - 1 #=> # @@ -6941,13 +6936,24 @@ d_lite_eql_p(VALUE self, VALUE other) static VALUE d_lite_hash(VALUE self) { - st_index_t v, h[4]; + st_index_t v, h[5]; + VALUE nth; get_d1(self); - h[0] = m_nth(dat); - h[1] = m_jd(dat); - h[2] = m_df(dat); - h[3] = m_sf(dat); + nth = m_nth(dat); + + if (FIXNUM_P(nth)) { + h[0] = 0; + h[1] = (st_index_t)nth; + } else { + h[0] = 1; + h[1] = (st_index_t)FIX2LONG(rb_hash(nth)); + } + + h[2] = m_jd(dat); + h[3] = m_df(dat); + h[4] = m_sf(dat); + v = rb_memhash(h, sizeof(h)); return ST2FIX(v); } @@ -7522,10 +7528,7 @@ d_lite_marshal_dump_old(VALUE self) m_of_in_day(dat), DBL2NUM(m_sg(dat))); - if (FL_TEST(self, FL_EXIVAR)) { - rb_copy_generic_ivar(a, self); - FL_SET(a, FL_EXIVAR); - } + rb_copy_generic_ivar(a, self); return a; } @@ -7547,10 +7550,8 @@ d_lite_marshal_dump(VALUE self) INT2FIX(m_of(dat)), DBL2NUM(m_sg(dat))); - if (FL_TEST(self, FL_EXIVAR)) { - rb_copy_generic_ivar(a, self); - FL_SET(a, FL_EXIVAR); - } + + rb_copy_generic_ivar(a, self); return a; } @@ -7623,10 +7624,7 @@ d_lite_marshal_load(VALUE self, VALUE a) HAVE_JD | HAVE_DF); } - if (FL_TEST(a, FL_EXIVAR)) { - rb_copy_generic_ivar(self, a); - FL_SET(self, FL_EXIVAR); - } + rb_copy_generic_ivar(self, a); return self; } @@ -8379,7 +8377,7 @@ datetime_s_strptime(int argc, VALUE *argv, VALUE klass) switch (argc) { case 0: - str = rb_str_new2("-4712-01-01T00:00:00+00:00"); + str = rb_str_new2(JULIAN_EPOCH_DATETIME); case 1: fmt = rb_str_new2("%FT%T%z"); case 2: @@ -8427,12 +8425,11 @@ datetime_s_parse(int argc, VALUE *argv, VALUE klass) { VALUE str, comp, sg, opt; - rb_scan_args(argc, argv, "03:", &str, &comp, &sg, &opt); - if (!NIL_P(opt)) argc--; + argc = rb_scan_args(argc, argv, "03:", &str, &comp, &sg, &opt); switch (argc) { case 0: - str = rb_str_new2("-4712-01-01T00:00:00+00:00"); + str = rb_str_new2(JULIAN_EPOCH_DATETIME); case 1: comp = Qtrue; case 2: @@ -8474,12 +8471,11 @@ datetime_s_iso8601(int argc, VALUE *argv, VALUE klass) { VALUE str, sg, opt; - rb_scan_args(argc, argv, "02:", &str, &sg, &opt); - if (!NIL_P(opt)) argc--; + argc = rb_scan_args(argc, argv, "02:", &str, &sg, &opt); switch (argc) { case 0: - str = rb_str_new2("-4712-01-01T00:00:00+00:00"); + str = rb_str_new2(JULIAN_EPOCH_DATETIME); case 1: sg = INT2FIX(DEFAULT_SG); } @@ -8489,7 +8485,7 @@ datetime_s_iso8601(int argc, VALUE *argv, VALUE klass) VALUE argv2[2], hash; argv2[0] = str; argv2[1] = opt; - if (!NIL_P(opt)) argc2--; + if (!NIL_P(opt)) argc2++; hash = date_s__iso8601(argc2, argv2, klass); return dt_new_by_frags(klass, hash, sg); } @@ -8514,12 +8510,11 @@ datetime_s_rfc3339(int argc, VALUE *argv, VALUE klass) { VALUE str, sg, opt; - rb_scan_args(argc, argv, "02:", &str, &sg, &opt); - if (!NIL_P(opt)) argc--; + argc = rb_scan_args(argc, argv, "02:", &str, &sg, &opt); switch (argc) { case 0: - str = rb_str_new2("-4712-01-01T00:00:00+00:00"); + str = rb_str_new2(JULIAN_EPOCH_DATETIME); case 1: sg = INT2FIX(DEFAULT_SG); } @@ -8554,12 +8549,11 @@ datetime_s_xmlschema(int argc, VALUE *argv, VALUE klass) { VALUE str, sg, opt; - rb_scan_args(argc, argv, "02:", &str, &sg, &opt); - if (!NIL_P(opt)) argc--; + argc = rb_scan_args(argc, argv, "02:", &str, &sg, &opt); switch (argc) { case 0: - str = rb_str_new2("-4712-01-01T00:00:00+00:00"); + str = rb_str_new2(JULIAN_EPOCH_DATETIME); case 1: sg = INT2FIX(DEFAULT_SG); } @@ -8595,12 +8589,11 @@ datetime_s_rfc2822(int argc, VALUE *argv, VALUE klass) { VALUE str, sg, opt; - rb_scan_args(argc, argv, "02:", &str, &sg, &opt); - if (!NIL_P(opt)) argc--; + argc = rb_scan_args(argc, argv, "02:", &str, &sg, &opt); switch (argc) { case 0: - str = rb_str_new2("Mon, 1 Jan -4712 00:00:00 +0000"); + str = rb_str_new2(JULIAN_EPOCH_DATETIME_RFC3339); case 1: sg = INT2FIX(DEFAULT_SG); } @@ -8635,12 +8628,11 @@ datetime_s_httpdate(int argc, VALUE *argv, VALUE klass) { VALUE str, sg, opt; - rb_scan_args(argc, argv, "02:", &str, &sg, &opt); - if (!NIL_P(opt)) argc--; + argc = rb_scan_args(argc, argv, "02:", &str, &sg, &opt); switch (argc) { case 0: - str = rb_str_new2("Mon, 01 Jan -4712 00:00:00 GMT"); + str = rb_str_new2(JULIAN_EPOCH_DATETIME_HTTPDATE); case 1: sg = INT2FIX(DEFAULT_SG); } @@ -8680,12 +8672,11 @@ datetime_s_jisx0301(int argc, VALUE *argv, VALUE klass) { VALUE str, sg, opt; - rb_scan_args(argc, argv, "02:", &str, &sg, &opt); - if (!NIL_P(opt)) argc--; + argc = rb_scan_args(argc, argv, "02:", &str, &sg, &opt); switch (argc) { case 0: - str = rb_str_new2("-4712-01-01T00:00:00+00:00"); + str = rb_str_new2(JULIAN_EPOCH_DATETIME); case 1: sg = INT2FIX(DEFAULT_SG); } @@ -8726,8 +8717,8 @@ dt_lite_to_s(VALUE self) * * DateTime.now.strftime # => "2022-07-01T11:03:19-05:00" * - * For other formats, see - * {Formats for Dates and Times}[doc/strftime_formatting.rdoc]. + * For other formats, + * see {Formats for Dates and Times}[rdoc-ref:strftime_formatting.rdoc]: * */ static VALUE @@ -8961,18 +8952,23 @@ time_to_datetime(VALUE self) static VALUE date_to_time(VALUE self) { + VALUE t; + get_d1a(self); if (m_julian_p(adat)) { - VALUE tmp = d_lite_gregorian(self); - get_d1b(tmp); + VALUE g = d_lite_gregorian(self); + get_d1b(g); adat = bdat; + self = g; } - return f_local3(rb_cTime, + t = f_local3(rb_cTime, m_real_year(adat), INT2FIX(m_mon(adat)), INT2FIX(m_mday(adat))); + RB_GC_GUARD(self); /* may be the converted gregorian */ + return t; } /* @@ -9042,9 +9038,10 @@ datetime_to_time(VALUE self) get_d1(self); if (m_julian_p(dat)) { - self = d_lite_gregorian(self); - get_d1a(self); + VALUE g = d_lite_gregorian(self); + get_d1a(g); dat = adat; + self = g; } { @@ -9061,6 +9058,7 @@ datetime_to_time(VALUE self) f_add(INT2FIX(m_sec(dat)), m_sf_in_sec(dat)), INT2FIX(m_of(dat))); + RB_GC_GUARD(self); /* may be the converted gregorian */ return t; } } @@ -9465,7 +9463,7 @@ mk_ary_of_str(long len, const char *a[]) } rb_ary_push(o, e); } - rb_obj_freeze(o); + rb_ary_freeze(o); return o; } @@ -9527,7 +9525,7 @@ Init_date_core(void) * * - You need both dates and times; \Date handles only dates. * - You need only Gregorian dates (and not Julian dates); - * see {Julian and Gregorian Calendars}[rdoc-ref:calendars.rdoc]. + * see {Julian and Gregorian Calendars}[rdoc-ref:date/calendars.rdoc]. * * A \Date object, once created, is immutable, and cannot be modified. * diff --git a/ext/date/date_parse.c b/ext/date/date_parse.c index c6f26ecb91432a..a1600e47085502 100644 --- a/ext/date/date_parse.c +++ b/ext/date/date_parse.c @@ -7,6 +7,9 @@ #include "ruby/re.h" #include +#undef strncasecmp +#define strncasecmp STRNCASECMP + RUBY_EXTERN VALUE rb_int_positive_pow(long x, unsigned long y); RUBY_EXTERN unsigned long ruby_scan_digits(const char *str, ssize_t len, int base, size_t *retlen, int *overflow); diff --git a/ext/date/date_strptime.c b/ext/date/date_strptime.c index f731629df196a9..f1c8201de8803c 100644 --- a/ext/date/date_strptime.c +++ b/ext/date/date_strptime.c @@ -7,6 +7,9 @@ #include "ruby/re.h" #include +#undef strncasecmp +#define strncasecmp STRNCASECMP + static const char *day_names[] = { "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", @@ -119,8 +122,9 @@ do { \ do { \ size_t l; \ l = read_digits(&str[si], slen - si, &n, w); \ - if (l == 0) \ + if (l == 0) { \ fail(); \ + } \ si += l; \ } while (0) diff --git a/ext/date/depend b/ext/date/depend index 82f85f7bf38c34..4fb78149a16509 100644 --- a/ext/date/depend +++ b/ext/date/depend @@ -138,6 +138,7 @@ date_core.o: $(hdrdir)/ruby/internal/intern/re.h date_core.o: $(hdrdir)/ruby/internal/intern/ruby.h date_core.o: $(hdrdir)/ruby/internal/intern/select.h date_core.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +date_core.o: $(hdrdir)/ruby/internal/intern/set.h date_core.o: $(hdrdir)/ruby/internal/intern/signal.h date_core.o: $(hdrdir)/ruby/internal/intern/sprintf.h date_core.o: $(hdrdir)/ruby/internal/intern/string.h @@ -157,6 +158,7 @@ date_core.o: $(hdrdir)/ruby/internal/special_consts.h date_core.o: $(hdrdir)/ruby/internal/static_assert.h date_core.o: $(hdrdir)/ruby/internal/stdalign.h date_core.o: $(hdrdir)/ruby/internal/stdbool.h +date_core.o: $(hdrdir)/ruby/internal/stdckdint.h date_core.o: $(hdrdir)/ruby/internal/symbol.h date_core.o: $(hdrdir)/ruby/internal/value.h date_core.o: $(hdrdir)/ruby/internal/value_type.h @@ -312,6 +314,7 @@ date_parse.o: $(hdrdir)/ruby/internal/intern/re.h date_parse.o: $(hdrdir)/ruby/internal/intern/ruby.h date_parse.o: $(hdrdir)/ruby/internal/intern/select.h date_parse.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +date_parse.o: $(hdrdir)/ruby/internal/intern/set.h date_parse.o: $(hdrdir)/ruby/internal/intern/signal.h date_parse.o: $(hdrdir)/ruby/internal/intern/sprintf.h date_parse.o: $(hdrdir)/ruby/internal/intern/string.h @@ -331,6 +334,7 @@ date_parse.o: $(hdrdir)/ruby/internal/special_consts.h date_parse.o: $(hdrdir)/ruby/internal/static_assert.h date_parse.o: $(hdrdir)/ruby/internal/stdalign.h date_parse.o: $(hdrdir)/ruby/internal/stdbool.h +date_parse.o: $(hdrdir)/ruby/internal/stdckdint.h date_parse.o: $(hdrdir)/ruby/internal/symbol.h date_parse.o: $(hdrdir)/ruby/internal/value.h date_parse.o: $(hdrdir)/ruby/internal/value_type.h @@ -476,6 +480,7 @@ date_strftime.o: $(hdrdir)/ruby/internal/intern/re.h date_strftime.o: $(hdrdir)/ruby/internal/intern/ruby.h date_strftime.o: $(hdrdir)/ruby/internal/intern/select.h date_strftime.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +date_strftime.o: $(hdrdir)/ruby/internal/intern/set.h date_strftime.o: $(hdrdir)/ruby/internal/intern/signal.h date_strftime.o: $(hdrdir)/ruby/internal/intern/sprintf.h date_strftime.o: $(hdrdir)/ruby/internal/intern/string.h @@ -495,6 +500,7 @@ date_strftime.o: $(hdrdir)/ruby/internal/special_consts.h date_strftime.o: $(hdrdir)/ruby/internal/static_assert.h date_strftime.o: $(hdrdir)/ruby/internal/stdalign.h date_strftime.o: $(hdrdir)/ruby/internal/stdbool.h +date_strftime.o: $(hdrdir)/ruby/internal/stdckdint.h date_strftime.o: $(hdrdir)/ruby/internal/symbol.h date_strftime.o: $(hdrdir)/ruby/internal/value.h date_strftime.o: $(hdrdir)/ruby/internal/value_type.h @@ -647,6 +653,7 @@ date_strptime.o: $(hdrdir)/ruby/internal/intern/re.h date_strptime.o: $(hdrdir)/ruby/internal/intern/ruby.h date_strptime.o: $(hdrdir)/ruby/internal/intern/select.h date_strptime.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +date_strptime.o: $(hdrdir)/ruby/internal/intern/set.h date_strptime.o: $(hdrdir)/ruby/internal/intern/signal.h date_strptime.o: $(hdrdir)/ruby/internal/intern/sprintf.h date_strptime.o: $(hdrdir)/ruby/internal/intern/string.h @@ -666,6 +673,7 @@ date_strptime.o: $(hdrdir)/ruby/internal/special_consts.h date_strptime.o: $(hdrdir)/ruby/internal/static_assert.h date_strptime.o: $(hdrdir)/ruby/internal/stdalign.h date_strptime.o: $(hdrdir)/ruby/internal/stdbool.h +date_strptime.o: $(hdrdir)/ruby/internal/stdckdint.h date_strptime.o: $(hdrdir)/ruby/internal/symbol.h date_strptime.o: $(hdrdir)/ruby/internal/value.h date_strptime.o: $(hdrdir)/ruby/internal/value_type.h diff --git a/ext/date/extconf.rb b/ext/date/extconf.rb index 358f64173a588e..8a1467df09e402 100644 --- a/ext/date/extconf.rb +++ b/ext/date/extconf.rb @@ -3,6 +3,7 @@ config_string("strict_warnflags") {|w| $warnflags += " #{w}"} +append_cflags("-Wno-compound-token-split-by-macro") if RUBY_VERSION < "2.7." have_func("rb_category_warn") with_werror("", {:werror => true}) do |opt, | have_var("timezone", "time.h", opt) diff --git a/ext/date/lib/date.rb b/ext/date/lib/date.rb index a9fe3ce4b0c183..aa630eb6d172b5 100644 --- a/ext/date/lib/date.rb +++ b/ext/date/lib/date.rb @@ -4,7 +4,7 @@ require 'date_core' class Date - VERSION = "3.3.3" # :nodoc: + VERSION = "3.4.1" # :nodoc: # call-seq: # infinite? -> false diff --git a/ext/date/prereq.mk b/ext/date/prereq.mk index cee7685975be07..b5d271a32cca15 100644 --- a/ext/date/prereq.mk +++ b/ext/date/prereq.mk @@ -1,7 +1,7 @@ .SUFFIXES: .list .list.h: - gperf --ignore-case -C -c -P -p -j1 -i 1 -g -o -t -N $(*F) $< \ + gperf --ignore-case -L ANSI-C -C -c -P -p -j1 -i 1 -g -o -t -N $(*F) $< \ | sed -f $(top_srcdir)/tool/gperf.sed \ > $(@F) diff --git a/ext/date/zonetab.h b/ext/date/zonetab.h index 7ced9e03087408..2a2e8910c988ef 100644 --- a/ext/date/zonetab.h +++ b/ext/date/zonetab.h @@ -1,5 +1,5 @@ /* ANSI-C code produced by gperf version 3.1 */ -/* Command-line: gperf --ignore-case -C -c -P -p -j1 -i 1 -g -o -t -N zonetab zonetab.list */ +/* Command-line: gperf --ignore-case -L ANSI-C -C -c -P -p -j1 -i 1 -g -o -t -N zonetab zonetab.list */ /* Computed positions: -k'1-4,9' */ #if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \ @@ -29,15 +29,17 @@ #error "gperf generated tables don't work with this execution character set. Please report a bug to ." #endif -#define gperf_offsetof(s, n) (short)offsetof(struct s##_t, s##_str##n) #line 1 "zonetab.list" +#define GPERF_DOWNCASE 1 +#define GPERF_CASE_STRNCMP 1 +#define gperf_case_strncmp strncasecmp struct zone { int name; int offset; }; static const struct zone *zonetab(register const char *str, register size_t len); -#line 9 "zonetab.list" +#line 12 "zonetab.list" struct zone; #define TOTAL_KEYWORDS 316 @@ -49,7 +51,7 @@ struct zone; #ifndef GPERF_DOWNCASE #define GPERF_DOWNCASE 1 -static const unsigned char gperf_downcase[256] = +static unsigned char gperf_downcase[256] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, @@ -808,736 +810,736 @@ zonetab (register const char *str, register size_t len) static const struct zone wordlist[] = { {-1}, {-1}, -#line 34 "zonetab.list" - {gperf_offsetof(stringpool, 2), -2*3600}, -#line 43 "zonetab.list" - {gperf_offsetof(stringpool, 3), -11*3600}, -#line 45 "zonetab.list" - {gperf_offsetof(stringpool, 4), 0*3600}, -#line 36 "zonetab.list" - {gperf_offsetof(stringpool, 5), -4*3600}, - {-1}, {-1}, -#line 269 "zonetab.list" - {gperf_offsetof(stringpool, 8),21600}, -#line 268 "zonetab.list" - {gperf_offsetof(stringpool, 9),25200}, -#line 35 "zonetab.list" - {gperf_offsetof(stringpool, 10), -3*3600}, +#line 37 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str2, -2*3600}, +#line 46 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str3, -11*3600}, +#line 48 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str4, 0*3600}, +#line 39 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str5, -4*3600}, {-1}, {-1}, -#line 21 "zonetab.list" - {gperf_offsetof(stringpool, 13), 1*3600}, -#line 25 "zonetab.list" - {gperf_offsetof(stringpool, 14), 5*3600}, -#line 271 "zonetab.list" - {gperf_offsetof(stringpool, 15),-18000}, -#line 279 "zonetab.list" - {gperf_offsetof(stringpool, 16),-10800}, -#line 273 "zonetab.list" - {gperf_offsetof(stringpool, 17),43200}, #line 272 "zonetab.list" - {gperf_offsetof(stringpool, 18),43200}, -#line 80 "zonetab.list" - {gperf_offsetof(stringpool, 19), 2*3600}, -#line 186 "zonetab.list" - {gperf_offsetof(stringpool, 20),36000}, -#line 88 "zonetab.list" - {gperf_offsetof(stringpool, 21), 3*3600}, -#line 87 "zonetab.list" - {gperf_offsetof(stringpool, 22), 3*3600}, - {-1}, -#line 101 "zonetab.list" - {gperf_offsetof(stringpool, 24),-6*3600}, -#line 217 "zonetab.list" - {gperf_offsetof(stringpool, 25),-18000}, -#line 19 "zonetab.list" - {gperf_offsetof(stringpool, 26), -8*3600}, -#line 133 "zonetab.list" - {gperf_offsetof(stringpool, 27), -18000}, -#line 32 "zonetab.list" - {gperf_offsetof(stringpool, 28), 12*3600}, -#line 56 "zonetab.list" - {gperf_offsetof(stringpool, 29), -4*3600}, -#line 13 "zonetab.list" - {gperf_offsetof(stringpool, 30), -5*3600}, -#line 23 "zonetab.list" - {gperf_offsetof(stringpool, 31), 3*3600}, -#line 256 "zonetab.list" - {gperf_offsetof(stringpool, 32),23400}, -#line 73 "zonetab.list" - {gperf_offsetof(stringpool, 33), 1*3600}, - {-1}, -#line 82 "zonetab.list" - {gperf_offsetof(stringpool, 35), 2*3600}, -#line 71 "zonetab.list" - {gperf_offsetof(stringpool, 36), 1*3600}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str8,21600}, +#line 271 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str9,25200}, +#line 38 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str10, -3*3600}, + {-1}, {-1}, #line 24 "zonetab.list" - {gperf_offsetof(stringpool, 37), 4*3600}, -#line 79 "zonetab.list" - {gperf_offsetof(stringpool, 38), 2*3600}, -#line 65 "zonetab.list" - {gperf_offsetof(stringpool, 39),2*3600}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str13, 1*3600}, +#line 28 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str14, 5*3600}, +#line 274 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str15,-18000}, +#line 282 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str16,-10800}, +#line 276 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str17,43200}, +#line 275 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str18,43200}, +#line 83 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str19, 2*3600}, +#line 189 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str20,36000}, +#line 91 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str21, 3*3600}, +#line 90 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str22, 3*3600}, {-1}, -#line 202 "zonetab.list" - {gperf_offsetof(stringpool, 41),28800}, -#line 252 "zonetab.list" - {gperf_offsetof(stringpool, 42),39600}, -#line 251 "zonetab.list" - {gperf_offsetof(stringpool, 43),43200}, -#line 17 "zonetab.list" - {gperf_offsetof(stringpool, 44), -7*3600}, -#line 89 "zonetab.list" - {gperf_offsetof(stringpool, 45), 3*3600}, -#line 212 "zonetab.list" - {gperf_offsetof(stringpool, 46),-18000}, -#line 15 "zonetab.list" - {gperf_offsetof(stringpool, 47), -6*3600}, -#line 192 "zonetab.list" - {gperf_offsetof(stringpool, 48),18000}, -#line 26 "zonetab.list" - {gperf_offsetof(stringpool, 49), 6*3600}, - {-1}, {-1}, -#line 51 "zonetab.list" - {gperf_offsetof(stringpool, 52), -3*3600}, -#line 226 "zonetab.list" - {gperf_offsetof(stringpool, 53),-7200}, -#line 221 "zonetab.list" - {gperf_offsetof(stringpool, 54),10800}, +#line 104 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str24,-6*3600}, +#line 220 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str25,-18000}, #line 22 "zonetab.list" - {gperf_offsetof(stringpool, 55), 2*3600}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str26, -8*3600}, +#line 136 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str27, -18000}, +#line 35 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str28, 12*3600}, +#line 59 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str29, -4*3600}, +#line 16 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str30, -5*3600}, +#line 26 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str31, 3*3600}, +#line 259 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str32,23400}, +#line 76 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str33, 1*3600}, {-1}, -#line 190 "zonetab.list" - {gperf_offsetof(stringpool, 57),43200}, -#line 189 "zonetab.list" - {gperf_offsetof(stringpool, 58),43200}, -#line 199 "zonetab.list" - {gperf_offsetof(stringpool, 59),28800}, -#line 29 "zonetab.list" - {gperf_offsetof(stringpool, 60), 9*3600}, -#line 276 "zonetab.list" - {gperf_offsetof(stringpool, 61),28800}, -#line 48 "zonetab.list" - {gperf_offsetof(stringpool, 62), -2*3600}, -#line 94 "zonetab.list" - {gperf_offsetof(stringpool, 63), 6*3600}, +#line 85 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str35, 2*3600}, #line 74 "zonetab.list" - {gperf_offsetof(stringpool, 64), 1*3600}, -#line 81 "zonetab.list" - {gperf_offsetof(stringpool, 65), 2*3600}, -#line 64 "zonetab.list" - {gperf_offsetof(stringpool, 66),-10*3600}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str36, 1*3600}, +#line 27 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str37, 4*3600}, +#line 82 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str38, 2*3600}, +#line 68 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str39,2*3600}, + {-1}, +#line 205 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str41,28800}, +#line 255 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str42,39600}, #line 254 "zonetab.list" - {gperf_offsetof(stringpool, 67),18000}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str43,43200}, +#line 20 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str44, -7*3600}, #line 92 "zonetab.list" - {gperf_offsetof(stringpool, 68), 5*3600}, - {-1}, -#line 200 "zonetab.list" - {gperf_offsetof(stringpool, 70),-14400}, -#line 70 "zonetab.list" - {gperf_offsetof(stringpool, 71), 1*3600}, -#line 281 "zonetab.list" - {gperf_offsetof(stringpool, 72),32400}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str45, 3*3600}, +#line 215 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str46,-18000}, +#line 18 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str47, -6*3600}, +#line 195 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str48,18000}, +#line 29 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str49, 6*3600}, + {-1}, {-1}, +#line 54 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str52, -3*3600}, +#line 229 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str53,-7200}, +#line 224 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str54,10800}, +#line 25 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str55, 2*3600}, {-1}, -#line 280 "zonetab.list" - {gperf_offsetof(stringpool, 74),39600}, -#line 238 "zonetab.list" - {gperf_offsetof(stringpool, 75),21600}, -#line 93 "zonetab.list" - {gperf_offsetof(stringpool, 76), (5*3600+1800)}, -#line 194 "zonetab.list" - {gperf_offsetof(stringpool, 77),28800}, +#line 193 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str57,43200}, +#line 192 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str58,43200}, +#line 202 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str59,28800}, +#line 32 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str60, 9*3600}, +#line 279 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str61,28800}, +#line 51 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str62, -2*3600}, +#line 97 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str63, 6*3600}, +#line 77 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str64, 1*3600}, +#line 84 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str65, 2*3600}, +#line 67 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str66,-10*3600}, +#line 257 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str67,18000}, +#line 95 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str68, 5*3600}, {-1}, -#line 255 "zonetab.list" - {gperf_offsetof(stringpool, 79),43200}, -#line 75 "zonetab.list" - {gperf_offsetof(stringpool, 80), 1*3600}, -#line 270 "zonetab.list" - {gperf_offsetof(stringpool, 81),18000}, -#line 83 "zonetab.list" - {gperf_offsetof(stringpool, 82), 2*3600}, +#line 203 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str70,-14400}, +#line 73 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str71, 1*3600}, +#line 284 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str72,32400}, {-1}, -#line 207 "zonetab.list" - {gperf_offsetof(stringpool, 84),36000}, -#line 278 "zonetab.list" - {gperf_offsetof(stringpool, 85),-7200}, - {-1}, {-1}, -#line 126 "zonetab.list" - {gperf_offsetof(stringpool, 88), -21600}, -#line 185 "zonetab.list" - {gperf_offsetof(stringpool, 89),39600}, -#line 183 "zonetab.list" - {gperf_offsetof(stringpool, 90),-18000}, -#line 218 "zonetab.list" - {gperf_offsetof(stringpool, 91),-18000}, -#line 182 "zonetab.list" - {gperf_offsetof(stringpool, 92),34200}, -#line 103 "zonetab.list" - {gperf_offsetof(stringpool, 93),11*3600}, -#line 53 "zonetab.list" - {gperf_offsetof(stringpool, 94), -3*3600}, -#line 208 "zonetab.list" - {gperf_offsetof(stringpool, 95),36000}, -#line 49 "zonetab.list" - {gperf_offsetof(stringpool, 96),-2*3600}, -#line 120 "zonetab.list" - {gperf_offsetof(stringpool, 97), 34200}, - {-1}, {-1}, -#line 215 "zonetab.list" - {gperf_offsetof(stringpool, 100),25200}, -#line 242 "zonetab.list" - {gperf_offsetof(stringpool, 101),12600}, +#line 283 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str74,39600}, #line 241 "zonetab.list" - {gperf_offsetof(stringpool, 102),28800}, -#line 240 "zonetab.list" - {gperf_offsetof(stringpool, 103),32400}, -#line 86 "zonetab.list" - {gperf_offsetof(stringpool, 104), 3*3600}, -#line 33 "zonetab.list" - {gperf_offsetof(stringpool, 105), -1*3600}, -#line 201 "zonetab.list" - {gperf_offsetof(stringpool, 106),21600}, -#line 148 "zonetab.list" - {gperf_offsetof(stringpool, 107), -25200}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str75,21600}, #line 96 "zonetab.list" - {gperf_offsetof(stringpool, 108), (6*3600+1800)}, -#line 42 "zonetab.list" - {gperf_offsetof(stringpool, 109), -10*3600}, -#line 31 "zonetab.list" - {gperf_offsetof(stringpool, 110), 11*3600}, -#line 72 "zonetab.list" - {gperf_offsetof(stringpool, 111), 1*3600}, - {-1}, -#line 90 "zonetab.list" - {gperf_offsetof(stringpool, 113), 4*3600}, -#line 47 "zonetab.list" - {gperf_offsetof(stringpool, 114), 0*3600}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str76, (5*3600+1800)}, +#line 197 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str77,28800}, {-1}, +#line 258 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str79,43200}, #line 78 "zonetab.list" - {gperf_offsetof(stringpool, 116), 1*3600}, -#line 77 "zonetab.list" - {gperf_offsetof(stringpool, 117), 1*3600}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str80, 1*3600}, +#line 273 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str81,18000}, +#line 86 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str82, 2*3600}, {-1}, -#line 95 "zonetab.list" - {gperf_offsetof(stringpool, 119), 2*3600}, -#line 313 "zonetab.list" - {gperf_offsetof(stringpool, 120),43200}, -#line 55 "zonetab.list" - {gperf_offsetof(stringpool, 121), -(2*3600+1800)}, -#line 184 "zonetab.list" - {gperf_offsetof(stringpool, 122),31500}, -#line 204 "zonetab.list" - {gperf_offsetof(stringpool, 123),45900}, #line 210 "zonetab.list" - {gperf_offsetof(stringpool, 124),-18000}, -#line 198 "zonetab.list" - {gperf_offsetof(stringpool, 125),14400}, -#line 57 "zonetab.list" - {gperf_offsetof(stringpool, 126), -4*3600}, -#line 197 "zonetab.list" - {gperf_offsetof(stringpool, 127),18000}, -#line 54 "zonetab.list" - {gperf_offsetof(stringpool, 128),-3*3600}, -#line 253 "zonetab.list" - {gperf_offsetof(stringpool, 129),-30600}, -#line 91 "zonetab.list" - {gperf_offsetof(stringpool, 130), 4*3600}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str84,36000}, +#line 281 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str85,-7200}, + {-1}, {-1}, +#line 129 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str88, -21600}, +#line 188 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str89,39600}, +#line 186 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str90,-18000}, +#line 221 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str91,-18000}, +#line 185 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str92,34200}, +#line 106 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str93,11*3600}, +#line 56 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str94, -3*3600}, +#line 211 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str95,36000}, +#line 52 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str96,-2*3600}, +#line 123 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str97, 34200}, + {-1}, {-1}, +#line 218 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str100,25200}, +#line 245 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str101,12600}, +#line 244 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str102,28800}, +#line 243 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str103,32400}, +#line 89 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str104, 3*3600}, +#line 36 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str105, -1*3600}, +#line 204 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str106,21600}, +#line 151 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str107, -25200}, #line 99 "zonetab.list" - {gperf_offsetof(stringpool, 131), 9*3600}, -#line 122 "zonetab.list" - {gperf_offsetof(stringpool, 132), 21600}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str108, (6*3600+1800)}, +#line 45 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str109, -10*3600}, +#line 34 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str110, 11*3600}, +#line 75 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str111, 1*3600}, + {-1}, +#line 93 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str113, 4*3600}, +#line 50 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str114, 0*3600}, + {-1}, +#line 81 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str116, 1*3600}, +#line 80 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str117, 1*3600}, + {-1}, +#line 98 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str119, 2*3600}, +#line 316 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str120,43200}, +#line 58 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str121, -(2*3600+1800)}, #line 187 "zonetab.list" - {gperf_offsetof(stringpool, 133),16200}, -#line 132 "zonetab.list" - {gperf_offsetof(stringpool, 134), -10800}, -#line 121 "zonetab.list" - {gperf_offsetof(stringpool, 135), -21600}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str122,31500}, +#line 207 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str123,45900}, +#line 213 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str124,-18000}, +#line 201 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str125,14400}, +#line 60 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str126, -4*3600}, +#line 200 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str127,18000}, +#line 57 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str128,-3*3600}, +#line 256 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str129,-30600}, +#line 94 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str130, 4*3600}, +#line 102 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str131, 9*3600}, +#line 125 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str132, 21600}, +#line 190 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str133,16200}, +#line 135 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str134, -10800}, +#line 124 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str135, -21600}, {-1}, -#line 236 "zonetab.list" - {gperf_offsetof(stringpool, 137),25200}, +#line 239 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str137,25200}, {-1}, {-1}, {-1}, {-1}, {-1}, -#line 274 "zonetab.list" - {gperf_offsetof(stringpool, 143),36000}, -#line 266 "zonetab.list" - {gperf_offsetof(stringpool, 144),43200}, -#line 146 "zonetab.list" - {gperf_offsetof(stringpool, 145), -21600}, -#line 193 "zonetab.list" - {gperf_offsetof(stringpool, 146),32400}, -#line 220 "zonetab.list" - {gperf_offsetof(stringpool, 147),-3600}, -#line 214 "zonetab.list" - {gperf_offsetof(stringpool, 148),25200}, -#line 219 "zonetab.list" - {gperf_offsetof(stringpool, 149),0}, -#line 275 "zonetab.list" - {gperf_offsetof(stringpool, 150),46800}, -#line 109 "zonetab.list" - {gperf_offsetof(stringpool, 151), -32400}, +#line 277 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str143,36000}, +#line 269 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str144,43200}, +#line 149 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str145, -21600}, +#line 196 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str146,32400}, +#line 223 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str147,-3600}, +#line 217 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str148,25200}, +#line 222 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str149,0}, +#line 278 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str150,46800}, +#line 112 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str151, -32400}, {-1}, {-1}, -#line 68 "zonetab.list" - {gperf_offsetof(stringpool, 154), -11*3600}, +#line 71 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str154, -11*3600}, {-1}, {-1}, {-1}, -#line 321 "zonetab.list" - {gperf_offsetof(stringpool, 158),0}, +#line 324 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str158,0}, {-1}, -#line 178 "zonetab.list" - {gperf_offsetof(stringpool, 160), 18000}, #line 181 "zonetab.list" - {gperf_offsetof(stringpool, 161),37800}, -#line 265 "zonetab.list" - {gperf_offsetof(stringpool, 162),20700}, -#line 249 "zonetab.list" - {gperf_offsetof(stringpool, 163),37800}, -#line 108 "zonetab.list" - {gperf_offsetof(stringpool, 164), 16200}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str160, 18000}, +#line 184 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str161,37800}, +#line 268 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str162,20700}, +#line 252 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str163,37800}, +#line 111 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str164, 16200}, {-1}, {-1}, -#line 30 "zonetab.list" - {gperf_offsetof(stringpool, 167), 10*3600}, +#line 33 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str167, 10*3600}, {-1}, -#line 27 "zonetab.list" - {gperf_offsetof(stringpool, 169), 7*3600}, -#line 239 "zonetab.list" - {gperf_offsetof(stringpool, 170),16200}, -#line 206 "zonetab.list" - {gperf_offsetof(stringpool, 171),28800}, -#line 205 "zonetab.list" - {gperf_offsetof(stringpool, 172),32400}, -#line 12 "zonetab.list" - {gperf_offsetof(stringpool, 173), 0*3600}, -#line 229 "zonetab.list" - {gperf_offsetof(stringpool, 174),14400}, -#line 264 "zonetab.list" - {gperf_offsetof(stringpool, 175),25200}, +#line 30 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str169, 7*3600}, +#line 242 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str170,16200}, +#line 209 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str171,28800}, +#line 208 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str172,32400}, +#line 15 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str173, 0*3600}, +#line 232 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str174,14400}, +#line 267 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str175,25200}, +#line 266 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str176,25200}, +#line 226 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str177,43200}, +#line 43 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str178, -8*3600}, +#line 225 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str179,46800}, + {-1}, +#line 285 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str181,-10800}, #line 263 "zonetab.list" - {gperf_offsetof(stringpool, 176),25200}, -#line 223 "zonetab.list" - {gperf_offsetof(stringpool, 177),43200}, -#line 40 "zonetab.list" - {gperf_offsetof(stringpool, 178), -8*3600}, -#line 222 "zonetab.list" - {gperf_offsetof(stringpool, 179),46800}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str182,39600}, +#line 103 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str183, 9*3600}, +#line 247 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str184,39600}, +#line 105 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str185, 10*3600}, +#line 146 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str186, 12600}, +#line 132 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str187, 10800}, +#line 101 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str188, 8*3600}, +#line 42 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str189, -7*3600}, +#line 133 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str190, 36000}, +#line 41 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str191, -6*3600}, +#line 206 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str192,49500}, +#line 301 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str193,18000}, +#line 212 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str194,-14400}, +#line 194 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str195,-43200}, {-1}, -#line 282 "zonetab.list" - {gperf_offsetof(stringpool, 181),-10800}, +#line 262 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str197,28800}, +#line 182 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str198, 36000}, #line 260 "zonetab.list" - {gperf_offsetof(stringpool, 182),39600}, -#line 100 "zonetab.list" - {gperf_offsetof(stringpool, 183), 9*3600}, -#line 244 "zonetab.list" - {gperf_offsetof(stringpool, 184),39600}, -#line 102 "zonetab.list" - {gperf_offsetof(stringpool, 185), 10*3600}, -#line 143 "zonetab.list" - {gperf_offsetof(stringpool, 186), 12600}, -#line 129 "zonetab.list" - {gperf_offsetof(stringpool, 187), 10800}, -#line 98 "zonetab.list" - {gperf_offsetof(stringpool, 188), 8*3600}, -#line 39 "zonetab.list" - {gperf_offsetof(stringpool, 189), -7*3600}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str199,14400}, +#line 322 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str200,32400}, +#line 87 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str201, 2*3600}, +#line 289 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str202,39600}, +#line 155 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str203, 43200}, +#line 303 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str204,46800}, #line 130 "zonetab.list" - {gperf_offsetof(stringpool, 190), 36000}, -#line 38 "zonetab.list" - {gperf_offsetof(stringpool, 191), -6*3600}, -#line 203 "zonetab.list" - {gperf_offsetof(stringpool, 192),49500}, -#line 298 "zonetab.list" - {gperf_offsetof(stringpool, 193),18000}, -#line 209 "zonetab.list" - {gperf_offsetof(stringpool, 194),-14400}, -#line 191 "zonetab.list" - {gperf_offsetof(stringpool, 195),-43200}, - {-1}, -#line 259 "zonetab.list" - {gperf_offsetof(stringpool, 197),28800}, -#line 179 "zonetab.list" - {gperf_offsetof(stringpool, 198), 36000}, -#line 257 "zonetab.list" - {gperf_offsetof(stringpool, 199),14400}, -#line 319 "zonetab.list" - {gperf_offsetof(stringpool, 200),32400}, -#line 84 "zonetab.list" - {gperf_offsetof(stringpool, 201), 2*3600}, -#line 286 "zonetab.list" - {gperf_offsetof(stringpool, 202),39600}, -#line 152 "zonetab.list" - {gperf_offsetof(stringpool, 203), 43200}, -#line 300 "zonetab.list" - {gperf_offsetof(stringpool, 204),46800}, -#line 127 "zonetab.list" - {gperf_offsetof(stringpool, 205), 28800}, -#line 299 "zonetab.list" - {gperf_offsetof(stringpool, 206),50400}, -#line 85 "zonetab.list" - {gperf_offsetof(stringpool, 207), -11*3600}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str205, 28800}, +#line 302 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str206,50400}, +#line 88 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str207, -11*3600}, {-1}, -#line 142 "zonetab.list" - {gperf_offsetof(stringpool, 209), 19800}, +#line 145 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str209, 19800}, {-1}, -#line 314 "zonetab.list" - {gperf_offsetof(stringpool, 211),-10800}, -#line 288 "zonetab.list" - {gperf_offsetof(stringpool, 212),39600}, +#line 317 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str211,-10800}, +#line 291 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str212,39600}, {-1}, -#line 196 "zonetab.list" - {gperf_offsetof(stringpool, 214),-3600}, -#line 195 "zonetab.list" - {gperf_offsetof(stringpool, 215),0}, -#line 293 "zonetab.list" - {gperf_offsetof(stringpool, 216),-36000}, -#line 106 "zonetab.list" - {gperf_offsetof(stringpool, 217), 12*3600}, +#line 199 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str214,-3600}, +#line 198 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str215,0}, +#line 296 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str216,-36000}, +#line 109 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str217, 12*3600}, +#line 131 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str218, -43200}, +#line 108 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str219,12*3600}, +#line 173 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str220, 32400}, #line 128 "zonetab.list" - {gperf_offsetof(stringpool, 218), -43200}, -#line 105 "zonetab.list" - {gperf_offsetof(stringpool, 219),12*3600}, -#line 170 "zonetab.list" - {gperf_offsetof(stringpool, 220), 32400}, -#line 125 "zonetab.list" - {gperf_offsetof(stringpool, 221), 39600}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str221, 39600}, {-1}, -#line 283 "zonetab.list" - {gperf_offsetof(stringpool, 223),21600}, -#line 113 "zonetab.list" - {gperf_offsetof(stringpool, 224), -14400}, -#line 262 "zonetab.list" - {gperf_offsetof(stringpool, 225),39600}, - {-1}, -#line 11 "zonetab.list" - {gperf_offsetof(stringpool, 227), 0*3600}, -#line 301 "zonetab.list" - {gperf_offsetof(stringpool, 228),10800}, -#line 315 "zonetab.list" - {gperf_offsetof(stringpool, 229),43200}, -#line 291 "zonetab.list" - {gperf_offsetof(stringpool, 230),-10800}, -#line 20 "zonetab.list" - {gperf_offsetof(stringpool, 231), -7*3600}, -#line 248 "zonetab.list" - {gperf_offsetof(stringpool, 232),39600}, +#line 286 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str223,21600}, +#line 116 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str224, -14400}, +#line 265 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str225,39600}, {-1}, -#line 52 "zonetab.list" - {gperf_offsetof(stringpool, 234), -3*3600}, #line 14 "zonetab.list" - {gperf_offsetof(stringpool, 235), -4*3600}, - {-1}, {-1}, -#line 277 "zonetab.list" - {gperf_offsetof(stringpool, 238),18000}, -#line 188 "zonetab.list" - {gperf_offsetof(stringpool, 239),21600}, -#line 320 "zonetab.list" - {gperf_offsetof(stringpool, 240),28800}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str227, 0*3600}, +#line 304 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str228,10800}, +#line 318 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str229,43200}, +#line 294 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str230,-10800}, +#line 23 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str231, -7*3600}, +#line 251 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str232,39600}, {-1}, -#line 317 "zonetab.list" - {gperf_offsetof(stringpool, 242),-10800}, -#line 60 "zonetab.list" - {gperf_offsetof(stringpool, 243),-9*3600}, -#line 316 "zonetab.list" - {gperf_offsetof(stringpool, 244),-7200}, +#line 55 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str234, -3*3600}, +#line 17 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str235, -4*3600}, + {-1}, {-1}, +#line 280 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str238,18000}, +#line 191 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str239,21600}, +#line 323 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str240,28800}, {-1}, -#line 246 "zonetab.list" - {gperf_offsetof(stringpool, 246),25200}, -#line 245 "zonetab.list" - {gperf_offsetof(stringpool, 247),28800}, -#line 147 "zonetab.list" - {gperf_offsetof(stringpool, 248), -7200}, -#line 18 "zonetab.list" - {gperf_offsetof(stringpool, 249), -6*3600}, -#line 250 "zonetab.list" - {gperf_offsetof(stringpool, 250),50400}, -#line 165 "zonetab.list" - {gperf_offsetof(stringpool, 251), 28800}, -#line 16 "zonetab.list" - {gperf_offsetof(stringpool, 252), -5*3600}, -#line 76 "zonetab.list" - {gperf_offsetof(stringpool, 253), 1*3600}, +#line 320 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str242,-7200}, +#line 63 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str243,-9*3600}, +#line 319 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str244,-3600}, {-1}, -#line 164 "zonetab.list" - {gperf_offsetof(stringpool, 255), 25200}, -#line 41 "zonetab.list" - {gperf_offsetof(stringpool, 256), -9*3600}, +#line 249 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str246,25200}, +#line 248 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str247,28800}, +#line 150 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str248, -7200}, +#line 21 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str249, -6*3600}, +#line 253 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str250,50400}, +#line 168 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str251, 28800}, +#line 19 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str252, -5*3600}, +#line 79 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str253, 1*3600}, {-1}, -#line 171 "zonetab.list" - {gperf_offsetof(stringpool, 258), 46800}, -#line 211 "zonetab.list" - {gperf_offsetof(stringpool, 259),-36000}, +#line 167 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str255, 25200}, +#line 44 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str256, -9*3600}, {-1}, -#line 308 "zonetab.list" - {gperf_offsetof(stringpool, 261),-14400}, -#line 119 "zonetab.list" - {gperf_offsetof(stringpool, 262), 14400}, -#line 123 "zonetab.list" - {gperf_offsetof(stringpool, 263), 3600}, -#line 28 "zonetab.list" - {gperf_offsetof(stringpool, 264), 8*3600}, -#line 124 "zonetab.list" - {gperf_offsetof(stringpool, 265), 3600}, -#line 153 "zonetab.list" - {gperf_offsetof(stringpool, 266), -12600}, -#line 110 "zonetab.list" - {gperf_offsetof(stringpool, 267), 10800}, -#line 289 "zonetab.list" - {gperf_offsetof(stringpool, 268),14400}, -#line 112 "zonetab.list" - {gperf_offsetof(stringpool, 269), 10800}, -#line 111 "zonetab.list" - {gperf_offsetof(stringpool, 270), 14400}, -#line 216 "zonetab.list" - {gperf_offsetof(stringpool, 271),36000}, +#line 174 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str258, 46800}, +#line 214 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str259,-36000}, {-1}, #line 311 "zonetab.list" - {gperf_offsetof(stringpool, 273),21600}, -#line 66 "zonetab.list" - {gperf_offsetof(stringpool, 274),-10*3600}, -#line 151 "zonetab.list" - {gperf_offsetof(stringpool, 275), 20700}, -#line 267 "zonetab.list" - {gperf_offsetof(stringpool, 276),-39600}, -#line 225 "zonetab.list" - {gperf_offsetof(stringpool, 277),-14400}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str261,-14400}, +#line 122 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str262, 14400}, +#line 126 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str263, 3600}, +#line 31 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str264, 8*3600}, +#line 127 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str265, 3600}, +#line 156 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str266, -12600}, +#line 113 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str267, 10800}, +#line 292 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str268,14400}, +#line 115 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str269, 10800}, +#line 114 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str270, 14400}, +#line 219 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str271,36000}, {-1}, -#line 224 "zonetab.list" - {gperf_offsetof(stringpool, 279),-10800}, -#line 67 "zonetab.list" - {gperf_offsetof(stringpool, 280),-10*3600}, -#line 237 "zonetab.list" - {gperf_offsetof(stringpool, 281),10800}, +#line 314 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str273,21600}, +#line 69 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str274,-10*3600}, +#line 154 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str275, 20700}, +#line 270 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str276,-39600}, +#line 228 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str277,-14400}, + {-1}, +#line 227 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str279,-10800}, +#line 70 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str280,-10*3600}, +#line 240 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str281,10800}, {-1}, {-1}, -#line 297 "zonetab.list" - {gperf_offsetof(stringpool, 284),32400}, -#line 175 "zonetab.list" - {gperf_offsetof(stringpool, 285), 28800}, -#line 134 "zonetab.list" - {gperf_offsetof(stringpool, 286), 7200}, -#line 149 "zonetab.list" - {gperf_offsetof(stringpool, 287), 23400}, -#line 107 "zonetab.list" - {gperf_offsetof(stringpool, 288),13*3600}, -#line 230 "zonetab.list" - {gperf_offsetof(stringpool, 289),-10800}, -#line 307 "zonetab.list" - {gperf_offsetof(stringpool, 290),18000}, +#line 300 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str284,32400}, +#line 178 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str285, 28800}, +#line 137 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str286, 7200}, +#line 152 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str287, 23400}, +#line 110 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str288,13*3600}, +#line 233 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str289,-10800}, +#line 310 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str290,18000}, {-1}, {-1}, -#line 155 "zonetab.list" - {gperf_offsetof(stringpool, 293), 25200}, -#line 258 "zonetab.list" - {gperf_offsetof(stringpool, 294),18000}, -#line 227 "zonetab.list" - {gperf_offsetof(stringpool, 295),-21600}, +#line 158 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str293, 25200}, #line 261 "zonetab.list" - {gperf_offsetof(stringpool, 296),43200}, -#line 213 "zonetab.list" - {gperf_offsetof(stringpool, 297),-3600}, -#line 154 "zonetab.list" - {gperf_offsetof(stringpool, 298), 28800}, - {-1}, -#line 243 "zonetab.list" - {gperf_offsetof(stringpool, 300),21600}, -#line 114 "zonetab.list" - {gperf_offsetof(stringpool, 301), 34200}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str294,18000}, +#line 230 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str295,-21600}, +#line 264 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str296,43200}, +#line 216 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str297,-3600}, #line 157 "zonetab.list" - {gperf_offsetof(stringpool, 302), -28800}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str298, 28800}, {-1}, +#line 246 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str300,21600}, #line 117 "zonetab.list" - {gperf_offsetof(stringpool, 304), -21600}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str301, 34200}, +#line 160 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str302, -28800}, {-1}, -#line 156 "zonetab.list" - {gperf_offsetof(stringpool, 306), -14400}, -#line 116 "zonetab.list" - {gperf_offsetof(stringpool, 307), -3600}, -#line 228 "zonetab.list" - {gperf_offsetof(stringpool, 308),-32400}, -#line 294 "zonetab.list" - {gperf_offsetof(stringpool, 309),18000}, -#line 37 "zonetab.list" - {gperf_offsetof(stringpool, 310), -5*3600}, -#line 137 "zonetab.list" - {gperf_offsetof(stringpool, 311), 7200}, -#line 58 "zonetab.list" - {gperf_offsetof(stringpool, 312),-8*3600}, -#line 304 "zonetab.list" - {gperf_offsetof(stringpool, 313),28800}, -#line 303 "zonetab.list" - {gperf_offsetof(stringpool, 314),32400}, -#line 284 "zonetab.list" - {gperf_offsetof(stringpool, 315),14400}, +#line 120 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str304, -21600}, {-1}, -#line 295 "zonetab.list" - {gperf_offsetof(stringpool, 317),18000}, +#line 159 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str306, -14400}, +#line 119 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str307, -3600}, +#line 231 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str308,-32400}, +#line 297 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str309,18000}, +#line 40 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str310, -5*3600}, +#line 140 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str311, 7200}, +#line 61 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str312,-8*3600}, +#line 307 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str313,28800}, +#line 306 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str314,32400}, +#line 287 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str315,14400}, {-1}, -#line 166 "zonetab.list" - {gperf_offsetof(stringpool, 319), 7200}, +#line 298 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str317,18000}, + {-1}, +#line 169 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str319, 7200}, {-1}, {-1}, {-1}, {-1}, -#line 97 "zonetab.list" - {gperf_offsetof(stringpool, 324), 8*3600}, +#line 100 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str324, 8*3600}, {-1}, -#line 50 "zonetab.list" - {gperf_offsetof(stringpool, 326), -(1*3600+1800)}, -#line 285 "zonetab.list" - {gperf_offsetof(stringpool, 327),-10800}, +#line 53 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str326, -(1*3600+1800)}, +#line 288 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str327,-10800}, {-1}, {-1}, -#line 287 "zonetab.list" - {gperf_offsetof(stringpool, 330),14400}, +#line 290 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str330,14400}, {-1}, -#line 169 "zonetab.list" - {gperf_offsetof(stringpool, 332), 36000}, +#line 172 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str332, 36000}, {-1}, -#line 235 "zonetab.list" - {gperf_offsetof(stringpool, 334),25200}, -#line 234 "zonetab.list" - {gperf_offsetof(stringpool, 335),28800}, +#line 238 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str334,25200}, +#line 237 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str335,28800}, {-1}, {-1}, -#line 232 "zonetab.list" - {gperf_offsetof(stringpool, 338),-14400}, +#line 235 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str338,-14400}, {-1}, {-1}, {-1}, -#line 44 "zonetab.list" - {gperf_offsetof(stringpool, 342), -12*3600}, -#line 61 "zonetab.list" - {gperf_offsetof(stringpool, 343),-9*3600}, -#line 162 "zonetab.list" - {gperf_offsetof(stringpool, 344), -14400}, -#line 141 "zonetab.list" - {gperf_offsetof(stringpool, 345), -36000}, +#line 47 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str342, -12*3600}, +#line 64 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str343,-9*3600}, +#line 165 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str344, -14400}, +#line 144 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str345, -36000}, {-1}, -#line 306 "zonetab.list" - {gperf_offsetof(stringpool, 347),-10800}, +#line 309 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str347,-10800}, {-1}, -#line 305 "zonetab.list" - {gperf_offsetof(stringpool, 349),-7200}, +#line 308 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str349,-7200}, +#line 329 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str350,18000}, +#line 328 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str351,21600}, +#line 250 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str352,14400}, #line 326 "zonetab.list" - {gperf_offsetof(stringpool, 350),18000}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str353,32400}, #line 325 "zonetab.list" - {gperf_offsetof(stringpool, 351),21600}, -#line 247 "zonetab.list" - {gperf_offsetof(stringpool, 352),14400}, -#line 323 "zonetab.list" - {gperf_offsetof(stringpool, 353),32400}, -#line 322 "zonetab.list" - {gperf_offsetof(stringpool, 354),36000}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str354,36000}, {-1}, {-1}, {-1}, -#line 63 "zonetab.list" - {gperf_offsetof(stringpool, 358), -9*3600}, -#line 144 "zonetab.list" - {gperf_offsetof(stringpool, 359), 7200}, +#line 66 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str358, -9*3600}, +#line 147 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str359, 7200}, {-1}, {-1}, {-1}, {-1}, {-1}, -#line 167 "zonetab.list" - {gperf_offsetof(stringpool, 365), 21600}, +#line 170 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str365, 21600}, {-1}, -#line 180 "zonetab.list" - {gperf_offsetof(stringpool, 367), 32400}, +#line 183 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str367, 32400}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -#line 318 "zonetab.list" - {gperf_offsetof(stringpool, 375),25200}, +#line 321 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str375,25200}, {-1}, -#line 115 "zonetab.list" - {gperf_offsetof(stringpool, 377), 36000}, -#line 231 "zonetab.list" - {gperf_offsetof(stringpool, 378),43200}, +#line 118 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str377, 36000}, +#line 234 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str378,43200}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -#line 173 "zonetab.list" - {gperf_offsetof(stringpool, 387), -25200}, +#line 176 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str387, -25200}, {-1}, {-1}, {-1}, -#line 310 "zonetab.list" - {gperf_offsetof(stringpool, 391),36000}, -#line 309 "zonetab.list" - {gperf_offsetof(stringpool, 392),39600}, +#line 313 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str391,36000}, +#line 312 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str392,39600}, {-1}, {-1}, -#line 140 "zonetab.list" - {gperf_offsetof(stringpool, 395), 7200}, +#line 143 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str395, 7200}, {-1}, {-1}, -#line 168 "zonetab.list" - {gperf_offsetof(stringpool, 398), 28800}, -#line 290 "zonetab.list" - {gperf_offsetof(stringpool, 399),39600}, +#line 171 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str398, 28800}, +#line 293 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str399,39600}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -#line 118 "zonetab.list" - {gperf_offsetof(stringpool, 408), -3600}, +#line 121 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str408, -3600}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -#line 296 "zonetab.list" - {gperf_offsetof(stringpool, 417),46800}, -#line 163 "zonetab.list" - {gperf_offsetof(stringpool, 418), -39600}, +#line 299 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str417,46800}, +#line 166 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str418, -39600}, {-1}, {-1}, -#line 161 "zonetab.list" - {gperf_offsetof(stringpool, 421), -18000}, +#line 164 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str421, -18000}, {-1}, {-1}, {-1}, {-1}, {-1}, -#line 312 "zonetab.list" - {gperf_offsetof(stringpool, 427),39600}, -#line 69 "zonetab.list" - {gperf_offsetof(stringpool, 428),-12*3600}, +#line 315 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str427,39600}, +#line 72 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str428,-12*3600}, {-1}, {-1}, {-1}, -#line 136 "zonetab.list" - {gperf_offsetof(stringpool, 432), 43200}, +#line 139 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str432, 43200}, {-1}, {-1}, -#line 46 "zonetab.list" - {gperf_offsetof(stringpool, 435), 0*3600}, +#line 49 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str435, 0*3600}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -#line 145 "zonetab.list" - {gperf_offsetof(stringpool, 443), 32400}, +#line 148 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str443, 32400}, {-1}, -#line 131 "zonetab.list" - {gperf_offsetof(stringpool, 445), 7200}, +#line 134 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str445, 7200}, {-1}, {-1}, {-1}, -#line 292 "zonetab.list" - {gperf_offsetof(stringpool, 449),10800}, +#line 295 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str449,10800}, {-1}, {-1}, -#line 150 "zonetab.list" - {gperf_offsetof(stringpool, 452), 21600}, +#line 153 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str452, 21600}, {-1}, {-1}, -#line 302 "zonetab.list" - {gperf_offsetof(stringpool, 455),43200}, +#line 305 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str455,43200}, {-1}, {-1}, -#line 176 "zonetab.list" - {gperf_offsetof(stringpool, 458), 3600}, +#line 179 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str458, 3600}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -#line 135 "zonetab.list" - {gperf_offsetof(stringpool, 466), 18000}, +#line 138 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str466, 18000}, {-1}, -#line 174 "zonetab.list" - {gperf_offsetof(stringpool, 468), 36000}, +#line 177 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str468, 36000}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -#line 324 "zonetab.list" - {gperf_offsetof(stringpool, 476),36000}, -#line 172 "zonetab.list" - {gperf_offsetof(stringpool, 477), -18000}, +#line 327 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str476,36000}, +#line 175 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str477, -18000}, {-1}, {-1}, {-1}, {-1}, -#line 160 "zonetab.list" - {gperf_offsetof(stringpool, 482), -10800}, +#line 163 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str482, -10800}, {-1}, {-1}, -#line 62 "zonetab.list" - {gperf_offsetof(stringpool, 485), -9*3600}, -#line 159 "zonetab.list" - {gperf_offsetof(stringpool, 486), 10800}, +#line 65 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str485, -9*3600}, +#line 162 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str486, 10800}, {-1}, {-1}, {-1}, {-1}, {-1}, -#line 233 "zonetab.list" - {gperf_offsetof(stringpool, 492),28800}, +#line 236 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str492,28800}, {-1}, {-1}, {-1}, {-1}, -#line 158 "zonetab.list" - {gperf_offsetof(stringpool, 497), 3600}, +#line 161 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str497, 3600}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -#line 177 "zonetab.list" - {gperf_offsetof(stringpool, 540), 3600}, +#line 180 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str540, 3600}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -#line 59 "zonetab.list" - {gperf_offsetof(stringpool, 563), -8*3600}, +#line 62 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str563, -8*3600}, {-1}, {-1}, -#line 104 "zonetab.list" - {gperf_offsetof(stringpool, 566),12*3600}, -#line 139 "zonetab.list" - {gperf_offsetof(stringpool, 567), 0}, +#line 107 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str566,12*3600}, +#line 142 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str567, 0}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, -#line 138 "zonetab.list" - {gperf_offsetof(stringpool, 619), -10800} +#line 141 "zonetab.list" + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str619, -10800} }; if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) @@ -1558,5 +1560,5 @@ zonetab (register const char *str, register size_t len) } return 0; } -#line 327 "zonetab.list" +#line 330 "zonetab.list" diff --git a/ext/date/zonetab.list b/ext/date/zonetab.list index 748aec1d8a93f0..63b6873447554b 100644 --- a/ext/date/zonetab.list +++ b/ext/date/zonetab.list @@ -1,4 +1,7 @@ %{ +#define GPERF_DOWNCASE 1 +#define GPERF_CASE_STRNCMP 1 +#define gperf_case_strncmp strncasecmp struct zone { int name; int offset; @@ -313,8 +316,8 @@ vut,39600 wakt,43200 warst,-10800 wft,43200 -wgst,-7200 -wgt,-10800 +wgst,-3600 +wgt,-7200 wib,25200 wit,32400 wita,28800 diff --git a/ext/digest/.document b/ext/digest/.document new file mode 100644 index 00000000000000..beab275b5a015a --- /dev/null +++ b/ext/digest/.document @@ -0,0 +1,3 @@ +digest.c +bubblebabble/bubblebabble.c +*/*init.c diff --git a/ext/digest/bubblebabble/bubblebabble.c b/ext/digest/bubblebabble/bubblebabble.c index 358ab416b97b64..dac603c0d7a0e8 100644 --- a/ext/digest/bubblebabble/bubblebabble.c +++ b/ext/digest/bubblebabble/bubblebabble.c @@ -129,15 +129,14 @@ Init_bubblebabble(void) rb_require("digest"); - rb_mDigest = rb_path2class("Digest"); - rb_mDigest_Instance = rb_path2class("Digest::Instance"); - rb_cDigest_Class = rb_path2class("Digest::Class"); - #if 0 rb_mDigest = rb_define_module("Digest"); rb_mDigest_Instance = rb_define_module_under(rb_mDigest, "Instance"); rb_cDigest_Class = rb_define_class_under(rb_mDigest, "Class", rb_cObject); #endif + rb_mDigest = rb_digest_namespace(); + rb_mDigest_Instance = rb_const_get(rb_mDigest, rb_intern_const("Instance")); + rb_cDigest_Class = rb_const_get(rb_mDigest, rb_intern_const("Class")); rb_define_module_function(rb_mDigest, "bubblebabble", rb_digest_s_bubblebabble, 1); rb_define_singleton_method(rb_cDigest_Class, "bubblebabble", rb_digest_class_s_bubblebabble, -1); diff --git a/ext/digest/bubblebabble/depend b/ext/digest/bubblebabble/depend index 6f0003a66d926a..02d88e960c112a 100644 --- a/ext/digest/bubblebabble/depend +++ b/ext/digest/bubblebabble/depend @@ -128,6 +128,7 @@ bubblebabble.o: $(hdrdir)/ruby/internal/intern/re.h bubblebabble.o: $(hdrdir)/ruby/internal/intern/ruby.h bubblebabble.o: $(hdrdir)/ruby/internal/intern/select.h bubblebabble.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +bubblebabble.o: $(hdrdir)/ruby/internal/intern/set.h bubblebabble.o: $(hdrdir)/ruby/internal/intern/signal.h bubblebabble.o: $(hdrdir)/ruby/internal/intern/sprintf.h bubblebabble.o: $(hdrdir)/ruby/internal/intern/string.h @@ -147,6 +148,7 @@ bubblebabble.o: $(hdrdir)/ruby/internal/special_consts.h bubblebabble.o: $(hdrdir)/ruby/internal/static_assert.h bubblebabble.o: $(hdrdir)/ruby/internal/stdalign.h bubblebabble.o: $(hdrdir)/ruby/internal/stdbool.h +bubblebabble.o: $(hdrdir)/ruby/internal/stdckdint.h bubblebabble.o: $(hdrdir)/ruby/internal/symbol.h bubblebabble.o: $(hdrdir)/ruby/internal/value.h bubblebabble.o: $(hdrdir)/ruby/internal/value_type.h diff --git a/ext/digest/defs.h b/ext/digest/defs.h index 77a134f36449e7..9b11f4eca9a762 100644 --- a/ext/digest/defs.h +++ b/ext/digest/defs.h @@ -16,4 +16,26 @@ # define __END_DECLS #endif +#define RB_DIGEST_DIAGNOSTIC(compiler, op, flag) _Pragma(STRINGIZE(compiler diagnostic op flag)) +#ifdef RBIMPL_WARNING_IGNORED +# define RB_DIGEST_WARNING_IGNORED(flag) RBIMPL_WARNING_IGNORED(flag) +# define RB_DIGEST_WARNING_PUSH() RBIMPL_WARNING_PUSH() +# define RB_DIGEST_WARNING_POP() RBIMPL_WARNING_POP() +#elif defined(__clang__) +# define RB_DIGEST_WARNING_IGNORED(flag) RB_DIGEST_DIAGNOSTIC(clang, ignored, #flag) +# define RB_DIGEST_WARNING_PUSH() _Pragma("clang diagnostic push") +# define RB_DIGEST_WARNING_POP() _Pragma("clang diagnostic pop") +#else /* __GNUC__ */ +# define RB_DIGEST_WARNING_IGNORED(flag) RB_DIGEST_DIAGNOSTIC(GCC, ignored, #flag) +# define RB_DIGEST_WARNING_PUSH() _Pragma("GCC diagnostic push") +# define RB_DIGEST_WARNING_POP() _Pragma("GCC diagnostic pop") +#endif +#ifdef RBIMPL_HAS_WARNING +# define RB_DIGEST_HAS_WARNING(_) RBIMPL_HAS_WARNING(_) +#elif defined(__has_warning) +# define RB_DIGEST_HAS_WARNING(_) __has_warning(_) +#else +# define RB_DIGEST_HAS_WARNING(_) 0 +#endif + #endif /* DEFS_H */ diff --git a/ext/digest/depend b/ext/digest/depend index 6df940a67984a1..3eabb1d1d6a570 100644 --- a/ext/digest/depend +++ b/ext/digest/depend @@ -128,6 +128,7 @@ digest.o: $(hdrdir)/ruby/internal/intern/re.h digest.o: $(hdrdir)/ruby/internal/intern/ruby.h digest.o: $(hdrdir)/ruby/internal/intern/select.h digest.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +digest.o: $(hdrdir)/ruby/internal/intern/set.h digest.o: $(hdrdir)/ruby/internal/intern/signal.h digest.o: $(hdrdir)/ruby/internal/intern/sprintf.h digest.o: $(hdrdir)/ruby/internal/intern/string.h @@ -147,6 +148,7 @@ digest.o: $(hdrdir)/ruby/internal/special_consts.h digest.o: $(hdrdir)/ruby/internal/static_assert.h digest.o: $(hdrdir)/ruby/internal/stdalign.h digest.o: $(hdrdir)/ruby/internal/stdbool.h +digest.o: $(hdrdir)/ruby/internal/stdckdint.h digest.o: $(hdrdir)/ruby/internal/symbol.h digest.o: $(hdrdir)/ruby/internal/value.h digest.o: $(hdrdir)/ruby/internal/value_type.h diff --git a/ext/digest/digest.c b/ext/digest/digest.c index 68837a674c7479..bd8d3e815ffe6a 100644 --- a/ext/digest/digest.c +++ b/ext/digest/digest.c @@ -534,9 +534,39 @@ rb_digest_class_init(VALUE self) * * * rb_ivar_set(cDigest_SHA1, rb_intern("metadata"), - * Data_Wrap_Struct(0, 0, 0, (void *)&sha1)); + * rb_digest_make_metadata(&sha1)); */ +#ifdef DIGEST_USE_RB_EXT_RESOLVE_SYMBOL +static const rb_data_type_t metadata_type = { + "digest/metadata", + {0}, +}; + +RUBY_FUNC_EXPORTED VALUE +rb_digest_wrap_metadata(const rb_digest_metadata_t *meta) +{ + return rb_obj_freeze(TypedData_Wrap_Struct(0, &metadata_type, (void *)meta)); +} +#endif + +static rb_digest_metadata_t * +get_metadata_ptr(VALUE obj) +{ + rb_digest_metadata_t *algo; + +#ifdef DIGEST_USE_RB_EXT_RESOLVE_SYMBOL + if (!rb_typeddata_is_kind_of(obj, &metadata_type)) return 0; + algo = RTYPEDDATA_DATA(obj); +#else +# undef RUBY_UNTYPED_DATA_WARNING +# define RUBY_UNTYPED_DATA_WARNING 0 + Data_Get_Struct(obj, rb_digest_metadata_t, algo); +#endif + + return algo; +} + static rb_digest_metadata_t * get_digest_base_metadata(VALUE klass) { @@ -554,8 +584,8 @@ get_digest_base_metadata(VALUE klass) if (NIL_P(p)) rb_raise(rb_eRuntimeError, "Digest::Base cannot be directly inherited in Ruby"); - if (!RB_TYPE_P(obj, T_DATA) || RTYPEDDATA_P(obj)) { - wrong: + algo = get_metadata_ptr(obj); + if (!algo) { if (p == klass) rb_raise(rb_eTypeError, "%"PRIsVALUE"::metadata is not initialized properly", klass); @@ -564,12 +594,6 @@ get_digest_base_metadata(VALUE klass) klass, p); } -#undef RUBY_UNTYPED_DATA_WARNING -#define RUBY_UNTYPED_DATA_WARNING 0 - Data_Get_Struct(obj, rb_digest_metadata_t, algo); - - if (!algo) goto wrong; - switch (algo->api_version) { case 3: break; diff --git a/ext/digest/digest.h b/ext/digest/digest.h index 8a4c5b7e4e5884..c5c37583a6e7c9 100644 --- a/ext/digest/digest.h +++ b/ext/digest/digest.h @@ -40,7 +40,8 @@ rb_digest_##name##_update(void *ctx, unsigned char *ptr, size_t size) \ for (; size > stride; size -= stride, ptr += stride) { \ name##_Update(ctx, ptr, stride); \ } \ - if (size > 0) name##_Update(ctx, ptr, size); \ + /* Since size <= stride, size should fit into an unsigned int */ \ + if (size > 0) name##_Update(ctx, ptr, (unsigned int)size); \ } #define DEFINE_FINISH_FUNC_FROM_FINAL(name) \ @@ -63,10 +64,43 @@ rb_id_metadata(void) return rb_intern_const("metadata"); } +#if !defined(HAVE_RB_EXT_RESOLVE_SYMBOL) +#elif !defined(RUBY_UNTYPED_DATA_WARNING) +# error RUBY_UNTYPED_DATA_WARNING is not defined +#elif RUBY_UNTYPED_DATA_WARNING +/* rb_ext_resolve_symbol() has been defined since Ruby 3.3, but digest + * bundled with 3.3 didn't use it. */ +# define DIGEST_USE_RB_EXT_RESOLVE_SYMBOL 1 +#endif + static inline VALUE rb_digest_make_metadata(const rb_digest_metadata_t *meta) { -#undef RUBY_UNTYPED_DATA_WARNING -#define RUBY_UNTYPED_DATA_WARNING 0 +#if defined(EXTSTATIC) && EXTSTATIC + /* The extension is built as a static library, so safe to refer to + * rb_digest_wrap_metadata directly. */ + extern VALUE rb_digest_wrap_metadata(const rb_digest_metadata_t *meta); + return rb_digest_wrap_metadata(meta); +#else + /* The extension is built as a shared library, so we can't refer + * to rb_digest_wrap_metadata directly. */ +# ifdef DIGEST_USE_RB_EXT_RESOLVE_SYMBOL + /* If rb_ext_resolve_symbol() is available, use it to get the address of + * rb_digest_wrap_metadata. */ + typedef VALUE (*wrapper_func_type)(const rb_digest_metadata_t *meta); + static wrapper_func_type wrapper; + if (!wrapper) { + wrapper = (wrapper_func_type)(uintptr_t) + rb_ext_resolve_symbol("digest.so", "rb_digest_wrap_metadata"); + if (!wrapper) rb_raise(rb_eLoadError, "rb_digest_wrap_metadata not found"); + } + return wrapper(meta); +# else + /* If rb_ext_resolve_symbol() is not available, keep using untyped + * data. */ +# undef RUBY_UNTYPED_DATA_WARNING +# define RUBY_UNTYPED_DATA_WARNING 0 return rb_obj_freeze(Data_Wrap_Struct(0, 0, 0, (void *)meta)); +# endif +#endif } diff --git a/ext/digest/digest_conf.rb b/ext/digest/digest_conf.rb index 36a7d75289d081..099d20fcbe31c3 100644 --- a/ext/digest/digest_conf.rb +++ b/ext/digest/digest_conf.rb @@ -2,14 +2,16 @@ def digest_conf(name) unless with_config("bundled-#{name}") - cc = with_config("common-digest") - if cc != false or /\b#{name}\b/ =~ cc - if File.exist?("#$srcdir/#{name}cc.h") and - have_header("CommonCrypto/CommonDigest.h") - $defs << "-D#{name.upcase}_USE_COMMONDIGEST" - $headers << "#{name}cc.h" - return :commondigest - end + case cc = with_config("common-digest", true) + when true, false + else + cc = cc.split(/[\s,]++/).any? {|pat| File.fnmatch?(pat, name)} + end + if cc and File.exist?("#$srcdir/#{name}cc.h") and + have_header("CommonCrypto/CommonDigest.h") + $defs << "-D#{name.upcase}_USE_COMMONDIGEST" + $headers << "#{name}cc.h" + return :commondigest end end $objs << "#{name}.#{$OBJEXT}" diff --git a/ext/digest/lib/digest/version.rb b/ext/digest/lib/digest/version.rb index 42fd7acf6e4b88..854106165cab52 100644 --- a/ext/digest/lib/digest/version.rb +++ b/ext/digest/lib/digest/version.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true module Digest - VERSION = "3.1.1" + VERSION = "3.2.0" end diff --git a/ext/digest/md5/depend b/ext/digest/md5/depend index da1b345999d792..d1c25c28c89aa7 100644 --- a/ext/digest/md5/depend +++ b/ext/digest/md5/depend @@ -131,6 +131,7 @@ md5.o: $(hdrdir)/ruby/internal/intern/re.h md5.o: $(hdrdir)/ruby/internal/intern/ruby.h md5.o: $(hdrdir)/ruby/internal/intern/select.h md5.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +md5.o: $(hdrdir)/ruby/internal/intern/set.h md5.o: $(hdrdir)/ruby/internal/intern/signal.h md5.o: $(hdrdir)/ruby/internal/intern/sprintf.h md5.o: $(hdrdir)/ruby/internal/intern/string.h @@ -150,6 +151,7 @@ md5.o: $(hdrdir)/ruby/internal/special_consts.h md5.o: $(hdrdir)/ruby/internal/static_assert.h md5.o: $(hdrdir)/ruby/internal/stdalign.h md5.o: $(hdrdir)/ruby/internal/stdbool.h +md5.o: $(hdrdir)/ruby/internal/stdckdint.h md5.o: $(hdrdir)/ruby/internal/symbol.h md5.o: $(hdrdir)/ruby/internal/value.h md5.o: $(hdrdir)/ruby/internal/value_type.h @@ -292,6 +294,7 @@ md5init.o: $(hdrdir)/ruby/internal/intern/re.h md5init.o: $(hdrdir)/ruby/internal/intern/ruby.h md5init.o: $(hdrdir)/ruby/internal/intern/select.h md5init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +md5init.o: $(hdrdir)/ruby/internal/intern/set.h md5init.o: $(hdrdir)/ruby/internal/intern/signal.h md5init.o: $(hdrdir)/ruby/internal/intern/sprintf.h md5init.o: $(hdrdir)/ruby/internal/intern/string.h @@ -311,6 +314,7 @@ md5init.o: $(hdrdir)/ruby/internal/special_consts.h md5init.o: $(hdrdir)/ruby/internal/static_assert.h md5init.o: $(hdrdir)/ruby/internal/stdalign.h md5init.o: $(hdrdir)/ruby/internal/stdbool.h +md5init.o: $(hdrdir)/ruby/internal/stdckdint.h md5init.o: $(hdrdir)/ruby/internal/symbol.h md5init.o: $(hdrdir)/ruby/internal/value.h md5init.o: $(hdrdir)/ruby/internal/value_type.h diff --git a/ext/digest/md5/md5cc.h b/ext/digest/md5/md5cc.h index e34d7d5c115a0c..a002c17604da8b 100644 --- a/ext/digest/md5/md5cc.h +++ b/ext/digest/md5/md5cc.h @@ -1,8 +1,8 @@ #define COMMON_DIGEST_FOR_OPENSSL 1 #include -#ifdef __clang__ -# pragma clang diagnostic ignored "-Wdeprecated-declarations" +#ifdef __GNUC__ +RB_DIGEST_WARNING_IGNORED(-Wdeprecated-declarations) /* Suppress deprecation warnings of MD5 from Xcode 11.1 */ /* Although we know MD5 is deprecated too, provide just for backward * compatibility, as well as Apple does. */ @@ -17,3 +17,11 @@ static DEFINE_FINISH_FUNC_FROM_FINAL(MD5) #undef MD5_Finish #define MD5_Update rb_digest_MD5_update #define MD5_Finish rb_digest_MD5_finish + +/* + * Pre-10.6 defines are with args, which don't match the argless use in + * the function pointer inits. Thus, we redefine MD5_Init as well. + * This is a NOP on 10.6+. + */ +#undef MD5_Init +#define MD5_Init CC_MD5_Init diff --git a/ext/digest/md5/md5init.c b/ext/digest/md5/md5init.c index 52cba78bf1131c..c919060587676c 100644 --- a/ext/digest/md5/md5init.c +++ b/ext/digest/md5/md5init.c @@ -3,6 +3,7 @@ #include #include "../digest.h" +#include "../defs.h" #if defined(MD5_USE_COMMONDIGEST) #include "md5cc.h" #else @@ -53,9 +54,8 @@ Init_md5(void) mDigest = rb_define_module("Digest"); /* let rdoc know */ #endif mDigest = rb_digest_namespace(); - cDigest_Base = rb_path2class("Digest::Base"); + cDigest_Base = rb_const_get(mDigest, rb_intern_const("Base")); cDigest_MD5 = rb_define_class_under(mDigest, "MD5", cDigest_Base); - rb_iv_set(cDigest_MD5, "metadata", rb_digest_make_metadata(&md5)); } diff --git a/ext/digest/rmd160/depend b/ext/digest/rmd160/depend index abfa08b02350aa..aec484f7b3ee38 100644 --- a/ext/digest/rmd160/depend +++ b/ext/digest/rmd160/depend @@ -131,6 +131,7 @@ rmd160.o: $(hdrdir)/ruby/internal/intern/re.h rmd160.o: $(hdrdir)/ruby/internal/intern/ruby.h rmd160.o: $(hdrdir)/ruby/internal/intern/select.h rmd160.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +rmd160.o: $(hdrdir)/ruby/internal/intern/set.h rmd160.o: $(hdrdir)/ruby/internal/intern/signal.h rmd160.o: $(hdrdir)/ruby/internal/intern/sprintf.h rmd160.o: $(hdrdir)/ruby/internal/intern/string.h @@ -150,6 +151,7 @@ rmd160.o: $(hdrdir)/ruby/internal/special_consts.h rmd160.o: $(hdrdir)/ruby/internal/static_assert.h rmd160.o: $(hdrdir)/ruby/internal/stdalign.h rmd160.o: $(hdrdir)/ruby/internal/stdbool.h +rmd160.o: $(hdrdir)/ruby/internal/stdckdint.h rmd160.o: $(hdrdir)/ruby/internal/symbol.h rmd160.o: $(hdrdir)/ruby/internal/value.h rmd160.o: $(hdrdir)/ruby/internal/value_type.h @@ -292,6 +294,7 @@ rmd160init.o: $(hdrdir)/ruby/internal/intern/re.h rmd160init.o: $(hdrdir)/ruby/internal/intern/ruby.h rmd160init.o: $(hdrdir)/ruby/internal/intern/select.h rmd160init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +rmd160init.o: $(hdrdir)/ruby/internal/intern/set.h rmd160init.o: $(hdrdir)/ruby/internal/intern/signal.h rmd160init.o: $(hdrdir)/ruby/internal/intern/sprintf.h rmd160init.o: $(hdrdir)/ruby/internal/intern/string.h @@ -311,6 +314,7 @@ rmd160init.o: $(hdrdir)/ruby/internal/special_consts.h rmd160init.o: $(hdrdir)/ruby/internal/static_assert.h rmd160init.o: $(hdrdir)/ruby/internal/stdalign.h rmd160init.o: $(hdrdir)/ruby/internal/stdbool.h +rmd160init.o: $(hdrdir)/ruby/internal/stdckdint.h rmd160init.o: $(hdrdir)/ruby/internal/symbol.h rmd160init.o: $(hdrdir)/ruby/internal/value.h rmd160init.o: $(hdrdir)/ruby/internal/value_type.h diff --git a/ext/digest/rmd160/rmd160init.c b/ext/digest/rmd160/rmd160init.c index 2ae81ec4d60346..e4b707ed9e0dd8 100644 --- a/ext/digest/rmd160/rmd160init.c +++ b/ext/digest/rmd160/rmd160init.c @@ -49,9 +49,8 @@ Init_rmd160(void) mDigest = rb_define_module("Digest"); /* let rdoc know */ #endif mDigest = rb_digest_namespace(); - cDigest_Base = rb_path2class("Digest::Base"); + cDigest_Base = rb_const_get(mDigest, rb_intern_const("Base")); cDigest_RMD160 = rb_define_class_under(mDigest, "RMD160", cDigest_Base); - rb_iv_set(cDigest_RMD160, "metadata", rb_digest_make_metadata(&rmd160)); } diff --git a/ext/digest/sha1/depend b/ext/digest/sha1/depend index d17338e92b77ec..e6bd9d8f731cd9 100644 --- a/ext/digest/sha1/depend +++ b/ext/digest/sha1/depend @@ -131,6 +131,7 @@ sha1.o: $(hdrdir)/ruby/internal/intern/re.h sha1.o: $(hdrdir)/ruby/internal/intern/ruby.h sha1.o: $(hdrdir)/ruby/internal/intern/select.h sha1.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +sha1.o: $(hdrdir)/ruby/internal/intern/set.h sha1.o: $(hdrdir)/ruby/internal/intern/signal.h sha1.o: $(hdrdir)/ruby/internal/intern/sprintf.h sha1.o: $(hdrdir)/ruby/internal/intern/string.h @@ -150,6 +151,7 @@ sha1.o: $(hdrdir)/ruby/internal/special_consts.h sha1.o: $(hdrdir)/ruby/internal/static_assert.h sha1.o: $(hdrdir)/ruby/internal/stdalign.h sha1.o: $(hdrdir)/ruby/internal/stdbool.h +sha1.o: $(hdrdir)/ruby/internal/stdckdint.h sha1.o: $(hdrdir)/ruby/internal/symbol.h sha1.o: $(hdrdir)/ruby/internal/value.h sha1.o: $(hdrdir)/ruby/internal/value_type.h @@ -292,6 +294,7 @@ sha1init.o: $(hdrdir)/ruby/internal/intern/re.h sha1init.o: $(hdrdir)/ruby/internal/intern/ruby.h sha1init.o: $(hdrdir)/ruby/internal/intern/select.h sha1init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +sha1init.o: $(hdrdir)/ruby/internal/intern/set.h sha1init.o: $(hdrdir)/ruby/internal/intern/signal.h sha1init.o: $(hdrdir)/ruby/internal/intern/sprintf.h sha1init.o: $(hdrdir)/ruby/internal/intern/string.h @@ -311,6 +314,7 @@ sha1init.o: $(hdrdir)/ruby/internal/special_consts.h sha1init.o: $(hdrdir)/ruby/internal/static_assert.h sha1init.o: $(hdrdir)/ruby/internal/stdalign.h sha1init.o: $(hdrdir)/ruby/internal/stdbool.h +sha1init.o: $(hdrdir)/ruby/internal/stdckdint.h sha1init.o: $(hdrdir)/ruby/internal/symbol.h sha1init.o: $(hdrdir)/ruby/internal/value.h sha1init.o: $(hdrdir)/ruby/internal/value_type.h diff --git a/ext/digest/sha1/sha1.c b/ext/digest/sha1/sha1.c index 53112275498795..ce200270b72ba6 100644 --- a/ext/digest/sha1/sha1.c +++ b/ext/digest/sha1/sha1.c @@ -232,8 +232,14 @@ void SHA1_Update(SHA1_CTX *context, const uint8_t *data, size_t len) if ((j + len) > 63) { (void)memcpy(&context->buffer[j], data, (i = 64-j)); SHA1_Transform(context->state, context->buffer); - for ( ; i + 63 < len; i += 64) + for ( ; i + 63 < len; i += 64) { + RB_DIGEST_WARNING_PUSH(); +#if defined(__GNUC__) && !defined(__clang__) && __GNUC__ >= 11 + RB_DIGEST_WARNING_IGNORED(-Wstringop-overread); +#endif SHA1_Transform(context->state, &data[i]); + RB_DIGEST_WARNING_POP(); + } j = 0; } else { i = 0; diff --git a/ext/digest/sha1/sha1cc.h b/ext/digest/sha1/sha1cc.h index 2ed8d646ab3fa1..f39ecc623405c3 100644 --- a/ext/digest/sha1/sha1cc.h +++ b/ext/digest/sha1/sha1cc.h @@ -12,3 +12,11 @@ static DEFINE_FINISH_FUNC_FROM_FINAL(SHA1) #undef SHA1_Finish #define SHA1_Update rb_digest_SHA1_update #define SHA1_Finish rb_digest_SHA1_finish + +/* + * Pre-10.6 defines are with args, which don't match the argless use in + * the function pointer inits. Thus, we redefine SHA1_Init as well. + * This is a NOP on 10.6+. + */ +#undef SHA1_Init +#define SHA1_Init CC_SHA1_Init diff --git a/ext/digest/sha1/sha1init.c b/ext/digest/sha1/sha1init.c index f7047bc6d3c3c1..c39959f428ac04 100644 --- a/ext/digest/sha1/sha1init.c +++ b/ext/digest/sha1/sha1init.c @@ -55,9 +55,8 @@ Init_sha1(void) mDigest = rb_define_module("Digest"); /* let rdoc know */ #endif mDigest = rb_digest_namespace(); - cDigest_Base = rb_path2class("Digest::Base"); + cDigest_Base = rb_const_get(mDigest, rb_intern_const("Base")); cDigest_SHA1 = rb_define_class_under(mDigest, "SHA1", cDigest_Base); - rb_iv_set(cDigest_SHA1, "metadata", rb_digest_make_metadata(&sha1)); } diff --git a/ext/digest/sha2/depend b/ext/digest/sha2/depend index 7b88b6411f3307..2b74776b3e097c 100644 --- a/ext/digest/sha2/depend +++ b/ext/digest/sha2/depend @@ -131,6 +131,7 @@ sha2.o: $(hdrdir)/ruby/internal/intern/re.h sha2.o: $(hdrdir)/ruby/internal/intern/ruby.h sha2.o: $(hdrdir)/ruby/internal/intern/select.h sha2.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +sha2.o: $(hdrdir)/ruby/internal/intern/set.h sha2.o: $(hdrdir)/ruby/internal/intern/signal.h sha2.o: $(hdrdir)/ruby/internal/intern/sprintf.h sha2.o: $(hdrdir)/ruby/internal/intern/string.h @@ -150,6 +151,7 @@ sha2.o: $(hdrdir)/ruby/internal/special_consts.h sha2.o: $(hdrdir)/ruby/internal/static_assert.h sha2.o: $(hdrdir)/ruby/internal/stdalign.h sha2.o: $(hdrdir)/ruby/internal/stdbool.h +sha2.o: $(hdrdir)/ruby/internal/stdckdint.h sha2.o: $(hdrdir)/ruby/internal/symbol.h sha2.o: $(hdrdir)/ruby/internal/value.h sha2.o: $(hdrdir)/ruby/internal/value_type.h @@ -292,6 +294,7 @@ sha2init.o: $(hdrdir)/ruby/internal/intern/re.h sha2init.o: $(hdrdir)/ruby/internal/intern/ruby.h sha2init.o: $(hdrdir)/ruby/internal/intern/select.h sha2init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +sha2init.o: $(hdrdir)/ruby/internal/intern/set.h sha2init.o: $(hdrdir)/ruby/internal/intern/signal.h sha2init.o: $(hdrdir)/ruby/internal/intern/sprintf.h sha2init.o: $(hdrdir)/ruby/internal/intern/string.h @@ -311,6 +314,7 @@ sha2init.o: $(hdrdir)/ruby/internal/special_consts.h sha2init.o: $(hdrdir)/ruby/internal/static_assert.h sha2init.o: $(hdrdir)/ruby/internal/stdalign.h sha2init.o: $(hdrdir)/ruby/internal/stdbool.h +sha2init.o: $(hdrdir)/ruby/internal/stdckdint.h sha2init.o: $(hdrdir)/ruby/internal/symbol.h sha2init.o: $(hdrdir)/ruby/internal/value.h sha2init.o: $(hdrdir)/ruby/internal/value_type.h diff --git a/ext/digest/sha2/sha2cc.h b/ext/digest/sha2/sha2cc.h index 3f99604465b6e0..1245a2e2c7d6b4 100644 --- a/ext/digest/sha2/sha2cc.h +++ b/ext/digest/sha2/sha2cc.h @@ -1,6 +1,33 @@ #define COMMON_DIGEST_FOR_OPENSSL 1 #include +/* + * Prior to 10.5, OpenSSL-compatible definitions are missing for + * SHA2 macros, though the CC_ versions are present. + * Add the missing definitions we actually use here if needed. + * Note that the definitions are the argless 10.6+-style. + * The weird CTX mismatch is copied from the 10.6 header. + */ +#ifndef SHA256_DIGEST_LENGTH +#define SHA256_DIGEST_LENGTH CC_SHA256_DIGEST_LENGTH +#define SHA256_CTX CC_SHA256_CTX +#define SHA256_Update CC_SHA256_Update +#define SHA256_Final CC_SHA256_Final +#endif /* !defined SHA256_DIGEST_LENGTH */ + +#ifndef SHA384_DIGEST_LENGTH +#define SHA384_DIGEST_LENGTH CC_SHA384_DIGEST_LENGTH +#define SHA512_CTX CC_SHA512_CTX +#define SHA384_Update CC_SHA384_Update +#define SHA384_Final CC_SHA384_Final +#endif /* !defined SHA384_DIGEST_LENGTH */ + +#ifndef SHA512_DIGEST_LENGTH +#define SHA512_DIGEST_LENGTH CC_SHA512_DIGEST_LENGTH +#define SHA512_Update CC_SHA512_Update +#define SHA512_Final CC_SHA512_Final +#endif /* !defined SHA512_DIGEST_LENGTH */ + #define SHA256_BLOCK_LENGTH CC_SHA256_BLOCK_BYTES #define SHA384_BLOCK_LENGTH CC_SHA384_BLOCK_BYTES #define SHA512_BLOCK_LENGTH CC_SHA512_BLOCK_BYTES @@ -29,3 +56,15 @@ static DEFINE_FINISH_FUNC_FROM_FINAL(SHA512) #undef SHA512_Finish #define SHA512_Update rb_digest_SHA512_update #define SHA512_Finish rb_digest_SHA512_finish + +/* + * Pre-10.6 defines are with args, which don't match the argless use in + * the function pointer inits. Thus, we redefine SHA*_Init as well. + * This is a NOP on 10.6+. + */ +#undef SHA256_Init +#define SHA256_Init CC_SHA256_Init +#undef SHA384_Init +#define SHA384_Init CC_SHA384_Init +#undef SHA512_Init +#define SHA512_Init CC_SHA512_Init diff --git a/ext/digest/sha2/sha2init.c b/ext/digest/sha2/sha2init.c index 94cccf3febb936..3923e3724c3eed 100644 --- a/ext/digest/sha2/sha2init.c +++ b/ext/digest/sha2/sha2init.c @@ -25,29 +25,50 @@ static const rb_digest_metadata_t sha##bitlen = { \ FOREACH_BITLEN(DEFINE_ALGO_METADATA) /* + * Document-class: Digest::SHA256 < Digest::Base + * * Classes for calculating message digests using the SHA-256/384/512 * Secure Hash Algorithm(s) by NIST (the US' National Institute of * Standards and Technology), described in FIPS PUB 180-2. + * + * See SHA2. + */ +/* + * Document-class: Digest::SHA384 < Digest::Base + * + * Classes for calculating message digests using the SHA-256/384/512 + * Secure Hash Algorithm(s) by NIST (the US' National Institute of + * Standards and Technology), described in FIPS PUB 180-2. + * + * See SHA2. + */ +/* + * Document-class: Digest::SHA512 < Digest::Base + * + * Classes for calculating message digests using the SHA-256/384/512 + * Secure Hash Algorithm(s) by NIST (the US' National Institute of + * Standards and Technology), described in FIPS PUB 180-2. + * + * See SHA2. */ void Init_sha2(void) { - VALUE mDigest, cDigest_Base; + VALUE mDigest, cDigest_Base, cDigest_SHA2; ID id_metadata = rb_id_metadata(); -#define DECLARE_ALGO_CLASS(bitlen) \ - VALUE cDigest_SHA##bitlen; - - FOREACH_BITLEN(DECLARE_ALGO_CLASS) - +#if 0 + mDigest = rb_define_module("Digest"); /* let rdoc know */ +#endif mDigest = rb_digest_namespace(); - cDigest_Base = rb_path2class("Digest::Base"); + cDigest_Base = rb_const_get(mDigest, rb_intern_const("Base")); + + cDigest_SHA2 = rb_define_class_under(mDigest, "SHA256", cDigest_Base); + rb_ivar_set(cDigest_SHA2, id_metadata, rb_digest_make_metadata(&sha256)); -#define DEFINE_ALGO_CLASS(bitlen) \ - cDigest_SHA##bitlen = rb_define_class_under(mDigest, "SHA" #bitlen, cDigest_Base); \ -\ - rb_ivar_set(cDigest_SHA##bitlen, id_metadata, \ - rb_digest_make_metadata(&sha##bitlen)); + cDigest_SHA2 = rb_define_class_under(mDigest, "SHA384", cDigest_Base); + rb_ivar_set(cDigest_SHA2, id_metadata, rb_digest_make_metadata(&sha384)); - FOREACH_BITLEN(DEFINE_ALGO_CLASS) + cDigest_SHA2 = rb_define_class_under(mDigest, "SHA512", cDigest_Base); + rb_ivar_set(cDigest_SHA2, id_metadata, rb_digest_make_metadata(&sha512)); } diff --git a/ext/digest/test.sh b/ext/digest/test.sh deleted file mode 100644 index 328c7575e64072..00000000000000 --- a/ext/digest/test.sh +++ /dev/null @@ -1,30 +0,0 @@ -#!/bin/sh -# -# $RoughId: test.sh,v 1.5 2001/07/13 15:38:27 knu Exp $ -# $Id$ - -RUBY=${RUBY:=ruby} -MAKE=${MAKE:=make} -CFLAGS=${CFLAGS:=-Wall} - -${RUBY} extconf.rb --with-cflags="${CFLAGS}" -${MAKE} clean -${MAKE} - -for algo in md5 rmd160 sha1 sha2; do - args=--with-cflags="${CFLAGS}" - - if [ $WITH_BUNDLED_ENGINES ]; then - args="$args --with-bundled-$algo" - fi - - (cd $algo && - ${RUBY} extconf.rb $args; - ${MAKE} clean; - ${MAKE}) - ln -sf ../../$algo/$algo.so lib/digest/ -done - -${RUBY} -I. -I./lib ../../test/digest/test_digest.rb - -rm lib/digest/*.so diff --git a/ext/erb/escape/escape.c b/ext/erb/escape/escape.c index 67b2d1ef34d2d7..db2abd97738b0b 100644 --- a/ext/erb/escape/escape.c +++ b/ext/erb/escape/escape.c @@ -65,9 +65,12 @@ optimized_escape_html(VALUE str) return escaped; } -// ERB::Util.html_escape is different from CGI.escapeHTML in the following two parts: -// * ERB::Util.html_escape converts an argument with #to_s first (only if it's not T_STRING) -// * ERB::Util.html_escape does not allocate a new string when nothing needs to be escaped +/* + * ERB::Util.html_escape is similar to CGI.escapeHTML but different in the following two parts: + * + * * ERB::Util.html_escape converts an argument with #to_s first (only if it's not T_STRING) + * * ERB::Util.html_escape does not allocate a new string when nothing needs to be escaped + */ static VALUE erb_escape_html(VALUE self, VALUE str) { diff --git a/ext/erb/escape/extconf.rb b/ext/erb/escape/extconf.rb index c1002548ad2a53..783e8c1f5562f8 100644 --- a/ext/erb/escape/extconf.rb +++ b/ext/erb/escape/extconf.rb @@ -1,6 +1,7 @@ require 'mkmf' -if RUBY_ENGINE == 'truffleruby' +case RUBY_ENGINE +when 'jruby', 'truffleruby' File.write('Makefile', dummy_makefile($srcdir).join) else create_makefile 'erb/escape' diff --git a/ext/etc/.document b/ext/etc/.document new file mode 100644 index 00000000000000..9bbea23b9299f1 --- /dev/null +++ b/ext/etc/.document @@ -0,0 +1,2 @@ +etc.c +constdefs.h diff --git a/ext/etc/depend b/ext/etc/depend index 00787b6aaf67e9..77fe56a6bf054b 100644 --- a/ext/etc/depend +++ b/ext/etc/depend @@ -143,6 +143,7 @@ etc.o: $(hdrdir)/ruby/internal/intern/re.h etc.o: $(hdrdir)/ruby/internal/intern/ruby.h etc.o: $(hdrdir)/ruby/internal/intern/select.h etc.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +etc.o: $(hdrdir)/ruby/internal/intern/set.h etc.o: $(hdrdir)/ruby/internal/intern/signal.h etc.o: $(hdrdir)/ruby/internal/intern/sprintf.h etc.o: $(hdrdir)/ruby/internal/intern/string.h @@ -162,6 +163,7 @@ etc.o: $(hdrdir)/ruby/internal/special_consts.h etc.o: $(hdrdir)/ruby/internal/static_assert.h etc.o: $(hdrdir)/ruby/internal/stdalign.h etc.o: $(hdrdir)/ruby/internal/stdbool.h +etc.o: $(hdrdir)/ruby/internal/stdckdint.h etc.o: $(hdrdir)/ruby/internal/symbol.h etc.o: $(hdrdir)/ruby/internal/value.h etc.o: $(hdrdir)/ruby/internal/value_type.h diff --git a/ext/etc/etc.c b/ext/etc/etc.c index 78657b43d0f77d..e2d621547e9bef 100644 --- a/ext/etc/etc.c +++ b/ext/etc/etc.c @@ -54,9 +54,11 @@ static VALUE sGroup; # include # endif #endif -char *getlogin(void); +RUBY_EXTERN char *getlogin(void); -#define RUBY_ETC_VERSION "1.4.2" +#define RUBY_ETC_VERSION "1.4.5" + +#define SYMBOL_LIT(str) ID2SYM(rb_intern_const(str "")) #ifdef HAVE_RB_DEPRECATE_CONSTANT void rb_deprecate_constant(VALUE mod, const char *name); @@ -203,7 +205,7 @@ setup_passwd(struct passwd *pwd) #endif /* call-seq: - * getpwuid(uid) -> Passwd + * getpwuid(uid) -> Etc::Passwd * * Returns the /etc/passwd information for the user with the given * integer +uid+. @@ -215,7 +217,7 @@ setup_passwd(struct passwd *pwd) * * See the unix manpage for getpwuid(3) for more detail. * - * === Example: + * *Example:* * * Etc.getpwuid(0) * #=> # @@ -243,7 +245,7 @@ etc_getpwuid(int argc, VALUE *argv, VALUE obj) } /* call-seq: - * getpwnam(name) -> Passwd + * getpwnam(name) -> Etc::Passwd * * Returns the /etc/passwd information for the user with specified * login +name+. @@ -252,7 +254,7 @@ etc_getpwuid(int argc, VALUE *argv, VALUE obj) * * See the unix manpage for getpwnam(3) for more detail. * - * === Example: + * *Example:* * * Etc.getpwnam('root') * #=> # @@ -307,8 +309,8 @@ each_passwd(void) #endif /* call-seq: - * Etc.passwd { |struct| block } -> Passwd - * Etc.passwd -> Passwd + * passwd { |struct| block } + * passwd -> Etc::Passwd * * Provides a convenient Ruby iterator which executes a block for each entry * in the /etc/passwd file. @@ -317,7 +319,7 @@ each_passwd(void) * * See ::getpwent above for details. * - * Example: + * *Example:* * * require 'etc' * @@ -343,7 +345,7 @@ etc_passwd(VALUE obj) } /* call-seq: - * Etc::Passwd.each { |struct| block } -> Passwd + * Etc::Passwd.each { |struct| block } -> Etc::Passwd * Etc::Passwd.each -> Enumerator * * Iterates for each entry in the /etc/passwd file if a block is @@ -355,7 +357,7 @@ etc_passwd(VALUE obj) * * See Etc.getpwent above for details. * - * Example: + * *Example:* * * require 'etc' * @@ -377,7 +379,10 @@ etc_each_passwd(VALUE obj) return obj; } -/* Resets the process of reading the /etc/passwd file, so that the +/* call-seq: + * setpwent + * + * Resets the process of reading the /etc/passwd file, so that the * next call to ::getpwent will return the first entry again. */ static VALUE @@ -389,7 +394,10 @@ etc_setpwent(VALUE obj) return Qnil; } -/* Ends the process of scanning through the /etc/passwd file begun +/* call-seq: + * endpwent + * + * Ends the process of scanning through the /etc/passwd file begun * with ::getpwent, and closes the file. */ static VALUE @@ -401,7 +409,10 @@ etc_endpwent(VALUE obj) return Qnil; } -/* Returns an entry from the /etc/passwd file. +/* call-seq: + * getpwent -> Etc::Passwd + * + * Returns an entry from the /etc/passwd file. * * The first time it is called it opens the file and returns the first entry; * each successive call returns the next entry, or +nil+ if the end of the file @@ -449,7 +460,7 @@ setup_group(struct group *grp) #endif /* call-seq: - * getgrgid(group_id) -> Group + * getgrgid(group_id) -> Etc::Group * * Returns information about the group with specified integer +group_id+, * as found in /etc/group. @@ -458,7 +469,7 @@ setup_group(struct group *grp) * * See the unix manpage for getgrgid(3) for more detail. * - * === Example: + * *Example:* * * Etc.getgrgid(100) * #=> # @@ -487,7 +498,7 @@ etc_getgrgid(int argc, VALUE *argv, VALUE obj) } /* call-seq: - * getgrnam(name) -> Group + * getgrnam(name) -> Etc::Group * * Returns information about the group with specified +name+, as found in * /etc/group. @@ -496,7 +507,7 @@ etc_getgrgid(int argc, VALUE *argv, VALUE obj) * * See the unix manpage for getgrnam(3) for more detail. * - * === Example: + * *Example:* * * Etc.getgrnam('users') * #=> # @@ -529,7 +540,6 @@ group_ensure(VALUE _) return Qnil; } - static VALUE group_iterate(VALUE _) { @@ -552,14 +562,18 @@ each_group(void) } #endif -/* Provides a convenient Ruby iterator which executes a block for each entry +/* call-seq: + * group { |struct| block } + * group -> Etc::Group + * + * Provides a convenient Ruby iterator which executes a block for each entry * in the /etc/group file. * * The code block is passed an Group struct. * * See ::getgrent above for details. * - * Example: + * *Example:* * * require 'etc' * @@ -586,7 +600,7 @@ etc_group(VALUE obj) #ifdef HAVE_GETGRENT /* call-seq: - * Etc::Group.each { |group| block } -> obj + * Etc::Group.each { |group| block } -> Etc::Group * Etc::Group.each -> Enumerator * * Iterates for each entry in the /etc/group file if a block is @@ -596,7 +610,7 @@ etc_group(VALUE obj) * * The code block is passed a Group struct. * - * Example: + * *Example:* * * require 'etc' * @@ -617,7 +631,10 @@ etc_each_group(VALUE obj) } #endif -/* Resets the process of reading the /etc/group file, so that the +/* call-seq: + * setgrent + * + * Resets the process of reading the /etc/group file, so that the * next call to ::getgrent will return the first entry again. */ static VALUE @@ -629,7 +646,10 @@ etc_setgrent(VALUE obj) return Qnil; } -/* Ends the process of scanning through the /etc/group file begun +/* call-seq: + * endgrent + * + * Ends the process of scanning through the /etc/group file begun * by ::getgrent, and closes the file. */ static VALUE @@ -641,7 +661,10 @@ etc_endgrent(VALUE obj) return Qnil; } -/* Returns an entry from the /etc/group file. +/* call-seq: + * getgrent -> Etc::Group + * + * Returns an entry from the /etc/group file. * * The first time it is called it opens the file and returns the first entry; * each successive call returns the next entry, or +nil+ if the end of the file @@ -670,9 +693,21 @@ etc_getgrent(VALUE obj) VALUE rb_w32_special_folder(int type); UINT rb_w32_system_tmpdir(WCHAR *path, UINT len); VALUE rb_w32_conv_from_wchar(const WCHAR *wstr, rb_encoding *enc); +#elif defined(LOAD_RELATIVE) +static inline VALUE +rbconfig(void) +{ + VALUE config; + rb_require("rbconfig"); + config = rb_const_get(rb_path2class("RbConfig"), rb_intern_const("CONFIG")); + Check_Type(config, T_HASH); + return config; +} #endif -/* +/* call-seq: + * sysconfdir -> String + * * Returns system configuration directory. * * This is typically "/etc", but is modified by the prefix used @@ -687,12 +722,16 @@ etc_sysconfdir(VALUE obj) { #ifdef _WIN32 return rb_w32_special_folder(CSIDL_COMMON_APPDATA); +#elif defined(LOAD_RELATIVE) + return rb_hash_aref(rbconfig(), rb_str_new_lit("sysconfdir")); #else return rb_filesystem_str_new_cstr(SYSCONFDIR); #endif } -/* +/* call-seq: + * systmpdir -> String + * * Returns system temporary directory; typically "/tmp". */ static VALUE @@ -736,13 +775,15 @@ etc_systmpdir(VALUE _) } #ifdef HAVE_UNAME -/* +/* call-seq: + * uname -> hash + * * Returns the system information obtained by uname system call. * * The return value is a hash which has 5 keys at least: * :sysname, :nodename, :release, :version, :machine * - * Example: + * *Example:* * * require 'etc' * require 'pp' @@ -784,12 +825,12 @@ etc_uname(VALUE obj) sysname = "Windows"; break; } - rb_hash_aset(result, ID2SYM(rb_intern("sysname")), rb_str_new_cstr(sysname)); + rb_hash_aset(result, SYMBOL_LIT("sysname"), rb_str_new_cstr(sysname)); release = rb_sprintf("%lu.%lu.%lu", v.dwMajorVersion, v.dwMinorVersion, v.dwBuildNumber); - rb_hash_aset(result, ID2SYM(rb_intern("release")), release); + rb_hash_aset(result, SYMBOL_LIT("release"), release); version = rb_sprintf("%s Version %"PRIsVALUE": %"PRIsVALUE, sysname, release, rb_w32_conv_from_wchar(v.szCSDVersion, rb_utf8_encoding())); - rb_hash_aset(result, ID2SYM(rb_intern("version")), version); + rb_hash_aset(result, SYMBOL_LIT("version"), version); # if defined _MSC_VER && _MSC_VER < 1300 # define GET_COMPUTER_NAME(ptr, plen) GetComputerNameW(ptr, plen) @@ -803,7 +844,7 @@ etc_uname(VALUE obj) } ALLOCV_END(vbuf); if (NIL_P(nodename)) nodename = rb_str_new(0, 0); - rb_hash_aset(result, ID2SYM(rb_intern("nodename")), nodename); + rb_hash_aset(result, SYMBOL_LIT("nodename"), nodename); # ifndef PROCESSOR_ARCHITECTURE_AMD64 # define PROCESSOR_ARCHITECTURE_AMD64 9 @@ -827,7 +868,7 @@ etc_uname(VALUE obj) break; } - rb_hash_aset(result, ID2SYM(rb_intern("machine")), rb_str_new_cstr(mach)); + rb_hash_aset(result, SYMBOL_LIT("machine"), rb_str_new_cstr(mach)); #else struct utsname u; int ret; @@ -838,11 +879,11 @@ etc_uname(VALUE obj) rb_sys_fail("uname"); result = rb_hash_new(); - rb_hash_aset(result, ID2SYM(rb_intern("sysname")), rb_str_new_cstr(u.sysname)); - rb_hash_aset(result, ID2SYM(rb_intern("nodename")), rb_str_new_cstr(u.nodename)); - rb_hash_aset(result, ID2SYM(rb_intern("release")), rb_str_new_cstr(u.release)); - rb_hash_aset(result, ID2SYM(rb_intern("version")), rb_str_new_cstr(u.version)); - rb_hash_aset(result, ID2SYM(rb_intern("machine")), rb_str_new_cstr(u.machine)); + rb_hash_aset(result, SYMBOL_LIT("sysname"), rb_str_new_cstr(u.sysname)); + rb_hash_aset(result, SYMBOL_LIT("nodename"), rb_str_new_cstr(u.nodename)); + rb_hash_aset(result, SYMBOL_LIT("release"), rb_str_new_cstr(u.release)); + rb_hash_aset(result, SYMBOL_LIT("version"), rb_str_new_cstr(u.version)); + rb_hash_aset(result, SYMBOL_LIT("machine"), rb_str_new_cstr(u.machine)); #endif return result; @@ -852,7 +893,9 @@ etc_uname(VALUE obj) #endif #ifdef HAVE_SYSCONF -/* +/* call-seq: + * sysconf(name) -> Integer + * * Returns system configuration variable using sysconf(). * * _name_ should be a constant under Etc which begins with SC_. @@ -886,7 +929,9 @@ etc_sysconf(VALUE obj, VALUE arg) #endif #ifdef HAVE_CONFSTR -/* +/* call-seq: + * confstr(name) -> String + * * Returns system configuration variable using confstr(). * * _name_ should be a constant under Etc which begins with CS_. @@ -933,7 +978,9 @@ etc_confstr(VALUE obj, VALUE arg) #endif #ifdef HAVE_FPATHCONF -/* +/* call-seq: + * pathconf(name) -> Integer + * * Returns pathname configuration variable using fpathconf(). * * _name_ should be a constant under Etc which begins with PC_. @@ -1025,7 +1072,9 @@ etc_nprocessors_affin(void) } #endif -/* +/* call-seq: + * nprocessors -> Integer + * * Returns the number of online processors. * * The result is intended as the number of processes to @@ -1035,7 +1084,7 @@ etc_nprocessors_affin(void) * - sched_getaffinity(): Linux * - sysconf(_SC_NPROCESSORS_ONLN): GNU/Linux, NetBSD, FreeBSD, OpenBSD, DragonFly BSD, OpenIndiana, Mac OS X, AIX * - * Example: + * *Example:* * * require 'etc' * p Etc.nprocessors #=> 4 @@ -1044,7 +1093,7 @@ etc_nprocessors_affin(void) * process is bound to specific cpus. This is intended for getting better * parallel processing. * - * Example: (Linux) + * *Example:* (Linux) * * linux$ taskset 0x3 ./ruby -retc -e "p Etc.nprocessors" #=> 2 * @@ -1094,7 +1143,7 @@ etc_nprocessors(VALUE obj) * The Etc module provides a more reliable way to access information about * the logged in user than environment variables such as +$USER+. * - * == Example: + * *Example:* * * require 'etc' * @@ -1114,13 +1163,26 @@ Init_etc(void) { VALUE mEtc; -#ifdef HAVE_RB_EXT_RACTOR_SAFE - RB_EXT_RACTOR_SAFE(true); -#endif mEtc = rb_define_module("Etc"); + /* The version */ rb_define_const(mEtc, "VERSION", rb_str_new_cstr(RUBY_ETC_VERSION)); init_constants(mEtc); + /* Ractor-safe methods */ +#ifdef HAVE_RB_EXT_RACTOR_SAFE + RB_EXT_RACTOR_SAFE(true); +#endif + rb_define_module_function(mEtc, "systmpdir", etc_systmpdir, 0); + rb_define_module_function(mEtc, "uname", etc_uname, 0); + rb_define_module_function(mEtc, "sysconf", etc_sysconf, 1); + rb_define_module_function(mEtc, "confstr", etc_confstr, 1); + rb_define_method(rb_cIO, "pathconf", io_pathconf, 1); + rb_define_module_function(mEtc, "nprocessors", etc_nprocessors, 0); + + /* Non-Ractor-safe methods, see https://bugs.ruby-lang.org/issues/21115 */ +#ifdef HAVE_RB_EXT_RACTOR_SAFE + RB_EXT_RACTOR_SAFE(false); +#endif rb_define_module_function(mEtc, "getlogin", etc_getlogin, 0); rb_define_module_function(mEtc, "getpwuid", etc_getpwuid, -1); @@ -1136,13 +1198,9 @@ Init_etc(void) rb_define_module_function(mEtc, "setgrent", etc_setgrent, 0); rb_define_module_function(mEtc, "endgrent", etc_endgrent, 0); rb_define_module_function(mEtc, "getgrent", etc_getgrent, 0); + + /* Uses RbConfig::CONFIG so does not work in a Ractor */ rb_define_module_function(mEtc, "sysconfdir", etc_sysconfdir, 0); - rb_define_module_function(mEtc, "systmpdir", etc_systmpdir, 0); - rb_define_module_function(mEtc, "uname", etc_uname, 0); - rb_define_module_function(mEtc, "sysconf", etc_sysconf, 1); - rb_define_module_function(mEtc, "confstr", etc_confstr, 1); - rb_define_method(rb_cIO, "pathconf", io_pathconf, 1); - rb_define_module_function(mEtc, "nprocessors", etc_nprocessors, 0); sPasswd = rb_struct_define_under(mEtc, "Passwd", "name", @@ -1253,4 +1311,8 @@ Init_etc(void) rb_extend_object(sGroup, rb_mEnumerable); rb_define_singleton_method(sGroup, "each", etc_each_group, 0); #endif + +#if defined(HAVE_GETPWENT) || defined(HAVE_GETGRENT) + (void)safe_setup_str; +#endif } diff --git a/ext/etc/etc.gemspec b/ext/etc/etc.gemspec index 98c6d66faa8a10..3facc7486669a9 100644 --- a/ext/etc/etc.gemspec +++ b/ext/etc/etc.gemspec @@ -24,7 +24,8 @@ Gem::Specification.new do |spec| changelogs = Dir.glob("logs/ChangeLog-[1-9]*[^~]", base: __dir__) spec.files = %w[ - LICENSE.txt + BSDL + COPYING README.md ChangeLog ext/etc/constdefs.h diff --git a/ext/etc/extconf.rb b/ext/etc/extconf.rb index 2e28d5803775b5..497303a4fa51f7 100644 --- a/ext/etc/extconf.rb +++ b/ext/etc/extconf.rb @@ -10,8 +10,30 @@ have_library("sun", "getpwnam") # NIS (== YP) interface for IRIX 4 have_func("uname((struct utsname *)NULL)", headers) have_func("getlogin") -have_func("getpwent") -have_func("getgrent") +if have_func("getpwent") + have_struct_member('struct passwd', 'pw_gecos', 'pwd.h') + have_struct_member('struct passwd', 'pw_change', 'pwd.h') + have_struct_member('struct passwd', 'pw_quota', 'pwd.h') + if have_struct_member('struct passwd', 'pw_age', 'pwd.h') + case what_type?('struct passwd', 'pw_age', 'pwd.h') + when "string" + f = "safe_setup_str" + when "long long" + f = "LL2NUM" + else + f = "INT2NUM" + end + $defs.push("-DPW_AGE2VAL="+f) + end + have_struct_member('struct passwd', 'pw_class', 'pwd.h') + have_struct_member('struct passwd', 'pw_comment', 'pwd.h') unless /cygwin/ === RUBY_PLATFORM + have_struct_member('struct passwd', 'pw_expire', 'pwd.h') + have_struct_member('struct passwd', 'pw_passwd', 'pwd.h') +end +if have_func("getgrent") + have_struct_member('struct group', 'gr_passwd', 'grp.h') +end + if (sysconfdir = RbConfig::CONFIG["sysconfdir"] and !RbConfig.expand(sysconfdir.dup, "prefix"=>"", "DESTDIR"=>"").empty?) $defs.push("-DSYSCONFDIR=#{Shellwords.escape(sysconfdir.dump)}") @@ -21,26 +43,6 @@ have_func("confstr") have_func("fpathconf") -have_struct_member('struct passwd', 'pw_gecos', 'pwd.h') -have_struct_member('struct passwd', 'pw_change', 'pwd.h') -have_struct_member('struct passwd', 'pw_quota', 'pwd.h') -if have_struct_member('struct passwd', 'pw_age', 'pwd.h') - case what_type?('struct passwd', 'pw_age', 'pwd.h') - when "string" - f = "safe_setup_str" - when "long long" - f = "LL2NUM" - else - f = "INT2NUM" - end - $defs.push("-DPW_AGE2VAL="+f) -end -have_struct_member('struct passwd', 'pw_class', 'pwd.h') -have_struct_member('struct passwd', 'pw_comment', 'pwd.h') unless /cygwin/ === RUBY_PLATFORM -have_struct_member('struct passwd', 'pw_expire', 'pwd.h') -have_struct_member('struct passwd', 'pw_passwd', 'pwd.h') -have_struct_member('struct group', 'gr_passwd', 'grp.h') - # for https://github.com/ruby/etc srcdir = File.expand_path("..", __FILE__) constdefs = "#{srcdir}/constdefs.h" @@ -58,7 +60,7 @@ # TODO: remove when dropping 2.7 support, as exported since 3.0 have_func('rb_deprecate_constant(Qnil, "None")') -have_func("rb_io_descriptor") +have_func("rb_io_descriptor", "ruby/io.h") $distcleanfiles << "constdefs.h" diff --git a/ext/etc/mkconstants.rb b/ext/etc/mkconstants.rb index a752d64519fca0..a766560a8a051d 100644 --- a/ext/etc/mkconstants.rb +++ b/ext/etc/mkconstants.rb @@ -35,6 +35,12 @@ def c_str(str) opt.parse! +CONST_PREFIXES = { + 'SC' => 'for Etc.sysconf; See man sysconf', + 'CS' => 'for Etc.confstr; See man constr', + 'PC' => 'for IO#pathconf; See man fpathconf', +} + h = {} COMMENTS = {} @@ -49,6 +55,13 @@ def c_str(str) next end h[name] = default_value + if additional = CONST_PREFIXES[name[/\A_([A-Z]+)_/, 1]] + if comment&.match(/\w\z/) + comment << " " << additional + else + (comment ||= String.new) << " " << additional.sub(/\A\w/) {$&.upcase} + end + end COMMENTS[name] = comment if comment } DEFS = h.to_a @@ -66,15 +79,11 @@ def each_name(pat) } end -erb_new = lambda do |src, safe, trim| - if ERB.instance_method(:initialize).parameters.assoc(:key) # Ruby 2.6+ - ERB.new(src, trim_mode: trim) - else - ERB.new(src, safe, trim) - end +erb_new = lambda do |src, trim| + ERB.new(src, trim_mode: trim) end -erb_new.call(<<'EOS', nil, '%').def_method(Object, "gen_const_decls") +erb_new.call(<<'EOS', '%').def_method(Object, "gen_const_decls") % each_const {|name, default_value| #if !defined(<%=name%>) # if defined(HAVE_CONST_<%=name.upcase%>) @@ -88,7 +97,7 @@ def each_name(pat) % } EOS -erb_new.call(<<'EOS', nil, '%').def_method(Object, "gen_const_defs") +erb_new.call(<<'EOS', '%').def_method(Object, "gen_const_defs") % each_const {|name, default_value| #if defined(<%=name%>) % if comment = COMMENTS[name] @@ -99,13 +108,13 @@ def each_name(pat) % } EOS -header_result = erb_new.call(<<'EOS', nil, '%').result(binding) +header_result = erb_new.call(<<'EOS', '%').result(binding) /* autogenerated file */ <%= gen_const_decls %> EOS -result = erb_new.call(<<'EOS', nil, '%').result(binding) +result = erb_new.call(<<'EOS', '%').result(binding) /* autogenerated file */ #ifdef HAVE_LONG_LONG @@ -123,6 +132,9 @@ def each_name(pat) static void init_constants(VALUE mod) { +#if 0 + mod = rb_define_module("Etc"); +#endif <%= gen_const_defs %> } EOS diff --git a/ext/extmk.rb b/ext/extmk.rb index 428ffc91a639ad..39cbce1bc9fe68 100755 --- a/ext/extmk.rb +++ b/ext/extmk.rb @@ -2,7 +2,13 @@ # -*- mode: ruby; coding: us-ascii -*- # frozen_string_literal: false -module Gem; end # only needs Gem::Platform +module Gem + # Used by Gem::Platform.local + def self.target_rbconfig + RbConfig::CONFIG + end +end +# only needs Gem::Platform require 'rubygems/platform' # :stopdoc: @@ -104,7 +110,7 @@ def extract_makefile(makefile, keep = true) end return false end - srcs = Dir[File.join($srcdir, "*.{#{SRC_EXT.join(%q{,})}}")].map {|fn| File.basename(fn)}.sort + srcs = Dir[*SRC_EXT.map {|e| "*.#{e}"}, base: $srcdir].map {|fn| File.basename(fn)}.sort if !srcs.empty? old_srcs = m[/^ORIG_SRCS[ \t]*=[ \t](.*)/, 1] or return false (old_srcs.split - srcs).empty? or return false @@ -132,6 +138,14 @@ def extract_makefile(makefile, keep = true) true end +def create_makefile(target, srcprefix = nil) + if $static and target.include?("/") + base = File.basename(target) + $defs << "-DInit_#{base}=Init_#{target.tr('/', '_')}" + end + super +end + def extmake(target, basedir = 'ext', maybestatic = true) FileUtils.mkpath target unless File.directory?(target) begin @@ -159,8 +173,6 @@ def extmake(target, basedir = 'ext', maybestatic = true) $mdir = target $srcdir = File.join($top_srcdir, basedir, $mdir) $preload = nil - $objs = [] - $srcs = [] $extso = [] makefile = "./Makefile" static = $static @@ -194,7 +206,7 @@ def extmake(target, basedir = 'ext', maybestatic = true) begin $extconf_h = nil ok &&= extract_makefile(makefile) - old_objs = $objs + old_objs = $objs || [] old_cleanfiles = $distcleanfiles | $cleanfiles conf = ["#{$srcdir}/makefile.rb", "#{$srcdir}/extconf.rb"].find {|f| File.exist?(f)} if (!ok || ($extconf_h && !File.exist?($extconf_h)) || @@ -257,6 +269,8 @@ def extmake(target, basedir = 'ext', maybestatic = true) unless $destdir.to_s.empty? or $mflags.defined?("DESTDIR") args += ["DESTDIR=" + relative_from($destdir, "../"+prefix)] end + $objs ||= [] + $srcs ||= [] if $static and ok and !$objs.empty? and !noinstall args += ["static"] $extlist.push [(maybestatic ? $static : false), target, $target, $preload] @@ -472,12 +486,13 @@ def $mflags.defined?(var) $extension = [exts] if exts if ext_prefix.start_with?('.') @gemname = exts - elsif exts - $static_ext.delete_if {|t, *| !File.fnmatch(t, exts)} + exts = [] + else + exts &&= $static_ext.select {|t, *| File.fnmatch(t, exts)} end end -ext_prefix = "#{$top_srcdir}/#{ext_prefix || 'ext'}" -exts = $static_ext.sort_by {|t, i| i}.collect {|t, i| t} +ext_prefix ||= 'ext' +exts = (exts || $static_ext).sort_by {|t, i| i}.collect {|t, i| t} default_exclude_exts = case when $cygwin @@ -490,28 +505,30 @@ def $mflags.defined?(var) mandatory_exts = {} withes, withouts = [["--with", nil], ["--without", default_exclude_exts]].collect {|w, d| if !(w = %w[-extensions -ext].collect {|o|arg_config(w+o)}).any? - d ? proc {|c1| d.any?(&c1)} : proc {true} + d ? proc {|&c1| d.any?(&c1)} : proc {true} elsif (w = w.grep(String)).empty? proc {true} else w = w.collect {|o| o.split(/,/)}.flatten w.collect! {|o| o == '+' ? d : o}.flatten! - proc {|c1| w.any?(&c1)} + proc {|&c1| w.any?(&c1)} end } cond = proc {|ext, *| - withes.call(proc {|n| - !n or (mandatory_exts[ext] = true if File.fnmatch(n, ext)) - }) and - !withouts.call(proc {|n| File.fnmatch(n, ext)}) + withes.call {|n| !n or (mandatory_exts[ext] = true if File.fnmatch(n, ext))} and + !withouts.call {|n| File.fnmatch(n, ext)} } ($extension || %w[*]).each do |e| e = e.sub(/\A(?:\.\/)+/, '') - incl, excl = Dir.glob("#{ext_prefix}/#{e}/**/extconf.rb").collect {|d| - d = File.dirname(d) - d.slice!(0, ext_prefix.length + 1) - d + incl, excl = Dir.glob("#{e}/**/extconf.rb", base: "#$top_srcdir/#{ext_prefix}").collect {|d| + File.dirname(d) }.partition {|ext| + if @gemname + ext = ext[%r[\A[^/]+]] # extract gem name + Dir.glob("*.gemspec", base: "#$top_srcdir/#{ext_prefix}/#{ext}") do |g| + break ext = g if ext.start_with?("#{g.chomp!(".gemspec")}-") + end + end with_config(ext, &cond) } incl.sort! @@ -522,7 +539,7 @@ def $mflags.defined?(var) exts.delete_if {|d| File.fnmatch?("-*", d)} end end -ext_prefix = ext_prefix[$top_srcdir.size+1..-2] +ext_prefix.chomp!("/") @ext_prefix = ext_prefix @inplace = inplace @@ -545,7 +562,13 @@ def configuration(srcdir) end def create_makefile(*args, &block) - return super unless @gemname + unless @gemname + if $static and (target = args.first).include?("/") + base = File.basename(target) + $defs << "-DInit_#{base}=Init_#{target.tr('/', '_')}" + end + return super + end super(*args) do |conf| conf.find do |s| s.sub!(%r(^(srcdir *= *)\$\(top_srcdir\)/\.bundle/gems/[^/]+(?=/))) { @@ -561,7 +584,8 @@ def create_makefile(*args, &block) } end - gemlib = File.directory?("#{$top_srcdir}/#{@ext_prefix}/#{@gemname}/lib") + conf = yield conf if block + if conf.any? {|s| /^TARGET *= *\S/ =~ s} conf << %{ gem_platform = #{Gem::Platform.local} @@ -594,23 +618,25 @@ def create_makefile(*args, &block) clean-gemspec: -$(Q)$(RM) $(gemspec) -} - - if gemlib - conf << %{ -install-rb: gemlib -clean-rb:: clean-gemlib LN_S = #{config_string('LN_S')} CP_R = #{config_string('CP')} -r - -gemlib = $(TARGET_TOPDIR)/gems/$(gem)/lib -gemlib:#{%{ $(gemlib)\n$(gemlib): $(gem_srcdir)/lib} if $nmake} - $(Q) #{@inplace ? '$(NULLCMD) ' : ''}$(RUBY) $(top_srcdir)/tool/ln_sr.rb -q -f -T $(gem_srcdir)/lib $(gemlib) - -clean-gemlib: - $(Q) $(#{@inplace ? 'NULLCMD' : 'RM_RF'}) $(gemlib) } + unless @inplace + %w[bin lib].each do |d| + next unless File.directory?("#{$top_srcdir}/#{@ext_prefix}/#{@gemname}/#{d}") + conf << %{ +install-rb: gem#{d} +clean-rb:: clean-gem#{d} + +gem#{d} = $(TARGET_TOPDIR)/gems/$(gem)/#{d} +gem#{d}:#{%{ $(gem#{d})\n$(gem#{d}): $(gem_srcdir)/#{d}} if $nmake} + $(Q) $(RUBY) $(top_srcdir)/tool/ln_sr.rb -q -f -T $(gem_srcdir)/#{d} $(gem#{d}) + +clean-gem#{d}: + $(Q) $(RM_RF) $(gem#{d}) +} + end end end @@ -628,7 +654,9 @@ def create_makefile(*args, &block) extso = [] fails = [] exts.each do |d| - $static = $force_static ? true : $static_ext[d] + $static = $force_static ? true : $static_ext.fetch(d) do + $static_ext.any? {|t, | File.fnmatch?(t, d)} + end if !$nodynamic or $static result = extmake(d, ext_prefix, !@gemname) or abort @@ -754,7 +782,6 @@ def mf.macro(name, values, max = 70) end submakeopts << 'EXTLDFLAGS="$(EXTLDFLAGS)"' submakeopts << 'EXTINITS="$(EXTINITS)"' - submakeopts << 'UPDATE_LIBRARIES="$(UPDATE_LIBRARIES)"' submakeopts << 'SHOWFLAGS=' mf.macro "SUBMAKEOPTS", submakeopts mf.macro "NOTE_MESG", %w[$(RUBY) $(top_srcdir)/tool/lib/colorize.rb skip] @@ -793,9 +820,9 @@ def mf.macro(name, values, max = 70) if $gnumake == "yes" submake = "$(MAKE) -C $(@D)" else - submake = "cd $(@D) && " - config_string("exec") {|str| submake << str << " "} - submake << "$(MAKE)" + submake = ["cd", (sep ? "$(@D:/=#{sep})" : "$(@D)"), "&&"] + config_string("exec") {|str| submake << str} + submake = (submake << "$(MAKE)").join(" ") end targets.each do |tgt| exts.each do |d| @@ -810,7 +837,7 @@ def mf.macro(name, values, max = 70) end mf.puts "#{t}:#{pd}\n\t$(Q)#{submake} $(MFLAGS) V=$(V) $(@F)" if clean and clean.begin(1) - mf.puts "\t$(Q)$(RM) $(ext_build_dir)/exts.mk\n\t$(Q)$(RMDIRS) -p $(@D)" + mf.puts "\t$(Q)$(RM) $(ext_build_dir)/exts.mk\n\t$(Q)$(RMDIRS) $(@D)" end end end diff --git a/ext/fcntl/depend b/ext/fcntl/depend index 9ce9fa30ef0000..57ea0f21068068 100644 --- a/ext/fcntl/depend +++ b/ext/fcntl/depend @@ -128,6 +128,7 @@ fcntl.o: $(hdrdir)/ruby/internal/intern/re.h fcntl.o: $(hdrdir)/ruby/internal/intern/ruby.h fcntl.o: $(hdrdir)/ruby/internal/intern/select.h fcntl.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +fcntl.o: $(hdrdir)/ruby/internal/intern/set.h fcntl.o: $(hdrdir)/ruby/internal/intern/signal.h fcntl.o: $(hdrdir)/ruby/internal/intern/sprintf.h fcntl.o: $(hdrdir)/ruby/internal/intern/string.h @@ -147,6 +148,7 @@ fcntl.o: $(hdrdir)/ruby/internal/special_consts.h fcntl.o: $(hdrdir)/ruby/internal/static_assert.h fcntl.o: $(hdrdir)/ruby/internal/stdalign.h fcntl.o: $(hdrdir)/ruby/internal/stdbool.h +fcntl.o: $(hdrdir)/ruby/internal/stdckdint.h fcntl.o: $(hdrdir)/ruby/internal/symbol.h fcntl.o: $(hdrdir)/ruby/internal/value.h fcntl.o: $(hdrdir)/ruby/internal/value_type.h diff --git a/ext/fcntl/fcntl.c b/ext/fcntl/fcntl.c index 4ea7b29bf54c2e..86bee5fb45b648 100644 --- a/ext/fcntl/fcntl.c +++ b/ext/fcntl/fcntl.c @@ -28,7 +28,10 @@ pack up your own arguments to pass as args for locking functions, etc. #include "ruby.h" #include -/* Fcntl loads the constants defined in the system's C header +/* + * Document-module: Fcntl + * + * Fcntl loads the constants defined in the system's C header * file, and used with both the fcntl(2) and open(2) POSIX system calls. * * To perform a fcntl(2) operation, use IO::fcntl. @@ -62,18 +65,18 @@ pack up your own arguments to pass as args for locking functions, etc. * */ -#define FCNTL_VERSION "1.0.2" +#define FCNTL_VERSION "1.2.0" void Init_fcntl(void) { VALUE mFcntl = rb_define_module("Fcntl"); + /* The version string. */ rb_define_const(mFcntl, "VERSION", rb_str_new_cstr(FCNTL_VERSION)); #ifdef F_DUPFD - /* Document-const: F_DUPFD - * + /* * Duplicate a file descriptor to the minimum unused file descriptor * greater than or equal to the argument. * @@ -84,195 +87,164 @@ Init_fcntl(void) rb_define_const(mFcntl, "F_DUPFD", INT2NUM(F_DUPFD)); #endif #ifdef F_GETFD - /* Document-const: F_GETFD - * + /* * Read the close-on-exec flag of a file descriptor. */ rb_define_const(mFcntl, "F_GETFD", INT2NUM(F_GETFD)); #endif #ifdef F_GETLK - /* Document-const: F_GETLK - * + /* * Determine whether a given region of a file is locked. This uses one of * the F_*LK flags. */ rb_define_const(mFcntl, "F_GETLK", INT2NUM(F_GETLK)); #endif #ifdef F_SETFD - /* Document-const: F_SETFD - * + /* * Set the close-on-exec flag of a file descriptor. */ rb_define_const(mFcntl, "F_SETFD", INT2NUM(F_SETFD)); #endif #ifdef F_GETFL - /* Document-const: F_GETFL - * + /* * Get the file descriptor flags. This will be one or more of the O_* * flags. */ rb_define_const(mFcntl, "F_GETFL", INT2NUM(F_GETFL)); #endif #ifdef F_SETFL - /* Document-const: F_SETFL - * + /* * Set the file descriptor flags. This will be one or more of the O_* * flags. */ rb_define_const(mFcntl, "F_SETFL", INT2NUM(F_SETFL)); #endif #ifdef F_SETLK - /* Document-const: F_SETLK - * + /* * Acquire a lock on a region of a file. This uses one of the F_*LCK * flags. */ rb_define_const(mFcntl, "F_SETLK", INT2NUM(F_SETLK)); #endif #ifdef F_SETLKW - /* Document-const: F_SETLKW - * + /* * Acquire a lock on a region of a file, waiting if necessary. This uses * one of the F_*LCK flags */ rb_define_const(mFcntl, "F_SETLKW", INT2NUM(F_SETLKW)); #endif #ifdef FD_CLOEXEC - /* Document-const: FD_CLOEXEC - * + /* * the value of the close-on-exec flag. */ rb_define_const(mFcntl, "FD_CLOEXEC", INT2NUM(FD_CLOEXEC)); #endif #ifdef F_RDLCK - /* Document-const: F_RDLCK - * + /* * Read lock for a region of a file */ rb_define_const(mFcntl, "F_RDLCK", INT2NUM(F_RDLCK)); #endif #ifdef F_UNLCK - /* Document-const: F_UNLCK - * + /* * Remove lock for a region of a file */ rb_define_const(mFcntl, "F_UNLCK", INT2NUM(F_UNLCK)); #endif #ifdef F_WRLCK - /* Document-const: F_WRLCK - * + /* * Write lock for a region of a file */ rb_define_const(mFcntl, "F_WRLCK", INT2NUM(F_WRLCK)); #endif #ifdef F_SETPIPE_SZ - /* Document-const: F_SETPIPE_SZ - * + /* * Change the capacity of the pipe referred to by fd to be at least arg bytes. */ rb_define_const(mFcntl, "F_SETPIPE_SZ", INT2NUM(F_SETPIPE_SZ)); #endif #ifdef F_GETPIPE_SZ - /* Document-const: F_GETPIPE_SZ - * + /* * Return (as the function result) the capacity of the pipe referred to by fd. */ rb_define_const(mFcntl, "F_GETPIPE_SZ", INT2NUM(F_GETPIPE_SZ)); #endif #ifdef O_CREAT - /* Document-const: O_CREAT - * + /* * Create the file if it doesn't exist */ rb_define_const(mFcntl, "O_CREAT", INT2NUM(O_CREAT)); #endif #ifdef O_EXCL - /* Document-const: O_EXCL - * + /* * Used with O_CREAT, fail if the file exists */ rb_define_const(mFcntl, "O_EXCL", INT2NUM(O_EXCL)); #endif #ifdef O_NOCTTY - /* Document-const: O_NOCTTY - * + /* * Open TTY without it becoming the controlling TTY */ rb_define_const(mFcntl, "O_NOCTTY", INT2NUM(O_NOCTTY)); #endif #ifdef O_TRUNC - /* Document-const: O_TRUNC - * + /* * Truncate the file on open */ rb_define_const(mFcntl, "O_TRUNC", INT2NUM(O_TRUNC)); #endif #ifdef O_APPEND - /* Document-const: O_APPEND - * + /* * Open the file in append mode */ rb_define_const(mFcntl, "O_APPEND", INT2NUM(O_APPEND)); #endif #ifdef O_NONBLOCK - /* Document-const: O_NONBLOCK - * + /* * Open the file in non-blocking mode */ rb_define_const(mFcntl, "O_NONBLOCK", INT2NUM(O_NONBLOCK)); #endif #ifdef O_NDELAY - /* Document-const: O_NDELAY - * + /* * Open the file in non-blocking mode */ rb_define_const(mFcntl, "O_NDELAY", INT2NUM(O_NDELAY)); #endif #ifdef O_RDONLY - /* Document-const: O_RDONLY - * + /* * Open the file in read-only mode */ rb_define_const(mFcntl, "O_RDONLY", INT2NUM(O_RDONLY)); #endif #ifdef O_RDWR - /* Document-const: O_RDWR - * + /* * Open the file in read-write mode */ rb_define_const(mFcntl, "O_RDWR", INT2NUM(O_RDWR)); #endif #ifdef O_WRONLY - /* Document-const: O_WRONLY - * + /* * Open the file in write-only mode. */ rb_define_const(mFcntl, "O_WRONLY", INT2NUM(O_WRONLY)); #endif -#ifdef O_ACCMODE - /* Document-const: O_ACCMODE - * +#ifndef O_ACCMODE + int O_ACCMODE = (O_RDONLY | O_WRONLY | O_RDWR); +#endif + /* * Mask to extract the read/write flags */ rb_define_const(mFcntl, "O_ACCMODE", INT2FIX(O_ACCMODE)); -#else - /* Document-const: O_ACCMODE - * - * Mask to extract the read/write flags - */ - rb_define_const(mFcntl, "O_ACCMODE", INT2FIX(O_RDONLY | O_WRONLY | O_RDWR)); -#endif #ifdef F_DUP2FD - /* Document-const: F_DUP2FD - * + /* * It is a FreeBSD specific constant and equivalent * to dup2 call. */ rb_define_const(mFcntl, "F_DUP2FD", INT2NUM(F_DUP2FD)); #endif #ifdef F_DUP2FD_CLOEXEC - /* Document-const: F_DUP2FD_CLOEXEC - * + /* * It is a FreeBSD specific constant and acts * similarly as F_DUP2FD but set the FD_CLOEXEC * flag in addition. diff --git a/ext/fcntl/fcntl.gemspec b/ext/fcntl/fcntl.gemspec index 54aadb4b81a789..613a90d1ae551e 100644 --- a/ext/fcntl/fcntl.gemspec +++ b/ext/fcntl/fcntl.gemspec @@ -23,9 +23,10 @@ Gem::Specification.new do |spec| spec.licenses = ["Ruby", "BSD-2-Clause"] spec.files = ["ext/fcntl/extconf.rb", "ext/fcntl/fcntl.c"] + spec.extra_rdoc_files = [".document", ".rdoc_options", "BSDL", "COPYING", "README.md"] spec.bindir = "exe" spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } spec.require_paths = ["lib"] spec.extensions = "ext/fcntl/extconf.rb" - spec.required_ruby_version = ">= 2.3.0" + spec.required_ruby_version = ">= 2.5.0" end diff --git a/ext/fiddle/closure.c b/ext/fiddle/closure.c deleted file mode 100644 index 3772dfda353b8f..00000000000000 --- a/ext/fiddle/closure.c +++ /dev/null @@ -1,436 +0,0 @@ -#include -#include - -int ruby_thread_has_gvl_p(void); /* from internal.h */ - -VALUE cFiddleClosure; - -typedef struct { - void * code; - ffi_closure *pcl; - ffi_cif cif; - int argc; - ffi_type **argv; -} fiddle_closure; - -#if defined(__OpenBSD__) -# define USE_FFI_CLOSURE_ALLOC 0 -#endif - -#if defined(USE_FFI_CLOSURE_ALLOC) -#elif !defined(HAVE_FFI_CLOSURE_ALLOC) -# define USE_FFI_CLOSURE_ALLOC 0 -#else -# define USE_FFI_CLOSURE_ALLOC 1 -#endif - -static void -dealloc(void * ptr) -{ - fiddle_closure * cls = (fiddle_closure *)ptr; -#if USE_FFI_CLOSURE_ALLOC - ffi_closure_free(cls->pcl); -#else - munmap(cls->pcl, sizeof(*cls->pcl)); -#endif - if (cls->argv) xfree(cls->argv); - xfree(cls); -} - -static size_t -closure_memsize(const void * ptr) -{ - fiddle_closure * cls = (fiddle_closure *)ptr; - size_t size = 0; - - size += sizeof(*cls); -#if !defined(FFI_NO_RAW_API) || !FFI_NO_RAW_API - size += ffi_raw_size(&cls->cif); -#endif - size += sizeof(*cls->argv); - size += sizeof(ffi_closure); - - return size; -} - -const rb_data_type_t closure_data_type = { - .wrap_struct_name = "fiddle/closure", - .function = { - .dmark = 0, - .dfree = dealloc, - .dsize = closure_memsize - }, - .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED, -}; - -struct callback_args { - ffi_cif *cif; - void *resp; - void **args; - void *ctx; -}; - -static void * -with_gvl_callback(void *ptr) -{ - struct callback_args *x = ptr; - - VALUE self = (VALUE)x->ctx; - VALUE rbargs = rb_iv_get(self, "@args"); - VALUE ctype = rb_iv_get(self, "@ctype"); - int argc = RARRAY_LENINT(rbargs); - VALUE params = rb_ary_tmp_new(argc); - VALUE ret; - VALUE cPointer; - int i, type; - - cPointer = rb_const_get(mFiddle, rb_intern("Pointer")); - - for (i = 0; i < argc; i++) { - type = NUM2INT(RARRAY_AREF(rbargs, i)); - switch (type) { - case TYPE_VOID: - argc = 0; - break; - case TYPE_INT: - rb_ary_push(params, INT2NUM(*(int *)x->args[i])); - break; - case TYPE_UINT: - rb_ary_push(params, UINT2NUM(*(unsigned int *)x->args[i])); - break; - case TYPE_VOIDP: - rb_ary_push(params, - rb_funcall(cPointer, rb_intern("[]"), 1, - PTR2NUM(*(void **)x->args[i]))); - break; - case TYPE_LONG: - rb_ary_push(params, LONG2NUM(*(long *)x->args[i])); - break; - case TYPE_ULONG: - rb_ary_push(params, ULONG2NUM(*(unsigned long *)x->args[i])); - break; - case TYPE_CHAR: - rb_ary_push(params, INT2NUM(*(signed char *)x->args[i])); - break; - case TYPE_UCHAR: - rb_ary_push(params, UINT2NUM(*(unsigned char *)x->args[i])); - break; - case TYPE_SHORT: - rb_ary_push(params, INT2NUM(*(signed short *)x->args[i])); - break; - case TYPE_USHORT: - rb_ary_push(params, UINT2NUM(*(unsigned short *)x->args[i])); - break; - case TYPE_DOUBLE: - rb_ary_push(params, rb_float_new(*(double *)x->args[i])); - break; - case TYPE_FLOAT: - rb_ary_push(params, rb_float_new(*(float *)x->args[i])); - break; -#if HAVE_LONG_LONG - case TYPE_LONG_LONG: - rb_ary_push(params, LL2NUM(*(LONG_LONG *)x->args[i])); - break; - case TYPE_ULONG_LONG: - rb_ary_push(params, ULL2NUM(*(unsigned LONG_LONG *)x->args[i])); - break; -#endif - case TYPE_CONST_STRING: - rb_ary_push(params, - rb_str_new_cstr(*((const char **)(x->args[i])))); - break; - default: - rb_raise(rb_eRuntimeError, "closure args: %d", type); - } - } - - ret = rb_funcall2(self, rb_intern("call"), argc, RARRAY_CONST_PTR(params)); - RB_GC_GUARD(params); - - type = NUM2INT(ctype); - switch (type) { - case TYPE_VOID: - break; - case TYPE_LONG: - *(long *)x->resp = NUM2LONG(ret); - break; - case TYPE_ULONG: - *(unsigned long *)x->resp = NUM2ULONG(ret); - break; - case TYPE_CHAR: - case TYPE_SHORT: - case TYPE_INT: - *(ffi_sarg *)x->resp = NUM2INT(ret); - break; - case TYPE_UCHAR: - case TYPE_USHORT: - case TYPE_UINT: - *(ffi_arg *)x->resp = NUM2UINT(ret); - break; - case TYPE_VOIDP: - *(void **)x->resp = NUM2PTR(ret); - break; - case TYPE_DOUBLE: - *(double *)x->resp = NUM2DBL(ret); - break; - case TYPE_FLOAT: - *(float *)x->resp = (float)NUM2DBL(ret); - break; -#if HAVE_LONG_LONG - case TYPE_LONG_LONG: - *(LONG_LONG *)x->resp = NUM2LL(ret); - break; - case TYPE_ULONG_LONG: - *(unsigned LONG_LONG *)x->resp = NUM2ULL(ret); - break; -#endif - case TYPE_CONST_STRING: - /* Dangerous. Callback must keep reference of the String. */ - *((const char **)(x->resp)) = StringValueCStr(ret); - break; - default: - rb_raise(rb_eRuntimeError, "closure retval: %d", type); - } - return 0; -} - -static void -callback(ffi_cif *cif, void *resp, void **args, void *ctx) -{ - struct callback_args x; - - x.cif = cif; - x.resp = resp; - x.args = args; - x.ctx = ctx; - - if (ruby_thread_has_gvl_p()) { - (void)with_gvl_callback(&x); - } else { - (void)rb_thread_call_with_gvl(with_gvl_callback, &x); - } -} - -static VALUE -allocate(VALUE klass) -{ - fiddle_closure * closure; - - VALUE i = TypedData_Make_Struct(klass, fiddle_closure, - &closure_data_type, closure); - -#if USE_FFI_CLOSURE_ALLOC - closure->pcl = ffi_closure_alloc(sizeof(ffi_closure), &closure->code); -#else - closure->pcl = mmap(NULL, sizeof(ffi_closure), PROT_READ | PROT_WRITE, - MAP_ANON | MAP_PRIVATE, -1, 0); -#endif - - return i; -} - -static fiddle_closure * -get_raw(VALUE self) -{ - fiddle_closure *closure; - TypedData_Get_Struct(self, fiddle_closure, &closure_data_type, closure); - if (!closure) { - rb_raise(rb_eArgError, "already freed: %+"PRIsVALUE, self); - } - return closure; -} - -typedef struct { - VALUE self; - int argc; - VALUE *argv; -} initialize_data; - -static VALUE -initialize_body(VALUE user_data) -{ - initialize_data *data = (initialize_data *)user_data; - VALUE ret; - VALUE args; - VALUE normalized_args; - VALUE abi; - fiddle_closure * cl; - ffi_cif * cif; - ffi_closure *pcl; - ffi_status result; - int i, argc; - - if (2 == rb_scan_args(data->argc, data->argv, "21", &ret, &args, &abi)) - abi = INT2NUM(FFI_DEFAULT_ABI); - - Check_Type(args, T_ARRAY); - - argc = RARRAY_LENINT(args); - - TypedData_Get_Struct(data->self, fiddle_closure, &closure_data_type, cl); - - cl->argv = (ffi_type **)xcalloc(argc + 1, sizeof(ffi_type *)); - - normalized_args = rb_ary_new_capa(argc); - for (i = 0; i < argc; i++) { - VALUE arg = rb_fiddle_type_ensure(RARRAY_AREF(args, i)); - rb_ary_push(normalized_args, arg); - cl->argv[i] = rb_fiddle_int_to_ffi_type(NUM2INT(arg)); - } - cl->argv[argc] = NULL; - - ret = rb_fiddle_type_ensure(ret); - rb_iv_set(data->self, "@ctype", ret); - rb_iv_set(data->self, "@args", normalized_args); - - cif = &cl->cif; - pcl = cl->pcl; - - result = ffi_prep_cif(cif, - NUM2INT(abi), - argc, - rb_fiddle_int_to_ffi_type(NUM2INT(ret)), - cl->argv); - - if (FFI_OK != result) { - rb_raise(rb_eRuntimeError, "error prepping CIF %d", result); - } - -#if USE_FFI_CLOSURE_ALLOC - result = ffi_prep_closure_loc(pcl, cif, callback, - (void *)(data->self), cl->code); -#else - result = ffi_prep_closure(pcl, cif, callback, (void *)(data->self)); - cl->code = (void *)pcl; - i = mprotect(pcl, sizeof(*pcl), PROT_READ | PROT_EXEC); - if (i) { - rb_sys_fail("mprotect"); - } -#endif - - if (FFI_OK != result) { - rb_raise(rb_eRuntimeError, "error prepping closure %d", result); - } - - return data->self; -} - -static VALUE -initialize_rescue(VALUE user_data, VALUE exception) -{ - initialize_data *data = (initialize_data *)user_data; - dealloc(RTYPEDDATA_DATA(data->self)); - RTYPEDDATA_DATA(data->self) = NULL; - rb_exc_raise(exception); - return data->self; -} - -static VALUE -initialize(int argc, VALUE *argv, VALUE self) -{ - initialize_data data; - data.self = self; - data.argc = argc; - data.argv = argv; - return rb_rescue(initialize_body, (VALUE)&data, - initialize_rescue, (VALUE)&data); -} - -static VALUE -to_i(VALUE self) -{ - fiddle_closure *closure = get_raw(self); - return PTR2NUM(closure->code); -} - -static VALUE -closure_free(VALUE self) -{ - fiddle_closure *closure; - TypedData_Get_Struct(self, fiddle_closure, &closure_data_type, closure); - if (closure) { - dealloc(closure); - RTYPEDDATA_DATA(self) = NULL; - } - return RUBY_Qnil; -} - -static VALUE -closure_freed_p(VALUE self) -{ - fiddle_closure *closure; - TypedData_Get_Struct(self, fiddle_closure, &closure_data_type, closure); - return closure ? RUBY_Qfalse : RUBY_Qtrue; -} - -void -Init_fiddle_closure(void) -{ -#if 0 - mFiddle = rb_define_module("Fiddle"); /* let rdoc know about mFiddle */ -#endif - - /* - * Document-class: Fiddle::Closure - * - * == Description - * - * An FFI closure wrapper, for handling callbacks. - * - * == Example - * - * closure = Class.new(Fiddle::Closure) { - * def call - * 10 - * end - * }.new(Fiddle::TYPE_INT, []) - * #=> #<#:0x0000000150d240> - * func = Fiddle::Function.new(closure, [], Fiddle::TYPE_INT) - * #=> # - * func.call - * #=> 10 - */ - cFiddleClosure = rb_define_class_under(mFiddle, "Closure", rb_cObject); - - rb_define_alloc_func(cFiddleClosure, allocate); - - /* - * Document-method: new - * - * call-seq: new(ret, args, abi = Fiddle::DEFAULT) - * - * Construct a new Closure object. - * - * * +ret+ is the C type to be returned - * * +args+ is an Array of arguments, passed to the callback function - * * +abi+ is the abi of the closure - * - * If there is an error in preparing the ffi_cif or ffi_prep_closure, - * then a RuntimeError will be raised. - */ - rb_define_method(cFiddleClosure, "initialize", initialize, -1); - - /* - * Document-method: to_i - * - * Returns the memory address for this closure. - */ - rb_define_method(cFiddleClosure, "to_i", to_i, 0); - - /* - * Document-method: free - * - * Free this closure explicitly. You can't use this closure anymore. - * - * If this closure is already freed, this does nothing. - */ - rb_define_method(cFiddleClosure, "free", closure_free, 0); - - /* - * Document-method: freed? - * - * Whether this closure was freed explicitly. - */ - rb_define_method(cFiddleClosure, "freed?", closure_freed_p, 0); -} -/* vim: set noet sw=4 sts=4 */ diff --git a/ext/fiddle/closure.h b/ext/fiddle/closure.h deleted file mode 100644 index d0a8be6180746e..00000000000000 --- a/ext/fiddle/closure.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef FIDDLE_CLOSURE_H -#define FIDDLE_CLOSURE_H - -#include - -void Init_fiddle_closure(void); - -#endif diff --git a/ext/fiddle/conversions.c b/ext/fiddle/conversions.c deleted file mode 100644 index 66058d5d12a550..00000000000000 --- a/ext/fiddle/conversions.c +++ /dev/null @@ -1,360 +0,0 @@ -#include - -#include - -VALUE -rb_fiddle_type_bool(void) -{ - if (sizeof(bool) == sizeof(char)) { - return INT2NUM(TYPE_UCHAR); - } else if (sizeof(bool) == sizeof(short)) { - return INT2NUM(TYPE_USHORT); - } else if (sizeof(bool) == sizeof(int)) { - return INT2NUM(TYPE_UINT); - } else if (sizeof(bool) == sizeof(long)) { - return INT2NUM(TYPE_ULONG); - } else { - rb_raise(rb_eNotImpError, - "bool isn't supported: %u", - (unsigned int)sizeof(bool)); - return RUBY_Qnil; - } -} - -VALUE -rb_fiddle_type_ensure(VALUE type) -{ - VALUE original_type = type; - - if (!RB_SYMBOL_P(type)) { - VALUE type_string = rb_check_string_type(type); - if (!NIL_P(type_string)) { - type = rb_to_symbol(type_string); - } - } - - if (RB_SYMBOL_P(type)) { - ID type_id = rb_sym2id(type); - ID void_id; - ID voidp_id; - ID char_id; - ID short_id; - ID int_id; - ID long_id; -#ifdef TYPE_LONG_LONG - ID long_long_id; -#endif -#ifdef TYPE_INT8_T - ID int8_t_id; -#endif -#ifdef TYPE_INT16_T - ID int16_t_id; -#endif -#ifdef TYPE_INT32_T - ID int32_t_id; -#endif -#ifdef TYPE_INT64_T - ID int64_t_id; -#endif - ID float_id; - ID double_id; - ID variadic_id; - ID const_string_id; - ID size_t_id; - ID ssize_t_id; - ID ptrdiff_t_id; - ID intptr_t_id; - ID uintptr_t_id; - ID bool_id; - RUBY_CONST_ID(void_id, "void"); - RUBY_CONST_ID(voidp_id, "voidp"); - RUBY_CONST_ID(char_id, "char"); - RUBY_CONST_ID(short_id, "short"); - RUBY_CONST_ID(int_id, "int"); - RUBY_CONST_ID(long_id, "long"); -#ifdef TYPE_LONG_LONG - RUBY_CONST_ID(long_long_id, "long_long"); -#endif -#ifdef TYPE_INT8_T - RUBY_CONST_ID(int8_t_id, "int8_t"); -#endif -#ifdef TYPE_INT16_T - RUBY_CONST_ID(int16_t_id, "int16_t"); -#endif -#ifdef TYPE_INT32_T - RUBY_CONST_ID(int32_t_id, "int32_t"); -#endif -#ifdef TYPE_INT64_T - RUBY_CONST_ID(int64_t_id, "int64_t"); -#endif - RUBY_CONST_ID(float_id, "float"); - RUBY_CONST_ID(double_id, "double"); - RUBY_CONST_ID(variadic_id, "variadic"); - RUBY_CONST_ID(const_string_id, "const_string"); - RUBY_CONST_ID(size_t_id, "size_t"); - RUBY_CONST_ID(ssize_t_id, "ssize_t"); - RUBY_CONST_ID(ptrdiff_t_id, "ptrdiff_t"); - RUBY_CONST_ID(intptr_t_id, "intptr_t"); - RUBY_CONST_ID(uintptr_t_id, "uintptr_t"); - RUBY_CONST_ID(bool_id, "bool"); - if (type_id == void_id) { - return INT2NUM(TYPE_VOID); - } - else if (type_id == voidp_id) { - return INT2NUM(TYPE_VOIDP); - } - else if (type_id == char_id) { - return INT2NUM(TYPE_CHAR); - } - else if (type_id == short_id) { - return INT2NUM(TYPE_SHORT); - } - else if (type_id == int_id) { - return INT2NUM(TYPE_INT); - } - else if (type_id == long_id) { - return INT2NUM(TYPE_LONG); - } -#ifdef TYPE_LONG_LONG - else if (type_id == long_long_id) { - return INT2NUM(TYPE_LONG_LONG); - } -#endif -#ifdef TYPE_INT8_T - else if (type_id == int8_t_id) { - return INT2NUM(TYPE_INT8_T); - } -#endif -#ifdef TYPE_INT16_T - else if (type_id == int16_t_id) { - return INT2NUM(TYPE_INT16_T); - } -#endif -#ifdef TYPE_INT32_T - else if (type_id == int32_t_id) { - return INT2NUM(TYPE_INT32_T); - } -#endif -#ifdef TYPE_INT64_T - else if (type_id == int64_t_id) { - return INT2NUM(TYPE_INT64_T); - } -#endif - else if (type_id == float_id) { - return INT2NUM(TYPE_FLOAT); - } - else if (type_id == double_id) { - return INT2NUM(TYPE_DOUBLE); - } - else if (type_id == variadic_id) { - return INT2NUM(TYPE_VARIADIC); - } - else if (type_id == const_string_id) { - return INT2NUM(TYPE_CONST_STRING); - } - else if (type_id == size_t_id) { - return INT2NUM(TYPE_SIZE_T); - } - else if (type_id == ssize_t_id) { - return INT2NUM(TYPE_SSIZE_T); - } - else if (type_id == ptrdiff_t_id) { - return INT2NUM(TYPE_PTRDIFF_T); - } - else if (type_id == intptr_t_id) { - return INT2NUM(TYPE_INTPTR_T); - } - else if (type_id == uintptr_t_id) { - return INT2NUM(TYPE_UINTPTR_T); - } - else if (type_id == bool_id) { - return rb_fiddle_type_bool(); - } - else { - type = original_type; - } - } - - return rb_to_int(type); -} - -ffi_type * -rb_fiddle_int_to_ffi_type(int type) -{ - int signed_p = 1; - - if (type < 0) { - type = -1 * type; - signed_p = 0; - } - -#define rb_ffi_type_of(t) (signed_p ? &ffi_type_s##t : &ffi_type_u##t) - - switch (type) { - case TYPE_VOID: - return &ffi_type_void; - case TYPE_VOIDP: - return &ffi_type_pointer; - case TYPE_CHAR: - return rb_ffi_type_of(char); - case TYPE_SHORT: - return rb_ffi_type_of(short); - case TYPE_INT: - return rb_ffi_type_of(int); - case TYPE_LONG: - return rb_ffi_type_of(long); -#if HAVE_LONG_LONG - case TYPE_LONG_LONG: - return rb_ffi_type_of(long_long); -#endif - case TYPE_FLOAT: - return &ffi_type_float; - case TYPE_DOUBLE: - return &ffi_type_double; - case TYPE_CONST_STRING: - return &ffi_type_pointer; - default: - rb_raise(rb_eRuntimeError, "unknown type %d", type); - } - return &ffi_type_pointer; -} - -ffi_type * -int_to_ffi_type(int type) -{ - return rb_fiddle_int_to_ffi_type(type); -} - -void -rb_fiddle_value_to_generic(int type, VALUE *src, fiddle_generic *dst) -{ - switch (type) { - case TYPE_VOID: - break; - case TYPE_VOIDP: - dst->pointer = NUM2PTR(rb_Integer(*src)); - break; - case TYPE_CHAR: - if (RB_TYPE_P(*src, RUBY_T_STRING) && RSTRING_LEN(*src) == 1) { - dst->schar = RSTRING_PTR(*src)[0]; - } else { - dst->schar = (signed char)NUM2INT(*src); - } - break; - case TYPE_UCHAR: - dst->uchar = (unsigned char)NUM2UINT(*src); - break; - case TYPE_SHORT: - dst->sshort = (unsigned short)NUM2INT(*src); - break; - case TYPE_USHORT: - dst->sshort = (signed short)NUM2UINT(*src); - break; - case TYPE_INT: - dst->sint = NUM2INT(*src); - break; - case TYPE_UINT: - dst->uint = NUM2UINT(*src); - break; - case TYPE_LONG: - dst->slong = NUM2LONG(*src); - break; - case TYPE_ULONG: - dst->ulong = NUM2ULONG(*src); - break; -#if HAVE_LONG_LONG - case TYPE_LONG_LONG: - dst->slong_long = NUM2LL(*src); - break; - case TYPE_ULONG_LONG: - dst->ulong_long = NUM2ULL(*src); - break; -#endif - case TYPE_FLOAT: - dst->ffloat = (float)NUM2DBL(*src); - break; - case TYPE_DOUBLE: - dst->ddouble = NUM2DBL(*src); - break; - case TYPE_CONST_STRING: - if (NIL_P(*src)) { - dst->pointer = NULL; - } - else { - dst->pointer = rb_string_value_cstr(src); - } - break; - default: - rb_raise(rb_eRuntimeError, "unknown type %d", type); - } -} - -void -value_to_generic(int type, VALUE src, fiddle_generic *dst) -{ - /* src isn't safe from GC when type is TYPE_CONST_STRING and src - * isn't String. */ - rb_fiddle_value_to_generic(type, &src, dst); -} - -VALUE -rb_fiddle_generic_to_value(VALUE rettype, fiddle_generic retval) -{ - int type = NUM2INT(rettype); - VALUE cPointer; - - cPointer = rb_const_get(mFiddle, rb_intern("Pointer")); - - switch (type) { - case TYPE_VOID: - return Qnil; - case TYPE_VOIDP: - return rb_funcall(cPointer, rb_intern("[]"), 1, - PTR2NUM((void *)retval.pointer)); - case TYPE_CHAR: - return INT2NUM((signed char)retval.fffi_sarg); - case TYPE_UCHAR: - return INT2NUM((unsigned char)retval.fffi_arg); - case TYPE_SHORT: - return INT2NUM((signed short)retval.fffi_sarg); - case TYPE_USHORT: - return INT2NUM((unsigned short)retval.fffi_arg); - case TYPE_INT: - return INT2NUM((signed int)retval.fffi_sarg); - case TYPE_UINT: - return UINT2NUM((unsigned int)retval.fffi_arg); - case TYPE_LONG: - return LONG2NUM(retval.slong); - case TYPE_ULONG: - return ULONG2NUM(retval.ulong); -#if HAVE_LONG_LONG - case TYPE_LONG_LONG: - return LL2NUM(retval.slong_long); - case TYPE_ULONG_LONG: - return ULL2NUM(retval.ulong_long); -#endif - case TYPE_FLOAT: - return rb_float_new(retval.ffloat); - case TYPE_DOUBLE: - return rb_float_new(retval.ddouble); - case TYPE_CONST_STRING: - if (retval.pointer) { - return rb_str_new_cstr(retval.pointer); - } - else { - return Qnil; - } - default: - rb_raise(rb_eRuntimeError, "unknown type %d", type); - } - - UNREACHABLE; -} - -VALUE -generic_to_value(VALUE rettype, fiddle_generic retval) -{ - return rb_fiddle_generic_to_value(rettype, retval); -} - -/* vim: set noet sw=4 sts=4 */ diff --git a/ext/fiddle/conversions.h b/ext/fiddle/conversions.h deleted file mode 100644 index 5ea569e3ff9851..00000000000000 --- a/ext/fiddle/conversions.h +++ /dev/null @@ -1,54 +0,0 @@ -#ifndef FIDDLE_CONVERSIONS_H -#define FIDDLE_CONVERSIONS_H - -#include - -typedef union -{ - ffi_arg fffi_arg; /* rvalue smaller than unsigned long */ - ffi_sarg fffi_sarg; /* rvalue smaller than signed long */ - unsigned char uchar; /* ffi_type_uchar */ - signed char schar; /* ffi_type_schar */ - unsigned short ushort; /* ffi_type_sshort */ - signed short sshort; /* ffi_type_ushort */ - unsigned int uint; /* ffi_type_uint */ - signed int sint; /* ffi_type_sint */ - unsigned long ulong; /* ffi_type_ulong */ - signed long slong; /* ffi_type_slong */ - float ffloat; /* ffi_type_float */ - double ddouble; /* ffi_type_double */ -#if HAVE_LONG_LONG - unsigned LONG_LONG ulong_long; /* ffi_type_ulong_long */ - signed LONG_LONG slong_long; /* ffi_type_ulong_long */ -#endif - void * pointer; /* ffi_type_pointer */ -} fiddle_generic; - -VALUE rb_fiddle_type_bool(void); -VALUE rb_fiddle_type_ensure(VALUE type); -ffi_type * rb_fiddle_int_to_ffi_type(int type); -void rb_fiddle_value_to_generic(int type, VALUE *src, fiddle_generic *dst); -VALUE rb_fiddle_generic_to_value(VALUE rettype, fiddle_generic retval); - -/* Deprecated. Use rb_fiddle_*() version. */ -ffi_type * int_to_ffi_type(int type); -void value_to_generic(int type, VALUE src, fiddle_generic *dst); -VALUE generic_to_value(VALUE rettype, fiddle_generic retval); - -#define VALUE2GENERIC(_type, _src, _dst) \ - rb_fiddle_value_to_generic((_type), &(_src), (_dst)) -#define INT2FFI_TYPE(_type) \ - rb_fiddle_int_to_ffi_type(_type) -#define GENERIC2VALUE(_type, _retval) \ - rb_fiddle_generic_to_value((_type), (_retval)) - -#if SIZEOF_VOIDP == SIZEOF_LONG -# define PTR2NUM(x) (LONG2NUM((long)(x))) -# define NUM2PTR(x) ((void*)(NUM2ULONG(x))) -#else -/* # error --->> Ruby/DL2 requires sizeof(void*) == sizeof(long) to be compiled. <<--- */ -# define PTR2NUM(x) (LL2NUM((LONG_LONG)(x))) -# define NUM2PTR(x) ((void*)(NUM2ULL(x))) -#endif - -#endif diff --git a/ext/fiddle/depend b/ext/fiddle/depend deleted file mode 100644 index 561785275eb577..00000000000000 --- a/ext/fiddle/depend +++ /dev/null @@ -1,1388 +0,0 @@ -PWD = - -CONFIGURE_LIBFFI = \ - $(LIBFFI_CONFIGURE) --disable-shared \ - --host=$(LIBFFI_ARCH) --enable-builddir=$(arch) \ - CC="$(CC)" CFLAGS="$(LIBFFI_CFLAGS)" \ - LD="$(LD)" LDFLAGS="$(LIBFFI_LDFLAGS)" - -$(STATIC_LIB) $(RUBYARCHDIR)/$(DLLIB) $(DLLIB): $(LIBFFI_A) - -$(OBJS): $(FFI_H) - -.PHONY: .FORCE hdr - -.FORCE: - -hdr: $(FFI_H) - -configure-libffi build-libffi: .FORCE -configure-libffi \ -$(LIBFFI_DIR)/include/ffi.h \ -$(LIBFFI_DIR)/include/ffitarget.h \ -$(LIBFFI_DIR)/fficonfig.h \ -$(LIBFFI_DIR)/Makefile: - $(Q) $(MAKEDIRS) $(LIBFFI_DIR) - $(Q) $(CONFIGURE_LIBFFI) - -build-libffi $(LIBFFI_A): - $(Q) $(SUBMAKE_PRE) $(MAKE) $(SUBMAKE_ARG) - -clean-none: -clean-libffi: - $(Q) $(SUBMAKE_PRE) $(MAKE) $(SUBMAKE_ARG) clean - -distclean-none: -distclean-libffi: - $(Q) $(SUBMAKE_PRE) $(MAKE) $(SUBMAKE_ARG) distclean - $(Q) $(RM) $(LIBFFI_DIR)/local.exp - $(Q) $(RUBY) -rfileutils -e "FileUtils.rmdir(Dir.glob(ARGV[0]+'/**/{,.*/}'), :parents=>true)" $(LIBFFI_DIR) - -realclean-none: -realclean-libffi: - $(Q) $(RMALL) $(LIBFFI_DIR) - -.PHONY: clean-libffi distclean-libffi realclean-libffi -.PHONY: clean-none distclean-none realclean-none - -clean: clean-$(LIBFFI_CLEAN) -distclean: distclean-$(LIBFFI_CLEAN) -realclean: realclean-$(LIBFFI_CLEAN) - -.PHONY: configure configure-libffi - -# AUTOGENERATED DEPENDENCIES START -closure.o: $(RUBY_EXTCONF_H) -closure.o: $(arch_hdrdir)/ruby/config.h -closure.o: $(hdrdir)/ruby.h -closure.o: $(hdrdir)/ruby/assert.h -closure.o: $(hdrdir)/ruby/backward.h -closure.o: $(hdrdir)/ruby/backward/2/assume.h -closure.o: $(hdrdir)/ruby/backward/2/attributes.h -closure.o: $(hdrdir)/ruby/backward/2/bool.h -closure.o: $(hdrdir)/ruby/backward/2/inttypes.h -closure.o: $(hdrdir)/ruby/backward/2/limits.h -closure.o: $(hdrdir)/ruby/backward/2/long_long.h -closure.o: $(hdrdir)/ruby/backward/2/stdalign.h -closure.o: $(hdrdir)/ruby/backward/2/stdarg.h -closure.o: $(hdrdir)/ruby/defines.h -closure.o: $(hdrdir)/ruby/intern.h -closure.o: $(hdrdir)/ruby/internal/abi.h -closure.o: $(hdrdir)/ruby/internal/anyargs.h -closure.o: $(hdrdir)/ruby/internal/arithmetic.h -closure.o: $(hdrdir)/ruby/internal/arithmetic/char.h -closure.o: $(hdrdir)/ruby/internal/arithmetic/double.h -closure.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h -closure.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h -closure.o: $(hdrdir)/ruby/internal/arithmetic/int.h -closure.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h -closure.o: $(hdrdir)/ruby/internal/arithmetic/long.h -closure.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h -closure.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h -closure.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h -closure.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h -closure.o: $(hdrdir)/ruby/internal/arithmetic/short.h -closure.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h -closure.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h -closure.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h -closure.o: $(hdrdir)/ruby/internal/assume.h -closure.o: $(hdrdir)/ruby/internal/attr/alloc_size.h -closure.o: $(hdrdir)/ruby/internal/attr/artificial.h -closure.o: $(hdrdir)/ruby/internal/attr/cold.h -closure.o: $(hdrdir)/ruby/internal/attr/const.h -closure.o: $(hdrdir)/ruby/internal/attr/constexpr.h -closure.o: $(hdrdir)/ruby/internal/attr/deprecated.h -closure.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h -closure.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h -closure.o: $(hdrdir)/ruby/internal/attr/error.h -closure.o: $(hdrdir)/ruby/internal/attr/flag_enum.h -closure.o: $(hdrdir)/ruby/internal/attr/forceinline.h -closure.o: $(hdrdir)/ruby/internal/attr/format.h -closure.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h -closure.o: $(hdrdir)/ruby/internal/attr/noalias.h -closure.o: $(hdrdir)/ruby/internal/attr/nodiscard.h -closure.o: $(hdrdir)/ruby/internal/attr/noexcept.h -closure.o: $(hdrdir)/ruby/internal/attr/noinline.h -closure.o: $(hdrdir)/ruby/internal/attr/nonnull.h -closure.o: $(hdrdir)/ruby/internal/attr/noreturn.h -closure.o: $(hdrdir)/ruby/internal/attr/packed_struct.h -closure.o: $(hdrdir)/ruby/internal/attr/pure.h -closure.o: $(hdrdir)/ruby/internal/attr/restrict.h -closure.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h -closure.o: $(hdrdir)/ruby/internal/attr/warning.h -closure.o: $(hdrdir)/ruby/internal/attr/weakref.h -closure.o: $(hdrdir)/ruby/internal/cast.h -closure.o: $(hdrdir)/ruby/internal/compiler_is.h -closure.o: $(hdrdir)/ruby/internal/compiler_is/apple.h -closure.o: $(hdrdir)/ruby/internal/compiler_is/clang.h -closure.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h -closure.o: $(hdrdir)/ruby/internal/compiler_is/intel.h -closure.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h -closure.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h -closure.o: $(hdrdir)/ruby/internal/compiler_since.h -closure.o: $(hdrdir)/ruby/internal/config.h -closure.o: $(hdrdir)/ruby/internal/constant_p.h -closure.o: $(hdrdir)/ruby/internal/core.h -closure.o: $(hdrdir)/ruby/internal/core/rarray.h -closure.o: $(hdrdir)/ruby/internal/core/rbasic.h -closure.o: $(hdrdir)/ruby/internal/core/rbignum.h -closure.o: $(hdrdir)/ruby/internal/core/rclass.h -closure.o: $(hdrdir)/ruby/internal/core/rdata.h -closure.o: $(hdrdir)/ruby/internal/core/rfile.h -closure.o: $(hdrdir)/ruby/internal/core/rhash.h -closure.o: $(hdrdir)/ruby/internal/core/robject.h -closure.o: $(hdrdir)/ruby/internal/core/rregexp.h -closure.o: $(hdrdir)/ruby/internal/core/rstring.h -closure.o: $(hdrdir)/ruby/internal/core/rstruct.h -closure.o: $(hdrdir)/ruby/internal/core/rtypeddata.h -closure.o: $(hdrdir)/ruby/internal/ctype.h -closure.o: $(hdrdir)/ruby/internal/dllexport.h -closure.o: $(hdrdir)/ruby/internal/dosish.h -closure.o: $(hdrdir)/ruby/internal/error.h -closure.o: $(hdrdir)/ruby/internal/eval.h -closure.o: $(hdrdir)/ruby/internal/event.h -closure.o: $(hdrdir)/ruby/internal/fl_type.h -closure.o: $(hdrdir)/ruby/internal/gc.h -closure.o: $(hdrdir)/ruby/internal/glob.h -closure.o: $(hdrdir)/ruby/internal/globals.h -closure.o: $(hdrdir)/ruby/internal/has/attribute.h -closure.o: $(hdrdir)/ruby/internal/has/builtin.h -closure.o: $(hdrdir)/ruby/internal/has/c_attribute.h -closure.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h -closure.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h -closure.o: $(hdrdir)/ruby/internal/has/extension.h -closure.o: $(hdrdir)/ruby/internal/has/feature.h -closure.o: $(hdrdir)/ruby/internal/has/warning.h -closure.o: $(hdrdir)/ruby/internal/intern/array.h -closure.o: $(hdrdir)/ruby/internal/intern/bignum.h -closure.o: $(hdrdir)/ruby/internal/intern/class.h -closure.o: $(hdrdir)/ruby/internal/intern/compar.h -closure.o: $(hdrdir)/ruby/internal/intern/complex.h -closure.o: $(hdrdir)/ruby/internal/intern/cont.h -closure.o: $(hdrdir)/ruby/internal/intern/dir.h -closure.o: $(hdrdir)/ruby/internal/intern/enum.h -closure.o: $(hdrdir)/ruby/internal/intern/enumerator.h -closure.o: $(hdrdir)/ruby/internal/intern/error.h -closure.o: $(hdrdir)/ruby/internal/intern/eval.h -closure.o: $(hdrdir)/ruby/internal/intern/file.h -closure.o: $(hdrdir)/ruby/internal/intern/hash.h -closure.o: $(hdrdir)/ruby/internal/intern/io.h -closure.o: $(hdrdir)/ruby/internal/intern/load.h -closure.o: $(hdrdir)/ruby/internal/intern/marshal.h -closure.o: $(hdrdir)/ruby/internal/intern/numeric.h -closure.o: $(hdrdir)/ruby/internal/intern/object.h -closure.o: $(hdrdir)/ruby/internal/intern/parse.h -closure.o: $(hdrdir)/ruby/internal/intern/proc.h -closure.o: $(hdrdir)/ruby/internal/intern/process.h -closure.o: $(hdrdir)/ruby/internal/intern/random.h -closure.o: $(hdrdir)/ruby/internal/intern/range.h -closure.o: $(hdrdir)/ruby/internal/intern/rational.h -closure.o: $(hdrdir)/ruby/internal/intern/re.h -closure.o: $(hdrdir)/ruby/internal/intern/ruby.h -closure.o: $(hdrdir)/ruby/internal/intern/select.h -closure.o: $(hdrdir)/ruby/internal/intern/select/largesize.h -closure.o: $(hdrdir)/ruby/internal/intern/signal.h -closure.o: $(hdrdir)/ruby/internal/intern/sprintf.h -closure.o: $(hdrdir)/ruby/internal/intern/string.h -closure.o: $(hdrdir)/ruby/internal/intern/struct.h -closure.o: $(hdrdir)/ruby/internal/intern/thread.h -closure.o: $(hdrdir)/ruby/internal/intern/time.h -closure.o: $(hdrdir)/ruby/internal/intern/variable.h -closure.o: $(hdrdir)/ruby/internal/intern/vm.h -closure.o: $(hdrdir)/ruby/internal/interpreter.h -closure.o: $(hdrdir)/ruby/internal/iterator.h -closure.o: $(hdrdir)/ruby/internal/memory.h -closure.o: $(hdrdir)/ruby/internal/method.h -closure.o: $(hdrdir)/ruby/internal/module.h -closure.o: $(hdrdir)/ruby/internal/newobj.h -closure.o: $(hdrdir)/ruby/internal/scan_args.h -closure.o: $(hdrdir)/ruby/internal/special_consts.h -closure.o: $(hdrdir)/ruby/internal/static_assert.h -closure.o: $(hdrdir)/ruby/internal/stdalign.h -closure.o: $(hdrdir)/ruby/internal/stdbool.h -closure.o: $(hdrdir)/ruby/internal/symbol.h -closure.o: $(hdrdir)/ruby/internal/value.h -closure.o: $(hdrdir)/ruby/internal/value_type.h -closure.o: $(hdrdir)/ruby/internal/variable.h -closure.o: $(hdrdir)/ruby/internal/warning_push.h -closure.o: $(hdrdir)/ruby/internal/xmalloc.h -closure.o: $(hdrdir)/ruby/missing.h -closure.o: $(hdrdir)/ruby/ruby.h -closure.o: $(hdrdir)/ruby/st.h -closure.o: $(hdrdir)/ruby/subst.h -closure.o: $(hdrdir)/ruby/thread.h -closure.o: closure.c -closure.o: closure.h -closure.o: conversions.h -closure.o: fiddle.h -closure.o: function.h -conversions.o: $(RUBY_EXTCONF_H) -conversions.o: $(arch_hdrdir)/ruby/config.h -conversions.o: $(hdrdir)/ruby.h -conversions.o: $(hdrdir)/ruby/assert.h -conversions.o: $(hdrdir)/ruby/backward.h -conversions.o: $(hdrdir)/ruby/backward/2/assume.h -conversions.o: $(hdrdir)/ruby/backward/2/attributes.h -conversions.o: $(hdrdir)/ruby/backward/2/bool.h -conversions.o: $(hdrdir)/ruby/backward/2/inttypes.h -conversions.o: $(hdrdir)/ruby/backward/2/limits.h -conversions.o: $(hdrdir)/ruby/backward/2/long_long.h -conversions.o: $(hdrdir)/ruby/backward/2/stdalign.h -conversions.o: $(hdrdir)/ruby/backward/2/stdarg.h -conversions.o: $(hdrdir)/ruby/defines.h -conversions.o: $(hdrdir)/ruby/intern.h -conversions.o: $(hdrdir)/ruby/internal/abi.h -conversions.o: $(hdrdir)/ruby/internal/anyargs.h -conversions.o: $(hdrdir)/ruby/internal/arithmetic.h -conversions.o: $(hdrdir)/ruby/internal/arithmetic/char.h -conversions.o: $(hdrdir)/ruby/internal/arithmetic/double.h -conversions.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h -conversions.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h -conversions.o: $(hdrdir)/ruby/internal/arithmetic/int.h -conversions.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h -conversions.o: $(hdrdir)/ruby/internal/arithmetic/long.h -conversions.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h -conversions.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h -conversions.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h -conversions.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h -conversions.o: $(hdrdir)/ruby/internal/arithmetic/short.h -conversions.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h -conversions.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h -conversions.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h -conversions.o: $(hdrdir)/ruby/internal/assume.h -conversions.o: $(hdrdir)/ruby/internal/attr/alloc_size.h -conversions.o: $(hdrdir)/ruby/internal/attr/artificial.h -conversions.o: $(hdrdir)/ruby/internal/attr/cold.h -conversions.o: $(hdrdir)/ruby/internal/attr/const.h -conversions.o: $(hdrdir)/ruby/internal/attr/constexpr.h -conversions.o: $(hdrdir)/ruby/internal/attr/deprecated.h -conversions.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h -conversions.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h -conversions.o: $(hdrdir)/ruby/internal/attr/error.h -conversions.o: $(hdrdir)/ruby/internal/attr/flag_enum.h -conversions.o: $(hdrdir)/ruby/internal/attr/forceinline.h -conversions.o: $(hdrdir)/ruby/internal/attr/format.h -conversions.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h -conversions.o: $(hdrdir)/ruby/internal/attr/noalias.h -conversions.o: $(hdrdir)/ruby/internal/attr/nodiscard.h -conversions.o: $(hdrdir)/ruby/internal/attr/noexcept.h -conversions.o: $(hdrdir)/ruby/internal/attr/noinline.h -conversions.o: $(hdrdir)/ruby/internal/attr/nonnull.h -conversions.o: $(hdrdir)/ruby/internal/attr/noreturn.h -conversions.o: $(hdrdir)/ruby/internal/attr/packed_struct.h -conversions.o: $(hdrdir)/ruby/internal/attr/pure.h -conversions.o: $(hdrdir)/ruby/internal/attr/restrict.h -conversions.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h -conversions.o: $(hdrdir)/ruby/internal/attr/warning.h -conversions.o: $(hdrdir)/ruby/internal/attr/weakref.h -conversions.o: $(hdrdir)/ruby/internal/cast.h -conversions.o: $(hdrdir)/ruby/internal/compiler_is.h -conversions.o: $(hdrdir)/ruby/internal/compiler_is/apple.h -conversions.o: $(hdrdir)/ruby/internal/compiler_is/clang.h -conversions.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h -conversions.o: $(hdrdir)/ruby/internal/compiler_is/intel.h -conversions.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h -conversions.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h -conversions.o: $(hdrdir)/ruby/internal/compiler_since.h -conversions.o: $(hdrdir)/ruby/internal/config.h -conversions.o: $(hdrdir)/ruby/internal/constant_p.h -conversions.o: $(hdrdir)/ruby/internal/core.h -conversions.o: $(hdrdir)/ruby/internal/core/rarray.h -conversions.o: $(hdrdir)/ruby/internal/core/rbasic.h -conversions.o: $(hdrdir)/ruby/internal/core/rbignum.h -conversions.o: $(hdrdir)/ruby/internal/core/rclass.h -conversions.o: $(hdrdir)/ruby/internal/core/rdata.h -conversions.o: $(hdrdir)/ruby/internal/core/rfile.h -conversions.o: $(hdrdir)/ruby/internal/core/rhash.h -conversions.o: $(hdrdir)/ruby/internal/core/robject.h -conversions.o: $(hdrdir)/ruby/internal/core/rregexp.h -conversions.o: $(hdrdir)/ruby/internal/core/rstring.h -conversions.o: $(hdrdir)/ruby/internal/core/rstruct.h -conversions.o: $(hdrdir)/ruby/internal/core/rtypeddata.h -conversions.o: $(hdrdir)/ruby/internal/ctype.h -conversions.o: $(hdrdir)/ruby/internal/dllexport.h -conversions.o: $(hdrdir)/ruby/internal/dosish.h -conversions.o: $(hdrdir)/ruby/internal/error.h -conversions.o: $(hdrdir)/ruby/internal/eval.h -conversions.o: $(hdrdir)/ruby/internal/event.h -conversions.o: $(hdrdir)/ruby/internal/fl_type.h -conversions.o: $(hdrdir)/ruby/internal/gc.h -conversions.o: $(hdrdir)/ruby/internal/glob.h -conversions.o: $(hdrdir)/ruby/internal/globals.h -conversions.o: $(hdrdir)/ruby/internal/has/attribute.h -conversions.o: $(hdrdir)/ruby/internal/has/builtin.h -conversions.o: $(hdrdir)/ruby/internal/has/c_attribute.h -conversions.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h -conversions.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h -conversions.o: $(hdrdir)/ruby/internal/has/extension.h -conversions.o: $(hdrdir)/ruby/internal/has/feature.h -conversions.o: $(hdrdir)/ruby/internal/has/warning.h -conversions.o: $(hdrdir)/ruby/internal/intern/array.h -conversions.o: $(hdrdir)/ruby/internal/intern/bignum.h -conversions.o: $(hdrdir)/ruby/internal/intern/class.h -conversions.o: $(hdrdir)/ruby/internal/intern/compar.h -conversions.o: $(hdrdir)/ruby/internal/intern/complex.h -conversions.o: $(hdrdir)/ruby/internal/intern/cont.h -conversions.o: $(hdrdir)/ruby/internal/intern/dir.h -conversions.o: $(hdrdir)/ruby/internal/intern/enum.h -conversions.o: $(hdrdir)/ruby/internal/intern/enumerator.h -conversions.o: $(hdrdir)/ruby/internal/intern/error.h -conversions.o: $(hdrdir)/ruby/internal/intern/eval.h -conversions.o: $(hdrdir)/ruby/internal/intern/file.h -conversions.o: $(hdrdir)/ruby/internal/intern/hash.h -conversions.o: $(hdrdir)/ruby/internal/intern/io.h -conversions.o: $(hdrdir)/ruby/internal/intern/load.h -conversions.o: $(hdrdir)/ruby/internal/intern/marshal.h -conversions.o: $(hdrdir)/ruby/internal/intern/numeric.h -conversions.o: $(hdrdir)/ruby/internal/intern/object.h -conversions.o: $(hdrdir)/ruby/internal/intern/parse.h -conversions.o: $(hdrdir)/ruby/internal/intern/proc.h -conversions.o: $(hdrdir)/ruby/internal/intern/process.h -conversions.o: $(hdrdir)/ruby/internal/intern/random.h -conversions.o: $(hdrdir)/ruby/internal/intern/range.h -conversions.o: $(hdrdir)/ruby/internal/intern/rational.h -conversions.o: $(hdrdir)/ruby/internal/intern/re.h -conversions.o: $(hdrdir)/ruby/internal/intern/ruby.h -conversions.o: $(hdrdir)/ruby/internal/intern/select.h -conversions.o: $(hdrdir)/ruby/internal/intern/select/largesize.h -conversions.o: $(hdrdir)/ruby/internal/intern/signal.h -conversions.o: $(hdrdir)/ruby/internal/intern/sprintf.h -conversions.o: $(hdrdir)/ruby/internal/intern/string.h -conversions.o: $(hdrdir)/ruby/internal/intern/struct.h -conversions.o: $(hdrdir)/ruby/internal/intern/thread.h -conversions.o: $(hdrdir)/ruby/internal/intern/time.h -conversions.o: $(hdrdir)/ruby/internal/intern/variable.h -conversions.o: $(hdrdir)/ruby/internal/intern/vm.h -conversions.o: $(hdrdir)/ruby/internal/interpreter.h -conversions.o: $(hdrdir)/ruby/internal/iterator.h -conversions.o: $(hdrdir)/ruby/internal/memory.h -conversions.o: $(hdrdir)/ruby/internal/method.h -conversions.o: $(hdrdir)/ruby/internal/module.h -conversions.o: $(hdrdir)/ruby/internal/newobj.h -conversions.o: $(hdrdir)/ruby/internal/scan_args.h -conversions.o: $(hdrdir)/ruby/internal/special_consts.h -conversions.o: $(hdrdir)/ruby/internal/static_assert.h -conversions.o: $(hdrdir)/ruby/internal/stdalign.h -conversions.o: $(hdrdir)/ruby/internal/stdbool.h -conversions.o: $(hdrdir)/ruby/internal/symbol.h -conversions.o: $(hdrdir)/ruby/internal/value.h -conversions.o: $(hdrdir)/ruby/internal/value_type.h -conversions.o: $(hdrdir)/ruby/internal/variable.h -conversions.o: $(hdrdir)/ruby/internal/warning_push.h -conversions.o: $(hdrdir)/ruby/internal/xmalloc.h -conversions.o: $(hdrdir)/ruby/missing.h -conversions.o: $(hdrdir)/ruby/ruby.h -conversions.o: $(hdrdir)/ruby/st.h -conversions.o: $(hdrdir)/ruby/subst.h -conversions.o: closure.h -conversions.o: conversions.c -conversions.o: conversions.h -conversions.o: fiddle.h -conversions.o: function.h -fiddle.o: $(RUBY_EXTCONF_H) -fiddle.o: $(arch_hdrdir)/ruby/config.h -fiddle.o: $(hdrdir)/ruby.h -fiddle.o: $(hdrdir)/ruby/assert.h -fiddle.o: $(hdrdir)/ruby/backward.h -fiddle.o: $(hdrdir)/ruby/backward/2/assume.h -fiddle.o: $(hdrdir)/ruby/backward/2/attributes.h -fiddle.o: $(hdrdir)/ruby/backward/2/bool.h -fiddle.o: $(hdrdir)/ruby/backward/2/inttypes.h -fiddle.o: $(hdrdir)/ruby/backward/2/limits.h -fiddle.o: $(hdrdir)/ruby/backward/2/long_long.h -fiddle.o: $(hdrdir)/ruby/backward/2/stdalign.h -fiddle.o: $(hdrdir)/ruby/backward/2/stdarg.h -fiddle.o: $(hdrdir)/ruby/defines.h -fiddle.o: $(hdrdir)/ruby/intern.h -fiddle.o: $(hdrdir)/ruby/internal/abi.h -fiddle.o: $(hdrdir)/ruby/internal/anyargs.h -fiddle.o: $(hdrdir)/ruby/internal/arithmetic.h -fiddle.o: $(hdrdir)/ruby/internal/arithmetic/char.h -fiddle.o: $(hdrdir)/ruby/internal/arithmetic/double.h -fiddle.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h -fiddle.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h -fiddle.o: $(hdrdir)/ruby/internal/arithmetic/int.h -fiddle.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h -fiddle.o: $(hdrdir)/ruby/internal/arithmetic/long.h -fiddle.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h -fiddle.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h -fiddle.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h -fiddle.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h -fiddle.o: $(hdrdir)/ruby/internal/arithmetic/short.h -fiddle.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h -fiddle.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h -fiddle.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h -fiddle.o: $(hdrdir)/ruby/internal/assume.h -fiddle.o: $(hdrdir)/ruby/internal/attr/alloc_size.h -fiddle.o: $(hdrdir)/ruby/internal/attr/artificial.h -fiddle.o: $(hdrdir)/ruby/internal/attr/cold.h -fiddle.o: $(hdrdir)/ruby/internal/attr/const.h -fiddle.o: $(hdrdir)/ruby/internal/attr/constexpr.h -fiddle.o: $(hdrdir)/ruby/internal/attr/deprecated.h -fiddle.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h -fiddle.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h -fiddle.o: $(hdrdir)/ruby/internal/attr/error.h -fiddle.o: $(hdrdir)/ruby/internal/attr/flag_enum.h -fiddle.o: $(hdrdir)/ruby/internal/attr/forceinline.h -fiddle.o: $(hdrdir)/ruby/internal/attr/format.h -fiddle.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h -fiddle.o: $(hdrdir)/ruby/internal/attr/noalias.h -fiddle.o: $(hdrdir)/ruby/internal/attr/nodiscard.h -fiddle.o: $(hdrdir)/ruby/internal/attr/noexcept.h -fiddle.o: $(hdrdir)/ruby/internal/attr/noinline.h -fiddle.o: $(hdrdir)/ruby/internal/attr/nonnull.h -fiddle.o: $(hdrdir)/ruby/internal/attr/noreturn.h -fiddle.o: $(hdrdir)/ruby/internal/attr/packed_struct.h -fiddle.o: $(hdrdir)/ruby/internal/attr/pure.h -fiddle.o: $(hdrdir)/ruby/internal/attr/restrict.h -fiddle.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h -fiddle.o: $(hdrdir)/ruby/internal/attr/warning.h -fiddle.o: $(hdrdir)/ruby/internal/attr/weakref.h -fiddle.o: $(hdrdir)/ruby/internal/cast.h -fiddle.o: $(hdrdir)/ruby/internal/compiler_is.h -fiddle.o: $(hdrdir)/ruby/internal/compiler_is/apple.h -fiddle.o: $(hdrdir)/ruby/internal/compiler_is/clang.h -fiddle.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h -fiddle.o: $(hdrdir)/ruby/internal/compiler_is/intel.h -fiddle.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h -fiddle.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h -fiddle.o: $(hdrdir)/ruby/internal/compiler_since.h -fiddle.o: $(hdrdir)/ruby/internal/config.h -fiddle.o: $(hdrdir)/ruby/internal/constant_p.h -fiddle.o: $(hdrdir)/ruby/internal/core.h -fiddle.o: $(hdrdir)/ruby/internal/core/rarray.h -fiddle.o: $(hdrdir)/ruby/internal/core/rbasic.h -fiddle.o: $(hdrdir)/ruby/internal/core/rbignum.h -fiddle.o: $(hdrdir)/ruby/internal/core/rclass.h -fiddle.o: $(hdrdir)/ruby/internal/core/rdata.h -fiddle.o: $(hdrdir)/ruby/internal/core/rfile.h -fiddle.o: $(hdrdir)/ruby/internal/core/rhash.h -fiddle.o: $(hdrdir)/ruby/internal/core/robject.h -fiddle.o: $(hdrdir)/ruby/internal/core/rregexp.h -fiddle.o: $(hdrdir)/ruby/internal/core/rstring.h -fiddle.o: $(hdrdir)/ruby/internal/core/rstruct.h -fiddle.o: $(hdrdir)/ruby/internal/core/rtypeddata.h -fiddle.o: $(hdrdir)/ruby/internal/ctype.h -fiddle.o: $(hdrdir)/ruby/internal/dllexport.h -fiddle.o: $(hdrdir)/ruby/internal/dosish.h -fiddle.o: $(hdrdir)/ruby/internal/error.h -fiddle.o: $(hdrdir)/ruby/internal/eval.h -fiddle.o: $(hdrdir)/ruby/internal/event.h -fiddle.o: $(hdrdir)/ruby/internal/fl_type.h -fiddle.o: $(hdrdir)/ruby/internal/gc.h -fiddle.o: $(hdrdir)/ruby/internal/glob.h -fiddle.o: $(hdrdir)/ruby/internal/globals.h -fiddle.o: $(hdrdir)/ruby/internal/has/attribute.h -fiddle.o: $(hdrdir)/ruby/internal/has/builtin.h -fiddle.o: $(hdrdir)/ruby/internal/has/c_attribute.h -fiddle.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h -fiddle.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h -fiddle.o: $(hdrdir)/ruby/internal/has/extension.h -fiddle.o: $(hdrdir)/ruby/internal/has/feature.h -fiddle.o: $(hdrdir)/ruby/internal/has/warning.h -fiddle.o: $(hdrdir)/ruby/internal/intern/array.h -fiddle.o: $(hdrdir)/ruby/internal/intern/bignum.h -fiddle.o: $(hdrdir)/ruby/internal/intern/class.h -fiddle.o: $(hdrdir)/ruby/internal/intern/compar.h -fiddle.o: $(hdrdir)/ruby/internal/intern/complex.h -fiddle.o: $(hdrdir)/ruby/internal/intern/cont.h -fiddle.o: $(hdrdir)/ruby/internal/intern/dir.h -fiddle.o: $(hdrdir)/ruby/internal/intern/enum.h -fiddle.o: $(hdrdir)/ruby/internal/intern/enumerator.h -fiddle.o: $(hdrdir)/ruby/internal/intern/error.h -fiddle.o: $(hdrdir)/ruby/internal/intern/eval.h -fiddle.o: $(hdrdir)/ruby/internal/intern/file.h -fiddle.o: $(hdrdir)/ruby/internal/intern/hash.h -fiddle.o: $(hdrdir)/ruby/internal/intern/io.h -fiddle.o: $(hdrdir)/ruby/internal/intern/load.h -fiddle.o: $(hdrdir)/ruby/internal/intern/marshal.h -fiddle.o: $(hdrdir)/ruby/internal/intern/numeric.h -fiddle.o: $(hdrdir)/ruby/internal/intern/object.h -fiddle.o: $(hdrdir)/ruby/internal/intern/parse.h -fiddle.o: $(hdrdir)/ruby/internal/intern/proc.h -fiddle.o: $(hdrdir)/ruby/internal/intern/process.h -fiddle.o: $(hdrdir)/ruby/internal/intern/random.h -fiddle.o: $(hdrdir)/ruby/internal/intern/range.h -fiddle.o: $(hdrdir)/ruby/internal/intern/rational.h -fiddle.o: $(hdrdir)/ruby/internal/intern/re.h -fiddle.o: $(hdrdir)/ruby/internal/intern/ruby.h -fiddle.o: $(hdrdir)/ruby/internal/intern/select.h -fiddle.o: $(hdrdir)/ruby/internal/intern/select/largesize.h -fiddle.o: $(hdrdir)/ruby/internal/intern/signal.h -fiddle.o: $(hdrdir)/ruby/internal/intern/sprintf.h -fiddle.o: $(hdrdir)/ruby/internal/intern/string.h -fiddle.o: $(hdrdir)/ruby/internal/intern/struct.h -fiddle.o: $(hdrdir)/ruby/internal/intern/thread.h -fiddle.o: $(hdrdir)/ruby/internal/intern/time.h -fiddle.o: $(hdrdir)/ruby/internal/intern/variable.h -fiddle.o: $(hdrdir)/ruby/internal/intern/vm.h -fiddle.o: $(hdrdir)/ruby/internal/interpreter.h -fiddle.o: $(hdrdir)/ruby/internal/iterator.h -fiddle.o: $(hdrdir)/ruby/internal/memory.h -fiddle.o: $(hdrdir)/ruby/internal/method.h -fiddle.o: $(hdrdir)/ruby/internal/module.h -fiddle.o: $(hdrdir)/ruby/internal/newobj.h -fiddle.o: $(hdrdir)/ruby/internal/scan_args.h -fiddle.o: $(hdrdir)/ruby/internal/special_consts.h -fiddle.o: $(hdrdir)/ruby/internal/static_assert.h -fiddle.o: $(hdrdir)/ruby/internal/stdalign.h -fiddle.o: $(hdrdir)/ruby/internal/stdbool.h -fiddle.o: $(hdrdir)/ruby/internal/symbol.h -fiddle.o: $(hdrdir)/ruby/internal/value.h -fiddle.o: $(hdrdir)/ruby/internal/value_type.h -fiddle.o: $(hdrdir)/ruby/internal/variable.h -fiddle.o: $(hdrdir)/ruby/internal/warning_push.h -fiddle.o: $(hdrdir)/ruby/internal/xmalloc.h -fiddle.o: $(hdrdir)/ruby/missing.h -fiddle.o: $(hdrdir)/ruby/ruby.h -fiddle.o: $(hdrdir)/ruby/st.h -fiddle.o: $(hdrdir)/ruby/subst.h -fiddle.o: closure.h -fiddle.o: conversions.h -fiddle.o: fiddle.c -fiddle.o: fiddle.h -fiddle.o: function.h -function.o: $(RUBY_EXTCONF_H) -function.o: $(arch_hdrdir)/ruby/config.h -function.o: $(hdrdir)/ruby.h -function.o: $(hdrdir)/ruby/assert.h -function.o: $(hdrdir)/ruby/backward.h -function.o: $(hdrdir)/ruby/backward/2/assume.h -function.o: $(hdrdir)/ruby/backward/2/attributes.h -function.o: $(hdrdir)/ruby/backward/2/bool.h -function.o: $(hdrdir)/ruby/backward/2/inttypes.h -function.o: $(hdrdir)/ruby/backward/2/limits.h -function.o: $(hdrdir)/ruby/backward/2/long_long.h -function.o: $(hdrdir)/ruby/backward/2/stdalign.h -function.o: $(hdrdir)/ruby/backward/2/stdarg.h -function.o: $(hdrdir)/ruby/defines.h -function.o: $(hdrdir)/ruby/intern.h -function.o: $(hdrdir)/ruby/internal/abi.h -function.o: $(hdrdir)/ruby/internal/anyargs.h -function.o: $(hdrdir)/ruby/internal/arithmetic.h -function.o: $(hdrdir)/ruby/internal/arithmetic/char.h -function.o: $(hdrdir)/ruby/internal/arithmetic/double.h -function.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h -function.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h -function.o: $(hdrdir)/ruby/internal/arithmetic/int.h -function.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h -function.o: $(hdrdir)/ruby/internal/arithmetic/long.h -function.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h -function.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h -function.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h -function.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h -function.o: $(hdrdir)/ruby/internal/arithmetic/short.h -function.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h -function.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h -function.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h -function.o: $(hdrdir)/ruby/internal/assume.h -function.o: $(hdrdir)/ruby/internal/attr/alloc_size.h -function.o: $(hdrdir)/ruby/internal/attr/artificial.h -function.o: $(hdrdir)/ruby/internal/attr/cold.h -function.o: $(hdrdir)/ruby/internal/attr/const.h -function.o: $(hdrdir)/ruby/internal/attr/constexpr.h -function.o: $(hdrdir)/ruby/internal/attr/deprecated.h -function.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h -function.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h -function.o: $(hdrdir)/ruby/internal/attr/error.h -function.o: $(hdrdir)/ruby/internal/attr/flag_enum.h -function.o: $(hdrdir)/ruby/internal/attr/forceinline.h -function.o: $(hdrdir)/ruby/internal/attr/format.h -function.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h -function.o: $(hdrdir)/ruby/internal/attr/noalias.h -function.o: $(hdrdir)/ruby/internal/attr/nodiscard.h -function.o: $(hdrdir)/ruby/internal/attr/noexcept.h -function.o: $(hdrdir)/ruby/internal/attr/noinline.h -function.o: $(hdrdir)/ruby/internal/attr/nonnull.h -function.o: $(hdrdir)/ruby/internal/attr/noreturn.h -function.o: $(hdrdir)/ruby/internal/attr/packed_struct.h -function.o: $(hdrdir)/ruby/internal/attr/pure.h -function.o: $(hdrdir)/ruby/internal/attr/restrict.h -function.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h -function.o: $(hdrdir)/ruby/internal/attr/warning.h -function.o: $(hdrdir)/ruby/internal/attr/weakref.h -function.o: $(hdrdir)/ruby/internal/cast.h -function.o: $(hdrdir)/ruby/internal/compiler_is.h -function.o: $(hdrdir)/ruby/internal/compiler_is/apple.h -function.o: $(hdrdir)/ruby/internal/compiler_is/clang.h -function.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h -function.o: $(hdrdir)/ruby/internal/compiler_is/intel.h -function.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h -function.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h -function.o: $(hdrdir)/ruby/internal/compiler_since.h -function.o: $(hdrdir)/ruby/internal/config.h -function.o: $(hdrdir)/ruby/internal/constant_p.h -function.o: $(hdrdir)/ruby/internal/core.h -function.o: $(hdrdir)/ruby/internal/core/rarray.h -function.o: $(hdrdir)/ruby/internal/core/rbasic.h -function.o: $(hdrdir)/ruby/internal/core/rbignum.h -function.o: $(hdrdir)/ruby/internal/core/rclass.h -function.o: $(hdrdir)/ruby/internal/core/rdata.h -function.o: $(hdrdir)/ruby/internal/core/rfile.h -function.o: $(hdrdir)/ruby/internal/core/rhash.h -function.o: $(hdrdir)/ruby/internal/core/robject.h -function.o: $(hdrdir)/ruby/internal/core/rregexp.h -function.o: $(hdrdir)/ruby/internal/core/rstring.h -function.o: $(hdrdir)/ruby/internal/core/rstruct.h -function.o: $(hdrdir)/ruby/internal/core/rtypeddata.h -function.o: $(hdrdir)/ruby/internal/ctype.h -function.o: $(hdrdir)/ruby/internal/dllexport.h -function.o: $(hdrdir)/ruby/internal/dosish.h -function.o: $(hdrdir)/ruby/internal/error.h -function.o: $(hdrdir)/ruby/internal/eval.h -function.o: $(hdrdir)/ruby/internal/event.h -function.o: $(hdrdir)/ruby/internal/fl_type.h -function.o: $(hdrdir)/ruby/internal/gc.h -function.o: $(hdrdir)/ruby/internal/glob.h -function.o: $(hdrdir)/ruby/internal/globals.h -function.o: $(hdrdir)/ruby/internal/has/attribute.h -function.o: $(hdrdir)/ruby/internal/has/builtin.h -function.o: $(hdrdir)/ruby/internal/has/c_attribute.h -function.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h -function.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h -function.o: $(hdrdir)/ruby/internal/has/extension.h -function.o: $(hdrdir)/ruby/internal/has/feature.h -function.o: $(hdrdir)/ruby/internal/has/warning.h -function.o: $(hdrdir)/ruby/internal/intern/array.h -function.o: $(hdrdir)/ruby/internal/intern/bignum.h -function.o: $(hdrdir)/ruby/internal/intern/class.h -function.o: $(hdrdir)/ruby/internal/intern/compar.h -function.o: $(hdrdir)/ruby/internal/intern/complex.h -function.o: $(hdrdir)/ruby/internal/intern/cont.h -function.o: $(hdrdir)/ruby/internal/intern/dir.h -function.o: $(hdrdir)/ruby/internal/intern/enum.h -function.o: $(hdrdir)/ruby/internal/intern/enumerator.h -function.o: $(hdrdir)/ruby/internal/intern/error.h -function.o: $(hdrdir)/ruby/internal/intern/eval.h -function.o: $(hdrdir)/ruby/internal/intern/file.h -function.o: $(hdrdir)/ruby/internal/intern/hash.h -function.o: $(hdrdir)/ruby/internal/intern/io.h -function.o: $(hdrdir)/ruby/internal/intern/load.h -function.o: $(hdrdir)/ruby/internal/intern/marshal.h -function.o: $(hdrdir)/ruby/internal/intern/numeric.h -function.o: $(hdrdir)/ruby/internal/intern/object.h -function.o: $(hdrdir)/ruby/internal/intern/parse.h -function.o: $(hdrdir)/ruby/internal/intern/proc.h -function.o: $(hdrdir)/ruby/internal/intern/process.h -function.o: $(hdrdir)/ruby/internal/intern/random.h -function.o: $(hdrdir)/ruby/internal/intern/range.h -function.o: $(hdrdir)/ruby/internal/intern/rational.h -function.o: $(hdrdir)/ruby/internal/intern/re.h -function.o: $(hdrdir)/ruby/internal/intern/ruby.h -function.o: $(hdrdir)/ruby/internal/intern/select.h -function.o: $(hdrdir)/ruby/internal/intern/select/largesize.h -function.o: $(hdrdir)/ruby/internal/intern/signal.h -function.o: $(hdrdir)/ruby/internal/intern/sprintf.h -function.o: $(hdrdir)/ruby/internal/intern/string.h -function.o: $(hdrdir)/ruby/internal/intern/struct.h -function.o: $(hdrdir)/ruby/internal/intern/thread.h -function.o: $(hdrdir)/ruby/internal/intern/time.h -function.o: $(hdrdir)/ruby/internal/intern/variable.h -function.o: $(hdrdir)/ruby/internal/intern/vm.h -function.o: $(hdrdir)/ruby/internal/interpreter.h -function.o: $(hdrdir)/ruby/internal/iterator.h -function.o: $(hdrdir)/ruby/internal/memory.h -function.o: $(hdrdir)/ruby/internal/method.h -function.o: $(hdrdir)/ruby/internal/module.h -function.o: $(hdrdir)/ruby/internal/newobj.h -function.o: $(hdrdir)/ruby/internal/scan_args.h -function.o: $(hdrdir)/ruby/internal/special_consts.h -function.o: $(hdrdir)/ruby/internal/static_assert.h -function.o: $(hdrdir)/ruby/internal/stdalign.h -function.o: $(hdrdir)/ruby/internal/stdbool.h -function.o: $(hdrdir)/ruby/internal/symbol.h -function.o: $(hdrdir)/ruby/internal/value.h -function.o: $(hdrdir)/ruby/internal/value_type.h -function.o: $(hdrdir)/ruby/internal/variable.h -function.o: $(hdrdir)/ruby/internal/warning_push.h -function.o: $(hdrdir)/ruby/internal/xmalloc.h -function.o: $(hdrdir)/ruby/missing.h -function.o: $(hdrdir)/ruby/ruby.h -function.o: $(hdrdir)/ruby/st.h -function.o: $(hdrdir)/ruby/subst.h -function.o: $(hdrdir)/ruby/thread.h -function.o: closure.h -function.o: conversions.h -function.o: fiddle.h -function.o: function.c -function.o: function.h -handle.o: $(RUBY_EXTCONF_H) -handle.o: $(arch_hdrdir)/ruby/config.h -handle.o: $(hdrdir)/ruby.h -handle.o: $(hdrdir)/ruby/assert.h -handle.o: $(hdrdir)/ruby/backward.h -handle.o: $(hdrdir)/ruby/backward/2/assume.h -handle.o: $(hdrdir)/ruby/backward/2/attributes.h -handle.o: $(hdrdir)/ruby/backward/2/bool.h -handle.o: $(hdrdir)/ruby/backward/2/inttypes.h -handle.o: $(hdrdir)/ruby/backward/2/limits.h -handle.o: $(hdrdir)/ruby/backward/2/long_long.h -handle.o: $(hdrdir)/ruby/backward/2/stdalign.h -handle.o: $(hdrdir)/ruby/backward/2/stdarg.h -handle.o: $(hdrdir)/ruby/defines.h -handle.o: $(hdrdir)/ruby/intern.h -handle.o: $(hdrdir)/ruby/internal/abi.h -handle.o: $(hdrdir)/ruby/internal/anyargs.h -handle.o: $(hdrdir)/ruby/internal/arithmetic.h -handle.o: $(hdrdir)/ruby/internal/arithmetic/char.h -handle.o: $(hdrdir)/ruby/internal/arithmetic/double.h -handle.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h -handle.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h -handle.o: $(hdrdir)/ruby/internal/arithmetic/int.h -handle.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h -handle.o: $(hdrdir)/ruby/internal/arithmetic/long.h -handle.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h -handle.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h -handle.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h -handle.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h -handle.o: $(hdrdir)/ruby/internal/arithmetic/short.h -handle.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h -handle.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h -handle.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h -handle.o: $(hdrdir)/ruby/internal/assume.h -handle.o: $(hdrdir)/ruby/internal/attr/alloc_size.h -handle.o: $(hdrdir)/ruby/internal/attr/artificial.h -handle.o: $(hdrdir)/ruby/internal/attr/cold.h -handle.o: $(hdrdir)/ruby/internal/attr/const.h -handle.o: $(hdrdir)/ruby/internal/attr/constexpr.h -handle.o: $(hdrdir)/ruby/internal/attr/deprecated.h -handle.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h -handle.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h -handle.o: $(hdrdir)/ruby/internal/attr/error.h -handle.o: $(hdrdir)/ruby/internal/attr/flag_enum.h -handle.o: $(hdrdir)/ruby/internal/attr/forceinline.h -handle.o: $(hdrdir)/ruby/internal/attr/format.h -handle.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h -handle.o: $(hdrdir)/ruby/internal/attr/noalias.h -handle.o: $(hdrdir)/ruby/internal/attr/nodiscard.h -handle.o: $(hdrdir)/ruby/internal/attr/noexcept.h -handle.o: $(hdrdir)/ruby/internal/attr/noinline.h -handle.o: $(hdrdir)/ruby/internal/attr/nonnull.h -handle.o: $(hdrdir)/ruby/internal/attr/noreturn.h -handle.o: $(hdrdir)/ruby/internal/attr/packed_struct.h -handle.o: $(hdrdir)/ruby/internal/attr/pure.h -handle.o: $(hdrdir)/ruby/internal/attr/restrict.h -handle.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h -handle.o: $(hdrdir)/ruby/internal/attr/warning.h -handle.o: $(hdrdir)/ruby/internal/attr/weakref.h -handle.o: $(hdrdir)/ruby/internal/cast.h -handle.o: $(hdrdir)/ruby/internal/compiler_is.h -handle.o: $(hdrdir)/ruby/internal/compiler_is/apple.h -handle.o: $(hdrdir)/ruby/internal/compiler_is/clang.h -handle.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h -handle.o: $(hdrdir)/ruby/internal/compiler_is/intel.h -handle.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h -handle.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h -handle.o: $(hdrdir)/ruby/internal/compiler_since.h -handle.o: $(hdrdir)/ruby/internal/config.h -handle.o: $(hdrdir)/ruby/internal/constant_p.h -handle.o: $(hdrdir)/ruby/internal/core.h -handle.o: $(hdrdir)/ruby/internal/core/rarray.h -handle.o: $(hdrdir)/ruby/internal/core/rbasic.h -handle.o: $(hdrdir)/ruby/internal/core/rbignum.h -handle.o: $(hdrdir)/ruby/internal/core/rclass.h -handle.o: $(hdrdir)/ruby/internal/core/rdata.h -handle.o: $(hdrdir)/ruby/internal/core/rfile.h -handle.o: $(hdrdir)/ruby/internal/core/rhash.h -handle.o: $(hdrdir)/ruby/internal/core/robject.h -handle.o: $(hdrdir)/ruby/internal/core/rregexp.h -handle.o: $(hdrdir)/ruby/internal/core/rstring.h -handle.o: $(hdrdir)/ruby/internal/core/rstruct.h -handle.o: $(hdrdir)/ruby/internal/core/rtypeddata.h -handle.o: $(hdrdir)/ruby/internal/ctype.h -handle.o: $(hdrdir)/ruby/internal/dllexport.h -handle.o: $(hdrdir)/ruby/internal/dosish.h -handle.o: $(hdrdir)/ruby/internal/error.h -handle.o: $(hdrdir)/ruby/internal/eval.h -handle.o: $(hdrdir)/ruby/internal/event.h -handle.o: $(hdrdir)/ruby/internal/fl_type.h -handle.o: $(hdrdir)/ruby/internal/gc.h -handle.o: $(hdrdir)/ruby/internal/glob.h -handle.o: $(hdrdir)/ruby/internal/globals.h -handle.o: $(hdrdir)/ruby/internal/has/attribute.h -handle.o: $(hdrdir)/ruby/internal/has/builtin.h -handle.o: $(hdrdir)/ruby/internal/has/c_attribute.h -handle.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h -handle.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h -handle.o: $(hdrdir)/ruby/internal/has/extension.h -handle.o: $(hdrdir)/ruby/internal/has/feature.h -handle.o: $(hdrdir)/ruby/internal/has/warning.h -handle.o: $(hdrdir)/ruby/internal/intern/array.h -handle.o: $(hdrdir)/ruby/internal/intern/bignum.h -handle.o: $(hdrdir)/ruby/internal/intern/class.h -handle.o: $(hdrdir)/ruby/internal/intern/compar.h -handle.o: $(hdrdir)/ruby/internal/intern/complex.h -handle.o: $(hdrdir)/ruby/internal/intern/cont.h -handle.o: $(hdrdir)/ruby/internal/intern/dir.h -handle.o: $(hdrdir)/ruby/internal/intern/enum.h -handle.o: $(hdrdir)/ruby/internal/intern/enumerator.h -handle.o: $(hdrdir)/ruby/internal/intern/error.h -handle.o: $(hdrdir)/ruby/internal/intern/eval.h -handle.o: $(hdrdir)/ruby/internal/intern/file.h -handle.o: $(hdrdir)/ruby/internal/intern/hash.h -handle.o: $(hdrdir)/ruby/internal/intern/io.h -handle.o: $(hdrdir)/ruby/internal/intern/load.h -handle.o: $(hdrdir)/ruby/internal/intern/marshal.h -handle.o: $(hdrdir)/ruby/internal/intern/numeric.h -handle.o: $(hdrdir)/ruby/internal/intern/object.h -handle.o: $(hdrdir)/ruby/internal/intern/parse.h -handle.o: $(hdrdir)/ruby/internal/intern/proc.h -handle.o: $(hdrdir)/ruby/internal/intern/process.h -handle.o: $(hdrdir)/ruby/internal/intern/random.h -handle.o: $(hdrdir)/ruby/internal/intern/range.h -handle.o: $(hdrdir)/ruby/internal/intern/rational.h -handle.o: $(hdrdir)/ruby/internal/intern/re.h -handle.o: $(hdrdir)/ruby/internal/intern/ruby.h -handle.o: $(hdrdir)/ruby/internal/intern/select.h -handle.o: $(hdrdir)/ruby/internal/intern/select/largesize.h -handle.o: $(hdrdir)/ruby/internal/intern/signal.h -handle.o: $(hdrdir)/ruby/internal/intern/sprintf.h -handle.o: $(hdrdir)/ruby/internal/intern/string.h -handle.o: $(hdrdir)/ruby/internal/intern/struct.h -handle.o: $(hdrdir)/ruby/internal/intern/thread.h -handle.o: $(hdrdir)/ruby/internal/intern/time.h -handle.o: $(hdrdir)/ruby/internal/intern/variable.h -handle.o: $(hdrdir)/ruby/internal/intern/vm.h -handle.o: $(hdrdir)/ruby/internal/interpreter.h -handle.o: $(hdrdir)/ruby/internal/iterator.h -handle.o: $(hdrdir)/ruby/internal/memory.h -handle.o: $(hdrdir)/ruby/internal/method.h -handle.o: $(hdrdir)/ruby/internal/module.h -handle.o: $(hdrdir)/ruby/internal/newobj.h -handle.o: $(hdrdir)/ruby/internal/scan_args.h -handle.o: $(hdrdir)/ruby/internal/special_consts.h -handle.o: $(hdrdir)/ruby/internal/static_assert.h -handle.o: $(hdrdir)/ruby/internal/stdalign.h -handle.o: $(hdrdir)/ruby/internal/stdbool.h -handle.o: $(hdrdir)/ruby/internal/symbol.h -handle.o: $(hdrdir)/ruby/internal/value.h -handle.o: $(hdrdir)/ruby/internal/value_type.h -handle.o: $(hdrdir)/ruby/internal/variable.h -handle.o: $(hdrdir)/ruby/internal/warning_push.h -handle.o: $(hdrdir)/ruby/internal/xmalloc.h -handle.o: $(hdrdir)/ruby/missing.h -handle.o: $(hdrdir)/ruby/ruby.h -handle.o: $(hdrdir)/ruby/st.h -handle.o: $(hdrdir)/ruby/subst.h -handle.o: closure.h -handle.o: conversions.h -handle.o: fiddle.h -handle.o: function.h -handle.o: handle.c -memory_view.o: $(RUBY_EXTCONF_H) -memory_view.o: $(arch_hdrdir)/ruby/config.h -memory_view.o: $(hdrdir)/ruby.h -memory_view.o: $(hdrdir)/ruby/assert.h -memory_view.o: $(hdrdir)/ruby/backward.h -memory_view.o: $(hdrdir)/ruby/backward/2/assume.h -memory_view.o: $(hdrdir)/ruby/backward/2/attributes.h -memory_view.o: $(hdrdir)/ruby/backward/2/bool.h -memory_view.o: $(hdrdir)/ruby/backward/2/inttypes.h -memory_view.o: $(hdrdir)/ruby/backward/2/limits.h -memory_view.o: $(hdrdir)/ruby/backward/2/long_long.h -memory_view.o: $(hdrdir)/ruby/backward/2/stdalign.h -memory_view.o: $(hdrdir)/ruby/backward/2/stdarg.h -memory_view.o: $(hdrdir)/ruby/defines.h -memory_view.o: $(hdrdir)/ruby/encoding.h -memory_view.o: $(hdrdir)/ruby/intern.h -memory_view.o: $(hdrdir)/ruby/internal/abi.h -memory_view.o: $(hdrdir)/ruby/internal/anyargs.h -memory_view.o: $(hdrdir)/ruby/internal/arithmetic.h -memory_view.o: $(hdrdir)/ruby/internal/arithmetic/char.h -memory_view.o: $(hdrdir)/ruby/internal/arithmetic/double.h -memory_view.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h -memory_view.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h -memory_view.o: $(hdrdir)/ruby/internal/arithmetic/int.h -memory_view.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h -memory_view.o: $(hdrdir)/ruby/internal/arithmetic/long.h -memory_view.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h -memory_view.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h -memory_view.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h -memory_view.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h -memory_view.o: $(hdrdir)/ruby/internal/arithmetic/short.h -memory_view.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h -memory_view.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h -memory_view.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h -memory_view.o: $(hdrdir)/ruby/internal/assume.h -memory_view.o: $(hdrdir)/ruby/internal/attr/alloc_size.h -memory_view.o: $(hdrdir)/ruby/internal/attr/artificial.h -memory_view.o: $(hdrdir)/ruby/internal/attr/cold.h -memory_view.o: $(hdrdir)/ruby/internal/attr/const.h -memory_view.o: $(hdrdir)/ruby/internal/attr/constexpr.h -memory_view.o: $(hdrdir)/ruby/internal/attr/deprecated.h -memory_view.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h -memory_view.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h -memory_view.o: $(hdrdir)/ruby/internal/attr/error.h -memory_view.o: $(hdrdir)/ruby/internal/attr/flag_enum.h -memory_view.o: $(hdrdir)/ruby/internal/attr/forceinline.h -memory_view.o: $(hdrdir)/ruby/internal/attr/format.h -memory_view.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h -memory_view.o: $(hdrdir)/ruby/internal/attr/noalias.h -memory_view.o: $(hdrdir)/ruby/internal/attr/nodiscard.h -memory_view.o: $(hdrdir)/ruby/internal/attr/noexcept.h -memory_view.o: $(hdrdir)/ruby/internal/attr/noinline.h -memory_view.o: $(hdrdir)/ruby/internal/attr/nonnull.h -memory_view.o: $(hdrdir)/ruby/internal/attr/noreturn.h -memory_view.o: $(hdrdir)/ruby/internal/attr/packed_struct.h -memory_view.o: $(hdrdir)/ruby/internal/attr/pure.h -memory_view.o: $(hdrdir)/ruby/internal/attr/restrict.h -memory_view.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h -memory_view.o: $(hdrdir)/ruby/internal/attr/warning.h -memory_view.o: $(hdrdir)/ruby/internal/attr/weakref.h -memory_view.o: $(hdrdir)/ruby/internal/cast.h -memory_view.o: $(hdrdir)/ruby/internal/compiler_is.h -memory_view.o: $(hdrdir)/ruby/internal/compiler_is/apple.h -memory_view.o: $(hdrdir)/ruby/internal/compiler_is/clang.h -memory_view.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h -memory_view.o: $(hdrdir)/ruby/internal/compiler_is/intel.h -memory_view.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h -memory_view.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h -memory_view.o: $(hdrdir)/ruby/internal/compiler_since.h -memory_view.o: $(hdrdir)/ruby/internal/config.h -memory_view.o: $(hdrdir)/ruby/internal/constant_p.h -memory_view.o: $(hdrdir)/ruby/internal/core.h -memory_view.o: $(hdrdir)/ruby/internal/core/rarray.h -memory_view.o: $(hdrdir)/ruby/internal/core/rbasic.h -memory_view.o: $(hdrdir)/ruby/internal/core/rbignum.h -memory_view.o: $(hdrdir)/ruby/internal/core/rclass.h -memory_view.o: $(hdrdir)/ruby/internal/core/rdata.h -memory_view.o: $(hdrdir)/ruby/internal/core/rfile.h -memory_view.o: $(hdrdir)/ruby/internal/core/rhash.h -memory_view.o: $(hdrdir)/ruby/internal/core/robject.h -memory_view.o: $(hdrdir)/ruby/internal/core/rregexp.h -memory_view.o: $(hdrdir)/ruby/internal/core/rstring.h -memory_view.o: $(hdrdir)/ruby/internal/core/rstruct.h -memory_view.o: $(hdrdir)/ruby/internal/core/rtypeddata.h -memory_view.o: $(hdrdir)/ruby/internal/ctype.h -memory_view.o: $(hdrdir)/ruby/internal/dllexport.h -memory_view.o: $(hdrdir)/ruby/internal/dosish.h -memory_view.o: $(hdrdir)/ruby/internal/encoding/coderange.h -memory_view.o: $(hdrdir)/ruby/internal/encoding/ctype.h -memory_view.o: $(hdrdir)/ruby/internal/encoding/encoding.h -memory_view.o: $(hdrdir)/ruby/internal/encoding/pathname.h -memory_view.o: $(hdrdir)/ruby/internal/encoding/re.h -memory_view.o: $(hdrdir)/ruby/internal/encoding/sprintf.h -memory_view.o: $(hdrdir)/ruby/internal/encoding/string.h -memory_view.o: $(hdrdir)/ruby/internal/encoding/symbol.h -memory_view.o: $(hdrdir)/ruby/internal/encoding/transcode.h -memory_view.o: $(hdrdir)/ruby/internal/error.h -memory_view.o: $(hdrdir)/ruby/internal/eval.h -memory_view.o: $(hdrdir)/ruby/internal/event.h -memory_view.o: $(hdrdir)/ruby/internal/fl_type.h -memory_view.o: $(hdrdir)/ruby/internal/gc.h -memory_view.o: $(hdrdir)/ruby/internal/glob.h -memory_view.o: $(hdrdir)/ruby/internal/globals.h -memory_view.o: $(hdrdir)/ruby/internal/has/attribute.h -memory_view.o: $(hdrdir)/ruby/internal/has/builtin.h -memory_view.o: $(hdrdir)/ruby/internal/has/c_attribute.h -memory_view.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h -memory_view.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h -memory_view.o: $(hdrdir)/ruby/internal/has/extension.h -memory_view.o: $(hdrdir)/ruby/internal/has/feature.h -memory_view.o: $(hdrdir)/ruby/internal/has/warning.h -memory_view.o: $(hdrdir)/ruby/internal/intern/array.h -memory_view.o: $(hdrdir)/ruby/internal/intern/bignum.h -memory_view.o: $(hdrdir)/ruby/internal/intern/class.h -memory_view.o: $(hdrdir)/ruby/internal/intern/compar.h -memory_view.o: $(hdrdir)/ruby/internal/intern/complex.h -memory_view.o: $(hdrdir)/ruby/internal/intern/cont.h -memory_view.o: $(hdrdir)/ruby/internal/intern/dir.h -memory_view.o: $(hdrdir)/ruby/internal/intern/enum.h -memory_view.o: $(hdrdir)/ruby/internal/intern/enumerator.h -memory_view.o: $(hdrdir)/ruby/internal/intern/error.h -memory_view.o: $(hdrdir)/ruby/internal/intern/eval.h -memory_view.o: $(hdrdir)/ruby/internal/intern/file.h -memory_view.o: $(hdrdir)/ruby/internal/intern/hash.h -memory_view.o: $(hdrdir)/ruby/internal/intern/io.h -memory_view.o: $(hdrdir)/ruby/internal/intern/load.h -memory_view.o: $(hdrdir)/ruby/internal/intern/marshal.h -memory_view.o: $(hdrdir)/ruby/internal/intern/numeric.h -memory_view.o: $(hdrdir)/ruby/internal/intern/object.h -memory_view.o: $(hdrdir)/ruby/internal/intern/parse.h -memory_view.o: $(hdrdir)/ruby/internal/intern/proc.h -memory_view.o: $(hdrdir)/ruby/internal/intern/process.h -memory_view.o: $(hdrdir)/ruby/internal/intern/random.h -memory_view.o: $(hdrdir)/ruby/internal/intern/range.h -memory_view.o: $(hdrdir)/ruby/internal/intern/rational.h -memory_view.o: $(hdrdir)/ruby/internal/intern/re.h -memory_view.o: $(hdrdir)/ruby/internal/intern/ruby.h -memory_view.o: $(hdrdir)/ruby/internal/intern/select.h -memory_view.o: $(hdrdir)/ruby/internal/intern/select/largesize.h -memory_view.o: $(hdrdir)/ruby/internal/intern/signal.h -memory_view.o: $(hdrdir)/ruby/internal/intern/sprintf.h -memory_view.o: $(hdrdir)/ruby/internal/intern/string.h -memory_view.o: $(hdrdir)/ruby/internal/intern/struct.h -memory_view.o: $(hdrdir)/ruby/internal/intern/thread.h -memory_view.o: $(hdrdir)/ruby/internal/intern/time.h -memory_view.o: $(hdrdir)/ruby/internal/intern/variable.h -memory_view.o: $(hdrdir)/ruby/internal/intern/vm.h -memory_view.o: $(hdrdir)/ruby/internal/interpreter.h -memory_view.o: $(hdrdir)/ruby/internal/iterator.h -memory_view.o: $(hdrdir)/ruby/internal/memory.h -memory_view.o: $(hdrdir)/ruby/internal/method.h -memory_view.o: $(hdrdir)/ruby/internal/module.h -memory_view.o: $(hdrdir)/ruby/internal/newobj.h -memory_view.o: $(hdrdir)/ruby/internal/scan_args.h -memory_view.o: $(hdrdir)/ruby/internal/special_consts.h -memory_view.o: $(hdrdir)/ruby/internal/static_assert.h -memory_view.o: $(hdrdir)/ruby/internal/stdalign.h -memory_view.o: $(hdrdir)/ruby/internal/stdbool.h -memory_view.o: $(hdrdir)/ruby/internal/symbol.h -memory_view.o: $(hdrdir)/ruby/internal/value.h -memory_view.o: $(hdrdir)/ruby/internal/value_type.h -memory_view.o: $(hdrdir)/ruby/internal/variable.h -memory_view.o: $(hdrdir)/ruby/internal/warning_push.h -memory_view.o: $(hdrdir)/ruby/internal/xmalloc.h -memory_view.o: $(hdrdir)/ruby/memory_view.h -memory_view.o: $(hdrdir)/ruby/missing.h -memory_view.o: $(hdrdir)/ruby/onigmo.h -memory_view.o: $(hdrdir)/ruby/oniguruma.h -memory_view.o: $(hdrdir)/ruby/ruby.h -memory_view.o: $(hdrdir)/ruby/st.h -memory_view.o: $(hdrdir)/ruby/subst.h -memory_view.o: closure.h -memory_view.o: conversions.h -memory_view.o: fiddle.h -memory_view.o: function.h -memory_view.o: memory_view.c -pinned.o: $(RUBY_EXTCONF_H) -pinned.o: $(arch_hdrdir)/ruby/config.h -pinned.o: $(hdrdir)/ruby.h -pinned.o: $(hdrdir)/ruby/assert.h -pinned.o: $(hdrdir)/ruby/backward.h -pinned.o: $(hdrdir)/ruby/backward/2/assume.h -pinned.o: $(hdrdir)/ruby/backward/2/attributes.h -pinned.o: $(hdrdir)/ruby/backward/2/bool.h -pinned.o: $(hdrdir)/ruby/backward/2/inttypes.h -pinned.o: $(hdrdir)/ruby/backward/2/limits.h -pinned.o: $(hdrdir)/ruby/backward/2/long_long.h -pinned.o: $(hdrdir)/ruby/backward/2/stdalign.h -pinned.o: $(hdrdir)/ruby/backward/2/stdarg.h -pinned.o: $(hdrdir)/ruby/defines.h -pinned.o: $(hdrdir)/ruby/intern.h -pinned.o: $(hdrdir)/ruby/internal/abi.h -pinned.o: $(hdrdir)/ruby/internal/anyargs.h -pinned.o: $(hdrdir)/ruby/internal/arithmetic.h -pinned.o: $(hdrdir)/ruby/internal/arithmetic/char.h -pinned.o: $(hdrdir)/ruby/internal/arithmetic/double.h -pinned.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h -pinned.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h -pinned.o: $(hdrdir)/ruby/internal/arithmetic/int.h -pinned.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h -pinned.o: $(hdrdir)/ruby/internal/arithmetic/long.h -pinned.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h -pinned.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h -pinned.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h -pinned.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h -pinned.o: $(hdrdir)/ruby/internal/arithmetic/short.h -pinned.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h -pinned.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h -pinned.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h -pinned.o: $(hdrdir)/ruby/internal/assume.h -pinned.o: $(hdrdir)/ruby/internal/attr/alloc_size.h -pinned.o: $(hdrdir)/ruby/internal/attr/artificial.h -pinned.o: $(hdrdir)/ruby/internal/attr/cold.h -pinned.o: $(hdrdir)/ruby/internal/attr/const.h -pinned.o: $(hdrdir)/ruby/internal/attr/constexpr.h -pinned.o: $(hdrdir)/ruby/internal/attr/deprecated.h -pinned.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h -pinned.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h -pinned.o: $(hdrdir)/ruby/internal/attr/error.h -pinned.o: $(hdrdir)/ruby/internal/attr/flag_enum.h -pinned.o: $(hdrdir)/ruby/internal/attr/forceinline.h -pinned.o: $(hdrdir)/ruby/internal/attr/format.h -pinned.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h -pinned.o: $(hdrdir)/ruby/internal/attr/noalias.h -pinned.o: $(hdrdir)/ruby/internal/attr/nodiscard.h -pinned.o: $(hdrdir)/ruby/internal/attr/noexcept.h -pinned.o: $(hdrdir)/ruby/internal/attr/noinline.h -pinned.o: $(hdrdir)/ruby/internal/attr/nonnull.h -pinned.o: $(hdrdir)/ruby/internal/attr/noreturn.h -pinned.o: $(hdrdir)/ruby/internal/attr/packed_struct.h -pinned.o: $(hdrdir)/ruby/internal/attr/pure.h -pinned.o: $(hdrdir)/ruby/internal/attr/restrict.h -pinned.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h -pinned.o: $(hdrdir)/ruby/internal/attr/warning.h -pinned.o: $(hdrdir)/ruby/internal/attr/weakref.h -pinned.o: $(hdrdir)/ruby/internal/cast.h -pinned.o: $(hdrdir)/ruby/internal/compiler_is.h -pinned.o: $(hdrdir)/ruby/internal/compiler_is/apple.h -pinned.o: $(hdrdir)/ruby/internal/compiler_is/clang.h -pinned.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h -pinned.o: $(hdrdir)/ruby/internal/compiler_is/intel.h -pinned.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h -pinned.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h -pinned.o: $(hdrdir)/ruby/internal/compiler_since.h -pinned.o: $(hdrdir)/ruby/internal/config.h -pinned.o: $(hdrdir)/ruby/internal/constant_p.h -pinned.o: $(hdrdir)/ruby/internal/core.h -pinned.o: $(hdrdir)/ruby/internal/core/rarray.h -pinned.o: $(hdrdir)/ruby/internal/core/rbasic.h -pinned.o: $(hdrdir)/ruby/internal/core/rbignum.h -pinned.o: $(hdrdir)/ruby/internal/core/rclass.h -pinned.o: $(hdrdir)/ruby/internal/core/rdata.h -pinned.o: $(hdrdir)/ruby/internal/core/rfile.h -pinned.o: $(hdrdir)/ruby/internal/core/rhash.h -pinned.o: $(hdrdir)/ruby/internal/core/robject.h -pinned.o: $(hdrdir)/ruby/internal/core/rregexp.h -pinned.o: $(hdrdir)/ruby/internal/core/rstring.h -pinned.o: $(hdrdir)/ruby/internal/core/rstruct.h -pinned.o: $(hdrdir)/ruby/internal/core/rtypeddata.h -pinned.o: $(hdrdir)/ruby/internal/ctype.h -pinned.o: $(hdrdir)/ruby/internal/dllexport.h -pinned.o: $(hdrdir)/ruby/internal/dosish.h -pinned.o: $(hdrdir)/ruby/internal/error.h -pinned.o: $(hdrdir)/ruby/internal/eval.h -pinned.o: $(hdrdir)/ruby/internal/event.h -pinned.o: $(hdrdir)/ruby/internal/fl_type.h -pinned.o: $(hdrdir)/ruby/internal/gc.h -pinned.o: $(hdrdir)/ruby/internal/glob.h -pinned.o: $(hdrdir)/ruby/internal/globals.h -pinned.o: $(hdrdir)/ruby/internal/has/attribute.h -pinned.o: $(hdrdir)/ruby/internal/has/builtin.h -pinned.o: $(hdrdir)/ruby/internal/has/c_attribute.h -pinned.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h -pinned.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h -pinned.o: $(hdrdir)/ruby/internal/has/extension.h -pinned.o: $(hdrdir)/ruby/internal/has/feature.h -pinned.o: $(hdrdir)/ruby/internal/has/warning.h -pinned.o: $(hdrdir)/ruby/internal/intern/array.h -pinned.o: $(hdrdir)/ruby/internal/intern/bignum.h -pinned.o: $(hdrdir)/ruby/internal/intern/class.h -pinned.o: $(hdrdir)/ruby/internal/intern/compar.h -pinned.o: $(hdrdir)/ruby/internal/intern/complex.h -pinned.o: $(hdrdir)/ruby/internal/intern/cont.h -pinned.o: $(hdrdir)/ruby/internal/intern/dir.h -pinned.o: $(hdrdir)/ruby/internal/intern/enum.h -pinned.o: $(hdrdir)/ruby/internal/intern/enumerator.h -pinned.o: $(hdrdir)/ruby/internal/intern/error.h -pinned.o: $(hdrdir)/ruby/internal/intern/eval.h -pinned.o: $(hdrdir)/ruby/internal/intern/file.h -pinned.o: $(hdrdir)/ruby/internal/intern/hash.h -pinned.o: $(hdrdir)/ruby/internal/intern/io.h -pinned.o: $(hdrdir)/ruby/internal/intern/load.h -pinned.o: $(hdrdir)/ruby/internal/intern/marshal.h -pinned.o: $(hdrdir)/ruby/internal/intern/numeric.h -pinned.o: $(hdrdir)/ruby/internal/intern/object.h -pinned.o: $(hdrdir)/ruby/internal/intern/parse.h -pinned.o: $(hdrdir)/ruby/internal/intern/proc.h -pinned.o: $(hdrdir)/ruby/internal/intern/process.h -pinned.o: $(hdrdir)/ruby/internal/intern/random.h -pinned.o: $(hdrdir)/ruby/internal/intern/range.h -pinned.o: $(hdrdir)/ruby/internal/intern/rational.h -pinned.o: $(hdrdir)/ruby/internal/intern/re.h -pinned.o: $(hdrdir)/ruby/internal/intern/ruby.h -pinned.o: $(hdrdir)/ruby/internal/intern/select.h -pinned.o: $(hdrdir)/ruby/internal/intern/select/largesize.h -pinned.o: $(hdrdir)/ruby/internal/intern/signal.h -pinned.o: $(hdrdir)/ruby/internal/intern/sprintf.h -pinned.o: $(hdrdir)/ruby/internal/intern/string.h -pinned.o: $(hdrdir)/ruby/internal/intern/struct.h -pinned.o: $(hdrdir)/ruby/internal/intern/thread.h -pinned.o: $(hdrdir)/ruby/internal/intern/time.h -pinned.o: $(hdrdir)/ruby/internal/intern/variable.h -pinned.o: $(hdrdir)/ruby/internal/intern/vm.h -pinned.o: $(hdrdir)/ruby/internal/interpreter.h -pinned.o: $(hdrdir)/ruby/internal/iterator.h -pinned.o: $(hdrdir)/ruby/internal/memory.h -pinned.o: $(hdrdir)/ruby/internal/method.h -pinned.o: $(hdrdir)/ruby/internal/module.h -pinned.o: $(hdrdir)/ruby/internal/newobj.h -pinned.o: $(hdrdir)/ruby/internal/scan_args.h -pinned.o: $(hdrdir)/ruby/internal/special_consts.h -pinned.o: $(hdrdir)/ruby/internal/static_assert.h -pinned.o: $(hdrdir)/ruby/internal/stdalign.h -pinned.o: $(hdrdir)/ruby/internal/stdbool.h -pinned.o: $(hdrdir)/ruby/internal/symbol.h -pinned.o: $(hdrdir)/ruby/internal/value.h -pinned.o: $(hdrdir)/ruby/internal/value_type.h -pinned.o: $(hdrdir)/ruby/internal/variable.h -pinned.o: $(hdrdir)/ruby/internal/warning_push.h -pinned.o: $(hdrdir)/ruby/internal/xmalloc.h -pinned.o: $(hdrdir)/ruby/missing.h -pinned.o: $(hdrdir)/ruby/ruby.h -pinned.o: $(hdrdir)/ruby/st.h -pinned.o: $(hdrdir)/ruby/subst.h -pinned.o: closure.h -pinned.o: conversions.h -pinned.o: fiddle.h -pinned.o: function.h -pinned.o: pinned.c -pointer.o: $(RUBY_EXTCONF_H) -pointer.o: $(arch_hdrdir)/ruby/config.h -pointer.o: $(hdrdir)/ruby.h -pointer.o: $(hdrdir)/ruby/assert.h -pointer.o: $(hdrdir)/ruby/backward.h -pointer.o: $(hdrdir)/ruby/backward/2/assume.h -pointer.o: $(hdrdir)/ruby/backward/2/attributes.h -pointer.o: $(hdrdir)/ruby/backward/2/bool.h -pointer.o: $(hdrdir)/ruby/backward/2/inttypes.h -pointer.o: $(hdrdir)/ruby/backward/2/limits.h -pointer.o: $(hdrdir)/ruby/backward/2/long_long.h -pointer.o: $(hdrdir)/ruby/backward/2/stdalign.h -pointer.o: $(hdrdir)/ruby/backward/2/stdarg.h -pointer.o: $(hdrdir)/ruby/defines.h -pointer.o: $(hdrdir)/ruby/encoding.h -pointer.o: $(hdrdir)/ruby/intern.h -pointer.o: $(hdrdir)/ruby/internal/abi.h -pointer.o: $(hdrdir)/ruby/internal/anyargs.h -pointer.o: $(hdrdir)/ruby/internal/arithmetic.h -pointer.o: $(hdrdir)/ruby/internal/arithmetic/char.h -pointer.o: $(hdrdir)/ruby/internal/arithmetic/double.h -pointer.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h -pointer.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h -pointer.o: $(hdrdir)/ruby/internal/arithmetic/int.h -pointer.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h -pointer.o: $(hdrdir)/ruby/internal/arithmetic/long.h -pointer.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h -pointer.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h -pointer.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h -pointer.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h -pointer.o: $(hdrdir)/ruby/internal/arithmetic/short.h -pointer.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h -pointer.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h -pointer.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h -pointer.o: $(hdrdir)/ruby/internal/assume.h -pointer.o: $(hdrdir)/ruby/internal/attr/alloc_size.h -pointer.o: $(hdrdir)/ruby/internal/attr/artificial.h -pointer.o: $(hdrdir)/ruby/internal/attr/cold.h -pointer.o: $(hdrdir)/ruby/internal/attr/const.h -pointer.o: $(hdrdir)/ruby/internal/attr/constexpr.h -pointer.o: $(hdrdir)/ruby/internal/attr/deprecated.h -pointer.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h -pointer.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h -pointer.o: $(hdrdir)/ruby/internal/attr/error.h -pointer.o: $(hdrdir)/ruby/internal/attr/flag_enum.h -pointer.o: $(hdrdir)/ruby/internal/attr/forceinline.h -pointer.o: $(hdrdir)/ruby/internal/attr/format.h -pointer.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h -pointer.o: $(hdrdir)/ruby/internal/attr/noalias.h -pointer.o: $(hdrdir)/ruby/internal/attr/nodiscard.h -pointer.o: $(hdrdir)/ruby/internal/attr/noexcept.h -pointer.o: $(hdrdir)/ruby/internal/attr/noinline.h -pointer.o: $(hdrdir)/ruby/internal/attr/nonnull.h -pointer.o: $(hdrdir)/ruby/internal/attr/noreturn.h -pointer.o: $(hdrdir)/ruby/internal/attr/packed_struct.h -pointer.o: $(hdrdir)/ruby/internal/attr/pure.h -pointer.o: $(hdrdir)/ruby/internal/attr/restrict.h -pointer.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h -pointer.o: $(hdrdir)/ruby/internal/attr/warning.h -pointer.o: $(hdrdir)/ruby/internal/attr/weakref.h -pointer.o: $(hdrdir)/ruby/internal/cast.h -pointer.o: $(hdrdir)/ruby/internal/compiler_is.h -pointer.o: $(hdrdir)/ruby/internal/compiler_is/apple.h -pointer.o: $(hdrdir)/ruby/internal/compiler_is/clang.h -pointer.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h -pointer.o: $(hdrdir)/ruby/internal/compiler_is/intel.h -pointer.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h -pointer.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h -pointer.o: $(hdrdir)/ruby/internal/compiler_since.h -pointer.o: $(hdrdir)/ruby/internal/config.h -pointer.o: $(hdrdir)/ruby/internal/constant_p.h -pointer.o: $(hdrdir)/ruby/internal/core.h -pointer.o: $(hdrdir)/ruby/internal/core/rarray.h -pointer.o: $(hdrdir)/ruby/internal/core/rbasic.h -pointer.o: $(hdrdir)/ruby/internal/core/rbignum.h -pointer.o: $(hdrdir)/ruby/internal/core/rclass.h -pointer.o: $(hdrdir)/ruby/internal/core/rdata.h -pointer.o: $(hdrdir)/ruby/internal/core/rfile.h -pointer.o: $(hdrdir)/ruby/internal/core/rhash.h -pointer.o: $(hdrdir)/ruby/internal/core/robject.h -pointer.o: $(hdrdir)/ruby/internal/core/rregexp.h -pointer.o: $(hdrdir)/ruby/internal/core/rstring.h -pointer.o: $(hdrdir)/ruby/internal/core/rstruct.h -pointer.o: $(hdrdir)/ruby/internal/core/rtypeddata.h -pointer.o: $(hdrdir)/ruby/internal/ctype.h -pointer.o: $(hdrdir)/ruby/internal/dllexport.h -pointer.o: $(hdrdir)/ruby/internal/dosish.h -pointer.o: $(hdrdir)/ruby/internal/encoding/coderange.h -pointer.o: $(hdrdir)/ruby/internal/encoding/ctype.h -pointer.o: $(hdrdir)/ruby/internal/encoding/encoding.h -pointer.o: $(hdrdir)/ruby/internal/encoding/pathname.h -pointer.o: $(hdrdir)/ruby/internal/encoding/re.h -pointer.o: $(hdrdir)/ruby/internal/encoding/sprintf.h -pointer.o: $(hdrdir)/ruby/internal/encoding/string.h -pointer.o: $(hdrdir)/ruby/internal/encoding/symbol.h -pointer.o: $(hdrdir)/ruby/internal/encoding/transcode.h -pointer.o: $(hdrdir)/ruby/internal/error.h -pointer.o: $(hdrdir)/ruby/internal/eval.h -pointer.o: $(hdrdir)/ruby/internal/event.h -pointer.o: $(hdrdir)/ruby/internal/fl_type.h -pointer.o: $(hdrdir)/ruby/internal/gc.h -pointer.o: $(hdrdir)/ruby/internal/glob.h -pointer.o: $(hdrdir)/ruby/internal/globals.h -pointer.o: $(hdrdir)/ruby/internal/has/attribute.h -pointer.o: $(hdrdir)/ruby/internal/has/builtin.h -pointer.o: $(hdrdir)/ruby/internal/has/c_attribute.h -pointer.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h -pointer.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h -pointer.o: $(hdrdir)/ruby/internal/has/extension.h -pointer.o: $(hdrdir)/ruby/internal/has/feature.h -pointer.o: $(hdrdir)/ruby/internal/has/warning.h -pointer.o: $(hdrdir)/ruby/internal/intern/array.h -pointer.o: $(hdrdir)/ruby/internal/intern/bignum.h -pointer.o: $(hdrdir)/ruby/internal/intern/class.h -pointer.o: $(hdrdir)/ruby/internal/intern/compar.h -pointer.o: $(hdrdir)/ruby/internal/intern/complex.h -pointer.o: $(hdrdir)/ruby/internal/intern/cont.h -pointer.o: $(hdrdir)/ruby/internal/intern/dir.h -pointer.o: $(hdrdir)/ruby/internal/intern/enum.h -pointer.o: $(hdrdir)/ruby/internal/intern/enumerator.h -pointer.o: $(hdrdir)/ruby/internal/intern/error.h -pointer.o: $(hdrdir)/ruby/internal/intern/eval.h -pointer.o: $(hdrdir)/ruby/internal/intern/file.h -pointer.o: $(hdrdir)/ruby/internal/intern/hash.h -pointer.o: $(hdrdir)/ruby/internal/intern/io.h -pointer.o: $(hdrdir)/ruby/internal/intern/load.h -pointer.o: $(hdrdir)/ruby/internal/intern/marshal.h -pointer.o: $(hdrdir)/ruby/internal/intern/numeric.h -pointer.o: $(hdrdir)/ruby/internal/intern/object.h -pointer.o: $(hdrdir)/ruby/internal/intern/parse.h -pointer.o: $(hdrdir)/ruby/internal/intern/proc.h -pointer.o: $(hdrdir)/ruby/internal/intern/process.h -pointer.o: $(hdrdir)/ruby/internal/intern/random.h -pointer.o: $(hdrdir)/ruby/internal/intern/range.h -pointer.o: $(hdrdir)/ruby/internal/intern/rational.h -pointer.o: $(hdrdir)/ruby/internal/intern/re.h -pointer.o: $(hdrdir)/ruby/internal/intern/ruby.h -pointer.o: $(hdrdir)/ruby/internal/intern/select.h -pointer.o: $(hdrdir)/ruby/internal/intern/select/largesize.h -pointer.o: $(hdrdir)/ruby/internal/intern/signal.h -pointer.o: $(hdrdir)/ruby/internal/intern/sprintf.h -pointer.o: $(hdrdir)/ruby/internal/intern/string.h -pointer.o: $(hdrdir)/ruby/internal/intern/struct.h -pointer.o: $(hdrdir)/ruby/internal/intern/thread.h -pointer.o: $(hdrdir)/ruby/internal/intern/time.h -pointer.o: $(hdrdir)/ruby/internal/intern/variable.h -pointer.o: $(hdrdir)/ruby/internal/intern/vm.h -pointer.o: $(hdrdir)/ruby/internal/interpreter.h -pointer.o: $(hdrdir)/ruby/internal/iterator.h -pointer.o: $(hdrdir)/ruby/internal/memory.h -pointer.o: $(hdrdir)/ruby/internal/method.h -pointer.o: $(hdrdir)/ruby/internal/module.h -pointer.o: $(hdrdir)/ruby/internal/newobj.h -pointer.o: $(hdrdir)/ruby/internal/scan_args.h -pointer.o: $(hdrdir)/ruby/internal/special_consts.h -pointer.o: $(hdrdir)/ruby/internal/static_assert.h -pointer.o: $(hdrdir)/ruby/internal/stdalign.h -pointer.o: $(hdrdir)/ruby/internal/stdbool.h -pointer.o: $(hdrdir)/ruby/internal/symbol.h -pointer.o: $(hdrdir)/ruby/internal/value.h -pointer.o: $(hdrdir)/ruby/internal/value_type.h -pointer.o: $(hdrdir)/ruby/internal/variable.h -pointer.o: $(hdrdir)/ruby/internal/warning_push.h -pointer.o: $(hdrdir)/ruby/internal/xmalloc.h -pointer.o: $(hdrdir)/ruby/io.h -pointer.o: $(hdrdir)/ruby/memory_view.h -pointer.o: $(hdrdir)/ruby/missing.h -pointer.o: $(hdrdir)/ruby/onigmo.h -pointer.o: $(hdrdir)/ruby/oniguruma.h -pointer.o: $(hdrdir)/ruby/ruby.h -pointer.o: $(hdrdir)/ruby/st.h -pointer.o: $(hdrdir)/ruby/subst.h -pointer.o: closure.h -pointer.o: conversions.h -pointer.o: fiddle.h -pointer.o: function.h -pointer.o: pointer.c -# AUTOGENERATED DEPENDENCIES END diff --git a/ext/fiddle/extconf.rb b/ext/fiddle/extconf.rb deleted file mode 100644 index cf8b5223bb85d5..00000000000000 --- a/ext/fiddle/extconf.rb +++ /dev/null @@ -1,251 +0,0 @@ -# frozen_string_literal: true -require 'mkmf' - -# :stopdoc: - -def gcc? - RbConfig::CONFIG["GCC"] == "yes" -end - -def disable_optimization_build_flag(flags) - if gcc? - expanded_flags = RbConfig.expand(flags.dup) - optimization_option_pattern = /(^|\s)?-O\d(\s|$)?/ - if optimization_option_pattern.match?(expanded_flags) - expanded_flags.gsub(optimization_option_pattern, '\\1-Og\\2') - else - flags + " -Og" - end - else - flags - end -end - -def enable_debug_build_flag(flags) - if gcc? - expanded_flags = RbConfig.expand(flags.dup) - debug_option_pattern = /(^|\s)-g(?:gdb)?\d?(\s|$)/ - if debug_option_pattern.match?(expanded_flags) - expanded_flags.gsub(debug_option_pattern, '\\1-ggdb3\\2') - else - flags + " -ggdb3" - end - else - flags - end -end - -checking_for(checking_message("--enable-debug-build option")) do - enable_debug_build = enable_config("debug-build", false) - if enable_debug_build - $CFLAGS = disable_optimization_build_flag($CFLAGS) - $CFLAGS = enable_debug_build_flag($CFLAGS) - end - enable_debug_build -end - -libffi_version = nil -have_libffi = false -bundle = with_config("libffi-source-dir") -unless bundle - dir_config 'libffi' - - if pkg_config("libffi") - libffi_version = pkg_config("libffi", "modversion") - end - - have_ffi_header = false - if have_header(ffi_header = 'ffi.h') - have_ffi_header = true - elsif have_header(ffi_header = 'ffi/ffi.h') - $defs.push('-DUSE_HEADER_HACKS') - have_ffi_header = true - end - if have_ffi_header && (have_library('ffi') || have_library('libffi')) - have_libffi = true - end -end - -unless have_libffi - if bundle - libffi_srcdir = libffi_package_name = bundle - else - raise "missing libffi. Please install libffi or use --with-libffi-source-dir with libffi source location." - end - ffi_header = 'ffi.h' - libffi = Struct.new(*%I[dir srcdir builddir include lib a cflags ldflags opt arch]).new - libffi.dir = libffi_package_name - if $srcdir == "." - libffi.builddir = libffi_package_name - libffi.srcdir = "." - else - libffi.builddir = libffi.dir - libffi.srcdir = relative_from(libffi_srcdir, "..") - end - libffi.include = "#{libffi.builddir}/include" - libffi.lib = "#{libffi.builddir}/.libs" - libffi.a = "#{libffi.lib}/libffi_convenience.#{$LIBEXT}" - nowarn = CONFIG.merge("warnflags"=>"") - libffi.cflags = RbConfig.expand("$(CFLAGS)".dup, nowarn) - libffi_version = libffi_package_name[/libffi-(.*)/, 1] - - FileUtils.mkdir_p(libffi.dir) - libffi.opt = CONFIG['configure_args'][/'(-C)'/, 1] - libffi.ldflags = RbConfig.expand("$(LDFLAGS) #{libpathflag([relative_from($topdir, "..")])} #{$LIBRUBYARG}".dup) - libffi.arch = RbConfig::CONFIG['host'] - if $mswin - unless find_executable(as = /x64/ =~ libffi.arch ? "ml64" : "ml") - raise "missing #{as} command." - end - $defs << "-DFFI_BUILDING" - libffi_config = "#{relative_from($srcdir, '..')}/win32/libffi-config.rb" - config = CONFIG.merge("top_srcdir" => $top_srcdir) - args = $ruby.gsub(/:\/=\\/, '') - args.gsub!(/\)\\/, ')/') - args = args.shellsplit - args.map! {|s| RbConfig.expand(s, config)} - args << '-C' << libffi.dir << libffi_config - opts = {} - else - args = %W[sh #{libffi.srcdir}/configure ] - opts = {chdir: libffi.dir} - end - cc = RbConfig::CONFIG['CC'] - cxx = RbConfig::CONFIG['CXX'] - ld = RbConfig::CONFIG['LD'] - args.concat %W[ - --srcdir=#{libffi.srcdir} - --host=#{libffi.arch} - ] - args << ($enable_shared || !$static ? '--enable-shared' : '--enable-static') - args << libffi.opt if libffi.opt - args.concat %W[ - CC=#{cc} CFLAGS=#{libffi.cflags} - CXX=#{cxx} CXXFLAGS=#{RbConfig.expand("$(CXXFLAGS)".dup, nowarn)} - LD=#{ld} LDFLAGS=#{libffi.ldflags} - ] - - FileUtils.rm_f("#{libffi.include}/ffitarget.h") - Logging::open do - Logging.message("%p in %p\n", args, opts) - unless system(*args, **opts) - begin - IO.copy_stream(libffi.dir + "/config.log", Logging.instance_variable_get(:@logfile)) - rescue SystemCallError => e - Logging.message("%s\n", e.message) - end - raise "failed to configure libffi. Please install libffi." - end - end - if $mswin && File.file?("#{libffi.include}/ffitarget.h") - FileUtils.rm_f("#{libffi.include}/ffitarget.h") - end - unless File.file?("#{libffi.include}/ffitarget.h") - FileUtils.cp("#{libffi_srcdir}/src/x86/ffitarget.h", libffi.include, preserve: true) - end - $INCFLAGS << " -I" << libffi.include -end - -if libffi_version - # If libffi_version contains rc version, just ignored. - libffi_version = libffi_version.gsub(/-rc\d+/, '') - libffi_version = (libffi_version.split('.').map(&:to_i) + [0,0])[0,3] - $defs.push(%{-DRUBY_LIBFFI_MODVERSION=#{ '%d%03d%03d' % libffi_version }}) - warn "libffi_version: #{libffi_version.join('.')}" -end - -case -when $mswin, $mingw, (libffi_version && (libffi_version <=> [3, 2]) >= 0) - $defs << "-DUSE_FFI_CLOSURE_ALLOC=1" -when (libffi_version && (libffi_version <=> [3, 2]) < 0) -else - have_func('ffi_closure_alloc', ffi_header) -end - -if libffi_version - if (libffi_version <=> [3, 0, 11]) >= 0 - $defs << "-DHAVE_FFI_PREP_CIF_VAR" - end -else - have_func('ffi_prep_cif_var', ffi_header) -end - -have_header 'sys/mman.h' -have_header 'link.h' - -if have_header "dlfcn.h" - have_library "dl" - - %w{ dlopen dlclose dlsym }.each do |func| - abort "missing function #{func}" unless have_func(func) - end - - have_func "dlerror" - have_func "dlinfo" - have_const("RTLD_DI_LINKMAP", "dlfcn.h") -elsif have_header "windows.h" - %w{ LoadLibrary FreeLibrary GetProcAddress GetModuleFileName }.each do |func| - abort "missing function #{func}" unless have_func(func) - end - - have_library "ws2_32" -end - -have_const('FFI_STDCALL', ffi_header) - -config = File.read(RbConfig.expand(File.join($arch_hdrdir, "ruby/config.h"))) -types = {"SIZE_T"=>"SSIZE_T", "PTRDIFF_T"=>nil, "INTPTR_T"=>nil} -types.each do |type, signed| - if /^\#define\s+SIZEOF_#{type}\s+(SIZEOF_(.+)|\d+)/ =~ config - if size = $2 and size != 'VOIDP' - size = types.fetch(size) {size} - $defs << "-DTYPE_#{signed||type}=TYPE_#{size}" - end - if signed - check_signedness(type.downcase, "stddef.h") - end - else - check_signedness(type.downcase, "stddef.h") - end -end - -if libffi - $LOCAL_LIBS.prepend("#{libffi.a} ").strip! # to exts.mk - $INCFLAGS.gsub!(/-I#{libffi.dir}/, '-I$(LIBFFI_DIR)') -end -create_makefile 'fiddle' do |conf| - if !libffi - next conf << "LIBFFI_CLEAN = none\n" - elsif $gnumake && !$nmake - submake_arg = "-C $(LIBFFI_DIR)\n" - else - submake_pre = "cd $(LIBFFI_DIR) && #{config_string("exec")}".strip - end - if $nmake - cmd = "$(RUBY) -C $(LIBFFI_DIR) #{libffi_config} --srcdir=$(LIBFFI_SRCDIR)" - else - cmd = "cd $(LIBFFI_DIR) && #$exec $(LIBFFI_SRCDIR)/configure #{libffi.opt}" - end - sep = "/" - seprpl = config_string('BUILD_FILE_SEPARATOR') {|s| sep = s; ":/=#{s}" if s != "/"} || "" - conf << <<-MK.gsub(/^ +| +$/, '') - PWD = - LIBFFI_CONFIGURE = #{cmd} - LIBFFI_ARCH = #{libffi.arch} - LIBFFI_SRCDIR = #{libffi.srcdir.sub(libffi.dir, '$(LIBFFI_DIR)')} - LIBFFI_DIR = #{libffi.dir} - LIBFFI_A = #{libffi.a.sub(libffi.dir, '$(LIBFFI_DIR)')} - LIBFFI_CFLAGS = #{libffi.cflags} - LIBFFI_LDFLAGS = #{libffi.ldflags} - FFI_H = $(LIBFFI_DIR)/include/ffi.h - SUBMAKE_PRE = #{submake_pre} - SUBMAKE_ARG = #{submake_arg} - LIBFFI_CLEAN = libffi - MK -end - -if libffi - $LIBPATH.pop -end - -# :startdoc: diff --git a/ext/fiddle/fiddle.c b/ext/fiddle/fiddle.c deleted file mode 100644 index 49120704aba184..00000000000000 --- a/ext/fiddle/fiddle.c +++ /dev/null @@ -1,706 +0,0 @@ -#include - -#include - -VALUE mFiddle; -VALUE rb_eFiddleDLError; -VALUE rb_eFiddleError; - -void Init_fiddle_pointer(void); -void Init_fiddle_pinned(void); - -#ifdef HAVE_RUBY_MEMORY_VIEW_H -void Init_fiddle_memory_view(void); -#endif - -/* - * call-seq: Fiddle.malloc(size) - * - * Allocate +size+ bytes of memory and return the integer memory address - * for the allocated memory. - */ -static VALUE -rb_fiddle_malloc(VALUE self, VALUE size) -{ - void *ptr; - ptr = (void*)ruby_xcalloc(1, NUM2SIZET(size)); - return PTR2NUM(ptr); -} - -/* - * call-seq: Fiddle.realloc(addr, size) - * - * Change the size of the memory allocated at the memory location +addr+ to - * +size+ bytes. Returns the memory address of the reallocated memory, which - * may be different than the address passed in. - */ -static VALUE -rb_fiddle_realloc(VALUE self, VALUE addr, VALUE size) -{ - void *ptr = NUM2PTR(addr); - - ptr = (void*)ruby_xrealloc(ptr, NUM2SIZET(size)); - return PTR2NUM(ptr); -} - -/* - * call-seq: Fiddle.free(addr) - * - * Free the memory at address +addr+ - */ -VALUE -rb_fiddle_free(VALUE self, VALUE addr) -{ - void *ptr = NUM2PTR(addr); - - ruby_xfree(ptr); - return Qnil; -} - -/* - * call-seq: Fiddle.dlunwrap(addr) - * - * Returns the Ruby object stored at the memory address +addr+ - * - * Example: - * - * x = Object.new - * # => # - * Fiddle.dlwrap(x) - * # => 4425504880 - * Fiddle.dlunwrap(_) - * # => # - */ -VALUE -rb_fiddle_ptr2value(VALUE self, VALUE addr) -{ - return (VALUE)NUM2PTR(addr); -} - -/* - * call-seq: Fiddle.dlwrap(val) - * - * Returns the memory address of the Ruby object stored at +val+ - * - * Example: - * - * x = Object.new - * # => # - * Fiddle.dlwrap(x) - * # => 4425504880 - * - * In the case +val+ is not a heap allocated object, this method will return - * the tagged pointer value. - * - * Example: - * - * Fiddle.dlwrap(123) - * # => 247 - */ -static VALUE -rb_fiddle_value2ptr(VALUE self, VALUE val) -{ - return PTR2NUM((void*)val); -} - -void Init_fiddle_handle(void); - -void -Init_fiddle(void) -{ - /* - * Document-module: Fiddle - * - * A libffi wrapper for Ruby. - * - * == Description - * - * Fiddle is an extension to translate a foreign function interface (FFI) - * with ruby. - * - * It wraps {libffi}[http://sourceware.org/libffi/], a popular C library - * which provides a portable interface that allows code written in one - * language to call code written in another language. - * - * == Example - * - * Here we will use Fiddle::Function to wrap {floor(3) from - * libm}[http://linux.die.net/man/3/floor] - * - * require 'fiddle' - * - * libm = Fiddle.dlopen('/lib/libm.so.6') - * - * floor = Fiddle::Function.new( - * libm['floor'], - * [Fiddle::TYPE_DOUBLE], - * Fiddle::TYPE_DOUBLE - * ) - * - * puts floor.call(3.14159) #=> 3.0 - * - * - */ - mFiddle = rb_define_module("Fiddle"); - - /* - * Document-class: Fiddle::Error - * - * Generic error class for Fiddle - */ - rb_eFiddleError = rb_define_class_under(mFiddle, "Error", rb_eStandardError); - - /* - * Ruby installed by RubyInstaller for Windows always require - * bundled Fiddle because ruby_installer/runtime/dll_directory.rb - * requires Fiddle. It's used by - * rubygems/defaults/operating_system.rb. It means that the - * bundled Fiddle is always required on initialization. - * - * We just remove existing Fiddle::DLError here to override - * the bundled Fiddle. - */ - if (rb_const_defined(mFiddle, rb_intern("DLError"))) { - rb_const_remove(mFiddle, rb_intern("DLError")); - } - - /* - * Document-class: Fiddle::DLError - * - * standard dynamic load exception - */ - rb_eFiddleDLError = rb_define_class_under(mFiddle, "DLError", rb_eFiddleError); - - VALUE mFiddleTypes = rb_define_module_under(mFiddle, "Types"); - - /* Document-const: Fiddle::Types::VOID - * - * C type - void - */ - rb_define_const(mFiddleTypes, "VOID", INT2NUM(TYPE_VOID)); - - /* Document-const: Fiddle::Types::VOIDP - * - * C type - void* - */ - rb_define_const(mFiddleTypes, "VOIDP", INT2NUM(TYPE_VOIDP)); - - /* Document-const: Fiddle::Types::CHAR - * - * C type - char - */ - rb_define_const(mFiddleTypes, "CHAR", INT2NUM(TYPE_CHAR)); - - /* Document-const: Fiddle::Types::UCHAR - * - * C type - unsigned char - */ - rb_define_const(mFiddleTypes, "UCHAR", INT2NUM(TYPE_UCHAR)); - - /* Document-const: Fiddle::Types::SHORT - * - * C type - short - */ - rb_define_const(mFiddleTypes, "SHORT", INT2NUM(TYPE_SHORT)); - - /* Document-const: Fiddle::Types::USHORT - * - * C type - unsigned short - */ - rb_define_const(mFiddleTypes, "USHORT", INT2NUM(TYPE_USHORT)); - - /* Document-const: Fiddle::Types::INT - * - * C type - int - */ - rb_define_const(mFiddleTypes, "INT", INT2NUM(TYPE_INT)); - - /* Document-const: Fiddle::Types::UINT - * - * C type - unsigned int - */ - rb_define_const(mFiddleTypes, "UINT", INT2NUM(TYPE_UINT)); - - /* Document-const: Fiddle::Types::LONG - * - * C type - long - */ - rb_define_const(mFiddleTypes, "LONG", INT2NUM(TYPE_LONG)); - - /* Document-const: Fiddle::Types::ULONG - * - * C type - long - */ - rb_define_const(mFiddleTypes, "ULONG", INT2NUM(TYPE_ULONG)); - -#if HAVE_LONG_LONG - /* Document-const: Fiddle::Types::LONG_LONG - * - * C type - long long - */ - rb_define_const(mFiddleTypes, "LONG_LONG", INT2NUM(TYPE_LONG_LONG)); - - /* Document-const: Fiddle::Types::ULONG_LONG - * - * C type - long long - */ - rb_define_const(mFiddleTypes, "ULONG_LONG", INT2NUM(TYPE_ULONG_LONG)); -#endif - -#ifdef TYPE_INT8_T - /* Document-const: Fiddle::Types::INT8_T - * - * C type - int8_t - */ - rb_define_const(mFiddleTypes, "INT8_T", INT2NUM(TYPE_INT8_T)); - - /* Document-const: Fiddle::Types::UINT8_T - * - * C type - uint8_t - */ - rb_define_const(mFiddleTypes, "UINT8_T", INT2NUM(TYPE_UINT8_T)); -#endif - -#ifdef TYPE_INT16_T - /* Document-const: Fiddle::Types::INT16_T - * - * C type - int16_t - */ - rb_define_const(mFiddleTypes, "INT16_T", INT2NUM(TYPE_INT16_T)); - - /* Document-const: Fiddle::Types::UINT16_T - * - * C type - uint16_t - */ - rb_define_const(mFiddleTypes, "UINT16_T", INT2NUM(TYPE_UINT16_T)); -#endif - -#ifdef TYPE_INT32_T - /* Document-const: Fiddle::Types::INT32_T - * - * C type - int32_t - */ - rb_define_const(mFiddleTypes, "INT32_T", INT2NUM(TYPE_INT32_T)); - - /* Document-const: Fiddle::Types::UINT32_T - * - * C type - uint32_t - */ - rb_define_const(mFiddleTypes, "UINT32_T", INT2NUM(TYPE_UINT32_T)); -#endif - -#ifdef TYPE_INT64_T - /* Document-const: Fiddle::Types::INT64_T - * - * C type - int64_t - */ - rb_define_const(mFiddleTypes, "INT64_T", INT2NUM(TYPE_INT64_T)); - - /* Document-const: Fiddle::Types::UINT64_T - * - * C type - uint64_t - */ - rb_define_const(mFiddleTypes, "UINT64_T", INT2NUM(TYPE_UINT64_T)); -#endif - - /* Document-const: Fiddle::Types::FLOAT - * - * C type - float - */ - rb_define_const(mFiddleTypes, "FLOAT", INT2NUM(TYPE_FLOAT)); - - /* Document-const: Fiddle::Types::DOUBLE - * - * C type - double - */ - rb_define_const(mFiddleTypes, "DOUBLE", INT2NUM(TYPE_DOUBLE)); - -#ifdef HAVE_FFI_PREP_CIF_VAR - /* Document-const: Fiddle::Types::VARIADIC - * - * C type - ... - */ - rb_define_const(mFiddleTypes, "VARIADIC", INT2NUM(TYPE_VARIADIC)); -#endif - - /* Document-const: Fiddle::Types::CONST_STRING - * - * C type - const char* ('\0' terminated const char*) - */ - rb_define_const(mFiddleTypes, "CONST_STRING", INT2NUM(TYPE_CONST_STRING)); - - /* Document-const: Fiddle::Types::SIZE_T - * - * C type - size_t - */ - rb_define_const(mFiddleTypes, "SIZE_T", INT2NUM(TYPE_SIZE_T)); - - /* Document-const: Fiddle::Types::SSIZE_T - * - * C type - ssize_t - */ - rb_define_const(mFiddleTypes, "SSIZE_T", INT2NUM(TYPE_SSIZE_T)); - - /* Document-const: Fiddle::Types::PTRDIFF_T - * - * C type - ptrdiff_t - */ - rb_define_const(mFiddleTypes, "PTRDIFF_T", INT2NUM(TYPE_PTRDIFF_T)); - - /* Document-const: Fiddle::Types::INTPTR_T - * - * C type - intptr_t - */ - rb_define_const(mFiddleTypes, "INTPTR_T", INT2NUM(TYPE_INTPTR_T)); - - /* Document-const: Fiddle::Types::UINTPTR_T - * - * C type - uintptr_t - */ - rb_define_const(mFiddleTypes, "UINTPTR_T", INT2NUM(TYPE_UINTPTR_T)); - - /* Document-const: Fiddle::Types::BOOL - * - * C type - bool - */ - rb_define_const(mFiddleTypes, "BOOL" , rb_fiddle_type_bool()); - - /* Document-const: ALIGN_VOIDP - * - * The alignment size of a void* - */ - rb_define_const(mFiddle, "ALIGN_VOIDP", INT2NUM(ALIGN_VOIDP)); - - /* Document-const: ALIGN_CHAR - * - * The alignment size of a char - */ - rb_define_const(mFiddle, "ALIGN_CHAR", INT2NUM(ALIGN_CHAR)); - - /* Document-const: ALIGN_SHORT - * - * The alignment size of a short - */ - rb_define_const(mFiddle, "ALIGN_SHORT", INT2NUM(ALIGN_SHORT)); - - /* Document-const: ALIGN_INT - * - * The alignment size of an int - */ - rb_define_const(mFiddle, "ALIGN_INT", INT2NUM(ALIGN_INT)); - - /* Document-const: ALIGN_LONG - * - * The alignment size of a long - */ - rb_define_const(mFiddle, "ALIGN_LONG", INT2NUM(ALIGN_LONG)); - -#if HAVE_LONG_LONG - /* Document-const: ALIGN_LONG_LONG - * - * The alignment size of a long long - */ - rb_define_const(mFiddle, "ALIGN_LONG_LONG", INT2NUM(ALIGN_LONG_LONG)); -#endif - - /* Document-const: ALIGN_INT8_T - * - * The alignment size of a int8_t - */ - rb_define_const(mFiddle, "ALIGN_INT8_T", INT2NUM(ALIGN_INT8_T)); - - /* Document-const: ALIGN_INT16_T - * - * The alignment size of a int16_t - */ - rb_define_const(mFiddle, "ALIGN_INT16_T", INT2NUM(ALIGN_INT16_T)); - - /* Document-const: ALIGN_INT32_T - * - * The alignment size of a int32_t - */ - rb_define_const(mFiddle, "ALIGN_INT32_T", INT2NUM(ALIGN_INT32_T)); - - /* Document-const: ALIGN_INT64_T - * - * The alignment size of a int64_t - */ - rb_define_const(mFiddle, "ALIGN_INT64_T", INT2NUM(ALIGN_INT64_T)); - - /* Document-const: ALIGN_FLOAT - * - * The alignment size of a float - */ - rb_define_const(mFiddle, "ALIGN_FLOAT", INT2NUM(ALIGN_FLOAT)); - - /* Document-const: ALIGN_DOUBLE - * - * The alignment size of a double - */ - rb_define_const(mFiddle, "ALIGN_DOUBLE",INT2NUM(ALIGN_DOUBLE)); - - /* Document-const: ALIGN_SIZE_T - * - * The alignment size of a size_t - */ - rb_define_const(mFiddle, "ALIGN_SIZE_T", INT2NUM(ALIGN_OF(size_t))); - - /* Document-const: ALIGN_SSIZE_T - * - * The alignment size of a ssize_t - */ - rb_define_const(mFiddle, "ALIGN_SSIZE_T", INT2NUM(ALIGN_OF(size_t))); /* same as size_t */ - - /* Document-const: ALIGN_PTRDIFF_T - * - * The alignment size of a ptrdiff_t - */ - rb_define_const(mFiddle, "ALIGN_PTRDIFF_T", INT2NUM(ALIGN_OF(ptrdiff_t))); - - /* Document-const: ALIGN_INTPTR_T - * - * The alignment size of a intptr_t - */ - rb_define_const(mFiddle, "ALIGN_INTPTR_T", INT2NUM(ALIGN_OF(intptr_t))); - - /* Document-const: ALIGN_UINTPTR_T - * - * The alignment size of a uintptr_t - */ - rb_define_const(mFiddle, "ALIGN_UINTPTR_T", INT2NUM(ALIGN_OF(uintptr_t))); - - /* Document-const: WINDOWS - * - * Returns a boolean regarding whether the host is WIN32 - */ -#if defined(_WIN32) - rb_define_const(mFiddle, "WINDOWS", Qtrue); -#else - rb_define_const(mFiddle, "WINDOWS", Qfalse); -#endif - - /* Document-const: SIZEOF_VOIDP - * - * size of a void* - */ - rb_define_const(mFiddle, "SIZEOF_VOIDP", INT2NUM(sizeof(void*))); - - /* Document-const: SIZEOF_CHAR - * - * size of a char - */ - rb_define_const(mFiddle, "SIZEOF_CHAR", INT2NUM(sizeof(char))); - - /* Document-const: SIZEOF_UCHAR - * - * size of a unsigned char - */ - rb_define_const(mFiddle, "SIZEOF_UCHAR", INT2NUM(sizeof(unsigned char))); - - /* Document-const: SIZEOF_SHORT - * - * size of a short - */ - rb_define_const(mFiddle, "SIZEOF_SHORT", INT2NUM(sizeof(short))); - - /* Document-const: SIZEOF_USHORT - * - * size of a unsigned short - */ - rb_define_const(mFiddle, "SIZEOF_USHORT", INT2NUM(sizeof(unsigned short))); - - /* Document-const: SIZEOF_INT - * - * size of an int - */ - rb_define_const(mFiddle, "SIZEOF_INT", INT2NUM(sizeof(int))); - - /* Document-const: SIZEOF_UINT - * - * size of an unsigned int - */ - rb_define_const(mFiddle, "SIZEOF_UINT", INT2NUM(sizeof(unsigned int))); - - /* Document-const: SIZEOF_LONG - * - * size of a long - */ - rb_define_const(mFiddle, "SIZEOF_LONG", INT2NUM(sizeof(long))); - - /* Document-const: SIZEOF_ULONG - * - * size of a unsigned long - */ - rb_define_const(mFiddle, "SIZEOF_ULONG", INT2NUM(sizeof(unsigned long))); - -#if HAVE_LONG_LONG - /* Document-const: SIZEOF_LONG_LONG - * - * size of a long long - */ - rb_define_const(mFiddle, "SIZEOF_LONG_LONG", INT2NUM(sizeof(LONG_LONG))); - - /* Document-const: SIZEOF_ULONG_LONG - * - * size of a unsigned long long - */ - rb_define_const(mFiddle, "SIZEOF_ULONG_LONG", INT2NUM(sizeof(unsigned LONG_LONG))); -#endif - - /* Document-const: SIZEOF_INT8_T - * - * size of a int8_t - */ - rb_define_const(mFiddle, "SIZEOF_INT8_T", INT2NUM(sizeof(int8_t))); - - /* Document-const: SIZEOF_UINT8_T - * - * size of a uint8_t - */ - rb_define_const(mFiddle, "SIZEOF_UINT8_T", INT2NUM(sizeof(uint8_t))); - - /* Document-const: SIZEOF_INT16_T - * - * size of a int16_t - */ - rb_define_const(mFiddle, "SIZEOF_INT16_T", INT2NUM(sizeof(int16_t))); - - /* Document-const: SIZEOF_UINT16_T - * - * size of a uint16_t - */ - rb_define_const(mFiddle, "SIZEOF_UINT16_T", INT2NUM(sizeof(uint16_t))); - - /* Document-const: SIZEOF_INT32_T - * - * size of a int32_t - */ - rb_define_const(mFiddle, "SIZEOF_INT32_T", INT2NUM(sizeof(int32_t))); - - /* Document-const: SIZEOF_UINT32_T - * - * size of a uint32_t - */ - rb_define_const(mFiddle, "SIZEOF_UINT32_T", INT2NUM(sizeof(uint32_t))); - - /* Document-const: SIZEOF_INT64_T - * - * size of a int64_t - */ - rb_define_const(mFiddle, "SIZEOF_INT64_T", INT2NUM(sizeof(int64_t))); - - /* Document-const: SIZEOF_UINT64_T - * - * size of a uint64_t - */ - rb_define_const(mFiddle, "SIZEOF_UINT64_T", INT2NUM(sizeof(uint64_t))); - - /* Document-const: SIZEOF_FLOAT - * - * size of a float - */ - rb_define_const(mFiddle, "SIZEOF_FLOAT", INT2NUM(sizeof(float))); - - /* Document-const: SIZEOF_DOUBLE - * - * size of a double - */ - rb_define_const(mFiddle, "SIZEOF_DOUBLE",INT2NUM(sizeof(double))); - - /* Document-const: SIZEOF_SIZE_T - * - * size of a size_t - */ - rb_define_const(mFiddle, "SIZEOF_SIZE_T", INT2NUM(sizeof(size_t))); - - /* Document-const: SIZEOF_SSIZE_T - * - * size of a ssize_t - */ - rb_define_const(mFiddle, "SIZEOF_SSIZE_T", INT2NUM(sizeof(size_t))); /* same as size_t */ - - /* Document-const: SIZEOF_PTRDIFF_T - * - * size of a ptrdiff_t - */ - rb_define_const(mFiddle, "SIZEOF_PTRDIFF_T", INT2NUM(sizeof(ptrdiff_t))); - - /* Document-const: SIZEOF_INTPTR_T - * - * size of a intptr_t - */ - rb_define_const(mFiddle, "SIZEOF_INTPTR_T", INT2NUM(sizeof(intptr_t))); - - /* Document-const: SIZEOF_UINTPTR_T - * - * size of a uintptr_t - */ - rb_define_const(mFiddle, "SIZEOF_UINTPTR_T", INT2NUM(sizeof(uintptr_t))); - - /* Document-const: SIZEOF_CONST_STRING - * - * size of a const char* - */ - rb_define_const(mFiddle, "SIZEOF_CONST_STRING", INT2NUM(sizeof(const char*))); - - /* Document-const: SIZEOF_BOOL - * - * size of a bool - */ - rb_define_const(mFiddle, "SIZEOF_BOOL", INT2NUM(sizeof(bool))); - - /* Document-const: RUBY_FREE - * - * Address of the ruby_xfree() function - */ - rb_define_const(mFiddle, "RUBY_FREE", PTR2NUM(ruby_xfree)); - - /* Document-const: BUILD_RUBY_PLATFORM - * - * Platform built against (i.e. "x86_64-linux", etc.) - * - * See also RUBY_PLATFORM - */ - rb_define_const(mFiddle, "BUILD_RUBY_PLATFORM", rb_str_new2(RUBY_PLATFORM)); - - rb_define_module_function(mFiddle, "dlwrap", rb_fiddle_value2ptr, 1); - rb_define_module_function(mFiddle, "dlunwrap", rb_fiddle_ptr2value, 1); - rb_define_module_function(mFiddle, "malloc", rb_fiddle_malloc, 1); - rb_define_module_function(mFiddle, "realloc", rb_fiddle_realloc, 2); - rb_define_module_function(mFiddle, "free", rb_fiddle_free, 1); - - /* Document-const: Qtrue - * - * The value of Qtrue - */ - rb_define_const(mFiddle, "Qtrue", INT2NUM(Qtrue)); - - /* Document-const: Qfalse - * - * The value of Qfalse - */ - rb_define_const(mFiddle, "Qfalse", INT2NUM(Qfalse)); - - /* Document-const: Qnil - * - * The value of Qnil - */ - rb_define_const(mFiddle, "Qnil", INT2NUM(Qnil)); - - /* Document-const: Qundef - * - * The value of Qundef - */ - rb_define_const(mFiddle, "Qundef", INT2NUM(Qundef)); - - Init_fiddle_function(); - Init_fiddle_closure(); - Init_fiddle_handle(); - Init_fiddle_pointer(); - Init_fiddle_pinned(); - -#ifdef HAVE_RUBY_MEMORY_VIEW_H - Init_fiddle_memory_view(); -#endif -} -/* vim: set noet sws=4 sw=4: */ diff --git a/ext/fiddle/fiddle.gemspec b/ext/fiddle/fiddle.gemspec deleted file mode 100644 index 878109395bf77c..00000000000000 --- a/ext/fiddle/fiddle.gemspec +++ /dev/null @@ -1,59 +0,0 @@ -# frozen_string_literal: true - -version_module = Module.new do - version_rb = File.join(__dir__, "lib/fiddle/version.rb") - module_eval(File.read(version_rb), version_rb, __LINE__) -end - -Gem::Specification.new do |spec| - spec.name = "fiddle" - spec.version = version_module::Fiddle::VERSION - spec.authors = ["Aaron Patterson", "SHIBATA Hiroshi"] - spec.email = ["aaron@tenderlovemaking.com", "hsbt@ruby-lang.org"] - - spec.summary = %q{A libffi wrapper for Ruby.} - spec.description = %q{A libffi wrapper for Ruby.} - spec.homepage = "https://github.com/ruby/fiddle" - spec.licenses = ["Ruby", "BSD-2-Clause"] - - spec.files = [ - "LICENSE.txt", - "README.md", - "Rakefile", - "ext/fiddle/closure.c", - "ext/fiddle/closure.h", - "ext/fiddle/conversions.c", - "ext/fiddle/conversions.h", - "ext/fiddle/depend", - "ext/fiddle/extconf.rb", - "ext/fiddle/fiddle.c", - "ext/fiddle/fiddle.h", - "ext/fiddle/function.c", - "ext/fiddle/function.h", - "ext/fiddle/handle.c", - "ext/fiddle/memory_view.c", - "ext/fiddle/pinned.c", - "ext/fiddle/pointer.c", - "ext/fiddle/win32/fficonfig.h", - "ext/fiddle/win32/libffi-3.2.1-mswin.patch", - "ext/fiddle/win32/libffi-config.rb", - "ext/fiddle/win32/libffi.mk.tmpl", - "fiddle.gemspec", - "lib/fiddle.rb", - "lib/fiddle/closure.rb", - "lib/fiddle/cparser.rb", - "lib/fiddle/function.rb", - "lib/fiddle/import.rb", - "lib/fiddle/pack.rb", - "lib/fiddle/struct.rb", - "lib/fiddle/types.rb", - "lib/fiddle/value.rb", - "lib/fiddle/version.rb", - ] - spec.require_paths = ["lib"] - spec.extensions = ["ext/fiddle/extconf.rb"] - - spec.required_ruby_version = ">= 2.5.0" - - spec.metadata["msys2_mingw_dependencies"] = "libffi" -end diff --git a/ext/fiddle/fiddle.h b/ext/fiddle/fiddle.h deleted file mode 100644 index 53db0588079a55..00000000000000 --- a/ext/fiddle/fiddle.h +++ /dev/null @@ -1,239 +0,0 @@ -#ifndef FIDDLE_H -#define FIDDLE_H - -#include -#include - -#if defined(_WIN32) -#include -#endif - -#ifdef HAVE_SYS_MMAN_H -#include -#endif - -#if defined(HAVE_LINK_H) -# include -#endif - -#if defined(HAVE_DLFCN_H) -# include -# /* some stranger systems may not define all of these */ -#ifndef RTLD_LAZY -#define RTLD_LAZY 0 -#endif -#ifndef RTLD_GLOBAL -#define RTLD_GLOBAL 0 -#endif -#ifndef RTLD_NOW -#define RTLD_NOW 0 -#endif -#else -# if defined(_WIN32) -# include -# define dlopen(name,flag) ((void*)LoadLibrary(name)) -# define dlerror() strerror(rb_w32_map_errno(GetLastError())) -# define dlsym(handle,name) ((void*)GetProcAddress((handle),(name))) -# define RTLD_LAZY -1 -# define RTLD_NOW -1 -# define RTLD_GLOBAL -1 -# endif -#endif - -#ifdef USE_HEADER_HACKS -#include -#else -#include -#endif - -#undef ffi_type_uchar -#undef ffi_type_schar -#undef ffi_type_ushort -#undef ffi_type_sshort -#undef ffi_type_uint -#undef ffi_type_sint -#undef ffi_type_ulong -#undef ffi_type_slong - -#if CHAR_BIT == 8 -# define ffi_type_uchar ffi_type_uint8 -# define ffi_type_schar ffi_type_sint8 -#else -# error "CHAR_BIT not supported" -#endif - -#if SIZEOF_SHORT == 2 -# define ffi_type_ushort ffi_type_uint16 -# define ffi_type_sshort ffi_type_sint16 -#elif SIZEOF_SHORT == 4 -# define ffi_type_ushort ffi_type_uint32 -# define ffi_type_sshort ffi_type_sint32 -#else -# error "short size not supported" -#endif - -#if SIZEOF_INT == 2 -# define ffi_type_uint ffi_type_uint16 -# define ffi_type_sint ffi_type_sint16 -#elif SIZEOF_INT == 4 -# define ffi_type_uint ffi_type_uint32 -# define ffi_type_sint ffi_type_sint32 -#elif SIZEOF_INT == 8 -# define ffi_type_uint ffi_type_uint64 -# define ffi_type_sint ffi_type_sint64 -#else -# error "int size not supported" -#endif - -#if SIZEOF_LONG == 4 -# define ffi_type_ulong ffi_type_uint32 -# define ffi_type_slong ffi_type_sint32 -#elif SIZEOF_LONG == 8 -# define ffi_type_ulong ffi_type_uint64 -# define ffi_type_slong ffi_type_sint64 -#else -# error "long size not supported" -#endif - -#if HAVE_LONG_LONG -# if SIZEOF_LONG_LONG == 8 -# define ffi_type_slong_long ffi_type_sint64 -# define ffi_type_ulong_long ffi_type_uint64 -# else -# error "long long size not supported" -# endif -#endif - -#include -#include -#include - -#define TYPE_VOID 0 -#define TYPE_VOIDP 1 -#define TYPE_CHAR 2 -#define TYPE_UCHAR -TYPE_CHAR -#define TYPE_SHORT 3 -#define TYPE_USHORT -TYPE_SHORT -#define TYPE_INT 4 -#define TYPE_UINT -TYPE_INT -#define TYPE_LONG 5 -#define TYPE_ULONG -TYPE_LONG -#ifdef HAVE_LONG_LONG -#define TYPE_LONG_LONG 6 -#define TYPE_ULONG_LONG -TYPE_LONG_LONG -#endif -#define TYPE_FLOAT 7 -#define TYPE_DOUBLE 8 -#define TYPE_VARIADIC 9 -#define TYPE_CONST_STRING 10 - -#define TYPE_INT8_T TYPE_CHAR -#define TYPE_UINT8_T -TYPE_INT8_T - -#if SIZEOF_SHORT == 2 -# define TYPE_INT16_T TYPE_SHORT -#elif SIZEOF_INT == 2 -# define TYPE_INT16_T TYPE_INT -#endif - -#ifdef TYPE_INT16_T -# define TYPE_UINT16_T -TYPE_INT16_T -#endif - -#if SIZEOF_SHORT == 4 -# define TYPE_INT32_T TYPE_SHORT -#elif SIZEOF_INT == 4 -# define TYPE_INT32_T TYPE_INT -#elif SIZEOF_LONG == 4 -# define TYPE_INT32_T TYPE_LONG -#endif - -#ifdef TYPE_INT32_T -#define TYPE_UINT32_T -TYPE_INT32_T -#endif - -#if SIZEOF_INT == 8 -# define TYPE_INT64_T TYPE_INT -#elif SIZEOF_LONG == 8 -# define TYPE_INT64_T TYPE_LONG -#elif defined(TYPE_LONG_LONG) -# define TYPE_INT64_T TYPE_LONG_LONG -#endif - -#ifdef TYPE_INT64_T -#define TYPE_UINT64_T -TYPE_INT64_T -#endif - -#ifndef TYPE_SSIZE_T -# if SIZEOF_SIZE_T == SIZEOF_INT -# define TYPE_SSIZE_T TYPE_INT -# elif SIZEOF_SIZE_T == SIZEOF_LONG -# define TYPE_SSIZE_T TYPE_LONG -# elif defined HAVE_LONG_LONG && SIZEOF_SIZE_T == SIZEOF_LONG_LONG -# define TYPE_SSIZE_T TYPE_LONG_LONG -# endif -#endif -#define TYPE_SIZE_T (-1*SIGNEDNESS_OF_SIZE_T*TYPE_SSIZE_T) - -#ifndef TYPE_PTRDIFF_T -# if SIZEOF_PTRDIFF_T == SIZEOF_INT -# define TYPE_PTRDIFF_T TYPE_INT -# elif SIZEOF_PTRDIFF_T == SIZEOF_LONG -# define TYPE_PTRDIFF_T TYPE_LONG -# elif defined HAVE_LONG_LONG && SIZEOF_PTRDIFF_T == SIZEOF_LONG_LONG -# define TYPE_PTRDIFF_T TYPE_LONG_LONG -# endif -#endif - -#ifndef TYPE_INTPTR_T -# if SIZEOF_INTPTR_T == SIZEOF_INT -# define TYPE_INTPTR_T TYPE_INT -# elif SIZEOF_INTPTR_T == SIZEOF_LONG -# define TYPE_INTPTR_T TYPE_LONG -# elif defined HAVE_LONG_LONG && SIZEOF_INTPTR_T == SIZEOF_LONG_LONG -# define TYPE_INTPTR_T TYPE_LONG_LONG -# endif -#endif -#define TYPE_UINTPTR_T (-TYPE_INTPTR_T) - -/* GCC releases before GCC 4.9 had a bug in _Alignof. See GCC bug 52023 - . - clang versions < 8.0.0 have the same bug. */ -#if defined(HAVE__ALIGNOF) -# /* Autoconf detected availability of a sane `_Alignof()`. */ -# define ALIGN_OF(type) RB_GNUC_EXTENSION(_Alignof(type)) -#elif (!defined(__STDC_VERSION__) || __STDC_VERSION__ < 201112 \ - || (defined(__GNUC__) && __GNUC__ < 4 + (__GNUC_MINOR__ < 9) \ - && !defined(__clang__)) \ - || (defined(__clang__) && __clang_major__ < 8)) -# define ALIGN_OF(type) offsetof(struct {char align_c; type align_x;}, align_x) -#else -# define ALIGN_OF(type) _Alignof(type) -#endif - -#define ALIGN_VOIDP ALIGN_OF(void*) -#define ALIGN_CHAR ALIGN_OF(char) -#define ALIGN_SHORT ALIGN_OF(short) -#define ALIGN_INT ALIGN_OF(int) -#define ALIGN_LONG ALIGN_OF(long) -#if HAVE_LONG_LONG -#define ALIGN_LONG_LONG ALIGN_OF(LONG_LONG) -#endif -#define ALIGN_FLOAT ALIGN_OF(float) -#define ALIGN_DOUBLE ALIGN_OF(double) - -#define ALIGN_INT8_T ALIGN_OF(int8_t) -#define ALIGN_INT16_T ALIGN_OF(int16_t) -#define ALIGN_INT32_T ALIGN_OF(int32_t) -#define ALIGN_INT64_T ALIGN_OF(int64_t) - -extern VALUE mFiddle; -extern VALUE rb_eFiddleDLError; - -VALUE rb_fiddle_new_function(VALUE address, VALUE arg_types, VALUE ret_type); - -typedef void (*rb_fiddle_freefunc_t)(void*); -VALUE rb_fiddle_ptr_new_wrap(void *ptr, long size, rb_fiddle_freefunc_t func, VALUE wrap0, VALUE wrap1); - -#endif -/* vim: set noet sws=4 sw=4: */ diff --git a/ext/fiddle/function.c b/ext/fiddle/function.c deleted file mode 100644 index 5469e09e371644..00000000000000 --- a/ext/fiddle/function.c +++ /dev/null @@ -1,496 +0,0 @@ -#include -#include - -#include - -#ifdef PRIsVALUE -# define RB_OBJ_CLASSNAME(obj) rb_obj_class(obj) -# define RB_OBJ_STRING(obj) (obj) -#else -# define PRIsVALUE "s" -# define RB_OBJ_CLASSNAME(obj) rb_obj_classname(obj) -# define RB_OBJ_STRING(obj) StringValueCStr(obj) -#endif - -VALUE cFiddleFunction; - -#define MAX_ARGS (SIZE_MAX / (sizeof(void *) + sizeof(fiddle_generic)) - 1) - -#define Check_Max_Args(name, len) \ - Check_Max_Args_(name, len, "") -#define Check_Max_Args_Long(name, len) \ - Check_Max_Args_(name, len, "l") -#define Check_Max_Args_(name, len, fmt) \ - do { \ - if ((size_t)(len) >= MAX_ARGS) { \ - rb_raise(rb_eTypeError, \ - "%s is so large " \ - "that it can cause integer overflow (%"fmt"d)", \ - (name), (len)); \ - } \ - } while (0) - -static void -deallocate(void *p) -{ - ffi_cif *cif = p; - if (cif->arg_types) xfree(cif->arg_types); - xfree(cif); -} - -static size_t -function_memsize(const void *p) -{ - /* const */ffi_cif *ptr = (ffi_cif *)p; - size_t size = 0; - - size += sizeof(*ptr); -#if !defined(FFI_NO_RAW_API) || !FFI_NO_RAW_API - size += ffi_raw_size(ptr); -#endif - - return size; -} - -const rb_data_type_t function_data_type = { - .wrap_struct_name = "fiddle/function", - .function = { - .dmark = 0, - .dfree = deallocate, - .dsize = function_memsize - }, - .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED, -}; - -static VALUE -allocate(VALUE klass) -{ - ffi_cif * cif; - - return TypedData_Make_Struct(klass, ffi_cif, &function_data_type, cif); -} - -VALUE -rb_fiddle_new_function(VALUE address, VALUE arg_types, VALUE ret_type) -{ - VALUE argv[3]; - - argv[0] = address; - argv[1] = arg_types; - argv[2] = ret_type; - - return rb_class_new_instance(3, argv, cFiddleFunction); -} - -static VALUE -normalize_argument_types(const char *name, - VALUE arg_types, - bool *is_variadic) -{ - VALUE normalized_arg_types; - int i; - int n_arg_types; - *is_variadic = false; - - Check_Type(arg_types, T_ARRAY); - n_arg_types = RARRAY_LENINT(arg_types); - Check_Max_Args(name, n_arg_types); - - normalized_arg_types = rb_ary_new_capa(n_arg_types); - for (i = 0; i < n_arg_types; i++) { - VALUE arg_type = RARRAY_AREF(arg_types, i); - int c_arg_type; - arg_type = rb_fiddle_type_ensure(arg_type); - c_arg_type = NUM2INT(arg_type); - if (c_arg_type == TYPE_VARIADIC) { - if (i != n_arg_types - 1) { - rb_raise(rb_eArgError, - "Fiddle::TYPE_VARIADIC must be the last argument type: " - "%"PRIsVALUE, - arg_types); - } - *is_variadic = true; - break; - } - else { - (void)INT2FFI_TYPE(c_arg_type); /* raise */ - } - rb_ary_push(normalized_arg_types, INT2FIX(c_arg_type)); - } - - /* freeze to prevent inconsistency at calling #to_int later */ - OBJ_FREEZE(normalized_arg_types); - return normalized_arg_types; -} - -static VALUE -initialize(int argc, VALUE argv[], VALUE self) -{ - ffi_cif * cif; - VALUE ptr, arg_types, ret_type, abi, kwargs; - VALUE name = Qnil; - VALUE need_gvl = Qfalse; - int c_ret_type; - bool is_variadic = false; - ffi_abi c_ffi_abi; - void *cfunc; - - rb_scan_args(argc, argv, "31:", &ptr, &arg_types, &ret_type, &abi, &kwargs); - rb_iv_set(self, "@closure", ptr); - - if (!NIL_P(kwargs)) { - enum { - kw_name, - kw_need_gvl, - kw_max_, - }; - static ID kw[kw_max_]; - VALUE args[kw_max_]; - if (!kw[0]) { - kw[kw_name] = rb_intern_const("name"); - kw[kw_need_gvl] = rb_intern_const("need_gvl"); - } - rb_get_kwargs(kwargs, kw, 0, kw_max_, args); - if (args[kw_name] != Qundef) { - name = args[kw_name]; - } - if (args[kw_need_gvl] != Qundef) { - need_gvl = args[kw_need_gvl]; - } - } - rb_iv_set(self, "@name", name); - rb_iv_set(self, "@need_gvl", need_gvl); - - ptr = rb_Integer(ptr); - cfunc = NUM2PTR(ptr); - PTR2NUM(cfunc); - c_ffi_abi = NIL_P(abi) ? FFI_DEFAULT_ABI : NUM2INT(abi); - abi = INT2FIX(c_ffi_abi); - ret_type = rb_fiddle_type_ensure(ret_type); - c_ret_type = NUM2INT(ret_type); - (void)INT2FFI_TYPE(c_ret_type); /* raise */ - ret_type = INT2FIX(c_ret_type); - - arg_types = normalize_argument_types("argument types", - arg_types, - &is_variadic); -#ifndef HAVE_FFI_PREP_CIF_VAR - if (is_variadic) { - rb_raise(rb_eNotImpError, - "ffi_prep_cif_var() is required in libffi " - "for variadic arguments"); - } -#endif - - rb_iv_set(self, "@ptr", ptr); - rb_iv_set(self, "@argument_types", arg_types); - rb_iv_set(self, "@return_type", ret_type); - rb_iv_set(self, "@abi", abi); - rb_iv_set(self, "@is_variadic", is_variadic ? Qtrue : Qfalse); - - TypedData_Get_Struct(self, ffi_cif, &function_data_type, cif); - cif->arg_types = NULL; - - return self; -} - -struct nogvl_ffi_call_args { - ffi_cif *cif; - void (*fn)(void); - void **values; - fiddle_generic retval; -}; - -static void * -nogvl_ffi_call(void *ptr) -{ - struct nogvl_ffi_call_args *args = ptr; - - ffi_call(args->cif, args->fn, &args->retval, args->values); - - return NULL; -} - -static VALUE -function_call(int argc, VALUE argv[], VALUE self) -{ - struct nogvl_ffi_call_args args = { 0 }; - fiddle_generic *generic_args; - VALUE cfunc; - VALUE abi; - VALUE arg_types; - VALUE cPointer; - VALUE is_variadic; - VALUE need_gvl; - int n_arg_types; - int n_fixed_args = 0; - int n_call_args = 0; - int i; - int i_call; - VALUE converted_args = Qnil; - VALUE alloc_buffer = 0; - - cfunc = rb_iv_get(self, "@ptr"); - abi = rb_iv_get(self, "@abi"); - arg_types = rb_iv_get(self, "@argument_types"); - cPointer = rb_const_get(mFiddle, rb_intern("Pointer")); - is_variadic = rb_iv_get(self, "@is_variadic"); - need_gvl = rb_iv_get(self, "@need_gvl"); - - n_arg_types = RARRAY_LENINT(arg_types); - n_fixed_args = n_arg_types; - if (RTEST(is_variadic)) { - if (argc < n_arg_types) { - rb_error_arity(argc, n_arg_types, UNLIMITED_ARGUMENTS); - } - if (((argc - n_arg_types) % 2) != 0) { - rb_raise(rb_eArgError, - "variadic arguments must be type and value pairs: " - "%"PRIsVALUE, - rb_ary_new_from_values(argc, argv)); - } - n_call_args = n_arg_types + ((argc - n_arg_types) / 2); - } - else { - if (argc != n_arg_types) { - rb_error_arity(argc, n_arg_types, n_arg_types); - } - n_call_args = n_arg_types; - } - Check_Max_Args("the number of arguments", n_call_args); - - TypedData_Get_Struct(self, ffi_cif, &function_data_type, args.cif); - - if (is_variadic && args.cif->arg_types) { - xfree(args.cif->arg_types); - args.cif->arg_types = NULL; - } - - if (!args.cif->arg_types) { - VALUE fixed_arg_types = arg_types; - VALUE return_type; - int c_return_type; - ffi_type *ffi_return_type; - ffi_type **ffi_arg_types; - ffi_status result; - - arg_types = rb_ary_dup(fixed_arg_types); - for (i = n_fixed_args; i < argc; i += 2) { - VALUE arg_type = argv[i]; - int c_arg_type; - arg_type = rb_fiddle_type_ensure(arg_type); - c_arg_type = NUM2INT(arg_type); - (void)INT2FFI_TYPE(c_arg_type); /* raise */ - rb_ary_push(arg_types, INT2FIX(c_arg_type)); - } - - return_type = rb_iv_get(self, "@return_type"); - c_return_type = FIX2INT(return_type); - ffi_return_type = INT2FFI_TYPE(c_return_type); - - ffi_arg_types = xcalloc(n_call_args + 1, sizeof(ffi_type *)); - for (i_call = 0; i_call < n_call_args; i_call++) { - VALUE arg_type; - int c_arg_type; - arg_type = RARRAY_AREF(arg_types, i_call); - c_arg_type = FIX2INT(arg_type); - ffi_arg_types[i_call] = INT2FFI_TYPE(c_arg_type); - } - ffi_arg_types[i_call] = NULL; - - if (is_variadic) { -#ifdef HAVE_FFI_PREP_CIF_VAR - result = ffi_prep_cif_var(args.cif, - FIX2INT(abi), - n_fixed_args, - n_call_args, - ffi_return_type, - ffi_arg_types); -#else - /* This code is never used because ffi_prep_cif_var() - * availability check is done in #initialize. */ - result = FFI_BAD_TYPEDEF; -#endif - } - else { - result = ffi_prep_cif(args.cif, - FIX2INT(abi), - n_call_args, - ffi_return_type, - ffi_arg_types); - } - if (result != FFI_OK) { - xfree(ffi_arg_types); - args.cif->arg_types = NULL; - rb_raise(rb_eRuntimeError, "error creating CIF %d", result); - } - } - - generic_args = ALLOCV(alloc_buffer, - sizeof(fiddle_generic) * n_call_args + - sizeof(void *) * (n_call_args + 1)); - args.values = (void **)((char *)generic_args + - sizeof(fiddle_generic) * n_call_args); - - for (i = 0, i_call = 0; - i < argc && i_call < n_call_args; - i++, i_call++) { - VALUE arg_type; - int c_arg_type; - VALUE original_src; - VALUE src; - arg_type = RARRAY_AREF(arg_types, i_call); - c_arg_type = FIX2INT(arg_type); - if (i >= n_fixed_args) { - i++; - } - src = argv[i]; - - if (c_arg_type == TYPE_VOIDP) { - if (NIL_P(src)) { - src = INT2FIX(0); - } - else if (cPointer != CLASS_OF(src)) { - src = rb_funcall(cPointer, rb_intern("[]"), 1, src); - if (NIL_P(converted_args)) { - converted_args = rb_ary_new(); - } - rb_ary_push(converted_args, src); - } - src = rb_Integer(src); - } - - original_src = src; - VALUE2GENERIC(c_arg_type, src, &generic_args[i_call]); - if (src != original_src) { - if (NIL_P(converted_args)) { - converted_args = rb_ary_new(); - } - rb_ary_push(converted_args, src); - } - args.values[i_call] = (void *)&generic_args[i_call]; - } - args.values[i_call] = NULL; - args.fn = (void(*)(void))NUM2PTR(cfunc); - - if (RTEST(need_gvl)) { - ffi_call(args.cif, args.fn, &(args.retval), args.values); - } - else { - (void)rb_thread_call_without_gvl(nogvl_ffi_call, &args, 0, 0); - } - - { - int errno_keep = errno; -#if defined(_WIN32) - DWORD error = WSAGetLastError(); - int socket_error = WSAGetLastError(); - rb_funcall(mFiddle, rb_intern("win32_last_error="), 1, - ULONG2NUM(error)); - rb_funcall(mFiddle, rb_intern("win32_last_socket_error="), 1, - INT2NUM(socket_error)); -#endif - rb_funcall(mFiddle, rb_intern("last_error="), 1, INT2NUM(errno_keep)); - } - - ALLOCV_END(alloc_buffer); - - return GENERIC2VALUE(rb_iv_get(self, "@return_type"), args.retval); -} - -void -Init_fiddle_function(void) -{ - /* - * Document-class: Fiddle::Function - * - * == Description - * - * A representation of a C function - * - * == Examples - * - * === 'strcpy' - * - * @libc = Fiddle.dlopen "/lib/libc.so.6" - * #=> # - * f = Fiddle::Function.new( - * @libc['strcpy'], - * [Fiddle::TYPE_VOIDP, Fiddle::TYPE_VOIDP], - * Fiddle::TYPE_VOIDP) - * #=> # - * buff = "000" - * #=> "000" - * str = f.call(buff, "123") - * #=> # - * str.to_s - * => "123" - * - * === ABI check - * - * @libc = Fiddle.dlopen "/lib/libc.so.6" - * #=> # - * f = Fiddle::Function.new(@libc['strcpy'], [TYPE_VOIDP, TYPE_VOIDP], TYPE_VOIDP) - * #=> # - * f.abi == Fiddle::Function::DEFAULT - * #=> true - */ - cFiddleFunction = rb_define_class_under(mFiddle, "Function", rb_cObject); - - /* - * Document-const: DEFAULT - * - * Default ABI - * - */ - rb_define_const(cFiddleFunction, "DEFAULT", INT2NUM(FFI_DEFAULT_ABI)); - -#ifdef HAVE_CONST_FFI_STDCALL - /* - * Document-const: STDCALL - * - * FFI implementation of WIN32 stdcall convention - * - */ - rb_define_const(cFiddleFunction, "STDCALL", INT2NUM(FFI_STDCALL)); -#endif - - rb_define_alloc_func(cFiddleFunction, allocate); - - /* - * Document-method: call - * - * Calls the constructed Function, with +args+. - * Caller must ensure the underlying function is called in a - * thread-safe manner if running in a multi-threaded process. - * - * Note that it is not thread-safe to use this method to - * directly or indirectly call many Ruby C-extension APIs unless - * you don't pass +need_gvl: true+ to Fiddle::Function#new. - * - * For an example see Fiddle::Function - * - */ - rb_define_method(cFiddleFunction, "call", function_call, -1); - - /* - * Document-method: new - * call-seq: new(ptr, - * args, - * ret_type, - * abi = DEFAULT, - * name: nil, - * need_gvl: false) - * - * Constructs a Function object. - * * +ptr+ is a referenced function, of a Fiddle::Handle - * * +args+ is an Array of arguments, passed to the +ptr+ function - * * +ret_type+ is the return type of the function - * * +abi+ is the ABI of the function - * * +name+ is the name of the function - * * +need_gvl+ is whether GVL is needed to call the function - * - */ - rb_define_method(cFiddleFunction, "initialize", initialize, -1); -} -/* vim: set noet sws=4 sw=4: */ diff --git a/ext/fiddle/function.h b/ext/fiddle/function.h deleted file mode 100644 index 829e592c8ad37a..00000000000000 --- a/ext/fiddle/function.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef FIDDLE_FUNCTION_H -#define FIDDLE_FUNCTION_H - -#include - -void Init_fiddle_function(void); - -#endif diff --git a/ext/fiddle/handle.c b/ext/fiddle/handle.c deleted file mode 100644 index 8ba416952a3fa2..00000000000000 --- a/ext/fiddle/handle.c +++ /dev/null @@ -1,591 +0,0 @@ -#include -#include - -VALUE rb_cHandle; - -struct dl_handle { - void *ptr; - int open; - int enable_close; -}; - -#ifdef _WIN32 -# ifndef _WIN32_WCE -static void * -w32_coredll(void) -{ - MEMORY_BASIC_INFORMATION m; - memset(&m, 0, sizeof(m)); - if( !VirtualQuery(_errno, &m, sizeof(m)) ) return NULL; - return m.AllocationBase; -} -# endif - -static int -w32_dlclose(void *ptr) -{ -# ifndef _WIN32_WCE - if( ptr == w32_coredll() ) return 0; -# endif - if( FreeLibrary((HMODULE)ptr) ) return 0; - return errno = rb_w32_map_errno(GetLastError()); -} -#define dlclose(ptr) w32_dlclose(ptr) -#endif - -static void -fiddle_handle_free(void *ptr) -{ - struct dl_handle *fiddle_handle = ptr; - if( fiddle_handle->ptr && fiddle_handle->open && fiddle_handle->enable_close ){ - dlclose(fiddle_handle->ptr); - } - xfree(ptr); -} - -static size_t -fiddle_handle_memsize(const void *ptr) -{ - return sizeof(struct dl_handle); -} - -static const rb_data_type_t fiddle_handle_data_type = { - .wrap_struct_name = "fiddle/handle", - .function = { - .dmark = 0, - .dfree = fiddle_handle_free, - .dsize = fiddle_handle_memsize - }, - .flags = RUBY_TYPED_WB_PROTECTED, -}; - -/* - * call-seq: close - * - * Close this handle. - * - * Calling close more than once will raise a Fiddle::DLError exception. - */ -static VALUE -rb_fiddle_handle_close(VALUE self) -{ - struct dl_handle *fiddle_handle; - - TypedData_Get_Struct(self, struct dl_handle, &fiddle_handle_data_type, fiddle_handle); - if(fiddle_handle->open) { - int ret = dlclose(fiddle_handle->ptr); - fiddle_handle->open = 0; - - /* Check dlclose for successful return value */ - if(ret) { -#if defined(HAVE_DLERROR) - rb_raise(rb_eFiddleDLError, "%s", dlerror()); -#else - rb_raise(rb_eFiddleDLError, "could not close handle"); -#endif - } - return INT2NUM(ret); - } - rb_raise(rb_eFiddleDLError, "dlclose() called too many times"); - - UNREACHABLE; -} - -static VALUE -rb_fiddle_handle_s_allocate(VALUE klass) -{ - VALUE obj; - struct dl_handle *fiddle_handle; - - obj = TypedData_Make_Struct(rb_cHandle, struct dl_handle, &fiddle_handle_data_type, fiddle_handle); - fiddle_handle->ptr = 0; - fiddle_handle->open = 0; - fiddle_handle->enable_close = 0; - - return obj; -} - -static VALUE -predefined_fiddle_handle(void *handle) -{ - VALUE obj = rb_fiddle_handle_s_allocate(rb_cHandle); - struct dl_handle *fiddle_handle = DATA_PTR(obj); - - fiddle_handle->ptr = handle; - fiddle_handle->open = 1; - OBJ_FREEZE(obj); - return obj; -} - -/* - * call-seq: - * new(library = nil, flags = Fiddle::RTLD_LAZY | Fiddle::RTLD_GLOBAL) - * - * Create a new handler that opens +library+ with +flags+. - * - * If no +library+ is specified or +nil+ is given, DEFAULT is used, which is - * the equivalent to RTLD_DEFAULT. See man 3 dlopen for more. - * - * lib = Fiddle::Handle.new - * - * The default is dependent on OS, and provide a handle for all libraries - * already loaded. For example, in most cases you can use this to access +libc+ - * functions, or ruby functions like +rb_str_new+. - */ -static VALUE -rb_fiddle_handle_initialize(int argc, VALUE argv[], VALUE self) -{ - void *ptr; - struct dl_handle *fiddle_handle; - VALUE lib, flag; - char *clib; - int cflag; - const char *err; - - switch( rb_scan_args(argc, argv, "02", &lib, &flag) ){ - case 0: - clib = NULL; - cflag = RTLD_LAZY | RTLD_GLOBAL; - break; - case 1: - clib = NIL_P(lib) ? NULL : StringValueCStr(lib); - cflag = RTLD_LAZY | RTLD_GLOBAL; - break; - case 2: - clib = NIL_P(lib) ? NULL : StringValueCStr(lib); - cflag = NUM2INT(flag); - break; - default: - rb_bug("rb_fiddle_handle_new"); - } - -#if defined(_WIN32) - if( !clib ){ - HANDLE rb_libruby_handle(void); - ptr = rb_libruby_handle(); - } - else if( STRCASECMP(clib, "libc") == 0 -# ifdef RUBY_COREDLL - || STRCASECMP(clib, RUBY_COREDLL) == 0 - || STRCASECMP(clib, RUBY_COREDLL".dll") == 0 -# endif - ){ -# ifdef _WIN32_WCE - ptr = dlopen("coredll.dll", cflag); -# else - (void)cflag; - ptr = w32_coredll(); -# endif - } - else -#endif - ptr = dlopen(clib, cflag); -#if defined(HAVE_DLERROR) - if( !ptr && (err = dlerror()) ){ - rb_raise(rb_eFiddleDLError, "%s", err); - } -#else - if( !ptr ){ - err = dlerror(); - rb_raise(rb_eFiddleDLError, "%s", err); - } -#endif - TypedData_Get_Struct(self, struct dl_handle, &fiddle_handle_data_type, fiddle_handle); - if( fiddle_handle->ptr && fiddle_handle->open && fiddle_handle->enable_close ){ - dlclose(fiddle_handle->ptr); - } - fiddle_handle->ptr = ptr; - fiddle_handle->open = 1; - fiddle_handle->enable_close = 0; - - if( rb_block_given_p() ){ - rb_ensure(rb_yield, self, rb_fiddle_handle_close, self); - } - - return Qnil; -} - -/* - * call-seq: enable_close - * - * Enable a call to dlclose() when this handle is garbage collected. - */ -static VALUE -rb_fiddle_handle_enable_close(VALUE self) -{ - struct dl_handle *fiddle_handle; - - TypedData_Get_Struct(self, struct dl_handle, &fiddle_handle_data_type, fiddle_handle); - fiddle_handle->enable_close = 1; - return Qnil; -} - -/* - * call-seq: disable_close - * - * Disable a call to dlclose() when this handle is garbage collected. - */ -static VALUE -rb_fiddle_handle_disable_close(VALUE self) -{ - struct dl_handle *fiddle_handle; - - TypedData_Get_Struct(self, struct dl_handle, &fiddle_handle_data_type, fiddle_handle); - fiddle_handle->enable_close = 0; - return Qnil; -} - -/* - * call-seq: close_enabled? - * - * Returns +true+ if dlclose() will be called when this handle is garbage collected. - * - * See man(3) dlclose() for more info. - */ -static VALUE -rb_fiddle_handle_close_enabled_p(VALUE self) -{ - struct dl_handle *fiddle_handle; - - TypedData_Get_Struct(self, struct dl_handle, &fiddle_handle_data_type, fiddle_handle); - - if(fiddle_handle->enable_close) return Qtrue; - return Qfalse; -} - -/* - * call-seq: to_i - * - * Returns the memory address for this handle. - */ -static VALUE -rb_fiddle_handle_to_i(VALUE self) -{ - struct dl_handle *fiddle_handle; - - TypedData_Get_Struct(self, struct dl_handle, &fiddle_handle_data_type, fiddle_handle); - return PTR2NUM(fiddle_handle->ptr); -} - -/* - * call-seq: to_ptr - * - * Returns the Fiddle::Pointer of this handle. - */ -static VALUE -rb_fiddle_handle_to_ptr(VALUE self) -{ - struct dl_handle *fiddle_handle; - - TypedData_Get_Struct(self, struct dl_handle, &fiddle_handle_data_type, fiddle_handle); - return rb_fiddle_ptr_new_wrap(fiddle_handle->ptr, 0, 0, self, 0); -} - -static VALUE fiddle_handle_sym(void *handle, VALUE symbol); - -/* - * Document-method: sym - * - * call-seq: sym(name) - * - * Get the address as an Integer for the function named +name+. - */ -static VALUE -rb_fiddle_handle_sym(VALUE self, VALUE sym) -{ - struct dl_handle *fiddle_handle; - - TypedData_Get_Struct(self, struct dl_handle, &fiddle_handle_data_type, fiddle_handle); - if( ! fiddle_handle->open ){ - rb_raise(rb_eFiddleDLError, "closed handle"); - } - - return fiddle_handle_sym(fiddle_handle->ptr, sym); -} - -#ifndef RTLD_NEXT -#define RTLD_NEXT NULL -#endif -#ifndef RTLD_DEFAULT -#define RTLD_DEFAULT NULL -#endif - -/* - * Document-method: sym - * - * call-seq: sym(name) - * - * Get the address as an Integer for the function named +name+. The function - * is searched via dlsym on RTLD_NEXT. - * - * See man(3) dlsym() for more info. - */ -static VALUE -rb_fiddle_handle_s_sym(VALUE self, VALUE sym) -{ - return fiddle_handle_sym(RTLD_NEXT, sym); -} - -typedef void (*fiddle_void_func)(void); - -static fiddle_void_func -fiddle_handle_find_func(void *handle, VALUE symbol) -{ -#if defined(HAVE_DLERROR) - const char *err; -# define CHECK_DLERROR if ((err = dlerror()) != 0) { func = 0; } -#else -# define CHECK_DLERROR -#endif - fiddle_void_func func; - const char *name = StringValueCStr(symbol); - -#ifdef HAVE_DLERROR - dlerror(); -#endif - func = (fiddle_void_func)(VALUE)dlsym(handle, name); - CHECK_DLERROR; -#if defined(FUNC_STDCALL) - if( !func ){ - int i; - int len = (int)strlen(name); - char *name_n; -#if defined(__CYGWIN__) || defined(_WIN32) || defined(__MINGW32__) - { - char *name_a = (char*)xmalloc(len+2); - strcpy(name_a, name); - name_n = name_a; - name_a[len] = 'A'; - name_a[len+1] = '\0'; - func = dlsym(handle, name_a); - CHECK_DLERROR; - if( func ) goto found; - name_n = xrealloc(name_a, len+6); - } -#else - name_n = (char*)xmalloc(len+6); -#endif - memcpy(name_n, name, len); - name_n[len++] = '@'; - for( i = 0; i < 256; i += 4 ){ - sprintf(name_n + len, "%d", i); - func = dlsym(handle, name_n); - CHECK_DLERROR; - if( func ) break; - } - if( func ) goto found; - name_n[len-1] = 'A'; - name_n[len++] = '@'; - for( i = 0; i < 256; i += 4 ){ - sprintf(name_n + len, "%d", i); - func = dlsym(handle, name_n); - CHECK_DLERROR; - if( func ) break; - } - found: - xfree(name_n); - } -#endif - - return func; -} - -static VALUE -rb_fiddle_handle_s_sym_defined(VALUE self, VALUE sym) -{ - fiddle_void_func func; - - func = fiddle_handle_find_func(RTLD_NEXT, sym); - - if( func ) { - return PTR2NUM(func); - } - else { - return Qnil; - } -} - -static VALUE -rb_fiddle_handle_sym_defined(VALUE self, VALUE sym) -{ - struct dl_handle *fiddle_handle; - fiddle_void_func func; - - TypedData_Get_Struct(self, struct dl_handle, &fiddle_handle_data_type, fiddle_handle); - if( ! fiddle_handle->open ){ - rb_raise(rb_eFiddleDLError, "closed handle"); - } - - func = fiddle_handle_find_func(fiddle_handle->ptr, sym); - - if( func ) { - return PTR2NUM(func); - } - else { - return Qnil; - } -} - -static VALUE -fiddle_handle_sym(void *handle, VALUE symbol) -{ - fiddle_void_func func; - - func = fiddle_handle_find_func(handle, symbol); - - if( !func ){ - rb_raise(rb_eFiddleDLError, "unknown symbol \"%"PRIsVALUE"\"", symbol); - } - - return PTR2NUM(func); -} - -/* - * call-seq: file_name - * - * Returns the file name of this handle. - */ -static VALUE -rb_fiddle_handle_file_name(VALUE self) -{ - struct dl_handle *fiddle_handle; - - TypedData_Get_Struct(self, struct dl_handle, &fiddle_handle_data_type, fiddle_handle); - -#if defined(HAVE_DLINFO) && defined(HAVE_CONST_RTLD_DI_LINKMAP) - { - struct link_map *lm = NULL; - int res = dlinfo(fiddle_handle->ptr, RTLD_DI_LINKMAP, &lm); - if (res == 0 && lm != NULL) { - return rb_str_new_cstr(lm->l_name); - } - else { -#if defined(HAVE_DLERROR) - rb_raise(rb_eFiddleDLError, "could not get handle file name: %s", dlerror()); -#else - rb_raise(rb_eFiddleDLError, "could not get handle file name"); -#endif - } - } -#elif defined(HAVE_GETMODULEFILENAME) - { - char filename[MAX_PATH]; - DWORD res = GetModuleFileName(fiddle_handle->ptr, filename, MAX_PATH); - if (res == 0) { - rb_raise(rb_eFiddleDLError, "could not get handle file name: %s", dlerror()); - } - return rb_str_new_cstr(filename); - } -#else - (void)fiddle_handle; - return Qnil; -#endif -} - -void -Init_fiddle_handle(void) -{ - /* - * Document-class: Fiddle::Handle - * - * The Fiddle::Handle is the manner to access the dynamic library - * - * == Example - * - * === Setup - * - * libc_so = "/lib64/libc.so.6" - * => "/lib64/libc.so.6" - * @handle = Fiddle::Handle.new(libc_so) - * => # - * - * === Setup, with flags - * - * libc_so = "/lib64/libc.so.6" - * => "/lib64/libc.so.6" - * @handle = Fiddle::Handle.new(libc_so, Fiddle::RTLD_LAZY | Fiddle::RTLD_GLOBAL) - * => # - * - * See RTLD_LAZY and RTLD_GLOBAL - * - * === Addresses to symbols - * - * strcpy_addr = @handle['strcpy'] - * => 140062278451968 - * - * or - * - * strcpy_addr = @handle.sym('strcpy') - * => 140062278451968 - * - */ - rb_cHandle = rb_define_class_under(mFiddle, "Handle", rb_cObject); - rb_define_alloc_func(rb_cHandle, rb_fiddle_handle_s_allocate); - rb_define_singleton_method(rb_cHandle, "sym", rb_fiddle_handle_s_sym, 1); - rb_define_singleton_method(rb_cHandle, "sym_defined?", rb_fiddle_handle_s_sym_defined, 1); - rb_define_singleton_method(rb_cHandle, "[]", rb_fiddle_handle_s_sym, 1); - - /* Document-const: NEXT - * - * A predefined pseudo-handle of RTLD_NEXT - * - * Which will find the next occurrence of a function in the search order - * after the current library. - */ - rb_define_const(rb_cHandle, "NEXT", predefined_fiddle_handle(RTLD_NEXT)); - - /* Document-const: DEFAULT - * - * A predefined pseudo-handle of RTLD_DEFAULT - * - * Which will find the first occurrence of the desired symbol using the - * default library search order - */ - rb_define_const(rb_cHandle, "DEFAULT", predefined_fiddle_handle(RTLD_DEFAULT)); - - /* Document-const: RTLD_GLOBAL - * - * rtld Fiddle::Handle flag. - * - * The symbols defined by this library will be made available for symbol - * resolution of subsequently loaded libraries. - */ - rb_define_const(rb_cHandle, "RTLD_GLOBAL", INT2NUM(RTLD_GLOBAL)); - - /* Document-const: RTLD_LAZY - * - * rtld Fiddle::Handle flag. - * - * Perform lazy binding. Only resolve symbols as the code that references - * them is executed. If the symbol is never referenced, then it is never - * resolved. (Lazy binding is only performed for function references; - * references to variables are always immediately bound when the library - * is loaded.) - */ - rb_define_const(rb_cHandle, "RTLD_LAZY", INT2NUM(RTLD_LAZY)); - - /* Document-const: RTLD_NOW - * - * rtld Fiddle::Handle flag. - * - * If this value is specified or the environment variable LD_BIND_NOW is - * set to a nonempty string, all undefined symbols in the library are - * resolved before Fiddle.dlopen returns. If this cannot be done an error - * is returned. - */ - rb_define_const(rb_cHandle, "RTLD_NOW", INT2NUM(RTLD_NOW)); - - rb_define_method(rb_cHandle, "initialize", rb_fiddle_handle_initialize, -1); - rb_define_method(rb_cHandle, "to_i", rb_fiddle_handle_to_i, 0); - rb_define_method(rb_cHandle, "to_ptr", rb_fiddle_handle_to_ptr, 0); - rb_define_method(rb_cHandle, "close", rb_fiddle_handle_close, 0); - rb_define_method(rb_cHandle, "sym", rb_fiddle_handle_sym, 1); - rb_define_method(rb_cHandle, "[]", rb_fiddle_handle_sym, 1); - rb_define_method(rb_cHandle, "sym_defined?", rb_fiddle_handle_sym_defined, 1); - rb_define_method(rb_cHandle, "file_name", rb_fiddle_handle_file_name, 0); - rb_define_method(rb_cHandle, "disable_close", rb_fiddle_handle_disable_close, 0); - rb_define_method(rb_cHandle, "enable_close", rb_fiddle_handle_enable_close, 0); - rb_define_method(rb_cHandle, "close_enabled?", rb_fiddle_handle_close_enabled_p, 0); -} - -/* vim: set noet sws=4 sw=4: */ diff --git a/ext/fiddle/lib/fiddle.rb b/ext/fiddle/lib/fiddle.rb deleted file mode 100644 index 6137c487c67887..00000000000000 --- a/ext/fiddle/lib/fiddle.rb +++ /dev/null @@ -1,103 +0,0 @@ -# frozen_string_literal: true - -require 'fiddle.so' -require 'fiddle/closure' -require 'fiddle/function' -require 'fiddle/version' - -module Fiddle - if WINDOWS - # Returns the last win32 +Error+ of the current executing +Thread+ or nil - # if none - def self.win32_last_error - Thread.current[:__FIDDLE_WIN32_LAST_ERROR__] - end - - # Sets the last win32 +Error+ of the current executing +Thread+ to +error+ - def self.win32_last_error= error - Thread.current[:__FIDDLE_WIN32_LAST_ERROR__] = error - end - - # Returns the last win32 socket +Error+ of the current executing - # +Thread+ or nil if none - def self.win32_last_socket_error - Thread.current[:__FIDDLE_WIN32_LAST_SOCKET_ERROR__] - end - - # Sets the last win32 socket +Error+ of the current executing - # +Thread+ to +error+ - def self.win32_last_socket_error= error - Thread.current[:__FIDDLE_WIN32_LAST_SOCKET_ERROR__] = error - end - end - - # Returns the last +Error+ of the current executing +Thread+ or nil if none - def self.last_error - Thread.current[:__FIDDLE_LAST_ERROR__] - end - - # Sets the last +Error+ of the current executing +Thread+ to +error+ - def self.last_error= error - Thread.current[:__DL2_LAST_ERROR__] = error - Thread.current[:__FIDDLE_LAST_ERROR__] = error - end - - # call-seq: dlopen(library) => Fiddle::Handle - # - # Creates a new handler that opens +library+, and returns an instance of - # Fiddle::Handle. - # - # If +nil+ is given for the +library+, Fiddle::Handle::DEFAULT is used, which - # is the equivalent to RTLD_DEFAULT. See man 3 dlopen for more. - # - # lib = Fiddle.dlopen(nil) - # - # The default is dependent on OS, and provide a handle for all libraries - # already loaded. For example, in most cases you can use this to access - # +libc+ functions, or ruby functions like +rb_str_new+. - # - # See Fiddle::Handle.new for more. - def dlopen library - begin - Fiddle::Handle.new(library) - rescue DLError => error - case RUBY_PLATFORM - when /linux/ - case error.message - when /\A(\/.+?): (?:invalid ELF header|file too short)/ - # This may be a linker script: - # https://sourceware.org/binutils/docs/ld.html#Scripts - path = $1 - else - raise - end - else - raise - end - - File.open(path) do |input| - input.each_line do |line| - case line - when /\A\s*(?:INPUT|GROUP)\s*\(\s*([^\s,\)]+)/ - # TODO: Should we support multiple files? - return dlopen($1) - end - end - end - - # Not found - raise - end - end - module_function :dlopen - - # Add constants for backwards compat - - RTLD_GLOBAL = Handle::RTLD_GLOBAL # :nodoc: - RTLD_LAZY = Handle::RTLD_LAZY # :nodoc: - RTLD_NOW = Handle::RTLD_NOW # :nodoc: - - Fiddle::Types.constants.each do |type| - const_set "TYPE_#{type}", Fiddle::Types.const_get(type) - end -end diff --git a/ext/fiddle/lib/fiddle/closure.rb b/ext/fiddle/lib/fiddle/closure.rb deleted file mode 100644 index 7e0077ea5222ec..00000000000000 --- a/ext/fiddle/lib/fiddle/closure.rb +++ /dev/null @@ -1,74 +0,0 @@ -# frozen_string_literal: true -module Fiddle - class Closure - class << self - # Create a new closure. If a block is given, the created closure - # is automatically freed after the given block is executed. - # - # The all given arguments are passed to Fiddle::Closure.new. So - # using this method without block equals to Fiddle::Closure.new. - # - # == Example - # - # Fiddle::Closure.create(TYPE_INT, [TYPE_INT]) do |closure| - # # closure is freed automatically when this block is finished. - # end - def create(*args) - if block_given? - closure = new(*args) - begin - yield(closure) - ensure - closure.free - end - else - new(*args) - end - end - end - - # the C type of the return of the FFI closure - attr_reader :ctype - - # arguments of the FFI closure - attr_reader :args - - # Extends Fiddle::Closure to allow for building the closure in a block - class BlockCaller < Fiddle::Closure - - # == Description - # - # Construct a new BlockCaller object. - # - # * +ctype+ is the C type to be returned - # * +args+ are passed the callback - # * +abi+ is the abi of the closure - # - # If there is an error in preparing the +ffi_cif+ or +ffi_prep_closure+, - # then a RuntimeError will be raised. - # - # == Example - # - # include Fiddle - # - # cb = Closure::BlockCaller.new(TYPE_INT, [TYPE_INT]) do |one| - # one - # end - # - # func = Function.new(cb, [TYPE_INT], TYPE_INT) - # - def initialize ctype, args, abi = Fiddle::Function::DEFAULT, &block - super(ctype, args, abi) - @block = block - end - - # Calls the constructed BlockCaller, with +args+ - # - # For an example see Fiddle::Closure::BlockCaller.new - # - def call *args - @block.call(*args) - end - end - end -end diff --git a/ext/fiddle/lib/fiddle/cparser.rb b/ext/fiddle/lib/fiddle/cparser.rb deleted file mode 100644 index 264ca166dddb7a..00000000000000 --- a/ext/fiddle/lib/fiddle/cparser.rb +++ /dev/null @@ -1,278 +0,0 @@ -# frozen_string_literal: true -module Fiddle - # A mixin that provides methods for parsing C struct and prototype signatures. - # - # == Example - # require 'fiddle/import' - # - # include Fiddle::CParser - # #=> Object - # - # parse_ctype('int') - # #=> Fiddle::TYPE_INT - # - # parse_struct_signature(['int i', 'char c']) - # #=> [[Fiddle::TYPE_INT, Fiddle::TYPE_CHAR], ["i", "c"]] - # - # parse_signature('double sum(double, double)') - # #=> ["sum", Fiddle::TYPE_DOUBLE, [Fiddle::TYPE_DOUBLE, Fiddle::TYPE_DOUBLE]] - # - module CParser - # Parses a C struct's members - # - # Example: - # require 'fiddle/import' - # - # include Fiddle::CParser - # #=> Object - # - # parse_struct_signature(['int i', 'char c']) - # #=> [[Fiddle::TYPE_INT, Fiddle::TYPE_CHAR], ["i", "c"]] - # - # parse_struct_signature(['char buffer[80]']) - # #=> [[[Fiddle::TYPE_CHAR, 80]], ["buffer"]] - # - def parse_struct_signature(signature, tymap=nil) - if signature.is_a?(String) - signature = split_arguments(signature, /[,;]/) - elsif signature.is_a?(Hash) - signature = [signature] - end - mems = [] - tys = [] - signature.each{|msig| - msig = compact(msig) if msig.is_a?(String) - case msig - when Hash - msig.each do |struct_name, struct_signature| - struct_name = struct_name.to_s if struct_name.is_a?(Symbol) - struct_name = compact(struct_name) - struct_count = nil - if struct_name =~ /^([\w\*\s]+)\[(\d+)\]$/ - struct_count = $2.to_i - struct_name = $1 - end - if struct_signature.respond_to?(:entity_class) - struct_type = struct_signature - else - parsed_struct = parse_struct_signature(struct_signature, tymap) - struct_type = CStructBuilder.create(CStruct, *parsed_struct) - end - if struct_count - ty = [struct_type, struct_count] - else - ty = struct_type - end - mems.push([struct_name, struct_type.members]) - tys.push(ty) - end - when /^[\w\*\s]+[\*\s](\w+)$/ - mems.push($1) - tys.push(parse_ctype(msig, tymap)) - when /^[\w\*\s]+\(\*(\w+)\)\(.*?\)$/ - mems.push($1) - tys.push(parse_ctype(msig, tymap)) - when /^([\w\*\s]+[\*\s])(\w+)\[(\d+)\]$/ - mems.push($2) - tys.push([parse_ctype($1.strip, tymap), $3.to_i]) - when /^([\w\*\s]+)\[(\d+)\](\w+)$/ - mems.push($3) - tys.push([parse_ctype($1.strip, tymap), $2.to_i]) - else - raise(RuntimeError,"can't parse the struct member: #{msig}") - end - } - return tys, mems - end - - # Parses a C prototype signature - # - # If Hash +tymap+ is provided, the return value and the arguments from the - # +signature+ are expected to be keys, and the value will be the C type to - # be looked up. - # - # Example: - # require 'fiddle/import' - # - # include Fiddle::CParser - # #=> Object - # - # parse_signature('double sum(double, double)') - # #=> ["sum", Fiddle::TYPE_DOUBLE, [Fiddle::TYPE_DOUBLE, Fiddle::TYPE_DOUBLE]] - # - # parse_signature('void update(void (*cb)(int code))') - # #=> ["update", Fiddle::TYPE_VOID, [Fiddle::TYPE_VOIDP]] - # - # parse_signature('char (*getbuffer(void))[80]') - # #=> ["getbuffer", Fiddle::TYPE_VOIDP, []] - # - def parse_signature(signature, tymap=nil) - tymap ||= {} - case compact(signature) - when /^(?:[\w\*\s]+)\(\*(\w+)\((.*?)\)\)(?:\[\w*\]|\(.*?\));?$/ - func, args = $1, $2 - return [func, TYPE_VOIDP, split_arguments(args).collect {|arg| parse_ctype(arg, tymap)}] - when /^([\w\*\s]+[\*\s])(\w+)\((.*?)\);?$/ - ret, func, args = $1.strip, $2, $3 - return [func, parse_ctype(ret, tymap), split_arguments(args).collect {|arg| parse_ctype(arg, tymap)}] - else - raise(RuntimeError,"can't parse the function prototype: #{signature}") - end - end - - # Given a String of C type +ty+, returns the corresponding Fiddle constant. - # - # +ty+ can also accept an Array of C type Strings, and will be returned in - # a corresponding Array. - # - # If Hash +tymap+ is provided, +ty+ is expected to be the key, and the - # value will be the C type to be looked up. - # - # Example: - # require 'fiddle/import' - # - # include Fiddle::CParser - # #=> Object - # - # parse_ctype('int') - # #=> Fiddle::TYPE_INT - # - # parse_ctype('double diff') - # #=> Fiddle::TYPE_DOUBLE - # - # parse_ctype('unsigned char byte') - # #=> -Fiddle::TYPE_CHAR - # - # parse_ctype('const char* const argv[]') - # #=> -Fiddle::TYPE_VOIDP - # - def parse_ctype(ty, tymap=nil) - tymap ||= {} - if ty.is_a?(Array) - return [parse_ctype(ty[0], tymap), ty[1]] - end - ty = ty.gsub(/\Aconst\s+/, "") - case ty - when 'void' - return TYPE_VOID - when /\A(?:(?:signed\s+)?long\s+long(?:\s+int\s+)?|int64_t)(?:\s+\w+)?\z/ - unless Fiddle.const_defined?(:TYPE_LONG_LONG) - raise(RuntimeError, "unsupported type: #{ty}") - end - return TYPE_LONG_LONG - when /\A(?:unsigned\s+long\s+long(?:\s+int\s+)?|uint64_t)(?:\s+\w+)?\z/ - unless Fiddle.const_defined?(:TYPE_LONG_LONG) - raise(RuntimeError, "unsupported type: #{ty}") - end - return TYPE_ULONG_LONG - when /\Aunsigned\s+long(?:\s+int\s+)?(?:\s+\w+)?\z/, - /\Aunsigned\s+int\s+long(?:\s+\w+)?\z/, - /\Along(?:\s+int)?\s+unsigned(?:\s+\w+)?\z/, - /\Aint\s+unsigned\s+long(?:\s+\w+)?\z/, - /\A(?:int\s+)?long\s+unsigned(?:\s+\w+)?\z/ - return TYPE_ULONG - when /\A(?:signed\s+)?long(?:\s+int\s+)?(?:\s+\w+)?\z/, - /\A(?:signed\s+)?int\s+long(?:\s+\w+)?\z/, - /\Along(?:\s+int)?\s+signed(?:\s+\w+)?\z/ - return TYPE_LONG - when /\Aunsigned\s+short(?:\s+int\s+)?(?:\s+\w+)?\z/, - /\Aunsigned\s+int\s+short(?:\s+\w+)?\z/, - /\Ashort(?:\s+int)?\s+unsigned(?:\s+\w+)?\z/, - /\Aint\s+unsigned\s+short(?:\s+\w+)?\z/, - /\A(?:int\s+)?short\s+unsigned(?:\s+\w+)?\z/ - return TYPE_USHORT - when /\A(?:signed\s+)?short(?:\s+int\s+)?(?:\s+\w+)?\z/, - /\A(?:signed\s+)?int\s+short(?:\s+\w+)?\z/, - /\Aint\s+(?:signed\s+)?short(?:\s+\w+)?\z/ - return TYPE_SHORT - when /\A(?:signed\s+)?int(?:\s+\w+)?\z/ - return TYPE_INT - when /\A(?:unsigned\s+int|uint)(?:\s+\w+)?\z/ - return TYPE_UINT - when /\A(?:signed\s+)?char(?:\s+\w+)?\z/ - return TYPE_CHAR - when /\Aunsigned\s+char(?:\s+\w+)?\z/ - return TYPE_UCHAR - when /\Aint8_t(?:\s+\w+)?\z/ - unless Fiddle.const_defined?(:TYPE_INT8_T) - raise(RuntimeError, "unsupported type: #{ty}") - end - return TYPE_INT8_T - when /\Auint8_t(?:\s+\w+)?\z/ - unless Fiddle.const_defined?(:TYPE_INT8_T) - raise(RuntimeError, "unsupported type: #{ty}") - end - return TYPE_UINT8_T - when /\Aint16_t(?:\s+\w+)?\z/ - unless Fiddle.const_defined?(:TYPE_INT16_T) - raise(RuntimeError, "unsupported type: #{ty}") - end - return TYPE_INT16_T - when /\Auint16_t(?:\s+\w+)?\z/ - unless Fiddle.const_defined?(:TYPE_INT16_T) - raise(RuntimeError, "unsupported type: #{ty}") - end - return TYPE_UINT16_T - when /\Aint32_t(?:\s+\w+)?\z/ - unless Fiddle.const_defined?(:TYPE_INT32_T) - raise(RuntimeError, "unsupported type: #{ty}") - end - return TYPE_INT32_T - when /\Auint32_t(?:\s+\w+)?\z/ - unless Fiddle.const_defined?(:TYPE_INT32_T) - raise(RuntimeError, "unsupported type: #{ty}") - end - return TYPE_UINT32_T - when /\Aint64_t(?:\s+\w+)?\z/ - unless Fiddle.const_defined?(:TYPE_INT64_T) - raise(RuntimeError, "unsupported type: #{ty}") - end - return TYPE_INT64_T - when /\Auint64_t(?:\s+\w+)?\z/ - unless Fiddle.const_defined?(:TYPE_INT64_T) - raise(RuntimeError, "unsupported type: #{ty}") - end - return TYPE_UINT64_T - when /\Afloat(?:\s+\w+)?\z/ - return TYPE_FLOAT - when /\Adouble(?:\s+\w+)?\z/ - return TYPE_DOUBLE - when /\Asize_t(?:\s+\w+)?\z/ - return TYPE_SIZE_T - when /\Assize_t(?:\s+\w+)?\z/ - return TYPE_SSIZE_T - when /\Aptrdiff_t(?:\s+\w+)?\z/ - return TYPE_PTRDIFF_T - when /\Aintptr_t(?:\s+\w+)?\z/ - return TYPE_INTPTR_T - when /\Auintptr_t(?:\s+\w+)?\z/ - return TYPE_UINTPTR_T - when "bool" - return TYPE_BOOL - when /\*/, /\[[\s\d]*\]/ - return TYPE_VOIDP - when "..." - return TYPE_VARIADIC - else - ty = ty.split(' ', 2)[0] - if( tymap[ty] ) - return parse_ctype(tymap[ty], tymap) - else - raise(DLError, "unknown type: #{ty}") - end - end - end - - private - - def split_arguments(arguments, sep=',') - return [] if arguments.strip == 'void' - arguments.scan(/([\w\*\s]+\(\*\w*\)\(.*?\)|[\w\*\s\[\]]+|\.\.\.)(?:#{sep}\s*|\z)/).collect {|m| m[0]} - end - - def compact(signature) - signature.gsub(/\s+/, ' ').gsub(/\s*([\(\)\[\]\*,;])\s*/, '\1').strip - end - - end -end diff --git a/ext/fiddle/lib/fiddle/function.rb b/ext/fiddle/lib/fiddle/function.rb deleted file mode 100644 index dc2e3e6bf57689..00000000000000 --- a/ext/fiddle/lib/fiddle/function.rb +++ /dev/null @@ -1,29 +0,0 @@ -# frozen_string_literal: true -module Fiddle - class Function - # The ABI of the Function. - attr_reader :abi - - # The address of this function - attr_reader :ptr - - # The name of this function - attr_reader :name - - # Whether GVL is needed to call this function - def need_gvl? - @need_gvl - end - - # The integer memory location of this function - def to_i - ptr.to_i - end - - # Turn this function in to a proc - def to_proc - this = self - lambda { |*args| this.call(*args) } - end - end -end diff --git a/ext/fiddle/lib/fiddle/import.rb b/ext/fiddle/lib/fiddle/import.rb deleted file mode 100644 index 09ffcef544c709..00000000000000 --- a/ext/fiddle/lib/fiddle/import.rb +++ /dev/null @@ -1,320 +0,0 @@ -# frozen_string_literal: true -require 'fiddle' -require 'fiddle/struct' -require 'fiddle/cparser' - -module Fiddle - - # Used internally by Fiddle::Importer - class CompositeHandler - # Create a new handler with the open +handlers+ - # - # Used internally by Fiddle::Importer.dlload - def initialize(handlers) - @handlers = handlers - end - - # Array of the currently loaded libraries. - def handlers() - @handlers - end - - # Returns the address as an Integer from any handlers with the function - # named +symbol+. - # - # Raises a DLError if the handle is closed. - def sym(symbol) - @handlers.each{|handle| - if( handle ) - begin - addr = handle.sym(symbol) - return addr - rescue DLError - end - end - } - return nil - end - - # See Fiddle::CompositeHandler.sym - def [](symbol) - sym(symbol) - end - end - - # A DSL that provides the means to dynamically load libraries and build - # modules around them including calling extern functions within the C - # library that has been loaded. - # - # == Example - # - # require 'fiddle' - # require 'fiddle/import' - # - # module LibSum - # extend Fiddle::Importer - # dlload './libsum.so' - # extern 'double sum(double*, int)' - # extern 'double split(double)' - # end - # - module Importer - include Fiddle - include CParser - extend Importer - - attr_reader :type_alias - private :type_alias - - # Creates an array of handlers for the given +libs+, can be an instance of - # Fiddle::Handle, Fiddle::Importer, or will create a new instance of - # Fiddle::Handle using Fiddle.dlopen - # - # Raises a DLError if the library cannot be loaded. - # - # See Fiddle.dlopen - def dlload(*libs) - handles = libs.collect{|lib| - case lib - when nil - nil - when Handle - lib - when Importer - lib.handlers - else - Fiddle.dlopen(lib) - end - }.flatten() - @handler = CompositeHandler.new(handles) - @func_map = {} - @type_alias = {} - end - - # Sets the type alias for +alias_type+ as +orig_type+ - def typealias(alias_type, orig_type) - @type_alias[alias_type] = orig_type - end - - # Returns the sizeof +ty+, using Fiddle::Importer.parse_ctype to determine - # the C type and the appropriate Fiddle constant. - def sizeof(ty) - case ty - when String - ty = parse_ctype(ty, type_alias).abs() - case ty - when TYPE_CHAR - return SIZEOF_CHAR - when TYPE_SHORT - return SIZEOF_SHORT - when TYPE_INT - return SIZEOF_INT - when TYPE_LONG - return SIZEOF_LONG - when TYPE_FLOAT - return SIZEOF_FLOAT - when TYPE_DOUBLE - return SIZEOF_DOUBLE - when TYPE_VOIDP - return SIZEOF_VOIDP - when TYPE_CONST_STRING - return SIZEOF_CONST_STRING - else - if defined?(TYPE_LONG_LONG) and - ty == TYPE_LONG_LONG - return SIZEOF_LONG_LONG - else - raise(DLError, "unknown type: #{ty}") - end - end - when Class - if( ty.instance_methods().include?(:to_ptr) ) - return ty.size() - end - end - return Pointer[ty].size() - end - - def parse_bind_options(opts) - h = {} - while( opt = opts.shift() ) - case opt - when :stdcall, :cdecl - h[:call_type] = opt - when :carried, :temp, :temporal, :bind - h[:callback_type] = opt - h[:carrier] = opts.shift() - else - h[opt] = true - end - end - h - end - private :parse_bind_options - - # :stopdoc: - CALL_TYPE_TO_ABI = Hash.new { |h, k| - raise RuntimeError, "unsupported call type: #{k}" - }.merge({ :stdcall => Function.const_defined?(:STDCALL) ? Function::STDCALL : - Function::DEFAULT, - :cdecl => Function::DEFAULT, - nil => Function::DEFAULT - }).freeze - private_constant :CALL_TYPE_TO_ABI - # :startdoc: - - # Creates a global method from the given C +signature+. - def extern(signature, *opts) - symname, ctype, argtype = parse_signature(signature, type_alias) - opt = parse_bind_options(opts) - f = import_function(symname, ctype, argtype, opt[:call_type]) - name = symname.gsub(/@.+/,'') - @func_map[name] = f - # define_method(name){|*args,&block| f.call(*args,&block)} - begin - /^(.+?):(\d+)/ =~ caller.first - file, line = $1, $2.to_i - rescue - file, line = __FILE__, __LINE__+3 - end - module_eval(<<-EOS, file, line) - def #{name}(*args, &block) - @func_map['#{name}'].call(*args,&block) - end - EOS - module_function(name) - f - end - - # Creates a global method from the given C +signature+ using the given - # +opts+ as bind parameters with the given block. - def bind(signature, *opts, &blk) - name, ctype, argtype = parse_signature(signature, type_alias) - h = parse_bind_options(opts) - case h[:callback_type] - when :bind, nil - f = bind_function(name, ctype, argtype, h[:call_type], &blk) - else - raise(RuntimeError, "unknown callback type: #{h[:callback_type]}") - end - @func_map[name] = f - #define_method(name){|*args,&block| f.call(*args,&block)} - begin - /^(.+?):(\d+)/ =~ caller.first - file, line = $1, $2.to_i - rescue - file, line = __FILE__, __LINE__+3 - end - module_eval(<<-EOS, file, line) - def #{name}(*args,&block) - @func_map['#{name}'].call(*args,&block) - end - EOS - module_function(name) - f - end - - # Creates a class to wrap the C struct described by +signature+. - # - # MyStruct = struct ['int i', 'char c'] - def struct(signature) - tys, mems = parse_struct_signature(signature, type_alias) - Fiddle::CStructBuilder.create(CStruct, tys, mems) - end - - # Creates a class to wrap the C union described by +signature+. - # - # MyUnion = union ['int i', 'char c'] - def union(signature) - tys, mems = parse_struct_signature(signature, type_alias) - Fiddle::CStructBuilder.create(CUnion, tys, mems) - end - - # Returns the function mapped to +name+, that was created by either - # Fiddle::Importer.extern or Fiddle::Importer.bind - def [](name) - @func_map[name] - end - - # Creates a class to wrap the C struct with the value +ty+ - # - # See also Fiddle::Importer.struct - def create_value(ty, val=nil) - s = struct([ty + " value"]) - ptr = s.malloc() - if( val ) - ptr.value = val - end - return ptr - end - alias value create_value - - # Returns a new instance of the C struct with the value +ty+ at the +addr+ - # address. - def import_value(ty, addr) - s = struct([ty + " value"]) - ptr = s.new(addr) - return ptr - end - - - # The Fiddle::CompositeHandler instance - # - # Will raise an error if no handlers are open. - def handler - (@handler ||= nil) or raise "call dlload before importing symbols and functions" - end - - # Returns a new Fiddle::Pointer instance at the memory address of the given - # +name+ symbol. - # - # Raises a DLError if the +name+ doesn't exist. - # - # See Fiddle::CompositeHandler.sym and Fiddle::Handle.sym - def import_symbol(name) - addr = handler.sym(name) - if( !addr ) - raise(DLError, "cannot find the symbol: #{name}") - end - Pointer.new(addr) - end - - # Returns a new Fiddle::Function instance at the memory address of the given - # +name+ function. - # - # Raises a DLError if the +name+ doesn't exist. - # - # * +argtype+ is an Array of arguments, passed to the +name+ function. - # * +ctype+ is the return type of the function - # * +call_type+ is the ABI of the function - # - # See also Fiddle:Function.new - # - # See Fiddle::CompositeHandler.sym and Fiddle::Handler.sym - def import_function(name, ctype, argtype, call_type = nil) - addr = handler.sym(name) - if( !addr ) - raise(DLError, "cannot find the function: #{name}()") - end - Function.new(addr, argtype, ctype, CALL_TYPE_TO_ABI[call_type], - name: name) - end - - # Returns a new closure wrapper for the +name+ function. - # - # * +ctype+ is the return type of the function - # * +argtype+ is an Array of arguments, passed to the callback function - # * +call_type+ is the abi of the closure - # * +block+ is passed to the callback - # - # See Fiddle::Closure - def bind_function(name, ctype, argtype, call_type = nil, &block) - abi = CALL_TYPE_TO_ABI[call_type] - closure = Class.new(Fiddle::Closure) { - define_method(:call, block) - }.new(ctype, argtype, abi) - - Function.new(closure, argtype, ctype, abi, name: name) - end - end -end diff --git a/ext/fiddle/lib/fiddle/pack.rb b/ext/fiddle/lib/fiddle/pack.rb deleted file mode 100644 index 545b985d503308..00000000000000 --- a/ext/fiddle/lib/fiddle/pack.rb +++ /dev/null @@ -1,137 +0,0 @@ -# frozen_string_literal: true -require 'fiddle' - -module Fiddle - module PackInfo # :nodoc: all - ALIGN_MAP = { - TYPE_VOIDP => ALIGN_VOIDP, - TYPE_CHAR => ALIGN_CHAR, - TYPE_SHORT => ALIGN_SHORT, - TYPE_INT => ALIGN_INT, - TYPE_LONG => ALIGN_LONG, - TYPE_FLOAT => ALIGN_FLOAT, - TYPE_DOUBLE => ALIGN_DOUBLE, - TYPE_UCHAR => ALIGN_CHAR, - TYPE_USHORT => ALIGN_SHORT, - TYPE_UINT => ALIGN_INT, - TYPE_ULONG => ALIGN_LONG, - } - - PACK_MAP = { - TYPE_VOIDP => "L!", - TYPE_CHAR => "c", - TYPE_SHORT => "s!", - TYPE_INT => "i!", - TYPE_LONG => "l!", - TYPE_FLOAT => "f", - TYPE_DOUBLE => "d", - TYPE_UCHAR => "C", - TYPE_USHORT => "S!", - TYPE_UINT => "I!", - TYPE_ULONG => "L!", - } - - SIZE_MAP = { - TYPE_VOIDP => SIZEOF_VOIDP, - TYPE_CHAR => SIZEOF_CHAR, - TYPE_SHORT => SIZEOF_SHORT, - TYPE_INT => SIZEOF_INT, - TYPE_LONG => SIZEOF_LONG, - TYPE_FLOAT => SIZEOF_FLOAT, - TYPE_DOUBLE => SIZEOF_DOUBLE, - TYPE_UCHAR => SIZEOF_CHAR, - TYPE_USHORT => SIZEOF_SHORT, - TYPE_UINT => SIZEOF_INT, - TYPE_ULONG => SIZEOF_LONG, - } - if defined?(TYPE_LONG_LONG) - ALIGN_MAP[TYPE_LONG_LONG] = ALIGN_MAP[TYPE_ULONG_LONG] = ALIGN_LONG_LONG - PACK_MAP[TYPE_LONG_LONG] = "q" - PACK_MAP[TYPE_ULONG_LONG] = "Q" - SIZE_MAP[TYPE_LONG_LONG] = SIZE_MAP[TYPE_ULONG_LONG] = SIZEOF_LONG_LONG - PACK_MAP[TYPE_VOIDP] = "Q" if SIZEOF_LONG_LONG == SIZEOF_VOIDP - end - - def align(addr, align) - d = addr % align - if( d == 0 ) - addr - else - addr + (align - d) - end - end - module_function :align - end - - class Packer # :nodoc: all - include PackInfo - - def self.[](*types) - new(types) - end - - def initialize(types) - parse_types(types) - end - - def size() - @size - end - - def pack(ary) - case SIZEOF_VOIDP - when SIZEOF_LONG - ary.pack(@template) - else - if defined?(TYPE_LONG_LONG) and - SIZEOF_VOIDP == SIZEOF_LONG_LONG - ary.pack(@template) - else - raise(RuntimeError, "sizeof(void*)?") - end - end - end - - def unpack(ary) - case SIZEOF_VOIDP - when SIZEOF_LONG - ary.join().unpack(@template) - else - if defined?(TYPE_LONG_LONG) and - SIZEOF_VOIDP == SIZEOF_LONG_LONG - ary.join().unpack(@template) - else - raise(RuntimeError, "sizeof(void*)?") - end - end - end - - private - - def parse_types(types) - @template = "".dup - addr = 0 - types.each{|t| - orig_addr = addr - if( t.is_a?(Array) ) - addr = align(orig_addr, ALIGN_MAP[TYPE_VOIDP]) - else - addr = align(orig_addr, ALIGN_MAP[t]) - end - d = addr - orig_addr - if( d > 0 ) - @template << "x#{d}" - end - if( t.is_a?(Array) ) - @template << (PACK_MAP[t[0]] * t[1]) - addr += (SIZE_MAP[t[0]] * t[1]) - else - @template << PACK_MAP[t] - addr += SIZE_MAP[t] - end - } - addr = align(addr, ALIGN_MAP[TYPE_VOIDP]) - @size = addr - end - end -end diff --git a/ext/fiddle/lib/fiddle/struct.rb b/ext/fiddle/lib/fiddle/struct.rb deleted file mode 100644 index 6d05bbd7421c24..00000000000000 --- a/ext/fiddle/lib/fiddle/struct.rb +++ /dev/null @@ -1,539 +0,0 @@ -# frozen_string_literal: true -require 'fiddle' -require 'fiddle/value' -require 'fiddle/pack' - -module Fiddle - # A base class for objects representing a C structure - class CStruct - include Enumerable - - # accessor to Fiddle::CStructEntity - def CStruct.entity_class - CStructEntity - end - - def self.offsetof(name, members, types) # :nodoc: - offset = 0 - worklist = name.split('.') - this_type = self - while search_name = worklist.shift - index = 0 - member_index = members.index(search_name) - - unless member_index - # Possibly a sub-structure - member_index = members.index { |member_name, _| - member_name == search_name - } - return unless member_index - end - - types.each { |type, count = 1| - orig_offset = offset - if type.respond_to?(:entity_class) - align = type.alignment - type_size = type.size - else - align = PackInfo::ALIGN_MAP[type] - type_size = PackInfo::SIZE_MAP[type] - end - - # Unions shouldn't advance the offset - if this_type.entity_class == CUnionEntity - type_size = 0 - end - - offset = PackInfo.align(orig_offset, align) - - if worklist.empty? - return offset if index == member_index - else - if index == member_index - subtype = types[member_index] - members = subtype.members - types = subtype.types - this_type = subtype - break - end - end - - offset += (type_size * count) - index += 1 - } - end - nil - end - - def each - return enum_for(__function__) unless block_given? - - self.class.members.each do |name,| - yield(self[name]) - end - end - - def each_pair - return enum_for(__function__) unless block_given? - - self.class.members.each do |name,| - yield(name, self[name]) - end - end - - def to_h - hash = {} - each_pair do |name, value| - hash[name] = unstruct(value) - end - hash - end - - def replace(another) - if another.nil? - self.class.members.each do |name,| - self[name] = nil - end - elsif another.respond_to?(:each_pair) - another.each_pair do |name, value| - self[name] = value - end - else - another.each do |name, value| - self[name] = value - end - end - self - end - - private - def unstruct(value) - case value - when CStruct - value.to_h - when Array - value.collect do |v| - unstruct(v) - end - else - value - end - end - end - - # A base class for objects representing a C union - class CUnion - # accessor to Fiddle::CUnionEntity - def CUnion.entity_class - CUnionEntity - end - - def self.offsetof(name, members, types) # :nodoc: - 0 - end - end - - # Wrapper for arrays within a struct - class StructArray < Array - include ValueUtil - - def initialize(ptr, type, initial_values) - @ptr = ptr - @type = type - @is_struct = @type.respond_to?(:entity_class) - if @is_struct - super(initial_values) - else - @size = Fiddle::PackInfo::SIZE_MAP[type] - @pack_format = Fiddle::PackInfo::PACK_MAP[type] - super(initial_values.collect { |v| unsigned_value(v, type) }) - end - end - - def to_ptr - @ptr - end - - def []=(index, value) - if index < 0 || index >= size - raise IndexError, 'index %d outside of array bounds 0...%d' % [index, size] - end - - if @is_struct - self[index].replace(value) - else - to_ptr[index * @size, @size] = [value].pack(@pack_format) - super(index, value) - end - end - end - - # Used to construct C classes (CUnion, CStruct, etc) - # - # Fiddle::Importer#struct and Fiddle::Importer#union wrap this functionality in an - # easy-to-use manner. - module CStructBuilder - # Construct a new class given a C: - # * class +klass+ (CUnion, CStruct, or other that provide an - # #entity_class) - # * +types+ (Fiddle::TYPE_INT, Fiddle::TYPE_SIZE_T, etc., see the C types - # constants) - # * corresponding +members+ - # - # Fiddle::Importer#struct and Fiddle::Importer#union wrap this functionality in an - # easy-to-use manner. - # - # Examples: - # - # require 'fiddle/struct' - # require 'fiddle/cparser' - # - # include Fiddle::CParser - # - # types, members = parse_struct_signature(['int i','char c']) - # - # MyStruct = Fiddle::CStructBuilder.create(Fiddle::CUnion, types, members) - # - # MyStruct.malloc(Fiddle::RUBY_FREE) do |obj| - # ... - # end - # - # obj = MyStruct.malloc(Fiddle::RUBY_FREE) - # begin - # ... - # ensure - # obj.call_free - # end - # - # obj = MyStruct.malloc - # begin - # ... - # ensure - # Fiddle.free obj.to_ptr - # end - # - def create(klass, types, members) - new_class = Class.new(klass){ - define_method(:initialize){|addr, func = nil| - if addr.is_a?(self.class.entity_class) - @entity = addr - else - @entity = self.class.entity_class.new(addr, types, func) - end - @entity.assign_names(members) - } - define_method(:[]) { |*args| @entity.send(:[], *args) } - define_method(:[]=) { |*args| @entity.send(:[]=, *args) } - define_method(:to_ptr){ @entity } - define_method(:to_i){ @entity.to_i } - define_singleton_method(:types) { types } - define_singleton_method(:members) { members } - - # Return the offset of a struct member given its name. - # For example: - # - # MyStruct = struct [ - # "int64_t i", - # "char c", - # ] - # - # MyStruct.offsetof("i") # => 0 - # MyStruct.offsetof("c") # => 8 - # - define_singleton_method(:offsetof) { |name| - klass.offsetof(name, members, types) - } - members.each{|name| - name = name[0] if name.is_a?(Array) # name is a nested struct - next if method_defined?(name) - define_method(name){ @entity[name] } - define_method(name + "="){|val| @entity[name] = val } - } - entity_class = klass.entity_class - alignment = entity_class.alignment(types) - size = entity_class.size(types) - define_singleton_method(:alignment) { alignment } - define_singleton_method(:size) { size } - define_singleton_method(:malloc) do |func=nil, &block| - if block - entity_class.malloc(types, func, size) do |entity| - block.call(new(entity)) - end - else - new(entity_class.malloc(types, func, size)) - end - end - } - return new_class - end - module_function :create - end - - # A pointer to a C structure - class CStructEntity < Fiddle::Pointer - include PackInfo - include ValueUtil - - def CStructEntity.alignment(types) - max = 1 - types.each do |type, count = 1| - if type.respond_to?(:entity_class) - n = type.alignment - else - n = ALIGN_MAP[type] - end - max = n if n > max - end - max - end - - # Allocates a C struct with the +types+ provided. - # - # See Fiddle::Pointer.malloc for memory management issues. - def CStructEntity.malloc(types, func = nil, size = size(types), &block) - if block_given? - super(size, func) do |struct| - struct.set_ctypes types - yield struct - end - else - struct = super(size, func) - struct.set_ctypes types - struct - end - end - - # Returns the offset for the packed sizes for the given +types+. - # - # Fiddle::CStructEntity.size( - # [ Fiddle::TYPE_DOUBLE, - # Fiddle::TYPE_INT, - # Fiddle::TYPE_CHAR, - # Fiddle::TYPE_VOIDP ]) #=> 24 - def CStructEntity.size(types) - offset = 0 - - max_align = types.map { |type, count = 1| - last_offset = offset - - if type.respond_to?(:entity_class) - align = type.alignment - type_size = type.size - else - align = PackInfo::ALIGN_MAP[type] - type_size = PackInfo::SIZE_MAP[type] - end - offset = PackInfo.align(last_offset, align) + - (type_size * count) - - align - }.max - - PackInfo.align(offset, max_align) - end - - # Wraps the C pointer +addr+ as a C struct with the given +types+. - # - # When the instance is garbage collected, the C function +func+ is called. - # - # See also Fiddle::Pointer.new - def initialize(addr, types, func = nil) - if func && addr.is_a?(Pointer) && addr.free - raise ArgumentError, 'free function specified on both underlying struct Pointer and when creating a CStructEntity - who do you want to free this?' - end - set_ctypes(types) - super(addr, @size, func) - end - - # Set the names of the +members+ in this C struct - def assign_names(members) - @members = [] - @nested_structs = {} - members.each_with_index do |member, index| - if member.is_a?(Array) # nested struct - member_name = member[0] - struct_type, struct_count = @ctypes[index] - if struct_count.nil? - struct = struct_type.new(to_i + @offset[index]) - else - structs = struct_count.times.map do |i| - struct_type.new(to_i + @offset[index] + i * struct_type.size) - end - struct = StructArray.new(to_i + @offset[index], - struct_type, - structs) - end - @nested_structs[member_name] = struct - else - member_name = member - end - @members << member_name - end - end - - # Calculates the offsets and sizes for the given +types+ in the struct. - def set_ctypes(types) - @ctypes = types - @offset = [] - offset = 0 - - max_align = types.map { |type, count = 1| - orig_offset = offset - if type.respond_to?(:entity_class) - align = type.alignment - type_size = type.size - else - align = ALIGN_MAP[type] - type_size = SIZE_MAP[type] - end - offset = PackInfo.align(orig_offset, align) - - @offset << offset - - offset += (type_size * count) - - align - }.max - - @size = PackInfo.align(offset, max_align) - end - - # Fetch struct member +name+ if only one argument is specified. If two - # arguments are specified, the first is an offset and the second is a - # length and this method returns the string of +length+ bytes beginning at - # +offset+. - # - # Examples: - # - # my_struct = struct(['int id']).malloc - # my_struct.id = 1 - # my_struct['id'] # => 1 - # my_struct[0, 4] # => "\x01\x00\x00\x00".b - # - def [](*args) - return super(*args) if args.size > 1 - name = args[0] - idx = @members.index(name) - if( idx.nil? ) - raise(ArgumentError, "no such member: #{name}") - end - ty = @ctypes[idx] - if( ty.is_a?(Array) ) - if ty.first.respond_to?(:entity_class) - return @nested_structs[name] - else - r = super(@offset[idx], SIZE_MAP[ty[0]] * ty[1]) - end - elsif ty.respond_to?(:entity_class) - return @nested_structs[name] - else - r = super(@offset[idx], SIZE_MAP[ty.abs]) - end - packer = Packer.new([ty]) - val = packer.unpack([r]) - case ty - when Array - case ty[0] - when TYPE_VOIDP - val = val.collect{|v| Pointer.new(v)} - end - when TYPE_VOIDP - val = Pointer.new(val[0]) - else - val = val[0] - end - if( ty.is_a?(Integer) && (ty < 0) ) - return unsigned_value(val, ty) - elsif( ty.is_a?(Array) && (ty[0] < 0) ) - return StructArray.new(self + @offset[idx], ty[0], val) - else - return val - end - end - - # Set struct member +name+, to value +val+. If more arguments are - # specified, writes the string of bytes to the memory at the given - # +offset+ and +length+. - # - # Examples: - # - # my_struct = struct(['int id']).malloc - # my_struct['id'] = 1 - # my_struct[0, 4] = "\x01\x00\x00\x00".b - # my_struct.id # => 1 - # - def []=(*args) - return super(*args) if args.size > 2 - name, val = *args - name = name.to_s if name.is_a?(Symbol) - nested_struct = @nested_structs[name] - if nested_struct - if nested_struct.is_a?(StructArray) - if val.nil? - nested_struct.each do |s| - s.replace(nil) - end - else - val.each_with_index do |v, i| - nested_struct[i] = v - end - end - else - nested_struct.replace(val) - end - return val - end - idx = @members.index(name) - if( idx.nil? ) - raise(ArgumentError, "no such member: #{name}") - end - ty = @ctypes[idx] - packer = Packer.new([ty]) - val = wrap_arg(val, ty, []) - buff = packer.pack([val].flatten()) - super(@offset[idx], buff.size, buff) - if( ty.is_a?(Integer) && (ty < 0) ) - return unsigned_value(val, ty) - elsif( ty.is_a?(Array) && (ty[0] < 0) ) - return val.collect{|v| unsigned_value(v,ty[0])} - else - return val - end - end - - undef_method :size= - def to_s() # :nodoc: - super(@size) - end - end - - # A pointer to a C union - class CUnionEntity < CStructEntity - include PackInfo - - # Returns the size needed for the union with the given +types+. - # - # Fiddle::CUnionEntity.size( - # [ Fiddle::TYPE_DOUBLE, - # Fiddle::TYPE_INT, - # Fiddle::TYPE_CHAR, - # Fiddle::TYPE_VOIDP ]) #=> 8 - def CUnionEntity.size(types) - types.map { |type, count = 1| - if type.respond_to?(:entity_class) - type.size * count - else - PackInfo::SIZE_MAP[type] * count - end - }.max - end - - # Calculate the necessary offset and for each union member with the given - # +types+ - def set_ctypes(types) - @ctypes = types - @offset = Array.new(types.length, 0) - @size = self.class.size types - end - end -end diff --git a/ext/fiddle/lib/fiddle/types.rb b/ext/fiddle/lib/fiddle/types.rb deleted file mode 100644 index 7baf31ec9ecb61..00000000000000 --- a/ext/fiddle/lib/fiddle/types.rb +++ /dev/null @@ -1,73 +0,0 @@ -# frozen_string_literal: true -module Fiddle - # Adds Windows type aliases to the including class for use with - # Fiddle::Importer. - # - # The aliases added are: - # * ATOM - # * BOOL - # * BYTE - # * DWORD - # * DWORD32 - # * DWORD64 - # * HANDLE - # * HDC - # * HINSTANCE - # * HWND - # * LPCSTR - # * LPSTR - # * PBYTE - # * PDWORD - # * PHANDLE - # * PVOID - # * PWORD - # * UCHAR - # * UINT - # * ULONG - # * WORD - module Win32Types - def included(m) # :nodoc: - # https://docs.microsoft.com/en-us/windows/win32/winprog/windows-data-types - m.module_eval{ - typealias "ATOM", "WORD" - typealias "BOOL", "int" - typealias "BYTE", "unsigned char" - typealias "DWORD", "unsigned long" - typealias "DWORD32", "uint32_t" - typealias "DWORD64", "uint64_t" - typealias "HANDLE", "PVOID" - typealias "HDC", "HANDLE" - typealias "HINSTANCE", "HANDLE" - typealias "HWND", "HANDLE" - typealias "LPCSTR", "const char *" - typealias "LPSTR", "char *" - typealias "PBYTE", "BYTE *" - typealias "PDWORD", "DWORD *" - typealias "PHANDLE", "HANDLE *" - typealias "PVOID", "void *" - typealias "PWORD", "WORD *" - typealias "UCHAR", "unsigned char" - typealias "UINT", "unsigned int" - typealias "ULONG", "unsigned long" - typealias "WORD", "unsigned short" - } - end - module_function :included - end - - # Adds basic type aliases to the including class for use with Fiddle::Importer. - # - # The aliases added are +uint+ and +u_int+ (unsigned int) and - # +ulong+ and +u_long+ (unsigned long) - module BasicTypes - def included(m) # :nodoc: - m.module_eval{ - typealias "uint", "unsigned int" - typealias "u_int", "unsigned int" - typealias "ulong", "unsigned long" - typealias "u_long", "unsigned long" - } - end - module_function :included - end -end diff --git a/ext/fiddle/lib/fiddle/value.rb b/ext/fiddle/lib/fiddle/value.rb deleted file mode 100644 index 5f0b2e951e7a76..00000000000000 --- a/ext/fiddle/lib/fiddle/value.rb +++ /dev/null @@ -1,120 +0,0 @@ -# frozen_string_literal: true -require 'fiddle' - -module Fiddle - module ValueUtil #:nodoc: all - def unsigned_value(val, ty) - case ty.abs - when TYPE_CHAR - [val].pack("c").unpack1("C") - when TYPE_SHORT - [val].pack("s!").unpack1("S!") - when TYPE_INT - [val].pack("i!").unpack1("I!") - when TYPE_LONG - [val].pack("l!").unpack1("L!") - else - if defined?(TYPE_LONG_LONG) and - ty.abs == TYPE_LONG_LONG - [val].pack("q").unpack1("Q") - else - val - end - end - end - - def signed_value(val, ty) - case ty.abs - when TYPE_CHAR - [val].pack("C").unpack1("c") - when TYPE_SHORT - [val].pack("S!").unpack1("s!") - when TYPE_INT - [val].pack("I!").unpack1("i!") - when TYPE_LONG - [val].pack("L!").unpack1("l!") - else - if defined?(TYPE_LONG_LONG) and - ty.abs == TYPE_LONG_LONG - [val].pack("Q").unpack1("q") - else - val - end - end - end - - def wrap_args(args, tys, funcs, &block) - result = [] - tys ||= [] - args.each_with_index{|arg, idx| - result.push(wrap_arg(arg, tys[idx], funcs, &block)) - } - result - end - - def wrap_arg(arg, ty, funcs = [], &block) - funcs ||= [] - case arg - when nil - return 0 - when Pointer - return arg.to_i - when IO - case ty - when TYPE_VOIDP - return Pointer[arg].to_i - else - return arg.to_i - end - when Function - if( block ) - arg.bind_at_call(&block) - funcs.push(arg) - elsif !arg.bound? - raise(RuntimeError, "block must be given.") - end - return arg.to_i - when String - if( ty.is_a?(Array) ) - return arg.unpack('C*') - else - case SIZEOF_VOIDP - when SIZEOF_LONG - return [arg].pack("p").unpack1("l!") - else - if defined?(SIZEOF_LONG_LONG) and - SIZEOF_VOIDP == SIZEOF_LONG_LONG - return [arg].pack("p").unpack1("q") - else - raise(RuntimeError, "sizeof(void*)?") - end - end - end - when Float, Integer - return arg - when Array - if( ty.is_a?(Array) ) # used only by struct - case ty[0] - when TYPE_VOIDP - return arg.collect{|v| Integer(v)} - when TYPE_CHAR - if( arg.is_a?(String) ) - return val.unpack('C*') - end - end - end - return arg - else - if( arg.respond_to?(:to_ptr) ) - return arg.to_ptr.to_i - else - begin - return Integer(arg) - rescue - raise(ArgumentError, "unknown argument type: #{arg.class}") - end - end - end - end - end -end diff --git a/ext/fiddle/lib/fiddle/version.rb b/ext/fiddle/lib/fiddle/version.rb deleted file mode 100644 index 706d98a7b5a7b0..00000000000000 --- a/ext/fiddle/lib/fiddle/version.rb +++ /dev/null @@ -1,3 +0,0 @@ -module Fiddle - VERSION = "1.1.2" -end diff --git a/ext/fiddle/memory_view.c b/ext/fiddle/memory_view.c deleted file mode 100644 index fa66fc2c7b26d1..00000000000000 --- a/ext/fiddle/memory_view.c +++ /dev/null @@ -1,321 +0,0 @@ -#include - -#ifdef HAVE_RUBY_MEMORY_VIEW_H - -#include -#include -#include -#include - -#if SIZEOF_INTPTR_T == SIZEOF_LONG_LONG -# define INTPTR2NUM LL2NUM -# define UINTPTR2NUM ULL2NUM -#elif SIZEOF_INTPTR_T == SIZEOF_LONG -# define INTPTR2NUM LONG2NUM -# define UINTPTR2NUM ULONG2NUM -#else -# define INTPTR2NUM INT2NUM -# define UINTPTR2NUM UINT2NUM -#endif - -VALUE rb_cMemoryView = Qnil; - -struct memview_data { - rb_memory_view_t view; - rb_memory_view_item_component_t *members; - size_t n_members; -}; - -static void -fiddle_memview_mark(void *ptr) -{ - const struct memview_data *data = ptr; - rb_gc_mark(data->view.obj); -} - -static void -fiddle_memview_release(struct memview_data *data) -{ - if (NIL_P(data->view.obj)) return; - - rb_memory_view_release(&data->view); - data->view.obj = Qnil; - data->view.byte_size = 0; - if (data->members) { - xfree(data->members); - data->members = NULL; - data->n_members = 0; - } -} - -static void -fiddle_memview_free(void *ptr) -{ - struct memview_data *data = ptr; - fiddle_memview_release(data); - xfree(ptr); -} - -static size_t -fiddle_memview_memsize(const void *ptr) -{ - const struct memview_data *data = ptr; - return sizeof(*data) + sizeof(rb_memory_view_item_component_t)*data->n_members + (size_t)data->view.byte_size; -} - -static const rb_data_type_t fiddle_memview_data_type = { - "fiddle/memory_view", - {fiddle_memview_mark, fiddle_memview_free, fiddle_memview_memsize,}, -}; - -static VALUE -rb_fiddle_memview_s_allocate(VALUE klass) -{ - struct memview_data *data; - VALUE obj = TypedData_Make_Struct(klass, struct memview_data, &fiddle_memview_data_type, data); - data->view.obj = Qnil; - data->view.byte_size = 0; - data->members = NULL; - data->n_members = 0; - return obj; -} - -static VALUE -rb_fiddle_memview_release(VALUE obj) -{ - struct memview_data *data; - TypedData_Get_Struct(obj, struct memview_data, &fiddle_memview_data_type, data); - - if (NIL_P(data->view.obj)) return Qnil; - fiddle_memview_release(data); - return Qnil; -} - -static VALUE -rb_fiddle_memview_s_export(VALUE klass, VALUE target) -{ - ID id_new; - CONST_ID(id_new, "new"); - VALUE memview = rb_funcall(klass, id_new, 1, target); - return rb_ensure(rb_yield, memview, rb_fiddle_memview_release, memview); -} - -static VALUE -rb_fiddle_memview_initialize(VALUE obj, VALUE target) -{ - struct memview_data *data; - TypedData_Get_Struct(obj, struct memview_data, &fiddle_memview_data_type, data); - - if (!rb_memory_view_get(target, &data->view, 0)) { - data->view.obj = Qnil; - rb_raise(rb_eArgError, "Unable to get a memory view from %+"PRIsVALUE, target); - } - - return Qnil; -} - -static VALUE -rb_fiddle_memview_get_obj(VALUE obj) -{ - struct memview_data *data; - TypedData_Get_Struct(obj, struct memview_data, &fiddle_memview_data_type, data); - - return data->view.obj; -} - -static VALUE -rb_fiddle_memview_get_byte_size(VALUE obj) -{ - struct memview_data *data; - TypedData_Get_Struct(obj, struct memview_data, &fiddle_memview_data_type, data); - - if (NIL_P(data->view.obj)) return Qnil; - return SSIZET2NUM(data->view.byte_size); -} - -static VALUE -rb_fiddle_memview_get_readonly(VALUE obj) -{ - struct memview_data *data; - TypedData_Get_Struct(obj, struct memview_data, &fiddle_memview_data_type, data); - - if (NIL_P(data->view.obj)) return Qnil; - return data->view.readonly ? Qtrue : Qfalse; -} - -static VALUE -rb_fiddle_memview_get_format(VALUE obj) -{ - struct memview_data *data; - TypedData_Get_Struct(obj, struct memview_data, &fiddle_memview_data_type, data); - - if (NIL_P(data->view.obj)) return Qnil; - return data->view.format == NULL ? Qnil : rb_str_new_cstr(data->view.format); -} - -static VALUE -rb_fiddle_memview_get_item_size(VALUE obj) -{ - struct memview_data *data; - TypedData_Get_Struct(obj, struct memview_data, &fiddle_memview_data_type, data); - - if (NIL_P(data->view.obj)) return Qnil; - return SSIZET2NUM(data->view.item_size); -} - -static VALUE -rb_fiddle_memview_get_ndim(VALUE obj) -{ - struct memview_data *data; - TypedData_Get_Struct(obj, struct memview_data, &fiddle_memview_data_type, data); - - if (NIL_P(data->view.obj)) return Qnil; - return SSIZET2NUM(data->view.ndim); -} - -static VALUE -rb_fiddle_memview_get_shape(VALUE obj) -{ - struct memview_data *data; - TypedData_Get_Struct(obj, struct memview_data, &fiddle_memview_data_type, data); - - if (NIL_P(data->view.obj)) return Qnil; - if (data->view.shape == NULL) return Qnil; - - const ssize_t ndim = data->view.ndim; - VALUE shape = rb_ary_new_capa(ndim); - ssize_t i; - for (i = 0; i < ndim; ++i) { - rb_ary_push(shape, SSIZET2NUM(data->view.shape[i])); - } - return shape; -} - -static VALUE -rb_fiddle_memview_get_strides(VALUE obj) -{ - struct memview_data *data; - TypedData_Get_Struct(obj, struct memview_data, &fiddle_memview_data_type, data); - - if (NIL_P(data->view.obj)) return Qnil; - if (data->view.strides == NULL) return Qnil; - - const ssize_t ndim = data->view.ndim; - VALUE strides = rb_ary_new_capa(ndim); - ssize_t i; - for (i = 0; i < ndim; ++i) { - rb_ary_push(strides, SSIZET2NUM(data->view.strides[i])); - } - return strides; -} - -static VALUE -rb_fiddle_memview_get_sub_offsets(VALUE obj) -{ - struct memview_data *data; - TypedData_Get_Struct(obj, struct memview_data, &fiddle_memview_data_type, data); - - if (NIL_P(data->view.obj)) return Qnil; - if (data->view.sub_offsets == NULL) return Qnil; - - const ssize_t ndim = data->view.ndim; - VALUE sub_offsets = rb_ary_new_capa(ndim); - ssize_t i; - for (i = 0; i < ndim; ++i) { - rb_ary_push(sub_offsets, SSIZET2NUM(data->view.sub_offsets[i])); - } - return sub_offsets; -} - -static VALUE -rb_fiddle_memview_aref(int argc, VALUE *argv, VALUE obj) -{ - struct memview_data *data; - TypedData_Get_Struct(obj, struct memview_data, &fiddle_memview_data_type, data); - - if (NIL_P(data->view.obj)) return Qnil; - - const ssize_t ndim = data->view.ndim; - if (argc != ndim) { - rb_raise(rb_eIndexError, "wrong number of index (%d for %"PRIdSIZE")", argc, ndim); - } - - VALUE indices_v = 0; - ssize_t *indices = ALLOCV_N(ssize_t, indices_v, ndim); - - ssize_t i; - for (i = 0; i < ndim; ++i) { - ssize_t x = NUM2SSIZET(argv[i]); - indices[i] = x; - } - - uint8_t *ptr = rb_memory_view_get_item_pointer(&data->view, indices); - ALLOCV_END(indices_v); - - if (data->view.format == NULL) { - return INT2FIX(*ptr); - } - - if (!data->members) { - const char *err; - if (rb_memory_view_parse_item_format(data->view.format, &data->members, &data->n_members, &err) < 0) { - rb_raise(rb_eRuntimeError, "Unable to recognize item format at %"PRIdSIZE" in \"%s\"", - err - data->view.format, data->view.format); - } - } - - return rb_memory_view_extract_item_members(ptr, data->members, data->n_members); -} - -static VALUE -rb_fiddle_memview_to_s(VALUE self) -{ - struct memview_data *data; - const char *raw_data; - long byte_size; - VALUE string; - - TypedData_Get_Struct(self, - struct memview_data, - &fiddle_memview_data_type, - data); - - if (NIL_P(data->view.obj)) { - raw_data = NULL; - byte_size = 0; - } else { - raw_data = data->view.data; - byte_size = data->view.byte_size; - } - - string = rb_enc_str_new_static(raw_data, byte_size, rb_ascii8bit_encoding()); - { - ID id_memory_view; - CONST_ID(id_memory_view, "memory_view"); - rb_ivar_set(string, id_memory_view, self); - } - return rb_obj_freeze(string); -} - -void -Init_fiddle_memory_view(void) -{ - rb_cMemoryView = rb_define_class_under(mFiddle, "MemoryView", rb_cObject); - rb_define_alloc_func(rb_cMemoryView, rb_fiddle_memview_s_allocate); - rb_define_singleton_method(rb_cMemoryView, "export", rb_fiddle_memview_s_export, 1); - rb_define_method(rb_cMemoryView, "initialize", rb_fiddle_memview_initialize, 1); - rb_define_method(rb_cMemoryView, "release", rb_fiddle_memview_release, 0); - rb_define_method(rb_cMemoryView, "obj", rb_fiddle_memview_get_obj, 0); - rb_define_method(rb_cMemoryView, "byte_size", rb_fiddle_memview_get_byte_size, 0); - rb_define_method(rb_cMemoryView, "readonly?", rb_fiddle_memview_get_readonly, 0); - rb_define_method(rb_cMemoryView, "format", rb_fiddle_memview_get_format, 0); - rb_define_method(rb_cMemoryView, "item_size", rb_fiddle_memview_get_item_size, 0); - rb_define_method(rb_cMemoryView, "ndim", rb_fiddle_memview_get_ndim, 0); - rb_define_method(rb_cMemoryView, "shape", rb_fiddle_memview_get_shape, 0); - rb_define_method(rb_cMemoryView, "strides", rb_fiddle_memview_get_strides, 0); - rb_define_method(rb_cMemoryView, "sub_offsets", rb_fiddle_memview_get_sub_offsets, 0); - rb_define_method(rb_cMemoryView, "[]", rb_fiddle_memview_aref, -1); - rb_define_method(rb_cMemoryView, "to_s", rb_fiddle_memview_to_s, 0); -} - -#endif /* HAVE_RUBY_MEMORY_VIEW_H */ diff --git a/ext/fiddle/pinned.c b/ext/fiddle/pinned.c deleted file mode 100644 index 019a3020e2647e..00000000000000 --- a/ext/fiddle/pinned.c +++ /dev/null @@ -1,123 +0,0 @@ -#include - -VALUE rb_cPinned; -VALUE rb_eFiddleClearedReferenceError; - -struct pinned_data { - VALUE ptr; -}; - -static void -pinned_mark(void *ptr) -{ - struct pinned_data *data = (struct pinned_data*)ptr; - /* Ensure reference is pinned */ - if (data->ptr) { - rb_gc_mark(data->ptr); - } -} - -static size_t -pinned_memsize(const void *ptr) -{ - return sizeof(struct pinned_data); -} - -static const rb_data_type_t pinned_data_type = { - "fiddle/pinned", - {pinned_mark, xfree, pinned_memsize, }, - 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED -}; - -static VALUE -allocate(VALUE klass) -{ - struct pinned_data *data; - VALUE obj = TypedData_Make_Struct(klass, struct pinned_data, &pinned_data_type, data); - data->ptr = 0; - return obj; -} - -/* - * call-seq: - * Fiddle::Pinned.new(object) => pinned_object - * - * Create a new pinned object reference. The Fiddle::Pinned instance will - * prevent the GC from moving +object+. - */ -static VALUE -initialize(VALUE self, VALUE ref) -{ - struct pinned_data *data; - TypedData_Get_Struct(self, struct pinned_data, &pinned_data_type, data); - RB_OBJ_WRITE(self, &data->ptr, ref); - return self; -} - -/* - * call-seq: ref - * - * Return the object that this pinned instance references. - */ -static VALUE -ref(VALUE self) -{ - struct pinned_data *data; - TypedData_Get_Struct(self, struct pinned_data, &pinned_data_type, data); - if (data->ptr) { - return data->ptr; - } else { - rb_raise(rb_eFiddleClearedReferenceError, "`ref` called on a cleared object"); - } -} - -/* - * call-seq: clear - * - * Clear the reference to the object this is pinning. - */ -static VALUE -clear(VALUE self) -{ - struct pinned_data *data; - TypedData_Get_Struct(self, struct pinned_data, &pinned_data_type, data); - data->ptr = 0; - return self; -} - -/* - * call-seq: cleared? - * - * Returns true if the reference has been cleared, otherwise returns false. - */ -static VALUE -cleared_p(VALUE self) -{ - struct pinned_data *data; - TypedData_Get_Struct(self, struct pinned_data, &pinned_data_type, data); - if (data->ptr) { - return Qfalse; - } else { - return Qtrue; - } -} - -extern VALUE rb_eFiddleError; - -void -Init_fiddle_pinned(void) -{ - rb_cPinned = rb_define_class_under(mFiddle, "Pinned", rb_cObject); - rb_define_alloc_func(rb_cPinned, allocate); - rb_define_method(rb_cPinned, "initialize", initialize, 1); - rb_define_method(rb_cPinned, "ref", ref, 0); - rb_define_method(rb_cPinned, "clear", clear, 0); - rb_define_method(rb_cPinned, "cleared?", cleared_p, 0); - - /* - * Document-class: Fiddle::ClearedReferenceError - * - * Cleared reference exception - */ - rb_eFiddleClearedReferenceError = rb_define_class_under(mFiddle, "ClearedReferenceError", rb_eFiddleError); -} diff --git a/ext/fiddle/pointer.c b/ext/fiddle/pointer.c deleted file mode 100644 index 1b7d7a69f6a4c3..00000000000000 --- a/ext/fiddle/pointer.c +++ /dev/null @@ -1,887 +0,0 @@ -/* -*- C -*- - * $Id$ - */ - -#include -#include -#include - -#include -#include - -#ifdef HAVE_RUBY_MEMORY_VIEW_H -# include -#endif - -#ifdef PRIsVALUE -# define RB_OBJ_CLASSNAME(obj) rb_obj_class(obj) -# define RB_OBJ_STRING(obj) (obj) -#else -# define PRIsVALUE "s" -# define RB_OBJ_CLASSNAME(obj) rb_obj_classname(obj) -# define RB_OBJ_STRING(obj) StringValueCStr(obj) -#endif - -VALUE rb_cPointer; - -typedef rb_fiddle_freefunc_t freefunc_t; - -struct ptr_data { - void *ptr; - long size; - freefunc_t free; - bool freed; - VALUE wrap[2]; -}; - -#define RPTR_DATA(obj) ((struct ptr_data *)(DATA_PTR(obj))) - -static inline freefunc_t -get_freefunc(VALUE func, volatile VALUE *wrap) -{ - VALUE addrnum; - if (NIL_P(func)) { - *wrap = 0; - return NULL; - } - addrnum = rb_Integer(func); - *wrap = (addrnum != func) ? func : 0; - return (freefunc_t)(VALUE)NUM2PTR(addrnum); -} - -static ID id_to_ptr; - -static void -fiddle_ptr_mark(void *ptr) -{ - struct ptr_data *data = ptr; - if (data->wrap[0]) { - rb_gc_mark(data->wrap[0]); - } - if (data->wrap[1]) { - rb_gc_mark(data->wrap[1]); - } -} - -static void -fiddle_ptr_free_ptr(void *ptr) -{ - struct ptr_data *data = ptr; - if (data->ptr && data->free && !data->freed) { - data->freed = true; - (*(data->free))(data->ptr); - } -} - -static void -fiddle_ptr_free(void *ptr) -{ - fiddle_ptr_free_ptr(ptr); - xfree(ptr); -} - -static size_t -fiddle_ptr_memsize(const void *ptr) -{ - const struct ptr_data *data = ptr; - return sizeof(*data) + data->size; -} - -static const rb_data_type_t fiddle_ptr_data_type = { - .wrap_struct_name = "fiddle/pointer", - .function = { - .dmark = fiddle_ptr_mark, - .dfree = fiddle_ptr_free, - .dsize = fiddle_ptr_memsize, - }, - .flags = RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED -}; - -#ifdef HAVE_RUBY_MEMORY_VIEW_H -static struct ptr_data * -fiddle_ptr_check_memory_view(VALUE obj) -{ - struct ptr_data *data; - TypedData_Get_Struct(obj, struct ptr_data, &fiddle_ptr_data_type, data); - if (data->ptr == NULL || data->size == 0) return NULL; - return data; -} - -static bool -fiddle_ptr_memory_view_available_p(VALUE obj) -{ - return fiddle_ptr_check_memory_view(obj) != NULL; -} - -static bool -fiddle_ptr_get_memory_view(VALUE obj, rb_memory_view_t *view, int flags) -{ - struct ptr_data *data = fiddle_ptr_check_memory_view(obj); - rb_memory_view_init_as_byte_array(view, obj, data->ptr, data->size, true); - - return true; -} - -static const rb_memory_view_entry_t fiddle_ptr_memory_view_entry = { - fiddle_ptr_get_memory_view, - NULL, - fiddle_ptr_memory_view_available_p -}; -#endif - -static VALUE -rb_fiddle_ptr_new2(VALUE klass, void *ptr, long size, freefunc_t func, VALUE wrap0, VALUE wrap1) -{ - struct ptr_data *data; - VALUE val; - - val = TypedData_Make_Struct(klass, struct ptr_data, &fiddle_ptr_data_type, data); - data->ptr = ptr; - data->free = func; - data->freed = false; - data->size = size; - RB_OBJ_WRITE(val, &data->wrap[0], wrap0); - RB_OBJ_WRITE(val, &data->wrap[1], wrap1); - - return val; -} - -VALUE -rb_fiddle_ptr_new_wrap(void *ptr, long size, freefunc_t func, VALUE wrap0, VALUE wrap1) -{ - return rb_fiddle_ptr_new2(rb_cPointer, ptr, size, func, wrap0, wrap1); -} - -static VALUE -rb_fiddle_ptr_new(void *ptr, long size, freefunc_t func) -{ - return rb_fiddle_ptr_new2(rb_cPointer, ptr, size, func, 0, 0); -} - -static VALUE -rb_fiddle_ptr_malloc(VALUE klass, long size, freefunc_t func) -{ - void *ptr; - - ptr = ruby_xmalloc((size_t)size); - memset(ptr,0,(size_t)size); - return rb_fiddle_ptr_new2(klass, ptr, size, func, 0, 0); -} - -static void * -rb_fiddle_ptr2cptr(VALUE val) -{ - struct ptr_data *data; - void *ptr; - - if (rb_obj_is_kind_of(val, rb_cPointer)) { - TypedData_Get_Struct(val, struct ptr_data, &fiddle_ptr_data_type, data); - ptr = data->ptr; - } - else if (val == Qnil) { - ptr = NULL; - } - else{ - rb_raise(rb_eTypeError, "Fiddle::Pointer was expected"); - } - - return ptr; -} - -static VALUE -rb_fiddle_ptr_s_allocate(VALUE klass) -{ - VALUE obj; - struct ptr_data *data; - - obj = TypedData_Make_Struct(klass, struct ptr_data, &fiddle_ptr_data_type, data); - data->ptr = 0; - data->size = 0; - data->free = 0; - data->freed = false; - - return obj; -} - -/* - * call-seq: - * Fiddle::Pointer.new(address) => fiddle_cptr - * new(address, size) => fiddle_cptr - * new(address, size, freefunc) => fiddle_cptr - * - * Create a new pointer to +address+ with an optional +size+ and +freefunc+. - * - * +freefunc+ will be called when the instance is garbage collected. - */ -static VALUE -rb_fiddle_ptr_initialize(int argc, VALUE argv[], VALUE self) -{ - VALUE ptr, sym, size, wrap = 0, funcwrap = 0; - struct ptr_data *data; - void *p = NULL; - freefunc_t f = NULL; - long s = 0; - - if (rb_scan_args(argc, argv, "12", &ptr, &size, &sym) >= 1) { - VALUE addrnum = rb_Integer(ptr); - if (addrnum != ptr) wrap = ptr; - p = NUM2PTR(addrnum); - } - if (argc >= 2) { - s = NUM2LONG(size); - } - if (argc >= 3) { - f = get_freefunc(sym, &funcwrap); - } - - if (p) { - TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data); - if (data->ptr && data->free) { - /* Free previous memory. Use of inappropriate initialize may cause SEGV. */ - (*(data->free))(data->ptr); - } - RB_OBJ_WRITE(self, &data->wrap[0], wrap); - RB_OBJ_WRITE(self, &data->wrap[1], funcwrap); - data->ptr = p; - data->size = s; - data->free = f; - } - - return Qnil; -} - -static VALUE -rb_fiddle_ptr_call_free(VALUE self); - -/* - * call-seq: - * Fiddle::Pointer.malloc(size, freefunc = nil) => fiddle pointer instance - * Fiddle::Pointer.malloc(size, freefunc) { |pointer| ... } => ... - * - * == Examples - * - * # Automatically freeing the pointer when the block is exited - recommended - * Fiddle::Pointer.malloc(size, Fiddle::RUBY_FREE) do |pointer| - * ... - * end - * - * # Manually freeing but relying on the garbage collector otherwise - * pointer = Fiddle::Pointer.malloc(size, Fiddle::RUBY_FREE) - * ... - * pointer.call_free - * - * # Relying on the garbage collector - may lead to unlimited memory allocated before freeing any, but safe - * pointer = Fiddle::Pointer.malloc(size, Fiddle::RUBY_FREE) - * ... - * - * # Only manually freeing - * pointer = Fiddle::Pointer.malloc(size) - * begin - * ... - * ensure - * Fiddle.free pointer - * end - * - * # No free function and no call to free - the native memory will leak if the pointer is garbage collected - * pointer = Fiddle::Pointer.malloc(size) - * ... - * - * Allocate +size+ bytes of memory and associate it with an optional - * +freefunc+. - * - * If a block is supplied, the pointer will be yielded to the block instead of - * being returned, and the return value of the block will be returned. A - * +freefunc+ must be supplied if a block is. - * - * If a +freefunc+ is supplied it will be called once, when the pointer is - * garbage collected or when the block is left if a block is supplied or - * when the user calls +call_free+, whichever happens first. +freefunc+ must be - * an address pointing to a function or an instance of +Fiddle::Function+. - */ -static VALUE -rb_fiddle_ptr_s_malloc(int argc, VALUE argv[], VALUE klass) -{ - VALUE size, sym, obj, wrap = 0; - long s; - freefunc_t f; - - switch (rb_scan_args(argc, argv, "11", &size, &sym)) { - case 1: - s = NUM2LONG(size); - f = NULL; - break; - case 2: - s = NUM2LONG(size); - f = get_freefunc(sym, &wrap); - break; - default: - rb_bug("rb_fiddle_ptr_s_malloc"); - } - - obj = rb_fiddle_ptr_malloc(klass, s,f); - if (wrap) RB_OBJ_WRITE(obj, &RPTR_DATA(obj)->wrap[1], wrap); - - if (rb_block_given_p()) { - if (!f) { - rb_raise(rb_eArgError, "a free function must be supplied to Fiddle::Pointer.malloc when it is called with a block"); - } - return rb_ensure(rb_yield, obj, rb_fiddle_ptr_call_free, obj); - } else { - return obj; - } -} - -/* - * call-seq: to_i - * - * Returns the integer memory location of this pointer. - */ -static VALUE -rb_fiddle_ptr_to_i(VALUE self) -{ - struct ptr_data *data; - - TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data); - return PTR2NUM(data->ptr); -} - -/* - * call-seq: to_value - * - * Cast this pointer to a ruby object. - */ -static VALUE -rb_fiddle_ptr_to_value(VALUE self) -{ - struct ptr_data *data; - TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data); - return (VALUE)(data->ptr); -} - -/* - * call-seq: ptr - * - * Returns a new Fiddle::Pointer instance that is a dereferenced pointer for - * this pointer. - * - * Analogous to the star operator in C. - */ -static VALUE -rb_fiddle_ptr_ptr(VALUE self) -{ - struct ptr_data *data; - - TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data); - return rb_fiddle_ptr_new(*((void**)(data->ptr)),0,0); -} - -/* - * call-seq: ref - * - * Returns a new Fiddle::Pointer instance that is a reference pointer for this - * pointer. - * - * Analogous to the ampersand operator in C. - */ -static VALUE -rb_fiddle_ptr_ref(VALUE self) -{ - struct ptr_data *data; - - TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data); - return rb_fiddle_ptr_new(&(data->ptr),0,0); -} - -/* - * call-seq: null? - * - * Returns +true+ if this is a null pointer. - */ -static VALUE -rb_fiddle_ptr_null_p(VALUE self) -{ - struct ptr_data *data; - - TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data); - return data->ptr ? Qfalse : Qtrue; -} - -/* - * call-seq: free=(function) - * - * Set the free function for this pointer to +function+ in the given - * Fiddle::Function. - */ -static VALUE -rb_fiddle_ptr_free_set(VALUE self, VALUE val) -{ - struct ptr_data *data; - - TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data); - data->free = get_freefunc(val, &data->wrap[1]); - - return Qnil; -} - -/* - * call-seq: free => Fiddle::Function - * - * Get the free function for this pointer. - * - * Returns a new instance of Fiddle::Function. - * - * See Fiddle::Function.new - */ -static VALUE -rb_fiddle_ptr_free_get(VALUE self) -{ - struct ptr_data *pdata; - VALUE address; - VALUE arg_types; - VALUE ret_type; - - TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, pdata); - - if (!pdata->free) - return Qnil; - - address = PTR2NUM(pdata->free); - ret_type = INT2NUM(TYPE_VOID); - arg_types = rb_ary_new(); - rb_ary_push(arg_types, INT2NUM(TYPE_VOIDP)); - - return rb_fiddle_new_function(address, arg_types, ret_type); -} - -/* - * call-seq: call_free => nil - * - * Call the free function for this pointer. Calling more than once will do - * nothing. Does nothing if there is no free function attached. - */ -static VALUE -rb_fiddle_ptr_call_free(VALUE self) -{ - struct ptr_data *pdata; - TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, pdata); - fiddle_ptr_free_ptr(pdata); - return Qnil; -} - -/* - * call-seq: freed? => bool - * - * Returns if the free function for this pointer has been called. - */ -static VALUE -rb_fiddle_ptr_freed_p(VALUE self) -{ - struct ptr_data *pdata; - TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, pdata); - return pdata->freed ? Qtrue : Qfalse; -} - -/* - * call-seq: - * - * ptr.to_s => string - * ptr.to_s(len) => string - * - * Returns the pointer contents as a string. - * - * When called with no arguments, this method will return the contents until - * the first NULL byte. - * - * When called with +len+, a string of +len+ bytes will be returned. - * - * See to_str - */ -static VALUE -rb_fiddle_ptr_to_s(int argc, VALUE argv[], VALUE self) -{ - struct ptr_data *data; - VALUE arg1, val; - int len; - - TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data); - switch (rb_scan_args(argc, argv, "01", &arg1)) { - case 0: - val = rb_str_new2((char*)(data->ptr)); - break; - case 1: - len = NUM2INT(arg1); - val = rb_str_new((char*)(data->ptr), len); - break; - default: - rb_bug("rb_fiddle_ptr_to_s"); - } - - return val; -} - -/* - * call-seq: - * - * ptr.to_str => string - * ptr.to_str(len) => string - * - * Returns the pointer contents as a string. - * - * When called with no arguments, this method will return the contents with the - * length of this pointer's +size+. - * - * When called with +len+, a string of +len+ bytes will be returned. - * - * See to_s - */ -static VALUE -rb_fiddle_ptr_to_str(int argc, VALUE argv[], VALUE self) -{ - struct ptr_data *data; - VALUE arg1, val; - int len; - - TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data); - switch (rb_scan_args(argc, argv, "01", &arg1)) { - case 0: - val = rb_str_new((char*)(data->ptr),data->size); - break; - case 1: - len = NUM2INT(arg1); - val = rb_str_new((char*)(data->ptr), len); - break; - default: - rb_bug("rb_fiddle_ptr_to_str"); - } - - return val; -} - -/* - * call-seq: inspect - * - * Returns a string formatted with an easily readable representation of the - * internal state of the pointer. - */ -static VALUE -rb_fiddle_ptr_inspect(VALUE self) -{ - struct ptr_data *data; - - TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data); - return rb_sprintf("#<%"PRIsVALUE":%p ptr=%p size=%ld free=%p>", - RB_OBJ_CLASSNAME(self), (void *)data, data->ptr, data->size, (void *)data->free); -} - -/* - * call-seq: - * ptr == other => true or false - * ptr.eql?(other) => true or false - * - * Returns true if +other+ wraps the same pointer, otherwise returns - * false. - */ -static VALUE -rb_fiddle_ptr_eql(VALUE self, VALUE other) -{ - void *ptr1, *ptr2; - - if(!rb_obj_is_kind_of(other, rb_cPointer)) return Qfalse; - - ptr1 = rb_fiddle_ptr2cptr(self); - ptr2 = rb_fiddle_ptr2cptr(other); - - return ptr1 == ptr2 ? Qtrue : Qfalse; -} - -/* - * call-seq: - * ptr <=> other => -1, 0, 1, or nil - * - * Returns -1 if less than, 0 if equal to, 1 if greater than +other+. - * - * Returns nil if +ptr+ cannot be compared to +other+. - */ -static VALUE -rb_fiddle_ptr_cmp(VALUE self, VALUE other) -{ - void *ptr1, *ptr2; - SIGNED_VALUE diff; - - if(!rb_obj_is_kind_of(other, rb_cPointer)) return Qnil; - - ptr1 = rb_fiddle_ptr2cptr(self); - ptr2 = rb_fiddle_ptr2cptr(other); - diff = (SIGNED_VALUE)ptr1 - (SIGNED_VALUE)ptr2; - if (!diff) return INT2FIX(0); - return diff > 0 ? INT2NUM(1) : INT2NUM(-1); -} - -/* - * call-seq: - * ptr + n => new cptr - * - * Returns a new pointer instance that has been advanced +n+ bytes. - */ -static VALUE -rb_fiddle_ptr_plus(VALUE self, VALUE other) -{ - void *ptr; - long num, size; - - ptr = rb_fiddle_ptr2cptr(self); - size = RPTR_DATA(self)->size; - num = NUM2LONG(other); - return rb_fiddle_ptr_new((char *)ptr + num, size - num, 0); -} - -/* - * call-seq: - * ptr - n => new cptr - * - * Returns a new pointer instance that has been moved back +n+ bytes. - */ -static VALUE -rb_fiddle_ptr_minus(VALUE self, VALUE other) -{ - void *ptr; - long num, size; - - ptr = rb_fiddle_ptr2cptr(self); - size = RPTR_DATA(self)->size; - num = NUM2LONG(other); - return rb_fiddle_ptr_new((char *)ptr - num, size + num, 0); -} - -/* - * call-seq: - * ptr[index] -> an_integer - * ptr[start, length] -> a_string - * - * Returns integer stored at _index_. - * - * If _start_ and _length_ are given, a string containing the bytes from - * _start_ of _length_ will be returned. - */ -static VALUE -rb_fiddle_ptr_aref(int argc, VALUE argv[], VALUE self) -{ - VALUE arg0, arg1; - VALUE retval = Qnil; - size_t offset, len; - struct ptr_data *data; - - TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data); - if (!data->ptr) rb_raise(rb_eFiddleDLError, "NULL pointer dereference"); - switch( rb_scan_args(argc, argv, "11", &arg0, &arg1) ){ - case 1: - offset = NUM2ULONG(arg0); - retval = INT2NUM(*((char *)data->ptr + offset)); - break; - case 2: - offset = NUM2ULONG(arg0); - len = NUM2ULONG(arg1); - retval = rb_str_new((char *)data->ptr + offset, len); - break; - default: - rb_bug("rb_fiddle_ptr_aref()"); - } - return retval; -} - -/* - * call-seq: - * ptr[index] = int -> int - * ptr[start, length] = string or cptr or addr -> string or dl_cptr or addr - * - * Set the value at +index+ to +int+. - * - * Or, set the memory at +start+ until +length+ with the contents of +string+, - * the memory from +dl_cptr+, or the memory pointed at by the memory address - * +addr+. - */ -static VALUE -rb_fiddle_ptr_aset(int argc, VALUE argv[], VALUE self) -{ - VALUE arg0, arg1, arg2; - VALUE retval = Qnil; - size_t offset, len; - void *mem; - struct ptr_data *data; - - TypedData_Get_Struct(self, struct ptr_data, &fiddle_ptr_data_type, data); - if (!data->ptr) rb_raise(rb_eFiddleDLError, "NULL pointer dereference"); - switch( rb_scan_args(argc, argv, "21", &arg0, &arg1, &arg2) ){ - case 2: - offset = NUM2ULONG(arg0); - ((char*)data->ptr)[offset] = NUM2UINT(arg1); - retval = arg1; - break; - case 3: - offset = NUM2ULONG(arg0); - len = NUM2ULONG(arg1); - if (RB_TYPE_P(arg2, T_STRING)) { - mem = StringValuePtr(arg2); - } - else if( rb_obj_is_kind_of(arg2, rb_cPointer) ){ - mem = rb_fiddle_ptr2cptr(arg2); - } - else{ - mem = NUM2PTR(arg2); - } - memcpy((char *)data->ptr + offset, mem, len); - retval = arg2; - break; - default: - rb_bug("rb_fiddle_ptr_aset()"); - } - return retval; -} - -/* - * call-seq: size=(size) - * - * Set the size of this pointer to +size+ - */ -static VALUE -rb_fiddle_ptr_size_set(VALUE self, VALUE size) -{ - RPTR_DATA(self)->size = NUM2LONG(size); - return size; -} - -/* - * call-seq: size - * - * Get the size of this pointer. - */ -static VALUE -rb_fiddle_ptr_size_get(VALUE self) -{ - return LONG2NUM(RPTR_DATA(self)->size); -} - -/* - * call-seq: - * Fiddle::Pointer[val] => cptr - * to_ptr(val) => cptr - * - * Get the underlying pointer for ruby object +val+ and return it as a - * Fiddle::Pointer object. - */ -static VALUE -rb_fiddle_ptr_s_to_ptr(VALUE self, VALUE val) -{ - VALUE ptr, wrap = val, vptr; - - if (RTEST(rb_obj_is_kind_of(val, rb_cIO))){ - rb_io_t *fptr; - FILE *fp; - GetOpenFile(val, fptr); - fp = rb_io_stdio_file(fptr); - ptr = rb_fiddle_ptr_new(fp, 0, NULL); - } - else if (RTEST(rb_obj_is_kind_of(val, rb_cString))){ - char *str = StringValuePtr(val); - wrap = val; - ptr = rb_fiddle_ptr_new(str, RSTRING_LEN(val), NULL); - } - else if ((vptr = rb_check_funcall(val, id_to_ptr, 0, 0)) != Qundef){ - if (rb_obj_is_kind_of(vptr, rb_cPointer)){ - ptr = vptr; - wrap = 0; - } - else{ - rb_raise(rb_eFiddleDLError, "to_ptr should return a Fiddle::Pointer object"); - } - } - else{ - VALUE num = rb_Integer(val); - if (num == val) wrap = 0; - ptr = rb_fiddle_ptr_new(NUM2PTR(num), 0, NULL); - } - if (wrap) RB_OBJ_WRITE(ptr, &RPTR_DATA(ptr)->wrap[0], wrap); - return ptr; -} - -/* - * call-seq: - * Fiddle::Pointer.read(address, len) => string - * - * Or read the memory at address +address+ with length +len+ and return a - * string with that memory - */ - -static VALUE -rb_fiddle_ptr_read_mem(VALUE klass, VALUE address, VALUE len) -{ - return rb_str_new((char *)NUM2PTR(address), NUM2ULONG(len)); -} - -/* - * call-seq: - * Fiddle::Pointer.write(address, str) - * - * Write bytes in +str+ to the location pointed to by +address+. - */ -static VALUE -rb_fiddle_ptr_write_mem(VALUE klass, VALUE addr, VALUE str) -{ - memcpy(NUM2PTR(addr), StringValuePtr(str), RSTRING_LEN(str)); - return str; -} - -void -Init_fiddle_pointer(void) -{ -#undef rb_intern - id_to_ptr = rb_intern("to_ptr"); - - /* Document-class: Fiddle::Pointer - * - * Fiddle::Pointer is a class to handle C pointers - * - */ - rb_cPointer = rb_define_class_under(mFiddle, "Pointer", rb_cObject); - rb_define_alloc_func(rb_cPointer, rb_fiddle_ptr_s_allocate); - rb_define_singleton_method(rb_cPointer, "malloc", rb_fiddle_ptr_s_malloc, -1); - rb_define_singleton_method(rb_cPointer, "to_ptr", rb_fiddle_ptr_s_to_ptr, 1); - rb_define_singleton_method(rb_cPointer, "[]", rb_fiddle_ptr_s_to_ptr, 1); - rb_define_singleton_method(rb_cPointer, "read", rb_fiddle_ptr_read_mem, 2); - rb_define_singleton_method(rb_cPointer, "write", rb_fiddle_ptr_write_mem, 2); - rb_define_method(rb_cPointer, "initialize", rb_fiddle_ptr_initialize, -1); - rb_define_method(rb_cPointer, "free=", rb_fiddle_ptr_free_set, 1); - rb_define_method(rb_cPointer, "free", rb_fiddle_ptr_free_get, 0); - rb_define_method(rb_cPointer, "call_free", rb_fiddle_ptr_call_free, 0); - rb_define_method(rb_cPointer, "freed?", rb_fiddle_ptr_freed_p, 0); - rb_define_method(rb_cPointer, "to_i", rb_fiddle_ptr_to_i, 0); - rb_define_method(rb_cPointer, "to_int", rb_fiddle_ptr_to_i, 0); - rb_define_method(rb_cPointer, "to_value", rb_fiddle_ptr_to_value, 0); - rb_define_method(rb_cPointer, "ptr", rb_fiddle_ptr_ptr, 0); - rb_define_method(rb_cPointer, "+@", rb_fiddle_ptr_ptr, 0); - rb_define_method(rb_cPointer, "ref", rb_fiddle_ptr_ref, 0); - rb_define_method(rb_cPointer, "-@", rb_fiddle_ptr_ref, 0); - rb_define_method(rb_cPointer, "null?", rb_fiddle_ptr_null_p, 0); - rb_define_method(rb_cPointer, "to_s", rb_fiddle_ptr_to_s, -1); - rb_define_method(rb_cPointer, "to_str", rb_fiddle_ptr_to_str, -1); - rb_define_method(rb_cPointer, "inspect", rb_fiddle_ptr_inspect, 0); - rb_define_method(rb_cPointer, "<=>", rb_fiddle_ptr_cmp, 1); - rb_define_method(rb_cPointer, "==", rb_fiddle_ptr_eql, 1); - rb_define_method(rb_cPointer, "eql?", rb_fiddle_ptr_eql, 1); - rb_define_method(rb_cPointer, "+", rb_fiddle_ptr_plus, 1); - rb_define_method(rb_cPointer, "-", rb_fiddle_ptr_minus, 1); - rb_define_method(rb_cPointer, "[]", rb_fiddle_ptr_aref, -1); - rb_define_method(rb_cPointer, "[]=", rb_fiddle_ptr_aset, -1); - rb_define_method(rb_cPointer, "size", rb_fiddle_ptr_size_get, 0); - rb_define_method(rb_cPointer, "size=", rb_fiddle_ptr_size_set, 1); - -#ifdef HAVE_RUBY_MEMORY_VIEW_H - rb_memory_view_register(rb_cPointer, &fiddle_ptr_memory_view_entry); -#endif - - /* Document-const: NULL - * - * A NULL pointer - */ - rb_define_const(mFiddle, "NULL", rb_fiddle_ptr_new(0, 0, 0)); -} diff --git a/ext/fiddle/win32/fficonfig.h b/ext/fiddle/win32/fficonfig.h deleted file mode 100644 index 776808159c9dee..00000000000000 --- a/ext/fiddle/win32/fficonfig.h +++ /dev/null @@ -1,29 +0,0 @@ -#define HAVE_ALLOCA 1 -#define HAVE_MEMCPY 1 -#define HAVE_MEMORY_H 1 -#define HAVE_STDLIB_H 1 -#define HAVE_STRING_H 1 -#define HAVE_SYS_STAT_H 1 -#define HAVE_SYS_TYPES_H 1 -#if _MSC_VER >= 1600 -#define HAVE_INTTYPES_H 1 -#define HAVE_STDINT_H 1 -#endif - -#define SIZEOF_DOUBLE 8 -#if defined(X86_WIN64) -#define SIZEOF_SIZE_T 8 -#else -#define SIZEOF_SIZE_T 4 -#endif - -#define STACK_DIRECTION -1 - -#define STDC_HEADERS 1 - -#ifdef LIBFFI_ASM -#define FFI_HIDDEN(name) -#else -#define FFI_HIDDEN -#endif - diff --git a/ext/fiddle/win32/libffi-3.2.1-mswin.patch b/ext/fiddle/win32/libffi-3.2.1-mswin.patch deleted file mode 100644 index f9100e703db581..00000000000000 --- a/ext/fiddle/win32/libffi-3.2.1-mswin.patch +++ /dev/null @@ -1,191 +0,0 @@ -diff -ru libffi-3.2.1/src/x86/ffi.c libffi-3.2.1/src/x86/ffi.c ---- libffi-3.2.1/src/x86/ffi.c 2014-11-08 21:47:24.000000000 +0900 -+++ libffi-3.2.1/src/x86/ffi.c 2014-12-25 18:46:14.806761900 +0900 -@@ -99,11 +99,13 @@ - i != 0; - i--, p_arg += dir, p_argv += dir) - { -+ size_t z; -+ - /* Align if necessary */ - if ((sizeof(void*) - 1) & (size_t) argp) - argp = (char *) ALIGN(argp, sizeof(void*)); - -- size_t z = (*p_arg)->size; -+ z = (*p_arg)->size; - - #ifdef X86_WIN64 - if (z > FFI_SIZEOF_ARG -@@ -202,6 +204,7 @@ - on top of stack, so that those can be moved to registers by call-handler. */ - if (stack_args_count > 0) - { -+ int i; - if (dir < 0 && stack_args_count > 1) - { - /* Reverse order if iterating arguments backwards */ -@@ -210,7 +213,6 @@ - *(ffi_arg*) p_stack_data[stack_args_count - 1] = tmp; - } - -- int i; - for (i = 0; i < stack_args_count; i++) - { - if (p_stack_data[i] != argp2) -@@ -569,11 +571,12 @@ - i < cif->nargs && passed_regs < max_stack_count; - i++, p_arg++) - { -+ size_t sz; - if ((*p_arg)->type == FFI_TYPE_FLOAT - || (*p_arg)->type == FFI_TYPE_STRUCT) - continue; - -- size_t sz = (*p_arg)->size; -+ sz = (*p_arg)->size; - if(sz == 0 || sz > FFI_SIZEOF_ARG) - continue; - -@@ -599,11 +602,13 @@ - i != 0; - i--, p_arg += dir, p_argv += dir) - { -+ size_t z; -+ - /* Align if necessary */ - if ((sizeof(void*) - 1) & (size_t) argp) - argp = (char *) ALIGN(argp, sizeof(void*)); - -- size_t z = (*p_arg)->size; -+ z = (*p_arg)->size; - - #ifdef X86_WIN64 - if (z > FFI_SIZEOF_ARG -@@ -642,7 +647,7 @@ - #endif - } - -- return (size_t)argp - (size_t)stack; -+ return (int)((size_t)argp - (size_t)stack); - } - - #define FFI_INIT_TRAMPOLINE_WIN64(TRAMP,FUN,CTX,MASK) \ -@@ -855,11 +860,12 @@ - - for (i = 0; i < cif->nargs && passed_regs <= max_regs; i++) - { -+ size_t sz; - if (cif->arg_types[i]->type == FFI_TYPE_FLOAT - || cif->arg_types[i]->type == FFI_TYPE_STRUCT) - continue; - -- size_t sz = cif->arg_types[i]->size; -+ sz = cif->arg_types[i]->size; - if (sz == 0 || sz > FFI_SIZEOF_ARG) - continue; - -diff -ru libffi-3.2.1/src/x86/ffitarget.h libffi-3.2.1/src/x86/ffitarget.h ---- libffi-3.2.1/src/x86/ffitarget.h 2014-11-08 21:47:24.000000000 +0900 -+++ libffi-3.2.1/src/x86/ffitarget.h 2014-12-22 15:45:54.000000000 +0900 -@@ -50,7 +50,9 @@ - #endif - - #define FFI_TARGET_SPECIFIC_STACK_SPACE_ALLOCATION -+#ifndef _MSC_VER - #define FFI_TARGET_HAS_COMPLEX_TYPE -+#endif - - /* ---- Generic type definitions ----------------------------------------- */ - -diff -ru libffi-3.2.1/src/x86/win64.S libffi-3.2.1/src/x86/win64.S ---- libffi-3.2.1/src/x86/win64.S 2014-11-08 21:47:24.000000000 +0900 -+++ libffi-3.2.1/src/x86/win64.S 2014-12-22 16:14:40.000000000 +0900 -@@ -127,7 +127,7 @@ - - mov rcx, QWORD PTR RVALUE[rbp] - mov DWORD PTR [rcx], eax -- jmp ret_void$ -+ jmp SHORT ret_void$ - - ret_struct2b$: - cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SMALL_STRUCT_2B -@@ -135,7 +135,7 @@ - - mov rcx, QWORD PTR RVALUE[rbp] - mov WORD PTR [rcx], ax -- jmp ret_void$ -+ jmp SHORT ret_void$ - - ret_struct1b$: - cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SMALL_STRUCT_1B -@@ -143,7 +143,7 @@ - - mov rcx, QWORD PTR RVALUE[rbp] - mov BYTE PTR [rcx], al -- jmp ret_void$ -+ jmp SHORT ret_void$ - - ret_uint8$: - cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_UINT8 -@@ -152,7 +152,7 @@ - mov rcx, QWORD PTR RVALUE[rbp] - movzx rax, al - mov QWORD PTR [rcx], rax -- jmp ret_void$ -+ jmp SHORT ret_void$ - - ret_sint8$: - cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SINT8 -@@ -161,7 +161,7 @@ - mov rcx, QWORD PTR RVALUE[rbp] - movsx rax, al - mov QWORD PTR [rcx], rax -- jmp ret_void$ -+ jmp SHORT ret_void$ - - ret_uint16$: - cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_UINT16 -@@ -188,7 +188,13 @@ - mov rcx, QWORD PTR RVALUE[rbp] - mov eax, eax - mov QWORD PTR [rcx], rax -- jmp SHORT ret_void$ -+ -+ret_void$: -+ xor rax, rax -+ -+ lea rsp, QWORD PTR [rbp+16] -+ pop rbp -+ ret 0 - - ret_sint32$: - cmp DWORD PTR CIF_FLAGS[rbp], FFI_TYPE_SINT32 -@@ -247,13 +253,6 @@ - cdqe - mov QWORD PTR [rcx], rax - jmp SHORT ret_void$ -- --ret_void$: -- xor rax, rax -- -- lea rsp, QWORD PTR [rbp+16] -- pop rbp -- ret 0 - ffi_call_win64 ENDP - _TEXT ENDS - END -diff -ru libffi-3.2.1/include/ffi.h.in libffi-3.2.1/include/ffi.h.in ---- libffi-3.2.1/include/ffi.h.in 2014-11-08 21:47:24.000000000 +0900 -+++ libffi-3.2.1/include/ffi.h.in 2015-01-11 12:35:30.000000000 +0900 -@@ -103,6 +103,11 @@ - # undef FFI_64_BIT_MAX - # define FFI_64_BIT_MAX 9223372036854775807LL - # endif -+# ifdef _MSC_VER -+# define FFI_LONG_LONG_MAX _I64_MAX -+# undef FFI_64_BIT_MAX -+# define FFI_64_BIT_MAX 9223372036854775807I64 -+# endif - # endif - #endif - diff --git a/ext/fiddle/win32/libffi-config.rb b/ext/fiddle/win32/libffi-config.rb deleted file mode 100755 index 8e8069a943a518..00000000000000 --- a/ext/fiddle/win32/libffi-config.rb +++ /dev/null @@ -1,48 +0,0 @@ -#!/usr/bin/ruby -# frozen_string_literal: true -require 'fileutils' - -basedir = File.dirname(__FILE__) -conf = {} -enable = {} -until ARGV.empty? - arg = ARGV.shift - case arg - when '-C' - # ignore - when /\A--srcdir=(.*)/ - conf['SRCDIR'] = srcdir = $1 - when /\A(CC|CFLAGS|CXX|CXXFLAGS|LD|LDFLAGS)=(.*)/ - conf[$1] = $2 - when /\A--host=(.*)/ - host = $1 - when /\A--enable-([^=]+)(?:=(.*))?/ - enable[$1] = $2 || true - when /\A--disable-([^=]+)/ - enable[$1] = false - end -end - -File.foreach("#{srcdir}/configure.ac") do |line| - if /^AC_INIT\((.*)\)/ =~ line - version = $1.split(/,\s*/)[1] - version.gsub!(/\A\[|\]\z/, '') - conf['VERSION'] = version - break - end -end - -builddir = srcdir == "." ? (enable['builddir'] || ".") : "." -conf['TARGET'] = /^x64/ =~ host ? "X86_WIN64" : "X86_WIN32" - -FileUtils.mkdir_p([builddir, "#{builddir}/include", "#{builddir}/src/x86"]) -FileUtils.cp("#{basedir}/fficonfig.h", ".", preserve: true) - -hdr = File.binread("#{srcdir}/include/ffi.h.in") -hdr.gsub!(/@(\w+)@/) {conf[$1] || $&} -hdr.gsub!(/^(#if\s+)@\w+@/, '\10') -File.binwrite("#{builddir}/include/ffi.h", hdr) - -mk = File.binread("#{basedir}/libffi.mk.tmpl") -mk.gsub!(/@(\w+)@/) {conf[$1] || $&} -File.binwrite("Makefile", mk) diff --git a/ext/fiddle/win32/libffi.mk.tmpl b/ext/fiddle/win32/libffi.mk.tmpl deleted file mode 100644 index 2a16e8efec6ab8..00000000000000 --- a/ext/fiddle/win32/libffi.mk.tmpl +++ /dev/null @@ -1,96 +0,0 @@ -# -*- makefile -*- -# ==================================================================== -# -# libffi Windows Makefile -# -# -# ==================================================================== -# -NAME = ffi -TARGET = @TARGET@ -CC = cl -!if "$(TARGET)" == "X86_WIN64" -AS = ml64 -!else -AS = ml -!endif -AR = link -DLEXT = dll -OBJEXT = obj -LIBEXT = lib -TOPDIR = @SRCDIR@ -CPP = $(CC) -EP -CFLAGS = @CFLAGS@ -ARFLAGS = -lib -ASFLAGS = -coff -W3 -Cx -INCLUDES= -I. -I./include -I./src/x86 \ - -I$(TOPDIR)/include -I$(TOPDIR)/include/src/x86 - -SRCDIR = $(TOPDIR)/src -WORKDIR = ./.libs -BUILDDIR= ./src -LIBNAME = lib$(NAME) -STATICLIB= $(WORKDIR)/$(LIBNAME)_convenience.$(LIBEXT) - -HEADERS = \ - ./fficonfig.h -FFI_HEADERS = \ - ./include/ffi.h \ - ./include/ffitarget.h - -!if "$(TARGET)" == "X86_WIN32" -OSSRC = win32 -!else if "$(TARGET)" == "X86_WIN64" -OSSRC = win64 -!else -! error unknown target: $(TARGET) -!endif - -OBJECTS = \ - $(BUILDDIR)/closures.$(OBJEXT) \ - $(BUILDDIR)/debug.$(OBJEXT) \ - $(BUILDDIR)/java_raw_api.$(OBJEXT) \ - $(BUILDDIR)/prep_cif.$(OBJEXT) \ - $(BUILDDIR)/raw_api.$(OBJEXT) \ - $(BUILDDIR)/types.$(OBJEXT) \ - $(BUILDDIR)/x86/ffi.$(OBJEXT) \ - $(BUILDDIR)/x86/$(OSSRC).$(OBJEXT) -ASMSRCS = \ - $(BUILDDIR)/x86/$(OSSRC).asm - -.SUFFIXES : .S .asm - -all: $(WORKDIR) $(STATICLIB) - -{$(SRCDIR)}.c{$(BUILDDIR)}.$(OBJEXT): - $(CC) -c $(CFLAGS) $(INCLUDES) -Fo$(@:\=/) -Fd$(WORKDIR)/$(NAME)-src $(<:\=/) - -{$(SRCDIR)/x86}.c{$(BUILDDIR)/x86}.$(OBJEXT): - $(CC) -c $(CFLAGS) $(INCLUDES) -Fo$(@:\=/) -Fd$(WORKDIR)/$(NAME)-src $(<:\=/) - -{$(SRCDIR)/x86}.S{$(BUILDDIR)/x86}.asm: - $(CPP) $(CFLAGS) $(INCLUDES) $(<:\=/) >$(@:\=/) - -{$(BUILDDIR)/x86}.asm{$(BUILDDIR)/x86}.$(OBJEXT): - cd $(@D) && $(AS) -c $(ASFLAGS) -Fo $(@F) $(NUL - -@del /Q $(ASMSRCS:/=\) 2>NUL - -@del /Q /S $(WORKDIR:/=\) 2>NUL - -distclean: clean - -@del /Q $(HEADERS:/=\) $(FFI_HEADERS:/=\) 2>NUL - -@del /Q Makefile 2>NUL diff --git a/ext/io/console/.document b/ext/io/console/.document new file mode 100644 index 00000000000000..945a377256e996 --- /dev/null +++ b/ext/io/console/.document @@ -0,0 +1,2 @@ +console.c +lib/size.rb diff --git a/ext/io/console/console.c b/ext/io/console/console.c index e852d68eedf93b..80c1cddd5a609a 100644 --- a/ext/io/console/console.c +++ b/ext/io/console/console.c @@ -2,6 +2,10 @@ /* * console IO module */ + +static const char *const +IO_CONSOLE_VERSION = "0.8.0"; + #include "ruby.h" #include "ruby/io.h" #include "ruby/thread.h" @@ -75,9 +79,16 @@ getattr(int fd, conmode *t) #define SET_LAST_ERROR (0) #endif -static ID id_getc, id_console, id_close; +#define CSI "\x1b\x5b" + +static ID id_getc, id_close; static ID id_gets, id_flush, id_chomp_bang; +#ifndef HAVE_RB_INTERNED_STR_CSTR +# define rb_str_to_interned_str(str) rb_str_freeze(str) +# define rb_interned_str_cstr(str) rb_str_freeze(rb_usascii_str_new_cstr(str)) +#endif + #if defined HAVE_RUBY_FIBER_SCHEDULER_H # include "ruby/fiber/scheduler.h" #elif defined HAVE_RB_SCHEDULER_TIMEOUT @@ -119,7 +130,14 @@ io_get_write_io_fallback(VALUE io) #define rb_io_get_write_io io_get_write_io_fallback #endif -#define sys_fail(io) rb_sys_fail_str(rb_io_path(io)) +#ifndef DHAVE_RB_SYSERR_FAIL_STR +# define rb_syserr_fail_str(e, mesg) rb_exc_raise(rb_syserr_new_str(e, mesg)) +#endif + +#define sys_fail(io) do { \ + int err = errno; \ + rb_syserr_fail_str(err, rb_io_path(io)); \ +} while (0) #ifndef HAVE_RB_F_SEND #ifndef RB_PASS_CALLED_KEYWORDS @@ -896,6 +914,16 @@ console_set_winsize(VALUE io, VALUE size) #endif #ifdef _WIN32 +/* + * call-seq: + * io.check_winsize_changed { ... } -> io + * + * Yields while console input events are queued. + * + * This method is Windows only. + * + * You must require 'io/console' to use this method. + */ static VALUE console_check_winsize_changed(VALUE io) { @@ -982,6 +1010,14 @@ console_ioflush(VALUE io) return io; } +/* + * call-seq: + * io.beep + * + * Beeps on the output console. + * + * You must require 'io/console' to use this method. + */ static VALUE console_beep(VALUE io) { @@ -1010,67 +1046,6 @@ mode_in_range(VALUE val, int high, const char *modename) } #if defined _WIN32 -static VALUE -console_goto(VALUE io, VALUE y, VALUE x) -{ - COORD pos; - int fd = GetWriteFD(io); - pos.X = NUM2UINT(x); - pos.Y = NUM2UINT(y); - if (!SetConsoleCursorPosition((HANDLE)rb_w32_get_osfhandle(fd), pos)) { - rb_syserr_fail(LAST_ERROR, 0); - } - return io; -} - -static VALUE -console_cursor_pos(VALUE io) -{ - rb_console_size_t ws; - int fd = GetWriteFD(io); - if (!GetConsoleScreenBufferInfo((HANDLE)rb_w32_get_osfhandle(fd), &ws)) { - rb_syserr_fail(LAST_ERROR, 0); - } - return rb_assoc_new(UINT2NUM(ws.dwCursorPosition.Y), UINT2NUM(ws.dwCursorPosition.X)); -} - -static VALUE -console_move(VALUE io, int y, int x) -{ - HANDLE h; - rb_console_size_t ws; - COORD *pos = &ws.dwCursorPosition; - - h = (HANDLE)rb_w32_get_osfhandle(GetWriteFD(io)); - if (!GetConsoleScreenBufferInfo(h, &ws)) { - rb_syserr_fail(LAST_ERROR, 0); - } - pos->X += x; - pos->Y += y; - if (!SetConsoleCursorPosition(h, *pos)) { - rb_syserr_fail(LAST_ERROR, 0); - } - return io; -} - -static VALUE -console_goto_column(VALUE io, VALUE val) -{ - HANDLE h; - rb_console_size_t ws; - COORD *pos = &ws.dwCursorPosition; - - h = (HANDLE)rb_w32_get_osfhandle(GetWriteFD(io)); - if (!GetConsoleScreenBufferInfo(h, &ws)) { - rb_syserr_fail(LAST_ERROR, 0); - } - pos->X = NUM2INT(val); - if (!SetConsoleCursorPosition(h, *pos)) { - rb_syserr_fail(LAST_ERROR, 0); - } - return io; -} - static void constat_clear(HANDLE handle, WORD attr, DWORD len, COORD pos) { @@ -1080,74 +1055,6 @@ constat_clear(HANDLE handle, WORD attr, DWORD len, COORD pos) FillConsoleOutputCharacterW(handle, L' ', len, pos, &written); } -static VALUE -console_erase_line(VALUE io, VALUE val) -{ - HANDLE h; - rb_console_size_t ws; - COORD *pos = &ws.dwCursorPosition; - DWORD w; - int mode = mode_in_range(val, 2, "line erase"); - - h = (HANDLE)rb_w32_get_osfhandle(GetWriteFD(io)); - if (!GetConsoleScreenBufferInfo(h, &ws)) { - rb_syserr_fail(LAST_ERROR, 0); - } - w = winsize_col(&ws); - switch (mode) { - case 0: /* after cursor */ - w -= pos->X; - break; - case 1: /* before *and* cursor */ - w = pos->X + 1; - pos->X = 0; - break; - case 2: /* entire line */ - pos->X = 0; - break; - } - constat_clear(h, ws.wAttributes, w, *pos); - return io; -} - -static VALUE -console_erase_screen(VALUE io, VALUE val) -{ - HANDLE h; - rb_console_size_t ws; - COORD *pos = &ws.dwCursorPosition; - DWORD w; - int mode = mode_in_range(val, 3, "screen erase"); - - h = (HANDLE)rb_w32_get_osfhandle(GetWriteFD(io)); - if (!GetConsoleScreenBufferInfo(h, &ws)) { - rb_syserr_fail(LAST_ERROR, 0); - } - w = winsize_col(&ws); - switch (mode) { - case 0: /* erase after cursor */ - w = (w * (ws.srWindow.Bottom - pos->Y + 1) - pos->X); - break; - case 1: /* erase before *and* cursor */ - w = (w * (pos->Y - ws.srWindow.Top) + pos->X + 1); - pos->X = 0; - pos->Y = ws.srWindow.Top; - break; - case 2: /* erase entire screen */ - w = (w * winsize_row(&ws)); - pos->X = 0; - pos->Y = ws.srWindow.Top; - break; - case 3: /* erase entire screen */ - w = (w * ws.dwSize.Y); - pos->X = 0; - pos->Y = 0; - break; - } - constat_clear(h, ws.wAttributes, w, *pos); - return io; -} - static VALUE console_scroll(VALUE io, int line) { @@ -1176,8 +1083,22 @@ console_scroll(VALUE io, int line) return io; } +#define GPERF_DOWNCASE 1 +#define GPERF_CASE_STRCMP 1 +#define gperf_case_strcmp STRCASECMP #include "win32_vk.inc" +/* + * call-seq: + * io.pressed?(key) -> bool + * + * Returns +true+ if +key+ is pressed. +key+ may be a virtual key + * code or its name (String or Symbol) with out "VK_" prefix. + * + * This method is Windows only. + * + * You must require 'io/console' to use this method. + */ static VALUE console_key_pressed_p(VALUE io, VALUE k) { @@ -1267,9 +1188,41 @@ console_vt_response(int argc, VALUE *argv, VALUE io, const struct query_args *qa return ret; } +static VALUE +console_scroll(VALUE io, int line) +{ + if (line) { + VALUE s = rb_sprintf(CSI "%d%c", line < 0 ? -line : line, + line < 0 ? 'T' : 'S'); + rb_io_write(io, s); + } + return io; +} + +# define console_key_pressed_p rb_f_notimplement +#endif + +/* + * call-seq: + * io.cursor -> [row, column] + * + * Returns the current cursor position as a two-element array of integers (row, column) + * + * io.cursor # => [3, 5] + * + * You must require 'io/console' to use this method. + */ static VALUE console_cursor_pos(VALUE io) { +#ifdef _WIN32 + rb_console_size_t ws; + int fd = GetWriteFD(io); + if (!GetConsoleScreenBufferInfo((HANDLE)rb_w32_get_osfhandle(fd), &ws)) { + rb_syserr_fail(LAST_ERROR, 0); + } + return rb_assoc_new(UINT2NUM(ws.dwCursorPosition.Y), UINT2NUM(ws.dwCursorPosition.X)); +#else static const struct query_args query = {"\033[6n", 0}; VALUE resp = console_vt_response(0, 0, io, &query); VALUE row, column, term; @@ -1286,64 +1239,205 @@ console_cursor_pos(VALUE io) RARRAY_ASET(resp, 0, INT2NUM(r)); RARRAY_ASET(resp, 1, INT2NUM(c)); return resp; +#endif } +/* + * call-seq: + * io.goto(line, column) -> io + * + * Set the cursor position at +line+ and +column+. + * + * You must require 'io/console' to use this method. + */ static VALUE console_goto(VALUE io, VALUE y, VALUE x) { - rb_io_write(io, rb_sprintf("\x1b[%d;%dH", NUM2UINT(y)+1, NUM2UINT(x)+1)); +#ifdef _WIN32 + COORD pos; + int fd = GetWriteFD(io); + pos.X = NUM2UINT(x); + pos.Y = NUM2UINT(y); + if (!SetConsoleCursorPosition((HANDLE)rb_w32_get_osfhandle(fd), pos)) { + rb_syserr_fail(LAST_ERROR, 0); + } +#else + rb_io_write(io, rb_sprintf(CSI "%d;%dH", NUM2UINT(y)+1, NUM2UINT(x)+1)); +#endif return io; } static VALUE console_move(VALUE io, int y, int x) { +#ifdef _WIN32 + HANDLE h; + rb_console_size_t ws; + COORD *pos = &ws.dwCursorPosition; + + h = (HANDLE)rb_w32_get_osfhandle(GetWriteFD(io)); + if (!GetConsoleScreenBufferInfo(h, &ws)) { + rb_syserr_fail(LAST_ERROR, 0); + } + pos->X += x; + pos->Y += y; + if (!SetConsoleCursorPosition(h, *pos)) { + rb_syserr_fail(LAST_ERROR, 0); + } +#else if (x || y) { VALUE s = rb_str_new_cstr(""); - if (y) rb_str_catf(s, "\x1b[%d%c", y < 0 ? -y : y, y < 0 ? 'A' : 'B'); - if (x) rb_str_catf(s, "\x1b[%d%c", x < 0 ? -x : x, x < 0 ? 'D' : 'C'); + if (y) rb_str_catf(s, CSI "%d%c", y < 0 ? -y : y, y < 0 ? 'A' : 'B'); + if (x) rb_str_catf(s, CSI "%d%c", x < 0 ? -x : x, x < 0 ? 'D' : 'C'); rb_io_write(io, s); rb_io_flush(io); } +#endif return io; } +/* + * call-seq: + * io.goto_column(column) -> io + * + * Set the cursor position at +column+ in the same line of the current + * position. + * + * You must require 'io/console' to use this method. + */ static VALUE console_goto_column(VALUE io, VALUE val) { - rb_io_write(io, rb_sprintf("\x1b[%dG", NUM2UINT(val)+1)); +#ifdef _WIN32 + HANDLE h; + rb_console_size_t ws; + COORD *pos = &ws.dwCursorPosition; + + h = (HANDLE)rb_w32_get_osfhandle(GetWriteFD(io)); + if (!GetConsoleScreenBufferInfo(h, &ws)) { + rb_syserr_fail(LAST_ERROR, 0); + } + pos->X = NUM2INT(val); + if (!SetConsoleCursorPosition(h, *pos)) { + rb_syserr_fail(LAST_ERROR, 0); + } +#else + rb_io_write(io, rb_sprintf(CSI "%dG", NUM2UINT(val)+1)); +#endif return io; } +/* + * call-seq: + * io.erase_line(mode) -> io + * + * Erases the line at the cursor corresponding to +mode+. + * +mode+ may be either: + * 0: after cursor + * 1: before and cursor + * 2: entire line + * + * You must require 'io/console' to use this method. + */ static VALUE console_erase_line(VALUE io, VALUE val) { int mode = mode_in_range(val, 2, "line erase"); - rb_io_write(io, rb_sprintf("\x1b[%dK", mode)); +#ifdef _WIN32 + HANDLE h; + rb_console_size_t ws; + COORD *pos = &ws.dwCursorPosition; + DWORD w; + + h = (HANDLE)rb_w32_get_osfhandle(GetWriteFD(io)); + if (!GetConsoleScreenBufferInfo(h, &ws)) { + rb_syserr_fail(LAST_ERROR, 0); + } + w = winsize_col(&ws); + switch (mode) { + case 0: /* after cursor */ + w -= pos->X; + break; + case 1: /* before *and* cursor */ + w = pos->X + 1; + pos->X = 0; + break; + case 2: /* entire line */ + pos->X = 0; + break; + } + constat_clear(h, ws.wAttributes, w, *pos); + return io; +#else + rb_io_write(io, rb_sprintf(CSI "%dK", mode)); +#endif return io; } +/* + * call-seq: + * io.erase_screen(mode) -> io + * + * Erases the screen at the cursor corresponding to +mode+. + * +mode+ may be either: + * 0: after cursor + * 1: before and cursor + * 2: entire screen + * + * You must require 'io/console' to use this method. + */ static VALUE console_erase_screen(VALUE io, VALUE val) { int mode = mode_in_range(val, 3, "screen erase"); - rb_io_write(io, rb_sprintf("\x1b[%dJ", mode)); - return io; -} +#ifdef _WIN32 + HANDLE h; + rb_console_size_t ws; + COORD *pos = &ws.dwCursorPosition; + DWORD w; -static VALUE -console_scroll(VALUE io, int line) -{ - if (line) { - VALUE s = rb_sprintf("\x1b[%d%c", line < 0 ? -line : line, - line < 0 ? 'T' : 'S'); - rb_io_write(io, s); + h = (HANDLE)rb_w32_get_osfhandle(GetWriteFD(io)); + if (!GetConsoleScreenBufferInfo(h, &ws)) { + rb_syserr_fail(LAST_ERROR, 0); + } + w = winsize_col(&ws); + switch (mode) { + case 0: /* erase after cursor */ + w = (w * (ws.srWindow.Bottom - pos->Y + 1) - pos->X); + break; + case 1: /* erase before *and* cursor */ + w = (w * (pos->Y - ws.srWindow.Top) + pos->X + 1); + pos->X = 0; + pos->Y = ws.srWindow.Top; + break; + case 2: /* erase entire screen */ + w = (w * winsize_row(&ws)); + pos->X = 0; + pos->Y = ws.srWindow.Top; + break; + case 3: /* erase entire screen */ + w = (w * ws.dwSize.Y); + pos->X = 0; + pos->Y = 0; + break; } + constat_clear(h, ws.wAttributes, w, *pos); +#else + rb_io_write(io, rb_sprintf(CSI "%dJ", mode)); +#endif return io; } -# define console_key_pressed_p rb_f_notimplement -#endif +/* + * call-seq: + * io.cursor = [line, column] -> io + * + * Same as io.goto(line, column) + * + * See IO#goto. + * + * You must require 'io/console' to use this method. + */ static VALUE console_cursor_set(VALUE io, VALUE cpos) { @@ -1352,42 +1446,98 @@ console_cursor_set(VALUE io, VALUE cpos) return console_goto(io, RARRAY_AREF(cpos, 0), RARRAY_AREF(cpos, 1)); } +/* + * call-seq: + * io.cursor_up(n) -> io + * + * Moves the cursor up +n+ lines. + * + * You must require 'io/console' to use this method. + */ static VALUE console_cursor_up(VALUE io, VALUE val) { return console_move(io, -NUM2INT(val), 0); } +/* + * call-seq: + * io.cursor_down(n) -> io + * + * Moves the cursor down +n+ lines. + * + * You must require 'io/console' to use this method. + */ static VALUE console_cursor_down(VALUE io, VALUE val) { return console_move(io, +NUM2INT(val), 0); } +/* + * call-seq: + * io.cursor_left(n) -> io + * + * Moves the cursor left +n+ columns. + * + * You must require 'io/console' to use this method. + */ static VALUE console_cursor_left(VALUE io, VALUE val) { return console_move(io, 0, -NUM2INT(val)); } +/* + * call-seq: + * io.cursor_right(n) -> io + * + * Moves the cursor right +n+ columns. + * + * You must require 'io/console' to use this method. + */ static VALUE console_cursor_right(VALUE io, VALUE val) { return console_move(io, 0, +NUM2INT(val)); } +/* + * call-seq: + * io.scroll_forward(n) -> io + * + * Scrolls the entire scrolls forward +n+ lines. + * + * You must require 'io/console' to use this method. + */ static VALUE console_scroll_forward(VALUE io, VALUE val) { return console_scroll(io, +NUM2INT(val)); } +/* + * call-seq: + * io.scroll_backward(n) -> io + * + * Scrolls the entire scrolls backward +n+ lines. + * + * You must require 'io/console' to use this method. + */ static VALUE console_scroll_backward(VALUE io, VALUE val) { return console_scroll(io, -NUM2INT(val)); } +/* + * call-seq: + * io.clear_screen -> io + * + * Clears the entire screen and moves the cursor top-left corner. + * + * You must require 'io/console' to use this method. + */ static VALUE console_clear_screen(VALUE io) { @@ -1400,10 +1550,8 @@ console_clear_screen(VALUE io) static VALUE io_open_descriptor_fallback(VALUE klass, int descriptor, int mode, VALUE path, VALUE timeout, void *encoding) { - rb_update_max_fd(descriptor); - VALUE arguments[2] = { - INT2NUM(descriptor), + (rb_update_max_fd(descriptor), INT2NUM(descriptor)), INT2FIX(mode), }; @@ -1428,6 +1576,62 @@ rb_io_closed_p(VALUE io) } #endif +#if defined(RB_EXT_RACTOR_SAFE) && defined(HAVE_RB_RACTOR_LOCAL_STORAGE_VALUE_NEWKEY) +# define USE_RACTOR_STORAGE 1 +#else +# define USE_RACTOR_STORAGE 0 +#endif + +#if USE_RACTOR_STORAGE +#include "ruby/ractor.h" +static rb_ractor_local_key_t key_console_dev; + +static bool +console_dev_get(VALUE klass, VALUE *dev) +{ + return rb_ractor_local_storage_value_lookup(key_console_dev, dev); +} + +static void +console_dev_set(VALUE klass, VALUE value) +{ + rb_ractor_local_storage_value_set(key_console_dev, value); +} + +static void +console_dev_remove(VALUE klass) +{ + console_dev_set(klass, Qnil); +} + +#else + +static ID id_console; + +static int +console_dev_get(VALUE klass, VALUE *dev) +{ + if (rb_const_defined(klass, id_console)) { + *dev = rb_const_get(klass, id_console); + return 1; + } + return 0; +} + +static void +console_dev_set(VALUE klass, VALUE value) +{ + rb_const_set(klass, id_console, value); +} + +static void +console_dev_remove(VALUE klass) +{ + rb_const_remove(klass, id_console); +} + +#endif + /* * call-seq: * IO.console -> # @@ -1456,10 +1660,9 @@ console_dev(int argc, VALUE *argv, VALUE klass) // Force the class to be File. if (klass == rb_cIO) klass = rb_cFile; - if (rb_const_defined(klass, id_console)) { - con = rb_const_get(klass, id_console); + if (console_dev_get(klass, &con)) { if (!RB_TYPE_P(con, T_FILE) || RTEST(rb_io_closed_p(con))) { - rb_const_remove(klass, id_console); + console_dev_remove(klass); con = 0; } } @@ -1468,7 +1671,7 @@ console_dev(int argc, VALUE *argv, VALUE klass) if (sym == ID2SYM(id_close) && argc == 1) { if (con) { rb_io_close(con); - rb_const_remove(klass, id_console); + console_dev_remove(klass); con = 0; } return Qnil; @@ -1488,7 +1691,6 @@ console_dev(int argc, VALUE *argv, VALUE klass) #endif #ifdef CONSOLE_DEVICE_FOR_WRITING VALUE out; - rb_io_t *ofptr; #endif int fd; VALUE path = rb_obj_freeze(rb_str_new2(CONSOLE_DEVICE)); @@ -1510,7 +1712,7 @@ console_dev(int argc, VALUE *argv, VALUE klass) #ifdef CONSOLE_DEVICE_FOR_WRITING rb_io_set_write_io(con, out); #endif - rb_const_set(klass, id_console, con); + console_dev_set(klass, con); } if (sym) { @@ -1621,18 +1823,81 @@ io_getpass(int argc, VALUE *argv, VALUE io) return str_chomp(str); } +#if defined(_WIN32) || defined(HAVE_TTYNAME_R) || defined(HAVE_TTYNAME) +/* + * call-seq: + * io.ttyname -> string or nil + * + * Returns name of associated terminal (tty) if +io+ is not a tty. + * Returns +nil+ otherwise. + */ +static VALUE +console_ttyname(VALUE io) +{ + int fd = rb_io_descriptor(io); + if (!isatty(fd)) return Qnil; +# if defined _WIN32 + return rb_usascii_str_new_lit("con"); +# elif defined HAVE_TTYNAME_R + { + char termname[1024], *tn = termname; + size_t size = sizeof(termname); + int e; + if (ttyname_r(fd, tn, size) == 0) + return rb_interned_str_cstr(tn); + if ((e = errno) == ERANGE) { + VALUE s = rb_str_new(0, size); + while (1) { + tn = RSTRING_PTR(s); + size = rb_str_capacity(s); + if (ttyname_r(fd, tn, size) == 0) { + return rb_str_to_interned_str(rb_str_resize(s, strlen(tn))); + } + if ((e = errno) != ERANGE) break; + if ((size *= 2) >= INT_MAX/2) break; + rb_str_resize(s, size); + } + } + rb_syserr_fail_str(e, rb_sprintf("ttyname_r(%d)", fd)); + UNREACHABLE_RETURN(Qnil); + } +# elif defined HAVE_TTYNAME + { + const char *tn = ttyname(fd); + if (!tn) { + int e = errno; + rb_syserr_fail_str(e, rb_sprintf("ttyname(%d)", fd)); + } + return rb_interned_str_cstr(tn); + } +# else +# error No ttyname function +# endif +} +#else +# define console_ttyname rb_f_notimplement +#endif + /* * IO console methods */ void Init_console(void) { +#if USE_RACTOR_STORAGE + RB_EXT_RACTOR_SAFE(true); +#endif + #undef rb_intern +#if USE_RACTOR_STORAGE + key_console_dev = rb_ractor_local_storage_value_newkey(); +#else + id_console = rb_intern("console"); +#endif id_getc = rb_intern("getc"); id_gets = rb_intern("gets"); id_flush = rb_intern("flush"); id_chomp_bang = rb_intern("chomp!"); - id_console = rb_intern("console"); id_close = rb_intern("close"); #define init_rawmode_opt_id(name) \ rawmode_opt_ids[kwd_##name] = rb_intern(#name) @@ -1680,15 +1945,19 @@ InitVM_console(void) rb_define_method(rb_cIO, "pressed?", console_key_pressed_p, 1); rb_define_method(rb_cIO, "check_winsize_changed", console_check_winsize_changed, 0); rb_define_method(rb_cIO, "getpass", console_getpass, -1); + rb_define_method(rb_cIO, "ttyname", console_ttyname, 0); rb_define_singleton_method(rb_cIO, "console", console_dev, -1); { + /* :stopdoc: */ VALUE mReadable = rb_define_module_under(rb_cIO, "generic_readable"); + /* :startdoc: */ rb_define_method(mReadable, "getch", io_getch, -1); rb_define_method(mReadable, "getpass", io_getpass, -1); } { /* :stopdoc: */ cConmode = rb_define_class_under(rb_cIO, "ConsoleMode", rb_cObject); + rb_define_const(cConmode, "VERSION", rb_obj_freeze(rb_str_new_cstr(IO_CONSOLE_VERSION))); rb_define_alloc_func(cConmode, conmode_alloc); rb_undef_method(cConmode, "initialize"); rb_define_method(cConmode, "initialize_copy", conmode_init_copy, 1); diff --git a/ext/io/console/depend b/ext/io/console/depend index 59ca3442c2c5c2..150a138d4dff55 100644 --- a/ext/io/console/depend +++ b/ext/io/console/depend @@ -139,6 +139,7 @@ console.o: $(hdrdir)/ruby/internal/intern/re.h console.o: $(hdrdir)/ruby/internal/intern/ruby.h console.o: $(hdrdir)/ruby/internal/intern/select.h console.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +console.o: $(hdrdir)/ruby/internal/intern/set.h console.o: $(hdrdir)/ruby/internal/intern/signal.h console.o: $(hdrdir)/ruby/internal/intern/sprintf.h console.o: $(hdrdir)/ruby/internal/intern/string.h @@ -158,6 +159,7 @@ console.o: $(hdrdir)/ruby/internal/special_consts.h console.o: $(hdrdir)/ruby/internal/static_assert.h console.o: $(hdrdir)/ruby/internal/stdalign.h console.o: $(hdrdir)/ruby/internal/stdbool.h +console.o: $(hdrdir)/ruby/internal/stdckdint.h console.o: $(hdrdir)/ruby/internal/symbol.h console.o: $(hdrdir)/ruby/internal/value.h console.o: $(hdrdir)/ruby/internal/value_type.h @@ -168,6 +170,7 @@ console.o: $(hdrdir)/ruby/io.h console.o: $(hdrdir)/ruby/missing.h console.o: $(hdrdir)/ruby/onigmo.h console.o: $(hdrdir)/ruby/oniguruma.h +console.o: $(hdrdir)/ruby/ractor.h console.o: $(hdrdir)/ruby/ruby.h console.o: $(hdrdir)/ruby/st.h console.o: $(hdrdir)/ruby/subst.h @@ -184,7 +187,7 @@ win32_vk.inc: win32_vk.list -e 'n=$$F[1] and (n.strip!; /\AVK_/=~n) and' \ -e 'puts(%[#ifndef #{n}\n# define #{n} UNDEFINED_VK\n#endif])' \ $< && \ - gperf --ignore-case -E -C -P -p -j1 -i 1 -g -o -t -K ofs -N console_win32_vk -k* $< \ + gperf --ignore-case -L ANSI-C -E -C -P -p -j1 -i 1 -g -o -t -K ofs -N console_win32_vk -k* $< \ | sed -f $(top_srcdir)/tool/gperf.sed \ ) > $(@F) diff --git a/ext/io/console/extconf.rb b/ext/io/console/extconf.rb index a72403c7f90fa4..dd3d221ae51df3 100644 --- a/ext/io/console/extconf.rb +++ b/ext/io/console/extconf.rb @@ -1,13 +1,30 @@ # frozen_string_literal: false require 'mkmf' -have_func("rb_io_path") -have_func("rb_io_descriptor") -have_func("rb_io_get_write_io") -have_func("rb_io_closed_p") -have_func("rb_io_open_descriptor") +# `--target-rbconfig` compatibility for Ruby 3.3 or earlier +# See https://bugs.ruby-lang.org/issues/20345 +MakeMakefile::RbConfig ||= ::RbConfig -ok = true if RUBY_ENGINE == "ruby" || RUBY_ENGINE == "truffleruby" +have_func("rb_syserr_fail_str(0, Qnil)") or +have_func("rb_syserr_new_str(0, Qnil)") or + abort + +have_func("rb_interned_str_cstr") +have_func("rb_io_path", "ruby/io.h") +have_func("rb_io_descriptor", "ruby/io.h") +have_func("rb_io_get_write_io", "ruby/io.h") +have_func("rb_io_closed_p", "ruby/io.h") +have_func("rb_io_open_descriptor", "ruby/io.h") +have_func("rb_ractor_local_storage_value_newkey") + +is_wasi = /wasi/ =~ MakeMakefile::RbConfig::CONFIG["platform"] +# `ok` can be `true`, `false`, or `nil`: +# * `true` : Required headers and functions available, proceed regular build. +# * `false`: Required headers or functions not available, abort build. +# * `nil` : Unsupported compilation target, generate dummy Makefile. +# +# Skip building io/console on WASI, as it does not support termios.h. +ok = true if (RUBY_ENGINE == "ruby" && !is_wasi) || RUBY_ENGINE == "truffleruby" hdr = nil case when macro_defined?("_WIN32", "") @@ -35,6 +52,7 @@ elsif have_func("rb_scheduler_timeout") # 3.0 have_func("rb_io_wait") end + have_func("ttyname_r") or have_func("ttyname") create_makefile("io/console") {|conf| conf << "\n""VK_HEADER = #{vk_header}\n" } diff --git a/ext/io/console/io-console.gemspec b/ext/io/console/io-console.gemspec index d26a757b010421..0a199927345be6 100644 --- a/ext/io/console/io-console.gemspec +++ b/ext/io/console/io-console.gemspec @@ -1,5 +1,13 @@ # -*- ruby -*- -_VERSION = "0.6.0" +_VERSION = ["", "ext/io/console/"].find do |dir| + begin + break File.open(File.join(__dir__, "#{dir}console.c")) {|f| + f.gets("\nIO_CONSOLE_VERSION ") + f.gets[/"(.+)"/, 1] + } + rescue Errno::ENOENT + end +end Gem::Specification.new do |s| s.name = "io-console" @@ -10,10 +18,13 @@ Gem::Specification.new do |s| s.required_ruby_version = ">= 2.6.0" s.homepage = "https://github.com/ruby/io-console" s.metadata["source_code_url"] = s.homepage + s.metadata["changelog_uri"] = s.homepage + "/releases" s.authors = ["Nobu Nakada"] s.require_path = %[lib] s.files = %w[ - LICENSE.txt + .document + BSDL + COPYING README.md ext/io/console/console.c ext/io/console/extconf.rb @@ -25,15 +36,16 @@ Gem::Specification.new do |s| if Gem::Platform === s.platform and s.platform =~ 'java' s.files.delete_if {|f| f.start_with?("ext/")} s.extensions.clear + s.require_paths.unshift('lib/ffi') s.files.concat(%w[ - lib/io/console.rb - lib/io/console/ffi/bsd_console.rb - lib/io/console/ffi/common.rb - lib/io/console/ffi/console.rb - lib/io/console/ffi/linux_console.rb - lib/io/console/ffi/native_console.rb - lib/io/console/ffi/stty_console.rb - lib/io/console/ffi/stub_console.rb + lib/ffi/io/console.rb + lib/ffi/io/console/bsd_console.rb + lib/ffi/io/console/common.rb + lib/ffi/io/console/linux_console.rb + lib/ffi/io/console/native_console.rb + lib/ffi/io/console/stty_console.rb + lib/ffi/io/console/stub_console.rb + lib/ffi/io/console/version.rb ]) end diff --git a/ext/io/console/win32_vk.inc b/ext/io/console/win32_vk.inc index cbec7bef150e26..348e6be5edf1fe 100644 --- a/ext/io/console/win32_vk.inc +++ b/ext/io/console/win32_vk.inc @@ -480,7 +480,7 @@ # define VK_OEM_CLEAR UNDEFINED_VK #endif /* ANSI-C code produced by gperf version 3.1 */ -/* Command-line: gperf --ignore-case -E -C -P -p -j1 -i 1 -g -o -t -K ofs -N console_win32_vk -k'*' win32_vk.list */ +/* Command-line: gperf --ignore-case -L ANSI-C -E -C -P -p -j1 -i 1 -g -o -t -K ofs -N console_win32_vk -k'*' win32_vk.list */ #if !((' ' == 32) && ('!' == 33) && ('"' == 34) && ('#' == 35) \ && ('%' == 37) && ('&' == 38) && ('\'' == 39) && ('(' == 40) \ @@ -509,11 +509,10 @@ #error "gperf generated tables don't work with this execution character set. Please report a bug to ." #endif -#define gperf_offsetof(s, n) (short)offsetof(struct s##_t, s##_str##n) #line 1 "win32_vk.list" struct vktable {short ofs; unsigned short vk;}; -static const struct vktable *console_win32_vk(/*const char *, unsigned int*/); +static const struct vktable *console_win32_vk(const char *, size_t); #line 5 "win32_vk.list" struct vktable; /* maximum key range = 245, duplicates = 0 */ @@ -1007,368 +1006,368 @@ console_win32_vk (register const char *str, register size_t len) {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, #line 40 "win32_vk.list" - {gperf_offsetof(stringpool, 12), VK_UP}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str12, VK_UP}, #line 52 "win32_vk.list" - {gperf_offsetof(stringpool, 13), VK_APPS}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str13, VK_APPS}, #line 159 "win32_vk.list" - {gperf_offsetof(stringpool, 14), VK_CRSEL}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str14, VK_CRSEL}, #line 34 "win32_vk.list" - {gperf_offsetof(stringpool, 15), VK_SPACE}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str15, VK_SPACE}, #line 95 "win32_vk.list" - {gperf_offsetof(stringpool, 16), VK_SCROLL}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str16, VK_SCROLL}, #line 29 "win32_vk.list" - {gperf_offsetof(stringpool, 17), VK_ESCAPE}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str17, VK_ESCAPE}, #line 9 "win32_vk.list" - {gperf_offsetof(stringpool, 18), VK_CANCEL}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str18, VK_CANCEL}, #line 32 "win32_vk.list" - {gperf_offsetof(stringpool, 19), VK_ACCEPT}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str19, VK_ACCEPT}, #line 66 "win32_vk.list" - {gperf_offsetof(stringpool, 20), VK_SEPARATOR}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str20, VK_SEPARATOR}, #line 43 "win32_vk.list" - {gperf_offsetof(stringpool, 21), VK_SELECT}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str21, VK_SELECT}, #line 18 "win32_vk.list" - {gperf_offsetof(stringpool, 22), VK_CONTROL}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str22, VK_CONTROL}, #line 166 "win32_vk.list" - {gperf_offsetof(stringpool, 23), VK_OEM_CLEAR}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str23, VK_OEM_CLEAR}, #line 145 "win32_vk.list" - {gperf_offsetof(stringpool, 24), VK_OEM_RESET}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str24, VK_OEM_RESET}, #line 155 "win32_vk.list" - {gperf_offsetof(stringpool, 25), VK_OEM_AUTO}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str25, VK_OEM_AUTO}, #line 151 "win32_vk.list" - {gperf_offsetof(stringpool, 26), VK_OEM_CUSEL}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str26, VK_OEM_CUSEL}, {-1}, #line 22 "win32_vk.list" - {gperf_offsetof(stringpool, 28), VK_KANA}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str28, VK_KANA}, #line 127 "win32_vk.list" - {gperf_offsetof(stringpool, 29), VK_OEM_PLUS}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str29, VK_OEM_PLUS}, #line 35 "win32_vk.list" - {gperf_offsetof(stringpool, 30), VK_PRIOR}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str30, VK_PRIOR}, #line 152 "win32_vk.list" - {gperf_offsetof(stringpool, 31), VK_OEM_ATTN}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str31, VK_OEM_ATTN}, #line 20 "win32_vk.list" - {gperf_offsetof(stringpool, 32), VK_PAUSE}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str32, VK_PAUSE}, #line 13 "win32_vk.list" - {gperf_offsetof(stringpool, 33), VK_BACK}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str33, VK_BACK}, #line 144 "win32_vk.list" - {gperf_offsetof(stringpool, 34), VK_PACKET}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str34, VK_PACKET}, #line 105 "win32_vk.list" - {gperf_offsetof(stringpool, 35), VK_RCONTROL}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str35, VK_RCONTROL}, #line 104 "win32_vk.list" - {gperf_offsetof(stringpool, 36), VK_LCONTROL}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str36, VK_LCONTROL}, #line 37 "win32_vk.list" - {gperf_offsetof(stringpool, 37), VK_END}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str37, VK_END}, #line 38 "win32_vk.list" - {gperf_offsetof(stringpool, 38), VK_HOME}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str38, VK_HOME}, #line 44 "win32_vk.list" - {gperf_offsetof(stringpool, 39), VK_PRINT}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str39, VK_PRINT}, #line 94 "win32_vk.list" - {gperf_offsetof(stringpool, 40), VK_NUMLOCK}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str40, VK_NUMLOCK}, #line 39 "win32_vk.list" - {gperf_offsetof(stringpool, 41), VK_LEFT}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str41, VK_LEFT}, #line 25 "win32_vk.list" - {gperf_offsetof(stringpool, 42), VK_JUNJA}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str42, VK_JUNJA}, #line 19 "win32_vk.list" - {gperf_offsetof(stringpool, 43), VK_MENU}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str43, VK_MENU}, #line 150 "win32_vk.list" - {gperf_offsetof(stringpool, 44), VK_OEM_WSCTRL}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str44, VK_OEM_WSCTRL}, #line 156 "win32_vk.list" - {gperf_offsetof(stringpool, 45), VK_OEM_ENLW}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str45, VK_OEM_ENLW}, #line 36 "win32_vk.list" - {gperf_offsetof(stringpool, 46), VK_NEXT}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str46, VK_NEXT}, #line 51 "win32_vk.list" - {gperf_offsetof(stringpool, 47), VK_RWIN}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str47, VK_RWIN}, #line 50 "win32_vk.list" - {gperf_offsetof(stringpool, 48), VK_LWIN}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str48, VK_LWIN}, #line 21 "win32_vk.list" - {gperf_offsetof(stringpool, 49), VK_CAPITAL}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str49, VK_CAPITAL}, #line 49 "win32_vk.list" - {gperf_offsetof(stringpool, 50), VK_HELP}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str50, VK_HELP}, #line 164 "win32_vk.list" - {gperf_offsetof(stringpool, 51), VK_NONAME}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str51, VK_NONAME}, #line 8 "win32_vk.list" - {gperf_offsetof(stringpool, 52), VK_RBUTTON}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str52, VK_RBUTTON}, #line 7 "win32_vk.list" - {gperf_offsetof(stringpool, 53), VK_LBUTTON}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str53, VK_LBUTTON}, #line 96 "win32_vk.list" - {gperf_offsetof(stringpool, 54), VK_OEM_NEC_EQUAL}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str54, VK_OEM_NEC_EQUAL}, {-1}, #line 47 "win32_vk.list" - {gperf_offsetof(stringpool, 56), VK_INSERT}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str56, VK_INSERT}, #line 27 "win32_vk.list" - {gperf_offsetof(stringpool, 57), VK_HANJA}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str57, VK_HANJA}, {-1}, {-1}, #line 46 "win32_vk.list" - {gperf_offsetof(stringpool, 60), VK_SNAPSHOT}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str60, VK_SNAPSHOT}, #line 158 "win32_vk.list" - {gperf_offsetof(stringpool, 61), VK_ATTN}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str61, VK_ATTN}, #line 14 "win32_vk.list" - {gperf_offsetof(stringpool, 62), VK_TAB}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str62, VK_TAB}, #line 157 "win32_vk.list" - {gperf_offsetof(stringpool, 63), VK_OEM_BACKTAB}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str63, VK_OEM_BACKTAB}, #line 143 "win32_vk.list" - {gperf_offsetof(stringpool, 64), VK_ICO_CLEAR}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str64, VK_ICO_CLEAR}, #line 30 "win32_vk.list" - {gperf_offsetof(stringpool, 65), VK_CONVERT}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str65, VK_CONVERT}, #line 16 "win32_vk.list" - {gperf_offsetof(stringpool, 66), VK_RETURN}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str66, VK_RETURN}, #line 146 "win32_vk.list" - {gperf_offsetof(stringpool, 67), VK_OEM_JUMP}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str67, VK_OEM_JUMP}, {-1}, {-1}, {-1}, #line 111 "win32_vk.list" - {gperf_offsetof(stringpool, 71), VK_BROWSER_STOP}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str71, VK_BROWSER_STOP}, #line 26 "win32_vk.list" - {gperf_offsetof(stringpool, 72), VK_FINAL}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str72, VK_FINAL}, #line 163 "win32_vk.list" - {gperf_offsetof(stringpool, 73), VK_ZOOM}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str73, VK_ZOOM}, #line 28 "win32_vk.list" - {gperf_offsetof(stringpool, 74), VK_KANJI}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str74, VK_KANJI}, #line 48 "win32_vk.list" - {gperf_offsetof(stringpool, 75), VK_DELETE}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str75, VK_DELETE}, #line 128 "win32_vk.list" - {gperf_offsetof(stringpool, 76), VK_OEM_COMMA}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str76, VK_OEM_COMMA}, #line 67 "win32_vk.list" - {gperf_offsetof(stringpool, 77), VK_SUBTRACT}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str77, VK_SUBTRACT}, {-1}, #line 10 "win32_vk.list" - {gperf_offsetof(stringpool, 79), VK_MBUTTON}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str79, VK_MBUTTON}, #line 78 "win32_vk.list" - {gperf_offsetof(stringpool, 80), VK_F9}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str80, VK_F9}, #line 17 "win32_vk.list" - {gperf_offsetof(stringpool, 81), VK_SHIFT}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str81, VK_SHIFT}, #line 103 "win32_vk.list" - {gperf_offsetof(stringpool, 82), VK_RSHIFT}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str82, VK_RSHIFT}, #line 102 "win32_vk.list" - {gperf_offsetof(stringpool, 83), VK_LSHIFT}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str83, VK_LSHIFT}, #line 65 "win32_vk.list" - {gperf_offsetof(stringpool, 84), VK_ADD}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str84, VK_ADD}, #line 31 "win32_vk.list" - {gperf_offsetof(stringpool, 85), VK_NONCONVERT}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str85, VK_NONCONVERT}, #line 160 "win32_vk.list" - {gperf_offsetof(stringpool, 86), VK_EXSEL}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str86, VK_EXSEL}, #line 126 "win32_vk.list" - {gperf_offsetof(stringpool, 87), VK_OEM_1}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str87, VK_OEM_1}, #line 138 "win32_vk.list" - {gperf_offsetof(stringpool, 88), VK_OEM_AX}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str88, VK_OEM_AX}, #line 108 "win32_vk.list" - {gperf_offsetof(stringpool, 89), VK_BROWSER_BACK}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str89, VK_BROWSER_BACK}, #line 137 "win32_vk.list" - {gperf_offsetof(stringpool, 90), VK_OEM_8}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str90, VK_OEM_8}, #line 129 "win32_vk.list" - {gperf_offsetof(stringpool, 91), VK_OEM_MINUS}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str91, VK_OEM_MINUS}, #line 162 "win32_vk.list" - {gperf_offsetof(stringpool, 92), VK_PLAY}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str92, VK_PLAY}, #line 131 "win32_vk.list" - {gperf_offsetof(stringpool, 93), VK_OEM_2}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str93, VK_OEM_2}, #line 15 "win32_vk.list" - {gperf_offsetof(stringpool, 94), VK_CLEAR}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str94, VK_CLEAR}, #line 99 "win32_vk.list" - {gperf_offsetof(stringpool, 95), VK_OEM_FJ_TOUROKU}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str95, VK_OEM_FJ_TOUROKU}, #line 147 "win32_vk.list" - {gperf_offsetof(stringpool, 96), VK_OEM_PA1}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str96, VK_OEM_PA1}, #line 140 "win32_vk.list" - {gperf_offsetof(stringpool, 97), VK_ICO_HELP}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str97, VK_ICO_HELP}, #line 112 "win32_vk.list" - {gperf_offsetof(stringpool, 98), VK_BROWSER_SEARCH}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str98, VK_BROWSER_SEARCH}, #line 53 "win32_vk.list" - {gperf_offsetof(stringpool, 99), VK_SLEEP}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str99, VK_SLEEP}, {-1}, #line 70 "win32_vk.list" - {gperf_offsetof(stringpool, 101), VK_F1}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str101, VK_F1}, #line 148 "win32_vk.list" - {gperf_offsetof(stringpool, 102), VK_OEM_PA2}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str102, VK_OEM_PA2}, #line 154 "win32_vk.list" - {gperf_offsetof(stringpool, 103), VK_OEM_COPY}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str103, VK_OEM_COPY}, #line 77 "win32_vk.list" - {gperf_offsetof(stringpool, 104), VK_F8}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str104, VK_F8}, #line 88 "win32_vk.list" - {gperf_offsetof(stringpool, 105), VK_F19}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str105, VK_F19}, #line 41 "win32_vk.list" - {gperf_offsetof(stringpool, 106), VK_RIGHT}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str106, VK_RIGHT}, #line 71 "win32_vk.list" - {gperf_offsetof(stringpool, 107), VK_F2}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str107, VK_F2}, #line 135 "win32_vk.list" - {gperf_offsetof(stringpool, 108), VK_OEM_6}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str108, VK_OEM_6}, #line 87 "win32_vk.list" - {gperf_offsetof(stringpool, 109), VK_F18}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str109, VK_F18}, {-1}, #line 117 "win32_vk.list" - {gperf_offsetof(stringpool, 111), VK_VOLUME_UP}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str111, VK_VOLUME_UP}, {-1}, {-1}, #line 120 "win32_vk.list" - {gperf_offsetof(stringpool, 114), VK_MEDIA_STOP}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str114, VK_MEDIA_STOP}, #line 130 "win32_vk.list" - {gperf_offsetof(stringpool, 115), VK_OEM_PERIOD}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str115, VK_OEM_PERIOD}, {-1}, #line 161 "win32_vk.list" - {gperf_offsetof(stringpool, 117), VK_EREOF}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str117, VK_EREOF}, {-1}, {-1}, {-1}, #line 114 "win32_vk.list" - {gperf_offsetof(stringpool, 121), VK_BROWSER_HOME}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str121, VK_BROWSER_HOME}, #line 75 "win32_vk.list" - {gperf_offsetof(stringpool, 122), VK_F6}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str122, VK_F6}, {-1}, #line 110 "win32_vk.list" - {gperf_offsetof(stringpool, 124), VK_BROWSER_REFRESH}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str124, VK_BROWSER_REFRESH}, {-1}, #line 165 "win32_vk.list" - {gperf_offsetof(stringpool, 126), VK_PA1}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str126, VK_PA1}, #line 142 "win32_vk.list" - {gperf_offsetof(stringpool, 127), VK_PROCESSKEY}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str127, VK_PROCESSKEY}, #line 68 "win32_vk.list" - {gperf_offsetof(stringpool, 128), VK_DECIMAL}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str128, VK_DECIMAL}, #line 132 "win32_vk.list" - {gperf_offsetof(stringpool, 129), VK_OEM_3}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str129, VK_OEM_3}, #line 107 "win32_vk.list" - {gperf_offsetof(stringpool, 130), VK_RMENU}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str130, VK_RMENU}, #line 106 "win32_vk.list" - {gperf_offsetof(stringpool, 131), VK_LMENU}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str131, VK_LMENU}, #line 98 "win32_vk.list" - {gperf_offsetof(stringpool, 132), VK_OEM_FJ_MASSHOU}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str132, VK_OEM_FJ_MASSHOU}, #line 54 "win32_vk.list" - {gperf_offsetof(stringpool, 133), VK_NUMPAD0}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str133, VK_NUMPAD0}, #line 24 "win32_vk.list" - {gperf_offsetof(stringpool, 134), VK_HANGUL}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str134, VK_HANGUL}, #line 63 "win32_vk.list" - {gperf_offsetof(stringpool, 135), VK_NUMPAD9}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str135, VK_NUMPAD9}, #line 23 "win32_vk.list" - {gperf_offsetof(stringpool, 136), VK_HANGEUL}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str136, VK_HANGEUL}, #line 134 "win32_vk.list" - {gperf_offsetof(stringpool, 137), VK_OEM_5}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str137, VK_OEM_5}, #line 149 "win32_vk.list" - {gperf_offsetof(stringpool, 138), VK_OEM_PA3}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str138, VK_OEM_PA3}, #line 115 "win32_vk.list" - {gperf_offsetof(stringpool, 139), VK_VOLUME_MUTE}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str139, VK_VOLUME_MUTE}, #line 133 "win32_vk.list" - {gperf_offsetof(stringpool, 140), VK_OEM_4}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str140, VK_OEM_4}, #line 122 "win32_vk.list" - {gperf_offsetof(stringpool, 141), VK_LAUNCH_MAIL}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str141, VK_LAUNCH_MAIL}, #line 97 "win32_vk.list" - {gperf_offsetof(stringpool, 142), VK_OEM_FJ_JISHO}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str142, VK_OEM_FJ_JISHO}, #line 72 "win32_vk.list" - {gperf_offsetof(stringpool, 143), VK_F3}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str143, VK_F3}, #line 101 "win32_vk.list" - {gperf_offsetof(stringpool, 144), VK_OEM_FJ_ROYA}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str144, VK_OEM_FJ_ROYA}, #line 100 "win32_vk.list" - {gperf_offsetof(stringpool, 145), VK_OEM_FJ_LOYA}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str145, VK_OEM_FJ_LOYA}, {-1}, #line 42 "win32_vk.list" - {gperf_offsetof(stringpool, 147), VK_DOWN}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str147, VK_DOWN}, {-1}, #line 153 "win32_vk.list" - {gperf_offsetof(stringpool, 149), VK_OEM_FINISH}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str149, VK_OEM_FINISH}, {-1}, #line 74 "win32_vk.list" - {gperf_offsetof(stringpool, 151), VK_F5}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str151, VK_F5}, {-1}, #line 136 "win32_vk.list" - {gperf_offsetof(stringpool, 153), VK_OEM_7}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str153, VK_OEM_7}, #line 73 "win32_vk.list" - {gperf_offsetof(stringpool, 154), VK_F4}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str154, VK_F4}, #line 86 "win32_vk.list" - {gperf_offsetof(stringpool, 155), VK_F17}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str155, VK_F17}, #line 55 "win32_vk.list" - {gperf_offsetof(stringpool, 156), VK_NUMPAD1}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str156, VK_NUMPAD1}, #line 141 "win32_vk.list" - {gperf_offsetof(stringpool, 157), VK_ICO_00}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str157, VK_ICO_00}, {-1}, #line 62 "win32_vk.list" - {gperf_offsetof(stringpool, 159), VK_NUMPAD8}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str159, VK_NUMPAD8}, {-1}, {-1}, #line 56 "win32_vk.list" - {gperf_offsetof(stringpool, 162), VK_NUMPAD2}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str162, VK_NUMPAD2}, {-1}, #line 124 "win32_vk.list" - {gperf_offsetof(stringpool, 164), VK_LAUNCH_APP1}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str164, VK_LAUNCH_APP1}, #line 109 "win32_vk.list" - {gperf_offsetof(stringpool, 165), VK_BROWSER_FORWARD}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str165, VK_BROWSER_FORWARD}, {-1}, #line 76 "win32_vk.list" - {gperf_offsetof(stringpool, 167), VK_F7}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str167, VK_F7}, {-1}, {-1}, #line 125 "win32_vk.list" - {gperf_offsetof(stringpool, 170), VK_LAUNCH_APP2}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str170, VK_LAUNCH_APP2}, #line 64 "win32_vk.list" - {gperf_offsetof(stringpool, 171), VK_MULTIPLY}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str171, VK_MULTIPLY}, {-1}, {-1}, #line 45 "win32_vk.list" - {gperf_offsetof(stringpool, 174), VK_EXECUTE}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str174, VK_EXECUTE}, {-1}, #line 113 "win32_vk.list" - {gperf_offsetof(stringpool, 176), VK_BROWSER_FAVORITES}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str176, VK_BROWSER_FAVORITES}, #line 60 "win32_vk.list" - {gperf_offsetof(stringpool, 177), VK_NUMPAD6}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str177, VK_NUMPAD6}, {-1}, #line 85 "win32_vk.list" - {gperf_offsetof(stringpool, 179), VK_F16}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str179, VK_F16}, {-1}, {-1}, #line 79 "win32_vk.list" - {gperf_offsetof(stringpool, 182), VK_F10}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str182, VK_F10}, {-1}, {-1}, #line 116 "win32_vk.list" - {gperf_offsetof(stringpool, 185), VK_VOLUME_DOWN}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str185, VK_VOLUME_DOWN}, {-1}, {-1}, #line 89 "win32_vk.list" - {gperf_offsetof(stringpool, 188), VK_F20}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str188, VK_F20}, #line 119 "win32_vk.list" - {gperf_offsetof(stringpool, 189), VK_MEDIA_PREV_TRACK}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str189, VK_MEDIA_PREV_TRACK}, {-1}, #line 33 "win32_vk.list" - {gperf_offsetof(stringpool, 191), VK_MODECHANGE}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str191, VK_MODECHANGE}, {-1}, {-1}, {-1}, {-1}, {-1}, #line 83 "win32_vk.list" - {gperf_offsetof(stringpool, 197), VK_F14}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str197, VK_F14}, #line 57 "win32_vk.list" - {gperf_offsetof(stringpool, 198), VK_NUMPAD3}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str198, VK_NUMPAD3}, #line 11 "win32_vk.list" - {gperf_offsetof(stringpool, 199), VK_XBUTTON1}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str199, VK_XBUTTON1}, {-1}, {-1}, {-1}, #line 93 "win32_vk.list" - {gperf_offsetof(stringpool, 203), VK_F24}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str203, VK_F24}, {-1}, #line 12 "win32_vk.list" - {gperf_offsetof(stringpool, 205), VK_XBUTTON2}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str205, VK_XBUTTON2}, #line 59 "win32_vk.list" - {gperf_offsetof(stringpool, 206), VK_NUMPAD5}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str206, VK_NUMPAD5}, {-1}, {-1}, #line 58 "win32_vk.list" - {gperf_offsetof(stringpool, 209), VK_NUMPAD4}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str209, VK_NUMPAD4}, {-1}, {-1}, {-1}, {-1}, {-1}, #line 121 "win32_vk.list" - {gperf_offsetof(stringpool, 215), VK_MEDIA_PLAY_PAUSE}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str215, VK_MEDIA_PLAY_PAUSE}, {-1}, #line 123 "win32_vk.list" - {gperf_offsetof(stringpool, 217), VK_LAUNCH_MEDIA_SELECT}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str217, VK_LAUNCH_MEDIA_SELECT}, #line 80 "win32_vk.list" - {gperf_offsetof(stringpool, 218), VK_F11}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str218, VK_F11}, {-1}, #line 139 "win32_vk.list" - {gperf_offsetof(stringpool, 220), VK_OEM_102}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str220, VK_OEM_102}, #line 118 "win32_vk.list" - {gperf_offsetof(stringpool, 221), VK_MEDIA_NEXT_TRACK}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str221, VK_MEDIA_NEXT_TRACK}, #line 61 "win32_vk.list" - {gperf_offsetof(stringpool, 222), VK_NUMPAD7}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str222, VK_NUMPAD7}, {-1}, #line 90 "win32_vk.list" - {gperf_offsetof(stringpool, 224), VK_F21}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str224, VK_F21}, {-1}, #line 82 "win32_vk.list" - {gperf_offsetof(stringpool, 226), VK_F13}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str226, VK_F13}, {-1}, {-1}, #line 81 "win32_vk.list" - {gperf_offsetof(stringpool, 229), VK_F12}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str229, VK_F12}, {-1}, {-1}, #line 92 "win32_vk.list" - {gperf_offsetof(stringpool, 232), VK_F23}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str232, VK_F23}, {-1}, {-1}, #line 91 "win32_vk.list" - {gperf_offsetof(stringpool, 235), VK_F22}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str235, VK_F22}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, #line 84 "win32_vk.list" - {gperf_offsetof(stringpool, 242), VK_F15}, + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str242, VK_F15}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, {-1}, #line 69 "win32_vk.list" - {gperf_offsetof(stringpool, 256), VK_DIVIDE} + {(int)(size_t)&((struct stringpool_t *)0)->stringpool_str256, VK_DIVIDE} }; if (len <= MAX_WORD_LENGTH && len >= MIN_WORD_LENGTH) diff --git a/ext/io/console/win32_vk.list b/ext/io/console/win32_vk.list index 7909a4d1f0a6e9..5df3d6da57a71a 100644 --- a/ext/io/console/win32_vk.list +++ b/ext/io/console/win32_vk.list @@ -1,6 +1,6 @@ %{ struct vktable {short ofs; unsigned short vk;}; -static const struct vktable *console_win32_vk(/*!ANSI{*/const char *, unsigned int/*}!ANSI*/); +static const struct vktable *console_win32_vk(const char *, size_t); %} struct vktable %% diff --git a/ext/io/nonblock/depend b/ext/io/nonblock/depend index 48384fca62822d..e78a05c31609d0 100644 --- a/ext/io/nonblock/depend +++ b/ext/io/nonblock/depend @@ -138,6 +138,7 @@ nonblock.o: $(hdrdir)/ruby/internal/intern/re.h nonblock.o: $(hdrdir)/ruby/internal/intern/ruby.h nonblock.o: $(hdrdir)/ruby/internal/intern/select.h nonblock.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +nonblock.o: $(hdrdir)/ruby/internal/intern/set.h nonblock.o: $(hdrdir)/ruby/internal/intern/signal.h nonblock.o: $(hdrdir)/ruby/internal/intern/sprintf.h nonblock.o: $(hdrdir)/ruby/internal/intern/string.h @@ -157,6 +158,7 @@ nonblock.o: $(hdrdir)/ruby/internal/special_consts.h nonblock.o: $(hdrdir)/ruby/internal/static_assert.h nonblock.o: $(hdrdir)/ruby/internal/stdalign.h nonblock.o: $(hdrdir)/ruby/internal/stdbool.h +nonblock.o: $(hdrdir)/ruby/internal/stdckdint.h nonblock.o: $(hdrdir)/ruby/internal/symbol.h nonblock.o: $(hdrdir)/ruby/internal/value.h nonblock.o: $(hdrdir)/ruby/internal/value_type.h diff --git a/ext/io/nonblock/extconf.rb b/ext/io/nonblock/extconf.rb index a1e6075c9b5052..505c9e6252fb99 100644 --- a/ext/io/nonblock/extconf.rb +++ b/ext/io/nonblock/extconf.rb @@ -7,7 +7,7 @@ return end -have_func("rb_io_descriptor") +have_func("rb_io_descriptor", "ruby/io.h") hdr = %w"fcntl.h" if have_macro("O_NONBLOCK", hdr) and diff --git a/ext/io/nonblock/io-nonblock.gemspec b/ext/io/nonblock/io-nonblock.gemspec index d6df21a84d985c..b0fc662fac9fc2 100644 --- a/ext/io/nonblock/io-nonblock.gemspec +++ b/ext/io/nonblock/io-nonblock.gemspec @@ -1,6 +1,6 @@ Gem::Specification.new do |spec| spec.name = "io-nonblock" - spec.version = "0.2.0" + spec.version = "0.3.1" spec.authors = ["Nobu Nakada"] spec.email = ["nobu@ruby-lang.org"] @@ -8,7 +8,7 @@ Gem::Specification.new do |spec| spec.description = %q{Enables non-blocking mode with IO class} spec.homepage = "https://github.com/ruby/io-nonblock" spec.licenses = ["Ruby", "BSD-2-Clause"] - spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0") + spec.required_ruby_version = Gem::Requirement.new(">= 3.0") spec.metadata["homepage_uri"] = spec.homepage spec.metadata["source_code_uri"] = spec.homepage diff --git a/ext/io/nonblock/nonblock.c b/ext/io/nonblock/nonblock.c index 4c729a760c4c38..cd40ea3335ca09 100644 --- a/ext/io/nonblock/nonblock.c +++ b/ext/io/nonblock/nonblock.c @@ -66,6 +66,8 @@ set_fcntl_flags(int fd, int f) rb_sys_fail(0); } +#ifndef RUBY_IO_NONBLOCK_METHODS + static int io_nonblock_set(int fd, int f, int nb) { @@ -146,6 +148,8 @@ rb_io_nonblock_set(VALUE self, VALUE value) return self; } +#endif /* RUBY_IO_NONBLOCK_METHODS */ + static VALUE io_nonblock_restore(VALUE arg) { @@ -193,7 +197,14 @@ rb_io_nonblock_block(int argc, VALUE *argv, VALUE self) void Init_nonblock(void) { +#ifdef HAVE_RB_EXT_RACTOR_SAFE + rb_ext_ractor_safe(true); +#endif + +#ifndef RUBY_IO_NONBLOCK_METHODS rb_define_method(rb_cIO, "nonblock?", rb_io_nonblock_p, 0); rb_define_method(rb_cIO, "nonblock=", rb_io_nonblock_set, 1); +#endif + rb_define_method(rb_cIO, "nonblock", rb_io_nonblock_block, -1); } diff --git a/ext/io/wait/depend b/ext/io/wait/depend index 83cf8f94c8a879..41d53c14000951 100644 --- a/ext/io/wait/depend +++ b/ext/io/wait/depend @@ -1,5 +1,4 @@ # AUTOGENERATED DEPENDENCIES START -# wait.o: $(hdrdir)/ruby/assert.h # not in 2.6 wait.o: $(RUBY_EXTCONF_H) wait.o: $(arch_hdrdir)/ruby/config.h wait.o: $(hdrdir)/ruby.h @@ -139,6 +138,7 @@ wait.o: $(hdrdir)/ruby/internal/intern/re.h wait.o: $(hdrdir)/ruby/internal/intern/ruby.h wait.o: $(hdrdir)/ruby/internal/intern/select.h wait.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +wait.o: $(hdrdir)/ruby/internal/intern/set.h wait.o: $(hdrdir)/ruby/internal/intern/signal.h wait.o: $(hdrdir)/ruby/internal/intern/sprintf.h wait.o: $(hdrdir)/ruby/internal/intern/string.h @@ -158,6 +158,7 @@ wait.o: $(hdrdir)/ruby/internal/special_consts.h wait.o: $(hdrdir)/ruby/internal/static_assert.h wait.o: $(hdrdir)/ruby/internal/stdalign.h wait.o: $(hdrdir)/ruby/internal/stdbool.h +wait.o: $(hdrdir)/ruby/internal/stdckdint.h wait.o: $(hdrdir)/ruby/internal/symbol.h wait.o: $(hdrdir)/ruby/internal/value.h wait.o: $(hdrdir)/ruby/internal/value_type.h diff --git a/ext/io/wait/extconf.rb b/ext/io/wait/extconf.rb index e63c0461873187..e97efa179d29c7 100644 --- a/ext/io/wait/extconf.rb +++ b/ext/io/wait/extconf.rb @@ -1,25 +1,21 @@ # frozen_string_literal: false require 'mkmf' -if RUBY_VERSION < "2.6" - File.write("Makefile", dummy_makefile($srcdir).join("")) +target = "io/wait" +have_func("rb_io_wait", "ruby/io.h") +have_func("rb_io_descriptor", "ruby/io.h") +unless macro_defined?("DOSISH", "#include ") + have_header(ioctl_h = "sys/ioctl.h") or ioctl_h = nil + fionread = %w[sys/ioctl.h sys/filio.h sys/socket.h].find do |h| + have_macro("FIONREAD", [h, ioctl_h].compact) + end + if fionread + $defs << "-DFIONREAD_HEADER=\"<#{fionread}>\"" + create_makefile(target) + end else - target = "io/wait" - have_func("rb_io_wait") - have_func("rb_io_descriptor") - unless macro_defined?("DOSISH", "#include ") - have_header(ioctl_h = "sys/ioctl.h") or ioctl_h = nil - fionread = %w[sys/ioctl.h sys/filio.h sys/socket.h].find do |h| - have_macro("FIONREAD", [h, ioctl_h].compact) - end - if fionread - $defs << "-DFIONREAD_HEADER=\"<#{fionread}>\"" - create_makefile(target) - end - else - if have_func("rb_w32_ioctlsocket", "ruby.h") - have_func("rb_w32_is_socket", "ruby.h") - create_makefile(target) - end + if have_func("rb_w32_ioctlsocket", "ruby.h") + have_func("rb_w32_is_socket", "ruby.h") + create_makefile(target) end end diff --git a/ext/io/wait/io-wait.gemspec b/ext/io/wait/io-wait.gemspec index ebc1f6f5c767a9..016b43100ef6bc 100644 --- a/ext/io/wait/io-wait.gemspec +++ b/ext/io/wait/io-wait.gemspec @@ -1,4 +1,4 @@ -_VERSION = "0.3.0" +_VERSION = "0.3.1" Gem::Specification.new do |spec| spec.name = "io-wait" @@ -10,6 +10,7 @@ Gem::Specification.new do |spec| spec.description = %q{Waits until IO is readable or writable without blocking.} spec.homepage = "https://github.com/ruby/io-wait" spec.licenses = ["Ruby", "BSD-2-Clause"] + spec.required_ruby_version = Gem::Requirement.new(">= 3.0") spec.metadata["homepage_uri"] = spec.homepage spec.metadata["source_code_uri"] = spec.homepage diff --git a/ext/io/wait/wait.c b/ext/io/wait/wait.c index 8835670e59e2c8..88e6dd2af1fb58 100644 --- a/ext/io/wait/wait.c +++ b/ext/io/wait/wait.c @@ -312,7 +312,7 @@ io_event_from_value(VALUE value) /* * call-seq: * io.wait(events, timeout) -> event mask, false or nil - * io.wait(timeout = nil, mode = :read) -> self, true, or false + * io.wait(*event_symbols[, timeout]) -> self, true, or false * * Waits until the IO becomes ready for the specified events and returns the * subset of events that become ready, or a falsy value when times out. @@ -320,10 +320,14 @@ io_event_from_value(VALUE value) * The events can be a bit mask of +IO::READABLE+, +IO::WRITABLE+ or * +IO::PRIORITY+. * - * Returns a truthy value immediately when buffered data is available. + * Returns an event mask (truthy value) immediately when buffered data is + * available. * - * Optional parameter +mode+ is one of +:read+, +:write+, or - * +:read_write+. + * The second form: if one or more event symbols (+:read+, +:write+, or + * +:read_write+) are passed, the event mask is the bit OR of the bitmask + * corresponding to those symbols. In this form, +timeout+ is optional, the + * order of the arguments is arbitrary, and returns +io+ if any of the + * events is ready. * * You must require 'io/wait' to use this method. */ @@ -360,10 +364,6 @@ io_wait(int argc, VALUE *argv, VALUE io) rb_io_event_t events = 0; int i, return_io = 0; - /* The documented signature for this method is actually incorrect. - * A single timeout is allowed in any position, and multiple symbols can be given. - * Whether this is intentional or not, I don't know, and as such I consider this to - * be a legacy/slow path. */ if (argc != 2 || (RB_SYMBOL_P(argv[0]) || RB_SYMBOL_P(argv[1]))) { /* We'd prefer to return the actual mask, but this form would return the io itself: */ return_io = 1; diff --git a/ext/json/VERSION b/ext/json/VERSION deleted file mode 100644 index ec1cf33c3f6e22..00000000000000 --- a/ext/json/VERSION +++ /dev/null @@ -1 +0,0 @@ -2.6.3 diff --git a/ext/json/fbuffer/fbuffer.h b/ext/json/fbuffer/fbuffer.h index dc8f406b5b8594..d32371476c85a2 100644 --- a/ext/json/fbuffer/fbuffer.h +++ b/ext/json/fbuffer/fbuffer.h @@ -1,89 +1,109 @@ - #ifndef _FBUFFER_H_ #define _FBUFFER_H_ #include "ruby.h" - -#ifndef RHASH_SIZE -#define RHASH_SIZE(hsh) (RHASH(hsh)->tbl->num_entries) +#include "ruby/encoding.h" +#include "../vendor/jeaiii-ltoa.h" + +/* shims */ +/* This is the fallback definition from Ruby 3.4 */ + +#ifndef RBIMPL_STDBOOL_H +#if defined(__cplusplus) +# if defined(HAVE_STDBOOL_H) && (__cplusplus >= 201103L) +# include +# endif +#elif defined(HAVE_STDBOOL_H) +# include +#elif !defined(HAVE__BOOL) +typedef unsigned char _Bool; +# define bool _Bool +# define true ((_Bool)+1) +# define false ((_Bool)+0) +# define __bool_true_false_are_defined #endif - -#ifndef RFLOAT_VALUE -#define RFLOAT_VALUE(val) (RFLOAT(val)->value) #endif -#ifndef RARRAY_LEN -#define RARRAY_LEN(ARRAY) RARRAY(ARRAY)->len -#endif -#ifndef RSTRING_PTR -#define RSTRING_PTR(string) RSTRING(string)->ptr -#endif -#ifndef RSTRING_LEN -#define RSTRING_LEN(string) RSTRING(string)->len +#ifndef RB_UNLIKELY +#define RB_UNLIKELY(expr) expr #endif -#ifdef PRIsVALUE -# define RB_OBJ_CLASSNAME(obj) rb_obj_class(obj) -# define RB_OBJ_STRING(obj) (obj) -#else -# define PRIsVALUE "s" -# define RB_OBJ_CLASSNAME(obj) rb_obj_classname(obj) -# define RB_OBJ_STRING(obj) StringValueCStr(obj) +#ifndef RB_LIKELY +#define RB_LIKELY(expr) expr #endif -#ifdef HAVE_RUBY_ENCODING_H -#include "ruby/encoding.h" -#define FORCE_UTF8(obj) rb_enc_associate((obj), rb_utf8_encoding()) -#else -#define FORCE_UTF8(obj) +#ifndef MAYBE_UNUSED +# define MAYBE_UNUSED(x) x #endif -/* We don't need to guard objects for rbx, so let's do nothing at all. */ -#ifndef RB_GC_GUARD -#define RB_GC_GUARD(object) +#ifdef RUBY_DEBUG +#ifndef JSON_DEBUG +#define JSON_DEBUG RUBY_DEBUG +#endif #endif +enum fbuffer_type { + FBUFFER_HEAP_ALLOCATED = 0, + FBUFFER_STACK_ALLOCATED = 1, +}; + typedef struct FBufferStruct { + enum fbuffer_type type; unsigned long initial_length; - char *ptr; unsigned long len; unsigned long capa; +#ifdef JSON_DEBUG + unsigned long requested; +#endif + char *ptr; + VALUE io; } FBuffer; +#define FBUFFER_STACK_SIZE 512 +#define FBUFFER_IO_BUFFER_SIZE (16384 - 1) #define FBUFFER_INITIAL_LENGTH_DEFAULT 1024 -#define FBUFFER_PTR(fb) (fb->ptr) -#define FBUFFER_LEN(fb) (fb->len) -#define FBUFFER_CAPA(fb) (fb->capa) +#define FBUFFER_PTR(fb) ((fb)->ptr) +#define FBUFFER_LEN(fb) ((fb)->len) +#define FBUFFER_CAPA(fb) ((fb)->capa) #define FBUFFER_PAIR(fb) FBUFFER_PTR(fb), FBUFFER_LEN(fb) -static FBuffer *fbuffer_alloc(unsigned long initial_length); static void fbuffer_free(FBuffer *fb); static void fbuffer_clear(FBuffer *fb); static void fbuffer_append(FBuffer *fb, const char *newstr, unsigned long len); -#ifdef JSON_GENERATOR static void fbuffer_append_long(FBuffer *fb, long number); +static inline void fbuffer_append_char(FBuffer *fb, char newchr); +static VALUE fbuffer_finalize(FBuffer *fb); + +static void fbuffer_stack_init(FBuffer *fb, unsigned long initial_length, char *stack_buffer, long stack_buffer_size) +{ + fb->initial_length = (initial_length > 0) ? initial_length : FBUFFER_INITIAL_LENGTH_DEFAULT; + if (stack_buffer) { + fb->type = FBUFFER_STACK_ALLOCATED; + fb->ptr = stack_buffer; + fb->capa = stack_buffer_size; + } +#ifdef JSON_DEBUG + fb->requested = 0; #endif -static void fbuffer_append_char(FBuffer *fb, char newchr); -#ifdef JSON_GENERATOR -static FBuffer *fbuffer_dup(FBuffer *fb); -static VALUE fbuffer_to_s(FBuffer *fb); -#endif +} -static FBuffer *fbuffer_alloc(unsigned long initial_length) +static inline void fbuffer_consumed(FBuffer *fb, unsigned long consumed) { - FBuffer *fb; - if (initial_length <= 0) initial_length = FBUFFER_INITIAL_LENGTH_DEFAULT; - fb = ALLOC(FBuffer); - memset((void *) fb, 0, sizeof(FBuffer)); - fb->initial_length = initial_length; - return fb; +#ifdef JSON_DEBUG + if (consumed > fb->requested) { + rb_bug("fbuffer: Out of bound write"); + } + fb->requested = 0; +#endif + fb->len += consumed; } static void fbuffer_free(FBuffer *fb) { - if (fb->ptr) ruby_xfree(fb->ptr); - ruby_xfree(fb); + if (fb->ptr && fb->type == FBUFFER_HEAP_ALLOCATED) { + ruby_xfree(fb->ptr); + } } static void fbuffer_clear(FBuffer *fb) @@ -91,20 +111,61 @@ static void fbuffer_clear(FBuffer *fb) fb->len = 0; } -static void fbuffer_inc_capa(FBuffer *fb, unsigned long requested) +static void fbuffer_flush(FBuffer *fb) +{ + rb_io_write(fb->io, rb_utf8_str_new(fb->ptr, fb->len)); + fbuffer_clear(fb); +} + +static void fbuffer_realloc(FBuffer *fb, unsigned long required) +{ + if (required > fb->capa) { + if (fb->type == FBUFFER_STACK_ALLOCATED) { + const char *old_buffer = fb->ptr; + fb->ptr = ALLOC_N(char, required); + fb->type = FBUFFER_HEAP_ALLOCATED; + MEMCPY(fb->ptr, old_buffer, char, fb->len); + } else { + REALLOC_N(fb->ptr, char, required); + } + fb->capa = required; + } +} + +static void fbuffer_do_inc_capa(FBuffer *fb, unsigned long requested) { + if (RB_UNLIKELY(fb->io)) { + if (fb->capa < FBUFFER_IO_BUFFER_SIZE) { + fbuffer_realloc(fb, FBUFFER_IO_BUFFER_SIZE); + } else { + fbuffer_flush(fb); + } + + if (RB_LIKELY(requested < fb->capa)) { + return; + } + } + unsigned long required; - if (!fb->ptr) { + if (RB_UNLIKELY(!fb->ptr)) { fb->ptr = ALLOC_N(char, fb->initial_length); fb->capa = fb->initial_length; } for (required = fb->capa; requested > required - fb->len; required <<= 1); - if (required > fb->capa) { - REALLOC_N(fb->ptr, char, required); - fb->capa = required; + fbuffer_realloc(fb, required); +} + +static inline void fbuffer_inc_capa(FBuffer *fb, unsigned long requested) +{ +#ifdef JSON_DEBUG + fb->requested = requested; +#endif + + if (RB_UNLIKELY(requested > fb->capa - fb->len)) { + fbuffer_do_inc_capa(fb, requested); } } @@ -113,11 +174,24 @@ static void fbuffer_append(FBuffer *fb, const char *newstr, unsigned long len) if (len > 0) { fbuffer_inc_capa(fb, len); MEMCPY(fb->ptr + fb->len, newstr, char, len); - fb->len += len; + fbuffer_consumed(fb, len); } } -#ifdef JSON_GENERATOR +/* Appends a character into a buffer. The buffer needs to have sufficient capacity, via fbuffer_inc_capa(...). */ +static inline void fbuffer_append_reserved_char(FBuffer *fb, char chr) +{ +#ifdef JSON_DEBUG + if (fb->requested < 1) { + rb_bug("fbuffer: unreserved write"); + } + fb->requested--; +#endif + + fb->ptr[fb->len] = chr; + fb->len++; +} + static void fbuffer_append_str(FBuffer *fb, VALUE str) { const char *newstr = StringValuePtr(str); @@ -127,61 +201,70 @@ static void fbuffer_append_str(FBuffer *fb, VALUE str) fbuffer_append(fb, newstr, len); } -#endif -static void fbuffer_append_char(FBuffer *fb, char newchr) +static inline void fbuffer_append_char(FBuffer *fb, char newchr) { fbuffer_inc_capa(fb, 1); *(fb->ptr + fb->len) = newchr; - fb->len++; + fbuffer_consumed(fb, 1); } -#ifdef JSON_GENERATOR -static void freverse(char *start, char *end) +static inline char *fbuffer_cursor(FBuffer *fb) { - char c; - - while (end > start) { - c = *end, *end-- = *start, *start++ = c; - } + return fb->ptr + fb->len; } -static long fltoa(long number, char *buf) +static inline void fbuffer_advance_to(FBuffer *fb, char *end) { - static char digits[] = "0123456789"; - long sign = number; - char* tmp = buf; - - if (sign < 0) number = -number; - do *tmp++ = digits[number % 10]; while (number /= 10); - if (sign < 0) *tmp++ = '-'; - freverse(buf, tmp - 1); - return tmp - buf; + fbuffer_consumed(fb, (end - fb->ptr) - fb->len); } +/* + * Appends the decimal string representation of \a number into the buffer. + */ static void fbuffer_append_long(FBuffer *fb, long number) { - char buf[20]; - unsigned long len = fltoa(number, buf); - fbuffer_append(fb, buf, len); -} - -static FBuffer *fbuffer_dup(FBuffer *fb) -{ - unsigned long len = fb->len; - FBuffer *result; + /* + * The jeaiii_ultoa() function produces digits left-to-right, + * allowing us to write directly into the buffer, but we don't know + * the number of resulting characters. + * + * We do know, however, that the `number` argument is always in the + * range 0xc000000000000000 to 0x3fffffffffffffff, or, in decimal, + * -4611686018427387904 to 4611686018427387903. The max number of chars + * generated is therefore 20 (including a potential sign character). + */ + + static const int MAX_CHARS_FOR_LONG = 20; + + fbuffer_inc_capa(fb, MAX_CHARS_FOR_LONG); + + if (number < 0) { + fbuffer_append_reserved_char(fb, '-'); + + /* + * Since number is always > LONG_MIN, `-number` will not overflow + * and is always the positive abs() value. + */ + number = -number; + } - result = fbuffer_alloc(len); - fbuffer_append(result, FBUFFER_PAIR(fb)); - return result; + char *end = jeaiii_ultoa(fbuffer_cursor(fb), number); + fbuffer_advance_to(fb, end); } -static VALUE fbuffer_to_s(FBuffer *fb) +static VALUE fbuffer_finalize(FBuffer *fb) { - VALUE result = rb_str_new(FBUFFER_PTR(fb), FBUFFER_LEN(fb)); - fbuffer_free(fb); - FORCE_UTF8(result); - return result; + if (fb->io) { + fbuffer_flush(fb); + fbuffer_free(fb); + rb_io_flush(fb->io); + return fb->io; + } else { + VALUE result = rb_utf8_str_new(FBUFFER_PTR(fb), FBUFFER_LEN(fb)); + fbuffer_free(fb); + return result; + } } -#endif + #endif diff --git a/ext/json/generator/depend b/ext/json/generator/depend index 42752d1a35eefb..aee4ab94ebcce8 100644 --- a/ext/json/generator/depend +++ b/ext/json/generator/depend @@ -1,5 +1,5 @@ $(OBJS): $(ruby_headers) -generator.o: generator.c generator.h $(srcdir)/../fbuffer/fbuffer.h +generator.o: generator.c $(srcdir)/../fbuffer/fbuffer.h # AUTOGENERATED DEPENDENCIES START generator.o: $(RUBY_EXTCONF_H) @@ -142,6 +142,7 @@ generator.o: $(hdrdir)/ruby/internal/intern/re.h generator.o: $(hdrdir)/ruby/internal/intern/ruby.h generator.o: $(hdrdir)/ruby/internal/intern/select.h generator.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +generator.o: $(hdrdir)/ruby/internal/intern/set.h generator.o: $(hdrdir)/ruby/internal/intern/signal.h generator.o: $(hdrdir)/ruby/internal/intern/sprintf.h generator.o: $(hdrdir)/ruby/internal/intern/string.h @@ -161,6 +162,7 @@ generator.o: $(hdrdir)/ruby/internal/special_consts.h generator.o: $(hdrdir)/ruby/internal/static_assert.h generator.o: $(hdrdir)/ruby/internal/stdalign.h generator.o: $(hdrdir)/ruby/internal/stdbool.h +generator.o: $(hdrdir)/ruby/internal/stdckdint.h generator.o: $(hdrdir)/ruby/internal/symbol.h generator.o: $(hdrdir)/ruby/internal/value.h generator.o: $(hdrdir)/ruby/internal/value_type.h @@ -176,6 +178,8 @@ generator.o: $(hdrdir)/ruby/ruby.h generator.o: $(hdrdir)/ruby/st.h generator.o: $(hdrdir)/ruby/subst.h generator.o: $(srcdir)/../fbuffer/fbuffer.h +generator.o: $(srcdir)/../simd/simd.h +generator.o: $(srcdir)/../vendor/fpconv.c +generator.o: $(srcdir)/../vendor/jeaiii-ltoa.h generator.o: generator.c -generator.o: generator.h # AUTOGENERATED DEPENDENCIES END diff --git a/ext/json/generator/extconf.rb b/ext/json/generator/extconf.rb index 8627c5f4bdd5c6..fb9afd07f7bfee 100644 --- a/ext/json/generator/extconf.rb +++ b/ext/json/generator/extconf.rb @@ -1,4 +1,16 @@ require 'mkmf' -$defs << "-DJSON_GENERATOR" -create_makefile 'json/ext/generator' +if RUBY_ENGINE == 'truffleruby' + # The pure-Ruby generator is faster on TruffleRuby, so skip compiling the generator extension + File.write('Makefile', dummy_makefile("").join) +else + append_cflags("-std=c99") + $defs << "-DJSON_GENERATOR" + $defs << "-DJSON_DEBUG" if ENV["JSON_DEBUG"] + + if enable_config('generator-use-simd', default=!ENV["JSON_DISABLE_SIMD"]) + load __dir__ + "/../simd/conf.rb" + end + + create_makefile 'json/ext/generator' +end diff --git a/ext/json/generator/generator.c b/ext/json/generator/generator.c index 8f7c57e042034d..33b1bf349d29c8 100644 --- a/ext/json/generator/generator.c +++ b/ext/json/generator/generator.c @@ -1,324 +1,675 @@ +#include "ruby.h" #include "../fbuffer/fbuffer.h" -#include "generator.h" +#include "../vendor/fpconv.c" -static VALUE mJSON, mExt, mGenerator, cState, mGeneratorMethods, mObject, - mHash, mArray, +#include +#include + +#include "../simd/simd.h" + +/* ruby api and some helpers */ + +typedef struct JSON_Generator_StateStruct { + VALUE indent; + VALUE space; + VALUE space_before; + VALUE object_nl; + VALUE array_nl; + VALUE as_json; + + long max_nesting; + long depth; + long buffer_initial_length; + + bool allow_nan; + bool ascii_only; + bool script_safe; + bool strict; +} JSON_Generator_State; + +#ifndef RB_UNLIKELY +#define RB_UNLIKELY(cond) (cond) +#endif + +static VALUE mJSON, cState, cFragment, mString_Extend, eGeneratorError, eNestingError, Encoding_UTF_8; + +static ID i_to_s, i_to_json, i_new, i_pack, i_unpack, i_create_id, i_extend, i_encode; +static VALUE sym_indent, sym_space, sym_space_before, sym_object_nl, sym_array_nl, sym_max_nesting, sym_allow_nan, + sym_ascii_only, sym_depth, sym_buffer_initial_length, sym_script_safe, sym_escape_slash, sym_strict, sym_as_json; + + +#define GET_STATE_TO(self, state) \ + TypedData_Get_Struct(self, JSON_Generator_State, &JSON_Generator_State_type, state) + +#define GET_STATE(self) \ + JSON_Generator_State *state; \ + GET_STATE_TO(self, state) + +struct generate_json_data; + +typedef void (*generator_func)(FBuffer *buffer, struct generate_json_data *data, VALUE obj); + +struct generate_json_data { + FBuffer *buffer; + VALUE vstate; + JSON_Generator_State *state; + VALUE obj; + generator_func func; +}; + +static VALUE cState_from_state_s(VALUE self, VALUE opts); +static VALUE cState_partial_generate(VALUE self, VALUE obj, generator_func, VALUE io); +static void generate_json(FBuffer *buffer, struct generate_json_data *data, VALUE obj); +static void generate_json_object(FBuffer *buffer, struct generate_json_data *data, VALUE obj); +static void generate_json_array(FBuffer *buffer, struct generate_json_data *data, VALUE obj); +static void generate_json_string(FBuffer *buffer, struct generate_json_data *data, VALUE obj); +static void generate_json_null(FBuffer *buffer, struct generate_json_data *data, VALUE obj); +static void generate_json_false(FBuffer *buffer, struct generate_json_data *data, VALUE obj); +static void generate_json_true(FBuffer *buffer, struct generate_json_data *data, VALUE obj); #ifdef RUBY_INTEGER_UNIFICATION - mInteger, +static void generate_json_integer(FBuffer *buffer, struct generate_json_data *data, VALUE obj); +#endif +static void generate_json_fixnum(FBuffer *buffer, struct generate_json_data *data, VALUE obj); +static void generate_json_bignum(FBuffer *buffer, struct generate_json_data *data, VALUE obj); +static void generate_json_float(FBuffer *buffer, struct generate_json_data *data, VALUE obj); +static void generate_json_fragment(FBuffer *buffer, struct generate_json_data *data, VALUE obj); + +static int usascii_encindex, utf8_encindex, binary_encindex; + +#ifdef RBIMPL_ATTR_NORETURN +RBIMPL_ATTR_NORETURN() +#endif +static void raise_generator_error_str(VALUE invalid_object, VALUE str) +{ + VALUE exc = rb_exc_new_str(eGeneratorError, str); + rb_ivar_set(exc, rb_intern("@invalid_object"), invalid_object); + rb_exc_raise(exc); +} + +#ifdef RBIMPL_ATTR_NORETURN +RBIMPL_ATTR_NORETURN() +#endif +#ifdef RBIMPL_ATTR_FORMAT +RBIMPL_ATTR_FORMAT(RBIMPL_PRINTF_FORMAT, 2, 3) +#endif +static void raise_generator_error(VALUE invalid_object, const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + VALUE str = rb_vsprintf(fmt, args); + va_end(args); + raise_generator_error_str(invalid_object, str); +} + +// 0 - single byte char that don't need to be escaped. +// (x | 8) - char that needs to be escaped. +static const unsigned char CHAR_LENGTH_MASK = 7; +static const unsigned char ESCAPE_MASK = 8; + +typedef struct _search_state { + const char *ptr; + const char *end; + const char *cursor; + FBuffer *buffer; + +#ifdef HAVE_SIMD + const char *chunk_base; + const char *chunk_end; + bool has_matches; + +#if defined(HAVE_SIMD_NEON) + uint64_t matches_mask; +#elif defined(HAVE_SIMD_SSE2) + int matches_mask; +#else +#error "Unknown SIMD Implementation." +#endif /* HAVE_SIMD_NEON */ +#endif /* HAVE_SIMD */ +} search_state; + +#if (defined(__GNUC__ ) || defined(__clang__)) +#define FORCE_INLINE __attribute__((always_inline)) #else - mFixnum, mBignum, +#define FORCE_INLINE #endif - mFloat, mString, mString_Extend, - mTrueClass, mFalseClass, mNilClass, eGeneratorError, - eNestingError; -static ID i_to_s, i_to_json, i_new, i_indent, i_space, i_space_before, - i_object_nl, i_array_nl, i_max_nesting, i_allow_nan, i_ascii_only, - i_pack, i_unpack, i_create_id, i_extend, i_key_p, - i_aref, i_send, i_respond_to_p, i_match, i_keys, i_depth, - i_buffer_initial_length, i_dup, i_escape_slash; +static inline FORCE_INLINE void search_flush(search_state *search) +{ + // Do not remove this conditional without profiling, specifically escape-heavy text. + // escape_UTF8_char_basic will advance search->ptr and search->cursor (effectively a search_flush). + // For back-to-back characters that need to be escaped, specifcally for the SIMD code paths, this method + // will be called just before calling escape_UTF8_char_basic. There will be no characers to append for the + // consecutive characters that need to be escaped. While the fbuffer_append is a no-op if + // nothing needs to be flushed, we can save a few memory references with this conditional. + if (search->ptr > search->cursor) { + fbuffer_append(search->buffer, search->cursor, search->ptr - search->cursor); + search->cursor = search->ptr; + } +} -/* - * Copyright 2001-2004 Unicode, Inc. +static const unsigned char escape_table_basic[256] = { + // ASCII Control Characters + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + // ASCII Characters + 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // '"' + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, // '\\' + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; + +static unsigned char (*search_escape_basic_impl)(search_state *); + +static inline unsigned char search_escape_basic(search_state *search) +{ + while (search->ptr < search->end) { + if (RB_UNLIKELY(escape_table_basic[(const unsigned char)*search->ptr])) { + search_flush(search); + return 1; + } else { + search->ptr++; + } + } + search_flush(search); + return 0; +} + +static inline FORCE_INLINE void escape_UTF8_char_basic(search_state *search) +{ + const unsigned char ch = (unsigned char)*search->ptr; + switch (ch) { + case '"': fbuffer_append(search->buffer, "\\\"", 2); break; + case '\\': fbuffer_append(search->buffer, "\\\\", 2); break; + case '/': fbuffer_append(search->buffer, "\\/", 2); break; + case '\b': fbuffer_append(search->buffer, "\\b", 2); break; + case '\f': fbuffer_append(search->buffer, "\\f", 2); break; + case '\n': fbuffer_append(search->buffer, "\\n", 2); break; + case '\r': fbuffer_append(search->buffer, "\\r", 2); break; + case '\t': fbuffer_append(search->buffer, "\\t", 2); break; + default: { + const char *hexdig = "0123456789abcdef"; + char scratch[6] = { '\\', 'u', '0', '0', 0, 0 }; + scratch[4] = hexdig[(ch >> 4) & 0xf]; + scratch[5] = hexdig[ch & 0xf]; + fbuffer_append(search->buffer, scratch, 6); + break; + } + } + search->ptr++; + search->cursor = search->ptr; +} + +/* Converts in_string to a JSON string (without the wrapping '"' + * characters) in FBuffer out_buffer. * - * Disclaimer + * Character are JSON-escaped according to: * - * This source code is provided as is by Unicode, Inc. No claims are - * made as to fitness for any particular purpose. No warranties of any - * kind are expressed or implied. The recipient agrees to determine - * applicability of information provided. If this file has been - * purchased on magnetic or optical media from Unicode, Inc., the - * sole remedy for any claim will be exchange of defective media - * within 90 days of receipt. + * - Always: ASCII control characters (0x00-0x1F), dquote, and + * backslash. * - * Limitations on Rights to Redistribute This Code + * - If out_ascii_only: non-ASCII characters (>0x7F) * - * Unicode, Inc. hereby grants the right to freely use the information - * supplied in this file in the creation of products supporting the - * Unicode Standard, and to make copies of this file in any form - * for internal or external distribution as long as this notice - * remains attached. + * - If script_safe: forwardslash (/), line separator (U+2028), and + * paragraph separator (U+2029) + * + * Everything else (should be UTF-8) is just passed through and + * appended to the result. */ +static inline void convert_UTF8_to_JSON(search_state *search) +{ + while (search_escape_basic_impl(search)) { + escape_UTF8_char_basic(search); + } +} -/* - * Index into the table below with the first byte of a UTF-8 sequence to - * get the number of trailing bytes that are supposed to follow it. - * Note that *legal* UTF-8 values can't have 4 or 5-bytes. The table is - * left as-is for anyone who may want to do such conversion, which was - * allowed in earlier algorithms. - */ -static const char trailingBytesForUTF8[256] = { - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, - 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, - 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5 -}; +static inline void escape_UTF8_char(search_state *search, unsigned char ch_len) +{ + const unsigned char ch = (unsigned char)*search->ptr; + switch (ch_len) { + case 1: { + switch (ch) { + case '"': fbuffer_append(search->buffer, "\\\"", 2); break; + case '\\': fbuffer_append(search->buffer, "\\\\", 2); break; + case '/': fbuffer_append(search->buffer, "\\/", 2); break; + case '\b': fbuffer_append(search->buffer, "\\b", 2); break; + case '\f': fbuffer_append(search->buffer, "\\f", 2); break; + case '\n': fbuffer_append(search->buffer, "\\n", 2); break; + case '\r': fbuffer_append(search->buffer, "\\r", 2); break; + case '\t': fbuffer_append(search->buffer, "\\t", 2); break; + default: { + const char *hexdig = "0123456789abcdef"; + char scratch[6] = { '\\', 'u', '0', '0', 0, 0 }; + scratch[4] = hexdig[(ch >> 4) & 0xf]; + scratch[5] = hexdig[ch & 0xf]; + fbuffer_append(search->buffer, scratch, 6); + break; + } + } + break; + } + case 3: { + if (search->ptr[2] & 1) { + fbuffer_append(search->buffer, "\\u2029", 6); + } else { + fbuffer_append(search->buffer, "\\u2028", 6); + } + break; + } + } + search->cursor = (search->ptr += ch_len); +} -/* - * Magic values subtracted from a buffer value during UTF8 conversion. - * This table contains as many values as there might be trailing bytes - * in a UTF-8 sequence. - */ -static const UTF32 offsetsFromUTF8[6] = { 0x00000000UL, 0x00003080UL, 0x000E2080UL, - 0x03C82080UL, 0xFA082080UL, 0x82082080UL }; +#ifdef HAVE_SIMD -/* - * Utility routine to tell whether a sequence of bytes is legal UTF-8. - * This must be called with the length pre-determined by the first byte. - * If not calling this from ConvertUTF8to*, then the length can be set by: - * length = trailingBytesForUTF8[*source]+1; - * and the sequence is illegal right away if there aren't that many bytes - * available. - * If presented with a length > 4, this returns 0. The Unicode - * definition of UTF-8 goes up to 4-byte sequences. - */ -static unsigned char isLegalUTF8(const UTF8 *source, unsigned long length) -{ - UTF8 a; - const UTF8 *srcptr = source+length; - switch (length) { - default: return 0; - /* Everything else falls through when "1"... */ - case 4: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return 0; - case 3: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return 0; - case 2: if ((a = (*--srcptr)) > 0xBF) return 0; - - switch (*source) { - /* no fall-through in this inner switch */ - case 0xE0: if (a < 0xA0) return 0; break; - case 0xED: if (a > 0x9F) return 0; break; - case 0xF0: if (a < 0x90) return 0; break; - case 0xF4: if (a > 0x8F) return 0; break; - default: if (a < 0x80) return 0; - } +static inline FORCE_INLINE char *copy_remaining_bytes(search_state *search, unsigned long vec_len, unsigned long len) +{ + // Flush the buffer so everything up until the last 'len' characters are unflushed. + search_flush(search); - case 1: if (*source >= 0x80 && *source < 0xC2) return 0; - } - if (*source > 0xF4) return 0; - return 1; + FBuffer *buf = search->buffer; + fbuffer_inc_capa(buf, vec_len); + + char *s = (buf->ptr + buf->len); + + // Pad the buffer with dummy characters that won't need escaping. + // This seem wateful at first sight, but memset of vector length is very fast. + memset(s, 'X', vec_len); + + // Optimistically copy the remaining 'len' characters to the output FBuffer. If there are no characters + // to escape, then everything ends up in the correct spot. Otherwise it was convenient temporary storage. + MEMCPY(s, search->ptr, char, len); + + return s; } -/* Escapes the UTF16 character and stores the result in the buffer buf. */ -static void unicode_escape(char *buf, UTF16 character) +#ifdef HAVE_SIMD_NEON + +static inline FORCE_INLINE unsigned char neon_next_match(search_state *search) { - const char *digits = "0123456789abcdef"; + uint64_t mask = search->matches_mask; + uint32_t index = trailing_zeros64(mask) >> 2; - buf[2] = digits[character >> 12]; - buf[3] = digits[(character >> 8) & 0xf]; - buf[4] = digits[(character >> 4) & 0xf]; - buf[5] = digits[character & 0xf]; + // It is assumed escape_UTF8_char_basic will only ever increase search->ptr by at most one character. + // If we want to use a similar approach for full escaping we'll need to ensure: + // search->chunk_base + index >= search->ptr + // However, since we know escape_UTF8_char_basic only increases search->ptr by one, if the next match + // is one byte after the previous match then: + // search->chunk_base + index == search->ptr + search->ptr = search->chunk_base + index; + mask &= mask - 1; + search->matches_mask = mask; + search_flush(search); + return 1; } -/* Escapes the UTF16 character and stores the result in the buffer buf, then - * the buffer buf is appended to the FBuffer buffer. */ -static void unicode_escape_to_buffer(FBuffer *buffer, char buf[6], UTF16 - character) +static inline unsigned char search_escape_basic_neon(search_state *search) { - unicode_escape(buf, character); - fbuffer_append(buffer, buf, 6); + if (RB_UNLIKELY(search->has_matches)) { + // There are more matches if search->matches_mask > 0. + if (search->matches_mask > 0) { + return neon_next_match(search); + } else { + // neon_next_match will only advance search->ptr up to the last matching character. + // Skip over any characters in the last chunk that occur after the last match. + search->has_matches = false; + search->ptr = search->chunk_end; + } + } + + /* + * The code below implements an SIMD-based algorithm to determine if N bytes at a time + * need to be escaped. + * + * Assume the ptr = "Te\sting!" (the double quotes are included in the string) + * + * The explanation will be limited to the first 8 bytes of the string for simplicity. However + * the vector insructions may work on larger vectors. + * + * First, we load three constants 'lower_bound', 'backslash' and 'dblquote" in vector registers. + * + * lower_bound: [20 20 20 20 20 20 20 20] + * backslash: [5C 5C 5C 5C 5C 5C 5C 5C] + * dblquote: [22 22 22 22 22 22 22 22] + * + * Next we load the first chunk of the ptr: + * [22 54 65 5C 73 74 69 6E] (" T e \ s t i n) + * + * First we check if any byte in chunk is less than 32 (0x20). This returns the following vector + * as no bytes are less than 32 (0x20): + * [0 0 0 0 0 0 0 0] + * + * Next, we check if any byte in chunk is equal to a backslash: + * [0 0 0 FF 0 0 0 0] + * + * Finally we check if any byte in chunk is equal to a double quote: + * [FF 0 0 0 0 0 0 0] + * + * Now we have three vectors where each byte indicates if the corresponding byte in chunk + * needs to be escaped. We combine these vectors with a series of logical OR instructions. + * This is the needs_escape vector and it is equal to: + * [FF 0 0 FF 0 0 0 0] + * + * Next we compute the bitwise AND between each byte and 0x1 and compute the horizontal sum of + * the values in the vector. This computes how many bytes need to be escaped within this chunk. + * + * Finally we compute a mask that indicates which bytes need to be escaped. If the mask is 0 then, + * no bytes need to be escaped and we can continue to the next chunk. If the mask is not 0 then we + * have at least one byte that needs to be escaped. + */ + + if (string_scan_simd_neon(&search->ptr, search->end, &search->matches_mask)) { + search->has_matches = true; + search->chunk_base = search->ptr; + search->chunk_end = search->ptr + sizeof(uint8x16_t); + return neon_next_match(search); + } + + // There are fewer than 16 bytes left. + unsigned long remaining = (search->end - search->ptr); + if (remaining >= SIMD_MINIMUM_THRESHOLD) { + char *s = copy_remaining_bytes(search, sizeof(uint8x16_t), remaining); + + uint64_t mask = compute_chunk_mask_neon(s); + + if (!mask) { + // Nothing to escape, ensure search_flush doesn't do anything by setting + // search->cursor to search->ptr. + fbuffer_consumed(search->buffer, remaining); + search->ptr = search->end; + search->cursor = search->end; + return 0; + } + + search->matches_mask = mask; + search->has_matches = true; + search->chunk_end = search->end; + search->chunk_base = search->ptr; + return neon_next_match(search); + } + + if (search->ptr < search->end) { + return search_escape_basic(search); + } + + search_flush(search); + return 0; } +#endif /* HAVE_SIMD_NEON */ + +#ifdef HAVE_SIMD_SSE2 -/* Converts string to a JSON string in FBuffer buffer, where all but the ASCII - * and control characters are JSON escaped. */ -static void convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string, char escape_slash) +static inline FORCE_INLINE unsigned char sse2_next_match(search_state *search) { - const UTF8 *source = (UTF8 *) RSTRING_PTR(string); - const UTF8 *sourceEnd = source + RSTRING_LEN(string); - char buf[6] = { '\\', 'u' }; + int mask = search->matches_mask; + int index = trailing_zeros(mask); - while (source < sourceEnd) { - UTF32 ch = 0; - unsigned short extraBytesToRead = trailingBytesForUTF8[*source]; - if (source + extraBytesToRead >= sourceEnd) { - rb_raise(rb_path2class("JSON::GeneratorError"), - "partial character in source, but hit end"); - } - if (!isLegalUTF8(source, extraBytesToRead+1)) { - rb_raise(rb_path2class("JSON::GeneratorError"), - "source sequence is illegal/malformed utf-8"); - } - /* - * The cases all fall through. See "Note A" below. - */ - switch (extraBytesToRead) { - case 5: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */ - case 4: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */ - case 3: ch += *source++; ch <<= 6; - case 2: ch += *source++; ch <<= 6; - case 1: ch += *source++; ch <<= 6; - case 0: ch += *source++; - } - ch -= offsetsFromUTF8[extraBytesToRead]; - - if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */ - /* UTF-16 surrogate values are illegal in UTF-32 */ - if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) { -#if UNI_STRICT_CONVERSION - source -= (extraBytesToRead+1); /* return to the illegal value itself */ - rb_raise(rb_path2class("JSON::GeneratorError"), - "source sequence is illegal/malformed utf-8"); + // It is assumed escape_UTF8_char_basic will only ever increase search->ptr by at most one character. + // If we want to use a similar approach for full escaping we'll need to ensure: + // search->chunk_base + index >= search->ptr + // However, since we know escape_UTF8_char_basic only increases search->ptr by one, if the next match + // is one byte after the previous match then: + // search->chunk_base + index == search->ptr + search->ptr = search->chunk_base + index; + mask &= mask - 1; + search->matches_mask = mask; + search_flush(search); + return 1; +} + +#if defined(__clang__) || defined(__GNUC__) +#define TARGET_SSE2 __attribute__((target("sse2"))) #else - unicode_escape_to_buffer(buffer, buf, UNI_REPLACEMENT_CHAR); +#define TARGET_SSE2 #endif + +static inline TARGET_SSE2 FORCE_INLINE unsigned char search_escape_basic_sse2(search_state *search) +{ + if (RB_UNLIKELY(search->has_matches)) { + // There are more matches if search->matches_mask > 0. + if (search->matches_mask > 0) { + return sse2_next_match(search); + } else { + // sse2_next_match will only advance search->ptr up to the last matching character. + // Skip over any characters in the last chunk that occur after the last match. + search->has_matches = false; + if (RB_UNLIKELY(search->chunk_base + sizeof(__m128i) >= search->end)) { + search->ptr = search->end; } else { - /* normal case */ - if (ch >= 0x20 && ch <= 0x7f) { - switch (ch) { - case '\\': - fbuffer_append(buffer, "\\\\", 2); - break; - case '"': - fbuffer_append(buffer, "\\\"", 2); - break; - case '/': - if(escape_slash) { - fbuffer_append(buffer, "\\/", 2); - break; - } - default: - fbuffer_append_char(buffer, (char)ch); - break; - } - } else { - switch (ch) { - case '\n': - fbuffer_append(buffer, "\\n", 2); - break; - case '\r': - fbuffer_append(buffer, "\\r", 2); - break; - case '\t': - fbuffer_append(buffer, "\\t", 2); - break; - case '\f': - fbuffer_append(buffer, "\\f", 2); - break; - case '\b': - fbuffer_append(buffer, "\\b", 2); - break; - default: - unicode_escape_to_buffer(buffer, buf, (UTF16) ch); - break; + search->ptr = search->chunk_base + sizeof(__m128i); + } + } + } + + if (string_scan_simd_sse2(&search->ptr, search->end, &search->matches_mask)) { + search->has_matches = true; + search->chunk_base = search->ptr; + search->chunk_end = search->ptr + sizeof(__m128i); + return sse2_next_match(search); + } + + // There are fewer than 16 bytes left. + unsigned long remaining = (search->end - search->ptr); + if (remaining >= SIMD_MINIMUM_THRESHOLD) { + char *s = copy_remaining_bytes(search, sizeof(__m128i), remaining); + + int needs_escape_mask = compute_chunk_mask_sse2(s); + + if (needs_escape_mask == 0) { + // Nothing to escape, ensure search_flush doesn't do anything by setting + // search->cursor to search->ptr. + fbuffer_consumed(search->buffer, remaining); + search->ptr = search->end; + search->cursor = search->end; + return 0; + } + + search->has_matches = true; + search->matches_mask = needs_escape_mask; + search->chunk_base = search->ptr; + return sse2_next_match(search); + } + + if (search->ptr < search->end) { + return search_escape_basic(search); + } + + search_flush(search); + return 0; +} + +#endif /* HAVE_SIMD_SSE2 */ + +#endif /* HAVE_SIMD */ + +static const unsigned char script_safe_escape_table[256] = { + // ASCII Control Characters + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + // ASCII Characters + 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, // '"' and '/' + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, // '\\' + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + // Continuation byte + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + // First byte of a 2-byte code point + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + // First byte of a 3-byte code point + 3, 3,11, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, // 0xE2 is the start of \u2028 and \u2029 + //First byte of a 4+ byte code point + 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 9, 9, +}; + +static inline unsigned char search_script_safe_escape(search_state *search) +{ + while (search->ptr < search->end) { + unsigned char ch = (unsigned char)*search->ptr; + unsigned char ch_len = script_safe_escape_table[ch]; + + if (RB_UNLIKELY(ch_len)) { + if (ch_len & ESCAPE_MASK) { + if (RB_UNLIKELY(ch_len == 11)) { + const unsigned char *uptr = (const unsigned char *)search->ptr; + if (!(uptr[1] == 0x80 && (uptr[2] >> 1) == 0x54)) { + search->ptr += 3; + continue; } } + search_flush(search); + return ch_len & CHAR_LENGTH_MASK; + } else { + search->ptr += ch_len; } - } else if (ch > UNI_MAX_UTF16) { -#if UNI_STRICT_CONVERSION - source -= (extraBytesToRead+1); /* return to the start */ - rb_raise(rb_path2class("JSON::GeneratorError"), - "source sequence is illegal/malformed utf8"); -#else - unicode_escape_to_buffer(buffer, buf, UNI_REPLACEMENT_CHAR); -#endif } else { - /* target is a character in range 0xFFFF - 0x10FFFF. */ - ch -= halfBase; - unicode_escape_to_buffer(buffer, buf, (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START)); - unicode_escape_to_buffer(buffer, buf, (UTF16)((ch & halfMask) + UNI_SUR_LOW_START)); + search->ptr++; } } - RB_GC_GUARD(string); -} - -/* Converts string to a JSON string in FBuffer buffer, where only the - * characters required by the JSON standard are JSON escaped. The remaining - * characters (should be UTF8) are just passed through and appended to the - * result. */ -static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string, char escape_slash) -{ - const char *ptr = RSTRING_PTR(string), *p; - unsigned long len = RSTRING_LEN(string), start = 0, end = 0; - const char *escape = NULL; - int escape_len; - unsigned char c; - char buf[6] = { '\\', 'u' }; - int ascii_only = rb_enc_str_asciionly_p(string); - - for (start = 0, end = 0; end < len;) { - p = ptr + end; - c = (unsigned char) *p; - if (c < 0x20) { - switch (c) { - case '\n': - escape = "\\n"; - escape_len = 2; - break; - case '\r': - escape = "\\r"; - escape_len = 2; - break; - case '\t': - escape = "\\t"; - escape_len = 2; - break; - case '\f': - escape = "\\f"; - escape_len = 2; - break; - case '\b': - escape = "\\b"; - escape_len = 2; - break; - default: - unicode_escape(buf, (UTF16) *p); - escape = buf; - escape_len = 6; + search_flush(search); + return 0; +} + +static void convert_UTF8_to_script_safe_JSON(search_state *search) +{ + unsigned char ch_len; + while ((ch_len = search_script_safe_escape(search))) { + escape_UTF8_char(search, ch_len); + } +} + +static const unsigned char ascii_only_escape_table[256] = { + // ASCII Control Characters + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, + // ASCII Characters + 0, 0, 9, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // '"' + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 9, 0, 0, 0, // '\\' + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + // Continuation byte + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + // First byte of a 2-byte code point + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, + // First byte of a 3-byte code point + 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + //First byte of a 4+ byte code point + 4, 4, 4, 4, 4, 4, 4, 4, 5, 5, 5, 5, 6, 6, 9, 9, +}; + +static inline unsigned char search_ascii_only_escape(search_state *search, const unsigned char escape_table[256]) +{ + while (search->ptr < search->end) { + unsigned char ch = (unsigned char)*search->ptr; + unsigned char ch_len = escape_table[ch]; + + if (RB_UNLIKELY(ch_len)) { + search_flush(search); + return ch_len & CHAR_LENGTH_MASK; + } else { + search->ptr++; + } + } + search_flush(search); + return 0; +} + +static inline void full_escape_UTF8_char(search_state *search, unsigned char ch_len) +{ + const unsigned char ch = (unsigned char)*search->ptr; + switch (ch_len) { + case 1: { + switch (ch) { + case '"': fbuffer_append(search->buffer, "\\\"", 2); break; + case '\\': fbuffer_append(search->buffer, "\\\\", 2); break; + case '/': fbuffer_append(search->buffer, "\\/", 2); break; + case '\b': fbuffer_append(search->buffer, "\\b", 2); break; + case '\f': fbuffer_append(search->buffer, "\\f", 2); break; + case '\n': fbuffer_append(search->buffer, "\\n", 2); break; + case '\r': fbuffer_append(search->buffer, "\\r", 2); break; + case '\t': fbuffer_append(search->buffer, "\\t", 2); break; + default: { + const char *hexdig = "0123456789abcdef"; + char scratch[6] = { '\\', 'u', '0', '0', 0, 0 }; + scratch[4] = hexdig[(ch >> 4) & 0xf]; + scratch[5] = hexdig[ch & 0xf]; + fbuffer_append(search->buffer, scratch, 6); break; + } } - } else { - switch (c) { - case '\\': - escape = "\\\\"; - escape_len = 2; + break; + } + default: { + const char *hexdig = "0123456789abcdef"; + char scratch[12] = { '\\', 'u', 0, 0, 0, 0, '\\', 'u' }; + + uint32_t wchar = 0; + + switch (ch_len) { + case 2: + wchar = ch & 0x1F; break; - case '"': - escape = "\\\""; - escape_len = 2; + case 3: + wchar = ch & 0x0F; break; - case '/': - if(escape_slash) { - escape = "\\/"; - escape_len = 2; - break; - } - default: - { - unsigned short clen = 1; - if (!ascii_only) { - clen += trailingBytesForUTF8[c]; - if (end + clen > len) { - rb_raise(rb_path2class("JSON::GeneratorError"), - "partial character in source, but hit end"); - } - if (!isLegalUTF8((UTF8 *) p, clen)) { - rb_raise(rb_path2class("JSON::GeneratorError"), - "source sequence is illegal/malformed utf-8"); - } - } - end += clen; - } - continue; + case 4: + wchar = ch & 0x07; break; } + + for (short i = 1; i < ch_len; i++) { + wchar = (wchar << 6) | (search->ptr[i] & 0x3F); + } + + if (wchar <= 0xFFFF) { + scratch[2] = hexdig[wchar >> 12]; + scratch[3] = hexdig[(wchar >> 8) & 0xf]; + scratch[4] = hexdig[(wchar >> 4) & 0xf]; + scratch[5] = hexdig[wchar & 0xf]; + fbuffer_append(search->buffer, scratch, 6); + } else { + uint16_t hi, lo; + wchar -= 0x10000; + hi = 0xD800 + (uint16_t)(wchar >> 10); + lo = 0xDC00 + (uint16_t)(wchar & 0x3FF); + + scratch[2] = hexdig[hi >> 12]; + scratch[3] = hexdig[(hi >> 8) & 0xf]; + scratch[4] = hexdig[(hi >> 4) & 0xf]; + scratch[5] = hexdig[hi & 0xf]; + + scratch[8] = hexdig[lo >> 12]; + scratch[9] = hexdig[(lo >> 8) & 0xf]; + scratch[10] = hexdig[(lo >> 4) & 0xf]; + scratch[11] = hexdig[lo & 0xf]; + + fbuffer_append(search->buffer, scratch, 12); + } + + break; } - fbuffer_append(buffer, ptr + start, end - start); - fbuffer_append(buffer, escape, escape_len); - start = ++end; - escape = NULL; } - fbuffer_append(buffer, ptr + start, end - start); + search->cursor = (search->ptr += ch_len); } -static char *fstrndup(const char *ptr, unsigned long len) { - char *result; - if (len <= 0) return NULL; - result = ALLOC_N(char, len); - memcpy(result, ptr, len); - return result; +static void convert_UTF8_to_ASCII_only_JSON(search_state *search, const unsigned char escape_table[256]) +{ + unsigned char ch_len; + while ((ch_len = search_ascii_only_escape(search, escape_table))) { + full_escape_UTF8_char(search, ch_len); + } } /* @@ -413,7 +764,9 @@ static char *fstrndup(const char *ptr, unsigned long len) { */ static VALUE mHash_to_json(int argc, VALUE *argv, VALUE self) { - GENERATE_JSON(object); + rb_check_arity(argc, 0, 1); + VALUE Vstate = cState_from_state_s(cState, argc == 1 ? argv[0] : Qnil); + return cState_partial_generate(Vstate, self, generate_json_object, Qfalse); } /* @@ -424,8 +777,11 @@ static VALUE mHash_to_json(int argc, VALUE *argv, VALUE self) * _state_ is a JSON::State object, that can also be used to configure the * produced JSON string output further. */ -static VALUE mArray_to_json(int argc, VALUE *argv, VALUE self) { - GENERATE_JSON(array); +static VALUE mArray_to_json(int argc, VALUE *argv, VALUE self) +{ + rb_check_arity(argc, 0, 1); + VALUE Vstate = cState_from_state_s(cState, argc == 1 ? argv[0] : Qnil); + return cState_partial_generate(Vstate, self, generate_json_array, Qfalse); } #ifdef RUBY_INTEGER_UNIFICATION @@ -436,7 +792,9 @@ static VALUE mArray_to_json(int argc, VALUE *argv, VALUE self) { */ static VALUE mInteger_to_json(int argc, VALUE *argv, VALUE self) { - GENERATE_JSON(integer); + rb_check_arity(argc, 0, 1); + VALUE Vstate = cState_from_state_s(cState, argc == 1 ? argv[0] : Qnil); + return cState_partial_generate(Vstate, self, generate_json_integer, Qfalse); } #else @@ -447,7 +805,9 @@ static VALUE mInteger_to_json(int argc, VALUE *argv, VALUE self) */ static VALUE mFixnum_to_json(int argc, VALUE *argv, VALUE self) { - GENERATE_JSON(fixnum); + rb_check_arity(argc, 0, 1); + VALUE Vstate = cState_from_state_s(cState, argc == 1 ? argv[0] : Qnil); + return cState_partial_generate(Vstate, self, generate_json_fixnum, Qfalse); } /* @@ -457,7 +817,9 @@ static VALUE mFixnum_to_json(int argc, VALUE *argv, VALUE self) */ static VALUE mBignum_to_json(int argc, VALUE *argv, VALUE self) { - GENERATE_JSON(bignum); + rb_check_arity(argc, 0, 1); + VALUE Vstate = cState_from_state_s(cState, argc == 1 ? argv[0] : Qnil); + return cState_partial_generate(Vstate, self, generate_json_bignum, Qfalse); } #endif @@ -468,7 +830,9 @@ static VALUE mBignum_to_json(int argc, VALUE *argv, VALUE self) */ static VALUE mFloat_to_json(int argc, VALUE *argv, VALUE self) { - GENERATE_JSON(float); + rb_check_arity(argc, 0, 1); + VALUE Vstate = cState_from_state_s(cState, argc == 1 ? argv[0] : Qnil); + return cState_partial_generate(Vstate, self, generate_json_float, Qfalse); } /* @@ -476,7 +840,8 @@ static VALUE mFloat_to_json(int argc, VALUE *argv, VALUE self) * * Extends _modul_ with the String::Extend module. */ -static VALUE mString_included_s(VALUE self, VALUE modul) { +static VALUE mString_included_s(VALUE self, VALUE modul) +{ VALUE result = rb_funcall(modul, i_extend, 1, mString_Extend); rb_call_super(1, &modul); return result; @@ -491,7 +856,9 @@ static VALUE mString_included_s(VALUE self, VALUE modul) { */ static VALUE mString_to_json(int argc, VALUE *argv, VALUE self) { - GENERATE_JSON(string); + rb_check_arity(argc, 0, 1); + VALUE Vstate = cState_from_state_s(cState, argc == 1 ? argv[0] : Qnil); + return cState_partial_generate(Vstate, self, generate_json_string, Qfalse); } /* @@ -508,7 +875,7 @@ static VALUE mString_to_json_raw_object(VALUE self) VALUE result = rb_hash_new(); rb_hash_aset(result, rb_funcall(mJSON, i_create_id, 0), rb_class_name(rb_obj_class(self))); ary = rb_funcall(self, i_unpack, 1, rb_str_new2("C*")); - rb_hash_aset(result, rb_str_new2("raw"), ary); + rb_hash_aset(result, rb_utf8_str_new_lit("raw"), ary); return result; } @@ -546,7 +913,8 @@ static VALUE mString_Extend_json_create(VALUE self, VALUE o) */ static VALUE mTrueClass_to_json(int argc, VALUE *argv, VALUE self) { - GENERATE_JSON(true); + rb_check_arity(argc, 0, 1); + return rb_utf8_str_new("true", 4); } /* @@ -556,7 +924,8 @@ static VALUE mTrueClass_to_json(int argc, VALUE *argv, VALUE self) */ static VALUE mFalseClass_to_json(int argc, VALUE *argv, VALUE self) { - GENERATE_JSON(false); + rb_check_arity(argc, 0, 1); + return rb_utf8_str_new("false", 5); } /* @@ -566,7 +935,8 @@ static VALUE mFalseClass_to_json(int argc, VALUE *argv, VALUE self) */ static VALUE mNilClass_to_json(int argc, VALUE *argv, VALUE self) { - GENERATE_JSON(null); + rb_check_arity(argc, 0, 1); + return rb_utf8_str_new("null", 4); } /* @@ -583,36 +953,40 @@ static VALUE mObject_to_json(int argc, VALUE *argv, VALUE self) rb_scan_args(argc, argv, "01", &state); Check_Type(string, T_STRING); state = cState_from_state_s(cState, state); - return cState_partial_generate(state, string); + return cState_partial_generate(state, string, generate_json_string, Qfalse); +} + +static void State_mark(void *ptr) +{ + JSON_Generator_State *state = ptr; + rb_gc_mark_movable(state->indent); + rb_gc_mark_movable(state->space); + rb_gc_mark_movable(state->space_before); + rb_gc_mark_movable(state->object_nl); + rb_gc_mark_movable(state->array_nl); + rb_gc_mark_movable(state->as_json); +} + +static void State_compact(void *ptr) +{ + JSON_Generator_State *state = ptr; + state->indent = rb_gc_location(state->indent); + state->space = rb_gc_location(state->space); + state->space_before = rb_gc_location(state->space_before); + state->object_nl = rb_gc_location(state->object_nl); + state->array_nl = rb_gc_location(state->array_nl); + state->as_json = rb_gc_location(state->as_json); } static void State_free(void *ptr) { JSON_Generator_State *state = ptr; - if (state->indent) ruby_xfree(state->indent); - if (state->space) ruby_xfree(state->space); - if (state->space_before) ruby_xfree(state->space_before); - if (state->object_nl) ruby_xfree(state->object_nl); - if (state->array_nl) ruby_xfree(state->array_nl); - if (state->array_delim) fbuffer_free(state->array_delim); - if (state->object_delim) fbuffer_free(state->object_delim); - if (state->object_delim2) fbuffer_free(state->object_delim2); ruby_xfree(state); } static size_t State_memsize(const void *ptr) { - const JSON_Generator_State *state = ptr; - size_t size = sizeof(*state); - if (state->indent) size += state->indent_len + 1; - if (state->space) size += state->space_len + 1; - if (state->space_before) size += state->space_before_len + 1; - if (state->object_nl) size += state->object_nl_len + 1; - if (state->array_nl) size += state->array_nl_len + 1; - if (state->array_delim) size += FBUFFER_CAPA(state->array_delim); - if (state->object_delim) size += FBUFFER_CAPA(state->object_delim); - if (state->object_delim2) size += FBUFFER_CAPA(state->object_delim2); - return size; + return sizeof(JSON_Generator_State); } #ifndef HAVE_RB_EXT_RACTOR_SAFE @@ -620,508 +994,517 @@ static size_t State_memsize(const void *ptr) # define RUBY_TYPED_FROZEN_SHAREABLE 0 #endif -#ifdef NEW_TYPEDDATA_WRAPPER static const rb_data_type_t JSON_Generator_State_type = { "JSON/Generator/State", - {NULL, State_free, State_memsize,}, -#ifdef RUBY_TYPED_FREE_IMMEDIATELY + { + .dmark = State_mark, + .dfree = State_free, + .dsize = State_memsize, + .dcompact = State_compact, + }, 0, 0, - RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_FROZEN_SHAREABLE, -#endif + RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_FROZEN_SHAREABLE, }; -#endif -static VALUE cState_s_allocate(VALUE klass) +static void state_init(JSON_Generator_State *state) { - JSON_Generator_State *state; - return TypedData_Make_Struct(klass, JSON_Generator_State, - &JSON_Generator_State_type, state); -} - -/* - * call-seq: configure(opts) - * - * Configure this State instance with the Hash _opts_, and return - * itself. - */ -static VALUE cState_configure(VALUE self, VALUE opts) -{ - VALUE tmp; - GET_STATE(self); - tmp = rb_check_convert_type(opts, T_HASH, "Hash", "to_hash"); - if (NIL_P(tmp)) tmp = rb_convert_type(opts, T_HASH, "Hash", "to_h"); - opts = tmp; - tmp = rb_hash_aref(opts, ID2SYM(i_indent)); - if (RTEST(tmp)) { - unsigned long len; - Check_Type(tmp, T_STRING); - len = RSTRING_LEN(tmp); - state->indent = fstrndup(RSTRING_PTR(tmp), len + 1); - state->indent_len = len; - } - tmp = rb_hash_aref(opts, ID2SYM(i_space)); - if (RTEST(tmp)) { - unsigned long len; - Check_Type(tmp, T_STRING); - len = RSTRING_LEN(tmp); - state->space = fstrndup(RSTRING_PTR(tmp), len + 1); - state->space_len = len; - } - tmp = rb_hash_aref(opts, ID2SYM(i_space_before)); - if (RTEST(tmp)) { - unsigned long len; - Check_Type(tmp, T_STRING); - len = RSTRING_LEN(tmp); - state->space_before = fstrndup(RSTRING_PTR(tmp), len + 1); - state->space_before_len = len; - } - tmp = rb_hash_aref(opts, ID2SYM(i_array_nl)); - if (RTEST(tmp)) { - unsigned long len; - Check_Type(tmp, T_STRING); - len = RSTRING_LEN(tmp); - state->array_nl = fstrndup(RSTRING_PTR(tmp), len + 1); - state->array_nl_len = len; - } - tmp = rb_hash_aref(opts, ID2SYM(i_object_nl)); - if (RTEST(tmp)) { - unsigned long len; - Check_Type(tmp, T_STRING); - len = RSTRING_LEN(tmp); - state->object_nl = fstrndup(RSTRING_PTR(tmp), len + 1); - state->object_nl_len = len; - } - tmp = ID2SYM(i_max_nesting); state->max_nesting = 100; - if (option_given_p(opts, tmp)) { - VALUE max_nesting = rb_hash_aref(opts, tmp); - if (RTEST(max_nesting)) { - Check_Type(max_nesting, T_FIXNUM); - state->max_nesting = FIX2LONG(max_nesting); - } else { - state->max_nesting = 0; - } - } - tmp = ID2SYM(i_depth); - state->depth = 0; - if (option_given_p(opts, tmp)) { - VALUE depth = rb_hash_aref(opts, tmp); - if (RTEST(depth)) { - Check_Type(depth, T_FIXNUM); - state->depth = FIX2LONG(depth); - } else { - state->depth = 0; - } - } - tmp = ID2SYM(i_buffer_initial_length); - if (option_given_p(opts, tmp)) { - VALUE buffer_initial_length = rb_hash_aref(opts, tmp); - if (RTEST(buffer_initial_length)) { - long initial_length; - Check_Type(buffer_initial_length, T_FIXNUM); - initial_length = FIX2LONG(buffer_initial_length); - if (initial_length > 0) state->buffer_initial_length = initial_length; - } - } - tmp = rb_hash_aref(opts, ID2SYM(i_allow_nan)); - state->allow_nan = RTEST(tmp); - tmp = rb_hash_aref(opts, ID2SYM(i_ascii_only)); - state->ascii_only = RTEST(tmp); - tmp = rb_hash_aref(opts, ID2SYM(i_escape_slash)); - state->escape_slash = RTEST(tmp); - return self; + state->buffer_initial_length = FBUFFER_INITIAL_LENGTH_DEFAULT; } -static void set_state_ivars(VALUE hash, VALUE state) +static VALUE cState_s_allocate(VALUE klass) { - VALUE ivars = rb_obj_instance_variables(state); - int i = 0; - for (i = 0; i < RARRAY_LEN(ivars); i++) { - VALUE key = rb_funcall(rb_ary_entry(ivars, i), i_to_s, 0); - long key_len = RSTRING_LEN(key); - VALUE value = rb_iv_get(state, StringValueCStr(key)); - rb_hash_aset(hash, rb_str_intern(rb_str_substr(key, 1, key_len - 1)), value); - } + JSON_Generator_State *state; + VALUE obj = TypedData_Make_Struct(klass, JSON_Generator_State, &JSON_Generator_State_type, state); + state_init(state); + return obj; } -/* - * call-seq: to_h - * - * Returns the configuration instance variables as a hash, that can be - * passed to the configure method. - */ -static VALUE cState_to_h(VALUE self) +static void vstate_spill(struct generate_json_data *data) { - VALUE result = rb_hash_new(); - GET_STATE(self); - set_state_ivars(result, self); - rb_hash_aset(result, ID2SYM(i_indent), rb_str_new(state->indent, state->indent_len)); - rb_hash_aset(result, ID2SYM(i_space), rb_str_new(state->space, state->space_len)); - rb_hash_aset(result, ID2SYM(i_space_before), rb_str_new(state->space_before, state->space_before_len)); - rb_hash_aset(result, ID2SYM(i_object_nl), rb_str_new(state->object_nl, state->object_nl_len)); - rb_hash_aset(result, ID2SYM(i_array_nl), rb_str_new(state->array_nl, state->array_nl_len)); - rb_hash_aset(result, ID2SYM(i_allow_nan), state->allow_nan ? Qtrue : Qfalse); - rb_hash_aset(result, ID2SYM(i_ascii_only), state->ascii_only ? Qtrue : Qfalse); - rb_hash_aset(result, ID2SYM(i_max_nesting), LONG2FIX(state->max_nesting)); - rb_hash_aset(result, ID2SYM(i_escape_slash), state->escape_slash ? Qtrue : Qfalse); - rb_hash_aset(result, ID2SYM(i_depth), LONG2FIX(state->depth)); - rb_hash_aset(result, ID2SYM(i_buffer_initial_length), LONG2FIX(state->buffer_initial_length)); - return result; + VALUE vstate = cState_s_allocate(cState); + GET_STATE(vstate); + MEMCPY(state, data->state, JSON_Generator_State, 1); + data->state = state; + data->vstate = vstate; + RB_OBJ_WRITTEN(vstate, Qundef, state->indent); + RB_OBJ_WRITTEN(vstate, Qundef, state->space); + RB_OBJ_WRITTEN(vstate, Qundef, state->space_before); + RB_OBJ_WRITTEN(vstate, Qundef, state->object_nl); + RB_OBJ_WRITTEN(vstate, Qundef, state->array_nl); + RB_OBJ_WRITTEN(vstate, Qundef, state->as_json); } -/* -* call-seq: [](name) -* -* Returns the value returned by method +name+. -*/ -static VALUE cState_aref(VALUE self, VALUE name) +static inline VALUE vstate_get(struct generate_json_data *data) { - name = rb_funcall(name, i_to_s, 0); - if (RTEST(rb_funcall(self, i_respond_to_p, 1, name))) { - return rb_funcall(self, i_send, 1, name); - } else { - return rb_attr_get(self, rb_intern_str(rb_str_concat(rb_str_new2("@"), name))); + if (RB_UNLIKELY(!data->vstate)) { + vstate_spill(data); } + return data->vstate; } -/* -* call-seq: []=(name, value) -* -* Sets the attribute name to value. -*/ -static VALUE cState_aset(VALUE self, VALUE name, VALUE value) +struct hash_foreach_arg { + struct generate_json_data *data; + int iter; +}; + +static VALUE +convert_string_subclass(VALUE key) { - VALUE name_writer; + VALUE key_to_s = rb_funcall(key, i_to_s, 0); - name = rb_funcall(name, i_to_s, 0); - name_writer = rb_str_cat2(rb_str_dup(name), "="); - if (RTEST(rb_funcall(self, i_respond_to_p, 1, name_writer))) { - return rb_funcall(self, i_send, 2, name_writer, value); - } else { - rb_ivar_set(self, rb_intern_str(rb_str_concat(rb_str_new2("@"), name)), value); + if (RB_UNLIKELY(!RB_TYPE_P(key_to_s, T_STRING))) { + VALUE cname = rb_obj_class(key); + rb_raise(rb_eTypeError, + "can't convert %"PRIsVALUE" to %s (%"PRIsVALUE"#%s gives %"PRIsVALUE")", + cname, "String", cname, "to_s", rb_obj_class(key_to_s)); } - return Qnil; -} -struct hash_foreach_arg { - FBuffer *buffer; - JSON_Generator_State *state; - VALUE Vstate; - int iter; -}; + return key_to_s; +} static int json_object_i(VALUE key, VALUE val, VALUE _arg) { struct hash_foreach_arg *arg = (struct hash_foreach_arg *)_arg; - FBuffer *buffer = arg->buffer; - JSON_Generator_State *state = arg->state; - VALUE Vstate = arg->Vstate; - - char *object_nl = state->object_nl; - long object_nl_len = state->object_nl_len; - char *indent = state->indent; - long indent_len = state->indent_len; - char *delim = FBUFFER_PTR(state->object_delim); - long delim_len = FBUFFER_LEN(state->object_delim); - char *delim2 = FBUFFER_PTR(state->object_delim2); - long delim2_len = FBUFFER_LEN(state->object_delim2); + struct generate_json_data *data = arg->data; + + FBuffer *buffer = data->buffer; + JSON_Generator_State *state = data->state; + long depth = state->depth; int j; - VALUE klass, key_to_s; - if (arg->iter > 0) fbuffer_append(buffer, delim, delim_len); - if (object_nl) { - fbuffer_append(buffer, object_nl, object_nl_len); + if (arg->iter > 0) fbuffer_append_char(buffer, ','); + if (RB_UNLIKELY(data->state->object_nl)) { + fbuffer_append_str(buffer, data->state->object_nl); } - if (indent) { + if (RB_UNLIKELY(data->state->indent)) { for (j = 0; j < depth; j++) { - fbuffer_append(buffer, indent, indent_len); + fbuffer_append_str(buffer, data->state->indent); } } - klass = CLASS_OF(key); - if (klass == rb_cString) { - key_to_s = key; - } else if (klass == rb_cSymbol) { - key_to_s = rb_id2str(SYM2ID(key)); + VALUE key_to_s; + switch (rb_type(key)) { + case T_STRING: + if (RB_LIKELY(RBASIC_CLASS(key) == rb_cString)) { + key_to_s = key; + } else { + key_to_s = convert_string_subclass(key); + } + break; + case T_SYMBOL: + key_to_s = rb_sym2str(key); + break; + default: + key_to_s = rb_convert_type(key, T_STRING, "String", "to_s"); + break; + } + + if (RB_LIKELY(RBASIC_CLASS(key_to_s) == rb_cString)) { + generate_json_string(buffer, data, key_to_s); } else { - key_to_s = rb_funcall(key, i_to_s, 0); + generate_json(buffer, data, key_to_s); } - Check_Type(key_to_s, T_STRING); - generate_json(buffer, Vstate, state, key_to_s); - fbuffer_append(buffer, delim2, delim2_len); - generate_json(buffer, Vstate, state, val); + if (RB_UNLIKELY(state->space_before)) fbuffer_append_str(buffer, data->state->space_before); + fbuffer_append_char(buffer, ':'); + if (RB_UNLIKELY(state->space)) fbuffer_append_str(buffer, data->state->space); + generate_json(buffer, data, val); arg->iter++; return ST_CONTINUE; } -static void generate_json_object(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj) +static inline long increase_depth(struct generate_json_data *data) { - char *object_nl = state->object_nl; - long object_nl_len = state->object_nl_len; - char *indent = state->indent; - long indent_len = state->indent_len; - long max_nesting = state->max_nesting; + JSON_Generator_State *state = data->state; long depth = ++state->depth; + if (RB_UNLIKELY(depth > state->max_nesting && state->max_nesting)) { + rb_raise(eNestingError, "nesting of %ld is too deep", --state->depth); + } + return depth; +} + +static void generate_json_object(FBuffer *buffer, struct generate_json_data *data, VALUE obj) +{ int j; - struct hash_foreach_arg arg; + long depth = increase_depth(data); - if (max_nesting != 0 && depth > max_nesting) { - fbuffer_free(buffer); - rb_raise(eNestingError, "nesting of %ld is too deep", --state->depth); + if (RHASH_SIZE(obj) == 0) { + fbuffer_append(buffer, "{}", 2); + --data->state->depth; + return; } + fbuffer_append_char(buffer, '{'); - arg.buffer = buffer; - arg.state = state; - arg.Vstate = Vstate; - arg.iter = 0; + struct hash_foreach_arg arg = { + .data = data, + .iter = 0, + }; rb_hash_foreach(obj, json_object_i, (VALUE)&arg); - depth = --state->depth; - if (object_nl) { - fbuffer_append(buffer, object_nl, object_nl_len); - if (indent) { + depth = --data->state->depth; + if (RB_UNLIKELY(data->state->object_nl)) { + fbuffer_append_str(buffer, data->state->object_nl); + if (RB_UNLIKELY(data->state->indent)) { for (j = 0; j < depth; j++) { - fbuffer_append(buffer, indent, indent_len); + fbuffer_append_str(buffer, data->state->indent); } } } fbuffer_append_char(buffer, '}'); } -static void generate_json_array(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj) +static void generate_json_array(FBuffer *buffer, struct generate_json_data *data, VALUE obj) { - char *array_nl = state->array_nl; - long array_nl_len = state->array_nl_len; - char *indent = state->indent; - long indent_len = state->indent_len; - long max_nesting = state->max_nesting; - char *delim = FBUFFER_PTR(state->array_delim); - long delim_len = FBUFFER_LEN(state->array_delim); - long depth = ++state->depth; int i, j; - if (max_nesting != 0 && depth > max_nesting) { - fbuffer_free(buffer); - rb_raise(eNestingError, "nesting of %ld is too deep", --state->depth); + long depth = increase_depth(data); + + if (RARRAY_LEN(obj) == 0) { + fbuffer_append(buffer, "[]", 2); + --data->state->depth; + return; } + fbuffer_append_char(buffer, '['); - if (array_nl) fbuffer_append(buffer, array_nl, array_nl_len); - for(i = 0; i < RARRAY_LEN(obj); i++) { - if (i > 0) fbuffer_append(buffer, delim, delim_len); - if (indent) { + if (RB_UNLIKELY(data->state->array_nl)) fbuffer_append_str(buffer, data->state->array_nl); + for (i = 0; i < RARRAY_LEN(obj); i++) { + if (i > 0) { + fbuffer_append_char(buffer, ','); + if (RB_UNLIKELY(data->state->array_nl)) fbuffer_append_str(buffer, data->state->array_nl); + } + if (RB_UNLIKELY(data->state->indent)) { for (j = 0; j < depth; j++) { - fbuffer_append(buffer, indent, indent_len); + fbuffer_append_str(buffer, data->state->indent); } } - generate_json(buffer, Vstate, state, rb_ary_entry(obj, i)); + generate_json(buffer, data, RARRAY_AREF(obj, i)); } - state->depth = --depth; - if (array_nl) { - fbuffer_append(buffer, array_nl, array_nl_len); - if (indent) { + data->state->depth = --depth; + if (RB_UNLIKELY(data->state->array_nl)) { + fbuffer_append_str(buffer, data->state->array_nl); + if (RB_UNLIKELY(data->state->indent)) { for (j = 0; j < depth; j++) { - fbuffer_append(buffer, indent, indent_len); + fbuffer_append_str(buffer, data->state->indent); } } } fbuffer_append_char(buffer, ']'); } -#ifdef HAVE_RUBY_ENCODING_H -static int enc_utf8_compatible_p(rb_encoding *enc) +static inline int enc_utf8_compatible_p(int enc_idx) { - if (enc == rb_usascii_encoding()) return 1; - if (enc == rb_utf8_encoding()) return 1; + if (enc_idx == usascii_encindex) return 1; + if (enc_idx == utf8_encindex) return 1; return 0; } -#endif -static void generate_json_string(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj) +static VALUE encode_json_string_try(VALUE str) { + return rb_funcall(str, i_encode, 1, Encoding_UTF_8); +} + +static VALUE encode_json_string_rescue(VALUE str, VALUE exception) +{ + raise_generator_error_str(str, rb_funcall(exception, rb_intern("message"), 0)); + return Qundef; +} + +static inline VALUE ensure_valid_encoding(VALUE str) +{ + int encindex = RB_ENCODING_GET(str); + VALUE utf8_string; + if (RB_UNLIKELY(!enc_utf8_compatible_p(encindex))) { + if (encindex == binary_encindex) { + utf8_string = rb_enc_associate_index(rb_str_dup(str), utf8_encindex); + switch (rb_enc_str_coderange(utf8_string)) { + case ENC_CODERANGE_7BIT: + return utf8_string; + case ENC_CODERANGE_VALID: + // For historical reason, we silently reinterpret binary strings as UTF-8 if it would work. + // TODO: Raise in 3.0.0 + rb_warn("JSON.generate: UTF-8 string passed as BINARY, this will raise an encoding error in json 3.0"); + return utf8_string; + break; + } + } + + str = rb_rescue(encode_json_string_try, str, encode_json_string_rescue, str); + } + return str; +} + +static void generate_json_string(FBuffer *buffer, struct generate_json_data *data, VALUE obj) +{ + obj = ensure_valid_encoding(obj); + fbuffer_append_char(buffer, '"'); -#ifdef HAVE_RUBY_ENCODING_H - if (!enc_utf8_compatible_p(rb_enc_get(obj))) { - obj = rb_str_export_to_enc(obj, rb_utf8_encoding()); + + long len; + search_state search; + search.buffer = buffer; + RSTRING_GETMEM(obj, search.ptr, len); + search.cursor = search.ptr; + search.end = search.ptr + len; + +#ifdef HAVE_SIMD + search.matches_mask = 0; + search.has_matches = false; + search.chunk_base = NULL; +#endif /* HAVE_SIMD */ + + switch (rb_enc_str_coderange(obj)) { + case ENC_CODERANGE_7BIT: + case ENC_CODERANGE_VALID: + if (RB_UNLIKELY(data->state->ascii_only)) { + convert_UTF8_to_ASCII_only_JSON(&search, data->state->script_safe ? script_safe_escape_table : ascii_only_escape_table); + } else if (RB_UNLIKELY(data->state->script_safe)) { + convert_UTF8_to_script_safe_JSON(&search); + } else { + convert_UTF8_to_JSON(&search); + } + break; + default: + raise_generator_error(obj, "source sequence is illegal/malformed utf-8"); + break; } -#endif - if (state->ascii_only) { - convert_UTF8_to_JSON_ASCII(buffer, obj, state->escape_slash); + fbuffer_append_char(buffer, '"'); +} + +static void generate_json_fallback(FBuffer *buffer, struct generate_json_data *data, VALUE obj) +{ + VALUE tmp; + if (rb_respond_to(obj, i_to_json)) { + tmp = rb_funcall(obj, i_to_json, 1, vstate_get(data)); + Check_Type(tmp, T_STRING); + fbuffer_append_str(buffer, tmp); } else { - convert_UTF8_to_JSON(buffer, obj, state->escape_slash); + tmp = rb_funcall(obj, i_to_s, 0); + Check_Type(tmp, T_STRING); + generate_json_string(buffer, data, tmp); } - fbuffer_append_char(buffer, '"'); } -static void generate_json_null(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj) +static inline void generate_json_symbol(FBuffer *buffer, struct generate_json_data *data, VALUE obj) +{ + if (data->state->strict) { + generate_json_string(buffer, data, rb_sym2str(obj)); + } else { + generate_json_fallback(buffer, data, obj); + } +} + +static void generate_json_null(FBuffer *buffer, struct generate_json_data *data, VALUE obj) { fbuffer_append(buffer, "null", 4); } -static void generate_json_false(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj) +static void generate_json_false(FBuffer *buffer, struct generate_json_data *data, VALUE obj) { fbuffer_append(buffer, "false", 5); } -static void generate_json_true(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj) +static void generate_json_true(FBuffer *buffer, struct generate_json_data *data, VALUE obj) { fbuffer_append(buffer, "true", 4); } -static void generate_json_fixnum(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj) +static void generate_json_fixnum(FBuffer *buffer, struct generate_json_data *data, VALUE obj) { fbuffer_append_long(buffer, FIX2LONG(obj)); } -static void generate_json_bignum(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj) +static void generate_json_bignum(FBuffer *buffer, struct generate_json_data *data, VALUE obj) { VALUE tmp = rb_funcall(obj, i_to_s, 0); fbuffer_append_str(buffer, tmp); } #ifdef RUBY_INTEGER_UNIFICATION -static void generate_json_integer(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj) +static void generate_json_integer(FBuffer *buffer, struct generate_json_data *data, VALUE obj) { if (FIXNUM_P(obj)) - generate_json_fixnum(buffer, Vstate, state, obj); + generate_json_fixnum(buffer, data, obj); else - generate_json_bignum(buffer, Vstate, state, obj); + generate_json_bignum(buffer, data, obj); } #endif -static void generate_json_float(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj) + +static void generate_json_float(FBuffer *buffer, struct generate_json_data *data, VALUE obj) { double value = RFLOAT_VALUE(obj); - char allow_nan = state->allow_nan; - VALUE tmp = rb_funcall(obj, i_to_s, 0); - if (!allow_nan) { - if (isinf(value)) { - fbuffer_free(buffer); - rb_raise(eGeneratorError, "%"PRIsVALUE" not allowed in JSON", RB_OBJ_STRING(tmp)); - } else if (isnan(value)) { - fbuffer_free(buffer); - rb_raise(eGeneratorError, "%"PRIsVALUE" not allowed in JSON", RB_OBJ_STRING(tmp)); + char allow_nan = data->state->allow_nan; + if (isinf(value) || isnan(value)) { + /* for NaN and Infinity values we either raise an error or rely on Float#to_s. */ + if (!allow_nan) { + if (data->state->strict && data->state->as_json) { + VALUE casted_obj = rb_proc_call_with_block(data->state->as_json, 1, &obj, Qnil); + if (casted_obj != obj) { + increase_depth(data); + generate_json(buffer, data, casted_obj); + data->state->depth--; + return; + } + } + raise_generator_error(obj, "%"PRIsVALUE" not allowed in JSON", rb_funcall(obj, i_to_s, 0)); } + + VALUE tmp = rb_funcall(obj, i_to_s, 0); + fbuffer_append_str(buffer, tmp); + return; } - fbuffer_append_str(buffer, tmp); + + /* This implementation writes directly into the buffer. We reserve + * the 28 characters that fpconv_dtoa states as its maximum. + */ + fbuffer_inc_capa(buffer, 28); + char* d = buffer->ptr + buffer->len; + int len = fpconv_dtoa(value, d); + + /* fpconv_dtoa converts a float to its shortest string representation, + * but it adds a ".0" if this is a plain integer. + */ + fbuffer_consumed(buffer, len); } -static void generate_json(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj) +static void generate_json_fragment(FBuffer *buffer, struct generate_json_data *data, VALUE obj) { - VALUE tmp; - VALUE klass = CLASS_OF(obj); - if (klass == rb_cHash) { - generate_json_object(buffer, Vstate, state, obj); - } else if (klass == rb_cArray) { - generate_json_array(buffer, Vstate, state, obj); - } else if (klass == rb_cString) { - generate_json_string(buffer, Vstate, state, obj); - } else if (obj == Qnil) { - generate_json_null(buffer, Vstate, state, obj); + VALUE fragment = RSTRUCT_GET(obj, 0); + Check_Type(fragment, T_STRING); + fbuffer_append_str(buffer, fragment); +} + +static void generate_json(FBuffer *buffer, struct generate_json_data *data, VALUE obj) +{ + bool as_json_called = false; +start: + if (obj == Qnil) { + generate_json_null(buffer, data, obj); } else if (obj == Qfalse) { - generate_json_false(buffer, Vstate, state, obj); + generate_json_false(buffer, data, obj); } else if (obj == Qtrue) { - generate_json_true(buffer, Vstate, state, obj); - } else if (FIXNUM_P(obj)) { - generate_json_fixnum(buffer, Vstate, state, obj); - } else if (RB_TYPE_P(obj, T_BIGNUM)) { - generate_json_bignum(buffer, Vstate, state, obj); - } else if (klass == rb_cFloat) { - generate_json_float(buffer, Vstate, state, obj); - } else if (rb_respond_to(obj, i_to_json)) { - tmp = rb_funcall(obj, i_to_json, 1, Vstate); - Check_Type(tmp, T_STRING); - fbuffer_append_str(buffer, tmp); + generate_json_true(buffer, data, obj); + } else if (RB_SPECIAL_CONST_P(obj)) { + if (RB_FIXNUM_P(obj)) { + generate_json_fixnum(buffer, data, obj); + } else if (RB_FLONUM_P(obj)) { + generate_json_float(buffer, data, obj); + } else if (RB_STATIC_SYM_P(obj)) { + generate_json_symbol(buffer, data, obj); + } else { + goto general; + } } else { - tmp = rb_funcall(obj, i_to_s, 0); - Check_Type(tmp, T_STRING); - generate_json_string(buffer, Vstate, state, tmp); + VALUE klass = RBASIC_CLASS(obj); + switch (RB_BUILTIN_TYPE(obj)) { + case T_BIGNUM: + generate_json_bignum(buffer, data, obj); + break; + case T_HASH: + if (klass != rb_cHash) goto general; + generate_json_object(buffer, data, obj); + break; + case T_ARRAY: + if (klass != rb_cArray) goto general; + generate_json_array(buffer, data, obj); + break; + case T_STRING: + if (klass != rb_cString) goto general; + generate_json_string(buffer, data, obj); + break; + case T_SYMBOL: + generate_json_symbol(buffer, data, obj); + break; + case T_FLOAT: + if (klass != rb_cFloat) goto general; + generate_json_float(buffer, data, obj); + break; + case T_STRUCT: + if (klass != cFragment) goto general; + generate_json_fragment(buffer, data, obj); + break; + default: + general: + if (data->state->strict) { + if (RTEST(data->state->as_json) && !as_json_called) { + obj = rb_proc_call_with_block(data->state->as_json, 1, &obj, Qnil); + as_json_called = true; + goto start; + } else { + raise_generator_error(obj, "%"PRIsVALUE" not allowed in JSON", CLASS_OF(obj)); + } + } else { + generate_json_fallback(buffer, data, obj); + } + } } } -static FBuffer *cState_prepare_buffer(VALUE self) +static VALUE generate_json_try(VALUE d) { - FBuffer *buffer; - GET_STATE(self); - buffer = fbuffer_alloc(state->buffer_initial_length); + struct generate_json_data *data = (struct generate_json_data *)d; - if (state->object_delim) { - fbuffer_clear(state->object_delim); - } else { - state->object_delim = fbuffer_alloc(16); - } - fbuffer_append_char(state->object_delim, ','); - if (state->object_delim2) { - fbuffer_clear(state->object_delim2); - } else { - state->object_delim2 = fbuffer_alloc(16); - } - if (state->space_before) fbuffer_append(state->object_delim2, state->space_before, state->space_before_len); - fbuffer_append_char(state->object_delim2, ':'); - if (state->space) fbuffer_append(state->object_delim2, state->space, state->space_len); + data->func(data->buffer, data, data->obj); - if (state->array_delim) { - fbuffer_clear(state->array_delim); - } else { - state->array_delim = fbuffer_alloc(16); - } - fbuffer_append_char(state->array_delim, ','); - if (state->array_nl) fbuffer_append(state->array_delim, state->array_nl, state->array_nl_len); - return buffer; + return Qnil; } -static VALUE cState_partial_generate(VALUE self, VALUE obj) +static VALUE generate_json_rescue(VALUE d, VALUE exc) +{ + struct generate_json_data *data = (struct generate_json_data *)d; + fbuffer_free(data->buffer); + + rb_exc_raise(exc); + + return Qundef; +} + +static VALUE cState_partial_generate(VALUE self, VALUE obj, generator_func func, VALUE io) { - FBuffer *buffer = cState_prepare_buffer(self); GET_STATE(self); - generate_json(buffer, self, state, obj); - return fbuffer_to_s(buffer); + + char stack_buffer[FBUFFER_STACK_SIZE]; + FBuffer buffer = { + .io = RTEST(io) ? io : Qfalse, + }; + fbuffer_stack_init(&buffer, state->buffer_initial_length, stack_buffer, FBUFFER_STACK_SIZE); + + struct generate_json_data data = { + .buffer = &buffer, + .vstate = self, + .state = state, + .obj = obj, + .func = func + }; + rb_rescue(generate_json_try, (VALUE)&data, generate_json_rescue, (VALUE)&data); + + return fbuffer_finalize(&buffer); } -/* - * call-seq: generate(obj) +/* call-seq: + * generate(obj) -> String + * generate(obj, anIO) -> anIO * * Generates a valid JSON document from object +obj+ and returns the * result. If no valid JSON document can be created this method raises a * GeneratorError exception. */ -static VALUE cState_generate(VALUE self, VALUE obj) +static VALUE cState_generate(int argc, VALUE *argv, VALUE self) { - VALUE result = cState_partial_generate(self, obj); + rb_check_arity(argc, 1, 2); + VALUE obj = argv[0]; + VALUE io = argc > 1 ? argv[1] : Qnil; + VALUE result = cState_partial_generate(self, obj, generate_json, io); GET_STATE(self); (void)state; return result; } -/* - * call-seq: new(opts = {}) - * - * Instantiates a new State object, configured by _opts_. - * - * _opts_ can have the following keys: - * - * * *indent*: a string used to indent levels (default: ''), - * * *space*: a string that is put after, a : or , delimiter (default: ''), - * * *space_before*: a string that is put before a : pair delimiter (default: ''), - * * *object_nl*: a string that is put at the end of a JSON object (default: ''), - * * *array_nl*: a string that is put at the end of a JSON array (default: ''), - * * *allow_nan*: true if NaN, Infinity, and -Infinity should be - * generated, otherwise an exception is thrown, if these values are - * encountered. This options defaults to false. - * * *ascii_only*: true if only ASCII characters should be generated. This - * option defaults to false. - * * *buffer_initial_length*: sets the initial length of the generator's - * internal buffer. - */ static VALUE cState_initialize(int argc, VALUE *argv, VALUE self) { - VALUE opts; - GET_STATE(self); - state->max_nesting = 100; - state->buffer_initial_length = FBUFFER_INITIAL_LENGTH_DEFAULT; - rb_scan_args(argc, argv, "01", &opts); - if (!NIL_P(opts)) cState_configure(self, opts); + rb_warn("The json gem extension was loaded with the stdlib ruby code. You should upgrade rubygems with `gem update --system`"); return self; } @@ -1141,14 +1524,12 @@ static VALUE cState_init_copy(VALUE obj, VALUE orig) if (!objState) rb_raise(rb_eArgError, "unallocated JSON::State"); MEMCPY(objState, origState, JSON_Generator_State, 1); - objState->indent = fstrndup(origState->indent, origState->indent_len); - objState->space = fstrndup(origState->space, origState->space_len); - objState->space_before = fstrndup(origState->space_before, origState->space_before_len); - objState->object_nl = fstrndup(origState->object_nl, origState->object_nl_len); - objState->array_nl = fstrndup(origState->array_nl, origState->array_nl_len); - if (origState->array_delim) objState->array_delim = fbuffer_dup(origState->array_delim); - if (origState->object_delim) objState->object_delim = fbuffer_dup(origState->object_delim); - if (origState->object_delim2) objState->object_delim2 = fbuffer_dup(origState->object_delim2); + objState->indent = origState->indent; + objState->space = origState->space; + objState->space_before = origState->space_before; + objState->object_nl = origState->object_nl; + objState->array_nl = origState->array_nl; + objState->as_json = origState->as_json; return obj; } @@ -1178,7 +1559,18 @@ static VALUE cState_from_state_s(VALUE self, VALUE opts) static VALUE cState_indent(VALUE self) { GET_STATE(self); - return state->indent ? rb_str_new(state->indent, state->indent_len) : rb_str_new2(""); + return state->indent ? state->indent : rb_str_freeze(rb_utf8_str_new("", 0)); +} + +static VALUE string_config(VALUE config) +{ + if (RTEST(config)) { + Check_Type(config, T_STRING); + if (RSTRING_LEN(config)) { + return rb_str_new_frozen(config); + } + } + return Qfalse; } /* @@ -1188,21 +1580,8 @@ static VALUE cState_indent(VALUE self) */ static VALUE cState_indent_set(VALUE self, VALUE indent) { - unsigned long len; GET_STATE(self); - Check_Type(indent, T_STRING); - len = RSTRING_LEN(indent); - if (len == 0) { - if (state->indent) { - ruby_xfree(state->indent); - state->indent = NULL; - state->indent_len = 0; - } - } else { - if (state->indent) ruby_xfree(state->indent); - state->indent = fstrndup(RSTRING_PTR(indent), len); - state->indent_len = len; - } + RB_OBJ_WRITE(self, &state->indent, string_config(indent)); return Qnil; } @@ -1215,7 +1594,7 @@ static VALUE cState_indent_set(VALUE self, VALUE indent) static VALUE cState_space(VALUE self) { GET_STATE(self); - return state->space ? rb_str_new(state->space, state->space_len) : rb_str_new2(""); + return state->space ? state->space : rb_str_freeze(rb_utf8_str_new("", 0)); } /* @@ -1226,21 +1605,8 @@ static VALUE cState_space(VALUE self) */ static VALUE cState_space_set(VALUE self, VALUE space) { - unsigned long len; GET_STATE(self); - Check_Type(space, T_STRING); - len = RSTRING_LEN(space); - if (len == 0) { - if (state->space) { - ruby_xfree(state->space); - state->space = NULL; - state->space_len = 0; - } - } else { - if (state->space) ruby_xfree(state->space); - state->space = fstrndup(RSTRING_PTR(space), len); - state->space_len = len; - } + RB_OBJ_WRITE(self, &state->space, string_config(space)); return Qnil; } @@ -1252,7 +1618,7 @@ static VALUE cState_space_set(VALUE self, VALUE space) static VALUE cState_space_before(VALUE self) { GET_STATE(self); - return state->space_before ? rb_str_new(state->space_before, state->space_before_len) : rb_str_new2(""); + return state->space_before ? state->space_before : rb_str_freeze(rb_utf8_str_new("", 0)); } /* @@ -1262,21 +1628,8 @@ static VALUE cState_space_before(VALUE self) */ static VALUE cState_space_before_set(VALUE self, VALUE space_before) { - unsigned long len; GET_STATE(self); - Check_Type(space_before, T_STRING); - len = RSTRING_LEN(space_before); - if (len == 0) { - if (state->space_before) { - ruby_xfree(state->space_before); - state->space_before = NULL; - state->space_before_len = 0; - } - } else { - if (state->space_before) ruby_xfree(state->space_before); - state->space_before = fstrndup(RSTRING_PTR(space_before), len); - state->space_before_len = len; - } + RB_OBJ_WRITE(self, &state->space_before, string_config(space_before)); return Qnil; } @@ -1289,7 +1642,7 @@ static VALUE cState_space_before_set(VALUE self, VALUE space_before) static VALUE cState_object_nl(VALUE self) { GET_STATE(self); - return state->object_nl ? rb_str_new(state->object_nl, state->object_nl_len) : rb_str_new2(""); + return state->object_nl ? state->object_nl : rb_str_freeze(rb_utf8_str_new("", 0)); } /* @@ -1300,20 +1653,8 @@ static VALUE cState_object_nl(VALUE self) */ static VALUE cState_object_nl_set(VALUE self, VALUE object_nl) { - unsigned long len; GET_STATE(self); - Check_Type(object_nl, T_STRING); - len = RSTRING_LEN(object_nl); - if (len == 0) { - if (state->object_nl) { - ruby_xfree(state->object_nl); - state->object_nl = NULL; - } - } else { - if (state->object_nl) ruby_xfree(state->object_nl); - state->object_nl = fstrndup(RSTRING_PTR(object_nl), len); - state->object_nl_len = len; - } + RB_OBJ_WRITE(self, &state->object_nl, string_config(object_nl)); return Qnil; } @@ -1325,7 +1666,7 @@ static VALUE cState_object_nl_set(VALUE self, VALUE object_nl) static VALUE cState_array_nl(VALUE self) { GET_STATE(self); - return state->array_nl ? rb_str_new(state->array_nl, state->array_nl_len) : rb_str_new2(""); + return state->array_nl ? state->array_nl : rb_str_freeze(rb_utf8_str_new("", 0)); } /* @@ -1335,23 +1676,33 @@ static VALUE cState_array_nl(VALUE self) */ static VALUE cState_array_nl_set(VALUE self, VALUE array_nl) { - unsigned long len; GET_STATE(self); - Check_Type(array_nl, T_STRING); - len = RSTRING_LEN(array_nl); - if (len == 0) { - if (state->array_nl) { - ruby_xfree(state->array_nl); - state->array_nl = NULL; - } - } else { - if (state->array_nl) ruby_xfree(state->array_nl); - state->array_nl = fstrndup(RSTRING_PTR(array_nl), len); - state->array_nl_len = len; - } + RB_OBJ_WRITE(self, &state->array_nl, string_config(array_nl)); return Qnil; } +/* + * call-seq: as_json() + * + * This string is put at the end of a line that holds a JSON array. + */ +static VALUE cState_as_json(VALUE self) +{ + GET_STATE(self); + return state->as_json; +} + +/* + * call-seq: as_json=(as_json) + * + * This string is put at the end of a line that holds a JSON array. + */ +static VALUE cState_as_json_set(VALUE self, VALUE as_json) +{ + GET_STATE(self); + RB_OBJ_WRITE(self, &state->as_json, rb_convert_type(as_json, T_DATA, "Proc", "to_proc")); + return Qnil; +} /* * call-seq: check_circular? @@ -1377,6 +1728,11 @@ static VALUE cState_max_nesting(VALUE self) return LONG2FIX(state->max_nesting); } +static long long_config(VALUE num) +{ + return RTEST(num) ? FIX2LONG(num) : 0; +} + /* * call-seq: max_nesting=(depth) * @@ -1386,32 +1742,63 @@ static VALUE cState_max_nesting(VALUE self) static VALUE cState_max_nesting_set(VALUE self, VALUE depth) { GET_STATE(self); - Check_Type(depth, T_FIXNUM); - return state->max_nesting = FIX2LONG(depth); + state->max_nesting = long_config(depth); + return Qnil; } /* - * call-seq: escape_slash + * call-seq: script_safe * * If this boolean is true, the forward slashes will be escaped in * the json output. */ -static VALUE cState_escape_slash(VALUE self) +static VALUE cState_script_safe(VALUE self) { GET_STATE(self); - return state->escape_slash ? Qtrue : Qfalse; + return state->script_safe ? Qtrue : Qfalse; } /* - * call-seq: escape_slash=(depth) + * call-seq: script_safe=(enable) * * This sets whether or not the forward slashes will be escaped in * the json output. */ -static VALUE cState_escape_slash_set(VALUE self, VALUE enable) +static VALUE cState_script_safe_set(VALUE self, VALUE enable) { GET_STATE(self); - state->escape_slash = RTEST(enable); + state->script_safe = RTEST(enable); + return Qnil; +} + +/* + * call-seq: strict + * + * If this boolean is false, types unsupported by the JSON format will + * be serialized as strings. + * If this boolean is true, types unsupported by the JSON format will + * raise a JSON::GeneratorError. + */ +static VALUE cState_strict(VALUE self) +{ + GET_STATE(self); + return state->strict ? Qtrue : Qfalse; +} + +/* + * call-seq: strict=(enable) + * + * This sets whether or not to serialize types unsupported by the + * JSON format as strings. + * If this boolean is false, types unsupported by the JSON format will + * be serialized as strings. + * If this boolean is true, types unsupported by the JSON format will + * raise a JSON::GeneratorError. + */ +static VALUE cState_strict_set(VALUE self, VALUE enable) +{ + GET_STATE(self); + state->strict = RTEST(enable); return Qnil; } @@ -1427,6 +1814,18 @@ static VALUE cState_allow_nan_p(VALUE self) return state->allow_nan ? Qtrue : Qfalse; } +/* + * call-seq: allow_nan=(enable) + * + * This sets whether or not to serialize NaN, Infinity, and -Infinity + */ +static VALUE cState_allow_nan_set(VALUE self, VALUE enable) +{ + GET_STATE(self); + state->allow_nan = RTEST(enable); + return Qnil; +} + /* * call-seq: ascii_only? * @@ -1439,6 +1838,18 @@ static VALUE cState_ascii_only_p(VALUE self) return state->ascii_only ? Qtrue : Qfalse; } +/* + * call-seq: ascii_only=(enable) + * + * This sets whether only ASCII characters should be generated. + */ +static VALUE cState_ascii_only_set(VALUE self, VALUE enable) +{ + GET_STATE(self); + state->ascii_only = RTEST(enable); + return Qnil; +} + /* * call-seq: depth * @@ -1459,8 +1870,7 @@ static VALUE cState_depth(VALUE self) static VALUE cState_depth_set(VALUE self, VALUE depth) { GET_STATE(self); - Check_Type(depth, T_FIXNUM); - state->depth = FIX2LONG(depth); + state->depth = long_config(depth); return Qnil; } @@ -1475,6 +1885,15 @@ static VALUE cState_buffer_initial_length(VALUE self) return LONG2FIX(state->buffer_initial_length); } +static void buffer_initial_length_set(JSON_Generator_State *state, VALUE buffer_initial_length) +{ + Check_Type(buffer_initial_length, T_FIXNUM); + long initial_length = FIX2LONG(buffer_initial_length); + if (initial_length > 0) { + state->buffer_initial_length = initial_length; + } +} + /* * call-seq: buffer_initial_length=(length) * @@ -1483,16 +1902,76 @@ static VALUE cState_buffer_initial_length(VALUE self) */ static VALUE cState_buffer_initial_length_set(VALUE self, VALUE buffer_initial_length) { - long initial_length; GET_STATE(self); - Check_Type(buffer_initial_length, T_FIXNUM); - initial_length = FIX2LONG(buffer_initial_length); - if (initial_length > 0) { - state->buffer_initial_length = initial_length; - } + buffer_initial_length_set(state, buffer_initial_length); return Qnil; } +static int configure_state_i(VALUE key, VALUE val, VALUE _arg) +{ + JSON_Generator_State *state = (JSON_Generator_State *)_arg; + + if (key == sym_indent) { state->indent = string_config(val); } + else if (key == sym_space) { state->space = string_config(val); } + else if (key == sym_space_before) { state->space_before = string_config(val); } + else if (key == sym_object_nl) { state->object_nl = string_config(val); } + else if (key == sym_array_nl) { state->array_nl = string_config(val); } + else if (key == sym_max_nesting) { state->max_nesting = long_config(val); } + else if (key == sym_allow_nan) { state->allow_nan = RTEST(val); } + else if (key == sym_ascii_only) { state->ascii_only = RTEST(val); } + else if (key == sym_depth) { state->depth = long_config(val); } + else if (key == sym_buffer_initial_length) { buffer_initial_length_set(state, val); } + else if (key == sym_script_safe) { state->script_safe = RTEST(val); } + else if (key == sym_escape_slash) { state->script_safe = RTEST(val); } + else if (key == sym_strict) { state->strict = RTEST(val); } + else if (key == sym_as_json) { state->as_json = RTEST(val) ? rb_convert_type(val, T_DATA, "Proc", "to_proc") : Qfalse; } + return ST_CONTINUE; +} + +static void configure_state(JSON_Generator_State *state, VALUE config) +{ + if (!RTEST(config)) return; + + Check_Type(config, T_HASH); + + if (!RHASH_SIZE(config)) return; + + // We assume in most cases few keys are set so it's faster to go over + // the provided keys than to check all possible keys. + rb_hash_foreach(config, configure_state_i, (VALUE)state); +} + +static VALUE cState_configure(VALUE self, VALUE opts) +{ + GET_STATE(self); + configure_state(state, opts); + return self; +} + +static VALUE cState_m_generate(VALUE klass, VALUE obj, VALUE opts, VALUE io) +{ + JSON_Generator_State state = {0}; + state_init(&state); + configure_state(&state, opts); + + char stack_buffer[FBUFFER_STACK_SIZE]; + FBuffer buffer = { + .io = RTEST(io) ? io : Qfalse, + }; + fbuffer_stack_init(&buffer, state.buffer_initial_length, stack_buffer, FBUFFER_STACK_SIZE); + + struct generate_json_data data = { + .buffer = &buffer, + .vstate = Qfalse, + .state = &state, + .obj = obj, + .func = generate_json, + }; + rb_rescue(generate_json_try, (VALUE)&data, generate_json_rescue, (VALUE)&data); + + return fbuffer_finalize(&buffer); +} + /* * */ @@ -1506,18 +1985,26 @@ void Init_generator(void) rb_require("json/common"); mJSON = rb_define_module("JSON"); - mExt = rb_define_module_under(mJSON, "Ext"); - mGenerator = rb_define_module_under(mExt, "Generator"); + rb_global_variable(&cFragment); + cFragment = rb_const_get(mJSON, rb_intern("Fragment")); + + VALUE mExt = rb_define_module_under(mJSON, "Ext"); + VALUE mGenerator = rb_define_module_under(mExt, "Generator"); + + rb_global_variable(&eGeneratorError); eGeneratorError = rb_path2class("JSON::GeneratorError"); + + rb_global_variable(&eNestingError); eNestingError = rb_path2class("JSON::NestingError"); - rb_gc_register_mark_object(eGeneratorError); - rb_gc_register_mark_object(eNestingError); cState = rb_define_class_under(mGenerator, "State", rb_cObject); rb_define_alloc_func(cState, cState_s_allocate); rb_define_singleton_method(cState, "from_state", cState_from_state_s, 1); rb_define_method(cState, "initialize", cState_initialize, -1); + rb_define_alias(cState, "initialize", "initialize"); // avoid method redefinition warnings + rb_define_private_method(cState, "_configure", cState_configure, 1); + rb_define_method(cState, "initialize_copy", cState_init_copy, 1); rb_define_method(cState, "indent", cState_indent, 0); rb_define_method(cState, "indent=", cState_indent_set, 1); @@ -1529,81 +2016,124 @@ void Init_generator(void) rb_define_method(cState, "object_nl=", cState_object_nl_set, 1); rb_define_method(cState, "array_nl", cState_array_nl, 0); rb_define_method(cState, "array_nl=", cState_array_nl_set, 1); + rb_define_method(cState, "as_json", cState_as_json, 0); + rb_define_method(cState, "as_json=", cState_as_json_set, 1); rb_define_method(cState, "max_nesting", cState_max_nesting, 0); rb_define_method(cState, "max_nesting=", cState_max_nesting_set, 1); - rb_define_method(cState, "escape_slash", cState_escape_slash, 0); - rb_define_method(cState, "escape_slash?", cState_escape_slash, 0); - rb_define_method(cState, "escape_slash=", cState_escape_slash_set, 1); + rb_define_method(cState, "script_safe", cState_script_safe, 0); + rb_define_method(cState, "script_safe?", cState_script_safe, 0); + rb_define_method(cState, "script_safe=", cState_script_safe_set, 1); + rb_define_alias(cState, "escape_slash", "script_safe"); + rb_define_alias(cState, "escape_slash?", "script_safe?"); + rb_define_alias(cState, "escape_slash=", "script_safe="); + rb_define_method(cState, "strict", cState_strict, 0); + rb_define_method(cState, "strict?", cState_strict, 0); + rb_define_method(cState, "strict=", cState_strict_set, 1); rb_define_method(cState, "check_circular?", cState_check_circular_p, 0); rb_define_method(cState, "allow_nan?", cState_allow_nan_p, 0); + rb_define_method(cState, "allow_nan=", cState_allow_nan_set, 1); rb_define_method(cState, "ascii_only?", cState_ascii_only_p, 0); + rb_define_method(cState, "ascii_only=", cState_ascii_only_set, 1); rb_define_method(cState, "depth", cState_depth, 0); rb_define_method(cState, "depth=", cState_depth_set, 1); rb_define_method(cState, "buffer_initial_length", cState_buffer_initial_length, 0); rb_define_method(cState, "buffer_initial_length=", cState_buffer_initial_length_set, 1); - rb_define_method(cState, "configure", cState_configure, 1); - rb_define_alias(cState, "merge", "configure"); - rb_define_method(cState, "to_h", cState_to_h, 0); - rb_define_alias(cState, "to_hash", "to_h"); - rb_define_method(cState, "[]", cState_aref, 1); - rb_define_method(cState, "[]=", cState_aset, 2); - rb_define_method(cState, "generate", cState_generate, 1); - - mGeneratorMethods = rb_define_module_under(mGenerator, "GeneratorMethods"); - mObject = rb_define_module_under(mGeneratorMethods, "Object"); + rb_define_method(cState, "generate", cState_generate, -1); + rb_define_alias(cState, "generate_new", "generate"); // :nodoc: + + rb_define_singleton_method(cState, "generate", cState_m_generate, 3); + + VALUE mGeneratorMethods = rb_define_module_under(mGenerator, "GeneratorMethods"); + + VALUE mObject = rb_define_module_under(mGeneratorMethods, "Object"); rb_define_method(mObject, "to_json", mObject_to_json, -1); - mHash = rb_define_module_under(mGeneratorMethods, "Hash"); + + VALUE mHash = rb_define_module_under(mGeneratorMethods, "Hash"); rb_define_method(mHash, "to_json", mHash_to_json, -1); - mArray = rb_define_module_under(mGeneratorMethods, "Array"); + + VALUE mArray = rb_define_module_under(mGeneratorMethods, "Array"); rb_define_method(mArray, "to_json", mArray_to_json, -1); + #ifdef RUBY_INTEGER_UNIFICATION - mInteger = rb_define_module_under(mGeneratorMethods, "Integer"); + VALUE mInteger = rb_define_module_under(mGeneratorMethods, "Integer"); rb_define_method(mInteger, "to_json", mInteger_to_json, -1); #else - mFixnum = rb_define_module_under(mGeneratorMethods, "Fixnum"); + VALUE mFixnum = rb_define_module_under(mGeneratorMethods, "Fixnum"); rb_define_method(mFixnum, "to_json", mFixnum_to_json, -1); - mBignum = rb_define_module_under(mGeneratorMethods, "Bignum"); + + VALUE mBignum = rb_define_module_under(mGeneratorMethods, "Bignum"); rb_define_method(mBignum, "to_json", mBignum_to_json, -1); #endif - mFloat = rb_define_module_under(mGeneratorMethods, "Float"); + VALUE mFloat = rb_define_module_under(mGeneratorMethods, "Float"); rb_define_method(mFloat, "to_json", mFloat_to_json, -1); - mString = rb_define_module_under(mGeneratorMethods, "String"); + + VALUE mString = rb_define_module_under(mGeneratorMethods, "String"); rb_define_singleton_method(mString, "included", mString_included_s, 1); rb_define_method(mString, "to_json", mString_to_json, -1); rb_define_method(mString, "to_json_raw", mString_to_json_raw, -1); rb_define_method(mString, "to_json_raw_object", mString_to_json_raw_object, 0); + mString_Extend = rb_define_module_under(mString, "Extend"); rb_define_method(mString_Extend, "json_create", mString_Extend_json_create, 1); - mTrueClass = rb_define_module_under(mGeneratorMethods, "TrueClass"); + + VALUE mTrueClass = rb_define_module_under(mGeneratorMethods, "TrueClass"); rb_define_method(mTrueClass, "to_json", mTrueClass_to_json, -1); - mFalseClass = rb_define_module_under(mGeneratorMethods, "FalseClass"); + + VALUE mFalseClass = rb_define_module_under(mGeneratorMethods, "FalseClass"); rb_define_method(mFalseClass, "to_json", mFalseClass_to_json, -1); - mNilClass = rb_define_module_under(mGeneratorMethods, "NilClass"); + + VALUE mNilClass = rb_define_module_under(mGeneratorMethods, "NilClass"); rb_define_method(mNilClass, "to_json", mNilClass_to_json, -1); + rb_global_variable(&Encoding_UTF_8); + Encoding_UTF_8 = rb_const_get(rb_path2class("Encoding"), rb_intern("UTF_8")); + i_to_s = rb_intern("to_s"); i_to_json = rb_intern("to_json"); i_new = rb_intern("new"); - i_indent = rb_intern("indent"); - i_space = rb_intern("space"); - i_space_before = rb_intern("space_before"); - i_object_nl = rb_intern("object_nl"); - i_array_nl = rb_intern("array_nl"); - i_max_nesting = rb_intern("max_nesting"); - i_escape_slash = rb_intern("escape_slash"); - i_allow_nan = rb_intern("allow_nan"); - i_ascii_only = rb_intern("ascii_only"); - i_depth = rb_intern("depth"); - i_buffer_initial_length = rb_intern("buffer_initial_length"); i_pack = rb_intern("pack"); i_unpack = rb_intern("unpack"); i_create_id = rb_intern("create_id"); i_extend = rb_intern("extend"); - i_key_p = rb_intern("key?"); - i_aref = rb_intern("[]"); - i_send = rb_intern("__send__"); - i_respond_to_p = rb_intern("respond_to?"); - i_match = rb_intern("match"); - i_keys = rb_intern("keys"); - i_dup = rb_intern("dup"); + i_encode = rb_intern("encode"); + + sym_indent = ID2SYM(rb_intern("indent")); + sym_space = ID2SYM(rb_intern("space")); + sym_space_before = ID2SYM(rb_intern("space_before")); + sym_object_nl = ID2SYM(rb_intern("object_nl")); + sym_array_nl = ID2SYM(rb_intern("array_nl")); + sym_max_nesting = ID2SYM(rb_intern("max_nesting")); + sym_allow_nan = ID2SYM(rb_intern("allow_nan")); + sym_ascii_only = ID2SYM(rb_intern("ascii_only")); + sym_depth = ID2SYM(rb_intern("depth")); + sym_buffer_initial_length = ID2SYM(rb_intern("buffer_initial_length")); + sym_script_safe = ID2SYM(rb_intern("script_safe")); + sym_escape_slash = ID2SYM(rb_intern("escape_slash")); + sym_strict = ID2SYM(rb_intern("strict")); + sym_as_json = ID2SYM(rb_intern("as_json")); + + usascii_encindex = rb_usascii_encindex(); + utf8_encindex = rb_utf8_encindex(); + binary_encindex = rb_ascii8bit_encindex(); + + rb_require("json/ext/generator/state"); + + + switch (find_simd_implementation()) { +#ifdef HAVE_SIMD +#ifdef HAVE_SIMD_NEON + case SIMD_NEON: + search_escape_basic_impl = search_escape_basic_neon; + break; +#endif /* HAVE_SIMD_NEON */ +#ifdef HAVE_SIMD_SSE2 + case SIMD_SSE2: + search_escape_basic_impl = search_escape_basic_sse2; + break; +#endif /* HAVE_SIMD_SSE2 */ +#endif /* HAVE_SIMD */ + default: + search_escape_basic_impl = search_escape_basic; + break; + } } diff --git a/ext/json/generator/generator.h b/ext/json/generator/generator.h deleted file mode 100644 index 3ebd622554e69a..00000000000000 --- a/ext/json/generator/generator.h +++ /dev/null @@ -1,174 +0,0 @@ -#ifndef _GENERATOR_H_ -#define _GENERATOR_H_ - -#include -#include - -#include "ruby.h" - -#ifdef HAVE_RUBY_RE_H -#include "ruby/re.h" -#else -#include "re.h" -#endif - -#ifndef rb_intern_str -#define rb_intern_str(string) SYM2ID(rb_str_intern(string)) -#endif - -#ifndef rb_obj_instance_variables -#define rb_obj_instance_variables(object) rb_funcall(object, rb_intern("instance_variables"), 0) -#endif - -#define option_given_p(opts, key) RTEST(rb_funcall(opts, i_key_p, 1, key)) - -/* unicode definitions */ - -#define UNI_STRICT_CONVERSION 1 - -typedef unsigned long UTF32; /* at least 32 bits */ -typedef unsigned short UTF16; /* at least 16 bits */ -typedef unsigned char UTF8; /* typically 8 bits */ - -#define UNI_REPLACEMENT_CHAR (UTF32)0x0000FFFD -#define UNI_MAX_BMP (UTF32)0x0000FFFF -#define UNI_MAX_UTF16 (UTF32)0x0010FFFF -#define UNI_MAX_UTF32 (UTF32)0x7FFFFFFF -#define UNI_MAX_LEGAL_UTF32 (UTF32)0x0010FFFF - -#define UNI_SUR_HIGH_START (UTF32)0xD800 -#define UNI_SUR_HIGH_END (UTF32)0xDBFF -#define UNI_SUR_LOW_START (UTF32)0xDC00 -#define UNI_SUR_LOW_END (UTF32)0xDFFF - -static const int halfShift = 10; /* used for shifting by 10 bits */ - -static const UTF32 halfBase = 0x0010000UL; -static const UTF32 halfMask = 0x3FFUL; - -static unsigned char isLegalUTF8(const UTF8 *source, unsigned long length); -static void unicode_escape(char *buf, UTF16 character); -static void unicode_escape_to_buffer(FBuffer *buffer, char buf[6], UTF16 character); -static void convert_UTF8_to_JSON_ASCII(FBuffer *buffer, VALUE string, char escape_slash); -static void convert_UTF8_to_JSON(FBuffer *buffer, VALUE string, char escape_slash); -static char *fstrndup(const char *ptr, unsigned long len); - -/* ruby api and some helpers */ - -typedef struct JSON_Generator_StateStruct { - char *indent; - long indent_len; - char *space; - long space_len; - char *space_before; - long space_before_len; - char *object_nl; - long object_nl_len; - char *array_nl; - long array_nl_len; - FBuffer *array_delim; - FBuffer *object_delim; - FBuffer *object_delim2; - long max_nesting; - char allow_nan; - char ascii_only; - char escape_slash; - long depth; - long buffer_initial_length; -} JSON_Generator_State; - -#define GET_STATE_TO(self, state) \ - TypedData_Get_Struct(self, JSON_Generator_State, &JSON_Generator_State_type, state) - -#define GET_STATE(self) \ - JSON_Generator_State *state; \ - GET_STATE_TO(self, state) - -#define GENERATE_JSON(type) \ - FBuffer *buffer; \ - VALUE Vstate; \ - JSON_Generator_State *state; \ - \ - rb_scan_args(argc, argv, "01", &Vstate); \ - Vstate = cState_from_state_s(cState, Vstate); \ - TypedData_Get_Struct(Vstate, JSON_Generator_State, &JSON_Generator_State_type, state); \ - buffer = cState_prepare_buffer(Vstate); \ - generate_json_##type(buffer, Vstate, state, self); \ - return fbuffer_to_s(buffer) - -static VALUE mHash_to_json(int argc, VALUE *argv, VALUE self); -static VALUE mArray_to_json(int argc, VALUE *argv, VALUE self); -#ifdef RUBY_INTEGER_UNIFICATION -static VALUE mInteger_to_json(int argc, VALUE *argv, VALUE self); -#else -static VALUE mFixnum_to_json(int argc, VALUE *argv, VALUE self); -static VALUE mBignum_to_json(int argc, VALUE *argv, VALUE self); -#endif -static VALUE mFloat_to_json(int argc, VALUE *argv, VALUE self); -static VALUE mString_included_s(VALUE self, VALUE modul); -static VALUE mString_to_json(int argc, VALUE *argv, VALUE self); -static VALUE mString_to_json_raw_object(VALUE self); -static VALUE mString_to_json_raw(int argc, VALUE *argv, VALUE self); -static VALUE mString_Extend_json_create(VALUE self, VALUE o); -static VALUE mTrueClass_to_json(int argc, VALUE *argv, VALUE self); -static VALUE mFalseClass_to_json(int argc, VALUE *argv, VALUE self); -static VALUE mNilClass_to_json(int argc, VALUE *argv, VALUE self); -static VALUE mObject_to_json(int argc, VALUE *argv, VALUE self); -static void State_free(void *state); -static VALUE cState_s_allocate(VALUE klass); -static VALUE cState_configure(VALUE self, VALUE opts); -static VALUE cState_to_h(VALUE self); -static void generate_json(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj); -static void generate_json_object(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj); -static void generate_json_array(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj); -static void generate_json_string(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj); -static void generate_json_null(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj); -static void generate_json_false(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj); -static void generate_json_true(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj); -#ifdef RUBY_INTEGER_UNIFICATION -static void generate_json_integer(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj); -#endif -static void generate_json_fixnum(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj); -static void generate_json_bignum(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj); -static void generate_json_float(FBuffer *buffer, VALUE Vstate, JSON_Generator_State *state, VALUE obj); -static VALUE cState_partial_generate(VALUE self, VALUE obj); -static VALUE cState_generate(VALUE self, VALUE obj); -static VALUE cState_initialize(int argc, VALUE *argv, VALUE self); -static VALUE cState_from_state_s(VALUE self, VALUE opts); -static VALUE cState_indent(VALUE self); -static VALUE cState_indent_set(VALUE self, VALUE indent); -static VALUE cState_space(VALUE self); -static VALUE cState_space_set(VALUE self, VALUE space); -static VALUE cState_space_before(VALUE self); -static VALUE cState_space_before_set(VALUE self, VALUE space_before); -static VALUE cState_object_nl(VALUE self); -static VALUE cState_object_nl_set(VALUE self, VALUE object_nl); -static VALUE cState_array_nl(VALUE self); -static VALUE cState_array_nl_set(VALUE self, VALUE array_nl); -static VALUE cState_max_nesting(VALUE self); -static VALUE cState_max_nesting_set(VALUE self, VALUE depth); -static VALUE cState_allow_nan_p(VALUE self); -static VALUE cState_ascii_only_p(VALUE self); -static VALUE cState_depth(VALUE self); -static VALUE cState_depth_set(VALUE self, VALUE depth); -static VALUE cState_escape_slash(VALUE self); -static VALUE cState_escape_slash_set(VALUE self, VALUE depth); -static FBuffer *cState_prepare_buffer(VALUE self); -#ifndef ZALLOC -#define ZALLOC(type) ((type *)ruby_zalloc(sizeof(type))) -static inline void *ruby_zalloc(size_t n) -{ - void *p = ruby_xmalloc(n); - memset(p, 0, n); - return p; -} -#endif -#ifdef TypedData_Make_Struct -static const rb_data_type_t JSON_Generator_State_type; -#define NEW_TYPEDDATA_WRAPPER 1 -#else -#define TypedData_Make_Struct(klass, type, ignore, json) Data_Make_Struct(klass, type, NULL, State_free, json) -#define TypedData_Get_Struct(self, JSON_Generator_State, ignore, json) Data_Get_Struct(self, JSON_Generator_State, json) -#endif - -#endif diff --git a/ext/json/json.gemspec b/ext/json/json.gemspec index f4b2ae791dabbe..55757310250dae 100644 --- a/ext/json/json.gemspec +++ b/ext/json/json.gemspec @@ -1,67 +1,62 @@ -# -*- encoding: utf-8 -*- +# frozen_string_literal: true + +version = File.foreach(File.join(__dir__, "lib/json/version.rb")) do |line| + /^\s*VERSION\s*=\s*'(.*)'/ =~ line and break $1 +end rescue nil + +spec = Gem::Specification.new do |s| + java_ext = Gem::Platform === s.platform && s.platform =~ 'java' || RUBY_ENGINE == 'jruby' -Gem::Specification.new do |s| s.name = "json" - s.version = File.read(File.expand_path('../VERSION', __FILE__)).chomp + s.version = version s.summary = "JSON Implementation for Ruby" - s.description = "This is a JSON implementation as a Ruby extension in C." + s.homepage = "https://github.com/ruby/json" + s.metadata = { + 'bug_tracker_uri' => 'https://github.com/ruby/json/issues', + 'changelog_uri' => 'https://github.com/ruby/json/blob/master/CHANGES.md', + 'documentation_uri' => 'https://docs.ruby-lang.org/en/master/JSON.html', + 'homepage_uri' => s.homepage, + 'source_code_uri' => 'https://github.com/ruby/json', + } + + s.required_ruby_version = Gem::Requirement.new(">= 2.7") + + if java_ext + s.description = "A JSON implementation as a JRuby extension." + s.author = "Daniel Luz" + s.email = "dev+ruby@mernen.com" + else + s.description = "This is a JSON implementation as a Ruby extension in C." + s.authors = ["Florian Frank"] + s.email = "flori@ping.de" + end + s.licenses = ["Ruby"] - s.authors = ["Florian Frank"] - s.email = "flori@ping.de" - s.extensions = ["ext/json/ext/generator/extconf.rb", "ext/json/ext/parser/extconf.rb", "ext/json/extconf.rb"] s.extra_rdoc_files = ["README.md"] s.rdoc_options = ["--title", "JSON implementation for Ruby", "--main", "README.md"] + s.files = [ "CHANGES.md", - "LICENSE", + "COPYING", + "BSDL", + "LEGAL", "README.md", - "VERSION", - "ext/json/ext/fbuffer/fbuffer.h", - "ext/json/ext/generator/depend", - "ext/json/ext/generator/extconf.rb", - "ext/json/ext/generator/generator.c", - "ext/json/ext/generator/generator.h", - "ext/json/ext/parser/depend", - "ext/json/ext/parser/extconf.rb", - "ext/json/ext/parser/parser.c", - "ext/json/ext/parser/parser.h", - "ext/json/ext/parser/parser.rl", - "ext/json/extconf.rb", "json.gemspec", - "lib/json.rb", - "lib/json/add/bigdecimal.rb", - "lib/json/add/complex.rb", - "lib/json/add/core.rb", - "lib/json/add/date.rb", - "lib/json/add/date_time.rb", - "lib/json/add/exception.rb", - "lib/json/add/ostruct.rb", - "lib/json/add/range.rb", - "lib/json/add/rational.rb", - "lib/json/add/regexp.rb", - "lib/json/add/set.rb", - "lib/json/add/struct.rb", - "lib/json/add/symbol.rb", - "lib/json/add/time.rb", - "lib/json/common.rb", - "lib/json/ext.rb", - "lib/json/generic_object.rb", - "lib/json/pure.rb", - "lib/json/pure/generator.rb", - "lib/json/pure/parser.rb", - "lib/json/version.rb", - ] - s.homepage = "https://flori.github.io/json" - s.metadata = { - 'bug_tracker_uri' => 'https://github.com/flori/json/issues', - 'changelog_uri' => 'https://github.com/flori/json/blob/master/CHANGES.md', - 'documentation_uri' => 'https://flori.github.io/json/doc/index.html', - 'homepage_uri' => s.homepage, - 'source_code_uri' => 'https://github.com/flori/json', - 'wiki_uri' => 'https://github.com/flori/json/wiki' - } + ] + Dir.glob("lib/**/*.rb", base: File.expand_path("..", __FILE__)) + + if java_ext + s.platform = 'java' + s.files += Dir["lib/json/ext/**/*.jar"] + else + s.extensions = Dir["ext/json/**/extconf.rb"] + s.files += Dir["ext/json/**/*.{c,h,rb}"] + end +end - s.required_ruby_version = Gem::Requirement.new(">= 2.3") +if RUBY_ENGINE == 'jruby' && $0 == __FILE__ + Gem::Builder.new(spec).build +else + spec end diff --git a/ext/json/lib/json.rb b/ext/json/lib/json.rb index 1e64bfcb1ac824..735f2380667daa 100644 --- a/ext/json/lib/json.rb +++ b/ext/json/lib/json.rb @@ -1,4 +1,4 @@ -#frozen_string_literal: false +# frozen_string_literal: true require 'json/common' ## @@ -127,6 +127,24 @@ # # --- # +# Option +allow_duplicate_key+ specifies whether duplicate keys in objects +# should be ignored or cause an error to be raised: +# +# When not specified: +# # The last value is used and a deprecation warning emitted. +# JSON.parse('{"a": 1, "a":2}') => {"a" => 2} +# # waring: detected duplicate keys in JSON object. +# # This will raise an error in json 3.0 unless enabled via `allow_duplicate_key: true` +# +# When set to `+true+` +# # The last value is used. +# JSON.parse('{"a": 1, "a":2}') => {"a" => 2} +# +# When set to `+false+`, the future default: +# JSON.parse('{"a": 1, "a":2}') => duplicate key at line 1 column 1 (JSON::ParserError) +# +# --- +# # Option +allow_nan+ (boolean) specifies whether to allow # NaN, Infinity, and MinusInfinity in +source+; # defaults to +false+. @@ -143,8 +161,23 @@ # ruby = JSON.parse(source, {allow_nan: true}) # ruby # => [NaN, Infinity, -Infinity] # +# --- +# +# Option +allow_trailing_comma+ (boolean) specifies whether to allow +# trailing commas in objects and arrays; +# defaults to +false+. +# +# With the default, +false+: +# JSON.parse('[1,]') # unexpected character: ']' at line 1 column 4 (JSON::ParserError) +# +# When enabled: +# JSON.parse('[1,]', allow_trailing_comma: true) # => [1] +# # ====== Output Options # +# Option +freeze+ (boolean) specifies whether the returned objects will be frozen; +# defaults to +false+. +# # Option +symbolize_names+ (boolean) specifies whether returned \Hash keys # should be Symbols; # defaults to +false+ (use Strings). @@ -285,6 +318,15 @@ # # Raises JSON::NestingError (nesting of 2 is too deep): # JSON.generate(obj, max_nesting: 2) # +# ====== Escaping Options +# +# Options +script_safe+ (boolean) specifies wether '\u2028', '\u2029' +# and '/' should be escaped as to make the JSON object safe to interpolate in script +# tags. +# +# Options +ascii_only+ (boolean) specifies wether all characters outside the ASCII range +# should be escaped. +# # ====== Output Options # # The default formatting options generate the most compact @@ -369,13 +411,13 @@ # json1 = JSON.generate(ruby) # ruby1 = JSON.parse(json1, create_additions: true) # # Make a nice display. -# display = <BigDecimal#as_json and +BigDecimal.json_create+ may be used + # to serialize and deserialize a \BigDecimal object; + # see Marshal[rdoc-ref:Marshal]. + # + # \Method BigDecimal#as_json serializes +self+, + # returning a 2-element hash representing +self+: + # + # require 'json/add/bigdecimal' + # x = BigDecimal(2).as_json # => {"json_class"=>"BigDecimal", "b"=>"27:0.2e1"} + # y = BigDecimal(2.0, 4).as_json # => {"json_class"=>"BigDecimal", "b"=>"36:0.2e1"} + # z = BigDecimal(Complex(2, 0)).as_json # => {"json_class"=>"BigDecimal", "b"=>"27:0.2e1"} + # + # \Method +JSON.create+ deserializes such a hash, returning a \BigDecimal object: + # + # BigDecimal.json_create(x) # => 0.2e1 + # BigDecimal.json_create(y) # => 0.2e1 + # BigDecimal.json_create(z) # => 0.2e1 # - # method used for JSON marshalling support. def as_json(*) { JSON.create_id => self.class.name, - 'b' => _dump, + 'b' => _dump.force_encoding(Encoding::UTF_8), } end - # return the JSON value + # Returns a JSON string representing +self+: + # + # require 'json/add/bigdecimal' + # puts BigDecimal(2).to_json + # puts BigDecimal(2.0, 4).to_json + # puts BigDecimal(Complex(2, 0)).to_json + # + # Output: + # + # {"json_class":"BigDecimal","b":"27:0.2e1"} + # {"json_class":"BigDecimal","b":"36:0.2e1"} + # {"json_class":"BigDecimal","b":"27:0.2e1"} + # def to_json(*args) as_json.to_json(*args) end diff --git a/ext/json/lib/json/add/complex.rb b/ext/json/lib/json/add/complex.rb index e63e29fd22663d..9e3c6f2d0aa85b 100644 --- a/ext/json/lib/json/add/complex.rb +++ b/ext/json/lib/json/add/complex.rb @@ -1,18 +1,31 @@ -#frozen_string_literal: false +# frozen_string_literal: true unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED require 'json' end class Complex - # Deserializes JSON string by converting Real value r, imaginary - # value i, to a Complex object. + # See #as_json. def self.json_create(object) Complex(object['r'], object['i']) end - # Returns a hash, that will be turned into a JSON object and represent this - # object. + # Methods Complex#as_json and +Complex.json_create+ may be used + # to serialize and deserialize a \Complex object; + # see Marshal[rdoc-ref:Marshal]. + # + # \Method Complex#as_json serializes +self+, + # returning a 2-element hash representing +self+: + # + # require 'json/add/complex' + # x = Complex(2).as_json # => {"json_class"=>"Complex", "r"=>2, "i"=>0} + # y = Complex(2.0, 4).as_json # => {"json_class"=>"Complex", "r"=>2.0, "i"=>4} + # + # \Method +JSON.create+ deserializes such a hash, returning a \Complex object: + # + # Complex.json_create(x) # => (2+0i) + # Complex.json_create(y) # => (2.0+4i) + # def as_json(*) { JSON.create_id => self.class.name, @@ -21,7 +34,17 @@ def as_json(*) } end - # Stores class name (Complex) along with real value r and imaginary value i as JSON string + # Returns a JSON string representing +self+: + # + # require 'json/add/complex' + # puts Complex(2).to_json + # puts Complex(2.0, 4).to_json + # + # Output: + # + # {"json_class":"Complex","r":2,"i":0} + # {"json_class":"Complex","r":2.0,"i":4} + # def to_json(*args) as_json.to_json(*args) end diff --git a/ext/json/lib/json/add/core.rb b/ext/json/lib/json/add/core.rb index bfb017c46082bd..485f097fff4317 100644 --- a/ext/json/lib/json/add/core.rb +++ b/ext/json/lib/json/add/core.rb @@ -1,4 +1,4 @@ -#frozen_string_literal: false +# frozen_string_literal: true # This file requires the implementations of ruby core's custom objects for # serialisation/deserialisation. diff --git a/ext/json/lib/json/add/date.rb b/ext/json/lib/json/add/date.rb index 25523561a52a11..88a098b6379775 100644 --- a/ext/json/lib/json/add/date.rb +++ b/ext/json/lib/json/add/date.rb @@ -1,4 +1,4 @@ -#frozen_string_literal: false +# frozen_string_literal: true unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED require 'json' end @@ -6,16 +6,29 @@ class Date - # Deserializes JSON string by converting Julian year y, month - # m, day d and Day of Calendar Reform sg to Date. + # See #as_json. def self.json_create(object) civil(*object.values_at('y', 'm', 'd', 'sg')) end alias start sg unless method_defined?(:start) - # Returns a hash, that will be turned into a JSON object and represent this - # object. + # Methods Date#as_json and +Date.json_create+ may be used + # to serialize and deserialize a \Date object; + # see Marshal[rdoc-ref:Marshal]. + # + # \Method Date#as_json serializes +self+, + # returning a 2-element hash representing +self+: + # + # require 'json/add/date' + # x = Date.today.as_json + # # => {"json_class"=>"Date", "y"=>2023, "m"=>11, "d"=>21, "sg"=>2299161.0} + # + # \Method +JSON.create+ deserializes such a hash, returning a \Date object: + # + # Date.json_create(x) + # # => # + # def as_json(*) { JSON.create_id => self.class.name, @@ -26,8 +39,15 @@ def as_json(*) } end - # Stores class name (Date) with Julian year y, month m, day - # d and Day of Calendar Reform sg as JSON string + # Returns a JSON string representing +self+: + # + # require 'json/add/date' + # puts Date.today.to_json + # + # Output: + # + # {"json_class":"Date","y":2023,"m":11,"d":21,"sg":2299161.0} + # def to_json(*args) as_json.to_json(*args) end diff --git a/ext/json/lib/json/add/date_time.rb b/ext/json/lib/json/add/date_time.rb index 38b0e86ab8fa13..8b0bb5d181d0c8 100644 --- a/ext/json/lib/json/add/date_time.rb +++ b/ext/json/lib/json/add/date_time.rb @@ -1,4 +1,4 @@ -#frozen_string_literal: false +# frozen_string_literal: true unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED require 'json' end @@ -6,9 +6,7 @@ class DateTime - # Deserializes JSON string by converting year y, month m, - # day d, hour H, minute M, second S, - # offset of and Day of Calendar Reform sg to DateTime. + # See #as_json. def self.json_create(object) args = object.values_at('y', 'm', 'd', 'H', 'M', 'S') of_a, of_b = object['of'].split('/') @@ -23,8 +21,21 @@ def self.json_create(object) alias start sg unless method_defined?(:start) - # Returns a hash, that will be turned into a JSON object and represent this - # object. + # Methods DateTime#as_json and +DateTime.json_create+ may be used + # to serialize and deserialize a \DateTime object; + # see Marshal[rdoc-ref:Marshal]. + # + # \Method DateTime#as_json serializes +self+, + # returning a 2-element hash representing +self+: + # + # require 'json/add/datetime' + # x = DateTime.now.as_json + # # => {"json_class"=>"DateTime", "y"=>2023, "m"=>11, "d"=>21, "sg"=>2299161.0} + # + # \Method +JSON.create+ deserializes such a hash, returning a \DateTime object: + # + # DateTime.json_create(x) # BUG? Raises Date::Error "invalid date" + # def as_json(*) { JSON.create_id => self.class.name, @@ -39,9 +50,15 @@ def as_json(*) } end - # Stores class name (DateTime) with Julian year y, month m, - # day d, hour H, minute M, second S, - # offset of and Day of Calendar Reform sg as JSON string + # Returns a JSON string representing +self+: + # + # require 'json/add/datetime' + # puts DateTime.now.to_json + # + # Output: + # + # {"json_class":"DateTime","y":2023,"m":11,"d":21,"sg":2299161.0} + # def to_json(*args) as_json.to_json(*args) end diff --git a/ext/json/lib/json/add/exception.rb b/ext/json/lib/json/add/exception.rb index a107e5b3c4789c..e85d404982f2a8 100644 --- a/ext/json/lib/json/add/exception.rb +++ b/ext/json/lib/json/add/exception.rb @@ -1,20 +1,31 @@ -#frozen_string_literal: false +# frozen_string_literal: true unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED require 'json' end class Exception - # Deserializes JSON string by constructing new Exception object with message - # m and backtrace b serialized with to_json + # See #as_json. def self.json_create(object) result = new(object['m']) result.set_backtrace object['b'] result end - # Returns a hash, that will be turned into a JSON object and represent this - # object. + # Methods Exception#as_json and +Exception.json_create+ may be used + # to serialize and deserialize a \Exception object; + # see Marshal[rdoc-ref:Marshal]. + # + # \Method Exception#as_json serializes +self+, + # returning a 2-element hash representing +self+: + # + # require 'json/add/exception' + # x = Exception.new('Foo').as_json # => {"json_class"=>"Exception", "m"=>"Foo", "b"=>nil} + # + # \Method +JSON.create+ deserializes such a hash, returning a \Exception object: + # + # Exception.json_create(x) # => # + # def as_json(*) { JSON.create_id => self.class.name, @@ -23,8 +34,15 @@ def as_json(*) } end - # Stores class name (Exception) with message m and backtrace array - # b as JSON string + # Returns a JSON string representing +self+: + # + # require 'json/add/exception' + # puts Exception.new('Foo').to_json + # + # Output: + # + # {"json_class":"Exception","m":"Foo","b":null} + # def to_json(*args) as_json.to_json(*args) end diff --git a/ext/json/lib/json/add/ostruct.rb b/ext/json/lib/json/add/ostruct.rb index 686cf0025d4616..7750498144d75c 100644 --- a/ext/json/lib/json/add/ostruct.rb +++ b/ext/json/lib/json/add/ostruct.rb @@ -1,19 +1,35 @@ -#frozen_string_literal: false +# frozen_string_literal: true unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED require 'json' end -require 'ostruct' +begin + require 'ostruct' +rescue LoadError +end class OpenStruct - # Deserializes JSON string by constructing new Struct object with values - # t serialized by to_json. + # See #as_json. def self.json_create(object) new(object['t'] || object[:t]) end - # Returns a hash, that will be turned into a JSON object and represent this - # object. + # Methods OpenStruct#as_json and +OpenStruct.json_create+ may be used + # to serialize and deserialize a \OpenStruct object; + # see Marshal[rdoc-ref:Marshal]. + # + # \Method OpenStruct#as_json serializes +self+, + # returning a 2-element hash representing +self+: + # + # require 'json/add/ostruct' + # x = OpenStruct.new('name' => 'Rowdy', :age => nil).as_json + # # => {"json_class"=>"OpenStruct", "t"=>{:name=>'Rowdy', :age=>nil}} + # + # \Method +JSON.create+ deserializes such a hash, returning a \OpenStruct object: + # + # OpenStruct.json_create(x) + # # => # + # def as_json(*) klass = self.class.name klass.to_s.empty? and raise JSON::JSONError, "Only named structs are supported!" @@ -23,9 +39,16 @@ def as_json(*) } end - # Stores class name (OpenStruct) with this struct's values t as a - # JSON string. + # Returns a JSON string representing +self+: + # + # require 'json/add/ostruct' + # puts OpenStruct.new('name' => 'Rowdy', :age => nil).to_json + # + # Output: + # + # {"json_class":"OpenStruct","t":{'name':'Rowdy',"age":null}} + # def to_json(*args) as_json.to_json(*args) end -end +end if defined?(::OpenStruct) diff --git a/ext/json/lib/json/add/range.rb b/ext/json/lib/json/add/range.rb index 93529fb1c4eb95..408d2c32f6fb66 100644 --- a/ext/json/lib/json/add/range.rb +++ b/ext/json/lib/json/add/range.rb @@ -1,18 +1,33 @@ -#frozen_string_literal: false +# frozen_string_literal: true unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED require 'json' end class Range - # Deserializes JSON string by constructing new Range object with arguments - # a serialized by to_json. + # See #as_json. def self.json_create(object) new(*object['a']) end - # Returns a hash, that will be turned into a JSON object and represent this - # object. + # Methods Range#as_json and +Range.json_create+ may be used + # to serialize and deserialize a \Range object; + # see Marshal[rdoc-ref:Marshal]. + # + # \Method Range#as_json serializes +self+, + # returning a 2-element hash representing +self+: + # + # require 'json/add/range' + # x = (1..4).as_json # => {"json_class"=>"Range", "a"=>[1, 4, false]} + # y = (1...4).as_json # => {"json_class"=>"Range", "a"=>[1, 4, true]} + # z = ('a'..'d').as_json # => {"json_class"=>"Range", "a"=>["a", "d", false]} + # + # \Method +JSON.create+ deserializes such a hash, returning a \Range object: + # + # Range.json_create(x) # => 1..4 + # Range.json_create(y) # => 1...4 + # Range.json_create(z) # => "a".."d" + # def as_json(*) { JSON.create_id => self.class.name, @@ -20,9 +35,19 @@ def as_json(*) } end - # Stores class name (Range) with JSON array of arguments a which - # include first (integer), last (integer), and - # exclude_end? (boolean) as JSON string. + # Returns a JSON string representing +self+: + # + # require 'json/add/range' + # puts (1..4).to_json + # puts (1...4).to_json + # puts ('a'..'d').to_json + # + # Output: + # + # {"json_class":"Range","a":[1,4,false]} + # {"json_class":"Range","a":[1,4,true]} + # {"json_class":"Range","a":["a","d",false]} + # def to_json(*args) as_json.to_json(*args) end diff --git a/ext/json/lib/json/add/rational.rb b/ext/json/lib/json/add/rational.rb index f77622604678e3..c95812ea8eea01 100644 --- a/ext/json/lib/json/add/rational.rb +++ b/ext/json/lib/json/add/rational.rb @@ -1,17 +1,31 @@ -#frozen_string_literal: false +# frozen_string_literal: true unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED require 'json' end class Rational - # Deserializes JSON string by converting numerator value n, - # denominator value d, to a Rational object. + + # See #as_json. def self.json_create(object) Rational(object['n'], object['d']) end - # Returns a hash, that will be turned into a JSON object and represent this - # object. + # Methods Rational#as_json and +Rational.json_create+ may be used + # to serialize and deserialize a \Rational object; + # see Marshal[rdoc-ref:Marshal]. + # + # \Method Rational#as_json serializes +self+, + # returning a 2-element hash representing +self+: + # + # require 'json/add/rational' + # x = Rational(2, 3).as_json + # # => {"json_class"=>"Rational", "n"=>2, "d"=>3} + # + # \Method +JSON.create+ deserializes such a hash, returning a \Rational object: + # + # Rational.json_create(x) + # # => (2/3) + # def as_json(*) { JSON.create_id => self.class.name, @@ -20,7 +34,15 @@ def as_json(*) } end - # Stores class name (Rational) along with numerator value n and denominator value d as JSON string + # Returns a JSON string representing +self+: + # + # require 'json/add/rational' + # puts Rational(2, 3).to_json + # + # Output: + # + # {"json_class":"Rational","n":2,"d":3} + # def to_json(*args) as_json.to_json(*args) end diff --git a/ext/json/lib/json/add/regexp.rb b/ext/json/lib/json/add/regexp.rb index 39d69fede7b070..aebfb2db5cb807 100644 --- a/ext/json/lib/json/add/regexp.rb +++ b/ext/json/lib/json/add/regexp.rb @@ -1,19 +1,30 @@ -#frozen_string_literal: false +# frozen_string_literal: true unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED require 'json' end class Regexp - # Deserializes JSON string by constructing new Regexp object with source - # s (Regexp or String) and options o serialized by - # to_json + # See #as_json. def self.json_create(object) new(object['s'], object['o']) end - # Returns a hash, that will be turned into a JSON object and represent this - # object. + # Methods Regexp#as_json and +Regexp.json_create+ may be used + # to serialize and deserialize a \Regexp object; + # see Marshal[rdoc-ref:Marshal]. + # + # \Method Regexp#as_json serializes +self+, + # returning a 2-element hash representing +self+: + # + # require 'json/add/regexp' + # x = /foo/.as_json + # # => {"json_class"=>"Regexp", "o"=>0, "s"=>"foo"} + # + # \Method +JSON.create+ deserializes such a hash, returning a \Regexp object: + # + # Regexp.json_create(x) # => /foo/ + # def as_json(*) { JSON.create_id => self.class.name, @@ -22,8 +33,15 @@ def as_json(*) } end - # Stores class name (Regexp) with options o and source s - # (Regexp or String) as JSON string + # Returns a JSON string representing +self+: + # + # require 'json/add/regexp' + # puts /foo/.to_json + # + # Output: + # + # {"json_class":"Regexp","o":0,"s":"foo"} + # def to_json(*args) as_json.to_json(*args) end diff --git a/ext/json/lib/json/add/set.rb b/ext/json/lib/json/add/set.rb index 71e2a0ac8b75fe..19183531874015 100644 --- a/ext/json/lib/json/add/set.rb +++ b/ext/json/lib/json/add/set.rb @@ -4,16 +4,27 @@ defined?(::Set) or require 'set' class Set - # Import a JSON Marshalled object. - # - # method used for JSON marshalling support. + + # See #as_json. def self.json_create(object) new object['a'] end - # Marshal the object to JSON. + # Methods Set#as_json and +Set.json_create+ may be used + # to serialize and deserialize a \Set object; + # see Marshal[rdoc-ref:Marshal]. + # + # \Method Set#as_json serializes +self+, + # returning a 2-element hash representing +self+: + # + # require 'json/add/set' + # x = Set.new(%w/foo bar baz/).as_json + # # => {"json_class"=>"Set", "a"=>["foo", "bar", "baz"]} + # + # \Method +JSON.create+ deserializes such a hash, returning a \Set object: + # + # Set.json_create(x) # => # # - # method used for JSON marshalling support. def as_json(*) { JSON.create_id => self.class.name, @@ -21,7 +32,15 @@ def as_json(*) } end - # return the JSON value + # Returns a JSON string representing +self+: + # + # require 'json/add/set' + # puts Set.new(%w/foo bar baz/).to_json + # + # Output: + # + # {"json_class":"Set","a":["foo","bar","baz"]} + # def to_json(*args) as_json.to_json(*args) end diff --git a/ext/json/lib/json/add/struct.rb b/ext/json/lib/json/add/struct.rb index e8395ed42f0361..6760c3d86c0b6b 100644 --- a/ext/json/lib/json/add/struct.rb +++ b/ext/json/lib/json/add/struct.rb @@ -1,18 +1,32 @@ -#frozen_string_literal: false +# frozen_string_literal: true unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED require 'json' end class Struct - # Deserializes JSON string by constructing new Struct object with values - # v serialized by to_json. + # See #as_json. def self.json_create(object) new(*object['v']) end - # Returns a hash, that will be turned into a JSON object and represent this - # object. + # Methods Struct#as_json and +Struct.json_create+ may be used + # to serialize and deserialize a \Struct object; + # see Marshal[rdoc-ref:Marshal]. + # + # \Method Struct#as_json serializes +self+, + # returning a 2-element hash representing +self+: + # + # require 'json/add/struct' + # Customer = Struct.new('Customer', :name, :address, :zip) + # x = Struct::Customer.new.as_json + # # => {"json_class"=>"Struct::Customer", "v"=>[nil, nil, nil]} + # + # \Method +JSON.create+ deserializes such a hash, returning a \Struct object: + # + # Struct::Customer.json_create(x) + # # => # + # def as_json(*) klass = self.class.name klass.to_s.empty? and raise JSON::JSONError, "Only named structs are supported!" @@ -22,8 +36,16 @@ def as_json(*) } end - # Stores class name (Struct) with Struct values v as a JSON string. - # Only named structs are supported. + # Returns a JSON string representing +self+: + # + # require 'json/add/struct' + # Customer = Struct.new('Customer', :name, :address, :zip) + # puts Struct::Customer.new.to_json + # + # Output: + # + # {"json_class":"Struct","t":{'name':'Rowdy',"age":null}} + # def to_json(*args) as_json.to_json(*args) end diff --git a/ext/json/lib/json/add/symbol.rb b/ext/json/lib/json/add/symbol.rb index 74b13a423f3c09..806be4f025f0fd 100644 --- a/ext/json/lib/json/add/symbol.rb +++ b/ext/json/lib/json/add/symbol.rb @@ -1,11 +1,25 @@ -#frozen_string_literal: false +# frozen_string_literal: true unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED require 'json' end class Symbol - # Returns a hash, that will be turned into a JSON object and represent this - # object. + + # Methods Symbol#as_json and +Symbol.json_create+ may be used + # to serialize and deserialize a \Symbol object; + # see Marshal[rdoc-ref:Marshal]. + # + # \Method Symbol#as_json serializes +self+, + # returning a 2-element hash representing +self+: + # + # require 'json/add/symbol' + # x = :foo.as_json + # # => {"json_class"=>"Symbol", "s"=>"foo"} + # + # \Method +JSON.create+ deserializes such a hash, returning a \Symbol object: + # + # Symbol.json_create(x) # => :foo + # def as_json(*) { JSON.create_id => self.class.name, @@ -13,12 +27,25 @@ def as_json(*) } end - # Stores class name (Symbol) with String representation of Symbol as a JSON string. - def to_json(*a) - as_json.to_json(*a) + # Returns a JSON string representing +self+: + # + # require 'json/add/symbol' + # puts :foo.to_json + # + # Output: + # + # # {"json_class":"Symbol","s":"foo"} + # + def to_json(state = nil, *a) + state = ::JSON::State.from_state(state) + if state.strict? + super + else + as_json.to_json(state, *a) + end end - # Deserializes JSON string by converting the string value stored in the object to a Symbol + # See #as_json. def self.json_create(o) o['s'].to_sym end diff --git a/ext/json/lib/json/add/time.rb b/ext/json/lib/json/add/time.rb index b73acc4086c32b..b03d4ff2516ffa 100644 --- a/ext/json/lib/json/add/time.rb +++ b/ext/json/lib/json/add/time.rb @@ -1,37 +1,51 @@ -#frozen_string_literal: false +# frozen_string_literal: true unless defined?(::JSON::JSON_LOADED) and ::JSON::JSON_LOADED require 'json' end class Time - # Deserializes JSON string by converting time since epoch to Time + # See #as_json. def self.json_create(object) if usec = object.delete('u') # used to be tv_usec -> tv_nsec object['n'] = usec * 1000 end - if method_defined?(:tv_nsec) - at(object['s'], Rational(object['n'], 1000)) - else - at(object['s'], object['n'] / 1000) - end + at(object['s'], Rational(object['n'], 1000)) end - # Returns a hash, that will be turned into a JSON object and represent this - # object. + # Methods Time#as_json and +Time.json_create+ may be used + # to serialize and deserialize a \Time object; + # see Marshal[rdoc-ref:Marshal]. + # + # \Method Time#as_json serializes +self+, + # returning a 2-element hash representing +self+: + # + # require 'json/add/time' + # x = Time.now.as_json + # # => {"json_class"=>"Time", "s"=>1700931656, "n"=>472846644} + # + # \Method +JSON.create+ deserializes such a hash, returning a \Time object: + # + # Time.json_create(x) + # # => 2023-11-25 11:00:56.472846644 -0600 + # def as_json(*) - nanoseconds = [ tv_usec * 1000 ] - respond_to?(:tv_nsec) and nanoseconds << tv_nsec - nanoseconds = nanoseconds.max { JSON.create_id => self.class.name, 's' => tv_sec, - 'n' => nanoseconds, + 'n' => tv_nsec, } end - # Stores class name (Time) with number of seconds since epoch and number of - # microseconds for Time as JSON string + # Returns a JSON string representing +self+: + # + # require 'json/add/time' + # puts Time.now.to_json + # + # Output: + # + # {"json_class":"Time","s":1700931678,"n":980650786} + # def to_json(*args) as_json.to_json(*args) end diff --git a/ext/json/lib/json/common.rb b/ext/json/lib/json/common.rb index 173af04be038ed..486ec62a582450 100644 --- a/ext/json/lib/json/common.rb +++ b/ext/json/lib/json/common.rb @@ -1,8 +1,116 @@ -#frozen_string_literal: false +# frozen_string_literal: true + require 'json/version' -require 'json/generic_object' module JSON + autoload :GenericObject, 'json/generic_object' + + module ParserOptions # :nodoc: + class << self + def prepare(opts) + if opts[:object_class] || opts[:array_class] + opts = opts.dup + on_load = opts[:on_load] + + on_load = object_class_proc(opts[:object_class], on_load) if opts[:object_class] + on_load = array_class_proc(opts[:array_class], on_load) if opts[:array_class] + opts[:on_load] = on_load + end + + if opts.fetch(:create_additions, false) != false + opts = create_additions_proc(opts) + end + + opts + end + + private + + def object_class_proc(object_class, on_load) + ->(obj) do + if Hash === obj + object = object_class.new + obj.each { |k, v| object[k] = v } + obj = object + end + on_load.nil? ? obj : on_load.call(obj) + end + end + + def array_class_proc(array_class, on_load) + ->(obj) do + if Array === obj + array = array_class.new + obj.each { |v| array << v } + obj = array + end + on_load.nil? ? obj : on_load.call(obj) + end + end + + # TODO: exctract :create_additions support to another gem for version 3.0 + def create_additions_proc(opts) + if opts[:symbolize_names] + raise ArgumentError, "options :symbolize_names and :create_additions cannot be used in conjunction" + end + + opts = opts.dup + create_additions = opts.fetch(:create_additions, false) + on_load = opts[:on_load] + object_class = opts[:object_class] || Hash + + opts[:on_load] = ->(object) do + case object + when String + opts[:match_string]&.each do |pattern, klass| + if match = pattern.match(object) + create_additions_warning if create_additions.nil? + object = klass.json_create(object) + break + end + end + when object_class + if opts[:create_additions] != false + if class_name = object[JSON.create_id] + klass = JSON.deep_const_get(class_name) + if (klass.respond_to?(:json_creatable?) && klass.json_creatable?) || klass.respond_to?(:json_create) + create_additions_warning if create_additions.nil? + object = klass.json_create(object) + end + end + end + end + + on_load.nil? ? object : on_load.call(object) + end + + opts + end + + GEM_ROOT = File.expand_path("../../../", __FILE__) + "/" + def create_additions_warning + message = "JSON.load implicit support for `create_additions: true` is deprecated " \ + "and will be removed in 3.0, use JSON.unsafe_load or explicitly " \ + "pass `create_additions: true`" + + uplevel = 4 + caller_locations(uplevel, 10).each do |frame| + if frame.path.nil? || frame.path.start_with?(GEM_ROOT) || frame.path.end_with?("/truffle/cext_ruby.rb", ".c") + uplevel += 1 + else + break + end + end + + if RUBY_VERSION >= "3.0" + warn(message, uplevel: uplevel - 1, category: :deprecated) + else + warn(message, uplevel: uplevel - 1) + end + end + end + end + class << self # :call-seq: # JSON[object] -> new_array or new_string @@ -15,17 +123,20 @@ class << self # Otherwise, calls JSON.generate with +object+ and +opts+ (see method #generate): # ruby = [0, 1, nil] # JSON[ruby] # => '[0,1,null]' - def [](object, opts = {}) - if object.respond_to? :to_str - JSON.parse(object.to_str, opts) - else - JSON.generate(object, opts) + def [](object, opts = nil) + if object.is_a?(String) + return JSON.parse(object, opts) + elsif object.respond_to?(:to_str) + str = object.to_str + if str.is_a?(String) + return JSON.parse(str, opts) + end end + + JSON.generate(object, opts) end - # Returns the JSON parser class that is used by JSON. This is either - # JSON::Ext::Parser or JSON::Pure::Parser: - # JSON.parser # => JSON::Ext::Parser + # Returns the JSON parser class that is used by JSON. attr_reader :parser # Set the JSON parser class _parser_ to be used by JSON. @@ -40,18 +151,9 @@ def parser=(parser) # :nodoc: # level (absolute namespace path?). If there doesn't exist a constant at # the given path, an ArgumentError is raised. def deep_const_get(path) # :nodoc: - path.to_s.split(/::/).inject(Object) do |p, c| - case - when c.empty? then p - when p.const_defined?(c, true) then p.const_get(c) - else - begin - p.const_missing(c) - rescue NameError => e - raise ArgumentError, "can't get const #{path}: #{e}" - end - end - end + Object.const_get(path) + rescue NameError => e + raise ArgumentError, "can't get const #{path}: #{e}" end # Set the module _generator_ to be used by JSON. @@ -60,7 +162,7 @@ def generator=(generator) # :nodoc: @generator = generator generator_methods = generator::GeneratorMethods for const in generator_methods.constants - klass = deep_const_get(const) + klass = const_get(const) modul = generator_methods.const_get(const) klass.class_eval do instance_methods(false).each do |m| @@ -70,97 +172,116 @@ def generator=(generator) # :nodoc: end end self.state = generator::State - const_set :State, self.state - const_set :SAFE_STATE_PROTOTYPE, State.new # for JRuby - const_set :FAST_STATE_PROTOTYPE, create_fast_state - const_set :PRETTY_STATE_PROTOTYPE, create_pretty_state + const_set :State, state ensure $VERBOSE = old end - def create_fast_state - State.new( - :indent => '', - :space => '', - :object_nl => "", - :array_nl => "", - :max_nesting => false - ) - end - - def create_pretty_state - State.new( - :indent => ' ', - :space => ' ', - :object_nl => "\n", - :array_nl => "\n" - ) - end - - # Returns the JSON generator module that is used by JSON. This is - # either JSON::Ext::Generator or JSON::Pure::Generator: - # JSON.generator # => JSON::Ext::Generator + # Returns the JSON generator module that is used by JSON. attr_reader :generator - # Sets or Returns the JSON generator state class that is used by JSON. This is - # either JSON::Ext::Generator::State or JSON::Pure::Generator::State: - # JSON.state # => JSON::Ext::Generator::State + # Sets or Returns the JSON generator state class that is used by JSON. attr_accessor :state - end - DEFAULT_CREATE_ID = 'json_class'.freeze - private_constant :DEFAULT_CREATE_ID + private + + def deprecated_singleton_attr_accessor(*attrs) + args = RUBY_VERSION >= "3.0" ? ", category: :deprecated" : "" + attrs.each do |attr| + singleton_class.class_eval <<~RUBY + def #{attr} + warn "JSON.#{attr} is deprecated and will be removed in json 3.0.0", uplevel: 1 #{args} + @#{attr} + end + + def #{attr}=(val) + warn "JSON.#{attr}= is deprecated and will be removed in json 3.0.0", uplevel: 1 #{args} + @#{attr} = val + end - CREATE_ID_TLS_KEY = "JSON.create_id".freeze - private_constant :CREATE_ID_TLS_KEY + def _#{attr} + @#{attr} + end + RUBY + end + end + end # Sets create identifier, which is used to decide if the _json_create_ # hook of a class should be called; initial value is +json_class+: # JSON.create_id # => 'json_class' def self.create_id=(new_value) - Thread.current[CREATE_ID_TLS_KEY] = new_value.dup.freeze + Thread.current[:"JSON.create_id"] = new_value.dup.freeze end # Returns the current create identifier. # See also JSON.create_id=. def self.create_id - Thread.current[CREATE_ID_TLS_KEY] || DEFAULT_CREATE_ID + Thread.current[:"JSON.create_id"] || 'json_class' end - NaN = 0.0/0 + NaN = Float::NAN - Infinity = 1.0/0 + Infinity = Float::INFINITY MinusInfinity = -Infinity # The base exception for JSON errors. - class JSONError < StandardError - def self.wrap(exception) - obj = new("Wrapped(#{exception.class}): #{exception.message.inspect}") - obj.set_backtrace exception.backtrace - obj - end - end + class JSONError < StandardError; end # This exception is raised if a parser error occurs. - class ParserError < JSONError; end + class ParserError < JSONError + attr_reader :line, :column + end # This exception is raised if the nesting of parsed data structures is too # deep. class NestingError < ParserError; end - # :stopdoc: - class CircularDatastructure < NestingError; end - # :startdoc: - # This exception is raised if a generator or unparser error occurs. - class GeneratorError < JSONError; end - # For backwards compatibility - UnparserError = GeneratorError # :nodoc: + class GeneratorError < JSONError + attr_reader :invalid_object + + def initialize(message, invalid_object = nil) + super(message) + @invalid_object = invalid_object + end + + def detailed_message(...) + # Exception#detailed_message doesn't exist until Ruby 3.2 + super_message = defined?(super) ? super : message + + if @invalid_object.nil? + super_message + else + "#{super_message}\nInvalid object: #{@invalid_object.inspect}" + end + end + end - # This exception is raised if the required unicode support is missing on the - # system. Usually this means that the iconv library is not installed. - class MissingUnicodeSupport < JSONError; end + # Fragment of JSON document that is to be included as is: + # fragment = JSON::Fragment.new("[1, 2, 3]") + # JSON.generate({ count: 3, items: fragments }) + # + # This allows to easily assemble multiple JSON fragments that have + # been persisted somewhere without having to parse them nor resorting + # to string interpolation. + # + # Note: no validation is performed on the provided string. It is the + # responsibility of the caller to ensure the string contains valid JSON. + Fragment = Struct.new(:json) do + def initialize(json) + unless string = String.try_convert(json) + raise TypeError, " no implicit conversion of #{json.class} into String" + end + + super(string) + end + + def to_json(state = nil, *) + json + end + end module_function @@ -192,17 +313,17 @@ class MissingUnicodeSupport < JSONError; end # {Parsing \JSON}[#module-JSON-label-Parsing+JSON]. # # Parses nested JSON objects: - # source = <<-EOT - # { - # "name": "Dave", - # "age" :40, - # "hats": [ - # "Cattleman's", - # "Panama", - # "Tophat" - # ] - # } - # EOT + # source = <<~JSON + # { + # "name": "Dave", + # "age" :40, + # "hats": [ + # "Cattleman's", + # "Panama", + # "Tophat" + # ] + # } + # JSON # ruby = JSON.parse(source) # ruby # => {"name"=>"Dave", "age"=>40, "hats"=>["Cattleman's", "Panama", "Tophat"]} # @@ -212,10 +333,17 @@ class MissingUnicodeSupport < JSONError; end # # Raises JSON::ParserError (783: unexpected token at ''): # JSON.parse('') # - def parse(source, opts = {}) - Parser.new(source, **(opts||{})).parse + def parse(source, opts = nil) + opts = ParserOptions.prepare(opts) unless opts.nil? + Parser.parse(source, opts) end + PARSE_L_OPTIONS = { + max_nesting: false, + allow_nan: true, + }.freeze + private_constant :PARSE_L_OPTIONS + # :call-seq: # JSON.parse!(source, opts) -> object # @@ -227,12 +355,12 @@ def parse(source, opts = {}) # - Option +max_nesting+, if not provided, defaults to +false+, # which disables checking for nesting depth. # - Option +allow_nan+, if not provided, defaults to +true+. - def parse!(source, opts = {}) - opts = { - :max_nesting => false, - :allow_nan => true - }.merge(opts) - Parser.new(source, **(opts||{})).parse + def parse!(source, opts = nil) + if opts.nil? + parse(source, PARSE_L_OPTIONS) + else + parse(source, PARSE_L_OPTIONS.merge(opts)) + end end # :call-seq: @@ -242,8 +370,8 @@ def parse!(source, opts = {}) # parse(File.read(path), opts) # # See method #parse. - def load_file(filespec, opts = {}) - parse(File.read(filespec), opts) + def load_file(filespec, opts = nil) + parse(File.read(filespec, encoding: Encoding::UTF_8), opts) end # :call-seq: @@ -253,8 +381,8 @@ def load_file(filespec, opts = {}) # JSON.parse!(File.read(path, opts)) # # See method #parse! - def load_file!(filespec, opts = {}) - parse!(File.read(filespec), opts) + def load_file!(filespec, opts = nil) + parse!(File.read(filespec, encoding: Encoding::UTF_8), opts) end # :call-seq: @@ -295,20 +423,12 @@ def load_file!(filespec, opts = {}) # def generate(obj, opts = nil) if State === opts - state = opts + opts.generate(obj) else - state = State.new(opts) + State.generate(obj, opts, nil) end - state.generate(obj) end - # :stopdoc: - # I want to deprecate these later, so I'll first be silent about them, and - # later delete them. - alias unparse generate - module_function :unparse - # :startdoc: - # :call-seq: # JSON.fast_generate(obj, opts) -> new_string # @@ -323,19 +443,21 @@ def generate(obj, opts = nil) # # Raises SystemStackError (stack level too deep): # JSON.fast_generate(a) def fast_generate(obj, opts = nil) - if State === opts - state = opts + if RUBY_VERSION >= "3.0" + warn "JSON.fast_generate is deprecated and will be removed in json 3.0.0, just use JSON.generate", uplevel: 1, category: :deprecated else - state = JSON.create_fast_state.configure(opts) + warn "JSON.fast_generate is deprecated and will be removed in json 3.0.0, just use JSON.generate", uplevel: 1 end - state.generate(obj) + generate(obj, opts) end - # :stopdoc: - # I want to deprecate these later, so I'll first be silent about them, and later delete them. - alias fast_unparse fast_generate - module_function :fast_unparse - # :startdoc: + PRETTY_GENERATE_OPTIONS = { + indent: ' ', + space: ' ', + object_nl: "\n", + array_nl: "\n", + }.freeze + private_constant :PRETTY_GENERATE_OPTIONS # :call-seq: # JSON.pretty_generate(obj, opts = nil) -> new_string @@ -368,49 +490,59 @@ def fast_generate(obj, opts = nil) # } # def pretty_generate(obj, opts = nil) - if State === opts - state, opts = opts, nil - else - state = JSON.create_pretty_state - end + return opts.generate(obj) if State === opts + + options = PRETTY_GENERATE_OPTIONS + if opts - if opts.respond_to? :to_hash - opts = opts.to_hash - elsif opts.respond_to? :to_h - opts = opts.to_h - else - raise TypeError, "can't convert #{opts.class} into Hash" + unless opts.is_a?(Hash) + if opts.respond_to? :to_hash + opts = opts.to_hash + elsif opts.respond_to? :to_h + opts = opts.to_h + else + raise TypeError, "can't convert #{opts.class} into Hash" + end end - state.configure(opts) + options = options.merge(opts) end - state.generate(obj) + + State.generate(obj, options, nil) end - # :stopdoc: - # I want to deprecate these later, so I'll first be silent about them, and later delete them. - alias pretty_unparse pretty_generate - module_function :pretty_unparse - # :startdoc: + # Sets or returns default options for the JSON.unsafe_load method. + # Initially: + # opts = JSON.load_default_options + # opts # => {:max_nesting=>false, :allow_nan=>true, :allow_blank=>true, :create_additions=>true} + deprecated_singleton_attr_accessor :unsafe_load_default_options - class << self - # Sets or returns default options for the JSON.load method. - # Initially: - # opts = JSON.load_default_options - # opts # => {:max_nesting=>false, :allow_nan=>true, :allow_blank=>true, :create_additions=>true} - attr_accessor :load_default_options - end - self.load_default_options = { + @unsafe_load_default_options = { :max_nesting => false, :allow_nan => true, - :allow_blank => true, + :allow_blank => true, :create_additions => true, } + # Sets or returns default options for the JSON.load method. + # Initially: + # opts = JSON.load_default_options + # opts # => {:max_nesting=>false, :allow_nan=>true, :allow_blank=>true, :create_additions=>true} + deprecated_singleton_attr_accessor :load_default_options + + @load_default_options = { + :allow_nan => true, + :allow_blank => true, + :create_additions => nil, + } # :call-seq: - # JSON.load(source, proc = nil, options = {}) -> object + # JSON.unsafe_load(source, proc = nil, options = {}) -> object # # Returns the Ruby objects created by parsing the given +source+. # + # BEWARE: This method is meant to serialise data from trusted user input, + # like from your own database server or clients under your control, it could + # be dangerous to allow untrusted users to pass JSON sources into it. + # # - Argument +source+ must be, or be convertible to, a \String: # - If +source+ responds to instance method +to_str+, # source.to_str becomes the source. @@ -425,12 +557,9 @@ class << self # - Argument +proc+, if given, must be a \Proc that accepts one argument. # It will be called recursively with each result (depth-first order). # See details below. - # BEWARE: This method is meant to serialise data from trusted user input, - # like from your own database server or clients under your control, it could - # be dangerous to allow untrusted users to pass JSON sources into it. # - Argument +opts+, if given, contains a \Hash of options for the parsing. # See {Parsing Options}[#module-JSON-label-Parsing+Options]. - # The default options can be changed via method JSON.load_default_options=. + # The default options can be changed via method JSON.unsafe_load_default_options=. # # --- # @@ -438,17 +567,177 @@ class << self # parse(source, opts); see #parse. # # Source for following examples: - # source = <<-EOT + # source = <<~JSON + # { + # "name": "Dave", + # "age" :40, + # "hats": [ + # "Cattleman's", + # "Panama", + # "Tophat" + # ] + # } + # JSON + # + # Load a \String: + # ruby = JSON.unsafe_load(source) + # ruby # => {"name"=>"Dave", "age"=>40, "hats"=>["Cattleman's", "Panama", "Tophat"]} + # + # Load an \IO object: + # require 'stringio' + # object = JSON.unsafe_load(StringIO.new(source)) + # object # => {"name"=>"Dave", "age"=>40, "hats"=>["Cattleman's", "Panama", "Tophat"]} + # + # Load a \File object: + # path = 't.json' + # File.write(path, source) + # File.open(path) do |file| + # JSON.unsafe_load(file) + # end # => {"name"=>"Dave", "age"=>40, "hats"=>["Cattleman's", "Panama", "Tophat"]} + # + # --- + # + # When +proc+ is given: + # - Modifies +source+ as above. + # - Gets the +result+ from calling parse(source, opts). + # - Recursively calls proc(result). + # - Returns the final result. + # + # Example: + # require 'json' + # + # # Some classes for the example. + # class Base + # def initialize(attributes) + # @attributes = attributes + # end + # end + # class User < Base; end + # class Account < Base; end + # class Admin < Base; end + # # The JSON source. + # json = <<-EOF # { - # "name": "Dave", - # "age" :40, - # "hats": [ - # "Cattleman's", - # "Panama", - # "Tophat" - # ] + # "users": [ + # {"type": "User", "username": "jane", "email": "jane@example.com"}, + # {"type": "User", "username": "john", "email": "john@example.com"} + # ], + # "accounts": [ + # {"account": {"type": "Account", "paid": true, "account_id": "1234"}}, + # {"account": {"type": "Account", "paid": false, "account_id": "1235"}} + # ], + # "admins": {"type": "Admin", "password": "0wn3d"} # } - # EOT + # EOF + # # Deserializer method. + # def deserialize_obj(obj, safe_types = %w(User Account Admin)) + # type = obj.is_a?(Hash) && obj["type"] + # safe_types.include?(type) ? Object.const_get(type).new(obj) : obj + # end + # # Call to JSON.unsafe_load + # ruby = JSON.unsafe_load(json, proc {|obj| + # case obj + # when Hash + # obj.each {|k, v| obj[k] = deserialize_obj v } + # when Array + # obj.map! {|v| deserialize_obj v } + # end + # }) + # pp ruby + # Output: + # {"users"=> + # [#"User", "username"=>"jane", "email"=>"jane@example.com"}>, + # #"User", "username"=>"john", "email"=>"john@example.com"}>], + # "accounts"=> + # [{"account"=> + # #"Account", "paid"=>true, "account_id"=>"1234"}>}, + # {"account"=> + # #"Account", "paid"=>false, "account_id"=>"1235"}>}], + # "admins"=> + # #"Admin", "password"=>"0wn3d"}>} + # + def unsafe_load(source, proc = nil, options = nil) + opts = if options.nil? + _unsafe_load_default_options + else + _unsafe_load_default_options.merge(options) + end + + unless source.is_a?(String) + if source.respond_to? :to_str + source = source.to_str + elsif source.respond_to? :to_io + source = source.to_io.read + elsif source.respond_to?(:read) + source = source.read + end + end + + if opts[:allow_blank] && (source.nil? || source.empty?) + source = 'null' + end + result = parse(source, opts) + recurse_proc(result, &proc) if proc + result + end + + # :call-seq: + # JSON.load(source, proc = nil, options = {}) -> object + # + # Returns the Ruby objects created by parsing the given +source+. + # + # BEWARE: This method is meant to serialise data from trusted user input, + # like from your own database server or clients under your control, it could + # be dangerous to allow untrusted users to pass JSON sources into it. + # If you must use it, use JSON.unsafe_load instead to make it clear. + # + # Since JSON version 2.8.0, `load` emits a deprecation warning when a + # non native type is deserialized, without `create_additions` being explicitly + # enabled, and in JSON version 3.0, `load` will have `create_additions` disabled + # by default. + # + # - Argument +source+ must be, or be convertible to, a \String: + # - If +source+ responds to instance method +to_str+, + # source.to_str becomes the source. + # - If +source+ responds to instance method +to_io+, + # source.to_io.read becomes the source. + # - If +source+ responds to instance method +read+, + # source.read becomes the source. + # - If both of the following are true, source becomes the \String 'null': + # - Option +allow_blank+ specifies a truthy value. + # - The source, as defined above, is +nil+ or the empty \String ''. + # - Otherwise, +source+ remains the source. + # - Argument +proc+, if given, must be a \Proc that accepts one argument. + # It will be called recursively with each result (depth-first order). + # See details below. + # - Argument +opts+, if given, contains a \Hash of options for the parsing. + # See {Parsing Options}[#module-JSON-label-Parsing+Options]. + # The default options can be changed via method JSON.load_default_options=. + # + # --- + # + # When no +proc+ is given, modifies +source+ as above and returns the result of + # parse(source, opts); see #parse. + # + # Source for following examples: + # source = <<~JSON + # { + # "name": "Dave", + # "age" :40, + # "hats": [ + # "Cattleman's", + # "Panama", + # "Tophat" + # ] + # } + # JSON # # Load a \String: # ruby = JSON.load(source) @@ -534,51 +823,43 @@ class << self # #"Admin", "password"=>"0wn3d"}>} # - def load(source, proc = nil, options = {}) - opts = load_default_options.merge options - if source.respond_to? :to_str - source = source.to_str - elsif source.respond_to? :to_io - source = source.to_io.read - elsif source.respond_to?(:read) - source = source.read + def load(source, proc = nil, options = nil) + opts = if options.nil? + _load_default_options + else + _load_default_options.merge(options) end + + unless source.is_a?(String) + if source.respond_to? :to_str + source = source.to_str + elsif source.respond_to? :to_io + source = source.to_io.read + elsif source.respond_to?(:read) + source = source.read + end + end + if opts[:allow_blank] && (source.nil? || source.empty?) source = 'null' end - result = parse(source, opts) - recurse_proc(result, &proc) if proc - result - end - # Recursively calls passed _Proc_ if the parsed data structure is an _Array_ or _Hash_ - def recurse_proc(result, &proc) # :nodoc: - case result - when Array - result.each { |x| recurse_proc x, &proc } - proc.call result - when Hash - result.each { |x, y| recurse_proc x, &proc; recurse_proc y, &proc } - proc.call result - else - proc.call result + if proc + opts = opts.dup + opts[:on_load] = proc.to_proc end - end - - alias restore load - module_function :restore - class << self - # Sets or returns the default options for the JSON.dump method. - # Initially: - # opts = JSON.dump_default_options - # opts # => {:max_nesting=>false, :allow_nan=>true, :escape_slash=>false} - attr_accessor :dump_default_options + parse(source, opts) end - self.dump_default_options = { + + # Sets or returns the default options for the JSON.dump method. + # Initially: + # opts = JSON.dump_default_options + # opts # => {:max_nesting=>false, :allow_nan=>true} + deprecated_singleton_attr_accessor :dump_default_options + @dump_default_options = { :max_nesting => false, :allow_nan => true, - :escape_slash => false, } # :call-seq: @@ -608,30 +889,173 @@ class << self # puts File.read(path) # Output: # {"foo":[0,1],"bar":{"baz":2,"bat":3},"bam":"bad"} - def dump(obj, anIO = nil, limit = nil) - if anIO and limit.nil? - anIO = anIO.to_io if anIO.respond_to?(:to_io) - unless anIO.respond_to?(:write) - limit = anIO - anIO = nil + def dump(obj, anIO = nil, limit = nil, kwargs = nil) + if kwargs.nil? + if limit.nil? + if anIO.is_a?(Hash) + kwargs = anIO + anIO = nil + end + elsif limit.is_a?(Hash) + kwargs = limit + limit = nil end end - opts = JSON.dump_default_options + + unless anIO.nil? + if anIO.respond_to?(:to_io) + anIO = anIO.to_io + elsif limit.nil? && !anIO.respond_to?(:write) + anIO, limit = nil, anIO + end + end + + opts = JSON._dump_default_options opts = opts.merge(:max_nesting => limit) if limit - result = generate(obj, opts) - if anIO - anIO.write result - anIO + opts = opts.merge(kwargs) if kwargs + + begin + State.generate(obj, opts, anIO) + rescue JSON::NestingError + raise ArgumentError, "exceed depth limit" + end + end + + # :stopdoc: + # All these were meant to be deprecated circa 2009, but were just set as undocumented + # so usage still exist in the wild. + def unparse(...) + if RUBY_VERSION >= "3.0" + warn "JSON.unparse is deprecated and will be removed in json 3.0.0, just use JSON.generate", uplevel: 1, category: :deprecated else - result + warn "JSON.unparse is deprecated and will be removed in json 3.0.0, just use JSON.generate", uplevel: 1 + end + generate(...) + end + module_function :unparse + + def fast_unparse(...) + if RUBY_VERSION >= "3.0" + warn "JSON.fast_unparse is deprecated and will be removed in json 3.0.0, just use JSON.generate", uplevel: 1, category: :deprecated + else + warn "JSON.fast_unparse is deprecated and will be removed in json 3.0.0, just use JSON.generate", uplevel: 1 + end + generate(...) + end + module_function :fast_unparse + + def pretty_unparse(...) + if RUBY_VERSION >= "3.0" + warn "JSON.pretty_unparse is deprecated and will be removed in json 3.0.0, just use JSON.pretty_generate", uplevel: 1, category: :deprecated + else + warn "JSON.pretty_unparse is deprecated and will be removed in json 3.0.0, just use JSON.pretty_generate", uplevel: 1 + end + pretty_generate(...) + end + module_function :fast_unparse + + def restore(...) + if RUBY_VERSION >= "3.0" + warn "JSON.restore is deprecated and will be removed in json 3.0.0, just use JSON.load", uplevel: 1, category: :deprecated + else + warn "JSON.restore is deprecated and will be removed in json 3.0.0, just use JSON.load", uplevel: 1 + end + load(...) + end + module_function :restore + + class << self + private + + def const_missing(const_name) + case const_name + when :PRETTY_STATE_PROTOTYPE + if RUBY_VERSION >= "3.0" + warn "JSON::PRETTY_STATE_PROTOTYPE is deprecated and will be removed in json 3.0.0, just use JSON.pretty_generate", uplevel: 1, category: :deprecated + else + warn "JSON::PRETTY_STATE_PROTOTYPE is deprecated and will be removed in json 3.0.0, just use JSON.pretty_generate", uplevel: 1 + end + state.new(PRETTY_GENERATE_OPTIONS) + else + super + end end - rescue JSON::NestingError - raise ArgumentError, "exceed depth limit" end + # :startdoc: + + # JSON::Coder holds a parser and generator configuration. + # + # module MyApp + # JSONC_CODER = JSON::Coder.new( + # allow_trailing_comma: true + # ) + # end + # + # MyApp::JSONC_CODER.load(document) + # + class Coder + # :call-seq: + # JSON.new(options = nil, &block) + # + # Argument +options+, if given, contains a \Hash of options for both parsing and generating. + # See {Parsing Options}[#module-JSON-label-Parsing+Options], and {Generating Options}[#module-JSON-label-Generating+Options]. + # + # For generation, the strict: true option is always set. When a Ruby object with no native \JSON counterpart is + # encoutered, the block provided to the initialize method is invoked, and must return a Ruby object that has a native + # \JSON counterpart: + # + # module MyApp + # API_JSON_CODER = JSON::Coder.new do |object| + # case object + # when Time + # object.iso8601(3) + # else + # object # Unknown type, will raise + # end + # end + # end + # + # puts MyApp::API_JSON_CODER.dump(Time.now.utc) # => "2025-01-21T08:41:44.286Z" + # + def initialize(options = nil, &as_json) + if options.nil? + options = { strict: true } + else + options = options.dup + options[:strict] = true + end + options[:as_json] = as_json if as_json + + @state = State.new(options).freeze + @parser_config = Ext::Parser::Config.new(ParserOptions.prepare(options)) + end + + # call-seq: + # dump(object) -> String + # dump(object, io) -> io + # + # Serialize the given object into a \JSON document. + def dump(object, io = nil) + @state.generate_new(object, io) + end + alias_method :generate, :dump + + # call-seq: + # load(string) -> Object + # + # Parse the given \JSON document and return an equivalent Ruby object. + def load(source) + @parser_config.parse(source) + end + alias_method :parse, :load - # Encodes string using String.encode. - def self.iconv(to, from, string) - string.encode(to, from) + # call-seq: + # load(path) -> Object + # + # Parse the given \JSON document and return an equivalent Ruby object. + def load_file(path) + load(File.read(path, encoding: Encoding::UTF_8)) + end end end @@ -641,8 +1065,14 @@ module ::Kernel # Outputs _objs_ to STDOUT as JSON strings in the shortest form, that is in # one line. def j(*objs) + if RUBY_VERSION >= "3.0" + warn "Kernel#j is deprecated and will be removed in json 3.0.0", uplevel: 1, category: :deprecated + else + warn "Kernel#j is deprecated and will be removed in json 3.0.0", uplevel: 1 + end + objs.each do |obj| - puts JSON::generate(obj, :allow_nan => true, :max_nesting => false) + puts JSON.generate(obj, :allow_nan => true, :max_nesting => false) end nil end @@ -650,8 +1080,14 @@ def j(*objs) # Outputs _objs_ to STDOUT as JSON strings in a pretty format, with # indentation and over many lines. def jj(*objs) + if RUBY_VERSION >= "3.0" + warn "Kernel#jj is deprecated and will be removed in json 3.0.0", uplevel: 1, category: :deprecated + else + warn "Kernel#jj is deprecated and will be removed in json 3.0.0", uplevel: 1 + end + objs.each do |obj| - puts JSON::pretty_generate(obj, :allow_nan => true, :max_nesting => false) + puts JSON.pretty_generate(obj, :allow_nan => true, :max_nesting => false) end nil end @@ -662,22 +1098,7 @@ def jj(*objs) # # The _opts_ argument is passed through to generate/parse respectively. See # generate and parse for their documentation. - def JSON(object, *args) - if object.respond_to? :to_str - JSON.parse(object.to_str, args.first) - else - JSON.generate(object, args.first) - end - end -end - -# Extends any Class to include _json_creatable?_ method. -class ::Class - # Returns true if this class can be used to create an instance - # from a serialised JSON string. The class has to implement a class - # method _json_create_ that expects a hash as first parameter. The hash - # should include the required data. - def json_creatable? - respond_to?(:json_create) + def JSON(object, opts = nil) + JSON[object, opts] end end diff --git a/ext/json/lib/json/ext.rb b/ext/json/lib/json/ext.rb index 7264a857fa0653..5bacc5e371212f 100644 --- a/ext/json/lib/json/ext.rb +++ b/ext/json/lib/json/ext.rb @@ -1,15 +1,45 @@ +# frozen_string_literal: true + require 'json/common' module JSON # This module holds all the modules/classes that implement JSON's # functionality as C extensions. module Ext + class Parser + class << self + def parse(...) + new(...).parse + end + alias_method :parse, :parse # Allow redefinition by extensions + end + + def initialize(source, opts = nil) + @source = source + @config = Config.new(opts) + end + + def source + @source.dup + end + + def parse + @config.parse(@source) + end + end + require 'json/ext/parser' - require 'json/ext/generator' - $DEBUG and warn "Using Ext extension for JSON." - JSON.parser = Parser - JSON.generator = Generator + Ext::Parser::Config = Ext::ParserConfig + JSON.parser = Ext::Parser + + if RUBY_ENGINE == 'truffleruby' + require 'json/truffle_ruby/generator' + JSON.generator = JSON::TruffleRuby::Generator + else + require 'json/ext/generator' + JSON.generator = Generator + end end - JSON_LOADED = true unless defined?(::JSON::JSON_LOADED) + JSON_LOADED = true unless defined?(JSON::JSON_LOADED) end diff --git a/ext/json/lib/json/ext/generator/state.rb b/ext/json/lib/json/ext/generator/state.rb new file mode 100644 index 00000000000000..d40c3b5ec35a30 --- /dev/null +++ b/ext/json/lib/json/ext/generator/state.rb @@ -0,0 +1,106 @@ +# frozen_string_literal: true + +module JSON + module Ext + module Generator + class State + # call-seq: new(opts = {}) + # + # Instantiates a new State object, configured by _opts_. + # + # _opts_ can have the following keys: + # + # * *indent*: a string used to indent levels (default: ''), + # * *space*: a string that is put after, a : or , delimiter (default: ''), + # * *space_before*: a string that is put before a : pair delimiter (default: ''), + # * *object_nl*: a string that is put at the end of a JSON object (default: ''), + # * *array_nl*: a string that is put at the end of a JSON array (default: ''), + # * *allow_nan*: true if NaN, Infinity, and -Infinity should be + # generated, otherwise an exception is thrown, if these values are + # encountered. This options defaults to false. + # * *ascii_only*: true if only ASCII characters should be generated. This + # option defaults to false. + # * *buffer_initial_length*: sets the initial length of the generator's + # internal buffer. + def initialize(opts = nil) + if opts && !opts.empty? + configure(opts) + end + end + + # call-seq: configure(opts) + # + # Configure this State instance with the Hash _opts_, and return + # itself. + def configure(opts) + unless opts.is_a?(Hash) + if opts.respond_to?(:to_hash) + opts = opts.to_hash + elsif opts.respond_to?(:to_h) + opts = opts.to_h + else + raise TypeError, "can't convert #{opts.class} into Hash" + end + end + _configure(opts) + end + + alias_method :merge, :configure + + # call-seq: to_h + # + # Returns the configuration instance variables as a hash, that can be + # passed to the configure method. + def to_h + result = { + indent: indent, + space: space, + space_before: space_before, + object_nl: object_nl, + array_nl: array_nl, + as_json: as_json, + allow_nan: allow_nan?, + ascii_only: ascii_only?, + max_nesting: max_nesting, + script_safe: script_safe?, + strict: strict?, + depth: depth, + buffer_initial_length: buffer_initial_length, + } + + instance_variables.each do |iv| + iv = iv.to_s[1..-1] + result[iv.to_sym] = self[iv] + end + + result + end + + alias_method :to_hash, :to_h + + # call-seq: [](name) + # + # Returns the value returned by method +name+. + def [](name) + if respond_to?(name) + __send__(name) + else + instance_variable_get("@#{name}") if + instance_variables.include?("@#{name}".to_sym) # avoid warning + end + end + + # call-seq: []=(name, value) + # + # Sets the attribute name to value. + def []=(name, value) + if respond_to?(name_writer = "#{name}=") + __send__ name_writer, value + else + instance_variable_set "@#{name}", value + end + end + end + end + end +end diff --git a/ext/json/lib/json/generic_object.rb b/ext/json/lib/json/generic_object.rb index 108309db265fca..ec5aa9dcb2977e 100644 --- a/ext/json/lib/json/generic_object.rb +++ b/ext/json/lib/json/generic_object.rb @@ -1,5 +1,9 @@ -#frozen_string_literal: false -require 'ostruct' +# frozen_string_literal: true +begin + require 'ostruct' +rescue LoadError + warn "JSON::GenericObject requires 'ostruct'. Please install it with `gem install ostruct`." +end module JSON class GenericObject < OpenStruct @@ -67,5 +71,5 @@ def as_json(*) def to_json(*a) as_json.to_json(*a) end - end + end if defined?(::OpenStruct) end diff --git a/ext/json/lib/json/version.rb b/ext/json/lib/json/version.rb index 3d4326d836c66d..15ebd12f5158ac 100644 --- a/ext/json/lib/json/version.rb +++ b/ext/json/lib/json/version.rb @@ -1,9 +1,5 @@ -# frozen_string_literal: false +# frozen_string_literal: true + module JSON - # JSON version - VERSION = '2.6.3' - VERSION_ARRAY = VERSION.split(/\./).map { |x| x.to_i } # :nodoc: - VERSION_MAJOR = VERSION_ARRAY[0] # :nodoc: - VERSION_MINOR = VERSION_ARRAY[1] # :nodoc: - VERSION_BUILD = VERSION_ARRAY[2] # :nodoc: + VERSION = '2.12.2' end diff --git a/ext/json/parser/depend b/ext/json/parser/depend index cb6e547d2968d7..1bb03d3517590e 100644 --- a/ext/json/parser/depend +++ b/ext/json/parser/depend @@ -1,5 +1,5 @@ $(OBJS): $(ruby_headers) -parser.o: parser.c parser.h $(srcdir)/../fbuffer/fbuffer.h +parser.o: parser.c $(srcdir)/../fbuffer/fbuffer.h # AUTOGENERATED DEPENDENCIES START parser.o: $(RUBY_EXTCONF_H) @@ -141,6 +141,7 @@ parser.o: $(hdrdir)/ruby/internal/intern/re.h parser.o: $(hdrdir)/ruby/internal/intern/ruby.h parser.o: $(hdrdir)/ruby/internal/intern/select.h parser.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +parser.o: $(hdrdir)/ruby/internal/intern/set.h parser.o: $(hdrdir)/ruby/internal/intern/signal.h parser.o: $(hdrdir)/ruby/internal/intern/sprintf.h parser.o: $(hdrdir)/ruby/internal/intern/string.h @@ -160,6 +161,7 @@ parser.o: $(hdrdir)/ruby/internal/special_consts.h parser.o: $(hdrdir)/ruby/internal/static_assert.h parser.o: $(hdrdir)/ruby/internal/stdalign.h parser.o: $(hdrdir)/ruby/internal/stdbool.h +parser.o: $(hdrdir)/ruby/internal/stdckdint.h parser.o: $(hdrdir)/ruby/internal/symbol.h parser.o: $(hdrdir)/ruby/internal/value.h parser.o: $(hdrdir)/ruby/internal/value_type.h @@ -173,7 +175,6 @@ parser.o: $(hdrdir)/ruby/ruby.h parser.o: $(hdrdir)/ruby/st.h parser.o: $(hdrdir)/ruby/subst.h parser.o: $(srcdir)/../fbuffer/fbuffer.h +parser.o: $(srcdir)/../simd/simd.h parser.o: parser.c -parser.o: parser.h -parser.o: parser.rl # AUTOGENERATED DEPENDENCIES END diff --git a/ext/json/parser/extconf.rb b/ext/json/parser/extconf.rb index feb586e1b4d687..de5d5758b46c42 100644 --- a/ext/json/parser/extconf.rb +++ b/ext/json/parser/extconf.rb @@ -1,32 +1,15 @@ -# frozen_string_literal: false +# frozen_string_literal: true require 'mkmf' -have_func("rb_enc_raise", "ruby.h") -have_func("rb_enc_interned_str", "ruby.h") +have_func("rb_enc_interned_str", "ruby/encoding.h") # RUBY_VERSION >= 3.0 +have_func("rb_hash_new_capa", "ruby.h") # RUBY_VERSION >= 3.2 +have_func("rb_hash_bulk_insert", "ruby.h") # Missing on TruffleRuby +have_func("strnlen", "string.h") # Missing on Solaris 10 -# checking if String#-@ (str_uminus) dedupes... ' -begin - a = -(%w(t e s t).join) - b = -(%w(t e s t).join) - if a.equal?(b) - $CFLAGS << ' -DSTR_UMINUS_DEDUPE=1 ' - else - $CFLAGS << ' -DSTR_UMINUS_DEDUPE=0 ' - end -rescue NoMethodError - $CFLAGS << ' -DSTR_UMINUS_DEDUPE=0 ' -end +append_cflags("-std=c99") -# checking if String#-@ (str_uminus) directly interns frozen strings... ' -begin - s = rand.to_s.freeze - if (-s).equal?(s) && (-s.dup).equal?(s) - $CFLAGS << ' -DSTR_UMINUS_DEDUPE_FROZEN=1 ' - else - $CFLAGS << ' -DSTR_UMINUS_DEDUPE_FROZEN=0 ' - end -rescue NoMethodError - $CFLAGS << ' -DSTR_UMINUS_DEDUPE_FROZEN=0 ' +if enable_config('parser-use-simd', default=!ENV["JSON_DISABLE_SIMD"]) + load __dir__ + "/../simd/conf.rb" end create_makefile 'json/ext/parser' diff --git a/ext/json/parser/parser.c b/ext/json/parser/parser.c index 876bec5769e27f..01b6e6293b7aaf 100644 --- a/ext/json/parser/parser.c +++ b/ext/json/parser/parser.c @@ -1,69 +1,345 @@ -/* This file is automatically generated from parser.rl by using ragel */ -#line 1 "parser.rl" -#include "../fbuffer/fbuffer.h" -#include "parser.h" - -#if defined HAVE_RUBY_ENCODING_H -# define EXC_ENCODING rb_utf8_encoding(), -# ifndef HAVE_RB_ENC_RAISE -static void -enc_raise(rb_encoding *enc, VALUE exc, const char *fmt, ...) -{ - va_list args; - VALUE mesg; +#include "ruby.h" +#include "ruby/encoding.h" - va_start(args, fmt); - mesg = rb_enc_vsprintf(enc, fmt, args); - va_end(args); +/* shims */ +/* This is the fallback definition from Ruby 3.4 */ - rb_exc_raise(rb_exc_new3(exc, mesg)); -} -# define rb_enc_raise enc_raise +#ifndef RBIMPL_STDBOOL_H +#if defined(__cplusplus) +# if defined(HAVE_STDBOOL_H) && (__cplusplus >= 201103L) +# include # endif -#else -# define EXC_ENCODING /* nothing */ -# define rb_enc_raise rb_raise +#elif defined(HAVE_STDBOOL_H) +# include +#elif !defined(HAVE__BOOL) +typedef unsigned char _Bool; +# define bool _Bool +# define true ((_Bool)+1) +# define false ((_Bool)+0) +# define __bool_true_false_are_defined +#endif #endif -/* unicode */ +#include "../simd/simd.h" -static const signed char digit_values[256] = { - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, - -1, -1, -1, -1, -1, -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1 +#ifndef RB_UNLIKELY +#define RB_UNLIKELY(expr) expr +#endif + +#ifndef RB_LIKELY +#define RB_LIKELY(expr) expr +#endif + +static VALUE mJSON, eNestingError, Encoding_UTF_8; +static VALUE CNaN, CInfinity, CMinusInfinity; + +static ID i_chr, i_aset, i_aref, + i_leftshift, i_new, i_try_convert, i_uminus, i_encode; + +static VALUE sym_max_nesting, sym_allow_nan, sym_allow_trailing_comma, sym_symbolize_names, sym_freeze, + sym_decimal_class, sym_on_load, sym_allow_duplicate_key; + +static int binary_encindex; +static int utf8_encindex; + +#ifndef HAVE_RB_HASH_BULK_INSERT +// For TruffleRuby +void +rb_hash_bulk_insert(long count, const VALUE *pairs, VALUE hash) +{ + long index = 0; + while (index < count) { + VALUE name = pairs[index++]; + VALUE value = pairs[index++]; + rb_hash_aset(hash, name, value); + } + RB_GC_GUARD(hash); +} +#endif + +#ifndef HAVE_RB_HASH_NEW_CAPA +#define rb_hash_new_capa(n) rb_hash_new() +#endif + + +/* name cache */ + +#include +#include + +// Object names are likely to be repeated, and are frozen. +// As such we can re-use them if we keep a cache of the ones we've seen so far, +// and save much more expensive lookups into the global fstring table. +// This cache implementation is deliberately simple, as we're optimizing for compactness, +// to be able to fit safely on the stack. +// As such, binary search into a sorted array gives a good tradeoff between compactness and +// performance. +#define JSON_RVALUE_CACHE_CAPA 63 +typedef struct rvalue_cache_struct { + int length; + VALUE entries[JSON_RVALUE_CACHE_CAPA]; +} rvalue_cache; + +static rb_encoding *enc_utf8; + +#define JSON_RVALUE_CACHE_MAX_ENTRY_LENGTH 55 + +static inline VALUE build_interned_string(const char *str, const long length) +{ +# ifdef HAVE_RB_ENC_INTERNED_STR + return rb_enc_interned_str(str, length, enc_utf8); +# else + VALUE rstring = rb_utf8_str_new(str, length); + return rb_funcall(rb_str_freeze(rstring), i_uminus, 0); +# endif +} + +static inline VALUE build_symbol(const char *str, const long length) +{ + return rb_str_intern(build_interned_string(str, length)); +} + +static void rvalue_cache_insert_at(rvalue_cache *cache, int index, VALUE rstring) +{ + MEMMOVE(&cache->entries[index + 1], &cache->entries[index], VALUE, cache->length - index); + cache->length++; + cache->entries[index] = rstring; +} + +static inline int rstring_cache_cmp(const char *str, const long length, VALUE rstring) +{ + long rstring_length = RSTRING_LEN(rstring); + if (length == rstring_length) { + return memcmp(str, RSTRING_PTR(rstring), length); + } else { + return (int)(length - rstring_length); + } +} + +static VALUE rstring_cache_fetch(rvalue_cache *cache, const char *str, const long length) +{ + if (RB_UNLIKELY(length > JSON_RVALUE_CACHE_MAX_ENTRY_LENGTH)) { + // Common names aren't likely to be very long. So we just don't + // cache names above an arbitrary threshold. + return Qfalse; + } + + if (RB_UNLIKELY(!isalpha((unsigned char)str[0]))) { + // Simple heuristic, if the first character isn't a letter, + // we're much less likely to see this string again. + // We mostly want to cache strings that are likely to be repeated. + return Qfalse; + } + + int low = 0; + int high = cache->length - 1; + int mid = 0; + int last_cmp = 0; + + while (low <= high) { + mid = (high + low) >> 1; + VALUE entry = cache->entries[mid]; + last_cmp = rstring_cache_cmp(str, length, entry); + + if (last_cmp == 0) { + return entry; + } else if (last_cmp > 0) { + low = mid + 1; + } else { + high = mid - 1; + } + } + + if (RB_UNLIKELY(memchr(str, '\\', length))) { + // We assume the overwhelming majority of names don't need to be escaped. + // But if they do, we have to fallback to the slow path. + return Qfalse; + } + + VALUE rstring = build_interned_string(str, length); + + if (cache->length < JSON_RVALUE_CACHE_CAPA) { + if (last_cmp > 0) { + mid += 1; + } + + rvalue_cache_insert_at(cache, mid, rstring); + } + return rstring; +} + +static VALUE rsymbol_cache_fetch(rvalue_cache *cache, const char *str, const long length) +{ + if (RB_UNLIKELY(length > JSON_RVALUE_CACHE_MAX_ENTRY_LENGTH)) { + // Common names aren't likely to be very long. So we just don't + // cache names above an arbitrary threshold. + return Qfalse; + } + + if (RB_UNLIKELY(!isalpha((unsigned char)str[0]))) { + // Simple heuristic, if the first character isn't a letter, + // we're much less likely to see this string again. + // We mostly want to cache strings that are likely to be repeated. + return Qfalse; + } + + int low = 0; + int high = cache->length - 1; + int mid = 0; + int last_cmp = 0; + + while (low <= high) { + mid = (high + low) >> 1; + VALUE entry = cache->entries[mid]; + last_cmp = rstring_cache_cmp(str, length, rb_sym2str(entry)); + + if (last_cmp == 0) { + return entry; + } else if (last_cmp > 0) { + low = mid + 1; + } else { + high = mid - 1; + } + } + + if (RB_UNLIKELY(memchr(str, '\\', length))) { + // We assume the overwhelming majority of names don't need to be escaped. + // But if they do, we have to fallback to the slow path. + return Qfalse; + } + + VALUE rsymbol = build_symbol(str, length); + + if (cache->length < JSON_RVALUE_CACHE_CAPA) { + if (last_cmp > 0) { + mid += 1; + } + + rvalue_cache_insert_at(cache, mid, rsymbol); + } + return rsymbol; +} + +/* rvalue stack */ + +#define RVALUE_STACK_INITIAL_CAPA 128 + +enum rvalue_stack_type { + RVALUE_STACK_HEAP_ALLOCATED = 0, + RVALUE_STACK_STACK_ALLOCATED = 1, }; -static UTF32 unescape_unicode(const unsigned char *p) +typedef struct rvalue_stack_struct { + enum rvalue_stack_type type; + long capa; + long head; + VALUE *ptr; +} rvalue_stack; + +static rvalue_stack *rvalue_stack_spill(rvalue_stack *old_stack, VALUE *handle, rvalue_stack **stack_ref); + +static rvalue_stack *rvalue_stack_grow(rvalue_stack *stack, VALUE *handle, rvalue_stack **stack_ref) { - signed char b; - UTF32 result = 0; - b = digit_values[p[0]]; - if (b < 0) return UNI_REPLACEMENT_CHAR; - result = (result << 4) | (unsigned char)b; - b = digit_values[p[1]]; - if (b < 0) return UNI_REPLACEMENT_CHAR; - result = (result << 4) | (unsigned char)b; - b = digit_values[p[2]]; - if (b < 0) return UNI_REPLACEMENT_CHAR; - result = (result << 4) | (unsigned char)b; - b = digit_values[p[3]]; - if (b < 0) return UNI_REPLACEMENT_CHAR; - result = (result << 4) | (unsigned char)b; - return result; + long required = stack->capa * 2; + + if (stack->type == RVALUE_STACK_STACK_ALLOCATED) { + stack = rvalue_stack_spill(stack, handle, stack_ref); + } else { + REALLOC_N(stack->ptr, VALUE, required); + stack->capa = required; + } + return stack; +} + +static VALUE rvalue_stack_push(rvalue_stack *stack, VALUE value, VALUE *handle, rvalue_stack **stack_ref) +{ + if (RB_UNLIKELY(stack->head >= stack->capa)) { + stack = rvalue_stack_grow(stack, handle, stack_ref); + } + stack->ptr[stack->head] = value; + stack->head++; + return value; +} + +static inline VALUE *rvalue_stack_peek(rvalue_stack *stack, long count) +{ + return stack->ptr + (stack->head - count); } -static int convert_UTF32_to_UTF8(char *buf, UTF32 ch) +static inline void rvalue_stack_pop(rvalue_stack *stack, long count) +{ + stack->head -= count; +} + +static void rvalue_stack_mark(void *ptr) +{ + rvalue_stack *stack = (rvalue_stack *)ptr; + long index; + for (index = 0; index < stack->head; index++) { + rb_gc_mark(stack->ptr[index]); + } +} + +static void rvalue_stack_free(void *ptr) +{ + rvalue_stack *stack = (rvalue_stack *)ptr; + if (stack) { + ruby_xfree(stack->ptr); + ruby_xfree(stack); + } +} + +static size_t rvalue_stack_memsize(const void *ptr) +{ + const rvalue_stack *stack = (const rvalue_stack *)ptr; + return sizeof(rvalue_stack) + sizeof(VALUE) * stack->capa; +} + +static const rb_data_type_t JSON_Parser_rvalue_stack_type = { + "JSON::Ext::Parser/rvalue_stack", + { + .dmark = rvalue_stack_mark, + .dfree = rvalue_stack_free, + .dsize = rvalue_stack_memsize, + }, + 0, 0, + RUBY_TYPED_FREE_IMMEDIATELY, +}; + +static rvalue_stack *rvalue_stack_spill(rvalue_stack *old_stack, VALUE *handle, rvalue_stack **stack_ref) +{ + rvalue_stack *stack; + *handle = TypedData_Make_Struct(0, rvalue_stack, &JSON_Parser_rvalue_stack_type, stack); + *stack_ref = stack; + MEMCPY(stack, old_stack, rvalue_stack, 1); + + stack->capa = old_stack->capa << 1; + stack->ptr = ALLOC_N(VALUE, stack->capa); + stack->type = RVALUE_STACK_HEAP_ALLOCATED; + MEMCPY(stack->ptr, old_stack->ptr, VALUE, old_stack->head); + return stack; +} + +static void rvalue_stack_eagerly_release(VALUE handle) +{ + if (handle) { + rvalue_stack *stack; + TypedData_Get_Struct(handle, rvalue_stack, &JSON_Parser_rvalue_stack_type, stack); + RTYPEDDATA_DATA(handle) = NULL; + rvalue_stack_free(stack); + } +} + + +#ifndef HAVE_STRNLEN +static size_t strnlen(const char *s, size_t maxlen) +{ + char *p; + return ((p = memchr(s, '\0', maxlen)) ? p - s : maxlen); +} +#endif + +static int convert_UTF32_to_UTF8(char *buf, uint32_t ch) { int len = 1; if (ch <= 0x7F) { @@ -89,1677 +365,869 @@ static int convert_UTF32_to_UTF8(char *buf, UTF32 ch) return len; } -static VALUE mJSON, mExt, cParser, eParserError, eNestingError; -static VALUE CNaN, CInfinity, CMinusInfinity; +enum duplicate_key_action { + JSON_DEPRECATED = 0, + JSON_IGNORE, + JSON_RAISE, +}; -static ID i_json_creatable_p, i_json_create, i_create_id, i_create_additions, - i_chr, i_max_nesting, i_allow_nan, i_symbolize_names, - i_object_class, i_array_class, i_decimal_class, i_key_p, - i_deep_const_get, i_match, i_match_string, i_aset, i_aref, - i_leftshift, i_new, i_try_convert, i_freeze, i_uminus; +typedef struct JSON_ParserStruct { + VALUE on_load_proc; + VALUE decimal_class; + ID decimal_method_id; + enum duplicate_key_action on_duplicate_key; + int max_nesting; + bool allow_nan; + bool allow_trailing_comma; + bool parsing_name; + bool symbolize_names; + bool freeze; +} JSON_ParserConfig; + +typedef struct JSON_ParserStateStruct { + VALUE stack_handle; + const char *start; + const char *cursor; + const char *end; + rvalue_stack *stack; + rvalue_cache name_cache; + int in_array; + int current_nesting; +} JSON_ParserState; + +static void cursor_position(JSON_ParserState *state, long *line_out, long *column_out) +{ + const char *cursor = state->cursor; + long column = 0; + long line = 1; + while (cursor >= state->start) { + if (*cursor-- == '\n') { + break; + } + column++; + } -#line 125 "parser.rl" + while (cursor >= state->start) { + if (*cursor-- == '\n') { + line++; + } + } + *line_out = line; + *column_out = column; +} +static void emit_parse_warning(const char *message, JSON_ParserState *state) +{ + long line, column; + cursor_position(state, &line, &column); + + rb_warn("%s at line %ld column %ld", message, line, column); +} + +#define PARSE_ERROR_FRAGMENT_LEN 32 +#ifdef RBIMPL_ATTR_NORETURN +RBIMPL_ATTR_NORETURN() +#endif +static void raise_parse_error(const char *format, JSON_ParserState *state) +{ + unsigned char buffer[PARSE_ERROR_FRAGMENT_LEN + 3]; + long line, column; + cursor_position(state, &line, &column); + + const char *ptr = "EOF"; + if (state->cursor && state->cursor < state->end) { + ptr = state->cursor; + size_t len = 0; + while (len < PARSE_ERROR_FRAGMENT_LEN) { + char ch = ptr[len]; + if (!ch || ch == '\n' || ch == ' ' || ch == '\t' || ch == '\r') { + break; + } + len++; + } + if (len) { + buffer[0] = '\''; + MEMCPY(buffer + 1, ptr, char, len); -#line 107 "parser.c" -enum {JSON_object_start = 1}; -enum {JSON_object_first_final = 27}; -enum {JSON_object_error = 0}; + while (buffer[len] >= 0x80 && buffer[len] < 0xC0) { // Is continuation byte + len--; + } -enum {JSON_object_en_main = 1}; + if (buffer[len] >= 0xC0) { // multibyte character start + len--; + } + buffer[len + 1] = '\''; + buffer[len + 2] = '\0'; + ptr = (const char *)buffer; + } + } -#line 167 "parser.rl" + VALUE msg = rb_sprintf(format, ptr); + VALUE message = rb_enc_sprintf(enc_utf8, "%s at line %ld column %ld", RSTRING_PTR(msg), line, column); + RB_GC_GUARD(msg); + VALUE exc = rb_exc_new_str(rb_path2class("JSON::ParserError"), message); + rb_ivar_set(exc, rb_intern("@line"), LONG2NUM(line)); + rb_ivar_set(exc, rb_intern("@column"), LONG2NUM(column)); + rb_exc_raise(exc); +} -static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting) +#ifdef RBIMPL_ATTR_NORETURN +RBIMPL_ATTR_NORETURN() +#endif +static void raise_parse_error_at(const char *format, JSON_ParserState *state, const char *at) { - int cs = EVIL; - VALUE last_name = Qnil; - VALUE object_class = json->object_class; + state->cursor = at; + raise_parse_error(format, state); +} - if (json->max_nesting && current_nesting > json->max_nesting) { - rb_raise(eNestingError, "nesting of %d is too deep", current_nesting); - } +/* unicode */ - *result = NIL_P(object_class) ? rb_hash_new() : rb_class_new_instance(0, 0, object_class); - - -#line 131 "parser.c" - { - cs = JSON_object_start; - } - -#line 182 "parser.rl" - -#line 138 "parser.c" - { - if ( p == pe ) - goto _test_eof; - switch ( cs ) - { -case 1: - if ( (*p) == 123 ) - goto st2; - goto st0; -st0: -cs = 0; - goto _out; -st2: - if ( ++p == pe ) - goto _test_eof2; -case 2: - switch( (*p) ) { - case 13: goto st2; - case 32: goto st2; - case 34: goto tr2; - case 47: goto st23; - case 125: goto tr4; - } - if ( 9 <= (*p) && (*p) <= 10 ) - goto st2; - goto st0; -tr2: -#line 149 "parser.rl" - { - char *np; - json->parsing_name = 1; - np = JSON_parse_string(json, p, pe, &last_name); - json->parsing_name = 0; - if (np == NULL) { p--; {p++; cs = 3; goto _out;} } else {p = (( np))-1;} - } - goto st3; -st3: - if ( ++p == pe ) - goto _test_eof3; -case 3: -#line 179 "parser.c" - switch( (*p) ) { - case 13: goto st3; - case 32: goto st3; - case 47: goto st4; - case 58: goto st8; - } - if ( 9 <= (*p) && (*p) <= 10 ) - goto st3; - goto st0; -st4: - if ( ++p == pe ) - goto _test_eof4; -case 4: - switch( (*p) ) { - case 42: goto st5; - case 47: goto st7; - } - goto st0; -st5: - if ( ++p == pe ) - goto _test_eof5; -case 5: - if ( (*p) == 42 ) - goto st6; - goto st5; -st6: - if ( ++p == pe ) - goto _test_eof6; -case 6: - switch( (*p) ) { - case 42: goto st6; - case 47: goto st3; - } - goto st5; -st7: - if ( ++p == pe ) - goto _test_eof7; -case 7: - if ( (*p) == 10 ) - goto st3; - goto st7; -st8: - if ( ++p == pe ) - goto _test_eof8; -case 8: - switch( (*p) ) { - case 13: goto st8; - case 32: goto st8; - case 34: goto tr11; - case 45: goto tr11; - case 47: goto st19; - case 73: goto tr11; - case 78: goto tr11; - case 91: goto tr11; - case 102: goto tr11; - case 110: goto tr11; - case 116: goto tr11; - case 123: goto tr11; - } - if ( (*p) > 10 ) { - if ( 48 <= (*p) && (*p) <= 57 ) - goto tr11; - } else if ( (*p) >= 9 ) - goto st8; - goto st0; -tr11: -#line 133 "parser.rl" - { - VALUE v = Qnil; - char *np = JSON_parse_value(json, p, pe, &v, current_nesting); - if (np == NULL) { - p--; {p++; cs = 9; goto _out;} - } else { - if (NIL_P(json->object_class)) { - OBJ_FREEZE(last_name); - rb_hash_aset(*result, last_name, v); - } else { - rb_funcall(*result, i_aset, 2, last_name, v); - } - {p = (( np))-1;} - } - } - goto st9; -st9: - if ( ++p == pe ) - goto _test_eof9; -case 9: -#line 267 "parser.c" - switch( (*p) ) { - case 13: goto st9; - case 32: goto st9; - case 44: goto st10; - case 47: goto st15; - case 125: goto tr4; - } - if ( 9 <= (*p) && (*p) <= 10 ) - goto st9; - goto st0; -st10: - if ( ++p == pe ) - goto _test_eof10; -case 10: - switch( (*p) ) { - case 13: goto st10; - case 32: goto st10; - case 34: goto tr2; - case 47: goto st11; - } - if ( 9 <= (*p) && (*p) <= 10 ) - goto st10; - goto st0; -st11: - if ( ++p == pe ) - goto _test_eof11; -case 11: - switch( (*p) ) { - case 42: goto st12; - case 47: goto st14; - } - goto st0; -st12: - if ( ++p == pe ) - goto _test_eof12; -case 12: - if ( (*p) == 42 ) - goto st13; - goto st12; -st13: - if ( ++p == pe ) - goto _test_eof13; -case 13: - switch( (*p) ) { - case 42: goto st13; - case 47: goto st10; - } - goto st12; -st14: - if ( ++p == pe ) - goto _test_eof14; -case 14: - if ( (*p) == 10 ) - goto st10; - goto st14; -st15: - if ( ++p == pe ) - goto _test_eof15; -case 15: - switch( (*p) ) { - case 42: goto st16; - case 47: goto st18; - } - goto st0; -st16: - if ( ++p == pe ) - goto _test_eof16; -case 16: - if ( (*p) == 42 ) - goto st17; - goto st16; -st17: - if ( ++p == pe ) - goto _test_eof17; -case 17: - switch( (*p) ) { - case 42: goto st17; - case 47: goto st9; - } - goto st16; -st18: - if ( ++p == pe ) - goto _test_eof18; -case 18: - if ( (*p) == 10 ) - goto st9; - goto st18; -tr4: -#line 157 "parser.rl" - { p--; {p++; cs = 27; goto _out;} } - goto st27; -st27: - if ( ++p == pe ) - goto _test_eof27; -case 27: -#line 363 "parser.c" - goto st0; -st19: - if ( ++p == pe ) - goto _test_eof19; -case 19: - switch( (*p) ) { - case 42: goto st20; - case 47: goto st22; - } - goto st0; -st20: - if ( ++p == pe ) - goto _test_eof20; -case 20: - if ( (*p) == 42 ) - goto st21; - goto st20; -st21: - if ( ++p == pe ) - goto _test_eof21; -case 21: - switch( (*p) ) { - case 42: goto st21; - case 47: goto st8; - } - goto st20; -st22: - if ( ++p == pe ) - goto _test_eof22; -case 22: - if ( (*p) == 10 ) - goto st8; - goto st22; -st23: - if ( ++p == pe ) - goto _test_eof23; -case 23: - switch( (*p) ) { - case 42: goto st24; - case 47: goto st26; - } - goto st0; -st24: - if ( ++p == pe ) - goto _test_eof24; -case 24: - if ( (*p) == 42 ) - goto st25; - goto st24; -st25: - if ( ++p == pe ) - goto _test_eof25; -case 25: - switch( (*p) ) { - case 42: goto st25; - case 47: goto st2; - } - goto st24; -st26: - if ( ++p == pe ) - goto _test_eof26; -case 26: - if ( (*p) == 10 ) - goto st2; - goto st26; - } - _test_eof2: cs = 2; goto _test_eof; - _test_eof3: cs = 3; goto _test_eof; - _test_eof4: cs = 4; goto _test_eof; - _test_eof5: cs = 5; goto _test_eof; - _test_eof6: cs = 6; goto _test_eof; - _test_eof7: cs = 7; goto _test_eof; - _test_eof8: cs = 8; goto _test_eof; - _test_eof9: cs = 9; goto _test_eof; - _test_eof10: cs = 10; goto _test_eof; - _test_eof11: cs = 11; goto _test_eof; - _test_eof12: cs = 12; goto _test_eof; - _test_eof13: cs = 13; goto _test_eof; - _test_eof14: cs = 14; goto _test_eof; - _test_eof15: cs = 15; goto _test_eof; - _test_eof16: cs = 16; goto _test_eof; - _test_eof17: cs = 17; goto _test_eof; - _test_eof18: cs = 18; goto _test_eof; - _test_eof27: cs = 27; goto _test_eof; - _test_eof19: cs = 19; goto _test_eof; - _test_eof20: cs = 20; goto _test_eof; - _test_eof21: cs = 21; goto _test_eof; - _test_eof22: cs = 22; goto _test_eof; - _test_eof23: cs = 23; goto _test_eof; - _test_eof24: cs = 24; goto _test_eof; - _test_eof25: cs = 25; goto _test_eof; - _test_eof26: cs = 26; goto _test_eof; - - _test_eof: {} - _out: {} - } - -#line 183 "parser.rl" - - if (cs >= JSON_object_first_final) { - if (json->create_additions) { - VALUE klassname; - if (NIL_P(json->object_class)) { - klassname = rb_hash_aref(*result, json->create_id); - } else { - klassname = rb_funcall(*result, i_aref, 1, json->create_id); +static const signed char digit_values[256] = { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, + -1, -1, -1, -1, -1, -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1 +}; + +static uint32_t unescape_unicode(JSON_ParserState *state, const unsigned char *p) +{ + signed char b; + uint32_t result = 0; + b = digit_values[p[0]]; + if (b < 0) raise_parse_error_at("incomplete unicode character escape sequence at %s", state, (char *)p - 2); + result = (result << 4) | (unsigned char)b; + b = digit_values[p[1]]; + if (b < 0) raise_parse_error_at("incomplete unicode character escape sequence at %s", state, (char *)p - 2); + result = (result << 4) | (unsigned char)b; + b = digit_values[p[2]]; + if (b < 0) raise_parse_error_at("incomplete unicode character escape sequence at %s", state, (char *)p - 2); + result = (result << 4) | (unsigned char)b; + b = digit_values[p[3]]; + if (b < 0) raise_parse_error_at("incomplete unicode character escape sequence at %s", state, (char *)p - 2); + result = (result << 4) | (unsigned char)b; + return result; +} + +#define GET_PARSER_CONFIG \ + JSON_ParserConfig *config; \ + TypedData_Get_Struct(self, JSON_ParserConfig, &JSON_ParserConfig_type, config) + +static const rb_data_type_t JSON_ParserConfig_type; + +static const bool whitespace[256] = { + [' '] = 1, + ['\t'] = 1, + ['\n'] = 1, + ['\r'] = 1, + ['/'] = 1, +}; + +static void +json_eat_comments(JSON_ParserState *state) +{ + if (state->cursor + 1 < state->end) { + switch (state->cursor[1]) { + case '/': { + state->cursor = memchr(state->cursor, '\n', state->end - state->cursor); + if (!state->cursor) { + state->cursor = state->end; + } else { + state->cursor++; + } + break; } - if (!NIL_P(klassname)) { - VALUE klass = rb_funcall(mJSON, i_deep_const_get, 1, klassname); - if (RTEST(rb_funcall(klass, i_json_creatable_p, 0))) { - *result = rb_funcall(klass, i_json_create, 1, *result); + case '*': { + state->cursor += 2; + while (true) { + state->cursor = memchr(state->cursor, '*', state->end - state->cursor); + if (!state->cursor) { + raise_parse_error_at("unexpected end of input, expected closing '*/'", state, state->end); + } else { + state->cursor++; + if (state->cursor < state->end && *state->cursor == '/') { + state->cursor++; + break; + } + } } + break; } + default: + raise_parse_error("unexpected token %s", state); + break; } - return p + 1; } else { - return NULL; + raise_parse_error("unexpected token %s", state); } } +static inline void +json_eat_whitespace(JSON_ParserState *state) +{ + while (state->cursor < state->end && RB_UNLIKELY(whitespace[(unsigned char)*state->cursor])) { + if (RB_LIKELY(*state->cursor != '/')) { + state->cursor++; + } else { + json_eat_comments(state); + } + } +} +static inline VALUE build_string(const char *start, const char *end, bool intern, bool symbolize) +{ + if (symbolize) { + intern = true; + } + VALUE result; +# ifdef HAVE_RB_ENC_INTERNED_STR + if (intern) { + result = rb_enc_interned_str(start, (long)(end - start), enc_utf8); + } else { + result = rb_utf8_str_new(start, (long)(end - start)); + } +# else + result = rb_utf8_str_new(start, (long)(end - start)); + if (intern) { + result = rb_funcall(rb_str_freeze(result), i_uminus, 0); + } +# endif -#line 486 "parser.c" -enum {JSON_value_start = 1}; -enum {JSON_value_first_final = 29}; -enum {JSON_value_error = 0}; - -enum {JSON_value_en_main = 1}; + if (symbolize) { + result = rb_str_intern(result); + } + return result; +} -#line 283 "parser.rl" +static inline VALUE json_string_fastpath(JSON_ParserState *state, const char *string, const char *stringEnd, bool is_name, bool intern, bool symbolize) +{ + size_t bufferSize = stringEnd - string; + if (is_name && state->in_array) { + VALUE cached_key; + if (RB_UNLIKELY(symbolize)) { + cached_key = rsymbol_cache_fetch(&state->name_cache, string, bufferSize); + } else { + cached_key = rstring_cache_fetch(&state->name_cache, string, bufferSize); + } -static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting) -{ - int cs = EVIL; - - -#line 502 "parser.c" - { - cs = JSON_value_start; - } - -#line 290 "parser.rl" - -#line 509 "parser.c" - { - if ( p == pe ) - goto _test_eof; - switch ( cs ) - { -st1: - if ( ++p == pe ) - goto _test_eof1; -case 1: - switch( (*p) ) { - case 13: goto st1; - case 32: goto st1; - case 34: goto tr2; - case 45: goto tr3; - case 47: goto st6; - case 73: goto st10; - case 78: goto st17; - case 91: goto tr7; - case 102: goto st19; - case 110: goto st23; - case 116: goto st26; - case 123: goto tr11; - } - if ( (*p) > 10 ) { - if ( 48 <= (*p) && (*p) <= 57 ) - goto tr3; - } else if ( (*p) >= 9 ) - goto st1; - goto st0; -st0: -cs = 0; - goto _out; -tr2: -#line 235 "parser.rl" - { - char *np = JSON_parse_string(json, p, pe, result); - if (np == NULL) { p--; {p++; cs = 29; goto _out;} } else {p = (( np))-1;} - } - goto st29; -tr3: -#line 240 "parser.rl" - { - char *np; - if(pe > p + 8 && !strncmp(MinusInfinity, p, 9)) { - if (json->allow_nan) { - *result = CMinusInfinity; - {p = (( p + 10))-1;} - p--; {p++; cs = 29; goto _out;} - } else { - rb_enc_raise(EXC_ENCODING eParserError, "unexpected token at '%s'", p); - } + if (RB_LIKELY(cached_key)) { + return cached_key; } - np = JSON_parse_float(json, p, pe, result); - if (np != NULL) {p = (( np))-1;} - np = JSON_parse_integer(json, p, pe, result); - if (np != NULL) {p = (( np))-1;} - p--; {p++; cs = 29; goto _out;} - } - goto st29; -tr7: -#line 258 "parser.rl" - { - char *np; - np = JSON_parse_array(json, p, pe, result, current_nesting + 1); - if (np == NULL) { p--; {p++; cs = 29; goto _out;} } else {p = (( np))-1;} - } - goto st29; -tr11: -#line 264 "parser.rl" - { - char *np; - np = JSON_parse_object(json, p, pe, result, current_nesting + 1); - if (np == NULL) { p--; {p++; cs = 29; goto _out;} } else {p = (( np))-1;} } - goto st29; -tr25: -#line 228 "parser.rl" - { - if (json->allow_nan) { - *result = CInfinity; + + return build_string(string, stringEnd, intern, symbolize); +} + +static VALUE json_string_unescape(JSON_ParserState *state, const char *string, const char *stringEnd, bool is_name, bool intern, bool symbolize) +{ + size_t bufferSize = stringEnd - string; + const char *p = string, *pe = string, *unescape, *bufferStart; + char *buffer; + int unescape_len; + char buf[4]; + + if (is_name && state->in_array) { + VALUE cached_key; + if (RB_UNLIKELY(symbolize)) { + cached_key = rsymbol_cache_fetch(&state->name_cache, string, bufferSize); } else { - rb_enc_raise(EXC_ENCODING eParserError, "unexpected token at '%s'", p - 8); + cached_key = rstring_cache_fetch(&state->name_cache, string, bufferSize); + } + + if (RB_LIKELY(cached_key)) { + return cached_key; } } - goto st29; -tr27: -#line 221 "parser.rl" - { - if (json->allow_nan) { - *result = CNaN; - } else { - rb_enc_raise(EXC_ENCODING eParserError, "unexpected token at '%s'", p - 2); + + VALUE result = rb_str_buf_new(bufferSize); + rb_enc_associate_index(result, utf8_encindex); + buffer = RSTRING_PTR(result); + bufferStart = buffer; + + while (pe < stringEnd && (pe = memchr(pe, '\\', stringEnd - pe))) { + unescape = (char *) "?"; + unescape_len = 1; + if (pe > p) { + MEMCPY(buffer, p, char, pe - p); + buffer += pe - p; } + switch (*++pe) { + case 'n': + unescape = (char *) "\n"; + break; + case 'r': + unescape = (char *) "\r"; + break; + case 't': + unescape = (char *) "\t"; + break; + case '"': + unescape = (char *) "\""; + break; + case '\\': + unescape = (char *) "\\"; + break; + case 'b': + unescape = (char *) "\b"; + break; + case 'f': + unescape = (char *) "\f"; + break; + case 'u': + if (pe > stringEnd - 5) { + raise_parse_error_at("incomplete unicode character escape sequence at %s", state, p); + } else { + uint32_t ch = unescape_unicode(state, (unsigned char *) ++pe); + pe += 3; + /* To handle values above U+FFFF, we take a sequence of + * \uXXXX escapes in the U+D800..U+DBFF then + * U+DC00..U+DFFF ranges, take the low 10 bits from each + * to make a 20-bit number, then add 0x10000 to get the + * final codepoint. + * + * See Unicode 15: 3.8 "Surrogates", 5.3 "Handling + * Surrogate Pairs in UTF-16", and 23.6 "Surrogates + * Area". + */ + if ((ch & 0xFC00) == 0xD800) { + pe++; + if (pe > stringEnd - 6) { + raise_parse_error_at("incomplete surrogate pair at %s", state, p); + } + if (pe[0] == '\\' && pe[1] == 'u') { + uint32_t sur = unescape_unicode(state, (unsigned char *) pe + 2); + ch = (((ch & 0x3F) << 10) | ((((ch >> 6) & 0xF) + 1) << 16) + | (sur & 0x3FF)); + pe += 5; + } else { + unescape = (char *) "?"; + break; + } + } + unescape_len = convert_UTF32_to_UTF8(buf, ch); + unescape = buf; + } + break; + default: + p = pe; + continue; + } + MEMCPY(buffer, unescape, char, unescape_len); + buffer += unescape_len; + p = ++pe; } - goto st29; -tr31: -#line 215 "parser.rl" - { - *result = Qfalse; + + if (stringEnd > p) { + MEMCPY(buffer, p, char, stringEnd - p); + buffer += stringEnd - p; } - goto st29; -tr34: -#line 212 "parser.rl" - { - *result = Qnil; + rb_str_set_len(result, buffer - bufferStart); + + if (symbolize) { + result = rb_str_intern(result); + } else if (intern) { + result = rb_funcall(rb_str_freeze(result), i_uminus, 0); } - goto st29; -tr37: -#line 218 "parser.rl" - { - *result = Qtrue; + + return result; +} + +#define MAX_FAST_INTEGER_SIZE 18 +static inline VALUE fast_decode_integer(const char *p, const char *pe) +{ + bool negative = false; + if (*p == '-') { + negative = true; + p++; } - goto st29; -st29: - if ( ++p == pe ) - goto _test_eof29; -case 29: -#line 270 "parser.rl" - { p--; {p++; cs = 29; goto _out;} } -#line 629 "parser.c" - switch( (*p) ) { - case 13: goto st29; - case 32: goto st29; - case 47: goto st2; - } - if ( 9 <= (*p) && (*p) <= 10 ) - goto st29; - goto st0; -st2: - if ( ++p == pe ) - goto _test_eof2; -case 2: - switch( (*p) ) { - case 42: goto st3; - case 47: goto st5; - } - goto st0; -st3: - if ( ++p == pe ) - goto _test_eof3; -case 3: - if ( (*p) == 42 ) - goto st4; - goto st3; -st4: - if ( ++p == pe ) - goto _test_eof4; -case 4: - switch( (*p) ) { - case 42: goto st4; - case 47: goto st29; - } - goto st3; -st5: - if ( ++p == pe ) - goto _test_eof5; -case 5: - if ( (*p) == 10 ) - goto st29; - goto st5; -st6: - if ( ++p == pe ) - goto _test_eof6; -case 6: - switch( (*p) ) { - case 42: goto st7; - case 47: goto st9; - } - goto st0; -st7: - if ( ++p == pe ) - goto _test_eof7; -case 7: - if ( (*p) == 42 ) - goto st8; - goto st7; -st8: - if ( ++p == pe ) - goto _test_eof8; -case 8: - switch( (*p) ) { - case 42: goto st8; - case 47: goto st1; - } - goto st7; -st9: - if ( ++p == pe ) - goto _test_eof9; -case 9: - if ( (*p) == 10 ) - goto st1; - goto st9; -st10: - if ( ++p == pe ) - goto _test_eof10; -case 10: - if ( (*p) == 110 ) - goto st11; - goto st0; -st11: - if ( ++p == pe ) - goto _test_eof11; -case 11: - if ( (*p) == 102 ) - goto st12; - goto st0; -st12: - if ( ++p == pe ) - goto _test_eof12; -case 12: - if ( (*p) == 105 ) - goto st13; - goto st0; -st13: - if ( ++p == pe ) - goto _test_eof13; -case 13: - if ( (*p) == 110 ) - goto st14; - goto st0; -st14: - if ( ++p == pe ) - goto _test_eof14; -case 14: - if ( (*p) == 105 ) - goto st15; - goto st0; -st15: - if ( ++p == pe ) - goto _test_eof15; -case 15: - if ( (*p) == 116 ) - goto st16; - goto st0; -st16: - if ( ++p == pe ) - goto _test_eof16; -case 16: - if ( (*p) == 121 ) - goto tr25; - goto st0; -st17: - if ( ++p == pe ) - goto _test_eof17; -case 17: - if ( (*p) == 97 ) - goto st18; - goto st0; -st18: - if ( ++p == pe ) - goto _test_eof18; -case 18: - if ( (*p) == 78 ) - goto tr27; - goto st0; -st19: - if ( ++p == pe ) - goto _test_eof19; -case 19: - if ( (*p) == 97 ) - goto st20; - goto st0; -st20: - if ( ++p == pe ) - goto _test_eof20; -case 20: - if ( (*p) == 108 ) - goto st21; - goto st0; -st21: - if ( ++p == pe ) - goto _test_eof21; -case 21: - if ( (*p) == 115 ) - goto st22; - goto st0; -st22: - if ( ++p == pe ) - goto _test_eof22; -case 22: - if ( (*p) == 101 ) - goto tr31; - goto st0; -st23: - if ( ++p == pe ) - goto _test_eof23; -case 23: - if ( (*p) == 117 ) - goto st24; - goto st0; -st24: - if ( ++p == pe ) - goto _test_eof24; -case 24: - if ( (*p) == 108 ) - goto st25; - goto st0; -st25: - if ( ++p == pe ) - goto _test_eof25; -case 25: - if ( (*p) == 108 ) - goto tr34; - goto st0; -st26: - if ( ++p == pe ) - goto _test_eof26; -case 26: - if ( (*p) == 114 ) - goto st27; - goto st0; -st27: - if ( ++p == pe ) - goto _test_eof27; -case 27: - if ( (*p) == 117 ) - goto st28; - goto st0; -st28: - if ( ++p == pe ) - goto _test_eof28; -case 28: - if ( (*p) == 101 ) - goto tr37; - goto st0; - } - _test_eof1: cs = 1; goto _test_eof; - _test_eof29: cs = 29; goto _test_eof; - _test_eof2: cs = 2; goto _test_eof; - _test_eof3: cs = 3; goto _test_eof; - _test_eof4: cs = 4; goto _test_eof; - _test_eof5: cs = 5; goto _test_eof; - _test_eof6: cs = 6; goto _test_eof; - _test_eof7: cs = 7; goto _test_eof; - _test_eof8: cs = 8; goto _test_eof; - _test_eof9: cs = 9; goto _test_eof; - _test_eof10: cs = 10; goto _test_eof; - _test_eof11: cs = 11; goto _test_eof; - _test_eof12: cs = 12; goto _test_eof; - _test_eof13: cs = 13; goto _test_eof; - _test_eof14: cs = 14; goto _test_eof; - _test_eof15: cs = 15; goto _test_eof; - _test_eof16: cs = 16; goto _test_eof; - _test_eof17: cs = 17; goto _test_eof; - _test_eof18: cs = 18; goto _test_eof; - _test_eof19: cs = 19; goto _test_eof; - _test_eof20: cs = 20; goto _test_eof; - _test_eof21: cs = 21; goto _test_eof; - _test_eof22: cs = 22; goto _test_eof; - _test_eof23: cs = 23; goto _test_eof; - _test_eof24: cs = 24; goto _test_eof; - _test_eof25: cs = 25; goto _test_eof; - _test_eof26: cs = 26; goto _test_eof; - _test_eof27: cs = 27; goto _test_eof; - _test_eof28: cs = 28; goto _test_eof; - - _test_eof: {} - _out: {} - } - -#line 291 "parser.rl" - - if (json->freeze) { - OBJ_FREEZE(*result); + + long long memo = 0; + while (p < pe) { + memo *= 10; + memo += *p - '0'; + p++; } - if (cs >= JSON_value_first_final) { - return p; + if (negative) { + memo = -memo; + } + return LL2NUM(memo); +} + +static VALUE json_decode_large_integer(const char *start, long len) +{ + VALUE buffer_v; + char *buffer = RB_ALLOCV_N(char, buffer_v, len + 1); + MEMCPY(buffer, start, char, len); + buffer[len] = '\0'; + VALUE number = rb_cstr2inum(buffer, 10); + RB_ALLOCV_END(buffer_v); + return number; +} + +static inline VALUE +json_decode_integer(const char *start, const char *end) +{ + long len = end - start; + if (RB_LIKELY(len < MAX_FAST_INTEGER_SIZE)) { + return fast_decode_integer(start, end); + } + return json_decode_large_integer(start, len); +} + +static VALUE json_decode_large_float(const char *start, long len) +{ + VALUE buffer_v; + char *buffer = RB_ALLOCV_N(char, buffer_v, len + 1); + MEMCPY(buffer, start, char, len); + buffer[len] = '\0'; + VALUE number = DBL2NUM(rb_cstr_to_dbl(buffer, 1)); + RB_ALLOCV_END(buffer_v); + return number; +} + +static VALUE json_decode_float(JSON_ParserConfig *config, const char *start, const char *end) +{ + long len = end - start; + + if (RB_UNLIKELY(config->decimal_class)) { + VALUE text = rb_str_new(start, len); + return rb_funcallv(config->decimal_class, config->decimal_method_id, 1, &text); + } else if (RB_LIKELY(len < 64)) { + char buffer[64]; + MEMCPY(buffer, start, char, len); + buffer[len] = '\0'; + return DBL2NUM(rb_cstr_to_dbl(buffer, 1)); } else { - return NULL; + return json_decode_large_float(start, len); } } +static inline VALUE json_decode_array(JSON_ParserState *state, JSON_ParserConfig *config, long count) +{ + VALUE array = rb_ary_new_from_values(count, rvalue_stack_peek(state->stack, count)); + rvalue_stack_pop(state->stack, count); -#line 884 "parser.c" -enum {JSON_integer_start = 1}; -enum {JSON_integer_first_final = 3}; -enum {JSON_integer_error = 0}; + if (config->freeze) { + RB_OBJ_FREEZE(array); + } -enum {JSON_integer_en_main = 1}; + return array; +} +static inline VALUE json_decode_object(JSON_ParserState *state, JSON_ParserConfig *config, size_t count) +{ + size_t entries_count = count / 2; + VALUE object = rb_hash_new_capa(entries_count); + rb_hash_bulk_insert(count, rvalue_stack_peek(state->stack, count), object); + + if (RB_UNLIKELY(RHASH_SIZE(object) < entries_count)) { + switch (config->on_duplicate_key) { + case JSON_IGNORE: + break; + case JSON_DEPRECATED: + emit_parse_warning("detected duplicate keys in JSON object. This will raise an error in json 3.0 unless enabled via `allow_duplicate_key: true`", state); + break; + case JSON_RAISE: + raise_parse_error("duplicate key", state); + break; + } + } + + rvalue_stack_pop(state->stack, count); -#line 311 "parser.rl" + if (config->freeze) { + RB_OBJ_FREEZE(object); + } + return object; +} -static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *result) +static inline VALUE json_decode_string(JSON_ParserState *state, JSON_ParserConfig *config, const char *start, const char *end, bool escaped, bool is_name) { - int cs = EVIL; - - -#line 900 "parser.c" - { - cs = JSON_integer_start; - } - -#line 318 "parser.rl" - json->memo = p; - -#line 908 "parser.c" - { - if ( p == pe ) - goto _test_eof; - switch ( cs ) - { -case 1: - switch( (*p) ) { - case 45: goto st2; - case 48: goto st3; - } - if ( 49 <= (*p) && (*p) <= 57 ) - goto st5; - goto st0; -st0: -cs = 0; - goto _out; -st2: - if ( ++p == pe ) - goto _test_eof2; -case 2: - if ( (*p) == 48 ) - goto st3; - if ( 49 <= (*p) && (*p) <= 57 ) - goto st5; - goto st0; -st3: - if ( ++p == pe ) - goto _test_eof3; -case 3: - if ( 48 <= (*p) && (*p) <= 57 ) - goto st0; - goto tr4; -tr4: -#line 308 "parser.rl" - { p--; {p++; cs = 4; goto _out;} } - goto st4; -st4: - if ( ++p == pe ) - goto _test_eof4; -case 4: -#line 949 "parser.c" - goto st0; -st5: - if ( ++p == pe ) - goto _test_eof5; -case 5: - if ( 48 <= (*p) && (*p) <= 57 ) - goto st5; - goto tr4; - } - _test_eof2: cs = 2; goto _test_eof; - _test_eof3: cs = 3; goto _test_eof; - _test_eof4: cs = 4; goto _test_eof; - _test_eof5: cs = 5; goto _test_eof; - - _test_eof: {} - _out: {} - } - -#line 320 "parser.rl" - - if (cs >= JSON_integer_first_final) { - long len = p - json->memo; - fbuffer_clear(json->fbuffer); - fbuffer_append(json->fbuffer, json->memo, len); - fbuffer_append_char(json->fbuffer, '\0'); - *result = rb_cstr2inum(FBUFFER_PTR(json->fbuffer), 10); - return p + 1; + VALUE string; + bool intern = is_name || config->freeze; + bool symbolize = is_name && config->symbolize_names; + if (escaped) { + string = json_string_unescape(state, start, end, is_name, intern, symbolize); } else { - return NULL; + string = json_string_fastpath(state, start, end, is_name, intern, symbolize); } + + return string; } +static inline VALUE json_push_value(JSON_ParserState *state, JSON_ParserConfig *config, VALUE value) +{ + if (RB_UNLIKELY(config->on_load_proc)) { + value = rb_proc_call_with_block(config->on_load_proc, 1, &value, Qnil); + } + rvalue_stack_push(state->stack, value, &state->stack_handle, &state->stack); + return value; +} -#line 983 "parser.c" -enum {JSON_float_start = 1}; -enum {JSON_float_first_final = 8}; -enum {JSON_float_error = 0}; +static const bool string_scan_table[256] = { + // ASCII Control Characters + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + // ASCII Characters + 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // '"' + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, // '\\' + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +}; -enum {JSON_float_en_main = 1}; +#if (defined(__GNUC__ ) || defined(__clang__)) +#define FORCE_INLINE __attribute__((always_inline)) +#else +#define FORCE_INLINE +#endif +#ifdef HAVE_SIMD +static SIMD_Implementation simd_impl = SIMD_NONE; +#endif /* HAVE_SIMD */ -#line 345 "parser.rl" +static inline bool FORCE_INLINE string_scan(JSON_ParserState *state) +{ +#ifdef HAVE_SIMD +#if defined(HAVE_SIMD_NEON) + uint64_t mask = 0; + if (string_scan_simd_neon(&state->cursor, state->end, &mask)) { + state->cursor += trailing_zeros64(mask) >> 2; + return 1; + } -static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *result) -{ - int cs = EVIL; - - -#line 999 "parser.c" - { - cs = JSON_float_start; - } - -#line 352 "parser.rl" - json->memo = p; - -#line 1007 "parser.c" - { - if ( p == pe ) - goto _test_eof; - switch ( cs ) - { -case 1: - switch( (*p) ) { - case 45: goto st2; - case 48: goto st3; - } - if ( 49 <= (*p) && (*p) <= 57 ) - goto st7; - goto st0; -st0: -cs = 0; - goto _out; -st2: - if ( ++p == pe ) - goto _test_eof2; -case 2: - if ( (*p) == 48 ) - goto st3; - if ( 49 <= (*p) && (*p) <= 57 ) - goto st7; - goto st0; -st3: - if ( ++p == pe ) - goto _test_eof3; -case 3: - switch( (*p) ) { - case 46: goto st4; - case 69: goto st5; - case 101: goto st5; - } - goto st0; -st4: - if ( ++p == pe ) - goto _test_eof4; -case 4: - if ( 48 <= (*p) && (*p) <= 57 ) - goto st8; - goto st0; -st8: - if ( ++p == pe ) - goto _test_eof8; -case 8: - switch( (*p) ) { - case 69: goto st5; - case 101: goto st5; - } - if ( (*p) > 46 ) { - if ( 48 <= (*p) && (*p) <= 57 ) - goto st8; - } else if ( (*p) >= 45 ) - goto st0; - goto tr9; -tr9: -#line 339 "parser.rl" - { p--; {p++; cs = 9; goto _out;} } - goto st9; -st9: - if ( ++p == pe ) - goto _test_eof9; -case 9: -#line 1072 "parser.c" - goto st0; -st5: - if ( ++p == pe ) - goto _test_eof5; -case 5: - switch( (*p) ) { - case 43: goto st6; - case 45: goto st6; - } - if ( 48 <= (*p) && (*p) <= 57 ) - goto st10; - goto st0; -st6: - if ( ++p == pe ) - goto _test_eof6; -case 6: - if ( 48 <= (*p) && (*p) <= 57 ) - goto st10; - goto st0; -st10: - if ( ++p == pe ) - goto _test_eof10; -case 10: - switch( (*p) ) { - case 69: goto st0; - case 101: goto st0; - } - if ( (*p) > 46 ) { - if ( 48 <= (*p) && (*p) <= 57 ) - goto st10; - } else if ( (*p) >= 45 ) - goto st0; - goto tr9; -st7: - if ( ++p == pe ) - goto _test_eof7; -case 7: - switch( (*p) ) { - case 46: goto st4; - case 69: goto st5; - case 101: goto st5; - } - if ( 48 <= (*p) && (*p) <= 57 ) - goto st7; - goto st0; - } - _test_eof2: cs = 2; goto _test_eof; - _test_eof3: cs = 3; goto _test_eof; - _test_eof4: cs = 4; goto _test_eof; - _test_eof8: cs = 8; goto _test_eof; - _test_eof9: cs = 9; goto _test_eof; - _test_eof5: cs = 5; goto _test_eof; - _test_eof6: cs = 6; goto _test_eof; - _test_eof10: cs = 10; goto _test_eof; - _test_eof7: cs = 7; goto _test_eof; - - _test_eof: {} - _out: {} - } - -#line 354 "parser.rl" - - if (cs >= JSON_float_first_final) { - VALUE mod = Qnil; - ID method_id = 0; - if (rb_respond_to(json->decimal_class, i_try_convert)) { - mod = json->decimal_class; - method_id = i_try_convert; - } else if (rb_respond_to(json->decimal_class, i_new)) { - mod = json->decimal_class; - method_id = i_new; - } else if (RB_TYPE_P(json->decimal_class, T_CLASS)) { - VALUE name = rb_class_name(json->decimal_class); - const char *name_cstr = RSTRING_PTR(name); - const char *last_colon = strrchr(name_cstr, ':'); - if (last_colon) { - const char *mod_path_end = last_colon - 1; - VALUE mod_path = rb_str_substr(name, 0, mod_path_end - name_cstr); - mod = rb_path_to_class(mod_path); - - const char *method_name_beg = last_colon + 1; - long before_len = method_name_beg - name_cstr; - long len = RSTRING_LEN(name) - before_len; - VALUE method_name = rb_str_substr(name, before_len, len); - method_id = SYM2ID(rb_str_intern(method_name)); - } else { - mod = rb_mKernel; - method_id = SYM2ID(rb_str_intern(name)); - } +#elif defined(HAVE_SIMD_SSE2) + if (simd_impl == SIMD_SSE2) { + int mask = 0; + if (string_scan_simd_sse2(&state->cursor, state->end, &mask)) { + state->cursor += trailing_zeros(mask); + return 1; } + } +#endif /* HAVE_SIMD_NEON or HAVE_SIMD_SSE2 */ +#endif /* HAVE_SIMD */ - long len = p - json->memo; - fbuffer_clear(json->fbuffer); - fbuffer_append(json->fbuffer, json->memo, len); - fbuffer_append_char(json->fbuffer, '\0'); + while (state->cursor < state->end) { + if (RB_UNLIKELY(string_scan_table[(unsigned char)*state->cursor])) { + return 1; + } + *state->cursor++; + } + return 0; +} - if (method_id) { - VALUE text = rb_str_new2(FBUFFER_PTR(json->fbuffer)); - *result = rb_funcallv(mod, method_id, 1, &text); - } else { - *result = DBL2NUM(rb_cstr_to_dbl(FBUFFER_PTR(json->fbuffer), 1)); +static inline VALUE json_parse_string(JSON_ParserState *state, JSON_ParserConfig *config, bool is_name) +{ + state->cursor++; + const char *start = state->cursor; + bool escaped = false; + + while (RB_UNLIKELY(string_scan(state))) { + switch (*state->cursor) { + case '"': { + VALUE string = json_decode_string(state, config, start, state->cursor, escaped, is_name); + state->cursor++; + return json_push_value(state, config, string); + } + case '\\': { + state->cursor++; + escaped = true; + if ((unsigned char)*state->cursor < 0x20) { + raise_parse_error("invalid ASCII control character in string: %s", state); + } + break; + } + default: + raise_parse_error("invalid ASCII control character in string: %s", state); + break; } - return p + 1; - } else { - return NULL; + state->cursor++; } + + raise_parse_error("unexpected end of input, expected closing \"", state); + return Qfalse; } +static VALUE json_parse_any(JSON_ParserState *state, JSON_ParserConfig *config) +{ + json_eat_whitespace(state); + if (state->cursor >= state->end) { + raise_parse_error("unexpected end of input", state); + } + switch (*state->cursor) { + case 'n': + if ((state->end - state->cursor >= 4) && (memcmp(state->cursor, "null", 4) == 0)) { + state->cursor += 4; + return json_push_value(state, config, Qnil); + } -#line 1184 "parser.c" -enum {JSON_array_start = 1}; -enum {JSON_array_first_final = 17}; -enum {JSON_array_error = 0}; + raise_parse_error("unexpected token %s", state); + break; + case 't': + if ((state->end - state->cursor >= 4) && (memcmp(state->cursor, "true", 4) == 0)) { + state->cursor += 4; + return json_push_value(state, config, Qtrue); + } -enum {JSON_array_en_main = 1}; + raise_parse_error("unexpected token %s", state); + break; + case 'f': + // Note: memcmp with a small power of two compile to an integer comparison + if ((state->end - state->cursor >= 5) && (memcmp(state->cursor + 1, "alse", 4) == 0)) { + state->cursor += 5; + return json_push_value(state, config, Qfalse); + } + raise_parse_error("unexpected token %s", state); + break; + case 'N': + // Note: memcmp with a small power of two compile to an integer comparison + if (config->allow_nan && (state->end - state->cursor >= 3) && (memcmp(state->cursor + 1, "aN", 2) == 0)) { + state->cursor += 3; + return json_push_value(state, config, CNaN); + } -#line 432 "parser.rl" + raise_parse_error("unexpected token %s", state); + break; + case 'I': + if (config->allow_nan && (state->end - state->cursor >= 8) && (memcmp(state->cursor, "Infinity", 8) == 0)) { + state->cursor += 8; + return json_push_value(state, config, CInfinity); + } + raise_parse_error("unexpected token %s", state); + break; + case '-': + // Note: memcmp with a small power of two compile to an integer comparison + if ((state->end - state->cursor >= 9) && (memcmp(state->cursor + 1, "Infinity", 8) == 0)) { + if (config->allow_nan) { + state->cursor += 9; + return json_push_value(state, config, CMinusInfinity); + } else { + raise_parse_error("unexpected token %s", state); + } + } + // Fallthrough + case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { + bool integer = true; -static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting) -{ - int cs = EVIL; - VALUE array_class = json->array_class; + // /\A-?(0|[1-9]\d*)(\.\d+)?([Ee][-+]?\d+)?/ + const char *start = state->cursor; + state->cursor++; - if (json->max_nesting && current_nesting > json->max_nesting) { - rb_raise(eNestingError, "nesting of %d is too deep", current_nesting); - } - *result = NIL_P(array_class) ? rb_ary_new() : rb_class_new_instance(0, 0, array_class); - - -#line 1206 "parser.c" - { - cs = JSON_array_start; - } - -#line 445 "parser.rl" - -#line 1213 "parser.c" - { - if ( p == pe ) - goto _test_eof; - switch ( cs ) - { -case 1: - if ( (*p) == 91 ) - goto st2; - goto st0; -st0: -cs = 0; - goto _out; -st2: - if ( ++p == pe ) - goto _test_eof2; -case 2: - switch( (*p) ) { - case 13: goto st2; - case 32: goto st2; - case 34: goto tr2; - case 45: goto tr2; - case 47: goto st13; - case 73: goto tr2; - case 78: goto tr2; - case 91: goto tr2; - case 93: goto tr4; - case 102: goto tr2; - case 110: goto tr2; - case 116: goto tr2; - case 123: goto tr2; - } - if ( (*p) > 10 ) { - if ( 48 <= (*p) && (*p) <= 57 ) - goto tr2; - } else if ( (*p) >= 9 ) - goto st2; - goto st0; -tr2: -#line 409 "parser.rl" - { - VALUE v = Qnil; - char *np = JSON_parse_value(json, p, pe, &v, current_nesting); - if (np == NULL) { - p--; {p++; cs = 3; goto _out;} - } else { - if (NIL_P(json->array_class)) { - rb_ary_push(*result, v); - } else { - rb_funcall(*result, i_leftshift, 1, v); + while ((state->cursor < state->end) && (*state->cursor >= '0') && (*state->cursor <= '9')) { + state->cursor++; } - {p = (( np))-1;} - } - } - goto st3; -st3: - if ( ++p == pe ) - goto _test_eof3; -case 3: -#line 1272 "parser.c" - switch( (*p) ) { - case 13: goto st3; - case 32: goto st3; - case 44: goto st4; - case 47: goto st9; - case 93: goto tr4; - } - if ( 9 <= (*p) && (*p) <= 10 ) - goto st3; - goto st0; -st4: - if ( ++p == pe ) - goto _test_eof4; -case 4: - switch( (*p) ) { - case 13: goto st4; - case 32: goto st4; - case 34: goto tr2; - case 45: goto tr2; - case 47: goto st5; - case 73: goto tr2; - case 78: goto tr2; - case 91: goto tr2; - case 102: goto tr2; - case 110: goto tr2; - case 116: goto tr2; - case 123: goto tr2; - } - if ( (*p) > 10 ) { - if ( 48 <= (*p) && (*p) <= 57 ) - goto tr2; - } else if ( (*p) >= 9 ) - goto st4; - goto st0; -st5: - if ( ++p == pe ) - goto _test_eof5; -case 5: - switch( (*p) ) { - case 42: goto st6; - case 47: goto st8; - } - goto st0; -st6: - if ( ++p == pe ) - goto _test_eof6; -case 6: - if ( (*p) == 42 ) - goto st7; - goto st6; -st7: - if ( ++p == pe ) - goto _test_eof7; -case 7: - switch( (*p) ) { - case 42: goto st7; - case 47: goto st4; - } - goto st6; -st8: - if ( ++p == pe ) - goto _test_eof8; -case 8: - if ( (*p) == 10 ) - goto st4; - goto st8; -st9: - if ( ++p == pe ) - goto _test_eof9; -case 9: - switch( (*p) ) { - case 42: goto st10; - case 47: goto st12; - } - goto st0; -st10: - if ( ++p == pe ) - goto _test_eof10; -case 10: - if ( (*p) == 42 ) - goto st11; - goto st10; -st11: - if ( ++p == pe ) - goto _test_eof11; -case 11: - switch( (*p) ) { - case 42: goto st11; - case 47: goto st3; - } - goto st10; -st12: - if ( ++p == pe ) - goto _test_eof12; -case 12: - if ( (*p) == 10 ) - goto st3; - goto st12; -tr4: -#line 424 "parser.rl" - { p--; {p++; cs = 17; goto _out;} } - goto st17; -st17: - if ( ++p == pe ) - goto _test_eof17; -case 17: -#line 1379 "parser.c" - goto st0; -st13: - if ( ++p == pe ) - goto _test_eof13; -case 13: - switch( (*p) ) { - case 42: goto st14; - case 47: goto st16; - } - goto st0; -st14: - if ( ++p == pe ) - goto _test_eof14; -case 14: - if ( (*p) == 42 ) - goto st15; - goto st14; -st15: - if ( ++p == pe ) - goto _test_eof15; -case 15: - switch( (*p) ) { - case 42: goto st15; - case 47: goto st2; - } - goto st14; -st16: - if ( ++p == pe ) - goto _test_eof16; -case 16: - if ( (*p) == 10 ) - goto st2; - goto st16; - } - _test_eof2: cs = 2; goto _test_eof; - _test_eof3: cs = 3; goto _test_eof; - _test_eof4: cs = 4; goto _test_eof; - _test_eof5: cs = 5; goto _test_eof; - _test_eof6: cs = 6; goto _test_eof; - _test_eof7: cs = 7; goto _test_eof; - _test_eof8: cs = 8; goto _test_eof; - _test_eof9: cs = 9; goto _test_eof; - _test_eof10: cs = 10; goto _test_eof; - _test_eof11: cs = 11; goto _test_eof; - _test_eof12: cs = 12; goto _test_eof; - _test_eof17: cs = 17; goto _test_eof; - _test_eof13: cs = 13; goto _test_eof; - _test_eof14: cs = 14; goto _test_eof; - _test_eof15: cs = 15; goto _test_eof; - _test_eof16: cs = 16; goto _test_eof; - - _test_eof: {} - _out: {} - } - -#line 446 "parser.rl" - - if(cs >= JSON_array_first_final) { - return p + 1; - } else { - rb_enc_raise(EXC_ENCODING eParserError, "unexpected token at '%s'", p); - return NULL; - } -} -static const size_t MAX_STACK_BUFFER_SIZE = 128; -static VALUE json_string_unescape(char *string, char *stringEnd, int intern, int symbolize) -{ - VALUE result = Qnil; - size_t bufferSize = stringEnd - string; - char *p = string, *pe = string, *unescape, *bufferStart, *buffer; - int unescape_len; - char buf[4]; + long integer_length = state->cursor - start; - if (bufferSize > MAX_STACK_BUFFER_SIZE) { -# ifdef HAVE_RB_ENC_INTERNED_STR - bufferStart = buffer = ALLOC_N(char, bufferSize ? bufferSize : 1); -# else - bufferStart = buffer = ALLOC_N(char, bufferSize); -# endif - } else { -# ifdef HAVE_RB_ENC_INTERNED_STR - bufferStart = buffer = ALLOCA_N(char, bufferSize ? bufferSize : 1); -# else - bufferStart = buffer = ALLOCA_N(char, bufferSize); -# endif - } + if (RB_UNLIKELY(start[0] == '0' && integer_length > 1)) { + raise_parse_error_at("invalid number: %s", state, start); + } else if (RB_UNLIKELY(integer_length > 2 && start[0] == '-' && start[1] == '0')) { + raise_parse_error_at("invalid number: %s", state, start); + } else if (RB_UNLIKELY(integer_length == 1 && start[0] == '-')) { + raise_parse_error_at("invalid number: %s", state, start); + } + + if ((state->cursor < state->end) && (*state->cursor == '.')) { + integer = false; + state->cursor++; + + if (state->cursor == state->end || *state->cursor < '0' || *state->cursor > '9') { + raise_parse_error("invalid number: %s", state); + } - while (pe < stringEnd) { - if (*pe == '\\') { - unescape = (char *) "?"; - unescape_len = 1; - if (pe > p) { - MEMCPY(buffer, p, char, pe - p); - buffer += pe - p; + while ((state->cursor < state->end) && (*state->cursor >= '0') && (*state->cursor <= '9')) { + state->cursor++; + } } - switch (*++pe) { - case 'n': - unescape = (char *) "\n"; - break; - case 'r': - unescape = (char *) "\r"; - break; - case 't': - unescape = (char *) "\t"; - break; - case '"': - unescape = (char *) "\""; - break; - case '\\': - unescape = (char *) "\\"; - break; - case 'b': - unescape = (char *) "\b"; - break; - case 'f': - unescape = (char *) "\f"; - break; - case 'u': - if (pe > stringEnd - 4) { - if (bufferSize > MAX_STACK_BUFFER_SIZE) { - free(bufferStart); - } - rb_enc_raise( - EXC_ENCODING eParserError, - "incomplete unicode character escape sequence at '%s'", p - ); - } else { - UTF32 ch = unescape_unicode((unsigned char *) ++pe); - pe += 3; - if (UNI_SUR_HIGH_START == (ch & 0xFC00)) { - pe++; - if (pe > stringEnd - 6) { - if (bufferSize > MAX_STACK_BUFFER_SIZE) { - free(bufferStart); - } - rb_enc_raise( - EXC_ENCODING eParserError, - "incomplete surrogate pair at '%s'", p - ); - } - if (pe[0] == '\\' && pe[1] == 'u') { - UTF32 sur = unescape_unicode((unsigned char *) pe + 2); - ch = (((ch & 0x3F) << 10) | ((((ch >> 6) & 0xF) + 1) << 16) - | (sur & 0x3FF)); - pe += 5; - } else { - unescape = (char *) "?"; - break; + + if ((state->cursor < state->end) && ((*state->cursor == 'e') || (*state->cursor == 'E'))) { + integer = false; + state->cursor++; + if ((state->cursor < state->end) && ((*state->cursor == '+') || (*state->cursor == '-'))) { + state->cursor++; + } + + if (state->cursor == state->end || *state->cursor < '0' || *state->cursor > '9') { + raise_parse_error("invalid number: %s", state); + } + + while ((state->cursor < state->end) && (*state->cursor >= '0') && (*state->cursor <= '9')) { + state->cursor++; + } + } + + if (integer) { + return json_push_value(state, config, json_decode_integer(start, state->cursor)); + } + return json_push_value(state, config, json_decode_float(config, start, state->cursor)); + } + case '"': { + // %r{\A"[^"\\\t\n\x00]*(?:\\[bfnrtu\\/"][^"\\]*)*"} + return json_parse_string(state, config, false); + break; + } + case '[': { + state->cursor++; + json_eat_whitespace(state); + long stack_head = state->stack->head; + + if ((state->cursor < state->end) && (*state->cursor == ']')) { + state->cursor++; + return json_push_value(state, config, json_decode_array(state, config, 0)); + } else { + state->current_nesting++; + if (RB_UNLIKELY(config->max_nesting && (config->max_nesting < state->current_nesting))) { + rb_raise(eNestingError, "nesting of %d is too deep", state->current_nesting); + } + state->in_array++; + json_parse_any(state, config); + } + + while (true) { + json_eat_whitespace(state); + + if (state->cursor < state->end) { + if (*state->cursor == ']') { + state->cursor++; + long count = state->stack->head - stack_head; + state->current_nesting--; + state->in_array--; + return json_push_value(state, config, json_decode_array(state, config, count)); + } + + if (*state->cursor == ',') { + state->cursor++; + if (config->allow_trailing_comma) { + json_eat_whitespace(state); + if ((state->cursor < state->end) && (*state->cursor == ']')) { + continue; } } - unescape_len = convert_UTF32_to_UTF8(buf, ch); - unescape = buf; + json_parse_any(state, config); + continue; } - break; - default: - p = pe; - continue; + } + + raise_parse_error("expected ',' or ']' after array value", state); } - MEMCPY(buffer, unescape, char, unescape_len); - buffer += unescape_len; - p = ++pe; - } else { - pe++; + break; } - } + case '{': { + const char *object_start_cursor = state->cursor; - if (pe > p) { - MEMCPY(buffer, p, char, pe - p); - buffer += pe - p; - } + state->cursor++; + json_eat_whitespace(state); + long stack_head = state->stack->head; -# ifdef HAVE_RB_ENC_INTERNED_STR - if (intern) { - result = rb_enc_interned_str(bufferStart, (long)(buffer - bufferStart), rb_utf8_encoding()); - } else { - result = rb_utf8_str_new(bufferStart, (long)(buffer - bufferStart)); - } - if (bufferSize > MAX_STACK_BUFFER_SIZE) { - free(bufferStart); - } -# else - result = rb_utf8_str_new(bufferStart, (long)(buffer - bufferStart)); + if ((state->cursor < state->end) && (*state->cursor == '}')) { + state->cursor++; + return json_push_value(state, config, json_decode_object(state, config, 0)); + } else { + state->current_nesting++; + if (RB_UNLIKELY(config->max_nesting && (config->max_nesting < state->current_nesting))) { + rb_raise(eNestingError, "nesting of %d is too deep", state->current_nesting); + } - if (bufferSize > MAX_STACK_BUFFER_SIZE) { - free(bufferStart); - } + if (*state->cursor != '"') { + raise_parse_error("expected object key, got %s", state); + } + json_parse_string(state, config, true); - if (intern) { - # if STR_UMINUS_DEDUPE_FROZEN - // Starting from MRI 2.8 it is preferable to freeze the string - // before deduplication so that it can be interned directly - // otherwise it would be duplicated first which is wasteful. - result = rb_funcall(rb_str_freeze(result), i_uminus, 0); - # elif STR_UMINUS_DEDUPE - // MRI 2.5 and older do not deduplicate strings that are already - // frozen. - result = rb_funcall(result, i_uminus, 0); - # else - result = rb_str_freeze(result); - # endif - } -# endif + json_eat_whitespace(state); + if ((state->cursor >= state->end) || (*state->cursor != ':')) { + raise_parse_error("expected ':' after object key", state); + } + state->cursor++; - if (symbolize) { - result = rb_str_intern(result); - } + json_parse_any(state, config); + } - return result; -} + while (true) { + json_eat_whitespace(state); + if (state->cursor < state->end) { + if (*state->cursor == '}') { + state->cursor++; + state->current_nesting--; + size_t count = state->stack->head - stack_head; -#line 1592 "parser.c" -enum {JSON_string_start = 1}; -enum {JSON_string_first_final = 8}; -enum {JSON_string_error = 0}; + // Temporary rewind cursor in case an error is raised + const char *final_cursor = state->cursor; + state->cursor = object_start_cursor; + VALUE object = json_decode_object(state, config, count); + state->cursor = final_cursor; -enum {JSON_string_en_main = 1}; + return json_push_value(state, config, object); + } + if (*state->cursor == ',') { + state->cursor++; + json_eat_whitespace(state); -#line 620 "parser.rl" + if (config->allow_trailing_comma) { + if ((state->cursor < state->end) && (*state->cursor == '}')) { + continue; + } + } + if (*state->cursor != '"') { + raise_parse_error("expected object key, got: %s", state); + } + json_parse_string(state, config, true); -static int -match_i(VALUE regexp, VALUE klass, VALUE memo) -{ - if (regexp == Qundef) return ST_STOP; - if (RTEST(rb_funcall(klass, i_json_creatable_p, 0)) && - RTEST(rb_funcall(regexp, i_match, 1, rb_ary_entry(memo, 0)))) { - rb_ary_push(memo, klass); - return ST_STOP; - } - return ST_CONTINUE; -} + json_eat_whitespace(state); + if ((state->cursor >= state->end) || (*state->cursor != ':')) { + raise_parse_error("expected ':' after object key, got: %s", state); + } + state->cursor++; -static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *result) -{ - int cs = EVIL; - VALUE match_string; - - -#line 1621 "parser.c" - { - cs = JSON_string_start; - } - -#line 640 "parser.rl" - json->memo = p; - -#line 1629 "parser.c" - { - if ( p == pe ) - goto _test_eof; - switch ( cs ) - { -case 1: - if ( (*p) == 34 ) - goto st2; - goto st0; -st0: -cs = 0; - goto _out; -st2: - if ( ++p == pe ) - goto _test_eof2; -case 2: - switch( (*p) ) { - case 34: goto tr2; - case 92: goto st3; - } - if ( 0 <= (signed char)(*(p)) && (*(p)) <= 31 ) - goto st0; - goto st2; -tr2: -#line 607 "parser.rl" - { - *result = json_string_unescape(json->memo + 1, p, json->parsing_name || json-> freeze, json->parsing_name && json->symbolize_names); - if (NIL_P(*result)) { - p--; - {p++; cs = 8; goto _out;} - } else { - {p = (( p + 1))-1;} + json_parse_any(state, config); + + continue; + } + } + + raise_parse_error("expected ',' or '}' after object value, got: %s", state); + } + break; } - } -#line 617 "parser.rl" - { p--; {p++; cs = 8; goto _out;} } - goto st8; -st8: - if ( ++p == pe ) - goto _test_eof8; -case 8: -#line 1671 "parser.c" - goto st0; -st3: - if ( ++p == pe ) - goto _test_eof3; -case 3: - if ( (*p) == 117 ) - goto st4; - if ( 0 <= (signed char)(*(p)) && (*(p)) <= 31 ) - goto st0; - goto st2; -st4: - if ( ++p == pe ) - goto _test_eof4; -case 4: - if ( (*p) < 65 ) { - if ( 48 <= (*p) && (*p) <= 57 ) - goto st5; - } else if ( (*p) > 70 ) { - if ( 97 <= (*p) && (*p) <= 102 ) - goto st5; - } else - goto st5; - goto st0; -st5: - if ( ++p == pe ) - goto _test_eof5; -case 5: - if ( (*p) < 65 ) { - if ( 48 <= (*p) && (*p) <= 57 ) - goto st6; - } else if ( (*p) > 70 ) { - if ( 97 <= (*p) && (*p) <= 102 ) - goto st6; - } else - goto st6; - goto st0; -st6: - if ( ++p == pe ) - goto _test_eof6; -case 6: - if ( (*p) < 65 ) { - if ( 48 <= (*p) && (*p) <= 57 ) - goto st7; - } else if ( (*p) > 70 ) { - if ( 97 <= (*p) && (*p) <= 102 ) - goto st7; - } else - goto st7; - goto st0; -st7: - if ( ++p == pe ) - goto _test_eof7; -case 7: - if ( (*p) < 65 ) { - if ( 48 <= (*p) && (*p) <= 57 ) - goto st2; - } else if ( (*p) > 70 ) { - if ( 97 <= (*p) && (*p) <= 102 ) - goto st2; - } else - goto st2; - goto st0; - } - _test_eof2: cs = 2; goto _test_eof; - _test_eof8: cs = 8; goto _test_eof; - _test_eof3: cs = 3; goto _test_eof; - _test_eof4: cs = 4; goto _test_eof; - _test_eof5: cs = 5; goto _test_eof; - _test_eof6: cs = 6; goto _test_eof; - _test_eof7: cs = 7; goto _test_eof; - - _test_eof: {} - _out: {} - } - -#line 642 "parser.rl" - - if (json->create_additions && RTEST(match_string = json->match_string)) { - VALUE klass; - VALUE memo = rb_ary_new2(2); - rb_ary_push(memo, *result); - rb_hash_foreach(match_string, match_i, memo); - klass = rb_ary_entry(memo, 1); - if (RTEST(klass)) { - *result = rb_funcall(klass, i_json_create, 1, *result); - } + + default: + raise_parse_error("unexpected character: %s", state); + break; } - if (cs >= JSON_string_first_final) { - return p + 1; - } else { - return NULL; + raise_parse_error("unreacheable: %s", state); +} + +static void json_ensure_eof(JSON_ParserState *state) +{ + json_eat_whitespace(state); + if (state->cursor != state->end) { + raise_parse_error("unexpected token at end of stream %s", state); } } @@ -1777,24 +1245,83 @@ case 7: static VALUE convert_encoding(VALUE source) { -#ifdef HAVE_RUBY_ENCODING_H - rb_encoding *enc = rb_enc_get(source); - if (enc == rb_ascii8bit_encoding()) { - if (OBJ_FROZEN(source)) { - source = rb_str_dup(source); - } - FORCE_UTF8(source); - } else { - source = rb_str_conv_enc(source, rb_enc_get(source), rb_utf8_encoding()); - } -#endif + int encindex = RB_ENCODING_GET(source); + + if (RB_LIKELY(encindex == utf8_encindex)) { return source; + } + + if (encindex == binary_encindex) { + // For historical reason, we silently reinterpret binary strings as UTF-8 + return rb_enc_associate_index(rb_str_dup(source), utf8_encindex); + } + + return rb_funcall(source, i_encode, 1, Encoding_UTF_8); +} + +static int parser_config_init_i(VALUE key, VALUE val, VALUE data) +{ + JSON_ParserConfig *config = (JSON_ParserConfig *)data; + + if (key == sym_max_nesting) { config->max_nesting = RTEST(val) ? FIX2INT(val) : 0; } + else if (key == sym_allow_nan) { config->allow_nan = RTEST(val); } + else if (key == sym_allow_trailing_comma) { config->allow_trailing_comma = RTEST(val); } + else if (key == sym_symbolize_names) { config->symbolize_names = RTEST(val); } + else if (key == sym_freeze) { config->freeze = RTEST(val); } + else if (key == sym_on_load) { config->on_load_proc = RTEST(val) ? val : Qfalse; } + else if (key == sym_allow_duplicate_key) { config->on_duplicate_key = RTEST(val) ? JSON_IGNORE : JSON_RAISE; } + else if (key == sym_decimal_class) { + if (RTEST(val)) { + if (rb_respond_to(val, i_try_convert)) { + config->decimal_class = val; + config->decimal_method_id = i_try_convert; + } else if (rb_respond_to(val, i_new)) { + config->decimal_class = val; + config->decimal_method_id = i_new; + } else if (RB_TYPE_P(val, T_CLASS)) { + VALUE name = rb_class_name(val); + const char *name_cstr = RSTRING_PTR(name); + const char *last_colon = strrchr(name_cstr, ':'); + if (last_colon) { + const char *mod_path_end = last_colon - 1; + VALUE mod_path = rb_str_substr(name, 0, mod_path_end - name_cstr); + config->decimal_class = rb_path_to_class(mod_path); + + const char *method_name_beg = last_colon + 1; + long before_len = method_name_beg - name_cstr; + long len = RSTRING_LEN(name) - before_len; + VALUE method_name = rb_str_substr(name, before_len, len); + config->decimal_method_id = SYM2ID(rb_str_intern(method_name)); + } else { + config->decimal_class = rb_mKernel; + config->decimal_method_id = SYM2ID(rb_str_intern(name)); + } + } + } + } + + return ST_CONTINUE; +} + +static void parser_config_init(JSON_ParserConfig *config, VALUE opts) +{ + config->max_nesting = 100; + + if (!NIL_P(opts)) { + Check_Type(opts, T_HASH); + if (RHASH_SIZE(opts) > 0) { + // We assume in most cases few keys are set so it's faster to go over + // the provided keys than to check all possible keys. + rb_hash_foreach(opts, parser_config_init_i, (VALUE)config); + } + + } } /* - * call-seq: new(source, opts => {}) + * call-seq: new(opts => {}) * - * Creates a new JSON::Ext::Parser instance for the string _source_. + * Creates a new JSON::Ext::ParserConfig instance. * * It will be configured by the _opts_ hash. _opts_ can have the following * keys: @@ -1810,343 +1337,114 @@ static VALUE convert_encoding(VALUE source) * (keys) in a JSON object. Otherwise strings are returned, which is * also the default. It's not possible to use this option in * conjunction with the *create_additions* option. - * * *create_additions*: If set to false, the Parser doesn't create - * additions even if a matching class and create_id was found. This option - * defaults to false. - * * *object_class*: Defaults to Hash - * * *array_class*: Defaults to Array + * * *decimal_class*: Specifies which class to use instead of the default + * (Float) when parsing decimal numbers. This class must accept a single + * string argument in its constructor. */ -static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self) +static VALUE cParserConfig_initialize(VALUE self, VALUE opts) { - VALUE source, opts; - GET_PARSER_INIT; + GET_PARSER_CONFIG; + + parser_config_init(config, opts); + + RB_OBJ_WRITTEN(self, Qundef, config->decimal_class); - if (json->Vsource) { - rb_raise(rb_eTypeError, "already initialized instance"); - } - rb_scan_args(argc, argv, "1:", &source, &opts); - if (!NIL_P(opts)) { - VALUE tmp = ID2SYM(i_max_nesting); - if (option_given_p(opts, tmp)) { - VALUE max_nesting = rb_hash_aref(opts, tmp); - if (RTEST(max_nesting)) { - Check_Type(max_nesting, T_FIXNUM); - json->max_nesting = FIX2INT(max_nesting); - } else { - json->max_nesting = 0; - } - } else { - json->max_nesting = 100; - } - tmp = ID2SYM(i_allow_nan); - if (option_given_p(opts, tmp)) { - json->allow_nan = RTEST(rb_hash_aref(opts, tmp)) ? 1 : 0; - } else { - json->allow_nan = 0; - } - tmp = ID2SYM(i_symbolize_names); - if (option_given_p(opts, tmp)) { - json->symbolize_names = RTEST(rb_hash_aref(opts, tmp)) ? 1 : 0; - } else { - json->symbolize_names = 0; - } - tmp = ID2SYM(i_freeze); - if (option_given_p(opts, tmp)) { - json->freeze = RTEST(rb_hash_aref(opts, tmp)) ? 1 : 0; - } else { - json->freeze = 0; - } - tmp = ID2SYM(i_create_additions); - if (option_given_p(opts, tmp)) { - json->create_additions = RTEST(rb_hash_aref(opts, tmp)); - } else { - json->create_additions = 0; - } - if (json->symbolize_names && json->create_additions) { - rb_raise(rb_eArgError, - "options :symbolize_names and :create_additions cannot be " - " used in conjunction"); - } - tmp = ID2SYM(i_create_id); - if (option_given_p(opts, tmp)) { - json->create_id = rb_hash_aref(opts, tmp); - } else { - json->create_id = rb_funcall(mJSON, i_create_id, 0); - } - tmp = ID2SYM(i_object_class); - if (option_given_p(opts, tmp)) { - json->object_class = rb_hash_aref(opts, tmp); - } else { - json->object_class = Qnil; - } - tmp = ID2SYM(i_array_class); - if (option_given_p(opts, tmp)) { - json->array_class = rb_hash_aref(opts, tmp); - } else { - json->array_class = Qnil; - } - tmp = ID2SYM(i_decimal_class); - if (option_given_p(opts, tmp)) { - json->decimal_class = rb_hash_aref(opts, tmp); - } else { - json->decimal_class = Qnil; - } - tmp = ID2SYM(i_match_string); - if (option_given_p(opts, tmp)) { - VALUE match_string = rb_hash_aref(opts, tmp); - json->match_string = RTEST(match_string) ? match_string : Qnil; - } else { - json->match_string = Qnil; - } - } else { - json->max_nesting = 100; - json->allow_nan = 0; - json->create_additions = 0; - json->create_id = rb_funcall(mJSON, i_create_id, 0); - json->object_class = Qnil; - json->array_class = Qnil; - json->decimal_class = Qnil; - } - source = convert_encoding(StringValue(source)); - StringValue(source); - json->len = RSTRING_LEN(source); - json->source = RSTRING_PTR(source);; - json->Vsource = source; return self; } +static VALUE cParser_parse(JSON_ParserConfig *config, VALUE Vsource) +{ + Vsource = convert_encoding(StringValue(Vsource)); + StringValue(Vsource); + + VALUE rvalue_stack_buffer[RVALUE_STACK_INITIAL_CAPA]; + rvalue_stack stack = { + .type = RVALUE_STACK_STACK_ALLOCATED, + .ptr = rvalue_stack_buffer, + .capa = RVALUE_STACK_INITIAL_CAPA, + }; + + long len; + const char *start; + RSTRING_GETMEM(Vsource, start, len); -#line 1920 "parser.c" -enum {JSON_start = 1}; -enum {JSON_first_final = 10}; -enum {JSON_error = 0}; + JSON_ParserState _state = { + .start = start, + .cursor = start, + .end = start + len, + .stack = &stack, + }; + JSON_ParserState *state = &_state; -enum {JSON_en_main = 1}; + VALUE result = json_parse_any(state, config); + // This may be skipped in case of exception, but + // it won't cause a leak. + rvalue_stack_eagerly_release(state->stack_handle); -#line 828 "parser.rl" + json_ensure_eof(state); + return result; +} /* - * call-seq: parse() + * call-seq: parse(source) * * Parses the current JSON text _source_ and returns the complete data * structure as a result. * It raises JSON::ParserError if fail to parse. */ -static VALUE cParser_parse(VALUE self) +static VALUE cParserConfig_parse(VALUE self, VALUE Vsource) { - char *p, *pe; - int cs = EVIL; - VALUE result = Qnil; - GET_PARSER; - - -#line 1946 "parser.c" - { - cs = JSON_start; - } - -#line 845 "parser.rl" - p = json->source; - pe = p + json->len; - -#line 1955 "parser.c" - { - if ( p == pe ) - goto _test_eof; - switch ( cs ) - { -st1: - if ( ++p == pe ) - goto _test_eof1; -case 1: - switch( (*p) ) { - case 13: goto st1; - case 32: goto st1; - case 34: goto tr2; - case 45: goto tr2; - case 47: goto st6; - case 73: goto tr2; - case 78: goto tr2; - case 91: goto tr2; - case 102: goto tr2; - case 110: goto tr2; - case 116: goto tr2; - case 123: goto tr2; - } - if ( (*p) > 10 ) { - if ( 48 <= (*p) && (*p) <= 57 ) - goto tr2; - } else if ( (*p) >= 9 ) - goto st1; - goto st0; -st0: -cs = 0; - goto _out; -tr2: -#line 820 "parser.rl" - { - char *np = JSON_parse_value(json, p, pe, &result, 0); - if (np == NULL) { p--; {p++; cs = 10; goto _out;} } else {p = (( np))-1;} - } - goto st10; -st10: - if ( ++p == pe ) - goto _test_eof10; -case 10: -#line 1999 "parser.c" - switch( (*p) ) { - case 13: goto st10; - case 32: goto st10; - case 47: goto st2; - } - if ( 9 <= (*p) && (*p) <= 10 ) - goto st10; - goto st0; -st2: - if ( ++p == pe ) - goto _test_eof2; -case 2: - switch( (*p) ) { - case 42: goto st3; - case 47: goto st5; - } - goto st0; -st3: - if ( ++p == pe ) - goto _test_eof3; -case 3: - if ( (*p) == 42 ) - goto st4; - goto st3; -st4: - if ( ++p == pe ) - goto _test_eof4; -case 4: - switch( (*p) ) { - case 42: goto st4; - case 47: goto st10; - } - goto st3; -st5: - if ( ++p == pe ) - goto _test_eof5; -case 5: - if ( (*p) == 10 ) - goto st10; - goto st5; -st6: - if ( ++p == pe ) - goto _test_eof6; -case 6: - switch( (*p) ) { - case 42: goto st7; - case 47: goto st9; - } - goto st0; -st7: - if ( ++p == pe ) - goto _test_eof7; -case 7: - if ( (*p) == 42 ) - goto st8; - goto st7; -st8: - if ( ++p == pe ) - goto _test_eof8; -case 8: - switch( (*p) ) { - case 42: goto st8; - case 47: goto st1; - } - goto st7; -st9: - if ( ++p == pe ) - goto _test_eof9; -case 9: - if ( (*p) == 10 ) - goto st1; - goto st9; - } - _test_eof1: cs = 1; goto _test_eof; - _test_eof10: cs = 10; goto _test_eof; - _test_eof2: cs = 2; goto _test_eof; - _test_eof3: cs = 3; goto _test_eof; - _test_eof4: cs = 4; goto _test_eof; - _test_eof5: cs = 5; goto _test_eof; - _test_eof6: cs = 6; goto _test_eof; - _test_eof7: cs = 7; goto _test_eof; - _test_eof8: cs = 8; goto _test_eof; - _test_eof9: cs = 9; goto _test_eof; - - _test_eof: {} - _out: {} - } - -#line 848 "parser.rl" - - if (cs >= JSON_first_final && p == pe) { - return result; - } else { - rb_enc_raise(EXC_ENCODING eParserError, "unexpected token at '%s'", p); - return Qnil; - } + GET_PARSER_CONFIG; + return cParser_parse(config, Vsource); } -static void JSON_mark(void *ptr) +static VALUE cParser_m_parse(VALUE klass, VALUE Vsource, VALUE opts) { - JSON_Parser *json = ptr; - rb_gc_mark_maybe(json->Vsource); - rb_gc_mark_maybe(json->create_id); - rb_gc_mark_maybe(json->object_class); - rb_gc_mark_maybe(json->array_class); - rb_gc_mark_maybe(json->decimal_class); - rb_gc_mark_maybe(json->match_string); + Vsource = convert_encoding(StringValue(Vsource)); + StringValue(Vsource); + + JSON_ParserConfig _config = {0}; + JSON_ParserConfig *config = &_config; + parser_config_init(config, opts); + + return cParser_parse(config, Vsource); +} + +static void JSON_ParserConfig_mark(void *ptr) +{ + JSON_ParserConfig *config = ptr; + rb_gc_mark(config->on_load_proc); + rb_gc_mark(config->decimal_class); } -static void JSON_free(void *ptr) +static void JSON_ParserConfig_free(void *ptr) { - JSON_Parser *json = ptr; - fbuffer_free(json->fbuffer); - ruby_xfree(json); + JSON_ParserConfig *config = ptr; + ruby_xfree(config); } -static size_t JSON_memsize(const void *ptr) +static size_t JSON_ParserConfig_memsize(const void *ptr) { - const JSON_Parser *json = ptr; - return sizeof(*json) + FBUFFER_CAPA(json->fbuffer); + return sizeof(JSON_ParserConfig); } -#ifdef NEW_TYPEDDATA_WRAPPER -static const rb_data_type_t JSON_Parser_type = { - "JSON/Parser", - {JSON_mark, JSON_free, JSON_memsize,}, -#ifdef RUBY_TYPED_FREE_IMMEDIATELY +static const rb_data_type_t JSON_ParserConfig_type = { + "JSON::Ext::Parser/ParserConfig", + { + JSON_ParserConfig_mark, + JSON_ParserConfig_free, + JSON_ParserConfig_memsize, + }, 0, 0, - RUBY_TYPED_FREE_IMMEDIATELY, -#endif + RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED, }; -#endif static VALUE cJSON_parser_s_allocate(VALUE klass) { - JSON_Parser *json; - VALUE obj = TypedData_Make_Struct(klass, JSON_Parser, &JSON_Parser_type, json); - json->fbuffer = fbuffer_alloc(0); - return obj; -} - -/* - * call-seq: source() - * - * Returns a copy of the current _source_ string, that was used to construct - * this Parser. - */ -static VALUE cParser_source(VALUE self) -{ - GET_PARSER; - return rb_str_dup(json->Vsource); + JSON_ParserConfig *config; + return TypedData_Make_Struct(klass, JSON_ParserConfig, &JSON_ParserConfig_type, config); } void Init_parser(void) @@ -2158,16 +1456,16 @@ void Init_parser(void) #undef rb_intern rb_require("json/common"); mJSON = rb_define_module("JSON"); - mExt = rb_define_module_under(mJSON, "Ext"); - cParser = rb_define_class_under(mExt, "Parser", rb_cObject); - eParserError = rb_path2class("JSON::ParserError"); + VALUE mExt = rb_define_module_under(mJSON, "Ext"); + VALUE cParserConfig = rb_define_class_under(mExt, "ParserConfig", rb_cObject); eNestingError = rb_path2class("JSON::NestingError"); - rb_gc_register_mark_object(eParserError); rb_gc_register_mark_object(eNestingError); - rb_define_alloc_func(cParser, cJSON_parser_s_allocate); - rb_define_method(cParser, "initialize", cParser_initialize, -1); - rb_define_method(cParser, "parse", cParser_parse, 0); - rb_define_method(cParser, "source", cParser_source, 0); + rb_define_alloc_func(cParserConfig, cJSON_parser_s_allocate); + rb_define_method(cParserConfig, "initialize", cParserConfig_initialize, 1); + rb_define_method(cParserConfig, "parse", cParserConfig_parse, 1); + + VALUE cParser = rb_define_class_under(mExt, "Parser", rb_cObject); + rb_define_singleton_method(cParser, "parse", cParser_m_parse, 2); CNaN = rb_const_get(mJSON, rb_intern("NaN")); rb_gc_register_mark_object(CNaN); @@ -2178,34 +1476,32 @@ void Init_parser(void) CMinusInfinity = rb_const_get(mJSON, rb_intern("MinusInfinity")); rb_gc_register_mark_object(CMinusInfinity); - i_json_creatable_p = rb_intern("json_creatable?"); - i_json_create = rb_intern("json_create"); - i_create_id = rb_intern("create_id"); - i_create_additions = rb_intern("create_additions"); + rb_global_variable(&Encoding_UTF_8); + Encoding_UTF_8 = rb_const_get(rb_path2class("Encoding"), rb_intern("UTF_8")); + + sym_max_nesting = ID2SYM(rb_intern("max_nesting")); + sym_allow_nan = ID2SYM(rb_intern("allow_nan")); + sym_allow_trailing_comma = ID2SYM(rb_intern("allow_trailing_comma")); + sym_symbolize_names = ID2SYM(rb_intern("symbolize_names")); + sym_freeze = ID2SYM(rb_intern("freeze")); + sym_on_load = ID2SYM(rb_intern("on_load")); + sym_decimal_class = ID2SYM(rb_intern("decimal_class")); + sym_allow_duplicate_key = ID2SYM(rb_intern("allow_duplicate_key")); + i_chr = rb_intern("chr"); - i_max_nesting = rb_intern("max_nesting"); - i_allow_nan = rb_intern("allow_nan"); - i_symbolize_names = rb_intern("symbolize_names"); - i_object_class = rb_intern("object_class"); - i_array_class = rb_intern("array_class"); - i_decimal_class = rb_intern("decimal_class"); - i_match = rb_intern("match"); - i_match_string = rb_intern("match_string"); - i_key_p = rb_intern("key?"); - i_deep_const_get = rb_intern("deep_const_get"); i_aset = rb_intern("[]="); i_aref = rb_intern("[]"); i_leftshift = rb_intern("<<"); i_new = rb_intern("new"); i_try_convert = rb_intern("try_convert"); - i_freeze = rb_intern("freeze"); i_uminus = rb_intern("-@"); -} + i_encode = rb_intern("encode"); -/* - * Local variables: - * mode: c - * c-file-style: ruby - * indent-tabs-mode: nil - * End: - */ + binary_encindex = rb_ascii8bit_encindex(); + utf8_encindex = rb_utf8_encindex(); + enc_utf8 = rb_utf8_encoding(); + +#ifdef HAVE_SIMD + simd_impl = find_simd_implementation(); +#endif +} diff --git a/ext/json/parser/parser.h b/ext/json/parser/parser.h deleted file mode 100644 index 92ed3fdc5dad3c..00000000000000 --- a/ext/json/parser/parser.h +++ /dev/null @@ -1,96 +0,0 @@ -#ifndef _PARSER_H_ -#define _PARSER_H_ - -#include "ruby.h" - -#ifndef HAVE_RUBY_RE_H -#include "re.h" -#endif - -#ifdef HAVE_RUBY_ST_H -#include "ruby/st.h" -#else -#include "st.h" -#endif - -#ifndef MAYBE_UNUSED -# define MAYBE_UNUSED(x) x -#endif - -#define option_given_p(opts, key) RTEST(rb_funcall(opts, i_key_p, 1, key)) - -/* unicode */ - -typedef unsigned long UTF32; /* at least 32 bits */ -typedef unsigned short UTF16; /* at least 16 bits */ -typedef unsigned char UTF8; /* typically 8 bits */ - -#define UNI_REPLACEMENT_CHAR (UTF32)0x0000FFFD -#define UNI_SUR_HIGH_START (UTF32)0xD800 -#define UNI_SUR_HIGH_END (UTF32)0xDBFF -#define UNI_SUR_LOW_START (UTF32)0xDC00 -#define UNI_SUR_LOW_END (UTF32)0xDFFF - -typedef struct JSON_ParserStruct { - VALUE Vsource; - char *source; - long len; - char *memo; - VALUE create_id; - int max_nesting; - int allow_nan; - int parsing_name; - int symbolize_names; - int freeze; - VALUE object_class; - VALUE array_class; - VALUE decimal_class; - int create_additions; - VALUE match_string; - FBuffer *fbuffer; -} JSON_Parser; - -#define GET_PARSER \ - GET_PARSER_INIT; \ - if (!json->Vsource) rb_raise(rb_eTypeError, "uninitialized instance") -#define GET_PARSER_INIT \ - JSON_Parser *json; \ - TypedData_Get_Struct(self, JSON_Parser, &JSON_Parser_type, json) - -#define MinusInfinity "-Infinity" -#define EVIL 0x666 - -static UTF32 unescape_unicode(const unsigned char *p); -static int convert_UTF32_to_UTF8(char *buf, UTF32 ch); -static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting); -static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting); -static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *result); -static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *result); -static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting); -static VALUE json_string_unescape(char *string, char *stringEnd, int intern, int symbolize); -static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *result); -static VALUE convert_encoding(VALUE source); -static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self); -static VALUE cParser_parse(VALUE self); -static void JSON_mark(void *json); -static void JSON_free(void *json); -static VALUE cJSON_parser_s_allocate(VALUE klass); -static VALUE cParser_source(VALUE self); -#ifndef ZALLOC -#define ZALLOC(type) ((type *)ruby_zalloc(sizeof(type))) -static inline void *ruby_zalloc(size_t n) -{ - void *p = ruby_xmalloc(n); - memset(p, 0, n); - return p; -} -#endif -#ifdef TypedData_Make_Struct -static const rb_data_type_t JSON_Parser_type; -#define NEW_TYPEDDATA_WRAPPER 1 -#else -#define TypedData_Make_Struct(klass, type, ignore, json) Data_Make_Struct(klass, type, NULL, JSON_free, json) -#define TypedData_Get_Struct(self, JSON_Parser, ignore, json) Data_Get_Struct(self, JSON_Parser, json) -#endif - -#endif diff --git a/ext/json/parser/parser.rl b/ext/json/parser/parser.rl deleted file mode 100644 index 1ecf3317c79bb7..00000000000000 --- a/ext/json/parser/parser.rl +++ /dev/null @@ -1,971 +0,0 @@ -#include "../fbuffer/fbuffer.h" -#include "parser.h" - -#if defined HAVE_RUBY_ENCODING_H -# define EXC_ENCODING rb_utf8_encoding(), -# ifndef HAVE_RB_ENC_RAISE -static void -enc_raise(rb_encoding *enc, VALUE exc, const char *fmt, ...) -{ - va_list args; - VALUE mesg; - - va_start(args, fmt); - mesg = rb_enc_vsprintf(enc, fmt, args); - va_end(args); - - rb_exc_raise(rb_exc_new3(exc, mesg)); -} -# define rb_enc_raise enc_raise -# endif -#else -# define EXC_ENCODING /* nothing */ -# define rb_enc_raise rb_raise -#endif - -/* unicode */ - -static const signed char digit_values[256] = { - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, -1, - -1, -1, -1, -1, -1, -1, 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 10, 11, 12, 13, 14, 15, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1 -}; - -static UTF32 unescape_unicode(const unsigned char *p) -{ - signed char b; - UTF32 result = 0; - b = digit_values[p[0]]; - if (b < 0) return UNI_REPLACEMENT_CHAR; - result = (result << 4) | (unsigned char)b; - b = digit_values[p[1]]; - if (b < 0) return UNI_REPLACEMENT_CHAR; - result = (result << 4) | (unsigned char)b; - b = digit_values[p[2]]; - if (b < 0) return UNI_REPLACEMENT_CHAR; - result = (result << 4) | (unsigned char)b; - b = digit_values[p[3]]; - if (b < 0) return UNI_REPLACEMENT_CHAR; - result = (result << 4) | (unsigned char)b; - return result; -} - -static int convert_UTF32_to_UTF8(char *buf, UTF32 ch) -{ - int len = 1; - if (ch <= 0x7F) { - buf[0] = (char) ch; - } else if (ch <= 0x07FF) { - buf[0] = (char) ((ch >> 6) | 0xC0); - buf[1] = (char) ((ch & 0x3F) | 0x80); - len++; - } else if (ch <= 0xFFFF) { - buf[0] = (char) ((ch >> 12) | 0xE0); - buf[1] = (char) (((ch >> 6) & 0x3F) | 0x80); - buf[2] = (char) ((ch & 0x3F) | 0x80); - len += 2; - } else if (ch <= 0x1fffff) { - buf[0] =(char) ((ch >> 18) | 0xF0); - buf[1] =(char) (((ch >> 12) & 0x3F) | 0x80); - buf[2] =(char) (((ch >> 6) & 0x3F) | 0x80); - buf[3] =(char) ((ch & 0x3F) | 0x80); - len += 3; - } else { - buf[0] = '?'; - } - return len; -} - -static VALUE mJSON, mExt, cParser, eParserError, eNestingError; -static VALUE CNaN, CInfinity, CMinusInfinity; - -static ID i_json_creatable_p, i_json_create, i_create_id, i_create_additions, - i_chr, i_max_nesting, i_allow_nan, i_symbolize_names, - i_object_class, i_array_class, i_decimal_class, i_key_p, - i_deep_const_get, i_match, i_match_string, i_aset, i_aref, - i_leftshift, i_new, i_try_convert, i_freeze, i_uminus; - -%%{ - machine JSON_common; - - cr = '\n'; - cr_neg = [^\n]; - ws = [ \t\r\n]; - c_comment = '/*' ( any* - (any* '*/' any* ) ) '*/'; - cpp_comment = '//' cr_neg* cr; - comment = c_comment | cpp_comment; - ignore = ws | comment; - name_separator = ':'; - value_separator = ','; - Vnull = 'null'; - Vfalse = 'false'; - Vtrue = 'true'; - VNaN = 'NaN'; - VInfinity = 'Infinity'; - VMinusInfinity = '-Infinity'; - begin_value = [nft\"\-\[\{NI] | digit; - begin_object = '{'; - end_object = '}'; - begin_array = '['; - end_array = ']'; - begin_string = '"'; - begin_name = begin_string; - begin_number = digit | '-'; -}%% - -%%{ - machine JSON_object; - include JSON_common; - - write data; - - action parse_value { - VALUE v = Qnil; - char *np = JSON_parse_value(json, fpc, pe, &v, current_nesting); - if (np == NULL) { - fhold; fbreak; - } else { - if (NIL_P(json->object_class)) { - OBJ_FREEZE(last_name); - rb_hash_aset(*result, last_name, v); - } else { - rb_funcall(*result, i_aset, 2, last_name, v); - } - fexec np; - } - } - - action parse_name { - char *np; - json->parsing_name = 1; - np = JSON_parse_string(json, fpc, pe, &last_name); - json->parsing_name = 0; - if (np == NULL) { fhold; fbreak; } else fexec np; - } - - action exit { fhold; fbreak; } - - pair = ignore* begin_name >parse_name ignore* name_separator ignore* begin_value >parse_value; - next_pair = ignore* value_separator pair; - - main := ( - begin_object - (pair (next_pair)*)? ignore* - end_object - ) @exit; -}%% - -static char *JSON_parse_object(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting) -{ - int cs = EVIL; - VALUE last_name = Qnil; - VALUE object_class = json->object_class; - - if (json->max_nesting && current_nesting > json->max_nesting) { - rb_raise(eNestingError, "nesting of %d is too deep", current_nesting); - } - - *result = NIL_P(object_class) ? rb_hash_new() : rb_class_new_instance(0, 0, object_class); - - %% write init; - %% write exec; - - if (cs >= JSON_object_first_final) { - if (json->create_additions) { - VALUE klassname; - if (NIL_P(json->object_class)) { - klassname = rb_hash_aref(*result, json->create_id); - } else { - klassname = rb_funcall(*result, i_aref, 1, json->create_id); - } - if (!NIL_P(klassname)) { - VALUE klass = rb_funcall(mJSON, i_deep_const_get, 1, klassname); - if (RTEST(rb_funcall(klass, i_json_creatable_p, 0))) { - *result = rb_funcall(klass, i_json_create, 1, *result); - } - } - } - return p + 1; - } else { - return NULL; - } -} - - -%%{ - machine JSON_value; - include JSON_common; - - write data; - - action parse_null { - *result = Qnil; - } - action parse_false { - *result = Qfalse; - } - action parse_true { - *result = Qtrue; - } - action parse_nan { - if (json->allow_nan) { - *result = CNaN; - } else { - rb_enc_raise(EXC_ENCODING eParserError, "unexpected token at '%s'", p - 2); - } - } - action parse_infinity { - if (json->allow_nan) { - *result = CInfinity; - } else { - rb_enc_raise(EXC_ENCODING eParserError, "unexpected token at '%s'", p - 8); - } - } - action parse_string { - char *np = JSON_parse_string(json, fpc, pe, result); - if (np == NULL) { fhold; fbreak; } else fexec np; - } - - action parse_number { - char *np; - if(pe > fpc + 8 && !strncmp(MinusInfinity, fpc, 9)) { - if (json->allow_nan) { - *result = CMinusInfinity; - fexec p + 10; - fhold; fbreak; - } else { - rb_enc_raise(EXC_ENCODING eParserError, "unexpected token at '%s'", p); - } - } - np = JSON_parse_float(json, fpc, pe, result); - if (np != NULL) fexec np; - np = JSON_parse_integer(json, fpc, pe, result); - if (np != NULL) fexec np; - fhold; fbreak; - } - - action parse_array { - char *np; - np = JSON_parse_array(json, fpc, pe, result, current_nesting + 1); - if (np == NULL) { fhold; fbreak; } else fexec np; - } - - action parse_object { - char *np; - np = JSON_parse_object(json, fpc, pe, result, current_nesting + 1); - if (np == NULL) { fhold; fbreak; } else fexec np; - } - - action exit { fhold; fbreak; } - -main := ignore* ( - Vnull @parse_null | - Vfalse @parse_false | - Vtrue @parse_true | - VNaN @parse_nan | - VInfinity @parse_infinity | - begin_number >parse_number | - begin_string >parse_string | - begin_array >parse_array | - begin_object >parse_object - ) ignore* %*exit; -}%% - -static char *JSON_parse_value(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting) -{ - int cs = EVIL; - - %% write init; - %% write exec; - - if (json->freeze) { - OBJ_FREEZE(*result); - } - - if (cs >= JSON_value_first_final) { - return p; - } else { - return NULL; - } -} - -%%{ - machine JSON_integer; - - write data; - - action exit { fhold; fbreak; } - - main := '-'? ('0' | [1-9][0-9]*) (^[0-9]? @exit); -}%% - -static char *JSON_parse_integer(JSON_Parser *json, char *p, char *pe, VALUE *result) -{ - int cs = EVIL; - - %% write init; - json->memo = p; - %% write exec; - - if (cs >= JSON_integer_first_final) { - long len = p - json->memo; - fbuffer_clear(json->fbuffer); - fbuffer_append(json->fbuffer, json->memo, len); - fbuffer_append_char(json->fbuffer, '\0'); - *result = rb_cstr2inum(FBUFFER_PTR(json->fbuffer), 10); - return p + 1; - } else { - return NULL; - } -} - -%%{ - machine JSON_float; - include JSON_common; - - write data; - - action exit { fhold; fbreak; } - - main := '-'? ( - (('0' | [1-9][0-9]*) '.' [0-9]+ ([Ee] [+\-]?[0-9]+)?) - | (('0' | [1-9][0-9]*) ([Ee] [+\-]?[0-9]+)) - ) (^[0-9Ee.\-]? @exit ); -}%% - -static char *JSON_parse_float(JSON_Parser *json, char *p, char *pe, VALUE *result) -{ - int cs = EVIL; - - %% write init; - json->memo = p; - %% write exec; - - if (cs >= JSON_float_first_final) { - VALUE mod = Qnil; - ID method_id = 0; - if (rb_respond_to(json->decimal_class, i_try_convert)) { - mod = json->decimal_class; - method_id = i_try_convert; - } else if (rb_respond_to(json->decimal_class, i_new)) { - mod = json->decimal_class; - method_id = i_new; - } else if (RB_TYPE_P(json->decimal_class, T_CLASS)) { - VALUE name = rb_class_name(json->decimal_class); - const char *name_cstr = RSTRING_PTR(name); - const char *last_colon = strrchr(name_cstr, ':'); - if (last_colon) { - const char *mod_path_end = last_colon - 1; - VALUE mod_path = rb_str_substr(name, 0, mod_path_end - name_cstr); - mod = rb_path_to_class(mod_path); - - const char *method_name_beg = last_colon + 1; - long before_len = method_name_beg - name_cstr; - long len = RSTRING_LEN(name) - before_len; - VALUE method_name = rb_str_substr(name, before_len, len); - method_id = SYM2ID(rb_str_intern(method_name)); - } else { - mod = rb_mKernel; - method_id = SYM2ID(rb_str_intern(name)); - } - } - - long len = p - json->memo; - fbuffer_clear(json->fbuffer); - fbuffer_append(json->fbuffer, json->memo, len); - fbuffer_append_char(json->fbuffer, '\0'); - - if (method_id) { - VALUE text = rb_str_new2(FBUFFER_PTR(json->fbuffer)); - *result = rb_funcallv(mod, method_id, 1, &text); - } else { - *result = DBL2NUM(rb_cstr_to_dbl(FBUFFER_PTR(json->fbuffer), 1)); - } - - return p + 1; - } else { - return NULL; - } -} - - -%%{ - machine JSON_array; - include JSON_common; - - write data; - - action parse_value { - VALUE v = Qnil; - char *np = JSON_parse_value(json, fpc, pe, &v, current_nesting); - if (np == NULL) { - fhold; fbreak; - } else { - if (NIL_P(json->array_class)) { - rb_ary_push(*result, v); - } else { - rb_funcall(*result, i_leftshift, 1, v); - } - fexec np; - } - } - - action exit { fhold; fbreak; } - - next_element = value_separator ignore* begin_value >parse_value; - - main := begin_array ignore* - ((begin_value >parse_value ignore*) - (ignore* next_element ignore*)*)? - end_array @exit; -}%% - -static char *JSON_parse_array(JSON_Parser *json, char *p, char *pe, VALUE *result, int current_nesting) -{ - int cs = EVIL; - VALUE array_class = json->array_class; - - if (json->max_nesting && current_nesting > json->max_nesting) { - rb_raise(eNestingError, "nesting of %d is too deep", current_nesting); - } - *result = NIL_P(array_class) ? rb_ary_new() : rb_class_new_instance(0, 0, array_class); - - %% write init; - %% write exec; - - if(cs >= JSON_array_first_final) { - return p + 1; - } else { - rb_enc_raise(EXC_ENCODING eParserError, "unexpected token at '%s'", p); - return NULL; - } -} - -static const size_t MAX_STACK_BUFFER_SIZE = 128; -static VALUE json_string_unescape(char *string, char *stringEnd, int intern, int symbolize) -{ - VALUE result = Qnil; - size_t bufferSize = stringEnd - string; - char *p = string, *pe = string, *unescape, *bufferStart, *buffer; - int unescape_len; - char buf[4]; - - if (bufferSize > MAX_STACK_BUFFER_SIZE) { -# ifdef HAVE_RB_ENC_INTERNED_STR - bufferStart = buffer = ALLOC_N(char, bufferSize ? bufferSize : 1); -# else - bufferStart = buffer = ALLOC_N(char, bufferSize); -# endif - } else { -# ifdef HAVE_RB_ENC_INTERNED_STR - bufferStart = buffer = ALLOCA_N(char, bufferSize ? bufferSize : 1); -# else - bufferStart = buffer = ALLOCA_N(char, bufferSize); -# endif - } - - while (pe < stringEnd) { - if (*pe == '\\') { - unescape = (char *) "?"; - unescape_len = 1; - if (pe > p) { - MEMCPY(buffer, p, char, pe - p); - buffer += pe - p; - } - switch (*++pe) { - case 'n': - unescape = (char *) "\n"; - break; - case 'r': - unescape = (char *) "\r"; - break; - case 't': - unescape = (char *) "\t"; - break; - case '"': - unescape = (char *) "\""; - break; - case '\\': - unescape = (char *) "\\"; - break; - case 'b': - unescape = (char *) "\b"; - break; - case 'f': - unescape = (char *) "\f"; - break; - case 'u': - if (pe > stringEnd - 4) { - if (bufferSize > MAX_STACK_BUFFER_SIZE) { - free(bufferStart); - } - rb_enc_raise( - EXC_ENCODING eParserError, - "incomplete unicode character escape sequence at '%s'", p - ); - } else { - UTF32 ch = unescape_unicode((unsigned char *) ++pe); - pe += 3; - if (UNI_SUR_HIGH_START == (ch & 0xFC00)) { - pe++; - if (pe > stringEnd - 6) { - if (bufferSize > MAX_STACK_BUFFER_SIZE) { - free(bufferStart); - } - rb_enc_raise( - EXC_ENCODING eParserError, - "incomplete surrogate pair at '%s'", p - ); - } - if (pe[0] == '\\' && pe[1] == 'u') { - UTF32 sur = unescape_unicode((unsigned char *) pe + 2); - ch = (((ch & 0x3F) << 10) | ((((ch >> 6) & 0xF) + 1) << 16) - | (sur & 0x3FF)); - pe += 5; - } else { - unescape = (char *) "?"; - break; - } - } - unescape_len = convert_UTF32_to_UTF8(buf, ch); - unescape = buf; - } - break; - default: - p = pe; - continue; - } - MEMCPY(buffer, unescape, char, unescape_len); - buffer += unescape_len; - p = ++pe; - } else { - pe++; - } - } - - if (pe > p) { - MEMCPY(buffer, p, char, pe - p); - buffer += pe - p; - } - -# ifdef HAVE_RB_ENC_INTERNED_STR - if (intern) { - result = rb_enc_interned_str(bufferStart, (long)(buffer - bufferStart), rb_utf8_encoding()); - } else { - result = rb_utf8_str_new(bufferStart, (long)(buffer - bufferStart)); - } - if (bufferSize > MAX_STACK_BUFFER_SIZE) { - free(bufferStart); - } -# else - result = rb_utf8_str_new(bufferStart, (long)(buffer - bufferStart)); - - if (bufferSize > MAX_STACK_BUFFER_SIZE) { - free(bufferStart); - } - - if (intern) { - # if STR_UMINUS_DEDUPE_FROZEN - // Starting from MRI 2.8 it is preferable to freeze the string - // before deduplication so that it can be interned directly - // otherwise it would be duplicated first which is wasteful. - result = rb_funcall(rb_str_freeze(result), i_uminus, 0); - # elif STR_UMINUS_DEDUPE - // MRI 2.5 and older do not deduplicate strings that are already - // frozen. - result = rb_funcall(result, i_uminus, 0); - # else - result = rb_str_freeze(result); - # endif - } -# endif - - if (symbolize) { - result = rb_str_intern(result); - } - - return result; -} - -%%{ - machine JSON_string; - include JSON_common; - - write data; - - action parse_string { - *result = json_string_unescape(json->memo + 1, p, json->parsing_name || json-> freeze, json->parsing_name && json->symbolize_names); - if (NIL_P(*result)) { - fhold; - fbreak; - } else { - fexec p + 1; - } - } - - action exit { fhold; fbreak; } - - main := '"' ((^([\"\\] | 0..0x1f) | '\\'[\"\\/bfnrt] | '\\u'[0-9a-fA-F]{4} | '\\'^([\"\\/bfnrtu]|0..0x1f))* %parse_string) '"' @exit; -}%% - -static int -match_i(VALUE regexp, VALUE klass, VALUE memo) -{ - if (regexp == Qundef) return ST_STOP; - if (RTEST(rb_funcall(klass, i_json_creatable_p, 0)) && - RTEST(rb_funcall(regexp, i_match, 1, rb_ary_entry(memo, 0)))) { - rb_ary_push(memo, klass); - return ST_STOP; - } - return ST_CONTINUE; -} - -static char *JSON_parse_string(JSON_Parser *json, char *p, char *pe, VALUE *result) -{ - int cs = EVIL; - VALUE match_string; - - %% write init; - json->memo = p; - %% write exec; - - if (json->create_additions && RTEST(match_string = json->match_string)) { - VALUE klass; - VALUE memo = rb_ary_new2(2); - rb_ary_push(memo, *result); - rb_hash_foreach(match_string, match_i, memo); - klass = rb_ary_entry(memo, 1); - if (RTEST(klass)) { - *result = rb_funcall(klass, i_json_create, 1, *result); - } - } - - if (cs >= JSON_string_first_final) { - return p + 1; - } else { - return NULL; - } -} - -/* - * Document-class: JSON::Ext::Parser - * - * This is the JSON parser implemented as a C extension. It can be configured - * to be used by setting - * - * JSON.parser = JSON::Ext::Parser - * - * with the method parser= in JSON. - * - */ - -static VALUE convert_encoding(VALUE source) -{ -#ifdef HAVE_RUBY_ENCODING_H - rb_encoding *enc = rb_enc_get(source); - if (enc == rb_ascii8bit_encoding()) { - if (OBJ_FROZEN(source)) { - source = rb_str_dup(source); - } - FORCE_UTF8(source); - } else { - source = rb_str_conv_enc(source, rb_enc_get(source), rb_utf8_encoding()); - } -#endif - return source; -} - -/* - * call-seq: new(source, opts => {}) - * - * Creates a new JSON::Ext::Parser instance for the string _source_. - * - * It will be configured by the _opts_ hash. _opts_ can have the following - * keys: - * - * _opts_ can have the following keys: - * * *max_nesting*: The maximum depth of nesting allowed in the parsed data - * structures. Disable depth checking with :max_nesting => false|nil|0, it - * defaults to 100. - * * *allow_nan*: If set to true, allow NaN, Infinity and -Infinity in - * defiance of RFC 4627 to be parsed by the Parser. This option defaults to - * false. - * * *symbolize_names*: If set to true, returns symbols for the names - * (keys) in a JSON object. Otherwise strings are returned, which is - * also the default. It's not possible to use this option in - * conjunction with the *create_additions* option. - * * *create_additions*: If set to false, the Parser doesn't create - * additions even if a matching class and create_id was found. This option - * defaults to false. - * * *object_class*: Defaults to Hash - * * *array_class*: Defaults to Array - */ -static VALUE cParser_initialize(int argc, VALUE *argv, VALUE self) -{ - VALUE source, opts; - GET_PARSER_INIT; - - if (json->Vsource) { - rb_raise(rb_eTypeError, "already initialized instance"); - } - rb_scan_args(argc, argv, "1:", &source, &opts); - if (!NIL_P(opts)) { - VALUE tmp = ID2SYM(i_max_nesting); - if (option_given_p(opts, tmp)) { - VALUE max_nesting = rb_hash_aref(opts, tmp); - if (RTEST(max_nesting)) { - Check_Type(max_nesting, T_FIXNUM); - json->max_nesting = FIX2INT(max_nesting); - } else { - json->max_nesting = 0; - } - } else { - json->max_nesting = 100; - } - tmp = ID2SYM(i_allow_nan); - if (option_given_p(opts, tmp)) { - json->allow_nan = RTEST(rb_hash_aref(opts, tmp)) ? 1 : 0; - } else { - json->allow_nan = 0; - } - tmp = ID2SYM(i_symbolize_names); - if (option_given_p(opts, tmp)) { - json->symbolize_names = RTEST(rb_hash_aref(opts, tmp)) ? 1 : 0; - } else { - json->symbolize_names = 0; - } - tmp = ID2SYM(i_freeze); - if (option_given_p(opts, tmp)) { - json->freeze = RTEST(rb_hash_aref(opts, tmp)) ? 1 : 0; - } else { - json->freeze = 0; - } - tmp = ID2SYM(i_create_additions); - if (option_given_p(opts, tmp)) { - json->create_additions = RTEST(rb_hash_aref(opts, tmp)); - } else { - json->create_additions = 0; - } - if (json->symbolize_names && json->create_additions) { - rb_raise(rb_eArgError, - "options :symbolize_names and :create_additions cannot be " - " used in conjunction"); - } - tmp = ID2SYM(i_create_id); - if (option_given_p(opts, tmp)) { - json->create_id = rb_hash_aref(opts, tmp); - } else { - json->create_id = rb_funcall(mJSON, i_create_id, 0); - } - tmp = ID2SYM(i_object_class); - if (option_given_p(opts, tmp)) { - json->object_class = rb_hash_aref(opts, tmp); - } else { - json->object_class = Qnil; - } - tmp = ID2SYM(i_array_class); - if (option_given_p(opts, tmp)) { - json->array_class = rb_hash_aref(opts, tmp); - } else { - json->array_class = Qnil; - } - tmp = ID2SYM(i_decimal_class); - if (option_given_p(opts, tmp)) { - json->decimal_class = rb_hash_aref(opts, tmp); - } else { - json->decimal_class = Qnil; - } - tmp = ID2SYM(i_match_string); - if (option_given_p(opts, tmp)) { - VALUE match_string = rb_hash_aref(opts, tmp); - json->match_string = RTEST(match_string) ? match_string : Qnil; - } else { - json->match_string = Qnil; - } - } else { - json->max_nesting = 100; - json->allow_nan = 0; - json->create_additions = 0; - json->create_id = rb_funcall(mJSON, i_create_id, 0); - json->object_class = Qnil; - json->array_class = Qnil; - json->decimal_class = Qnil; - } - source = convert_encoding(StringValue(source)); - StringValue(source); - json->len = RSTRING_LEN(source); - json->source = RSTRING_PTR(source);; - json->Vsource = source; - return self; -} - -%%{ - machine JSON; - - write data; - - include JSON_common; - - action parse_value { - char *np = JSON_parse_value(json, fpc, pe, &result, 0); - if (np == NULL) { fhold; fbreak; } else fexec np; - } - - main := ignore* ( - begin_value >parse_value - ) ignore*; -}%% - -/* - * call-seq: parse() - * - * Parses the current JSON text _source_ and returns the complete data - * structure as a result. - * It raises JSON::ParserError if fail to parse. - */ -static VALUE cParser_parse(VALUE self) -{ - char *p, *pe; - int cs = EVIL; - VALUE result = Qnil; - GET_PARSER; - - %% write init; - p = json->source; - pe = p + json->len; - %% write exec; - - if (cs >= JSON_first_final && p == pe) { - return result; - } else { - rb_enc_raise(EXC_ENCODING eParserError, "unexpected token at '%s'", p); - return Qnil; - } -} - -static void JSON_mark(void *ptr) -{ - JSON_Parser *json = ptr; - rb_gc_mark_maybe(json->Vsource); - rb_gc_mark_maybe(json->create_id); - rb_gc_mark_maybe(json->object_class); - rb_gc_mark_maybe(json->array_class); - rb_gc_mark_maybe(json->decimal_class); - rb_gc_mark_maybe(json->match_string); -} - -static void JSON_free(void *ptr) -{ - JSON_Parser *json = ptr; - fbuffer_free(json->fbuffer); - ruby_xfree(json); -} - -static size_t JSON_memsize(const void *ptr) -{ - const JSON_Parser *json = ptr; - return sizeof(*json) + FBUFFER_CAPA(json->fbuffer); -} - -#ifdef NEW_TYPEDDATA_WRAPPER -static const rb_data_type_t JSON_Parser_type = { - "JSON/Parser", - {JSON_mark, JSON_free, JSON_memsize,}, -#ifdef RUBY_TYPED_FREE_IMMEDIATELY - 0, 0, - RUBY_TYPED_FREE_IMMEDIATELY, -#endif -}; -#endif - -static VALUE cJSON_parser_s_allocate(VALUE klass) -{ - JSON_Parser *json; - VALUE obj = TypedData_Make_Struct(klass, JSON_Parser, &JSON_Parser_type, json); - json->fbuffer = fbuffer_alloc(0); - return obj; -} - -/* - * call-seq: source() - * - * Returns a copy of the current _source_ string, that was used to construct - * this Parser. - */ -static VALUE cParser_source(VALUE self) -{ - GET_PARSER; - return rb_str_dup(json->Vsource); -} - -void Init_parser(void) -{ -#ifdef HAVE_RB_EXT_RACTOR_SAFE - rb_ext_ractor_safe(true); -#endif - -#undef rb_intern - rb_require("json/common"); - mJSON = rb_define_module("JSON"); - mExt = rb_define_module_under(mJSON, "Ext"); - cParser = rb_define_class_under(mExt, "Parser", rb_cObject); - eParserError = rb_path2class("JSON::ParserError"); - eNestingError = rb_path2class("JSON::NestingError"); - rb_gc_register_mark_object(eParserError); - rb_gc_register_mark_object(eNestingError); - rb_define_alloc_func(cParser, cJSON_parser_s_allocate); - rb_define_method(cParser, "initialize", cParser_initialize, -1); - rb_define_method(cParser, "parse", cParser_parse, 0); - rb_define_method(cParser, "source", cParser_source, 0); - - CNaN = rb_const_get(mJSON, rb_intern("NaN")); - rb_gc_register_mark_object(CNaN); - - CInfinity = rb_const_get(mJSON, rb_intern("Infinity")); - rb_gc_register_mark_object(CInfinity); - - CMinusInfinity = rb_const_get(mJSON, rb_intern("MinusInfinity")); - rb_gc_register_mark_object(CMinusInfinity); - - i_json_creatable_p = rb_intern("json_creatable?"); - i_json_create = rb_intern("json_create"); - i_create_id = rb_intern("create_id"); - i_create_additions = rb_intern("create_additions"); - i_chr = rb_intern("chr"); - i_max_nesting = rb_intern("max_nesting"); - i_allow_nan = rb_intern("allow_nan"); - i_symbolize_names = rb_intern("symbolize_names"); - i_object_class = rb_intern("object_class"); - i_array_class = rb_intern("array_class"); - i_decimal_class = rb_intern("decimal_class"); - i_match = rb_intern("match"); - i_match_string = rb_intern("match_string"); - i_key_p = rb_intern("key?"); - i_deep_const_get = rb_intern("deep_const_get"); - i_aset = rb_intern("[]="); - i_aref = rb_intern("[]"); - i_leftshift = rb_intern("<<"); - i_new = rb_intern("new"); - i_try_convert = rb_intern("try_convert"); - i_freeze = rb_intern("freeze"); - i_uminus = rb_intern("-@"); -} - -/* - * Local variables: - * mode: c - * c-file-style: ruby - * indent-tabs-mode: nil - * End: - */ diff --git a/ext/json/parser/prereq.mk b/ext/json/parser/prereq.mk deleted file mode 100644 index fc591690568874..00000000000000 --- a/ext/json/parser/prereq.mk +++ /dev/null @@ -1,13 +0,0 @@ -RAGEL = ragel - -.SUFFIXES: .rl - -.rl.c: - $(RAGEL) -G2 $< - $(BASERUBY) -pli -e '$$_.sub!(/[ \t]+$$/, "")' \ - -e '$$_.sub!(/^static const int (JSON_.*=.*);$$/, "enum {\\1};")' \ - -e '$$_.sub!(/^(static const char) (_JSON(?:_\w+)?_nfa_\w+)(?=\[\] =)/, "\\1 MAYBE_UNUSED(\\2)")' \ - -e '$$_.sub!(/0 <= ([\( ]+\*[\( ]*p\)+) && \1 <= 31/, "0 <= (signed char)(*(p)) && (*(p)) <= 31")' \ - -e '$$_ = "/* This file is automatically generated from parser.rl by using ragel */\n" + $$_ if $$. == 1' $@ - -parser.c: diff --git a/ext/json/simd/conf.rb b/ext/json/simd/conf.rb new file mode 100644 index 00000000000000..8e7d8ee26133d1 --- /dev/null +++ b/ext/json/simd/conf.rb @@ -0,0 +1,20 @@ +case RbConfig::CONFIG['host_cpu'] +when /^(arm|aarch64)/ + # Try to compile a small program using NEON instructions + header, type, init = 'arm_neon.h', 'uint8x16_t', 'vdupq_n_u8(32)' +when /^(x86_64|x64)/ + header, type, init = 'x86intrin.h', '__m128i', '_mm_set1_epi8(32)' +end +if header + have_header(header) && try_compile(<<~SRC) + #{cpp_include(header)} + int main(int argc, char **argv) { + #{type} test = #{init}; + if (argc > 100000) printf("%p", &test); + return 0; + } + SRC + $defs.push("-DJSON_ENABLE_SIMD") +end + +have_header('cpuid.h') diff --git a/ext/json/simd/simd.h b/ext/json/simd/simd.h new file mode 100644 index 00000000000000..f8503d1395c271 --- /dev/null +++ b/ext/json/simd/simd.h @@ -0,0 +1,187 @@ +typedef enum { + SIMD_NONE, + SIMD_NEON, + SIMD_SSE2 +} SIMD_Implementation; + +#ifdef JSON_ENABLE_SIMD + +#ifdef __clang__ + #if __has_builtin(__builtin_ctzll) + #define HAVE_BUILTIN_CTZLL 1 + #else + #define HAVE_BUILTIN_CTZLL 0 + #endif +#elif defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3)) + #define HAVE_BUILTIN_CTZLL 1 +#else + #define HAVE_BUILTIN_CTZLL 0 +#endif + +static inline uint32_t trailing_zeros64(uint64_t input) +{ +#if HAVE_BUILTIN_CTZLL + return __builtin_ctzll(input); +#else + uint32_t trailing_zeros = 0; + uint64_t temp = input; + while ((temp & 1) == 0 && temp > 0) { + trailing_zeros++; + temp >>= 1; + } + return trailing_zeros; +#endif +} + +static inline int trailing_zeros(int input) +{ + #if HAVE_BUILTIN_CTZLL + return __builtin_ctz(input); + #else + int trailing_zeros = 0; + int temp = input; + while ((temp & 1) == 0 && temp > 0) { + trailing_zeros++; + temp >>= 1; + } + return trailing_zeros; + #endif +} + +#if (defined(__GNUC__ ) || defined(__clang__)) +#define FORCE_INLINE __attribute__((always_inline)) +#else +#define FORCE_INLINE +#endif + + +#define SIMD_MINIMUM_THRESHOLD 6 + +#if defined(__ARM_NEON) || defined(__ARM_NEON__) || defined(__aarch64__) || defined(_M_ARM64) +#include + +#define FIND_SIMD_IMPLEMENTATION_DEFINED 1 +static inline SIMD_Implementation find_simd_implementation(void) +{ + return SIMD_NEON; +} + +#define HAVE_SIMD 1 +#define HAVE_SIMD_NEON 1 + +// See: https://community.arm.com/arm-community-blogs/b/servers-and-cloud-computing-blog/posts/porting-x86-vector-bitmask-optimizations-to-arm-neon +static inline FORCE_INLINE uint64_t neon_match_mask(uint8x16_t matches) +{ + const uint8x8_t res = vshrn_n_u16(vreinterpretq_u16_u8(matches), 4); + const uint64_t mask = vget_lane_u64(vreinterpret_u64_u8(res), 0); + return mask & 0x8888888888888888ull; +} + +static inline FORCE_INLINE uint64_t compute_chunk_mask_neon(const char *ptr) +{ + uint8x16_t chunk = vld1q_u8((const unsigned char *)ptr); + + // Trick: c < 32 || c == 34 can be factored as c ^ 2 < 33 + // https://lemire.me/blog/2025/04/13/detect-control-characters-quotes-and-backslashes-efficiently-using-swar/ + const uint8x16_t too_low_or_dbl_quote = vcltq_u8(veorq_u8(chunk, vdupq_n_u8(2)), vdupq_n_u8(33)); + + uint8x16_t has_backslash = vceqq_u8(chunk, vdupq_n_u8('\\')); + uint8x16_t needs_escape = vorrq_u8(too_low_or_dbl_quote, has_backslash); + return neon_match_mask(needs_escape); +} + +static inline FORCE_INLINE int string_scan_simd_neon(const char **ptr, const char *end, uint64_t *mask) +{ + while (*ptr + sizeof(uint8x16_t) <= end) { + uint64_t chunk_mask = compute_chunk_mask_neon(*ptr); + if (chunk_mask) { + *mask = chunk_mask; + return 1; + } + *ptr += sizeof(uint8x16_t); + } + return 0; +} + +uint8x16x4_t load_uint8x16_4(const unsigned char *table) { + uint8x16x4_t tab; + tab.val[0] = vld1q_u8(table); + tab.val[1] = vld1q_u8(table+16); + tab.val[2] = vld1q_u8(table+32); + tab.val[3] = vld1q_u8(table+48); + return tab; +} + +#endif /* ARM Neon Support.*/ + +#if defined(__amd64__) || defined(__amd64) || defined(__x86_64__) || defined(__x86_64) || defined(_M_X64) || defined(_M_AMD64) + +#ifdef HAVE_X86INTRIN_H +#include + +#define HAVE_SIMD 1 +#define HAVE_SIMD_SSE2 1 + +#ifdef HAVE_CPUID_H +#define FIND_SIMD_IMPLEMENTATION_DEFINED 1 + +#if defined(__clang__) || defined(__GNUC__) +#define TARGET_SSE2 __attribute__((target("sse2"))) +#else +#define TARGET_SSE2 +#endif + +#define _mm_cmpge_epu8(a, b) _mm_cmpeq_epi8(_mm_max_epu8(a, b), a) +#define _mm_cmple_epu8(a, b) _mm_cmpge_epu8(b, a) +#define _mm_cmpgt_epu8(a, b) _mm_xor_si128(_mm_cmple_epu8(a, b), _mm_set1_epi8(-1)) +#define _mm_cmplt_epu8(a, b) _mm_cmpgt_epu8(b, a) + +static inline TARGET_SSE2 FORCE_INLINE int compute_chunk_mask_sse2(const char *ptr) +{ + __m128i chunk = _mm_loadu_si128((__m128i const*)ptr); + // Trick: c < 32 || c == 34 can be factored as c ^ 2 < 33 + // https://lemire.me/blog/2025/04/13/detect-control-characters-quotes-and-backslashes-efficiently-using-swar/ + __m128i too_low_or_dbl_quote = _mm_cmplt_epu8(_mm_xor_si128(chunk, _mm_set1_epi8(2)), _mm_set1_epi8(33)); + __m128i has_backslash = _mm_cmpeq_epi8(chunk, _mm_set1_epi8('\\')); + __m128i needs_escape = _mm_or_si128(too_low_or_dbl_quote, has_backslash); + return _mm_movemask_epi8(needs_escape); +} + +static inline TARGET_SSE2 FORCE_INLINE int string_scan_simd_sse2(const char **ptr, const char *end, int *mask) +{ + while (*ptr + sizeof(__m128i) <= end) { + int chunk_mask = compute_chunk_mask_sse2(*ptr); + if (chunk_mask) { + *mask = chunk_mask; + return 1; + } + *ptr += sizeof(__m128i); + } + + return 0; +} + +#include +#endif /* HAVE_CPUID_H */ + +static inline SIMD_Implementation find_simd_implementation(void) +{ + // TODO Revisit. I think the SSE version now only uses SSE2 instructions. + if (__builtin_cpu_supports("sse2")) { + return SIMD_SSE2; + } + + return SIMD_NONE; +} + +#endif /* HAVE_X86INTRIN_H */ +#endif /* X86_64 Support */ + +#endif /* JSON_ENABLE_SIMD */ + +#ifndef FIND_SIMD_IMPLEMENTATION_DEFINED +static inline SIMD_Implementation find_simd_implementation(void) +{ + return SIMD_NONE; +} +#endif diff --git a/ext/json/vendor/fpconv.c b/ext/json/vendor/fpconv.c new file mode 100644 index 00000000000000..75efd46f11e624 --- /dev/null +++ b/ext/json/vendor/fpconv.c @@ -0,0 +1,479 @@ +// Boost Software License - Version 1.0 - August 17th, 2003 +// +// Permission is hereby granted, free of charge, to any person or organization +// obtaining a copy of the software and accompanying documentation covered by +// this license (the "Software") to use, reproduce, display, distribute, +// execute, and transmit the Software, and to prepare derivative works of the +// Software, and to permit third-parties to whom the Software is furnished to +// do so, all subject to the following: +// +// The copyright notices in the Software and this entire statement, including +// the above license grant, this restriction and the following disclaimer, +// must be included in all copies of the Software, in whole or in part, and +// all derivative works of the Software, unless such copies or derivative +// works are solely in the form of machine-executable object code generated by +// a source language processor. +// +// 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, TITLE AND NON-INFRINGEMENT. IN NO EVENT +// SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE +// FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +// DEALINGS IN THE SOFTWARE. + +// The contents of this file is extracted from https://github.com/night-shift/fpconv +// It was slightly modified to append ".0" to plain floats, for use with the https://github.com/ruby/json package. + +#include +#include +#include + +#define npowers 87 +#define steppowers 8 +#define firstpower -348 /* 10 ^ -348 */ + +#define expmax -32 +#define expmin -60 + +typedef struct Fp { + uint64_t frac; + int exp; +} Fp; + +static const Fp powers_ten[] = { + { 18054884314459144840U, -1220 }, { 13451937075301367670U, -1193 }, + { 10022474136428063862U, -1166 }, { 14934650266808366570U, -1140 }, + { 11127181549972568877U, -1113 }, { 16580792590934885855U, -1087 }, + { 12353653155963782858U, -1060 }, { 18408377700990114895U, -1034 }, + { 13715310171984221708U, -1007 }, { 10218702384817765436U, -980 }, + { 15227053142812498563U, -954 }, { 11345038669416679861U, -927 }, + { 16905424996341287883U, -901 }, { 12595523146049147757U, -874 }, + { 9384396036005875287U, -847 }, { 13983839803942852151U, -821 }, + { 10418772551374772303U, -794 }, { 15525180923007089351U, -768 }, + { 11567161174868858868U, -741 }, { 17236413322193710309U, -715 }, + { 12842128665889583758U, -688 }, { 9568131466127621947U, -661 }, + { 14257626930069360058U, -635 }, { 10622759856335341974U, -608 }, + { 15829145694278690180U, -582 }, { 11793632577567316726U, -555 }, + { 17573882009934360870U, -529 }, { 13093562431584567480U, -502 }, + { 9755464219737475723U, -475 }, { 14536774485912137811U, -449 }, + { 10830740992659433045U, -422 }, { 16139061738043178685U, -396 }, + { 12024538023802026127U, -369 }, { 17917957937422433684U, -343 }, + { 13349918974505688015U, -316 }, { 9946464728195732843U, -289 }, + { 14821387422376473014U, -263 }, { 11042794154864902060U, -236 }, + { 16455045573212060422U, -210 }, { 12259964326927110867U, -183 }, + { 18268770466636286478U, -157 }, { 13611294676837538539U, -130 }, + { 10141204801825835212U, -103 }, { 15111572745182864684U, -77 }, + { 11258999068426240000U, -50 }, { 16777216000000000000U, -24 }, + { 12500000000000000000U, 3 }, { 9313225746154785156U, 30 }, + { 13877787807814456755U, 56 }, { 10339757656912845936U, 83 }, + { 15407439555097886824U, 109 }, { 11479437019748901445U, 136 }, + { 17105694144590052135U, 162 }, { 12744735289059618216U, 189 }, + { 9495567745759798747U, 216 }, { 14149498560666738074U, 242 }, + { 10542197943230523224U, 269 }, { 15709099088952724970U, 295 }, + { 11704190886730495818U, 322 }, { 17440603504673385349U, 348 }, + { 12994262207056124023U, 375 }, { 9681479787123295682U, 402 }, + { 14426529090290212157U, 428 }, { 10748601772107342003U, 455 }, + { 16016664761464807395U, 481 }, { 11933345169920330789U, 508 }, + { 17782069995880619868U, 534 }, { 13248674568444952270U, 561 }, + { 9871031767461413346U, 588 }, { 14708983551653345445U, 614 }, + { 10959046745042015199U, 641 }, { 16330252207878254650U, 667 }, + { 12166986024289022870U, 694 }, { 18130221999122236476U, 720 }, + { 13508068024458167312U, 747 }, { 10064294952495520794U, 774 }, + { 14996968138956309548U, 800 }, { 11173611982879273257U, 827 }, + { 16649979327439178909U, 853 }, { 12405201291620119593U, 880 }, + { 9242595204427927429U, 907 }, { 13772540099066387757U, 933 }, + { 10261342003245940623U, 960 }, { 15290591125556738113U, 986 }, + { 11392378155556871081U, 1013 }, { 16975966327722178521U, 1039 }, + { 12648080533535911531U, 1066 } +}; + +static Fp find_cachedpow10(int exp, int* k) +{ + const double one_log_ten = 0.30102999566398114; + + int approx = (int)(-(exp + npowers) * one_log_ten); + int idx = (approx - firstpower) / steppowers; + + while(1) { + int current = exp + powers_ten[idx].exp + 64; + + if(current < expmin) { + idx++; + continue; + } + + if(current > expmax) { + idx--; + continue; + } + + *k = (firstpower + idx * steppowers); + + return powers_ten[idx]; + } +} + +#define fracmask 0x000FFFFFFFFFFFFFU +#define expmask 0x7FF0000000000000U +#define hiddenbit 0x0010000000000000U +#define signmask 0x8000000000000000U +#define expbias (1023 + 52) + +#define absv(n) ((n) < 0 ? -(n) : (n)) +#define minv(a, b) ((a) < (b) ? (a) : (b)) + +static const uint64_t tens[] = { + 10000000000000000000U, 1000000000000000000U, 100000000000000000U, + 10000000000000000U, 1000000000000000U, 100000000000000U, + 10000000000000U, 1000000000000U, 100000000000U, + 10000000000U, 1000000000U, 100000000U, + 10000000U, 1000000U, 100000U, + 10000U, 1000U, 100U, + 10U, 1U +}; + +static inline uint64_t get_dbits(double d) +{ + union { + double dbl; + uint64_t i; + } dbl_bits = { d }; + + return dbl_bits.i; +} + +static Fp build_fp(double d) +{ + uint64_t bits = get_dbits(d); + + Fp fp; + fp.frac = bits & fracmask; + fp.exp = (bits & expmask) >> 52; + + if(fp.exp) { + fp.frac += hiddenbit; + fp.exp -= expbias; + + } else { + fp.exp = -expbias + 1; + } + + return fp; +} + +static void normalize(Fp* fp) +{ + while ((fp->frac & hiddenbit) == 0) { + fp->frac <<= 1; + fp->exp--; + } + + int shift = 64 - 52 - 1; + fp->frac <<= shift; + fp->exp -= shift; +} + +static void get_normalized_boundaries(Fp* fp, Fp* lower, Fp* upper) +{ + upper->frac = (fp->frac << 1) + 1; + upper->exp = fp->exp - 1; + + while ((upper->frac & (hiddenbit << 1)) == 0) { + upper->frac <<= 1; + upper->exp--; + } + + int u_shift = 64 - 52 - 2; + + upper->frac <<= u_shift; + upper->exp = upper->exp - u_shift; + + + int l_shift = fp->frac == hiddenbit ? 2 : 1; + + lower->frac = (fp->frac << l_shift) - 1; + lower->exp = fp->exp - l_shift; + + + lower->frac <<= lower->exp - upper->exp; + lower->exp = upper->exp; +} + +static Fp multiply(Fp* a, Fp* b) +{ + const uint64_t lomask = 0x00000000FFFFFFFF; + + uint64_t ah_bl = (a->frac >> 32) * (b->frac & lomask); + uint64_t al_bh = (a->frac & lomask) * (b->frac >> 32); + uint64_t al_bl = (a->frac & lomask) * (b->frac & lomask); + uint64_t ah_bh = (a->frac >> 32) * (b->frac >> 32); + + uint64_t tmp = (ah_bl & lomask) + (al_bh & lomask) + (al_bl >> 32); + /* round up */ + tmp += 1U << 31; + + Fp fp = { + ah_bh + (ah_bl >> 32) + (al_bh >> 32) + (tmp >> 32), + a->exp + b->exp + 64 + }; + + return fp; +} + +static void round_digit(char* digits, int ndigits, uint64_t delta, uint64_t rem, uint64_t kappa, uint64_t frac) +{ + while (rem < frac && delta - rem >= kappa && + (rem + kappa < frac || frac - rem > rem + kappa - frac)) { + + digits[ndigits - 1]--; + rem += kappa; + } +} + +static int generate_digits(Fp* fp, Fp* upper, Fp* lower, char* digits, int* K) +{ + uint64_t wfrac = upper->frac - fp->frac; + uint64_t delta = upper->frac - lower->frac; + + Fp one; + one.frac = 1ULL << -upper->exp; + one.exp = upper->exp; + + uint64_t part1 = upper->frac >> -one.exp; + uint64_t part2 = upper->frac & (one.frac - 1); + + int idx = 0, kappa = 10; + const uint64_t* divp; + /* 1000000000 */ + for(divp = tens + 10; kappa > 0; divp++) { + + uint64_t div = *divp; + unsigned digit = (unsigned) (part1 / div); + + if (digit || idx) { + digits[idx++] = digit + '0'; + } + + part1 -= digit * div; + kappa--; + + uint64_t tmp = (part1 <<-one.exp) + part2; + if (tmp <= delta) { + *K += kappa; + round_digit(digits, idx, delta, tmp, div << -one.exp, wfrac); + + return idx; + } + } + + /* 10 */ + const uint64_t* unit = tens + 18; + + while(true) { + part2 *= 10; + delta *= 10; + kappa--; + + unsigned digit = (unsigned) (part2 >> -one.exp); + if (digit || idx) { + digits[idx++] = digit + '0'; + } + + part2 &= one.frac - 1; + if (part2 < delta) { + *K += kappa; + round_digit(digits, idx, delta, part2, one.frac, wfrac * *unit); + + return idx; + } + + unit--; + } +} + +static int grisu2(double d, char* digits, int* K) +{ + Fp w = build_fp(d); + + Fp lower, upper; + get_normalized_boundaries(&w, &lower, &upper); + + normalize(&w); + + int k; + Fp cp = find_cachedpow10(upper.exp, &k); + + w = multiply(&w, &cp); + upper = multiply(&upper, &cp); + lower = multiply(&lower, &cp); + + lower.frac++; + upper.frac--; + + *K = -k; + + return generate_digits(&w, &upper, &lower, digits, K); +} + +static int emit_digits(char* digits, int ndigits, char* dest, int K, bool neg) +{ + int exp = absv(K + ndigits - 1); + + int max_trailing_zeros = 7; + + if(neg) { + max_trailing_zeros -= 1; + } + + /* write plain integer */ + if(K >= 0 && (exp < (ndigits + max_trailing_zeros))) { + + memcpy(dest, digits, ndigits); + memset(dest + ndigits, '0', K); + + /* add a .0 to mark this as a float. */ + dest[ndigits + K] = '.'; + dest[ndigits + K + 1] = '0'; + + return ndigits + K + 2; + } + + /* write decimal w/o scientific notation */ + if(K < 0 && (K > -7 || exp < 10)) { + int offset = ndigits - absv(K); + /* fp < 1.0 -> write leading zero */ + if(offset <= 0) { + offset = -offset; + dest[0] = '0'; + dest[1] = '.'; + memset(dest + 2, '0', offset); + memcpy(dest + offset + 2, digits, ndigits); + + return ndigits + 2 + offset; + + /* fp > 1.0 */ + } else { + memcpy(dest, digits, offset); + dest[offset] = '.'; + memcpy(dest + offset + 1, digits + offset, ndigits - offset); + + return ndigits + 1; + } + } + + /* write decimal w/ scientific notation */ + ndigits = minv(ndigits, 18 - neg); + + int idx = 0; + dest[idx++] = digits[0]; + + if(ndigits > 1) { + dest[idx++] = '.'; + memcpy(dest + idx, digits + 1, ndigits - 1); + idx += ndigits - 1; + } + + dest[idx++] = 'e'; + + char sign = K + ndigits - 1 < 0 ? '-' : '+'; + dest[idx++] = sign; + + int cent = 0; + + if(exp > 99) { + cent = exp / 100; + dest[idx++] = cent + '0'; + exp -= cent * 100; + } + if(exp > 9) { + int dec = exp / 10; + dest[idx++] = dec + '0'; + exp -= dec * 10; + + } else if(cent) { + dest[idx++] = '0'; + } + + dest[idx++] = exp % 10 + '0'; + + return idx; +} + +static int filter_special(double fp, char* dest) +{ + if(fp == 0.0) { + dest[0] = '0'; + dest[1] = '.'; + dest[2] = '0'; + return 3; + } + + uint64_t bits = get_dbits(fp); + + bool nan = (bits & expmask) == expmask; + + if(!nan) { + return 0; + } + + if(bits & fracmask) { + dest[0] = 'n'; dest[1] = 'a'; dest[2] = 'n'; + + } else { + dest[0] = 'i'; dest[1] = 'n'; dest[2] = 'f'; + } + + return 3; +} + +/* Fast and accurate double to string conversion based on Florian Loitsch's + * Grisu-algorithm[1]. + * + * Input: + * fp -> the double to convert, dest -> destination buffer. + * The generated string will never be longer than 28 characters. + * Make sure to pass a pointer to at least 28 bytes of memory. + * The emitted string will not be null terminated. + * + * Output: + * The number of written characters. + * + * Exemplary usage: + * + * void print(double d) + * { + * char buf[28 + 1] // plus null terminator + * int str_len = fpconv_dtoa(d, buf); + * + * buf[str_len] = '\0'; + * printf("%s", buf); + * } + * + */ +static int fpconv_dtoa(double d, char dest[28]) +{ + char digits[18]; + + int str_len = 0; + bool neg = false; + + if(get_dbits(d) & signmask) { + dest[0] = '-'; + str_len++; + neg = true; + } + + int spec = filter_special(d, dest + str_len); + + if(spec) { + return str_len + spec; + } + + int K = 0; + int ndigits = grisu2(d, digits, &K); + + str_len += emit_digits(digits, ndigits, dest + str_len, K, neg); + + return str_len; +} diff --git a/ext/json/vendor/jeaiii-ltoa.h b/ext/json/vendor/jeaiii-ltoa.h new file mode 100644 index 00000000000000..ba4f497fc8b22b --- /dev/null +++ b/ext/json/vendor/jeaiii-ltoa.h @@ -0,0 +1,267 @@ +/* + +This file is released under the terms of the MIT License. It is based on the +work of James Edward Anhalt III, with the original license listed below. + +MIT License + +Copyright (c) 2024,2025 Enrico Thierbach - https://github.com/radiospiel +Copyright (c) 2022 James Edward Anhalt III - https://github.com/jeaiii/itoa + +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 JEAIII_TO_TEXT_H_ +#define JEAIII_TO_TEXT_H_ + +#include + +typedef uint_fast32_t u32_t; +typedef uint_fast64_t u64_t; + +#define u32(x) ((u32_t)(x)) +#define u64(x) ((u64_t)(x)) + +struct digit_pair +{ + char dd[2]; +}; + +static const struct digit_pair *digits_dd = (struct digit_pair *)( + "00" "01" "02" "03" "04" "05" "06" "07" "08" "09" + "10" "11" "12" "13" "14" "15" "16" "17" "18" "19" + "20" "21" "22" "23" "24" "25" "26" "27" "28" "29" + "30" "31" "32" "33" "34" "35" "36" "37" "38" "39" + "40" "41" "42" "43" "44" "45" "46" "47" "48" "49" + "50" "51" "52" "53" "54" "55" "56" "57" "58" "59" + "60" "61" "62" "63" "64" "65" "66" "67" "68" "69" + "70" "71" "72" "73" "74" "75" "76" "77" "78" "79" + "80" "81" "82" "83" "84" "85" "86" "87" "88" "89" + "90" "91" "92" "93" "94" "95" "96" "97" "98" "99" +); + +static const struct digit_pair *digits_fd = (struct digit_pair *)( + "0_" "1_" "2_" "3_" "4_" "5_" "6_" "7_" "8_" "9_" + "10" "11" "12" "13" "14" "15" "16" "17" "18" "19" + "20" "21" "22" "23" "24" "25" "26" "27" "28" "29" + "30" "31" "32" "33" "34" "35" "36" "37" "38" "39" + "40" "41" "42" "43" "44" "45" "46" "47" "48" "49" + "50" "51" "52" "53" "54" "55" "56" "57" "58" "59" + "60" "61" "62" "63" "64" "65" "66" "67" "68" "69" + "70" "71" "72" "73" "74" "75" "76" "77" "78" "79" + "80" "81" "82" "83" "84" "85" "86" "87" "88" "89" + "90" "91" "92" "93" "94" "95" "96" "97" "98" "99" +); + +static const u64_t mask24 = (u64(1) << 24) - 1; +static const u64_t mask32 = (u64(1) << 32) - 1; +static const u64_t mask57 = (u64(1) << 57) - 1; + +#define COPY(buffer, digits) memcpy(buffer, &(digits), sizeof(struct digit_pair)) + +static char * +jeaiii_ultoa(char *b, u64_t n) +{ + if (n < u32(1e2)) { + COPY(b, digits_fd[n]); + return n < 10 ? b + 1 : b + 2; + } + + if (n < u32(1e6)) { + if (n < u32(1e4)) { + u32_t f0 = u32((10 * (1 << 24) / 1e3 + 1) * n); + COPY(b, digits_fd[f0 >> 24]); + + b -= n < u32(1e3); + u32_t f2 = (f0 & mask24) * 100; + COPY(b + 2, digits_dd[f2 >> 24]); + + return b + 4; + } + + u64_t f0 = u64(10 * (1ull << 32ull)/ 1e5 + 1) * n; + COPY(b, digits_fd[f0 >> 32]); + + b -= n < u32(1e5); + u64_t f2 = (f0 & mask32) * 100; + COPY(b + 2, digits_dd[f2 >> 32]); + + u64_t f4 = (f2 & mask32) * 100; + COPY(b + 4, digits_dd[f4 >> 32]); + return b + 6; + } + + if (n < u64(1ull << 32ull)) { + if (n < u32(1e8)) { + u64_t f0 = u64(10 * (1ull << 48ull) / 1e7 + 1) * n >> 16; + COPY(b, digits_fd[f0 >> 32]); + + b -= n < u32(1e7); + u64_t f2 = (f0 & mask32) * 100; + COPY(b + 2, digits_dd[f2 >> 32]); + + u64_t f4 = (f2 & mask32) * 100; + COPY(b + 4, digits_dd[f4 >> 32]); + + u64_t f6 = (f4 & mask32) * 100; + COPY(b + 6, digits_dd[f6 >> 32]); + + return b + 8; + } + + u64_t f0 = u64(10 * (1ull << 57ull) / 1e9 + 1) * n; + COPY(b, digits_fd[f0 >> 57]); + + b -= n < u32(1e9); + u64_t f2 = (f0 & mask57) * 100; + COPY(b + 2, digits_dd[f2 >> 57]); + + u64_t f4 = (f2 & mask57) * 100; + COPY(b + 4, digits_dd[f4 >> 57]); + + u64_t f6 = (f4 & mask57) * 100; + COPY(b + 6, digits_dd[f6 >> 57]); + + u64_t f8 = (f6 & mask57) * 100; + COPY(b + 8, digits_dd[f8 >> 57]); + + return b + 10; + } + + // if we get here U must be u64 but some compilers don't know that, so reassign n to a u64 to avoid warnings + u32_t z = n % u32(1e8); + u64_t u = n / u32(1e8); + + if (u < u32(1e2)) { + // u can't be 1 digit (if u < 10 it would have been handled above as a 9 digit 32bit number) + COPY(b, digits_dd[u]); + b += 2; + } + else if (u < u32(1e6)) { + if (u < u32(1e4)) { + u32_t f0 = u32((10 * (1 << 24) / 1e3 + 1) * u); + COPY(b, digits_fd[f0 >> 24]); + + b -= u < u32(1e3); + u32_t f2 = (f0 & mask24) * 100; + COPY(b + 2, digits_dd[f2 >> 24]); + b += 4; + } + else { + u64_t f0 = u64(10 * (1ull << 32ull) / 1e5 + 1) * u; + COPY(b, digits_fd[f0 >> 32]); + + b -= u < u32(1e5); + u64_t f2 = (f0 & mask32) * 100; + COPY(b + 2, digits_dd[f2 >> 32]); + + u64_t f4 = (f2 & mask32) * 100; + COPY(b + 4, digits_dd[f4 >> 32]); + b += 6; + } + } + else if (u < u32(1e8)) { + u64_t f0 = u64(10 * (1ull << 48ull) / 1e7 + 1) * u >> 16; + COPY(b, digits_fd[f0 >> 32]); + + b -= u < u32(1e7); + u64_t f2 = (f0 & mask32) * 100; + COPY(b + 2, digits_dd[f2 >> 32]); + + u64_t f4 = (f2 & mask32) * 100; + COPY(b + 4, digits_dd[f4 >> 32]); + + u64_t f6 = (f4 & mask32) * 100; + COPY(b + 6, digits_dd[f6 >> 32]); + + b += 8; + } + else if (u < u64(1ull << 32ull)) { + u64_t f0 = u64(10 * (1ull << 57ull) / 1e9 + 1) * u; + COPY(b, digits_fd[f0 >> 57]); + + b -= u < u32(1e9); + u64_t f2 = (f0 & mask57) * 100; + COPY(b + 2, digits_dd[f2 >> 57]); + + u64_t f4 = (f2 & mask57) * 100; + COPY(b + 4, digits_dd[f4 >> 57]); + + u64_t f6 = (f4 & mask57) * 100; + COPY(b + 6, digits_dd[f6 >> 57]); + + u64_t f8 = (f6 & mask57) * 100; + COPY(b + 8, digits_dd[f8 >> 57]); + b += 10; + } + else { + u32_t y = u % u32(1e8); + u /= u32(1e8); + + // u is 2, 3, or 4 digits (if u < 10 it would have been handled above) + if (u < u32(1e2)) { + COPY(b, digits_dd[u]); + b += 2; + } + else { + u32_t f0 = u32((10 * (1 << 24) / 1e3 + 1) * u); + COPY(b, digits_fd[f0 >> 24]); + + b -= u < u32(1e3); + u32_t f2 = (f0 & mask24) * 100; + COPY(b + 2, digits_dd[f2 >> 24]); + + b += 4; + } + // do 8 digits + u64_t f0 = (u64((1ull << 48ull) / 1e6 + 1) * y >> 16) + 1; + COPY(b, digits_dd[f0 >> 32]); + + u64_t f2 = (f0 & mask32) * 100; + COPY(b + 2, digits_dd[f2 >> 32]); + + u64_t f4 = (f2 & mask32) * 100; + COPY(b + 4, digits_dd[f4 >> 32]); + + u64_t f6 = (f4 & mask32) * 100; + COPY(b + 6, digits_dd[f6 >> 32]); + b += 8; + } + + // do 8 digits + u64_t f0 = (u64((1ull << 48ull) / 1e6 + 1) * z >> 16) + 1; + COPY(b, digits_dd[f0 >> 32]); + + u64_t f2 = (f0 & mask32) * 100; + COPY(b + 2, digits_dd[f2 >> 32]); + + u64_t f4 = (f2 & mask32) * 100; + COPY(b + 4, digits_dd[f4 >> 32]); + + u64_t f6 = (f4 & mask32) * 100; + COPY(b + 6, digits_dd[f6 >> 32]); + + return b + 8; +} + +#undef u32 +#undef u64 +#undef COPY + +#endif // JEAIII_TO_TEXT_H_ diff --git a/ext/monitor/depend b/ext/monitor/depend index 38e21b3f669f97..0c7d54afc8dc57 100644 --- a/ext/monitor/depend +++ b/ext/monitor/depend @@ -127,6 +127,7 @@ monitor.o: $(hdrdir)/ruby/internal/intern/re.h monitor.o: $(hdrdir)/ruby/internal/intern/ruby.h monitor.o: $(hdrdir)/ruby/internal/intern/select.h monitor.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +monitor.o: $(hdrdir)/ruby/internal/intern/set.h monitor.o: $(hdrdir)/ruby/internal/intern/signal.h monitor.o: $(hdrdir)/ruby/internal/intern/sprintf.h monitor.o: $(hdrdir)/ruby/internal/intern/string.h @@ -146,6 +147,7 @@ monitor.o: $(hdrdir)/ruby/internal/special_consts.h monitor.o: $(hdrdir)/ruby/internal/static_assert.h monitor.o: $(hdrdir)/ruby/internal/stdalign.h monitor.o: $(hdrdir)/ruby/internal/stdbool.h +monitor.o: $(hdrdir)/ruby/internal/stdckdint.h monitor.o: $(hdrdir)/ruby/internal/symbol.h monitor.o: $(hdrdir)/ruby/internal/value.h monitor.o: $(hdrdir)/ruby/internal/value_type.h diff --git a/ext/monitor/lib/monitor.rb b/ext/monitor/lib/monitor.rb index 31d6d2b3c4a1b6..82d0a75c5665f4 100644 --- a/ext/monitor/lib/monitor.rb +++ b/ext/monitor/lib/monitor.rb @@ -143,13 +143,13 @@ def broadcast private - def initialize(monitor) + def initialize(monitor) # :nodoc: @monitor = monitor @cond = Thread::ConditionVariable.new end end - def self.extend_object(obj) + def self.extend_object(obj) # :nodoc: super(obj) obj.__send__(:mon_initialize) end @@ -238,6 +238,8 @@ def mon_initialize @mon_data_owner_object_id = self.object_id end + # Ensures that the MonitorMixin is owned by the current thread, + # otherwise raises an exception. def mon_check_owner @mon_data.mon_check_owner end @@ -254,6 +256,10 @@ def mon_check_owner # end # class Monitor + # + # Creates a new MonitorMixin::ConditionVariable associated with the + # Monitor object. + # def new_cond ::MonitorMixin::ConditionVariable.new(self) end diff --git a/ext/monitor/monitor.c b/ext/monitor/monitor.c index 86613f6adecf9e..819c6e76996f61 100644 --- a/ext/monitor/monitor.c +++ b/ext/monitor/monitor.c @@ -56,6 +56,12 @@ mc_owner_p(struct rb_monitor *mc) return mc->owner == rb_fiber_current(); } +/* + * call-seq: + * try_enter -> true or false + * + * Attempts to enter exclusive section. Returns +false+ if lock fails. + */ static VALUE monitor_try_enter(VALUE monitor) { @@ -72,6 +78,12 @@ monitor_try_enter(VALUE monitor) return Qtrue; } +/* + * call-seq: + * enter -> nil + * + * Enters exclusive section. + */ static VALUE monitor_enter(VALUE monitor) { @@ -85,6 +97,7 @@ monitor_enter(VALUE monitor) return Qnil; } +/* :nodoc: */ static VALUE monitor_check_owner(VALUE monitor) { @@ -95,6 +108,12 @@ monitor_check_owner(VALUE monitor) return Qnil; } +/* + * call-seq: + * exit -> nil + * + * Leaves exclusive section. + */ static VALUE monitor_exit(VALUE monitor) { @@ -112,6 +131,7 @@ monitor_exit(VALUE monitor) return Qnil; } +/* :nodoc: */ static VALUE monitor_locked_p(VALUE monitor) { @@ -119,6 +139,7 @@ monitor_locked_p(VALUE monitor) return rb_mutex_locked_p(mc->mutex); } +/* :nodoc: */ static VALUE monitor_owned_p(VALUE monitor) { @@ -166,6 +187,7 @@ monitor_enter_for_cond(VALUE v) return Qnil; } +/* :nodoc: */ static VALUE monitor_wait_for_cond(VALUE monitor, VALUE cond, VALUE timeout) { @@ -193,6 +215,14 @@ monitor_sync_ensure(VALUE monitor) return monitor_exit(monitor); } +/* + * call-seq: + * synchronize { } -> result of the block + * + * Enters exclusive section and executes the block. Leaves the exclusive + * section automatically when the block exits. See example under + * +MonitorMixin+. + */ static VALUE monitor_synchronize(VALUE monitor) { diff --git a/ext/nkf/depend b/ext/nkf/depend deleted file mode 100644 index 98afc5f201fcc8..00000000000000 --- a/ext/nkf/depend +++ /dev/null @@ -1,181 +0,0 @@ -# BSD make needs "nkf.o: nkf.c" dependency BEFORE "nkf.o: nkf-utf8/nkf.c". -# It seems BSD make searches the target for implicit rule in dependencies at first. -nkf.o: nkf.c - -# AUTOGENERATED DEPENDENCIES START -nkf.o: $(RUBY_EXTCONF_H) -nkf.o: $(arch_hdrdir)/ruby/config.h -nkf.o: $(hdrdir)/ruby/assert.h -nkf.o: $(hdrdir)/ruby/backward.h -nkf.o: $(hdrdir)/ruby/backward/2/assume.h -nkf.o: $(hdrdir)/ruby/backward/2/attributes.h -nkf.o: $(hdrdir)/ruby/backward/2/bool.h -nkf.o: $(hdrdir)/ruby/backward/2/inttypes.h -nkf.o: $(hdrdir)/ruby/backward/2/limits.h -nkf.o: $(hdrdir)/ruby/backward/2/long_long.h -nkf.o: $(hdrdir)/ruby/backward/2/stdalign.h -nkf.o: $(hdrdir)/ruby/backward/2/stdarg.h -nkf.o: $(hdrdir)/ruby/defines.h -nkf.o: $(hdrdir)/ruby/encoding.h -nkf.o: $(hdrdir)/ruby/intern.h -nkf.o: $(hdrdir)/ruby/internal/abi.h -nkf.o: $(hdrdir)/ruby/internal/anyargs.h -nkf.o: $(hdrdir)/ruby/internal/arithmetic.h -nkf.o: $(hdrdir)/ruby/internal/arithmetic/char.h -nkf.o: $(hdrdir)/ruby/internal/arithmetic/double.h -nkf.o: $(hdrdir)/ruby/internal/arithmetic/fixnum.h -nkf.o: $(hdrdir)/ruby/internal/arithmetic/gid_t.h -nkf.o: $(hdrdir)/ruby/internal/arithmetic/int.h -nkf.o: $(hdrdir)/ruby/internal/arithmetic/intptr_t.h -nkf.o: $(hdrdir)/ruby/internal/arithmetic/long.h -nkf.o: $(hdrdir)/ruby/internal/arithmetic/long_long.h -nkf.o: $(hdrdir)/ruby/internal/arithmetic/mode_t.h -nkf.o: $(hdrdir)/ruby/internal/arithmetic/off_t.h -nkf.o: $(hdrdir)/ruby/internal/arithmetic/pid_t.h -nkf.o: $(hdrdir)/ruby/internal/arithmetic/short.h -nkf.o: $(hdrdir)/ruby/internal/arithmetic/size_t.h -nkf.o: $(hdrdir)/ruby/internal/arithmetic/st_data_t.h -nkf.o: $(hdrdir)/ruby/internal/arithmetic/uid_t.h -nkf.o: $(hdrdir)/ruby/internal/assume.h -nkf.o: $(hdrdir)/ruby/internal/attr/alloc_size.h -nkf.o: $(hdrdir)/ruby/internal/attr/artificial.h -nkf.o: $(hdrdir)/ruby/internal/attr/cold.h -nkf.o: $(hdrdir)/ruby/internal/attr/const.h -nkf.o: $(hdrdir)/ruby/internal/attr/constexpr.h -nkf.o: $(hdrdir)/ruby/internal/attr/deprecated.h -nkf.o: $(hdrdir)/ruby/internal/attr/diagnose_if.h -nkf.o: $(hdrdir)/ruby/internal/attr/enum_extensibility.h -nkf.o: $(hdrdir)/ruby/internal/attr/error.h -nkf.o: $(hdrdir)/ruby/internal/attr/flag_enum.h -nkf.o: $(hdrdir)/ruby/internal/attr/forceinline.h -nkf.o: $(hdrdir)/ruby/internal/attr/format.h -nkf.o: $(hdrdir)/ruby/internal/attr/maybe_unused.h -nkf.o: $(hdrdir)/ruby/internal/attr/noalias.h -nkf.o: $(hdrdir)/ruby/internal/attr/nodiscard.h -nkf.o: $(hdrdir)/ruby/internal/attr/noexcept.h -nkf.o: $(hdrdir)/ruby/internal/attr/noinline.h -nkf.o: $(hdrdir)/ruby/internal/attr/nonnull.h -nkf.o: $(hdrdir)/ruby/internal/attr/noreturn.h -nkf.o: $(hdrdir)/ruby/internal/attr/packed_struct.h -nkf.o: $(hdrdir)/ruby/internal/attr/pure.h -nkf.o: $(hdrdir)/ruby/internal/attr/restrict.h -nkf.o: $(hdrdir)/ruby/internal/attr/returns_nonnull.h -nkf.o: $(hdrdir)/ruby/internal/attr/warning.h -nkf.o: $(hdrdir)/ruby/internal/attr/weakref.h -nkf.o: $(hdrdir)/ruby/internal/cast.h -nkf.o: $(hdrdir)/ruby/internal/compiler_is.h -nkf.o: $(hdrdir)/ruby/internal/compiler_is/apple.h -nkf.o: $(hdrdir)/ruby/internal/compiler_is/clang.h -nkf.o: $(hdrdir)/ruby/internal/compiler_is/gcc.h -nkf.o: $(hdrdir)/ruby/internal/compiler_is/intel.h -nkf.o: $(hdrdir)/ruby/internal/compiler_is/msvc.h -nkf.o: $(hdrdir)/ruby/internal/compiler_is/sunpro.h -nkf.o: $(hdrdir)/ruby/internal/compiler_since.h -nkf.o: $(hdrdir)/ruby/internal/config.h -nkf.o: $(hdrdir)/ruby/internal/constant_p.h -nkf.o: $(hdrdir)/ruby/internal/core.h -nkf.o: $(hdrdir)/ruby/internal/core/rarray.h -nkf.o: $(hdrdir)/ruby/internal/core/rbasic.h -nkf.o: $(hdrdir)/ruby/internal/core/rbignum.h -nkf.o: $(hdrdir)/ruby/internal/core/rclass.h -nkf.o: $(hdrdir)/ruby/internal/core/rdata.h -nkf.o: $(hdrdir)/ruby/internal/core/rfile.h -nkf.o: $(hdrdir)/ruby/internal/core/rhash.h -nkf.o: $(hdrdir)/ruby/internal/core/robject.h -nkf.o: $(hdrdir)/ruby/internal/core/rregexp.h -nkf.o: $(hdrdir)/ruby/internal/core/rstring.h -nkf.o: $(hdrdir)/ruby/internal/core/rstruct.h -nkf.o: $(hdrdir)/ruby/internal/core/rtypeddata.h -nkf.o: $(hdrdir)/ruby/internal/ctype.h -nkf.o: $(hdrdir)/ruby/internal/dllexport.h -nkf.o: $(hdrdir)/ruby/internal/dosish.h -nkf.o: $(hdrdir)/ruby/internal/encoding/coderange.h -nkf.o: $(hdrdir)/ruby/internal/encoding/ctype.h -nkf.o: $(hdrdir)/ruby/internal/encoding/encoding.h -nkf.o: $(hdrdir)/ruby/internal/encoding/pathname.h -nkf.o: $(hdrdir)/ruby/internal/encoding/re.h -nkf.o: $(hdrdir)/ruby/internal/encoding/sprintf.h -nkf.o: $(hdrdir)/ruby/internal/encoding/string.h -nkf.o: $(hdrdir)/ruby/internal/encoding/symbol.h -nkf.o: $(hdrdir)/ruby/internal/encoding/transcode.h -nkf.o: $(hdrdir)/ruby/internal/error.h -nkf.o: $(hdrdir)/ruby/internal/eval.h -nkf.o: $(hdrdir)/ruby/internal/event.h -nkf.o: $(hdrdir)/ruby/internal/fl_type.h -nkf.o: $(hdrdir)/ruby/internal/gc.h -nkf.o: $(hdrdir)/ruby/internal/glob.h -nkf.o: $(hdrdir)/ruby/internal/globals.h -nkf.o: $(hdrdir)/ruby/internal/has/attribute.h -nkf.o: $(hdrdir)/ruby/internal/has/builtin.h -nkf.o: $(hdrdir)/ruby/internal/has/c_attribute.h -nkf.o: $(hdrdir)/ruby/internal/has/cpp_attribute.h -nkf.o: $(hdrdir)/ruby/internal/has/declspec_attribute.h -nkf.o: $(hdrdir)/ruby/internal/has/extension.h -nkf.o: $(hdrdir)/ruby/internal/has/feature.h -nkf.o: $(hdrdir)/ruby/internal/has/warning.h -nkf.o: $(hdrdir)/ruby/internal/intern/array.h -nkf.o: $(hdrdir)/ruby/internal/intern/bignum.h -nkf.o: $(hdrdir)/ruby/internal/intern/class.h -nkf.o: $(hdrdir)/ruby/internal/intern/compar.h -nkf.o: $(hdrdir)/ruby/internal/intern/complex.h -nkf.o: $(hdrdir)/ruby/internal/intern/cont.h -nkf.o: $(hdrdir)/ruby/internal/intern/dir.h -nkf.o: $(hdrdir)/ruby/internal/intern/enum.h -nkf.o: $(hdrdir)/ruby/internal/intern/enumerator.h -nkf.o: $(hdrdir)/ruby/internal/intern/error.h -nkf.o: $(hdrdir)/ruby/internal/intern/eval.h -nkf.o: $(hdrdir)/ruby/internal/intern/file.h -nkf.o: $(hdrdir)/ruby/internal/intern/hash.h -nkf.o: $(hdrdir)/ruby/internal/intern/io.h -nkf.o: $(hdrdir)/ruby/internal/intern/load.h -nkf.o: $(hdrdir)/ruby/internal/intern/marshal.h -nkf.o: $(hdrdir)/ruby/internal/intern/numeric.h -nkf.o: $(hdrdir)/ruby/internal/intern/object.h -nkf.o: $(hdrdir)/ruby/internal/intern/parse.h -nkf.o: $(hdrdir)/ruby/internal/intern/proc.h -nkf.o: $(hdrdir)/ruby/internal/intern/process.h -nkf.o: $(hdrdir)/ruby/internal/intern/random.h -nkf.o: $(hdrdir)/ruby/internal/intern/range.h -nkf.o: $(hdrdir)/ruby/internal/intern/rational.h -nkf.o: $(hdrdir)/ruby/internal/intern/re.h -nkf.o: $(hdrdir)/ruby/internal/intern/ruby.h -nkf.o: $(hdrdir)/ruby/internal/intern/select.h -nkf.o: $(hdrdir)/ruby/internal/intern/select/largesize.h -nkf.o: $(hdrdir)/ruby/internal/intern/signal.h -nkf.o: $(hdrdir)/ruby/internal/intern/sprintf.h -nkf.o: $(hdrdir)/ruby/internal/intern/string.h -nkf.o: $(hdrdir)/ruby/internal/intern/struct.h -nkf.o: $(hdrdir)/ruby/internal/intern/thread.h -nkf.o: $(hdrdir)/ruby/internal/intern/time.h -nkf.o: $(hdrdir)/ruby/internal/intern/variable.h -nkf.o: $(hdrdir)/ruby/internal/intern/vm.h -nkf.o: $(hdrdir)/ruby/internal/interpreter.h -nkf.o: $(hdrdir)/ruby/internal/iterator.h -nkf.o: $(hdrdir)/ruby/internal/memory.h -nkf.o: $(hdrdir)/ruby/internal/method.h -nkf.o: $(hdrdir)/ruby/internal/module.h -nkf.o: $(hdrdir)/ruby/internal/newobj.h -nkf.o: $(hdrdir)/ruby/internal/scan_args.h -nkf.o: $(hdrdir)/ruby/internal/special_consts.h -nkf.o: $(hdrdir)/ruby/internal/static_assert.h -nkf.o: $(hdrdir)/ruby/internal/stdalign.h -nkf.o: $(hdrdir)/ruby/internal/stdbool.h -nkf.o: $(hdrdir)/ruby/internal/symbol.h -nkf.o: $(hdrdir)/ruby/internal/value.h -nkf.o: $(hdrdir)/ruby/internal/value_type.h -nkf.o: $(hdrdir)/ruby/internal/variable.h -nkf.o: $(hdrdir)/ruby/internal/warning_push.h -nkf.o: $(hdrdir)/ruby/internal/xmalloc.h -nkf.o: $(hdrdir)/ruby/missing.h -nkf.o: $(hdrdir)/ruby/onigmo.h -nkf.o: $(hdrdir)/ruby/oniguruma.h -nkf.o: $(hdrdir)/ruby/ruby.h -nkf.o: $(hdrdir)/ruby/st.h -nkf.o: $(hdrdir)/ruby/subst.h -nkf.o: nkf-utf8/config.h -nkf.o: nkf-utf8/nkf.c -nkf.o: nkf-utf8/nkf.h -nkf.o: nkf-utf8/utf8tbl.c -nkf.o: nkf-utf8/utf8tbl.h -nkf.o: nkf.c -# AUTOGENERATED DEPENDENCIES END diff --git a/ext/nkf/extconf.rb b/ext/nkf/extconf.rb deleted file mode 100644 index f41f6b11dc8fbf..00000000000000 --- a/ext/nkf/extconf.rb +++ /dev/null @@ -1,3 +0,0 @@ -# frozen_string_literal: false -require 'mkmf' -create_makefile('nkf') diff --git a/ext/nkf/lib/kconv.rb b/ext/nkf/lib/kconv.rb deleted file mode 100644 index f52b755288b78b..00000000000000 --- a/ext/nkf/lib/kconv.rb +++ /dev/null @@ -1,283 +0,0 @@ -# frozen_string_literal: false -# -# kconv.rb - Kanji Converter. -# -# $Id$ -# -# ---- -# -# kconv.rb implements the Kconv class for Kanji Converter. Additionally, -# some methods in String classes are added to allow easy conversion. -# - -require 'nkf' - -# -# Kanji Converter for Ruby. -# -module Kconv - # - # Public Constants - # - - #Constant of Encoding - - # Auto-Detect - AUTO = NKF::AUTO - # ISO-2022-JP - JIS = NKF::JIS - # EUC-JP - EUC = NKF::EUC - # Shift_JIS - SJIS = NKF::SJIS - # BINARY - BINARY = NKF::BINARY - # NOCONV - NOCONV = NKF::NOCONV - # ASCII - ASCII = NKF::ASCII - # UTF-8 - UTF8 = NKF::UTF8 - # UTF-16 - UTF16 = NKF::UTF16 - # UTF-32 - UTF32 = NKF::UTF32 - # UNKNOWN - UNKNOWN = NKF::UNKNOWN - - # - # Public Methods - # - - # call-seq: - # Kconv.kconv(str, to_enc, from_enc=nil) - # - # Convert str to to_enc. - # to_enc and from_enc are given as constants of Kconv or Encoding objects. - def kconv(str, to_enc, from_enc=nil) - opt = '' - opt += ' --ic=' + from_enc.to_s if from_enc - opt += ' --oc=' + to_enc.to_s if to_enc - - ::NKF::nkf(opt, str) - end - module_function :kconv - - # - # Encode to - # - - # call-seq: - # Kconv.tojis(str) => string - # - # Convert str to ISO-2022-JP - def tojis(str) - kconv(str, JIS) - end - module_function :tojis - - # call-seq: - # Kconv.toeuc(str) => string - # - # Convert str to EUC-JP - def toeuc(str) - kconv(str, EUC) - end - module_function :toeuc - - # call-seq: - # Kconv.tosjis(str) => string - # - # Convert str to Shift_JIS - def tosjis(str) - kconv(str, SJIS) - end - module_function :tosjis - - # call-seq: - # Kconv.toutf8(str) => string - # - # Convert str to UTF-8 - def toutf8(str) - kconv(str, UTF8) - end - module_function :toutf8 - - # call-seq: - # Kconv.toutf16(str) => string - # - # Convert str to UTF-16 - def toutf16(str) - kconv(str, UTF16) - end - module_function :toutf16 - - # call-seq: - # Kconv.toutf32(str) => string - # - # Convert str to UTF-32 - def toutf32(str) - kconv(str, UTF32) - end - module_function :toutf32 - - # call-seq: - # Kconv.tolocale => string - # - # Convert self to locale encoding - def tolocale(str) - kconv(str, Encoding.locale_charmap) - end - module_function :tolocale - - # - # guess - # - - # call-seq: - # Kconv.guess(str) => encoding - # - # Guess input encoding by NKF.guess - def guess(str) - ::NKF::guess(str) - end - module_function :guess - - # - # isEncoding - # - - # call-seq: - # Kconv.iseuc(str) => true or false - # - # Returns whether input encoding is EUC-JP or not. - # - # *Note* don't expect this return value is MatchData. - def iseuc(str) - str.dup.force_encoding(EUC).valid_encoding? - end - module_function :iseuc - - # call-seq: - # Kconv.issjis(str) => true or false - # - # Returns whether input encoding is Shift_JIS or not. - def issjis(str) - str.dup.force_encoding(SJIS).valid_encoding? - end - module_function :issjis - - # call-seq: - # Kconv.isjis(str) => true or false - # - # Returns whether input encoding is ISO-2022-JP or not. - def isjis(str) - /\A [\t\n\r\x20-\x7E]* - (?: - (?:\x1b \x28 I [\x21-\x7E]* - |\x1b \x28 J [\x21-\x7E]* - |\x1b \x24 @ (?:[\x21-\x7E]{2})* - |\x1b \x24 B (?:[\x21-\x7E]{2})* - |\x1b \x24 \x28 D (?:[\x21-\x7E]{2})* - )* - \x1b \x28 B [\t\n\r\x20-\x7E]* - )* - \z/nox =~ str.dup.force_encoding('BINARY') ? true : false - end - module_function :isjis - - # call-seq: - # Kconv.isutf8(str) => true or false - # - # Returns whether input encoding is UTF-8 or not. - def isutf8(str) - str.dup.force_encoding(UTF8).valid_encoding? - end - module_function :isutf8 -end - -class String - # call-seq: - # String#kconv(to_enc, from_enc) - # - # Convert self to to_enc. - # to_enc and from_enc are given as constants of Kconv or Encoding objects. - def kconv(to_enc, from_enc=nil) - from_enc = self.encoding if !from_enc && self.encoding != Encoding.list[0] - Kconv::kconv(self, to_enc, from_enc) - end - - # - # to Encoding - # - - # call-seq: - # String#tojis => string - # - # Convert self to ISO-2022-JP - def tojis; Kconv.tojis(self) end - - # call-seq: - # String#toeuc => string - # - # Convert self to EUC-JP - def toeuc; Kconv.toeuc(self) end - - # call-seq: - # String#tosjis => string - # - # Convert self to Shift_JIS - def tosjis; Kconv.tosjis(self) end - - # call-seq: - # String#toutf8 => string - # - # Convert self to UTF-8 - def toutf8; Kconv.toutf8(self) end - - # call-seq: - # String#toutf16 => string - # - # Convert self to UTF-16 - def toutf16; Kconv.toutf16(self) end - - # call-seq: - # String#toutf32 => string - # - # Convert self to UTF-32 - def toutf32; Kconv.toutf32(self) end - - # call-seq: - # String#tolocale => string - # - # Convert self to locale encoding - def tolocale; Kconv.tolocale(self) end - - # - # is Encoding - # - - # call-seq: - # String#iseuc => true or false - # - # Returns whether self's encoding is EUC-JP or not. - def iseuc; Kconv.iseuc(self) end - - # call-seq: - # String#issjis => true or false - # - # Returns whether self's encoding is Shift_JIS or not. - def issjis; Kconv.issjis(self) end - - # call-seq: - # String#isjis => true or false - # - # Returns whether self's encoding is ISO-2022-JP or not. - def isjis; Kconv.isjis(self) end - - # call-seq: - # String#isutf8 => true or false - # - # Returns whether self's encoding is UTF-8 or not. - def isutf8; Kconv.isutf8(self) end -end diff --git a/ext/nkf/nkf-utf8/config.h b/ext/nkf/nkf-utf8/config.h deleted file mode 100644 index 36898c0b4b1d98..00000000000000 --- a/ext/nkf/nkf-utf8/config.h +++ /dev/null @@ -1,51 +0,0 @@ -#ifndef _CONFIG_H_ -#define _CONFIG_H_ - -/* UTF8 input and output */ -#define UTF8_INPUT_ENABLE -#define UTF8_OUTPUT_ENABLE - -/* invert characters invalid in Shift_JIS to CP932 */ -#define SHIFTJIS_CP932 - -/* fix input encoding when given by option */ -#define INPUT_CODE_FIX - -/* --overwrite option */ -/* by Satoru Takabayashi */ -#define OVERWRITE - -/* --cap-input, --url-input option */ -#define INPUT_OPTION - -/* --numchar-input option */ -#define NUMCHAR_OPTION - -/* --debug, --no-output option */ -#define CHECK_OPTION - -/* JIS X0212 */ -#define X0212_ENABLE - -/* --exec-in, --exec-out option - * require pipe, fork, execvp and so on. - * please undef this on MS-DOS, MinGW - * this is still buggy around child process - */ -/* #define EXEC_IO */ - -/* Unicode Normalization */ -#define UNICODE_NORMALIZATION - -/* - * Select Default Output Encoding - * - */ - -/* #define DEFAULT_CODE_JIS */ -/* #define DEFAULT_CODE_SJIS */ -/* #define DEFAULT_CODE_WINDOWS_31J */ -/* #define DEFAULT_CODE_EUC */ -/* #define DEFAULT_CODE_UTF8 */ - -#endif /* _CONFIG_H_ */ diff --git a/ext/nkf/nkf-utf8/nkf.c b/ext/nkf/nkf-utf8/nkf.c deleted file mode 100644 index 6888a439183c67..00000000000000 --- a/ext/nkf/nkf-utf8/nkf.c +++ /dev/null @@ -1,7205 +0,0 @@ -/* - * Copyright (c) 1987, Fujitsu LTD. (Itaru ICHIKAWA). - * Copyright (c) 1996-2018, The nkf Project. - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the authors be held liable for any damages - * arising from the use of this software. - * - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software - * in a product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * - * 3. This notice may not be removed or altered from any source distribution. - */ -#define NKF_VERSION "2.1.5" -#define NKF_RELEASE_DATE "2018-12-15" -#define COPY_RIGHT \ - "Copyright (C) 1987, FUJITSU LTD. (I.Ichikawa).\n" \ - "Copyright (C) 1996-2018, The nkf Project." - -#include "config.h" -#include "nkf.h" -#include "utf8tbl.h" -#ifdef __WIN32__ -#include -#include -#endif -#if defined(__OS2__) -# define INCL_DOS -# define INCL_DOSERRORS -# include -#endif -#include - - -/* state of output_mode and input_mode - - c2 0 means ASCII - JIS_X_0201_1976_K - ISO_8859_1 - JIS_X_0208 - EOF all termination - c1 32bit data - - */ - -/* MIME ENCODE */ - -#define FIXED_MIME 7 -#define STRICT_MIME 8 - -/* byte order */ -enum byte_order { - ENDIAN_BIG = 1, - ENDIAN_LITTLE = 2, - ENDIAN_2143 = 3, - ENDIAN_3412 = 4 -}; - -/* ASCII CODE */ - -#define BS 0x08 -#define TAB 0x09 -#define LF 0x0a -#define CR 0x0d -#define ESC 0x1b -#define SP 0x20 -#define DEL 0x7f -#define SI 0x0f -#define SO 0x0e -#define SS2 0x8e -#define SS3 0x8f -#define CRLF 0x0D0A - - -/* encodings */ - -enum nkf_encodings { - ASCII, - ISO_8859_1, - ISO_2022_JP, - CP50220, - CP50221, - CP50222, - ISO_2022_JP_1, - ISO_2022_JP_3, - ISO_2022_JP_2004, - SHIFT_JIS, - WINDOWS_31J, - CP10001, - EUC_JP, - EUCJP_NKF, - CP51932, - EUCJP_MS, - EUCJP_ASCII, - SHIFT_JISX0213, - SHIFT_JIS_2004, - EUC_JISX0213, - EUC_JIS_2004, - UTF_8, - UTF_8N, - UTF_8_BOM, - UTF8_MAC, - UTF_16, - UTF_16BE, - UTF_16BE_BOM, - UTF_16LE, - UTF_16LE_BOM, - UTF_32, - UTF_32BE, - UTF_32BE_BOM, - UTF_32LE, - UTF_32LE_BOM, - BINARY, - NKF_ENCODING_TABLE_SIZE, - JIS_X_0201_1976_K = 0x1013, /* I */ /* JIS C 6220-1969 */ - /* JIS_X_0201_1976_R = 0x1014, */ /* J */ /* JIS C 6220-1969 */ - /* JIS_X_0208_1978 = 0x1040, */ /* @ */ /* JIS C 6226-1978 */ - /* JIS_X_0208_1983 = 0x1087, */ /* B */ /* JIS C 6226-1983 */ - JIS_X_0208 = 0x1168, /* @B */ - JIS_X_0212 = 0x1159, /* D */ - /* JIS_X_0213_2000_1 = 0x1228, */ /* O */ - JIS_X_0213_2 = 0x1229, /* P */ - JIS_X_0213_1 = 0x1233 /* Q */ -}; - -static nkf_char s_iconv(nkf_char c2, nkf_char c1, nkf_char c0); -static nkf_char e_iconv(nkf_char c2, nkf_char c1, nkf_char c0); -static nkf_char w_iconv(nkf_char c2, nkf_char c1, nkf_char c0); -static nkf_char w_iconv16(nkf_char c2, nkf_char c1, nkf_char c0); -static nkf_char w_iconv32(nkf_char c2, nkf_char c1, nkf_char c0); -static void j_oconv(nkf_char c2, nkf_char c1); -static void s_oconv(nkf_char c2, nkf_char c1); -static void e_oconv(nkf_char c2, nkf_char c1); -static void w_oconv(nkf_char c2, nkf_char c1); -static void w_oconv16(nkf_char c2, nkf_char c1); -static void w_oconv32(nkf_char c2, nkf_char c1); - -typedef const struct { - const char *name; - nkf_char (*iconv)(nkf_char c2, nkf_char c1, nkf_char c0); - void (*oconv)(nkf_char c2, nkf_char c1); -} nkf_native_encoding; - -nkf_native_encoding NkfEncodingASCII = { "ASCII", e_iconv, e_oconv }; -nkf_native_encoding NkfEncodingISO_2022_JP = { "ISO-2022-JP", e_iconv, j_oconv }; -nkf_native_encoding NkfEncodingShift_JIS = { "Shift_JIS", s_iconv, s_oconv }; -nkf_native_encoding NkfEncodingEUC_JP = { "EUC-JP", e_iconv, e_oconv }; -nkf_native_encoding NkfEncodingUTF_8 = { "UTF-8", w_iconv, w_oconv }; -nkf_native_encoding NkfEncodingUTF_16 = { "UTF-16", w_iconv16, w_oconv16 }; -nkf_native_encoding NkfEncodingUTF_32 = { "UTF-32", w_iconv32, w_oconv32 }; - -typedef const struct { - int id; - const char *name; - nkf_native_encoding *base_encoding; -} nkf_encoding; - -nkf_encoding nkf_encoding_table[] = { - {ASCII, "US-ASCII", &NkfEncodingASCII}, - {ISO_8859_1, "ISO-8859-1", &NkfEncodingASCII}, - {ISO_2022_JP, "ISO-2022-JP", &NkfEncodingISO_2022_JP}, - {CP50220, "CP50220", &NkfEncodingISO_2022_JP}, - {CP50221, "CP50221", &NkfEncodingISO_2022_JP}, - {CP50222, "CP50222", &NkfEncodingISO_2022_JP}, - {ISO_2022_JP_1, "ISO-2022-JP-1", &NkfEncodingISO_2022_JP}, - {ISO_2022_JP_3, "ISO-2022-JP-3", &NkfEncodingISO_2022_JP}, - {ISO_2022_JP_2004, "ISO-2022-JP-2004", &NkfEncodingISO_2022_JP}, - {SHIFT_JIS, "Shift_JIS", &NkfEncodingShift_JIS}, - {WINDOWS_31J, "Windows-31J", &NkfEncodingShift_JIS}, - {CP10001, "CP10001", &NkfEncodingShift_JIS}, - {EUC_JP, "EUC-JP", &NkfEncodingEUC_JP}, - {EUCJP_NKF, "eucJP-nkf", &NkfEncodingEUC_JP}, - {CP51932, "CP51932", &NkfEncodingEUC_JP}, - {EUCJP_MS, "eucJP-MS", &NkfEncodingEUC_JP}, - {EUCJP_ASCII, "eucJP-ASCII", &NkfEncodingEUC_JP}, - {SHIFT_JISX0213, "Shift_JISX0213", &NkfEncodingShift_JIS}, - {SHIFT_JIS_2004, "Shift_JIS-2004", &NkfEncodingShift_JIS}, - {EUC_JISX0213, "EUC-JISX0213", &NkfEncodingEUC_JP}, - {EUC_JIS_2004, "EUC-JIS-2004", &NkfEncodingEUC_JP}, - {UTF_8, "UTF-8", &NkfEncodingUTF_8}, - {UTF_8N, "UTF-8N", &NkfEncodingUTF_8}, - {UTF_8_BOM, "UTF-8-BOM", &NkfEncodingUTF_8}, - {UTF8_MAC, "UTF8-MAC", &NkfEncodingUTF_8}, - {UTF_16, "UTF-16", &NkfEncodingUTF_16}, - {UTF_16BE, "UTF-16BE", &NkfEncodingUTF_16}, - {UTF_16BE_BOM, "UTF-16BE-BOM", &NkfEncodingUTF_16}, - {UTF_16LE, "UTF-16LE", &NkfEncodingUTF_16}, - {UTF_16LE_BOM, "UTF-16LE-BOM", &NkfEncodingUTF_16}, - {UTF_32, "UTF-32", &NkfEncodingUTF_32}, - {UTF_32BE, "UTF-32BE", &NkfEncodingUTF_32}, - {UTF_32BE_BOM, "UTF-32BE-BOM", &NkfEncodingUTF_32}, - {UTF_32LE, "UTF-32LE", &NkfEncodingUTF_32}, - {UTF_32LE_BOM, "UTF-32LE-BOM", &NkfEncodingUTF_32}, - {BINARY, "BINARY", &NkfEncodingASCII}, - {-1, NULL, NULL} -}; - -static const struct { - const char *name; - int id; -} encoding_name_to_id_table[] = { - {"US-ASCII", ASCII}, - {"ASCII", ASCII}, - {"646", ASCII}, - {"ROMAN8", ASCII}, - {"ISO-2022-JP", ISO_2022_JP}, - {"ISO2022JP-CP932", CP50220}, - {"CP50220", CP50220}, - {"CP50221", CP50221}, - {"CSISO2022JP", CP50221}, - {"CP50222", CP50222}, - {"ISO-2022-JP-1", ISO_2022_JP_1}, - {"ISO-2022-JP-3", ISO_2022_JP_3}, - {"ISO-2022-JP-2004", ISO_2022_JP_2004}, - {"SHIFT_JIS", SHIFT_JIS}, - {"SJIS", SHIFT_JIS}, - {"MS_Kanji", SHIFT_JIS}, - {"PCK", SHIFT_JIS}, - {"WINDOWS-31J", WINDOWS_31J}, - {"CSWINDOWS31J", WINDOWS_31J}, - {"CP932", WINDOWS_31J}, - {"MS932", WINDOWS_31J}, - {"CP10001", CP10001}, - {"EUCJP", EUC_JP}, - {"EUC-JP", EUC_JP}, - {"EUCJP-NKF", EUCJP_NKF}, - {"CP51932", CP51932}, - {"EUC-JP-MS", EUCJP_MS}, - {"EUCJP-MS", EUCJP_MS}, - {"EUCJPMS", EUCJP_MS}, - {"EUC-JP-ASCII", EUCJP_ASCII}, - {"EUCJP-ASCII", EUCJP_ASCII}, - {"SHIFT_JISX0213", SHIFT_JISX0213}, - {"SHIFT_JIS-2004", SHIFT_JIS_2004}, - {"EUC-JISX0213", EUC_JISX0213}, - {"EUC-JIS-2004", EUC_JIS_2004}, - {"UTF-8", UTF_8}, - {"UTF-8N", UTF_8N}, - {"UTF-8-BOM", UTF_8_BOM}, - {"UTF8-MAC", UTF8_MAC}, - {"UTF-8-MAC", UTF8_MAC}, - {"UTF-16", UTF_16}, - {"UTF-16BE", UTF_16BE}, - {"UTF-16BE-BOM", UTF_16BE_BOM}, - {"UTF-16LE", UTF_16LE}, - {"UTF-16LE-BOM", UTF_16LE_BOM}, - {"UTF-32", UTF_32}, - {"UTF-32BE", UTF_32BE}, - {"UTF-32BE-BOM", UTF_32BE_BOM}, - {"UTF-32LE", UTF_32LE}, - {"UTF-32LE-BOM", UTF_32LE_BOM}, - {"BINARY", BINARY}, - {NULL, -1} -}; - -#if defined(DEFAULT_CODE_JIS) -#define DEFAULT_ENCIDX ISO_2022_JP -#elif defined(DEFAULT_CODE_SJIS) -#define DEFAULT_ENCIDX SHIFT_JIS -#elif defined(DEFAULT_CODE_WINDOWS_31J) -#define DEFAULT_ENCIDX WINDOWS_31J -#elif defined(DEFAULT_CODE_EUC) -#define DEFAULT_ENCIDX EUC_JP -#elif defined(DEFAULT_CODE_UTF8) -#define DEFAULT_ENCIDX UTF_8 -#endif - - -#define is_alnum(c) \ - (('a'<=c && c<='z')||('A'<= c && c<='Z')||('0'<=c && c<='9')) - -/* I don't trust portablity of toupper */ -#define nkf_toupper(c) (('a'<=c && c<='z')?(c-('a'-'A')):c) -#define nkf_isoctal(c) ('0'<=c && c<='7') -#define nkf_isdigit(c) ('0'<=c && c<='9') -#define nkf_isxdigit(c) (nkf_isdigit(c) || ('a'<=c && c<='f') || ('A'<=c && c <= 'F')) -#define nkf_isblank(c) (c == SP || c == TAB) -#define nkf_isspace(c) (nkf_isblank(c) || c == CR || c == LF) -#define nkf_isalpha(c) (('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z')) -#define nkf_isalnum(c) (nkf_isdigit(c) || nkf_isalpha(c)) -#define nkf_isprint(c) (SP<=c && c<='~') -#define nkf_isgraph(c) ('!'<=c && c<='~') -#define hex2bin(c) (('0'<=c&&c<='9') ? (c-'0') : \ - ('A'<=c&&c<='F') ? (c-'A'+10) : \ - ('a'<=c&&c<='f') ? (c-'a'+10) : 0) -#define bin2hex(c) ("0123456789ABCDEF"[c&15]) -#define is_eucg3(c2) (((unsigned short)c2 >> 8) == SS3) -#define nkf_noescape_mime(c) ((c == CR) || (c == LF) || \ - ((c > SP) && (c < DEL) && (c != '?') && (c != '=') && (c != '_') \ - && (c != '(') && (c != ')') && (c != '.') && (c != 0x22))) - -#define is_ibmext_in_sjis(c2) (CP932_TABLE_BEGIN <= c2 && c2 <= CP932_TABLE_END) -#define nkf_byte_jisx0201_katakana_p(c) (SP <= c && c <= 0x5F) - -#define HOLD_SIZE 1024 -#if defined(INT_IS_SHORT) -#define IOBUF_SIZE 2048 -#else -#define IOBUF_SIZE 16384 -#endif - -#define DEFAULT_J 'B' -#define DEFAULT_R 'B' - - -#define GETA1 0x22 -#define GETA2 0x2e - - -/* MIME preprocessor */ - -#ifdef EASYWIN /*Easy Win */ -extern POINT _BufferSize; -#endif - -struct input_code{ - const char *name; - nkf_char stat; - nkf_char score; - nkf_char index; - nkf_char buf[3]; - void (*status_func)(struct input_code *, nkf_char); - nkf_char (*iconv_func)(nkf_char c2, nkf_char c1, nkf_char c0); - int _file_stat; -}; - -static const char *input_codename = NULL; /* NULL: unestablished, "": BINARY */ -static nkf_encoding *input_encoding = NULL; -static nkf_encoding *output_encoding = NULL; - -#if defined(UTF8_INPUT_ENABLE) || defined(UTF8_OUTPUT_ENABLE) -/* UCS Mapping - * 0: Shift_JIS, eucJP-ascii - * 1: eucJP-ms - * 2: CP932, CP51932 - * 3: CP10001 - */ -#define UCS_MAP_ASCII 0 -#define UCS_MAP_MS 1 -#define UCS_MAP_CP932 2 -#define UCS_MAP_CP10001 3 -static int ms_ucs_map_f = UCS_MAP_ASCII; -#endif -#ifdef UTF8_INPUT_ENABLE -/* no NEC special, NEC-selected IBM extended and IBM extended characters */ -static int no_cp932ext_f = FALSE; -/* ignore ZERO WIDTH NO-BREAK SPACE */ -static int no_best_fit_chars_f = FALSE; -static int input_endian = ENDIAN_BIG; -static int input_bom_f = FALSE; -static nkf_char unicode_subchar = '?'; /* the regular substitution character */ -static void (*encode_fallback)(nkf_char c) = NULL; -static void w_status(struct input_code *, nkf_char); -#endif -#ifdef UTF8_OUTPUT_ENABLE -static int output_bom_f = FALSE; -static int output_endian = ENDIAN_BIG; -#endif - -static void std_putc(nkf_char c); -static nkf_char std_getc(FILE *f); -static nkf_char std_ungetc(nkf_char c,FILE *f); - -static nkf_char broken_getc(FILE *f); -static nkf_char broken_ungetc(nkf_char c,FILE *f); - -static nkf_char mime_getc(FILE *f); - -static void mime_putc(nkf_char c); - -/* buffers */ - -#if !defined(PERL_XS) && !defined(WIN32DLL) -static unsigned char stdibuf[IOBUF_SIZE]; -static unsigned char stdobuf[IOBUF_SIZE]; -#endif - -#define NKF_UNSPECIFIED (-TRUE) - -/* flags */ -static int unbuf_f = FALSE; -static int estab_f = FALSE; -static int nop_f = FALSE; -static int binmode_f = TRUE; /* binary mode */ -static int rot_f = FALSE; /* rot14/43 mode */ -static int hira_f = FALSE; /* hira/kata henkan */ -static int alpha_f = FALSE; /* convert JIx0208 alphbet to ASCII */ -static int mime_f = MIME_DECODE_DEFAULT; /* convert MIME B base64 or Q */ -static int mime_decode_f = FALSE; /* mime decode is explicitly on */ -static int mimebuf_f = FALSE; /* MIME buffered input */ -static int broken_f = FALSE; /* convert ESC-less broken JIS */ -static int iso8859_f = FALSE; /* ISO8859 through */ -static int mimeout_f = FALSE; /* base64 mode */ -static int x0201_f = NKF_UNSPECIFIED; /* convert JIS X 0201 */ -static int iso2022jp_f = FALSE; /* replace non ISO-2022-JP with GETA */ - -#ifdef UNICODE_NORMALIZATION -static int nfc_f = FALSE; -static nkf_char (*i_nfc_getc)(FILE *) = std_getc; /* input of ugetc */ -static nkf_char (*i_nfc_ungetc)(nkf_char c ,FILE *f) = std_ungetc; -#endif - -#ifdef INPUT_OPTION -static int cap_f = FALSE; -static nkf_char (*i_cgetc)(FILE *) = std_getc; /* input of cgetc */ -static nkf_char (*i_cungetc)(nkf_char c ,FILE *f) = std_ungetc; - -static int url_f = FALSE; -static nkf_char (*i_ugetc)(FILE *) = std_getc; /* input of ugetc */ -static nkf_char (*i_uungetc)(nkf_char c ,FILE *f) = std_ungetc; -#endif - -#define PREFIX_EUCG3 NKF_INT32_C(0x8F00) -#define CLASS_MASK NKF_INT32_C(0xFF000000) -#define CLASS_UNICODE NKF_INT32_C(0x01000000) -#define VALUE_MASK NKF_INT32_C(0x00FFFFFF) -#define UNICODE_BMP_MAX NKF_INT32_C(0x0000FFFF) -#define UNICODE_MAX NKF_INT32_C(0x0010FFFF) -#define nkf_char_euc3_new(c) ((c) | PREFIX_EUCG3) -#define nkf_char_unicode_new(c) ((c) | CLASS_UNICODE) -#define nkf_char_unicode_p(c) ((c & CLASS_MASK) == CLASS_UNICODE) -#define nkf_char_unicode_bmp_p(c) ((c & VALUE_MASK) <= UNICODE_BMP_MAX) -#define nkf_char_unicode_value_p(c) ((c & VALUE_MASK) <= UNICODE_MAX) - -#define UTF16_TO_UTF32(lead, trail) (((lead) << 10) + (trail) - NKF_INT32_C(0x35FDC00)) - -#ifdef NUMCHAR_OPTION -static int numchar_f = FALSE; -static nkf_char (*i_ngetc)(FILE *) = std_getc; /* input of ugetc */ -static nkf_char (*i_nungetc)(nkf_char c ,FILE *f) = std_ungetc; -#endif - -#ifdef CHECK_OPTION -static int noout_f = FALSE; -static void no_putc(nkf_char c); -static int debug_f = FALSE; -static void debug(const char *str); -static nkf_char (*iconv_for_check)(nkf_char c2,nkf_char c1,nkf_char c0) = 0; -#endif - -static int guess_f = 0; /* 0: OFF, 1: ON, 2: VERBOSE */ -static void set_input_codename(const char *codename); - -#ifdef EXEC_IO -static int exec_f = 0; -#endif - -#ifdef SHIFTJIS_CP932 -/* invert IBM extended characters to others */ -static int cp51932_f = FALSE; - -/* invert NEC-selected IBM extended characters to IBM extended characters */ -static int cp932inv_f = TRUE; - -/* static nkf_char cp932_conv(nkf_char c2, nkf_char c1); */ -#endif /* SHIFTJIS_CP932 */ - -static int x0212_f = FALSE; -static int x0213_f = FALSE; - -static unsigned char prefix_table[256]; - -static void e_status(struct input_code *, nkf_char); -static void s_status(struct input_code *, nkf_char); - -struct input_code input_code_list[] = { - {"EUC-JP", 0, 0, 0, {0, 0, 0}, e_status, e_iconv, 0}, - {"Shift_JIS", 0, 0, 0, {0, 0, 0}, s_status, s_iconv, 0}, -#ifdef UTF8_INPUT_ENABLE - {"UTF-8", 0, 0, 0, {0, 0, 0}, w_status, w_iconv, 0}, - {"UTF-16", 0, 0, 0, {0, 0, 0}, NULL, w_iconv16, 0}, - {"UTF-32", 0, 0, 0, {0, 0, 0}, NULL, w_iconv32, 0}, -#endif - {NULL, 0, 0, 0, {0, 0, 0}, NULL, NULL, 0} -}; - -static int mimeout_mode = 0; /* 0, -1, 'Q', 'B', 1, 2 */ -static int base64_count = 0; - -/* X0208 -> ASCII converter */ - -/* fold parameter */ -static int f_line = 0; /* chars in line */ -static int f_prev = 0; -static int fold_preserve_f = FALSE; /* preserve new lines */ -static int fold_f = FALSE; -static int fold_len = 0; - -/* options */ -static unsigned char kanji_intro = DEFAULT_J; -static unsigned char ascii_intro = DEFAULT_R; - -/* Folding */ - -#define FOLD_MARGIN 10 -#define DEFAULT_FOLD 60 - -static int fold_margin = FOLD_MARGIN; - -/* process default */ - -static nkf_char -no_connection2(ARG_UNUSED nkf_char c2, ARG_UNUSED nkf_char c1, ARG_UNUSED nkf_char c0) -{ - fprintf(stderr,"nkf internal module connection failure.\n"); - exit(EXIT_FAILURE); - return 0; /* LINT */ -} - -static void -no_connection(nkf_char c2, nkf_char c1) -{ - no_connection2(c2,c1,0); -} - -static nkf_char (*iconv)(nkf_char c2,nkf_char c1,nkf_char c0) = no_connection2; -static void (*oconv)(nkf_char c2,nkf_char c1) = no_connection; - -static void (*o_zconv)(nkf_char c2,nkf_char c1) = no_connection; -static void (*o_fconv)(nkf_char c2,nkf_char c1) = no_connection; -static void (*o_eol_conv)(nkf_char c2,nkf_char c1) = no_connection; -static void (*o_rot_conv)(nkf_char c2,nkf_char c1) = no_connection; -static void (*o_hira_conv)(nkf_char c2,nkf_char c1) = no_connection; -static void (*o_base64conv)(nkf_char c2,nkf_char c1) = no_connection; -static void (*o_iso2022jp_check_conv)(nkf_char c2,nkf_char c1) = no_connection; - -/* static redirections */ - -static void (*o_putc)(nkf_char c) = std_putc; - -static nkf_char (*i_getc)(FILE *f) = std_getc; /* general input */ -static nkf_char (*i_ungetc)(nkf_char c,FILE *f) =std_ungetc; - -static nkf_char (*i_bgetc)(FILE *) = std_getc; /* input of mgetc */ -static nkf_char (*i_bungetc)(nkf_char c ,FILE *f) = std_ungetc; - -static void (*o_mputc)(nkf_char c) = std_putc ; /* output of mputc */ - -static nkf_char (*i_mgetc)(FILE *) = std_getc; /* input of mgetc */ -static nkf_char (*i_mungetc)(nkf_char c ,FILE *f) = std_ungetc; - -/* for strict mime */ -static nkf_char (*i_mgetc_buf)(FILE *) = std_getc; /* input of mgetc_buf */ -static nkf_char (*i_mungetc_buf)(nkf_char c,FILE *f) = std_ungetc; - -/* Global states */ -static int output_mode = ASCII; /* output kanji mode */ -static int input_mode = ASCII; /* input kanji mode */ -static int mime_decode_mode = FALSE; /* MIME mode B base64, Q hex */ - -/* X0201 / X0208 conversion tables */ - -/* X0201 kana conversion table */ -/* 90-9F A0-DF */ -static const unsigned char cv[]= { - 0x21,0x21,0x21,0x23,0x21,0x56,0x21,0x57, - 0x21,0x22,0x21,0x26,0x25,0x72,0x25,0x21, - 0x25,0x23,0x25,0x25,0x25,0x27,0x25,0x29, - 0x25,0x63,0x25,0x65,0x25,0x67,0x25,0x43, - 0x21,0x3c,0x25,0x22,0x25,0x24,0x25,0x26, - 0x25,0x28,0x25,0x2a,0x25,0x2b,0x25,0x2d, - 0x25,0x2f,0x25,0x31,0x25,0x33,0x25,0x35, - 0x25,0x37,0x25,0x39,0x25,0x3b,0x25,0x3d, - 0x25,0x3f,0x25,0x41,0x25,0x44,0x25,0x46, - 0x25,0x48,0x25,0x4a,0x25,0x4b,0x25,0x4c, - 0x25,0x4d,0x25,0x4e,0x25,0x4f,0x25,0x52, - 0x25,0x55,0x25,0x58,0x25,0x5b,0x25,0x5e, - 0x25,0x5f,0x25,0x60,0x25,0x61,0x25,0x62, - 0x25,0x64,0x25,0x66,0x25,0x68,0x25,0x69, - 0x25,0x6a,0x25,0x6b,0x25,0x6c,0x25,0x6d, - 0x25,0x6f,0x25,0x73,0x21,0x2b,0x21,0x2c, - 0x00,0x00}; - - -/* X0201 kana conversion table for dakuten */ -/* 90-9F A0-DF */ -static const unsigned char dv[]= { - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x25,0x74, - 0x00,0x00,0x00,0x00,0x25,0x2c,0x25,0x2e, - 0x25,0x30,0x25,0x32,0x25,0x34,0x25,0x36, - 0x25,0x38,0x25,0x3a,0x25,0x3c,0x25,0x3e, - 0x25,0x40,0x25,0x42,0x25,0x45,0x25,0x47, - 0x25,0x49,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x25,0x50,0x25,0x53, - 0x25,0x56,0x25,0x59,0x25,0x5c,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00}; - -/* X0201 kana conversion table for han-dakuten */ -/* 90-9F A0-DF */ -static const unsigned char ev[]= { - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x25,0x51,0x25,0x54, - 0x25,0x57,0x25,0x5a,0x25,0x5d,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00}; - -/* X0201 kana to X0213 conversion table for han-dakuten */ -/* 90-9F A0-DF */ -static const unsigned char ev_x0213[]= { - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x25,0x77,0x25,0x78, - 0x25,0x79,0x25,0x7a,0x25,0x7b,0x00,0x00, - 0x00,0x00,0x00,0x00,0x25,0x7c,0x00,0x00, - 0x00,0x00,0x00,0x00,0x25,0x7d,0x00,0x00, - 0x25,0x7e,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00}; - - -/* X0208 kigou conversion table */ -/* 0x8140 - 0x819e */ -static const unsigned char fv[] = { - - 0x00,0x00,0x00,0x00,0x2c,0x2e,0x00,0x3a, - 0x3b,0x3f,0x21,0x00,0x00,0x27,0x60,0x00, - 0x5e,0x00,0x5f,0x00,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x2d,0x00,0x2f, - 0x5c,0x00,0x00,0x7c,0x00,0x00,0x60,0x27, - 0x22,0x22,0x28,0x29,0x00,0x00,0x5b,0x5d, - 0x7b,0x7d,0x3c,0x3e,0x00,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x2b,0x2d,0x00,0x00, - 0x00,0x3d,0x00,0x3c,0x3e,0x00,0x00,0x00, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00, - 0x24,0x00,0x00,0x25,0x23,0x26,0x2a,0x40, - 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 -} ; - - - -static int option_mode = 0; -static int file_out_f = FALSE; -#ifdef OVERWRITE -static int overwrite_f = FALSE; -static int preserve_time_f = FALSE; -static int backup_f = FALSE; -static char *backup_suffix = ""; -#endif - -static int eolmode_f = 0; /* CR, LF, CRLF */ -static int input_eol = 0; /* 0: unestablished, EOF: MIXED */ -static nkf_char prev_cr = 0; /* CR or 0 */ -#ifdef EASYWIN /*Easy Win */ -static int end_check; -#endif /*Easy Win */ - -static void * -nkf_xmalloc(size_t size) -{ - void *ptr; - - if (size == 0) size = 1; - - ptr = malloc(size); - if (ptr == NULL) { - perror("can't malloc"); - exit(EXIT_FAILURE); - } - - return ptr; -} - -static void * -nkf_xrealloc(void *ptr, size_t size) -{ - if (size == 0) size = 1; - - ptr = realloc(ptr, size); - if (ptr == NULL) { - perror("can't realloc"); - exit(EXIT_FAILURE); - } - - return ptr; -} - -#define nkf_xfree(ptr) free(ptr) - -static int -nkf_str_caseeql(const char *src, const char *target) -{ - int i; - for (i = 0; src[i] && target[i]; i++) { - if (nkf_toupper(src[i]) != nkf_toupper(target[i])) return FALSE; - } - if (src[i] || target[i]) return FALSE; - else return TRUE; -} - -static nkf_encoding* -nkf_enc_from_index(int idx) -{ - if (idx < 0 || NKF_ENCODING_TABLE_SIZE <= idx) { - return 0; - } - return &nkf_encoding_table[idx]; -} - -static int -nkf_enc_find_index(const char *name) -{ - int i; - if (name[0] == 'X' && *(name+1) == '-') name += 2; - for (i = 0; encoding_name_to_id_table[i].id >= 0; i++) { - if (nkf_str_caseeql(encoding_name_to_id_table[i].name, name)) { - return encoding_name_to_id_table[i].id; - } - } - return -1; -} - -static nkf_encoding* -nkf_enc_find(const char *name) -{ - int idx = -1; - idx = nkf_enc_find_index(name); - if (idx < 0) return 0; - return nkf_enc_from_index(idx); -} - -#define nkf_enc_name(enc) (enc)->name -#define nkf_enc_to_index(enc) (enc)->id -#define nkf_enc_to_base_encoding(enc) (enc)->base_encoding -#define nkf_enc_to_iconv(enc) nkf_enc_to_base_encoding(enc)->iconv -#define nkf_enc_to_oconv(enc) nkf_enc_to_base_encoding(enc)->oconv -#define nkf_enc_asciicompat(enc) (\ - nkf_enc_to_base_encoding(enc) == &NkfEncodingASCII ||\ - nkf_enc_to_base_encoding(enc) == &NkfEncodingISO_2022_JP) -#define nkf_enc_unicode_p(enc) (\ - nkf_enc_to_base_encoding(enc) == &NkfEncodingUTF_8 ||\ - nkf_enc_to_base_encoding(enc) == &NkfEncodingUTF_16 ||\ - nkf_enc_to_base_encoding(enc) == &NkfEncodingUTF_32) -#define nkf_enc_cp5022x_p(enc) (\ - nkf_enc_to_index(enc) == CP50220 ||\ - nkf_enc_to_index(enc) == CP50221 ||\ - nkf_enc_to_index(enc) == CP50222) - -#ifdef DEFAULT_CODE_LOCALE -static const char* -nkf_locale_charmap(void) -{ -#ifdef HAVE_LANGINFO_H - return nl_langinfo(CODESET); -#elif defined(__WIN32__) - static char buf[16]; - sprintf(buf, "CP%d", GetACP()); - return buf; -#elif defined(__OS2__) -# if defined(INT_IS_SHORT) - /* OS/2 1.x */ - return NULL; -# else - /* OS/2 32bit */ - static char buf[16]; - ULONG ulCP[1], ulncp; - DosQueryCp(sizeof(ulCP), ulCP, &ulncp); - if (ulCP[0] == 932 || ulCP[0] == 943) - strcpy(buf, "Shift_JIS"); - else - sprintf(buf, "CP%lu", ulCP[0]); - return buf; -# endif -#endif - return NULL; -} - -static nkf_encoding* -nkf_locale_encoding(void) -{ - nkf_encoding *enc = 0; - const char *encname = nkf_locale_charmap(); - if (encname) - enc = nkf_enc_find(encname); - return enc; -} -#endif /* DEFAULT_CODE_LOCALE */ - -static nkf_encoding* -nkf_utf8_encoding(void) -{ - return &nkf_encoding_table[UTF_8]; -} - -static nkf_encoding* -nkf_default_encoding(void) -{ - nkf_encoding *enc = 0; -#ifdef DEFAULT_CODE_LOCALE - enc = nkf_locale_encoding(); -#elif defined(DEFAULT_ENCIDX) - enc = nkf_enc_from_index(DEFAULT_ENCIDX); -#endif - if (!enc) enc = nkf_utf8_encoding(); - return enc; -} - -typedef struct { - long capa; - long len; - nkf_char *ptr; -} nkf_buf_t; - -static nkf_buf_t * -nkf_buf_new(int length) -{ - nkf_buf_t *buf = nkf_xmalloc(sizeof(nkf_buf_t)); - buf->ptr = nkf_xmalloc(sizeof(nkf_char) * length); - buf->capa = length; - buf->len = 0; - return buf; -} - -#if 0 -static void -nkf_buf_dispose(nkf_buf_t *buf) -{ - nkf_xfree(buf->ptr); - nkf_xfree(buf); -} -#endif - -#define nkf_buf_length(buf) ((buf)->len) -#define nkf_buf_empty_p(buf) ((buf)->len == 0) - -static nkf_char -nkf_buf_at(nkf_buf_t *buf, int index) -{ - assert(index <= buf->len); - return buf->ptr[index]; -} - -static void -nkf_buf_clear(nkf_buf_t *buf) -{ - buf->len = 0; -} - -static void -nkf_buf_push(nkf_buf_t *buf, nkf_char c) -{ - if (buf->capa <= buf->len) { - exit(EXIT_FAILURE); - } - buf->ptr[buf->len++] = c; -} - -static nkf_char -nkf_buf_pop(nkf_buf_t *buf) -{ - assert(!nkf_buf_empty_p(buf)); - return buf->ptr[--buf->len]; -} - -/* Normalization Form C */ -#ifndef PERL_XS -#ifdef WIN32DLL -#define fprintf dllprintf -#endif - -static void -version(void) -{ - fprintf(HELP_OUTPUT,"Network Kanji Filter Version " NKF_VERSION " (" NKF_RELEASE_DATE ") \n" COPY_RIGHT "\n"); -} - -static void -usage(void) -{ - fprintf(HELP_OUTPUT, - "Usage: nkf -[flags] [--] [in file] .. [out file for -O flag]\n" -#ifdef UTF8_OUTPUT_ENABLE - " j/s/e/w Specify output encoding ISO-2022-JP, Shift_JIS, EUC-JP\n" - " UTF options is -w[8[0],{16,32}[{B,L}[0]]]\n" -#else -#endif -#ifdef UTF8_INPUT_ENABLE - " J/S/E/W Specify input encoding ISO-2022-JP, Shift_JIS, EUC-JP\n" - " UTF option is -W[8,[16,32][B,L]]\n" -#else - " J/S/E Specify output encoding ISO-2022-JP, Shift_JIS, EUC-JP\n" -#endif - ); - fprintf(HELP_OUTPUT, - " m[BQSN0] MIME decode [B:base64,Q:quoted,S:strict,N:nonstrict,0:no decode]\n" - " M[BQ] MIME encode [B:base64 Q:quoted]\n" - " f/F Folding: -f60 or -f or -f60-10 (fold margin 10) F preserve nl\n" - ); - fprintf(HELP_OUTPUT, - " Z[0-4] Default/0: Convert JISX0208 Alphabet to ASCII\n" - " 1: Kankaku to one space 2: to two spaces 3: HTML Entity\n" - " 4: JISX0208 Katakana to JISX0201 Katakana\n" - " X,x Convert Halfwidth Katakana to Fullwidth or preserve it\n" - ); - fprintf(HELP_OUTPUT, - " O Output to File (DEFAULT 'nkf.out')\n" - " L[uwm] Line mode u:LF w:CRLF m:CR (DEFAULT noconversion)\n" - ); - fprintf(HELP_OUTPUT, - " --ic= Specify the input encoding\n" - " --oc= Specify the output encoding\n" - " --hiragana --katakana Hiragana/Katakana Conversion\n" - " --katakana-hiragana Converts each other\n" - ); - fprintf(HELP_OUTPUT, -#ifdef INPUT_OPTION - " --{cap, url}-input Convert hex after ':' or '%%'\n" -#endif -#ifdef NUMCHAR_OPTION - " --numchar-input Convert Unicode Character Reference\n" -#endif -#ifdef UTF8_INPUT_ENABLE - " --fb-{skip, html, xml, perl, java, subchar}\n" - " Specify unassigned character's replacement\n" -#endif - ); - fprintf(HELP_OUTPUT, -#ifdef OVERWRITE - " --in-place[=SUF] Overwrite original files\n" - " --overwrite[=SUF] Preserve timestamp of original files\n" -#endif - " -g --guess Guess the input code\n" - " -v --version Print the version\n" - " --help/-V Print this help / configuration\n" - ); - version(); -} - -static void -show_configuration(void) -{ - fprintf(HELP_OUTPUT, - "Summary of my nkf " NKF_VERSION " (" NKF_RELEASE_DATE ") configuration:\n" - " Compile-time options:\n" - " Compiled at: " __DATE__ " " __TIME__ "\n" - ); - fprintf(HELP_OUTPUT, - " Default output encoding: " -#ifdef DEFAULT_CODE_LOCALE - "LOCALE (%s)\n", nkf_enc_name(nkf_default_encoding()) -#elif defined(DEFAULT_ENCIDX) - "CONFIG (%s)\n", nkf_enc_name(nkf_default_encoding()) -#else - "NONE\n" -#endif - ); - fprintf(HELP_OUTPUT, - " Default output end of line: " -#if DEFAULT_NEWLINE == CR - "CR" -#elif DEFAULT_NEWLINE == CRLF - "CRLF" -#else - "LF" -#endif - "\n" - " Decode MIME encoded string: " -#if MIME_DECODE_DEFAULT - "ON" -#else - "OFF" -#endif - "\n" - " Convert JIS X 0201 Katakana: " -#if X0201_DEFAULT - "ON" -#else - "OFF" -#endif - "\n" - " --help, --version output: " -#if HELP_OUTPUT_HELP_OUTPUT - "HELP_OUTPUT" -#else - "STDOUT" -#endif - "\n"); -} -#endif /*PERL_XS*/ - -#ifdef OVERWRITE -static char* -get_backup_filename(const char *suffix, const char *filename) -{ - char *backup_filename; - int asterisk_count = 0; - int i, j; - int filename_length = strlen(filename); - - for(i = 0; suffix[i]; i++){ - if(suffix[i] == '*') asterisk_count++; - } - - if(asterisk_count){ - backup_filename = nkf_xmalloc(strlen(suffix) + (asterisk_count * (filename_length - 1)) + 1); - for(i = 0, j = 0; suffix[i];){ - if(suffix[i] == '*'){ - backup_filename[j] = '\0'; - strncat(backup_filename, filename, filename_length); - i++; - j += filename_length; - }else{ - backup_filename[j++] = suffix[i++]; - } - } - backup_filename[j] = '\0'; - }else{ - j = filename_length + strlen(suffix); - backup_filename = nkf_xmalloc(j + 1); - strcpy(backup_filename, filename); - strcat(backup_filename, suffix); - backup_filename[j] = '\0'; - } - return backup_filename; -} -#endif - -#ifdef UTF8_INPUT_ENABLE -static void -nkf_each_char_to_hex(void (*f)(nkf_char c2,nkf_char c1), nkf_char c) -{ - int shift = 20; - c &= VALUE_MASK; - while(shift >= 0){ - if(c >= NKF_INT32_C(1)<= 0){ - (*f)(0, bin2hex(c>>shift)); - shift -= 4; - } - }else{ - shift -= 4; - } - } - return; -} - -static void -encode_fallback_html(nkf_char c) -{ - (*oconv)(0, '&'); - (*oconv)(0, '#'); - c &= VALUE_MASK; - if(c >= NKF_INT32_C(1000000)) - (*oconv)(0, 0x30+(c/NKF_INT32_C(1000000))%10); - if(c >= NKF_INT32_C(100000)) - (*oconv)(0, 0x30+(c/NKF_INT32_C(100000) )%10); - if(c >= 10000) - (*oconv)(0, 0x30+(c/10000 )%10); - if(c >= 1000) - (*oconv)(0, 0x30+(c/1000 )%10); - if(c >= 100) - (*oconv)(0, 0x30+(c/100 )%10); - if(c >= 10) - (*oconv)(0, 0x30+(c/10 )%10); - if(c >= 0) - (*oconv)(0, 0x30+ c %10); - (*oconv)(0, ';'); - return; -} - -static void -encode_fallback_xml(nkf_char c) -{ - (*oconv)(0, '&'); - (*oconv)(0, '#'); - (*oconv)(0, 'x'); - nkf_each_char_to_hex(oconv, c); - (*oconv)(0, ';'); - return; -} - -static void -encode_fallback_java(nkf_char c) -{ - (*oconv)(0, '\\'); - c &= VALUE_MASK; - if(!nkf_char_unicode_bmp_p(c)){ - int high = (c >> 10) + NKF_INT32_C(0xD7C0); /* high surrogate */ - int low = (c & 0x3FF) + NKF_INT32_C(0xDC00); /* low surrogate */ - (*oconv)(0, 'u'); - (*oconv)(0, bin2hex(high>>12)); - (*oconv)(0, bin2hex(high>> 8)); - (*oconv)(0, bin2hex(high>> 4)); - (*oconv)(0, bin2hex(high )); - (*oconv)(0, '\\'); - (*oconv)(0, 'u'); - (*oconv)(0, bin2hex(low>>12)); - (*oconv)(0, bin2hex(low>> 8)); - (*oconv)(0, bin2hex(low>> 4)); - (*oconv)(0, bin2hex(low )); - }else{ - (*oconv)(0, 'u'); - (*oconv)(0, bin2hex(c>>12)); - (*oconv)(0, bin2hex(c>> 8)); - (*oconv)(0, bin2hex(c>> 4)); - (*oconv)(0, bin2hex(c )); - } - return; -} - -static void -encode_fallback_perl(nkf_char c) -{ - (*oconv)(0, '\\'); - (*oconv)(0, 'x'); - (*oconv)(0, '{'); - nkf_each_char_to_hex(oconv, c); - (*oconv)(0, '}'); - return; -} - -static void -encode_fallback_subchar(nkf_char c) -{ - c = unicode_subchar; - (*oconv)((c>>8)&0xFF, c&0xFF); - return; -} -#endif - -static const struct { - const char *name; - const char *alias; -} long_option[] = { - {"ic=", ""}, - {"oc=", ""}, - {"base64","jMB"}, - {"euc","e"}, - {"euc-input","E"}, - {"fj","jm"}, - {"help",""}, - {"jis","j"}, - {"jis-input","J"}, - {"mac","sLm"}, - {"mime","jM"}, - {"mime-input","m"}, - {"msdos","sLw"}, - {"sjis","s"}, - {"sjis-input","S"}, - {"unix","eLu"}, - {"version","v"}, - {"windows","sLw"}, - {"hiragana","h1"}, - {"katakana","h2"}, - {"katakana-hiragana","h3"}, - {"guess=", ""}, - {"guess", "g2"}, - {"cp932", ""}, - {"no-cp932", ""}, -#ifdef X0212_ENABLE - {"x0212", ""}, -#endif -#ifdef UTF8_OUTPUT_ENABLE - {"utf8", "w"}, - {"utf16", "w16"}, - {"ms-ucs-map", ""}, - {"fb-skip", ""}, - {"fb-html", ""}, - {"fb-xml", ""}, - {"fb-perl", ""}, - {"fb-java", ""}, - {"fb-subchar", ""}, - {"fb-subchar=", ""}, -#endif -#ifdef UTF8_INPUT_ENABLE - {"utf8-input", "W"}, - {"utf16-input", "W16"}, - {"no-cp932ext", ""}, - {"no-best-fit-chars",""}, -#endif -#ifdef UNICODE_NORMALIZATION - {"utf8mac-input", ""}, -#endif -#ifdef OVERWRITE - {"overwrite", ""}, - {"overwrite=", ""}, - {"in-place", ""}, - {"in-place=", ""}, -#endif -#ifdef INPUT_OPTION - {"cap-input", ""}, - {"url-input", ""}, -#endif -#ifdef NUMCHAR_OPTION - {"numchar-input", ""}, -#endif -#ifdef CHECK_OPTION - {"no-output", ""}, - {"debug", ""}, -#endif -#ifdef SHIFTJIS_CP932 - {"cp932inv", ""}, -#endif -#ifdef EXEC_IO - {"exec-in", ""}, - {"exec-out", ""}, -#endif - {"prefix=", ""}, -}; - -static void -set_input_encoding(nkf_encoding *enc) -{ - switch (nkf_enc_to_index(enc)) { - case ISO_8859_1: - iso8859_f = TRUE; - break; - case CP50221: - case CP50222: - if (x0201_f == NKF_UNSPECIFIED) x0201_f = FALSE; /* -x specified implicitly */ - case CP50220: -#ifdef SHIFTJIS_CP932 - cp51932_f = TRUE; -#endif -#ifdef UTF8_OUTPUT_ENABLE - ms_ucs_map_f = UCS_MAP_CP932; -#endif - break; - case ISO_2022_JP_1: - x0212_f = TRUE; - break; - case ISO_2022_JP_3: - x0212_f = TRUE; - x0213_f = TRUE; - break; - case ISO_2022_JP_2004: - x0212_f = TRUE; - x0213_f = TRUE; - break; - case SHIFT_JIS: - break; - case WINDOWS_31J: - if (x0201_f == NKF_UNSPECIFIED) x0201_f = FALSE; /* -x specified implicitly */ -#ifdef SHIFTJIS_CP932 - cp51932_f = TRUE; -#endif -#ifdef UTF8_OUTPUT_ENABLE - ms_ucs_map_f = UCS_MAP_CP932; -#endif - break; - break; - case CP10001: -#ifdef SHIFTJIS_CP932 - cp51932_f = TRUE; -#endif -#ifdef UTF8_OUTPUT_ENABLE - ms_ucs_map_f = UCS_MAP_CP10001; -#endif - break; - case EUC_JP: - break; - case EUCJP_NKF: - break; - case CP51932: - if (x0201_f == NKF_UNSPECIFIED) x0201_f = FALSE; /* -x specified implicitly */ -#ifdef SHIFTJIS_CP932 - cp51932_f = TRUE; -#endif -#ifdef UTF8_OUTPUT_ENABLE - ms_ucs_map_f = UCS_MAP_CP932; -#endif - break; - case EUCJP_MS: - if (x0201_f == NKF_UNSPECIFIED) x0201_f = FALSE; /* -x specified implicitly */ -#ifdef SHIFTJIS_CP932 - cp51932_f = FALSE; -#endif -#ifdef UTF8_OUTPUT_ENABLE - ms_ucs_map_f = UCS_MAP_MS; -#endif - break; - case EUCJP_ASCII: - if (x0201_f == NKF_UNSPECIFIED) x0201_f = FALSE; /* -x specified implicitly */ -#ifdef SHIFTJIS_CP932 - cp51932_f = FALSE; -#endif -#ifdef UTF8_OUTPUT_ENABLE - ms_ucs_map_f = UCS_MAP_ASCII; -#endif - break; - case SHIFT_JISX0213: - case SHIFT_JIS_2004: - x0213_f = TRUE; -#ifdef SHIFTJIS_CP932 - cp51932_f = FALSE; - if (cp932inv_f == TRUE) cp932inv_f = FALSE; -#endif - break; - case EUC_JISX0213: - case EUC_JIS_2004: - x0213_f = TRUE; -#ifdef SHIFTJIS_CP932 - cp51932_f = FALSE; -#endif - break; -#ifdef UTF8_INPUT_ENABLE -#ifdef UNICODE_NORMALIZATION - case UTF8_MAC: - nfc_f = TRUE; - break; -#endif - case UTF_16: - case UTF_16BE: - case UTF_16BE_BOM: - input_endian = ENDIAN_BIG; - break; - case UTF_16LE: - case UTF_16LE_BOM: - input_endian = ENDIAN_LITTLE; - break; - case UTF_32: - case UTF_32BE: - case UTF_32BE_BOM: - input_endian = ENDIAN_BIG; - break; - case UTF_32LE: - case UTF_32LE_BOM: - input_endian = ENDIAN_LITTLE; - break; -#endif - } -} - -static void -set_output_encoding(nkf_encoding *enc) -{ - switch (nkf_enc_to_index(enc)) { - case CP50220: -#ifdef SHIFTJIS_CP932 - if (cp932inv_f == TRUE) cp932inv_f = FALSE; -#endif -#ifdef UTF8_OUTPUT_ENABLE - ms_ucs_map_f = UCS_MAP_CP932; -#endif - break; - case CP50221: - if (x0201_f == NKF_UNSPECIFIED) x0201_f = FALSE; /* -x specified implicitly */ -#ifdef SHIFTJIS_CP932 - if (cp932inv_f == TRUE) cp932inv_f = FALSE; -#endif -#ifdef UTF8_OUTPUT_ENABLE - ms_ucs_map_f = UCS_MAP_CP932; -#endif - break; - case ISO_2022_JP: -#ifdef SHIFTJIS_CP932 - if (cp932inv_f == TRUE) cp932inv_f = FALSE; -#endif - break; - case ISO_2022_JP_1: - x0212_f = TRUE; -#ifdef SHIFTJIS_CP932 - if (cp932inv_f == TRUE) cp932inv_f = FALSE; -#endif - break; - case ISO_2022_JP_3: - case ISO_2022_JP_2004: - x0212_f = TRUE; - x0213_f = TRUE; -#ifdef SHIFTJIS_CP932 - if (cp932inv_f == TRUE) cp932inv_f = FALSE; -#endif - break; - case SHIFT_JIS: - break; - case WINDOWS_31J: - if (x0201_f == NKF_UNSPECIFIED) x0201_f = FALSE; /* -x specified implicitly */ -#ifdef UTF8_OUTPUT_ENABLE - ms_ucs_map_f = UCS_MAP_CP932; -#endif - break; - case CP10001: -#ifdef UTF8_OUTPUT_ENABLE - ms_ucs_map_f = UCS_MAP_CP10001; -#endif - break; - case EUC_JP: - x0212_f = TRUE; -#ifdef SHIFTJIS_CP932 - if (cp932inv_f == TRUE) cp932inv_f = FALSE; -#endif -#ifdef UTF8_OUTPUT_ENABLE - ms_ucs_map_f = UCS_MAP_ASCII; -#endif - break; - case EUCJP_NKF: - x0212_f = FALSE; -#ifdef SHIFTJIS_CP932 - if (cp932inv_f == TRUE) cp932inv_f = FALSE; -#endif -#ifdef UTF8_OUTPUT_ENABLE - ms_ucs_map_f = UCS_MAP_ASCII; -#endif - break; - case CP51932: - if (x0201_f == NKF_UNSPECIFIED) x0201_f = FALSE; /* -x specified implicitly */ -#ifdef SHIFTJIS_CP932 - if (cp932inv_f == TRUE) cp932inv_f = FALSE; -#endif -#ifdef UTF8_OUTPUT_ENABLE - ms_ucs_map_f = UCS_MAP_CP932; -#endif - break; - case EUCJP_MS: - if (x0201_f == NKF_UNSPECIFIED) x0201_f = FALSE; /* -x specified implicitly */ - x0212_f = TRUE; -#ifdef UTF8_OUTPUT_ENABLE - ms_ucs_map_f = UCS_MAP_MS; -#endif - break; - case EUCJP_ASCII: - if (x0201_f == NKF_UNSPECIFIED) x0201_f = FALSE; /* -x specified implicitly */ - x0212_f = TRUE; -#ifdef UTF8_OUTPUT_ENABLE - ms_ucs_map_f = UCS_MAP_ASCII; -#endif - break; - case SHIFT_JISX0213: - case SHIFT_JIS_2004: - x0213_f = TRUE; -#ifdef SHIFTJIS_CP932 - if (cp932inv_f == TRUE) cp932inv_f = FALSE; -#endif - break; - case EUC_JISX0213: - case EUC_JIS_2004: - x0212_f = TRUE; - x0213_f = TRUE; -#ifdef SHIFTJIS_CP932 - if (cp932inv_f == TRUE) cp932inv_f = FALSE; -#endif - break; -#ifdef UTF8_OUTPUT_ENABLE - case UTF_8_BOM: - output_bom_f = TRUE; - break; - case UTF_16: - case UTF_16BE_BOM: - output_bom_f = TRUE; - break; - case UTF_16LE: - output_endian = ENDIAN_LITTLE; - output_bom_f = FALSE; - break; - case UTF_16LE_BOM: - output_endian = ENDIAN_LITTLE; - output_bom_f = TRUE; - break; - case UTF_32: - case UTF_32BE_BOM: - output_bom_f = TRUE; - break; - case UTF_32LE: - output_endian = ENDIAN_LITTLE; - output_bom_f = FALSE; - break; - case UTF_32LE_BOM: - output_endian = ENDIAN_LITTLE; - output_bom_f = TRUE; - break; -#endif - } -} - -static struct input_code* -find_inputcode_byfunc(nkf_char (*iconv_func)(nkf_char c2,nkf_char c1,nkf_char c0)) -{ - if (iconv_func){ - struct input_code *p = input_code_list; - while (p->name){ - if (iconv_func == p->iconv_func){ - return p; - } - p++; - } - } - return 0; -} - -static void -set_iconv(nkf_char f, nkf_char (*iconv_func)(nkf_char c2,nkf_char c1,nkf_char c0)) -{ -#ifdef INPUT_CODE_FIX - if (f || !input_encoding) -#endif - if (estab_f != f){ - estab_f = f; - } - - if (iconv_func -#ifdef INPUT_CODE_FIX - && (f == -TRUE || !input_encoding) /* -TRUE means "FORCE" */ -#endif - ){ - iconv = iconv_func; - } -#ifdef CHECK_OPTION - if (estab_f && iconv_for_check != iconv){ - struct input_code *p = find_inputcode_byfunc(iconv); - if (p){ - set_input_codename(p->name); - debug(p->name); - } - iconv_for_check = iconv; - } -#endif -} - -#ifdef X0212_ENABLE -static nkf_char -x0212_shift(nkf_char c) -{ - nkf_char ret = c; - c &= 0x7f; - if (is_eucg3(ret)){ - if (0x75 <= c && c <= 0x7f){ - ret = c + (0x109 - 0x75); - } - }else{ - if (0x75 <= c && c <= 0x7f){ - ret = c + (0x113 - 0x75); - } - } - return ret; -} - - -static nkf_char -x0212_unshift(nkf_char c) -{ - nkf_char ret = c; - if (0x7f <= c && c <= 0x88){ - ret = c + (0x75 - 0x7f); - }else if (0x89 <= c && c <= 0x92){ - ret = PREFIX_EUCG3 | 0x80 | (c + (0x75 - 0x89)); - } - return ret; -} -#endif /* X0212_ENABLE */ - -static int -is_x0213_2_in_x0212(nkf_char c1) -{ - static const char x0213_2_table[] = - {0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1}; - int ku = c1 - 0x20; - if (ku <= 15) - return x0213_2_table[ku]; /* 1, 3-5, 8, 12-15 */ - if (78 <= ku && ku <= 94) - return 1; - return 0; -} - -static nkf_char -e2s_conv(nkf_char c2, nkf_char c1, nkf_char *p2, nkf_char *p1) -{ - nkf_char ndx; - if (is_eucg3(c2)){ - ndx = c2 & 0x7f; - if (x0213_f && is_x0213_2_in_x0212(ndx)){ - if((0x21 <= ndx && ndx <= 0x2F)){ - if (p2) *p2 = ((ndx - 1) >> 1) + 0xec - ndx / 8 * 3; - if (p1) *p1 = c1 + ((ndx & 1) ? ((c1 < 0x60) ? 0x1f : 0x20) : 0x7e); - return 0; - }else if(0x6E <= ndx && ndx <= 0x7E){ - if (p2) *p2 = ((ndx - 1) >> 1) + 0xbe; - if (p1) *p1 = c1 + ((ndx & 1) ? ((c1 < 0x60) ? 0x1f : 0x20) : 0x7e); - return 0; - } - return 1; - } -#ifdef X0212_ENABLE - else if(nkf_isgraph(ndx)){ - nkf_char val = 0; - const unsigned short *ptr; - ptr = x0212_shiftjis[ndx - 0x21]; - if (ptr){ - val = ptr[(c1 & 0x7f) - 0x21]; - } - if (val){ - c2 = val >> 8; - c1 = val & 0xff; - if (p2) *p2 = c2; - if (p1) *p1 = c1; - return 0; - } - c2 = x0212_shift(c2); - } -#endif /* X0212_ENABLE */ - } - if(0x7F < c2) return 1; - if (p2) *p2 = ((c2 - 1) >> 1) + ((c2 <= 0x5e) ? 0x71 : 0xb1); - if (p1) *p1 = c1 + ((c2 & 1) ? ((c1 < 0x60) ? 0x1f : 0x20) : 0x7e); - return 0; -} - -static nkf_char -s2e_conv(nkf_char c2, nkf_char c1, nkf_char *p2, nkf_char *p1) -{ -#if defined(SHIFTJIS_CP932) || defined(X0212_ENABLE) - nkf_char val; -#endif - static const char shift_jisx0213_s1a3_table[5][2] ={ { 1, 8}, { 3, 4}, { 5,12}, {13,14}, {15, 0} }; - if (0xFC < c1) return 1; -#ifdef SHIFTJIS_CP932 - if (!cp932inv_f && !x0213_f && is_ibmext_in_sjis(c2)){ - val = shiftjis_cp932[c2 - CP932_TABLE_BEGIN][c1 - 0x40]; - if (val){ - c2 = val >> 8; - c1 = val & 0xff; - } - } - if (cp932inv_f - && CP932INV_TABLE_BEGIN <= c2 && c2 <= CP932INV_TABLE_END){ - val = cp932inv[c2 - CP932INV_TABLE_BEGIN][c1 - 0x40]; - if (val){ - c2 = val >> 8; - c1 = val & 0xff; - } - } -#endif /* SHIFTJIS_CP932 */ -#ifdef X0212_ENABLE - if (!x0213_f && is_ibmext_in_sjis(c2)){ - val = shiftjis_x0212[c2 - 0xfa][c1 - 0x40]; - if (val){ - if (val > 0x7FFF){ - c2 = PREFIX_EUCG3 | ((val >> 8) & 0x7f); - c1 = val & 0xff; - }else{ - c2 = val >> 8; - c1 = val & 0xff; - } - if (p2) *p2 = c2; - if (p1) *p1 = c1; - return 0; - } - } -#endif - if(c2 >= 0x80){ - if(x0213_f && c2 >= 0xF0){ - if(c2 <= 0xF3 || (c2 == 0xF4 && c1 < 0x9F)){ /* k=1, 3<=k<=5, k=8, 12<=k<=15 */ - c2 = PREFIX_EUCG3 | 0x20 | shift_jisx0213_s1a3_table[c2 - 0xF0][0x9E < c1]; - }else{ /* 78<=k<=94 */ - c2 = PREFIX_EUCG3 | (c2 * 2 - 0x17B); - if (0x9E < c1) c2++; - } - }else{ -#define SJ0162 0x00e1 /* 01 - 62 ku offset */ -#define SJ6394 0x0161 /* 63 - 94 ku offset */ - c2 = c2 + c2 - ((c2 <= 0x9F) ? SJ0162 : SJ6394); - if (0x9E < c1) c2++; - } - if (c1 < 0x9F) - c1 = c1 - ((c1 > DEL) ? SP : 0x1F); - else { - c1 = c1 - 0x7E; - } - } - -#ifdef X0212_ENABLE - c2 = x0212_unshift(c2); -#endif - if (p2) *p2 = c2; - if (p1) *p1 = c1; - return 0; -} - -#if defined(UTF8_INPUT_ENABLE) || defined(UTF8_OUTPUT_ENABLE) -static void -nkf_unicode_to_utf8(nkf_char val, nkf_char *p1, nkf_char *p2, nkf_char *p3, nkf_char *p4) -{ - val &= VALUE_MASK; - if (val < 0x80){ - *p1 = val; - *p2 = 0; - *p3 = 0; - *p4 = 0; - }else if (val < 0x800){ - *p1 = 0xc0 | (val >> 6); - *p2 = 0x80 | (val & 0x3f); - *p3 = 0; - *p4 = 0; - } else if (nkf_char_unicode_bmp_p(val)) { - *p1 = 0xe0 | (val >> 12); - *p2 = 0x80 | ((val >> 6) & 0x3f); - *p3 = 0x80 | ( val & 0x3f); - *p4 = 0; - } else if (nkf_char_unicode_value_p(val)) { - *p1 = 0xf0 | (val >> 18); - *p2 = 0x80 | ((val >> 12) & 0x3f); - *p3 = 0x80 | ((val >> 6) & 0x3f); - *p4 = 0x80 | ( val & 0x3f); - } else { - *p1 = 0; - *p2 = 0; - *p3 = 0; - *p4 = 0; - } -} - -static nkf_char -nkf_utf8_to_unicode(nkf_char c1, nkf_char c2, nkf_char c3, nkf_char c4) -{ - nkf_char wc; - if (c1 <= 0x7F) { - /* single byte */ - wc = c1; - } - else if (c1 <= 0xC1) { - /* trail byte or invalid */ - return -1; - } - else if (c1 <= 0xDF) { - /* 2 bytes */ - wc = (c1 & 0x1F) << 6; - wc |= (c2 & 0x3F); - } - else if (c1 <= 0xEF) { - /* 3 bytes */ - wc = (c1 & 0x0F) << 12; - wc |= (c2 & 0x3F) << 6; - wc |= (c3 & 0x3F); - } - else if (c2 <= 0xF4) { - /* 4 bytes */ - wc = (c1 & 0x0F) << 18; - wc |= (c2 & 0x3F) << 12; - wc |= (c3 & 0x3F) << 6; - wc |= (c4 & 0x3F); - } - else { - return -1; - } - return wc; -} -#endif - -#ifdef UTF8_INPUT_ENABLE -static int -unicode_to_jis_common2(nkf_char c1, nkf_char c0, - const unsigned short *const *pp, nkf_char psize, - nkf_char *p2, nkf_char *p1) -{ - nkf_char c2; - const unsigned short *p; - unsigned short val; - - if (pp == 0) return 1; - - c1 -= 0x80; - if (c1 < 0 || psize <= c1) return 1; - p = pp[c1]; - if (p == 0) return 1; - - c0 -= 0x80; - if (c0 < 0 || sizeof_utf8_to_euc_C2 <= c0) return 1; - val = p[c0]; - if (val == 0) return 1; - if (no_cp932ext_f && ( - (val>>8) == 0x2D || /* NEC special characters */ - val > NKF_INT32_C(0xF300) /* IBM extended characters */ - )) return 1; - - c2 = val >> 8; - if (val > 0x7FFF){ - c2 &= 0x7f; - c2 |= PREFIX_EUCG3; - } - if (c2 == SO) c2 = JIS_X_0201_1976_K; - c1 = val & 0xFF; - if (p2) *p2 = c2; - if (p1) *p1 = c1; - return 0; -} - -static int -unicode_to_jis_common(nkf_char c2, nkf_char c1, nkf_char c0, nkf_char *p2, nkf_char *p1) -{ - const unsigned short *const *pp; - const unsigned short *const *const *ppp; - static const char no_best_fit_chars_table_C2[] = - {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1, 1, 2, 1, 1, 2, - 0, 0, 1, 1, 0, 1, 0, 1, 2, 1, 1, 1, 1, 1, 1, 1}; - static const char no_best_fit_chars_table_C2_ms[] = - {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, - 0, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0}; - static const char no_best_fit_chars_table_932_C2[] = - {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, - 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0}; - static const char no_best_fit_chars_table_932_C3[] = - {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1}; - nkf_char ret = 0; - - if(c2 < 0x80){ - *p2 = 0; - *p1 = c2; - }else if(c2 < 0xe0){ - if(no_best_fit_chars_f){ - if(ms_ucs_map_f == UCS_MAP_CP932){ - switch(c2){ - case 0xC2: - if(no_best_fit_chars_table_932_C2[c1&0x3F]) return 1; - break; - case 0xC3: - if(no_best_fit_chars_table_932_C3[c1&0x3F]) return 1; - break; - } - }else if(!cp932inv_f){ - switch(c2){ - case 0xC2: - if(no_best_fit_chars_table_C2[c1&0x3F]) return 1; - break; - case 0xC3: - if(no_best_fit_chars_table_932_C3[c1&0x3F]) return 1; - break; - } - }else if(ms_ucs_map_f == UCS_MAP_MS){ - if(c2 == 0xC2 && no_best_fit_chars_table_C2_ms[c1&0x3F]) return 1; - }else if(ms_ucs_map_f == UCS_MAP_CP10001){ - switch(c2){ - case 0xC2: - switch(c1){ - case 0xA2: - case 0xA3: - case 0xA5: - case 0xA6: - case 0xAC: - case 0xAF: - case 0xB8: - return 1; - } - break; - } - } - } - pp = - ms_ucs_map_f == UCS_MAP_CP932 ? utf8_to_euc_2bytes_932 : - ms_ucs_map_f == UCS_MAP_MS ? utf8_to_euc_2bytes_ms : - ms_ucs_map_f == UCS_MAP_CP10001 ? utf8_to_euc_2bytes_mac : - x0213_f ? utf8_to_euc_2bytes_x0213 : - utf8_to_euc_2bytes; - ret = unicode_to_jis_common2(c2, c1, pp, sizeof_utf8_to_euc_2bytes, p2, p1); - }else if(c0 < 0xF0){ - if(no_best_fit_chars_f){ - if(ms_ucs_map_f == UCS_MAP_CP932){ - if(c2 == 0xE3 && c1 == 0x82 && c0 == 0x94) return 1; - }else if(ms_ucs_map_f == UCS_MAP_MS){ - switch(c2){ - case 0xE2: - switch(c1){ - case 0x80: - if(c0 == 0x94 || c0 == 0x96 || c0 == 0xBE) return 1; - break; - case 0x88: - if(c0 == 0x92) return 1; - break; - } - break; - case 0xE3: - if(c1 == 0x80 || c0 == 0x9C) return 1; - break; - } - }else if(ms_ucs_map_f == UCS_MAP_CP10001){ - switch(c2){ - case 0xE3: - switch(c1){ - case 0x82: - if(c0 == 0x94) return 1; - break; - case 0x83: - if(c0 == 0xBB) return 1; - break; - } - break; - } - }else{ - switch(c2){ - case 0xE2: - switch(c1){ - case 0x80: - if(c0 == 0x95) return 1; - break; - case 0x88: - if(c0 == 0xA5) return 1; - break; - } - break; - case 0xEF: - switch(c1){ - case 0xBC: - if(c0 == 0x8D) return 1; - break; - case 0xBD: - if(c0 == 0x9E && !cp932inv_f) return 1; - break; - case 0xBF: - if(0xA0 <= c0 && c0 <= 0xA5) return 1; - break; - } - break; - } - } - } - ppp = - ms_ucs_map_f == UCS_MAP_CP932 ? utf8_to_euc_3bytes_932 : - ms_ucs_map_f == UCS_MAP_MS ? utf8_to_euc_3bytes_ms : - ms_ucs_map_f == UCS_MAP_CP10001 ? utf8_to_euc_3bytes_mac : - x0213_f ? utf8_to_euc_3bytes_x0213 : - utf8_to_euc_3bytes; - ret = unicode_to_jis_common2(c1, c0, ppp[c2 - 0xE0], sizeof_utf8_to_euc_C2, p2, p1); - }else return -1; -#ifdef SHIFTJIS_CP932 - if (!ret&& is_eucg3(*p2)) { - if (cp932inv_f) { - if (encode_fallback) ret = 1; - } - else { - nkf_char s2, s1; - if (e2s_conv(*p2, *p1, &s2, &s1) == 0) { - s2e_conv(s2, s1, p2, p1); - }else{ - ret = 1; - } - } - } -#endif - return ret; -} - -#ifdef UTF8_OUTPUT_ENABLE -#define X0213_SURROGATE_FIND(tbl, size, euc) do { \ - int i; \ - for (i = 0; i < size; i++) \ - if (tbl[i][0] == euc) { \ - low = tbl[i][2]; \ - break; \ - } \ - } while (0) - -static nkf_char -e2w_conv(nkf_char c2, nkf_char c1) -{ - const unsigned short *p; - - if (c2 == JIS_X_0201_1976_K) { - if (ms_ucs_map_f == UCS_MAP_CP10001) { - switch (c1) { - case 0x20: - return 0xA0; - case 0x7D: - return 0xA9; - } - } - p = euc_to_utf8_1byte; -#ifdef X0212_ENABLE - } else if (is_eucg3(c2)){ - if(ms_ucs_map_f == UCS_MAP_ASCII&& c2 == NKF_INT32_C(0x8F22) && c1 == 0x43){ - return 0xA6; - } - c2 = (c2&0x7f) - 0x21; - if (0<=c2 && c2= sizeof_x0213_combining_chars) - return 0; - euc = (c2&0x7f)<<8 | (c1&0x7f); - for (i = 0; i < sizeof_x0213_combining_table; i++) - if (x0213_combining_table[i][0] == euc) - return x0213_combining_table[i][1]; - return 0; -} -#endif - -static nkf_char -w2e_conv(nkf_char c2, nkf_char c1, nkf_char c0, nkf_char *p2, nkf_char *p1) -{ - nkf_char ret = 0; - - if (!c1){ - *p2 = 0; - *p1 = c2; - }else if (0xc0 <= c2 && c2 <= 0xef) { - ret = unicode_to_jis_common(c2, c1, c0, p2, p1); -#ifdef NUMCHAR_OPTION - if (ret > 0){ - if (p2) *p2 = 0; - if (p1) *p1 = nkf_char_unicode_new(nkf_utf8_to_unicode(c2, c1, c0, 0)); - ret = 0; - } -#endif - } - return ret; -} - -#ifdef UTF8_INPUT_ENABLE -static nkf_char -w16e_conv(nkf_char val, nkf_char *p2, nkf_char *p1) -{ - nkf_char c1, c2, c3, c4; - nkf_char ret = 0; - val &= VALUE_MASK; - if (val < 0x80) { - *p2 = 0; - *p1 = val; - } - else if (nkf_char_unicode_bmp_p(val)){ - nkf_unicode_to_utf8(val, &c1, &c2, &c3, &c4); - ret = unicode_to_jis_common(c1, c2, c3, p2, p1); - if (ret > 0){ - *p2 = 0; - *p1 = nkf_char_unicode_new(val); - ret = 0; - } - } - else { - int i; - if (x0213_f) { - c1 = (val >> 10) + NKF_INT32_C(0xD7C0); /* high surrogate */ - c2 = (val & 0x3FF) + NKF_INT32_C(0xDC00); /* low surrogate */ - for (i = 0; i < sizeof_x0213_1_surrogate_table; i++) - if (x0213_1_surrogate_table[i][1] == c1 && x0213_1_surrogate_table[i][2] == c2) { - val = x0213_1_surrogate_table[i][0]; - *p2 = val >> 8; - *p1 = val & 0xFF; - return 0; - } - for (i = 0; i < sizeof_x0213_2_surrogate_table; i++) - if (x0213_2_surrogate_table[i][1] == c1 && x0213_2_surrogate_table[i][2] == c2) { - val = x0213_2_surrogate_table[i][0]; - *p2 = PREFIX_EUCG3 | (val >> 8); - *p1 = val & 0xFF; - return 0; - } - } - *p2 = 0; - *p1 = nkf_char_unicode_new(val); - } - return ret; -} -#endif - -static nkf_char -e_iconv(nkf_char c2, nkf_char c1, nkf_char c0) -{ - if (c2 == JIS_X_0201_1976_K || c2 == SS2){ - if (iso2022jp_f && !x0201_f) { - c2 = GETA1; c1 = GETA2; - } else { - c2 = JIS_X_0201_1976_K; - c1 &= 0x7f; - } -#ifdef X0212_ENABLE - }else if (c2 == 0x8f){ - if (c0 == 0){ - return -1; - } - if (!cp51932_f && !x0213_f && 0xF5 <= c1 && c1 <= 0xFE && 0xA1 <= c0 && c0 <= 0xFE) { - /* encoding is eucJP-ms, so invert to Unicode Private User Area */ - c1 = nkf_char_unicode_new((c1 - 0xF5) * 94 + c0 - 0xA1 + 0xE3AC); - c2 = 0; - } else { - c2 = (c2 << 8) | (c1 & 0x7f); - c1 = c0 & 0x7f; -#ifdef SHIFTJIS_CP932 - if (cp51932_f){ - nkf_char s2, s1; - if (e2s_conv(c2, c1, &s2, &s1) == 0){ - s2e_conv(s2, s1, &c2, &c1); - if (c2 < 0x100){ - c1 &= 0x7f; - c2 &= 0x7f; - } - } - } -#endif /* SHIFTJIS_CP932 */ - } -#endif /* X0212_ENABLE */ - } else if ((c2 == EOF) || (c2 == 0) || c2 < SP || c2 == ISO_8859_1) { - /* NOP */ - } else { - if (!cp51932_f && ms_ucs_map_f && 0xF5 <= c2 && c2 <= 0xFE && 0xA1 <= c1 && c1 <= 0xFE) { - /* encoding is eucJP-ms, so invert to Unicode Private User Area */ - c1 = nkf_char_unicode_new((c2 - 0xF5) * 94 + c1 - 0xA1 + 0xE000); - c2 = 0; - } else { - c1 &= 0x7f; - c2 &= 0x7f; -#ifdef SHIFTJIS_CP932 - if (cp51932_f && 0x79 <= c2 && c2 <= 0x7c){ - nkf_char s2, s1; - if (e2s_conv(c2, c1, &s2, &s1) == 0){ - s2e_conv(s2, s1, &c2, &c1); - if (c2 < 0x100){ - c1 &= 0x7f; - c2 &= 0x7f; - } - } - } -#endif /* SHIFTJIS_CP932 */ - } - } - (*oconv)(c2, c1); - return 0; -} - -static nkf_char -s_iconv(ARG_UNUSED nkf_char c2, nkf_char c1, ARG_UNUSED nkf_char c0) -{ - if (c2 == JIS_X_0201_1976_K || (0xA1 <= c2 && c2 <= 0xDF)) { - if (iso2022jp_f && !x0201_f) { - c2 = GETA1; c1 = GETA2; - } else { - c1 &= 0x7f; - } - } else if ((c2 == EOF) || (c2 == 0) || c2 < SP) { - /* NOP */ - } else if (!x0213_f && 0xF0 <= c2 && c2 <= 0xF9 && 0x40 <= c1 && c1 <= 0xFC) { - /* CP932 UDC */ - if(c1 == 0x7F) return 0; - c1 = nkf_char_unicode_new((c2 - 0xF0) * 188 + (c1 - 0x40 - (0x7E < c1)) + 0xE000); - c2 = 0; - } else { - nkf_char ret = s2e_conv(c2, c1, &c2, &c1); - if (ret) return ret; - } - (*oconv)(c2, c1); - return 0; -} - -static int -x0213_wait_combining_p(nkf_char wc) -{ - int i; - for (i = 0; i < sizeof_x0213_combining_table; i++) { - if (x0213_combining_table[i][1] == wc) { - return TRUE; - } - } - return FALSE; -} - -static int -x0213_combining_p(nkf_char wc) -{ - int i; - for (i = 0; i < sizeof_x0213_combining_chars; i++) { - if (x0213_combining_chars[i] == wc) { - return TRUE; - } - } - return FALSE; -} - -static nkf_char -w_iconv(nkf_char c1, nkf_char c2, nkf_char c3) -{ - nkf_char ret = 0, c4 = 0; - static const char w_iconv_utf8_1st_byte[] = - { /* 0xC0 - 0xFF */ - 20, 20, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, 21, - 30, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, 32, 33, 33, - 40, 41, 41, 41, 42, 43, 43, 43, 50, 50, 50, 50, 60, 60, 70, 70}; - - if (c3 > 0xFF) { - c4 = c3 & 0xFF; - c3 >>= 8; - } - - if (c1 < 0 || 0xff < c1) { - }else if (c1 == 0) { /* 0 : 1 byte*/ - c3 = 0; - } else if ((c1 & 0xC0) == 0x80) { /* 0x80-0xbf : trail byte */ - return 0; - } else{ - switch (w_iconv_utf8_1st_byte[c1 - 0xC0]) { - case 21: - if (c2 < 0x80 || 0xBF < c2) return 0; - break; - case 30: - if (c3 == 0) return -1; - if (c2 < 0xA0 || 0xBF < c2 || (c3 & 0xC0) != 0x80) - return 0; - break; - case 31: - case 33: - if (c3 == 0) return -1; - if ((c2 & 0xC0) != 0x80 || (c3 & 0xC0) != 0x80) - return 0; - break; - case 32: - if (c3 == 0) return -1; - if (c2 < 0x80 || 0x9F < c2 || (c3 & 0xC0) != 0x80) - return 0; - break; - case 40: - if (c3 == 0) return -2; - if (c2 < 0x90 || 0xBF < c2 || (c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80) - return 0; - break; - case 41: - if (c3 == 0) return -2; - if (c2 < 0x80 || 0xBF < c2 || (c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80) - return 0; - break; - case 42: - if (c3 == 0) return -2; - if (c2 < 0x80 || 0x8F < c2 || (c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80) - return 0; - break; - default: - return 0; - break; - } - } - if (c1 == 0 || c1 == EOF){ - } else if ((c1 & 0xf8) == 0xf0) { /* 4 bytes */ - c2 = nkf_char_unicode_new(nkf_utf8_to_unicode(c1, c2, c3, c4)); - c1 = 0; - } else { - if (x0213_f && x0213_wait_combining_p(nkf_utf8_to_unicode(c1, c2, c3, c4))) - return -3; - ret = w2e_conv(c1, c2, c3, &c1, &c2); - } - if (ret == 0){ - (*oconv)(c1, c2); - } - return ret; -} - -static nkf_char -w_iconv_nocombine(nkf_char c1, nkf_char c2, nkf_char c3) -{ - /* continue from the line below 'return -3;' in w_iconv() */ - nkf_char ret = w2e_conv(c1, c2, c3, &c1, &c2); - if (ret == 0){ - (*oconv)(c1, c2); - } - return ret; -} - -#define NKF_ICONV_INVALID_CODE_RANGE -13 -#define NKF_ICONV_WAIT_COMBINING_CHAR -14 -#define NKF_ICONV_NOT_COMBINED -15 -static size_t -unicode_iconv(nkf_char wc, int nocombine) -{ - nkf_char c1, c2; - int ret = 0; - - if (wc < 0x80) { - c2 = 0; - c1 = wc; - }else if ((wc>>11) == 27) { - /* unpaired surrogate */ - return NKF_ICONV_INVALID_CODE_RANGE; - }else if (wc < 0xFFFF) { - if (!nocombine && x0213_f && x0213_wait_combining_p(wc)) - return NKF_ICONV_WAIT_COMBINING_CHAR; - ret = w16e_conv(wc, &c2, &c1); - if (ret) return ret; - }else if (wc < 0x10FFFF) { - c2 = 0; - c1 = nkf_char_unicode_new(wc); - } else { - return NKF_ICONV_INVALID_CODE_RANGE; - } - (*oconv)(c2, c1); - return 0; -} - -static nkf_char -unicode_iconv_combine(nkf_char wc, nkf_char wc2) -{ - nkf_char c1, c2; - int i; - - if (wc2 < 0x80) { - return NKF_ICONV_NOT_COMBINED; - }else if ((wc2>>11) == 27) { - /* unpaired surrogate */ - return NKF_ICONV_INVALID_CODE_RANGE; - }else if (wc2 < 0xFFFF) { - if (!x0213_combining_p(wc2)) - return NKF_ICONV_NOT_COMBINED; - for (i = 0; i < sizeof_x0213_combining_table; i++) { - if (x0213_combining_table[i][1] == wc && - x0213_combining_table[i][2] == wc2) { - c2 = x0213_combining_table[i][0] >> 8; - c1 = x0213_combining_table[i][0] & 0x7f; - (*oconv)(c2, c1); - return 0; - } - } - }else if (wc2 < 0x10FFFF) { - return NKF_ICONV_NOT_COMBINED; - } else { - return NKF_ICONV_INVALID_CODE_RANGE; - } - return NKF_ICONV_NOT_COMBINED; -} - -static nkf_char -w_iconv_combine(nkf_char c1, nkf_char c2, nkf_char c3, nkf_char c4, nkf_char c5, nkf_char c6) -{ - nkf_char wc, wc2; - wc = nkf_utf8_to_unicode(c1, c2, c3, 0); - wc2 = nkf_utf8_to_unicode(c4, c5, c6, 0); - if (wc2 < 0) - return wc2; - return unicode_iconv_combine(wc, wc2); -} - -#define NKF_ICONV_NEED_ONE_MORE_BYTE (size_t)-1 -#define NKF_ICONV_NEED_TWO_MORE_BYTES (size_t)-2 -static size_t -nkf_iconv_utf_16(nkf_char c1, nkf_char c2, nkf_char c3, nkf_char c4) -{ - nkf_char wc; - - if (c1 == EOF) { - (*oconv)(EOF, 0); - return 0; - } - - if (input_endian == ENDIAN_BIG) { - if (0xD8 <= c1 && c1 <= 0xDB) { - if (0xDC <= c3 && c3 <= 0xDF) { - wc = UTF16_TO_UTF32(c1 << 8 | c2, c3 << 8 | c4); - } else return NKF_ICONV_NEED_TWO_MORE_BYTES; - } else { - wc = c1 << 8 | c2; - } - } else { - if (0xD8 <= c2 && c2 <= 0xDB) { - if (0xDC <= c4 && c4 <= 0xDF) { - wc = UTF16_TO_UTF32(c2 << 8 | c1, c4 << 8 | c3); - } else return NKF_ICONV_NEED_TWO_MORE_BYTES; - } else { - wc = c2 << 8 | c1; - } - } - - return (*unicode_iconv)(wc, FALSE); -} - -static size_t -nkf_iconv_utf_16_combine(nkf_char c1, nkf_char c2, nkf_char c3, nkf_char c4) -{ - nkf_char wc, wc2; - - if (input_endian == ENDIAN_BIG) { - if (0xD8 <= c3 && c3 <= 0xDB) { - return NKF_ICONV_NOT_COMBINED; - } else { - wc = c1 << 8 | c2; - wc2 = c3 << 8 | c4; - } - } else { - if (0xD8 <= c2 && c2 <= 0xDB) { - return NKF_ICONV_NOT_COMBINED; - } else { - wc = c2 << 8 | c1; - wc2 = c4 << 8 | c3; - } - } - - return unicode_iconv_combine(wc, wc2); -} - -static size_t -nkf_iconv_utf_16_nocombine(nkf_char c1, nkf_char c2) -{ - nkf_char wc; - if (input_endian == ENDIAN_BIG) - wc = c1 << 8 | c2; - else - wc = c2 << 8 | c1; - return (*unicode_iconv)(wc, TRUE); -} - -static nkf_char -w_iconv16(nkf_char c2, nkf_char c1, ARG_UNUSED nkf_char c0) -{ - (*oconv)(c2, c1); - return 16; /* different from w_iconv32 */ -} - -static nkf_char -w_iconv32(nkf_char c2, nkf_char c1, ARG_UNUSED nkf_char c0) -{ - (*oconv)(c2, c1); - return 32; /* different from w_iconv16 */ -} - -static nkf_char -utf32_to_nkf_char(nkf_char c1, nkf_char c2, nkf_char c3, nkf_char c4) -{ - nkf_char wc; - - switch(input_endian){ - case ENDIAN_BIG: - wc = c2 << 16 | c3 << 8 | c4; - break; - case ENDIAN_LITTLE: - wc = c3 << 16 | c2 << 8 | c1; - break; - case ENDIAN_2143: - wc = c1 << 16 | c4 << 8 | c3; - break; - case ENDIAN_3412: - wc = c4 << 16 | c1 << 8 | c2; - break; - default: - return NKF_ICONV_INVALID_CODE_RANGE; - } - return wc; -} - -static size_t -nkf_iconv_utf_32(nkf_char c1, nkf_char c2, nkf_char c3, nkf_char c4) -{ - nkf_char wc; - - if (c1 == EOF) { - (*oconv)(EOF, 0); - return 0; - } - - wc = utf32_to_nkf_char(c1, c2, c3, c4); - if (wc < 0) - return wc; - - return (*unicode_iconv)(wc, FALSE); -} - -static nkf_char -nkf_iconv_utf_32_combine(nkf_char c1, nkf_char c2, nkf_char c3, nkf_char c4, nkf_char c5, nkf_char c6, nkf_char c7, nkf_char c8) -{ - nkf_char wc, wc2; - - wc = utf32_to_nkf_char(c1, c2, c3, c4); - if (wc < 0) - return wc; - wc2 = utf32_to_nkf_char(c5, c6, c7, c8); - if (wc2 < 0) - return wc2; - - return unicode_iconv_combine(wc, wc2); -} - -static size_t -nkf_iconv_utf_32_nocombine(nkf_char c1, nkf_char c2, nkf_char c3, nkf_char c4) -{ - nkf_char wc; - - wc = utf32_to_nkf_char(c1, c2, c3, c4); - return (*unicode_iconv)(wc, TRUE); -} -#endif - -#define output_ascii_escape_sequence(mode) do { \ - if (output_mode != ASCII && output_mode != ISO_8859_1) { \ - (*o_putc)(ESC); \ - (*o_putc)('('); \ - (*o_putc)(ascii_intro); \ - output_mode = mode; \ - } \ - } while (0) - -static void -output_escape_sequence(int mode) -{ - if (output_mode == mode) - return; - switch(mode) { - case ISO_8859_1: - (*o_putc)(ESC); - (*o_putc)('.'); - (*o_putc)('A'); - break; - case JIS_X_0201_1976_K: - (*o_putc)(ESC); - (*o_putc)('('); - (*o_putc)('I'); - break; - case JIS_X_0208: - (*o_putc)(ESC); - (*o_putc)('$'); - (*o_putc)(kanji_intro); - break; - case JIS_X_0212: - (*o_putc)(ESC); - (*o_putc)('$'); - (*o_putc)('('); - (*o_putc)('D'); - break; - case JIS_X_0213_1: - (*o_putc)(ESC); - (*o_putc)('$'); - (*o_putc)('('); - (*o_putc)('Q'); - break; - case JIS_X_0213_2: - (*o_putc)(ESC); - (*o_putc)('$'); - (*o_putc)('('); - (*o_putc)('P'); - break; - } - output_mode = mode; -} - -static void -j_oconv(nkf_char c2, nkf_char c1) -{ -#ifdef NUMCHAR_OPTION - if (c2 == 0 && nkf_char_unicode_p(c1)){ - w16e_conv(c1, &c2, &c1); - if (c2 == 0 && nkf_char_unicode_p(c1)){ - c2 = c1 & VALUE_MASK; - if (ms_ucs_map_f && 0xE000 <= c2 && c2 <= 0xE757) { - /* CP5022x UDC */ - c1 &= 0xFFF; - c2 = 0x7F + c1 / 94; - c1 = 0x21 + c1 % 94; - } else { - if (encode_fallback) (*encode_fallback)(c1); - return; - } - } - } -#endif - if (c2 == 0) { - output_ascii_escape_sequence(ASCII); - (*o_putc)(c1); - } - else if (c2 == EOF) { - output_ascii_escape_sequence(ASCII); - (*o_putc)(EOF); - } - else if (c2 == ISO_8859_1) { - output_ascii_escape_sequence(ISO_8859_1); - (*o_putc)(c1|0x80); - } - else if (c2 == JIS_X_0201_1976_K) { - output_escape_sequence(JIS_X_0201_1976_K); - (*o_putc)(c1); -#ifdef X0212_ENABLE - } else if (is_eucg3(c2)){ - output_escape_sequence(x0213_f ? JIS_X_0213_2 : JIS_X_0212); - (*o_putc)(c2 & 0x7f); - (*o_putc)(c1); -#endif - } else { - if(ms_ucs_map_f - ? c2<0x20 || 0x92 0x3e); - (*o_putc)(c2); - (*o_putc)(c1); - return; - } else { - if(encode_fallback)(*encode_fallback)(c1); - return; - } - } - } -#endif - if (c2 == EOF) { - (*o_putc)(EOF); - return; - } else if (c2 == 0) { - output_mode = ASCII; - (*o_putc)(c1); - } else if (c2 == JIS_X_0201_1976_K) { - output_mode = SHIFT_JIS; - (*o_putc)(c1|0x80); - } else if (c2 == ISO_8859_1) { - output_mode = ISO_8859_1; - (*o_putc)(c1 | 0x080); -#ifdef X0212_ENABLE - } else if (is_eucg3(c2)){ - output_mode = SHIFT_JIS; - if (e2s_conv(c2, c1, &c2, &c1) == 0){ - (*o_putc)(c2); - (*o_putc)(c1); - } -#endif - } else { - if (!nkf_isprint(c1) || !nkf_isprint(c2)) { - set_iconv(FALSE, 0); - return; /* too late to rescue this char */ - } - output_mode = SHIFT_JIS; - e2s_conv(c2, c1, &c2, &c1); - -#ifdef SHIFTJIS_CP932 - if (cp932inv_f - && CP932INV_TABLE_BEGIN <= c2 && c2 <= CP932INV_TABLE_END){ - nkf_char c = cp932inv[c2 - CP932INV_TABLE_BEGIN][c1 - 0x40]; - if (c){ - c2 = c >> 8; - c1 = c & 0xff; - } - } -#endif /* SHIFTJIS_CP932 */ - - (*o_putc)(c2); - if (prefix_table[(unsigned char)c1]){ - (*o_putc)(prefix_table[(unsigned char)c1]); - } - (*o_putc)(c1); - } -} - -#ifdef UTF8_OUTPUT_ENABLE -#define OUTPUT_UTF8(val) do { \ - nkf_unicode_to_utf8(val, &c1, &c2, &c3, &c4); \ - (*o_putc)(c1); \ - if (c2) (*o_putc)(c2); \ - if (c3) (*o_putc)(c3); \ - if (c4) (*o_putc)(c4); \ - } while (0) - -static void -w_oconv(nkf_char c2, nkf_char c1) -{ - nkf_char c3, c4; - nkf_char val, val2; - - if (output_bom_f) { - output_bom_f = FALSE; - (*o_putc)('\357'); - (*o_putc)('\273'); - (*o_putc)('\277'); - } - - if (c2 == EOF) { - (*o_putc)(EOF); - return; - } - - if (c2 == 0 && nkf_char_unicode_p(c1)){ - val = c1 & VALUE_MASK; - OUTPUT_UTF8(val); - return; - } - - if (c2 == 0) { - (*o_putc)(c1); - } else { - val = e2w_conv(c2, c1); - if (val){ - val2 = e2w_combining(val, c2, c1); - if (val2) - OUTPUT_UTF8(val2); - OUTPUT_UTF8(val); - } - } -} - -#define OUTPUT_UTF16_BYTES(c1, c2) do { \ - if (output_endian == ENDIAN_LITTLE){ \ - (*o_putc)(c1); \ - (*o_putc)(c2); \ - }else{ \ - (*o_putc)(c2); \ - (*o_putc)(c1); \ - } \ - } while (0) - -#define OUTPUT_UTF16(val) do { \ - if (nkf_char_unicode_bmp_p(val)) { \ - c2 = (val >> 8) & 0xff; \ - c1 = val & 0xff; \ - OUTPUT_UTF16_BYTES(c1, c2); \ - } else { \ - val &= VALUE_MASK; \ - if (val <= UNICODE_MAX) { \ - c2 = (val >> 10) + NKF_INT32_C(0xD7C0); /* high surrogate */ \ - c1 = (val & 0x3FF) + NKF_INT32_C(0xDC00); /* low surrogate */ \ - OUTPUT_UTF16_BYTES(c2 & 0xff, (c2 >> 8) & 0xff); \ - OUTPUT_UTF16_BYTES(c1 & 0xff, (c1 >> 8) & 0xff); \ - } \ - } \ - } while (0) - -static void -w_oconv16(nkf_char c2, nkf_char c1) -{ - if (output_bom_f) { - output_bom_f = FALSE; - OUTPUT_UTF16_BYTES(0xFF, 0xFE); - } - - if (c2 == EOF) { - (*o_putc)(EOF); - return; - } - - if (c2 == 0 && nkf_char_unicode_p(c1)) { - OUTPUT_UTF16(c1); - } else if (c2) { - nkf_char val, val2; - val = e2w_conv(c2, c1); - if (!val) return; - val2 = e2w_combining(val, c2, c1); - if (val2) - OUTPUT_UTF16(val2); - OUTPUT_UTF16(val); - } else { - OUTPUT_UTF16_BYTES(c1, c2); - } -} - -#define OUTPUT_UTF32(c) do { \ - if (output_endian == ENDIAN_LITTLE){ \ - (*o_putc)( (c) & 0xFF); \ - (*o_putc)(((c) >> 8) & 0xFF); \ - (*o_putc)(((c) >> 16) & 0xFF); \ - (*o_putc)(0); \ - }else{ \ - (*o_putc)(0); \ - (*o_putc)(((c) >> 16) & 0xFF); \ - (*o_putc)(((c) >> 8) & 0xFF); \ - (*o_putc)( (c) & 0xFF); \ - } \ - } while (0) - -static void -w_oconv32(nkf_char c2, nkf_char c1) -{ - if (output_bom_f) { - output_bom_f = FALSE; - if (output_endian == ENDIAN_LITTLE){ - (*o_putc)(0xFF); - (*o_putc)(0xFE); - (*o_putc)(0); - (*o_putc)(0); - }else{ - (*o_putc)(0); - (*o_putc)(0); - (*o_putc)(0xFE); - (*o_putc)(0xFF); - } - } - - if (c2 == EOF) { - (*o_putc)(EOF); - return; - } - - if (c2 == ISO_8859_1) { - c1 |= 0x80; - } else if (c2 == 0 && nkf_char_unicode_p(c1)) { - c1 &= VALUE_MASK; - } else if (c2) { - nkf_char val, val2; - val = e2w_conv(c2, c1); - if (!val) return; - val2 = e2w_combining(val, c2, c1); - if (val2) - OUTPUT_UTF32(val2); - c1 = val; - } - OUTPUT_UTF32(c1); -} -#endif - -#define SCORE_L2 (1) /* Kanji Level 2 */ -#define SCORE_KANA (SCORE_L2 << 1) /* Halfwidth Katakana */ -#define SCORE_DEPEND (SCORE_KANA << 1) /* MD Characters */ -#define SCORE_CP932 (SCORE_DEPEND << 1) /* IBM extended characters */ -#define SCORE_X0212 (SCORE_CP932 << 1) /* JIS X 0212 */ -#define SCORE_X0213 (SCORE_X0212 << 1) /* JIS X 0213 */ -#define SCORE_NO_EXIST (SCORE_X0213 << 1) /* Undefined Characters */ -#define SCORE_iMIME (SCORE_NO_EXIST << 1) /* MIME selected */ -#define SCORE_ERROR (SCORE_iMIME << 1) /* Error */ - -#define SCORE_INIT (SCORE_iMIME) - -static const nkf_char score_table_A0[] = { - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, SCORE_DEPEND, SCORE_DEPEND, SCORE_DEPEND, - SCORE_DEPEND, SCORE_DEPEND, SCORE_DEPEND, SCORE_X0213, -}; - -static const nkf_char score_table_F0[] = { - SCORE_L2, SCORE_L2, SCORE_L2, SCORE_L2, - SCORE_L2, SCORE_DEPEND, SCORE_X0213, SCORE_X0213, - SCORE_DEPEND, SCORE_DEPEND, SCORE_CP932, SCORE_CP932, - SCORE_CP932, SCORE_X0213, SCORE_X0213, SCORE_ERROR, -}; - -static const nkf_char score_table_8FA0[] = { - 0, SCORE_X0213, SCORE_X0212, SCORE_X0213, - SCORE_X0213, SCORE_X0213, SCORE_X0212, SCORE_X0212, - SCORE_X0213, SCORE_X0212, SCORE_X0212, SCORE_X0212, - SCORE_X0213, SCORE_X0213, SCORE_X0213, SCORE_X0213, -}; - -static const nkf_char score_table_8FE0[] = { - SCORE_X0212, SCORE_X0212, SCORE_X0212, SCORE_X0212, - SCORE_X0212, SCORE_X0212, SCORE_X0212, SCORE_X0212, - SCORE_X0212, SCORE_X0212, SCORE_X0212, SCORE_X0212, - SCORE_X0212, SCORE_X0212, SCORE_X0213, SCORE_X0213, -}; - -static const nkf_char score_table_8FF0[] = { - SCORE_X0213, SCORE_X0213, SCORE_X0213, SCORE_X0212, - SCORE_X0212, SCORE_X0213, SCORE_X0213, SCORE_X0213, - SCORE_X0213, SCORE_X0213, SCORE_X0213, SCORE_X0213, - SCORE_X0213, SCORE_X0213, SCORE_X0213, SCORE_X0213, -}; - -static void -set_code_score(struct input_code *ptr, nkf_char score) -{ - if (ptr){ - ptr->score |= score; - } -} - -static void -clr_code_score(struct input_code *ptr, nkf_char score) -{ - if (ptr){ - ptr->score &= ~score; - } -} - -static void -code_score(struct input_code *ptr) -{ - nkf_char c2 = ptr->buf[0]; - nkf_char c1 = ptr->buf[1]; - if (c2 < 0){ - set_code_score(ptr, SCORE_ERROR); - }else if (c2 == SS2){ - set_code_score(ptr, SCORE_KANA); - }else if (c2 == 0x8f){ - if ((c1 & 0x70) == 0x20){ - set_code_score(ptr, score_table_8FA0[c1 & 0x0f]); - }else if ((c1 & 0x70) == 0x60){ - set_code_score(ptr, score_table_8FE0[c1 & 0x0f]); - }else if ((c1 & 0x70) == 0x70){ - set_code_score(ptr, score_table_8FF0[c1 & 0x0f]); - }else{ - set_code_score(ptr, SCORE_X0212); - } -#ifdef UTF8_OUTPUT_ENABLE - }else if (!e2w_conv(c2, c1)){ - set_code_score(ptr, SCORE_NO_EXIST); -#endif - }else if ((c2 & 0x70) == 0x20){ - set_code_score(ptr, score_table_A0[c2 & 0x0f]); - }else if ((c2 & 0x70) == 0x70){ - set_code_score(ptr, score_table_F0[c2 & 0x0f]); - }else if ((c2 & 0x70) >= 0x50){ - set_code_score(ptr, SCORE_L2); - } -} - -static void -status_disable(struct input_code *ptr) -{ - ptr->stat = -1; - ptr->buf[0] = -1; - code_score(ptr); - if (iconv == ptr->iconv_func) set_iconv(FALSE, 0); -} - -static void -status_push_ch(struct input_code *ptr, nkf_char c) -{ - ptr->buf[ptr->index++] = c; -} - -static void -status_clear(struct input_code *ptr) -{ - ptr->stat = 0; - ptr->index = 0; -} - -static void -status_reset(struct input_code *ptr) -{ - status_clear(ptr); - ptr->score = SCORE_INIT; -} - -static void -status_reinit(struct input_code *ptr) -{ - status_reset(ptr); - ptr->_file_stat = 0; -} - -static void -status_check(struct input_code *ptr, nkf_char c) -{ - if (c <= DEL && estab_f){ - status_reset(ptr); - } -} - -static void -s_status(struct input_code *ptr, nkf_char c) -{ - switch(ptr->stat){ - case -1: - status_check(ptr, c); - break; - case 0: - if (c <= DEL){ - break; - }else if (nkf_char_unicode_p(c)){ - break; - }else if (0xa1 <= c && c <= 0xdf){ - status_push_ch(ptr, SS2); - status_push_ch(ptr, c); - code_score(ptr); - status_clear(ptr); - }else if ((0x81 <= c && c < 0xa0) || (0xe0 <= c && c <= 0xea)){ - ptr->stat = 1; - status_push_ch(ptr, c); - }else if (0xed <= c && c <= 0xee){ - ptr->stat = 3; - status_push_ch(ptr, c); -#ifdef SHIFTJIS_CP932 - }else if (is_ibmext_in_sjis(c)){ - ptr->stat = 2; - status_push_ch(ptr, c); -#endif /* SHIFTJIS_CP932 */ -#ifdef X0212_ENABLE - }else if (0xf0 <= c && c <= 0xfc){ - ptr->stat = 1; - status_push_ch(ptr, c); -#endif /* X0212_ENABLE */ - }else{ - status_disable(ptr); - } - break; - case 1: - if ((0x40 <= c && c <= 0x7e) || (0x80 <= c && c <= 0xfc)){ - status_push_ch(ptr, c); - s2e_conv(ptr->buf[0], ptr->buf[1], &ptr->buf[0], &ptr->buf[1]); - code_score(ptr); - status_clear(ptr); - }else{ - status_disable(ptr); - } - break; - case 2: -#ifdef SHIFTJIS_CP932 - if ((0x40 <= c && c <= 0x7e) || (0x80 <= c && c <= 0xfc)) { - status_push_ch(ptr, c); - if (s2e_conv(ptr->buf[0], ptr->buf[1], &ptr->buf[0], &ptr->buf[1]) == 0) { - set_code_score(ptr, SCORE_CP932); - status_clear(ptr); - break; - } - } -#endif /* SHIFTJIS_CP932 */ - status_disable(ptr); - break; - case 3: - if ((0x40 <= c && c <= 0x7e) || (0x80 <= c && c <= 0xfc)){ - status_push_ch(ptr, c); - s2e_conv(ptr->buf[0], ptr->buf[1], &ptr->buf[0], &ptr->buf[1]); - set_code_score(ptr, SCORE_CP932); - status_clear(ptr); - }else{ - status_disable(ptr); - } - break; - } -} - -static void -e_status(struct input_code *ptr, nkf_char c) -{ - switch (ptr->stat){ - case -1: - status_check(ptr, c); - break; - case 0: - if (c <= DEL){ - break; - }else if (nkf_char_unicode_p(c)){ - break; - }else if (SS2 == c || (0xa1 <= c && c <= 0xfe)){ - ptr->stat = 1; - status_push_ch(ptr, c); -#ifdef X0212_ENABLE - }else if (0x8f == c){ - ptr->stat = 2; - status_push_ch(ptr, c); -#endif /* X0212_ENABLE */ - }else{ - status_disable(ptr); - } - break; - case 1: - if (0xa1 <= c && c <= 0xfe){ - status_push_ch(ptr, c); - code_score(ptr); - status_clear(ptr); - }else{ - status_disable(ptr); - } - break; -#ifdef X0212_ENABLE - case 2: - if (0xa1 <= c && c <= 0xfe){ - ptr->stat = 1; - status_push_ch(ptr, c); - }else{ - status_disable(ptr); - } -#endif /* X0212_ENABLE */ - } -} - -#ifdef UTF8_INPUT_ENABLE -static void -w_status(struct input_code *ptr, nkf_char c) -{ - switch (ptr->stat){ - case -1: - status_check(ptr, c); - break; - case 0: - if (c <= DEL){ - break; - }else if (nkf_char_unicode_p(c)){ - break; - }else if (0xc0 <= c && c <= 0xdf){ - ptr->stat = 1; - status_push_ch(ptr, c); - }else if (0xe0 <= c && c <= 0xef){ - ptr->stat = 2; - status_push_ch(ptr, c); - }else if (0xf0 <= c && c <= 0xf4){ - ptr->stat = 3; - status_push_ch(ptr, c); - }else{ - status_disable(ptr); - } - break; - case 1: - case 2: - if (0x80 <= c && c <= 0xbf){ - status_push_ch(ptr, c); - if (ptr->index > ptr->stat){ - int bom = (ptr->buf[0] == 0xef && ptr->buf[1] == 0xbb - && ptr->buf[2] == 0xbf); - w2e_conv(ptr->buf[0], ptr->buf[1], ptr->buf[2], - &ptr->buf[0], &ptr->buf[1]); - if (!bom){ - code_score(ptr); - } - status_clear(ptr); - } - }else{ - status_disable(ptr); - } - break; - case 3: - if (0x80 <= c && c <= 0xbf){ - if (ptr->index < ptr->stat){ - status_push_ch(ptr, c); - } else { - status_clear(ptr); - } - }else{ - status_disable(ptr); - } - break; - } -} -#endif - -static void -code_status(nkf_char c) -{ - int action_flag = 1; - struct input_code *result = 0; - struct input_code *p = input_code_list; - while (p->name){ - if (!p->status_func) { - ++p; - continue; - } - if (!p->status_func) - continue; - (p->status_func)(p, c); - if (p->stat > 0){ - action_flag = 0; - }else if(p->stat == 0){ - if (result){ - action_flag = 0; - }else{ - result = p; - } - } - ++p; - } - - if (action_flag){ - if (result && !estab_f){ - set_iconv(TRUE, result->iconv_func); - }else if (c <= DEL){ - struct input_code *ptr = input_code_list; - while (ptr->name){ - status_reset(ptr); - ++ptr; - } - } - } -} - -typedef struct { - nkf_buf_t *std_gc_buf; - nkf_char broken_state; - nkf_buf_t *broken_buf; - nkf_char mimeout_state; - nkf_buf_t *nfc_buf; -} nkf_state_t; - -static nkf_state_t *nkf_state = NULL; - -#define STD_GC_BUFSIZE (256) - -static void -nkf_state_init(void) -{ - if (nkf_state) { - nkf_buf_clear(nkf_state->std_gc_buf); - nkf_buf_clear(nkf_state->broken_buf); - nkf_buf_clear(nkf_state->nfc_buf); - } - else { - nkf_state = nkf_xmalloc(sizeof(nkf_state_t)); - nkf_state->std_gc_buf = nkf_buf_new(STD_GC_BUFSIZE); - nkf_state->broken_buf = nkf_buf_new(3); - nkf_state->nfc_buf = nkf_buf_new(9); - } - nkf_state->broken_state = 0; - nkf_state->mimeout_state = 0; -} - -#ifndef WIN32DLL -static nkf_char -std_getc(FILE *f) -{ - if (!nkf_buf_empty_p(nkf_state->std_gc_buf)){ - return nkf_buf_pop(nkf_state->std_gc_buf); - } - return getc(f); -} -#endif /*WIN32DLL*/ - -static nkf_char -std_ungetc(nkf_char c, ARG_UNUSED FILE *f) -{ - nkf_buf_push(nkf_state->std_gc_buf, c); - return c; -} - -#ifndef WIN32DLL -static void -std_putc(nkf_char c) -{ - if(c!=EOF) - putchar(c); -} -#endif /*WIN32DLL*/ - -static nkf_char hold_buf[HOLD_SIZE*2]; -static int hold_count = 0; -static nkf_char -push_hold_buf(nkf_char c2) -{ - if (hold_count >= HOLD_SIZE*2) - return (EOF); - hold_buf[hold_count++] = c2; - return ((hold_count >= HOLD_SIZE*2) ? EOF : hold_count); -} - -static int -h_conv(FILE *f, nkf_char c1, nkf_char c2) -{ - int ret; - int hold_index; - int fromhold_count; - nkf_char c3, c4; - - /** it must NOT be in the kanji shifte sequence */ - /** it must NOT be written in JIS7 */ - /** and it must be after 2 byte 8bit code */ - - hold_count = 0; - push_hold_buf(c1); - push_hold_buf(c2); - - while ((c2 = (*i_getc)(f)) != EOF) { - if (c2 == ESC){ - (*i_ungetc)(c2,f); - break; - } - code_status(c2); - if (push_hold_buf(c2) == EOF || estab_f) { - break; - } - } - - if (!estab_f) { - struct input_code *p = input_code_list; - struct input_code *result = p; - if (c2 == EOF) { - code_status(c2); - } - while (p->name) { - if (p->status_func && p->score < result->score) { - result = p; - } - p++; - } - set_iconv(TRUE, result->iconv_func); - } - - - /** now, - ** 1) EOF is detected, or - ** 2) Code is established, or - ** 3) Buffer is FULL (but last word is pushed) - ** - ** in 1) and 3) cases, we continue to use - ** Kanji codes by oconv and leave estab_f unchanged. - **/ - - ret = c2; - hold_index = 0; - while (hold_index < hold_count){ - c1 = hold_buf[hold_index++]; - if (nkf_char_unicode_p(c1)) { - (*oconv)(0, c1); - continue; - } - else if (c1 <= DEL){ - (*iconv)(0, c1, 0); - continue; - }else if (iconv == s_iconv && 0xa1 <= c1 && c1 <= 0xdf){ - (*iconv)(JIS_X_0201_1976_K, c1, 0); - continue; - } - fromhold_count = 1; - if (hold_index < hold_count){ - c2 = hold_buf[hold_index++]; - fromhold_count++; - }else{ - c2 = (*i_getc)(f); - if (c2 == EOF){ - c4 = EOF; - break; - } - code_status(c2); - } - c3 = 0; - switch ((*iconv)(c1, c2, 0)) { /* can be EUC/SJIS/UTF-8 */ - case -2: - /* 4 bytes UTF-8 */ - if (hold_index < hold_count){ - c3 = hold_buf[hold_index++]; - } else if ((c3 = (*i_getc)(f)) == EOF) { - ret = EOF; - break; - } - code_status(c3); - if (hold_index < hold_count){ - c4 = hold_buf[hold_index++]; - } else if ((c4 = (*i_getc)(f)) == EOF) { - c3 = ret = EOF; - break; - } - code_status(c4); - (*iconv)(c1, c2, (c3<<8)|c4); - break; - case -3: - /* 4 bytes UTF-8 (check combining character) */ - if (hold_index < hold_count){ - c3 = hold_buf[hold_index++]; - fromhold_count++; - } else if ((c3 = (*i_getc)(f)) == EOF) { - w_iconv_nocombine(c1, c2, 0); - break; - } - if (hold_index < hold_count){ - c4 = hold_buf[hold_index++]; - fromhold_count++; - } else if ((c4 = (*i_getc)(f)) == EOF) { - w_iconv_nocombine(c1, c2, 0); - if (fromhold_count <= 2) - (*i_ungetc)(c3,f); - else - hold_index--; - continue; - } - if (w_iconv_combine(c1, c2, 0, c3, c4, 0)) { - w_iconv_nocombine(c1, c2, 0); - if (fromhold_count <= 2) { - (*i_ungetc)(c4,f); - (*i_ungetc)(c3,f); - } else if (fromhold_count == 3) { - (*i_ungetc)(c4,f); - hold_index--; - } else { - hold_index -= 2; - } - } - break; - case -1: - /* 3 bytes EUC or UTF-8 */ - if (hold_index < hold_count){ - c3 = hold_buf[hold_index++]; - fromhold_count++; - } else if ((c3 = (*i_getc)(f)) == EOF) { - ret = EOF; - break; - } else { - code_status(c3); - } - if ((*iconv)(c1, c2, c3) == -3) { - /* 6 bytes UTF-8 (check combining character) */ - nkf_char c5, c6; - if (hold_index < hold_count){ - c4 = hold_buf[hold_index++]; - fromhold_count++; - } else if ((c4 = (*i_getc)(f)) == EOF) { - w_iconv_nocombine(c1, c2, c3); - continue; - } - if (hold_index < hold_count){ - c5 = hold_buf[hold_index++]; - fromhold_count++; - } else if ((c5 = (*i_getc)(f)) == EOF) { - w_iconv_nocombine(c1, c2, c3); - if (fromhold_count == 4) - hold_index--; - else - (*i_ungetc)(c4,f); - continue; - } - if (hold_index < hold_count){ - c6 = hold_buf[hold_index++]; - fromhold_count++; - } else if ((c6 = (*i_getc)(f)) == EOF) { - w_iconv_nocombine(c1, c2, c3); - if (fromhold_count == 5) { - hold_index -= 2; - } else if (fromhold_count == 4) { - hold_index--; - (*i_ungetc)(c5,f); - } else { - (*i_ungetc)(c5,f); - (*i_ungetc)(c4,f); - } - continue; - } - if (w_iconv_combine(c1, c2, c3, c4, c5, c6)) { - w_iconv_nocombine(c1, c2, c3); - if (fromhold_count == 6) { - hold_index -= 3; - } else if (fromhold_count == 5) { - hold_index -= 2; - (*i_ungetc)(c6,f); - } else if (fromhold_count == 4) { - hold_index--; - (*i_ungetc)(c6,f); - (*i_ungetc)(c5,f); - } else { - (*i_ungetc)(c6,f); - (*i_ungetc)(c5,f); - (*i_ungetc)(c4,f); - } - } - } - break; - } - if (c3 == EOF) break; - } - return ret; -} - -/* - * Check and Ignore BOM - */ -static void -check_bom(FILE *f) -{ - int c2; - input_bom_f = FALSE; - switch(c2 = (*i_getc)(f)){ - case 0x00: - if((c2 = (*i_getc)(f)) == 0x00){ - if((c2 = (*i_getc)(f)) == 0xFE){ - if((c2 = (*i_getc)(f)) == 0xFF){ - if(!input_encoding){ - set_iconv(TRUE, w_iconv32); - } - if (iconv == w_iconv32) { - input_bom_f = TRUE; - input_endian = ENDIAN_BIG; - return; - } - (*i_ungetc)(0xFF,f); - }else (*i_ungetc)(c2,f); - (*i_ungetc)(0xFE,f); - }else if(c2 == 0xFF){ - if((c2 = (*i_getc)(f)) == 0xFE){ - if(!input_encoding){ - set_iconv(TRUE, w_iconv32); - } - if (iconv == w_iconv32) { - input_endian = ENDIAN_2143; - return; - } - (*i_ungetc)(0xFF,f); - }else (*i_ungetc)(c2,f); - (*i_ungetc)(0xFF,f); - }else (*i_ungetc)(c2,f); - (*i_ungetc)(0x00,f); - }else (*i_ungetc)(c2,f); - (*i_ungetc)(0x00,f); - break; - case 0xEF: - if((c2 = (*i_getc)(f)) == 0xBB){ - if((c2 = (*i_getc)(f)) == 0xBF){ - if(!input_encoding){ - set_iconv(TRUE, w_iconv); - } - if (iconv == w_iconv) { - input_bom_f = TRUE; - return; - } - (*i_ungetc)(0xBF,f); - }else (*i_ungetc)(c2,f); - (*i_ungetc)(0xBB,f); - }else (*i_ungetc)(c2,f); - (*i_ungetc)(0xEF,f); - break; - case 0xFE: - if((c2 = (*i_getc)(f)) == 0xFF){ - if((c2 = (*i_getc)(f)) == 0x00){ - if((c2 = (*i_getc)(f)) == 0x00){ - if(!input_encoding){ - set_iconv(TRUE, w_iconv32); - } - if (iconv == w_iconv32) { - input_endian = ENDIAN_3412; - return; - } - (*i_ungetc)(0x00,f); - }else (*i_ungetc)(c2,f); - (*i_ungetc)(0x00,f); - }else (*i_ungetc)(c2,f); - if(!input_encoding){ - set_iconv(TRUE, w_iconv16); - } - if (iconv == w_iconv16) { - input_endian = ENDIAN_BIG; - input_bom_f = TRUE; - return; - } - (*i_ungetc)(0xFF,f); - }else (*i_ungetc)(c2,f); - (*i_ungetc)(0xFE,f); - break; - case 0xFF: - if((c2 = (*i_getc)(f)) == 0xFE){ - if((c2 = (*i_getc)(f)) == 0x00){ - if((c2 = (*i_getc)(f)) == 0x00){ - if(!input_encoding){ - set_iconv(TRUE, w_iconv32); - } - if (iconv == w_iconv32) { - input_endian = ENDIAN_LITTLE; - input_bom_f = TRUE; - return; - } - (*i_ungetc)(0x00,f); - }else (*i_ungetc)(c2,f); - (*i_ungetc)(0x00,f); - }else (*i_ungetc)(c2,f); - if(!input_encoding){ - set_iconv(TRUE, w_iconv16); - } - if (iconv == w_iconv16) { - input_endian = ENDIAN_LITTLE; - input_bom_f = TRUE; - return; - } - (*i_ungetc)(0xFE,f); - }else (*i_ungetc)(c2,f); - (*i_ungetc)(0xFF,f); - break; - default: - (*i_ungetc)(c2,f); - break; - } -} - -static nkf_char -broken_getc(FILE *f) -{ - nkf_char c, c1; - - if (!nkf_buf_empty_p(nkf_state->broken_buf)) { - return nkf_buf_pop(nkf_state->broken_buf); - } - c = (*i_bgetc)(f); - if (c=='$' && nkf_state->broken_state != ESC - && (input_mode == ASCII || input_mode == JIS_X_0201_1976_K)) { - c1= (*i_bgetc)(f); - nkf_state->broken_state = 0; - if (c1=='@'|| c1=='B') { - nkf_buf_push(nkf_state->broken_buf, c1); - nkf_buf_push(nkf_state->broken_buf, c); - return ESC; - } else { - (*i_bungetc)(c1,f); - return c; - } - } else if (c=='(' && nkf_state->broken_state != ESC - && (input_mode == JIS_X_0208 || input_mode == JIS_X_0201_1976_K)) { - c1= (*i_bgetc)(f); - nkf_state->broken_state = 0; - if (c1=='J'|| c1=='B') { - nkf_buf_push(nkf_state->broken_buf, c1); - nkf_buf_push(nkf_state->broken_buf, c); - return ESC; - } else { - (*i_bungetc)(c1,f); - return c; - } - } else { - nkf_state->broken_state = c; - return c; - } -} - -static nkf_char -broken_ungetc(nkf_char c, ARG_UNUSED FILE *f) -{ - if (nkf_buf_length(nkf_state->broken_buf) < 2) - nkf_buf_push(nkf_state->broken_buf, c); - return c; -} - -static void -eol_conv(nkf_char c2, nkf_char c1) -{ - if (guess_f && input_eol != EOF) { - if (c2 == 0 && c1 == LF) { - if (!input_eol) input_eol = prev_cr ? CRLF : LF; - else if (input_eol != (prev_cr ? CRLF : LF)) input_eol = EOF; - } else if (c2 == 0 && c1 == CR && input_eol == LF) input_eol = EOF; - else if (!prev_cr); - else if (!input_eol) input_eol = CR; - else if (input_eol != CR) input_eol = EOF; - } - if (prev_cr || (c2 == 0 && c1 == LF)) { - prev_cr = 0; - if (eolmode_f != LF) (*o_eol_conv)(0, CR); - if (eolmode_f != CR) (*o_eol_conv)(0, LF); - } - if (c2 == 0 && c1 == CR) prev_cr = CR; - else if (c2 != 0 || c1 != LF) (*o_eol_conv)(c2, c1); -} - -static void -put_newline(void (*func)(nkf_char)) -{ - switch (eolmode_f ? eolmode_f : DEFAULT_NEWLINE) { - case CRLF: - (*func)(0x0D); - (*func)(0x0A); - break; - case CR: - (*func)(0x0D); - break; - case LF: - (*func)(0x0A); - break; - } -} - -static void -oconv_newline(void (*func)(nkf_char, nkf_char)) -{ - switch (eolmode_f ? eolmode_f : DEFAULT_NEWLINE) { - case CRLF: - (*func)(0, 0x0D); - (*func)(0, 0x0A); - break; - case CR: - (*func)(0, 0x0D); - break; - case LF: - (*func)(0, 0x0A); - break; - } -} - -/* - Return value of fold_conv() - - LF add newline and output char - CR add newline and output nothing - SP space - 0 skip - 1 (or else) normal output - - fold state in prev (previous character) - - >0x80 Japanese (X0208/X0201) - <0x80 ASCII - LF new line - SP space - - This fold algorithm does not preserve heading space in a line. - This is the main difference from fmt. - */ - -#define char_size(c2,c1) (c2?2:1) - -static void -fold_conv(nkf_char c2, nkf_char c1) -{ - nkf_char prev0; - nkf_char fold_state; - - if (c1== CR && !fold_preserve_f) { - fold_state=0; /* ignore cr */ - }else if (c1== LF&&f_prev==CR && fold_preserve_f) { - f_prev = LF; - fold_state=0; /* ignore cr */ - } else if (c1== BS) { - if (f_line>0) f_line--; - fold_state = 1; - } else if (c2==EOF && f_line != 0) { /* close open last line */ - fold_state = LF; - } else if ((c1==LF && !fold_preserve_f) - || ((c1==CR||(c1==LF&&f_prev!=CR)) - && fold_preserve_f)) { - /* new line */ - if (fold_preserve_f) { - f_prev = c1; - f_line = 0; - fold_state = CR; - } else if ((f_prev == c1) - || (f_prev == LF) - ) { /* duplicate newline */ - if (f_line) { - f_line = 0; - fold_state = LF; /* output two newline */ - } else { - f_line = 0; - fold_state = 1; - } - } else { - if (f_prev&0x80) { /* Japanese? */ - f_prev = c1; - fold_state = 0; /* ignore given single newline */ - } else if (f_prev==SP) { - fold_state = 0; - } else { - f_prev = c1; - if (++f_line<=fold_len) - fold_state = SP; - else { - f_line = 0; - fold_state = CR; /* fold and output nothing */ - } - } - } - } else if (c1=='\f') { - f_prev = LF; - f_line = 0; - fold_state = LF; /* output newline and clear */ - } else if ((c2==0 && nkf_isblank(c1)) || (c2 == '!' && c1 == '!')) { - /* X0208 kankaku or ascii space */ - if (f_prev == SP) { - fold_state = 0; /* remove duplicate spaces */ - } else { - f_prev = SP; - if (++f_line<=fold_len) - fold_state = SP; /* output ASCII space only */ - else { - f_prev = SP; f_line = 0; - fold_state = CR; /* fold and output nothing */ - } - } - } else { - prev0 = f_prev; /* we still need this one... , but almost done */ - f_prev = c1; - if (c2 || c2 == JIS_X_0201_1976_K) - f_prev |= 0x80; /* this is Japanese */ - f_line += c2 == JIS_X_0201_1976_K ? 1: char_size(c2,c1); - if (f_line<=fold_len) { /* normal case */ - fold_state = 1; - } else { - if (f_line>fold_len+fold_margin) { /* too many kinsoku suspension */ - f_line = char_size(c2,c1); - fold_state = LF; /* We can't wait, do fold now */ - } else if (c2 == JIS_X_0201_1976_K) { - /* simple kinsoku rules return 1 means no folding */ - if (c1==(0xde&0x7f)) fold_state = 1; /* $B!+(B*/ - else if (c1==(0xdf&0x7f)) fold_state = 1; /* $B!,(B*/ - else if (c1==(0xa4&0x7f)) fold_state = 1; /* $B!#(B*/ - else if (c1==(0xa3&0x7f)) fold_state = 1; /* $B!$(B*/ - else if (c1==(0xa1&0x7f)) fold_state = 1; /* $B!W(B*/ - else if (c1==(0xb0&0x7f)) fold_state = 1; /* - */ - else if (SP<=c1 && c1<=(0xdf&0x7f)) { /* X0201 */ - f_line = 1; - fold_state = LF;/* add one new f_line before this character */ - } else { - f_line = 1; - fold_state = LF;/* add one new f_line before this character */ - } - } else if (c2==0) { - /* kinsoku point in ASCII */ - if ( c1==')'|| /* { [ ( */ - c1==']'|| - c1=='}'|| - c1=='.'|| - c1==','|| - c1=='!'|| - c1=='?'|| - c1=='/'|| - c1==':'|| - c1==';') { - fold_state = 1; - /* just after special */ - } else if (!is_alnum(prev0)) { - f_line = char_size(c2,c1); - fold_state = LF; - } else if ((prev0==SP) || /* ignored new f_line */ - (prev0==LF)|| /* ignored new f_line */ - (prev0&0x80)) { /* X0208 - ASCII */ - f_line = char_size(c2,c1); - fold_state = LF;/* add one new f_line before this character */ - } else { - fold_state = 1; /* default no fold in ASCII */ - } - } else { - if (c2=='!') { - if (c1=='"') fold_state = 1; /* $B!"(B */ - else if (c1=='#') fold_state = 1; /* $B!#(B */ - else if (c1=='W') fold_state = 1; /* $B!W(B */ - else if (c1=='K') fold_state = 1; /* $B!K(B */ - else if (c1=='$') fold_state = 1; /* $B!$(B */ - else if (c1=='%') fold_state = 1; /* $B!%(B */ - else if (c1=='\'') fold_state = 1; /* $B!\(B */ - else if (c1=='(') fold_state = 1; /* $B!((B */ - else if (c1==')') fold_state = 1; /* $B!)(B */ - else if (c1=='*') fold_state = 1; /* $B!*(B */ - else if (c1=='+') fold_state = 1; /* $B!+(B */ - else if (c1==',') fold_state = 1; /* $B!,(B */ - /* default no fold in kinsoku */ - else { - fold_state = LF; - f_line = char_size(c2,c1); - /* add one new f_line before this character */ - } - } else { - f_line = char_size(c2,c1); - fold_state = LF; - /* add one new f_line before this character */ - } - } - } - } - /* terminator process */ - switch(fold_state) { - case LF: - oconv_newline(o_fconv); - (*o_fconv)(c2,c1); - break; - case 0: - return; - case CR: - oconv_newline(o_fconv); - break; - case TAB: - case SP: - (*o_fconv)(0,SP); - break; - default: - (*o_fconv)(c2,c1); - } -} - -static nkf_char z_prev2=0,z_prev1=0; - -static void -z_conv(nkf_char c2, nkf_char c1) -{ - - /* if (c2) c1 &= 0x7f; assertion */ - - if (c2 == JIS_X_0201_1976_K && (c1 == 0x20 || c1 == 0x7D || c1 == 0x7E)) { - (*o_zconv)(c2,c1); - return; - } - - if (x0201_f) { - if (z_prev2 == JIS_X_0201_1976_K) { - if (c2 == JIS_X_0201_1976_K) { - if (c1 == (0xde&0x7f)) { /* $BByE@(B */ - z_prev2 = 0; - (*o_zconv)(dv[(z_prev1-SP)*2], dv[(z_prev1-SP)*2+1]); - return; - } else if (c1 == (0xdf&0x7f) && ev[(z_prev1-SP)*2]) { /* $BH>ByE@(B */ - z_prev2 = 0; - (*o_zconv)(ev[(z_prev1-SP)*2], ev[(z_prev1-SP)*2+1]); - return; - } else if (x0213_f && c1 == (0xdf&0x7f) && ev_x0213[(z_prev1-SP)*2]) { /* $BH>ByE@(B */ - z_prev2 = 0; - (*o_zconv)(ev_x0213[(z_prev1-SP)*2], ev_x0213[(z_prev1-SP)*2+1]); - return; - } - } - z_prev2 = 0; - (*o_zconv)(cv[(z_prev1-SP)*2], cv[(z_prev1-SP)*2+1]); - } - if (c2 == JIS_X_0201_1976_K) { - if (dv[(c1-SP)*2] || ev[(c1-SP)*2] || (x0213_f && ev_x0213[(c1-SP)*2])) { - /* wait for $BByE@(B or $BH>ByE@(B */ - z_prev1 = c1; - z_prev2 = c2; - return; - } else { - (*o_zconv)(cv[(c1-SP)*2], cv[(c1-SP)*2+1]); - return; - } - } - } - - if (c2 == EOF) { - (*o_zconv)(c2, c1); - return; - } - - if (alpha_f&1 && c2 == 0x23) { - /* JISX0208 Alphabet */ - c2 = 0; - } else if (c2 == 0x21) { - /* JISX0208 Kigou */ - if (0x21==c1) { - if (alpha_f&2) { - c2 = 0; - c1 = SP; - } else if (alpha_f&4) { - (*o_zconv)(0, SP); - (*o_zconv)(0, SP); - return; - } - } else if (alpha_f&1 && 0x20': entity = ">"; break; - case '<': entity = "<"; break; - case '\"': entity = """; break; - case '&': entity = "&"; break; - } - if (entity){ - while (*entity) (*o_zconv)(0, *entity++); - return; - } - } - - if (alpha_f & 16) { - /* JIS X 0208 Katakana to JIS X 0201 Katakana */ - if (c2 == 0x21) { - nkf_char c = 0; - switch (c1) { - case 0x23: - /* U+3002 (0x8142) Ideographic Full Stop -> U+FF61 (0xA1) Halfwidth Ideographic Full Stop */ - c = 0xA1; - break; - case 0x56: - /* U+300C (0x8175) Left Corner Bracket -> U+FF62 (0xA2) Halfwidth Left Corner Bracket */ - c = 0xA2; - break; - case 0x57: - /* U+300D (0x8176) Right Corner Bracket -> U+FF63 (0xA3) Halfwidth Right Corner Bracket */ - c = 0xA3; - break; - case 0x22: - /* U+3001 (0x8141) Ideographic Comma -> U+FF64 (0xA4) Halfwidth Ideographic Comma */ - c = 0xA4; - break; - case 0x26: - /* U+30FB (0x8145) Katakana Middle Dot -> U+FF65 (0xA5) Halfwidth Katakana Middle Dot */ - c = 0xA5; - break; - case 0x3C: - /* U+30FC (0x815B) Katakana-Hiragana Prolonged Sound Mark -> U+FF70 (0xB0) Halfwidth Katakana-Hiragana Prolonged Sound Mark */ - c = 0xB0; - break; - case 0x2B: - /* U+309B (0x814A) Katakana-Hiragana Voiced Sound Mark -> U+FF9E (0xDE) Halfwidth Katakana Voiced Sound Mark */ - c = 0xDE; - break; - case 0x2C: - /* U+309C (0x814B) Katakana-Hiragana Semi-Voiced Sound Mark -> U+FF9F (0xDF) Halfwidth Katakana Semi-Voiced Sound Mark */ - c = 0xDF; - break; - } - if (c) { - (*o_zconv)(JIS_X_0201_1976_K, c); - return; - } - } else if (c2 == 0x25) { - /* JISX0208 Katakana */ - static const int fullwidth_to_halfwidth[] = - { - 0x0000, 0x2700, 0x3100, 0x2800, 0x3200, 0x2900, 0x3300, 0x2A00, - 0x3400, 0x2B00, 0x3500, 0x3600, 0x365E, 0x3700, 0x375E, 0x3800, - 0x385E, 0x3900, 0x395E, 0x3A00, 0x3A5E, 0x3B00, 0x3B5E, 0x3C00, - 0x3C5E, 0x3D00, 0x3D5E, 0x3E00, 0x3E5E, 0x3F00, 0x3F5E, 0x4000, - 0x405E, 0x4100, 0x415E, 0x2F00, 0x4200, 0x425E, 0x4300, 0x435E, - 0x4400, 0x445E, 0x4500, 0x4600, 0x4700, 0x4800, 0x4900, 0x4A00, - 0x4A5E, 0x4A5F, 0x4B00, 0x4B5E, 0x4B5F, 0x4C00, 0x4C5E, 0x4C5F, - 0x4D00, 0x4D5E, 0x4D5F, 0x4E00, 0x4E5E, 0x4E5F, 0x4F00, 0x5000, - 0x5100, 0x5200, 0x5300, 0x2C00, 0x5400, 0x2D00, 0x5500, 0x2E00, - 0x5600, 0x5700, 0x5800, 0x5900, 0x5A00, 0x5B00, 0x0000, 0x5C00, - 0x0000, 0x0000, 0x2600, 0x5D00, 0x335E, 0x0000, 0x0000, 0x365F, - 0x375F, 0x385F, 0x395F, 0x3A5F, 0x3E5F, 0x425F, 0x445F, 0x0000 - }; - if (fullwidth_to_halfwidth[c1-0x20]){ - c2 = fullwidth_to_halfwidth[c1-0x20]; - (*o_zconv)(JIS_X_0201_1976_K, c2>>8); - if (c2 & 0xFF) { - (*o_zconv)(JIS_X_0201_1976_K, c2&0xFF); - } - return; - } - } else if (c2 == 0 && nkf_char_unicode_p(c1) && - ((c1&VALUE_MASK) == 0x3099 || (c1&VALUE_MASK) == 0x309A)) { /* $B9g@.MQByE@!&H>ByE@(B */ - (*o_zconv)(JIS_X_0201_1976_K, 0x5E + (c1&VALUE_MASK) - 0x3099); - return; - } - } - (*o_zconv)(c2,c1); -} - - -#define rot13(c) ( \ - ( c < 'A') ? c: \ - (c <= 'M') ? (c + 13): \ - (c <= 'Z') ? (c - 13): \ - (c < 'a') ? (c): \ - (c <= 'm') ? (c + 13): \ - (c <= 'z') ? (c - 13): \ - (c) \ - ) - -#define rot47(c) ( \ - ( c < '!') ? c: \ - ( c <= 'O') ? (c + 47) : \ - ( c <= '~') ? (c - 47) : \ - c \ - ) - -static void -rot_conv(nkf_char c2, nkf_char c1) -{ - if (c2 == 0 || c2 == JIS_X_0201_1976_K || c2 == ISO_8859_1) { - c1 = rot13(c1); - } else if (c2) { - c1 = rot47(c1); - c2 = rot47(c2); - } - (*o_rot_conv)(c2,c1); -} - -static void -hira_conv(nkf_char c2, nkf_char c1) -{ - if (hira_f & 1) { - if (c2 == 0x25) { - if (0x20 < c1 && c1 < 0x74) { - c2 = 0x24; - (*o_hira_conv)(c2,c1); - return; - } else if (c1 == 0x74 && nkf_enc_unicode_p(output_encoding)) { - c2 = 0; - c1 = nkf_char_unicode_new(0x3094); - (*o_hira_conv)(c2,c1); - return; - } - } else if (c2 == 0x21 && (c1 == 0x33 || c1 == 0x34)) { - c1 += 2; - (*o_hira_conv)(c2,c1); - return; - } - } - if (hira_f & 2) { - if (c2 == 0 && c1 == nkf_char_unicode_new(0x3094)) { - c2 = 0x25; - c1 = 0x74; - } else if (c2 == 0x24 && 0x20 < c1 && c1 < 0x74) { - c2 = 0x25; - } else if (c2 == 0x21 && (c1 == 0x35 || c1 == 0x36)) { - c1 -= 2; - } - } - (*o_hira_conv)(c2,c1); -} - - -static void -iso2022jp_check_conv(nkf_char c2, nkf_char c1) -{ -#define RANGE_NUM_MAX 18 - static const nkf_char range[RANGE_NUM_MAX][2] = { - {0x222f, 0x2239,}, - {0x2242, 0x2249,}, - {0x2251, 0x225b,}, - {0x226b, 0x2271,}, - {0x227a, 0x227d,}, - {0x2321, 0x232f,}, - {0x233a, 0x2340,}, - {0x235b, 0x2360,}, - {0x237b, 0x237e,}, - {0x2474, 0x247e,}, - {0x2577, 0x257e,}, - {0x2639, 0x2640,}, - {0x2659, 0x267e,}, - {0x2742, 0x2750,}, - {0x2772, 0x277e,}, - {0x2841, 0x287e,}, - {0x4f54, 0x4f7e,}, - {0x7425, 0x747e}, - }; - nkf_char i; - nkf_char start, end, c; - - if(c2 >= 0x00 && c2 <= 0x20 && c1 >= 0x7f && c1 <= 0xff) { - c2 = GETA1; - c1 = GETA2; - } - if((c2 >= 0x29 && c2 <= 0x2f) || (c2 >= 0x75 && c2 <= 0x7e)) { - c2 = GETA1; - c1 = GETA2; - } - - for (i = 0; i < RANGE_NUM_MAX; i++) { - start = range[i][0]; - end = range[i][1]; - c = (c2 << 8) + c1; - if (c >= start && c <= end) { - c2 = GETA1; - c1 = GETA2; - } - } - (*o_iso2022jp_check_conv)(c2,c1); -} - - -/* This converts =?ISO-2022-JP?B?HOGE HOGE?= */ - -static const unsigned char *mime_pattern[] = { - (const unsigned char *)"\075?EUC-JP?B?", - (const unsigned char *)"\075?SHIFT_JIS?B?", - (const unsigned char *)"\075?ISO-8859-1?Q?", - (const unsigned char *)"\075?ISO-8859-1?B?", - (const unsigned char *)"\075?ISO-2022-JP?B?", - (const unsigned char *)"\075?ISO-2022-JP?B?", - (const unsigned char *)"\075?ISO-2022-JP?Q?", -#if defined(UTF8_INPUT_ENABLE) - (const unsigned char *)"\075?UTF-8?B?", - (const unsigned char *)"\075?UTF-8?Q?", -#endif - (const unsigned char *)"\075?US-ASCII?Q?", - NULL -}; - - -/* $B3:Ev$9$k%3!<%I$NM%@hEY$r>e$2$k$?$a$NL\0u(B */ -static nkf_char (*const mime_priority_func[])(nkf_char c2, nkf_char c1, nkf_char c0) = { - e_iconv, s_iconv, 0, 0, 0, 0, 0, -#if defined(UTF8_INPUT_ENABLE) - w_iconv, w_iconv, -#endif - 0, -}; - -static const nkf_char mime_encode[] = { - EUC_JP, SHIFT_JIS, ISO_8859_1, ISO_8859_1, JIS_X_0208, JIS_X_0201_1976_K, JIS_X_0201_1976_K, -#if defined(UTF8_INPUT_ENABLE) - UTF_8, UTF_8, -#endif - ASCII, - 0 -}; - -static const nkf_char mime_encode_method[] = { - 'B', 'B','Q', 'B', 'B', 'B', 'Q', -#if defined(UTF8_INPUT_ENABLE) - 'B', 'Q', -#endif - 'Q', - 0 -}; - - -/* MIME preprocessor fifo */ - -#define MIME_BUF_SIZE (1024) /* 2^n ring buffer */ -#define MIME_BUF_MASK (MIME_BUF_SIZE-1) -#define mime_input_buf(n) mime_input_state.buf[(n)&MIME_BUF_MASK] -static struct { - unsigned char buf[MIME_BUF_SIZE]; - unsigned int top; - unsigned int last; /* decoded */ - unsigned int input; /* undecoded */ -} mime_input_state; -static nkf_char (*mime_iconv_back)(nkf_char c2,nkf_char c1,nkf_char c0) = NULL; - -#define MAXRECOVER 20 - -static void -mime_input_buf_unshift(nkf_char c) -{ - mime_input_buf(--mime_input_state.top) = (unsigned char)c; -} - -static nkf_char -mime_ungetc(nkf_char c, ARG_UNUSED FILE *f) -{ - mime_input_buf_unshift(c); - return c; -} - -static nkf_char -mime_ungetc_buf(nkf_char c, FILE *f) -{ - if (mimebuf_f) - (*i_mungetc_buf)(c,f); - else - mime_input_buf(--mime_input_state.input) = (unsigned char)c; - return c; -} - -static nkf_char -mime_getc_buf(FILE *f) -{ - /* we don't keep eof of mime_input_buf, because it contains ?= as - a terminator. It was checked in mime_integrity. */ - return ((mimebuf_f)? - (*i_mgetc_buf)(f):mime_input_buf(mime_input_state.input++)); -} - -static void -switch_mime_getc(void) -{ - if (i_getc!=mime_getc) { - i_mgetc = i_getc; i_getc = mime_getc; - i_mungetc = i_ungetc; i_ungetc = mime_ungetc; - if(mime_f==STRICT_MIME) { - i_mgetc_buf = i_mgetc; i_mgetc = mime_getc_buf; - i_mungetc_buf = i_mungetc; i_mungetc = mime_ungetc_buf; - } - } -} - -static void -unswitch_mime_getc(void) -{ - if(mime_f==STRICT_MIME) { - i_mgetc = i_mgetc_buf; - i_mungetc = i_mungetc_buf; - } - i_getc = i_mgetc; - i_ungetc = i_mungetc; - if(mime_iconv_back)set_iconv(FALSE, mime_iconv_back); - mime_iconv_back = NULL; -} - -static nkf_char -mime_integrity(FILE *f, const unsigned char *p) -{ - nkf_char c,d; - unsigned int q; - /* In buffered mode, read until =? or NL or buffer full - */ - mime_input_state.input = mime_input_state.top; - mime_input_state.last = mime_input_state.top; - - while(*p) mime_input_buf(mime_input_state.input++) = *p++; - d = 0; - q = mime_input_state.input; - while((c=(*i_getc)(f))!=EOF) { - if (((mime_input_state.input-mime_input_state.top)&MIME_BUF_MASK)==0) { - break; /* buffer full */ - } - if (c=='=' && d=='?') { - /* checked. skip header, start decode */ - mime_input_buf(mime_input_state.input++) = (unsigned char)c; - /* mime_last_input = mime_input_state.input; */ - mime_input_state.input = q; - switch_mime_getc(); - return 1; - } - if (!( (c=='+'||c=='/'|| c=='=' || c=='?' || is_alnum(c)))) - break; - /* Should we check length mod 4? */ - mime_input_buf(mime_input_state.input++) = (unsigned char)c; - d=c; - } - /* In case of Incomplete MIME, no MIME decode */ - mime_input_buf(mime_input_state.input++) = (unsigned char)c; - mime_input_state.last = mime_input_state.input; /* point undecoded buffer */ - mime_decode_mode = 1; /* no decode on mime_input_buf last in mime_getc */ - switch_mime_getc(); /* anyway we need buffered getc */ - return 1; -} - -static nkf_char -mime_begin_strict(FILE *f) -{ - nkf_char c1 = 0; - int i,j,k; - const unsigned char *p,*q; - nkf_char r[MAXRECOVER]; /* recovery buffer, max mime pattern length */ - - mime_decode_mode = FALSE; - /* =? has been checked */ - j = 0; - p = mime_pattern[j]; - r[0]='='; r[1]='?'; - - for(i=2;p[i]>SP;i++) { /* start at =? */ - if (((r[i] = c1 = (*i_getc)(f))==EOF) || nkf_toupper(c1) != p[i]) { - /* pattern fails, try next one */ - q = p; - while (mime_pattern[++j]) { - p = mime_pattern[j]; - for(k=2;k i */ - if (p[k]!=q[k]) break; - if (k==i && nkf_toupper(c1)==p[k]) break; - } - p = mime_pattern[j]; - if (p) continue; /* found next one, continue */ - /* all fails, output from recovery buffer */ - (*i_ungetc)(c1,f); - for(j=0;jscore & (SCORE_DEPEND|SCORE_CP932)) - input_codename = "CP932"; - } else if (strcmp(input_codename, "EUC-JP") == 0) { - if (p->score & SCORE_X0213) - input_codename = "EUC-JIS-2004"; - else if (p->score & (SCORE_X0212)) - input_codename = "EUCJP-MS"; - else if (p->score & (SCORE_DEPEND|SCORE_CP932)) - input_codename = "CP51932"; - } else if (strcmp(input_codename, "ISO-2022-JP") == 0) { - if (p->score & (SCORE_KANA)) - input_codename = "CP50221"; - else if (p->score & (SCORE_DEPEND|SCORE_CP932)) - input_codename = "CP50220"; - } - } - return input_codename; -} - -#if !defined(PERL_XS) && !defined(WIN32DLL) -static void -print_guessed_code(char *filename) -{ - if (filename != NULL) printf("%s: ", filename); - if (input_codename && !*input_codename) { - printf("BINARY\n"); - } else { - input_codename = get_guessed_code(); - if (guess_f == 1) { - printf("%s\n", input_codename); - } else { - printf("%s%s%s%s\n", - input_codename, - iconv != w_iconv16 && iconv != w_iconv32 ? "" : - input_endian == ENDIAN_LITTLE ? " LE" : - input_endian == ENDIAN_BIG ? " BE" : - "[BUG]", - input_bom_f ? " (BOM)" : "", - input_eol == CR ? " (CR)" : - input_eol == LF ? " (LF)" : - input_eol == CRLF ? " (CRLF)" : - input_eol == EOF ? " (MIXED NL)" : - ""); - } - } -} -#endif /*WIN32DLL*/ - -#ifdef INPUT_OPTION - -static nkf_char -hex_getc(nkf_char ch, FILE *f, nkf_char (*g)(FILE *f), nkf_char (*u)(nkf_char c, FILE *f)) -{ - nkf_char c1, c2, c3; - c1 = (*g)(f); - if (c1 != ch){ - return c1; - } - c2 = (*g)(f); - if (!nkf_isxdigit(c2)){ - (*u)(c2, f); - return c1; - } - c3 = (*g)(f); - if (!nkf_isxdigit(c3)){ - (*u)(c2, f); - (*u)(c3, f); - return c1; - } - return (hex2bin(c2) << 4) | hex2bin(c3); -} - -static nkf_char -cap_getc(FILE *f) -{ - return hex_getc(':', f, i_cgetc, i_cungetc); -} - -static nkf_char -cap_ungetc(nkf_char c, FILE *f) -{ - return (*i_cungetc)(c, f); -} - -static nkf_char -url_getc(FILE *f) -{ - return hex_getc('%', f, i_ugetc, i_uungetc); -} - -static nkf_char -url_ungetc(nkf_char c, FILE *f) -{ - return (*i_uungetc)(c, f); -} -#endif - -#ifdef NUMCHAR_OPTION -static nkf_char -numchar_getc(FILE *f) -{ - nkf_char (*g)(FILE *) = i_ngetc; - nkf_char (*u)(nkf_char c ,FILE *f) = i_nungetc; - int i = 0, j; - nkf_char buf[12]; - nkf_char c = -1; - - buf[i] = (*g)(f); - if (buf[i] == '&'){ - buf[++i] = (*g)(f); - if (buf[i] == '#'){ - c = 0; - buf[++i] = (*g)(f); - if (buf[i] == 'x' || buf[i] == 'X'){ - for (j = 0; j < 7; j++){ - buf[++i] = (*g)(f); - if (!nkf_isxdigit(buf[i])){ - if (buf[i] != ';'){ - c = -1; - } - break; - } - c <<= 4; - c |= hex2bin(buf[i]); - } - }else{ - for (j = 0; j < 8; j++){ - if (j){ - buf[++i] = (*g)(f); - } - if (!nkf_isdigit(buf[i])){ - if (buf[i] != ';'){ - c = -1; - } - break; - } - c *= 10; - c += hex2bin(buf[i]); - } - } - } - } - if (c != -1){ - return nkf_char_unicode_new(c); - } - while (i > 0){ - (*u)(buf[i], f); - --i; - } - return buf[0]; -} - -static nkf_char -numchar_ungetc(nkf_char c, FILE *f) -{ - return (*i_nungetc)(c, f); -} -#endif - -#ifdef UNICODE_NORMALIZATION - -static nkf_char -nfc_getc(FILE *f) -{ - nkf_char (*g)(FILE *f) = i_nfc_getc; - nkf_char (*u)(nkf_char c ,FILE *f) = i_nfc_ungetc; - nkf_buf_t *buf = nkf_state->nfc_buf; - const unsigned char *array; - int lower=0, upper=NORMALIZATION_TABLE_LENGTH-1; - nkf_char c = (*g)(f); - - if (c == EOF || c > 0xFF || (c & 0xc0) == 0x80) return c; - - nkf_buf_push(buf, c); - do { - while (lower <= upper) { - int mid = (lower+upper) / 2; - int len; - array = normalization_table[mid].nfd; - for (len=0; len < NORMALIZATION_TABLE_NFD_LENGTH && array[len]; len++) { - if (len >= nkf_buf_length(buf)) { - c = (*g)(f); - if (c == EOF) { - len = 0; - lower = 1, upper = 0; - break; - } - nkf_buf_push(buf, c); - } - if (array[len] != nkf_buf_at(buf, len)) { - if (array[len] < nkf_buf_at(buf, len)) lower = mid + 1; - else upper = mid - 1; - len = 0; - break; - } - } - if (len > 0) { - int i; - array = normalization_table[mid].nfc; - nkf_buf_clear(buf); - for (i=0; i < NORMALIZATION_TABLE_NFC_LENGTH && array[i]; i++) - nkf_buf_push(buf, array[i]); - break; - } - } - } while (lower <= upper); - - while (nkf_buf_length(buf) > 1) (*u)(nkf_buf_pop(buf), f); - c = nkf_buf_pop(buf); - - return c; -} - -static nkf_char -nfc_ungetc(nkf_char c, FILE *f) -{ - return (*i_nfc_ungetc)(c, f); -} -#endif /* UNICODE_NORMALIZATION */ - - -static nkf_char -base64decode(nkf_char c) -{ - int i; - if (c > '@') { - if (c < '[') { - i = c - 'A'; /* A..Z 0-25 */ - } else if (c == '_') { - i = '?' /* 63 */ ; /* _ 63 */ - } else { - i = c - 'G' /* - 'a' + 26 */ ; /* a..z 26-51 */ - } - } else if (c > '/') { - i = c - '0' + '4' /* - '0' + 52 */ ; /* 0..9 52-61 */ - } else if (c == '+' || c == '-') { - i = '>' /* 62 */ ; /* + and - 62 */ - } else { - i = '?' /* 63 */ ; /* / 63 */ - } - return (i); -} - -static nkf_char -mime_getc(FILE *f) -{ - nkf_char c1, c2, c3, c4, cc; - nkf_char t1, t2, t3, t4, mode, exit_mode; - nkf_char lwsp_count; - char *lwsp_buf; - char *lwsp_buf_new; - nkf_char lwsp_size = 128; - - if (mime_input_state.top != mime_input_state.last) { /* Something is in FIFO */ - return mime_input_buf(mime_input_state.top++); - } - if (mime_decode_mode==1 ||mime_decode_mode==FALSE) { - mime_decode_mode=FALSE; - unswitch_mime_getc(); - return (*i_getc)(f); - } - - if (mimebuf_f == FIXED_MIME) - exit_mode = mime_decode_mode; - else - exit_mode = FALSE; - if (mime_decode_mode == 'Q') { - if ((c1 = (*i_mgetc)(f)) == EOF) return (EOF); - restart_mime_q: - if (c1=='_' && mimebuf_f != FIXED_MIME) return SP; - if (c1<=SP || DEL<=c1) { - mime_decode_mode = exit_mode; /* prepare for quit */ - return c1; - } - if (c1!='=' && (c1!='?' || mimebuf_f == FIXED_MIME)) { - return c1; - } - - mime_decode_mode = exit_mode; /* prepare for quit */ - if ((c2 = (*i_mgetc)(f)) == EOF) return (EOF); - if (c1=='?'&&c2=='=' && mimebuf_f != FIXED_MIME) { - /* end Q encoding */ - input_mode = exit_mode; - lwsp_count = 0; - lwsp_buf = nkf_xmalloc((lwsp_size+5)*sizeof(char)); - while ((c1=(*i_getc)(f))!=EOF) { - switch (c1) { - case LF: - case CR: - if (c1==LF) { - if ((c1=(*i_getc)(f))!=EOF && nkf_isblank(c1)) { - i_ungetc(SP,f); - continue; - } else { - i_ungetc(c1,f); - } - c1 = LF; - } else { - if ((c1=(*i_getc)(f))!=EOF && c1 == LF) { - if ((c1=(*i_getc)(f))!=EOF && nkf_isblank(c1)) { - i_ungetc(SP,f); - continue; - } else { - i_ungetc(c1,f); - } - i_ungetc(LF,f); - } else { - i_ungetc(c1,f); - } - c1 = CR; - } - break; - case SP: - case TAB: - lwsp_buf[lwsp_count] = (unsigned char)c1; - if (lwsp_count++>lwsp_size){ - lwsp_size <<= 1; - lwsp_buf_new = nkf_xrealloc(lwsp_buf, (lwsp_size+5)*sizeof(char)); - lwsp_buf = lwsp_buf_new; - } - continue; - } - break; - } - if (lwsp_count > 0 && (c1 != '=' || (lwsp_buf[lwsp_count-1] != SP && lwsp_buf[lwsp_count-1] != TAB))) { - i_ungetc(c1,f); - for(lwsp_count--;lwsp_count>0;lwsp_count--) - i_ungetc(lwsp_buf[lwsp_count],f); - c1 = lwsp_buf[0]; - } - nkf_xfree(lwsp_buf); - return c1; - } - if (c1=='='&&c20;lwsp_count--) - i_ungetc(lwsp_buf[lwsp_count],f); - c1 = lwsp_buf[0]; - } - nkf_xfree(lwsp_buf); - return c1; - } - mime_c3_retry: - if ((c3 = (*i_mgetc)(f))<=SP) { - if (c3==EOF) - return (EOF); - if (mime_f != STRICT_MIME) goto mime_c3_retry; - if (mimebuf_f!=FIXED_MIME) input_mode = ASCII; - return c3; - } - mime_c4_retry: - if ((c4 = (*i_mgetc)(f))<=SP) { - if (c4==EOF) - return (EOF); - if (mime_f != STRICT_MIME) goto mime_c4_retry; - if (mimebuf_f!=FIXED_MIME) input_mode = ASCII; - return c4; - } - - mime_decode_mode = mode; /* still in MIME sigh... */ - - /* BASE 64 decoding */ - - t1 = 0x3f & base64decode(c1); - t2 = 0x3f & base64decode(c2); - t3 = 0x3f & base64decode(c3); - t4 = 0x3f & base64decode(c4); - cc = ((t1 << 2) & 0x0fc) | ((t2 >> 4) & 0x03); - if (c2 != '=') { - mime_input_buf(mime_input_state.last++) = (unsigned char)cc; - cc = ((t2 << 4) & 0x0f0) | ((t3 >> 2) & 0x0f); - if (c3 != '=') { - mime_input_buf(mime_input_state.last++) = (unsigned char)cc; - cc = ((t3 << 6) & 0x0c0) | (t4 & 0x3f); - if (c4 != '=') - mime_input_buf(mime_input_state.last++) = (unsigned char)cc; - } - } else { - return c1; - } - return mime_input_buf(mime_input_state.top++); -} - -static const char basis_64[] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - -#define MIMEOUT_BUF_LENGTH 74 -static struct { - unsigned char buf[MIMEOUT_BUF_LENGTH+1]; - int count; -} mimeout_state; - -/*nkf_char mime_lastchar2, mime_lastchar1;*/ - -static void -open_mime(nkf_char mode) -{ - const unsigned char *p; - int i; - int j; - p = mime_pattern[0]; - for(i=0;mime_pattern[i];i++) { - if (mode == mime_encode[i]) { - p = mime_pattern[i]; - break; - } - } - mimeout_mode = mime_encode_method[i]; - i = 0; - if (base64_count>45) { - if (mimeout_state.count>0 && nkf_isblank(mimeout_state.buf[i])){ - (*o_mputc)(mimeout_state.buf[i]); - i++; - } - put_newline(o_mputc); - (*o_mputc)(SP); - base64_count = 1; - if (mimeout_state.count>0 && nkf_isspace(mimeout_state.buf[i])) { - i++; - } - } - for (;i 0){ - if (c2 == EOF){ - if (base64_count + mimeout_state.count/3*4> 73){ - (*o_base64conv)(EOF,0); - oconv_newline(o_base64conv); - (*o_base64conv)(0,SP); - base64_count = 1; - } - } else { - if ((c2 != 0 || c1 > DEL) && base64_count + mimeout_state.count/3*4> 66) { - (*o_base64conv)(EOF,0); - oconv_newline(o_base64conv); - (*o_base64conv)(0,SP); - base64_count = 1; - mimeout_mode = -1; - } - } - } else if (c2) { - if (c2 != EOF && base64_count + mimeout_state.count/3*4> 60) { - mimeout_mode = (output_mode==ASCII ||output_mode == ISO_8859_1) ? 'Q' : 'B'; - open_mime(output_mode); - (*o_base64conv)(EOF,0); - oconv_newline(o_base64conv); - (*o_base64conv)(0,SP); - base64_count = 1; - mimeout_mode = -1; - } - } -} - -static void -close_mime(void) -{ - (*o_mputc)('?'); - (*o_mputc)('='); - base64_count += 2; - mimeout_mode = 0; -} - -static void -eof_mime(void) -{ - switch(mimeout_mode) { - case 'Q': - case 'B': - break; - case 2: - (*o_mputc)(basis_64[((nkf_state->mimeout_state & 0x3)<< 4)]); - (*o_mputc)('='); - (*o_mputc)('='); - base64_count += 3; - break; - case 1: - (*o_mputc)(basis_64[((nkf_state->mimeout_state & 0xF) << 2)]); - (*o_mputc)('='); - base64_count += 2; - break; - } - if (mimeout_mode > 0) { - if (mimeout_f!=FIXED_MIME) { - close_mime(); - } else if (mimeout_mode != 'Q') - mimeout_mode = 'B'; - } -} - -static void -mimeout_addchar(nkf_char c) -{ - switch(mimeout_mode) { - case 'Q': - if (c==CR||c==LF) { - (*o_mputc)(c); - base64_count = 0; - } else if(!nkf_isalnum(c)) { - (*o_mputc)('='); - (*o_mputc)(bin2hex(((c>>4)&0xf))); - (*o_mputc)(bin2hex((c&0xf))); - base64_count += 3; - } else { - (*o_mputc)(c); - base64_count++; - } - break; - case 'B': - nkf_state->mimeout_state=c; - (*o_mputc)(basis_64[c>>2]); - mimeout_mode=2; - base64_count ++; - break; - case 2: - (*o_mputc)(basis_64[((nkf_state->mimeout_state & 0x3)<< 4) | ((c & 0xF0) >> 4)]); - nkf_state->mimeout_state=c; - mimeout_mode=1; - base64_count ++; - break; - case 1: - (*o_mputc)(basis_64[((nkf_state->mimeout_state & 0xF) << 2) | ((c & 0xC0) >>6)]); - (*o_mputc)(basis_64[c & 0x3F]); - mimeout_mode='B'; - base64_count += 2; - break; - default: - (*o_mputc)(c); - base64_count++; - break; - } -} - -static void -mime_putc(nkf_char c) -{ - int i, j; - nkf_char lastchar; - - if (mimeout_f == FIXED_MIME){ - if (mimeout_mode == 'Q'){ - if (base64_count > 71){ - if (c!=CR && c!=LF) { - (*o_mputc)('='); - put_newline(o_mputc); - } - base64_count = 0; - } - }else{ - if (base64_count > 71){ - eof_mime(); - put_newline(o_mputc); - base64_count = 0; - } - if (c == EOF) { /* c==EOF */ - eof_mime(); - } - } - if (c != EOF) { /* c==EOF */ - mimeout_addchar(c); - } - return; - } - - /* mimeout_f != FIXED_MIME */ - - if (c == EOF) { /* c==EOF */ - if (mimeout_mode == -1 && mimeout_state.count > 1) open_mime(output_mode); - j = mimeout_state.count; - mimeout_state.count = 0; - i = 0; - if (mimeout_mode > 0) { - if (!nkf_isblank(mimeout_state.buf[j-1])) { - for (;i 0){ - lastchar = mimeout_state.buf[mimeout_state.count - 1]; - }else{ - lastchar = -1; - } - - if (mimeout_mode=='Q') { - if (c <= DEL && (output_mode==ASCII ||output_mode == ISO_8859_1)) { - if (c == CR || c == LF) { - close_mime(); - (*o_mputc)(c); - base64_count = 0; - return; - } else if (c <= SP) { - close_mime(); - if (base64_count > 70) { - put_newline(o_mputc); - base64_count = 0; - } - if (!nkf_isblank(c)) { - (*o_mputc)(SP); - base64_count++; - } - } else { - if (base64_count > 70) { - close_mime(); - put_newline(o_mputc); - (*o_mputc)(SP); - base64_count = 1; - open_mime(output_mode); - } - if (!nkf_noescape_mime(c)) { - mimeout_addchar(c); - return; - } - } - if (c != 0x1B) { - (*o_mputc)(c); - base64_count++; - return; - } - } - } - - if (mimeout_mode <= 0) { - if (c <= DEL && (output_mode==ASCII || output_mode == ISO_8859_1 || - output_mode == UTF_8)) { - if (nkf_isspace(c)) { - int flag = 0; - if (mimeout_mode == -1) { - flag = 1; - } - if (c==CR || c==LF) { - if (flag) { - open_mime(output_mode); - output_mode = 0; - } else { - base64_count = 0; - } - } - for (i=0;i 1 - && base64_count + mimeout_state.count > 76 - && mimeout_state.buf[0] != CR && mimeout_state.buf[0] != LF){ - static const char *str = "boundary=\""; - static int len = 10; - i = 0; - - for (; i < mimeout_state.count - len; ++i) { - if (!strncmp((char *)(mimeout_state.buf+i), str, len)) { - i += len - 2; - break; - } - } - - if (i == 0 || i == mimeout_state.count - len) { - put_newline(o_mputc); - base64_count = 0; - if (!nkf_isspace(mimeout_state.buf[0])){ - (*o_mputc)(SP); - base64_count++; - } - } - else { - int j; - for (j = 0; j <= i; ++j) { - (*o_mputc)(mimeout_state.buf[j]); - } - put_newline(o_mputc); - base64_count = 1; - for (; j <= mimeout_state.count; ++j) { - mimeout_state.buf[j - i] = mimeout_state.buf[j]; - } - mimeout_state.count -= i; - } - } - mimeout_state.buf[mimeout_state.count++] = (char)c; - if (mimeout_state.count>MIMEOUT_BUF_LENGTH) { - open_mime(output_mode); - } - } - return; - }else{ - if (lastchar==CR || lastchar == LF){ - for (i=0;iMIMEOUT_BUF_LENGTH) { - eof_mime(); - for (j=0;j0 && SPMIMEOUT_BUF_LENGTH) { - j = mimeout_state.count; - mimeout_state.count = 0; - for (i=0;i0) { - j = mimeout_state.count; - mimeout_state.count = 0; - for (i=0;iinput_buffer_size = IOBUF_SIZE; - converter->input_buffer = nkf_xmalloc(converter->input_buffer_size); - converter->output_buffer_size = IOBUF_SIZE * 2; - converter->output_buffer = nkf_xmalloc(converter->output_buffer_size); - converter->cd = iconv_open(tocode, fromcode); - if (converter->cd == (iconv_t)-1) - { - switch (errno) { - case EINVAL: - perror(fprintf("iconv doesn't support %s to %s conversion.", fromcode, tocode)); - return -1; - default: - perror("can't iconv_open"); - } - } -} - -static size_t -nkf_iconv_convert(nkf_iconv_t *converter, FILE *input) -{ - size_t invalid = (size_t)0; - char *input_buffer = converter->input_buffer; - size_t input_length = (size_t)0; - char *output_buffer = converter->output_buffer; - size_t output_length = converter->output_buffer_size; - int c; - - do { - if (c != EOF) { - while ((c = (*i_getc)(f)) != EOF) { - input_buffer[input_length++] = c; - if (input_length < converter->input_buffer_size) break; - } - } - - size_t ret = iconv(converter->cd, &input_buffer, &input_length, &output_buffer, &output_length); - while (output_length-- > 0) { - (*o_putc)(output_buffer[converter->output_buffer_size-output_length]); - } - if (ret == (size_t) - 1) { - switch (errno) { - case EINVAL: - if (input_buffer != converter->input_buffer) - memmove(converter->input_buffer, input_buffer, input_length); - break; - case E2BIG: - converter->output_buffer_size *= 2; - output_buffer = realloc(converter->outbuf, converter->output_buffer_size); - if (output_buffer == NULL) { - perror("can't realloc"); - return -1; - } - converter->output_buffer = output_buffer; - break; - default: - perror("can't iconv"); - return -1; - } - } else { - invalid += ret; - } - } while (1); - - return invalid; -} - - -static void -nkf_iconv_close(nkf_iconv_t *convert) -{ - nkf_xfree(converter->inbuf); - nkf_xfree(converter->outbuf); - iconv_close(converter->cd); -} -#endif - - -static void -reinit(void) -{ - { - struct input_code *p = input_code_list; - while (p->name){ - status_reinit(p++); - } - } - unbuf_f = FALSE; - estab_f = FALSE; - nop_f = FALSE; - binmode_f = TRUE; - rot_f = FALSE; - hira_f = FALSE; - alpha_f = FALSE; - mime_f = MIME_DECODE_DEFAULT; - mime_decode_f = FALSE; - mimebuf_f = FALSE; - broken_f = FALSE; - iso8859_f = FALSE; - mimeout_f = FALSE; - x0201_f = NKF_UNSPECIFIED; - iso2022jp_f = FALSE; -#if defined(UTF8_INPUT_ENABLE) || defined(UTF8_OUTPUT_ENABLE) - ms_ucs_map_f = UCS_MAP_ASCII; -#endif -#ifdef UTF8_INPUT_ENABLE - no_cp932ext_f = FALSE; - no_best_fit_chars_f = FALSE; - encode_fallback = NULL; - unicode_subchar = '?'; - input_endian = ENDIAN_BIG; -#endif -#ifdef UTF8_OUTPUT_ENABLE - output_bom_f = FALSE; - output_endian = ENDIAN_BIG; -#endif -#ifdef UNICODE_NORMALIZATION - nfc_f = FALSE; -#endif -#ifdef INPUT_OPTION - cap_f = FALSE; - url_f = FALSE; - numchar_f = FALSE; -#endif -#ifdef CHECK_OPTION - noout_f = FALSE; - debug_f = FALSE; -#endif - guess_f = 0; -#ifdef EXEC_IO - exec_f = 0; -#endif -#ifdef SHIFTJIS_CP932 - cp51932_f = TRUE; - cp932inv_f = TRUE; -#endif -#ifdef X0212_ENABLE - x0212_f = FALSE; - x0213_f = FALSE; -#endif - { - int i; - for (i = 0; i < 256; i++){ - prefix_table[i] = 0; - } - } - hold_count = 0; - mimeout_state.count = 0; - mimeout_mode = 0; - base64_count = 0; - f_line = 0; - f_prev = 0; - fold_preserve_f = FALSE; - fold_f = FALSE; - fold_len = 0; - kanji_intro = DEFAULT_J; - ascii_intro = DEFAULT_R; - fold_margin = FOLD_MARGIN; - o_zconv = no_connection; - o_fconv = no_connection; - o_eol_conv = no_connection; - o_rot_conv = no_connection; - o_hira_conv = no_connection; - o_base64conv = no_connection; - o_iso2022jp_check_conv = no_connection; - o_putc = std_putc; - i_getc = std_getc; - i_ungetc = std_ungetc; - i_bgetc = std_getc; - i_bungetc = std_ungetc; - o_mputc = std_putc; - i_mgetc = std_getc; - i_mungetc = std_ungetc; - i_mgetc_buf = std_getc; - i_mungetc_buf = std_ungetc; - output_mode = ASCII; - input_mode = ASCII; - mime_decode_mode = FALSE; - file_out_f = FALSE; - eolmode_f = 0; - input_eol = 0; - prev_cr = 0; - option_mode = 0; - z_prev2=0,z_prev1=0; -#ifdef CHECK_OPTION - iconv_for_check = 0; -#endif - input_codename = NULL; - input_encoding = NULL; - output_encoding = NULL; - nkf_state_init(); -#ifdef WIN32DLL - reinitdll(); -#endif /*WIN32DLL*/ -} - -static int -module_connection(void) -{ - if (input_encoding) set_input_encoding(input_encoding); - if (!output_encoding) { - output_encoding = nkf_default_encoding(); - } - if (!output_encoding) { - if (noout_f || guess_f) output_encoding = nkf_enc_from_index(ISO_2022_JP); - else return -1; - } - set_output_encoding(output_encoding); - oconv = nkf_enc_to_oconv(output_encoding); - o_putc = std_putc; - if (nkf_enc_unicode_p(output_encoding)) - output_mode = UTF_8; - - if (x0201_f == NKF_UNSPECIFIED) { - x0201_f = X0201_DEFAULT; - } - - /* replace continuation module, from output side */ - - /* output redirection */ -#ifdef CHECK_OPTION - if (noout_f || guess_f){ - o_putc = no_putc; - } -#endif - if (mimeout_f) { - o_mputc = o_putc; - o_putc = mime_putc; - if (mimeout_f == TRUE) { - o_base64conv = oconv; oconv = base64_conv; - } - /* base64_count = 0; */ - } - - if (eolmode_f || guess_f) { - o_eol_conv = oconv; oconv = eol_conv; - } - if (rot_f) { - o_rot_conv = oconv; oconv = rot_conv; - } - if (iso2022jp_f) { - o_iso2022jp_check_conv = oconv; oconv = iso2022jp_check_conv; - } - if (hira_f) { - o_hira_conv = oconv; oconv = hira_conv; - } - if (fold_f) { - o_fconv = oconv; oconv = fold_conv; - f_line = 0; - } - if (alpha_f || x0201_f) { - o_zconv = oconv; oconv = z_conv; - } - - i_getc = std_getc; - i_ungetc = std_ungetc; - /* input redirection */ -#ifdef INPUT_OPTION - if (cap_f){ - i_cgetc = i_getc; i_getc = cap_getc; - i_cungetc = i_ungetc; i_ungetc= cap_ungetc; - } - if (url_f){ - i_ugetc = i_getc; i_getc = url_getc; - i_uungetc = i_ungetc; i_ungetc= url_ungetc; - } -#endif -#ifdef NUMCHAR_OPTION - if (numchar_f){ - i_ngetc = i_getc; i_getc = numchar_getc; - i_nungetc = i_ungetc; i_ungetc= numchar_ungetc; - } -#endif -#ifdef UNICODE_NORMALIZATION - if (nfc_f){ - i_nfc_getc = i_getc; i_getc = nfc_getc; - i_nfc_ungetc = i_ungetc; i_ungetc= nfc_ungetc; - } -#endif - if (mime_f && mimebuf_f==FIXED_MIME) { - i_mgetc = i_getc; i_getc = mime_getc; - i_mungetc = i_ungetc; i_ungetc = mime_ungetc; - } - if (broken_f & 1) { - i_bgetc = i_getc; i_getc = broken_getc; - i_bungetc = i_ungetc; i_ungetc = broken_ungetc; - } - if (input_encoding) { - set_iconv(-TRUE, nkf_enc_to_iconv(input_encoding)); - } else { - set_iconv(FALSE, e_iconv); - } - - { - struct input_code *p = input_code_list; - while (p->name){ - status_reinit(p++); - } - } - return 0; -} - -/* - Conversion main loop. Code detection only. - */ - -#if !defined(PERL_XS) && !defined(WIN32DLL) -static nkf_char -noconvert(FILE *f) -{ - nkf_char c; - - if (nop_f == 2) - module_connection(); - while ((c = (*i_getc)(f)) != EOF) - (*o_putc)(c); - (*o_putc)(EOF); - return 1; -} -#endif - -#define NEXT continue /* no output, get next */ -#define SKIP c2=0;continue /* no output, get next */ -#define MORE c2=c1;continue /* need one more byte */ -#define SEND (void)0 /* output c1 and c2, get next */ -#define LAST break /* end of loop, go closing */ -#define set_input_mode(mode) do { \ - input_mode = mode; \ - shift_mode = 0; \ - set_input_codename("ISO-2022-JP"); \ - debug("ISO-2022-JP"); \ -} while (0) - -static int -kanji_convert(FILE *f) -{ - nkf_char c1=0, c2=0, c3=0, c4=0; - int shift_mode = 0; /* 0, 1, 2, 3 */ - int g2 = 0; - int is_8bit = FALSE; - - if (input_encoding && !nkf_enc_asciicompat(input_encoding)) { - is_8bit = TRUE; - } - - input_mode = ASCII; - output_mode = ASCII; - - if (module_connection() < 0) { -#if !defined(PERL_XS) && !defined(WIN32DLL) - fprintf(stderr, "no output encoding given\n"); -#endif - return -1; - } - check_bom(f); - -#ifdef UTF8_INPUT_ENABLE - if(iconv == w_iconv32){ - while ((c1 = (*i_getc)(f)) != EOF && - (c2 = (*i_getc)(f)) != EOF && - (c3 = (*i_getc)(f)) != EOF && - (c4 = (*i_getc)(f)) != EOF) { - nkf_char c5, c6, c7, c8; - if (nkf_iconv_utf_32(c1, c2, c3, c4) == (size_t)NKF_ICONV_WAIT_COMBINING_CHAR) { - if ((c5 = (*i_getc)(f)) != EOF && - (c6 = (*i_getc)(f)) != EOF && - (c7 = (*i_getc)(f)) != EOF && - (c8 = (*i_getc)(f)) != EOF) { - if (nkf_iconv_utf_32_combine(c1, c2, c3, c4, c5, c6, c7, c8)) { - (*i_ungetc)(c8, f); - (*i_ungetc)(c7, f); - (*i_ungetc)(c6, f); - (*i_ungetc)(c5, f); - nkf_iconv_utf_32_nocombine(c1, c2, c3, c4); - } - } else { - nkf_iconv_utf_32_nocombine(c1, c2, c3, c4); - } - } - } - goto finished; - } - else if (iconv == w_iconv16) { - while ((c1 = (*i_getc)(f)) != EOF && - (c2 = (*i_getc)(f)) != EOF) { - size_t ret = nkf_iconv_utf_16(c1, c2, 0, 0); - if (ret == NKF_ICONV_NEED_TWO_MORE_BYTES && - (c3 = (*i_getc)(f)) != EOF && - (c4 = (*i_getc)(f)) != EOF) { - nkf_iconv_utf_16(c1, c2, c3, c4); - } else if (ret == (size_t)NKF_ICONV_WAIT_COMBINING_CHAR) { - if ((c3 = (*i_getc)(f)) != EOF && - (c4 = (*i_getc)(f)) != EOF) { - if (nkf_iconv_utf_16_combine(c1, c2, c3, c4)) { - (*i_ungetc)(c4, f); - (*i_ungetc)(c3, f); - nkf_iconv_utf_16_nocombine(c1, c2); - } - } else { - nkf_iconv_utf_16_nocombine(c1, c2); - } - } - } - goto finished; - } -#endif - - while ((c1 = (*i_getc)(f)) != EOF) { -#ifdef INPUT_CODE_FIX - if (!input_encoding) -#endif - code_status(c1); - if (c2) { - /* second byte */ - if (c2 > ((input_encoding && nkf_enc_cp5022x_p(input_encoding)) ? 0x92 : DEL)) { - /* in case of 8th bit is on */ - if (!estab_f&&!mime_decode_mode) { - /* in case of not established yet */ - /* It is still ambiguous */ - if (h_conv(f, c2, c1)==EOF) { - LAST; - } - else { - SKIP; - } - } - else { - /* in case of already established */ - if (c1 < 0x40) { - /* ignore bogus code */ - SKIP; - } else { - SEND; - } - } - } - else { - /* 2nd byte of 7 bit code or SJIS */ - SEND; - } - } - else if (nkf_char_unicode_p(c1)) { - (*oconv)(0, c1); - NEXT; - } - else { - /* first byte */ - if (input_mode == JIS_X_0208 && DEL <= c1 && c1 < 0x92) { - /* CP5022x */ - MORE; - }else if (input_codename && input_codename[0] == 'I' && - 0xA1 <= c1 && c1 <= 0xDF) { - /* JIS X 0201 Katakana in 8bit JIS */ - c2 = JIS_X_0201_1976_K; - c1 &= 0x7f; - SEND; - } else if (c1 > DEL) { - /* 8 bit code */ - if (!estab_f && !iso8859_f) { - /* not established yet */ - MORE; - } else { /* estab_f==TRUE */ - if (iso8859_f) { - c2 = ISO_8859_1; - c1 &= 0x7f; - SEND; - } - else if ((iconv == s_iconv && 0xA0 <= c1 && c1 <= 0xDF) || - (ms_ucs_map_f == UCS_MAP_CP10001 && (c1 == 0xFD || c1 == 0xFE))) { - /* JIS X 0201 */ - c2 = JIS_X_0201_1976_K; - c1 &= 0x7f; - SEND; - } - else { - /* already established */ - MORE; - } - } - } else if (SP < c1 && c1 < DEL) { - /* in case of Roman characters */ - if (shift_mode) { - /* output 1 shifted byte */ - if (iso8859_f) { - c2 = ISO_8859_1; - SEND; - } else if (nkf_byte_jisx0201_katakana_p(c1)){ - /* output 1 shifted byte */ - c2 = JIS_X_0201_1976_K; - SEND; - } else { - /* look like bogus code */ - SKIP; - } - } else if (input_mode == JIS_X_0208 || input_mode == JIS_X_0212 || - input_mode == JIS_X_0213_1 || input_mode == JIS_X_0213_2) { - /* in case of Kanji shifted */ - MORE; - } else if (c1 == '=' && mime_f && !mime_decode_mode) { - /* Check MIME code */ - if ((c1 = (*i_getc)(f)) == EOF) { - (*oconv)(0, '='); - LAST; - } else if (c1 == '?') { - /* =? is mime conversion start sequence */ - if(mime_f == STRICT_MIME) { - /* check in real detail */ - if (mime_begin_strict(f) == EOF) - LAST; - SKIP; - } else if (mime_begin(f) == EOF) - LAST; - SKIP; - } else { - (*oconv)(0, '='); - (*i_ungetc)(c1,f); - SKIP; - } - } else { - /* normal ASCII code */ - SEND; - } - } else if (c1 == SI && (!is_8bit || mime_decode_mode)) { - shift_mode = 0; - SKIP; - } else if (c1 == SO && (!is_8bit || mime_decode_mode)) { - shift_mode = 1; - SKIP; - } else if (c1 == ESC && (!is_8bit || mime_decode_mode)) { - if ((c1 = (*i_getc)(f)) == EOF) { - (*oconv)(0, ESC); - LAST; - } - else if (c1 == '&') { - /* IRR */ - if ((c1 = (*i_getc)(f)) == EOF) { - LAST; - } else { - SKIP; - } - } - else if (c1 == '$') { - /* GZDMx */ - if ((c1 = (*i_getc)(f)) == EOF) { - /* don't send bogus code - (*oconv)(0, ESC); - (*oconv)(0, '$'); */ - LAST; - } else if (c1 == '@' || c1 == 'B') { - /* JIS X 0208 */ - set_input_mode(JIS_X_0208); - SKIP; - } else if (c1 == '(') { - /* GZDM4 */ - if ((c1 = (*i_getc)(f)) == EOF) { - /* don't send bogus code - (*oconv)(0, ESC); - (*oconv)(0, '$'); - (*oconv)(0, '('); - */ - LAST; - } else if (c1 == '@'|| c1 == 'B') { - /* JIS X 0208 */ - set_input_mode(JIS_X_0208); - SKIP; -#ifdef X0212_ENABLE - } else if (c1 == 'D'){ - set_input_mode(JIS_X_0212); - SKIP; -#endif /* X0212_ENABLE */ - } else if (c1 == 'O' || c1 == 'Q'){ - set_input_mode(JIS_X_0213_1); - SKIP; - } else if (c1 == 'P'){ - set_input_mode(JIS_X_0213_2); - SKIP; - } else { - /* could be some special code */ - (*oconv)(0, ESC); - (*oconv)(0, '$'); - (*oconv)(0, '('); - (*oconv)(0, c1); - SKIP; - } - } else if (broken_f&0x2) { - /* accept any ESC-(-x as broken code ... */ - input_mode = JIS_X_0208; - shift_mode = 0; - SKIP; - } else { - (*oconv)(0, ESC); - (*oconv)(0, '$'); - (*oconv)(0, c1); - SKIP; - } - } else if (c1 == '(') { - /* GZD4 */ - if ((c1 = (*i_getc)(f)) == EOF) { - /* don't send bogus code - (*oconv)(0, ESC); - (*oconv)(0, '('); */ - LAST; - } - else if (c1 == 'I') { - /* JIS X 0201 Katakana */ - set_input_mode(JIS_X_0201_1976_K); - shift_mode = 1; - SKIP; - } - else if (c1 == 'B' || c1 == 'J' || c1 == 'H') { - /* ISO-646IRV:1983 or JIS X 0201 Roman or JUNET */ - set_input_mode(ASCII); - SKIP; - } - else if (broken_f&0x2) { - set_input_mode(ASCII); - SKIP; - } - else { - (*oconv)(0, ESC); - (*oconv)(0, '('); - SEND; - } - } - else if (c1 == '.') { - /* G2D6 */ - if ((c1 = (*i_getc)(f)) == EOF) { - LAST; - } - else if (c1 == 'A') { - /* ISO-8859-1 */ - g2 = ISO_8859_1; - SKIP; - } - else { - (*oconv)(0, ESC); - (*oconv)(0, '.'); - SEND; - } - } - else if (c1 == 'N') { - /* SS2 */ - c1 = (*i_getc)(f); - if (g2 == ISO_8859_1) { - c2 = ISO_8859_1; - SEND; - }else{ - (*i_ungetc)(c1, f); - /* lonely ESC */ - (*oconv)(0, ESC); - SEND; - } - } - else { - i_ungetc(c1,f); - /* lonely ESC */ - (*oconv)(0, ESC); - SKIP; - } - } else if (c1 == ESC && iconv == s_iconv) { - /* ESC in Shift_JIS */ - if ((c1 = (*i_getc)(f)) == EOF) { - (*oconv)(0, ESC); - LAST; - } else if (c1 == '$') { - /* J-PHONE emoji */ - if ((c1 = (*i_getc)(f)) == EOF) { - LAST; - } else if (('E' <= c1 && c1 <= 'G') || - ('O' <= c1 && c1 <= 'Q')) { - /* - NUM : 0 1 2 3 4 5 - BYTE: G E F O P Q - C%7 : 1 6 0 2 3 4 - C%7 : 0 1 2 3 4 5 6 - NUM : 2 0 3 4 5 X 1 - */ - static const nkf_char jphone_emoji_first_table[7] = - {0xE1E0, 0xDFE0, 0xE2E0, 0xE3E0, 0xE4E0, 0xDFE0, 0xE0E0}; - c3 = nkf_char_unicode_new(jphone_emoji_first_table[c1 % 7]); - if ((c1 = (*i_getc)(f)) == EOF) LAST; - while (SP <= c1 && c1 <= 'z') { - (*oconv)(0, c1 + c3); - if ((c1 = (*i_getc)(f)) == EOF) LAST; - } - SKIP; - } - else { - (*oconv)(0, ESC); - (*oconv)(0, '$'); - SEND; - } - } - else { - i_ungetc(c1,f); - /* lonely ESC */ - (*oconv)(0, ESC); - SKIP; - } - } else if (c1 == LF || c1 == CR) { - if (broken_f&4) { - input_mode = ASCII; set_iconv(FALSE, 0); - SEND; - } else if (mime_decode_f && !mime_decode_mode){ - if (c1 == LF) { - if ((c1=(*i_getc)(f))!=EOF && c1 == SP) { - i_ungetc(SP,f); - continue; - } else { - i_ungetc(c1,f); - } - c1 = LF; - SEND; - } else { /* if (c1 == CR)*/ - if ((c1=(*i_getc)(f))!=EOF) { - if (c1==SP) { - i_ungetc(SP,f); - continue; - } else if (c1 == LF && (c1=(*i_getc)(f))!=EOF && c1 == SP) { - i_ungetc(SP,f); - continue; - } else { - i_ungetc(c1,f); - } - i_ungetc(LF,f); - } else { - i_ungetc(c1,f); - } - c1 = CR; - SEND; - } - } - } else - SEND; - } - /* send: */ - switch(input_mode){ - case ASCII: - switch ((*iconv)(c2, c1, 0)) { /* can be EUC / SJIS / UTF-8 */ - case -2: - /* 4 bytes UTF-8 */ - if ((c3 = (*i_getc)(f)) != EOF) { - code_status(c3); - c3 <<= 8; - if ((c4 = (*i_getc)(f)) != EOF) { - code_status(c4); - (*iconv)(c2, c1, c3|c4); - } - } - break; - case -3: - /* 4 bytes UTF-8 (check combining character) */ - if ((c3 = (*i_getc)(f)) != EOF) { - if ((c4 = (*i_getc)(f)) != EOF) { - if (w_iconv_combine(c2, c1, 0, c3, c4, 0)) { - (*i_ungetc)(c4, f); - (*i_ungetc)(c3, f); - w_iconv_nocombine(c2, c1, 0); - } - } else { - (*i_ungetc)(c3, f); - w_iconv_nocombine(c2, c1, 0); - } - } else { - w_iconv_nocombine(c2, c1, 0); - } - break; - case -1: - /* 3 bytes EUC or UTF-8 */ - if ((c3 = (*i_getc)(f)) != EOF) { - code_status(c3); - if ((*iconv)(c2, c1, c3) == -3) { - /* 6 bytes UTF-8 (check combining character) */ - nkf_char c5, c6; - if ((c4 = (*i_getc)(f)) != EOF) { - if ((c5 = (*i_getc)(f)) != EOF) { - if ((c6 = (*i_getc)(f)) != EOF) { - if (w_iconv_combine(c2, c1, c3, c4, c5, c6)) { - (*i_ungetc)(c6, f); - (*i_ungetc)(c5, f); - (*i_ungetc)(c4, f); - w_iconv_nocombine(c2, c1, c3); - } - } else { - (*i_ungetc)(c5, f); - (*i_ungetc)(c4, f); - w_iconv_nocombine(c2, c1, c3); - } - } else { - (*i_ungetc)(c4, f); - w_iconv_nocombine(c2, c1, c3); - } - } else { - w_iconv_nocombine(c2, c1, c3); - } - } - } - break; - } - break; - case JIS_X_0208: - case JIS_X_0213_1: - if (ms_ucs_map_f && - 0x7F <= c2 && c2 <= 0x92 && - 0x21 <= c1 && c1 <= 0x7E) { - /* CP932 UDC */ - c1 = nkf_char_unicode_new((c2 - 0x7F) * 94 + c1 - 0x21 + 0xE000); - c2 = 0; - } - (*oconv)(c2, c1); /* this is JIS, not SJIS/EUC case */ - break; -#ifdef X0212_ENABLE - case JIS_X_0212: - (*oconv)(PREFIX_EUCG3 | c2, c1); - break; -#endif /* X0212_ENABLE */ - case JIS_X_0213_2: - (*oconv)(PREFIX_EUCG3 | c2, c1); - break; - default: - (*oconv)(input_mode, c1); /* other special case */ - } - - c2 = 0; - c3 = 0; - continue; - /* goto next_word */ - } - -finished: - /* epilogue */ - (*iconv)(EOF, 0, 0); - if (!input_codename) - { - if (is_8bit) { - struct input_code *p = input_code_list; - struct input_code *result = p; - while (p->name){ - if (p->score < result->score) result = p; - ++p; - } - set_input_codename(result->name); -#ifdef CHECK_OPTION - debug(result->name); -#endif - } - } - return 0; -} - -/* - * int options(unsigned char *cp) - * - * return values: - * 0: success - * -1: ArgumentError - */ -static int -options(unsigned char *cp) -{ - nkf_char i, j; - unsigned char *p; - unsigned char *cp_back = NULL; - nkf_encoding *enc; - - if (option_mode==1) - return 0; - while(*cp && *cp++!='-'); - while (*cp || cp_back) { - if(!*cp){ - cp = cp_back; - cp_back = NULL; - continue; - } - p = 0; - switch (*cp++) { - case '-': /* literal options */ - if (!*cp || *cp == SP) { /* ignore the rest of arguments */ - option_mode = 1; - return 0; - } - for (i=0;i<(int)(sizeof(long_option)/sizeof(long_option[0]));i++) { - p = (unsigned char *)long_option[i].name; - for (j=0;*p && *p != '=' && *p == cp[j];p++, j++); - if (*p == cp[j] || cp[j] == SP){ - p = &cp[j] + 1; - break; - } - p = 0; - } - if (p == 0) { -#if !defined(PERL_XS) && !defined(WIN32DLL) - fprintf(stderr, "unknown long option: --%s\n", cp); -#endif - return -1; - } - while(*cp && *cp != SP && cp++); - if (long_option[i].alias[0]){ - cp_back = cp; - cp = (unsigned char *)long_option[i].alias; - }else{ -#ifndef PERL_XS - if (strcmp(long_option[i].name, "help") == 0){ - usage(); - exit(EXIT_SUCCESS); - } -#endif - if (strcmp(long_option[i].name, "ic=") == 0){ - enc = nkf_enc_find((char *)p); - if (!enc) continue; - input_encoding = enc; - continue; - } - if (strcmp(long_option[i].name, "oc=") == 0){ - enc = nkf_enc_find((char *)p); - /* if (enc <= 0) continue; */ - if (!enc) continue; - output_encoding = enc; - continue; - } - if (strcmp(long_option[i].name, "guess=") == 0){ - if (p[0] == '0' || p[0] == '1') { - guess_f = 1; - } else { - guess_f = 2; - } - continue; - } -#ifdef OVERWRITE - if (strcmp(long_option[i].name, "overwrite") == 0){ - file_out_f = TRUE; - overwrite_f = TRUE; - preserve_time_f = TRUE; - continue; - } - if (strcmp(long_option[i].name, "overwrite=") == 0){ - file_out_f = TRUE; - overwrite_f = TRUE; - preserve_time_f = TRUE; - backup_f = TRUE; - backup_suffix = (char *)p; - continue; - } - if (strcmp(long_option[i].name, "in-place") == 0){ - file_out_f = TRUE; - overwrite_f = TRUE; - preserve_time_f = FALSE; - continue; - } - if (strcmp(long_option[i].name, "in-place=") == 0){ - file_out_f = TRUE; - overwrite_f = TRUE; - preserve_time_f = FALSE; - backup_f = TRUE; - backup_suffix = (char *)p; - continue; - } -#endif -#ifdef INPUT_OPTION - if (strcmp(long_option[i].name, "cap-input") == 0){ - cap_f = TRUE; - continue; - } - if (strcmp(long_option[i].name, "url-input") == 0){ - url_f = TRUE; - continue; - } -#endif -#ifdef NUMCHAR_OPTION - if (strcmp(long_option[i].name, "numchar-input") == 0){ - numchar_f = TRUE; - continue; - } -#endif -#ifdef CHECK_OPTION - if (strcmp(long_option[i].name, "no-output") == 0){ - noout_f = TRUE; - continue; - } - if (strcmp(long_option[i].name, "debug") == 0){ - debug_f = TRUE; - continue; - } -#endif - if (strcmp(long_option[i].name, "cp932") == 0){ -#ifdef SHIFTJIS_CP932 - cp51932_f = TRUE; - cp932inv_f = -TRUE; -#endif -#ifdef UTF8_OUTPUT_ENABLE - ms_ucs_map_f = UCS_MAP_CP932; -#endif - continue; - } - if (strcmp(long_option[i].name, "no-cp932") == 0){ -#ifdef SHIFTJIS_CP932 - cp51932_f = FALSE; - cp932inv_f = FALSE; -#endif -#ifdef UTF8_OUTPUT_ENABLE - ms_ucs_map_f = UCS_MAP_ASCII; -#endif - continue; - } -#ifdef SHIFTJIS_CP932 - if (strcmp(long_option[i].name, "cp932inv") == 0){ - cp932inv_f = -TRUE; - continue; - } -#endif - -#ifdef X0212_ENABLE - if (strcmp(long_option[i].name, "x0212") == 0){ - x0212_f = TRUE; - continue; - } -#endif - -#ifdef EXEC_IO - if (strcmp(long_option[i].name, "exec-in") == 0){ - exec_f = 1; - return 0; - } - if (strcmp(long_option[i].name, "exec-out") == 0){ - exec_f = -1; - return 0; - } -#endif -#if defined(UTF8_OUTPUT_ENABLE) && defined(UTF8_INPUT_ENABLE) - if (strcmp(long_option[i].name, "no-cp932ext") == 0){ - no_cp932ext_f = TRUE; - continue; - } - if (strcmp(long_option[i].name, "no-best-fit-chars") == 0){ - no_best_fit_chars_f = TRUE; - continue; - } - if (strcmp(long_option[i].name, "fb-skip") == 0){ - encode_fallback = NULL; - continue; - } - if (strcmp(long_option[i].name, "fb-html") == 0){ - encode_fallback = encode_fallback_html; - continue; - } - if (strcmp(long_option[i].name, "fb-xml") == 0){ - encode_fallback = encode_fallback_xml; - continue; - } - if (strcmp(long_option[i].name, "fb-java") == 0){ - encode_fallback = encode_fallback_java; - continue; - } - if (strcmp(long_option[i].name, "fb-perl") == 0){ - encode_fallback = encode_fallback_perl; - continue; - } - if (strcmp(long_option[i].name, "fb-subchar") == 0){ - encode_fallback = encode_fallback_subchar; - continue; - } - if (strcmp(long_option[i].name, "fb-subchar=") == 0){ - encode_fallback = encode_fallback_subchar; - unicode_subchar = 0; - if (p[0] != '0'){ - /* decimal number */ - for (i = 0; i < 7 && nkf_isdigit(p[i]); i++){ - unicode_subchar *= 10; - unicode_subchar += hex2bin(p[i]); - } - }else if(p[1] == 'x' || p[1] == 'X'){ - /* hexadecimal number */ - for (i = 2; i < 8 && nkf_isxdigit(p[i]); i++){ - unicode_subchar <<= 4; - unicode_subchar |= hex2bin(p[i]); - } - }else{ - /* octal number */ - for (i = 1; i < 8 && nkf_isoctal(p[i]); i++){ - unicode_subchar *= 8; - unicode_subchar += hex2bin(p[i]); - } - } - w16e_conv(unicode_subchar, &i, &j); - unicode_subchar = i<<8 | j; - continue; - } -#endif -#ifdef UTF8_OUTPUT_ENABLE - if (strcmp(long_option[i].name, "ms-ucs-map") == 0){ - ms_ucs_map_f = UCS_MAP_MS; - continue; - } -#endif -#ifdef UNICODE_NORMALIZATION - if (strcmp(long_option[i].name, "utf8mac-input") == 0){ - nfc_f = TRUE; - continue; - } -#endif - if (strcmp(long_option[i].name, "prefix=") == 0){ - if (nkf_isgraph(p[0])){ - for (i = 1; nkf_isgraph(p[i]); i++){ - prefix_table[p[i]] = p[0]; - } - } - continue; - } -#if !defined(PERL_XS) && !defined(WIN32DLL) - fprintf(stderr, "unsupported long option: --%s\n", long_option[i].name); -#endif - return -1; - } - continue; - case 'b': /* buffered mode */ - unbuf_f = FALSE; - continue; - case 'u': /* non bufferd mode */ - unbuf_f = TRUE; - continue; - case 't': /* transparent mode */ - if (*cp=='1') { - /* alias of -t */ - cp++; - nop_f = TRUE; - } else if (*cp=='2') { - /* - * -t with put/get - * - * nkf -t2MB hoge.bin | nkf -t2mB | diff -s - hoge.bin - * - */ - cp++; - nop_f = 2; - } else - nop_f = TRUE; - continue; - case 'j': /* JIS output */ - case 'n': - output_encoding = nkf_enc_from_index(ISO_2022_JP); - continue; - case 'e': /* AT&T EUC output */ - output_encoding = nkf_enc_from_index(EUCJP_NKF); - continue; - case 's': /* SJIS output */ - output_encoding = nkf_enc_from_index(SHIFT_JIS); - continue; - case 'l': /* ISO8859 Latin-1 support, no conversion */ - iso8859_f = TRUE; /* Only compatible with ISO-2022-JP */ - input_encoding = nkf_enc_from_index(ISO_8859_1); - continue; - case 'i': /* Kanji IN ESC-$-@/B */ - if (*cp=='@'||*cp=='B') - kanji_intro = *cp++; - continue; - case 'o': /* ASCII IN ESC-(-J/B/H */ - /* ESC ( H was used in initial JUNET messages */ - if (*cp=='J'||*cp=='B'||*cp=='H') - ascii_intro = *cp++; - continue; - case 'h': - /* - bit:1 katakana->hiragana - bit:2 hiragana->katakana - */ - if ('9'>= *cp && *cp>='0') - hira_f |= (*cp++ -'0'); - else - hira_f |= 1; - continue; - case 'r': - rot_f = TRUE; - continue; -#if defined(MSDOS) || defined(__OS2__) - case 'T': - binmode_f = FALSE; - continue; -#endif -#ifndef PERL_XS - case 'V': - show_configuration(); - exit(EXIT_SUCCESS); - break; - case 'v': - version(); - exit(EXIT_SUCCESS); - break; -#endif -#ifdef UTF8_OUTPUT_ENABLE - case 'w': /* UTF-{8,16,32} output */ - if (cp[0] == '8') { - cp++; - if (cp[0] == '0'){ - cp++; - output_encoding = nkf_enc_from_index(UTF_8N); - } else { - output_bom_f = TRUE; - output_encoding = nkf_enc_from_index(UTF_8_BOM); - } - } else { - int enc_idx; - if ('1'== cp[0] && '6'==cp[1]) { - cp += 2; - enc_idx = UTF_16; - } else if ('3'== cp[0] && '2'==cp[1]) { - cp += 2; - enc_idx = UTF_32; - } else { - output_encoding = nkf_enc_from_index(UTF_8); - continue; - } - if (cp[0]=='L') { - cp++; - output_endian = ENDIAN_LITTLE; - output_bom_f = TRUE; - } else if (cp[0] == 'B') { - cp++; - output_bom_f = TRUE; - } - if (cp[0] == '0'){ - output_bom_f = FALSE; - cp++; - enc_idx = enc_idx == UTF_16 - ? (output_endian == ENDIAN_LITTLE ? UTF_16LE : UTF_16BE) - : (output_endian == ENDIAN_LITTLE ? UTF_32LE : UTF_32BE); - } else { - enc_idx = enc_idx == UTF_16 - ? (output_endian == ENDIAN_LITTLE ? UTF_16LE_BOM : UTF_16BE_BOM) - : (output_endian == ENDIAN_LITTLE ? UTF_32LE_BOM : UTF_32BE_BOM); - } - output_encoding = nkf_enc_from_index(enc_idx); - } - continue; -#endif -#ifdef UTF8_INPUT_ENABLE - case 'W': /* UTF input */ - if (cp[0] == '8') { - cp++; - input_encoding = nkf_enc_from_index(UTF_8); - }else{ - int enc_idx; - if ('1'== cp[0] && '6'==cp[1]) { - cp += 2; - input_endian = ENDIAN_BIG; - enc_idx = UTF_16; - } else if ('3'== cp[0] && '2'==cp[1]) { - cp += 2; - input_endian = ENDIAN_BIG; - enc_idx = UTF_32; - } else { - input_encoding = nkf_enc_from_index(UTF_8); - continue; - } - if (cp[0]=='L') { - cp++; - input_endian = ENDIAN_LITTLE; - } else if (cp[0] == 'B') { - cp++; - input_endian = ENDIAN_BIG; - } - enc_idx = (enc_idx == UTF_16 - ? (input_endian == ENDIAN_LITTLE ? UTF_16LE : UTF_16BE) - : (input_endian == ENDIAN_LITTLE ? UTF_32LE : UTF_32BE)); - input_encoding = nkf_enc_from_index(enc_idx); - } - continue; -#endif - /* Input code assumption */ - case 'J': /* ISO-2022-JP input */ - input_encoding = nkf_enc_from_index(ISO_2022_JP); - continue; - case 'E': /* EUC-JP input */ - input_encoding = nkf_enc_from_index(EUCJP_NKF); - continue; - case 'S': /* Shift_JIS input */ - input_encoding = nkf_enc_from_index(SHIFT_JIS); - continue; - case 'Z': /* Convert X0208 alphabet to ascii */ - /* alpha_f - bit:0 Convert JIS X 0208 Alphabet to ASCII - bit:1 Convert Kankaku to one space - bit:2 Convert Kankaku to two spaces - bit:3 Convert HTML Entity - bit:4 Convert JIS X 0208 Katakana to JIS X 0201 Katakana - */ - while ('0'<= *cp && *cp <='4') { - alpha_f |= 1 << (*cp++ - '0'); - } - alpha_f |= 1; - continue; - case 'x': /* Convert X0201 kana to X0208 or X0201 Conversion */ - x0201_f = FALSE; /* No X0201->X0208 conversion */ - /* accept X0201 - ESC-(-I in JIS, EUC, MS Kanji - SI/SO in JIS, EUC, MS Kanji - SS2 in EUC, JIS, not in MS Kanji - MS Kanji (0xa0-0xdf) - output X0201 - ESC-(-I in JIS (0x20-0x5f) - SS2 in EUC (0xa0-0xdf) - 0xa0-0xd in MS Kanji (0xa0-0xdf) - */ - continue; - case 'X': /* Convert X0201 kana to X0208 */ - x0201_f = TRUE; - continue; - case 'F': /* prserve new lines */ - fold_preserve_f = TRUE; - case 'f': /* folding -f60 or -f */ - fold_f = TRUE; - fold_len = 0; - while('0'<= *cp && *cp <='9') { /* we don't use atoi here */ - fold_len *= 10; - fold_len += *cp++ - '0'; - } - if (!(0= *cp && *cp>='0') - broken_f |= 1<<(*cp++ -'0'); - else - broken_f |= TRUE; - continue; -#ifndef PERL_XS - case 'O':/* for Output file */ - file_out_f = TRUE; - continue; -#endif - case 'c':/* add cr code */ - eolmode_f = CRLF; - continue; - case 'd':/* delete cr code */ - eolmode_f = LF; - continue; - case 'I': /* ISO-2022-JP output */ - iso2022jp_f = TRUE; - continue; - case 'L': /* line mode */ - if (*cp=='u') { /* unix */ - eolmode_f = LF; cp++; - } else if (*cp=='m') { /* mac */ - eolmode_f = CR; cp++; - } else if (*cp=='w') { /* windows */ - eolmode_f = CRLF; cp++; - } else if (*cp=='0') { /* no conversion */ - eolmode_f = 0; cp++; - } - continue; -#ifndef PERL_XS - case 'g': - if ('2' <= *cp && *cp <= '9') { - guess_f = 2; - cp++; - } else if (*cp == '0' || *cp == '1') { - guess_f = 1; - cp++; - } else { - guess_f = 1; - } - continue; -#endif - case SP: - /* module multiple options in a string are allowed for Perl module */ - while(*cp && *cp++!='-'); - continue; - default: -#if !defined(PERL_XS) && !defined(WIN32DLL) - fprintf(stderr, "unknown option: -%c\n", *(cp-1)); -#endif - /* bogus option but ignored */ - return -1; - } - } - return 0; -} - -#ifdef WIN32DLL -#include "nkf32dll.c" -#elif defined(PERL_XS) -#else /* WIN32DLL */ -int -main(int argc, char **argv) -{ - FILE *fin; - unsigned char *cp; - - char *outfname = NULL; - char *origfname; - -#ifdef EASYWIN /*Easy Win */ - _BufferSize.y = 400;/*Set Scroll Buffer Size*/ -#endif -#ifdef DEFAULT_CODE_LOCALE - setlocale(LC_CTYPE, ""); -#endif - nkf_state_init(); - - for (argc--,argv++; (argc > 0) && **argv == '-'; argc--, argv++) { - cp = (unsigned char *)*argv; - options(cp); -#ifdef EXEC_IO - if (exec_f){ - int fds[2], pid; - if (pipe(fds) < 0 || (pid = fork()) < 0){ - abort(); - } - if (pid == 0){ - if (exec_f > 0){ - close(fds[0]); - dup2(fds[1], 1); - }else{ - close(fds[1]); - dup2(fds[0], 0); - } - execvp(argv[1], &argv[1]); - } - if (exec_f > 0){ - close(fds[1]); - dup2(fds[0], 0); - }else{ - close(fds[0]); - dup2(fds[1], 1); - } - argc = 0; - break; - } -#endif - } - - if (guess_f) { -#ifdef CHECK_OPTION - int debug_f_back = debug_f; -#endif -#ifdef EXEC_IO - int exec_f_back = exec_f; -#endif -#ifdef X0212_ENABLE - int x0212_f_back = x0212_f; -#endif - int x0213_f_back = x0213_f; - int guess_f_back = guess_f; - reinit(); - guess_f = guess_f_back; - mime_f = FALSE; -#ifdef CHECK_OPTION - debug_f = debug_f_back; -#endif -#ifdef EXEC_IO - exec_f = exec_f_back; -#endif - x0212_f = x0212_f_back; - x0213_f = x0213_f_back; - } - - if (binmode_f == TRUE) -#if defined(__OS2__) && (defined(__IBMC__) || defined(__IBMCPP__)) - if (freopen("","wb",stdout) == NULL) - return (-1); -#else - setbinmode(stdout); -#endif - - if (unbuf_f) - setbuf(stdout, (char *) NULL); - else - setvbuffer(stdout, (char *) stdobuf, IOBUF_SIZE); - - if (argc == 0) { - if (binmode_f == TRUE) -#if defined(__OS2__) && (defined(__IBMC__) || defined(__IBMCPP__)) - if (freopen("","rb",stdin) == NULL) return (-1); -#else - setbinmode(stdin); -#endif - setvbuffer(stdin, (char *) stdibuf, IOBUF_SIZE); - if (nop_f) - noconvert(stdin); - else { - kanji_convert(stdin); - if (guess_f) print_guessed_code(NULL); - } - } else { - int nfiles = argc; - int is_argument_error = FALSE; - while (argc--) { - input_codename = NULL; - input_eol = 0; -#ifdef CHECK_OPTION - iconv_for_check = 0; -#endif - if ((fin = fopen((origfname = *argv++), "r")) == NULL) { - perror(*(argv-1)); - is_argument_error = TRUE; - continue; - } else { -#ifdef OVERWRITE - int fd = 0; - int fd_backup = 0; -#endif - - /* reopen file for stdout */ - if (file_out_f == TRUE) { -#ifdef OVERWRITE - if (overwrite_f){ - outfname = nkf_xmalloc(strlen(origfname) - + strlen(".nkftmpXXXXXX") - + 1); - strcpy(outfname, origfname); -#ifdef MSDOS - { - int i; - for (i = strlen(outfname); i; --i){ - if (outfname[i - 1] == '/' - || outfname[i - 1] == '\\'){ - break; - } - } - outfname[i] = '\0'; - } - strcat(outfname, "ntXXXXXX"); - mktemp(outfname); - fd = open(outfname, O_WRONLY | O_CREAT | O_TRUNC | O_EXCL, - S_IREAD | S_IWRITE); -#else - strcat(outfname, ".nkftmpXXXXXX"); - fd = mkstemp(outfname); -#endif - if (fd < 0 - || (fd_backup = dup(fileno(stdout))) < 0 - || dup2(fd, fileno(stdout)) < 0 - ){ - perror(origfname); - return -1; - } - }else -#endif - if(argc == 1) { - outfname = *argv++; - argc--; - } else { - outfname = "nkf.out"; - } - - if(freopen(outfname, "w", stdout) == NULL) { - perror (outfname); - return (-1); - } - if (binmode_f == TRUE) { -#if defined(__OS2__) && (defined(__IBMC__) || defined(__IBMCPP__)) - if (freopen("","wb",stdout) == NULL) - return (-1); -#else - setbinmode(stdout); -#endif - } - } - if (binmode_f == TRUE) -#if defined(__OS2__) && (defined(__IBMC__) || defined(__IBMCPP__)) - if (freopen("","rb",fin) == NULL) - return (-1); -#else - setbinmode(fin); -#endif - setvbuffer(fin, (char *) stdibuf, IOBUF_SIZE); - if (nop_f) - noconvert(fin); - else { - char *filename = NULL; - kanji_convert(fin); - if (nfiles > 1) filename = origfname; - if (guess_f) print_guessed_code(filename); - } - fclose(fin); -#ifdef OVERWRITE - if (overwrite_f) { - struct stat sb; -#if defined(MSDOS) && !defined(__MINGW32__) && !defined(__WIN32__) && !defined(__WATCOMC__) && !defined(__EMX__) && !defined(__OS2__) && !defined(__DJGPP__) - time_t tb[2]; -#else - struct utimbuf tb; -#endif - - fflush(stdout); - close(fd); - if (dup2(fd_backup, fileno(stdout)) < 0){ - perror("dup2"); - } - if (stat(origfname, &sb)) { - fprintf(stderr, "Can't stat %s\n", origfname); - } - /* $B%Q!<%_%C%7%g%s$rI|85(B */ - if (chmod(outfname, sb.st_mode)) { - fprintf(stderr, "Can't set permission %s\n", outfname); - } - - /* $B%?%$%`%9%?%s%W$rI|85(B */ - if(preserve_time_f){ -#if defined(MSDOS) && !defined(__MINGW32__) && !defined(__WIN32__) && !defined(__WATCOMC__) && !defined(__EMX__) && !defined(__OS2__) && !defined(__DJGPP__) - tb[0] = tb[1] = sb.st_mtime; - if (utime(outfname, tb)) { - fprintf(stderr, "Can't set timestamp %s\n", outfname); - } -#else - tb.actime = sb.st_atime; - tb.modtime = sb.st_mtime; - if (utime(outfname, &tb)) { - fprintf(stderr, "Can't set timestamp %s\n", outfname); - } -#endif - } - if(backup_f){ - char *backup_filename = get_backup_filename(backup_suffix, origfname); -#ifdef MSDOS - unlink(backup_filename); -#endif - if (rename(origfname, backup_filename)) { - perror(backup_filename); - fprintf(stderr, "Can't rename %s to %s\n", - origfname, backup_filename); - } - nkf_xfree(backup_filename); - }else{ -#ifdef MSDOS - if (unlink(origfname)){ - perror(origfname); - } -#endif - } - if (rename(outfname, origfname)) { - perror(origfname); - fprintf(stderr, "Can't rename %s to %s\n", - outfname, origfname); - } - nkf_xfree(outfname); - } -#endif - } - } - if (is_argument_error) - return(-1); - } -#ifdef EASYWIN /*Easy Win */ - if (file_out_f == FALSE) - scanf("%d",&end_check); - else - fclose(stdout); -#else /* for Other OS */ - if (file_out_f == TRUE) - fclose(stdout); -#endif /*Easy Win */ - return (0); -} -#endif /* WIN32DLL */ diff --git a/ext/nkf/nkf-utf8/nkf.h b/ext/nkf/nkf-utf8/nkf.h deleted file mode 100644 index b3a520da54edff..00000000000000 --- a/ext/nkf/nkf-utf8/nkf.h +++ /dev/null @@ -1,189 +0,0 @@ -/* - * - * nkf.h - Header file for nkf - * - */ - -#ifndef NKF_H -#define NKF_H - -/* Wrapper of configurations */ - -#ifndef MIME_DECODE_DEFAULT -#define MIME_DECODE_DEFAULT STRICT_MIME -#endif -#ifndef X0201_DEFAULT -#define X0201_DEFAULT TRUE -#endif - -#if defined(DEFAULT_NEWLINE) && DEFAULT_NEWLINE == 0x0D0A -#elif defined(DEFAULT_NEWLINE) && DEFAULT_NEWLINE == 0x0D -#else -#define DEFAULT_NEWLINE 0x0A -#endif -#ifdef HELP_OUTPUT_STDERR -#define HELP_OUTPUT stderr -#else -#define HELP_OUTPUT stdout -#endif - - -/* Compatibility definitions */ - -#ifdef nkf_char -#elif defined(INT_IS_SHORT) -typedef long nkf_char; -#define NKF_INT32_C(n) (n##L) -#else -typedef int nkf_char; -#define NKF_INT32_C(n) (n) -#endif - -#if (defined(__TURBOC__) || defined(_MSC_VER) || defined(LSI_C) || (defined(__WATCOMC__) && defined(__386__) && !defined(__LINUX__)) || defined(__MINGW32__) || defined(__EMX__) || defined(__MSDOS__) || defined(__WINDOWS__) || defined(__DOS__) || defined(__OS2__)) && !defined(MSDOS) -#define MSDOS -#if (defined(__Win32__) || defined(_WIN32)) && !defined(__WIN32__) -#define __WIN32__ -#endif -#endif - -#ifdef PERL_XS -#undef OVERWRITE -#endif - -#ifndef PERL_XS -#include -#endif - -#include -#include - -#if defined(MSDOS) || defined(__OS2__) -#include -#include -#if defined(_MSC_VER) || defined(__WATCOMC__) -#define mktemp _mktemp -#endif -#endif - -#ifdef MSDOS -#ifdef LSI_C -#define setbinmode(fp) fsetbin(fp) -#elif defined(__DJGPP__) -#include -void setbinmode(FILE *fp) -{ - /* we do not use libc's setmode(), which changes COOKED/RAW mode in device. */ - int fd, m; - fd = fileno(fp); - m = (__file_handle_modes[fd] & (~O_TEXT)) | O_BINARY; - __file_handle_set(fd, m); -} -#else /* Microsoft C, Turbo C */ -#define setbinmode(fp) setmode(fileno(fp), O_BINARY) -#endif -#else /* UNIX */ -#define setbinmode(fp) (void)(fp) -#endif - -#ifdef _IOFBF /* SysV and MSDOS, Windows */ -#define setvbuffer(fp, buf, size) setvbuf(fp, buf, _IOFBF, size) -#else /* BSD */ -#define setvbuffer(fp, buf, size) setbuffer(fp, buf, size) -#endif - -/*Borland C++ 4.5 EasyWin*/ -#if defined(__TURBOC__) && defined(_Windows) && !defined(__WIN32__) /*Easy Win */ -#define EASYWIN -#ifndef __WIN16__ -#define __WIN16__ -#endif -#include -#endif - -#ifdef OVERWRITE -/* added by satoru@isoternet.org */ -#if defined(__EMX__) -#include -#endif -#include -#if !defined(MSDOS) || defined(__DJGPP__) /* UNIX, djgpp */ -#include -#if defined(__WATCOMC__) -#include -#else -#include -#endif -#else /* defined(MSDOS) */ -#ifdef __WIN32__ -#ifdef __BORLANDC__ /* BCC32 */ -#include -#else /* !defined(__BORLANDC__) */ -#include -#endif /* (__BORLANDC__) */ -#else /* !defined(__WIN32__) */ -#if defined(_MSC_VER) || defined(__MINGW32__) || defined(__WATCOMC__) || defined(__OS2__) || defined(__EMX__) || defined(__IBMC__) || defined(__IBMCPP__) /* VC++, MinGW, Watcom, emx+gcc, IBM VAC++ */ -#include -#elif defined(__TURBOC__) /* BCC */ -#include -#elif defined(LSI_C) /* LSI C */ -#endif /* (__WIN32__) */ -#endif -#endif -#endif - -#if !defined(DEFAULT_CODE_JIS) && !defined(DEFAULT_CODE_SJIS) && \ - !defined(DEFAULT_CODE_WINDOWS_31J) && !defined(DEFAULT_CODE_EUC) && \ - !defined(DEFAULT_CODE_UTF8) && !defined(DEFAULT_CODE_LOCALE) -#define DEFAULT_CODE_LOCALE -#endif - -#ifdef DEFAULT_CODE_LOCALE - -#if defined(__WIN32__) /* not win32 should be posix */ -# ifndef HAVE_LOCALE_H -# define HAVE_LOCALE_H -# endif -#elif defined(__OS2__) -# undef HAVE_LANGINFO_H /* We do not use kLIBC's langinfo. */ -# ifndef HAVE_LOCALE_H -# define HAVE_LOCALE_H -# endif -#elif defined(MSDOS) -# ifndef HAVE_LOCALE_H -# define HAVE_LOCALE_H -# endif -#elif defined(__BIONIC__) /* bionic doesn't have locale */ -#else -# ifndef HAVE_LANGINFO_H -# define HAVE_LANGINFO_H -# endif -# ifndef HAVE_LOCALE_H -# define HAVE_LOCALE_H -# endif -#endif - -#ifdef HAVE_LANGINFO_H -#include -#endif -#ifdef HAVE_LOCALE_H -#include -#endif - -#endif /* DEFAULT_CODE_LOCALE */ - -#define FALSE 0 -#define TRUE 1 - -#ifndef ARG_UNUSED -#if defined(__GNUC__) -# define ARG_UNUSED __attribute__ ((unused)) -#else -# define ARG_UNUSED -#endif -#endif - -#ifdef WIN32DLL -#include "nkf32.h" -#endif - -#endif /* NKF_H */ diff --git a/ext/nkf/nkf-utf8/utf8tbl.c b/ext/nkf/nkf-utf8/utf8tbl.c deleted file mode 100644 index a31e4e7805dec0..00000000000000 --- a/ext/nkf/nkf-utf8/utf8tbl.c +++ /dev/null @@ -1,14638 +0,0 @@ -/* - * utf8tbl.c - Conversion Table for nkf - * - */ - -#include "config.h" -#include "utf8tbl.h" - -#ifdef UTF8_OUTPUT_ENABLE -static const unsigned short euc_to_utf8_A1[] = { - 0x3000, 0x3001, 0x3002, 0xFF0C, 0xFF0E, 0x30FB, 0xFF1A, - 0xFF1B, 0xFF1F, 0xFF01, 0x309B, 0x309C, 0x00B4, 0xFF40, 0x00A8, - 0xFF3E, 0x203E, 0xFF3F, 0x30FD, 0x30FE, 0x309D, 0x309E, 0x3003, - 0x4EDD, 0x3005, 0x3006, 0x3007, 0x30FC, 0x2014, 0x2010, 0xFF0F, - 0xFF3C, 0x301C, 0x2016, 0xFF5C, 0x2026, 0x2025, 0x2018, 0x2019, - 0x201C, 0x201D, 0xFF08, 0xFF09, 0x3014, 0x3015, 0xFF3B, 0xFF3D, - 0xFF5B, 0xFF5D, 0x3008, 0x3009, 0x300A, 0x300B, 0x300C, 0x300D, - 0x300E, 0x300F, 0x3010, 0x3011, 0xFF0B, 0x2212, 0x00B1, 0x00D7, - 0x00F7, 0xFF1D, 0x2260, 0xFF1C, 0xFF1E, 0x2266, 0x2267, 0x221E, - 0x2234, 0x2642, 0x2640, 0x00B0, 0x2032, 0x2033, 0x2103, 0x00A5, - 0xFF04, 0x00A2, 0x00A3, 0xFF05, 0xFF03, 0xFF06, 0xFF0A, 0xFF20, - 0x00A7, 0x2606, 0x2605, 0x25CB, 0x25CF, 0x25CE, 0x25C7, -}; - -/* Microsoft UCS Mapping Compatible */ -static const unsigned short euc_to_utf8_A1_ms[] = { - 0x3000, 0x3001, 0x3002, 0xFF0C, 0xFF0E, 0x30FB, 0xFF1A, - 0xFF1B, 0xFF1F, 0xFF01, 0x309B, 0x309C, 0x00B4, 0xFF40, 0x00A8, - 0xFF3E, 0xFFE3, 0xFF3F, 0x30FD, 0x30FE, 0x309D, 0x309E, 0x3003, - 0x4EDD, 0x3005, 0x3006, 0x3007, 0x30FC, 0x2015, 0x2010, 0xFF0F, - 0xFF3C, 0xFF5E, 0x2225, 0xFF5C, 0x2026, 0x2025, 0x2018, 0x2019, - 0x201C, 0x201D, 0xFF08, 0xFF09, 0x3014, 0x3015, 0xFF3B, 0xFF3D, - 0xFF5B, 0xFF5D, 0x3008, 0x3009, 0x300A, 0x300B, 0x300C, 0x300D, - 0x300E, 0x300F, 0x3010, 0x3011, 0xFF0B, 0xFF0D, 0x00B1, 0x00D7, - 0x00F7, 0xFF1D, 0x2260, 0xFF1C, 0xFF1E, 0x2266, 0x2267, 0x221E, - 0x2234, 0x2642, 0x2640, 0x00B0, 0x2032, 0x2033, 0x2103, 0xFFE5, - 0xFF04, 0xFFE0, 0xFFE1, 0xFF05, 0xFF03, 0xFF06, 0xFF0A, 0xFF20, - 0x00A7, 0x2606, 0x2605, 0x25CB, 0x25CF, 0x25CE, 0x25C7, -}; -static const unsigned short euc_to_utf8_A2[] = { - 0x25C6, 0x25A1, 0x25A0, 0x25B3, 0x25B2, 0x25BD, 0x25BC, - 0x203B, 0x3012, 0x2192, 0x2190, 0x2191, 0x2193, 0x3013, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0x2208, 0x220B, 0x2286, 0x2287, 0x2282, 0x2283, - 0x222A, 0x2229, 0, 0, 0, 0, 0, 0, - 0, 0, 0x2227, 0x2228, 0x00AC, 0x21D2, 0x21D4, 0x2200, - 0x2203, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0x2220, 0x22A5, 0x2312, 0x2202, - 0x2207, 0x2261, 0x2252, 0x226A, 0x226B, 0x221A, 0x223D, 0x221D, - 0x2235, 0x222B, 0x222C, 0, 0, 0, 0, 0, - 0, 0, 0x212B, 0x2030, 0x266F, 0x266D, 0x266A, 0x2020, - 0x2021, 0x00B6, 0, 0, 0, 0, 0x25EF, -}; - -/* Microsoft UCS Mapping Compatible */ -static const unsigned short euc_to_utf8_A2_ms[] = { - 0x25C6, 0x25A1, 0x25A0, 0x25B3, 0x25B2, 0x25BD, 0x25BC, - 0x203B, 0x3012, 0x2192, 0x2190, 0x2191, 0x2193, 0x3013, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0x2208, 0x220B, 0x2286, 0x2287, 0x2282, 0x2283, - 0x222A, 0x2229, 0, 0, 0, 0, 0, 0, - 0, 0, 0x2227, 0x2228, 0xFFE2, 0x21D2, 0x21D4, 0x2200, - 0x2203, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0x2220, 0x22A5, 0x2312, 0x2202, - 0x2207, 0x2261, 0x2252, 0x226A, 0x226B, 0x221A, 0x223D, 0x221D, - 0x2235, 0x222B, 0x222C, 0, 0, 0, 0, 0, - 0, 0, 0x212B, 0x2030, 0x266F, 0x266D, 0x266A, 0x2020, - 0x2021, 0x00B6, 0, 0, 0, 0, 0x25EF, -}; -static const unsigned short euc_to_utf8_A2_x0213[] = { - 0x25C6, 0x25A1, 0x25A0, 0x25B3, 0x25B2, 0x25BD, 0x25BC, - 0x203B, 0x3012, 0x2192, 0x2190, 0x2191, 0x2193, 0x3013, 0xFF07, - 0xFF02, 0xFF0D, 0xFF5E, 0x3033, 0x3034, 0x3035, 0x303B, 0x303C, - 0x30FF, 0x309F, 0x2208, 0x220B, 0x2286, 0x2287, 0x2282, 0x2283, - 0x222A, 0x2229, 0x2284, 0x2285, 0x228A, 0x228B, 0x2209, 0x2205, - 0x2305, 0x2306, 0x2227, 0x2228, 0x00AC, 0x21D2, 0x21D4, 0x2200, - 0x2203, 0x2295, 0x2296, 0x2297, 0x2225, 0x2226, 0xFF5F, 0xFF60, - 0x3018, 0x3019, 0x3016, 0x3017, 0x2220, 0x22A5, 0x2312, 0x2202, - 0x2207, 0x2261, 0x2252, 0x226A, 0x226B, 0x221A, 0x223D, 0x221D, - 0x2235, 0x222B, 0x222C, 0x2262, 0x2243, 0x2245, 0x2248, 0x2276, - 0x2277, 0x2194, 0x212B, 0x2030, 0x266F, 0x266D, 0x266A, 0x2020, - 0x2021, 0x00B6, 0x266E, 0x266B, 0x266C, 0x2669, 0x25EF, -}; -static const unsigned short euc_to_utf8_A3[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0xFF10, 0xFF11, 0xFF12, 0xFF13, 0xFF14, 0xFF15, 0xFF16, 0xFF17, - 0xFF18, 0xFF19, 0, 0, 0, 0, 0, 0, - 0, 0xFF21, 0xFF22, 0xFF23, 0xFF24, 0xFF25, 0xFF26, 0xFF27, - 0xFF28, 0xFF29, 0xFF2A, 0xFF2B, 0xFF2C, 0xFF2D, 0xFF2E, 0xFF2F, - 0xFF30, 0xFF31, 0xFF32, 0xFF33, 0xFF34, 0xFF35, 0xFF36, 0xFF37, - 0xFF38, 0xFF39, 0xFF3A, 0, 0, 0, 0, 0, - 0, 0xFF41, 0xFF42, 0xFF43, 0xFF44, 0xFF45, 0xFF46, 0xFF47, - 0xFF48, 0xFF49, 0xFF4A, 0xFF4B, 0xFF4C, 0xFF4D, 0xFF4E, 0xFF4F, - 0xFF50, 0xFF51, 0xFF52, 0xFF53, 0xFF54, 0xFF55, 0xFF56, 0xFF57, - 0xFF58, 0xFF59, 0xFF5A, 0, 0, 0, 0, -}; -static const unsigned short euc_to_utf8_A3_x0213[] = { - 0x25B7, 0x25B6, 0x25C1, 0x25C0, 0x2197, 0x2198, 0x2196, - 0x2199, 0x21C4, 0x21E8, 0x21E6, 0x21E7, 0x21E9, 0x2934, 0x2935, - 0xFF10, 0xFF11, 0xFF12, 0xFF13, 0xFF14, 0xFF15, 0xFF16, 0xFF17, - 0xFF18, 0xFF19, 0x29BF, 0x25C9, 0x303D, 0xFE46, 0xFE45, 0x25E6, - 0x2022, 0xFF21, 0xFF22, 0xFF23, 0xFF24, 0xFF25, 0xFF26, 0xFF27, - 0xFF28, 0xFF29, 0xFF2A, 0xFF2B, 0xFF2C, 0xFF2D, 0xFF2E, 0xFF2F, - 0xFF30, 0xFF31, 0xFF32, 0xFF33, 0xFF34, 0xFF35, 0xFF36, 0xFF37, - 0xFF38, 0xFF39, 0xFF3A, 0x2213, 0x2135, 0x210F, 0x33CB, 0x2113, - 0x2127, 0xFF41, 0xFF42, 0xFF43, 0xFF44, 0xFF45, 0xFF46, 0xFF47, - 0xFF48, 0xFF49, 0xFF4A, 0xFF4B, 0xFF4C, 0xFF4D, 0xFF4E, 0xFF4F, - 0xFF50, 0xFF51, 0xFF52, 0xFF53, 0xFF54, 0xFF55, 0xFF56, 0xFF57, - 0xFF58, 0xFF59, 0xFF5A, 0x30A0, 0x2013, 0x29FA, 0x29FB, -}; -static const unsigned short euc_to_utf8_A4[] = { - 0x3041, 0x3042, 0x3043, 0x3044, 0x3045, 0x3046, 0x3047, - 0x3048, 0x3049, 0x304A, 0x304B, 0x304C, 0x304D, 0x304E, 0x304F, - 0x3050, 0x3051, 0x3052, 0x3053, 0x3054, 0x3055, 0x3056, 0x3057, - 0x3058, 0x3059, 0x305A, 0x305B, 0x305C, 0x305D, 0x305E, 0x305F, - 0x3060, 0x3061, 0x3062, 0x3063, 0x3064, 0x3065, 0x3066, 0x3067, - 0x3068, 0x3069, 0x306A, 0x306B, 0x306C, 0x306D, 0x306E, 0x306F, - 0x3070, 0x3071, 0x3072, 0x3073, 0x3074, 0x3075, 0x3076, 0x3077, - 0x3078, 0x3079, 0x307A, 0x307B, 0x307C, 0x307D, 0x307E, 0x307F, - 0x3080, 0x3081, 0x3082, 0x3083, 0x3084, 0x3085, 0x3086, 0x3087, - 0x3088, 0x3089, 0x308A, 0x308B, 0x308C, 0x308D, 0x308E, 0x308F, - 0x3090, 0x3091, 0x3092, 0x3093, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short euc_to_utf8_A4_x0213[] = { - 0x3041, 0x3042, 0x3043, 0x3044, 0x3045, 0x3046, 0x3047, - 0x3048, 0x3049, 0x304A, 0x304B, 0x304C, 0x304D, 0x304E, 0x304F, - 0x3050, 0x3051, 0x3052, 0x3053, 0x3054, 0x3055, 0x3056, 0x3057, - 0x3058, 0x3059, 0x305A, 0x305B, 0x305C, 0x305D, 0x305E, 0x305F, - 0x3060, 0x3061, 0x3062, 0x3063, 0x3064, 0x3065, 0x3066, 0x3067, - 0x3068, 0x3069, 0x306A, 0x306B, 0x306C, 0x306D, 0x306E, 0x306F, - 0x3070, 0x3071, 0x3072, 0x3073, 0x3074, 0x3075, 0x3076, 0x3077, - 0x3078, 0x3079, 0x307A, 0x307B, 0x307C, 0x307D, 0x307E, 0x307F, - 0x3080, 0x3081, 0x3082, 0x3083, 0x3084, 0x3085, 0x3086, 0x3087, - 0x3088, 0x3089, 0x308A, 0x308B, 0x308C, 0x308D, 0x308E, 0x308F, - 0x3090, 0x3091, 0x3092, 0x3093, 0x3094, 0x3095, 0x3096, /*0x304B*/ 0x309A, - /*0x304D*/ 0x309A, /*0x304F*/ 0x309A, /*0x3051*/ 0x309A, /*0x3053*/ 0x309A, 0, 0, 0, -}; -static const unsigned short euc_to_utf8_A5[] = { - 0x30A1, 0x30A2, 0x30A3, 0x30A4, 0x30A5, 0x30A6, 0x30A7, - 0x30A8, 0x30A9, 0x30AA, 0x30AB, 0x30AC, 0x30AD, 0x30AE, 0x30AF, - 0x30B0, 0x30B1, 0x30B2, 0x30B3, 0x30B4, 0x30B5, 0x30B6, 0x30B7, - 0x30B8, 0x30B9, 0x30BA, 0x30BB, 0x30BC, 0x30BD, 0x30BE, 0x30BF, - 0x30C0, 0x30C1, 0x30C2, 0x30C3, 0x30C4, 0x30C5, 0x30C6, 0x30C7, - 0x30C8, 0x30C9, 0x30CA, 0x30CB, 0x30CC, 0x30CD, 0x30CE, 0x30CF, - 0x30D0, 0x30D1, 0x30D2, 0x30D3, 0x30D4, 0x30D5, 0x30D6, 0x30D7, - 0x30D8, 0x30D9, 0x30DA, 0x30DB, 0x30DC, 0x30DD, 0x30DE, 0x30DF, - 0x30E0, 0x30E1, 0x30E2, 0x30E3, 0x30E4, 0x30E5, 0x30E6, 0x30E7, - 0x30E8, 0x30E9, 0x30EA, 0x30EB, 0x30EC, 0x30ED, 0x30EE, 0x30EF, - 0x30F0, 0x30F1, 0x30F2, 0x30F3, 0x30F4, 0x30F5, 0x30F6, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short euc_to_utf8_A5_x0213[] = { - 0x30A1, 0x30A2, 0x30A3, 0x30A4, 0x30A5, 0x30A6, 0x30A7, - 0x30A8, 0x30A9, 0x30AA, 0x30AB, 0x30AC, 0x30AD, 0x30AE, 0x30AF, - 0x30B0, 0x30B1, 0x30B2, 0x30B3, 0x30B4, 0x30B5, 0x30B6, 0x30B7, - 0x30B8, 0x30B9, 0x30BA, 0x30BB, 0x30BC, 0x30BD, 0x30BE, 0x30BF, - 0x30C0, 0x30C1, 0x30C2, 0x30C3, 0x30C4, 0x30C5, 0x30C6, 0x30C7, - 0x30C8, 0x30C9, 0x30CA, 0x30CB, 0x30CC, 0x30CD, 0x30CE, 0x30CF, - 0x30D0, 0x30D1, 0x30D2, 0x30D3, 0x30D4, 0x30D5, 0x30D6, 0x30D7, - 0x30D8, 0x30D9, 0x30DA, 0x30DB, 0x30DC, 0x30DD, 0x30DE, 0x30DF, - 0x30E0, 0x30E1, 0x30E2, 0x30E3, 0x30E4, 0x30E5, 0x30E6, 0x30E7, - 0x30E8, 0x30E9, 0x30EA, 0x30EB, 0x30EC, 0x30ED, 0x30EE, 0x30EF, - 0x30F0, 0x30F1, 0x30F2, 0x30F3, 0x30F4, 0x30F5, 0x30F6, /*0x30AB*/ 0x309A, - /*0x30AD*/ 0x309A, /*0x30AF*/ 0x309A, /*0x30B1*/ 0x309A, /*0x30B3*/ 0x309A, /*0x30BB*/ 0x309A, /*0x30C4*/ 0x309A, /*0x30C8*/ 0x309A, -}; -static const unsigned short euc_to_utf8_A6[] = { - 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, - 0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F, - 0x03A0, 0x03A1, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, 0x03A8, - 0x03A9, 0, 0, 0, 0, 0, 0, 0, - 0, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, - 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, - 0x03C0, 0x03C1, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7, 0x03C8, - 0x03C9, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short euc_to_utf8_A6_x0213[] = { - 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, - 0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F, - 0x03A0, 0x03A1, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, 0x03A8, - 0x03A9, 0x2664, 0x2660, 0x2662, 0x2666, 0x2661, 0x2665, 0x2667, - 0x2663, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, - 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, - 0x03C0, 0x03C1, 0x03C3, 0x03C4, 0x03C5, 0x03C6, 0x03C7, 0x03C8, - 0x03C9, 0x03C2, 0x24F5, 0x24F6, 0x24F7, 0x24F8, 0x24F9, 0x24FA, - 0x24FB, 0x24FC, 0x24FD, 0x24FE, 0x2616, 0x2617, 0x3020, 0x260E, - 0x2600, 0x2601, 0x2602, 0x2603, 0x2668, 0x25B1, 0x31F0, 0x31F1, - 0x31F2, 0x31F3, 0x31F4, 0x31F5, 0x31F6, 0x31F7, 0x31F8, 0x31F9, - /*0x31F7*/ 0x309A, 0x31FA, 0x31FB, 0x31FC, 0x31FD, 0x31FE, 0x31FF, -}; -static const unsigned short euc_to_utf8_A7[] = { - 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0401, - 0x0416, 0x0417, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, - 0x041E, 0x041F, 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, - 0x0426, 0x0427, 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, - 0x042E, 0x042F, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0451, - 0x0436, 0x0437, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, - 0x043E, 0x043F, 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, - 0x0446, 0x0447, 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, - 0x044E, 0x044F, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short euc_to_utf8_A7_x0213[] = { - 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0401, - 0x0416, 0x0417, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, - 0x041E, 0x041F, 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, - 0x0426, 0x0427, 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, - 0x042E, 0x042F, 0x23BE, 0x23BF, 0x23C0, 0x23C1, 0x23C2, 0x23C3, - 0x23C4, 0x23C5, 0x23C6, 0x23C7, 0x23C8, 0x23C9, 0x23CA, 0x23CB, - 0x23CC, 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0451, - 0x0436, 0x0437, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, - 0x043E, 0x043F, 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, - 0x0446, 0x0447, 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, - 0x044E, 0x044F, 0x30F7, 0x30F8, 0x30F9, 0x30FA, 0x22DA, 0x22DB, - 0x2153, 0x2154, 0x2155, 0x2713, 0x2318, 0x2423, 0x23CE, -}; -static const unsigned short euc_to_utf8_A8[] = { - 0x2500, 0x2502, 0x250C, 0x2510, 0x2518, 0x2514, 0x251C, - 0x252C, 0x2524, 0x2534, 0x253C, 0x2501, 0x2503, 0x250F, 0x2513, - 0x251B, 0x2517, 0x2523, 0x2533, 0x252B, 0x253B, 0x254B, 0x2520, - 0x252F, 0x2528, 0x2537, 0x253F, 0x251D, 0x2530, 0x2525, 0x2538, - 0x2542, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short euc_to_utf8_A8_x0213[] = { - 0x2500, 0x2502, 0x250C, 0x2510, 0x2518, 0x2514, 0x251C, - 0x252C, 0x2524, 0x2534, 0x253C, 0x2501, 0x2503, 0x250F, 0x2513, - 0x251B, 0x2517, 0x2523, 0x2533, 0x252B, 0x253B, 0x254B, 0x2520, - 0x252F, 0x2528, 0x2537, 0x253F, 0x251D, 0x2530, 0x2525, 0x2538, - 0x2542, 0x3251, 0x3252, 0x3253, 0x3254, 0x3255, 0x3256, 0x3257, - 0x3258, 0x3259, 0x325A, 0x325B, 0x325C, 0x325D, 0x325E, 0x325F, - 0x32B1, 0x32B2, 0x32B3, 0x32B4, 0x32B5, 0x32B6, 0x32B7, 0x32B8, - 0x32B9, 0x32BA, 0x32BB, 0x32BC, 0x32BD, 0x32BE, 0x32BF, 0, - 0, 0, 0, 0, 0, 0, 0, 0x25D0, - 0x25D1, 0x25D2, 0x25D3, 0x203C, 0x2047, 0x2048, 0x2049, 0x01CD, - 0x01CE, 0x01D0, 0x1E3E, 0x1E3F, 0x01F8, 0x01F9, 0x01D1, 0x01D2, - 0x01D4, 0x01D6, 0x01D8, 0x01DA, 0x01DC, 0, 0, -}; -static const unsigned short euc_to_utf8_A9[] = { - 0x2460, 0x2461, 0x2462, 0x2463, 0x2464, 0x2465, 0x2466, - 0x2467, 0x2468, 0x2469, 0x246A, 0x246B, 0x246C, 0x246D, 0x246E, - 0x246F, 0x2470, 0x2471, 0x2472, 0x2473, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0x2474, - 0x2475, 0x2476, 0x2477, 0x2478, 0x2479, 0x247A, 0x247B, 0x247C, - 0x247D, 0x247E, 0x247F, 0x2480, 0x2481, 0x2482, 0x2483, 0x2484, - 0x2485, 0x2486, 0x2487, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0x2776, 0x2777, 0x2778, - 0x2779, 0x277A, 0x277B, 0x277C, 0x277D, 0x277E, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0x2488, 0x2489, 0x248A, 0x248B, 0x248C, 0x248D, - 0x248E, 0x248F, 0x2490, 0, 0, 0, 0, -}; -static const unsigned short euc_to_utf8_A9_x0213[] = { - 0x20AC, 0x00A0, 0x00A1, 0x00A4, 0x00A6, 0x00A9, 0x00AA, - 0x00AB, 0x00AD, 0x00AE, 0x00AF, 0x00B2, 0x00B3, 0x00B7, 0x00B8, - 0x00B9, 0x00BA, 0x00BB, 0x00BC, 0x00BD, 0x00BE, 0x00BF, 0x00C0, - 0x00C1, 0x00C2, 0x00C3, 0x00C4, 0x00C5, 0x00C6, 0x00C7, 0x00C8, - 0x00C9, 0x00CA, 0x00CB, 0x00CC, 0x00CD, 0x00CE, 0x00CF, 0x00D0, - 0x00D1, 0x00D2, 0x00D3, 0x00D4, 0x00D5, 0x00D6, 0x00D8, 0x00D9, - 0x00DA, 0x00DB, 0x00DC, 0x00DD, 0x00DE, 0x00DF, 0x00E0, 0x00E1, - 0x00E2, 0x00E3, 0x00E4, 0x00E5, 0x00E6, 0x00E7, 0x00E8, 0x00E9, - 0x00EA, 0x00EB, 0x00EC, 0x00ED, 0x00EE, 0x00EF, 0x00F0, 0x00F1, - 0x00F2, 0x00F3, 0x00F4, 0x00F5, 0x00F6, 0x00F8, 0x00F9, 0x00FA, - 0x00FB, 0x00FC, 0x00FD, 0x00FE, 0x00FF, 0x0100, 0x012A, 0x016A, - 0x0112, 0x014C, 0x0101, 0x012B, 0x016B, 0x0113, 0x014D, -}; -static const unsigned short euc_to_utf8_AA[] = { - 0x2160, 0x2161, 0x2162, 0x2163, 0x2164, 0x2165, 0x2166, - 0x2167, 0x2168, 0x2169, 0x216A, 0x216B, 0, 0, 0, - 0, 0, 0, 0, 0, 0x2170, 0x2171, 0x2172, - 0x2173, 0x2174, 0x2175, 0x2176, 0x2177, 0x2178, 0x2179, 0x217A, - 0x217B, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0x249C, 0x249D, 0x249E, - 0x249F, 0x24A0, 0x24A1, 0x24A2, 0x24A3, 0x24A4, 0x24A5, 0x24A6, - 0x24A7, 0x24A8, 0x24A9, 0x24AA, 0x24AB, 0x24AC, 0x24AD, 0x24AE, - 0x24AF, 0x24B0, 0x24B1, 0x24B2, 0x24B3, 0x24B4, 0x24B5, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short euc_to_utf8_AA_x0213[] = { - 0x0104, 0x02D8, 0x0141, 0x013D, 0x015A, 0x0160, 0x015E, - 0x0164, 0x0179, 0x017D, 0x017B, 0x0105, 0x02DB, 0x0142, 0x013E, - 0x015B, 0x02C7, 0x0161, 0x015F, 0x0165, 0x017A, 0x02DD, 0x017E, - 0x017C, 0x0154, 0x0102, 0x0139, 0x0106, 0x010C, 0x0118, 0x011A, - 0x010E, 0x0143, 0x0147, 0x0150, 0x0158, 0x016E, 0x0170, 0x0162, - 0x0155, 0x0103, 0x013A, 0x0107, 0x010D, 0x0119, 0x011B, 0x010F, - 0x0111, 0x0144, 0x0148, 0x0151, 0x0159, 0x016F, 0x0171, 0x0163, - 0x02D9, 0x0108, 0x011C, 0x0124, 0x0134, 0x015C, 0x016C, 0x0109, - 0x011D, 0x0125, 0x0135, 0x015D, 0x016D, 0x0271, 0x028B, 0x027E, - 0x0283, 0x0292, 0x026C, 0x026E, 0x0279, 0x0288, 0x0256, 0x0273, - 0x027D, 0x0282, 0x0290, 0x027B, 0x026D, 0x025F, 0x0272, 0x029D, - 0x028E, 0x0261, 0x014B, 0x0270, 0x0281, 0x0127, 0x0295, -}; -static const unsigned short euc_to_utf8_AB[] = { - 0x339C, 0x339F, 0x339D, 0x33A0, 0x33A4, 0, 0x33A1, - 0x33A5, 0x339E, 0x33A2, 0x338E, 0, 0x338F, 0x33C4, 0x3396, - 0x3397, 0x2113, 0x3398, 0x33B3, 0x33B2, 0x33B1, 0x33B0, 0x2109, - 0x33D4, 0x33CB, 0x3390, 0x3385, 0x3386, 0x3387, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0x2116, 0x33CD, 0x2121, 0, -}; -static const unsigned short euc_to_utf8_AB_x0213[] = { - 0x0294, 0x0266, 0x0298, 0x01C2, 0x0253, 0x0257, 0x0284, - 0x0260, 0x0193, 0x0153, 0x0152, 0x0268, 0x0289, 0x0258, 0x0275, - 0x0259, 0x025C, 0x025E, 0x0250, 0x026F, 0x028A, 0x0264, 0x028C, - 0x0254, 0x0251, 0x0252, 0x028D, 0x0265, 0x02A2, 0x02A1, 0x0255, - 0x0291, 0x027A, 0x0267, 0x025A, /*0x00E6*/ 0x0300, 0x01FD, 0x1F70, 0x1F71, - /*0x0254*/ 0x0300, /*0x0254*/ 0x0301, /*0x028C*/ 0x0300, /*0x028C*/ 0x0301, /*0x0259*/ 0x0300, /*0x0259*/ 0x0301, /*0x025A*/ 0x0300, /*0x025A*/ 0x0301, - 0x1F72, 0x1F73, 0x0361, 0x02C8, 0x02CC, 0x02D0, 0x02D1, 0x0306, - 0x203F, 0x030B, /*0*/ 0x0301, 0x0304, /*0*/ 0x0300, 0x030F, 0x030C, 0x0302, - /*0*/ 0x02E5, 0x02E6, 0x02E7, 0x02E8, /*0*/ 0x02E9, /*0x02E9*/ 0x02E5, /*0x02E5*/ 0x02E9, 0x0325, - 0x032C, 0x0339, 0x031C, 0x031F, 0x0320, 0x0308, 0x033D, 0x0329, - 0x032F, 0x02DE, 0x0324, 0x0330, 0x033C, 0x0334, 0x031D, 0x031E, - 0x0318, 0x0319, 0x032A, 0x033A, 0x033B, 0x0303, 0x031A, -}; -static const unsigned short euc_to_utf8_AC[] = { - 0x2664, 0x2667, 0x2661, 0x2662, 0x2660, 0x2663, 0x2665, - 0x2666, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0x3020, 0x260E, 0x3004, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0x261E, 0x261C, 0x261D, 0x261F, 0x21C6, 0x21C4, 0x21C5, - 0, 0x21E8, 0x21E6, 0x21E7, 0x21E9, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short euc_to_utf8_AC_mac[] = { - 0x2664, 0x2667, 0x2661, 0x2662, 0x2660, 0x2663, 0x2665, - 0x2666, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0x3020, 0x260E, 0x3004, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0x261E, 0x261C, 0x261D, 0x261F, 0x21C6, 0x21C4, 0x21C5, - 0, 0x21E8, 0x21E6, 0x21E7, 0x21E9, 0x2192, 0x2190, 0x2191, - 0x2193, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short euc_to_utf8_AC_x0213[] = { - 0x2776, 0x2777, 0x2778, 0x2779, 0x277A, 0x277B, 0x277C, - 0x277D, 0x277E, 0x277F, 0x24EB, 0x24EC, 0x24ED, 0x24EE, 0x24EF, - 0x24F0, 0x24F1, 0x24F2, 0x24F3, 0x24F4, 0x2170, 0x2171, 0x2172, - 0x2173, 0x2174, 0x2175, 0x2176, 0x2177, 0x2178, 0x2179, 0x217A, - 0x217B, 0x24D0, 0x24D1, 0x24D2, 0x24D3, 0x24D4, 0x24D5, 0x24D6, - 0x24D7, 0x24D8, 0x24D9, 0x24DA, 0x24DB, 0x24DC, 0x24DD, 0x24DE, - 0x24DF, 0x24E0, 0x24E1, 0x24E2, 0x24E3, 0x24E4, 0x24E5, 0x24E6, - 0x24E7, 0x24E8, 0x24E9, 0x32D0, 0x32D1, 0x32D2, 0x32D3, 0x32D4, - 0x32D5, 0x32D6, 0x32D7, 0x32D8, 0x32D9, 0x32DA, 0x32DB, 0x32DC, - 0x32DD, 0x32DE, 0x32DF, 0x32E0, 0x32E1, 0x32E2, 0x32E3, 0x32FA, - 0x32E9, 0x32E5, 0x32ED, 0x32EC, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0x2051, 0x2042, -}; -static const unsigned short euc_to_utf8_AD[] = { - 0x2460, 0x2461, 0x2462, 0x2463, 0x2464, 0x2465, 0x2466, - 0x2467, 0x2468, 0x2469, 0x246A, 0x246B, 0x246C, 0x246D, 0x246E, - 0x246F, 0x2470, 0x2471, 0x2472, 0x2473, 0x2160, 0x2161, 0x2162, - 0x2163, 0x2164, 0x2165, 0x2166, 0x2167, 0x2168, 0x2169, 0, - 0x3349, 0x3314, 0x3322, 0x334D, 0x3318, 0x3327, 0x3303, 0x3336, - 0x3351, 0x3357, 0x330D, 0x3326, 0x3323, 0x332B, 0x334A, 0x333B, - 0x339C, 0x339D, 0x339E, 0x338E, 0x338F, 0x33C4, 0x33A1, 0, - 0, 0, 0, 0, 0, 0, 0, 0x337B, - 0x301D, 0x301F, 0x2116, 0x33CD, 0x2121, 0x32A4, 0x32A5, 0x32A6, - 0x32A7, 0x32A8, 0x3231, 0x3232, 0x3239, 0x337E, 0x337D, 0x337C, - 0x2252, 0x2261, 0x222B, 0x222E, 0x2211, 0x221A, 0x22A5, 0x2220, - 0x221F, 0x22BF, 0x2235, 0x2229, 0x222A, 0, 0x3299, -}; -static const unsigned short euc_to_utf8_AD_mac[] = { - 0x65E5, 0x6708, 0x706B, 0x6C34, 0x6728, 0x91D1, 0x571F, - 0x796D, 0x795D, 0x81EA, 0x81F3, 0x3239, 0x547C, 0x3231, 0x8CC7, - 0x540D, 0x3232, 0x5B66, 0x8CA1, 0x793E, 0x7279, 0x76E3, 0x4F01, - 0x5354, 0x52B4, 0x2165, 0x2166, 0x2167, 0x2168, 0x2169, 0, - 0x3349, 0x3314, 0x3322, 0x334D, 0x3318, 0x3327, 0x3303, 0x3336, - 0x3351, 0x3357, 0x330D, 0x3326, 0x3323, 0x332B, 0x334A, 0x333B, - 0x339C, 0x339D, 0x339E, 0x338E, 0x338F, 0x33C4, 0x33A1, 0, - 0, 0, 0, 0, 0, 0, 0, 0x337B, - 0x301D, 0x301F, 0x2116, 0x33CD, 0x2121, 0x32A4, 0x32A5, 0x32A6, - 0x32A7, 0x32A8, 0x3231, 0x3232, 0x3239, 0x337E, 0x337D, 0x337C, - 0x2252, 0x5927, 0x5C0F, 0x32A4, 0x32A5, 0x32A6, 0x32A7, 0x32A8, - 0x533B, 0x8CA1, 0x512A, 0x52B4, 0x5370, 0x63A7, 0x79D8, -}; -static const unsigned short euc_to_utf8_AD_x0213[] = { - 0x2460, 0x2461, 0x2462, 0x2463, 0x2464, 0x2465, 0x2466, - 0x2467, 0x2468, 0x2469, 0x246A, 0x246B, 0x246C, 0x246D, 0x246E, - 0x246F, 0x2470, 0x2471, 0x2472, 0x2473, 0x2160, 0x2161, 0x2162, - 0x2163, 0x2164, 0x2165, 0x2166, 0x2167, 0x2168, 0x2169, 0x216A, - 0x3349, 0x3314, 0x3322, 0x334D, 0x3318, 0x3327, 0x3303, 0x3336, - 0x3351, 0x3357, 0x330D, 0x3326, 0x3323, 0x332B, 0x334A, 0x333B, - 0x339C, 0x339D, 0x339E, 0x338E, 0x338F, 0x33C4, 0x33A1, 0x216B, - 0, 0, 0, 0, 0, 0, 0, 0x337B, - 0x301D, 0x301F, 0x2116, 0x33CD, 0x2121, 0x32A4, 0x32A5, 0x32A6, - 0x32A7, 0x32A8, 0x3231, 0x3232, 0x3239, 0x337E, 0x337D, 0x337C, - 0x2252, 0x2261, 0x222B, 0x222E, 0x2211, 0x221A, 0x22A5, 0x2220, - 0x221F, 0x22BF, 0x2235, 0x2229, 0x222A, 0x2756, 0x261E, -}; -static const unsigned short euc_to_utf8_AE[] = { - 0x3349, 0x3322, 0x334D, 0x3314, 0x3316, 0x3305, 0x3333, - 0x334E, 0x3303, 0x3336, 0x3318, 0x3315, 0x3327, 0x3351, 0x334A, - 0x3339, 0x3357, 0x330D, 0x3342, 0x3323, 0x3326, 0x333B, 0x332B, - 0, 0, 0, 0, 0, 0, 0, 0x3300, - 0x331E, 0x332A, 0x3331, 0x3347, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0x337E, - 0x337D, 0x337C, 0x337B, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0x337F, 0, 0, -}; -static const unsigned short euc_to_utf8_AE_x0213[] = { - 0x4FF1, 0xD840 /*0xDC0B*/, 0x3402, 0x4E28, 0x4E2F, 0x4E30, 0x4E8D, - 0x4EE1, 0x4EFD, 0x4EFF, 0x4F03, 0x4F0B, 0x4F60, 0x4F48, 0x4F49, - 0x4F56, 0x4F5F, 0x4F6A, 0x4F6C, 0x4F7E, 0x4F8A, 0x4F94, 0x4F97, - 0xFA30, 0x4FC9, 0x4FE0, 0x5001, 0x5002, 0x500E, 0x5018, 0x5027, - 0x502E, 0x5040, 0x503B, 0x5041, 0x5094, 0x50CC, 0x50F2, 0x50D0, - 0x50E6, 0xFA31, 0x5106, 0x5103, 0x510B, 0x511E, 0x5135, 0x514A, - 0xFA32, 0x5155, 0x5157, 0x34B5, 0x519D, 0x51C3, 0x51CA, 0x51DE, - 0x51E2, 0x51EE, 0x5201, 0x34DB, 0x5213, 0x5215, 0x5249, 0x5257, - 0x5261, 0x5293, 0x52C8, 0xFA33, 0x52CC, 0x52D0, 0x52D6, 0x52DB, - 0xFA34, 0x52F0, 0x52FB, 0x5300, 0x5307, 0x531C, 0xFA35, 0x5361, - 0x5363, 0x537D, 0x5393, 0x539D, 0x53B2, 0x5412, 0x5427, 0x544D, - 0x549C, 0x546B, 0x5474, 0x547F, 0x5488, 0x5496, 0x54A1, -}; -static const unsigned short euc_to_utf8_AF[] = { - 0x222E, 0x221F, 0x22BF, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0x301D, 0x301F, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0x3094, 0, 0x30F7, 0x30F8, 0x30F9, 0x30FA, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short euc_to_utf8_AF_x0213[] = { - 0x54A9, 0x54C6, 0x54FF, 0x550E, 0x552B, 0x5535, 0x5550, - 0x555E, 0x5581, 0x5586, 0x558E, 0xFA36, 0x55AD, 0x55CE, 0xFA37, - 0x5608, 0x560E, 0x563B, 0x5649, 0x5676, 0x5666, 0xFA38, 0x566F, - 0x5671, 0x5672, 0x5699, 0x569E, 0x56A9, 0x56AC, 0x56B3, 0x56C9, - 0x56CA, 0x570A, 0xD844 /*0xDE3D*/, 0x5721, 0x572F, 0x5733, 0x5734, 0x5770, - 0x5777, 0x577C, 0x579C, 0xFA0F, 0xD844 /*0xDF1B*/, 0x57B8, 0x57C7, 0x57C8, - 0x57CF, 0x57E4, 0x57ED, 0x57F5, 0x57F6, 0x57FF, 0x5809, 0xFA10, - 0x5861, 0x5864, 0xFA39, 0x587C, 0x5889, 0x589E, 0xFA3A, 0x58A9, - 0xD845 /*0xDC6E*/, 0x58D2, 0x58CE, 0x58D4, 0x58DA, 0x58E0, 0x58E9, 0x590C, - 0x8641, 0x595D, 0x596D, 0x598B, 0x5992, 0x59A4, 0x59C3, 0x59D2, - 0x59DD, 0x5A13, 0x5A23, 0x5A67, 0x5A6D, 0x5A77, 0x5A7E, 0x5A84, - 0x5A9E, 0x5AA7, 0x5AC4, 0xD846 /*0xDCBD*/, 0x5B19, 0x5B25, 0x525D, -}; -static const unsigned short euc_to_utf8_B0[] = { - 0x4E9C, 0x5516, 0x5A03, 0x963F, 0x54C0, 0x611B, 0x6328, - 0x59F6, 0x9022, 0x8475, 0x831C, 0x7A50, 0x60AA, 0x63E1, 0x6E25, - 0x65ED, 0x8466, 0x82A6, 0x9BF5, 0x6893, 0x5727, 0x65A1, 0x6271, - 0x5B9B, 0x59D0, 0x867B, 0x98F4, 0x7D62, 0x7DBE, 0x9B8E, 0x6216, - 0x7C9F, 0x88B7, 0x5B89, 0x5EB5, 0x6309, 0x6697, 0x6848, 0x95C7, - 0x978D, 0x674F, 0x4EE5, 0x4F0A, 0x4F4D, 0x4F9D, 0x5049, 0x56F2, - 0x5937, 0x59D4, 0x5A01, 0x5C09, 0x60DF, 0x610F, 0x6170, 0x6613, - 0x6905, 0x70BA, 0x754F, 0x7570, 0x79FB, 0x7DAD, 0x7DEF, 0x80C3, - 0x840E, 0x8863, 0x8B02, 0x9055, 0x907A, 0x533B, 0x4E95, 0x4EA5, - 0x57DF, 0x80B2, 0x90C1, 0x78EF, 0x4E00, 0x58F1, 0x6EA2, 0x9038, - 0x7A32, 0x8328, 0x828B, 0x9C2F, 0x5141, 0x5370, 0x54BD, 0x54E1, - 0x56E0, 0x59FB, 0x5F15, 0x98F2, 0x6DEB, 0x80E4, 0x852D, -}; -static const unsigned short euc_to_utf8_B1[] = { - 0x9662, 0x9670, 0x96A0, 0x97FB, 0x540B, 0x53F3, 0x5B87, - 0x70CF, 0x7FBD, 0x8FC2, 0x96E8, 0x536F, 0x9D5C, 0x7ABA, 0x4E11, - 0x7893, 0x81FC, 0x6E26, 0x5618, 0x5504, 0x6B1D, 0x851A, 0x9C3B, - 0x59E5, 0x53A9, 0x6D66, 0x74DC, 0x958F, 0x5642, 0x4E91, 0x904B, - 0x96F2, 0x834F, 0x990C, 0x53E1, 0x55B6, 0x5B30, 0x5F71, 0x6620, - 0x66F3, 0x6804, 0x6C38, 0x6CF3, 0x6D29, 0x745B, 0x76C8, 0x7A4E, - 0x9834, 0x82F1, 0x885B, 0x8A60, 0x92ED, 0x6DB2, 0x75AB, 0x76CA, - 0x99C5, 0x60A6, 0x8B01, 0x8D8A, 0x95B2, 0x698E, 0x53AD, 0x5186, - 0x5712, 0x5830, 0x5944, 0x5BB4, 0x5EF6, 0x6028, 0x63A9, 0x63F4, - 0x6CBF, 0x6F14, 0x708E, 0x7114, 0x7159, 0x71D5, 0x733F, 0x7E01, - 0x8276, 0x82D1, 0x8597, 0x9060, 0x925B, 0x9D1B, 0x5869, 0x65BC, - 0x6C5A, 0x7525, 0x51F9, 0x592E, 0x5965, 0x5F80, 0x5FDC, -}; -static const unsigned short euc_to_utf8_B2[] = { - 0x62BC, 0x65FA, 0x6A2A, 0x6B27, 0x6BB4, 0x738B, 0x7FC1, - 0x8956, 0x9D2C, 0x9D0E, 0x9EC4, 0x5CA1, 0x6C96, 0x837B, 0x5104, - 0x5C4B, 0x61B6, 0x81C6, 0x6876, 0x7261, 0x4E59, 0x4FFA, 0x5378, - 0x6069, 0x6E29, 0x7A4F, 0x97F3, 0x4E0B, 0x5316, 0x4EEE, 0x4F55, - 0x4F3D, 0x4FA1, 0x4F73, 0x52A0, 0x53EF, 0x5609, 0x590F, 0x5AC1, - 0x5BB6, 0x5BE1, 0x79D1, 0x6687, 0x679C, 0x67B6, 0x6B4C, 0x6CB3, - 0x706B, 0x73C2, 0x798D, 0x79BE, 0x7A3C, 0x7B87, 0x82B1, 0x82DB, - 0x8304, 0x8377, 0x83EF, 0x83D3, 0x8766, 0x8AB2, 0x5629, 0x8CA8, - 0x8FE6, 0x904E, 0x971E, 0x868A, 0x4FC4, 0x5CE8, 0x6211, 0x7259, - 0x753B, 0x81E5, 0x82BD, 0x86FE, 0x8CC0, 0x96C5, 0x9913, 0x99D5, - 0x4ECB, 0x4F1A, 0x89E3, 0x56DE, 0x584A, 0x58CA, 0x5EFB, 0x5FEB, - 0x602A, 0x6094, 0x6062, 0x61D0, 0x6212, 0x62D0, 0x6539, -}; -static const unsigned short euc_to_utf8_B3[] = { - 0x9B41, 0x6666, 0x68B0, 0x6D77, 0x7070, 0x754C, 0x7686, - 0x7D75, 0x82A5, 0x87F9, 0x958B, 0x968E, 0x8C9D, 0x51F1, 0x52BE, - 0x5916, 0x54B3, 0x5BB3, 0x5D16, 0x6168, 0x6982, 0x6DAF, 0x788D, - 0x84CB, 0x8857, 0x8A72, 0x93A7, 0x9AB8, 0x6D6C, 0x99A8, 0x86D9, - 0x57A3, 0x67FF, 0x86CE, 0x920E, 0x5283, 0x5687, 0x5404, 0x5ED3, - 0x62E1, 0x64B9, 0x683C, 0x6838, 0x6BBB, 0x7372, 0x78BA, 0x7A6B, - 0x899A, 0x89D2, 0x8D6B, 0x8F03, 0x90ED, 0x95A3, 0x9694, 0x9769, - 0x5B66, 0x5CB3, 0x697D, 0x984D, 0x984E, 0x639B, 0x7B20, 0x6A2B, - 0x6A7F, 0x68B6, 0x9C0D, 0x6F5F, 0x5272, 0x559D, 0x6070, 0x62EC, - 0x6D3B, 0x6E07, 0x6ED1, 0x845B, 0x8910, 0x8F44, 0x4E14, 0x9C39, - 0x53F6, 0x691B, 0x6A3A, 0x9784, 0x682A, 0x515C, 0x7AC3, 0x84B2, - 0x91DC, 0x938C, 0x565B, 0x9D28, 0x6822, 0x8305, 0x8431, -}; -static const unsigned short euc_to_utf8_B4[] = { - 0x7CA5, 0x5208, 0x82C5, 0x74E6, 0x4E7E, 0x4F83, 0x51A0, - 0x5BD2, 0x520A, 0x52D8, 0x52E7, 0x5DFB, 0x559A, 0x582A, 0x59E6, - 0x5B8C, 0x5B98, 0x5BDB, 0x5E72, 0x5E79, 0x60A3, 0x611F, 0x6163, - 0x61BE, 0x63DB, 0x6562, 0x67D1, 0x6853, 0x68FA, 0x6B3E, 0x6B53, - 0x6C57, 0x6F22, 0x6F97, 0x6F45, 0x74B0, 0x7518, 0x76E3, 0x770B, - 0x7AFF, 0x7BA1, 0x7C21, 0x7DE9, 0x7F36, 0x7FF0, 0x809D, 0x8266, - 0x839E, 0x89B3, 0x8ACC, 0x8CAB, 0x9084, 0x9451, 0x9593, 0x9591, - 0x95A2, 0x9665, 0x97D3, 0x9928, 0x8218, 0x4E38, 0x542B, 0x5CB8, - 0x5DCC, 0x73A9, 0x764C, 0x773C, 0x5CA9, 0x7FEB, 0x8D0B, 0x96C1, - 0x9811, 0x9854, 0x9858, 0x4F01, 0x4F0E, 0x5371, 0x559C, 0x5668, - 0x57FA, 0x5947, 0x5B09, 0x5BC4, 0x5C90, 0x5E0C, 0x5E7E, 0x5FCC, - 0x63EE, 0x673A, 0x65D7, 0x65E2, 0x671F, 0x68CB, 0x68C4, -}; -static const unsigned short euc_to_utf8_B5[] = { - 0x6A5F, 0x5E30, 0x6BC5, 0x6C17, 0x6C7D, 0x757F, 0x7948, - 0x5B63, 0x7A00, 0x7D00, 0x5FBD, 0x898F, 0x8A18, 0x8CB4, 0x8D77, - 0x8ECC, 0x8F1D, 0x98E2, 0x9A0E, 0x9B3C, 0x4E80, 0x507D, 0x5100, - 0x5993, 0x5B9C, 0x622F, 0x6280, 0x64EC, 0x6B3A, 0x72A0, 0x7591, - 0x7947, 0x7FA9, 0x87FB, 0x8ABC, 0x8B70, 0x63AC, 0x83CA, 0x97A0, - 0x5409, 0x5403, 0x55AB, 0x6854, 0x6A58, 0x8A70, 0x7827, 0x6775, - 0x9ECD, 0x5374, 0x5BA2, 0x811A, 0x8650, 0x9006, 0x4E18, 0x4E45, - 0x4EC7, 0x4F11, 0x53CA, 0x5438, 0x5BAE, 0x5F13, 0x6025, 0x6551, - 0x673D, 0x6C42, 0x6C72, 0x6CE3, 0x7078, 0x7403, 0x7A76, 0x7AAE, - 0x7B08, 0x7D1A, 0x7CFE, 0x7D66, 0x65E7, 0x725B, 0x53BB, 0x5C45, - 0x5DE8, 0x62D2, 0x62E0, 0x6319, 0x6E20, 0x865A, 0x8A31, 0x8DDD, - 0x92F8, 0x6F01, 0x79A6, 0x9B5A, 0x4EA8, 0x4EAB, 0x4EAC, -}; -static const unsigned short euc_to_utf8_B6[] = { - 0x4F9B, 0x4FA0, 0x50D1, 0x5147, 0x7AF6, 0x5171, 0x51F6, - 0x5354, 0x5321, 0x537F, 0x53EB, 0x55AC, 0x5883, 0x5CE1, 0x5F37, - 0x5F4A, 0x602F, 0x6050, 0x606D, 0x631F, 0x6559, 0x6A4B, 0x6CC1, - 0x72C2, 0x72ED, 0x77EF, 0x80F8, 0x8105, 0x8208, 0x854E, 0x90F7, - 0x93E1, 0x97FF, 0x9957, 0x9A5A, 0x4EF0, 0x51DD, 0x5C2D, 0x6681, - 0x696D, 0x5C40, 0x66F2, 0x6975, 0x7389, 0x6850, 0x7C81, 0x50C5, - 0x52E4, 0x5747, 0x5DFE, 0x9326, 0x65A4, 0x6B23, 0x6B3D, 0x7434, - 0x7981, 0x79BD, 0x7B4B, 0x7DCA, 0x82B9, 0x83CC, 0x887F, 0x895F, - 0x8B39, 0x8FD1, 0x91D1, 0x541F, 0x9280, 0x4E5D, 0x5036, 0x53E5, - 0x533A, 0x72D7, 0x7396, 0x77E9, 0x82E6, 0x8EAF, 0x99C6, 0x99C8, - 0x99D2, 0x5177, 0x611A, 0x865E, 0x55B0, 0x7A7A, 0x5076, 0x5BD3, - 0x9047, 0x9685, 0x4E32, 0x6ADB, 0x91E7, 0x5C51, 0x5C48, -}; -static const unsigned short euc_to_utf8_B7[] = { - 0x6398, 0x7A9F, 0x6C93, 0x9774, 0x8F61, 0x7AAA, 0x718A, - 0x9688, 0x7C82, 0x6817, 0x7E70, 0x6851, 0x936C, 0x52F2, 0x541B, - 0x85AB, 0x8A13, 0x7FA4, 0x8ECD, 0x90E1, 0x5366, 0x8888, 0x7941, - 0x4FC2, 0x50BE, 0x5211, 0x5144, 0x5553, 0x572D, 0x73EA, 0x578B, - 0x5951, 0x5F62, 0x5F84, 0x6075, 0x6176, 0x6167, 0x61A9, 0x63B2, - 0x643A, 0x656C, 0x666F, 0x6842, 0x6E13, 0x7566, 0x7A3D, 0x7CFB, - 0x7D4C, 0x7D99, 0x7E4B, 0x7F6B, 0x830E, 0x834A, 0x86CD, 0x8A08, - 0x8A63, 0x8B66, 0x8EFD, 0x981A, 0x9D8F, 0x82B8, 0x8FCE, 0x9BE8, - 0x5287, 0x621F, 0x6483, 0x6FC0, 0x9699, 0x6841, 0x5091, 0x6B20, - 0x6C7A, 0x6F54, 0x7A74, 0x7D50, 0x8840, 0x8A23, 0x6708, 0x4EF6, - 0x5039, 0x5026, 0x5065, 0x517C, 0x5238, 0x5263, 0x55A7, 0x570F, - 0x5805, 0x5ACC, 0x5EFA, 0x61B2, 0x61F8, 0x62F3, 0x6372, -}; -static const unsigned short euc_to_utf8_B8[] = { - 0x691C, 0x6A29, 0x727D, 0x72AC, 0x732E, 0x7814, 0x786F, - 0x7D79, 0x770C, 0x80A9, 0x898B, 0x8B19, 0x8CE2, 0x8ED2, 0x9063, - 0x9375, 0x967A, 0x9855, 0x9A13, 0x9E78, 0x5143, 0x539F, 0x53B3, - 0x5E7B, 0x5F26, 0x6E1B, 0x6E90, 0x7384, 0x73FE, 0x7D43, 0x8237, - 0x8A00, 0x8AFA, 0x9650, 0x4E4E, 0x500B, 0x53E4, 0x547C, 0x56FA, - 0x59D1, 0x5B64, 0x5DF1, 0x5EAB, 0x5F27, 0x6238, 0x6545, 0x67AF, - 0x6E56, 0x72D0, 0x7CCA, 0x88B4, 0x80A1, 0x80E1, 0x83F0, 0x864E, - 0x8A87, 0x8DE8, 0x9237, 0x96C7, 0x9867, 0x9F13, 0x4E94, 0x4E92, - 0x4F0D, 0x5348, 0x5449, 0x543E, 0x5A2F, 0x5F8C, 0x5FA1, 0x609F, - 0x68A7, 0x6A8E, 0x745A, 0x7881, 0x8A9E, 0x8AA4, 0x8B77, 0x9190, - 0x4E5E, 0x9BC9, 0x4EA4, 0x4F7C, 0x4FAF, 0x5019, 0x5016, 0x5149, - 0x516C, 0x529F, 0x52B9, 0x52FE, 0x539A, 0x53E3, 0x5411, -}; -static const unsigned short euc_to_utf8_B9[] = { - 0x540E, 0x5589, 0x5751, 0x57A2, 0x597D, 0x5B54, 0x5B5D, - 0x5B8F, 0x5DE5, 0x5DE7, 0x5DF7, 0x5E78, 0x5E83, 0x5E9A, 0x5EB7, - 0x5F18, 0x6052, 0x614C, 0x6297, 0x62D8, 0x63A7, 0x653B, 0x6602, - 0x6643, 0x66F4, 0x676D, 0x6821, 0x6897, 0x69CB, 0x6C5F, 0x6D2A, - 0x6D69, 0x6E2F, 0x6E9D, 0x7532, 0x7687, 0x786C, 0x7A3F, 0x7CE0, - 0x7D05, 0x7D18, 0x7D5E, 0x7DB1, 0x8015, 0x8003, 0x80AF, 0x80B1, - 0x8154, 0x818F, 0x822A, 0x8352, 0x884C, 0x8861, 0x8B1B, 0x8CA2, - 0x8CFC, 0x90CA, 0x9175, 0x9271, 0x783F, 0x92FC, 0x95A4, 0x964D, - 0x9805, 0x9999, 0x9AD8, 0x9D3B, 0x525B, 0x52AB, 0x53F7, 0x5408, - 0x58D5, 0x62F7, 0x6FE0, 0x8C6A, 0x8F5F, 0x9EB9, 0x514B, 0x523B, - 0x544A, 0x56FD, 0x7A40, 0x9177, 0x9D60, 0x9ED2, 0x7344, 0x6F09, - 0x8170, 0x7511, 0x5FFD, 0x60DA, 0x9AA8, 0x72DB, 0x8FBC, -}; -static const unsigned short euc_to_utf8_BA[] = { - 0x6B64, 0x9803, 0x4ECA, 0x56F0, 0x5764, 0x58BE, 0x5A5A, - 0x6068, 0x61C7, 0x660F, 0x6606, 0x6839, 0x68B1, 0x6DF7, 0x75D5, - 0x7D3A, 0x826E, 0x9B42, 0x4E9B, 0x4F50, 0x53C9, 0x5506, 0x5D6F, - 0x5DE6, 0x5DEE, 0x67FB, 0x6C99, 0x7473, 0x7802, 0x8A50, 0x9396, - 0x88DF, 0x5750, 0x5EA7, 0x632B, 0x50B5, 0x50AC, 0x518D, 0x6700, - 0x54C9, 0x585E, 0x59BB, 0x5BB0, 0x5F69, 0x624D, 0x63A1, 0x683D, - 0x6B73, 0x6E08, 0x707D, 0x91C7, 0x7280, 0x7815, 0x7826, 0x796D, - 0x658E, 0x7D30, 0x83DC, 0x88C1, 0x8F09, 0x969B, 0x5264, 0x5728, - 0x6750, 0x7F6A, 0x8CA1, 0x51B4, 0x5742, 0x962A, 0x583A, 0x698A, - 0x80B4, 0x54B2, 0x5D0E, 0x57FC, 0x7895, 0x9DFA, 0x4F5C, 0x524A, - 0x548B, 0x643E, 0x6628, 0x6714, 0x67F5, 0x7A84, 0x7B56, 0x7D22, - 0x932F, 0x685C, 0x9BAD, 0x7B39, 0x5319, 0x518A, 0x5237, -}; -static const unsigned short euc_to_utf8_BB[] = { - 0x5BDF, 0x62F6, 0x64AE, 0x64E6, 0x672D, 0x6BBA, 0x85A9, - 0x96D1, 0x7690, 0x9BD6, 0x634C, 0x9306, 0x9BAB, 0x76BF, 0x6652, - 0x4E09, 0x5098, 0x53C2, 0x5C71, 0x60E8, 0x6492, 0x6563, 0x685F, - 0x71E6, 0x73CA, 0x7523, 0x7B97, 0x7E82, 0x8695, 0x8B83, 0x8CDB, - 0x9178, 0x9910, 0x65AC, 0x66AB, 0x6B8B, 0x4ED5, 0x4ED4, 0x4F3A, - 0x4F7F, 0x523A, 0x53F8, 0x53F2, 0x55E3, 0x56DB, 0x58EB, 0x59CB, - 0x59C9, 0x59FF, 0x5B50, 0x5C4D, 0x5E02, 0x5E2B, 0x5FD7, 0x601D, - 0x6307, 0x652F, 0x5B5C, 0x65AF, 0x65BD, 0x65E8, 0x679D, 0x6B62, - 0x6B7B, 0x6C0F, 0x7345, 0x7949, 0x79C1, 0x7CF8, 0x7D19, 0x7D2B, - 0x80A2, 0x8102, 0x81F3, 0x8996, 0x8A5E, 0x8A69, 0x8A66, 0x8A8C, - 0x8AEE, 0x8CC7, 0x8CDC, 0x96CC, 0x98FC, 0x6B6F, 0x4E8B, 0x4F3C, - 0x4F8D, 0x5150, 0x5B57, 0x5BFA, 0x6148, 0x6301, 0x6642, -}; -static const unsigned short euc_to_utf8_BC[] = { - 0x6B21, 0x6ECB, 0x6CBB, 0x723E, 0x74BD, 0x75D4, 0x78C1, - 0x793A, 0x800C, 0x8033, 0x81EA, 0x8494, 0x8F9E, 0x6C50, 0x9E7F, - 0x5F0F, 0x8B58, 0x9D2B, 0x7AFA, 0x8EF8, 0x5B8D, 0x96EB, 0x4E03, - 0x53F1, 0x57F7, 0x5931, 0x5AC9, 0x5BA4, 0x6089, 0x6E7F, 0x6F06, - 0x75BE, 0x8CEA, 0x5B9F, 0x8500, 0x7BE0, 0x5072, 0x67F4, 0x829D, - 0x5C61, 0x854A, 0x7E1E, 0x820E, 0x5199, 0x5C04, 0x6368, 0x8D66, - 0x659C, 0x716E, 0x793E, 0x7D17, 0x8005, 0x8B1D, 0x8ECA, 0x906E, - 0x86C7, 0x90AA, 0x501F, 0x52FA, 0x5C3A, 0x6753, 0x707C, 0x7235, - 0x914C, 0x91C8, 0x932B, 0x82E5, 0x5BC2, 0x5F31, 0x60F9, 0x4E3B, - 0x53D6, 0x5B88, 0x624B, 0x6731, 0x6B8A, 0x72E9, 0x73E0, 0x7A2E, - 0x816B, 0x8DA3, 0x9152, 0x9996, 0x5112, 0x53D7, 0x546A, 0x5BFF, - 0x6388, 0x6A39, 0x7DAC, 0x9700, 0x56DA, 0x53CE, 0x5468, -}; -static const unsigned short euc_to_utf8_BD[] = { - 0x5B97, 0x5C31, 0x5DDE, 0x4FEE, 0x6101, 0x62FE, 0x6D32, - 0x79C0, 0x79CB, 0x7D42, 0x7E4D, 0x7FD2, 0x81ED, 0x821F, 0x8490, - 0x8846, 0x8972, 0x8B90, 0x8E74, 0x8F2F, 0x9031, 0x914B, 0x916C, - 0x96C6, 0x919C, 0x4EC0, 0x4F4F, 0x5145, 0x5341, 0x5F93, 0x620E, - 0x67D4, 0x6C41, 0x6E0B, 0x7363, 0x7E26, 0x91CD, 0x9283, 0x53D4, - 0x5919, 0x5BBF, 0x6DD1, 0x795D, 0x7E2E, 0x7C9B, 0x587E, 0x719F, - 0x51FA, 0x8853, 0x8FF0, 0x4FCA, 0x5CFB, 0x6625, 0x77AC, 0x7AE3, - 0x821C, 0x99FF, 0x51C6, 0x5FAA, 0x65EC, 0x696F, 0x6B89, 0x6DF3, - 0x6E96, 0x6F64, 0x76FE, 0x7D14, 0x5DE1, 0x9075, 0x9187, 0x9806, - 0x51E6, 0x521D, 0x6240, 0x6691, 0x66D9, 0x6E1A, 0x5EB6, 0x7DD2, - 0x7F72, 0x66F8, 0x85AF, 0x85F7, 0x8AF8, 0x52A9, 0x53D9, 0x5973, - 0x5E8F, 0x5F90, 0x6055, 0x92E4, 0x9664, 0x50B7, 0x511F, -}; -static const unsigned short euc_to_utf8_BE[] = { - 0x52DD, 0x5320, 0x5347, 0x53EC, 0x54E8, 0x5546, 0x5531, - 0x5617, 0x5968, 0x59BE, 0x5A3C, 0x5BB5, 0x5C06, 0x5C0F, 0x5C11, - 0x5C1A, 0x5E84, 0x5E8A, 0x5EE0, 0x5F70, 0x627F, 0x6284, 0x62DB, - 0x638C, 0x6377, 0x6607, 0x660C, 0x662D, 0x6676, 0x677E, 0x68A2, - 0x6A1F, 0x6A35, 0x6CBC, 0x6D88, 0x6E09, 0x6E58, 0x713C, 0x7126, - 0x7167, 0x75C7, 0x7701, 0x785D, 0x7901, 0x7965, 0x79F0, 0x7AE0, - 0x7B11, 0x7CA7, 0x7D39, 0x8096, 0x83D6, 0x848B, 0x8549, 0x885D, - 0x88F3, 0x8A1F, 0x8A3C, 0x8A54, 0x8A73, 0x8C61, 0x8CDE, 0x91A4, - 0x9266, 0x937E, 0x9418, 0x969C, 0x9798, 0x4E0A, 0x4E08, 0x4E1E, - 0x4E57, 0x5197, 0x5270, 0x57CE, 0x5834, 0x58CC, 0x5B22, 0x5E38, - 0x60C5, 0x64FE, 0x6761, 0x6756, 0x6D44, 0x72B6, 0x7573, 0x7A63, - 0x84B8, 0x8B72, 0x91B8, 0x9320, 0x5631, 0x57F4, 0x98FE, -}; -static const unsigned short euc_to_utf8_BF[] = { - 0x62ED, 0x690D, 0x6B96, 0x71ED, 0x7E54, 0x8077, 0x8272, - 0x89E6, 0x98DF, 0x8755, 0x8FB1, 0x5C3B, 0x4F38, 0x4FE1, 0x4FB5, - 0x5507, 0x5A20, 0x5BDD, 0x5BE9, 0x5FC3, 0x614E, 0x632F, 0x65B0, - 0x664B, 0x68EE, 0x699B, 0x6D78, 0x6DF1, 0x7533, 0x75B9, 0x771F, - 0x795E, 0x79E6, 0x7D33, 0x81E3, 0x82AF, 0x85AA, 0x89AA, 0x8A3A, - 0x8EAB, 0x8F9B, 0x9032, 0x91DD, 0x9707, 0x4EBA, 0x4EC1, 0x5203, - 0x5875, 0x58EC, 0x5C0B, 0x751A, 0x5C3D, 0x814E, 0x8A0A, 0x8FC5, - 0x9663, 0x976D, 0x7B25, 0x8ACF, 0x9808, 0x9162, 0x56F3, 0x53A8, - 0x9017, 0x5439, 0x5782, 0x5E25, 0x63A8, 0x6C34, 0x708A, 0x7761, - 0x7C8B, 0x7FE0, 0x8870, 0x9042, 0x9154, 0x9310, 0x9318, 0x968F, - 0x745E, 0x9AC4, 0x5D07, 0x5D69, 0x6570, 0x67A2, 0x8DA8, 0x96DB, - 0x636E, 0x6749, 0x6919, 0x83C5, 0x9817, 0x96C0, 0x88FE, -}; -static const unsigned short euc_to_utf8_C0[] = { - 0x6F84, 0x647A, 0x5BF8, 0x4E16, 0x702C, 0x755D, 0x662F, - 0x51C4, 0x5236, 0x52E2, 0x59D3, 0x5F81, 0x6027, 0x6210, 0x653F, - 0x6574, 0x661F, 0x6674, 0x68F2, 0x6816, 0x6B63, 0x6E05, 0x7272, - 0x751F, 0x76DB, 0x7CBE, 0x8056, 0x58F0, 0x88FD, 0x897F, 0x8AA0, - 0x8A93, 0x8ACB, 0x901D, 0x9192, 0x9752, 0x9759, 0x6589, 0x7A0E, - 0x8106, 0x96BB, 0x5E2D, 0x60DC, 0x621A, 0x65A5, 0x6614, 0x6790, - 0x77F3, 0x7A4D, 0x7C4D, 0x7E3E, 0x810A, 0x8CAC, 0x8D64, 0x8DE1, - 0x8E5F, 0x78A9, 0x5207, 0x62D9, 0x63A5, 0x6442, 0x6298, 0x8A2D, - 0x7A83, 0x7BC0, 0x8AAC, 0x96EA, 0x7D76, 0x820C, 0x8749, 0x4ED9, - 0x5148, 0x5343, 0x5360, 0x5BA3, 0x5C02, 0x5C16, 0x5DDD, 0x6226, - 0x6247, 0x64B0, 0x6813, 0x6834, 0x6CC9, 0x6D45, 0x6D17, 0x67D3, - 0x6F5C, 0x714E, 0x717D, 0x65CB, 0x7A7F, 0x7BAD, 0x7DDA, -}; -static const unsigned short euc_to_utf8_C1[] = { - 0x7E4A, 0x7FA8, 0x817A, 0x821B, 0x8239, 0x85A6, 0x8A6E, - 0x8CCE, 0x8DF5, 0x9078, 0x9077, 0x92AD, 0x9291, 0x9583, 0x9BAE, - 0x524D, 0x5584, 0x6F38, 0x7136, 0x5168, 0x7985, 0x7E55, 0x81B3, - 0x7CCE, 0x564C, 0x5851, 0x5CA8, 0x63AA, 0x66FE, 0x66FD, 0x695A, - 0x72D9, 0x758F, 0x758E, 0x790E, 0x7956, 0x79DF, 0x7C97, 0x7D20, - 0x7D44, 0x8607, 0x8A34, 0x963B, 0x9061, 0x9F20, 0x50E7, 0x5275, - 0x53CC, 0x53E2, 0x5009, 0x55AA, 0x58EE, 0x594F, 0x723D, 0x5B8B, - 0x5C64, 0x531D, 0x60E3, 0x60F3, 0x635C, 0x6383, 0x633F, 0x63BB, - 0x64CD, 0x65E9, 0x66F9, 0x5DE3, 0x69CD, 0x69FD, 0x6F15, 0x71E5, - 0x4E89, 0x75E9, 0x76F8, 0x7A93, 0x7CDF, 0x7DCF, 0x7D9C, 0x8061, - 0x8349, 0x8358, 0x846C, 0x84BC, 0x85FB, 0x88C5, 0x8D70, 0x9001, - 0x906D, 0x9397, 0x971C, 0x9A12, 0x50CF, 0x5897, 0x618E, -}; -static const unsigned short euc_to_utf8_C2[] = { - 0x81D3, 0x8535, 0x8D08, 0x9020, 0x4FC3, 0x5074, 0x5247, - 0x5373, 0x606F, 0x6349, 0x675F, 0x6E2C, 0x8DB3, 0x901F, 0x4FD7, - 0x5C5E, 0x8CCA, 0x65CF, 0x7D9A, 0x5352, 0x8896, 0x5176, 0x63C3, - 0x5B58, 0x5B6B, 0x5C0A, 0x640D, 0x6751, 0x905C, 0x4ED6, 0x591A, - 0x592A, 0x6C70, 0x8A51, 0x553E, 0x5815, 0x59A5, 0x60F0, 0x6253, - 0x67C1, 0x8235, 0x6955, 0x9640, 0x99C4, 0x9A28, 0x4F53, 0x5806, - 0x5BFE, 0x8010, 0x5CB1, 0x5E2F, 0x5F85, 0x6020, 0x614B, 0x6234, - 0x66FF, 0x6CF0, 0x6EDE, 0x80CE, 0x817F, 0x82D4, 0x888B, 0x8CB8, - 0x9000, 0x902E, 0x968A, 0x9EDB, 0x9BDB, 0x4EE3, 0x53F0, 0x5927, - 0x7B2C, 0x918D, 0x984C, 0x9DF9, 0x6EDD, 0x7027, 0x5353, 0x5544, - 0x5B85, 0x6258, 0x629E, 0x62D3, 0x6CA2, 0x6FEF, 0x7422, 0x8A17, - 0x9438, 0x6FC1, 0x8AFE, 0x8338, 0x51E7, 0x86F8, 0x53EA, -}; -static const unsigned short euc_to_utf8_C3[] = { - 0x53E9, 0x4F46, 0x9054, 0x8FB0, 0x596A, 0x8131, 0x5DFD, - 0x7AEA, 0x8FBF, 0x68DA, 0x8C37, 0x72F8, 0x9C48, 0x6A3D, 0x8AB0, - 0x4E39, 0x5358, 0x5606, 0x5766, 0x62C5, 0x63A2, 0x65E6, 0x6B4E, - 0x6DE1, 0x6E5B, 0x70AD, 0x77ED, 0x7AEF, 0x7BAA, 0x7DBB, 0x803D, - 0x80C6, 0x86CB, 0x8A95, 0x935B, 0x56E3, 0x58C7, 0x5F3E, 0x65AD, - 0x6696, 0x6A80, 0x6BB5, 0x7537, 0x8AC7, 0x5024, 0x77E5, 0x5730, - 0x5F1B, 0x6065, 0x667A, 0x6C60, 0x75F4, 0x7A1A, 0x7F6E, 0x81F4, - 0x8718, 0x9045, 0x99B3, 0x7BC9, 0x755C, 0x7AF9, 0x7B51, 0x84C4, - 0x9010, 0x79E9, 0x7A92, 0x8336, 0x5AE1, 0x7740, 0x4E2D, 0x4EF2, - 0x5B99, 0x5FE0, 0x62BD, 0x663C, 0x67F1, 0x6CE8, 0x866B, 0x8877, - 0x8A3B, 0x914E, 0x92F3, 0x99D0, 0x6A17, 0x7026, 0x732A, 0x82E7, - 0x8457, 0x8CAF, 0x4E01, 0x5146, 0x51CB, 0x558B, 0x5BF5, -}; -static const unsigned short euc_to_utf8_C4[] = { - 0x5E16, 0x5E33, 0x5E81, 0x5F14, 0x5F35, 0x5F6B, 0x5FB4, - 0x61F2, 0x6311, 0x66A2, 0x671D, 0x6F6E, 0x7252, 0x753A, 0x773A, - 0x8074, 0x8139, 0x8178, 0x8776, 0x8ABF, 0x8ADC, 0x8D85, 0x8DF3, - 0x929A, 0x9577, 0x9802, 0x9CE5, 0x52C5, 0x6357, 0x76F4, 0x6715, - 0x6C88, 0x73CD, 0x8CC3, 0x93AE, 0x9673, 0x6D25, 0x589C, 0x690E, - 0x69CC, 0x8FFD, 0x939A, 0x75DB, 0x901A, 0x585A, 0x6802, 0x63B4, - 0x69FB, 0x4F43, 0x6F2C, 0x67D8, 0x8FBB, 0x8526, 0x7DB4, 0x9354, - 0x693F, 0x6F70, 0x576A, 0x58F7, 0x5B2C, 0x7D2C, 0x722A, 0x540A, - 0x91E3, 0x9DB4, 0x4EAD, 0x4F4E, 0x505C, 0x5075, 0x5243, 0x8C9E, - 0x5448, 0x5824, 0x5B9A, 0x5E1D, 0x5E95, 0x5EAD, 0x5EF7, 0x5F1F, - 0x608C, 0x62B5, 0x633A, 0x63D0, 0x68AF, 0x6C40, 0x7887, 0x798E, - 0x7A0B, 0x7DE0, 0x8247, 0x8A02, 0x8AE6, 0x8E44, 0x9013, -}; -static const unsigned short euc_to_utf8_C5[] = { - 0x90B8, 0x912D, 0x91D8, 0x9F0E, 0x6CE5, 0x6458, 0x64E2, - 0x6575, 0x6EF4, 0x7684, 0x7B1B, 0x9069, 0x93D1, 0x6EBA, 0x54F2, - 0x5FB9, 0x64A4, 0x8F4D, 0x8FED, 0x9244, 0x5178, 0x586B, 0x5929, - 0x5C55, 0x5E97, 0x6DFB, 0x7E8F, 0x751C, 0x8CBC, 0x8EE2, 0x985B, - 0x70B9, 0x4F1D, 0x6BBF, 0x6FB1, 0x7530, 0x96FB, 0x514E, 0x5410, - 0x5835, 0x5857, 0x59AC, 0x5C60, 0x5F92, 0x6597, 0x675C, 0x6E21, - 0x767B, 0x83DF, 0x8CED, 0x9014, 0x90FD, 0x934D, 0x7825, 0x783A, - 0x52AA, 0x5EA6, 0x571F, 0x5974, 0x6012, 0x5012, 0x515A, 0x51AC, - 0x51CD, 0x5200, 0x5510, 0x5854, 0x5858, 0x5957, 0x5B95, 0x5CF6, - 0x5D8B, 0x60BC, 0x6295, 0x642D, 0x6771, 0x6843, 0x68BC, 0x68DF, - 0x76D7, 0x6DD8, 0x6E6F, 0x6D9B, 0x706F, 0x71C8, 0x5F53, 0x75D8, - 0x7977, 0x7B49, 0x7B54, 0x7B52, 0x7CD6, 0x7D71, 0x5230, -}; -static const unsigned short euc_to_utf8_C6[] = { - 0x8463, 0x8569, 0x85E4, 0x8A0E, 0x8B04, 0x8C46, 0x8E0F, - 0x9003, 0x900F, 0x9419, 0x9676, 0x982D, 0x9A30, 0x95D8, 0x50CD, - 0x52D5, 0x540C, 0x5802, 0x5C0E, 0x61A7, 0x649E, 0x6D1E, 0x77B3, - 0x7AE5, 0x80F4, 0x8404, 0x9053, 0x9285, 0x5CE0, 0x9D07, 0x533F, - 0x5F97, 0x5FB3, 0x6D9C, 0x7279, 0x7763, 0x79BF, 0x7BE4, 0x6BD2, - 0x72EC, 0x8AAD, 0x6803, 0x6A61, 0x51F8, 0x7A81, 0x6934, 0x5C4A, - 0x9CF6, 0x82EB, 0x5BC5, 0x9149, 0x701E, 0x5678, 0x5C6F, 0x60C7, - 0x6566, 0x6C8C, 0x8C5A, 0x9041, 0x9813, 0x5451, 0x66C7, 0x920D, - 0x5948, 0x90A3, 0x5185, 0x4E4D, 0x51EA, 0x8599, 0x8B0E, 0x7058, - 0x637A, 0x934B, 0x6962, 0x99B4, 0x7E04, 0x7577, 0x5357, 0x6960, - 0x8EDF, 0x96E3, 0x6C5D, 0x4E8C, 0x5C3C, 0x5F10, 0x8FE9, 0x5302, - 0x8CD1, 0x8089, 0x8679, 0x5EFF, 0x65E5, 0x4E73, 0x5165, -}; -static const unsigned short euc_to_utf8_C7[] = { - 0x5982, 0x5C3F, 0x97EE, 0x4EFB, 0x598A, 0x5FCD, 0x8A8D, - 0x6FE1, 0x79B0, 0x7962, 0x5BE7, 0x8471, 0x732B, 0x71B1, 0x5E74, - 0x5FF5, 0x637B, 0x649A, 0x71C3, 0x7C98, 0x4E43, 0x5EFC, 0x4E4B, - 0x57DC, 0x56A2, 0x60A9, 0x6FC3, 0x7D0D, 0x80FD, 0x8133, 0x81BF, - 0x8FB2, 0x8997, 0x86A4, 0x5DF4, 0x628A, 0x64AD, 0x8987, 0x6777, - 0x6CE2, 0x6D3E, 0x7436, 0x7834, 0x5A46, 0x7F75, 0x82AD, 0x99AC, - 0x4FF3, 0x5EC3, 0x62DD, 0x6392, 0x6557, 0x676F, 0x76C3, 0x724C, - 0x80CC, 0x80BA, 0x8F29, 0x914D, 0x500D, 0x57F9, 0x5A92, 0x6885, - 0x6973, 0x7164, 0x72FD, 0x8CB7, 0x58F2, 0x8CE0, 0x966A, 0x9019, - 0x877F, 0x79E4, 0x77E7, 0x8429, 0x4F2F, 0x5265, 0x535A, 0x62CD, - 0x67CF, 0x6CCA, 0x767D, 0x7B94, 0x7C95, 0x8236, 0x8584, 0x8FEB, - 0x66DD, 0x6F20, 0x7206, 0x7E1B, 0x83AB, 0x99C1, 0x9EA6, -}; -static const unsigned short euc_to_utf8_C8[] = { - 0x51FD, 0x7BB1, 0x7872, 0x7BB8, 0x8087, 0x7B48, 0x6AE8, - 0x5E61, 0x808C, 0x7551, 0x7560, 0x516B, 0x9262, 0x6E8C, 0x767A, - 0x9197, 0x9AEA, 0x4F10, 0x7F70, 0x629C, 0x7B4F, 0x95A5, 0x9CE9, - 0x567A, 0x5859, 0x86E4, 0x96BC, 0x4F34, 0x5224, 0x534A, 0x53CD, - 0x53DB, 0x5E06, 0x642C, 0x6591, 0x677F, 0x6C3E, 0x6C4E, 0x7248, - 0x72AF, 0x73ED, 0x7554, 0x7E41, 0x822C, 0x85E9, 0x8CA9, 0x7BC4, - 0x91C6, 0x7169, 0x9812, 0x98EF, 0x633D, 0x6669, 0x756A, 0x76E4, - 0x78D0, 0x8543, 0x86EE, 0x532A, 0x5351, 0x5426, 0x5983, 0x5E87, - 0x5F7C, 0x60B2, 0x6249, 0x6279, 0x62AB, 0x6590, 0x6BD4, 0x6CCC, - 0x75B2, 0x76AE, 0x7891, 0x79D8, 0x7DCB, 0x7F77, 0x80A5, 0x88AB, - 0x8AB9, 0x8CBB, 0x907F, 0x975E, 0x98DB, 0x6A0B, 0x7C38, 0x5099, - 0x5C3E, 0x5FAE, 0x6787, 0x6BD8, 0x7435, 0x7709, 0x7F8E, -}; -static const unsigned short euc_to_utf8_C9[] = { - 0x9F3B, 0x67CA, 0x7A17, 0x5339, 0x758B, 0x9AED, 0x5F66, - 0x819D, 0x83F1, 0x8098, 0x5F3C, 0x5FC5, 0x7562, 0x7B46, 0x903C, - 0x6867, 0x59EB, 0x5A9B, 0x7D10, 0x767E, 0x8B2C, 0x4FF5, 0x5F6A, - 0x6A19, 0x6C37, 0x6F02, 0x74E2, 0x7968, 0x8868, 0x8A55, 0x8C79, - 0x5EDF, 0x63CF, 0x75C5, 0x79D2, 0x82D7, 0x9328, 0x92F2, 0x849C, - 0x86ED, 0x9C2D, 0x54C1, 0x5F6C, 0x658C, 0x6D5C, 0x7015, 0x8CA7, - 0x8CD3, 0x983B, 0x654F, 0x74F6, 0x4E0D, 0x4ED8, 0x57E0, 0x592B, - 0x5A66, 0x5BCC, 0x51A8, 0x5E03, 0x5E9C, 0x6016, 0x6276, 0x6577, - 0x65A7, 0x666E, 0x6D6E, 0x7236, 0x7B26, 0x8150, 0x819A, 0x8299, - 0x8B5C, 0x8CA0, 0x8CE6, 0x8D74, 0x961C, 0x9644, 0x4FAE, 0x64AB, - 0x6B66, 0x821E, 0x8461, 0x856A, 0x90E8, 0x5C01, 0x6953, 0x98A8, - 0x847A, 0x8557, 0x4F0F, 0x526F, 0x5FA9, 0x5E45, 0x670D, -}; -static const unsigned short euc_to_utf8_CA[] = { - 0x798F, 0x8179, 0x8907, 0x8986, 0x6DF5, 0x5F17, 0x6255, - 0x6CB8, 0x4ECF, 0x7269, 0x9B92, 0x5206, 0x543B, 0x5674, 0x58B3, - 0x61A4, 0x626E, 0x711A, 0x596E, 0x7C89, 0x7CDE, 0x7D1B, 0x96F0, - 0x6587, 0x805E, 0x4E19, 0x4F75, 0x5175, 0x5840, 0x5E63, 0x5E73, - 0x5F0A, 0x67C4, 0x4E26, 0x853D, 0x9589, 0x965B, 0x7C73, 0x9801, - 0x50FB, 0x58C1, 0x7656, 0x78A7, 0x5225, 0x77A5, 0x8511, 0x7B86, - 0x504F, 0x5909, 0x7247, 0x7BC7, 0x7DE8, 0x8FBA, 0x8FD4, 0x904D, - 0x4FBF, 0x52C9, 0x5A29, 0x5F01, 0x97AD, 0x4FDD, 0x8217, 0x92EA, - 0x5703, 0x6355, 0x6B69, 0x752B, 0x88DC, 0x8F14, 0x7A42, 0x52DF, - 0x5893, 0x6155, 0x620A, 0x66AE, 0x6BCD, 0x7C3F, 0x83E9, 0x5023, - 0x4FF8, 0x5305, 0x5446, 0x5831, 0x5949, 0x5B9D, 0x5CF0, 0x5CEF, - 0x5D29, 0x5E96, 0x62B1, 0x6367, 0x653E, 0x65B9, 0x670B, -}; -static const unsigned short euc_to_utf8_CB[] = { - 0x6CD5, 0x6CE1, 0x70F9, 0x7832, 0x7E2B, 0x80DE, 0x82B3, - 0x840C, 0x84EC, 0x8702, 0x8912, 0x8A2A, 0x8C4A, 0x90A6, 0x92D2, - 0x98FD, 0x9CF3, 0x9D6C, 0x4E4F, 0x4EA1, 0x508D, 0x5256, 0x574A, - 0x59A8, 0x5E3D, 0x5FD8, 0x5FD9, 0x623F, 0x66B4, 0x671B, 0x67D0, - 0x68D2, 0x5192, 0x7D21, 0x80AA, 0x81A8, 0x8B00, 0x8C8C, 0x8CBF, - 0x927E, 0x9632, 0x5420, 0x982C, 0x5317, 0x50D5, 0x535C, 0x58A8, - 0x64B2, 0x6734, 0x7267, 0x7766, 0x7A46, 0x91E6, 0x52C3, 0x6CA1, - 0x6B86, 0x5800, 0x5E4C, 0x5954, 0x672C, 0x7FFB, 0x51E1, 0x76C6, - 0x6469, 0x78E8, 0x9B54, 0x9EBB, 0x57CB, 0x59B9, 0x6627, 0x679A, - 0x6BCE, 0x54E9, 0x69D9, 0x5E55, 0x819C, 0x6795, 0x9BAA, 0x67FE, - 0x9C52, 0x685D, 0x4EA6, 0x4FE3, 0x53C8, 0x62B9, 0x672B, 0x6CAB, - 0x8FC4, 0x4FAD, 0x7E6D, 0x9EBF, 0x4E07, 0x6162, 0x6E80, -}; -static const unsigned short euc_to_utf8_CC[] = { - 0x6F2B, 0x8513, 0x5473, 0x672A, 0x9B45, 0x5DF3, 0x7B95, - 0x5CAC, 0x5BC6, 0x871C, 0x6E4A, 0x84D1, 0x7A14, 0x8108, 0x5999, - 0x7C8D, 0x6C11, 0x7720, 0x52D9, 0x5922, 0x7121, 0x725F, 0x77DB, - 0x9727, 0x9D61, 0x690B, 0x5A7F, 0x5A18, 0x51A5, 0x540D, 0x547D, - 0x660E, 0x76DF, 0x8FF7, 0x9298, 0x9CF4, 0x59EA, 0x725D, 0x6EC5, - 0x514D, 0x68C9, 0x7DBF, 0x7DEC, 0x9762, 0x9EBA, 0x6478, 0x6A21, - 0x8302, 0x5984, 0x5B5F, 0x6BDB, 0x731B, 0x76F2, 0x7DB2, 0x8017, - 0x8499, 0x5132, 0x6728, 0x9ED9, 0x76EE, 0x6762, 0x52FF, 0x9905, - 0x5C24, 0x623B, 0x7C7E, 0x8CB0, 0x554F, 0x60B6, 0x7D0B, 0x9580, - 0x5301, 0x4E5F, 0x51B6, 0x591C, 0x723A, 0x8036, 0x91CE, 0x5F25, - 0x77E2, 0x5384, 0x5F79, 0x7D04, 0x85AC, 0x8A33, 0x8E8D, 0x9756, - 0x67F3, 0x85AE, 0x9453, 0x6109, 0x6108, 0x6CB9, 0x7652, -}; -static const unsigned short euc_to_utf8_CD[] = { - 0x8AED, 0x8F38, 0x552F, 0x4F51, 0x512A, 0x52C7, 0x53CB, - 0x5BA5, 0x5E7D, 0x60A0, 0x6182, 0x63D6, 0x6709, 0x67DA, 0x6E67, - 0x6D8C, 0x7336, 0x7337, 0x7531, 0x7950, 0x88D5, 0x8A98, 0x904A, - 0x9091, 0x90F5, 0x96C4, 0x878D, 0x5915, 0x4E88, 0x4F59, 0x4E0E, - 0x8A89, 0x8F3F, 0x9810, 0x50AD, 0x5E7C, 0x5996, 0x5BB9, 0x5EB8, - 0x63DA, 0x63FA, 0x64C1, 0x66DC, 0x694A, 0x69D8, 0x6D0B, 0x6EB6, - 0x7194, 0x7528, 0x7AAF, 0x7F8A, 0x8000, 0x8449, 0x84C9, 0x8981, - 0x8B21, 0x8E0A, 0x9065, 0x967D, 0x990A, 0x617E, 0x6291, 0x6B32, - 0x6C83, 0x6D74, 0x7FCC, 0x7FFC, 0x6DC0, 0x7F85, 0x87BA, 0x88F8, - 0x6765, 0x83B1, 0x983C, 0x96F7, 0x6D1B, 0x7D61, 0x843D, 0x916A, - 0x4E71, 0x5375, 0x5D50, 0x6B04, 0x6FEB, 0x85CD, 0x862D, 0x89A7, - 0x5229, 0x540F, 0x5C65, 0x674E, 0x68A8, 0x7406, 0x7483, -}; -static const unsigned short euc_to_utf8_CE[] = { - 0x75E2, 0x88CF, 0x88E1, 0x91CC, 0x96E2, 0x9678, 0x5F8B, - 0x7387, 0x7ACB, 0x844E, 0x63A0, 0x7565, 0x5289, 0x6D41, 0x6E9C, - 0x7409, 0x7559, 0x786B, 0x7C92, 0x9686, 0x7ADC, 0x9F8D, 0x4FB6, - 0x616E, 0x65C5, 0x865C, 0x4E86, 0x4EAE, 0x50DA, 0x4E21, 0x51CC, - 0x5BEE, 0x6599, 0x6881, 0x6DBC, 0x731F, 0x7642, 0x77AD, 0x7A1C, - 0x7CE7, 0x826F, 0x8AD2, 0x907C, 0x91CF, 0x9675, 0x9818, 0x529B, - 0x7DD1, 0x502B, 0x5398, 0x6797, 0x6DCB, 0x71D0, 0x7433, 0x81E8, - 0x8F2A, 0x96A3, 0x9C57, 0x9E9F, 0x7460, 0x5841, 0x6D99, 0x7D2F, - 0x985E, 0x4EE4, 0x4F36, 0x4F8B, 0x51B7, 0x52B1, 0x5DBA, 0x601C, - 0x73B2, 0x793C, 0x82D3, 0x9234, 0x96B7, 0x96F6, 0x970A, 0x9E97, - 0x9F62, 0x66A6, 0x6B74, 0x5217, 0x52A3, 0x70C8, 0x88C2, 0x5EC9, - 0x604B, 0x6190, 0x6F23, 0x7149, 0x7C3E, 0x7DF4, 0x806F, -}; -static const unsigned short euc_to_utf8_CF[] = { - 0x84EE, 0x9023, 0x932C, 0x5442, 0x9B6F, 0x6AD3, 0x7089, - 0x8CC2, 0x8DEF, 0x9732, 0x52B4, 0x5A41, 0x5ECA, 0x5F04, 0x6717, - 0x697C, 0x6994, 0x6D6A, 0x6F0F, 0x7262, 0x72FC, 0x7BED, 0x8001, - 0x807E, 0x874B, 0x90CE, 0x516D, 0x9E93, 0x7984, 0x808B, 0x9332, - 0x8AD6, 0x502D, 0x548C, 0x8A71, 0x6B6A, 0x8CC4, 0x8107, 0x60D1, - 0x67A0, 0x9DF2, 0x4E99, 0x4E98, 0x9C10, 0x8A6B, 0x85C1, 0x8568, - 0x6900, 0x6E7E, 0x7897, 0x8155, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short euc_to_utf8_CF_x0213[] = { - 0x84EE, 0x9023, 0x932C, 0x5442, 0x9B6F, 0x6AD3, 0x7089, - 0x8CC2, 0x8DEF, 0x9732, 0x52B4, 0x5A41, 0x5ECA, 0x5F04, 0x6717, - 0x697C, 0x6994, 0x6D6A, 0x6F0F, 0x7262, 0x72FC, 0x7BED, 0x8001, - 0x807E, 0x874B, 0x90CE, 0x516D, 0x9E93, 0x7984, 0x808B, 0x9332, - 0x8AD6, 0x502D, 0x548C, 0x8A71, 0x6B6A, 0x8CC4, 0x8107, 0x60D1, - 0x67A0, 0x9DF2, 0x4E99, 0x4E98, 0x9C10, 0x8A6B, 0x85C1, 0x8568, - 0x6900, 0x6E7E, 0x7897, 0x8155, 0xD842 /*0xDF9F*/, 0x5B41, 0x5B56, 0x5B7D, - 0x5B93, 0x5BD8, 0x5BEC, 0x5C12, 0x5C1E, 0x5C23, 0x5C2B, 0x378D, - 0x5C62, 0xFA3B, 0xFA3C, 0xD845 /*0xDEB4*/, 0x5C7A, 0x5C8F, 0x5C9F, 0x5CA3, - 0x5CAA, 0x5CBA, 0x5CCB, 0x5CD0, 0x5CD2, 0x5CF4, 0xD847 /*0xDE34*/, 0x37E2, - 0x5D0D, 0x5D27, 0xFA11, 0x5D46, 0x5D47, 0x5D53, 0x5D4A, 0x5D6D, - 0x5D81, 0x5DA0, 0x5DA4, 0x5DA7, 0x5DB8, 0x5DCB, 0x541E, -}; -static const unsigned short euc_to_utf8_D0[] = { - 0x5F0C, 0x4E10, 0x4E15, 0x4E2A, 0x4E31, 0x4E36, 0x4E3C, - 0x4E3F, 0x4E42, 0x4E56, 0x4E58, 0x4E82, 0x4E85, 0x8C6B, 0x4E8A, - 0x8212, 0x5F0D, 0x4E8E, 0x4E9E, 0x4E9F, 0x4EA0, 0x4EA2, 0x4EB0, - 0x4EB3, 0x4EB6, 0x4ECE, 0x4ECD, 0x4EC4, 0x4EC6, 0x4EC2, 0x4ED7, - 0x4EDE, 0x4EED, 0x4EDF, 0x4EF7, 0x4F09, 0x4F5A, 0x4F30, 0x4F5B, - 0x4F5D, 0x4F57, 0x4F47, 0x4F76, 0x4F88, 0x4F8F, 0x4F98, 0x4F7B, - 0x4F69, 0x4F70, 0x4F91, 0x4F6F, 0x4F86, 0x4F96, 0x5118, 0x4FD4, - 0x4FDF, 0x4FCE, 0x4FD8, 0x4FDB, 0x4FD1, 0x4FDA, 0x4FD0, 0x4FE4, - 0x4FE5, 0x501A, 0x5028, 0x5014, 0x502A, 0x5025, 0x5005, 0x4F1C, - 0x4FF6, 0x5021, 0x5029, 0x502C, 0x4FFE, 0x4FEF, 0x5011, 0x5006, - 0x5043, 0x5047, 0x6703, 0x5055, 0x5050, 0x5048, 0x505A, 0x5056, - 0x506C, 0x5078, 0x5080, 0x509A, 0x5085, 0x50B4, 0x50B2, -}; -static const unsigned short euc_to_utf8_D1[] = { - 0x50C9, 0x50CA, 0x50B3, 0x50C2, 0x50D6, 0x50DE, 0x50E5, - 0x50ED, 0x50E3, 0x50EE, 0x50F9, 0x50F5, 0x5109, 0x5101, 0x5102, - 0x5116, 0x5115, 0x5114, 0x511A, 0x5121, 0x513A, 0x5137, 0x513C, - 0x513B, 0x513F, 0x5140, 0x5152, 0x514C, 0x5154, 0x5162, 0x7AF8, - 0x5169, 0x516A, 0x516E, 0x5180, 0x5182, 0x56D8, 0x518C, 0x5189, - 0x518F, 0x5191, 0x5193, 0x5195, 0x5196, 0x51A4, 0x51A6, 0x51A2, - 0x51A9, 0x51AA, 0x51AB, 0x51B3, 0x51B1, 0x51B2, 0x51B0, 0x51B5, - 0x51BD, 0x51C5, 0x51C9, 0x51DB, 0x51E0, 0x8655, 0x51E9, 0x51ED, - 0x51F0, 0x51F5, 0x51FE, 0x5204, 0x520B, 0x5214, 0x520E, 0x5227, - 0x522A, 0x522E, 0x5233, 0x5239, 0x524F, 0x5244, 0x524B, 0x524C, - 0x525E, 0x5254, 0x526A, 0x5274, 0x5269, 0x5273, 0x527F, 0x527D, - 0x528D, 0x5294, 0x5292, 0x5271, 0x5288, 0x5291, 0x8FA8, -}; -static const unsigned short euc_to_utf8_D2[] = { - 0x8FA7, 0x52AC, 0x52AD, 0x52BC, 0x52B5, 0x52C1, 0x52CD, - 0x52D7, 0x52DE, 0x52E3, 0x52E6, 0x98ED, 0x52E0, 0x52F3, 0x52F5, - 0x52F8, 0x52F9, 0x5306, 0x5308, 0x7538, 0x530D, 0x5310, 0x530F, - 0x5315, 0x531A, 0x5323, 0x532F, 0x5331, 0x5333, 0x5338, 0x5340, - 0x5346, 0x5345, 0x4E17, 0x5349, 0x534D, 0x51D6, 0x535E, 0x5369, - 0x536E, 0x5918, 0x537B, 0x5377, 0x5382, 0x5396, 0x53A0, 0x53A6, - 0x53A5, 0x53AE, 0x53B0, 0x53B6, 0x53C3, 0x7C12, 0x96D9, 0x53DF, - 0x66FC, 0x71EE, 0x53EE, 0x53E8, 0x53ED, 0x53FA, 0x5401, 0x543D, - 0x5440, 0x542C, 0x542D, 0x543C, 0x542E, 0x5436, 0x5429, 0x541D, - 0x544E, 0x548F, 0x5475, 0x548E, 0x545F, 0x5471, 0x5477, 0x5470, - 0x5492, 0x547B, 0x5480, 0x5476, 0x5484, 0x5490, 0x5486, 0x54C7, - 0x54A2, 0x54B8, 0x54A5, 0x54AC, 0x54C4, 0x54C8, 0x54A8, -}; -static const unsigned short euc_to_utf8_D3[] = { - 0x54AB, 0x54C2, 0x54A4, 0x54BE, 0x54BC, 0x54D8, 0x54E5, - 0x54E6, 0x550F, 0x5514, 0x54FD, 0x54EE, 0x54ED, 0x54FA, 0x54E2, - 0x5539, 0x5540, 0x5563, 0x554C, 0x552E, 0x555C, 0x5545, 0x5556, - 0x5557, 0x5538, 0x5533, 0x555D, 0x5599, 0x5580, 0x54AF, 0x558A, - 0x559F, 0x557B, 0x557E, 0x5598, 0x559E, 0x55AE, 0x557C, 0x5583, - 0x55A9, 0x5587, 0x55A8, 0x55DA, 0x55C5, 0x55DF, 0x55C4, 0x55DC, - 0x55E4, 0x55D4, 0x5614, 0x55F7, 0x5616, 0x55FE, 0x55FD, 0x561B, - 0x55F9, 0x564E, 0x5650, 0x71DF, 0x5634, 0x5636, 0x5632, 0x5638, - 0x566B, 0x5664, 0x562F, 0x566C, 0x566A, 0x5686, 0x5680, 0x568A, - 0x56A0, 0x5694, 0x568F, 0x56A5, 0x56AE, 0x56B6, 0x56B4, 0x56C2, - 0x56BC, 0x56C1, 0x56C3, 0x56C0, 0x56C8, 0x56CE, 0x56D1, 0x56D3, - 0x56D7, 0x56EE, 0x56F9, 0x5700, 0x56FF, 0x5704, 0x5709, -}; -static const unsigned short euc_to_utf8_D4[] = { - 0x5708, 0x570B, 0x570D, 0x5713, 0x5718, 0x5716, 0x55C7, - 0x571C, 0x5726, 0x5737, 0x5738, 0x574E, 0x573B, 0x5740, 0x574F, - 0x5769, 0x57C0, 0x5788, 0x5761, 0x577F, 0x5789, 0x5793, 0x57A0, - 0x57B3, 0x57A4, 0x57AA, 0x57B0, 0x57C3, 0x57C6, 0x57D4, 0x57D2, - 0x57D3, 0x580A, 0x57D6, 0x57E3, 0x580B, 0x5819, 0x581D, 0x5872, - 0x5821, 0x5862, 0x584B, 0x5870, 0x6BC0, 0x5852, 0x583D, 0x5879, - 0x5885, 0x58B9, 0x589F, 0x58AB, 0x58BA, 0x58DE, 0x58BB, 0x58B8, - 0x58AE, 0x58C5, 0x58D3, 0x58D1, 0x58D7, 0x58D9, 0x58D8, 0x58E5, - 0x58DC, 0x58E4, 0x58DF, 0x58EF, 0x58FA, 0x58F9, 0x58FB, 0x58FC, - 0x58FD, 0x5902, 0x590A, 0x5910, 0x591B, 0x68A6, 0x5925, 0x592C, - 0x592D, 0x5932, 0x5938, 0x593E, 0x7AD2, 0x5955, 0x5950, 0x594E, - 0x595A, 0x5958, 0x5962, 0x5960, 0x5967, 0x596C, 0x5969, -}; -static const unsigned short euc_to_utf8_D5[] = { - 0x5978, 0x5981, 0x599D, 0x4F5E, 0x4FAB, 0x59A3, 0x59B2, - 0x59C6, 0x59E8, 0x59DC, 0x598D, 0x59D9, 0x59DA, 0x5A25, 0x5A1F, - 0x5A11, 0x5A1C, 0x5A09, 0x5A1A, 0x5A40, 0x5A6C, 0x5A49, 0x5A35, - 0x5A36, 0x5A62, 0x5A6A, 0x5A9A, 0x5ABC, 0x5ABE, 0x5ACB, 0x5AC2, - 0x5ABD, 0x5AE3, 0x5AD7, 0x5AE6, 0x5AE9, 0x5AD6, 0x5AFA, 0x5AFB, - 0x5B0C, 0x5B0B, 0x5B16, 0x5B32, 0x5AD0, 0x5B2A, 0x5B36, 0x5B3E, - 0x5B43, 0x5B45, 0x5B40, 0x5B51, 0x5B55, 0x5B5A, 0x5B5B, 0x5B65, - 0x5B69, 0x5B70, 0x5B73, 0x5B75, 0x5B78, 0x6588, 0x5B7A, 0x5B80, - 0x5B83, 0x5BA6, 0x5BB8, 0x5BC3, 0x5BC7, 0x5BC9, 0x5BD4, 0x5BD0, - 0x5BE4, 0x5BE6, 0x5BE2, 0x5BDE, 0x5BE5, 0x5BEB, 0x5BF0, 0x5BF6, - 0x5BF3, 0x5C05, 0x5C07, 0x5C08, 0x5C0D, 0x5C13, 0x5C20, 0x5C22, - 0x5C28, 0x5C38, 0x5C39, 0x5C41, 0x5C46, 0x5C4E, 0x5C53, -}; -static const unsigned short euc_to_utf8_D6[] = { - 0x5C50, 0x5C4F, 0x5B71, 0x5C6C, 0x5C6E, 0x4E62, 0x5C76, - 0x5C79, 0x5C8C, 0x5C91, 0x5C94, 0x599B, 0x5CAB, 0x5CBB, 0x5CB6, - 0x5CBC, 0x5CB7, 0x5CC5, 0x5CBE, 0x5CC7, 0x5CD9, 0x5CE9, 0x5CFD, - 0x5CFA, 0x5CED, 0x5D8C, 0x5CEA, 0x5D0B, 0x5D15, 0x5D17, 0x5D5C, - 0x5D1F, 0x5D1B, 0x5D11, 0x5D14, 0x5D22, 0x5D1A, 0x5D19, 0x5D18, - 0x5D4C, 0x5D52, 0x5D4E, 0x5D4B, 0x5D6C, 0x5D73, 0x5D76, 0x5D87, - 0x5D84, 0x5D82, 0x5DA2, 0x5D9D, 0x5DAC, 0x5DAE, 0x5DBD, 0x5D90, - 0x5DB7, 0x5DBC, 0x5DC9, 0x5DCD, 0x5DD3, 0x5DD2, 0x5DD6, 0x5DDB, - 0x5DEB, 0x5DF2, 0x5DF5, 0x5E0B, 0x5E1A, 0x5E19, 0x5E11, 0x5E1B, - 0x5E36, 0x5E37, 0x5E44, 0x5E43, 0x5E40, 0x5E4E, 0x5E57, 0x5E54, - 0x5E5F, 0x5E62, 0x5E64, 0x5E47, 0x5E75, 0x5E76, 0x5E7A, 0x9EBC, - 0x5E7F, 0x5EA0, 0x5EC1, 0x5EC2, 0x5EC8, 0x5ED0, 0x5ECF, -}; -static const unsigned short euc_to_utf8_D7[] = { - 0x5ED6, 0x5EE3, 0x5EDD, 0x5EDA, 0x5EDB, 0x5EE2, 0x5EE1, - 0x5EE8, 0x5EE9, 0x5EEC, 0x5EF1, 0x5EF3, 0x5EF0, 0x5EF4, 0x5EF8, - 0x5EFE, 0x5F03, 0x5F09, 0x5F5D, 0x5F5C, 0x5F0B, 0x5F11, 0x5F16, - 0x5F29, 0x5F2D, 0x5F38, 0x5F41, 0x5F48, 0x5F4C, 0x5F4E, 0x5F2F, - 0x5F51, 0x5F56, 0x5F57, 0x5F59, 0x5F61, 0x5F6D, 0x5F73, 0x5F77, - 0x5F83, 0x5F82, 0x5F7F, 0x5F8A, 0x5F88, 0x5F91, 0x5F87, 0x5F9E, - 0x5F99, 0x5F98, 0x5FA0, 0x5FA8, 0x5FAD, 0x5FBC, 0x5FD6, 0x5FFB, - 0x5FE4, 0x5FF8, 0x5FF1, 0x5FDD, 0x60B3, 0x5FFF, 0x6021, 0x6060, - 0x6019, 0x6010, 0x6029, 0x600E, 0x6031, 0x601B, 0x6015, 0x602B, - 0x6026, 0x600F, 0x603A, 0x605A, 0x6041, 0x606A, 0x6077, 0x605F, - 0x604A, 0x6046, 0x604D, 0x6063, 0x6043, 0x6064, 0x6042, 0x606C, - 0x606B, 0x6059, 0x6081, 0x608D, 0x60E7, 0x6083, 0x609A, -}; -static const unsigned short euc_to_utf8_D8[] = { - 0x6084, 0x609B, 0x6096, 0x6097, 0x6092, 0x60A7, 0x608B, - 0x60E1, 0x60B8, 0x60E0, 0x60D3, 0x60B4, 0x5FF0, 0x60BD, 0x60C6, - 0x60B5, 0x60D8, 0x614D, 0x6115, 0x6106, 0x60F6, 0x60F7, 0x6100, - 0x60F4, 0x60FA, 0x6103, 0x6121, 0x60FB, 0x60F1, 0x610D, 0x610E, - 0x6147, 0x613E, 0x6128, 0x6127, 0x614A, 0x613F, 0x613C, 0x612C, - 0x6134, 0x613D, 0x6142, 0x6144, 0x6173, 0x6177, 0x6158, 0x6159, - 0x615A, 0x616B, 0x6174, 0x616F, 0x6165, 0x6171, 0x615F, 0x615D, - 0x6153, 0x6175, 0x6199, 0x6196, 0x6187, 0x61AC, 0x6194, 0x619A, - 0x618A, 0x6191, 0x61AB, 0x61AE, 0x61CC, 0x61CA, 0x61C9, 0x61F7, - 0x61C8, 0x61C3, 0x61C6, 0x61BA, 0x61CB, 0x7F79, 0x61CD, 0x61E6, - 0x61E3, 0x61F6, 0x61FA, 0x61F4, 0x61FF, 0x61FD, 0x61FC, 0x61FE, - 0x6200, 0x6208, 0x6209, 0x620D, 0x620C, 0x6214, 0x621B, -}; -static const unsigned short euc_to_utf8_D9[] = { - 0x621E, 0x6221, 0x622A, 0x622E, 0x6230, 0x6232, 0x6233, - 0x6241, 0x624E, 0x625E, 0x6263, 0x625B, 0x6260, 0x6268, 0x627C, - 0x6282, 0x6289, 0x627E, 0x6292, 0x6293, 0x6296, 0x62D4, 0x6283, - 0x6294, 0x62D7, 0x62D1, 0x62BB, 0x62CF, 0x62FF, 0x62C6, 0x64D4, - 0x62C8, 0x62DC, 0x62CC, 0x62CA, 0x62C2, 0x62C7, 0x629B, 0x62C9, - 0x630C, 0x62EE, 0x62F1, 0x6327, 0x6302, 0x6308, 0x62EF, 0x62F5, - 0x6350, 0x633E, 0x634D, 0x641C, 0x634F, 0x6396, 0x638E, 0x6380, - 0x63AB, 0x6376, 0x63A3, 0x638F, 0x6389, 0x639F, 0x63B5, 0x636B, - 0x6369, 0x63BE, 0x63E9, 0x63C0, 0x63C6, 0x63E3, 0x63C9, 0x63D2, - 0x63F6, 0x63C4, 0x6416, 0x6434, 0x6406, 0x6413, 0x6426, 0x6436, - 0x651D, 0x6417, 0x6428, 0x640F, 0x6467, 0x646F, 0x6476, 0x644E, - 0x652A, 0x6495, 0x6493, 0x64A5, 0x64A9, 0x6488, 0x64BC, -}; -static const unsigned short euc_to_utf8_DA[] = { - 0x64DA, 0x64D2, 0x64C5, 0x64C7, 0x64BB, 0x64D8, 0x64C2, - 0x64F1, 0x64E7, 0x8209, 0x64E0, 0x64E1, 0x62AC, 0x64E3, 0x64EF, - 0x652C, 0x64F6, 0x64F4, 0x64F2, 0x64FA, 0x6500, 0x64FD, 0x6518, - 0x651C, 0x6505, 0x6524, 0x6523, 0x652B, 0x6534, 0x6535, 0x6537, - 0x6536, 0x6538, 0x754B, 0x6548, 0x6556, 0x6555, 0x654D, 0x6558, - 0x655E, 0x655D, 0x6572, 0x6578, 0x6582, 0x6583, 0x8B8A, 0x659B, - 0x659F, 0x65AB, 0x65B7, 0x65C3, 0x65C6, 0x65C1, 0x65C4, 0x65CC, - 0x65D2, 0x65DB, 0x65D9, 0x65E0, 0x65E1, 0x65F1, 0x6772, 0x660A, - 0x6603, 0x65FB, 0x6773, 0x6635, 0x6636, 0x6634, 0x661C, 0x664F, - 0x6644, 0x6649, 0x6641, 0x665E, 0x665D, 0x6664, 0x6667, 0x6668, - 0x665F, 0x6662, 0x6670, 0x6683, 0x6688, 0x668E, 0x6689, 0x6684, - 0x6698, 0x669D, 0x66C1, 0x66B9, 0x66C9, 0x66BE, 0x66BC, -}; -static const unsigned short euc_to_utf8_DB[] = { - 0x66C4, 0x66B8, 0x66D6, 0x66DA, 0x66E0, 0x663F, 0x66E6, - 0x66E9, 0x66F0, 0x66F5, 0x66F7, 0x670F, 0x6716, 0x671E, 0x6726, - 0x6727, 0x9738, 0x672E, 0x673F, 0x6736, 0x6741, 0x6738, 0x6737, - 0x6746, 0x675E, 0x6760, 0x6759, 0x6763, 0x6764, 0x6789, 0x6770, - 0x67A9, 0x677C, 0x676A, 0x678C, 0x678B, 0x67A6, 0x67A1, 0x6785, - 0x67B7, 0x67EF, 0x67B4, 0x67EC, 0x67B3, 0x67E9, 0x67B8, 0x67E4, - 0x67DE, 0x67DD, 0x67E2, 0x67EE, 0x67B9, 0x67CE, 0x67C6, 0x67E7, - 0x6A9C, 0x681E, 0x6846, 0x6829, 0x6840, 0x684D, 0x6832, 0x684E, - 0x68B3, 0x682B, 0x6859, 0x6863, 0x6877, 0x687F, 0x689F, 0x688F, - 0x68AD, 0x6894, 0x689D, 0x689B, 0x6883, 0x6AAE, 0x68B9, 0x6874, - 0x68B5, 0x68A0, 0x68BA, 0x690F, 0x688D, 0x687E, 0x6901, 0x68CA, - 0x6908, 0x68D8, 0x6922, 0x6926, 0x68E1, 0x690C, 0x68CD, -}; -static const unsigned short euc_to_utf8_DC[] = { - 0x68D4, 0x68E7, 0x68D5, 0x6936, 0x6912, 0x6904, 0x68D7, - 0x68E3, 0x6925, 0x68F9, 0x68E0, 0x68EF, 0x6928, 0x692A, 0x691A, - 0x6923, 0x6921, 0x68C6, 0x6979, 0x6977, 0x695C, 0x6978, 0x696B, - 0x6954, 0x697E, 0x696E, 0x6939, 0x6974, 0x693D, 0x6959, 0x6930, - 0x6961, 0x695E, 0x695D, 0x6981, 0x696A, 0x69B2, 0x69AE, 0x69D0, - 0x69BF, 0x69C1, 0x69D3, 0x69BE, 0x69CE, 0x5BE8, 0x69CA, 0x69DD, - 0x69BB, 0x69C3, 0x69A7, 0x6A2E, 0x6991, 0x69A0, 0x699C, 0x6995, - 0x69B4, 0x69DE, 0x69E8, 0x6A02, 0x6A1B, 0x69FF, 0x6B0A, 0x69F9, - 0x69F2, 0x69E7, 0x6A05, 0x69B1, 0x6A1E, 0x69ED, 0x6A14, 0x69EB, - 0x6A0A, 0x6A12, 0x6AC1, 0x6A23, 0x6A13, 0x6A44, 0x6A0C, 0x6A72, - 0x6A36, 0x6A78, 0x6A47, 0x6A62, 0x6A59, 0x6A66, 0x6A48, 0x6A38, - 0x6A22, 0x6A90, 0x6A8D, 0x6AA0, 0x6A84, 0x6AA2, 0x6AA3, -}; -static const unsigned short euc_to_utf8_DD[] = { - 0x6A97, 0x8617, 0x6ABB, 0x6AC3, 0x6AC2, 0x6AB8, 0x6AB3, - 0x6AAC, 0x6ADE, 0x6AD1, 0x6ADF, 0x6AAA, 0x6ADA, 0x6AEA, 0x6AFB, - 0x6B05, 0x8616, 0x6AFA, 0x6B12, 0x6B16, 0x9B31, 0x6B1F, 0x6B38, - 0x6B37, 0x76DC, 0x6B39, 0x98EE, 0x6B47, 0x6B43, 0x6B49, 0x6B50, - 0x6B59, 0x6B54, 0x6B5B, 0x6B5F, 0x6B61, 0x6B78, 0x6B79, 0x6B7F, - 0x6B80, 0x6B84, 0x6B83, 0x6B8D, 0x6B98, 0x6B95, 0x6B9E, 0x6BA4, - 0x6BAA, 0x6BAB, 0x6BAF, 0x6BB2, 0x6BB1, 0x6BB3, 0x6BB7, 0x6BBC, - 0x6BC6, 0x6BCB, 0x6BD3, 0x6BDF, 0x6BEC, 0x6BEB, 0x6BF3, 0x6BEF, - 0x9EBE, 0x6C08, 0x6C13, 0x6C14, 0x6C1B, 0x6C24, 0x6C23, 0x6C5E, - 0x6C55, 0x6C62, 0x6C6A, 0x6C82, 0x6C8D, 0x6C9A, 0x6C81, 0x6C9B, - 0x6C7E, 0x6C68, 0x6C73, 0x6C92, 0x6C90, 0x6CC4, 0x6CF1, 0x6CD3, - 0x6CBD, 0x6CD7, 0x6CC5, 0x6CDD, 0x6CAE, 0x6CB1, 0x6CBE, -}; -static const unsigned short euc_to_utf8_DE[] = { - 0x6CBA, 0x6CDB, 0x6CEF, 0x6CD9, 0x6CEA, 0x6D1F, 0x884D, - 0x6D36, 0x6D2B, 0x6D3D, 0x6D38, 0x6D19, 0x6D35, 0x6D33, 0x6D12, - 0x6D0C, 0x6D63, 0x6D93, 0x6D64, 0x6D5A, 0x6D79, 0x6D59, 0x6D8E, - 0x6D95, 0x6FE4, 0x6D85, 0x6DF9, 0x6E15, 0x6E0A, 0x6DB5, 0x6DC7, - 0x6DE6, 0x6DB8, 0x6DC6, 0x6DEC, 0x6DDE, 0x6DCC, 0x6DE8, 0x6DD2, - 0x6DC5, 0x6DFA, 0x6DD9, 0x6DE4, 0x6DD5, 0x6DEA, 0x6DEE, 0x6E2D, - 0x6E6E, 0x6E2E, 0x6E19, 0x6E72, 0x6E5F, 0x6E3E, 0x6E23, 0x6E6B, - 0x6E2B, 0x6E76, 0x6E4D, 0x6E1F, 0x6E43, 0x6E3A, 0x6E4E, 0x6E24, - 0x6EFF, 0x6E1D, 0x6E38, 0x6E82, 0x6EAA, 0x6E98, 0x6EC9, 0x6EB7, - 0x6ED3, 0x6EBD, 0x6EAF, 0x6EC4, 0x6EB2, 0x6ED4, 0x6ED5, 0x6E8F, - 0x6EA5, 0x6EC2, 0x6E9F, 0x6F41, 0x6F11, 0x704C, 0x6EEC, 0x6EF8, - 0x6EFE, 0x6F3F, 0x6EF2, 0x6F31, 0x6EEF, 0x6F32, 0x6ECC, -}; -static const unsigned short euc_to_utf8_DF[] = { - 0x6F3E, 0x6F13, 0x6EF7, 0x6F86, 0x6F7A, 0x6F78, 0x6F81, - 0x6F80, 0x6F6F, 0x6F5B, 0x6FF3, 0x6F6D, 0x6F82, 0x6F7C, 0x6F58, - 0x6F8E, 0x6F91, 0x6FC2, 0x6F66, 0x6FB3, 0x6FA3, 0x6FA1, 0x6FA4, - 0x6FB9, 0x6FC6, 0x6FAA, 0x6FDF, 0x6FD5, 0x6FEC, 0x6FD4, 0x6FD8, - 0x6FF1, 0x6FEE, 0x6FDB, 0x7009, 0x700B, 0x6FFA, 0x7011, 0x7001, - 0x700F, 0x6FFE, 0x701B, 0x701A, 0x6F74, 0x701D, 0x7018, 0x701F, - 0x7030, 0x703E, 0x7032, 0x7051, 0x7063, 0x7099, 0x7092, 0x70AF, - 0x70F1, 0x70AC, 0x70B8, 0x70B3, 0x70AE, 0x70DF, 0x70CB, 0x70DD, - 0x70D9, 0x7109, 0x70FD, 0x711C, 0x7119, 0x7165, 0x7155, 0x7188, - 0x7166, 0x7162, 0x714C, 0x7156, 0x716C, 0x718F, 0x71FB, 0x7184, - 0x7195, 0x71A8, 0x71AC, 0x71D7, 0x71B9, 0x71BE, 0x71D2, 0x71C9, - 0x71D4, 0x71CE, 0x71E0, 0x71EC, 0x71E7, 0x71F5, 0x71FC, -}; -static const unsigned short euc_to_utf8_E0[] = { - 0x71F9, 0x71FF, 0x720D, 0x7210, 0x721B, 0x7228, 0x722D, - 0x722C, 0x7230, 0x7232, 0x723B, 0x723C, 0x723F, 0x7240, 0x7246, - 0x724B, 0x7258, 0x7274, 0x727E, 0x7282, 0x7281, 0x7287, 0x7292, - 0x7296, 0x72A2, 0x72A7, 0x72B9, 0x72B2, 0x72C3, 0x72C6, 0x72C4, - 0x72CE, 0x72D2, 0x72E2, 0x72E0, 0x72E1, 0x72F9, 0x72F7, 0x500F, - 0x7317, 0x730A, 0x731C, 0x7316, 0x731D, 0x7334, 0x732F, 0x7329, - 0x7325, 0x733E, 0x734E, 0x734F, 0x9ED8, 0x7357, 0x736A, 0x7368, - 0x7370, 0x7378, 0x7375, 0x737B, 0x737A, 0x73C8, 0x73B3, 0x73CE, - 0x73BB, 0x73C0, 0x73E5, 0x73EE, 0x73DE, 0x74A2, 0x7405, 0x746F, - 0x7425, 0x73F8, 0x7432, 0x743A, 0x7455, 0x743F, 0x745F, 0x7459, - 0x7441, 0x745C, 0x7469, 0x7470, 0x7463, 0x746A, 0x7476, 0x747E, - 0x748B, 0x749E, 0x74A7, 0x74CA, 0x74CF, 0x74D4, 0x73F1, -}; -static const unsigned short euc_to_utf8_E1[] = { - 0x74E0, 0x74E3, 0x74E7, 0x74E9, 0x74EE, 0x74F2, 0x74F0, - 0x74F1, 0x74F8, 0x74F7, 0x7504, 0x7503, 0x7505, 0x750C, 0x750E, - 0x750D, 0x7515, 0x7513, 0x751E, 0x7526, 0x752C, 0x753C, 0x7544, - 0x754D, 0x754A, 0x7549, 0x755B, 0x7546, 0x755A, 0x7569, 0x7564, - 0x7567, 0x756B, 0x756D, 0x7578, 0x7576, 0x7586, 0x7587, 0x7574, - 0x758A, 0x7589, 0x7582, 0x7594, 0x759A, 0x759D, 0x75A5, 0x75A3, - 0x75C2, 0x75B3, 0x75C3, 0x75B5, 0x75BD, 0x75B8, 0x75BC, 0x75B1, - 0x75CD, 0x75CA, 0x75D2, 0x75D9, 0x75E3, 0x75DE, 0x75FE, 0x75FF, - 0x75FC, 0x7601, 0x75F0, 0x75FA, 0x75F2, 0x75F3, 0x760B, 0x760D, - 0x7609, 0x761F, 0x7627, 0x7620, 0x7621, 0x7622, 0x7624, 0x7634, - 0x7630, 0x763B, 0x7647, 0x7648, 0x7646, 0x765C, 0x7658, 0x7661, - 0x7662, 0x7668, 0x7669, 0x766A, 0x7667, 0x766C, 0x7670, -}; -static const unsigned short euc_to_utf8_E2[] = { - 0x7672, 0x7676, 0x7678, 0x767C, 0x7680, 0x7683, 0x7688, - 0x768B, 0x768E, 0x7696, 0x7693, 0x7699, 0x769A, 0x76B0, 0x76B4, - 0x76B8, 0x76B9, 0x76BA, 0x76C2, 0x76CD, 0x76D6, 0x76D2, 0x76DE, - 0x76E1, 0x76E5, 0x76E7, 0x76EA, 0x862F, 0x76FB, 0x7708, 0x7707, - 0x7704, 0x7729, 0x7724, 0x771E, 0x7725, 0x7726, 0x771B, 0x7737, - 0x7738, 0x7747, 0x775A, 0x7768, 0x776B, 0x775B, 0x7765, 0x777F, - 0x777E, 0x7779, 0x778E, 0x778B, 0x7791, 0x77A0, 0x779E, 0x77B0, - 0x77B6, 0x77B9, 0x77BF, 0x77BC, 0x77BD, 0x77BB, 0x77C7, 0x77CD, - 0x77D7, 0x77DA, 0x77DC, 0x77E3, 0x77EE, 0x77FC, 0x780C, 0x7812, - 0x7926, 0x7820, 0x792A, 0x7845, 0x788E, 0x7874, 0x7886, 0x787C, - 0x789A, 0x788C, 0x78A3, 0x78B5, 0x78AA, 0x78AF, 0x78D1, 0x78C6, - 0x78CB, 0x78D4, 0x78BE, 0x78BC, 0x78C5, 0x78CA, 0x78EC, -}; -static const unsigned short euc_to_utf8_E3[] = { - 0x78E7, 0x78DA, 0x78FD, 0x78F4, 0x7907, 0x7912, 0x7911, - 0x7919, 0x792C, 0x792B, 0x7940, 0x7960, 0x7957, 0x795F, 0x795A, - 0x7955, 0x7953, 0x797A, 0x797F, 0x798A, 0x799D, 0x79A7, 0x9F4B, - 0x79AA, 0x79AE, 0x79B3, 0x79B9, 0x79BA, 0x79C9, 0x79D5, 0x79E7, - 0x79EC, 0x79E1, 0x79E3, 0x7A08, 0x7A0D, 0x7A18, 0x7A19, 0x7A20, - 0x7A1F, 0x7980, 0x7A31, 0x7A3B, 0x7A3E, 0x7A37, 0x7A43, 0x7A57, - 0x7A49, 0x7A61, 0x7A62, 0x7A69, 0x9F9D, 0x7A70, 0x7A79, 0x7A7D, - 0x7A88, 0x7A97, 0x7A95, 0x7A98, 0x7A96, 0x7AA9, 0x7AC8, 0x7AB0, - 0x7AB6, 0x7AC5, 0x7AC4, 0x7ABF, 0x9083, 0x7AC7, 0x7ACA, 0x7ACD, - 0x7ACF, 0x7AD5, 0x7AD3, 0x7AD9, 0x7ADA, 0x7ADD, 0x7AE1, 0x7AE2, - 0x7AE6, 0x7AED, 0x7AF0, 0x7B02, 0x7B0F, 0x7B0A, 0x7B06, 0x7B33, - 0x7B18, 0x7B19, 0x7B1E, 0x7B35, 0x7B28, 0x7B36, 0x7B50, -}; -static const unsigned short euc_to_utf8_E4[] = { - 0x7B7A, 0x7B04, 0x7B4D, 0x7B0B, 0x7B4C, 0x7B45, 0x7B75, - 0x7B65, 0x7B74, 0x7B67, 0x7B70, 0x7B71, 0x7B6C, 0x7B6E, 0x7B9D, - 0x7B98, 0x7B9F, 0x7B8D, 0x7B9C, 0x7B9A, 0x7B8B, 0x7B92, 0x7B8F, - 0x7B5D, 0x7B99, 0x7BCB, 0x7BC1, 0x7BCC, 0x7BCF, 0x7BB4, 0x7BC6, - 0x7BDD, 0x7BE9, 0x7C11, 0x7C14, 0x7BE6, 0x7BE5, 0x7C60, 0x7C00, - 0x7C07, 0x7C13, 0x7BF3, 0x7BF7, 0x7C17, 0x7C0D, 0x7BF6, 0x7C23, - 0x7C27, 0x7C2A, 0x7C1F, 0x7C37, 0x7C2B, 0x7C3D, 0x7C4C, 0x7C43, - 0x7C54, 0x7C4F, 0x7C40, 0x7C50, 0x7C58, 0x7C5F, 0x7C64, 0x7C56, - 0x7C65, 0x7C6C, 0x7C75, 0x7C83, 0x7C90, 0x7CA4, 0x7CAD, 0x7CA2, - 0x7CAB, 0x7CA1, 0x7CA8, 0x7CB3, 0x7CB2, 0x7CB1, 0x7CAE, 0x7CB9, - 0x7CBD, 0x7CC0, 0x7CC5, 0x7CC2, 0x7CD8, 0x7CD2, 0x7CDC, 0x7CE2, - 0x9B3B, 0x7CEF, 0x7CF2, 0x7CF4, 0x7CF6, 0x7CFA, 0x7D06, -}; -static const unsigned short euc_to_utf8_E5[] = { - 0x7D02, 0x7D1C, 0x7D15, 0x7D0A, 0x7D45, 0x7D4B, 0x7D2E, - 0x7D32, 0x7D3F, 0x7D35, 0x7D46, 0x7D73, 0x7D56, 0x7D4E, 0x7D72, - 0x7D68, 0x7D6E, 0x7D4F, 0x7D63, 0x7D93, 0x7D89, 0x7D5B, 0x7D8F, - 0x7D7D, 0x7D9B, 0x7DBA, 0x7DAE, 0x7DA3, 0x7DB5, 0x7DC7, 0x7DBD, - 0x7DAB, 0x7E3D, 0x7DA2, 0x7DAF, 0x7DDC, 0x7DB8, 0x7D9F, 0x7DB0, - 0x7DD8, 0x7DDD, 0x7DE4, 0x7DDE, 0x7DFB, 0x7DF2, 0x7DE1, 0x7E05, - 0x7E0A, 0x7E23, 0x7E21, 0x7E12, 0x7E31, 0x7E1F, 0x7E09, 0x7E0B, - 0x7E22, 0x7E46, 0x7E66, 0x7E3B, 0x7E35, 0x7E39, 0x7E43, 0x7E37, - 0x7E32, 0x7E3A, 0x7E67, 0x7E5D, 0x7E56, 0x7E5E, 0x7E59, 0x7E5A, - 0x7E79, 0x7E6A, 0x7E69, 0x7E7C, 0x7E7B, 0x7E83, 0x7DD5, 0x7E7D, - 0x8FAE, 0x7E7F, 0x7E88, 0x7E89, 0x7E8C, 0x7E92, 0x7E90, 0x7E93, - 0x7E94, 0x7E96, 0x7E8E, 0x7E9B, 0x7E9C, 0x7F38, 0x7F3A, -}; -static const unsigned short euc_to_utf8_E6[] = { - 0x7F45, 0x7F4C, 0x7F4D, 0x7F4E, 0x7F50, 0x7F51, 0x7F55, - 0x7F54, 0x7F58, 0x7F5F, 0x7F60, 0x7F68, 0x7F69, 0x7F67, 0x7F78, - 0x7F82, 0x7F86, 0x7F83, 0x7F88, 0x7F87, 0x7F8C, 0x7F94, 0x7F9E, - 0x7F9D, 0x7F9A, 0x7FA3, 0x7FAF, 0x7FB2, 0x7FB9, 0x7FAE, 0x7FB6, - 0x7FB8, 0x8B71, 0x7FC5, 0x7FC6, 0x7FCA, 0x7FD5, 0x7FD4, 0x7FE1, - 0x7FE6, 0x7FE9, 0x7FF3, 0x7FF9, 0x98DC, 0x8006, 0x8004, 0x800B, - 0x8012, 0x8018, 0x8019, 0x801C, 0x8021, 0x8028, 0x803F, 0x803B, - 0x804A, 0x8046, 0x8052, 0x8058, 0x805A, 0x805F, 0x8062, 0x8068, - 0x8073, 0x8072, 0x8070, 0x8076, 0x8079, 0x807D, 0x807F, 0x8084, - 0x8086, 0x8085, 0x809B, 0x8093, 0x809A, 0x80AD, 0x5190, 0x80AC, - 0x80DB, 0x80E5, 0x80D9, 0x80DD, 0x80C4, 0x80DA, 0x80D6, 0x8109, - 0x80EF, 0x80F1, 0x811B, 0x8129, 0x8123, 0x812F, 0x814B, -}; -static const unsigned short euc_to_utf8_E7[] = { - 0x968B, 0x8146, 0x813E, 0x8153, 0x8151, 0x80FC, 0x8171, - 0x816E, 0x8165, 0x8166, 0x8174, 0x8183, 0x8188, 0x818A, 0x8180, - 0x8182, 0x81A0, 0x8195, 0x81A4, 0x81A3, 0x815F, 0x8193, 0x81A9, - 0x81B0, 0x81B5, 0x81BE, 0x81B8, 0x81BD, 0x81C0, 0x81C2, 0x81BA, - 0x81C9, 0x81CD, 0x81D1, 0x81D9, 0x81D8, 0x81C8, 0x81DA, 0x81DF, - 0x81E0, 0x81E7, 0x81FA, 0x81FB, 0x81FE, 0x8201, 0x8202, 0x8205, - 0x8207, 0x820A, 0x820D, 0x8210, 0x8216, 0x8229, 0x822B, 0x8238, - 0x8233, 0x8240, 0x8259, 0x8258, 0x825D, 0x825A, 0x825F, 0x8264, - 0x8262, 0x8268, 0x826A, 0x826B, 0x822E, 0x8271, 0x8277, 0x8278, - 0x827E, 0x828D, 0x8292, 0x82AB, 0x829F, 0x82BB, 0x82AC, 0x82E1, - 0x82E3, 0x82DF, 0x82D2, 0x82F4, 0x82F3, 0x82FA, 0x8393, 0x8303, - 0x82FB, 0x82F9, 0x82DE, 0x8306, 0x82DC, 0x8309, 0x82D9, -}; -static const unsigned short euc_to_utf8_E8[] = { - 0x8335, 0x8334, 0x8316, 0x8332, 0x8331, 0x8340, 0x8339, - 0x8350, 0x8345, 0x832F, 0x832B, 0x8317, 0x8318, 0x8385, 0x839A, - 0x83AA, 0x839F, 0x83A2, 0x8396, 0x8323, 0x838E, 0x8387, 0x838A, - 0x837C, 0x83B5, 0x8373, 0x8375, 0x83A0, 0x8389, 0x83A8, 0x83F4, - 0x8413, 0x83EB, 0x83CE, 0x83FD, 0x8403, 0x83D8, 0x840B, 0x83C1, - 0x83F7, 0x8407, 0x83E0, 0x83F2, 0x840D, 0x8422, 0x8420, 0x83BD, - 0x8438, 0x8506, 0x83FB, 0x846D, 0x842A, 0x843C, 0x855A, 0x8484, - 0x8477, 0x846B, 0x84AD, 0x846E, 0x8482, 0x8469, 0x8446, 0x842C, - 0x846F, 0x8479, 0x8435, 0x84CA, 0x8462, 0x84B9, 0x84BF, 0x849F, - 0x84D9, 0x84CD, 0x84BB, 0x84DA, 0x84D0, 0x84C1, 0x84C6, 0x84D6, - 0x84A1, 0x8521, 0x84FF, 0x84F4, 0x8517, 0x8518, 0x852C, 0x851F, - 0x8515, 0x8514, 0x84FC, 0x8540, 0x8563, 0x8558, 0x8548, -}; -static const unsigned short euc_to_utf8_E9[] = { - 0x8541, 0x8602, 0x854B, 0x8555, 0x8580, 0x85A4, 0x8588, - 0x8591, 0x858A, 0x85A8, 0x856D, 0x8594, 0x859B, 0x85EA, 0x8587, - 0x859C, 0x8577, 0x857E, 0x8590, 0x85C9, 0x85BA, 0x85CF, 0x85B9, - 0x85D0, 0x85D5, 0x85DD, 0x85E5, 0x85DC, 0x85F9, 0x860A, 0x8613, - 0x860B, 0x85FE, 0x85FA, 0x8606, 0x8622, 0x861A, 0x8630, 0x863F, - 0x864D, 0x4E55, 0x8654, 0x865F, 0x8667, 0x8671, 0x8693, 0x86A3, - 0x86A9, 0x86AA, 0x868B, 0x868C, 0x86B6, 0x86AF, 0x86C4, 0x86C6, - 0x86B0, 0x86C9, 0x8823, 0x86AB, 0x86D4, 0x86DE, 0x86E9, 0x86EC, - 0x86DF, 0x86DB, 0x86EF, 0x8712, 0x8706, 0x8708, 0x8700, 0x8703, - 0x86FB, 0x8711, 0x8709, 0x870D, 0x86F9, 0x870A, 0x8734, 0x873F, - 0x8737, 0x873B, 0x8725, 0x8729, 0x871A, 0x8760, 0x875F, 0x8778, - 0x874C, 0x874E, 0x8774, 0x8757, 0x8768, 0x876E, 0x8759, -}; -static const unsigned short euc_to_utf8_EA[] = { - 0x8753, 0x8763, 0x876A, 0x8805, 0x87A2, 0x879F, 0x8782, - 0x87AF, 0x87CB, 0x87BD, 0x87C0, 0x87D0, 0x96D6, 0x87AB, 0x87C4, - 0x87B3, 0x87C7, 0x87C6, 0x87BB, 0x87EF, 0x87F2, 0x87E0, 0x880F, - 0x880D, 0x87FE, 0x87F6, 0x87F7, 0x880E, 0x87D2, 0x8811, 0x8816, - 0x8815, 0x8822, 0x8821, 0x8831, 0x8836, 0x8839, 0x8827, 0x883B, - 0x8844, 0x8842, 0x8852, 0x8859, 0x885E, 0x8862, 0x886B, 0x8881, - 0x887E, 0x889E, 0x8875, 0x887D, 0x88B5, 0x8872, 0x8882, 0x8897, - 0x8892, 0x88AE, 0x8899, 0x88A2, 0x888D, 0x88A4, 0x88B0, 0x88BF, - 0x88B1, 0x88C3, 0x88C4, 0x88D4, 0x88D8, 0x88D9, 0x88DD, 0x88F9, - 0x8902, 0x88FC, 0x88F4, 0x88E8, 0x88F2, 0x8904, 0x890C, 0x890A, - 0x8913, 0x8943, 0x891E, 0x8925, 0x892A, 0x892B, 0x8941, 0x8944, - 0x893B, 0x8936, 0x8938, 0x894C, 0x891D, 0x8960, 0x895E, -}; -static const unsigned short euc_to_utf8_EB[] = { - 0x8966, 0x8964, 0x896D, 0x896A, 0x896F, 0x8974, 0x8977, - 0x897E, 0x8983, 0x8988, 0x898A, 0x8993, 0x8998, 0x89A1, 0x89A9, - 0x89A6, 0x89AC, 0x89AF, 0x89B2, 0x89BA, 0x89BD, 0x89BF, 0x89C0, - 0x89DA, 0x89DC, 0x89DD, 0x89E7, 0x89F4, 0x89F8, 0x8A03, 0x8A16, - 0x8A10, 0x8A0C, 0x8A1B, 0x8A1D, 0x8A25, 0x8A36, 0x8A41, 0x8A5B, - 0x8A52, 0x8A46, 0x8A48, 0x8A7C, 0x8A6D, 0x8A6C, 0x8A62, 0x8A85, - 0x8A82, 0x8A84, 0x8AA8, 0x8AA1, 0x8A91, 0x8AA5, 0x8AA6, 0x8A9A, - 0x8AA3, 0x8AC4, 0x8ACD, 0x8AC2, 0x8ADA, 0x8AEB, 0x8AF3, 0x8AE7, - 0x8AE4, 0x8AF1, 0x8B14, 0x8AE0, 0x8AE2, 0x8AF7, 0x8ADE, 0x8ADB, - 0x8B0C, 0x8B07, 0x8B1A, 0x8AE1, 0x8B16, 0x8B10, 0x8B17, 0x8B20, - 0x8B33, 0x97AB, 0x8B26, 0x8B2B, 0x8B3E, 0x8B28, 0x8B41, 0x8B4C, - 0x8B4F, 0x8B4E, 0x8B49, 0x8B56, 0x8B5B, 0x8B5A, 0x8B6B, -}; -static const unsigned short euc_to_utf8_EC[] = { - 0x8B5F, 0x8B6C, 0x8B6F, 0x8B74, 0x8B7D, 0x8B80, 0x8B8C, - 0x8B8E, 0x8B92, 0x8B93, 0x8B96, 0x8B99, 0x8B9A, 0x8C3A, 0x8C41, - 0x8C3F, 0x8C48, 0x8C4C, 0x8C4E, 0x8C50, 0x8C55, 0x8C62, 0x8C6C, - 0x8C78, 0x8C7A, 0x8C82, 0x8C89, 0x8C85, 0x8C8A, 0x8C8D, 0x8C8E, - 0x8C94, 0x8C7C, 0x8C98, 0x621D, 0x8CAD, 0x8CAA, 0x8CBD, 0x8CB2, - 0x8CB3, 0x8CAE, 0x8CB6, 0x8CC8, 0x8CC1, 0x8CE4, 0x8CE3, 0x8CDA, - 0x8CFD, 0x8CFA, 0x8CFB, 0x8D04, 0x8D05, 0x8D0A, 0x8D07, 0x8D0F, - 0x8D0D, 0x8D10, 0x9F4E, 0x8D13, 0x8CCD, 0x8D14, 0x8D16, 0x8D67, - 0x8D6D, 0x8D71, 0x8D73, 0x8D81, 0x8D99, 0x8DC2, 0x8DBE, 0x8DBA, - 0x8DCF, 0x8DDA, 0x8DD6, 0x8DCC, 0x8DDB, 0x8DCB, 0x8DEA, 0x8DEB, - 0x8DDF, 0x8DE3, 0x8DFC, 0x8E08, 0x8E09, 0x8DFF, 0x8E1D, 0x8E1E, - 0x8E10, 0x8E1F, 0x8E42, 0x8E35, 0x8E30, 0x8E34, 0x8E4A, -}; -static const unsigned short euc_to_utf8_ED[] = { - 0x8E47, 0x8E49, 0x8E4C, 0x8E50, 0x8E48, 0x8E59, 0x8E64, - 0x8E60, 0x8E2A, 0x8E63, 0x8E55, 0x8E76, 0x8E72, 0x8E7C, 0x8E81, - 0x8E87, 0x8E85, 0x8E84, 0x8E8B, 0x8E8A, 0x8E93, 0x8E91, 0x8E94, - 0x8E99, 0x8EAA, 0x8EA1, 0x8EAC, 0x8EB0, 0x8EC6, 0x8EB1, 0x8EBE, - 0x8EC5, 0x8EC8, 0x8ECB, 0x8EDB, 0x8EE3, 0x8EFC, 0x8EFB, 0x8EEB, - 0x8EFE, 0x8F0A, 0x8F05, 0x8F15, 0x8F12, 0x8F19, 0x8F13, 0x8F1C, - 0x8F1F, 0x8F1B, 0x8F0C, 0x8F26, 0x8F33, 0x8F3B, 0x8F39, 0x8F45, - 0x8F42, 0x8F3E, 0x8F4C, 0x8F49, 0x8F46, 0x8F4E, 0x8F57, 0x8F5C, - 0x8F62, 0x8F63, 0x8F64, 0x8F9C, 0x8F9F, 0x8FA3, 0x8FAD, 0x8FAF, - 0x8FB7, 0x8FDA, 0x8FE5, 0x8FE2, 0x8FEA, 0x8FEF, 0x9087, 0x8FF4, - 0x9005, 0x8FF9, 0x8FFA, 0x9011, 0x9015, 0x9021, 0x900D, 0x901E, - 0x9016, 0x900B, 0x9027, 0x9036, 0x9035, 0x9039, 0x8FF8, -}; -static const unsigned short euc_to_utf8_EE[] = { - 0x904F, 0x9050, 0x9051, 0x9052, 0x900E, 0x9049, 0x903E, - 0x9056, 0x9058, 0x905E, 0x9068, 0x906F, 0x9076, 0x96A8, 0x9072, - 0x9082, 0x907D, 0x9081, 0x9080, 0x908A, 0x9089, 0x908F, 0x90A8, - 0x90AF, 0x90B1, 0x90B5, 0x90E2, 0x90E4, 0x6248, 0x90DB, 0x9102, - 0x9112, 0x9119, 0x9132, 0x9130, 0x914A, 0x9156, 0x9158, 0x9163, - 0x9165, 0x9169, 0x9173, 0x9172, 0x918B, 0x9189, 0x9182, 0x91A2, - 0x91AB, 0x91AF, 0x91AA, 0x91B5, 0x91B4, 0x91BA, 0x91C0, 0x91C1, - 0x91C9, 0x91CB, 0x91D0, 0x91D6, 0x91DF, 0x91E1, 0x91DB, 0x91FC, - 0x91F5, 0x91F6, 0x921E, 0x91FF, 0x9214, 0x922C, 0x9215, 0x9211, - 0x925E, 0x9257, 0x9245, 0x9249, 0x9264, 0x9248, 0x9295, 0x923F, - 0x924B, 0x9250, 0x929C, 0x9296, 0x9293, 0x929B, 0x925A, 0x92CF, - 0x92B9, 0x92B7, 0x92E9, 0x930F, 0x92FA, 0x9344, 0x932E, -}; -static const unsigned short euc_to_utf8_EF[] = { - 0x9319, 0x9322, 0x931A, 0x9323, 0x933A, 0x9335, 0x933B, - 0x935C, 0x9360, 0x937C, 0x936E, 0x9356, 0x93B0, 0x93AC, 0x93AD, - 0x9394, 0x93B9, 0x93D6, 0x93D7, 0x93E8, 0x93E5, 0x93D8, 0x93C3, - 0x93DD, 0x93D0, 0x93C8, 0x93E4, 0x941A, 0x9414, 0x9413, 0x9403, - 0x9407, 0x9410, 0x9436, 0x942B, 0x9435, 0x9421, 0x943A, 0x9441, - 0x9452, 0x9444, 0x945B, 0x9460, 0x9462, 0x945E, 0x946A, 0x9229, - 0x9470, 0x9475, 0x9477, 0x947D, 0x945A, 0x947C, 0x947E, 0x9481, - 0x947F, 0x9582, 0x9587, 0x958A, 0x9594, 0x9596, 0x9598, 0x9599, - 0x95A0, 0x95A8, 0x95A7, 0x95AD, 0x95BC, 0x95BB, 0x95B9, 0x95BE, - 0x95CA, 0x6FF6, 0x95C3, 0x95CD, 0x95CC, 0x95D5, 0x95D4, 0x95D6, - 0x95DC, 0x95E1, 0x95E5, 0x95E2, 0x9621, 0x9628, 0x962E, 0x962F, - 0x9642, 0x964C, 0x964F, 0x964B, 0x9677, 0x965C, 0x965E, -}; -static const unsigned short euc_to_utf8_F0[] = { - 0x965D, 0x965F, 0x9666, 0x9672, 0x966C, 0x968D, 0x9698, - 0x9695, 0x9697, 0x96AA, 0x96A7, 0x96B1, 0x96B2, 0x96B0, 0x96B4, - 0x96B6, 0x96B8, 0x96B9, 0x96CE, 0x96CB, 0x96C9, 0x96CD, 0x894D, - 0x96DC, 0x970D, 0x96D5, 0x96F9, 0x9704, 0x9706, 0x9708, 0x9713, - 0x970E, 0x9711, 0x970F, 0x9716, 0x9719, 0x9724, 0x972A, 0x9730, - 0x9739, 0x973D, 0x973E, 0x9744, 0x9746, 0x9748, 0x9742, 0x9749, - 0x975C, 0x9760, 0x9764, 0x9766, 0x9768, 0x52D2, 0x976B, 0x9771, - 0x9779, 0x9785, 0x977C, 0x9781, 0x977A, 0x9786, 0x978B, 0x978F, - 0x9790, 0x979C, 0x97A8, 0x97A6, 0x97A3, 0x97B3, 0x97B4, 0x97C3, - 0x97C6, 0x97C8, 0x97CB, 0x97DC, 0x97ED, 0x9F4F, 0x97F2, 0x7ADF, - 0x97F6, 0x97F5, 0x980F, 0x980C, 0x9838, 0x9824, 0x9821, 0x9837, - 0x983D, 0x9846, 0x984F, 0x984B, 0x986B, 0x986F, 0x9870, -}; -static const unsigned short euc_to_utf8_F1[] = { - 0x9871, 0x9874, 0x9873, 0x98AA, 0x98AF, 0x98B1, 0x98B6, - 0x98C4, 0x98C3, 0x98C6, 0x98E9, 0x98EB, 0x9903, 0x9909, 0x9912, - 0x9914, 0x9918, 0x9921, 0x991D, 0x991E, 0x9924, 0x9920, 0x992C, - 0x992E, 0x993D, 0x993E, 0x9942, 0x9949, 0x9945, 0x9950, 0x994B, - 0x9951, 0x9952, 0x994C, 0x9955, 0x9997, 0x9998, 0x99A5, 0x99AD, - 0x99AE, 0x99BC, 0x99DF, 0x99DB, 0x99DD, 0x99D8, 0x99D1, 0x99ED, - 0x99EE, 0x99F1, 0x99F2, 0x99FB, 0x99F8, 0x9A01, 0x9A0F, 0x9A05, - 0x99E2, 0x9A19, 0x9A2B, 0x9A37, 0x9A45, 0x9A42, 0x9A40, 0x9A43, - 0x9A3E, 0x9A55, 0x9A4D, 0x9A5B, 0x9A57, 0x9A5F, 0x9A62, 0x9A65, - 0x9A64, 0x9A69, 0x9A6B, 0x9A6A, 0x9AAD, 0x9AB0, 0x9ABC, 0x9AC0, - 0x9ACF, 0x9AD1, 0x9AD3, 0x9AD4, 0x9ADE, 0x9ADF, 0x9AE2, 0x9AE3, - 0x9AE6, 0x9AEF, 0x9AEB, 0x9AEE, 0x9AF4, 0x9AF1, 0x9AF7, -}; -static const unsigned short euc_to_utf8_F2[] = { - 0x9AFB, 0x9B06, 0x9B18, 0x9B1A, 0x9B1F, 0x9B22, 0x9B23, - 0x9B25, 0x9B27, 0x9B28, 0x9B29, 0x9B2A, 0x9B2E, 0x9B2F, 0x9B32, - 0x9B44, 0x9B43, 0x9B4F, 0x9B4D, 0x9B4E, 0x9B51, 0x9B58, 0x9B74, - 0x9B93, 0x9B83, 0x9B91, 0x9B96, 0x9B97, 0x9B9F, 0x9BA0, 0x9BA8, - 0x9BB4, 0x9BC0, 0x9BCA, 0x9BB9, 0x9BC6, 0x9BCF, 0x9BD1, 0x9BD2, - 0x9BE3, 0x9BE2, 0x9BE4, 0x9BD4, 0x9BE1, 0x9C3A, 0x9BF2, 0x9BF1, - 0x9BF0, 0x9C15, 0x9C14, 0x9C09, 0x9C13, 0x9C0C, 0x9C06, 0x9C08, - 0x9C12, 0x9C0A, 0x9C04, 0x9C2E, 0x9C1B, 0x9C25, 0x9C24, 0x9C21, - 0x9C30, 0x9C47, 0x9C32, 0x9C46, 0x9C3E, 0x9C5A, 0x9C60, 0x9C67, - 0x9C76, 0x9C78, 0x9CE7, 0x9CEC, 0x9CF0, 0x9D09, 0x9D08, 0x9CEB, - 0x9D03, 0x9D06, 0x9D2A, 0x9D26, 0x9DAF, 0x9D23, 0x9D1F, 0x9D44, - 0x9D15, 0x9D12, 0x9D41, 0x9D3F, 0x9D3E, 0x9D46, 0x9D48, -}; -static const unsigned short euc_to_utf8_F3[] = { - 0x9D5D, 0x9D5E, 0x9D64, 0x9D51, 0x9D50, 0x9D59, 0x9D72, - 0x9D89, 0x9D87, 0x9DAB, 0x9D6F, 0x9D7A, 0x9D9A, 0x9DA4, 0x9DA9, - 0x9DB2, 0x9DC4, 0x9DC1, 0x9DBB, 0x9DB8, 0x9DBA, 0x9DC6, 0x9DCF, - 0x9DC2, 0x9DD9, 0x9DD3, 0x9DF8, 0x9DE6, 0x9DED, 0x9DEF, 0x9DFD, - 0x9E1A, 0x9E1B, 0x9E1E, 0x9E75, 0x9E79, 0x9E7D, 0x9E81, 0x9E88, - 0x9E8B, 0x9E8C, 0x9E92, 0x9E95, 0x9E91, 0x9E9D, 0x9EA5, 0x9EA9, - 0x9EB8, 0x9EAA, 0x9EAD, 0x9761, 0x9ECC, 0x9ECE, 0x9ECF, 0x9ED0, - 0x9ED4, 0x9EDC, 0x9EDE, 0x9EDD, 0x9EE0, 0x9EE5, 0x9EE8, 0x9EEF, - 0x9EF4, 0x9EF6, 0x9EF7, 0x9EF9, 0x9EFB, 0x9EFC, 0x9EFD, 0x9F07, - 0x9F08, 0x76B7, 0x9F15, 0x9F21, 0x9F2C, 0x9F3E, 0x9F4A, 0x9F52, - 0x9F54, 0x9F63, 0x9F5F, 0x9F60, 0x9F61, 0x9F66, 0x9F67, 0x9F6C, - 0x9F6A, 0x9F77, 0x9F72, 0x9F76, 0x9F95, 0x9F9C, 0x9FA0, -}; -static const unsigned short euc_to_utf8_F4[] = { - 0x582F, 0x69C7, 0x9059, 0x7464, 0x51DC, 0x7199, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short euc_to_utf8_F4_x0213[] = { - 0x582F, 0x69C7, 0x9059, 0x7464, 0x51DC, 0x7199, 0x5653, - 0x5DE2, 0x5E14, 0x5E18, 0x5E58, 0x5E5E, 0x5EBE, 0xF928, 0x5ECB, - 0x5EF9, 0x5F00, 0x5F02, 0x5F07, 0x5F1D, 0x5F23, 0x5F34, 0x5F36, - 0x5F3D, 0x5F40, 0x5F45, 0x5F54, 0x5F58, 0x5F64, 0x5F67, 0x5F7D, - 0x5F89, 0x5F9C, 0x5FA7, 0x5FAF, 0x5FB5, 0x5FB7, 0x5FC9, 0x5FDE, - 0x5FE1, 0x5FE9, 0x600D, 0x6014, 0x6018, 0x6033, 0x6035, 0x6047, - 0xFA3D, 0x609D, 0x609E, 0x60CB, 0x60D4, 0x60D5, 0x60DD, 0x60F8, - 0x611C, 0x612B, 0x6130, 0x6137, 0xFA3E, 0x618D, 0xFA3F, 0x61BC, - 0x61B9, 0xFA40, 0x6222, 0x623E, 0x6243, 0x6256, 0x625A, 0x626F, - 0x6285, 0x62C4, 0x62D6, 0x62FC, 0x630A, 0x6318, 0x6339, 0x6343, - 0x6365, 0x637C, 0x63E5, 0x63ED, 0x63F5, 0x6410, 0x6414, 0x6422, - 0x6479, 0x6451, 0x6460, 0x646D, 0x64CE, 0x64BE, 0x64BF, -}; -static const unsigned short euc_to_utf8_F5[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0xFE33, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0xFE31, 0, 0, - 0, 0, 0, 0, 0, 0xFE30, 0, 0, - 0, 0, 0xFE35, 0xFE36, 0xFE39, 0xFE3A, 0, 0, - 0xFE37, 0xFE38, 0xFE3F, 0xFE40, 0xFE3D, 0xFE3E, 0xFE41, 0xFE42, - 0xFE43, 0xFE44, 0xFE3B, 0xFE3C, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short euc_to_utf8_F5_x0213[] = { - 0x64C4, 0x64CA, 0x64D0, 0x64F7, 0x64FB, 0x6522, 0x6529, - 0xFA41, 0x6567, 0x659D, 0xFA42, 0x6600, 0x6609, 0x6615, 0x661E, - 0x663A, 0x6622, 0x6624, 0x662B, 0x6630, 0x6631, 0x6633, 0x66FB, - 0x6648, 0x664C, 0xD84C /*0xDDC4*/, 0x6659, 0x665A, 0x6661, 0x6665, 0x6673, - 0x6677, 0x6678, 0x668D, 0xFA43, 0x66A0, 0x66B2, 0x66BB, 0x66C6, - 0x66C8, 0x3B22, 0x66DB, 0x66E8, 0x66FA, 0x6713, 0xF929, 0x6733, - 0x6766, 0x6747, 0x6748, 0x677B, 0x6781, 0x6793, 0x6798, 0x679B, - 0x67BB, 0x67F9, 0x67C0, 0x67D7, 0x67FC, 0x6801, 0x6852, 0x681D, - 0x682C, 0x6831, 0x685B, 0x6872, 0x6875, 0xFA44, 0x68A3, 0x68A5, - 0x68B2, 0x68C8, 0x68D0, 0x68E8, 0x68ED, 0x68F0, 0x68F1, 0x68FC, - 0x690A, 0x6949, 0xD84D /*0xDDC4*/, 0x6935, 0x6942, 0x6957, 0x6963, 0x6964, - 0x6968, 0x6980, 0xFA14, 0x69A5, 0x69AD, 0x69CF, 0x3BB6, -}; -static const unsigned short euc_to_utf8_F6_x0213[] = { - 0x3BC3, 0x69E2, 0x69E9, 0x69EA, 0x69F5, 0x69F6, 0x6A0F, - 0x6A15, 0xD84D /*0xDF3F*/, 0x6A3B, 0x6A3E, 0x6A45, 0x6A50, 0x6A56, 0x6A5B, - 0x6A6B, 0x6A73, 0xD84D /*0xDF63*/, 0x6A89, 0x6A94, 0x6A9D, 0x6A9E, 0x6AA5, - 0x6AE4, 0x6AE7, 0x3C0F, 0xF91D, 0x6B1B, 0x6B1E, 0x6B2C, 0x6B35, - 0x6B46, 0x6B56, 0x6B60, 0x6B65, 0x6B67, 0x6B77, 0x6B82, 0x6BA9, - 0x6BAD, 0xF970, 0x6BCF, 0x6BD6, 0x6BD7, 0x6BFF, 0x6C05, 0x6C10, - 0x6C33, 0x6C59, 0x6C5C, 0x6CAA, 0x6C74, 0x6C76, 0x6C85, 0x6C86, - 0x6C98, 0x6C9C, 0x6CFB, 0x6CC6, 0x6CD4, 0x6CE0, 0x6CEB, 0x6CEE, - 0xD84F /*0xDCFE*/, 0x6D04, 0x6D0E, 0x6D2E, 0x6D31, 0x6D39, 0x6D3F, 0x6D58, - 0x6D65, 0xFA45, 0x6D82, 0x6D87, 0x6D89, 0x6D94, 0x6DAA, 0x6DAC, - 0x6DBF, 0x6DC4, 0x6DD6, 0x6DDA, 0x6DDB, 0x6DDD, 0x6DFC, 0xFA46, - 0x6E34, 0x6E44, 0x6E5C, 0x6E5E, 0x6EAB, 0x6EB1, 0x6EC1, -}; -static const unsigned short euc_to_utf8_F7_x0213[] = { - 0x6EC7, 0x6ECE, 0x6F10, 0x6F1A, 0xFA47, 0x6F2A, 0x6F2F, - 0x6F33, 0x6F51, 0x6F59, 0x6F5E, 0x6F61, 0x6F62, 0x6F7E, 0x6F88, - 0x6F8C, 0x6F8D, 0x6F94, 0x6FA0, 0x6FA7, 0x6FB6, 0x6FBC, 0x6FC7, - 0x6FCA, 0x6FF9, 0x6FF0, 0x6FF5, 0x7005, 0x7006, 0x7028, 0x704A, - 0x705D, 0x705E, 0x704E, 0x7064, 0x7075, 0x7085, 0x70A4, 0x70AB, - 0x70B7, 0x70D4, 0x70D8, 0x70E4, 0x710F, 0x712B, 0x711E, 0x7120, - 0x712E, 0x7130, 0x7146, 0x7147, 0x7151, 0xFA48, 0x7152, 0x715C, - 0x7160, 0x7168, 0xFA15, 0x7185, 0x7187, 0x7192, 0x71C1, 0x71BA, - 0x71C4, 0x71FE, 0x7200, 0x7215, 0x7255, 0x7256, 0x3E3F, 0x728D, - 0x729B, 0x72BE, 0x72C0, 0x72FB, 0xD851 /*0xDFF1*/, 0x7327, 0x7328, 0xFA16, - 0x7350, 0x7366, 0x737C, 0x7395, 0x739F, 0x73A0, 0x73A2, 0x73A6, - 0x73AB, 0x73C9, 0x73CF, 0x73D6, 0x73D9, 0x73E3, 0x73E9, -}; -static const unsigned short euc_to_utf8_F8_x0213[] = { - 0x7407, 0x740A, 0x741A, 0x741B, 0xFA4A, 0x7426, 0x7428, - 0x742A, 0x742B, 0x742C, 0x742E, 0x742F, 0x7430, 0x7444, 0x7446, - 0x7447, 0x744B, 0x7457, 0x7462, 0x746B, 0x746D, 0x7486, 0x7487, - 0x7489, 0x7498, 0x749C, 0x749F, 0x74A3, 0x7490, 0x74A6, 0x74A8, - 0x74A9, 0x74B5, 0x74BF, 0x74C8, 0x74C9, 0x74DA, 0x74FF, 0x7501, - 0x7517, 0x752F, 0x756F, 0x7579, 0x7592, 0x3F72, 0x75CE, 0x75E4, - 0x7600, 0x7602, 0x7608, 0x7615, 0x7616, 0x7619, 0x761E, 0x762D, - 0x7635, 0x7643, 0x764B, 0x7664, 0x7665, 0x766D, 0x766F, 0x7671, - 0x7681, 0x769B, 0x769D, 0x769E, 0x76A6, 0x76AA, 0x76B6, 0x76C5, - 0x76CC, 0x76CE, 0x76D4, 0x76E6, 0x76F1, 0x76FC, 0x770A, 0x7719, - 0x7734, 0x7736, 0x7746, 0x774D, 0x774E, 0x775C, 0x775F, 0x7762, - 0x777A, 0x7780, 0x7794, 0x77AA, 0x77E0, 0x782D, 0xD855 /*0xDC8E*/, -}; -static const unsigned short euc_to_utf8_F9[] = { - 0x7E8A, 0x891C, 0x9348, 0x9288, 0x84DC, 0x4FC9, 0x70BB, - 0x6631, 0x68C8, 0x92F9, 0x66FB, 0x5F45, 0x4E28, 0x4EE1, 0x4EFC, - 0x4F00, 0x4F03, 0x4F39, 0x4F56, 0x4F92, 0x4F8A, 0x4F9A, 0x4F94, - 0x4FCD, 0x5040, 0x5022, 0x4FFF, 0x501E, 0x5046, 0x5070, 0x5042, - 0x5094, 0x50F4, 0x50D8, 0x514A, 0x5164, 0x519D, 0x51BE, 0x51EC, - 0x5215, 0x529C, 0x52A6, 0x52C0, 0x52DB, 0x5300, 0x5307, 0x5324, - 0x5372, 0x5393, 0x53B2, 0x53DD, 0xFA0E, 0x549C, 0x548A, 0x54A9, - 0x54FF, 0x5586, 0x5759, 0x5765, 0x57AC, 0x57C8, 0x57C7, 0xFA0F, - 0xFA10, 0x589E, 0x58B2, 0x590B, 0x5953, 0x595B, 0x595D, 0x5963, - 0x59A4, 0x59BA, 0x5B56, 0x5BC0, 0x752F, 0x5BD8, 0x5BEC, 0x5C1E, - 0x5CA6, 0x5CBA, 0x5CF5, 0x5D27, 0x5D53, 0xFA11, 0x5D42, 0x5D6D, - 0x5DB8, 0x5DB9, 0x5DD0, 0x5F21, 0x5F34, 0x5F67, 0x5FB7, -}; -static const unsigned short euc_to_utf8_F9_x0213[] = { - 0x7843, 0x784E, 0x784F, 0x7851, 0x7868, 0x786E, 0xFA4B, - 0x78B0, 0xD855 /*0xDD0E*/, 0x78AD, 0x78E4, 0x78F2, 0x7900, 0x78F7, 0x791C, - 0x792E, 0x7931, 0x7934, 0xFA4C, 0xFA4D, 0x7945, 0x7946, 0xFA4E, - 0xFA4F, 0xFA50, 0x795C, 0xFA51, 0xFA19, 0xFA1A, 0x7979, 0xFA52, - 0xFA53, 0xFA1B, 0x7998, 0x79B1, 0x79B8, 0x79C8, 0x79CA, 0xD855 /*0xDF71*/, - 0x79D4, 0x79DE, 0x79EB, 0x79ED, 0x7A03, 0xFA54, 0x7A39, 0x7A5D, - 0x7A6D, 0xFA55, 0x7A85, 0x7AA0, 0xD856 /*0xDDC4*/, 0x7AB3, 0x7ABB, 0x7ACE, - 0x7AEB, 0x7AFD, 0x7B12, 0x7B2D, 0x7B3B, 0x7B47, 0x7B4E, 0x7B60, - 0x7B6D, 0x7B6F, 0x7B72, 0x7B9E, 0xFA56, 0x7BD7, 0x7BD9, 0x7C01, - 0x7C31, 0x7C1E, 0x7C20, 0x7C33, 0x7C36, 0x4264, 0xD857 /*0xDDA1*/, 0x7C59, - 0x7C6D, 0x7C79, 0x7C8F, 0x7C94, 0x7CA0, 0x7CBC, 0x7CD5, 0x7CD9, - 0x7CDD, 0x7D07, 0x7D08, 0x7D13, 0x7D1D, 0x7D23, 0x7D31, -}; -static const unsigned short euc_to_utf8_FA[] = { - 0x5FDE, 0x605D, 0x6085, 0x608A, 0x60DE, 0x60D5, 0x6120, - 0x60F2, 0x6111, 0x6137, 0x6130, 0x6198, 0x6213, 0x62A6, 0x63F5, - 0x6460, 0x649D, 0x64CE, 0x654E, 0x6600, 0x6615, 0x663B, 0x6609, - 0x662E, 0x661E, 0x6624, 0x6665, 0x6657, 0x6659, 0xFA12, 0x6673, - 0x6699, 0x66A0, 0x66B2, 0x66BF, 0x66FA, 0x670E, 0xF929, 0x6766, - 0x67BB, 0x6852, 0x67C0, 0x6801, 0x6844, 0x68CF, 0xFA13, 0x6968, - 0xFA14, 0x6998, 0x69E2, 0x6A30, 0x6A6B, 0x6A46, 0x6A73, 0x6A7E, - 0x6AE2, 0x6AE4, 0x6BD6, 0x6C3F, 0x6C5C, 0x6C86, 0x6C6F, 0x6CDA, - 0x6D04, 0x6D87, 0x6D6F, 0x6D96, 0x6DAC, 0x6DCF, 0x6DF8, 0x6DF2, - 0x6DFC, 0x6E39, 0x6E5C, 0x6E27, 0x6E3C, 0x6EBF, 0x6F88, 0x6FB5, - 0x6FF5, 0x7005, 0x7007, 0x7028, 0x7085, 0x70AB, 0x710F, 0x7104, - 0x715C, 0x7146, 0x7147, 0xFA15, 0x71C1, 0x71FE, 0x72B1, -}; -static const unsigned short euc_to_utf8_FA_x0213[] = { - 0x7D41, 0x7D48, 0x7D53, 0x7D5C, 0x7D7A, 0x7D83, 0x7D8B, - 0x7DA0, 0x7DA6, 0x7DC2, 0x7DCC, 0x7DD6, 0x7DE3, 0xFA57, 0x7E28, - 0x7E08, 0x7E11, 0x7E15, 0xFA59, 0x7E47, 0x7E52, 0x7E61, 0x7E8A, - 0x7E8D, 0x7F47, 0xFA5A, 0x7F91, 0x7F97, 0x7FBF, 0x7FCE, 0x7FDB, - 0x7FDF, 0x7FEC, 0x7FEE, 0x7FFA, 0xFA5B, 0x8014, 0x8026, 0x8035, - 0x8037, 0x803C, 0x80CA, 0x80D7, 0x80E0, 0x80F3, 0x8118, 0x814A, - 0x8160, 0x8167, 0x8168, 0x816D, 0x81BB, 0x81CA, 0x81CF, 0x81D7, - 0xFA5C, 0x4453, 0x445B, 0x8260, 0x8274, 0xD85A /*0xDEFF*/, 0x828E, 0x82A1, - 0x82A3, 0x82A4, 0x82A9, 0x82AE, 0x82B7, 0x82BE, 0x82BF, 0x82C6, - 0x82D5, 0x82FD, 0x82FE, 0x8300, 0x8301, 0x8362, 0x8322, 0x832D, - 0x833A, 0x8343, 0x8347, 0x8351, 0x8355, 0x837D, 0x8386, 0x8392, - 0x8398, 0x83A7, 0x83A9, 0x83BF, 0x83C0, 0x83C7, 0x83CF, -}; -static const unsigned short euc_to_utf8_FB[] = { - 0x72BE, 0x7324, 0xFA16, 0x7377, 0x73BD, 0x73C9, 0x73D6, - 0x73E3, 0x73D2, 0x7407, 0x73F5, 0x7426, 0x742A, 0x7429, 0x742E, - 0x7462, 0x7489, 0x749F, 0x7501, 0x756F, 0x7682, 0x769C, 0x769E, - 0x769B, 0x76A6, 0xFA17, 0x7746, 0x52AF, 0x7821, 0x784E, 0x7864, - 0x787A, 0x7930, 0xFA18, 0xFA19, 0xFA1A, 0x7994, 0xFA1B, 0x799B, - 0x7AD1, 0x7AE7, 0xFA1C, 0x7AEB, 0x7B9E, 0xFA1D, 0x7D48, 0x7D5C, - 0x7DB7, 0x7DA0, 0x7DD6, 0x7E52, 0x7F47, 0x7FA1, 0xFA1E, 0x8301, - 0x8362, 0x837F, 0x83C7, 0x83F6, 0x8448, 0x84B4, 0x8553, 0x8559, - 0x856B, 0xFA1F, 0x85B0, 0xFA20, 0xFA21, 0x8807, 0x88F5, 0x8A12, - 0x8A37, 0x8A79, 0x8AA7, 0x8ABE, 0x8ADF, 0xFA22, 0x8AF6, 0x8B53, - 0x8B7F, 0x8CF0, 0x8CF4, 0x8D12, 0x8D76, 0xFA23, 0x8ECF, 0xFA24, - 0xFA25, 0x9067, 0x90DE, 0xFA26, 0x9115, 0x9127, 0x91DA, -}; -static const unsigned short euc_to_utf8_FB_x0213[] = { - 0x83D1, 0x83E1, 0x83EA, 0x8401, 0x8406, 0x840A, 0xFA5F, - 0x8448, 0x845F, 0x8470, 0x8473, 0x8485, 0x849E, 0x84AF, 0x84B4, - 0x84BA, 0x84C0, 0x84C2, 0xD85B /*0xDE40*/, 0x8532, 0x851E, 0x8523, 0x852F, - 0x8559, 0x8564, 0xFA1F, 0x85AD, 0x857A, 0x858C, 0x858F, 0x85A2, - 0x85B0, 0x85CB, 0x85CE, 0x85ED, 0x8612, 0x85FF, 0x8604, 0x8605, - 0x8610, 0xD85C /*0xDCF4*/, 0x8618, 0x8629, 0x8638, 0x8657, 0x865B, 0xF936, - 0x8662, 0x459D, 0x866C, 0x8675, 0x8698, 0x86B8, 0x86FA, 0x86FC, - 0x86FD, 0x870B, 0x8771, 0x8787, 0x8788, 0x87AC, 0x87AD, 0x87B5, - 0x45EA, 0x87D6, 0x87EC, 0x8806, 0x880A, 0x8810, 0x8814, 0x881F, - 0x8898, 0x88AA, 0x88CA, 0x88CE, 0xD85D /*0xDE84*/, 0x88F5, 0x891C, 0xFA60, - 0x8918, 0x8919, 0x891A, 0x8927, 0x8930, 0x8932, 0x8939, 0x8940, - 0x8994, 0xFA61, 0x89D4, 0x89E5, 0x89F6, 0x8A12, 0x8A15, -}; -static const unsigned short euc_to_utf8_FC[] = { - 0x91D7, 0x91DE, 0x91ED, 0x91EE, 0x91E4, 0x91E5, 0x9206, - 0x9210, 0x920A, 0x923A, 0x9240, 0x923C, 0x924E, 0x9259, 0x9251, - 0x9239, 0x9267, 0x92A7, 0x9277, 0x9278, 0x92E7, 0x92D7, 0x92D9, - 0x92D0, 0xFA27, 0x92D5, 0x92E0, 0x92D3, 0x9325, 0x9321, 0x92FB, - 0xFA28, 0x931E, 0x92FF, 0x931D, 0x9302, 0x9370, 0x9357, 0x93A4, - 0x93C6, 0x93DE, 0x93F8, 0x9431, 0x9445, 0x9448, 0x9592, 0xF9DC, - 0xFA29, 0x969D, 0x96AF, 0x9733, 0x973B, 0x9743, 0x974D, 0x974F, - 0x9751, 0x9755, 0x9857, 0x9865, 0xFA2A, 0xFA2B, 0x9927, 0xFA2C, - 0x999E, 0x9A4E, 0x9AD9, 0x9ADC, 0x9B75, 0x9B72, 0x9B8F, 0x9BB1, - 0x9BBB, 0x9C00, 0x9D70, 0x9D6B, 0xFA2D, 0x9E19, 0x9ED1, 0, - 0, 0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176, - 0x2177, 0x2178, 0x2179, 0xFFE2, 0x00A6, 0xFF07, 0xFF02, -}; - -/* Microsoft UCS Mapping Compatible */ -static const unsigned short euc_to_utf8_FC_ms[] = { - 0x91D7, 0x91DE, 0x91ED, 0x91EE, 0x91E4, 0x91E5, 0x9206, - 0x9210, 0x920A, 0x923A, 0x9240, 0x923C, 0x924E, 0x9259, 0x9251, - 0x9239, 0x9267, 0x92A7, 0x9277, 0x9278, 0x92E7, 0x92D7, 0x92D9, - 0x92D0, 0xFA27, 0x92D5, 0x92E0, 0x92D3, 0x9325, 0x9321, 0x92FB, - 0xFA28, 0x931E, 0x92FF, 0x931D, 0x9302, 0x9370, 0x9357, 0x93A4, - 0x93C6, 0x93DE, 0x93F8, 0x9431, 0x9445, 0x9448, 0x9592, 0xF9DC, - 0xFA29, 0x969D, 0x96AF, 0x9733, 0x973B, 0x9743, 0x974D, 0x974F, - 0x9751, 0x9755, 0x9857, 0x9865, 0xFA2A, 0xFA2B, 0x9927, 0xFA2C, - 0x999E, 0x9A4E, 0x9AD9, 0x9ADC, 0x9B75, 0x9B72, 0x9B8F, 0x9BB1, - 0x9BBB, 0x9C00, 0x9D70, 0x9D6B, 0xFA2D, 0x9E19, 0x9ED1, 0, - 0, 0x2170, 0x2171, 0x2172, 0x2173, 0x2174, 0x2175, 0x2176, - 0x2177, 0x2178, 0x2179, 0xFFE2, 0xFFE4, 0xFF07, 0xFF02, -}; -static const unsigned short euc_to_utf8_FC_x0213[] = { - 0x8A22, 0x8A37, 0x8A47, 0x8A4E, 0x8A5D, 0x8A61, 0x8A75, - 0x8A79, 0x8AA7, 0x8AD0, 0x8ADF, 0x8AF4, 0x8AF6, 0xFA22, 0xFA62, - 0xFA63, 0x8B46, 0x8B54, 0x8B59, 0x8B69, 0x8B9D, 0x8C49, 0x8C68, - 0xFA64, 0x8CE1, 0x8CF4, 0x8CF8, 0x8CFE, 0xFA65, 0x8D12, 0x8D1B, - 0x8DAF, 0x8DCE, 0x8DD1, 0x8DD7, 0x8E20, 0x8E23, 0x8E3D, 0x8E70, - 0x8E7B, 0xD860 /*0xDE77*/, 0x8EC0, 0x4844, 0x8EFA, 0x8F1E, 0x8F2D, 0x8F36, - 0x8F54, 0xD860 /*0xDFCD*/, 0x8FA6, 0x8FB5, 0x8FE4, 0x8FE8, 0x8FEE, 0x9008, - 0x902D, 0xFA67, 0x9088, 0x9095, 0x9097, 0x9099, 0x909B, 0x90A2, - 0x90B3, 0x90BE, 0x90C4, 0x90C5, 0x90C7, 0x90D7, 0x90DD, 0x90DE, - 0x90EF, 0x90F4, 0xFA26, 0x9114, 0x9115, 0x9116, 0x9122, 0x9123, - 0x9127, 0x912F, 0x9131, 0x9134, 0x913D, 0x9148, 0x915B, 0x9183, - 0x919E, 0x91AC, 0x91B1, 0x91BC, 0x91D7, 0x91FB, 0x91E4, -}; -static const unsigned short euc_to_utf8_FD_x0213[] = { - 0x91E5, 0x91ED, 0x91F1, 0x9207, 0x9210, 0x9238, 0x9239, - 0x923A, 0x923C, 0x9240, 0x9243, 0x924F, 0x9278, 0x9288, 0x92C2, - 0x92CB, 0x92CC, 0x92D3, 0x92E0, 0x92FF, 0x9304, 0x931F, 0x9321, - 0x9325, 0x9348, 0x9349, 0x934A, 0x9364, 0x9365, 0x936A, 0x9370, - 0x939B, 0x93A3, 0x93BA, 0x93C6, 0x93DE, 0x93DF, 0x9404, 0x93FD, - 0x9433, 0x944A, 0x9463, 0x946B, 0x9471, 0x9472, 0x958E, 0x959F, - 0x95A6, 0x95A9, 0x95AC, 0x95B6, 0x95BD, 0x95CB, 0x95D0, 0x95D3, - 0x49B0, 0x95DA, 0x95DE, 0x9658, 0x9684, 0xF9DC, 0x969D, 0x96A4, - 0x96A5, 0x96D2, 0x96DE, 0xFA68, 0x96E9, 0x96EF, 0x9733, 0x973B, - 0x974D, 0x974E, 0x974F, 0x975A, 0x976E, 0x9773, 0x9795, 0x97AE, - 0x97BA, 0x97C1, 0x97C9, 0x97DE, 0x97DB, 0x97F4, 0xFA69, 0x980A, - 0x981E, 0x982B, 0x9830, 0xFA6A, 0x9852, 0x9853, 0x9856, -}; -static const unsigned short euc_to_utf8_FE_x0213[] = { - 0x9857, 0x9859, 0x985A, 0xF9D0, 0x9865, 0x986C, 0x98BA, - 0x98C8, 0x98E7, 0x9958, 0x999E, 0x9A02, 0x9A03, 0x9A24, 0x9A2D, - 0x9A2E, 0x9A38, 0x9A4A, 0x9A4E, 0x9A52, 0x9AB6, 0x9AC1, 0x9AC3, - 0x9ACE, 0x9AD6, 0x9AF9, 0x9B02, 0x9B08, 0x9B20, 0x4C17, 0x9B2D, - 0x9B5E, 0x9B79, 0x9B66, 0x9B72, 0x9B75, 0x9B84, 0x9B8A, 0x9B8F, - 0x9B9E, 0x9BA7, 0x9BC1, 0x9BCE, 0x9BE5, 0x9BF8, 0x9BFD, 0x9C00, - 0x9C23, 0x9C41, 0x9C4F, 0x9C50, 0x9C53, 0x9C63, 0x9C65, 0x9C77, - 0x9D1D, 0x9D1E, 0x9D43, 0x9D47, 0x9D52, 0x9D63, 0x9D70, 0x9D7C, - 0x9D8A, 0x9D96, 0x9DC0, 0x9DAC, 0x9DBC, 0x9DD7, 0xD868 /*0xDD90*/, 0x9DE7, - 0x9E07, 0x9E15, 0x9E7C, 0x9E9E, 0x9EA4, 0x9EAC, 0x9EAF, 0x9EB4, - 0x9EB5, 0x9EC3, 0x9ED1, 0x9F10, 0x9F39, 0x9F57, 0x9F90, 0x9F94, - 0x9F97, 0x9FA2, 0x59F8, 0x5C5B, 0x5E77, 0x7626, 0x7E6B, -}; - -static const unsigned short euc_to_utf8_8FA1_x0213[] = { - 0xD840 /*0xDC89*/, 0x4E02, 0x4E0F, 0x4E12, 0x4E29, 0x4E2B, 0x4E2E, - 0x4E40, 0x4E47, 0x4E48, 0xD840 /*0xDCA2*/, 0x4E51, 0x3406, 0xD840 /*0xDCA4*/, 0x4E5A, - 0x4E69, 0x4E9D, 0x342C, 0x342E, 0x4EB9, 0x4EBB, 0xD840 /*0xDDA2*/, 0x4EBC, - 0x4EC3, 0x4EC8, 0x4ED0, 0x4EEB, 0x4EDA, 0x4EF1, 0x4EF5, 0x4F00, - 0x4F16, 0x4F64, 0x4F37, 0x4F3E, 0x4F54, 0x4F58, 0xD840 /*0xDE13*/, 0x4F77, - 0x4F78, 0x4F7A, 0x4F7D, 0x4F82, 0x4F85, 0x4F92, 0x4F9A, 0x4FE6, - 0x4FB2, 0x4FBE, 0x4FC5, 0x4FCB, 0x4FCF, 0x4FD2, 0x346A, 0x4FF2, - 0x5000, 0x5010, 0x5013, 0x501C, 0x501E, 0x5022, 0x3468, 0x5042, - 0x5046, 0x504E, 0x5053, 0x5057, 0x5063, 0x5066, 0x506A, 0x5070, - 0x50A3, 0x5088, 0x5092, 0x5093, 0x5095, 0x5096, 0x509C, 0x50AA, - 0xD840 /*0xDF2B*/, 0x50B1, 0x50BA, 0x50BB, 0x50C4, 0x50C7, 0x50F3, 0xD840 /*0xDF81*/, - 0x50CE, 0xD840 /*0xDF71*/, 0x50D4, 0x50D9, 0x50E1, 0x50E9, 0x3492, -}; -static const unsigned short euc_to_utf8_8FA3_x0213[] = { - 0x5108, 0xD840 /*0xDFF9*/, 0x5117, 0x511B, 0xD841 /*0xDC4A*/, 0x5160, 0xD841 /*0xDD09*/, - 0x5173, 0x5183, 0x518B, 0x34BC, 0x5198, 0x51A3, 0x51AD, 0x34C7, - 0x51BC, 0xD841 /*0xDDD6*/, 0xD841 /*0xDE28*/, 0x51F3, 0x51F4, 0x5202, 0x5212, 0x5216, - 0xD841 /*0xDF4F*/, 0x5255, 0x525C, 0x526C, 0x5277, 0x5284, 0x5282, 0xD842 /*0xDC07*/, - 0x5298, 0xD842 /*0xDC3A*/, 0x52A4, 0x52A6, 0x52AF, 0x52BA, 0x52BB, 0x52CA, - 0x351F, 0x52D1, 0xD842 /*0xDCB9*/, 0x52F7, 0x530A, 0x530B, 0x5324, 0x5335, - 0x533E, 0x5342, 0xD842 /*0xDD7C*/, 0xD842 /*0xDD9D*/, 0x5367, 0x536C, 0x537A, 0x53A4, - 0x53B4, 0xD842 /*0xDED3*/, 0x53B7, 0x53C0, 0xD842 /*0xDF1D*/, 0x355D, 0x355E, 0x53D5, - 0x53DA, 0x3563, 0x53F4, 0x53F5, 0x5455, 0x5424, 0x5428, 0x356E, - 0x5443, 0x5462, 0x5466, 0x546C, 0x548A, 0x548D, 0x5495, 0x54A0, - 0x54A6, 0x54AD, 0x54AE, 0x54B7, 0x54BA, 0x54BF, 0x54C3, 0xD843 /*0xDD45*/, - 0x54EC, 0x54EF, 0x54F1, 0x54F3, 0x5500, 0x5501, 0x5509, -}; -static const unsigned short euc_to_utf8_8FA4_x0213[] = { - 0x553C, 0x5541, 0x35A6, 0x5547, 0x554A, 0x35A8, 0x5560, - 0x5561, 0x5564, 0xD843 /*0xDDE1*/, 0x557D, 0x5582, 0x5588, 0x5591, 0x35C5, - 0x55D2, 0xD843 /*0xDE95*/, 0xD843 /*0xDE6D*/, 0x55BF, 0x55C9, 0x55CC, 0x55D1, 0x55DD, - 0x35DA, 0x55E2, 0xD843 /*0xDE64*/, 0x55E9, 0x5628, 0xD843 /*0xDF5F*/, 0x5607, 0x5610, - 0x5630, 0x5637, 0x35F4, 0x563D, 0x563F, 0x5640, 0x5647, 0x565E, - 0x5660, 0x566D, 0x3605, 0x5688, 0x568C, 0x5695, 0x569A, 0x569D, - 0x56A8, 0x56AD, 0x56B2, 0x56C5, 0x56CD, 0x56DF, 0x56E8, 0x56F6, - 0x56F7, 0xD844 /*0xDE01*/, 0x5715, 0x5723, 0xD844 /*0xDE55*/, 0x5729, 0xD844 /*0xDE7B*/, 0x5745, - 0x5746, 0x574C, 0x574D, 0xD844 /*0xDE74*/, 0x5768, 0x576F, 0x5773, 0x5774, - 0x5775, 0x577B, 0xD844 /*0xDEE4*/, 0xD844 /*0xDED7*/, 0x57AC, 0x579A, 0x579D, 0x579E, - 0x57A8, 0x57D7, 0xD844 /*0xDEFD*/, 0x57CC, 0xD844 /*0xDF36*/, 0xD844 /*0xDF44*/, 0x57DE, 0x57E6, - 0x57F0, 0x364A, 0x57F8, 0x57FB, 0x57FD, 0x5804, 0x581E, -}; -static const unsigned short euc_to_utf8_8FA5_x0213[] = { - 0x5820, 0x5827, 0x5832, 0x5839, 0xD844 /*0xDFC4*/, 0x5849, 0x584C, - 0x5867, 0x588A, 0x588B, 0x588D, 0x588F, 0x5890, 0x5894, 0x589D, - 0x58AA, 0x58B1, 0xD845 /*0xDC6D*/, 0x58C3, 0x58CD, 0x58E2, 0x58F3, 0x58F4, - 0x5905, 0x5906, 0x590B, 0x590D, 0x5914, 0x5924, 0xD845 /*0xDDD7*/, 0x3691, - 0x593D, 0x3699, 0x5946, 0x3696, 0xD85B /*0xDC29*/, 0x595B, 0x595F, 0xD845 /*0xDE47*/, - 0x5975, 0x5976, 0x597C, 0x599F, 0x59AE, 0x59BC, 0x59C8, 0x59CD, - 0x59DE, 0x59E3, 0x59E4, 0x59E7, 0x59EE, 0xD845 /*0xDF06*/, 0xD845 /*0xDF42*/, 0x36CF, - 0x5A0C, 0x5A0D, 0x5A17, 0x5A27, 0x5A2D, 0x5A55, 0x5A65, 0x5A7A, - 0x5A8B, 0x5A9C, 0x5A9F, 0x5AA0, 0x5AA2, 0x5AB1, 0x5AB3, 0x5AB5, - 0x5ABA, 0x5ABF, 0x5ADA, 0x5ADC, 0x5AE0, 0x5AE5, 0x5AF0, 0x5AEE, - 0x5AF5, 0x5B00, 0x5B08, 0x5B17, 0x5B34, 0x5B2D, 0x5B4C, 0x5B52, - 0x5B68, 0x5B6F, 0x5B7C, 0x5B7F, 0x5B81, 0x5B84, 0xD846 /*0xDDC3*/, -}; -static const unsigned short euc_to_utf8_8FA8_x0213[] = { - 0x5B96, 0x5BAC, 0x3761, 0x5BC0, 0x3762, 0x5BCE, 0x5BD6, - 0x376C, 0x376B, 0x5BF1, 0x5BFD, 0x3775, 0x5C03, 0x5C29, 0x5C30, - 0xD847 /*0xDC56*/, 0x5C5F, 0x5C63, 0x5C67, 0x5C68, 0x5C69, 0x5C70, 0xD847 /*0xDD2D*/, - 0xD847 /*0xDD45*/, 0x5C7C, 0xD847 /*0xDD78*/, 0xD847 /*0xDD62*/, 0x5C88, 0x5C8A, 0x37C1, 0xD847 /*0xDDA1*/, - 0xD847 /*0xDD9C*/, 0x5CA0, 0x5CA2, 0x5CA6, 0x5CA7, 0xD847 /*0xDD92*/, 0x5CAD, 0x5CB5, - 0xD847 /*0xDDB7*/, 0x5CC9, 0xD847 /*0xDDE0*/, 0xD847 /*0xDE33*/, 0x5D06, 0x5D10, 0x5D2B, 0x5D1D, - 0x5D20, 0x5D24, 0x5D26, 0x5D31, 0x5D39, 0x5D42, 0x37E8, 0x5D61, - 0x5D6A, 0x37F4, 0x5D70, 0xD847 /*0xDF1E*/, 0x37FD, 0x5D88, 0x3800, 0x5D92, - 0x5D94, 0x5D97, 0x5D99, 0x5DB0, 0x5DB2, 0x5DB4, 0xD847 /*0xDF76*/, 0x5DB9, - 0x5DD1, 0x5DD7, 0x5DD8, 0x5DE0, 0xD847 /*0xDFFA*/, 0x5DE4, 0x5DE9, 0x382F, - 0x5E00, 0x3836, 0x5E12, 0x5E15, 0x3840, 0x5E1F, 0x5E2E, 0x5E3E, - 0x5E49, 0x385C, 0x5E56, 0x3861, 0x5E6B, 0x5E6C, 0x5E6D, -}; -static const unsigned short euc_to_utf8_8FAC_x0213[] = { - 0x5E6E, 0xD848 /*0xDD7B*/, 0x5EA5, 0x5EAA, 0x5EAC, 0x5EB9, 0x5EBF, - 0x5EC6, 0x5ED2, 0x5ED9, 0xD848 /*0xDF1E*/, 0x5EFD, 0x5F08, 0x5F0E, 0x5F1C, - 0xD848 /*0xDFAD*/, 0x5F1E, 0x5F47, 0x5F63, 0x5F72, 0x5F7E, 0x5F8F, 0x5FA2, - 0x5FA4, 0x5FB8, 0x5FC4, 0x38FA, 0x5FC7, 0x5FCB, 0x5FD2, 0x5FD3, - 0x5FD4, 0x5FE2, 0x5FEE, 0x5FEF, 0x5FF3, 0x5FFC, 0x3917, 0x6017, - 0x6022, 0x6024, 0x391A, 0x604C, 0x607F, 0x608A, 0x6095, 0x60A8, - 0xD849 /*0xDEF3*/, 0x60B0, 0x60B1, 0x60BE, 0x60C8, 0x60D9, 0x60DB, 0x60EE, - 0x60F2, 0x60F5, 0x6110, 0x6112, 0x6113, 0x6119, 0x611E, 0x613A, - 0x396F, 0x6141, 0x6146, 0x6160, 0x617C, 0xD84A /*0xDC5B*/, 0x6192, 0x6193, - 0x6197, 0x6198, 0x61A5, 0x61A8, 0x61AD, 0xD84A /*0xDCAB*/, 0x61D5, 0x61DD, - 0x61DF, 0x61F5, 0xD84A /*0xDD8F*/, 0x6215, 0x6223, 0x6229, 0x6246, 0x624C, - 0x6251, 0x6252, 0x6261, 0x6264, 0x627B, 0x626D, 0x6273, -}; -static const unsigned short euc_to_utf8_8FAD_x0213[] = { - 0x6299, 0x62A6, 0x62D5, 0xD84A /*0xDEB8*/, 0x62FD, 0x6303, 0x630D, - 0x6310, 0xD84A /*0xDF4F*/, 0xD84A /*0xDF50*/, 0x6332, 0x6335, 0x633B, 0x633C, 0x6341, - 0x6344, 0x634E, 0xD84A /*0xDF46*/, 0x6359, 0xD84B /*0xDC1D*/, 0xD84A /*0xDFA6*/, 0x636C, 0x6384, - 0x6399, 0xD84B /*0xDC24*/, 0x6394, 0x63BD, 0x63F7, 0x63D4, 0x63D5, 0x63DC, - 0x63E0, 0x63EB, 0x63EC, 0x63F2, 0x6409, 0x641E, 0x6425, 0x6429, - 0x642F, 0x645A, 0x645B, 0x645D, 0x6473, 0x647D, 0x6487, 0x6491, - 0x649D, 0x649F, 0x64CB, 0x64CC, 0x64D5, 0x64D7, 0xD84B /*0xDDE1*/, 0x64E4, - 0x64E5, 0x64FF, 0x6504, 0x3A6E, 0x650F, 0x6514, 0x6516, 0x3A73, - 0x651E, 0x6532, 0x6544, 0x6554, 0x656B, 0x657A, 0x6581, 0x6584, - 0x6585, 0x658A, 0x65B2, 0x65B5, 0x65B8, 0x65BF, 0x65C2, 0x65C9, - 0x65D4, 0x3AD6, 0x65F2, 0x65F9, 0x65FC, 0x6604, 0x6608, 0x6621, - 0x662A, 0x6645, 0x6651, 0x664E, 0x3AEA, 0xD84C /*0xDDC3*/, 0x6657, -}; -static const unsigned short euc_to_utf8_8FAE_x0213[] = { - 0x665B, 0x6663, 0xD84C /*0xDDF5*/, 0xD84C /*0xDDB6*/, 0x666A, 0x666B, 0x666C, - 0x666D, 0x667B, 0x6680, 0x6690, 0x6692, 0x6699, 0x3B0E, 0x66AD, - 0x66B1, 0x66B5, 0x3B1A, 0x66BF, 0x3B1C, 0x66EC, 0x3AD7, 0x6701, - 0x6705, 0x6712, 0xD84C /*0xDF72*/, 0x6719, 0xD84C /*0xDFD3*/, 0xD84C /*0xDFD2*/, 0x674C, 0x674D, - 0x6754, 0x675D, 0xD84C /*0xDFD0*/, 0xD84C /*0xDFE4*/, 0xD84C /*0xDFD5*/, 0x6774, 0x6776, 0xD84C /*0xDFDA*/, - 0x6792, 0xD84C /*0xDFDF*/, 0x8363, 0x6810, 0x67B0, 0x67B2, 0x67C3, 0x67C8, - 0x67D2, 0x67D9, 0x67DB, 0x67F0, 0x67F7, 0xD84D /*0xDC4A*/, 0xD84D /*0xDC51*/, 0xD84D /*0xDC4B*/, - 0x6818, 0x681F, 0x682D, 0xD84D /*0xDC65*/, 0x6833, 0x683B, 0x683E, 0x6844, - 0x6845, 0x6849, 0x684C, 0x6855, 0x6857, 0x3B77, 0x686B, 0x686E, - 0x687A, 0x687C, 0x6882, 0x6890, 0x6896, 0x3B6D, 0x6898, 0x6899, - 0x689A, 0x689C, 0x68AA, 0x68AB, 0x68B4, 0x68BB, 0x68FB, 0xD84D /*0xDCE4*/, - 0xD84D /*0xDD5A*/, 0xFA13, 0x68C3, 0x68C5, 0x68CC, 0x68CF, 0x68D6, -}; -static const unsigned short euc_to_utf8_8FAF_x0213[] = { - 0x68D9, 0x68E4, 0x68E5, 0x68EC, 0x68F7, 0x6903, 0x6907, - 0x3B87, 0x3B88, 0xD84D /*0xDD94*/, 0x693B, 0x3B8D, 0x6946, 0x6969, 0x696C, - 0x6972, 0x697A, 0x697F, 0x6992, 0x3BA4, 0x6996, 0x6998, 0x69A6, - 0x69B0, 0x69B7, 0x69BA, 0x69BC, 0x69C0, 0x69D1, 0x69D6, 0xD84D /*0xDE39*/, - 0xD84D /*0xDE47*/, 0x6A30, 0xD84D /*0xDE38*/, 0xD84D /*0xDE3A*/, 0x69E3, 0x69EE, 0x69EF, 0x69F3, - 0x3BCD, 0x69F4, 0x69FE, 0x6A11, 0x6A1A, 0x6A1D, 0xD84D /*0xDF1C*/, 0x6A32, - 0x6A33, 0x6A34, 0x6A3F, 0x6A46, 0x6A49, 0x6A7A, 0x6A4E, 0x6A52, - 0x6A64, 0xD84D /*0xDF0C*/, 0x6A7E, 0x6A83, 0x6A8B, 0x3BF0, 0x6A91, 0x6A9F, - 0x6AA1, 0xD84D /*0xDF64*/, 0x6AAB, 0x6ABD, 0x6AC6, 0x6AD4, 0x6AD0, 0x6ADC, - 0x6ADD, 0xD84D /*0xDFFF*/, 0xD84D /*0xDFE7*/, 0x6AEC, 0x6AF1, 0x6AF2, 0x6AF3, 0x6AFD, - 0xD84E /*0xDC24*/, 0x6B0B, 0x6B0F, 0x6B10, 0x6B11, 0xD84E /*0xDC3D*/, 0x6B17, 0x3C26, - 0x6B2F, 0x6B4A, 0x6B58, 0x6B6C, 0x6B75, 0x6B7A, 0x6B81, -}; -static const unsigned short euc_to_utf8_8FEE_x0213[] = { - 0x6B9B, 0x6BAE, 0xD84E /*0xDE98*/, 0x6BBD, 0x6BBE, 0x6BC7, 0x6BC8, - 0x6BC9, 0x6BDA, 0x6BE6, 0x6BE7, 0x6BEE, 0x6BF1, 0x6C02, 0x6C0A, - 0x6C0E, 0x6C35, 0x6C36, 0x6C3A, 0xD84F /*0xDC7F*/, 0x6C3F, 0x6C4D, 0x6C5B, - 0x6C6D, 0x6C84, 0x6C89, 0x3CC3, 0x6C94, 0x6C95, 0x6C97, 0x6CAD, - 0x6CC2, 0x6CD0, 0x3CD2, 0x6CD6, 0x6CDA, 0x6CDC, 0x6CE9, 0x6CEC, - 0x6CED, 0xD84F /*0xDD00*/, 0x6D00, 0x6D0A, 0x6D24, 0x6D26, 0x6D27, 0x6C67, - 0x6D2F, 0x6D3C, 0x6D5B, 0x6D5E, 0x6D60, 0x6D70, 0x6D80, 0x6D81, - 0x6D8A, 0x6D8D, 0x6D91, 0x6D98, 0xD84F /*0xDD40*/, 0x6E17, 0xD84F /*0xDDFA*/, 0xD84F /*0xDDF9*/, - 0xD84F /*0xDDD3*/, 0x6DAB, 0x6DAE, 0x6DB4, 0x6DC2, 0x6D34, 0x6DC8, 0x6DCE, - 0x6DCF, 0x6DD0, 0x6DDF, 0x6DE9, 0x6DF6, 0x6E36, 0x6E1E, 0x6E22, - 0x6E27, 0x3D11, 0x6E32, 0x6E3C, 0x6E48, 0x6E49, 0x6E4B, 0x6E4C, - 0x6E4F, 0x6E51, 0x6E53, 0x6E54, 0x6E57, 0x6E63, 0x3D1E, -}; -static const unsigned short euc_to_utf8_8FEF_x0213[] = { - 0x6E93, 0x6EA7, 0x6EB4, 0x6EBF, 0x6EC3, 0x6ECA, 0x6ED9, - 0x6F35, 0x6EEB, 0x6EF9, 0x6EFB, 0x6F0A, 0x6F0C, 0x6F18, 0x6F25, - 0x6F36, 0x6F3C, 0xD84F /*0xDF7E*/, 0x6F52, 0x6F57, 0x6F5A, 0x6F60, 0x6F68, - 0x6F98, 0x6F7D, 0x6F90, 0x6F96, 0x6FBE, 0x6F9F, 0x6FA5, 0x6FAF, - 0x3D64, 0x6FB5, 0x6FC8, 0x6FC9, 0x6FDA, 0x6FDE, 0x6FE9, 0xD850 /*0xDC96*/, - 0x6FFC, 0x7000, 0x7007, 0x700A, 0x7023, 0xD850 /*0xDD03*/, 0x7039, 0x703A, - 0x703C, 0x7043, 0x7047, 0x704B, 0x3D9A, 0x7054, 0x7065, 0x7069, - 0x706C, 0x706E, 0x7076, 0x707E, 0x7081, 0x7086, 0x7095, 0x7097, - 0x70BB, 0xD850 /*0xDDC6*/, 0x709F, 0x70B1, 0xD850 /*0xDDFE*/, 0x70EC, 0x70CA, 0x70D1, - 0x70D3, 0x70DC, 0x7103, 0x7104, 0x7106, 0x7107, 0x7108, 0x710C, - 0x3DC0, 0x712F, 0x7131, 0x7150, 0x714A, 0x7153, 0x715E, 0x3DD4, - 0x7196, 0x7180, 0x719B, 0x71A0, 0x71A2, 0x71AE, 0x71AF, -}; -static const unsigned short euc_to_utf8_8FF0_x0213[] = { - 0x71B3, 0xD850 /*0xDFBC*/, 0x71CB, 0x71D3, 0x71D9, 0x71DC, 0x7207, - 0x3E05, 0xFA49, 0x722B, 0x7234, 0x7238, 0x7239, 0x4E2C, 0x7242, - 0x7253, 0x7257, 0x7263, 0xD851 /*0xDE29*/, 0x726E, 0x726F, 0x7278, 0x727F, - 0x728E, 0xD851 /*0xDEA5*/, 0x72AD, 0x72AE, 0x72B0, 0x72B1, 0x72C1, 0x3E60, - 0x72CC, 0x3E66, 0x3E68, 0x72F3, 0x72FA, 0x7307, 0x7312, 0x7318, - 0x7319, 0x3E83, 0x7339, 0x732C, 0x7331, 0x7333, 0x733D, 0x7352, - 0x3E94, 0x736B, 0x736C, 0xD852 /*0xDC96*/, 0x736E, 0x736F, 0x7371, 0x7377, - 0x7381, 0x7385, 0x738A, 0x7394, 0x7398, 0x739C, 0x739E, 0x73A5, - 0x73A8, 0x73B5, 0x73B7, 0x73B9, 0x73BC, 0x73BF, 0x73C5, 0x73CB, - 0x73E1, 0x73E7, 0x73F9, 0x7413, 0x73FA, 0x7401, 0x7424, 0x7431, - 0x7439, 0x7453, 0x7440, 0x7443, 0x744D, 0x7452, 0x745D, 0x7471, - 0x7481, 0x7485, 0x7488, 0xD852 /*0xDE4D*/, 0x7492, 0x7497, 0x7499, -}; -static const unsigned short euc_to_utf8_8FF1_x0213[] = { - 0x74A0, 0x74A1, 0x74A5, 0x74AA, 0x74AB, 0x74B9, 0x74BB, - 0x74BA, 0x74D6, 0x74D8, 0x74DE, 0x74EF, 0x74EB, 0xD852 /*0xDF56*/, 0x74FA, - 0xD852 /*0xDF6F*/, 0x7520, 0x7524, 0x752A, 0x3F57, 0xD853 /*0xDC16*/, 0x753D, 0x753E, - 0x7540, 0x7548, 0x754E, 0x7550, 0x7552, 0x756C, 0x7572, 0x7571, - 0x757A, 0x757D, 0x757E, 0x7581, 0xD853 /*0xDD14*/, 0x758C, 0x3F75, 0x75A2, - 0x3F77, 0x75B0, 0x75B7, 0x75BF, 0x75C0, 0x75C6, 0x75CF, 0x75D3, - 0x75DD, 0x75DF, 0x75E0, 0x75E7, 0x75EC, 0x75EE, 0x75F1, 0x75F9, - 0x7603, 0x7618, 0x7607, 0x760F, 0x3FAE, 0xD853 /*0xDE0E*/, 0x7613, 0x761B, - 0x761C, 0xD853 /*0xDE37*/, 0x7625, 0x7628, 0x763C, 0x7633, 0xD853 /*0xDE6A*/, 0x3FC9, - 0x7641, 0xD853 /*0xDE8B*/, 0x7649, 0x7655, 0x3FD7, 0x766E, 0x7695, 0x769C, - 0x76A1, 0x76A0, 0x76A7, 0x76A8, 0x76AF, 0xD854 /*0xDC4A*/, 0x76C9, 0xD854 /*0xDC55*/, - 0x76E8, 0x76EC, 0xD854 /*0xDD22*/, 0x7717, 0x771A, 0x772D, 0x7735, -}; -static const unsigned short euc_to_utf8_8FF2_x0213[] = { - 0xD854 /*0xDDA9*/, 0x4039, 0xD854 /*0xDDE5*/, 0xD854 /*0xDDCD*/, 0x7758, 0x7760, 0x776A, - 0xD854 /*0xDE1E*/, 0x7772, 0x777C, 0x777D, 0xD854 /*0xDE4C*/, 0x4058, 0x779A, 0x779F, - 0x77A2, 0x77A4, 0x77A9, 0x77DE, 0x77DF, 0x77E4, 0x77E6, 0x77EA, - 0x77EC, 0x4093, 0x77F0, 0x77F4, 0x77FB, 0xD855 /*0xDC2E*/, 0x7805, 0x7806, - 0x7809, 0x780D, 0x7819, 0x7821, 0x782C, 0x7847, 0x7864, 0x786A, - 0xD855 /*0xDCD9*/, 0x788A, 0x7894, 0x78A4, 0x789D, 0x789E, 0x789F, 0x78BB, - 0x78C8, 0x78CC, 0x78CE, 0x78D5, 0x78E0, 0x78E1, 0x78E6, 0x78F9, - 0x78FA, 0x78FB, 0x78FE, 0xD855 /*0xDDA7*/, 0x7910, 0x791B, 0x7930, 0x7925, - 0x793B, 0x794A, 0x7958, 0x795B, 0x4105, 0x7967, 0x7972, 0x7994, - 0x7995, 0x7996, 0x799B, 0x79A1, 0x79A9, 0x79B4, 0x79BB, 0x79C2, - 0x79C7, 0x79CC, 0x79CD, 0x79D6, 0x4148, 0xD855 /*0xDFA9*/, 0xD855 /*0xDFB4*/, 0x414F, - 0x7A0A, 0x7A11, 0x7A15, 0x7A1B, 0x7A1E, 0x4163, 0x7A2D, -}; -static const unsigned short euc_to_utf8_8FF3_x0213[] = { - 0x7A38, 0x7A47, 0x7A4C, 0x7A56, 0x7A59, 0x7A5C, 0x7A5F, - 0x7A60, 0x7A67, 0x7A6A, 0x7A75, 0x7A78, 0x7A82, 0x7A8A, 0x7A90, - 0x7AA3, 0x7AAC, 0xD856 /*0xDDD4*/, 0x41B4, 0x7AB9, 0x7ABC, 0x7ABE, 0x41BF, - 0x7ACC, 0x7AD1, 0x7AE7, 0x7AE8, 0x7AF4, 0xD856 /*0xDEE4*/, 0xD856 /*0xDEE3*/, 0x7B07, - 0xD856 /*0xDEF1*/, 0x7B3D, 0x7B27, 0x7B2A, 0x7B2E, 0x7B2F, 0x7B31, 0x41E6, - 0x41F3, 0x7B7F, 0x7B41, 0x41EE, 0x7B55, 0x7B79, 0x7B64, 0x7B66, - 0x7B69, 0x7B73, 0xD856 /*0xDFB2*/, 0x4207, 0x7B90, 0x7B91, 0x7B9B, 0x420E, - 0x7BAF, 0x7BB5, 0x7BBC, 0x7BC5, 0x7BCA, 0xD857 /*0xDC4B*/, 0xD857 /*0xDC64*/, 0x7BD4, - 0x7BD6, 0x7BDA, 0x7BEA, 0x7BF0, 0x7C03, 0x7C0B, 0x7C0E, 0x7C0F, - 0x7C26, 0x7C45, 0x7C4A, 0x7C51, 0x7C57, 0x7C5E, 0x7C61, 0x7C69, - 0x7C6E, 0x7C6F, 0x7C70, 0xD857 /*0xDE2E*/, 0xD857 /*0xDE56*/, 0xD857 /*0xDE65*/, 0x7CA6, 0xD857 /*0xDE62*/, - 0x7CB6, 0x7CB7, 0x7CBF, 0xD857 /*0xDED8*/, 0x7CC4, 0xD857 /*0xDEC2*/, 0x7CC8, -}; -static const unsigned short euc_to_utf8_8FF4_x0213[] = { - 0x7CCD, 0xD857 /*0xDEE8*/, 0x7CD7, 0xD857 /*0xDF23*/, 0x7CE6, 0x7CEB, 0xD857 /*0xDF5C*/, - 0x7CF5, 0x7D03, 0x7D09, 0x42C6, 0x7D12, 0x7D1E, 0xD857 /*0xDFE0*/, 0xD857 /*0xDFD4*/, - 0x7D3D, 0x7D3E, 0x7D40, 0x7D47, 0xD858 /*0xDC0C*/, 0xD857 /*0xDFFB*/, 0x42D6, 0x7D59, - 0x7D5A, 0x7D6A, 0x7D70, 0x42DD, 0x7D7F, 0xD858 /*0xDC17*/, 0x7D86, 0x7D88, - 0x7D8C, 0x7D97, 0xD858 /*0xDC60*/, 0x7D9D, 0x7DA7, 0x7DAA, 0x7DB6, 0x7DB7, - 0x7DC0, 0x7DD7, 0x7DD9, 0x7DE6, 0x7DF1, 0x7DF9, 0x4302, 0xD858 /*0xDCED*/, - 0xFA58, 0x7E10, 0x7E17, 0x7E1D, 0x7E20, 0x7E27, 0x7E2C, 0x7E45, - 0x7E73, 0x7E75, 0x7E7E, 0x7E86, 0x7E87, 0x432B, 0x7E91, 0x7E98, - 0x7E9A, 0x4343, 0x7F3C, 0x7F3B, 0x7F3E, 0x7F43, 0x7F44, 0x7F4F, - 0x34C1, 0xD858 /*0xDE70*/, 0x7F52, 0xD858 /*0xDE86*/, 0x7F61, 0x7F63, 0x7F64, 0x7F6D, - 0x7F7D, 0x7F7E, 0xD858 /*0xDF4C*/, 0x7F90, 0x517B, 0xD84F /*0xDD0E*/, 0x7F96, 0x7F9C, - 0x7FAD, 0xD859 /*0xDC02*/, 0x7FC3, 0x7FCF, 0x7FE3, 0x7FE5, 0x7FEF, -}; -static const unsigned short euc_to_utf8_8FF5_x0213[] = { - 0x7FF2, 0x8002, 0x800A, 0x8008, 0x800E, 0x8011, 0x8016, - 0x8024, 0x802C, 0x8030, 0x8043, 0x8066, 0x8071, 0x8075, 0x807B, - 0x8099, 0x809C, 0x80A4, 0x80A7, 0x80B8, 0xD859 /*0xDE7E*/, 0x80C5, 0x80D5, - 0x80D8, 0x80E6, 0xD859 /*0xDEB0*/, 0x810D, 0x80F5, 0x80FB, 0x43EE, 0x8135, - 0x8116, 0x811E, 0x43F0, 0x8124, 0x8127, 0x812C, 0xD859 /*0xDF1D*/, 0x813D, - 0x4408, 0x8169, 0x4417, 0x8181, 0x441C, 0x8184, 0x8185, 0x4422, - 0x8198, 0x81B2, 0x81C1, 0x81C3, 0x81D6, 0x81DB, 0xD85A /*0xDCDD*/, 0x81E4, - 0xD85A /*0xDCEA*/, 0x81EC, 0xD85A /*0xDD51*/, 0x81FD, 0x81FF, 0xD85A /*0xDD6F*/, 0x8204, 0xD85A /*0xDDDD*/, - 0x8219, 0x8221, 0x8222, 0xD85A /*0xDE1E*/, 0x8232, 0x8234, 0x823C, 0x8246, - 0x8249, 0x8245, 0xD85A /*0xDE58*/, 0x824B, 0x4476, 0x824F, 0x447A, 0x8257, - 0xD85A /*0xDE8C*/, 0x825C, 0x8263, 0xD85A /*0xDEB7*/, 0xFA5D, 0xFA5E, 0x8279, 0x4491, - 0x827D, 0x827F, 0x8283, 0x828A, 0x8293, 0x82A7, 0x82A8, -}; -static const unsigned short euc_to_utf8_8FF6_x0213[] = { - 0x82B2, 0x82B4, 0x82BA, 0x82BC, 0x82E2, 0x82E8, 0x82F7, - 0x8307, 0x8308, 0x830C, 0x8354, 0x831B, 0x831D, 0x8330, 0x833C, - 0x8344, 0x8357, 0x44BE, 0x837F, 0x44D4, 0x44B3, 0x838D, 0x8394, - 0x8395, 0x839B, 0x839D, 0x83C9, 0x83D0, 0x83D4, 0x83DD, 0x83E5, - 0x83F9, 0x840F, 0x8411, 0x8415, 0xD85B /*0xDC73*/, 0x8417, 0x8439, 0x844A, - 0x844F, 0x8451, 0x8452, 0x8459, 0x845A, 0x845C, 0xD85B /*0xDCDD*/, 0x8465, - 0x8476, 0x8478, 0x847C, 0x8481, 0x450D, 0x84DC, 0x8497, 0x84A6, - 0x84BE, 0x4508, 0x84CE, 0x84CF, 0x84D3, 0xD85B /*0xDE65*/, 0x84E7, 0x84EA, - 0x84EF, 0x84F0, 0x84F1, 0x84FA, 0x84FD, 0x850C, 0x851B, 0x8524, - 0x8525, 0x852B, 0x8534, 0x854F, 0x856F, 0x4525, 0x4543, 0x853E, - 0x8551, 0x8553, 0x855E, 0x8561, 0x8562, 0xD85B /*0xDF94*/, 0x857B, 0x857D, - 0x857F, 0x8581, 0x8586, 0x8593, 0x859D, 0x859F, 0xD85B /*0xDFF8*/, -}; -static const unsigned short euc_to_utf8_8FF7_x0213[] = { - 0xD85B /*0xDFF6*/, 0xD85B /*0xDFF7*/, 0x85B7, 0x85BC, 0x85C7, 0x85CA, 0x85D8, - 0x85D9, 0x85DF, 0x85E1, 0x85E6, 0x85F6, 0x8600, 0x8611, 0x861E, - 0x8621, 0x8624, 0x8627, 0xD85C /*0xDD0D*/, 0x8639, 0x863C, 0xD85C /*0xDD39*/, 0x8640, - 0xFA20, 0x8653, 0x8656, 0x866F, 0x8677, 0x867A, 0x8687, 0x8689, - 0x868D, 0x8691, 0x869C, 0x869D, 0x86A8, 0xFA21, 0x86B1, 0x86B3, - 0x86C1, 0x86C3, 0x86D1, 0x86D5, 0x86D7, 0x86E3, 0x86E6, 0x45B8, - 0x8705, 0x8707, 0x870E, 0x8710, 0x8713, 0x8719, 0x871F, 0x8721, - 0x8723, 0x8731, 0x873A, 0x873E, 0x8740, 0x8743, 0x8751, 0x8758, - 0x8764, 0x8765, 0x8772, 0x877C, 0xD85C /*0xDFDB*/, 0xD85C /*0xDFDA*/, 0x87A7, 0x8789, - 0x878B, 0x8793, 0x87A0, 0xD85C /*0xDFFE*/, 0x45E5, 0x87BE, 0xD85D /*0xDC10*/, 0x87C1, - 0x87CE, 0x87F5, 0x87DF, 0xD85D /*0xDC49*/, 0x87E3, 0x87E5, 0x87E6, 0x87EA, - 0x87EB, 0x87ED, 0x8801, 0x8803, 0x880B, 0x8813, 0x8828, -}; -static const unsigned short euc_to_utf8_8FF8_x0213[] = { - 0x882E, 0x8832, 0x883C, 0x460F, 0x884A, 0x8858, 0x885F, - 0x8864, 0xD85D /*0xDE15*/, 0xD85D /*0xDE14*/, 0x8869, 0xD85D /*0xDE31*/, 0x886F, 0x88A0, 0x88BC, - 0x88BD, 0x88BE, 0x88C0, 0x88D2, 0xD85D /*0xDE93*/, 0x88D1, 0x88D3, 0x88DB, - 0x88F0, 0x88F1, 0x4641, 0x8901, 0xD85D /*0xDF0E*/, 0x8937, 0xD85D /*0xDF23*/, 0x8942, - 0x8945, 0x8949, 0xD85D /*0xDF52*/, 0x4665, 0x8962, 0x8980, 0x8989, 0x8990, - 0x899F, 0x89B0, 0x89B7, 0x89D6, 0x89D8, 0x89EB, 0x46A1, 0x89F1, - 0x89F3, 0x89FD, 0x89FF, 0x46AF, 0x8A11, 0x8A14, 0xD85E /*0xDD85*/, 0x8A21, - 0x8A35, 0x8A3E, 0x8A45, 0x8A4D, 0x8A58, 0x8AAE, 0x8A90, 0x8AB7, - 0x8ABE, 0x8AD7, 0x8AFC, 0xD85E /*0xDE84*/, 0x8B0A, 0x8B05, 0x8B0D, 0x8B1C, - 0x8B1F, 0x8B2D, 0x8B43, 0x470C, 0x8B51, 0x8B5E, 0x8B76, 0x8B7F, - 0x8B81, 0x8B8B, 0x8B94, 0x8B95, 0x8B9C, 0x8B9E, 0x8C39, 0xD85E /*0xDFB3*/, - 0x8C3D, 0xD85E /*0xDFBE*/, 0xD85E /*0xDFC7*/, 0x8C45, 0x8C47, 0x8C4F, 0x8C54, -}; -static const unsigned short euc_to_utf8_8FF9_x0213[] = { - 0x8C57, 0x8C69, 0x8C6D, 0x8C73, 0xD85F /*0xDCB8*/, 0x8C93, 0x8C92, - 0x8C99, 0x4764, 0x8C9B, 0x8CA4, 0x8CD6, 0x8CD5, 0x8CD9, 0xD85F /*0xDDA0*/, - 0x8CF0, 0x8CF1, 0xD85F /*0xDE10*/, 0x8D09, 0x8D0E, 0x8D6C, 0x8D84, 0x8D95, - 0x8DA6, 0xD85F /*0xDFB7*/, 0x8DC6, 0x8DC8, 0x8DD9, 0x8DEC, 0x8E0C, 0x47FD, - 0x8DFD, 0x8E06, 0xD860 /*0xDC8A*/, 0x8E14, 0x8E16, 0x8E21, 0x8E22, 0x8E27, - 0xD860 /*0xDCBB*/, 0x4816, 0x8E36, 0x8E39, 0x8E4B, 0x8E54, 0x8E62, 0x8E6C, - 0x8E6D, 0x8E6F, 0x8E98, 0x8E9E, 0x8EAE, 0x8EB3, 0x8EB5, 0x8EB6, - 0x8EBB, 0xD860 /*0xDE82*/, 0x8ED1, 0x8ED4, 0x484E, 0x8EF9, 0xD860 /*0xDEF3*/, 0x8F00, - 0x8F08, 0x8F17, 0x8F2B, 0x8F40, 0x8F4A, 0x8F58, 0xD861 /*0xDC0C*/, 0x8FA4, - 0x8FB4, 0xFA66, 0x8FB6, 0xD861 /*0xDC55*/, 0x8FC1, 0x8FC6, 0xFA24, 0x8FCA, - 0x8FCD, 0x8FD3, 0x8FD5, 0x8FE0, 0x8FF1, 0x8FF5, 0x8FFB, 0x9002, - 0x900C, 0x9037, 0xD861 /*0xDD6B*/, 0x9043, 0x9044, 0x905D, 0xD861 /*0xDDC8*/, -}; -static const unsigned short euc_to_utf8_8FFA_x0213[] = { - 0xD861 /*0xDDC9*/, 0x9085, 0x908C, 0x9090, 0x961D, 0x90A1, 0x48B5, - 0x90B0, 0x90B6, 0x90C3, 0x90C8, 0xD861 /*0xDED7*/, 0x90DC, 0x90DF, 0xD861 /*0xDEFA*/, - 0x90F6, 0x90F2, 0x9100, 0x90EB, 0x90FE, 0x90FF, 0x9104, 0x9106, - 0x9118, 0x911C, 0x911E, 0x9137, 0x9139, 0x913A, 0x9146, 0x9147, - 0x9157, 0x9159, 0x9161, 0x9164, 0x9174, 0x9179, 0x9185, 0x918E, - 0x91A8, 0x91AE, 0x91B3, 0x91B6, 0x91C3, 0x91C4, 0x91DA, 0xD862 /*0xDD49*/, - 0xD862 /*0xDD46*/, 0x91EC, 0x91EE, 0x9201, 0x920A, 0x9216, 0x9217, 0xD862 /*0xDD6B*/, - 0x9233, 0x9242, 0x9247, 0x924A, 0x924E, 0x9251, 0x9256, 0x9259, - 0x9260, 0x9261, 0x9265, 0x9267, 0x9268, 0xD862 /*0xDD87*/, 0xD862 /*0xDD88*/, 0x927C, - 0x927D, 0x927F, 0x9289, 0x928D, 0x9297, 0x9299, 0x929F, 0x92A7, - 0x92AB, 0xD862 /*0xDDBA*/, 0xD862 /*0xDDBB*/, 0x92B2, 0x92BF, 0x92C0, 0x92C6, 0x92CE, - 0x92D0, 0x92D7, 0x92D9, 0x92E5, 0x92E7, 0x9311, 0xD862 /*0xDE1E*/, -}; -static const unsigned short euc_to_utf8_8FFB_x0213[] = { - 0xD862 /*0xDE29*/, 0x92F7, 0x92F9, 0x92FB, 0x9302, 0x930D, 0x9315, - 0x931D, 0x931E, 0x9327, 0x9329, 0xD862 /*0xDE71*/, 0xD862 /*0xDE43*/, 0x9347, 0x9351, - 0x9357, 0x935A, 0x936B, 0x9371, 0x9373, 0x93A1, 0xD862 /*0xDE99*/, 0xD862 /*0xDECD*/, - 0x9388, 0x938B, 0x938F, 0x939E, 0x93F5, 0xD862 /*0xDEE4*/, 0xD862 /*0xDEDD*/, 0x93F1, - 0x93C1, 0x93C7, 0x93DC, 0x93E2, 0x93E7, 0x9409, 0x940F, 0x9416, - 0x9417, 0x93FB, 0x9432, 0x9434, 0x943B, 0x9445, 0xD862 /*0xDFC1*/, 0xD862 /*0xDFEF*/, - 0x946D, 0x946F, 0x9578, 0x9579, 0x9586, 0x958C, 0x958D, 0xD863 /*0xDD10*/, - 0x95AB, 0x95B4, 0xD863 /*0xDD71*/, 0x95C8, 0xD863 /*0xDDFB*/, 0xD863 /*0xDE1F*/, 0x962C, 0x9633, - 0x9634, 0xD863 /*0xDE36*/, 0x963C, 0x9641, 0x9661, 0xD863 /*0xDE89*/, 0x9682, 0xD863 /*0xDEEB*/, - 0x969A, 0xD863 /*0xDF32*/, 0x49E7, 0x96A9, 0x96AF, 0x96B3, 0x96BA, 0x96BD, - 0x49FA, 0xD863 /*0xDFF8*/, 0x96D8, 0x96DA, 0x96DD, 0x4A04, 0x9714, 0x9723, - 0x4A29, 0x9736, 0x9741, 0x9747, 0x9755, 0x9757, 0x975B, -}; -static const unsigned short euc_to_utf8_8FFC_x0213[] = { - 0x976A, 0xD864 /*0xDEA0*/, 0xD864 /*0xDEB1*/, 0x9796, 0x979A, 0x979E, 0x97A2, - 0x97B1, 0x97B2, 0x97BE, 0x97CC, 0x97D1, 0x97D4, 0x97D8, 0x97D9, - 0x97E1, 0x97F1, 0x9804, 0x980D, 0x980E, 0x9814, 0x9816, 0x4ABC, - 0xD865 /*0xDC90*/, 0x9823, 0x9832, 0x9833, 0x9825, 0x9847, 0x9866, 0x98AB, - 0x98AD, 0x98B0, 0xD865 /*0xDDCF*/, 0x98B7, 0x98B8, 0x98BB, 0x98BC, 0x98BF, - 0x98C2, 0x98C7, 0x98CB, 0x98E0, 0xD865 /*0xDE7F*/, 0x98E1, 0x98E3, 0x98E5, - 0x98EA, 0x98F0, 0x98F1, 0x98F3, 0x9908, 0x4B3B, 0xD865 /*0xDEF0*/, 0x9916, - 0x9917, 0xD865 /*0xDF19*/, 0x991A, 0x991B, 0x991C, 0xD865 /*0xDF50*/, 0x9931, 0x9932, - 0x9933, 0x993A, 0x993B, 0x993C, 0x9940, 0x9941, 0x9946, 0x994D, - 0x994E, 0x995C, 0x995F, 0x9960, 0x99A3, 0x99A6, 0x99B9, 0x99BD, - 0x99BF, 0x99C3, 0x99C9, 0x99D4, 0x99D9, 0x99DE, 0xD866 /*0xDCC6*/, 0x99F0, - 0x99F9, 0x99FC, 0x9A0A, 0x9A11, 0x9A16, 0x9A1A, 0x9A20, -}; -static const unsigned short euc_to_utf8_8FFD_x0213[] = { - 0x9A31, 0x9A36, 0x9A44, 0x9A4C, 0x9A58, 0x4BC2, 0x9AAF, - 0x4BCA, 0x9AB7, 0x4BD2, 0x9AB9, 0xD866 /*0xDE72*/, 0x9AC6, 0x9AD0, 0x9AD2, - 0x9AD5, 0x4BE8, 0x9ADC, 0x9AE0, 0x9AE5, 0x9AE9, 0x9B03, 0x9B0C, - 0x9B10, 0x9B12, 0x9B16, 0x9B1C, 0x9B2B, 0x9B33, 0x9B3D, 0x4C20, - 0x9B4B, 0x9B63, 0x9B65, 0x9B6B, 0x9B6C, 0x9B73, 0x9B76, 0x9B77, - 0x9BA6, 0x9BAC, 0x9BB1, 0xD867 /*0xDDDB*/, 0xD867 /*0xDE3D*/, 0x9BB2, 0x9BB8, 0x9BBE, - 0x9BC7, 0x9BF3, 0x9BD8, 0x9BDD, 0x9BE7, 0x9BEA, 0x9BEB, 0x9BEF, - 0x9BEE, 0xD867 /*0xDE15*/, 0x9BFA, 0xD867 /*0xDE8A*/, 0x9BF7, 0xD867 /*0xDE49*/, 0x9C16, 0x9C18, - 0x9C19, 0x9C1A, 0x9C1D, 0x9C22, 0x9C27, 0x9C29, 0x9C2A, 0xD867 /*0xDEC4*/, - 0x9C31, 0x9C36, 0x9C37, 0x9C45, 0x9C5C, 0xD867 /*0xDEE9*/, 0x9C49, 0x9C4A, - 0xD867 /*0xDEDB*/, 0x9C54, 0x9C58, 0x9C5B, 0x9C5D, 0x9C5F, 0x9C69, 0x9C6A, - 0x9C6B, 0x9C6D, 0x9C6E, 0x9C70, 0x9C72, 0x9C75, 0x9C7A, -}; -static const unsigned short euc_to_utf8_8FFE_x0213[] = { - 0x9CE6, 0x9CF2, 0x9D0B, 0x9D02, 0xD867 /*0xDFCE*/, 0x9D11, 0x9D17, - 0x9D18, 0xD868 /*0xDC2F*/, 0x4CC4, 0xD868 /*0xDC1A*/, 0x9D32, 0x4CD1, 0x9D42, 0x9D4A, - 0x9D5F, 0x9D62, 0xD868 /*0xDCF9*/, 0x9D69, 0x9D6B, 0xD868 /*0xDC82*/, 0x9D73, 0x9D76, - 0x9D77, 0x9D7E, 0x9D84, 0x9D8D, 0x9D99, 0x9DA1, 0x9DBF, 0x9DB5, - 0x9DB9, 0x9DBD, 0x9DC3, 0x9DC7, 0x9DC9, 0x9DD6, 0x9DDA, 0x9DDF, - 0x9DE0, 0x9DE3, 0x9DF4, 0x4D07, 0x9E0A, 0x9E02, 0x9E0D, 0x9E19, - 0x9E1C, 0x9E1D, 0x9E7B, 0xD848 /*0xDE18*/, 0x9E80, 0x9E85, 0x9E9B, 0x9EA8, - 0xD868 /*0xDF8C*/, 0x9EBD, 0xD869 /*0xDC37*/, 0x9EDF, 0x9EE7, 0x9EEE, 0x9EFF, 0x9F02, - 0x4D77, 0x9F03, 0x9F17, 0x9F19, 0x9F2F, 0x9F37, 0x9F3A, 0x9F3D, - 0x9F41, 0x9F45, 0x9F46, 0x9F53, 0x9F55, 0x9F58, 0xD869 /*0xDDF1*/, 0x9F5D, - 0xD869 /*0xDE02*/, 0x9F69, 0xD869 /*0xDE1A*/, 0x9F6D, 0x9F70, 0x9F75, 0xD869 /*0xDEB2*/, 0, - 0, 0, 0, 0, 0, 0, 0, -}; - -#ifdef X0212_ENABLE -static const unsigned short euc_to_utf8_8FA2[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0x02D8, - 0x02C7, 0x00B8, 0x02D9, 0x02DD, 0x00AF, 0x02DB, 0x02DA, 0xFF5E, - 0x0384, 0x0385, 0, 0, 0, 0, 0, 0, - 0, 0, 0x00A1, 0xFFE4, 0x00BF, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0x00BA, 0x00AA, 0x00A9, 0x00AE, 0x2122, - 0x00A4, 0x2116, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short euc_to_utf8_8FA6[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0x0386, 0x0388, 0x0389, 0x038A, 0x03AA, 0, 0x038C, - 0, 0x038E, 0x03AB, 0, 0x038F, 0, 0, 0, - 0, 0x03AC, 0x03AD, 0x03AE, 0x03AF, 0x03CA, 0x0390, 0x03CC, - 0x03C2, 0x03CD, 0x03CB, 0x03B0, 0x03CE, 0, 0, -}; -static const unsigned short euc_to_utf8_8FA7[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0x0402, 0x0403, 0x0404, 0x0405, 0x0406, 0x0407, - 0x0408, 0x0409, 0x040A, 0x040B, 0x040C, 0x040E, 0x040F, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0x0452, 0x0453, 0x0454, 0x0455, 0x0456, 0x0457, - 0x0458, 0x0459, 0x045A, 0x045B, 0x045C, 0x045E, 0x045F, -}; -static const unsigned short euc_to_utf8_8FA9[] = { - 0x00C6, 0x0110, 0, 0x0126, 0, 0x0132, 0, - 0x0141, 0x013F, 0, 0x014A, 0x00D8, 0x0152, 0, 0x0166, - 0x00DE, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0x00E6, 0x0111, 0x00F0, 0x0127, 0x0131, 0x0133, 0x0138, - 0x0142, 0x0140, 0x0149, 0x014B, 0x00F8, 0x0153, 0x00DF, 0x0167, - 0x00FE, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short euc_to_utf8_8FAA[] = { - 0x00C1, 0x00C0, 0x00C4, 0x00C2, 0x0102, 0x01CD, 0x0100, - 0x0104, 0x00C5, 0x00C3, 0x0106, 0x0108, 0x010C, 0x00C7, 0x010A, - 0x010E, 0x00C9, 0x00C8, 0x00CB, 0x00CA, 0x011A, 0x0116, 0x0112, - 0x0118, 0, 0x011C, 0x011E, 0x0122, 0x0120, 0x0124, 0x00CD, - 0x00CC, 0x00CF, 0x00CE, 0x01CF, 0x0130, 0x012A, 0x012E, 0x0128, - 0x0134, 0x0136, 0x0139, 0x013D, 0x013B, 0x0143, 0x0147, 0x0145, - 0x00D1, 0x00D3, 0x00D2, 0x00D6, 0x00D4, 0x01D1, 0x0150, 0x014C, - 0x00D5, 0x0154, 0x0158, 0x0156, 0x015A, 0x015C, 0x0160, 0x015E, - 0x0164, 0x0162, 0x00DA, 0x00D9, 0x00DC, 0x00DB, 0x016C, 0x01D3, - 0x0170, 0x016A, 0x0172, 0x016E, 0x0168, 0x01D7, 0x01DB, 0x01D9, - 0x01D5, 0x0174, 0x00DD, 0x0178, 0x0176, 0x0179, 0x017D, 0x017B, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short euc_to_utf8_8FAB[] = { - 0x00E1, 0x00E0, 0x00E4, 0x00E2, 0x0103, 0x01CE, 0x0101, - 0x0105, 0x00E5, 0x00E3, 0x0107, 0x0109, 0x010D, 0x00E7, 0x010B, - 0x010F, 0x00E9, 0x00E8, 0x00EB, 0x00EA, 0x011B, 0x0117, 0x0113, - 0x0119, 0x01F5, 0x011D, 0x011F, 0, 0x0121, 0x0125, 0x00ED, - 0x00EC, 0x00EF, 0x00EE, 0x01D0, 0, 0x012B, 0x012F, 0x0129, - 0x0135, 0x0137, 0x013A, 0x013E, 0x013C, 0x0144, 0x0148, 0x0146, - 0x00F1, 0x00F3, 0x00F2, 0x00F6, 0x00F4, 0x01D2, 0x0151, 0x014D, - 0x00F5, 0x0155, 0x0159, 0x0157, 0x015B, 0x015D, 0x0161, 0x015F, - 0x0165, 0x0163, 0x00FA, 0x00F9, 0x00FC, 0x00FB, 0x016D, 0x01D4, - 0x0171, 0x016B, 0x0173, 0x016F, 0x0169, 0x01D8, 0x01DC, 0x01DA, - 0x01D6, 0x0175, 0x00FD, 0x00FF, 0x0177, 0x017A, 0x017E, 0x017C, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short euc_to_utf8_8FB0[] = { - 0x4E02, 0x4E04, 0x4E05, 0x4E0C, 0x4E12, 0x4E1F, 0x4E23, - 0x4E24, 0x4E28, 0x4E2B, 0x4E2E, 0x4E2F, 0x4E30, 0x4E35, 0x4E40, - 0x4E41, 0x4E44, 0x4E47, 0x4E51, 0x4E5A, 0x4E5C, 0x4E63, 0x4E68, - 0x4E69, 0x4E74, 0x4E75, 0x4E79, 0x4E7F, 0x4E8D, 0x4E96, 0x4E97, - 0x4E9D, 0x4EAF, 0x4EB9, 0x4EC3, 0x4ED0, 0x4EDA, 0x4EDB, 0x4EE0, - 0x4EE1, 0x4EE2, 0x4EE8, 0x4EEF, 0x4EF1, 0x4EF3, 0x4EF5, 0x4EFD, - 0x4EFE, 0x4EFF, 0x4F00, 0x4F02, 0x4F03, 0x4F08, 0x4F0B, 0x4F0C, - 0x4F12, 0x4F15, 0x4F16, 0x4F17, 0x4F19, 0x4F2E, 0x4F31, 0x4F60, - 0x4F33, 0x4F35, 0x4F37, 0x4F39, 0x4F3B, 0x4F3E, 0x4F40, 0x4F42, - 0x4F48, 0x4F49, 0x4F4B, 0x4F4C, 0x4F52, 0x4F54, 0x4F56, 0x4F58, - 0x4F5F, 0x4F63, 0x4F6A, 0x4F6C, 0x4F6E, 0x4F71, 0x4F77, 0x4F78, - 0x4F79, 0x4F7A, 0x4F7D, 0x4F7E, 0x4F81, 0x4F82, 0x4F84, -}; -static const unsigned short euc_to_utf8_8FB1[] = { - 0x4F85, 0x4F89, 0x4F8A, 0x4F8C, 0x4F8E, 0x4F90, 0x4F92, - 0x4F93, 0x4F94, 0x4F97, 0x4F99, 0x4F9A, 0x4F9E, 0x4F9F, 0x4FB2, - 0x4FB7, 0x4FB9, 0x4FBB, 0x4FBC, 0x4FBD, 0x4FBE, 0x4FC0, 0x4FC1, - 0x4FC5, 0x4FC6, 0x4FC8, 0x4FC9, 0x4FCB, 0x4FCC, 0x4FCD, 0x4FCF, - 0x4FD2, 0x4FDC, 0x4FE0, 0x4FE2, 0x4FF0, 0x4FF2, 0x4FFC, 0x4FFD, - 0x4FFF, 0x5000, 0x5001, 0x5004, 0x5007, 0x500A, 0x500C, 0x500E, - 0x5010, 0x5013, 0x5017, 0x5018, 0x501B, 0x501C, 0x501D, 0x501E, - 0x5022, 0x5027, 0x502E, 0x5030, 0x5032, 0x5033, 0x5035, 0x5040, - 0x5041, 0x5042, 0x5045, 0x5046, 0x504A, 0x504C, 0x504E, 0x5051, - 0x5052, 0x5053, 0x5057, 0x5059, 0x505F, 0x5060, 0x5062, 0x5063, - 0x5066, 0x5067, 0x506A, 0x506D, 0x5070, 0x5071, 0x503B, 0x5081, - 0x5083, 0x5084, 0x5086, 0x508A, 0x508E, 0x508F, 0x5090, -}; -static const unsigned short euc_to_utf8_8FB2[] = { - 0x5092, 0x5093, 0x5094, 0x5096, 0x509B, 0x509C, 0x509E, - 0x509F, 0x50A0, 0x50A1, 0x50A2, 0x50AA, 0x50AF, 0x50B0, 0x50B9, - 0x50BA, 0x50BD, 0x50C0, 0x50C3, 0x50C4, 0x50C7, 0x50CC, 0x50CE, - 0x50D0, 0x50D3, 0x50D4, 0x50D8, 0x50DC, 0x50DD, 0x50DF, 0x50E2, - 0x50E4, 0x50E6, 0x50E8, 0x50E9, 0x50EF, 0x50F1, 0x50F6, 0x50FA, - 0x50FE, 0x5103, 0x5106, 0x5107, 0x5108, 0x510B, 0x510C, 0x510D, - 0x510E, 0x50F2, 0x5110, 0x5117, 0x5119, 0x511B, 0x511C, 0x511D, - 0x511E, 0x5123, 0x5127, 0x5128, 0x512C, 0x512D, 0x512F, 0x5131, - 0x5133, 0x5134, 0x5135, 0x5138, 0x5139, 0x5142, 0x514A, 0x514F, - 0x5153, 0x5155, 0x5157, 0x5158, 0x515F, 0x5164, 0x5166, 0x517E, - 0x5183, 0x5184, 0x518B, 0x518E, 0x5198, 0x519D, 0x51A1, 0x51A3, - 0x51AD, 0x51B8, 0x51BA, 0x51BC, 0x51BE, 0x51BF, 0x51C2, -}; -static const unsigned short euc_to_utf8_8FB3[] = { - 0x51C8, 0x51CF, 0x51D1, 0x51D2, 0x51D3, 0x51D5, 0x51D8, - 0x51DE, 0x51E2, 0x51E5, 0x51EE, 0x51F2, 0x51F3, 0x51F4, 0x51F7, - 0x5201, 0x5202, 0x5205, 0x5212, 0x5213, 0x5215, 0x5216, 0x5218, - 0x5222, 0x5228, 0x5231, 0x5232, 0x5235, 0x523C, 0x5245, 0x5249, - 0x5255, 0x5257, 0x5258, 0x525A, 0x525C, 0x525F, 0x5260, 0x5261, - 0x5266, 0x526E, 0x5277, 0x5278, 0x5279, 0x5280, 0x5282, 0x5285, - 0x528A, 0x528C, 0x5293, 0x5295, 0x5296, 0x5297, 0x5298, 0x529A, - 0x529C, 0x52A4, 0x52A5, 0x52A6, 0x52A7, 0x52AF, 0x52B0, 0x52B6, - 0x52B7, 0x52B8, 0x52BA, 0x52BB, 0x52BD, 0x52C0, 0x52C4, 0x52C6, - 0x52C8, 0x52CC, 0x52CF, 0x52D1, 0x52D4, 0x52D6, 0x52DB, 0x52DC, - 0x52E1, 0x52E5, 0x52E8, 0x52E9, 0x52EA, 0x52EC, 0x52F0, 0x52F1, - 0x52F4, 0x52F6, 0x52F7, 0x5300, 0x5303, 0x530A, 0x530B, -}; -static const unsigned short euc_to_utf8_8FB4[] = { - 0x530C, 0x5311, 0x5313, 0x5318, 0x531B, 0x531C, 0x531E, - 0x531F, 0x5325, 0x5327, 0x5328, 0x5329, 0x532B, 0x532C, 0x532D, - 0x5330, 0x5332, 0x5335, 0x533C, 0x533D, 0x533E, 0x5342, 0x534C, - 0x534B, 0x5359, 0x535B, 0x5361, 0x5363, 0x5365, 0x536C, 0x536D, - 0x5372, 0x5379, 0x537E, 0x5383, 0x5387, 0x5388, 0x538E, 0x5393, - 0x5394, 0x5399, 0x539D, 0x53A1, 0x53A4, 0x53AA, 0x53AB, 0x53AF, - 0x53B2, 0x53B4, 0x53B5, 0x53B7, 0x53B8, 0x53BA, 0x53BD, 0x53C0, - 0x53C5, 0x53CF, 0x53D2, 0x53D3, 0x53D5, 0x53DA, 0x53DD, 0x53DE, - 0x53E0, 0x53E6, 0x53E7, 0x53F5, 0x5402, 0x5413, 0x541A, 0x5421, - 0x5427, 0x5428, 0x542A, 0x542F, 0x5431, 0x5434, 0x5435, 0x5443, - 0x5444, 0x5447, 0x544D, 0x544F, 0x545E, 0x5462, 0x5464, 0x5466, - 0x5467, 0x5469, 0x546B, 0x546D, 0x546E, 0x5474, 0x547F, -}; -static const unsigned short euc_to_utf8_8FB5[] = { - 0x5481, 0x5483, 0x5485, 0x5488, 0x5489, 0x548D, 0x5491, - 0x5495, 0x5496, 0x549C, 0x549F, 0x54A1, 0x54A6, 0x54A7, 0x54A9, - 0x54AA, 0x54AD, 0x54AE, 0x54B1, 0x54B7, 0x54B9, 0x54BA, 0x54BB, - 0x54BF, 0x54C6, 0x54CA, 0x54CD, 0x54CE, 0x54E0, 0x54EA, 0x54EC, - 0x54EF, 0x54F6, 0x54FC, 0x54FE, 0x54FF, 0x5500, 0x5501, 0x5505, - 0x5508, 0x5509, 0x550C, 0x550D, 0x550E, 0x5515, 0x552A, 0x552B, - 0x5532, 0x5535, 0x5536, 0x553B, 0x553C, 0x553D, 0x5541, 0x5547, - 0x5549, 0x554A, 0x554D, 0x5550, 0x5551, 0x5558, 0x555A, 0x555B, - 0x555E, 0x5560, 0x5561, 0x5564, 0x5566, 0x557F, 0x5581, 0x5582, - 0x5586, 0x5588, 0x558E, 0x558F, 0x5591, 0x5592, 0x5593, 0x5594, - 0x5597, 0x55A3, 0x55A4, 0x55AD, 0x55B2, 0x55BF, 0x55C1, 0x55C3, - 0x55C6, 0x55C9, 0x55CB, 0x55CC, 0x55CE, 0x55D1, 0x55D2, -}; -static const unsigned short euc_to_utf8_8FB6[] = { - 0x55D3, 0x55D7, 0x55D8, 0x55DB, 0x55DE, 0x55E2, 0x55E9, - 0x55F6, 0x55FF, 0x5605, 0x5608, 0x560A, 0x560D, 0x560E, 0x560F, - 0x5610, 0x5611, 0x5612, 0x5619, 0x562C, 0x5630, 0x5633, 0x5635, - 0x5637, 0x5639, 0x563B, 0x563C, 0x563D, 0x563F, 0x5640, 0x5641, - 0x5643, 0x5644, 0x5646, 0x5649, 0x564B, 0x564D, 0x564F, 0x5654, - 0x565E, 0x5660, 0x5661, 0x5662, 0x5663, 0x5666, 0x5669, 0x566D, - 0x566F, 0x5671, 0x5672, 0x5675, 0x5684, 0x5685, 0x5688, 0x568B, - 0x568C, 0x5695, 0x5699, 0x569A, 0x569D, 0x569E, 0x569F, 0x56A6, - 0x56A7, 0x56A8, 0x56A9, 0x56AB, 0x56AC, 0x56AD, 0x56B1, 0x56B3, - 0x56B7, 0x56BE, 0x56C5, 0x56C9, 0x56CA, 0x56CB, 0x56CF, 0x56D0, - 0x56CC, 0x56CD, 0x56D9, 0x56DC, 0x56DD, 0x56DF, 0x56E1, 0x56E4, - 0x56E5, 0x56E6, 0x56E7, 0x56E8, 0x56F1, 0x56EB, 0x56ED, -}; -static const unsigned short euc_to_utf8_8FB7[] = { - 0x56F6, 0x56F7, 0x5701, 0x5702, 0x5707, 0x570A, 0x570C, - 0x5711, 0x5715, 0x571A, 0x571B, 0x571D, 0x5720, 0x5722, 0x5723, - 0x5724, 0x5725, 0x5729, 0x572A, 0x572C, 0x572E, 0x572F, 0x5733, - 0x5734, 0x573D, 0x573E, 0x573F, 0x5745, 0x5746, 0x574C, 0x574D, - 0x5752, 0x5762, 0x5765, 0x5767, 0x5768, 0x576B, 0x576D, 0x576E, - 0x576F, 0x5770, 0x5771, 0x5773, 0x5774, 0x5775, 0x5777, 0x5779, - 0x577A, 0x577B, 0x577C, 0x577E, 0x5781, 0x5783, 0x578C, 0x5794, - 0x5797, 0x5799, 0x579A, 0x579C, 0x579D, 0x579E, 0x579F, 0x57A1, - 0x5795, 0x57A7, 0x57A8, 0x57A9, 0x57AC, 0x57B8, 0x57BD, 0x57C7, - 0x57C8, 0x57CC, 0x57CF, 0x57D5, 0x57DD, 0x57DE, 0x57E4, 0x57E6, - 0x57E7, 0x57E9, 0x57ED, 0x57F0, 0x57F5, 0x57F6, 0x57F8, 0x57FD, - 0x57FE, 0x57FF, 0x5803, 0x5804, 0x5808, 0x5809, 0x57E1, -}; -static const unsigned short euc_to_utf8_8FB8[] = { - 0x580C, 0x580D, 0x581B, 0x581E, 0x581F, 0x5820, 0x5826, - 0x5827, 0x582D, 0x5832, 0x5839, 0x583F, 0x5849, 0x584C, 0x584D, - 0x584F, 0x5850, 0x5855, 0x585F, 0x5861, 0x5864, 0x5867, 0x5868, - 0x5878, 0x587C, 0x587F, 0x5880, 0x5881, 0x5887, 0x5888, 0x5889, - 0x588A, 0x588C, 0x588D, 0x588F, 0x5890, 0x5894, 0x5896, 0x589D, - 0x58A0, 0x58A1, 0x58A2, 0x58A6, 0x58A9, 0x58B1, 0x58B2, 0x58C4, - 0x58BC, 0x58C2, 0x58C8, 0x58CD, 0x58CE, 0x58D0, 0x58D2, 0x58D4, - 0x58D6, 0x58DA, 0x58DD, 0x58E1, 0x58E2, 0x58E9, 0x58F3, 0x5905, - 0x5906, 0x590B, 0x590C, 0x5912, 0x5913, 0x5914, 0x8641, 0x591D, - 0x5921, 0x5923, 0x5924, 0x5928, 0x592F, 0x5930, 0x5933, 0x5935, - 0x5936, 0x593F, 0x5943, 0x5946, 0x5952, 0x5953, 0x5959, 0x595B, - 0x595D, 0x595E, 0x595F, 0x5961, 0x5963, 0x596B, 0x596D, -}; -static const unsigned short euc_to_utf8_8FB9[] = { - 0x596F, 0x5972, 0x5975, 0x5976, 0x5979, 0x597B, 0x597C, - 0x598B, 0x598C, 0x598E, 0x5992, 0x5995, 0x5997, 0x599F, 0x59A4, - 0x59A7, 0x59AD, 0x59AE, 0x59AF, 0x59B0, 0x59B3, 0x59B7, 0x59BA, - 0x59BC, 0x59C1, 0x59C3, 0x59C4, 0x59C8, 0x59CA, 0x59CD, 0x59D2, - 0x59DD, 0x59DE, 0x59DF, 0x59E3, 0x59E4, 0x59E7, 0x59EE, 0x59EF, - 0x59F1, 0x59F2, 0x59F4, 0x59F7, 0x5A00, 0x5A04, 0x5A0C, 0x5A0D, - 0x5A0E, 0x5A12, 0x5A13, 0x5A1E, 0x5A23, 0x5A24, 0x5A27, 0x5A28, - 0x5A2A, 0x5A2D, 0x5A30, 0x5A44, 0x5A45, 0x5A47, 0x5A48, 0x5A4C, - 0x5A50, 0x5A55, 0x5A5E, 0x5A63, 0x5A65, 0x5A67, 0x5A6D, 0x5A77, - 0x5A7A, 0x5A7B, 0x5A7E, 0x5A8B, 0x5A90, 0x5A93, 0x5A96, 0x5A99, - 0x5A9C, 0x5A9E, 0x5A9F, 0x5AA0, 0x5AA2, 0x5AA7, 0x5AAC, 0x5AB1, - 0x5AB2, 0x5AB3, 0x5AB5, 0x5AB8, 0x5ABA, 0x5ABB, 0x5ABF, -}; -static const unsigned short euc_to_utf8_8FBA[] = { - 0x5AC4, 0x5AC6, 0x5AC8, 0x5ACF, 0x5ADA, 0x5ADC, 0x5AE0, - 0x5AE5, 0x5AEA, 0x5AEE, 0x5AF5, 0x5AF6, 0x5AFD, 0x5B00, 0x5B01, - 0x5B08, 0x5B17, 0x5B34, 0x5B19, 0x5B1B, 0x5B1D, 0x5B21, 0x5B25, - 0x5B2D, 0x5B38, 0x5B41, 0x5B4B, 0x5B4C, 0x5B52, 0x5B56, 0x5B5E, - 0x5B68, 0x5B6E, 0x5B6F, 0x5B7C, 0x5B7D, 0x5B7E, 0x5B7F, 0x5B81, - 0x5B84, 0x5B86, 0x5B8A, 0x5B8E, 0x5B90, 0x5B91, 0x5B93, 0x5B94, - 0x5B96, 0x5BA8, 0x5BA9, 0x5BAC, 0x5BAD, 0x5BAF, 0x5BB1, 0x5BB2, - 0x5BB7, 0x5BBA, 0x5BBC, 0x5BC0, 0x5BC1, 0x5BCD, 0x5BCF, 0x5BD6, - 0x5BD7, 0x5BD8, 0x5BD9, 0x5BDA, 0x5BE0, 0x5BEF, 0x5BF1, 0x5BF4, - 0x5BFD, 0x5C0C, 0x5C17, 0x5C1E, 0x5C1F, 0x5C23, 0x5C26, 0x5C29, - 0x5C2B, 0x5C2C, 0x5C2E, 0x5C30, 0x5C32, 0x5C35, 0x5C36, 0x5C59, - 0x5C5A, 0x5C5C, 0x5C62, 0x5C63, 0x5C67, 0x5C68, 0x5C69, -}; -static const unsigned short euc_to_utf8_8FBB[] = { - 0x5C6D, 0x5C70, 0x5C74, 0x5C75, 0x5C7A, 0x5C7B, 0x5C7C, - 0x5C7D, 0x5C87, 0x5C88, 0x5C8A, 0x5C8F, 0x5C92, 0x5C9D, 0x5C9F, - 0x5CA0, 0x5CA2, 0x5CA3, 0x5CA6, 0x5CAA, 0x5CB2, 0x5CB4, 0x5CB5, - 0x5CBA, 0x5CC9, 0x5CCB, 0x5CD2, 0x5CDD, 0x5CD7, 0x5CEE, 0x5CF1, - 0x5CF2, 0x5CF4, 0x5D01, 0x5D06, 0x5D0D, 0x5D12, 0x5D2B, 0x5D23, - 0x5D24, 0x5D26, 0x5D27, 0x5D31, 0x5D34, 0x5D39, 0x5D3D, 0x5D3F, - 0x5D42, 0x5D43, 0x5D46, 0x5D48, 0x5D55, 0x5D51, 0x5D59, 0x5D4A, - 0x5D5F, 0x5D60, 0x5D61, 0x5D62, 0x5D64, 0x5D6A, 0x5D6D, 0x5D70, - 0x5D79, 0x5D7A, 0x5D7E, 0x5D7F, 0x5D81, 0x5D83, 0x5D88, 0x5D8A, - 0x5D92, 0x5D93, 0x5D94, 0x5D95, 0x5D99, 0x5D9B, 0x5D9F, 0x5DA0, - 0x5DA7, 0x5DAB, 0x5DB0, 0x5DB4, 0x5DB8, 0x5DB9, 0x5DC3, 0x5DC7, - 0x5DCB, 0x5DD0, 0x5DCE, 0x5DD8, 0x5DD9, 0x5DE0, 0x5DE4, -}; -static const unsigned short euc_to_utf8_8FBC[] = { - 0x5DE9, 0x5DF8, 0x5DF9, 0x5E00, 0x5E07, 0x5E0D, 0x5E12, - 0x5E14, 0x5E15, 0x5E18, 0x5E1F, 0x5E20, 0x5E2E, 0x5E28, 0x5E32, - 0x5E35, 0x5E3E, 0x5E4B, 0x5E50, 0x5E49, 0x5E51, 0x5E56, 0x5E58, - 0x5E5B, 0x5E5C, 0x5E5E, 0x5E68, 0x5E6A, 0x5E6B, 0x5E6C, 0x5E6D, - 0x5E6E, 0x5E70, 0x5E80, 0x5E8B, 0x5E8E, 0x5EA2, 0x5EA4, 0x5EA5, - 0x5EA8, 0x5EAA, 0x5EAC, 0x5EB1, 0x5EB3, 0x5EBD, 0x5EBE, 0x5EBF, - 0x5EC6, 0x5ECC, 0x5ECB, 0x5ECE, 0x5ED1, 0x5ED2, 0x5ED4, 0x5ED5, - 0x5EDC, 0x5EDE, 0x5EE5, 0x5EEB, 0x5F02, 0x5F06, 0x5F07, 0x5F08, - 0x5F0E, 0x5F19, 0x5F1C, 0x5F1D, 0x5F21, 0x5F22, 0x5F23, 0x5F24, - 0x5F28, 0x5F2B, 0x5F2C, 0x5F2E, 0x5F30, 0x5F34, 0x5F36, 0x5F3B, - 0x5F3D, 0x5F3F, 0x5F40, 0x5F44, 0x5F45, 0x5F47, 0x5F4D, 0x5F50, - 0x5F54, 0x5F58, 0x5F5B, 0x5F60, 0x5F63, 0x5F64, 0x5F67, -}; -static const unsigned short euc_to_utf8_8FBD[] = { - 0x5F6F, 0x5F72, 0x5F74, 0x5F75, 0x5F78, 0x5F7A, 0x5F7D, - 0x5F7E, 0x5F89, 0x5F8D, 0x5F8F, 0x5F96, 0x5F9C, 0x5F9D, 0x5FA2, - 0x5FA7, 0x5FAB, 0x5FA4, 0x5FAC, 0x5FAF, 0x5FB0, 0x5FB1, 0x5FB8, - 0x5FC4, 0x5FC7, 0x5FC8, 0x5FC9, 0x5FCB, 0x5FD0, 0x5FD1, 0x5FD2, - 0x5FD3, 0x5FD4, 0x5FDE, 0x5FE1, 0x5FE2, 0x5FE8, 0x5FE9, 0x5FEA, - 0x5FEC, 0x5FED, 0x5FEE, 0x5FEF, 0x5FF2, 0x5FF3, 0x5FF6, 0x5FFA, - 0x5FFC, 0x6007, 0x600A, 0x600D, 0x6013, 0x6014, 0x6017, 0x6018, - 0x601A, 0x601F, 0x6024, 0x602D, 0x6033, 0x6035, 0x6040, 0x6047, - 0x6048, 0x6049, 0x604C, 0x6051, 0x6054, 0x6056, 0x6057, 0x605D, - 0x6061, 0x6067, 0x6071, 0x607E, 0x607F, 0x6082, 0x6086, 0x6088, - 0x608A, 0x608E, 0x6091, 0x6093, 0x6095, 0x6098, 0x609D, 0x609E, - 0x60A2, 0x60A4, 0x60A5, 0x60A8, 0x60B0, 0x60B1, 0x60B7, -}; -static const unsigned short euc_to_utf8_8FBE[] = { - 0x60BB, 0x60BE, 0x60C2, 0x60C4, 0x60C8, 0x60C9, 0x60CA, - 0x60CB, 0x60CE, 0x60CF, 0x60D4, 0x60D5, 0x60D9, 0x60DB, 0x60DD, - 0x60DE, 0x60E2, 0x60E5, 0x60F2, 0x60F5, 0x60F8, 0x60FC, 0x60FD, - 0x6102, 0x6107, 0x610A, 0x610C, 0x6110, 0x6111, 0x6112, 0x6113, - 0x6114, 0x6116, 0x6117, 0x6119, 0x611C, 0x611E, 0x6122, 0x612A, - 0x612B, 0x6130, 0x6131, 0x6135, 0x6136, 0x6137, 0x6139, 0x6141, - 0x6145, 0x6146, 0x6149, 0x615E, 0x6160, 0x616C, 0x6172, 0x6178, - 0x617B, 0x617C, 0x617F, 0x6180, 0x6181, 0x6183, 0x6184, 0x618B, - 0x618D, 0x6192, 0x6193, 0x6197, 0x6198, 0x619C, 0x619D, 0x619F, - 0x61A0, 0x61A5, 0x61A8, 0x61AA, 0x61AD, 0x61B8, 0x61B9, 0x61BC, - 0x61C0, 0x61C1, 0x61C2, 0x61CE, 0x61CF, 0x61D5, 0x61DC, 0x61DD, - 0x61DE, 0x61DF, 0x61E1, 0x61E2, 0x61E7, 0x61E9, 0x61E5, -}; -static const unsigned short euc_to_utf8_8FBF[] = { - 0x61EC, 0x61ED, 0x61EF, 0x6201, 0x6203, 0x6204, 0x6207, - 0x6213, 0x6215, 0x621C, 0x6220, 0x6222, 0x6223, 0x6227, 0x6229, - 0x622B, 0x6239, 0x623D, 0x6242, 0x6243, 0x6244, 0x6246, 0x624C, - 0x6250, 0x6251, 0x6252, 0x6254, 0x6256, 0x625A, 0x625C, 0x6264, - 0x626D, 0x626F, 0x6273, 0x627A, 0x627D, 0x628D, 0x628E, 0x628F, - 0x6290, 0x62A6, 0x62A8, 0x62B3, 0x62B6, 0x62B7, 0x62BA, 0x62BE, - 0x62BF, 0x62C4, 0x62CE, 0x62D5, 0x62D6, 0x62DA, 0x62EA, 0x62F2, - 0x62F4, 0x62FC, 0x62FD, 0x6303, 0x6304, 0x630A, 0x630B, 0x630D, - 0x6310, 0x6313, 0x6316, 0x6318, 0x6329, 0x632A, 0x632D, 0x6335, - 0x6336, 0x6339, 0x633C, 0x6341, 0x6342, 0x6343, 0x6344, 0x6346, - 0x634A, 0x634B, 0x634E, 0x6352, 0x6353, 0x6354, 0x6358, 0x635B, - 0x6365, 0x6366, 0x636C, 0x636D, 0x6371, 0x6374, 0x6375, -}; -static const unsigned short euc_to_utf8_8FC0[] = { - 0x6378, 0x637C, 0x637D, 0x637F, 0x6382, 0x6384, 0x6387, - 0x638A, 0x6390, 0x6394, 0x6395, 0x6399, 0x639A, 0x639E, 0x63A4, - 0x63A6, 0x63AD, 0x63AE, 0x63AF, 0x63BD, 0x63C1, 0x63C5, 0x63C8, - 0x63CE, 0x63D1, 0x63D3, 0x63D4, 0x63D5, 0x63DC, 0x63E0, 0x63E5, - 0x63EA, 0x63EC, 0x63F2, 0x63F3, 0x63F5, 0x63F8, 0x63F9, 0x6409, - 0x640A, 0x6410, 0x6412, 0x6414, 0x6418, 0x641E, 0x6420, 0x6422, - 0x6424, 0x6425, 0x6429, 0x642A, 0x642F, 0x6430, 0x6435, 0x643D, - 0x643F, 0x644B, 0x644F, 0x6451, 0x6452, 0x6453, 0x6454, 0x645A, - 0x645B, 0x645C, 0x645D, 0x645F, 0x6460, 0x6461, 0x6463, 0x646D, - 0x6473, 0x6474, 0x647B, 0x647D, 0x6485, 0x6487, 0x648F, 0x6490, - 0x6491, 0x6498, 0x6499, 0x649B, 0x649D, 0x649F, 0x64A1, 0x64A3, - 0x64A6, 0x64A8, 0x64AC, 0x64B3, 0x64BD, 0x64BE, 0x64BF, -}; -static const unsigned short euc_to_utf8_8FC1[] = { - 0x64C4, 0x64C9, 0x64CA, 0x64CB, 0x64CC, 0x64CE, 0x64D0, - 0x64D1, 0x64D5, 0x64D7, 0x64E4, 0x64E5, 0x64E9, 0x64EA, 0x64ED, - 0x64F0, 0x64F5, 0x64F7, 0x64FB, 0x64FF, 0x6501, 0x6504, 0x6508, - 0x6509, 0x650A, 0x650F, 0x6513, 0x6514, 0x6516, 0x6519, 0x651B, - 0x651E, 0x651F, 0x6522, 0x6526, 0x6529, 0x652E, 0x6531, 0x653A, - 0x653C, 0x653D, 0x6543, 0x6547, 0x6549, 0x6550, 0x6552, 0x6554, - 0x655F, 0x6560, 0x6567, 0x656B, 0x657A, 0x657D, 0x6581, 0x6585, - 0x658A, 0x6592, 0x6595, 0x6598, 0x659D, 0x65A0, 0x65A3, 0x65A6, - 0x65AE, 0x65B2, 0x65B3, 0x65B4, 0x65BF, 0x65C2, 0x65C8, 0x65C9, - 0x65CE, 0x65D0, 0x65D4, 0x65D6, 0x65D8, 0x65DF, 0x65F0, 0x65F2, - 0x65F4, 0x65F5, 0x65F9, 0x65FE, 0x65FF, 0x6600, 0x6604, 0x6608, - 0x6609, 0x660D, 0x6611, 0x6612, 0x6615, 0x6616, 0x661D, -}; -static const unsigned short euc_to_utf8_8FC2[] = { - 0x661E, 0x6621, 0x6622, 0x6623, 0x6624, 0x6626, 0x6629, - 0x662A, 0x662B, 0x662C, 0x662E, 0x6630, 0x6631, 0x6633, 0x6639, - 0x6637, 0x6640, 0x6645, 0x6646, 0x664A, 0x664C, 0x6651, 0x664E, - 0x6657, 0x6658, 0x6659, 0x665B, 0x665C, 0x6660, 0x6661, 0x66FB, - 0x666A, 0x666B, 0x666C, 0x667E, 0x6673, 0x6675, 0x667F, 0x6677, - 0x6678, 0x6679, 0x667B, 0x6680, 0x667C, 0x668B, 0x668C, 0x668D, - 0x6690, 0x6692, 0x6699, 0x669A, 0x669B, 0x669C, 0x669F, 0x66A0, - 0x66A4, 0x66AD, 0x66B1, 0x66B2, 0x66B5, 0x66BB, 0x66BF, 0x66C0, - 0x66C2, 0x66C3, 0x66C8, 0x66CC, 0x66CE, 0x66CF, 0x66D4, 0x66DB, - 0x66DF, 0x66E8, 0x66EB, 0x66EC, 0x66EE, 0x66FA, 0x6705, 0x6707, - 0x670E, 0x6713, 0x6719, 0x671C, 0x6720, 0x6722, 0x6733, 0x673E, - 0x6745, 0x6747, 0x6748, 0x674C, 0x6754, 0x6755, 0x675D, -}; -static const unsigned short euc_to_utf8_8FC3[] = { - 0x6766, 0x676C, 0x676E, 0x6774, 0x6776, 0x677B, 0x6781, - 0x6784, 0x678E, 0x678F, 0x6791, 0x6793, 0x6796, 0x6798, 0x6799, - 0x679B, 0x67B0, 0x67B1, 0x67B2, 0x67B5, 0x67BB, 0x67BC, 0x67BD, - 0x67F9, 0x67C0, 0x67C2, 0x67C3, 0x67C5, 0x67C8, 0x67C9, 0x67D2, - 0x67D7, 0x67D9, 0x67DC, 0x67E1, 0x67E6, 0x67F0, 0x67F2, 0x67F6, - 0x67F7, 0x6852, 0x6814, 0x6819, 0x681D, 0x681F, 0x6828, 0x6827, - 0x682C, 0x682D, 0x682F, 0x6830, 0x6831, 0x6833, 0x683B, 0x683F, - 0x6844, 0x6845, 0x684A, 0x684C, 0x6855, 0x6857, 0x6858, 0x685B, - 0x686B, 0x686E, 0x686F, 0x6870, 0x6871, 0x6872, 0x6875, 0x6879, - 0x687A, 0x687B, 0x687C, 0x6882, 0x6884, 0x6886, 0x6888, 0x6896, - 0x6898, 0x689A, 0x689C, 0x68A1, 0x68A3, 0x68A5, 0x68A9, 0x68AA, - 0x68AE, 0x68B2, 0x68BB, 0x68C5, 0x68C8, 0x68CC, 0x68CF, -}; -static const unsigned short euc_to_utf8_8FC4[] = { - 0x68D0, 0x68D1, 0x68D3, 0x68D6, 0x68D9, 0x68DC, 0x68DD, - 0x68E5, 0x68E8, 0x68EA, 0x68EB, 0x68EC, 0x68ED, 0x68F0, 0x68F1, - 0x68F5, 0x68F6, 0x68FB, 0x68FC, 0x68FD, 0x6906, 0x6909, 0x690A, - 0x6910, 0x6911, 0x6913, 0x6916, 0x6917, 0x6931, 0x6933, 0x6935, - 0x6938, 0x693B, 0x6942, 0x6945, 0x6949, 0x694E, 0x6957, 0x695B, - 0x6963, 0x6964, 0x6965, 0x6966, 0x6968, 0x6969, 0x696C, 0x6970, - 0x6971, 0x6972, 0x697A, 0x697B, 0x697F, 0x6980, 0x698D, 0x6992, - 0x6996, 0x6998, 0x69A1, 0x69A5, 0x69A6, 0x69A8, 0x69AB, 0x69AD, - 0x69AF, 0x69B7, 0x69B8, 0x69BA, 0x69BC, 0x69C5, 0x69C8, 0x69D1, - 0x69D6, 0x69D7, 0x69E2, 0x69E5, 0x69EE, 0x69EF, 0x69F1, 0x69F3, - 0x69F5, 0x69FE, 0x6A00, 0x6A01, 0x6A03, 0x6A0F, 0x6A11, 0x6A15, - 0x6A1A, 0x6A1D, 0x6A20, 0x6A24, 0x6A28, 0x6A30, 0x6A32, -}; -static const unsigned short euc_to_utf8_8FC5[] = { - 0x6A34, 0x6A37, 0x6A3B, 0x6A3E, 0x6A3F, 0x6A45, 0x6A46, - 0x6A49, 0x6A4A, 0x6A4E, 0x6A50, 0x6A51, 0x6A52, 0x6A55, 0x6A56, - 0x6A5B, 0x6A64, 0x6A67, 0x6A6A, 0x6A71, 0x6A73, 0x6A7E, 0x6A81, - 0x6A83, 0x6A86, 0x6A87, 0x6A89, 0x6A8B, 0x6A91, 0x6A9B, 0x6A9D, - 0x6A9E, 0x6A9F, 0x6AA5, 0x6AAB, 0x6AAF, 0x6AB0, 0x6AB1, 0x6AB4, - 0x6ABD, 0x6ABE, 0x6ABF, 0x6AC6, 0x6AC9, 0x6AC8, 0x6ACC, 0x6AD0, - 0x6AD4, 0x6AD5, 0x6AD6, 0x6ADC, 0x6ADD, 0x6AE4, 0x6AE7, 0x6AEC, - 0x6AF0, 0x6AF1, 0x6AF2, 0x6AFC, 0x6AFD, 0x6B02, 0x6B03, 0x6B06, - 0x6B07, 0x6B09, 0x6B0F, 0x6B10, 0x6B11, 0x6B17, 0x6B1B, 0x6B1E, - 0x6B24, 0x6B28, 0x6B2B, 0x6B2C, 0x6B2F, 0x6B35, 0x6B36, 0x6B3B, - 0x6B3F, 0x6B46, 0x6B4A, 0x6B4D, 0x6B52, 0x6B56, 0x6B58, 0x6B5D, - 0x6B60, 0x6B67, 0x6B6B, 0x6B6E, 0x6B70, 0x6B75, 0x6B7D, -}; -static const unsigned short euc_to_utf8_8FC6[] = { - 0x6B7E, 0x6B82, 0x6B85, 0x6B97, 0x6B9B, 0x6B9F, 0x6BA0, - 0x6BA2, 0x6BA3, 0x6BA8, 0x6BA9, 0x6BAC, 0x6BAD, 0x6BAE, 0x6BB0, - 0x6BB8, 0x6BB9, 0x6BBD, 0x6BBE, 0x6BC3, 0x6BC4, 0x6BC9, 0x6BCC, - 0x6BD6, 0x6BDA, 0x6BE1, 0x6BE3, 0x6BE6, 0x6BE7, 0x6BEE, 0x6BF1, - 0x6BF7, 0x6BF9, 0x6BFF, 0x6C02, 0x6C04, 0x6C05, 0x6C09, 0x6C0D, - 0x6C0E, 0x6C10, 0x6C12, 0x6C19, 0x6C1F, 0x6C26, 0x6C27, 0x6C28, - 0x6C2C, 0x6C2E, 0x6C33, 0x6C35, 0x6C36, 0x6C3A, 0x6C3B, 0x6C3F, - 0x6C4A, 0x6C4B, 0x6C4D, 0x6C4F, 0x6C52, 0x6C54, 0x6C59, 0x6C5B, - 0x6C5C, 0x6C6B, 0x6C6D, 0x6C6F, 0x6C74, 0x6C76, 0x6C78, 0x6C79, - 0x6C7B, 0x6C85, 0x6C86, 0x6C87, 0x6C89, 0x6C94, 0x6C95, 0x6C97, - 0x6C98, 0x6C9C, 0x6C9F, 0x6CB0, 0x6CB2, 0x6CB4, 0x6CC2, 0x6CC6, - 0x6CCD, 0x6CCF, 0x6CD0, 0x6CD1, 0x6CD2, 0x6CD4, 0x6CD6, -}; -static const unsigned short euc_to_utf8_8FC7[] = { - 0x6CDA, 0x6CDC, 0x6CE0, 0x6CE7, 0x6CE9, 0x6CEB, 0x6CEC, - 0x6CEE, 0x6CF2, 0x6CF4, 0x6D04, 0x6D07, 0x6D0A, 0x6D0E, 0x6D0F, - 0x6D11, 0x6D13, 0x6D1A, 0x6D26, 0x6D27, 0x6D28, 0x6C67, 0x6D2E, - 0x6D2F, 0x6D31, 0x6D39, 0x6D3C, 0x6D3F, 0x6D57, 0x6D5E, 0x6D5F, - 0x6D61, 0x6D65, 0x6D67, 0x6D6F, 0x6D70, 0x6D7C, 0x6D82, 0x6D87, - 0x6D91, 0x6D92, 0x6D94, 0x6D96, 0x6D97, 0x6D98, 0x6DAA, 0x6DAC, - 0x6DB4, 0x6DB7, 0x6DB9, 0x6DBD, 0x6DBF, 0x6DC4, 0x6DC8, 0x6DCA, - 0x6DCE, 0x6DCF, 0x6DD6, 0x6DDB, 0x6DDD, 0x6DDF, 0x6DE0, 0x6DE2, - 0x6DE5, 0x6DE9, 0x6DEF, 0x6DF0, 0x6DF4, 0x6DF6, 0x6DFC, 0x6E00, - 0x6E04, 0x6E1E, 0x6E22, 0x6E27, 0x6E32, 0x6E36, 0x6E39, 0x6E3B, - 0x6E3C, 0x6E44, 0x6E45, 0x6E48, 0x6E49, 0x6E4B, 0x6E4F, 0x6E51, - 0x6E52, 0x6E53, 0x6E54, 0x6E57, 0x6E5C, 0x6E5D, 0x6E5E, -}; -static const unsigned short euc_to_utf8_8FC8[] = { - 0x6E62, 0x6E63, 0x6E68, 0x6E73, 0x6E7B, 0x6E7D, 0x6E8D, - 0x6E93, 0x6E99, 0x6EA0, 0x6EA7, 0x6EAD, 0x6EAE, 0x6EB1, 0x6EB3, - 0x6EBB, 0x6EBF, 0x6EC0, 0x6EC1, 0x6EC3, 0x6EC7, 0x6EC8, 0x6ECA, - 0x6ECD, 0x6ECE, 0x6ECF, 0x6EEB, 0x6EED, 0x6EEE, 0x6EF9, 0x6EFB, - 0x6EFD, 0x6F04, 0x6F08, 0x6F0A, 0x6F0C, 0x6F0D, 0x6F16, 0x6F18, - 0x6F1A, 0x6F1B, 0x6F26, 0x6F29, 0x6F2A, 0x6F2F, 0x6F30, 0x6F33, - 0x6F36, 0x6F3B, 0x6F3C, 0x6F2D, 0x6F4F, 0x6F51, 0x6F52, 0x6F53, - 0x6F57, 0x6F59, 0x6F5A, 0x6F5D, 0x6F5E, 0x6F61, 0x6F62, 0x6F68, - 0x6F6C, 0x6F7D, 0x6F7E, 0x6F83, 0x6F87, 0x6F88, 0x6F8B, 0x6F8C, - 0x6F8D, 0x6F90, 0x6F92, 0x6F93, 0x6F94, 0x6F96, 0x6F9A, 0x6F9F, - 0x6FA0, 0x6FA5, 0x6FA6, 0x6FA7, 0x6FA8, 0x6FAE, 0x6FAF, 0x6FB0, - 0x6FB5, 0x6FB6, 0x6FBC, 0x6FC5, 0x6FC7, 0x6FC8, 0x6FCA, -}; -static const unsigned short euc_to_utf8_8FC9[] = { - 0x6FDA, 0x6FDE, 0x6FE8, 0x6FE9, 0x6FF0, 0x6FF5, 0x6FF9, - 0x6FFC, 0x6FFD, 0x7000, 0x7005, 0x7006, 0x7007, 0x700D, 0x7017, - 0x7020, 0x7023, 0x702F, 0x7034, 0x7037, 0x7039, 0x703C, 0x7043, - 0x7044, 0x7048, 0x7049, 0x704A, 0x704B, 0x7054, 0x7055, 0x705D, - 0x705E, 0x704E, 0x7064, 0x7065, 0x706C, 0x706E, 0x7075, 0x7076, - 0x707E, 0x7081, 0x7085, 0x7086, 0x7094, 0x7095, 0x7096, 0x7097, - 0x7098, 0x709B, 0x70A4, 0x70AB, 0x70B0, 0x70B1, 0x70B4, 0x70B7, - 0x70CA, 0x70D1, 0x70D3, 0x70D4, 0x70D5, 0x70D6, 0x70D8, 0x70DC, - 0x70E4, 0x70FA, 0x7103, 0x7104, 0x7105, 0x7106, 0x7107, 0x710B, - 0x710C, 0x710F, 0x711E, 0x7120, 0x712B, 0x712D, 0x712F, 0x7130, - 0x7131, 0x7138, 0x7141, 0x7145, 0x7146, 0x7147, 0x714A, 0x714B, - 0x7150, 0x7152, 0x7157, 0x715A, 0x715C, 0x715E, 0x7160, -}; -static const unsigned short euc_to_utf8_8FCA[] = { - 0x7168, 0x7179, 0x7180, 0x7185, 0x7187, 0x718C, 0x7192, - 0x719A, 0x719B, 0x71A0, 0x71A2, 0x71AF, 0x71B0, 0x71B2, 0x71B3, - 0x71BA, 0x71BF, 0x71C0, 0x71C1, 0x71C4, 0x71CB, 0x71CC, 0x71D3, - 0x71D6, 0x71D9, 0x71DA, 0x71DC, 0x71F8, 0x71FE, 0x7200, 0x7207, - 0x7208, 0x7209, 0x7213, 0x7217, 0x721A, 0x721D, 0x721F, 0x7224, - 0x722B, 0x722F, 0x7234, 0x7238, 0x7239, 0x7241, 0x7242, 0x7243, - 0x7245, 0x724E, 0x724F, 0x7250, 0x7253, 0x7255, 0x7256, 0x725A, - 0x725C, 0x725E, 0x7260, 0x7263, 0x7268, 0x726B, 0x726E, 0x726F, - 0x7271, 0x7277, 0x7278, 0x727B, 0x727C, 0x727F, 0x7284, 0x7289, - 0x728D, 0x728E, 0x7293, 0x729B, 0x72A8, 0x72AD, 0x72AE, 0x72B1, - 0x72B4, 0x72BE, 0x72C1, 0x72C7, 0x72C9, 0x72CC, 0x72D5, 0x72D6, - 0x72D8, 0x72DF, 0x72E5, 0x72F3, 0x72F4, 0x72FA, 0x72FB, -}; -static const unsigned short euc_to_utf8_8FCB[] = { - 0x72FE, 0x7302, 0x7304, 0x7305, 0x7307, 0x730B, 0x730D, - 0x7312, 0x7313, 0x7318, 0x7319, 0x731E, 0x7322, 0x7324, 0x7327, - 0x7328, 0x732C, 0x7331, 0x7332, 0x7335, 0x733A, 0x733B, 0x733D, - 0x7343, 0x734D, 0x7350, 0x7352, 0x7356, 0x7358, 0x735D, 0x735E, - 0x735F, 0x7360, 0x7366, 0x7367, 0x7369, 0x736B, 0x736C, 0x736E, - 0x736F, 0x7371, 0x7377, 0x7379, 0x737C, 0x7380, 0x7381, 0x7383, - 0x7385, 0x7386, 0x738E, 0x7390, 0x7393, 0x7395, 0x7397, 0x7398, - 0x739C, 0x739E, 0x739F, 0x73A0, 0x73A2, 0x73A5, 0x73A6, 0x73AA, - 0x73AB, 0x73AD, 0x73B5, 0x73B7, 0x73B9, 0x73BC, 0x73BD, 0x73BF, - 0x73C5, 0x73C6, 0x73C9, 0x73CB, 0x73CC, 0x73CF, 0x73D2, 0x73D3, - 0x73D6, 0x73D9, 0x73DD, 0x73E1, 0x73E3, 0x73E6, 0x73E7, 0x73E9, - 0x73F4, 0x73F5, 0x73F7, 0x73F9, 0x73FA, 0x73FB, 0x73FD, -}; -static const unsigned short euc_to_utf8_8FCC[] = { - 0x73FF, 0x7400, 0x7401, 0x7404, 0x7407, 0x740A, 0x7411, - 0x741A, 0x741B, 0x7424, 0x7426, 0x7428, 0x7429, 0x742A, 0x742B, - 0x742C, 0x742D, 0x742E, 0x742F, 0x7430, 0x7431, 0x7439, 0x7440, - 0x7443, 0x7444, 0x7446, 0x7447, 0x744B, 0x744D, 0x7451, 0x7452, - 0x7457, 0x745D, 0x7462, 0x7466, 0x7467, 0x7468, 0x746B, 0x746D, - 0x746E, 0x7471, 0x7472, 0x7480, 0x7481, 0x7485, 0x7486, 0x7487, - 0x7489, 0x748F, 0x7490, 0x7491, 0x7492, 0x7498, 0x7499, 0x749A, - 0x749C, 0x749F, 0x74A0, 0x74A1, 0x74A3, 0x74A6, 0x74A8, 0x74A9, - 0x74AA, 0x74AB, 0x74AE, 0x74AF, 0x74B1, 0x74B2, 0x74B5, 0x74B9, - 0x74BB, 0x74BF, 0x74C8, 0x74C9, 0x74CC, 0x74D0, 0x74D3, 0x74D8, - 0x74DA, 0x74DB, 0x74DE, 0x74DF, 0x74E4, 0x74E8, 0x74EA, 0x74EB, - 0x74EF, 0x74F4, 0x74FA, 0x74FB, 0x74FC, 0x74FF, 0x7506, -}; -static const unsigned short euc_to_utf8_8FCD[] = { - 0x7512, 0x7516, 0x7517, 0x7520, 0x7521, 0x7524, 0x7527, - 0x7529, 0x752A, 0x752F, 0x7536, 0x7539, 0x753D, 0x753E, 0x753F, - 0x7540, 0x7543, 0x7547, 0x7548, 0x754E, 0x7550, 0x7552, 0x7557, - 0x755E, 0x755F, 0x7561, 0x756F, 0x7571, 0x7579, 0x757A, 0x757B, - 0x757C, 0x757D, 0x757E, 0x7581, 0x7585, 0x7590, 0x7592, 0x7593, - 0x7595, 0x7599, 0x759C, 0x75A2, 0x75A4, 0x75B4, 0x75BA, 0x75BF, - 0x75C0, 0x75C1, 0x75C4, 0x75C6, 0x75CC, 0x75CE, 0x75CF, 0x75D7, - 0x75DC, 0x75DF, 0x75E0, 0x75E1, 0x75E4, 0x75E7, 0x75EC, 0x75EE, - 0x75EF, 0x75F1, 0x75F9, 0x7600, 0x7602, 0x7603, 0x7604, 0x7607, - 0x7608, 0x760A, 0x760C, 0x760F, 0x7612, 0x7613, 0x7615, 0x7616, - 0x7619, 0x761B, 0x761C, 0x761D, 0x761E, 0x7623, 0x7625, 0x7626, - 0x7629, 0x762D, 0x7632, 0x7633, 0x7635, 0x7638, 0x7639, -}; -static const unsigned short euc_to_utf8_8FCE[] = { - 0x763A, 0x763C, 0x764A, 0x7640, 0x7641, 0x7643, 0x7644, - 0x7645, 0x7649, 0x764B, 0x7655, 0x7659, 0x765F, 0x7664, 0x7665, - 0x766D, 0x766E, 0x766F, 0x7671, 0x7674, 0x7681, 0x7685, 0x768C, - 0x768D, 0x7695, 0x769B, 0x769C, 0x769D, 0x769F, 0x76A0, 0x76A2, - 0x76A3, 0x76A4, 0x76A5, 0x76A6, 0x76A7, 0x76A8, 0x76AA, 0x76AD, - 0x76BD, 0x76C1, 0x76C5, 0x76C9, 0x76CB, 0x76CC, 0x76CE, 0x76D4, - 0x76D9, 0x76E0, 0x76E6, 0x76E8, 0x76EC, 0x76F0, 0x76F1, 0x76F6, - 0x76F9, 0x76FC, 0x7700, 0x7706, 0x770A, 0x770E, 0x7712, 0x7714, - 0x7715, 0x7717, 0x7719, 0x771A, 0x771C, 0x7722, 0x7728, 0x772D, - 0x772E, 0x772F, 0x7734, 0x7735, 0x7736, 0x7739, 0x773D, 0x773E, - 0x7742, 0x7745, 0x7746, 0x774A, 0x774D, 0x774E, 0x774F, 0x7752, - 0x7756, 0x7757, 0x775C, 0x775E, 0x775F, 0x7760, 0x7762, -}; -static const unsigned short euc_to_utf8_8FCF[] = { - 0x7764, 0x7767, 0x776A, 0x776C, 0x7770, 0x7772, 0x7773, - 0x7774, 0x777A, 0x777D, 0x7780, 0x7784, 0x778C, 0x778D, 0x7794, - 0x7795, 0x7796, 0x779A, 0x779F, 0x77A2, 0x77A7, 0x77AA, 0x77AE, - 0x77AF, 0x77B1, 0x77B5, 0x77BE, 0x77C3, 0x77C9, 0x77D1, 0x77D2, - 0x77D5, 0x77D9, 0x77DE, 0x77DF, 0x77E0, 0x77E4, 0x77E6, 0x77EA, - 0x77EC, 0x77F0, 0x77F1, 0x77F4, 0x77F8, 0x77FB, 0x7805, 0x7806, - 0x7809, 0x780D, 0x780E, 0x7811, 0x781D, 0x7821, 0x7822, 0x7823, - 0x782D, 0x782E, 0x7830, 0x7835, 0x7837, 0x7843, 0x7844, 0x7847, - 0x7848, 0x784C, 0x784E, 0x7852, 0x785C, 0x785E, 0x7860, 0x7861, - 0x7863, 0x7864, 0x7868, 0x786A, 0x786E, 0x787A, 0x787E, 0x788A, - 0x788F, 0x7894, 0x7898, 0x78A1, 0x789D, 0x789E, 0x789F, 0x78A4, - 0x78A8, 0x78AC, 0x78AD, 0x78B0, 0x78B1, 0x78B2, 0x78B3, -}; -static const unsigned short euc_to_utf8_8FD0[] = { - 0x78BB, 0x78BD, 0x78BF, 0x78C7, 0x78C8, 0x78C9, 0x78CC, - 0x78CE, 0x78D2, 0x78D3, 0x78D5, 0x78D6, 0x78E4, 0x78DB, 0x78DF, - 0x78E0, 0x78E1, 0x78E6, 0x78EA, 0x78F2, 0x78F3, 0x7900, 0x78F6, - 0x78F7, 0x78FA, 0x78FB, 0x78FF, 0x7906, 0x790C, 0x7910, 0x791A, - 0x791C, 0x791E, 0x791F, 0x7920, 0x7925, 0x7927, 0x7929, 0x792D, - 0x7931, 0x7934, 0x7935, 0x793B, 0x793D, 0x793F, 0x7944, 0x7945, - 0x7946, 0x794A, 0x794B, 0x794F, 0x7951, 0x7954, 0x7958, 0x795B, - 0x795C, 0x7967, 0x7969, 0x796B, 0x7972, 0x7979, 0x797B, 0x797C, - 0x797E, 0x798B, 0x798C, 0x7991, 0x7993, 0x7994, 0x7995, 0x7996, - 0x7998, 0x799B, 0x799C, 0x79A1, 0x79A8, 0x79A9, 0x79AB, 0x79AF, - 0x79B1, 0x79B4, 0x79B8, 0x79BB, 0x79C2, 0x79C4, 0x79C7, 0x79C8, - 0x79CA, 0x79CF, 0x79D4, 0x79D6, 0x79DA, 0x79DD, 0x79DE, -}; -static const unsigned short euc_to_utf8_8FD1[] = { - 0x79E0, 0x79E2, 0x79E5, 0x79EA, 0x79EB, 0x79ED, 0x79F1, - 0x79F8, 0x79FC, 0x7A02, 0x7A03, 0x7A07, 0x7A09, 0x7A0A, 0x7A0C, - 0x7A11, 0x7A15, 0x7A1B, 0x7A1E, 0x7A21, 0x7A27, 0x7A2B, 0x7A2D, - 0x7A2F, 0x7A30, 0x7A34, 0x7A35, 0x7A38, 0x7A39, 0x7A3A, 0x7A44, - 0x7A45, 0x7A47, 0x7A48, 0x7A4C, 0x7A55, 0x7A56, 0x7A59, 0x7A5C, - 0x7A5D, 0x7A5F, 0x7A60, 0x7A65, 0x7A67, 0x7A6A, 0x7A6D, 0x7A75, - 0x7A78, 0x7A7E, 0x7A80, 0x7A82, 0x7A85, 0x7A86, 0x7A8A, 0x7A8B, - 0x7A90, 0x7A91, 0x7A94, 0x7A9E, 0x7AA0, 0x7AA3, 0x7AAC, 0x7AB3, - 0x7AB5, 0x7AB9, 0x7ABB, 0x7ABC, 0x7AC6, 0x7AC9, 0x7ACC, 0x7ACE, - 0x7AD1, 0x7ADB, 0x7AE8, 0x7AE9, 0x7AEB, 0x7AEC, 0x7AF1, 0x7AF4, - 0x7AFB, 0x7AFD, 0x7AFE, 0x7B07, 0x7B14, 0x7B1F, 0x7B23, 0x7B27, - 0x7B29, 0x7B2A, 0x7B2B, 0x7B2D, 0x7B2E, 0x7B2F, 0x7B30, -}; -static const unsigned short euc_to_utf8_8FD2[] = { - 0x7B31, 0x7B34, 0x7B3D, 0x7B3F, 0x7B40, 0x7B41, 0x7B47, - 0x7B4E, 0x7B55, 0x7B60, 0x7B64, 0x7B66, 0x7B69, 0x7B6A, 0x7B6D, - 0x7B6F, 0x7B72, 0x7B73, 0x7B77, 0x7B84, 0x7B89, 0x7B8E, 0x7B90, - 0x7B91, 0x7B96, 0x7B9B, 0x7B9E, 0x7BA0, 0x7BA5, 0x7BAC, 0x7BAF, - 0x7BB0, 0x7BB2, 0x7BB5, 0x7BB6, 0x7BBA, 0x7BBB, 0x7BBC, 0x7BBD, - 0x7BC2, 0x7BC5, 0x7BC8, 0x7BCA, 0x7BD4, 0x7BD6, 0x7BD7, 0x7BD9, - 0x7BDA, 0x7BDB, 0x7BE8, 0x7BEA, 0x7BF2, 0x7BF4, 0x7BF5, 0x7BF8, - 0x7BF9, 0x7BFA, 0x7BFC, 0x7BFE, 0x7C01, 0x7C02, 0x7C03, 0x7C04, - 0x7C06, 0x7C09, 0x7C0B, 0x7C0C, 0x7C0E, 0x7C0F, 0x7C19, 0x7C1B, - 0x7C20, 0x7C25, 0x7C26, 0x7C28, 0x7C2C, 0x7C31, 0x7C33, 0x7C34, - 0x7C36, 0x7C39, 0x7C3A, 0x7C46, 0x7C4A, 0x7C55, 0x7C51, 0x7C52, - 0x7C53, 0x7C59, 0x7C5A, 0x7C5B, 0x7C5C, 0x7C5D, 0x7C5E, -}; -static const unsigned short euc_to_utf8_8FD3[] = { - 0x7C61, 0x7C63, 0x7C67, 0x7C69, 0x7C6D, 0x7C6E, 0x7C70, - 0x7C72, 0x7C79, 0x7C7C, 0x7C7D, 0x7C86, 0x7C87, 0x7C8F, 0x7C94, - 0x7C9E, 0x7CA0, 0x7CA6, 0x7CB0, 0x7CB6, 0x7CB7, 0x7CBA, 0x7CBB, - 0x7CBC, 0x7CBF, 0x7CC4, 0x7CC7, 0x7CC8, 0x7CC9, 0x7CCD, 0x7CCF, - 0x7CD3, 0x7CD4, 0x7CD5, 0x7CD7, 0x7CD9, 0x7CDA, 0x7CDD, 0x7CE6, - 0x7CE9, 0x7CEB, 0x7CF5, 0x7D03, 0x7D07, 0x7D08, 0x7D09, 0x7D0F, - 0x7D11, 0x7D12, 0x7D13, 0x7D16, 0x7D1D, 0x7D1E, 0x7D23, 0x7D26, - 0x7D2A, 0x7D2D, 0x7D31, 0x7D3C, 0x7D3D, 0x7D3E, 0x7D40, 0x7D41, - 0x7D47, 0x7D48, 0x7D4D, 0x7D51, 0x7D53, 0x7D57, 0x7D59, 0x7D5A, - 0x7D5C, 0x7D5D, 0x7D65, 0x7D67, 0x7D6A, 0x7D70, 0x7D78, 0x7D7A, - 0x7D7B, 0x7D7F, 0x7D81, 0x7D82, 0x7D83, 0x7D85, 0x7D86, 0x7D88, - 0x7D8B, 0x7D8C, 0x7D8D, 0x7D91, 0x7D96, 0x7D97, 0x7D9D, -}; -static const unsigned short euc_to_utf8_8FD4[] = { - 0x7D9E, 0x7DA6, 0x7DA7, 0x7DAA, 0x7DB3, 0x7DB6, 0x7DB7, - 0x7DB9, 0x7DC2, 0x7DC3, 0x7DC4, 0x7DC5, 0x7DC6, 0x7DCC, 0x7DCD, - 0x7DCE, 0x7DD7, 0x7DD9, 0x7E00, 0x7DE2, 0x7DE5, 0x7DE6, 0x7DEA, - 0x7DEB, 0x7DED, 0x7DF1, 0x7DF5, 0x7DF6, 0x7DF9, 0x7DFA, 0x7E08, - 0x7E10, 0x7E11, 0x7E15, 0x7E17, 0x7E1C, 0x7E1D, 0x7E20, 0x7E27, - 0x7E28, 0x7E2C, 0x7E2D, 0x7E2F, 0x7E33, 0x7E36, 0x7E3F, 0x7E44, - 0x7E45, 0x7E47, 0x7E4E, 0x7E50, 0x7E52, 0x7E58, 0x7E5F, 0x7E61, - 0x7E62, 0x7E65, 0x7E6B, 0x7E6E, 0x7E6F, 0x7E73, 0x7E78, 0x7E7E, - 0x7E81, 0x7E86, 0x7E87, 0x7E8A, 0x7E8D, 0x7E91, 0x7E95, 0x7E98, - 0x7E9A, 0x7E9D, 0x7E9E, 0x7F3C, 0x7F3B, 0x7F3D, 0x7F3E, 0x7F3F, - 0x7F43, 0x7F44, 0x7F47, 0x7F4F, 0x7F52, 0x7F53, 0x7F5B, 0x7F5C, - 0x7F5D, 0x7F61, 0x7F63, 0x7F64, 0x7F65, 0x7F66, 0x7F6D, -}; -static const unsigned short euc_to_utf8_8FD5[] = { - 0x7F71, 0x7F7D, 0x7F7E, 0x7F7F, 0x7F80, 0x7F8B, 0x7F8D, - 0x7F8F, 0x7F90, 0x7F91, 0x7F96, 0x7F97, 0x7F9C, 0x7FA1, 0x7FA2, - 0x7FA6, 0x7FAA, 0x7FAD, 0x7FB4, 0x7FBC, 0x7FBF, 0x7FC0, 0x7FC3, - 0x7FC8, 0x7FCE, 0x7FCF, 0x7FDB, 0x7FDF, 0x7FE3, 0x7FE5, 0x7FE8, - 0x7FEC, 0x7FEE, 0x7FEF, 0x7FF2, 0x7FFA, 0x7FFD, 0x7FFE, 0x7FFF, - 0x8007, 0x8008, 0x800A, 0x800D, 0x800E, 0x800F, 0x8011, 0x8013, - 0x8014, 0x8016, 0x801D, 0x801E, 0x801F, 0x8020, 0x8024, 0x8026, - 0x802C, 0x802E, 0x8030, 0x8034, 0x8035, 0x8037, 0x8039, 0x803A, - 0x803C, 0x803E, 0x8040, 0x8044, 0x8060, 0x8064, 0x8066, 0x806D, - 0x8071, 0x8075, 0x8081, 0x8088, 0x808E, 0x809C, 0x809E, 0x80A6, - 0x80A7, 0x80AB, 0x80B8, 0x80B9, 0x80C8, 0x80CD, 0x80CF, 0x80D2, - 0x80D4, 0x80D5, 0x80D7, 0x80D8, 0x80E0, 0x80ED, 0x80EE, -}; -static const unsigned short euc_to_utf8_8FD6[] = { - 0x80F0, 0x80F2, 0x80F3, 0x80F6, 0x80F9, 0x80FA, 0x80FE, - 0x8103, 0x810B, 0x8116, 0x8117, 0x8118, 0x811C, 0x811E, 0x8120, - 0x8124, 0x8127, 0x812C, 0x8130, 0x8135, 0x813A, 0x813C, 0x8145, - 0x8147, 0x814A, 0x814C, 0x8152, 0x8157, 0x8160, 0x8161, 0x8167, - 0x8168, 0x8169, 0x816D, 0x816F, 0x8177, 0x8181, 0x8190, 0x8184, - 0x8185, 0x8186, 0x818B, 0x818E, 0x8196, 0x8198, 0x819B, 0x819E, - 0x81A2, 0x81AE, 0x81B2, 0x81B4, 0x81BB, 0x81CB, 0x81C3, 0x81C5, - 0x81CA, 0x81CE, 0x81CF, 0x81D5, 0x81D7, 0x81DB, 0x81DD, 0x81DE, - 0x81E1, 0x81E4, 0x81EB, 0x81EC, 0x81F0, 0x81F1, 0x81F2, 0x81F5, - 0x81F6, 0x81F8, 0x81F9, 0x81FD, 0x81FF, 0x8200, 0x8203, 0x820F, - 0x8213, 0x8214, 0x8219, 0x821A, 0x821D, 0x8221, 0x8222, 0x8228, - 0x8232, 0x8234, 0x823A, 0x8243, 0x8244, 0x8245, 0x8246, -}; -static const unsigned short euc_to_utf8_8FD7[] = { - 0x824B, 0x824E, 0x824F, 0x8251, 0x8256, 0x825C, 0x8260, - 0x8263, 0x8267, 0x826D, 0x8274, 0x827B, 0x827D, 0x827F, 0x8280, - 0x8281, 0x8283, 0x8284, 0x8287, 0x8289, 0x828A, 0x828E, 0x8291, - 0x8294, 0x8296, 0x8298, 0x829A, 0x829B, 0x82A0, 0x82A1, 0x82A3, - 0x82A4, 0x82A7, 0x82A8, 0x82A9, 0x82AA, 0x82AE, 0x82B0, 0x82B2, - 0x82B4, 0x82B7, 0x82BA, 0x82BC, 0x82BE, 0x82BF, 0x82C6, 0x82D0, - 0x82D5, 0x82DA, 0x82E0, 0x82E2, 0x82E4, 0x82E8, 0x82EA, 0x82ED, - 0x82EF, 0x82F6, 0x82F7, 0x82FD, 0x82FE, 0x8300, 0x8301, 0x8307, - 0x8308, 0x830A, 0x830B, 0x8354, 0x831B, 0x831D, 0x831E, 0x831F, - 0x8321, 0x8322, 0x832C, 0x832D, 0x832E, 0x8330, 0x8333, 0x8337, - 0x833A, 0x833C, 0x833D, 0x8342, 0x8343, 0x8344, 0x8347, 0x834D, - 0x834E, 0x8351, 0x8355, 0x8356, 0x8357, 0x8370, 0x8378, -}; -static const unsigned short euc_to_utf8_8FD8[] = { - 0x837D, 0x837F, 0x8380, 0x8382, 0x8384, 0x8386, 0x838D, - 0x8392, 0x8394, 0x8395, 0x8398, 0x8399, 0x839B, 0x839C, 0x839D, - 0x83A6, 0x83A7, 0x83A9, 0x83AC, 0x83BE, 0x83BF, 0x83C0, 0x83C7, - 0x83C9, 0x83CF, 0x83D0, 0x83D1, 0x83D4, 0x83DD, 0x8353, 0x83E8, - 0x83EA, 0x83F6, 0x83F8, 0x83F9, 0x83FC, 0x8401, 0x8406, 0x840A, - 0x840F, 0x8411, 0x8415, 0x8419, 0x83AD, 0x842F, 0x8439, 0x8445, - 0x8447, 0x8448, 0x844A, 0x844D, 0x844F, 0x8451, 0x8452, 0x8456, - 0x8458, 0x8459, 0x845A, 0x845C, 0x8460, 0x8464, 0x8465, 0x8467, - 0x846A, 0x8470, 0x8473, 0x8474, 0x8476, 0x8478, 0x847C, 0x847D, - 0x8481, 0x8485, 0x8492, 0x8493, 0x8495, 0x849E, 0x84A6, 0x84A8, - 0x84A9, 0x84AA, 0x84AF, 0x84B1, 0x84B4, 0x84BA, 0x84BD, 0x84BE, - 0x84C0, 0x84C2, 0x84C7, 0x84C8, 0x84CC, 0x84CF, 0x84D3, -}; -static const unsigned short euc_to_utf8_8FD9[] = { - 0x84DC, 0x84E7, 0x84EA, 0x84EF, 0x84F0, 0x84F1, 0x84F2, - 0x84F7, 0x8532, 0x84FA, 0x84FB, 0x84FD, 0x8502, 0x8503, 0x8507, - 0x850C, 0x850E, 0x8510, 0x851C, 0x851E, 0x8522, 0x8523, 0x8524, - 0x8525, 0x8527, 0x852A, 0x852B, 0x852F, 0x8533, 0x8534, 0x8536, - 0x853F, 0x8546, 0x854F, 0x8550, 0x8551, 0x8552, 0x8553, 0x8556, - 0x8559, 0x855C, 0x855D, 0x855E, 0x855F, 0x8560, 0x8561, 0x8562, - 0x8564, 0x856B, 0x856F, 0x8579, 0x857A, 0x857B, 0x857D, 0x857F, - 0x8581, 0x8585, 0x8586, 0x8589, 0x858B, 0x858C, 0x858F, 0x8593, - 0x8598, 0x859D, 0x859F, 0x85A0, 0x85A2, 0x85A5, 0x85A7, 0x85B4, - 0x85B6, 0x85B7, 0x85B8, 0x85BC, 0x85BD, 0x85BE, 0x85BF, 0x85C2, - 0x85C7, 0x85CA, 0x85CB, 0x85CE, 0x85AD, 0x85D8, 0x85DA, 0x85DF, - 0x85E0, 0x85E6, 0x85E8, 0x85ED, 0x85F3, 0x85F6, 0x85FC, -}; -static const unsigned short euc_to_utf8_8FDA[] = { - 0x85FF, 0x8600, 0x8604, 0x8605, 0x860D, 0x860E, 0x8610, - 0x8611, 0x8612, 0x8618, 0x8619, 0x861B, 0x861E, 0x8621, 0x8627, - 0x8629, 0x8636, 0x8638, 0x863A, 0x863C, 0x863D, 0x8640, 0x8642, - 0x8646, 0x8652, 0x8653, 0x8656, 0x8657, 0x8658, 0x8659, 0x865D, - 0x8660, 0x8661, 0x8662, 0x8663, 0x8664, 0x8669, 0x866C, 0x866F, - 0x8675, 0x8676, 0x8677, 0x867A, 0x868D, 0x8691, 0x8696, 0x8698, - 0x869A, 0x869C, 0x86A1, 0x86A6, 0x86A7, 0x86A8, 0x86AD, 0x86B1, - 0x86B3, 0x86B4, 0x86B5, 0x86B7, 0x86B8, 0x86B9, 0x86BF, 0x86C0, - 0x86C1, 0x86C3, 0x86C5, 0x86D1, 0x86D2, 0x86D5, 0x86D7, 0x86DA, - 0x86DC, 0x86E0, 0x86E3, 0x86E5, 0x86E7, 0x8688, 0x86FA, 0x86FC, - 0x86FD, 0x8704, 0x8705, 0x8707, 0x870B, 0x870E, 0x870F, 0x8710, - 0x8713, 0x8714, 0x8719, 0x871E, 0x871F, 0x8721, 0x8723, -}; -static const unsigned short euc_to_utf8_8FDB[] = { - 0x8728, 0x872E, 0x872F, 0x8731, 0x8732, 0x8739, 0x873A, - 0x873C, 0x873D, 0x873E, 0x8740, 0x8743, 0x8745, 0x874D, 0x8758, - 0x875D, 0x8761, 0x8764, 0x8765, 0x876F, 0x8771, 0x8772, 0x877B, - 0x8783, 0x8784, 0x8785, 0x8786, 0x8787, 0x8788, 0x8789, 0x878B, - 0x878C, 0x8790, 0x8793, 0x8795, 0x8797, 0x8798, 0x8799, 0x879E, - 0x87A0, 0x87A3, 0x87A7, 0x87AC, 0x87AD, 0x87AE, 0x87B1, 0x87B5, - 0x87BE, 0x87BF, 0x87C1, 0x87C8, 0x87C9, 0x87CA, 0x87CE, 0x87D5, - 0x87D6, 0x87D9, 0x87DA, 0x87DC, 0x87DF, 0x87E2, 0x87E3, 0x87E4, - 0x87EA, 0x87EB, 0x87ED, 0x87F1, 0x87F3, 0x87F8, 0x87FA, 0x87FF, - 0x8801, 0x8803, 0x8806, 0x8809, 0x880A, 0x880B, 0x8810, 0x8819, - 0x8812, 0x8813, 0x8814, 0x8818, 0x881A, 0x881B, 0x881C, 0x881E, - 0x881F, 0x8828, 0x882D, 0x882E, 0x8830, 0x8832, 0x8835, -}; -static const unsigned short euc_to_utf8_8FDC[] = { - 0x883A, 0x883C, 0x8841, 0x8843, 0x8845, 0x8848, 0x8849, - 0x884A, 0x884B, 0x884E, 0x8851, 0x8855, 0x8856, 0x8858, 0x885A, - 0x885C, 0x885F, 0x8860, 0x8864, 0x8869, 0x8871, 0x8879, 0x887B, - 0x8880, 0x8898, 0x889A, 0x889B, 0x889C, 0x889F, 0x88A0, 0x88A8, - 0x88AA, 0x88BA, 0x88BD, 0x88BE, 0x88C0, 0x88CA, 0x88CB, 0x88CC, - 0x88CD, 0x88CE, 0x88D1, 0x88D2, 0x88D3, 0x88DB, 0x88DE, 0x88E7, - 0x88EF, 0x88F0, 0x88F1, 0x88F5, 0x88F7, 0x8901, 0x8906, 0x890D, - 0x890E, 0x890F, 0x8915, 0x8916, 0x8918, 0x8919, 0x891A, 0x891C, - 0x8920, 0x8926, 0x8927, 0x8928, 0x8930, 0x8931, 0x8932, 0x8935, - 0x8939, 0x893A, 0x893E, 0x8940, 0x8942, 0x8945, 0x8946, 0x8949, - 0x894F, 0x8952, 0x8957, 0x895A, 0x895B, 0x895C, 0x8961, 0x8962, - 0x8963, 0x896B, 0x896E, 0x8970, 0x8973, 0x8975, 0x897A, -}; -static const unsigned short euc_to_utf8_8FDD[] = { - 0x897B, 0x897C, 0x897D, 0x8989, 0x898D, 0x8990, 0x8994, - 0x8995, 0x899B, 0x899C, 0x899F, 0x89A0, 0x89A5, 0x89B0, 0x89B4, - 0x89B5, 0x89B6, 0x89B7, 0x89BC, 0x89D4, 0x89D5, 0x89D6, 0x89D7, - 0x89D8, 0x89E5, 0x89E9, 0x89EB, 0x89ED, 0x89F1, 0x89F3, 0x89F6, - 0x89F9, 0x89FD, 0x89FF, 0x8A04, 0x8A05, 0x8A07, 0x8A0F, 0x8A11, - 0x8A12, 0x8A14, 0x8A15, 0x8A1E, 0x8A20, 0x8A22, 0x8A24, 0x8A26, - 0x8A2B, 0x8A2C, 0x8A2F, 0x8A35, 0x8A37, 0x8A3D, 0x8A3E, 0x8A40, - 0x8A43, 0x8A45, 0x8A47, 0x8A49, 0x8A4D, 0x8A4E, 0x8A53, 0x8A56, - 0x8A57, 0x8A58, 0x8A5C, 0x8A5D, 0x8A61, 0x8A65, 0x8A67, 0x8A75, - 0x8A76, 0x8A77, 0x8A79, 0x8A7A, 0x8A7B, 0x8A7E, 0x8A7F, 0x8A80, - 0x8A83, 0x8A86, 0x8A8B, 0x8A8F, 0x8A90, 0x8A92, 0x8A96, 0x8A97, - 0x8A99, 0x8A9F, 0x8AA7, 0x8AA9, 0x8AAE, 0x8AAF, 0x8AB3, -}; -static const unsigned short euc_to_utf8_8FDE[] = { - 0x8AB6, 0x8AB7, 0x8ABB, 0x8ABE, 0x8AC3, 0x8AC6, 0x8AC8, - 0x8AC9, 0x8ACA, 0x8AD1, 0x8AD3, 0x8AD4, 0x8AD5, 0x8AD7, 0x8ADD, - 0x8ADF, 0x8AEC, 0x8AF0, 0x8AF4, 0x8AF5, 0x8AF6, 0x8AFC, 0x8AFF, - 0x8B05, 0x8B06, 0x8B0B, 0x8B11, 0x8B1C, 0x8B1E, 0x8B1F, 0x8B0A, - 0x8B2D, 0x8B30, 0x8B37, 0x8B3C, 0x8B42, 0x8B43, 0x8B44, 0x8B45, - 0x8B46, 0x8B48, 0x8B52, 0x8B53, 0x8B54, 0x8B59, 0x8B4D, 0x8B5E, - 0x8B63, 0x8B6D, 0x8B76, 0x8B78, 0x8B79, 0x8B7C, 0x8B7E, 0x8B81, - 0x8B84, 0x8B85, 0x8B8B, 0x8B8D, 0x8B8F, 0x8B94, 0x8B95, 0x8B9C, - 0x8B9E, 0x8B9F, 0x8C38, 0x8C39, 0x8C3D, 0x8C3E, 0x8C45, 0x8C47, - 0x8C49, 0x8C4B, 0x8C4F, 0x8C51, 0x8C53, 0x8C54, 0x8C57, 0x8C58, - 0x8C5B, 0x8C5D, 0x8C59, 0x8C63, 0x8C64, 0x8C66, 0x8C68, 0x8C69, - 0x8C6D, 0x8C73, 0x8C75, 0x8C76, 0x8C7B, 0x8C7E, 0x8C86, -}; -static const unsigned short euc_to_utf8_8FDF[] = { - 0x8C87, 0x8C8B, 0x8C90, 0x8C92, 0x8C93, 0x8C99, 0x8C9B, - 0x8C9C, 0x8CA4, 0x8CB9, 0x8CBA, 0x8CC5, 0x8CC6, 0x8CC9, 0x8CCB, - 0x8CCF, 0x8CD6, 0x8CD5, 0x8CD9, 0x8CDD, 0x8CE1, 0x8CE8, 0x8CEC, - 0x8CEF, 0x8CF0, 0x8CF2, 0x8CF5, 0x8CF7, 0x8CF8, 0x8CFE, 0x8CFF, - 0x8D01, 0x8D03, 0x8D09, 0x8D12, 0x8D17, 0x8D1B, 0x8D65, 0x8D69, - 0x8D6C, 0x8D6E, 0x8D7F, 0x8D82, 0x8D84, 0x8D88, 0x8D8D, 0x8D90, - 0x8D91, 0x8D95, 0x8D9E, 0x8D9F, 0x8DA0, 0x8DA6, 0x8DAB, 0x8DAC, - 0x8DAF, 0x8DB2, 0x8DB5, 0x8DB7, 0x8DB9, 0x8DBB, 0x8DC0, 0x8DC5, - 0x8DC6, 0x8DC7, 0x8DC8, 0x8DCA, 0x8DCE, 0x8DD1, 0x8DD4, 0x8DD5, - 0x8DD7, 0x8DD9, 0x8DE4, 0x8DE5, 0x8DE7, 0x8DEC, 0x8DF0, 0x8DBC, - 0x8DF1, 0x8DF2, 0x8DF4, 0x8DFD, 0x8E01, 0x8E04, 0x8E05, 0x8E06, - 0x8E0B, 0x8E11, 0x8E14, 0x8E16, 0x8E20, 0x8E21, 0x8E22, -}; -static const unsigned short euc_to_utf8_8FE0[] = { - 0x8E23, 0x8E26, 0x8E27, 0x8E31, 0x8E33, 0x8E36, 0x8E37, - 0x8E38, 0x8E39, 0x8E3D, 0x8E40, 0x8E41, 0x8E4B, 0x8E4D, 0x8E4E, - 0x8E4F, 0x8E54, 0x8E5B, 0x8E5C, 0x8E5D, 0x8E5E, 0x8E61, 0x8E62, - 0x8E69, 0x8E6C, 0x8E6D, 0x8E6F, 0x8E70, 0x8E71, 0x8E79, 0x8E7A, - 0x8E7B, 0x8E82, 0x8E83, 0x8E89, 0x8E90, 0x8E92, 0x8E95, 0x8E9A, - 0x8E9B, 0x8E9D, 0x8E9E, 0x8EA2, 0x8EA7, 0x8EA9, 0x8EAD, 0x8EAE, - 0x8EB3, 0x8EB5, 0x8EBA, 0x8EBB, 0x8EC0, 0x8EC1, 0x8EC3, 0x8EC4, - 0x8EC7, 0x8ECF, 0x8ED1, 0x8ED4, 0x8EDC, 0x8EE8, 0x8EEE, 0x8EF0, - 0x8EF1, 0x8EF7, 0x8EF9, 0x8EFA, 0x8EED, 0x8F00, 0x8F02, 0x8F07, - 0x8F08, 0x8F0F, 0x8F10, 0x8F16, 0x8F17, 0x8F18, 0x8F1E, 0x8F20, - 0x8F21, 0x8F23, 0x8F25, 0x8F27, 0x8F28, 0x8F2C, 0x8F2D, 0x8F2E, - 0x8F34, 0x8F35, 0x8F36, 0x8F37, 0x8F3A, 0x8F40, 0x8F41, -}; -static const unsigned short euc_to_utf8_8FE1[] = { - 0x8F43, 0x8F47, 0x8F4F, 0x8F51, 0x8F52, 0x8F53, 0x8F54, - 0x8F55, 0x8F58, 0x8F5D, 0x8F5E, 0x8F65, 0x8F9D, 0x8FA0, 0x8FA1, - 0x8FA4, 0x8FA5, 0x8FA6, 0x8FB5, 0x8FB6, 0x8FB8, 0x8FBE, 0x8FC0, - 0x8FC1, 0x8FC6, 0x8FCA, 0x8FCB, 0x8FCD, 0x8FD0, 0x8FD2, 0x8FD3, - 0x8FD5, 0x8FE0, 0x8FE3, 0x8FE4, 0x8FE8, 0x8FEE, 0x8FF1, 0x8FF5, - 0x8FF6, 0x8FFB, 0x8FFE, 0x9002, 0x9004, 0x9008, 0x900C, 0x9018, - 0x901B, 0x9028, 0x9029, 0x902F, 0x902A, 0x902C, 0x902D, 0x9033, - 0x9034, 0x9037, 0x903F, 0x9043, 0x9044, 0x904C, 0x905B, 0x905D, - 0x9062, 0x9066, 0x9067, 0x906C, 0x9070, 0x9074, 0x9079, 0x9085, - 0x9088, 0x908B, 0x908C, 0x908E, 0x9090, 0x9095, 0x9097, 0x9098, - 0x9099, 0x909B, 0x90A0, 0x90A1, 0x90A2, 0x90A5, 0x90B0, 0x90B2, - 0x90B3, 0x90B4, 0x90B6, 0x90BD, 0x90CC, 0x90BE, 0x90C3, -}; -static const unsigned short euc_to_utf8_8FE2[] = { - 0x90C4, 0x90C5, 0x90C7, 0x90C8, 0x90D5, 0x90D7, 0x90D8, - 0x90D9, 0x90DC, 0x90DD, 0x90DF, 0x90E5, 0x90D2, 0x90F6, 0x90EB, - 0x90EF, 0x90F0, 0x90F4, 0x90FE, 0x90FF, 0x9100, 0x9104, 0x9105, - 0x9106, 0x9108, 0x910D, 0x9110, 0x9114, 0x9116, 0x9117, 0x9118, - 0x911A, 0x911C, 0x911E, 0x9120, 0x9125, 0x9122, 0x9123, 0x9127, - 0x9129, 0x912E, 0x912F, 0x9131, 0x9134, 0x9136, 0x9137, 0x9139, - 0x913A, 0x913C, 0x913D, 0x9143, 0x9147, 0x9148, 0x914F, 0x9153, - 0x9157, 0x9159, 0x915A, 0x915B, 0x9161, 0x9164, 0x9167, 0x916D, - 0x9174, 0x9179, 0x917A, 0x917B, 0x9181, 0x9183, 0x9185, 0x9186, - 0x918A, 0x918E, 0x9191, 0x9193, 0x9194, 0x9195, 0x9198, 0x919E, - 0x91A1, 0x91A6, 0x91A8, 0x91AC, 0x91AD, 0x91AE, 0x91B0, 0x91B1, - 0x91B2, 0x91B3, 0x91B6, 0x91BB, 0x91BC, 0x91BD, 0x91BF, -}; -static const unsigned short euc_to_utf8_8FE3[] = { - 0x91C2, 0x91C3, 0x91C5, 0x91D3, 0x91D4, 0x91D7, 0x91D9, - 0x91DA, 0x91DE, 0x91E4, 0x91E5, 0x91E9, 0x91EA, 0x91EC, 0x91ED, - 0x91EE, 0x91EF, 0x91F0, 0x91F1, 0x91F7, 0x91F9, 0x91FB, 0x91FD, - 0x9200, 0x9201, 0x9204, 0x9205, 0x9206, 0x9207, 0x9209, 0x920A, - 0x920C, 0x9210, 0x9212, 0x9213, 0x9216, 0x9218, 0x921C, 0x921D, - 0x9223, 0x9224, 0x9225, 0x9226, 0x9228, 0x922E, 0x922F, 0x9230, - 0x9233, 0x9235, 0x9236, 0x9238, 0x9239, 0x923A, 0x923C, 0x923E, - 0x9240, 0x9242, 0x9243, 0x9246, 0x9247, 0x924A, 0x924D, 0x924E, - 0x924F, 0x9251, 0x9258, 0x9259, 0x925C, 0x925D, 0x9260, 0x9261, - 0x9265, 0x9267, 0x9268, 0x9269, 0x926E, 0x926F, 0x9270, 0x9275, - 0x9276, 0x9277, 0x9278, 0x9279, 0x927B, 0x927C, 0x927D, 0x927F, - 0x9288, 0x9289, 0x928A, 0x928D, 0x928E, 0x9292, 0x9297, -}; -static const unsigned short euc_to_utf8_8FE4[] = { - 0x9299, 0x929F, 0x92A0, 0x92A4, 0x92A5, 0x92A7, 0x92A8, - 0x92AB, 0x92AF, 0x92B2, 0x92B6, 0x92B8, 0x92BA, 0x92BB, 0x92BC, - 0x92BD, 0x92BF, 0x92C0, 0x92C1, 0x92C2, 0x92C3, 0x92C5, 0x92C6, - 0x92C7, 0x92C8, 0x92CB, 0x92CC, 0x92CD, 0x92CE, 0x92D0, 0x92D3, - 0x92D5, 0x92D7, 0x92D8, 0x92D9, 0x92DC, 0x92DD, 0x92DF, 0x92E0, - 0x92E1, 0x92E3, 0x92E5, 0x92E7, 0x92E8, 0x92EC, 0x92EE, 0x92F0, - 0x92F9, 0x92FB, 0x92FF, 0x9300, 0x9302, 0x9308, 0x930D, 0x9311, - 0x9314, 0x9315, 0x931C, 0x931D, 0x931E, 0x931F, 0x9321, 0x9324, - 0x9325, 0x9327, 0x9329, 0x932A, 0x9333, 0x9334, 0x9336, 0x9337, - 0x9347, 0x9348, 0x9349, 0x9350, 0x9351, 0x9352, 0x9355, 0x9357, - 0x9358, 0x935A, 0x935E, 0x9364, 0x9365, 0x9367, 0x9369, 0x936A, - 0x936D, 0x936F, 0x9370, 0x9371, 0x9373, 0x9374, 0x9376, -}; -static const unsigned short euc_to_utf8_8FE5[] = { - 0x937A, 0x937D, 0x937F, 0x9380, 0x9381, 0x9382, 0x9388, - 0x938A, 0x938B, 0x938D, 0x938F, 0x9392, 0x9395, 0x9398, 0x939B, - 0x939E, 0x93A1, 0x93A3, 0x93A4, 0x93A6, 0x93A8, 0x93AB, 0x93B4, - 0x93B5, 0x93B6, 0x93BA, 0x93A9, 0x93C1, 0x93C4, 0x93C5, 0x93C6, - 0x93C7, 0x93C9, 0x93CA, 0x93CB, 0x93CC, 0x93CD, 0x93D3, 0x93D9, - 0x93DC, 0x93DE, 0x93DF, 0x93E2, 0x93E6, 0x93E7, 0x93F9, 0x93F7, - 0x93F8, 0x93FA, 0x93FB, 0x93FD, 0x9401, 0x9402, 0x9404, 0x9408, - 0x9409, 0x940D, 0x940E, 0x940F, 0x9415, 0x9416, 0x9417, 0x941F, - 0x942E, 0x942F, 0x9431, 0x9432, 0x9433, 0x9434, 0x943B, 0x943F, - 0x943D, 0x9443, 0x9445, 0x9448, 0x944A, 0x944C, 0x9455, 0x9459, - 0x945C, 0x945F, 0x9461, 0x9463, 0x9468, 0x946B, 0x946D, 0x946E, - 0x946F, 0x9471, 0x9472, 0x9484, 0x9483, 0x9578, 0x9579, -}; -static const unsigned short euc_to_utf8_8FE6[] = { - 0x957E, 0x9584, 0x9588, 0x958C, 0x958D, 0x958E, 0x959D, - 0x959E, 0x959F, 0x95A1, 0x95A6, 0x95A9, 0x95AB, 0x95AC, 0x95B4, - 0x95B6, 0x95BA, 0x95BD, 0x95BF, 0x95C6, 0x95C8, 0x95C9, 0x95CB, - 0x95D0, 0x95D1, 0x95D2, 0x95D3, 0x95D9, 0x95DA, 0x95DD, 0x95DE, - 0x95DF, 0x95E0, 0x95E4, 0x95E6, 0x961D, 0x961E, 0x9622, 0x9624, - 0x9625, 0x9626, 0x962C, 0x9631, 0x9633, 0x9637, 0x9638, 0x9639, - 0x963A, 0x963C, 0x963D, 0x9641, 0x9652, 0x9654, 0x9656, 0x9657, - 0x9658, 0x9661, 0x966E, 0x9674, 0x967B, 0x967C, 0x967E, 0x967F, - 0x9681, 0x9682, 0x9683, 0x9684, 0x9689, 0x9691, 0x9696, 0x969A, - 0x969D, 0x969F, 0x96A4, 0x96A5, 0x96A6, 0x96A9, 0x96AE, 0x96AF, - 0x96B3, 0x96BA, 0x96CA, 0x96D2, 0x5DB2, 0x96D8, 0x96DA, 0x96DD, - 0x96DE, 0x96DF, 0x96E9, 0x96EF, 0x96F1, 0x96FA, 0x9702, -}; -static const unsigned short euc_to_utf8_8FE7[] = { - 0x9703, 0x9705, 0x9709, 0x971A, 0x971B, 0x971D, 0x9721, - 0x9722, 0x9723, 0x9728, 0x9731, 0x9733, 0x9741, 0x9743, 0x974A, - 0x974E, 0x974F, 0x9755, 0x9757, 0x9758, 0x975A, 0x975B, 0x9763, - 0x9767, 0x976A, 0x976E, 0x9773, 0x9776, 0x9777, 0x9778, 0x977B, - 0x977D, 0x977F, 0x9780, 0x9789, 0x9795, 0x9796, 0x9797, 0x9799, - 0x979A, 0x979E, 0x979F, 0x97A2, 0x97AC, 0x97AE, 0x97B1, 0x97B2, - 0x97B5, 0x97B6, 0x97B8, 0x97B9, 0x97BA, 0x97BC, 0x97BE, 0x97BF, - 0x97C1, 0x97C4, 0x97C5, 0x97C7, 0x97C9, 0x97CA, 0x97CC, 0x97CD, - 0x97CE, 0x97D0, 0x97D1, 0x97D4, 0x97D7, 0x97D8, 0x97D9, 0x97DD, - 0x97DE, 0x97E0, 0x97DB, 0x97E1, 0x97E4, 0x97EF, 0x97F1, 0x97F4, - 0x97F7, 0x97F8, 0x97FA, 0x9807, 0x980A, 0x9819, 0x980D, 0x980E, - 0x9814, 0x9816, 0x981C, 0x981E, 0x9820, 0x9823, 0x9826, -}; -static const unsigned short euc_to_utf8_8FE8[] = { - 0x982B, 0x982E, 0x982F, 0x9830, 0x9832, 0x9833, 0x9835, - 0x9825, 0x983E, 0x9844, 0x9847, 0x984A, 0x9851, 0x9852, 0x9853, - 0x9856, 0x9857, 0x9859, 0x985A, 0x9862, 0x9863, 0x9865, 0x9866, - 0x986A, 0x986C, 0x98AB, 0x98AD, 0x98AE, 0x98B0, 0x98B4, 0x98B7, - 0x98B8, 0x98BA, 0x98BB, 0x98BF, 0x98C2, 0x98C5, 0x98C8, 0x98CC, - 0x98E1, 0x98E3, 0x98E5, 0x98E6, 0x98E7, 0x98EA, 0x98F3, 0x98F6, - 0x9902, 0x9907, 0x9908, 0x9911, 0x9915, 0x9916, 0x9917, 0x991A, - 0x991B, 0x991C, 0x991F, 0x9922, 0x9926, 0x9927, 0x992B, 0x9931, - 0x9932, 0x9933, 0x9934, 0x9935, 0x9939, 0x993A, 0x993B, 0x993C, - 0x9940, 0x9941, 0x9946, 0x9947, 0x9948, 0x994D, 0x994E, 0x9954, - 0x9958, 0x9959, 0x995B, 0x995C, 0x995E, 0x995F, 0x9960, 0x999B, - 0x999D, 0x999F, 0x99A6, 0x99B0, 0x99B1, 0x99B2, 0x99B5, -}; -static const unsigned short euc_to_utf8_8FE9[] = { - 0x99B9, 0x99BA, 0x99BD, 0x99BF, 0x99C3, 0x99C9, 0x99D3, - 0x99D4, 0x99D9, 0x99DA, 0x99DC, 0x99DE, 0x99E7, 0x99EA, 0x99EB, - 0x99EC, 0x99F0, 0x99F4, 0x99F5, 0x99F9, 0x99FD, 0x99FE, 0x9A02, - 0x9A03, 0x9A04, 0x9A0B, 0x9A0C, 0x9A10, 0x9A11, 0x9A16, 0x9A1E, - 0x9A20, 0x9A22, 0x9A23, 0x9A24, 0x9A27, 0x9A2D, 0x9A2E, 0x9A33, - 0x9A35, 0x9A36, 0x9A38, 0x9A47, 0x9A41, 0x9A44, 0x9A4A, 0x9A4B, - 0x9A4C, 0x9A4E, 0x9A51, 0x9A54, 0x9A56, 0x9A5D, 0x9AAA, 0x9AAC, - 0x9AAE, 0x9AAF, 0x9AB2, 0x9AB4, 0x9AB5, 0x9AB6, 0x9AB9, 0x9ABB, - 0x9ABE, 0x9ABF, 0x9AC1, 0x9AC3, 0x9AC6, 0x9AC8, 0x9ACE, 0x9AD0, - 0x9AD2, 0x9AD5, 0x9AD6, 0x9AD7, 0x9ADB, 0x9ADC, 0x9AE0, 0x9AE4, - 0x9AE5, 0x9AE7, 0x9AE9, 0x9AEC, 0x9AF2, 0x9AF3, 0x9AF5, 0x9AF9, - 0x9AFA, 0x9AFD, 0x9AFF, 0x9B00, 0x9B01, 0x9B02, 0x9B03, -}; -static const unsigned short euc_to_utf8_8FEA[] = { - 0x9B04, 0x9B05, 0x9B08, 0x9B09, 0x9B0B, 0x9B0C, 0x9B0D, - 0x9B0E, 0x9B10, 0x9B12, 0x9B16, 0x9B19, 0x9B1B, 0x9B1C, 0x9B20, - 0x9B26, 0x9B2B, 0x9B2D, 0x9B33, 0x9B34, 0x9B35, 0x9B37, 0x9B39, - 0x9B3A, 0x9B3D, 0x9B48, 0x9B4B, 0x9B4C, 0x9B55, 0x9B56, 0x9B57, - 0x9B5B, 0x9B5E, 0x9B61, 0x9B63, 0x9B65, 0x9B66, 0x9B68, 0x9B6A, - 0x9B6B, 0x9B6C, 0x9B6D, 0x9B6E, 0x9B73, 0x9B75, 0x9B77, 0x9B78, - 0x9B79, 0x9B7F, 0x9B80, 0x9B84, 0x9B85, 0x9B86, 0x9B87, 0x9B89, - 0x9B8A, 0x9B8B, 0x9B8D, 0x9B8F, 0x9B90, 0x9B94, 0x9B9A, 0x9B9D, - 0x9B9E, 0x9BA6, 0x9BA7, 0x9BA9, 0x9BAC, 0x9BB0, 0x9BB1, 0x9BB2, - 0x9BB7, 0x9BB8, 0x9BBB, 0x9BBC, 0x9BBE, 0x9BBF, 0x9BC1, 0x9BC7, - 0x9BC8, 0x9BCE, 0x9BD0, 0x9BD7, 0x9BD8, 0x9BDD, 0x9BDF, 0x9BE5, - 0x9BE7, 0x9BEA, 0x9BEB, 0x9BEF, 0x9BF3, 0x9BF7, 0x9BF8, -}; -static const unsigned short euc_to_utf8_8FEB[] = { - 0x9BF9, 0x9BFA, 0x9BFD, 0x9BFF, 0x9C00, 0x9C02, 0x9C0B, - 0x9C0F, 0x9C11, 0x9C16, 0x9C18, 0x9C19, 0x9C1A, 0x9C1C, 0x9C1E, - 0x9C22, 0x9C23, 0x9C26, 0x9C27, 0x9C28, 0x9C29, 0x9C2A, 0x9C31, - 0x9C35, 0x9C36, 0x9C37, 0x9C3D, 0x9C41, 0x9C43, 0x9C44, 0x9C45, - 0x9C49, 0x9C4A, 0x9C4E, 0x9C4F, 0x9C50, 0x9C53, 0x9C54, 0x9C56, - 0x9C58, 0x9C5B, 0x9C5D, 0x9C5E, 0x9C5F, 0x9C63, 0x9C69, 0x9C6A, - 0x9C5C, 0x9C6B, 0x9C68, 0x9C6E, 0x9C70, 0x9C72, 0x9C75, 0x9C77, - 0x9C7B, 0x9CE6, 0x9CF2, 0x9CF7, 0x9CF9, 0x9D0B, 0x9D02, 0x9D11, - 0x9D17, 0x9D18, 0x9D1C, 0x9D1D, 0x9D1E, 0x9D2F, 0x9D30, 0x9D32, - 0x9D33, 0x9D34, 0x9D3A, 0x9D3C, 0x9D45, 0x9D3D, 0x9D42, 0x9D43, - 0x9D47, 0x9D4A, 0x9D53, 0x9D54, 0x9D5F, 0x9D63, 0x9D62, 0x9D65, - 0x9D69, 0x9D6A, 0x9D6B, 0x9D70, 0x9D76, 0x9D77, 0x9D7B, -}; -static const unsigned short euc_to_utf8_8FEC[] = { - 0x9D7C, 0x9D7E, 0x9D83, 0x9D84, 0x9D86, 0x9D8A, 0x9D8D, - 0x9D8E, 0x9D92, 0x9D93, 0x9D95, 0x9D96, 0x9D97, 0x9D98, 0x9DA1, - 0x9DAA, 0x9DAC, 0x9DAE, 0x9DB1, 0x9DB5, 0x9DB9, 0x9DBC, 0x9DBF, - 0x9DC3, 0x9DC7, 0x9DC9, 0x9DCA, 0x9DD4, 0x9DD5, 0x9DD6, 0x9DD7, - 0x9DDA, 0x9DDE, 0x9DDF, 0x9DE0, 0x9DE5, 0x9DE7, 0x9DE9, 0x9DEB, - 0x9DEE, 0x9DF0, 0x9DF3, 0x9DF4, 0x9DFE, 0x9E0A, 0x9E02, 0x9E07, - 0x9E0E, 0x9E10, 0x9E11, 0x9E12, 0x9E15, 0x9E16, 0x9E19, 0x9E1C, - 0x9E1D, 0x9E7A, 0x9E7B, 0x9E7C, 0x9E80, 0x9E82, 0x9E83, 0x9E84, - 0x9E85, 0x9E87, 0x9E8E, 0x9E8F, 0x9E96, 0x9E98, 0x9E9B, 0x9E9E, - 0x9EA4, 0x9EA8, 0x9EAC, 0x9EAE, 0x9EAF, 0x9EB0, 0x9EB3, 0x9EB4, - 0x9EB5, 0x9EC6, 0x9EC8, 0x9ECB, 0x9ED5, 0x9EDF, 0x9EE4, 0x9EE7, - 0x9EEC, 0x9EED, 0x9EEE, 0x9EF0, 0x9EF1, 0x9EF2, 0x9EF5, -}; -static const unsigned short euc_to_utf8_8FED[] = { - 0x9EF8, 0x9EFF, 0x9F02, 0x9F03, 0x9F09, 0x9F0F, 0x9F10, - 0x9F11, 0x9F12, 0x9F14, 0x9F16, 0x9F17, 0x9F19, 0x9F1A, 0x9F1B, - 0x9F1F, 0x9F22, 0x9F26, 0x9F2A, 0x9F2B, 0x9F2F, 0x9F31, 0x9F32, - 0x9F34, 0x9F37, 0x9F39, 0x9F3A, 0x9F3C, 0x9F3D, 0x9F3F, 0x9F41, - 0x9F43, 0x9F44, 0x9F45, 0x9F46, 0x9F47, 0x9F53, 0x9F55, 0x9F56, - 0x9F57, 0x9F58, 0x9F5A, 0x9F5D, 0x9F5E, 0x9F68, 0x9F69, 0x9F6D, - 0x9F6E, 0x9F6F, 0x9F70, 0x9F71, 0x9F73, 0x9F75, 0x9F7A, 0x9F7D, - 0x9F8F, 0x9F90, 0x9F91, 0x9F92, 0x9F94, 0x9F96, 0x9F97, 0x9F9E, - 0x9FA1, 0x9FA2, 0x9FA3, 0x9FA5, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short euc_to_utf8_8FF3[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0x2170, 0x2171, 0x2172, 0x2173, 0x2174, - 0x2175, 0x2176, 0x2177, 0x2178, 0x2179, 0x2160, 0x2161, -}; -static const unsigned short euc_to_utf8_8FF4[] = { - 0x2162, 0x2163, 0x2164, 0x2165, 0x2166, 0x2167, 0x2168, - 0x2169, 0xff07, 0xff02, 0x3231, 0x2116, 0x2121, 0x70bb, 0x4efc, - 0x50f4, 0x51ec, 0x5307, 0x5324, 0xfa0e, 0x548a, 0x5759, 0xfa0f, - 0xfa10, 0x589e, 0x5bec, 0x5cf5, 0x5d53, 0xfa11, 0x5fb7, 0x6085, - 0x6120, 0x654e, 0x663b, 0x6665, 0xfa12, 0xf929, 0x6801, 0xfa13, - 0xfa14, 0x6a6b, 0x6ae2, 0x6df8, 0x6df2, 0x7028, 0xfa15, 0xfa16, - 0x7501, 0x7682, 0x769e, 0xfa17, 0x7930, 0xfa18, 0xfa19, 0xfa1a, - 0xfa1b, 0x7ae7, 0xfa1c, 0xfa1d, 0x7da0, 0x7dd6, 0xfa1e, 0x8362, - 0xfa1f, 0x85b0, 0xfa20, 0xfa21, 0x8807, 0xfa22, 0x8b7f, 0x8cf4, - 0x8d76, 0xfa23, 0xfa24, 0xfa25, 0x90de, 0xfa26, 0x9115, 0xfa27, - 0xfa28, 0x9592, 0xf9dc, 0xfa29, 0x973b, 0x974d, 0x9751, 0xfa2a, - 0xfa2b, 0xfa2c, 0x999e, 0x9ad9, 0x9b72, 0xfa2d, 0x9ed1, -}; -#endif /* X0212_ENABLE */ - -const unsigned short euc_to_utf8_1byte[] = { - 0xFF61, 0xFF62, 0xFF63, 0xFF64, 0xFF65, 0xFF66, 0xFF67, - 0xFF68, 0xFF69, 0xFF6A, 0xFF6B, 0xFF6C, 0xFF6D, 0xFF6E, 0xFF6F, - 0xFF70, 0xFF71, 0xFF72, 0xFF73, 0xFF74, 0xFF75, 0xFF76, 0xFF77, - 0xFF78, 0xFF79, 0xFF7A, 0xFF7B, 0xFF7C, 0xFF7D, 0xFF7E, 0xFF7F, - 0xFF80, 0xFF81, 0xFF82, 0xFF83, 0xFF84, 0xFF85, 0xFF86, 0xFF87, - 0xFF88, 0xFF89, 0xFF8A, 0xFF8B, 0xFF8C, 0xFF8D, 0xFF8E, 0xFF8F, - 0xFF90, 0xFF91, 0xFF92, 0xFF93, 0xFF94, 0xFF95, 0xFF96, 0xFF97, - 0xFF98, 0xFF99, 0xFF9A, 0xFF9B, 0xFF9C, 0xFF9D, 0xFF9E, 0xFF9F, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0x00A9, 0x2122, -}; -const unsigned short *const euc_to_utf8_2bytes[] = { - euc_to_utf8_A1, euc_to_utf8_A2, euc_to_utf8_A3, - euc_to_utf8_A4, euc_to_utf8_A5, euc_to_utf8_A6, euc_to_utf8_A7, - euc_to_utf8_A8, euc_to_utf8_A9, euc_to_utf8_AA, euc_to_utf8_AB, - euc_to_utf8_AC, euc_to_utf8_AD, euc_to_utf8_AE, euc_to_utf8_AF, - euc_to_utf8_B0, euc_to_utf8_B1, euc_to_utf8_B2, euc_to_utf8_B3, - euc_to_utf8_B4, euc_to_utf8_B5, euc_to_utf8_B6, euc_to_utf8_B7, - euc_to_utf8_B8, euc_to_utf8_B9, euc_to_utf8_BA, euc_to_utf8_BB, - euc_to_utf8_BC, euc_to_utf8_BD, euc_to_utf8_BE, euc_to_utf8_BF, - euc_to_utf8_C0, euc_to_utf8_C1, euc_to_utf8_C2, euc_to_utf8_C3, - euc_to_utf8_C4, euc_to_utf8_C5, euc_to_utf8_C6, euc_to_utf8_C7, - euc_to_utf8_C8, euc_to_utf8_C9, euc_to_utf8_CA, euc_to_utf8_CB, - euc_to_utf8_CC, euc_to_utf8_CD, euc_to_utf8_CE, euc_to_utf8_CF, - euc_to_utf8_D0, euc_to_utf8_D1, euc_to_utf8_D2, euc_to_utf8_D3, - euc_to_utf8_D4, euc_to_utf8_D5, euc_to_utf8_D6, euc_to_utf8_D7, - euc_to_utf8_D8, euc_to_utf8_D9, euc_to_utf8_DA, euc_to_utf8_DB, - euc_to_utf8_DC, euc_to_utf8_DD, euc_to_utf8_DE, euc_to_utf8_DF, - euc_to_utf8_E0, euc_to_utf8_E1, euc_to_utf8_E2, euc_to_utf8_E3, - euc_to_utf8_E4, euc_to_utf8_E5, euc_to_utf8_E6, euc_to_utf8_E7, - euc_to_utf8_E8, euc_to_utf8_E9, euc_to_utf8_EA, euc_to_utf8_EB, - euc_to_utf8_EC, euc_to_utf8_ED, euc_to_utf8_EE, euc_to_utf8_EF, - euc_to_utf8_F0, euc_to_utf8_F1, euc_to_utf8_F2, euc_to_utf8_F3, - euc_to_utf8_F4, euc_to_utf8_F5, 0, 0, - 0, euc_to_utf8_F9, euc_to_utf8_FA, euc_to_utf8_FB, - euc_to_utf8_FC, 0, 0, -}; -/* Microsoft UCS Mapping Compatible */ -const unsigned short *const euc_to_utf8_2bytes_ms[] = { - euc_to_utf8_A1_ms, euc_to_utf8_A2_ms, euc_to_utf8_A3, - euc_to_utf8_A4, euc_to_utf8_A5, euc_to_utf8_A6, euc_to_utf8_A7, - euc_to_utf8_A8, euc_to_utf8_A9, euc_to_utf8_AA, euc_to_utf8_AB, - euc_to_utf8_AC, euc_to_utf8_AD, euc_to_utf8_AE, euc_to_utf8_AF, - euc_to_utf8_B0, euc_to_utf8_B1, euc_to_utf8_B2, euc_to_utf8_B3, - euc_to_utf8_B4, euc_to_utf8_B5, euc_to_utf8_B6, euc_to_utf8_B7, - euc_to_utf8_B8, euc_to_utf8_B9, euc_to_utf8_BA, euc_to_utf8_BB, - euc_to_utf8_BC, euc_to_utf8_BD, euc_to_utf8_BE, euc_to_utf8_BF, - euc_to_utf8_C0, euc_to_utf8_C1, euc_to_utf8_C2, euc_to_utf8_C3, - euc_to_utf8_C4, euc_to_utf8_C5, euc_to_utf8_C6, euc_to_utf8_C7, - euc_to_utf8_C8, euc_to_utf8_C9, euc_to_utf8_CA, euc_to_utf8_CB, - euc_to_utf8_CC, euc_to_utf8_CD, euc_to_utf8_CE, euc_to_utf8_CF, - euc_to_utf8_D0, euc_to_utf8_D1, euc_to_utf8_D2, euc_to_utf8_D3, - euc_to_utf8_D4, euc_to_utf8_D5, euc_to_utf8_D6, euc_to_utf8_D7, - euc_to_utf8_D8, euc_to_utf8_D9, euc_to_utf8_DA, euc_to_utf8_DB, - euc_to_utf8_DC, euc_to_utf8_DD, euc_to_utf8_DE, euc_to_utf8_DF, - euc_to_utf8_E0, euc_to_utf8_E1, euc_to_utf8_E2, euc_to_utf8_E3, - euc_to_utf8_E4, euc_to_utf8_E5, euc_to_utf8_E6, euc_to_utf8_E7, - euc_to_utf8_E8, euc_to_utf8_E9, euc_to_utf8_EA, euc_to_utf8_EB, - euc_to_utf8_EC, euc_to_utf8_ED, euc_to_utf8_EE, euc_to_utf8_EF, - euc_to_utf8_F0, euc_to_utf8_F1, euc_to_utf8_F2, euc_to_utf8_F3, - euc_to_utf8_F4, euc_to_utf8_F5, 0, 0, - 0, euc_to_utf8_F9, euc_to_utf8_FA, euc_to_utf8_FB, - euc_to_utf8_FC_ms, 0, 0, -}; -/* CP10001 */ -const unsigned short *const euc_to_utf8_2bytes_mac[] = { - euc_to_utf8_A1_ms, euc_to_utf8_A2_ms, euc_to_utf8_A3, - euc_to_utf8_A4, euc_to_utf8_A5, euc_to_utf8_A6, euc_to_utf8_A7, - euc_to_utf8_A8, euc_to_utf8_A9, euc_to_utf8_AA, euc_to_utf8_AB, - euc_to_utf8_AC_mac, euc_to_utf8_AD_mac, euc_to_utf8_AE, euc_to_utf8_AF, - euc_to_utf8_B0, euc_to_utf8_B1, euc_to_utf8_B2, euc_to_utf8_B3, - euc_to_utf8_B4, euc_to_utf8_B5, euc_to_utf8_B6, euc_to_utf8_B7, - euc_to_utf8_B8, euc_to_utf8_B9, euc_to_utf8_BA, euc_to_utf8_BB, - euc_to_utf8_BC, euc_to_utf8_BD, euc_to_utf8_BE, euc_to_utf8_BF, - euc_to_utf8_C0, euc_to_utf8_C1, euc_to_utf8_C2, euc_to_utf8_C3, - euc_to_utf8_C4, euc_to_utf8_C5, euc_to_utf8_C6, euc_to_utf8_C7, - euc_to_utf8_C8, euc_to_utf8_C9, euc_to_utf8_CA, euc_to_utf8_CB, - euc_to_utf8_CC, euc_to_utf8_CD, euc_to_utf8_CE, euc_to_utf8_CF, - euc_to_utf8_D0, euc_to_utf8_D1, euc_to_utf8_D2, euc_to_utf8_D3, - euc_to_utf8_D4, euc_to_utf8_D5, euc_to_utf8_D6, euc_to_utf8_D7, - euc_to_utf8_D8, euc_to_utf8_D9, euc_to_utf8_DA, euc_to_utf8_DB, - euc_to_utf8_DC, euc_to_utf8_DD, euc_to_utf8_DE, euc_to_utf8_DF, - euc_to_utf8_E0, euc_to_utf8_E1, euc_to_utf8_E2, euc_to_utf8_E3, - euc_to_utf8_E4, euc_to_utf8_E5, euc_to_utf8_E6, euc_to_utf8_E7, - euc_to_utf8_E8, euc_to_utf8_E9, euc_to_utf8_EA, euc_to_utf8_EB, - euc_to_utf8_EC, euc_to_utf8_ED, euc_to_utf8_EE, euc_to_utf8_EF, - euc_to_utf8_F0, euc_to_utf8_F1, euc_to_utf8_F2, euc_to_utf8_F3, - euc_to_utf8_F4, euc_to_utf8_F5, 0, 0, - 0, euc_to_utf8_F9, euc_to_utf8_FA, euc_to_utf8_FB, - euc_to_utf8_FC_ms, 0, 0, -}; -const unsigned short *const euc_to_utf8_2bytes_x0213[] = { - euc_to_utf8_A1, euc_to_utf8_A2_x0213, euc_to_utf8_A3_x0213, - euc_to_utf8_A4_x0213, euc_to_utf8_A5_x0213, euc_to_utf8_A6_x0213, euc_to_utf8_A7_x0213, - euc_to_utf8_A8_x0213, euc_to_utf8_A9_x0213, euc_to_utf8_AA_x0213, euc_to_utf8_AB_x0213, - euc_to_utf8_AC_x0213, euc_to_utf8_AD_x0213, euc_to_utf8_AE_x0213, euc_to_utf8_AF_x0213, - euc_to_utf8_B0, euc_to_utf8_B1, euc_to_utf8_B2, euc_to_utf8_B3, - euc_to_utf8_B4, euc_to_utf8_B5, euc_to_utf8_B6, euc_to_utf8_B7, - euc_to_utf8_B8, euc_to_utf8_B9, euc_to_utf8_BA, euc_to_utf8_BB, - euc_to_utf8_BC, euc_to_utf8_BD, euc_to_utf8_BE, euc_to_utf8_BF, - euc_to_utf8_C0, euc_to_utf8_C1, euc_to_utf8_C2, euc_to_utf8_C3, - euc_to_utf8_C4, euc_to_utf8_C5, euc_to_utf8_C6, euc_to_utf8_C7, - euc_to_utf8_C8, euc_to_utf8_C9, euc_to_utf8_CA, euc_to_utf8_CB, - euc_to_utf8_CC, euc_to_utf8_CD, euc_to_utf8_CE, euc_to_utf8_CF_x0213, - euc_to_utf8_D0, euc_to_utf8_D1, euc_to_utf8_D2, euc_to_utf8_D3, - euc_to_utf8_D4, euc_to_utf8_D5, euc_to_utf8_D6, euc_to_utf8_D7, - euc_to_utf8_D8, euc_to_utf8_D9, euc_to_utf8_DA, euc_to_utf8_DB, - euc_to_utf8_DC, euc_to_utf8_DD, euc_to_utf8_DE, euc_to_utf8_DF, - euc_to_utf8_E0, euc_to_utf8_E1, euc_to_utf8_E2, euc_to_utf8_E3, - euc_to_utf8_E4, euc_to_utf8_E5, euc_to_utf8_E6, euc_to_utf8_E7, - euc_to_utf8_E8, euc_to_utf8_E9, euc_to_utf8_EA, euc_to_utf8_EB, - euc_to_utf8_EC, euc_to_utf8_ED, euc_to_utf8_EE, euc_to_utf8_EF, - euc_to_utf8_F0, euc_to_utf8_F1, euc_to_utf8_F2, euc_to_utf8_F3, - euc_to_utf8_F4_x0213, euc_to_utf8_F5_x0213, euc_to_utf8_F6_x0213, euc_to_utf8_F7_x0213, - euc_to_utf8_F8_x0213, euc_to_utf8_F9_x0213, euc_to_utf8_FA_x0213, euc_to_utf8_FB_x0213, - euc_to_utf8_FC_x0213, euc_to_utf8_FD_x0213, euc_to_utf8_FE_x0213, -}; - -#ifdef X0212_ENABLE -const unsigned short *const x0212_to_utf8_2bytes[] = { - 0, euc_to_utf8_8FA2, 0, - 0, 0, euc_to_utf8_8FA6, euc_to_utf8_8FA7, - 0, euc_to_utf8_8FA9, euc_to_utf8_8FAA, euc_to_utf8_8FAB, - 0, 0, 0, 0, - euc_to_utf8_8FB0, euc_to_utf8_8FB1, euc_to_utf8_8FB2, euc_to_utf8_8FB3, - euc_to_utf8_8FB4, euc_to_utf8_8FB5, euc_to_utf8_8FB6, euc_to_utf8_8FB7, - euc_to_utf8_8FB8, euc_to_utf8_8FB9, euc_to_utf8_8FBA, euc_to_utf8_8FBB, - euc_to_utf8_8FBC, euc_to_utf8_8FBD, euc_to_utf8_8FBE, euc_to_utf8_8FBF, - euc_to_utf8_8FC0, euc_to_utf8_8FC1, euc_to_utf8_8FC2, euc_to_utf8_8FC3, - euc_to_utf8_8FC4, euc_to_utf8_8FC5, euc_to_utf8_8FC6, euc_to_utf8_8FC7, - euc_to_utf8_8FC8, euc_to_utf8_8FC9, euc_to_utf8_8FCA, euc_to_utf8_8FCB, - euc_to_utf8_8FCC, euc_to_utf8_8FCD, euc_to_utf8_8FCE, euc_to_utf8_8FCF, - euc_to_utf8_8FD0, euc_to_utf8_8FD1, euc_to_utf8_8FD2, euc_to_utf8_8FD3, - euc_to_utf8_8FD4, euc_to_utf8_8FD5, euc_to_utf8_8FD6, euc_to_utf8_8FD7, - euc_to_utf8_8FD8, euc_to_utf8_8FD9, euc_to_utf8_8FDA, euc_to_utf8_8FDB, - euc_to_utf8_8FDC, euc_to_utf8_8FDD, euc_to_utf8_8FDE, euc_to_utf8_8FDF, - euc_to_utf8_8FE0, euc_to_utf8_8FE1, euc_to_utf8_8FE2, euc_to_utf8_8FE3, - euc_to_utf8_8FE4, euc_to_utf8_8FE5, euc_to_utf8_8FE6, euc_to_utf8_8FE7, - euc_to_utf8_8FE8, euc_to_utf8_8FE9, euc_to_utf8_8FEA, euc_to_utf8_8FEB, - euc_to_utf8_8FEC, euc_to_utf8_8FED, 0, 0, - 0, 0, 0, euc_to_utf8_8FF3, - euc_to_utf8_8FF4, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0,}; - -const unsigned short *const x0212_to_utf8_2bytes_x0213[] = { - euc_to_utf8_8FA1_x0213, euc_to_utf8_8FA2, euc_to_utf8_8FA3_x0213, - euc_to_utf8_8FA4_x0213, euc_to_utf8_8FA5_x0213, euc_to_utf8_8FA6, euc_to_utf8_8FA7, - euc_to_utf8_8FA8_x0213, euc_to_utf8_8FA9, euc_to_utf8_8FAA, euc_to_utf8_8FAB, - euc_to_utf8_8FAC_x0213, euc_to_utf8_8FAD_x0213, euc_to_utf8_8FAE_x0213, euc_to_utf8_8FAF_x0213, - euc_to_utf8_8FB0, euc_to_utf8_8FB1, euc_to_utf8_8FB2, euc_to_utf8_8FB3, - euc_to_utf8_8FB4, euc_to_utf8_8FB5, euc_to_utf8_8FB6, euc_to_utf8_8FB7, - euc_to_utf8_8FB8, euc_to_utf8_8FB9, euc_to_utf8_8FBA, euc_to_utf8_8FBB, - euc_to_utf8_8FBC, euc_to_utf8_8FBD, euc_to_utf8_8FBE, euc_to_utf8_8FBF, - euc_to_utf8_8FC0, euc_to_utf8_8FC1, euc_to_utf8_8FC2, euc_to_utf8_8FC3, - euc_to_utf8_8FC4, euc_to_utf8_8FC5, euc_to_utf8_8FC6, euc_to_utf8_8FC7, - euc_to_utf8_8FC8, euc_to_utf8_8FC9, euc_to_utf8_8FCA, euc_to_utf8_8FCB, - euc_to_utf8_8FCC, euc_to_utf8_8FCD, euc_to_utf8_8FCE, euc_to_utf8_8FCF, - euc_to_utf8_8FD0, euc_to_utf8_8FD1, euc_to_utf8_8FD2, euc_to_utf8_8FD3, - euc_to_utf8_8FD4, euc_to_utf8_8FD5, euc_to_utf8_8FD6, euc_to_utf8_8FD7, - euc_to_utf8_8FD8, euc_to_utf8_8FD9, euc_to_utf8_8FDA, euc_to_utf8_8FDB, - euc_to_utf8_8FDC, euc_to_utf8_8FDD, euc_to_utf8_8FDE, euc_to_utf8_8FDF, - euc_to_utf8_8FE0, euc_to_utf8_8FE1, euc_to_utf8_8FE2, euc_to_utf8_8FE3, - euc_to_utf8_8FE4, euc_to_utf8_8FE5, euc_to_utf8_8FE6, euc_to_utf8_8FE7, - euc_to_utf8_8FE8, euc_to_utf8_8FE9, euc_to_utf8_8FEA, euc_to_utf8_8FEB, - euc_to_utf8_8FEC, euc_to_utf8_8FED, euc_to_utf8_8FEE_x0213, euc_to_utf8_8FEF_x0213, - euc_to_utf8_8FF0_x0213, euc_to_utf8_8FF1_x0213, euc_to_utf8_8FF2_x0213, euc_to_utf8_8FF3_x0213, - euc_to_utf8_8FF4_x0213, euc_to_utf8_8FF5_x0213, euc_to_utf8_8FF6_x0213, euc_to_utf8_8FF7_x0213, - euc_to_utf8_8FF8_x0213, euc_to_utf8_8FF9_x0213, euc_to_utf8_8FFA_x0213, euc_to_utf8_8FFB_x0213, - euc_to_utf8_8FFC_x0213, euc_to_utf8_8FFD_x0213, euc_to_utf8_8FFE_x0213,}; -#endif /* X0212_ENABLE */ - -const unsigned short x0213_combining_chars[sizeof_x0213_combining_chars] = { - 0x309A, 0x0300, 0x0301, 0x02E5, 0x02E9, -}; -const unsigned short x0213_combining_table[sizeof_x0213_combining_table][3] = { - {0x2477, 0x304B, 0x309A}, - {0x2478, 0x304D, 0x309A}, - {0x2479, 0x304F, 0x309A}, - {0x247A, 0x3051, 0x309A}, - {0x247B, 0x3053, 0x309A}, - {0x2577, 0x30AB, 0x309A}, - {0x2578, 0x30AD, 0x309A}, - {0x2579, 0x30AF, 0x309A}, - {0x257A, 0x30B1, 0x309A}, - {0x257B, 0x30B3, 0x309A}, - {0x257C, 0x30BB, 0x309A}, - {0x257D, 0x30C4, 0x309A}, - {0x257E, 0x30C8, 0x309A}, - {0x2678, 0x31F7, 0x309A}, - {0x2B44, 0x00E6, 0x0300}, - {0x2B48, 0x0254, 0x0300}, - {0x2B49, 0x0254, 0x0301}, - {0x2B4A, 0x028C, 0x0300}, - {0x2B4B, 0x028C, 0x0301}, - {0x2B4C, 0x0259, 0x0300}, - {0x2B4D, 0x0259, 0x0301}, - {0x2B4E, 0x025A, 0x0300}, - {0x2B4F, 0x025A, 0x0301}, - {0x2B65, 0x02E9, 0x02E5}, - {0x2B66, 0x02E5, 0x02E9}, -}; -const unsigned short x0213_1_surrogate_table[sizeof_x0213_1_surrogate_table][3] = { - {0x2E22, 0xD840, 0xDC0B}, - {0x2F42, 0xD844, 0xDE3D}, - {0x2F4C, 0xD844, 0xDF1B}, - {0x2F60, 0xD845, 0xDC6E}, - {0x2F7B, 0xD846, 0xDCBD}, - {0x4F54, 0xD842, 0xDF9F}, - {0x4F63, 0xD845, 0xDEB4}, - {0x4F6E, 0xD847, 0xDE34}, - {0x753A, 0xD84C, 0xDDC4}, - {0x7572, 0xD84D, 0xDDC4}, - {0x7629, 0xD84D, 0xDF3F}, - {0x7632, 0xD84D, 0xDF63}, - {0x7660, 0xD84F, 0xDCFE}, - {0x776C, 0xD851, 0xDFF1}, - {0x787E, 0xD855, 0xDC8E}, - {0x7929, 0xD855, 0xDD0E}, - {0x7947, 0xD855, 0xDF71}, - {0x7954, 0xD856, 0xDDC4}, - {0x796E, 0xD857, 0xDDA1}, - {0x7A5D, 0xD85A, 0xDEFF}, - {0x7B33, 0xD85B, 0xDE40}, - {0x7B49, 0xD85C, 0xDCF4}, - {0x7B6C, 0xD85D, 0xDE84}, - {0x7C49, 0xD860, 0xDE77}, - {0x7C51, 0xD860, 0xDFCD}, - {0x7E66, 0xD868, 0xDD90}, -}; -const unsigned short x0213_2_surrogate_table[sizeof_x0213_2_surrogate_table][3] = { - {0x2121, 0xD840, 0xDC89}, - {0x212B, 0xD840, 0xDCA2}, - {0x212E, 0xD840, 0xDCA4}, - {0x2136, 0xD840, 0xDDA2}, - {0x2146, 0xD840, 0xDE13}, - {0x2170, 0xD840, 0xDF2B}, - {0x2177, 0xD840, 0xDF81}, - {0x2179, 0xD840, 0xDF71}, - {0x2322, 0xD840, 0xDFF9}, - {0x2325, 0xD841, 0xDC4A}, - {0x2327, 0xD841, 0xDD09}, - {0x2331, 0xD841, 0xDDD6}, - {0x2332, 0xD841, 0xDE28}, - {0x2338, 0xD841, 0xDF4F}, - {0x233F, 0xD842, 0xDC07}, - {0x2341, 0xD842, 0xDC3A}, - {0x234A, 0xD842, 0xDCB9}, - {0x2352, 0xD842, 0xDD7C}, - {0x2353, 0xD842, 0xDD9D}, - {0x2359, 0xD842, 0xDED3}, - {0x235C, 0xD842, 0xDF1D}, - {0x2377, 0xD843, 0xDD45}, - {0x242A, 0xD843, 0xDDE1}, - {0x2431, 0xD843, 0xDE95}, - {0x2432, 0xD843, 0xDE6D}, - {0x243A, 0xD843, 0xDE64}, - {0x243D, 0xD843, 0xDF5F}, - {0x2459, 0xD844, 0xDE01}, - {0x245C, 0xD844, 0xDE55}, - {0x245E, 0xD844, 0xDE7B}, - {0x2463, 0xD844, 0xDE74}, - {0x246A, 0xD844, 0xDEE4}, - {0x246B, 0xD844, 0xDED7}, - {0x2472, 0xD844, 0xDEFD}, - {0x2474, 0xD844, 0xDF36}, - {0x2475, 0xD844, 0xDF44}, - {0x2525, 0xD844, 0xDFC4}, - {0x2532, 0xD845, 0xDC6D}, - {0x253E, 0xD845, 0xDDD7}, - {0x2544, 0xD85B, 0xDC29}, - {0x2547, 0xD845, 0xDE47}, - {0x2555, 0xD845, 0xDF06}, - {0x2556, 0xD845, 0xDF42}, - {0x257E, 0xD846, 0xDDC3}, - {0x2830, 0xD847, 0xDC56}, - {0x2837, 0xD847, 0xDD2D}, - {0x2838, 0xD847, 0xDD45}, - {0x283A, 0xD847, 0xDD78}, - {0x283B, 0xD847, 0xDD62}, - {0x283F, 0xD847, 0xDDA1}, - {0x2840, 0xD847, 0xDD9C}, - {0x2845, 0xD847, 0xDD92}, - {0x2848, 0xD847, 0xDDB7}, - {0x284A, 0xD847, 0xDDE0}, - {0x284B, 0xD847, 0xDE33}, - {0x285B, 0xD847, 0xDF1E}, - {0x2866, 0xD847, 0xDF76}, - {0x286C, 0xD847, 0xDFFA}, - {0x2C22, 0xD848, 0xDD7B}, - {0x2C2B, 0xD848, 0xDF1E}, - {0x2C30, 0xD848, 0xDFAD}, - {0x2C50, 0xD849, 0xDEF3}, - {0x2C65, 0xD84A, 0xDC5B}, - {0x2C6D, 0xD84A, 0xDCAB}, - {0x2C72, 0xD84A, 0xDD8F}, - {0x2D24, 0xD84A, 0xDEB8}, - {0x2D29, 0xD84A, 0xDF4F}, - {0x2D2A, 0xD84A, 0xDF50}, - {0x2D32, 0xD84A, 0xDF46}, - {0x2D34, 0xD84B, 0xDC1D}, - {0x2D35, 0xD84A, 0xDFA6}, - {0x2D39, 0xD84B, 0xDC24}, - {0x2D56, 0xD84B, 0xDDE1}, - {0x2D7D, 0xD84C, 0xDDC3}, - {0x2E23, 0xD84C, 0xDDF5}, - {0x2E24, 0xD84C, 0xDDB6}, - {0x2E3A, 0xD84C, 0xDF72}, - {0x2E3C, 0xD84C, 0xDFD3}, - {0x2E3D, 0xD84C, 0xDFD2}, - {0x2E42, 0xD84C, 0xDFD0}, - {0x2E43, 0xD84C, 0xDFE4}, - {0x2E44, 0xD84C, 0xDFD5}, - {0x2E47, 0xD84C, 0xDFDA}, - {0x2E49, 0xD84C, 0xDFDF}, - {0x2E55, 0xD84D, 0xDC4A}, - {0x2E56, 0xD84D, 0xDC51}, - {0x2E57, 0xD84D, 0xDC4B}, - {0x2E5B, 0xD84D, 0xDC65}, - {0x2E77, 0xD84D, 0xDCE4}, - {0x2E78, 0xD84D, 0xDD5A}, - {0x2F2A, 0xD84D, 0xDD94}, - {0x2F3F, 0xD84D, 0xDE39}, - {0x2F40, 0xD84D, 0xDE47}, - {0x2F42, 0xD84D, 0xDE38}, - {0x2F43, 0xD84D, 0xDE3A}, - {0x2F4E, 0xD84D, 0xDF1C}, - {0x2F59, 0xD84D, 0xDF0C}, - {0x2F61, 0xD84D, 0xDF64}, - {0x2F69, 0xD84D, 0xDFFF}, - {0x2F6A, 0xD84D, 0xDFE7}, - {0x2F70, 0xD84E, 0xDC24}, - {0x2F75, 0xD84E, 0xDC3D}, - {0x6E23, 0xD84E, 0xDE98}, - {0x6E34, 0xD84F, 0xDC7F}, - {0x6E49, 0xD84F, 0xDD00}, - {0x6E5C, 0xD84F, 0xDD40}, - {0x6E5E, 0xD84F, 0xDDFA}, - {0x6E5F, 0xD84F, 0xDDF9}, - {0x6E60, 0xD84F, 0xDDD3}, - {0x6F32, 0xD84F, 0xDF7E}, - {0x6F47, 0xD850, 0xDC96}, - {0x6F4D, 0xD850, 0xDD03}, - {0x6F61, 0xD850, 0xDDC6}, - {0x6F64, 0xD850, 0xDDFE}, - {0x7022, 0xD850, 0xDFBC}, - {0x7033, 0xD851, 0xDE29}, - {0x7039, 0xD851, 0xDEA5}, - {0x7053, 0xD852, 0xDC96}, - {0x707B, 0xD852, 0xDE4D}, - {0x712E, 0xD852, 0xDF56}, - {0x7130, 0xD852, 0xDF6F}, - {0x7135, 0xD853, 0xDC16}, - {0x7144, 0xD853, 0xDD14}, - {0x715D, 0xD853, 0xDE0E}, - {0x7161, 0xD853, 0xDE37}, - {0x7166, 0xD853, 0xDE6A}, - {0x7169, 0xD853, 0xDE8B}, - {0x7175, 0xD854, 0xDC4A}, - {0x7177, 0xD854, 0xDC55}, - {0x717A, 0xD854, 0xDD22}, - {0x7221, 0xD854, 0xDDA9}, - {0x7223, 0xD854, 0xDDE5}, - {0x7224, 0xD854, 0xDDCD}, - {0x7228, 0xD854, 0xDE1E}, - {0x722C, 0xD854, 0xDE4C}, - {0x723D, 0xD855, 0xDC2E}, - {0x7248, 0xD855, 0xDCD9}, - {0x725B, 0xD855, 0xDDA7}, - {0x7275, 0xD855, 0xDFA9}, - {0x7276, 0xD855, 0xDFB4}, - {0x7332, 0xD856, 0xDDD4}, - {0x733D, 0xD856, 0xDEE4}, - {0x733E, 0xD856, 0xDEE3}, - {0x7340, 0xD856, 0xDEF1}, - {0x7352, 0xD856, 0xDFB2}, - {0x735D, 0xD857, 0xDC4B}, - {0x735E, 0xD857, 0xDC64}, - {0x7373, 0xD857, 0xDE2E}, - {0x7374, 0xD857, 0xDE56}, - {0x7375, 0xD857, 0xDE65}, - {0x7377, 0xD857, 0xDE62}, - {0x737B, 0xD857, 0xDED8}, - {0x737D, 0xD857, 0xDEC2}, - {0x7422, 0xD857, 0xDEE8}, - {0x7424, 0xD857, 0xDF23}, - {0x7427, 0xD857, 0xDF5C}, - {0x742E, 0xD857, 0xDFE0}, - {0x742F, 0xD857, 0xDFD4}, - {0x7434, 0xD858, 0xDC0C}, - {0x7435, 0xD857, 0xDFFB}, - {0x743D, 0xD858, 0xDC17}, - {0x7442, 0xD858, 0xDC60}, - {0x744F, 0xD858, 0xDCED}, - {0x7469, 0xD858, 0xDE70}, - {0x746B, 0xD858, 0xDE86}, - {0x7472, 0xD858, 0xDF4C}, - {0x7475, 0xD84F, 0xDD0E}, - {0x7479, 0xD859, 0xDC02}, - {0x7535, 0xD859, 0xDE7E}, - {0x753A, 0xD859, 0xDEB0}, - {0x7546, 0xD859, 0xDF1D}, - {0x7556, 0xD85A, 0xDCDD}, - {0x7558, 0xD85A, 0xDCEA}, - {0x755A, 0xD85A, 0xDD51}, - {0x755D, 0xD85A, 0xDD6F}, - {0x755F, 0xD85A, 0xDDDD}, - {0x7563, 0xD85A, 0xDE1E}, - {0x756A, 0xD85A, 0xDE58}, - {0x7570, 0xD85A, 0xDE8C}, - {0x7573, 0xD85A, 0xDEB7}, - {0x7644, 0xD85B, 0xDC73}, - {0x764E, 0xD85B, 0xDCDD}, - {0x765D, 0xD85B, 0xDE65}, - {0x7675, 0xD85B, 0xDF94}, - {0x767E, 0xD85B, 0xDFF8}, - {0x7721, 0xD85B, 0xDFF6}, - {0x7722, 0xD85B, 0xDFF7}, - {0x7733, 0xD85C, 0xDD0D}, - {0x7736, 0xD85C, 0xDD39}, - {0x7764, 0xD85C, 0xDFDB}, - {0x7765, 0xD85C, 0xDFDA}, - {0x776B, 0xD85C, 0xDFFE}, - {0x776E, 0xD85D, 0xDC10}, - {0x7773, 0xD85D, 0xDC49}, - {0x7829, 0xD85D, 0xDE15}, - {0x782A, 0xD85D, 0xDE14}, - {0x782C, 0xD85D, 0xDE31}, - {0x7834, 0xD85D, 0xDE93}, - {0x783C, 0xD85D, 0xDF0E}, - {0x783E, 0xD85D, 0xDF23}, - {0x7842, 0xD85D, 0xDF52}, - {0x7856, 0xD85E, 0xDD85}, - {0x7863, 0xD85E, 0xDE84}, - {0x7877, 0xD85E, 0xDFB3}, - {0x7879, 0xD85E, 0xDFBE}, - {0x787A, 0xD85E, 0xDFC7}, - {0x7925, 0xD85F, 0xDCB8}, - {0x792F, 0xD85F, 0xDDA0}, - {0x7932, 0xD85F, 0xDE10}, - {0x7939, 0xD85F, 0xDFB7}, - {0x7942, 0xD860, 0xDC8A}, - {0x7948, 0xD860, 0xDCBB}, - {0x7959, 0xD860, 0xDE82}, - {0x795E, 0xD860, 0xDEF3}, - {0x7966, 0xD861, 0xDC0C}, - {0x796B, 0xD861, 0xDC55}, - {0x797A, 0xD861, 0xDD6B}, - {0x797E, 0xD861, 0xDDC8}, - {0x7A21, 0xD861, 0xDDC9}, - {0x7A2C, 0xD861, 0xDED7}, - {0x7A2F, 0xD861, 0xDEFA}, - {0x7A4F, 0xD862, 0xDD49}, - {0x7A50, 0xD862, 0xDD46}, - {0x7A57, 0xD862, 0xDD6B}, - {0x7A65, 0xD862, 0xDD87}, - {0x7A66, 0xD862, 0xDD88}, - {0x7A71, 0xD862, 0xDDBA}, - {0x7A72, 0xD862, 0xDDBB}, - {0x7A7E, 0xD862, 0xDE1E}, - {0x7B21, 0xD862, 0xDE29}, - {0x7B2C, 0xD862, 0xDE71}, - {0x7B2D, 0xD862, 0xDE43}, - {0x7B36, 0xD862, 0xDE99}, - {0x7B37, 0xD862, 0xDECD}, - {0x7B3D, 0xD862, 0xDEE4}, - {0x7B3E, 0xD862, 0xDEDD}, - {0x7B4E, 0xD862, 0xDFC1}, - {0x7B4F, 0xD862, 0xDFEF}, - {0x7B57, 0xD863, 0xDD10}, - {0x7B5A, 0xD863, 0xDD71}, - {0x7B5C, 0xD863, 0xDDFB}, - {0x7B5D, 0xD863, 0xDE1F}, - {0x7B61, 0xD863, 0xDE36}, - {0x7B65, 0xD863, 0xDE89}, - {0x7B67, 0xD863, 0xDEEB}, - {0x7B69, 0xD863, 0xDF32}, - {0x7B71, 0xD863, 0xDFF8}, - {0x7C22, 0xD864, 0xDEA0}, - {0x7C23, 0xD864, 0xDEB1}, - {0x7C38, 0xD865, 0xDC90}, - {0x7C42, 0xD865, 0xDDCF}, - {0x7C4C, 0xD865, 0xDE7F}, - {0x7C56, 0xD865, 0xDEF0}, - {0x7C59, 0xD865, 0xDF19}, - {0x7C5D, 0xD865, 0xDF50}, - {0x7C76, 0xD866, 0xDCC6}, - {0x7D2C, 0xD866, 0xDE72}, - {0x7D4B, 0xD867, 0xDDDB}, - {0x7D4C, 0xD867, 0xDE3D}, - {0x7D59, 0xD867, 0xDE15}, - {0x7D5B, 0xD867, 0xDE8A}, - {0x7D5D, 0xD867, 0xDE49}, - {0x7D67, 0xD867, 0xDEC4}, - {0x7D6D, 0xD867, 0xDEE9}, - {0x7D70, 0xD867, 0xDEDB}, - {0x7E25, 0xD867, 0xDFCE}, - {0x7E29, 0xD868, 0xDC2F}, - {0x7E2B, 0xD868, 0xDC1A}, - {0x7E32, 0xD868, 0xDCF9}, - {0x7E35, 0xD868, 0xDC82}, - {0x7E53, 0xD848, 0xDE18}, - {0x7E58, 0xD868, 0xDF8C}, - {0x7E5A, 0xD869, 0xDC37}, - {0x7E6E, 0xD869, 0xDDF1}, - {0x7E70, 0xD869, 0xDE02}, - {0x7E72, 0xD869, 0xDE1A}, - {0x7E76, 0xD869, 0xDEB2}, -}; -#endif /* UTF8_OUTPUT_ENABLE */ - -#ifdef UTF8_INPUT_ENABLE -static const unsigned short utf8_to_euc_C2[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0xA242, 0x2171, 0x2172, 0xA270, 0x216F, 0xA243, 0x2178, - 0x212F, 0xA26D, 0xA26C, 0, 0x224C, 0, 0xA26E, 0xA234, - 0x216B, 0x215E, 0, 0, 0x212D, 0, 0x2279, 0, - 0xA231, 0, 0xA26B, 0, 0, 0, 0, 0xA244, -}; -static const unsigned short utf8_to_euc_C2_ms[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0xA242, 0x2171, 0x2172, 0xA270, 0x5C, 0xA243, 0x2178, - 0x212F, 0xA26D, 0xA26C, 0, 0x224C, 0, 0xA26E, 0xA234, - 0x216B, 0x215E, 0, 0, 0x212D, 0, 0x2279, 0, - 0xA231, 0, 0xA26B, 0, 0, 0, 0, 0xA244, -}; -static const unsigned short utf8_to_euc_C2_mac[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x00A0, 0xA242, 0x2171, 0x2172, 0xA270, 0x5C, 0xA243, 0x2178, - 0x212F, 0x00FD, 0xA26C, 0, 0x224C, 0, 0xA26E, 0xA234, - 0x216B, 0x215E, 0, 0, 0x212D, 0, 0x2279, 0, - 0xA231, 0, 0xA26B, 0, 0, 0, 0, 0xA244, -}; -static const unsigned short utf8_to_euc_C2_932[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0x21, 0x2171, 0x2172, 0, 0x5C, 0x7C, 0x2178, - 0x212F, 0x63, 0x61, 0x2263, 0x224C, 0x2D, 0x52, 0x2131, - 0x216B, 0x215E, 0x32, 0x33, 0x212D, 0x264C, 0x2279, 0x2126, - 0x2124, 0x31, 0x6F, 0x2264, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_C2_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x2922, 0x2923, 0x2171, 0x2172, 0x2924, 0x216F, 0x2925, 0x2178, - 0x212F, 0x2926, 0x2927, 0x2928, 0x224C, 0x2929, 0x292A, 0x292B, - 0x216B, 0x215E, 0x292C, 0x292D, 0x212D, 0, 0x2279, 0x292E, - 0x292F, 0x2930, 0x2931, 0x2932, 0x2933, 0x2934, 0x2935, 0x2936, -}; -static const unsigned short utf8_to_euc_C3[] = { - 0xAA22, 0xAA21, 0xAA24, 0xAA2A, 0xAA23, 0xAA29, 0xA921, 0xAA2E, - 0xAA32, 0xAA31, 0xAA34, 0xAA33, 0xAA40, 0xAA3F, 0xAA42, 0xAA41, - 0, 0xAA50, 0xAA52, 0xAA51, 0xAA54, 0xAA58, 0xAA53, 0x215F, - 0xA92C, 0xAA63, 0xAA62, 0xAA65, 0xAA64, 0xAA72, 0xA930, 0xA94E, - 0xAB22, 0xAB21, 0xAB24, 0xAB2A, 0xAB23, 0xAB29, 0xA941, 0xAB2E, - 0xAB32, 0xAB31, 0xAB34, 0xAB33, 0xAB40, 0xAB3F, 0xAB42, 0xAB41, - 0xA943, 0xAB50, 0xAB52, 0xAB51, 0xAB54, 0xAB58, 0xAB53, 0x2160, - 0xA94C, 0xAB63, 0xAB62, 0xAB65, 0xAB64, 0xAB72, 0xA950, 0xAB73, -}; -static const unsigned short utf8_to_euc_C3_932[] = { - 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x41, 0x43, - 0x45, 0x45, 0x45, 0x45, 0x49, 0x49, 0x49, 0x49, - 0x44, 0x4E, 0x4F, 0x4F, 0x4F, 0x4F, 0x4F, 0x215F, - 0x4F, 0x55, 0x55, 0x55, 0x55, 0x59, 0x54, 0x73, - 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x61, 0x63, - 0x65, 0x65, 0x65, 0x65, 0x69, 0x69, 0x69, 0x69, - 0x64, 0x6E, 0x6F, 0x6F, 0x6F, 0x6F, 0x6F, 0x2160, - 0x6F, 0x75, 0x75, 0x75, 0x75, 0x79, 0x74, 0x79, -}; -static const unsigned short utf8_to_euc_C3_x0213[] = { - 0x2937, 0x2938, 0x2939, 0x293A, 0x293B, 0x293C, 0x293D, 0x293E, - 0x293F, 0x2940, 0x2941, 0x2942, 0x2943, 0x2944, 0x2945, 0x2946, - 0x2947, 0x2948, 0x2949, 0x294A, 0x294B, 0x294C, 0x294D, 0x215F, - 0x294E, 0x294F, 0x2950, 0x2951, 0x2952, 0x2953, 0x2954, 0x2955, - 0x2956, 0x2957, 0x2958, 0x2959, 0x295A, 0x295B, 0x295C, 0x295D, - 0x295E, 0x295F, 0x2960, 0x2961, 0x2962, 0x2963, 0x2964, 0x2965, - 0x2966, 0x2967, 0x2968, 0x2969, 0x296A, 0x296B, 0x296C, 0x2160, - 0x296D, 0x296E, 0x296F, 0x2970, 0x2971, 0x2972, 0x2973, 0x2974, -}; -static const unsigned short utf8_to_euc_C4[] = { - 0xAA27, 0xAB27, 0xAA25, 0xAB25, 0xAA28, 0xAB28, 0xAA2B, 0xAB2B, - 0xAA2C, 0xAB2C, 0xAA2F, 0xAB2F, 0xAA2D, 0xAB2D, 0xAA30, 0xAB30, - 0xA922, 0xA942, 0xAA37, 0xAB37, 0, 0, 0xAA36, 0xAB36, - 0xAA38, 0xAB38, 0xAA35, 0xAB35, 0xAA3A, 0xAB3A, 0xAA3B, 0xAB3B, - 0xAA3D, 0xAB3D, 0xAA3C, 0, 0xAA3E, 0xAB3E, 0xA924, 0xA944, - 0xAA47, 0xAB47, 0xAA45, 0xAB45, 0, 0, 0xAA46, 0xAB46, - 0xAA44, 0xA945, 0xA926, 0xA946, 0xAA48, 0xAB48, 0xAA49, 0xAB49, - 0xA947, 0xAA4A, 0xAB4A, 0xAA4C, 0xAB4C, 0xAA4B, 0xAB4B, 0xA929, -}; -static const unsigned short utf8_to_euc_C4_x0213[] = { - 0x2975, 0x297A, 0x2A3A, 0x2A49, 0x2A21, 0x2A2C, 0x2A3C, 0x2A4B, - 0x2A59, 0x2A5F, 0xAA2F, 0xAB2F, 0x2A3D, 0x2A4C, 0x2A40, 0x2A4F, - 0xA922, 0x2A50, 0x2978, 0x297D, 0, 0, 0xAA36, 0xAB36, - 0x2A3E, 0x2A4D, 0x2A3F, 0x2A4E, 0x2A5A, 0x2A60, 0xAA3B, 0xAB3B, - 0xAA3D, 0xAB3D, 0xAA3C, 0, 0x2A5B, 0x2A61, 0xA924, 0x2A7D, - 0xAA47, 0xAB47, 0x2976, 0x297B, 0, 0, 0xAA46, 0xAB46, - 0xAA44, 0xA945, 0xA926, 0xA946, 0x2A5C, 0x2A62, 0xAA49, 0xAB49, - 0xA947, 0x2A3B, 0x2A4A, 0xAA4C, 0xAB4C, 0x2A24, 0x2A2F, 0xA929, -}; -static const unsigned short utf8_to_euc_C5[] = { - 0xA949, 0xA928, 0xA948, 0xAA4D, 0xAB4D, 0xAA4F, 0xAB4F, 0xAA4E, - 0xAB4E, 0xA94A, 0xA92B, 0xA94B, 0xAA57, 0xAB57, 0, 0, - 0xAA56, 0xAB56, 0xA92D, 0xA94D, 0xAA59, 0xAB59, 0xAA5B, 0xAB5B, - 0xAA5A, 0xAB5A, 0xAA5C, 0xAB5C, 0xAA5D, 0xAB5D, 0xAA5F, 0xAB5F, - 0xAA5E, 0xAB5E, 0xAA61, 0xAB61, 0xAA60, 0xAB60, 0xA92F, 0xA94F, - 0xAA6C, 0xAB6C, 0xAA69, 0xAB69, 0xAA66, 0xAB66, 0xAA6B, 0xAB6B, - 0xAA68, 0xAB68, 0xAA6A, 0xAB6A, 0xAA71, 0xAB71, 0xAA74, 0xAB74, - 0xAA73, 0xAA75, 0xAB75, 0xAA77, 0xAB77, 0xAA76, 0xAB76, 0, -}; -static const unsigned short utf8_to_euc_C5_x0213[] = { - 0xA949, 0x2A23, 0x2A2E, 0x2A41, 0x2A51, 0xAA4F, 0xAB4F, 0x2A42, - 0x2A52, 0xA94A, 0xA92B, 0x2A7A, 0x2979, 0x297E, 0, 0, - 0x2A43, 0x2A53, 0x2B2B, 0x2B2A, 0x2A39, 0x2A48, 0xAA5B, 0xAB5B, - 0x2A44, 0x2A54, 0x2A25, 0x2A30, 0x2A5D, 0x2A63, 0x2A27, 0x2A33, - 0x2A26, 0x2A32, 0x2A47, 0x2A57, 0x2A28, 0x2A34, 0xA92F, 0xA94F, - 0xAA6C, 0xAB6C, 0x2977, 0x297C, 0x2A5E, 0x2A64, 0x2A45, 0x2A55, - 0x2A46, 0x2A56, 0xAA6A, 0xAB6A, 0xAA71, 0xAB71, 0xAA74, 0xAB74, - 0xAA73, 0x2A29, 0x2A35, 0x2A2B, 0x2A38, 0x2A2A, 0x2A37, 0, -}; -static const unsigned short utf8_to_euc_C6_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0x2B29, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_C7[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0xAA26, 0xAB26, 0xAA43, - 0xAB43, 0xAA55, 0xAB55, 0xAA67, 0xAB67, 0xAA70, 0xAB70, 0xAA6D, - 0xAB6D, 0xAA6F, 0xAB6F, 0xAA6E, 0xAB6E, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0xAB39, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_C7_x0213[] = { - 0, 0, 0x2B24, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0x286F, 0x2870, 0xAA43, - 0x2871, 0x2876, 0x2877, 0xAA67, 0x2878, 0xAA70, 0x2879, 0xAA6D, - 0x287A, 0xAA6F, 0x287B, 0xAA6E, 0x287C, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0xAB39, 0, 0, - 0x2874, 0x2875, 0, 0, 0, 0x2B45, 0, 0, -}; -static const unsigned short utf8_to_euc_C9_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x2B33, 0x2B39, 0x2B3A, 0x2B25, 0x2B38, 0x2B3F, 0x2A6E, 0x2B26, - 0x2B2E, 0x2B30, 0x2B43, 0, 0x2B31, 0, 0x2B32, 0x2A75, - 0x2B28, 0x2A79, 0, 0, 0x2B36, 0x2B3C, 0x2B22, 0x2B42, - 0x2B2C, 0, 0, 0, 0x2A6A, 0x2A74, 0x2A6B, 0x2B34, - 0x2A7B, 0x2A65, 0x2A76, 0x2A6F, 0, 0x2B2F, 0, 0, - 0, 0x2A6C, 0x2B41, 0x2A73, 0, 0x2A70, 0x2A67, 0, -}; -static const unsigned short utf8_to_euc_CA_x0213[] = { - 0, 0x2A7C, 0x2A71, 0x2A68, 0x2B27, 0, 0, 0, - 0x2A6D, 0x2B2D, 0x2B35, 0x2A66, 0x2B37, 0x2B3B, 0x2A78, 0, - 0x2A72, 0x2B40, 0x2A69, 0, 0x2B21, 0x2A7E, 0, 0, - 0x2B23, 0, 0, 0, 0, 0x2A77, 0, 0, - 0, 0x2B3E, 0x2B3D, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_CB[] = { - 0, 0, 0, 0, 0, 0, 0, 0xA230, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0xA22F, 0xA232, 0xA236, 0xA235, 0, 0xA233, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_CB_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0x2A31, - 0x2B53, 0, 0, 0, 0x2B54, 0, 0, 0, - 0x2B55, 0x2B56, 0, 0, 0, 0, 0, 0, - 0x2A22, 0x2A58, 0xA236, 0x2A2D, 0, 0x2A36, 0x2B71, 0, - 0, 0, 0, 0, 0, 0x2B60, 0x2B61, 0x2B62, - 0x2B63, 0x2B64, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_CC_x0213[] = { - 0x2B5C, 0x2B5A, 0x2B5F, 0x2B7D, 0x2B5B, 0, 0x2B57, 0, - 0x2B6D, 0, 0, 0x2B59, 0x2B5E, 0, 0, 0x2B5D, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x2B78, 0x2B79, 0x2B7E, 0, 0x2B6A, 0x2B76, 0x2B77, 0x2B6B, - 0x2B6C, 0, 0, 0, 0x2B72, 0x2B67, 0, 0, - 0, 0x2B6F, 0x2B7A, 0, 0x2B68, 0, 0, 0x2B70, - 0x2B73, 0, 0, 0, 0x2B75, 0, 0, 0, - 0, 0x2B69, 0x2B7B, 0x2B7C, 0x2B74, 0x2B6E, 0, 0, -}; -static const unsigned short utf8_to_euc_CD_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0x2B52, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_CE[] = { - 0, 0, 0, 0, 0xA238, 0xA239, 0xA661, 0, - 0xA662, 0xA663, 0xA664, 0, 0xA667, 0, 0xA669, 0xA66C, - 0xA676, 0x2621, 0x2622, 0x2623, 0x2624, 0x2625, 0x2626, 0x2627, - 0x2628, 0x2629, 0x262A, 0x262B, 0x262C, 0x262D, 0x262E, 0x262F, - 0x2630, 0x2631, 0, 0x2632, 0x2633, 0x2634, 0x2635, 0x2636, - 0x2637, 0x2638, 0xA665, 0xA66A, 0xA671, 0xA672, 0xA673, 0xA674, - 0xA67B, 0x2641, 0x2642, 0x2643, 0x2644, 0x2645, 0x2646, 0x2647, - 0x2648, 0x2649, 0x264A, 0x264B, 0x264C, 0x264D, 0x264E, 0x264F, -}; -static const unsigned short utf8_to_euc_CF[] = { - 0x2650, 0x2651, 0xA678, 0x2652, 0x2653, 0x2654, 0x2655, 0x2656, - 0x2657, 0x2658, 0xA675, 0xA67A, 0xA677, 0xA679, 0xA67C, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_CF_x0213[] = { - 0x2650, 0x2651, 0x2659, 0x2652, 0x2653, 0x2654, 0x2655, 0x2656, - 0x2657, 0x2658, 0xA675, 0xA67A, 0xA677, 0xA679, 0xA67C, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_D0[] = { - 0, 0x2727, 0xA742, 0xA743, 0xA744, 0xA745, 0xA746, 0xA747, - 0xA748, 0xA749, 0xA74A, 0xA74B, 0xA74C, 0, 0xA74D, 0xA74E, - 0x2721, 0x2722, 0x2723, 0x2724, 0x2725, 0x2726, 0x2728, 0x2729, - 0x272A, 0x272B, 0x272C, 0x272D, 0x272E, 0x272F, 0x2730, 0x2731, - 0x2732, 0x2733, 0x2734, 0x2735, 0x2736, 0x2737, 0x2738, 0x2739, - 0x273A, 0x273B, 0x273C, 0x273D, 0x273E, 0x273F, 0x2740, 0x2741, - 0x2751, 0x2752, 0x2753, 0x2754, 0x2755, 0x2756, 0x2758, 0x2759, - 0x275A, 0x275B, 0x275C, 0x275D, 0x275E, 0x275F, 0x2760, 0x2761, -}; -static const unsigned short utf8_to_euc_D1[] = { - 0x2762, 0x2763, 0x2764, 0x2765, 0x2766, 0x2767, 0x2768, 0x2769, - 0x276A, 0x276B, 0x276C, 0x276D, 0x276E, 0x276F, 0x2770, 0x2771, - 0, 0x2757, 0xA772, 0xA773, 0xA774, 0xA775, 0xA776, 0xA777, - 0xA778, 0xA779, 0xA77A, 0xA77B, 0xA77C, 0, 0xA77D, 0xA77E, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E1B8_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0x2872, 0x2873, -}; -static const unsigned short utf8_to_euc_E1BD_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x2B46, 0x2B47, 0x2B50, 0x2B51, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E280[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x213E, 0, 0, 0, 0x213D, 0x213D, 0x2142, 0, - 0x2146, 0x2147, 0, 0, 0x2148, 0x2149, 0, 0, - 0x2277, 0x2278, 0, 0, 0, 0x2145, 0x2144, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x2273, 0, 0x216C, 0x216D, 0, 0, 0, 0, - 0, 0, 0, 0x2228, 0, 0, 0x2131, 0, -}; -static const unsigned short utf8_to_euc_E280_ms[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x213E, 0, 0, 0, 0x213D, 0x213D, 0x2142, 0, - 0x2146, 0x2147, 0, 0, 0x2148, 0x2149, 0, 0, - 0x2277, 0x2278, 0, 0, 0, 0x2145, 0x2144, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x2273, 0, 0x216C, 0x216D, 0, 0, 0, 0, - 0, 0, 0, 0x2228, 0, 0, 0x7E, 0, -}; -static const unsigned short utf8_to_euc_E280_932[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x213E, 0, 0, 0, 0, 0x213D, 0, 0, - 0x2146, 0x2147, 0, 0, 0x2148, 0x2149, 0, 0, - 0x2277, 0x2278, 0, 0, 0, 0x2145, 0x2144, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x2273, 0, 0x216C, 0x216D, 0, 0, 0, 0, - 0, 0, 0, 0x2228, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E280_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x213E, 0, 0, 0x237C, 0x213D, 0x213D, 0x2142, 0, - 0x2146, 0x2147, 0, 0, 0x2148, 0x2149, 0, 0, - 0x2277, 0x2278, 0x2340, 0, 0, 0x2145, 0x2144, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x2273, 0, 0x216C, 0x216D, 0, 0, 0, 0, - 0, 0, 0, 0x2228, 0x286B, 0, 0x2131, 0x2B58, -}; -static const unsigned short utf8_to_euc_E281_x0213[] = { - 0, 0, 0x2C7E, 0, 0, 0, 0, 0x286C, - 0x286D, 0x286E, 0, 0, 0, 0, 0, 0, - 0, 0x2C7D, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E282_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0x2921, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E284[] = { - 0, 0, 0, 0x216E, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0x2D62, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0x2D64, 0xA26F, 0, 0, 0, 0, 0, - 0, 0, 0, 0x2272, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E284_mac[] = { - 0, 0, 0, 0x216E, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0x2B7B, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0x2B7D, 0x00FE, 0, 0, 0, 0, 0, - 0, 0, 0, 0x2272, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E284_x0213[] = { - 0, 0, 0, 0x216E, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0x235D, - 0, 0, 0, 0x235F, 0, 0, 0x2D62, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0x2D64, 0xA26F, 0, 0, 0, 0, 0x2360, - 0, 0, 0, 0x2272, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0x235C, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E285[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x2D35, 0x2D36, 0x2D37, 0x2D38, 0x2D39, 0x2D3A, 0x2D3B, 0x2D3C, - 0x2D3D, 0x2D3E, 0, 0, 0, 0, 0, 0, - 0xF373, 0xF374, 0xF375, 0xF376, 0xF377, 0xF378, 0xF379, 0xF37A, - 0xF37B, 0xF37C, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E285_mac[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x2A21, 0x2A22, 0x2A23, 0x2A24, 0x2A25, 0x2A26, 0x2A27, 0x2A28, - 0x2A29, 0x2A2A, 0, 0, 0, 0, 0, 0, - 0x2A35, 0x2A36, 0x2A37, 0x2A38, 0x2A39, 0x2A3A, 0x2A3B, 0x2A3C, - 0x2A3D, 0x2A3E, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E285_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0x2778, 0x2779, 0x277A, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x2D35, 0x2D36, 0x2D37, 0x2D38, 0x2D39, 0x2D3A, 0x2D3B, 0x2D3C, - 0x2D3D, 0x2D3E, 0x2D3F, 0x2D57, 0, 0, 0, 0, - 0x2C35, 0x2C36, 0x2C37, 0x2C38, 0x2C39, 0x2C3A, 0x2C3B, 0x2C3C, - 0x2C3D, 0x2C3E, 0x2C3F, 0x2C40, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E286[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x222B, 0x222C, 0x222A, 0x222D, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E286_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x222B, 0x222C, 0x222A, 0x222D, 0x2271, 0, 0x2327, 0x2325, - 0x2326, 0x2328, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E287[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0x224D, 0, 0x224E, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E287_x0213[] = { - 0, 0, 0, 0, 0x2329, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0x224D, 0, 0x224E, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0x232B, 0x232C, - 0x232A, 0x232D, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E288[] = { - 0x224F, 0, 0x225F, 0x2250, 0, 0, 0, 0x2260, - 0x223A, 0, 0, 0x223B, 0, 0, 0, 0, - 0, 0x2D74, 0x215D, 0, 0, 0, 0, 0, - 0, 0, 0x2265, 0, 0, 0x2267, 0x2167, 0x2D78, - 0x225C, 0, 0, 0, 0, 0x2142, 0, 0x224A, - 0x224B, 0x2241, 0x2240, 0x2269, 0x226A, 0, 0x2D73, 0, - 0, 0, 0, 0, 0x2168, 0x2268, 0, 0, - 0, 0, 0, 0, 0, 0x2266, 0, 0, -}; -static const unsigned short utf8_to_euc_E288_932[] = { - 0x224F, 0, 0x225F, 0x2250, 0, 0, 0, 0x2260, - 0x223A, 0, 0, 0x223B, 0, 0, 0, 0, - 0, 0x2D74, 0, 0, 0, 0, 0, 0, - 0, 0, 0x2265, 0, 0, 0x2267, 0x2167, 0x2D78, - 0x225C, 0, 0, 0, 0, 0x2142, 0, 0x224A, - 0x224B, 0x2241, 0x2240, 0x2269, 0x226A, 0, 0x2D73, 0, - 0, 0, 0, 0, 0x2168, 0x2268, 0, 0, - 0, 0, 0, 0, 0, 0x2266, 0, 0, -}; -static const unsigned short utf8_to_euc_E288_mac[] = { - 0x224F, 0, 0x225F, 0x2250, 0, 0, 0, 0x2260, - 0x223A, 0, 0, 0x223B, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0x2265, 0, 0, 0x2267, 0x2167, 0x2F22, - 0x225C, 0, 0, 0, 0, 0x2142, 0, 0x224A, - 0x224B, 0x2241, 0x2240, 0x2269, 0x226A, 0, 0x2F21, 0, - 0, 0, 0, 0, 0x2168, 0x2268, 0, 0, - 0, 0, 0, 0, 0, 0x2266, 0, 0, -}; -static const unsigned short utf8_to_euc_E288_x0213[] = { - 0x224F, 0, 0x225F, 0x2250, 0, 0x2247, 0, 0x2260, - 0x223A, 0x2246, 0, 0x223B, 0, 0, 0, 0, - 0, 0x2D74, 0x215D, 0x235B, 0, 0, 0, 0, - 0, 0, 0x2265, 0, 0, 0x2267, 0x2167, 0x2D78, - 0x225C, 0, 0, 0, 0, 0x2254, 0x2255, 0x224A, - 0x224B, 0x2241, 0x2240, 0x2269, 0x226A, 0, 0x2D73, 0, - 0, 0, 0, 0, 0x2168, 0x2268, 0, 0, - 0, 0, 0, 0, 0, 0x2266, 0, 0, -}; -static const unsigned short utf8_to_euc_E289[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0x2262, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x2162, 0x2261, 0, 0, 0, 0, 0x2165, 0x2166, - 0, 0, 0x2263, 0x2264, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E289_x0213[] = { - 0, 0, 0, 0x226C, 0, 0x226D, 0, 0, - 0x226E, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0x2262, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x2162, 0x2261, 0x226B, 0, 0, 0, 0x2165, 0x2166, - 0, 0, 0x2263, 0x2264, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0x226F, 0x2270, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E28A[] = { - 0, 0, 0x223E, 0x223F, 0, 0, 0x223C, 0x223D, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0x225D, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0x2D79, -}; -static const unsigned short utf8_to_euc_E28A_mac[] = { - 0, 0, 0x223E, 0x223F, 0, 0, 0x223C, 0x223D, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0x225D, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0x2F23, -}; -static const unsigned short utf8_to_euc_E28A_x0213[] = { - 0, 0, 0x223E, 0x223F, 0x2242, 0x2243, 0x223C, 0x223D, - 0, 0, 0x2244, 0x2245, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0x2251, 0x2252, 0x2253, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0x225D, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0x2D79, -}; -static const unsigned short utf8_to_euc_E28B_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0x2776, 0x2777, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E28C[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0x225E, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E28C_x0213[] = { - 0, 0, 0, 0, 0, 0x2248, 0x2249, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0x225E, 0, 0, 0, 0, 0, - 0x277C, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E28E_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0x2742, 0x2743, -}; -static const unsigned short utf8_to_euc_E28F_x0213[] = { - 0x2744, 0x2745, 0x2746, 0x2747, 0x2748, 0x2749, 0x274A, 0x274B, - 0x274C, 0x274D, 0x274E, 0x274F, 0x2750, 0, 0x277E, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E290_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0x277D, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E291[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x2D21, 0x2D22, 0x2D23, 0x2D24, 0x2D25, 0x2D26, 0x2D27, 0x2D28, - 0x2D29, 0x2D2A, 0x2D2B, 0x2D2C, 0x2D2D, 0x2D2E, 0x2D2F, 0x2D30, - 0x2D31, 0x2D32, 0x2D33, 0x2D34, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E291_mac[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x2921, 0x2922, 0x2923, 0x2924, 0x2925, 0x2926, 0x2927, 0x2928, - 0x2929, 0x292A, 0x292B, 0x292C, 0x292D, 0x292E, 0x292F, 0x2930, - 0x2931, 0x2932, 0x2933, 0x2934, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E293_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x2C41, 0x2C42, 0x2C43, 0x2C44, 0x2C45, 0x2C46, 0x2C47, 0x2C48, - 0x2C49, 0x2C4A, 0x2C4B, 0x2C4C, 0x2C4D, 0x2C4E, 0x2C4F, 0x2C50, - 0x2C51, 0x2C52, 0x2C53, 0x2C54, 0x2C55, 0x2C56, 0x2C57, 0x2C58, - 0x2C59, 0x2C5A, 0, 0x2C2B, 0x2C2C, 0x2C2D, 0x2C2E, 0x2C2F, - 0x2C30, 0x2C31, 0x2C32, 0x2C33, 0x2C34, 0x265A, 0x265B, 0x265C, - 0x265D, 0x265E, 0x265F, 0x2660, 0x2661, 0x2662, 0x2663, 0, -}; -static const unsigned short utf8_to_euc_E294[] = { - 0x2821, 0x282C, 0x2822, 0x282D, 0, 0, 0, 0, - 0, 0, 0, 0, 0x2823, 0, 0, 0x282E, - 0x2824, 0, 0, 0x282F, 0x2826, 0, 0, 0x2831, - 0x2825, 0, 0, 0x2830, 0x2827, 0x283C, 0, 0, - 0x2837, 0, 0, 0x2832, 0x2829, 0x283E, 0, 0, - 0x2839, 0, 0, 0x2834, 0x2828, 0, 0, 0x2838, - 0x283D, 0, 0, 0x2833, 0x282A, 0, 0, 0x283A, - 0x283F, 0, 0, 0x2835, 0x282B, 0, 0, 0x283B, -}; -static const unsigned short utf8_to_euc_E295[] = { - 0, 0, 0x2840, 0, 0, 0, 0, 0, - 0, 0, 0, 0x2836, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E296[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x2223, 0x2222, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0x2225, 0x2224, 0, 0, 0, 0, - 0, 0, 0, 0, 0x2227, 0x2226, 0, 0, -}; -static const unsigned short utf8_to_euc_E296_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x2223, 0x2222, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0x266D, 0x2225, 0x2224, 0, 0, 0x2322, 0x2321, - 0, 0, 0, 0, 0x2227, 0x2226, 0, 0, -}; -static const unsigned short utf8_to_euc_E297[] = { - 0, 0, 0, 0, 0, 0, 0x2221, 0x217E, - 0, 0, 0, 0x217B, 0, 0, 0x217D, 0x217C, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0x227E, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E297_x0213[] = { - 0x2324, 0x2323, 0, 0, 0, 0, 0x2221, 0x217E, - 0, 0x233B, 0, 0x217B, 0, 0, 0x217D, 0x217C, - 0x2867, 0x2868, 0x2869, 0x286A, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0x233F, 0, - 0, 0, 0, 0, 0, 0, 0, 0x227E, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E298[] = { - 0, 0, 0, 0, 0, 0x217A, 0x2179, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E298_x0213[] = { - 0x2668, 0x2669, 0x266A, 0x266B, 0, 0x217A, 0x2179, 0, - 0, 0, 0, 0, 0, 0, 0x2667, 0, - 0, 0, 0, 0, 0, 0, 0x2664, 0x2665, - 0, 0, 0, 0, 0, 0, 0x2D7E, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E299[] = { - 0x216A, 0, 0x2169, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0x2276, 0, 0, 0x2275, 0, 0x2274, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E299_x0213[] = { - 0x216A, 0, 0x2169, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x263A, 0x263D, 0x263B, 0x2640, 0x2639, 0x263E, 0x263C, 0x263F, - 0x266C, 0x227D, 0x2276, 0x227B, 0x227C, 0x2275, 0x227A, 0x2274, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E29C_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0x277B, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E29D_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0x2D7D, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0x2C21, 0x2C22, - 0x2C23, 0x2C24, 0x2C25, 0x2C26, 0x2C27, 0x2C28, 0x2C29, 0x2C2A, -}; -static const unsigned short utf8_to_euc_E2A4_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0x232E, 0x232F, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E2A6_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0x233A, -}; -static const unsigned short utf8_to_euc_E2A7_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0x237D, 0x237E, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E380[] = { - 0x2121, 0x2122, 0x2123, 0x2137, 0, 0x2139, 0x213A, 0x213B, - 0x2152, 0x2153, 0x2154, 0x2155, 0x2156, 0x2157, 0x2158, 0x2159, - 0x215A, 0x215B, 0x2229, 0x222E, 0x214C, 0x214D, 0, 0, - 0, 0, 0, 0, 0x2141, 0x2D60, 0, 0x2D61, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E380_932[] = { - 0x2121, 0x2122, 0x2123, 0x2137, 0, 0x2139, 0x213A, 0x213B, - 0x2152, 0x2153, 0x2154, 0x2155, 0x2156, 0x2157, 0x2158, 0x2159, - 0x215A, 0x215B, 0x2229, 0x222E, 0x214C, 0x214D, 0, 0, - 0, 0, 0, 0, 0, 0x2D60, 0, 0x2D61, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E380_x0213[] = { - 0x2121, 0x2122, 0x2123, 0x2137, 0, 0x2139, 0x213A, 0x213B, - 0x2152, 0x2153, 0x2154, 0x2155, 0x2156, 0x2157, 0x2158, 0x2159, - 0x215A, 0x215B, 0x2229, 0x222E, 0x214C, 0x214D, 0x225A, 0x225B, - 0x2258, 0x2259, 0, 0, 0x2141, 0x2D60, 0, 0x2D61, - 0x2666, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0x2233, 0x2234, 0x2235, 0, 0, - 0, 0, 0, 0x2236, 0x2237, 0x233C, 0, 0, -}; -static const unsigned short utf8_to_euc_E381[] = { - 0, 0x2421, 0x2422, 0x2423, 0x2424, 0x2425, 0x2426, 0x2427, - 0x2428, 0x2429, 0x242A, 0x242B, 0x242C, 0x242D, 0x242E, 0x242F, - 0x2430, 0x2431, 0x2432, 0x2433, 0x2434, 0x2435, 0x2436, 0x2437, - 0x2438, 0x2439, 0x243A, 0x243B, 0x243C, 0x243D, 0x243E, 0x243F, - 0x2440, 0x2441, 0x2442, 0x2443, 0x2444, 0x2445, 0x2446, 0x2447, - 0x2448, 0x2449, 0x244A, 0x244B, 0x244C, 0x244D, 0x244E, 0x244F, - 0x2450, 0x2451, 0x2452, 0x2453, 0x2454, 0x2455, 0x2456, 0x2457, - 0x2458, 0x2459, 0x245A, 0x245B, 0x245C, 0x245D, 0x245E, 0x245F, -}; -static const unsigned short utf8_to_euc_E382[] = { - 0x2460, 0x2461, 0x2462, 0x2463, 0x2464, 0x2465, 0x2466, 0x2467, - 0x2468, 0x2469, 0x246A, 0x246B, 0x246C, 0x246D, 0x246E, 0x246F, - 0x2470, 0x2471, 0x2472, 0x2473, 0, 0, 0, 0, - 0, 0, 0, 0x212B, 0x212C, 0x2135, 0x2136, 0, - 0, 0x2521, 0x2522, 0x2523, 0x2524, 0x2525, 0x2526, 0x2527, - 0x2528, 0x2529, 0x252A, 0x252B, 0x252C, 0x252D, 0x252E, 0x252F, - 0x2530, 0x2531, 0x2532, 0x2533, 0x2534, 0x2535, 0x2536, 0x2537, - 0x2538, 0x2539, 0x253A, 0x253B, 0x253C, 0x253D, 0x253E, 0x253F, -}; -static const unsigned short utf8_to_euc_E382_932[] = { - 0x2460, 0x2461, 0x2462, 0x2463, 0x2464, 0x2465, 0x2466, 0x2467, - 0x2468, 0x2469, 0x246A, 0x246B, 0x246C, 0x246D, 0x246E, 0x246F, - 0x2470, 0x2471, 0x2472, 0x2473, 0x2574, 0, 0, 0, - 0, 0, 0, 0x212B, 0x212C, 0x2135, 0x2136, 0, - 0, 0x2521, 0x2522, 0x2523, 0x2524, 0x2525, 0x2526, 0x2527, - 0x2528, 0x2529, 0x252A, 0x252B, 0x252C, 0x252D, 0x252E, 0x252F, - 0x2530, 0x2531, 0x2532, 0x2533, 0x2534, 0x2535, 0x2536, 0x2537, - 0x2538, 0x2539, 0x253A, 0x253B, 0x253C, 0x253D, 0x253E, 0x253F, -}; -static const unsigned short utf8_to_euc_E382_x0213[] = { - 0x2460, 0x2461, 0x2462, 0x2463, 0x2464, 0x2465, 0x2466, 0x2467, - 0x2468, 0x2469, 0x246A, 0x246B, 0x246C, 0x246D, 0x246E, 0x246F, - 0x2470, 0x2471, 0x2472, 0x2473, 0x2474, 0x2475, 0x2476, 0, - 0, 0, 0, 0x212B, 0x212C, 0x2135, 0x2136, 0x2239, - 0x237B, 0x2521, 0x2522, 0x2523, 0x2524, 0x2525, 0x2526, 0x2527, - 0x2528, 0x2529, 0x252A, 0x252B, 0x252C, 0x252D, 0x252E, 0x252F, - 0x2530, 0x2531, 0x2532, 0x2533, 0x2534, 0x2535, 0x2536, 0x2537, - 0x2538, 0x2539, 0x253A, 0x253B, 0x253C, 0x253D, 0x253E, 0x253F, -}; -static const unsigned short utf8_to_euc_E383[] = { - 0x2540, 0x2541, 0x2542, 0x2543, 0x2544, 0x2545, 0x2546, 0x2547, - 0x2548, 0x2549, 0x254A, 0x254B, 0x254C, 0x254D, 0x254E, 0x254F, - 0x2550, 0x2551, 0x2552, 0x2553, 0x2554, 0x2555, 0x2556, 0x2557, - 0x2558, 0x2559, 0x255A, 0x255B, 0x255C, 0x255D, 0x255E, 0x255F, - 0x2560, 0x2561, 0x2562, 0x2563, 0x2564, 0x2565, 0x2566, 0x2567, - 0x2568, 0x2569, 0x256A, 0x256B, 0x256C, 0x256D, 0x256E, 0x256F, - 0x2570, 0x2571, 0x2572, 0x2573, 0x2574, 0x2575, 0x2576, 0, - 0, 0, 0, 0x2126, 0x213C, 0x2133, 0x2134, 0, -}; -static const unsigned short utf8_to_euc_E383_x0213[] = { - 0x2540, 0x2541, 0x2542, 0x2543, 0x2544, 0x2545, 0x2546, 0x2547, - 0x2548, 0x2549, 0x254A, 0x254B, 0x254C, 0x254D, 0x254E, 0x254F, - 0x2550, 0x2551, 0x2552, 0x2553, 0x2554, 0x2555, 0x2556, 0x2557, - 0x2558, 0x2559, 0x255A, 0x255B, 0x255C, 0x255D, 0x255E, 0x255F, - 0x2560, 0x2561, 0x2562, 0x2563, 0x2564, 0x2565, 0x2566, 0x2567, - 0x2568, 0x2569, 0x256A, 0x256B, 0x256C, 0x256D, 0x256E, 0x256F, - 0x2570, 0x2571, 0x2572, 0x2573, 0x2574, 0x2575, 0x2576, 0x2772, - 0x2773, 0x2774, 0x2775, 0x2126, 0x213C, 0x2133, 0x2134, 0x2238, -}; -static const unsigned short utf8_to_euc_E387_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x266E, 0x266F, 0x2670, 0x2671, 0x2672, 0x2673, 0x2674, 0x2675, - 0x2676, 0x2677, 0x2679, 0x267A, 0x267B, 0x267C, 0x267D, 0x267E, -}; -static const unsigned short utf8_to_euc_E388[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0x2D6A, 0x2D6B, 0, 0, 0, 0, 0, - 0, 0x2D6C, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E388_mac[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0x2D2E, 0x2D31, 0, 0, 0, 0, 0, - 0, 0x2D2C, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E389_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0x2841, 0x2842, 0x2843, 0x2844, 0x2845, 0x2846, 0x2847, - 0x2848, 0x2849, 0x284A, 0x284B, 0x284C, 0x284D, 0x284E, 0x284F, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E38A[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0x2D65, 0x2D66, 0x2D67, 0x2D68, - 0x2D69, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E38A_mac[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0x2D73, 0x2D74, 0x2D75, 0x2D76, - 0x2D77, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E38A_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0x2D65, 0x2D66, 0x2D67, 0x2D68, - 0x2D69, 0, 0, 0, 0, 0, 0, 0, - 0, 0x2850, 0x2851, 0x2852, 0x2853, 0x2854, 0x2855, 0x2856, - 0x2857, 0x2858, 0x2859, 0x285A, 0x285B, 0x285C, 0x285D, 0x285E, -}; -static const unsigned short utf8_to_euc_E38B_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x2C5B, 0x2C5C, 0x2C5D, 0x2C5E, 0x2C5F, 0x2C60, 0x2C61, 0x2C62, - 0x2C63, 0x2C64, 0x2C65, 0x2C66, 0x2C67, 0x2C68, 0x2C69, 0x2C6A, - 0x2C6B, 0x2C6C, 0x2C6D, 0x2C6E, 0, 0x2C71, 0, 0, - 0, 0x2C70, 0, 0, 0x2C73, 0x2C72, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0x2C6F, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E38C[] = { - 0, 0, 0, 0x2D46, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0x2D4A, 0, 0, - 0, 0, 0, 0, 0x2D41, 0, 0, 0, - 0x2D44, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0x2D42, 0x2D4C, 0, 0, 0x2D4B, 0x2D45, - 0, 0, 0, 0x2D4D, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0x2D47, 0, - 0, 0, 0, 0x2D4F, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E38C_mac[] = { - 0, 0, 0, 0x2E29, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0x2E32, 0, 0, - 0, 0, 0, 0, 0x2E24, 0, 0, 0, - 0x2E2B, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0x2E22, 0x2E34, 0, 0, 0x2E35, 0x2E2D, - 0, 0, 0, 0x2E37, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0x2E2A, 0, - 0, 0, 0, 0x2E36, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E38D[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0x2D40, 0x2D4E, 0, 0, 0x2D43, 0, 0, - 0, 0x2D48, 0, 0, 0, 0, 0, 0x2D49, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0x2D5F, 0x2D6F, 0x2D6E, 0x2D6D, 0, -}; -static const unsigned short utf8_to_euc_E38D_mac[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0x2E21, 0x2E2F, 0, 0, 0x2E23, 0, 0, - 0, 0x2E2E, 0, 0, 0, 0, 0, 0x2E31, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0x2E6A, 0x2E69, 0x2E68, 0x2E67, 0, -}; -static const unsigned short utf8_to_euc_E38E[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0x2D53, 0x2D54, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0x2D50, 0x2D51, 0x2D52, 0, - 0, 0x2D56, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E38E_mac[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0x2B2B, 0x2B2D, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0x2B21, 0x2B23, 0x2B29, 0, - 0, 0x2B27, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E38F[] = { - 0, 0, 0, 0, 0x2D55, 0, 0, 0, - 0, 0, 0, 0, 0, 0x2D63, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E38F_mac[] = { - 0, 0, 0, 0, 0x2B2E, 0, 0, 0, - 0, 0, 0, 0, 0, 0x2B7C, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E38F_x0213[] = { - 0, 0, 0, 0, 0x2D55, 0, 0, 0, - 0, 0, 0, 0x235E, 0, 0x2D63, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E390_x0213[] = { - 0, 0, 0x2E23, 0, 0, 0, 0xA12D, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0xA132, 0, 0xA133, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E391_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0xA15E, 0, 0xA156, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E392_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0xA17E, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0x2E53, 0, 0, - 0, 0, 0, 0, 0xA32B, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E393_x0213[] = { - 0, 0xF468, 0, 0, 0, 0, 0, 0xA32F, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0x2E5B, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E394_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0xA348, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E395_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0xA35D, 0xA35E, 0, - 0, 0, 0, 0xA361, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0xA367, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E396_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0xA423, 0, - 0xA426, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E397_x0213[] = { - 0, 0, 0, 0, 0, 0xA42F, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0xA438, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0xA442, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E398_x0213[] = { - 0, 0, 0, 0, 0, 0xA44A, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E399_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0xA479, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E39A_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0xA53F, 0, 0, 0, 0, 0xA543, 0, - 0, 0xA541, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E39B_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0xA557, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E39D_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0xA823, 0xA825, 0, 0, 0, 0, 0, - 0, 0, 0, 0xA829, 0xA828, 0, 0, 0, - 0, 0, 0, 0, 0, 0xA82C, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E39E_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0x4F5F, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E39F_x0213[] = { - 0, 0xA83E, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0x4F6F, 0, 0, 0, 0, 0, - 0xA856, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0xA859, 0, 0, 0, - 0, 0, 0, 0, 0, 0xA85C, 0, 0, -}; -static const unsigned short utf8_to_euc_E3A0_x0213[] = { - 0xA85E, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0xA86F, - 0, 0, 0, 0, 0, 0, 0xA871, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E3A1_x0213[] = { - 0xA874, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0xA879, 0, 0, 0, - 0, 0xA87B, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E3A3_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0xAC3B, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E3A4_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0xAC46, - 0, 0, 0xAC4A, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E3A5_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0xAC60, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E3A9_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0xAD5B, 0, - 0, 0, 0, 0xAD5F, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E3AB_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0xAD71, 0xAE36, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0xAD7C, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E3AC_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0xAE2E, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0xAE32, 0, 0xAE34, 0, 0, 0, - 0, 0, 0x7549, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E3AD_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0xAE6D, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0xAE65, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E3AE_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0xAF28, - 0xAF29, 0, 0, 0, 0, 0xAF2C, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0xAF34, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0x757E, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E3AF_x0213[] = { - 0, 0, 0, 0x7621, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0xAF48, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0xAF5D, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E3B0_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0x763A, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0xAF77, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E3B3_x0213[] = { - 0, 0, 0, 0xEE3B, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0xEE42, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E3B4_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0xEE71, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0xEE7E, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E3B5_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0xEF40, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E3B6_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0xEF54, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E3B7_x0213[] = { - 0xEF70, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0xEF77, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E3B8_x0213[] = { - 0, 0, 0, 0, 0, 0xF028, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0x7766, -}; -static const unsigned short utf8_to_euc_E3B9_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0xF03F, 0, 0, 0, 0, 0, 0xF041, 0, - 0xF042, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E3BA_x0213[] = { - 0, 0, 0, 0xF049, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0xF050, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E3BD_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0xF134, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0x784D, 0, 0, 0xF146, 0, 0xF148, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E3BE_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0xF15C, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E3BF_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0xF167, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0xF16C, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E480_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0xF222, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E481_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0xF22D, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E482_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0xF239, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E484_x0213[] = { - 0, 0, 0, 0, 0, 0xF264, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E485_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0xF274, 0, 0, 0, 0, 0, 0, 0xF277, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0xF27D, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E486_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0xF333, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0xF337, -}; -static const unsigned short utf8_to_euc_E487_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0xF347, 0, - 0, 0, 0, 0, 0, 0, 0xF34B, 0, - 0, 0, 0, 0xF348, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E488_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0xF353, - 0, 0, 0, 0, 0, 0, 0xF357, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E489_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0x796D, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E48B_x0213[] = { - 0, 0, 0, 0, 0, 0, 0xF42B, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0xF436, 0, - 0, 0, 0, 0, 0, 0xF43B, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E48C_x0213[] = { - 0, 0, 0xF44E, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0xF45D, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E48D_x0213[] = { - 0, 0, 0, 0xF461, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E48F_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0xF53E, 0, - 0xF542, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E490_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0xF548, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0xF54A, - 0, 0, 0, 0, 0xF54C, 0, 0, 0, - 0, 0, 0xF54F, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E491_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0x7A59, 0, 0, 0, 0, - 0, 0, 0, 0x7A5A, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0xF56C, 0, - 0, 0, 0xF56E, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E492_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0xF577, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0xF635, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0xF632, 0, -}; -static const unsigned short utf8_to_euc_E493_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0xF634, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E494_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0xF659, 0, 0, 0, 0, 0xF654, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0xF66D, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E495_x0213[] = { - 0, 0, 0, 0xF66E, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E496_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0x7B51, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0xF74F, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E497_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0xF76C, 0, 0, - 0, 0, 0x7B60, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E498_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0xF824, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E499_x0213[] = { - 0, 0xF83A, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0xF843, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E49A_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0xF84E, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0xF853, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E49C_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0xF86B, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E49D_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0xF929, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E49F_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0xF93F, 0, 0, -}; -static const unsigned short utf8_to_euc_E4A0_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0xF949, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E4A1_x0213[] = { - 0, 0, 0, 0, 0x7C4B, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0xF95C, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E4A2_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0xFA27, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E4A6_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x7D58, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E4A7_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0xFB6A, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0xFB70, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E4A8_x0213[] = { - 0, 0, 0, 0, 0xFB75, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0xFB78, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E4AA_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0xFC37, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E4AC_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0xFC55, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E4AF_x0213[] = { - 0, 0, 0xFD26, 0, 0, 0, 0, 0, - 0, 0, 0xFD28, 0, 0, 0, 0, 0, - 0, 0, 0xFD2A, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0xFD31, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E4B0_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0x7E3E, - 0, 0, 0, 0, 0, 0, 0, 0, - 0xFD3F, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E4B3_x0213[] = { - 0, 0, 0, 0, 0xFE2A, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0xFE2D, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E4B4_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0xFE4B, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E4B5_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0xFE60, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E4B8[] = { - 0x306C, 0x437A, 0xB021, 0x3C37, 0xB022, 0xB023, 0, 0x4B7C, - 0x3E66, 0x3B30, 0x3E65, 0x323C, 0xB024, 0x4954, 0x4D3F, 0, - 0x5022, 0x312F, 0xB025, 0, 0x336E, 0x5023, 0x4024, 0x5242, - 0x3556, 0x4A3A, 0, 0, 0, 0, 0x3E67, 0xB026, - 0, 0x4E3E, 0, 0xB027, 0xB028, 0, 0x4A42, 0, - 0xB029, 0, 0x5024, 0xB02A, 0, 0x4366, 0xB02B, 0xB02C, - 0xB02D, 0x5025, 0x367A, 0, 0, 0xB02E, 0x5026, 0, - 0x345D, 0x4330, 0, 0x3C67, 0x5027, 0, 0, 0x5028, -}; -static const unsigned short utf8_to_euc_E4B8_x0213[] = { - 0x306C, 0x437A, 0xA122, 0x3C37, 0xB022, 0xB023, 0, 0x4B7C, - 0x3E66, 0x3B30, 0x3E65, 0x323C, 0xB024, 0x4954, 0x4D3F, 0xA123, - 0x5022, 0x312F, 0xA124, 0, 0x336E, 0x5023, 0x4024, 0x5242, - 0x3556, 0x4A3A, 0, 0, 0, 0, 0x3E67, 0xB026, - 0, 0x4E3E, 0, 0xB027, 0xB028, 0, 0x4A42, 0, - 0x2E24, 0xA125, 0x5024, 0xA126, 0xF02E, 0x4366, 0xA127, 0x2E25, - 0x2E26, 0x5025, 0x367A, 0, 0, 0xB02E, 0x5026, 0, - 0x345D, 0x4330, 0, 0x3C67, 0x5027, 0, 0, 0x5028, -}; -static const unsigned short utf8_to_euc_E4B9[] = { - 0xB02F, 0xB030, 0x5029, 0x4735, 0xB031, 0x3557, 0, 0xB032, - 0, 0, 0, 0x4737, 0, 0x4663, 0x3843, 0x4B33, - 0, 0xB033, 0, 0, 0, 0x6949, 0x502A, 0x3E68, - 0x502B, 0x3235, 0xB034, 0, 0xB035, 0x3665, 0x3870, 0x4C69, - 0, 0, 0x5626, 0xB036, 0, 0, 0, 0, - 0xB037, 0xB038, 0, 0, 0, 0, 0, 0, - 0, 0x4D70, 0, 0x467D, 0xB039, 0xB03A, 0, 0, - 0, 0xB03B, 0, 0, 0, 0, 0x3425, 0xB03C, -}; -static const unsigned short utf8_to_euc_E4B9_x0213[] = { - 0xA128, 0xB030, 0x5029, 0x4735, 0xB031, 0x3557, 0, 0xA129, - 0xA12A, 0, 0, 0x4737, 0, 0x4663, 0x3843, 0x4B33, - 0, 0xA12C, 0, 0, 0, 0x6949, 0x502A, 0x3E68, - 0x502B, 0x3235, 0xA12F, 0, 0xB035, 0x3665, 0x3870, 0x4C69, - 0, 0, 0x5626, 0xB036, 0, 0, 0, 0, - 0xB037, 0xA130, 0, 0, 0, 0, 0, 0, - 0, 0x4D70, 0, 0x467D, 0xB039, 0xB03A, 0, 0, - 0, 0xB03B, 0, 0, 0, 0, 0x3425, 0xB03C, -}; -static const unsigned short utf8_to_euc_E4BA[] = { - 0x3535, 0, 0x502C, 0, 0, 0x502D, 0x4E3B, 0, - 0x4D3D, 0x4168, 0x502F, 0x3B76, 0x4673, 0xB03D, 0x5032, 0, - 0, 0x313E, 0x385F, 0, 0x385E, 0x3066, 0xB03E, 0xB03F, - 0x4F4B, 0x4F4A, 0, 0x3A33, 0x3021, 0xB040, 0x5033, 0x5034, - 0x5035, 0x4B34, 0x5036, 0, 0x3872, 0x3067, 0x4B72, 0, - 0x357C, 0, 0, 0x357D, 0x357E, 0x4462, 0x4E3C, 0xB041, - 0x5037, 0, 0, 0x5038, 0, 0, 0x5039, 0, - 0, 0xB042, 0x3F4D, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E4BA_x0213[] = { - 0x3535, 0, 0x502C, 0, 0, 0x502D, 0x4E3B, 0, - 0x4D3D, 0x4168, 0x502F, 0x3B76, 0x4673, 0x2E27, 0x5032, 0, - 0, 0x313E, 0x385F, 0, 0x385E, 0x3066, 0xB03E, 0xB03F, - 0x4F4B, 0x4F4A, 0, 0x3A33, 0x3021, 0xA131, 0x5033, 0x5034, - 0x5035, 0x4B34, 0x5036, 0, 0x3872, 0x3067, 0x4B72, 0, - 0x357C, 0, 0, 0x357D, 0x357E, 0x4462, 0x4E3C, 0xB041, - 0x5037, 0, 0, 0x5038, 0, 0, 0x5039, 0, - 0, 0xA134, 0x3F4D, 0xA135, 0xA137, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E4BB[] = { - 0x3D3A, 0x3F4E, 0x503E, 0xB043, 0x503C, 0, 0x503D, 0x3558, - 0, 0, 0x3A23, 0x3270, 0, 0x503B, 0x503A, 0x4A29, - 0xB044, 0, 0, 0, 0x3B46, 0x3B45, 0x423E, 0x503F, - 0x4955, 0x4067, 0xB045, 0xB046, 0, 0x2138, 0x5040, 0x5042, - 0xB047, 0xB048, 0xB049, 0x4265, 0x4E61, 0x304A, 0, 0, - 0xB04A, 0, 0, 0, 0, 0x5041, 0x323E, 0xB04B, - 0x3644, 0xB04C, 0x4367, 0xB04D, 0, 0xB04E, 0x376F, 0x5043, - 0, 0, 0, 0x4724, 0xF42F, 0xB04F, 0xB050, 0xB051, -}; -static const unsigned short utf8_to_euc_E4BB_x0213[] = { - 0x3D3A, 0x3F4E, 0x503E, 0xA138, 0x503C, 0, 0x503D, 0x3558, - 0xA139, 0, 0x3A23, 0x3270, 0, 0x503B, 0x503A, 0x4A29, - 0xA13A, 0, 0, 0, 0x3B46, 0x3B45, 0x423E, 0x503F, - 0x4955, 0x4067, 0xA13C, 0xB046, 0, 0x2138, 0x5040, 0x5042, - 0xB047, 0x2E28, 0xB049, 0x4265, 0x4E61, 0x304A, 0, 0, - 0xB04A, 0, 0, 0xA13B, 0, 0x5041, 0x323E, 0xB04B, - 0x3644, 0xA13D, 0x4367, 0xB04D, 0, 0xA13E, 0x376F, 0x5043, - 0, 0, 0, 0x4724, 0, 0x2E29, 0xB050, 0x2E2A, -}; -static const unsigned short utf8_to_euc_E4BC[] = { - 0xB052, 0x346B, 0xB053, 0xB054, 0, 0, 0, 0, - 0xB055, 0x5044, 0x304B, 0xB056, 0xB057, 0x3860, 0x346C, 0x497A, - 0x4832, 0x3559, 0xB058, 0, 0, 0xB059, 0xB05A, 0xB05B, - 0, 0xB05C, 0x3271, 0, 0x5067, 0x4541, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0xB05D, 0x476C, - 0x5046, 0xB05E, 0, 0xB060, 0x483C, 0xB061, 0x4E62, 0xB062, - 0x3F2D, 0xB063, 0x3B47, 0xB064, 0x3B77, 0x3240, 0xB065, 0, -}; -static const unsigned short utf8_to_euc_E4BC_x0213[] = { - 0xA13F, 0x346B, 0xB053, 0x2E2B, 0, 0, 0, 0, - 0xB055, 0x5044, 0x304B, 0x2E2C, 0xB057, 0x3860, 0x346C, 0x497A, - 0x4832, 0x3559, 0xB058, 0, 0, 0xB059, 0xA140, 0xB05B, - 0, 0xB05C, 0x3271, 0, 0x5067, 0x4541, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0xB05D, 0x476C, - 0x5046, 0xB05E, 0, 0xB060, 0x483C, 0xB061, 0x4E62, 0xA142, - 0x3F2D, 0, 0x3B47, 0xB064, 0x3B77, 0x3240, 0xA143, 0, -}; -static const unsigned short utf8_to_euc_E4BD[] = { - 0xB066, 0, 0xB067, 0x4451, 0, 0, 0x4322, 0x504A, - 0xB068, 0xB069, 0, 0xB06A, 0xB06B, 0x304C, 0x4463, 0x3D3B, - 0x3A34, 0x4D24, 0xB06C, 0x424E, 0xB06D, 0x323F, 0xB06E, 0x5049, - 0xB06F, 0x4D3E, 0x5045, 0x5047, 0x3A6E, 0x5048, 0x5524, 0xB070, - 0xB05F, 0, 0, 0xB071, 0, 0, 0, 0, - 0, 0x5050, 0xB072, 0, 0xB073, 0, 0xB074, 0x5053, - 0x5051, 0xB075, 0, 0x3242, 0, 0x4A3B, 0x504B, 0xB076, - 0xB077, 0xB078, 0xB079, 0x504F, 0x3873, 0xB07A, 0xB07B, 0x3B48, -}; -static const unsigned short utf8_to_euc_E4BD_x0213[] = { - 0xB066, 0, 0xB067, 0x4451, 0, 0, 0x4322, 0x504A, - 0x2E2E, 0x2E2F, 0, 0xB06A, 0xB06B, 0x304C, 0x4463, 0x3D3B, - 0x3A34, 0x4D24, 0xB06C, 0x424E, 0xA144, 0x323F, 0x2E30, 0x5049, - 0xA145, 0x4D3E, 0x5045, 0x5047, 0x3A6E, 0x5048, 0x5524, 0x2E31, - 0x2E2D, 0, 0, 0xB071, 0xA141, 0, 0, 0, - 0, 0x5050, 0x2E32, 0, 0x2E33, 0, 0xB074, 0x5053, - 0x5051, 0xB075, 0, 0x3242, 0, 0x4A3B, 0x504B, 0xA147, - 0xA148, 0xB078, 0xA149, 0x504F, 0x3873, 0xA14A, 0x2E34, 0x3B48, -}; -static const unsigned short utf8_to_euc_E4BE[] = { - 0, 0xB07C, 0xB07D, 0x3426, 0xB07E, 0xB121, 0x5054, 0, - 0x504C, 0xB122, 0xB123, 0x4E63, 0xB124, 0x3B78, 0xB125, 0x504D, - 0xB126, 0x5052, 0xB127, 0xB128, 0xB129, 0, 0x5055, 0xB12A, - 0x504E, 0xB12B, 0xB12C, 0x3621, 0, 0x304D, 0xB12D, 0xB12E, - 0x3622, 0x3241, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0x5525, 0, 0x4B79, 0x496E, 0x3874, - 0, 0, 0xB12F, 0, 0, 0x3F2F, 0x4E37, 0xB130, - 0, 0xB131, 0, 0xB132, 0xB133, 0xB134, 0xB135, 0x4A58, -}; -static const unsigned short utf8_to_euc_E4BE_x0213[] = { - 0, 0xB07C, 0xA14B, 0x3426, 0xB07E, 0xA14C, 0x5054, 0, - 0x504C, 0xB122, 0x2E35, 0x4E63, 0xB124, 0x3B78, 0xB125, 0x504D, - 0xB126, 0x5052, 0xA14D, 0xB128, 0x2E36, 0, 0x5055, 0x2E37, - 0x504E, 0xB12B, 0xA14E, 0x3621, 0, 0x304D, 0xB12D, 0xB12E, - 0x3622, 0x3241, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0x5525, 0, 0x4B79, 0x496E, 0x3874, - 0, 0, 0xA150, 0, 0, 0x3F2F, 0x4E37, 0xB130, - 0, 0xB131, 0, 0xB132, 0xB133, 0xB134, 0xA151, 0x4A58, -}; -static const unsigned short utf8_to_euc_E4BF[] = { - 0xB136, 0xB137, 0x3738, 0x4225, 0x3264, 0xB138, 0xB139, 0, - 0xB13A, 0xB13B, 0x3D53, 0xB13C, 0xB13D, 0xB13E, 0x5059, 0xB13F, - 0x505E, 0x505C, 0xB140, 0, 0x5057, 0, 0, 0x422F, - 0x505A, 0, 0x505D, 0x505B, 0xB141, 0x4A5D, 0, 0x5058, - 0xB142, 0x3F2E, 0xB143, 0x4B73, 0x505F, 0x5060, 0, 0, - 0, 0, 0, 0, 0, 0, 0x3D24, 0x506D, - 0xB144, 0, 0xB145, 0x4750, 0, 0x4936, 0x5068, 0, - 0x4A70, 0, 0x3236, 0, 0xB146, 0xB147, 0x506C, 0xB148, -}; -static const unsigned short utf8_to_euc_E4BF_x0213[] = { - 0xB136, 0xB137, 0x3738, 0x4225, 0x3264, 0xA152, 0xB139, 0, - 0xB13A, 0x2E39, 0x3D53, 0xA153, 0xB13D, 0, 0x5059, 0xA154, - 0x505E, 0x505C, 0xA155, 0, 0x5057, 0, 0, 0x422F, - 0x505A, 0, 0x505D, 0x505B, 0xB141, 0x4A5D, 0, 0x5058, - 0x2E3A, 0x3F2E, 0xB143, 0x4B73, 0x505F, 0x5060, 0xA14F, 0, - 0, 0, 0, 0, 0, 0, 0x3D24, 0x506D, - 0xB144, 0x2E21, 0xA157, 0x4750, 0, 0x4936, 0x5068, 0, - 0x4A70, 0, 0x3236, 0, 0xB146, 0xB147, 0x506C, 0, -}; -static const unsigned short utf8_to_euc_E580[] = { - 0xB149, 0xB14A, 0, 0, 0xB14B, 0x5066, 0x506F, 0xB14C, - 0, 0x4152, 0xB14D, 0x3844, 0xB14E, 0x475C, 0xB14F, 0x6047, - 0xB150, 0x506E, 0x455D, 0xB151, 0x5063, 0, 0x3876, 0xB152, - 0xB153, 0x3875, 0x5061, 0xB154, 0xB155, 0xB156, 0xB157, 0x3C5A, - 0, 0x5069, 0xB158, 0x4A6F, 0x434D, 0x5065, 0x3771, 0xB159, - 0x5062, 0x506A, 0x5064, 0x4E51, 0x506B, 0x4F41, 0xB15A, 0, - 0xB15B, 0, 0xB15C, 0xB15D, 0, 0xB15E, 0x3666, 0, - 0, 0x3770, 0, 0xB176, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E580_x0213[] = { - 0xA158, 0x2E3B, 0x2E3C, 0, 0xB14B, 0x5066, 0x506F, 0xB14C, - 0, 0x4152, 0xB14D, 0x3844, 0xB14E, 0x475C, 0x2E3D, 0x6047, - 0xA159, 0x506E, 0x455D, 0xA15A, 0x5063, 0, 0x3876, 0xB152, - 0x2E3E, 0x3875, 0x5061, 0xB154, 0xA15B, 0xB156, 0xA15C, 0x3C5A, - 0, 0x5069, 0xA15D, 0x4A6F, 0x434D, 0x5065, 0x3771, 0x2E3F, - 0x5062, 0x506A, 0x5064, 0x4E51, 0x506B, 0x4F41, 0x2E40, 0, - 0xB15B, 0, 0xB15C, 0xB15D, 0, 0xB15E, 0x3666, 0, - 0, 0x3770, 0, 0x2E42, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E581[] = { - 0xB15F, 0xB160, 0xB161, 0x5070, 0, 0xB162, 0xB163, 0x5071, - 0x5075, 0x304E, 0xB164, 0, 0xB165, 0, 0xB166, 0x4A50, - 0x5074, 0xB167, 0xB168, 0xB169, 0, 0x5073, 0x5077, 0xB16A, - 0, 0xB16B, 0x5076, 0, 0x4464, 0, 0, 0xB16C, - 0xB16D, 0, 0xB16E, 0xB16F, 0, 0x3772, 0xB170, 0xB171, - 0, 0, 0xB172, 0, 0x5078, 0xB173, 0, 0, - 0xB174, 0xB175, 0x3C45, 0, 0x4226, 0x4465, 0x3676, 0, - 0x5079, 0, 0, 0, 0, 0x3536, 0, 0, -}; -static const unsigned short utf8_to_euc_E581_x0213[] = { - 0x2E41, 0x2E43, 0xA15F, 0x5070, 0, 0xB162, 0xA160, 0x5071, - 0x5075, 0x304E, 0xB164, 0, 0xB165, 0, 0xA161, 0x4A50, - 0x5074, 0xB167, 0xB168, 0xA162, 0, 0x5073, 0x5077, 0xA163, - 0, 0xB16B, 0x5076, 0, 0x4464, 0, 0, 0xB16C, - 0xB16D, 0, 0xB16E, 0xA164, 0, 0x3772, 0xA165, 0xB171, - 0, 0, 0xA166, 0, 0x5078, 0xB173, 0, 0, - 0xA167, 0xB175, 0x3C45, 0, 0x4226, 0x4465, 0x3676, 0, - 0x5079, 0, 0, 0, 0, 0x3536, 0, 0, -}; -static const unsigned short utf8_to_euc_E582[] = { - 0x507A, 0xB177, 0, 0xB178, 0xB179, 0x507C, 0xB17A, 0, - 0, 0, 0xB17B, 0, 0, 0x4B35, 0xB17C, 0xB17D, - 0xB17E, 0x3766, 0xB221, 0xB222, 0xB223, 0, 0xB224, 0, - 0x3B31, 0x4877, 0x507B, 0xB225, 0xB226, 0, 0xB227, 0xB228, - 0xB229, 0xB22A, 0xB22B, 0, 0, 0, 0, 0, - 0, 0, 0xB22C, 0, 0x3A45, 0x4D43, 0, 0xB22D, - 0xB22E, 0, 0x507E, 0x5123, 0x507D, 0x3A44, 0, 0x3D7D, - 0, 0xB22F, 0xB230, 0, 0, 0xB231, 0x3739, 0, -}; -static const unsigned short utf8_to_euc_E582_x0213[] = { - 0x507A, 0xB177, 0, 0xB178, 0xB179, 0x507C, 0xB17A, 0, - 0xA169, 0, 0xB17B, 0, 0, 0x4B35, 0xB17C, 0xB17D, - 0xB17E, 0x3766, 0xA16A, 0xA16B, 0x2E44, 0xA16C, 0xA16D, 0, - 0x3B31, 0x4877, 0x507B, 0xB225, 0xA16E, 0, 0xB227, 0xB228, - 0xB229, 0xB22A, 0xB22B, 0xA168, 0, 0, 0, 0, - 0, 0, 0xA16F, 0, 0x3A45, 0x4D43, 0, 0xB22D, - 0xB22E, 0xA171, 0x507E, 0x5123, 0x507D, 0x3A44, 0, 0x3D7D, - 0, 0xB22F, 0xA172, 0xA173, 0, 0xB231, 0x3739, 0, -}; -static const unsigned short utf8_to_euc_E583[] = { - 0xB232, 0, 0x5124, 0xB233, 0xB234, 0x364F, 0, 0xB235, - 0, 0x5121, 0x5122, 0, 0xB236, 0x462F, 0xB237, 0x417C, - 0xB238, 0x3623, 0, 0xB239, 0xB23A, 0x4B4D, 0x5125, 0, - 0xB23B, 0, 0x4E3D, 0, 0xB23C, 0xB23D, 0x5126, 0xB23E, - 0, 0, 0xB23F, 0x5129, 0xB240, 0x5127, 0xB241, 0x414E, - 0xB242, 0xB243, 0, 0, 0, 0x5128, 0x512A, 0xB244, - 0, 0xB245, 0xB251, 0, 0xF430, 0x512C, 0xB246, 0, - 0, 0x512B, 0xB247, 0x4A48, 0, 0, 0xB248, 0, -}; -static const unsigned short utf8_to_euc_E583_x0213[] = { - 0xB232, 0, 0x5124, 0xB233, 0xA174, 0x364F, 0, 0xA175, - 0, 0x5121, 0x5122, 0, 0x2E45, 0x462F, 0xA178, 0x417C, - 0x2E47, 0x3623, 0, 0xB239, 0xA17A, 0x4B4D, 0x5125, 0, - 0, 0xA17B, 0x4E3D, 0, 0xB23C, 0xB23D, 0x5126, 0xB23E, - 0, 0xA17C, 0xB23F, 0x5129, 0xB240, 0x5127, 0x2E48, 0x414E, - 0xB242, 0xA17D, 0, 0, 0, 0x5128, 0x512A, 0xB244, - 0, 0xB245, 0x2E46, 0xA176, 0, 0x512C, 0xB246, 0, - 0, 0x512B, 0xB247, 0x4A48, 0, 0, 0xB248, 0, -}; -static const unsigned short utf8_to_euc_E584[] = { - 0x3537, 0x512E, 0x512F, 0xB249, 0x322F, 0, 0xB24A, 0xB24B, - 0xB24C, 0x512D, 0, 0xB24D, 0xB24E, 0xB24F, 0xB250, 0, - 0xB252, 0, 0x3C74, 0, 0x5132, 0x5131, 0x5130, 0xB253, - 0x5056, 0xB254, 0x5133, 0xB255, 0xB256, 0xB257, 0xB258, 0x3D7E, - 0, 0x5134, 0, 0xB259, 0, 0, 0, 0xB25A, - 0xB25B, 0, 0x4D25, 0, 0xB25C, 0xB25D, 0, 0xB25E, - 0, 0xB25F, 0x4C59, 0xB260, 0xB261, 0xB262, 0, 0x5136, - 0xB263, 0xB264, 0x5135, 0x5138, 0x5137, 0, 0, 0x5139, -}; -static const unsigned short utf8_to_euc_E584_x0213[] = { - 0x3537, 0x512E, 0x512F, 0x2E4B, 0x322F, 0, 0x2E4A, 0xB24B, - 0xA321, 0x512D, 0, 0x2E4C, 0xB24E, 0xB24F, 0xB250, 0, - 0xB252, 0, 0x3C74, 0, 0x5132, 0x5131, 0x5130, 0xA323, - 0x5056, 0xB254, 0x5133, 0xA324, 0xB256, 0xB257, 0x2E4D, 0x3D7E, - 0, 0x5134, 0, 0xB259, 0, 0, 0, 0xB25A, - 0xB25B, 0, 0x4D25, 0, 0xB25C, 0xB25D, 0, 0xB25E, - 0, 0xB25F, 0x4C59, 0xB260, 0xB261, 0x2E4E, 0, 0x5136, - 0xB263, 0xB264, 0x5135, 0x5138, 0x5137, 0, 0, 0x5139, -}; -static const unsigned short utf8_to_euc_E585[] = { - 0x513A, 0x3074, 0xB265, 0x3835, 0x373B, 0x3D3C, 0x437B, 0x3624, - 0x4068, 0x3877, 0xB266, 0x396E, 0x513C, 0x4C48, 0x4546, 0xB267, - 0x3B79, 0, 0x513B, 0xB268, 0x513D, 0xB269, 0, 0xB26A, - 0xB26B, 0, 0x455E, 0, 0x3375, 0, 0, 0xB26C, - 0, 0, 0x513E, 0, 0xB26D, 0x467E, 0xB26E, 0, - 0x4134, 0x5140, 0x5141, 0x482C, 0x3878, 0x4F3B, 0x5142, 0, - 0, 0x3626, 0, 0, 0, 0x4A3C, 0x4236, 0x3671, - 0x4535, 0, 0, 0, 0x3773, 0, 0xB26F, 0, -}; -static const unsigned short utf8_to_euc_E585_x0213[] = { - 0x513A, 0x3074, 0xB265, 0x3835, 0x373B, 0x3D3C, 0x437B, 0x3624, - 0x4068, 0x3877, 0x2E4F, 0x396E, 0x513C, 0x4C48, 0x4546, 0xB267, - 0x3B79, 0, 0x513B, 0xB268, 0x513D, 0x2E51, 0, 0x2E52, - 0xB26B, 0, 0x455E, 0, 0x3375, 0, 0, 0xB26C, - 0xA326, 0, 0x513E, 0, 0, 0x467E, 0xB26E, 0, - 0x4134, 0x5140, 0x5141, 0x482C, 0x3878, 0x4F3B, 0x5142, 0, - 0, 0x3626, 0, 0xA328, 0, 0x4A3C, 0x4236, 0x3671, - 0x4535, 0, 0, 0xF474, 0x3773, 0, 0xB26F, 0, -}; -static const unsigned short utf8_to_euc_E586[] = { - 0x5143, 0, 0x5144, 0xB270, 0xB271, 0x4662, 0x315F, 0, - 0, 0x5147, 0x3A7D, 0xB272, 0x5146, 0x3A46, 0xB273, 0x5148, - 0x666E, 0x5149, 0x4B41, 0x514A, 0, 0x514B, 0x514C, 0x3E69, - 0xB274, 0x3C4C, 0, 0, 0, 0xB275, 0, 0, - 0x3427, 0xB276, 0x514F, 0xB277, 0x514D, 0x4C3D, 0x514E, 0, - 0x495A, 0x5150, 0x5151, 0x5152, 0x455F, 0xB278, 0, 0, - 0x5156, 0x5154, 0x5155, 0x5153, 0x3A63, 0x5157, 0x4C6A, 0x4E64, - 0xB279, 0, 0xB27A, 0, 0xB27B, 0x5158, 0xB27C, 0xB27D, -}; -static const unsigned short utf8_to_euc_E586_x0213[] = { - 0x5143, 0, 0x5144, 0xA329, 0xB271, 0x4662, 0x315F, 0, - 0, 0x5147, 0x3A7D, 0xA32A, 0x5146, 0x3A46, 0xB273, 0x5148, - 0x666E, 0x5149, 0x4B41, 0x514A, 0, 0x514B, 0x514C, 0x3E69, - 0xA32C, 0x3C4C, 0, 0, 0, 0x2E54, 0, 0, - 0x3427, 0xB276, 0x514F, 0xA32D, 0x514D, 0x4C3D, 0x514E, 0, - 0x495A, 0x5150, 0x5151, 0x5152, 0x455F, 0xA32E, 0, 0, - 0x5156, 0x5154, 0x5155, 0x5153, 0x3A63, 0x5157, 0x4C6A, 0x4E64, - 0xB279, 0, 0xB27A, 0, 0xA330, 0x5158, 0, 0xB27D, -}; -static const unsigned short utf8_to_euc_E587[] = { - 0, 0, 0xB27E, 0, 0x4028, 0x5159, 0x3D5A, 0, - 0xB321, 0x515A, 0, 0x437C, 0x4E3F, 0x4560, 0, 0xB322, - 0, 0xB323, 0xB324, 0xB325, 0, 0xB326, 0x5245, 0, - 0xB327, 0, 0, 0x515B, 0x7425, 0x3645, 0xB328, 0, - 0x515C, 0x4B5E, 0xB329, 0, 0, 0xB32A, 0x3D68, 0x427C, - 0, 0x515E, 0x4664, 0, 0xF431, 0x515F, 0xB32B, 0, - 0x5160, 0x332E, 0xB32C, 0xB32D, 0xB32E, 0x5161, 0x3627, 0xB32F, - 0x464C, 0x317A, 0x3D50, 0, 0, 0x4821, 0x5162, 0, -}; -static const unsigned short utf8_to_euc_E587_x0213[] = { - 0, 0, 0xB27E, 0x2E55, 0x4028, 0x5159, 0x3D5A, 0, - 0xB321, 0x515A, 0x2E56, 0x437C, 0x4E3F, 0x4560, 0, 0xB322, - 0, 0xB323, 0xB324, 0xB325, 0, 0xB326, 0x5245, 0, - 0xB327, 0, 0, 0x515B, 0x7425, 0x3645, 0x2E57, 0, - 0x515C, 0x4B5E, 0x2E58, 0, 0, 0xB32A, 0x3D68, 0x427C, - 0, 0x515E, 0x4664, 0, 0, 0x515F, 0x2E59, 0, - 0x5160, 0x332E, 0xB32C, 0xA333, 0xA334, 0x5161, 0x3627, 0xB32F, - 0x464C, 0x317A, 0x3D50, 0, 0, 0x4821, 0x5162, 0, -}; -static const unsigned short utf8_to_euc_E588[] = { - 0x4561, 0xB330, 0xB331, 0x3F4F, 0x5163, 0xB332, 0x4A2C, 0x405A, - 0x3422, 0, 0x3429, 0x5164, 0, 0, 0x5166, 0, - 0, 0x373A, 0xB333, 0xB334, 0x5165, 0xB335, 0xB336, 0x4E73, - 0xB337, 0, 0, 0, 0, 0x3D69, 0, 0, - 0, 0, 0xB338, 0, 0x483D, 0x4A4C, 0, 0x5167, - 0xB339, 0x4D78, 0x5168, 0, 0, 0, 0x5169, 0, - 0x457E, 0xB33A, 0xB33B, 0x516A, 0, 0xB33C, 0x4029, 0x3A7E, - 0x3774, 0x516B, 0x3B49, 0x396F, 0xB33D, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E588_x0213[] = { - 0x4561, 0x2E5A, 0xA335, 0x3F4F, 0x5163, 0xB332, 0x4A2C, 0x405A, - 0x3422, 0, 0x3429, 0x5164, 0, 0, 0x5166, 0, - 0, 0x373A, 0xA336, 0x2E5C, 0x5165, 0x2E5D, 0xA337, 0x4E73, - 0xB337, 0, 0, 0, 0, 0x3D69, 0, 0, - 0, 0, 0xB338, 0, 0x483D, 0x4A4C, 0, 0x5167, - 0xB339, 0x4D78, 0x5168, 0, 0, 0, 0x5169, 0, - 0x457E, 0xB33A, 0xB33B, 0x516A, 0, 0xB33C, 0x4029, 0x3A7E, - 0x3774, 0x516B, 0x3B49, 0x396F, 0xB33D, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E589[] = { - 0, 0, 0, 0x4466, 0x516D, 0xB33E, 0, 0x4227, - 0, 0xB33F, 0x3A6F, 0x516E, 0x516F, 0x4130, 0, 0x516C, - 0, 0, 0, 0, 0x5171, 0xB340, 0x4B36, 0xB341, - 0xB342, 0, 0xB343, 0x3964, 0xB344, 0, 0x5170, 0xB345, - 0xB346, 0xB347, 0, 0x3775, 0x3A5E, 0x476D, 0xB348, 0, - 0, 0x5174, 0x5172, 0, 0, 0, 0xB349, 0x497B, - 0x3E6A, 0x517B, 0x3364, 0x5175, 0x5173, 0x414F, 0, 0xB34A, - 0xB34B, 0xB34C, 0, 0, 0, 0x5177, 0, 0x5176, -}; -static const unsigned short utf8_to_euc_E589_x0213[] = { - 0, 0, 0, 0x4466, 0x516D, 0xB33E, 0, 0x4227, - 0, 0x2E5E, 0x3A6F, 0x516E, 0x516F, 0x4130, 0, 0x516C, - 0, 0, 0, 0, 0x5171, 0xA339, 0x4B36, 0x2E5F, - 0xB342, 0, 0xB343, 0x3964, 0xA33A, 0x2F7E, 0x5170, 0xB345, - 0xB346, 0x2E60, 0, 0x3775, 0x3A5E, 0x476D, 0xB348, 0, - 0, 0x5174, 0x5172, 0, 0xA33B, 0, 0xB349, 0x497B, - 0x3E6A, 0x517B, 0x3364, 0x5175, 0x5173, 0x414F, 0, 0xA33C, - 0xB34B, 0xB34C, 0, 0, 0, 0x5177, 0, 0x5176, -}; -static const unsigned short utf8_to_euc_E58A[] = { - 0xB34D, 0, 0xB34E, 0x3344, 0, 0xB34F, 0, 0x3760, - 0x517C, 0x4E2D, 0xB350, 0, 0xB351, 0x5178, 0, 0, - 0, 0x517D, 0x517A, 0xB352, 0x5179, 0xB353, 0xB354, 0xB355, - 0xB356, 0, 0xB357, 0x4E4F, 0xB358, 0, 0, 0x3879, - 0x3243, 0, 0, 0x4E74, 0xB359, 0xB35A, 0xB35B, 0xB35C, - 0, 0x3D75, 0x4558, 0x3965, 0x5222, 0x5223, 0, 0xB35D, - 0xB35E, 0x4E65, 0, 0, 0x4F2B, 0x5225, 0xB35F, 0xB360, - 0xB361, 0x387A, 0xB362, 0xB363, 0x5224, 0xB364, 0x332F, 0, -}; -static const unsigned short utf8_to_euc_E58A_x0213[] = { - 0xB34D, 0, 0xA33E, 0x3344, 0xA33D, 0xB34F, 0, 0x3760, - 0x517C, 0x4E2D, 0xB350, 0, 0xB351, 0x5178, 0, 0, - 0, 0x517D, 0x517A, 0x2E61, 0x5179, 0xB353, 0xB354, 0xB355, - 0xA340, 0, 0xB357, 0x4E4F, 0, 0, 0, 0x3879, - 0x3243, 0, 0, 0x4E74, 0xA342, 0xB35A, 0xA343, 0xB35C, - 0, 0x3D75, 0x4558, 0x3965, 0x5222, 0x5223, 0, 0xA344, - 0xB35E, 0x4E65, 0, 0, 0x4F2B, 0x5225, 0xB35F, 0xB360, - 0xB361, 0x387A, 0xA345, 0xA346, 0x5224, 0xB364, 0x332F, 0, -}; -static const unsigned short utf8_to_euc_E58B[] = { - 0xB365, 0x5226, 0, 0x4B56, 0xB366, 0x443C, 0xB367, 0x4D26, - 0xB368, 0x4A59, 0, 0, 0xB369, 0x5227, 0, 0xB36A, - 0, 0xB36B, 0x7055, 0, 0xB36C, 0x4630, 0xB36D, 0x5228, - 0x342A, 0x4C33, 0, 0xB36E, 0xB36F, 0x3E21, 0x5229, 0x4A67, - 0x522D, 0xB370, 0x402A, 0x522A, 0x3650, 0xB371, 0x522B, 0x342B, - 0xB372, 0xB373, 0xB374, 0, 0xB375, 0, 0, 0, - 0xB376, 0xB377, 0x372E, 0x522E, 0xB378, 0x522F, 0xB379, 0xB37A, - 0x5230, 0x5231, 0x3C5B, 0, 0, 0, 0x387B, 0x4C5E, -}; -static const unsigned short utf8_to_euc_E58B_x0213[] = { - 0, 0x5226, 0, 0x4B56, 0xB366, 0x443C, 0xB367, 0x4D26, - 0x2E62, 0x4A59, 0xA347, 0, 0x2E64, 0x5227, 0, 0xB36A, - 0x2E65, 0xA349, 0x7055, 0, 0xB36C, 0x4630, 0x2E66, 0x5228, - 0x342A, 0x4C33, 0, 0x2E67, 0xB36F, 0x3E21, 0x5229, 0x4A67, - 0x522D, 0xB370, 0x402A, 0x522A, 0x3650, 0xB371, 0x522B, 0x342B, - 0xB372, 0xB373, 0xB374, 0, 0xB375, 0, 0, 0, - 0x2E69, 0xB377, 0x372E, 0x522E, 0xB378, 0x522F, 0xB379, 0xA34B, - 0x5230, 0x5231, 0x3C5B, 0x2E6A, 0, 0, 0x387B, 0x4C5E, -}; -static const unsigned short utf8_to_euc_E58C[] = { - 0xB37B, 0x4C68, 0x4677, 0xB37C, 0, 0x4A71, 0x5232, 0xF432, - 0x5233, 0, 0xB37D, 0xB37E, 0xB421, 0x5235, 0, 0x5237, - 0x5236, 0xB422, 0, 0xB423, 0, 0x5238, 0x323D, 0x4B4C, - 0xB424, 0x3A7C, 0x5239, 0xB425, 0xB426, 0x4159, 0xB427, 0xB428, - 0x3E22, 0x3629, 0, 0x523A, 0xF433, 0xB429, 0, 0xB42A, - 0xB42B, 0xB42C, 0x485B, 0xB42D, 0xB42E, 0xB42F, 0, 0x523B, - 0xB430, 0x523C, 0xB431, 0x523D, 0, 0xB432, 0, 0, - 0x523E, 0x4924, 0x3668, 0x3065, 0xB433, 0xB434, 0xB435, 0x463F, -}; -static const unsigned short utf8_to_euc_E58C_x0213[] = { - 0x2E6B, 0x4C68, 0x4677, 0xB37C, 0, 0x4A71, 0x5232, 0x2E6C, - 0x5233, 0, 0xA34C, 0xA34D, 0xB421, 0x5235, 0, 0x5237, - 0x5236, 0xB422, 0, 0xB423, 0, 0x5238, 0x323D, 0x4B4C, - 0xB424, 0x3A7C, 0x5239, 0xB425, 0x2E6D, 0x4159, 0xB427, 0xB428, - 0x3E22, 0x3629, 0, 0x523A, 0xA34E, 0xB429, 0, 0xB42A, - 0xB42B, 0xB42C, 0x485B, 0xB42D, 0xB42E, 0xB42F, 0, 0x523B, - 0xB430, 0x523C, 0xB431, 0x523D, 0, 0xA34F, 0, 0, - 0x523E, 0x4924, 0x3668, 0x3065, 0xB433, 0xB434, 0xA350, 0x463F, -}; -static const unsigned short utf8_to_euc_E58D[] = { - 0x523F, 0x3D3D, 0xB436, 0x4069, 0, 0x5241, 0x5240, 0x3E23, - 0x3861, 0x5243, 0x483E, 0xB438, 0xB437, 0x5244, 0, 0, - 0, 0x485C, 0x4234, 0x426E, 0x3628, 0, 0, 0x466E, - 0x4331, 0xB439, 0x476E, 0xB43A, 0x4B4E, 0, 0x5246, 0, - 0x406A, 0xB43B, 0, 0xB43C, 0, 0xB43D, 0x3735, 0, - 0, 0x5247, 0, 0, 0xB43E, 0xB43F, 0x5248, 0x312C, - 0x3075, 0x346D, 0xB440, 0x4228, 0x3551, 0x4D71, 0, 0x524B, - 0x3237, 0xB441, 0, 0x524A, 0, 0, 0xB442, 0x362A, -}; -static const unsigned short utf8_to_euc_E58D_x0213[] = { - 0x523F, 0x3D3D, 0xA351, 0x4069, 0, 0x5241, 0x5240, 0x3E23, - 0x3861, 0x5243, 0x483E, 0xB438, 0xB437, 0x5244, 0, 0, - 0, 0x485C, 0x4234, 0x426E, 0x3628, 0, 0, 0x466E, - 0x4331, 0xB439, 0x476E, 0xB43A, 0x4B4E, 0, 0x5246, 0, - 0x406A, 0x2E6F, 0, 0x2E70, 0, 0xB43D, 0x3735, 0xA354, - 0, 0x5247, 0, 0, 0xA355, 0xB43F, 0x5248, 0x312C, - 0x3075, 0x346D, 0, 0x4228, 0x3551, 0x4D71, 0, 0x524B, - 0x3237, 0xB441, 0xA356, 0x524A, 0, 0x2E71, 0xB442, 0x362A, -}; -static const unsigned short utf8_to_euc_E58E[] = { - 0, 0, 0x524C, 0xB443, 0x4C71, 0, 0, 0xB444, - 0xB445, 0, 0, 0, 0, 0, 0xB446, 0, - 0, 0, 0, 0xB447, 0xB448, 0, 0x524D, 0, - 0x4E52, 0xB449, 0x387C, 0, 0, 0xB44A, 0, 0x3836, - 0x524E, 0xB44B, 0, 0, 0xB44C, 0x5250, 0x524F, 0, - 0x3F5F, 0x3139, 0xB44D, 0xB44E, 0, 0x315E, 0x5251, 0xB44F, - 0x5252, 0, 0xB450, 0x3837, 0xB451, 0xB452, 0x5253, 0xB453, - 0xB454, 0, 0xB455, 0x356E, 0, 0xB456, 0, 0, -}; -static const unsigned short utf8_to_euc_E58E_x0213[] = { - 0, 0, 0x524C, 0xB443, 0x4C71, 0, 0, 0xB444, - 0xB445, 0, 0, 0, 0, 0, 0xB446, 0, - 0, 0, 0, 0x2E72, 0xB448, 0, 0x524D, 0, - 0x4E52, 0xB449, 0x387C, 0, 0, 0x2E73, 0, 0x3836, - 0x524E, 0xB44B, 0, 0, 0xA357, 0x5250, 0x524F, 0, - 0x3F5F, 0x3139, 0xB44D, 0xB44E, 0, 0x315E, 0x5251, 0xB44F, - 0x5252, 0, 0x2E74, 0x3837, 0xA358, 0xB452, 0x5253, 0xA35A, - 0xB454, 0, 0xB455, 0x356E, 0, 0xB456, 0, 0, -}; -static const unsigned short utf8_to_euc_E58F[] = { - 0xB457, 0, 0x3B32, 0x5254, 0, 0xB458, 0, 0, - 0x4B74, 0x3A35, 0x355A, 0x4D27, 0x4150, 0x483F, 0x3C7D, 0xB459, - 0, 0, 0xB45A, 0xB45B, 0x3D47, 0xB45C, 0x3C68, 0x3C75, - 0, 0x3D76, 0xB45D, 0x4840, 0, 0xB45E, 0xB45F, 0x5257, - 0xB460, 0x3143, 0x4151, 0x387D, 0x3845, 0x3667, 0xB461, 0xB462, - 0x525B, 0x4321, 0x427E, 0x362B, 0x3E24, 0x525C, 0x525A, 0x3244, - 0x4266, 0x3C38, 0x3B4B, 0x3126, 0, 0xB463, 0x3370, 0x3966, - 0x3B4A, 0, 0x525D, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E58F_x0213[] = { - 0xA35B, 0, 0x3B32, 0x5254, 0, 0xB458, 0, 0, - 0x4B74, 0x3A35, 0x355A, 0x4D27, 0x4150, 0x483F, 0x3C7D, 0xB459, - 0, 0, 0xB45A, 0xB45B, 0x3D47, 0xA35F, 0x3C68, 0x3C75, - 0, 0x3D76, 0xA360, 0x4840, 0, 0, 0xB45F, 0x5257, - 0xB460, 0x3143, 0x4151, 0x387D, 0x3845, 0x3667, 0xB461, 0xB462, - 0x525B, 0x4321, 0x427E, 0x362B, 0x3E24, 0x525C, 0x525A, 0x3244, - 0x4266, 0x3C38, 0x3B4B, 0x3126, 0xA362, 0xA363, 0x3370, 0x3966, - 0x3B4A, 0, 0x525D, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E590[] = { - 0, 0x525E, 0xB464, 0x3549, 0x3346, 0, 0, 0, - 0x3967, 0x3548, 0x445F, 0x3125, 0x4631, 0x4C3E, 0x3921, 0x4D79, - 0x4547, 0x387E, 0, 0xB465, 0, 0, 0, 0, - 0, 0, 0xB466, 0x372F, 0, 0x5267, 0, 0x3663, - 0x4B4A, 0xB467, 0, 0, 0, 0, 0x485D, 0xB468, - 0xB469, 0x5266, 0xB46A, 0x345E, 0x5261, 0x5262, 0x5264, 0xB46B, - 0, 0xB46C, 0, 0, 0xB46D, 0xB46E, 0x5265, 0, - 0x355B, 0x3F61, 0, 0x4A2D, 0x5263, 0x525F, 0x3863, 0, -}; -static const unsigned short utf8_to_euc_E590_x0213[] = { - 0, 0x525E, 0xB464, 0x3549, 0x3346, 0, 0, 0, - 0x3967, 0x3548, 0x445F, 0x3125, 0x4631, 0x4C3E, 0x3921, 0x4D79, - 0x4547, 0x387E, 0x2E75, 0xB465, 0, 0, 0, 0, - 0, 0, 0xB466, 0x372F, 0, 0x5267, 0x4F7E, 0x3663, - 0x4B4A, 0xB467, 0, 0, 0xA365, 0, 0x485D, 0x2E76, - 0xA366, 0x5266, 0xB46A, 0x345E, 0x5261, 0x5262, 0x5264, 0xB46B, - 0, 0xB46C, 0, 0, 0xB46D, 0xB46E, 0x5265, 0, - 0x355B, 0x3F61, 0, 0x4A2D, 0x5263, 0x525F, 0x3863, 0, -}; -static const unsigned short utf8_to_euc_E591[] = { - 0x5260, 0, 0x4F24, 0xB46F, 0xB470, 0, 0x4A72, 0xB471, - 0x4468, 0x3862, 0x3970, 0, 0, 0xB472, 0x5268, 0xB473, - 0, 0x465D, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0xB474, 0x526C, - 0, 0, 0xB475, 0, 0xB476, 0, 0xB477, 0xB478, - 0x3C7E, 0xB479, 0x3C76, 0xB47A, 0, 0xB47B, 0xB47C, 0, - 0x526F, 0x526D, 0, 0x4C23, 0xB47D, 0x526A, 0x5273, 0x526E, - 0, 0, 0, 0x5271, 0x3846, 0x4C3F, 0, 0xB47E, -}; -static const unsigned short utf8_to_euc_E591_x0213[] = { - 0x5260, 0, 0x4F24, 0xA368, 0xB470, 0, 0x4A72, 0xB471, - 0x4468, 0x3862, 0x3970, 0, 0, 0x2E77, 0x5268, 0xB473, - 0, 0x465D, 0, 0, 0, 0xA364, 0, 0, - 0, 0, 0, 0, 0, 0, 0xB474, 0x526C, - 0, 0, 0xA369, 0, 0xB476, 0, 0xA36A, 0xB478, - 0x3C7E, 0xB479, 0x3C76, 0x2E79, 0xA36B, 0xB47B, 0xB47C, 0, - 0x526F, 0x526D, 0, 0x4C23, 0x2E7A, 0x526A, 0x5273, 0x526E, - 0, 0, 0, 0x5271, 0x3846, 0x4C3F, 0, 0x2E7B, -}; -static const unsigned short utf8_to_euc_E592[] = { - 0x5272, 0xB521, 0, 0xB522, 0x5274, 0xB523, 0x5276, 0, - 0xB524, 0xB525, 0xF435, 0x3A70, 0x4F42, 0xB526, 0x526B, 0x5269, - 0x5275, 0xB527, 0x5270, 0, 0, 0xB528, 0xB529, 0, - 0, 0, 0, 0, 0xB52A, 0, 0, 0xB52B, - 0, 0xB52C, 0x5278, 0, 0x5323, 0x527A, 0xB52D, 0xB52E, - 0x527E, 0xB52F, 0xB530, 0x5321, 0x527B, 0xB531, 0xB532, 0x533E, - 0, 0xB533, 0x3A69, 0x3331, 0, 0, 0, 0xB534, - 0x5279, 0xB535, 0xB536, 0xB537, 0x5325, 0x3076, 0x5324, 0xB538, -}; -static const unsigned short utf8_to_euc_E592_x0213[] = { - 0x5272, 0xB521, 0, 0xB522, 0x5274, 0xB523, 0x5276, 0, - 0x2E7C, 0xB525, 0xA36C, 0x3A70, 0x4F42, 0xA36D, 0x526B, 0x5269, - 0x5275, 0xB527, 0x5270, 0, 0, 0xA36E, 0x2E7D, 0, - 0, 0, 0, 0, 0x2E78, 0, 0, 0xB52B, - 0xA36F, 0x2E7E, 0x5278, 0, 0x5323, 0x527A, 0xA370, 0xB52E, - 0x527E, 0x2F21, 0xB530, 0x5321, 0x527B, 0xA371, 0xA372, 0x533E, - 0, 0xB533, 0x3A69, 0x3331, 0, 0, 0, 0xA373, - 0x5279, 0xB535, 0xA374, 0xB537, 0x5325, 0x3076, 0x5324, 0xA375, -}; -static const unsigned short utf8_to_euc_E593[] = { - 0x3025, 0x494A, 0x5322, 0, 0x527C, 0, 0xB539, 0x5277, - 0x527D, 0x3A48, 0xB53A, 0, 0, 0xB53B, 0xB53C, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x5326, 0, 0, 0, 0, 0, 0, 0, - 0xB53D, 0x3077, 0x532F, 0, 0, 0x5327, 0x5328, 0, - 0x3E25, 0x4B69, 0xB53E, 0, 0xB53F, 0x532D, 0x532C, 0xB540, - 0, 0, 0x452F, 0, 0, 0, 0xB541, 0, - 0, 0, 0x532E, 0, 0xB542, 0x532B, 0xB543, 0xB544, -}; -static const unsigned short utf8_to_euc_E593_x0213[] = { - 0x3025, 0x494A, 0x5322, 0xA376, 0x527C, 0, 0x2F22, 0x5277, - 0x527D, 0x3A48, 0xB53A, 0, 0, 0xB53B, 0xB53C, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x5326, 0, 0, 0, 0, 0, 0, 0, - 0xB53D, 0x3077, 0x532F, 0, 0, 0x5327, 0x5328, 0, - 0x3E25, 0x4B69, 0xB53E, 0, 0xA378, 0x532D, 0x532C, 0xA379, - 0, 0xA37A, 0x452F, 0xA37B, 0, 0, 0xB541, 0, - 0, 0, 0x532E, 0, 0xB542, 0x532B, 0xB543, 0x2F23, -}; -static const unsigned short utf8_to_euc_E594[] = { - 0xB545, 0xB546, 0, 0, 0x3134, 0xB547, 0x3A36, 0x3F30, - 0xB548, 0xB549, 0, 0, 0xB54A, 0xB54B, 0xB54C, 0x5329, - 0x4562, 0, 0, 0, 0x532A, 0xB54D, 0x3022, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0xB54E, 0xB54F, 0, 0, 0x5334, 0x4D23, - 0, 0x3E27, 0xB550, 0x533A, 0, 0xB551, 0xB552, 0, - 0x5339, 0x5330, 0, 0xB553, 0xB554, 0xB555, 0x4243, 0, -}; -static const unsigned short utf8_to_euc_E594_x0213[] = { - 0xA37C, 0xA37D, 0, 0, 0x3134, 0xB547, 0x3A36, 0x3F30, - 0xB548, 0xA37E, 0, 0, 0xB54A, 0xB54B, 0x2F24, 0x5329, - 0x4562, 0, 0, 0, 0x532A, 0xB54D, 0x3022, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0xB54E, 0x2F25, 0, 0, 0x5334, 0x4D23, - 0, 0x3E27, 0xB550, 0x533A, 0, 0x2F26, 0xB552, 0, - 0x5339, 0x5330, 0, 0xB553, 0xA421, 0xB555, 0x4243, 0, -}; -static const unsigned short utf8_to_euc_E595[] = { - 0x5331, 0xB556, 0, 0, 0x426F, 0x5336, 0x3E26, 0xB557, - 0, 0xB558, 0xB559, 0, 0x5333, 0xB55A, 0, 0x4C64, - 0xB55B, 0xB55C, 0, 0x373C, 0, 0, 0x5337, 0x5338, - 0xB55D, 0, 0xB55E, 0xB55F, 0x5335, 0x533B, 0xB560, 0, - 0xB561, 0xB562, 0, 0x5332, 0xB563, 0, 0xB564, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0x5341, 0x5346, 0, 0x5342, 0xB565, -}; -static const unsigned short utf8_to_euc_E595_x0213[] = { - 0x5331, 0xA422, 0, 0, 0x426F, 0x5336, 0x3E26, 0xA424, - 0, 0xB558, 0xA425, 0, 0x5333, 0xB55A, 0, 0x4C64, - 0x2F27, 0xB55C, 0, 0x373C, 0, 0, 0x5337, 0x5338, - 0xB55D, 0, 0xB55E, 0xB55F, 0x5335, 0x533B, 0x2F28, 0, - 0xA427, 0xA428, 0, 0x5332, 0xA429, 0, 0xB564, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0x5341, 0x5346, 0xA42B, 0x5342, 0xB565, -}; -static const unsigned short utf8_to_euc_E596[] = { - 0x533D, 0xB566, 0xB567, 0x5347, 0x4131, 0, 0xB568, 0x5349, - 0xB569, 0x3922, 0x533F, 0x437D, 0, 0, 0xB56A, 0xB56B, - 0, 0xB56C, 0xB56D, 0xB56E, 0xB56F, 0, 0, 0xB570, - 0x5343, 0x533C, 0x342D, 0, 0x346E, 0x3365, 0x5344, 0x5340, - 0, 0, 0, 0xB571, 0xB572, 0, 0, 0x3776, - 0x534A, 0x5348, 0x4153, 0x354A, 0x362C, 0xB573, 0x5345, 0, - 0x3674, 0, 0xB574, 0, 0, 0, 0x3144, 0, - 0, 0, 0, 0, 0, 0, 0, 0xB575, -}; -static const unsigned short utf8_to_euc_E596_x0213[] = { - 0x533D, 0x2F29, 0xA42C, 0x5347, 0x4131, 0, 0x2F2A, 0x5349, - 0xA42D, 0x3922, 0x533F, 0x437D, 0, 0, 0x2F2B, 0xB56B, - 0, 0xA42E, 0xB56D, 0xB56E, 0xB56F, 0, 0, 0xB570, - 0x5343, 0x533C, 0x342D, 0, 0x346E, 0x3365, 0x5344, 0x5340, - 0, 0, 0, 0xB571, 0xB572, 0, 0, 0x3776, - 0x534A, 0x5348, 0x4153, 0x354A, 0x362C, 0x2F2D, 0x5345, 0, - 0x3674, 0, 0xB574, 0, 0, 0, 0x3144, 0, - 0, 0, 0, 0, 0, 0, 0, 0xA433, -}; -static const unsigned short utf8_to_euc_E597[] = { - 0, 0xB576, 0, 0xB577, 0x534E, 0x534C, 0xB578, 0x5427, - 0, 0xB579, 0, 0xB57A, 0xB57B, 0, 0xB57C, 0, - 0, 0xB57D, 0xB57E, 0xB621, 0x5351, 0, 0, 0xB622, - 0xB623, 0, 0x534B, 0xB624, 0x534F, 0, 0xB625, 0x534D, - 0, 0, 0xB626, 0x3B4C, 0x5350, 0, 0, 0, - 0, 0xB627, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0xB628, 0x5353, - 0, 0x5358, 0, 0, 0, 0x5356, 0x5355, 0xB629, -}; -static const unsigned short utf8_to_euc_E597_x0213[] = { - 0, 0xB576, 0, 0xB577, 0x534E, 0x534C, 0xB578, 0x5427, - 0, 0xA434, 0, 0xB57A, 0xA435, 0, 0x2F2E, 0, - 0, 0xA436, 0xA430, 0xB621, 0x5351, 0, 0, 0xB622, - 0xB623, 0, 0x534B, 0xB624, 0x534F, 0xA437, 0xB625, 0x534D, - 0, 0, 0xA439, 0x3B4C, 0x5350, 0, 0, 0, - 0, 0xA43B, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0xB628, 0x5353, - 0, 0x5358, 0, 0, 0, 0x5356, 0x5355, 0xB629, -}; -static const unsigned short utf8_to_euc_E598[] = { - 0, 0, 0, 0, 0, 0xB62A, 0x4332, 0, - 0xB62B, 0x3245, 0xB62C, 0, 0, 0xB62D, 0xB62E, 0xB62F, - 0xB630, 0xB631, 0xB632, 0, 0x5352, 0, 0x5354, 0x3E28, - 0x3133, 0xB633, 0, 0x5357, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0x325E, 0, 0, 0xB634, 0, 0, 0x5362, - 0xB635, 0x3E7C, 0x535E, 0xB636, 0x535C, 0xB637, 0x535D, 0xB638, - 0x535F, 0xB639, 0, 0xB63A, 0xB63B, 0xB63C, 0, 0xB63D, -}; -static const unsigned short utf8_to_euc_E598_x0213[] = { - 0, 0, 0, 0, 0, 0xB62A, 0x4332, 0xA43E, - 0x2F30, 0x3245, 0xB62C, 0, 0, 0xB62D, 0x2F31, 0xB62F, - 0xA43F, 0xB631, 0xB632, 0, 0x5352, 0, 0x5354, 0x3E28, - 0x3133, 0xB633, 0, 0x5357, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0xA43C, 0x325E, 0, 0, 0xB634, 0, 0, 0x5362, - 0xA440, 0x3E7C, 0x535E, 0xB636, 0x535C, 0xB637, 0x535D, 0xA441, - 0x535F, 0xB639, 0, 0x2F32, 0xB63B, 0xA443, 0, 0xA444, -}; -static const unsigned short utf8_to_euc_E599[] = { - 0xB63E, 0xB63F, 0x313D, 0xB640, 0xB641, 0, 0xB642, 0, - 0, 0xB643, 0, 0xB644, 0x4139, 0xB645, 0x5359, 0xB646, - 0x535A, 0, 0, 0, 0xB647, 0, 0, 0, - 0, 0, 0, 0x337A, 0, 0, 0xB648, 0, - 0xB649, 0xB64A, 0xB64B, 0xB64C, 0x5361, 0, 0xB64D, 0, - 0x346F, 0xB64E, 0x5364, 0x5360, 0x5363, 0xB64F, 0, 0xB650, - 0, 0xB651, 0xB652, 0, 0x4A2E, 0xB653, 0, 0, - 0x4655, 0, 0x4838, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E599_x0213[] = { - 0xA445, 0xB63F, 0x313D, 0xB640, 0xB641, 0, 0xB642, 0xA446, - 0, 0x2F33, 0, 0xB644, 0x4139, 0xB645, 0x5359, 0xB646, - 0x535A, 0, 0, 0x7427, 0xB647, 0, 0, 0, - 0, 0, 0, 0x337A, 0, 0, 0xA447, 0, - 0xA448, 0xB64A, 0xB64B, 0xB64C, 0x5361, 0, 0x2F35, 0, - 0x346F, 0xB64E, 0x5364, 0x5360, 0x5363, 0xA449, 0, 0x2F37, - 0, 0x2F38, 0x2F39, 0, 0x4A2E, 0xB653, 0x2F34, 0, - 0x4655, 0, 0x4838, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E59A[] = { - 0x5366, 0, 0, 0, 0xB654, 0xB655, 0x5365, 0x3345, - 0xB656, 0, 0x5367, 0xB657, 0xB658, 0, 0, 0x536A, - 0, 0, 0, 0, 0x5369, 0xB659, 0, 0, - 0, 0xB65A, 0xB65B, 0, 0, 0xB65C, 0xB65D, 0xB65E, - 0x5368, 0, 0x4739, 0, 0, 0x536B, 0xB65F, 0xB660, - 0xB661, 0xB662, 0, 0xB663, 0xB664, 0xB665, 0x536C, 0, - 0, 0xB666, 0, 0xB667, 0x536E, 0, 0x536D, 0xB668, - 0, 0, 0, 0, 0x5370, 0, 0xB669, 0, -}; -static const unsigned short utf8_to_euc_E59A_x0213[] = { - 0x5366, 0, 0, 0, 0xB654, 0xB655, 0x5365, 0x3345, - 0xA44B, 0, 0x5367, 0xB657, 0xA44C, 0, 0, 0x536A, - 0, 0, 0, 0, 0x5369, 0xA44D, 0, 0, - 0, 0x2F3A, 0xA44E, 0, 0, 0xA44F, 0x2F3B, 0xB65E, - 0x5368, 0, 0x4739, 0, 0, 0x536B, 0xB65F, 0xB660, - 0xA450, 0x2F3C, 0, 0xB663, 0x2F3D, 0xA451, 0x536C, 0, - 0, 0xB666, 0xA452, 0x2F3E, 0x536E, 0, 0x536D, 0xB668, - 0, 0, 0, 0, 0x5370, 0, 0xB669, 0, -}; -static const unsigned short utf8_to_euc_E59B[] = { - 0x5373, 0x5371, 0x536F, 0x5372, 0, 0xB66A, 0, 0, - 0x5374, 0xB66B, 0xB66C, 0xB66D, 0xB670, 0xB671, 0x5375, 0xB66E, - 0xB66F, 0x5376, 0, 0x5377, 0, 0, 0, 0x5378, - 0x5145, 0xB672, 0x3C7C, 0x3B4D, 0xB673, 0xB674, 0x3273, 0xB675, - 0x3078, 0xB676, 0, 0x4344, 0xB677, 0xB678, 0xB679, 0xB67A, - 0xB67B, 0, 0, 0xB67D, 0, 0xB67E, 0x5379, 0, - 0x3A24, 0xB67C, 0x304F, 0x3F5E, 0, 0, 0xB721, 0xB722, - 0, 0x537A, 0x3847, 0, 0, 0x3971, 0, 0x537C, -}; -static const unsigned short utf8_to_euc_E59B_x0213[] = { - 0x5373, 0x5371, 0x536F, 0x5372, 0, 0xA453, 0, 0, - 0x5374, 0x2F3F, 0x2F40, 0xB66D, 0xB670, 0xA454, 0x5375, 0xB66E, - 0xB66F, 0x5376, 0, 0x5377, 0, 0, 0, 0x5378, - 0x5145, 0xB672, 0x3C7C, 0x3B4D, 0xB673, 0xB674, 0x3273, 0xA455, - 0x3078, 0xB676, 0, 0x4344, 0xB677, 0xB678, 0xB679, 0xB67A, - 0xA456, 0, 0, 0xB67D, 0, 0xB67E, 0x5379, 0, - 0x3A24, 0xB67C, 0x304F, 0x3F5E, 0, 0, 0xA457, 0xA458, - 0, 0x537A, 0x3847, 0, 0, 0x3971, 0, 0x537C, -}; -static const unsigned short utf8_to_euc_E59C[] = { - 0x537B, 0xB723, 0xB724, 0x4A60, 0x537D, 0, 0, 0xB725, - 0x5421, 0x537E, 0xB726, 0x5422, 0xB727, 0x5423, 0, 0x3777, - 0, 0xB728, 0x3160, 0x5424, 0, 0xB729, 0x5426, 0, - 0x5425, 0, 0xB72A, 0xB72B, 0x5428, 0xB72C, 0, 0x455A, - 0xB72D, 0, 0xB72E, 0xB72F, 0xB730, 0xB731, 0x5429, 0x3035, - 0x3A5F, 0xB732, 0xB733, 0, 0xB734, 0x373D, 0xB735, 0xB736, - 0x434F, 0, 0, 0xB737, 0xB738, 0, 0, 0x542A, - 0x542B, 0, 0, 0x542D, 0, 0xB739, 0xB73A, 0xB73B, -}; -static const unsigned short utf8_to_euc_E59C_x0213[] = { - 0x537B, 0xB723, 0xB724, 0x4A60, 0x537D, 0, 0, 0xB725, - 0x5421, 0x537E, 0x2F41, 0x5422, 0xB727, 0x5423, 0, 0x3777, - 0, 0xB728, 0x3160, 0x5424, 0, 0xA45A, 0x5426, 0, - 0x5425, 0, 0xB72A, 0xB72B, 0x5428, 0xB72C, 0, 0x455A, - 0xB72D, 0x2F43, 0xB72E, 0xA45B, 0xB730, 0xB731, 0x5429, 0x3035, - 0x3A5F, 0xA45D, 0xB733, 0, 0xB734, 0x373D, 0xB735, 0x2F44, - 0x434F, 0, 0, 0x2F45, 0x2F46, 0, 0, 0x542A, - 0x542B, 0, 0, 0x542D, 0, 0xB739, 0xB73A, 0xB73B, -}; -static const unsigned short utf8_to_euc_E59D[] = { - 0x542E, 0, 0x3A64, 0, 0, 0xB73C, 0xB73D, 0x3651, - 0, 0, 0x4B37, 0, 0xB73E, 0xB73F, 0x542C, 0x542F, - 0x3A41, 0x3923, 0xB740, 0, 0, 0, 0, 0, - 0, 0xF436, 0, 0, 0, 0, 0, 0, - 0, 0x5433, 0xB741, 0, 0x3A25, 0xB742, 0x4333, 0xB743, - 0xB744, 0x5430, 0x445A, 0xB745, 0, 0xB746, 0xB747, 0xB748, - 0xB749, 0xB74A, 0, 0xB74B, 0xB74C, 0xB74D, 0, 0xB74E, - 0, 0xB74F, 0xB750, 0xB751, 0xB752, 0, 0xB753, 0x5434, -}; -static const unsigned short utf8_to_euc_E59D_x0213[] = { - 0x542E, 0, 0x3A64, 0, 0, 0xA45F, 0xA460, 0x3651, - 0, 0, 0x4B37, 0, 0xA461, 0xA462, 0x542C, 0x542F, - 0x3A41, 0x3923, 0xB740, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0x5433, 0xB741, 0, 0x3A25, 0, 0x4333, 0xB743, - 0xA464, 0x5430, 0x445A, 0xB745, 0, 0xB746, 0xB747, 0xA465, - 0x2F47, 0xB74A, 0, 0xA466, 0xA467, 0xA468, 0, 0x2F48, - 0, 0xB74F, 0xB750, 0xA469, 0x2F49, 0, 0xB753, 0x5434, -}; -static const unsigned short utf8_to_euc_E59E[] = { - 0, 0xB754, 0x3F62, 0xB755, 0, 0, 0, 0, - 0x5432, 0x5435, 0, 0x373F, 0xB756, 0, 0, 0, - 0, 0, 0, 0x5436, 0xB757, 0xB760, 0, 0xB758, - 0, 0xB759, 0xB75A, 0, 0xB75B, 0xB75C, 0xB75D, 0xB75E, - 0x5437, 0xB75F, 0x3924, 0x3340, 0x5439, 0, 0, 0xB761, - 0xB762, 0xB763, 0x543A, 0, 0xB764, 0, 0, 0, - 0x543B, 0, 0, 0x5438, 0, 0, 0, 0, - 0xB765, 0, 0, 0, 0, 0xB766, 0, 0, -}; -static const unsigned short utf8_to_euc_E59E_x0213[] = { - 0, 0xB754, 0x3F62, 0xB755, 0, 0, 0, 0, - 0x5432, 0x5435, 0, 0x373F, 0xB756, 0, 0, 0, - 0, 0, 0, 0x5436, 0xB757, 0xB760, 0, 0xB758, - 0, 0xB759, 0xA46D, 0, 0x2F4A, 0xA46E, 0xA46F, 0xB75E, - 0x5437, 0xB75F, 0x3924, 0x3340, 0x5439, 0, 0, 0xB761, - 0xA470, 0xB763, 0x543A, 0, 0xA46C, 0, 0, 0, - 0x543B, 0, 0, 0x5438, 0, 0, 0, 0, - 0x2F4D, 0, 0, 0, 0, 0xB766, 0, 0, -}; -static const unsigned short utf8_to_euc_E59F[] = { - 0x5431, 0, 0, 0x543C, 0, 0, 0x543D, 0xB767, - 0xB768, 0, 0, 0x4B64, 0xB769, 0, 0x3E6B, 0xB76A, - 0, 0, 0x543F, 0x5440, 0x543E, 0xB76B, 0x5442, 0, - 0, 0, 0, 0, 0x4738, 0xB76C, 0xB76D, 0x3068, - 0x4956, 0xB77E, 0, 0x5443, 0xB76E, 0, 0xB76F, 0xB770, - 0, 0xB771, 0, 0, 0, 0xB772, 0, 0, - 0xB773, 0, 0, 0, 0x3E7D, 0xB774, 0xB775, 0x3C39, - 0xB776, 0x475D, 0x3470, 0, 0x3A6B, 0xB777, 0xB778, 0xB779, -}; -static const unsigned short utf8_to_euc_E59F_x0213[] = { - 0x5431, 0, 0, 0x543C, 0, 0, 0x543D, 0x2F4E, - 0x2F4F, 0, 0, 0x4B64, 0xA473, 0, 0x3E6B, 0x2F50, - 0, 0, 0x543F, 0x5440, 0x543E, 0xB76B, 0x5442, 0xA471, - 0, 0, 0, 0, 0x4738, 0xB76C, 0xA476, 0x3068, - 0x4956, 0xB77E, 0, 0x5443, 0x2F51, 0, 0xA477, 0xB770, - 0, 0xB771, 0, 0, 0, 0x2F52, 0, 0, - 0xA478, 0, 0, 0, 0x3E7D, 0x2F53, 0x2F54, 0x3C39, - 0xA47A, 0x475D, 0x3470, 0xA47B, 0x3A6B, 0xA47C, 0xB778, 0x2F55, -}; -static const unsigned short utf8_to_euc_E5A0[] = { - 0x4B59, 0, 0x4632, 0xB77A, 0xB77B, 0x3778, 0x424F, 0, - 0xB77C, 0xB77D, 0x5441, 0x5444, 0xB821, 0xB822, 0, 0, - 0, 0, 0, 0, 0, 0x4244, 0, 0, - 0, 0x5445, 0, 0xB823, 0, 0x5446, 0xB824, 0xB825, - 0xB826, 0x5448, 0, 0, 0x4469, 0, 0xB827, 0xB828, - 0, 0, 0x342E, 0, 0, 0xB829, 0, 0x7421, - 0x3161, 0x4A73, 0xB82A, 0, 0x3E6C, 0x4548, 0, 0, - 0, 0xB82B, 0x3A66, 0, 0, 0x544E, 0, 0xB82C, -}; -static const unsigned short utf8_to_euc_E5A0_x0213[] = { - 0x4B59, 0, 0x4632, 0xB77A, 0xA47D, 0x3778, 0x424F, 0, - 0xB77C, 0x2F56, 0x5441, 0x5444, 0xB821, 0xB822, 0, 0, - 0, 0, 0, 0, 0, 0x4244, 0, 0, - 0, 0x5445, 0, 0xB823, 0, 0x5446, 0xA47E, 0xB825, - 0xA521, 0x5448, 0, 0, 0x4469, 0, 0xB827, 0xA522, - 0, 0, 0x342E, 0, 0, 0xB829, 0, 0x7421, - 0x3161, 0x4A73, 0xA523, 0, 0x3E6C, 0x4548, 0, 0, - 0, 0xA524, 0x3A66, 0, 0, 0x544E, 0, 0xB82C, -}; -static const unsigned short utf8_to_euc_E5A1[] = { - 0x4A3D, 0x4E5D, 0, 0, 0, 0, 0, 0, - 0, 0xB82D, 0x3274, 0x544A, 0xB82E, 0xB82F, 0, 0xB830, - 0xB831, 0x413A, 0x544D, 0, 0x4563, 0xB832, 0, 0x4549, - 0x4564, 0x4839, 0x444D, 0, 0, 0, 0x3A49, 0xB833, - 0, 0xB834, 0x5449, 0, 0xB835, 0, 0, 0xB836, - 0xB837, 0x3176, 0, 0x4536, 0, 0, 0, 0, - 0x544B, 0, 0x5447, 0, 0, 0x3F50, 0, 0, - 0xB838, 0x544F, 0, 0, 0xB839, 0, 0x3D4E, 0xB83A, -}; -static const unsigned short utf8_to_euc_E5A1_x0213[] = { - 0x4A3D, 0x4E5D, 0, 0, 0, 0, 0, 0, - 0, 0xA526, 0x3274, 0x544A, 0xA527, 0xB82F, 0, 0xB830, - 0xB831, 0x413A, 0x544D, 0, 0x4563, 0xB832, 0, 0x4549, - 0x4564, 0x4839, 0x444D, 0, 0, 0, 0x3A49, 0xB833, - 0, 0x2F58, 0x5449, 0, 0x2F59, 0, 0, 0xA528, - 0xB837, 0x3176, 0, 0x4536, 0, 0, 0, 0, - 0x544B, 0, 0x5447, 0, 0, 0x3F50, 0, 0, - 0xB838, 0x544F, 0, 0, 0x2F5B, 0, 0x3D4E, 0xB83A, -}; -static const unsigned short utf8_to_euc_E5A2[] = { - 0xB83B, 0xB83C, 0, 0x362D, 0, 0x5450, 0, 0xB83D, - 0xB83E, 0xB83F, 0xB840, 0, 0xB841, 0xB842, 0, 0xB843, - 0xB844, 0, 0, 0x4A68, 0xB845, 0, 0xB846, 0x417D, - 0, 0, 0, 0, 0x4446, 0xB847, 0xF439, 0x5452, - 0xB848, 0xB849, 0xB84A, 0, 0, 0, 0xB84B, 0, - 0x4B4F, 0xB84C, 0, 0x5453, 0, 0, 0x5458, 0, - 0, 0xB84D, 0xB84E, 0x4A2F, 0, 0, 0, 0, - 0x5457, 0x5451, 0x5454, 0x5456, 0xB850, 0, 0x3A26, 0, -}; -static const unsigned short utf8_to_euc_E5A2_x0213[] = { - 0xB83B, 0xB83C, 0, 0x362D, 0, 0x5450, 0, 0xB83D, - 0xB83E, 0x2F5C, 0xA529, 0xA52A, 0xB841, 0xA52B, 0, 0xA52C, - 0xA52D, 0, 0, 0x4A68, 0xA52E, 0, 0xB846, 0x417D, - 0, 0, 0, 0, 0x4446, 0xA52F, 0x2F5D, 0x5452, - 0xB848, 0xB849, 0xB84A, 0, 0, 0, 0xB84B, 0, - 0x4B4F, 0x2F5F, 0xA530, 0x5453, 0, 0, 0x5458, 0, - 0, 0xA531, 0, 0x4A2F, 0, 0, 0, 0, - 0x5457, 0x5451, 0x5454, 0x5456, 0xB850, 0, 0x3A26, 0, -}; -static const unsigned short utf8_to_euc_E5A3[] = { - 0, 0x4A49, 0xB851, 0, 0xB84F, 0x5459, 0, 0x4345, - 0xB852, 0, 0x3275, 0, 0x3E6D, 0xB853, 0xB854, 0, - 0xB855, 0x545B, 0xB856, 0x545A, 0xB857, 0x3968, 0xB858, 0x545C, - 0x545E, 0x545D, 0xB859, 0, 0x5460, 0xB85A, 0x5455, 0x5462, - 0, 0xB85B, 0xB85C, 0, 0x5461, 0x545F, 0, 0, - 0, 0xB85D, 0, 0x3B4E, 0x3F51, 0, 0x4154, 0x5463, - 0x403C, 0x306D, 0x4764, 0xB85E, 0, 0, 0, 0x445B, - 0, 0x5465, 0x5464, 0x5466, 0x5467, 0x5468, 0, 0, -}; -static const unsigned short utf8_to_euc_E5A3_x0213[] = { - 0, 0x4A49, 0xB851, 0xA533, 0xB84F, 0x5459, 0, 0x4345, - 0xB852, 0, 0x3275, 0, 0x3E6D, 0xA534, 0x2F62, 0, - 0xB855, 0x545B, 0x2F61, 0x545A, 0x2F63, 0x3968, 0xB858, 0x545C, - 0x545E, 0x545D, 0x2F64, 0, 0x5460, 0xB85A, 0x5455, 0x5462, - 0x2F65, 0xB85B, 0xA535, 0, 0x5461, 0x545F, 0, 0, - 0, 0x2F66, 0, 0x3B4E, 0x3F51, 0, 0x4154, 0x5463, - 0x403C, 0x306D, 0x4764, 0xA536, 0xA537, 0, 0, 0x445B, - 0, 0x5465, 0x5464, 0x5466, 0x5467, 0x5468, 0, 0, -}; -static const unsigned short utf8_to_euc_E5A4[] = { - 0, 0, 0x5469, 0, 0, 0xB85F, 0xB860, 0, - 0, 0x4A51, 0x546A, 0xB861, 0xB862, 0, 0, 0x3246, - 0x546B, 0, 0xB863, 0xB864, 0xB865, 0x4D3C, 0x3330, 0, - 0x5249, 0x3D48, 0x423F, 0x546C, 0x4C6B, 0xB867, 0, 0, - 0, 0xB868, 0x4C34, 0xB869, 0xB86A, 0x546E, 0, 0x4267, - 0xB86B, 0x4537, 0x4240, 0x4957, 0x546F, 0x5470, 0x317B, 0xB86C, - 0xB86D, 0x3C3A, 0x5471, 0xB86E, 0, 0xB86F, 0xB870, 0x3050, - 0x5472, 0, 0, 0, 0, 0, 0x5473, 0xB871, -}; -static const unsigned short utf8_to_euc_E5A4_x0213[] = { - 0, 0, 0x5469, 0, 0, 0xA538, 0xA539, 0, - 0, 0x4A51, 0x546A, 0xA53A, 0x2F67, 0xA53B, 0, 0x3246, - 0x546B, 0, 0xB863, 0xB864, 0xA53C, 0x4D3C, 0x3330, 0, - 0x5249, 0x3D48, 0x423F, 0x546C, 0x4C6B, 0xB867, 0, 0, - 0, 0xB868, 0x4C34, 0xB869, 0xA53D, 0x546E, 0, 0x4267, - 0xB86B, 0x4537, 0x4240, 0x4957, 0x546F, 0x5470, 0x317B, 0xB86C, - 0xB86D, 0x3C3A, 0x5471, 0xB86E, 0, 0xB86F, 0xB870, 0x3050, - 0x5472, 0, 0, 0, 0, 0xA540, 0x5473, 0xB871, -}; -static const unsigned short utf8_to_euc_E5A5[] = { - 0, 0, 0, 0xB872, 0x3162, 0, 0xB873, 0x3471, - 0x4660, 0x4A74, 0, 0, 0, 0, 0x5477, 0x4155, - 0x5476, 0x3740, 0xB874, 0xB875, 0x4B5B, 0x5475, 0, 0x4565, - 0x5479, 0xB876, 0x5478, 0xB877, 0, 0xB878, 0xB879, 0xB87A, - 0x547B, 0xB87B, 0x547A, 0xB87C, 0, 0x317C, 0, 0x547C, - 0x3E29, 0x547E, 0x4325, 0xB87D, 0x547D, 0xB87E, 0x4A33, 0xB921, - 0, 0, 0xB922, 0x3D77, 0x455B, 0xB923, 0xB924, 0, - 0x5521, 0xB925, 0, 0xB926, 0xB927, 0x3925, 0, 0, -}; -static const unsigned short utf8_to_euc_E5A5_x0213[] = { - 0, 0, 0, 0xB872, 0x3162, 0, 0xA542, 0x3471, - 0x4660, 0x4A74, 0, 0, 0, 0, 0x5477, 0x4155, - 0x5476, 0x3740, 0xB874, 0, 0x4B5B, 0x5475, 0, 0x4565, - 0x5479, 0xB876, 0x5478, 0xA545, 0, 0x2F69, 0xB879, 0xA546, - 0x547B, 0xB87B, 0x547A, 0, 0, 0x317C, 0, 0x547C, - 0x3E29, 0x547E, 0x4325, 0xB87D, 0x547D, 0x2F6A, 0x4A33, 0xB921, - 0, 0, 0xB922, 0x3D77, 0x455B, 0xA548, 0xA549, 0, - 0x5521, 0xB925, 0, 0xB926, 0xA54A, 0x3925, 0, 0, -}; -static const unsigned short utf8_to_euc_E5A6[] = { - 0, 0x5522, 0x4721, 0x485E, 0x4C51, 0, 0, 0, - 0, 0, 0x4725, 0xB928, 0xB929, 0x552B, 0xB92A, 0, - 0, 0, 0xB92B, 0x3538, 0, 0xB92C, 0x4D45, 0xB92D, - 0, 0x4C2F, 0, 0x562C, 0, 0x5523, 0, 0xB92E, - 0, 0, 0, 0x5526, 0xB92F, 0x4245, 0, 0xB930, - 0x4B38, 0, 0, 0, 0x454A, 0xB931, 0xB932, 0xB933, - 0xB934, 0, 0x5527, 0xB935, 0, 0, 0, 0xB936, - 0, 0x4B65, 0xB937, 0x3A4A, 0xB938, 0, 0x3E2A, 0, -}; -static const unsigned short utf8_to_euc_E5A6_x0213[] = { - 0, 0x5522, 0x4721, 0x485E, 0x4C51, 0, 0, 0, - 0, 0, 0x4725, 0x2F6B, 0xB929, 0x552B, 0xB92A, 0, - 0, 0, 0x2F6C, 0x3538, 0, 0xB92C, 0x4D45, 0xB92D, - 0, 0x4C2F, 0, 0x562C, 0, 0x5523, 0, 0xA54B, - 0, 0, 0, 0x5526, 0x2F6D, 0x4245, 0, 0xB930, - 0x4B38, 0, 0, 0, 0x454A, 0xB931, 0xA54C, 0xB933, - 0xB934, 0, 0x5527, 0xB935, 0, 0, 0, 0xB936, - 0, 0x4B65, 0, 0x3A4A, 0xA54D, 0, 0x3E2A, 0, -}; -static const unsigned short utf8_to_euc_E5A7[] = { - 0, 0xB939, 0, 0xB93A, 0xB93B, 0, 0x5528, 0, - 0xB93C, 0x3B50, 0xB93D, 0x3B4F, 0, 0xB93E, 0, 0, - 0x3039, 0x3848, 0xB93F, 0x402B, 0x3051, 0, 0, 0, - 0, 0x552C, 0x552D, 0, 0x552A, 0xB940, 0xB941, 0xB942, - 0, 0, 0, 0xB943, 0xB944, 0x3138, 0x342F, 0xB945, - 0x5529, 0, 0x4C45, 0x4931, 0, 0, 0xB946, 0xB947, - 0, 0xB948, 0xB949, 0, 0xB94A, 0, 0x3028, 0xB94B, - 0, 0, 0, 0x3079, 0, 0, 0, 0x3B51, -}; -static const unsigned short utf8_to_euc_E5A7_x0213[] = { - 0, 0xB939, 0, 0x2F6E, 0xB93B, 0, 0x5528, 0, - 0xA54E, 0x3B50, 0xB93D, 0x3B4F, 0, 0xA54F, 0, 0, - 0x3039, 0x3848, 0x2F6F, 0x402B, 0x3051, 0, 0, 0, - 0, 0x552C, 0x552D, 0, 0x552A, 0x2F70, 0xA550, 0xB942, - 0, 0, 0, 0xA551, 0xA552, 0x3138, 0x342F, 0xA553, - 0x5529, 0, 0x4C45, 0x4931, 0, 0, 0xA554, 0xB947, - 0, 0xB948, 0xB949, 0, 0xB94A, 0, 0x3028, 0xB94B, - 0x7E7A, 0, 0, 0x3079, 0, 0, 0, 0x3B51, -}; -static const unsigned short utf8_to_euc_E5A8[] = { - 0xB94C, 0x3052, 0, 0x3023, 0xB94D, 0, 0, 0, - 0, 0x5532, 0, 0, 0xB94E, 0xB94F, 0xB950, 0, - 0, 0x5530, 0xB951, 0xB952, 0, 0, 0, 0, - 0x4C3C, 0, 0x5533, 0, 0x5531, 0, 0xB953, 0x552F, - 0x3F31, 0, 0, 0xB954, 0xB955, 0x552E, 0, 0xB956, - 0xB957, 0x4A5A, 0xB958, 0, 0, 0xB959, 0, 0x3864, - 0xB95A, 0, 0, 0, 0, 0x5537, 0x5538, 0, - 0, 0, 0, 0, 0x3E2B, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E5A8_x0213[] = { - 0xB94C, 0x3052, 0, 0x3023, 0xB94D, 0, 0, 0, - 0, 0x5532, 0, 0, 0xA558, 0xA559, 0xB950, 0, - 0, 0x5530, 0xB951, 0x2F71, 0, 0, 0, 0xA55A, - 0x4C3C, 0, 0x5533, 0, 0x5531, 0, 0xB953, 0x552F, - 0x3F31, 0, 0, 0x2F72, 0xB955, 0x552E, 0, 0xA55B, - 0xB957, 0x4A5A, 0xB958, 0, 0, 0xA55C, 0, 0x3864, - 0xB95A, 0, 0, 0, 0, 0x5537, 0x5538, 0, - 0, 0, 0, 0, 0x3E2B, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E5A9[] = { - 0x5534, 0x4F2C, 0, 0, 0xB95B, 0xB95C, 0x474C, 0xB95D, - 0xB95E, 0x5536, 0, 0, 0xB95F, 0, 0, 0, - 0xB960, 0, 0, 0, 0, 0xB961, 0, 0, - 0, 0, 0x3A27, 0, 0, 0, 0xB962, 0, - 0, 0, 0x5539, 0xB963, 0, 0xB964, 0x4958, 0xB965, - 0, 0, 0x553A, 0, 0x5535, 0xB966, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0xB967, - 0, 0, 0xB968, 0xB969, 0, 0, 0xB96A, 0x4C3B, -}; -static const unsigned short utf8_to_euc_E5A9_x0213[] = { - 0x5534, 0x4F2C, 0, 0, 0xB95B, 0xB95C, 0x474C, 0xB95D, - 0xB95E, 0x5536, 0, 0, 0xB95F, 0, 0, 0, - 0xB960, 0, 0, 0, 0, 0xA55D, 0, 0, - 0, 0, 0x3A27, 0, 0, 0, 0xB962, 0, - 0, 0, 0x5539, 0xB963, 0, 0xA55E, 0x4958, 0x2F73, - 0, 0, 0x553A, 0, 0x5535, 0x2F74, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0x2F75, - 0, 0, 0xA55F, 0xB969, 0, 0, 0x2F76, 0x4C3B, -}; -static const unsigned short utf8_to_euc_E5AA[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0xB96B, 0, 0, 0, 0, - 0xB96C, 0, 0x475E, 0xB96D, 0, 0, 0xB96E, 0, - 0, 0xB96F, 0x553B, 0x4932, 0xB970, 0, 0xB971, 0xB972, - 0xB973, 0, 0xB974, 0, 0, 0, 0, 0xB975, - 0, 0, 0, 0, 0xB976, 0, 0, 0, - 0, 0xB977, 0xB978, 0xB979, 0, 0xB97A, 0, 0, - 0xB97B, 0, 0xB97C, 0xB97D, 0x553C, 0x5540, 0x553D, 0xB97E, -}; -static const unsigned short utf8_to_euc_E5AA_x0213[] = { - 0, 0, 0, 0, 0x2F77, 0, 0, 0, - 0, 0, 0, 0xA560, 0, 0, 0, 0, - 0xB96C, 0, 0x475E, 0xB96D, 0, 0, 0xB96E, 0, - 0, 0xB96F, 0x553B, 0x4932, 0xA561, 0, 0x2F78, 0xA562, - 0xA563, 0, 0xA564, 0, 0, 0, 0, 0x2F79, - 0, 0, 0, 0, 0xB976, 0, 0, 0, - 0, 0xA565, 0xB978, 0xA566, 0, 0xA567, 0, 0, - 0xB97B, 0, 0xA568, 0xB97D, 0x553C, 0x5540, 0x553D, 0xA569, -}; -static const unsigned short utf8_to_euc_E5AB[] = { - 0, 0x3247, 0x553F, 0, 0xBA21, 0, 0xBA22, 0, - 0xBA23, 0x3C3B, 0, 0x553E, 0x3779, 0, 0, 0xBA24, - 0x554C, 0, 0, 0, 0, 0, 0x5545, 0x5542, - 0, 0, 0xBA25, 0, 0xBA26, 0, 0, 0, - 0xBA27, 0x4364, 0, 0x5541, 0, 0xBA28, 0x5543, 0, - 0, 0x5544, 0xBA29, 0, 0, 0, 0xBA2A, 0, - 0, 0, 0, 0, 0, 0xBA2B, 0xBA2C, 0, - 0, 0, 0x5546, 0x5547, 0, 0xBA2D, 0, 0, -}; -static const unsigned short utf8_to_euc_E5AB_x0213[] = { - 0, 0x3247, 0x553F, 0, 0x2F7A, 0, 0xBA22, 0, - 0xBA23, 0x3C3B, 0, 0x553E, 0x3779, 0, 0, 0xBA24, - 0x554C, 0, 0, 0, 0, 0, 0x5545, 0x5542, - 0, 0, 0xA56A, 0, 0xA56B, 0, 0, 0, - 0xA56C, 0x4364, 0, 0x5541, 0, 0xA56D, 0x5543, 0, - 0, 0x5544, 0xBA29, 0, 0, 0, 0xA56F, 0, - 0xA56E, 0, 0, 0, 0, 0xA570, 0xBA2C, 0, - 0, 0, 0x5546, 0x5547, 0, 0xBA2D, 0, 0, -}; -static const unsigned short utf8_to_euc_E5AC[] = { - 0xBA2E, 0xBA2F, 0, 0, 0, 0, 0, 0, - 0xBA30, 0x3472, 0, 0x5549, 0x5548, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0x554A, 0xBA31, - 0, 0xBA33, 0, 0xBA34, 0, 0xBA35, 0, 0, - 0, 0xBA36, 0x3E6E, 0, 0, 0xBA37, 0, 0, - 0, 0, 0x554D, 0, 0x445C, 0xBA38, 0, 0, - 0x3145, 0, 0x554B, 0, 0xBA32, 0, 0x554E, 0, - 0xBA39, 0, 0, 0, 0, 0, 0x554F, 0, -}; -static const unsigned short utf8_to_euc_E5AC_x0213[] = { - 0xA571, 0xBA2F, 0, 0, 0, 0, 0, 0, - 0xA572, 0x3472, 0, 0x5549, 0x5548, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0x554A, 0xA573, - 0, 0x2F7C, 0, 0xBA34, 0, 0xBA35, 0, 0, - 0, 0xBA36, 0x3E6E, 0, 0, 0x2F7D, 0, 0, - 0, 0, 0x554D, 0, 0x445C, 0xA575, 0, 0, - 0x3145, 0, 0x554B, 0, 0xA574, 0, 0x554E, 0, - 0xBA39, 0, 0, 0, 0, 0, 0x554F, 0, -}; -static const unsigned short utf8_to_euc_E5AD[] = { - 0x5552, 0xBA3A, 0, 0x5550, 0, 0x5551, 0, 0, - 0, 0, 0, 0xBA3B, 0xBA3C, 0, 0, 0, - 0x3B52, 0x5553, 0xBA3D, 0, 0x3926, 0x5554, 0xBA3E, 0x3B7A, - 0x4238, 0, 0x5555, 0x5556, 0x3B5A, 0x3927, 0xBA3F, 0x4C52, - 0, 0, 0, 0x3528, 0x3849, 0x5557, 0x3358, 0, - 0xBA40, 0x5558, 0, 0x4239, 0, 0, 0xBA41, 0xBA42, - 0x5559, 0x5623, 0, 0x555A, 0, 0x555B, 0, 0, - 0x555C, 0, 0x555E, 0, 0xBA43, 0xBA44, 0xBA45, 0xBA46, -}; -static const unsigned short utf8_to_euc_E5AD_x0213[] = { - 0x5552, 0x4F55, 0, 0x5550, 0, 0x5551, 0, 0, - 0, 0, 0, 0xBA3B, 0xA576, 0, 0, 0, - 0x3B52, 0x5553, 0xA577, 0, 0x3926, 0x5554, 0x4F56, 0x3B7A, - 0x4238, 0, 0x5555, 0x5556, 0x3B5A, 0x3927, 0xBA3F, 0x4C52, - 0, 0, 0, 0x3528, 0x3849, 0x5557, 0x3358, 0, - 0xA578, 0x5558, 0, 0x4239, 0, 0, 0xBA41, 0xA579, - 0x5559, 0x5623, 0, 0x555A, 0, 0x555B, 0, 0, - 0x555C, 0, 0x555E, 0, 0xA57A, 0x4F57, 0xBA45, 0xA57B, -}; -static const unsigned short utf8_to_euc_E5AE[] = { - 0x555F, 0xBA47, 0, 0x5560, 0xBA48, 0x4270, 0xBA49, 0x3127, - 0x3C69, 0x3042, 0xBA4A, 0x4157, 0x3430, 0x3C35, 0xBA4B, 0x3928, - 0xBA4C, 0xBA4D, 0, 0xBA4E, 0xBA4F, 0x4566, 0xBA50, 0x3D21, - 0x3431, 0x4368, 0x446A, 0x3038, 0x3539, 0x4A75, 0, 0x3C42, - 0, 0, 0x3552, 0x406B, 0x3C3C, 0x4D28, 0x5561, 0, - 0xBA51, 0xBA52, 0, 0, 0xBA53, 0xBA54, 0x355C, 0xBA55, - 0x3A4B, 0xBA56, 0xBA57, 0x3332, 0x3163, 0x3E2C, 0x3248, 0xBA58, - 0x5562, 0x4D46, 0xBA59, 0, 0xBA5A, 0, 0, 0x3D49, -}; -static const unsigned short utf8_to_euc_E5AE_x0213[] = { - 0x555F, 0xA57C, 0, 0x5560, 0xA57D, 0x4270, 0xBA49, 0x3127, - 0x3C69, 0x3042, 0xBA4A, 0x4157, 0x3430, 0x3C35, 0xBA4B, 0x3928, - 0xBA4C, 0xBA4D, 0, 0x4F58, 0xBA4F, 0x4566, 0xA821, 0x3D21, - 0x3431, 0x4368, 0x446A, 0x3038, 0x3539, 0x4A75, 0, 0x3C42, - 0, 0, 0x3552, 0x406B, 0x3C3C, 0x4D28, 0x5561, 0, - 0xBA51, 0xBA52, 0, 0, 0xA822, 0xBA54, 0x355C, 0xBA55, - 0x3A4B, 0xBA56, 0xBA57, 0x3332, 0x3163, 0x3E2C, 0x3248, 0xBA58, - 0x5562, 0x4D46, 0xBA59, 0, 0xBA5A, 0, 0, 0x3D49, -}; -static const unsigned short utf8_to_euc_E5AF[] = { - 0xBA5B, 0xBA5C, 0x3C64, 0x5563, 0x3473, 0x4652, 0x4C29, 0x5564, - 0, 0x5565, 0, 0, 0x4959, 0xBA5D, 0, 0xBA5E, - 0x5567, 0, 0x3428, 0x3677, 0x5566, 0, 0xBA5F, 0xBA60, - 0xBA61, 0xBA62, 0xBA63, 0x3432, 0, 0x3F32, 0x556B, 0x3B21, - 0xBA64, 0x3249, 0x556A, 0, 0x5568, 0x556C, 0x5569, 0x472B, - 0x5C4D, 0x3F33, 0, 0x556D, 0xF43A, 0, 0x4E40, 0xBA65, - 0x556E, 0xBA66, 0, 0x5570, 0xBA67, 0x437E, 0x556F, 0, - 0x4023, 0, 0x3B7B, 0, 0, 0xBA68, 0x4250, 0x3C77, -}; -static const unsigned short utf8_to_euc_E5AF_x0213[] = { - 0xA824, 0xBA5C, 0x3C64, 0x5563, 0x3473, 0x4652, 0x4C29, 0x5564, - 0, 0x5565, 0, 0, 0x4959, 0xBA5D, 0xA826, 0xBA5E, - 0x5567, 0, 0x3428, 0x3677, 0x5566, 0, 0xA827, 0xBA60, - 0x4F59, 0xBA62, 0xBA63, 0x3432, 0, 0x3F32, 0x556B, 0x3B21, - 0xBA64, 0x3249, 0x556A, 0, 0x5568, 0x556C, 0x5569, 0x472B, - 0x5C4D, 0x3F33, 0, 0x556D, 0x4F5A, 0, 0x4E40, 0xBA65, - 0x556E, 0xA82A, 0, 0x5570, 0xBA67, 0x437E, 0x556F, 0, - 0x4023, 0, 0x3B7B, 0, 0, 0xA82B, 0x4250, 0x3C77, -}; -static const unsigned short utf8_to_euc_E5B0[] = { - 0, 0x4975, 0x406C, 0, 0x3C4D, 0x5571, 0x3E2D, 0x5572, - 0x5573, 0x3053, 0x423A, 0x3F52, 0xBA69, 0x5574, 0x4633, 0x3E2E, - 0, 0x3E2F, 0, 0x5575, 0, 0, 0x406D, 0xBA6A, - 0, 0, 0x3E30, 0, 0, 0, 0xBA6B, 0xBA6C, - 0x5576, 0, 0x5577, 0xBA6D, 0x4C60, 0, 0xBA6E, 0, - 0x5578, 0xBA6F, 0, 0xBA70, 0xBA71, 0x3646, 0xBA72, 0, - 0xBA73, 0x3D22, 0xBA74, 0, 0, 0xBA75, 0xBA76, 0, - 0x5579, 0x557A, 0x3C5C, 0x3F2C, 0x4674, 0x3F54, 0x4878, 0x4722, -}; -static const unsigned short utf8_to_euc_E5B0_x0213[] = { - 0, 0x4975, 0x406C, 0xA82D, 0x3C4D, 0x5571, 0x3E2D, 0x5572, - 0x5573, 0x3053, 0x423A, 0x3F52, 0xBA69, 0x5574, 0x4633, 0x3E2E, - 0, 0x3E2F, 0x4F5B, 0x5575, 0, 0, 0x406D, 0xBA6A, - 0, 0, 0x3E30, 0, 0, 0, 0x4F5C, 0xBA6C, - 0x5576, 0, 0x5577, 0x4F5D, 0x4C60, 0, 0xBA6E, 0, - 0x5578, 0xA82E, 0, 0x4F5E, 0xBA71, 0x3646, 0xBA72, 0, - 0xA82F, 0x3D22, 0xBA74, 0, 0, 0xBA75, 0xBA76, 0, - 0x5579, 0x557A, 0x3C5C, 0x3F2C, 0x4674, 0x3F54, 0x4878, 0x4722, -}; -static const unsigned short utf8_to_euc_E5B1[] = { - 0x3649, 0x557B, 0, 0, 0, 0x356F, 0x557C, 0, - 0x367E, 0, 0x464F, 0x3230, 0, 0x3B53, 0x557D, 0x5622, - 0x5621, 0x367D, 0, 0x557E, 0, 0x4538, 0, 0, - 0, 0xBA77, 0xBA78, 0, 0xBA79, 0, 0x4230, 0, - 0x454B, 0x3C48, 0xBA7A, 0xBA7B, 0x4158, 0x4D7A, 0, 0xBA7C, - 0xBA7D, 0xBA7E, 0, 0, 0x5624, 0xBB21, 0x5625, 0x4656, - 0xBB22, 0x3B33, 0, 0, 0xBB23, 0xBB24, 0x5627, 0, - 0, 0x5628, 0xBB25, 0xBB26, 0xBB27, 0xBB28, 0, 0, -}; -static const unsigned short utf8_to_euc_E5B1_x0213[] = { - 0x3649, 0x557B, 0, 0, 0, 0x356F, 0x557C, 0, - 0x367E, 0, 0x464F, 0x3230, 0, 0x3B53, 0x557D, 0x5622, - 0x5621, 0x367D, 0, 0x557E, 0, 0x4538, 0, 0, - 0, 0xBA77, 0xBA78, 0x7E7B, 0xBA79, 0, 0x4230, 0xA831, - 0x454B, 0x3C48, 0x4F60, 0xA832, 0x4158, 0x4D7A, 0, 0xA833, - 0xA834, 0xA835, 0, 0, 0x5624, 0xBB21, 0x5625, 0x4656, - 0xA836, 0x3B33, 0, 0, 0xBB23, 0xBB24, 0x5627, 0, - 0, 0x5628, 0x4F64, 0xBB26, 0xA839, 0xBB28, 0, 0, -}; -static const unsigned short utf8_to_euc_E5B2[] = { - 0, 0, 0, 0, 0, 0, 0, 0xBB29, - 0xBB2A, 0, 0xBB2B, 0, 0x5629, 0, 0, 0xBB2C, - 0x3474, 0x562A, 0xBB2D, 0, 0x562B, 0, 0, 0, - 0, 0, 0, 0, 0, 0xBB2E, 0, 0xBB2F, - 0xBB30, 0x322C, 0xBB31, 0xBB32, 0, 0, 0xBB33, 0, - 0x413B, 0x3464, 0xBB34, 0x562D, 0x4C28, 0, 0, 0, - 0, 0x4252, 0xBB35, 0x3359, 0xBB36, 0xBB37, 0x562F, 0x5631, - 0x345F, 0, 0xBB38, 0x562E, 0x5630, 0, 0x5633, 0, -}; -static const unsigned short utf8_to_euc_E5B2_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0xBB29, - 0xA83C, 0, 0xA83D, 0, 0x5629, 0, 0, 0x4F65, - 0x3474, 0x562A, 0xBB2D, 0, 0x562B, 0, 0, 0, - 0, 0, 0, 0, 0, 0xBB2E, 0, 0x4F66, - 0xA841, 0x322C, 0xA842, 0x4F67, 0, 0, 0xA843, 0xA844, - 0x413B, 0x3464, 0x4F68, 0x562D, 0x4C28, 0xA846, 0, 0, - 0, 0x4252, 0xBB35, 0x3359, 0xBB36, 0xA847, 0x562F, 0x5631, - 0x345F, 0, 0x4F69, 0x562E, 0x5630, 0, 0x5633, 0, -}; -static const unsigned short utf8_to_euc_E5B3[] = { - 0, 0, 0, 0, 0, 0x5632, 0, 0x5634, - 0, 0xBB39, 0, 0xBB3A, 0, 0, 0, 0, - 0, 0, 0xBB3B, 0, 0, 0, 0, 0xBB3D, - 0, 0x5635, 0, 0, 0, 0xBB3C, 0, 0, - 0x463D, 0x362E, 0, 0, 0, 0, 0, 0, - 0x3265, 0x5636, 0x563B, 0, 0, 0x5639, 0xBB3E, 0x4A77, - 0x4A76, 0xBB3F, 0xBB40, 0, 0xBB41, 0xF43B, 0x4567, 0, - 0, 0, 0x5638, 0x3D54, 0, 0x5637, 0, 0, -}; -static const unsigned short utf8_to_euc_E5B3_x0213[] = { - 0, 0, 0, 0, 0, 0x5632, 0, 0x5634, - 0, 0xA849, 0, 0x4F6A, 0, 0, 0, 0, - 0x4F6B, 0, 0x4F6C, 0, 0, 0, 0, 0xBB3D, - 0, 0x5635, 0, 0, 0, 0xBB3C, 0, 0, - 0x463D, 0x362E, 0, 0, 0, 0, 0, 0, - 0x3265, 0x5636, 0x563B, 0, 0, 0x5639, 0xBB3E, 0x4A77, - 0x4A76, 0xBB3F, 0xBB40, 0, 0x4F6D, 0, 0x4567, 0, - 0, 0, 0x5638, 0x3D54, 0, 0x5637, 0, 0, -}; -static const unsigned short utf8_to_euc_E5B4[] = { - 0, 0xBB42, 0, 0, 0, 0, 0xBB43, 0x3F72, - 0, 0, 0, 0x563C, 0, 0xBB44, 0x3A6A, 0, - 0, 0x5642, 0xBB45, 0, 0x5643, 0x563D, 0x3333, 0x563E, - 0x5647, 0x5646, 0x5645, 0x5641, 0, 0, 0, 0x5640, - 0, 0, 0x5644, 0xBB47, 0xBB48, 0, 0xBB49, 0xBB4A, - 0, 0x4A78, 0, 0xBB46, 0, 0, 0, 0, - 0, 0xBB4B, 0, 0, 0xBB4C, 0, 0, 0, - 0, 0xBB4D, 0, 0, 0, 0xBB4E, 0, 0xBB4F, -}; -static const unsigned short utf8_to_euc_E5B4_x0213[] = { - 0, 0xBB42, 0, 0, 0, 0, 0xA84C, 0x3F72, - 0, 0, 0, 0x563C, 0, 0x4F70, 0x3A6A, 0, - 0xA84D, 0x5642, 0xBB45, 0, 0x5643, 0x563D, 0x3333, 0x563E, - 0x5647, 0x5646, 0x5645, 0x5641, 0, 0xA84F, 0, 0x5640, - 0xA850, 0, 0x5644, 0xBB47, 0xA851, 0, 0xA852, 0x4F71, - 0, 0x4A78, 0, 0xA84E, 0, 0, 0, 0, - 0, 0xA853, 0, 0, 0xBB4C, 0, 0, 0, - 0, 0xA854, 0, 0, 0, 0xBB4E, 0, 0xBB4F, -}; -static const unsigned short utf8_to_euc_E5B5[] = { - 0, 0, 0xBB50, 0xBB51, 0, 0, 0xBB52, 0, - 0xBB53, 0, 0xBB57, 0x564B, 0x5648, 0, 0x564A, 0, - 0x4D72, 0xBB55, 0x5649, 0xF43C, 0, 0xBB54, 0, 0, - 0, 0xBB56, 0, 0, 0x563F, 0, 0, 0xBB58, - 0xBB59, 0xBB5A, 0xBB5B, 0, 0xBB5C, 0, 0, 0, - 0, 0x3F73, 0xBB5D, 0, 0x564C, 0xBB5E, 0, 0x3A37, - 0xBB5F, 0, 0, 0x564D, 0, 0, 0x564E, 0, - 0, 0xBB60, 0xBB61, 0, 0, 0, 0xBB62, 0xBB63, -}; -static const unsigned short utf8_to_euc_E5B5_x0213[] = { - 0, 0, 0xA855, 0xBB51, 0, 0, 0x4F73, 0x4F74, - 0xBB53, 0, 0x4F76, 0x564B, 0x5648, 0, 0x564A, 0, - 0x4D72, 0xBB55, 0x5649, 0x4F75, 0, 0xBB54, 0, 0, - 0, 0xBB56, 0, 0, 0x563F, 0, 0, 0xBB58, - 0xBB59, 0xA857, 0xBB5B, 0, 0xBB5C, 0, 0, 0, - 0, 0x3F73, 0xA858, 0, 0x564C, 0x4F77, 0, 0x3A37, - 0xA85A, 0, 0, 0x564D, 0, 0, 0x564E, 0, - 0, 0xBB60, 0xBB61, 0, 0, 0, 0xBB62, 0xBB63, -}; -static const unsigned short utf8_to_euc_E5B6[] = { - 0, 0xBB64, 0x5651, 0xBB65, 0x5650, 0, 0, 0x564F, - 0xBB66, 0, 0xBB67, 0x4568, 0x563A, 0, 0, 0, - 0x5657, 0, 0xBB68, 0xBB69, 0xBB6A, 0xBB6B, 0, 0, - 0, 0xBB6C, 0, 0xBB6D, 0, 0x5653, 0, 0xBB6E, - 0xBB6F, 0, 0x5652, 0, 0, 0, 0, 0xBB70, - 0, 0, 0, 0xBB71, 0x5654, 0, 0x5655, 0, - 0xBB72, 0, 0xE674, 0, 0xBB73, 0, 0, 0x5658, - 0xBB74, 0xBB75, 0x4E66, 0, 0x5659, 0x5656, 0, 0, -}; -static const unsigned short utf8_to_euc_E5B6_x0213[] = { - 0, 0x4F78, 0x5651, 0xBB65, 0x5650, 0, 0, 0x564F, - 0xA85D, 0, 0xBB67, 0x4568, 0x563A, 0, 0, 0, - 0x5657, 0, 0xA85F, 0xBB69, 0xA860, 0xBB6B, 0, 0xA861, - 0, 0xA862, 0, 0xBB6D, 0, 0x5653, 0, 0xBB6E, - 0x4F79, 0, 0x5652, 0, 0x4F7A, 0, 0, 0x4F7B, - 0, 0, 0, 0xBB71, 0x5654, 0, 0x5655, 0, - 0xA863, 0, 0xA864, 0, 0xA865, 0, 0, 0x5658, - 0x4F7C, 0xA867, 0x4E66, 0, 0x5659, 0x5656, 0, 0, -}; -static const unsigned short utf8_to_euc_E5B7[] = { - 0, 0, 0, 0xBB76, 0, 0, 0, 0xBB77, - 0, 0x565A, 0, 0xBB78, 0x3460, 0x565B, 0xBB7A, 0, - 0xBB79, 0, 0x565D, 0x565C, 0, 0, 0x565E, 0, - 0xBB7B, 0xBB7C, 0, 0x565F, 0, 0x406E, 0x3D23, 0, - 0xBB7D, 0x3D64, 0, 0x4163, 0xBB7E, 0x3929, 0x3A38, 0x392A, - 0x3570, 0xBC21, 0, 0x5660, 0, 0, 0x3A39, 0, - 0, 0x384A, 0x5661, 0x4C26, 0x4743, 0x5662, 0, 0x392B, - 0xBC22, 0xBC23, 0, 0x342C, 0, 0x4327, 0x3652, 0, -}; -static const unsigned short utf8_to_euc_E5B7_x0213[] = { - 0, 0, 0, 0xBB76, 0, 0, 0, 0xBB77, - 0, 0x565A, 0, 0x4F7D, 0x3460, 0x565B, 0xBB7A, 0, - 0, 0xA868, 0x565D, 0x565C, 0, 0, 0x565E, 0xA869, - 0xA86A, 0xBB7C, 0, 0x565F, 0, 0x406E, 0x3D23, 0, - 0xA86B, 0x3D64, 0x7428, 0x4163, 0xA86D, 0x3929, 0x3A38, 0x392A, - 0x3570, 0xA86E, 0, 0x5660, 0, 0, 0x3A39, 0, - 0, 0x384A, 0x5661, 0x4C26, 0x4743, 0x5662, 0, 0x392B, - 0xBC22, 0xBC23, 0, 0x342C, 0, 0x4327, 0x3652, 0, -}; -static const unsigned short utf8_to_euc_E5B8[] = { - 0xBC24, 0, 0x3B54, 0x495B, 0, 0, 0x4841, 0xBC25, - 0, 0, 0, 0x5663, 0x3475, 0xBC26, 0, 0, - 0, 0x5666, 0xBC27, 0, 0xBC28, 0xBC29, 0x4421, 0, - 0xBC2A, 0x5665, 0x5664, 0x5667, 0, 0x446B, 0, 0xBC2B, - 0xBC2C, 0, 0, 0, 0, 0x3F63, 0, 0, - 0xBC2E, 0, 0, 0x3B55, 0, 0x404A, 0xBC2D, 0x4253, - 0x3522, 0, 0xBC2F, 0x4422, 0, 0xBC30, 0x5668, 0x5669, - 0x3E6F, 0, 0, 0, 0, 0x4B39, 0xBC31, 0, -}; -static const unsigned short utf8_to_euc_E5B8_x0213[] = { - 0xA870, 0, 0x3B54, 0x495B, 0, 0, 0x4841, 0xBC25, - 0, 0, 0, 0x5663, 0x3475, 0xBC26, 0, 0, - 0, 0x5666, 0xA872, 0, 0x7429, 0xA873, 0x4421, 0, - 0x742A, 0x5665, 0x5664, 0x5667, 0, 0x446B, 0, 0xA875, - 0xBC2C, 0, 0, 0, 0, 0x3F63, 0, 0, - 0xBC2E, 0, 0, 0x3B55, 0, 0x404A, 0xA876, 0x4253, - 0x3522, 0, 0xBC2F, 0x4422, 0, 0xBC30, 0x5668, 0x5669, - 0x3E6F, 0, 0, 0, 0, 0x4B39, 0xA877, 0, -}; -static const unsigned short utf8_to_euc_E5B9[] = { - 0x566C, 0, 0, 0x566B, 0x566A, 0x497D, 0, 0x5673, - 0, 0xBC34, 0, 0xBC32, 0x4B5A, 0, 0x566D, 0, - 0xBC33, 0xBC35, 0, 0, 0x566F, 0x4B6B, 0xBC36, 0x566E, - 0xBC37, 0, 0, 0xBC38, 0xBC39, 0, 0xBC3A, 0x5670, - 0, 0x4828, 0x5671, 0x4A3E, 0x5672, 0, 0, 0, - 0xBC3B, 0, 0xBC3C, 0xBC3D, 0xBC3E, 0xBC3F, 0xBC40, 0, - 0xBC41, 0, 0x3433, 0x4A3F, 0x472F, 0x5674, 0x5675, 0, - 0x392C, 0x3434, 0x5676, 0x3838, 0x4D44, 0x4D29, 0x3476, 0x5678, -}; -static const unsigned short utf8_to_euc_E5B9_x0213[] = { - 0x566C, 0, 0, 0x566B, 0x566A, 0x497D, 0, 0x5673, - 0, 0xA878, 0, 0xBC32, 0x4B5A, 0, 0x566D, 0, - 0xBC33, 0xBC35, 0, 0, 0x566F, 0x4B6B, 0xA87A, 0x566E, - 0x742B, 0, 0, 0xBC38, 0xBC39, 0, 0x742C, 0x5670, - 0, 0x4828, 0x5671, 0x4A3E, 0x5672, 0, 0, 0, - 0xBC3B, 0, 0xBC3C, 0xA87C, 0xA87D, 0xA87E, 0xAC21, 0, - 0xBC41, 0, 0x3433, 0x4A3F, 0x472F, 0x5674, 0x5675, 0x7E7C, - 0x392C, 0x3434, 0x5676, 0x3838, 0x4D44, 0x4D29, 0x3476, 0x5678, -}; -static const unsigned short utf8_to_euc_E5BA[] = { - 0xBC42, 0x4423, 0, 0x392D, 0x3E31, 0, 0, 0x485F, - 0, 0, 0x3E32, 0xBC43, 0, 0, 0xBC44, 0x3D78, - 0, 0, 0, 0, 0, 0x446C, 0x4A79, 0x4539, - 0, 0, 0x392E, 0, 0x495C, 0, 0, 0, - 0x5679, 0, 0xBC45, 0, 0xBC46, 0xBC47, 0x4559, 0x3A42, - 0xBC48, 0, 0xBC49, 0x384B, 0xBC4A, 0x446D, 0, 0, - 0, 0xBC4B, 0, 0xBC4C, 0, 0x3043, 0x3D6E, 0x392F, - 0x4D47, 0, 0, 0, 0, 0xBC4D, 0xBC4E, 0xBC4F, -}; -static const unsigned short utf8_to_euc_E5BA_x0213[] = { - 0xBC42, 0x4423, 0, 0x392D, 0x3E31, 0, 0, 0x485F, - 0, 0, 0x3E32, 0xBC43, 0, 0, 0xBC44, 0x3D78, - 0, 0, 0, 0, 0, 0x446C, 0x4A79, 0x4539, - 0, 0, 0x392E, 0, 0x495C, 0, 0, 0, - 0x5679, 0, 0xBC45, 0, 0xBC46, 0xAC23, 0x4559, 0x3A42, - 0xBC48, 0, 0xAC24, 0x384B, 0xAC25, 0x446D, 0, 0, - 0, 0xBC4B, 0, 0xBC4C, 0, 0x3043, 0x3D6E, 0x392F, - 0x4D47, 0xAC26, 0, 0, 0, 0xBC4D, 0x742D, 0xAC27, -}; -static const unsigned short utf8_to_euc_E5BB[] = { - 0, 0x567A, 0x567B, 0x4751, 0, 0, 0xBC50, 0, - 0x567C, 0x4E77, 0x4F2D, 0xBC52, 0xBC51, 0, 0xBC53, 0x567E, - 0x567D, 0xBC54, 0xBC55, 0x3347, 0xBC56, 0xBC57, 0x5721, 0, - 0, 0, 0x5724, 0x5725, 0xBC58, 0x5723, 0xBC59, 0x4940, - 0x3E33, 0x5727, 0x5726, 0x5722, 0, 0xBC5A, 0, 0, - 0x5728, 0x5729, 0, 0xBC5B, 0x572A, 0, 0, 0, - 0x572D, 0x572B, 0, 0x572C, 0x572E, 0, 0x3164, 0x446E, - 0x572F, 0, 0x377A, 0x3276, 0x4736, 0, 0x5730, 0x467B, -}; -static const unsigned short utf8_to_euc_E5BB_x0213[] = { - 0, 0x567A, 0x567B, 0x4751, 0, 0, 0xAC28, 0, - 0x567C, 0x4E77, 0x4F2D, 0x742F, 0xBC51, 0, 0xBC53, 0x567E, - 0x567D, 0xBC54, 0xAC29, 0x3347, 0xBC56, 0xBC57, 0x5721, 0, - 0, 0xAC2A, 0x5724, 0x5725, 0xBC58, 0x5723, 0xBC59, 0x4940, - 0x3E33, 0x5727, 0x5726, 0x5722, 0, 0xBC5A, 0, 0, - 0x5728, 0x5729, 0, 0xBC5B, 0x572A, 0, 0, 0, - 0x572D, 0x572B, 0, 0x572C, 0x572E, 0, 0x3164, 0x446E, - 0x572F, 0x7430, 0x377A, 0x3276, 0x4736, 0xAC2C, 0x5730, 0x467B, -}; -static const unsigned short utf8_to_euc_E5BC[] = { - 0, 0x4A5B, 0xBC5C, 0x5731, 0x4F2E, 0, 0xBC5D, 0xBC5E, - 0xBC5F, 0x5732, 0x4A40, 0x5735, 0x5021, 0x5031, 0xBC60, 0x3C30, - 0x4675, 0x5736, 0, 0x355D, 0x4424, 0x307A, 0x5737, 0x4A26, - 0x3930, 0xBC61, 0, 0x4350, 0xBC62, 0xBC63, 0, 0x446F, - 0, 0xBC64, 0xBC65, 0xBC66, 0xBC67, 0x4C6F, 0x3839, 0x384C, - 0xBC68, 0x5738, 0, 0xBC69, 0xBC6A, 0x5739, 0xBC6B, 0x573F, - 0xBC6C, 0x3C65, 0, 0, 0xBC6D, 0x4425, 0xBC6E, 0x362F, - 0x573A, 0, 0, 0xBC6F, 0x492B, 0xBC70, 0x4346, 0xBC71, -}; -static const unsigned short utf8_to_euc_E5BC_x0213[] = { - 0x7431, 0x4A5B, 0x7432, 0x5731, 0x4F2E, 0, 0xBC5D, 0x7433, - 0xAC2D, 0x5732, 0x4A40, 0x5735, 0x5021, 0x5031, 0xAC2E, 0x3C30, - 0x4675, 0x5736, 0, 0x355D, 0x4424, 0x307A, 0x5737, 0x4A26, - 0x3930, 0xBC61, 0, 0x4350, 0xAC2F, 0x7434, 0xAC31, 0x446F, - 0, 0, 0xBC65, 0x7435, 0xBC67, 0x4C6F, 0x3839, 0x384C, - 0xBC68, 0x5738, 0, 0xBC69, 0xBC6A, 0x5739, 0xBC6B, 0x573F, - 0xBC6C, 0x3C65, 0, 0, 0x7436, 0x4425, 0x7437, 0x362F, - 0x573A, 0, 0, 0xBC6F, 0x492B, 0x7438, 0x4346, 0xBC71, -}; -static const unsigned short utf8_to_euc_E5BD[] = { - 0xBC72, 0x573B, 0, 0, 0xBC73, 0xBC74, 0, 0xBC75, - 0x573C, 0, 0x3630, 0, 0x573D, 0xBC76, 0x573E, 0, - 0xBC77, 0x5740, 0, 0x4576, 0xBC78, 0, 0x5741, 0x5742, - 0xBC79, 0x5743, 0, 0xBC7A, 0x5734, 0x5733, 0, 0, - 0xBC7B, 0x5744, 0x3741, 0xBC7C, 0xBC7D, 0, 0x4927, 0xBC7E, - 0, 0x3A4C, 0x4937, 0x4426, 0x494B, 0x5745, 0, 0xBD21, - 0x3E34, 0x3146, 0xBD22, 0x5746, 0xBD23, 0xBD24, 0, 0x5747, - 0xBD25, 0x4C72, 0xBD26, 0, 0x4860, 0xBD27, 0xBD28, 0x574A, -}; -static const unsigned short utf8_to_euc_E5BD_x0213[] = { - 0x7439, 0x573B, 0, 0, 0xBC73, 0x743A, 0, 0xAC32, - 0x573C, 0, 0x3630, 0, 0x573D, 0xBC76, 0x573E, 0, - 0xBC77, 0x5740, 0, 0x4576, 0x743B, 0, 0x5741, 0x5742, - 0x743C, 0x5743, 0, 0xBC7A, 0x5734, 0x5733, 0, 0, - 0xBC7B, 0x5744, 0x3741, 0xAC33, 0x743D, 0, 0x4927, 0x743E, - 0, 0x3A4C, 0x4937, 0x4426, 0x494B, 0x5745, 0, 0xBD21, - 0x3E34, 0x3146, 0xAC34, 0x5746, 0xBD23, 0xBD24, 0, 0x5747, - 0xBD25, 0x4C72, 0xBD26, 0, 0x4860, 0x743F, 0xAC35, 0x574A, -}; -static const unsigned short utf8_to_euc_E5BE[] = { - 0x317D, 0x402C, 0x5749, 0x5748, 0x3742, 0x4254, 0, 0x574E, - 0x574C, 0xBD29, 0x574B, 0x4E27, 0x3865, 0xBD2A, 0, 0xBD2B, - 0x3D79, 0x574D, 0x454C, 0x3D3E, 0, 0, 0xBD2C, 0x4640, - 0x5751, 0x5750, 0, 0, 0xBD2D, 0xBD2E, 0x574F, 0, - 0x5752, 0x3866, 0xBD2F, 0, 0xBD32, 0, 0, 0xBD30, - 0x5753, 0x497C, 0x3D5B, 0xBD31, 0xBD33, 0x5754, 0x4879, 0xBD34, - 0xBD35, 0xBD36, 0, 0x4641, 0x4427, 0, 0, 0xF43E, - 0xBD37, 0x4530, 0, 0, 0x5755, 0x352B, 0, 0, -}; -static const unsigned short utf8_to_euc_E5BE_x0213[] = { - 0x317D, 0x402C, 0x5749, 0x5748, 0x3742, 0x4254, 0, 0x574E, - 0x574C, 0x7440, 0x574B, 0x4E27, 0x3865, 0xBD2A, 0, 0xAC36, - 0x3D79, 0x574D, 0x454C, 0x3D3E, 0, 0, 0xBD2C, 0x4640, - 0x5751, 0x5750, 0, 0, 0x7441, 0xBD2E, 0x574F, 0, - 0x5752, 0x3866, 0xAC37, 0, 0xAC38, 0, 0, 0x7442, - 0x5753, 0x497C, 0x3D5B, 0xBD31, 0xBD33, 0x5754, 0x4879, 0x7443, - 0xBD35, 0xBD36, 0, 0x4641, 0x4427, 0x7444, 0, 0x7445, - 0xAC39, 0x4530, 0, 0, 0x5755, 0x352B, 0, 0, -}; -static const unsigned short utf8_to_euc_E5BF[] = { - 0, 0, 0, 0x3F34, 0xBD38, 0x492C, 0, 0xBD39, - 0xBD3A, 0xBD3B, 0, 0xBD3C, 0x3477, 0x4726, 0, 0, - 0xBD3D, 0xBD3E, 0xBD3F, 0xBD40, 0xBD41, 0, 0x5756, 0x3B56, - 0x4B3A, 0x4B3B, 0, 0, 0x317E, 0x575B, 0xBD42, 0, - 0x4369, 0xBD43, 0xBD44, 0, 0x5758, 0, 0, 0, - 0xBD45, 0xBD46, 0xBD47, 0x3277, 0xBD48, 0xBD49, 0xBD4A, 0xBD4B, - 0x582D, 0x575A, 0xBD4C, 0xBD4D, 0, 0x4730, 0xBD4E, 0, - 0x5759, 0, 0xBD4F, 0x5757, 0xBD50, 0x397A, 0, 0x575D, -}; -static const unsigned short utf8_to_euc_E5BF_x0213[] = { - 0, 0, 0, 0x3F34, 0xAC3A, 0x492C, 0, 0xAC3C, - 0xBD3A, 0x7446, 0, 0xAC3D, 0x3477, 0x4726, 0, 0, - 0xBD3D, 0xBD3E, 0xAC3E, 0xAC3F, 0xAC40, 0, 0x5756, 0x3B56, - 0x4B3A, 0x4B3B, 0, 0, 0x317E, 0x575B, 0x7447, 0, - 0x4369, 0x7448, 0xAC41, 0, 0x5758, 0, 0, 0, - 0xBD45, 0x7449, 0xBD47, 0x3277, 0xBD48, 0xBD49, 0xAC42, 0xAC43, - 0x582D, 0x575A, 0xBD4C, 0xAC44, 0, 0x4730, 0xBD4E, 0, - 0x5759, 0, 0xBD4F, 0x5757, 0xAC45, 0x397A, 0, 0x575D, -}; -static const unsigned short utf8_to_euc_E680[] = { - 0, 0, 0, 0, 0, 0, 0, 0xBD51, - 0, 0, 0xBD52, 0, 0, 0xBD53, 0x5763, 0x5769, - 0x5761, 0, 0x455C, 0xBD54, 0xBD55, 0x5766, 0x495D, 0xBD56, - 0xBD57, 0x5760, 0xBD58, 0x5765, 0x4E67, 0x3B57, 0, 0xBD59, - 0x4255, 0x575E, 0, 0, 0xBD5A, 0x355E, 0x5768, 0x402D, - 0x3165, 0x5762, 0x3278, 0x5767, 0, 0xBD5B, 0, 0x3631, - 0, 0x5764, 0, 0xBD5C, 0, 0xBD5D, 0, 0, - 0, 0, 0x576A, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E680_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0xBD51, - 0, 0, 0xBD52, 0, 0, 0x744A, 0x5763, 0x5769, - 0x5761, 0, 0x455C, 0xBD54, 0x744B, 0x5766, 0x495D, 0xAC47, - 0x744C, 0x5760, 0xBD58, 0x5765, 0x4E67, 0x3B57, 0, 0xBD59, - 0x4255, 0x575E, 0xAC48, 0, 0xAC49, 0x355E, 0x5768, 0x402D, - 0x3165, 0x5762, 0x3278, 0x5767, 0, 0xBD5B, 0, 0x3631, - 0, 0x5764, 0, 0x744D, 0, 0x744E, 0, 0, - 0, 0, 0x576A, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E681[] = { - 0xBD5E, 0x576C, 0x5776, 0x5774, 0, 0, 0x5771, 0xBD5F, - 0xBD60, 0xBD61, 0x5770, 0x4E78, 0xBD62, 0x5772, 0, 0, - 0x3632, 0xBD63, 0x3931, 0, 0xBD64, 0x3D7A, 0xBD65, 0xBD66, - 0, 0x5779, 0x576B, 0, 0, 0xBD67, 0, 0x576F, - 0x575F, 0xBD68, 0x327A, 0x5773, 0x5775, 0x4351, 0, 0xBD69, - 0x3A28, 0x3238, 0x576D, 0x5778, 0x5777, 0x3633, 0, 0x4229, - 0x3366, 0xBD6A, 0, 0, 0, 0x3743, 0, 0x576E, - 0, 0, 0, 0, 0, 0, 0xBD6B, 0xBD6C, -}; -static const unsigned short utf8_to_euc_E681_x0213[] = { - 0xBD5E, 0x576C, 0x5776, 0x5774, 0, 0, 0x5771, 0x744F, - 0xBD60, 0xBD61, 0x5770, 0x4E78, 0xAC4B, 0x5772, 0, 0, - 0x3632, 0xBD63, 0x3931, 0, 0xBD64, 0x3D7A, 0xBD65, 0xBD66, - 0, 0x5779, 0x576B, 0, 0, 0, 0, 0x576F, - 0x575F, 0xBD68, 0x327A, 0x5773, 0x5775, 0x4351, 0, 0xBD69, - 0x3A28, 0x3238, 0x576D, 0x5778, 0x5777, 0x3633, 0, 0x4229, - 0x3366, 0xBD6A, 0, 0, 0, 0x3743, 0, 0x576E, - 0, 0, 0, 0, 0, 0, 0xBD6B, 0xAC4C, -}; -static const unsigned short utf8_to_euc_E682[] = { - 0, 0x577A, 0xBD6D, 0x577D, 0x5821, 0xF43F, 0xBD6E, 0, - 0xBD6F, 0x3C3D, 0xBD70, 0x5827, 0x4470, 0x577B, 0xBD71, 0, - 0, 0xBD72, 0x5825, 0xBD73, 0x3279, 0xBD74, 0x5823, 0x5824, - 0xBD75, 0, 0x577E, 0x5822, 0, 0xBD76, 0xBD77, 0x3867, - 0x4D2A, 0, 0xBD78, 0x3435, 0xBD79, 0xBD7A, 0x3159, 0x5826, - 0xBD7B, 0x473A, 0x302D, 0, 0, 0, 0, 0, - 0xBD7C, 0xBD7D, 0x4861, 0x575C, 0x582C, 0x5830, 0x4C65, 0xBD7E, - 0x5829, 0, 0, 0xBE21, 0x4569, 0x582E, 0xBE22, 0, -}; -static const unsigned short utf8_to_euc_E682_x0213[] = { - 0, 0x577A, 0xBD6D, 0x577D, 0x5821, 0, 0xBD6E, 0, - 0xBD6F, 0x3C3D, 0xAC4D, 0x5827, 0x4470, 0x577B, 0xBD71, 0, - 0, 0xBD72, 0x5825, 0xBD73, 0x3279, 0xAC4E, 0x5823, 0x5824, - 0xBD75, 0, 0x577E, 0x5822, 0, 0x7451, 0x7452, 0x3867, - 0x4D2A, 0, 0xBD78, 0x3435, 0xBD79, 0xBD7A, 0x3159, 0x5826, - 0xAC4F, 0x473A, 0x302D, 0, 0, 0, 0, 0, - 0xAC51, 0xAC52, 0x4861, 0x575C, 0x582C, 0x5830, 0x4C65, 0xBD7E, - 0x5829, 0, 0, 0xBE21, 0x4569, 0x582E, 0xAC53, 0, -}; -static const unsigned short utf8_to_euc_E683[] = { - 0, 0, 0xBE23, 0, 0xBE24, 0x3E70, 0x582F, 0x4657, - 0xBE25, 0xBE26, 0xBE27, 0xBE28, 0, 0, 0xBE29, 0xBE2A, - 0, 0x4F47, 0, 0x582B, 0xBE2B, 0xBE2C, 0, 0, - 0x5831, 0xBE2D, 0x397B, 0xBE2E, 0x404B, 0xBE2F, 0xBE30, 0x3054, - 0x582A, 0x5828, 0xBE31, 0x415A, 0, 0xBE32, 0, 0x577C, - 0x3B34, 0, 0, 0, 0, 0, 0, 0, - 0x4246, 0x583D, 0xBE33, 0x415B, 0x5838, 0xBE34, 0x5835, 0x5836, - 0xBE35, 0x3C66, 0x5839, 0x583C, 0xBE36, 0xBE37, 0, 0, -}; -static const unsigned short utf8_to_euc_E683_x0213[] = { - 0, 0, 0xBE23, 0, 0xBE24, 0x3E70, 0x582F, 0x4657, - 0xAC54, 0xBE26, 0xBE27, 0x7453, 0, 0, 0xBE29, 0xBE2A, - 0, 0x4F47, 0, 0x582B, 0x7454, 0x7455, 0, 0, - 0x5831, 0xAC55, 0x397B, 0xAC56, 0x404B, 0x7456, 0, 0x3054, - 0x582A, 0x5828, 0xBE31, 0x415A, 0, 0xBE32, 0, 0x577C, - 0x3B34, 0, 0, 0, 0, 0, 0xAC57, 0, - 0x4246, 0x583D, 0xAC58, 0x415B, 0x5838, 0xAC59, 0x5835, 0x5836, - 0x7457, 0x3C66, 0x5839, 0x583C, 0xBE36, 0xBE37, 0, 0, -}; -static const unsigned short utf8_to_euc_E684[] = { - 0x5837, 0x3D25, 0xBE38, 0x583A, 0, 0, 0x5834, 0xBE39, - 0x4C7C, 0x4C7B, 0xBE3A, 0, 0xBE3B, 0x583E, 0x583F, 0x3055, - 0xBE3C, 0xBE3D, 0xBE3E, 0xBE3F, 0xBE40, 0x5833, 0xBE41, 0xBE42, - 0, 0xBE43, 0x3672, 0x3026, 0xBE44, 0, 0xBE45, 0x3436, - 0xF440, 0x583B, 0xBE46, 0, 0, 0, 0, 0x5843, - 0x5842, 0, 0xBE47, 0xBE48, 0x5847, 0, 0, 0, - 0xBE49, 0xBE4A, 0, 0, 0x5848, 0xBE4B, 0xBE4C, 0xBE4D, - 0, 0xBE4E, 0, 0, 0x5846, 0x5849, 0x5841, 0x5845, -}; -static const unsigned short utf8_to_euc_E684_x0213[] = { - 0x5837, 0x3D25, 0xBE38, 0x583A, 0, 0, 0x5834, 0xBE39, - 0x4C7C, 0x4C7B, 0xBE3A, 0, 0xBE3B, 0x583E, 0x583F, 0x3055, - 0xAC5A, 0, 0xAC5B, 0xAC5C, 0xBE40, 0x5833, 0xBE41, 0xBE42, - 0, 0xAC5D, 0x3672, 0x3026, 0x7458, 0, 0xAC5E, 0x3436, - 0, 0x583B, 0xBE46, 0, 0, 0, 0, 0x5843, - 0x5842, 0, 0xBE47, 0x7459, 0x5847, 0, 0, 0, - 0x745A, 0xBE4A, 0, 0, 0x5848, 0xBE4B, 0xBE4C, 0x745B, - 0, 0xBE4E, 0xAC5F, 0, 0x5846, 0x5849, 0x5841, 0x5845, -}; -static const unsigned short utf8_to_euc_E685[] = { - 0, 0xBE4F, 0x584A, 0, 0x584B, 0xBE50, 0xBE51, 0x5840, - 0x3B7C, 0xBE52, 0x5844, 0x4256, 0x3932, 0x5832, 0x3F35, 0, - 0, 0, 0, 0x5858, 0, 0x4A69, 0, 0, - 0x584E, 0x584F, 0x5850, 0, 0, 0x5857, 0xBE53, 0x5856, - 0xBE54, 0, 0x4B7D, 0x3437, 0, 0x5854, 0, 0x3745, - 0x3334, 0, 0, 0x5851, 0xBE55, 0, 0x4E38, 0x5853, - 0x3056, 0x5855, 0xBE56, 0x584C, 0x5852, 0x5859, 0x3744, 0x584D, - 0xBE57, 0, 0, 0xBE58, 0xBE59, 0, 0x4D5D, 0xBE5A, -}; -static const unsigned short utf8_to_euc_E685_x0213[] = { - 0, 0xAC61, 0x584A, 0, 0x584B, 0xBE50, 0xAC62, 0x5840, - 0x3B7C, 0xBE52, 0x5844, 0x4256, 0x3932, 0x5832, 0x3F35, 0, - 0, 0, 0, 0x5858, 0, 0x4A69, 0, 0, - 0x584E, 0x584F, 0x5850, 0, 0, 0x5857, 0xBE53, 0x5856, - 0xAC63, 0, 0x4B7D, 0x3437, 0, 0x5854, 0, 0x3745, - 0x3334, 0, 0, 0x5851, 0xBE55, 0, 0x4E38, 0x5853, - 0x3056, 0x5855, 0xBE56, 0x584C, 0x5852, 0x5859, 0x3744, 0x584D, - 0xBE57, 0, 0, 0xBE58, 0xAC64, 0, 0x4D5D, 0xBE5A, -}; -static const unsigned short utf8_to_euc_E686[] = { - 0xBE5B, 0xBE5C, 0x4D2B, 0xBE5D, 0xBE5E, 0, 0, 0x585C, - 0, 0, 0x5860, 0xBE5F, 0, 0xBE60, 0x417E, 0, - 0x4E79, 0x5861, 0xBE61, 0xBE62, 0x585E, 0, 0x585B, 0xBE63, - 0xBE64, 0x585A, 0x585F, 0, 0xBE65, 0xBE66, 0, 0xBE67, - 0xBE68, 0, 0, 0, 0x4A30, 0xBE69, 0, 0x4634, - 0xBE6A, 0x3746, 0xBE6B, 0x5862, 0x585D, 0xBE6C, 0x5863, 0, - 0, 0, 0x377B, 0, 0, 0, 0x3231, 0, - 0xBE6D, 0xBE6E, 0x586B, 0, 0xBE6F, 0, 0x3438, 0, -}; -static const unsigned short utf8_to_euc_E686_x0213[] = { - 0xBE5B, 0xBE5C, 0x4D2B, 0xBE5D, 0xBE5E, 0, 0, 0x585C, - 0, 0, 0x5860, 0xBE5F, 0, 0x745D, 0x417E, 0, - 0x4E79, 0x5861, 0xAC66, 0xAC67, 0x585E, 0, 0x585B, 0xAC68, - 0xAC69, 0x585A, 0x585F, 0, 0xBE65, 0xBE66, 0, 0xBE67, - 0xBE68, 0, 0, 0, 0x4A30, 0xAC6A, 0, 0x4634, - 0xAC6B, 0x3746, 0xBE6B, 0x5862, 0x585D, 0xAC6C, 0x5863, 0, - 0, 0, 0x377B, 0, 0, 0, 0x3231, 0, - 0xBE6D, 0x7460, 0x586B, 0, 0x745F, 0, 0x3438, 0, -}; -static const unsigned short utf8_to_euc_E687[] = { - 0xBE70, 0xBE71, 0xBE72, 0x5869, 0, 0, 0x586A, 0x3A29, - 0x5868, 0x5866, 0x5865, 0x586C, 0x5864, 0x586E, 0xBE73, 0xBE74, - 0x327B, 0, 0, 0, 0, 0xBE75, 0, 0, - 0, 0, 0, 0, 0xBE76, 0xBE77, 0xBE78, 0xBE79, - 0, 0xBE7A, 0xBE7B, 0x5870, 0, 0xBE7E, 0x586F, 0xBE7C, - 0, 0xBE7D, 0, 0, 0xBF21, 0xBF22, 0, 0xBF23, - 0, 0, 0x4428, 0, 0x5873, 0, 0x5871, 0x5867, - 0x377C, 0, 0x5872, 0, 0x5876, 0x5875, 0x5877, 0x5874, -}; -static const unsigned short utf8_to_euc_E687_x0213[] = { - 0xBE70, 0xBE71, 0xBE72, 0x5869, 0, 0, 0x586A, 0x3A29, - 0x5868, 0x5866, 0x5865, 0x586C, 0x5864, 0x586E, 0xBE73, 0xBE74, - 0x327B, 0, 0, 0, 0, 0xAC6E, 0, 0, - 0, 0, 0, 0, 0xBE76, 0xAC6F, 0xBE78, 0xAC70, - 0, 0xBE7A, 0xBE7B, 0x5870, 0, 0xBE7E, 0x586F, 0xBE7C, - 0, 0xBE7D, 0, 0, 0xBF21, 0xBF22, 0, 0xBF23, - 0, 0, 0x4428, 0, 0x5873, 0xAC71, 0x5871, 0x5867, - 0x377C, 0, 0x5872, 0, 0x5876, 0x5875, 0x5877, 0x5874, -}; -static const unsigned short utf8_to_euc_E688[] = { - 0x5878, 0xBF24, 0, 0xBF25, 0xBF26, 0, 0, 0xBF27, - 0x5879, 0x587A, 0x4A6A, 0, 0x587C, 0x587B, 0x3D3F, 0, - 0x402E, 0x3266, 0x327C, 0xBF28, 0x587D, 0xBF29, 0x303F, 0, - 0, 0, 0x404C, 0x587E, 0xBF2A, 0x6C43, 0x5921, 0x3761, - 0xBF2B, 0x5922, 0xBF2C, 0xBF2D, 0, 0, 0x406F, 0xBF2E, - 0, 0xBF2F, 0x5923, 0xBF30, 0, 0, 0x5924, 0x353A, - 0x5925, 0, 0x5926, 0x5927, 0x4257, 0, 0, 0, - 0x384D, 0xBF31, 0, 0x4C61, 0, 0xBF32, 0, 0x4B3C, -}; -static const unsigned short utf8_to_euc_E688_x0213[] = { - 0x5878, 0xBF24, 0, 0xBF25, 0xBF26, 0, 0, 0xBF27, - 0x5879, 0x587A, 0x4A6A, 0, 0x587C, 0x587B, 0x3D3F, 0, - 0x402E, 0x3266, 0x327C, 0, 0x587D, 0xAC73, 0x303F, 0, - 0, 0, 0x404C, 0x587E, 0xBF2A, 0x6C43, 0x5921, 0x3761, - 0xBF2B, 0x5922, 0x7462, 0xAC74, 0, 0, 0x406F, 0xBF2E, - 0, 0xAC75, 0x5923, 0xBF30, 0, 0, 0x5924, 0x353A, - 0x5925, 0, 0x5926, 0x5927, 0x4257, 0, 0, 0, - 0x384D, 0xBF31, 0, 0x4C61, 0, 0xBF32, 0x7463, 0x4B3C, -}; -static const unsigned short utf8_to_euc_E689[] = { - 0x3D6A, 0x5928, 0xBF33, 0xBF34, 0xBF35, 0, 0xBF36, 0x4070, - 0x6E3D, 0x4862, 0, 0x3C6A, 0xBF37, 0x3A4D, 0x5929, 0, - 0xBF38, 0xBF39, 0xBF3A, 0x4247, 0xBF3B, 0x4A27, 0xBF3C, 0, - 0x4271, 0, 0xBF3D, 0x592C, 0xBF3E, 0, 0x592A, 0, - 0x592D, 0, 0, 0x592B, 0xBF3F, 0, 0, 0, - 0x592E, 0, 0, 0, 0, 0xBF40, 0x4A31, 0xBF41, - 0, 0x3037, 0, 0xBF42, 0, 0, 0x495E, 0, - 0, 0x4863, 0xBF43, 0, 0x592F, 0xBF44, 0x5932, 0x3E35, -}; -static const unsigned short utf8_to_euc_E689_x0213[] = { - 0x3D6A, 0x5928, 0xBF33, 0x7464, 0xBF35, 0, 0xAC76, 0x4070, - 0x6E3D, 0x4862, 0, 0x3C6A, 0xAC77, 0x3A4D, 0x5929, 0, - 0xBF38, 0xAC78, 0xAC79, 0x4247, 0xBF3B, 0x4A27, 0x7465, 0, - 0x4271, 0, 0x7466, 0x592C, 0xBF3E, 0, 0x592A, 0, - 0x592D, 0xAC7A, 0, 0x592B, 0xAC7B, 0, 0, 0, - 0x592E, 0, 0, 0, 0, 0xAC7D, 0x4A31, 0x7467, - 0, 0x3037, 0, 0xAC7E, 0, 0, 0x495E, 0, - 0, 0x4863, 0xBF43, 0xAC7C, 0x592F, 0xBF44, 0x5932, 0x3E35, -}; -static const unsigned short utf8_to_euc_E68A[] = { - 0x353B, 0, 0x5930, 0x5937, 0x3E36, 0, 0, 0, - 0, 0x5931, 0x4744, 0, 0, 0xBF45, 0xBF46, 0xBF47, - 0xBF48, 0x4D5E, 0x5933, 0x5934, 0x5938, 0x456A, 0x5935, 0x3933, - 0x405E, 0, 0, 0x5946, 0x4834, 0, 0x4272, 0, - 0, 0, 0, 0, 0, 0, 0xBF49, 0, - 0xBF4A, 0, 0, 0x4864, 0x5A2D, 0, 0, 0, - 0, 0x4A7A, 0, 0xBF4B, 0, 0x4471, 0xBF4C, 0xBF4D, - 0, 0x4B75, 0xBF4E, 0x593B, 0x3221, 0x436A, 0xBF4F, 0xBF50, -}; -static const unsigned short utf8_to_euc_E68A_x0213[] = { - 0x353B, 0, 0x5930, 0x5937, 0x3E36, 0x7468, 0, 0, - 0, 0x5931, 0x4744, 0, 0, 0xBF45, 0xBF46, 0xBF47, - 0xBF48, 0x4D5E, 0x5933, 0x5934, 0x5938, 0x456A, 0x5935, 0x3933, - 0x405E, 0xAD21, 0, 0x5946, 0x4834, 0, 0x4272, 0, - 0, 0, 0, 0, 0, 0, 0xAD22, 0, - 0xBF4A, 0, 0, 0x4864, 0x5A2D, 0, 0, 0, - 0, 0x4A7A, 0, 0xBF4B, 0, 0x4471, 0xBF4C, 0xBF4D, - 0, 0x4B75, 0xBF4E, 0x593B, 0x3221, 0x436A, 0xBF4F, 0xBF50, -}; -static const unsigned short utf8_to_euc_E68B[] = { - 0, 0, 0x5944, 0, 0xBF51, 0x4334, 0x593E, 0x5945, - 0x5940, 0x5947, 0x5943, 0, 0x5942, 0x476F, 0xBF52, 0x593C, - 0x327D, 0x593A, 0x3571, 0x4273, 0x5936, 0xBF53, 0xBF54, 0x5939, - 0x3934, 0x405B, 0xBF55, 0x3E37, 0x5941, 0x4752, 0, 0, - 0x3572, 0x3348, 0, 0, 0, 0, 0, 0, - 0, 0, 0xBF56, 0, 0x3367, 0x3F21, 0x5949, 0x594E, - 0, 0x594A, 0xBF57, 0x377D, 0xBF58, 0x594F, 0x3B22, 0x3969, - 0, 0, 0, 0, 0xBF59, 0xBF5A, 0x3D26, 0x593D, -}; -static const unsigned short utf8_to_euc_E68B_x0213[] = { - 0, 0, 0x5944, 0, 0x7469, 0x4334, 0x593E, 0x5945, - 0x5940, 0x5947, 0x5943, 0, 0x5942, 0x476F, 0xBF52, 0x593C, - 0x327D, 0x593A, 0x3571, 0x4273, 0x5936, 0xAD23, 0x746A, 0x5939, - 0x3934, 0x405B, 0xBF55, 0x3E37, 0x5941, 0x4752, 0, 0, - 0x3572, 0x3348, 0, 0, 0, 0, 0, 0, - 0, 0, 0xBF56, 0, 0x3367, 0x3F21, 0x5949, 0x594E, - 0, 0x594A, 0xBF57, 0x377D, 0xBF58, 0x594F, 0x3B22, 0x3969, - 0, 0, 0, 0, 0x746B, 0xAD25, 0x3D26, 0x593D, -}; -static const unsigned short utf8_to_euc_E68C[] = { - 0, 0x3B7D, 0x594C, 0xBF5B, 0xBF5C, 0, 0, 0x3B58, - 0x594D, 0x3044, 0xBF5D, 0xBF5E, 0x5948, 0xBF5F, 0, 0, - 0xBF60, 0x4429, 0, 0xBF61, 0, 0, 0xBF62, 0, - 0xBF63, 0x3573, 0, 0, 0, 0, 0, 0x3634, - 0, 0, 0, 0, 0, 0, 0, 0x594B, - 0x3027, 0xBF64, 0xBF65, 0x3A43, 0, 0xBF66, 0, 0x3F36, - 0, 0, 0, 0, 0, 0xBF67, 0xBF68, 0, - 0, 0xBF69, 0x4472, 0, 0xBF6A, 0x4854, 0x5951, 0x415E, -}; -static const unsigned short utf8_to_euc_E68C_x0213[] = { - 0, 0x3B7D, 0x594C, 0xAD26, 0xBF5C, 0, 0, 0x3B58, - 0x594D, 0x3044, 0x746C, 0xBF5E, 0x5948, 0xAD27, 0, 0, - 0xAD28, 0x4429, 0, 0xBF61, 0, 0, 0xBF62, 0, - 0x746D, 0x3573, 0, 0, 0, 0, 0, 0x3634, - 0, 0, 0, 0, 0, 0, 0, 0x594B, - 0x3027, 0xBF64, 0xBF65, 0x3A43, 0, 0xBF66, 0, 0x3F36, - 0, 0, 0xAD2B, 0, 0, 0xAD2C, 0xBF68, 0, - 0, 0x746E, 0x4472, 0xAD2D, 0xAD2E, 0x4854, 0x5951, 0x415E, -}; -static const unsigned short utf8_to_euc_E68D[] = { - 0, 0xBF6B, 0xBF6C, 0xBF6D, 0xBF6E, 0, 0xBF6F, 0, - 0, 0x422A, 0xBF70, 0xBF71, 0x3B2B, 0x5952, 0xBF72, 0x5954, - 0x5950, 0, 0xBF73, 0xBF74, 0xBF75, 0x4A61, 0, 0x443D, - 0xBF76, 0, 0, 0xBF77, 0x415C, 0, 0, 0, - 0, 0, 0, 0, 0, 0xBF78, 0xBF79, 0x4A7B, - 0x3C4E, 0x5960, 0, 0x595F, 0xBF7A, 0xBF7B, 0x3F78, 0, - 0, 0xBF7C, 0x377E, 0, 0xBF7D, 0xBF7E, 0x5959, 0x3E39, - 0xC021, 0, 0x4668, 0x4731, 0xC022, 0xC023, 0, 0xC024, -}; -static const unsigned short utf8_to_euc_E68D_x0213[] = { - 0, 0xAD2F, 0xBF6C, 0x746F, 0xAD30, 0, 0xBF6F, 0, - 0, 0x422A, 0xBF70, 0xBF71, 0x3B2B, 0x5952, 0xAD31, 0x5954, - 0x5950, 0, 0xBF73, 0xBF74, 0xBF75, 0x4A61, 0, 0x443D, - 0xBF76, 0xAD33, 0, 0xBF77, 0x415C, 0, 0, 0, - 0, 0, 0, 0, 0, 0x7470, 0xBF79, 0x4A7B, - 0x3C4E, 0x5960, 0, 0x595F, 0xAD36, 0xBF7B, 0x3F78, 0, - 0, 0xBF7C, 0x377E, 0, 0xBF7D, 0xBF7E, 0x5959, 0x3E39, - 0xC021, 0, 0x4668, 0x4731, 0x7471, 0xC023, 0, 0xC024, -}; -static const unsigned short utf8_to_euc_E68E[] = { - 0x5957, 0, 0xC025, 0x415D, 0xC026, 0, 0, 0xC027, - 0x3C78, 0x595C, 0xC028, 0, 0x3E38, 0, 0x5956, 0x595B, - 0xC029, 0, 0x4753, 0, 0xC02A, 0xC02B, 0x5955, 0, - 0x3721, 0xC02C, 0xC02D, 0x335D, 0, 0, 0xC02E, 0x595D, - 0x4E2B, 0x3A4E, 0x4335, 0x595A, 0xC02F, 0x405C, 0xC030, 0x3935, - 0x3F64, 0x3166, 0x413C, 0x5958, 0x3545, 0xC031, 0xC032, 0xC033, - 0, 0, 0x3747, 0, 0x444F, 0x595E, 0, 0, - 0, 0, 0, 0x415F, 0, 0xC034, 0x5961, 0, -}; -static const unsigned short utf8_to_euc_E68E_x0213[] = { - 0x5957, 0, 0xC025, 0x415D, 0xAD37, 0, 0, 0xC027, - 0x3C78, 0x595C, 0xC028, 0, 0x3E38, 0, 0x5956, 0x595B, - 0xC029, 0, 0x4753, 0, 0xAD3A, 0xC02B, 0x5955, 0, - 0x3721, 0xAD38, 0xC02D, 0x335D, 0, 0, 0xC02E, 0x595D, - 0x4E2B, 0x3A4E, 0x4335, 0x595A, 0xC02F, 0x405C, 0xC030, 0x3935, - 0x3F64, 0x3166, 0x413C, 0x5958, 0x3545, 0xC031, 0xC032, 0xC033, - 0, 0, 0x3747, 0, 0x444F, 0x595E, 0, 0, - 0, 0, 0, 0x415F, 0, 0xAD3B, 0x5961, 0, -}; -static const unsigned short utf8_to_euc_E68F[] = { - 0x5963, 0xC035, 0, 0x4237, 0x5969, 0xC036, 0x5964, 0, - 0xC037, 0x5966, 0, 0, 0, 0, 0xC038, 0x4941, - 0x4473, 0xC039, 0x5967, 0xC03A, 0xC03B, 0xC03C, 0x4D2C, 0, - 0, 0, 0x4D48, 0x3439, 0xC03D, 0, 0, 0, - 0xC03E, 0x302E, 0, 0x5965, 0, 0xC03F, 0, 0, - 0, 0x5962, 0xC040, 0, 0xC041, 0, 0x3478, 0, - 0, 0, 0xC042, 0xC043, 0x3167, 0xC044, 0x5968, 0, - 0xC045, 0xC046, 0x4D49, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E68F_x0213[] = { - 0x5963, 0xC035, 0, 0x4237, 0x5969, 0xC036, 0x5964, 0, - 0xC037, 0x5966, 0, 0, 0, 0, 0xC038, 0x4941, - 0x4473, 0xC039, 0x5967, 0xC03A, 0xAD3D, 0xAD3E, 0x4D2C, 0, - 0, 0, 0x4D48, 0x3439, 0xAD3F, 0, 0, 0, - 0xAD40, 0x302E, 0, 0x5965, 0, 0x7472, 0, 0, - 0, 0x5962, 0xC040, 0xAD41, 0xAD42, 0x7473, 0x3478, 0, - 0, 0, 0xAD43, 0xC043, 0x3167, 0x7474, 0x5968, 0xAD3C, - 0xC045, 0xC046, 0x4D49, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E690[] = { - 0, 0, 0, 0, 0, 0, 0x596C, 0, - 0, 0xC047, 0xC048, 0, 0, 0x423B, 0, 0x5973, - 0xC049, 0, 0xC04A, 0x596D, 0xC04B, 0, 0x596A, 0x5971, - 0xC04C, 0, 0, 0, 0x5953, 0, 0xC04D, 0, - 0xC04E, 0, 0xC04F, 0, 0xC050, 0xC051, 0x596E, 0, - 0x5972, 0xC052, 0xC053, 0, 0x4842, 0x456B, 0, 0xC054, - 0xC055, 0, 0, 0, 0x596B, 0xC056, 0x596F, 0, - 0, 0, 0x3748, 0, 0, 0xC057, 0x3A71, 0xC058, -}; -static const unsigned short utf8_to_euc_E690_x0213[] = { - 0, 0, 0, 0, 0, 0, 0x596C, 0, - 0, 0xAD44, 0xC048, 0, 0, 0x423B, 0, 0x5973, - 0x7475, 0, 0xC04A, 0x596D, 0x7476, 0, 0x596A, 0x5971, - 0xC04C, 0, 0, 0, 0x5953, 0, 0xAD45, 0, - 0xC04E, 0, 0x7477, 0, 0xC050, 0xAD46, 0x596E, 0, - 0x5972, 0xAD47, 0xC053, 0, 0x4842, 0x456B, 0, 0xAD48, - 0xC055, 0, 0, 0, 0x596B, 0xC056, 0x596F, 0, - 0, 0, 0x3748, 0, 0, 0xC057, 0x3A71, 0xC058, -}; -static const unsigned short utf8_to_euc_E691[] = { - 0, 0, 0x405D, 0, 0, 0, 0, 0, - 0, 0, 0, 0xC059, 0, 0, 0x5977, 0xC05A, - 0, 0xC05B, 0xC05C, 0xC05D, 0xC05E, 0, 0, 0, - 0x4526, 0, 0xC05F, 0xC060, 0xC061, 0xC062, 0, 0xC063, - 0xC064, 0xC065, 0, 0xC066, 0, 0, 0, 0x5974, - 0, 0x4B60, 0, 0, 0, 0xC067, 0, 0x5975, - 0, 0, 0, 0xC068, 0xC069, 0, 0x5976, 0, - 0x4C4E, 0, 0x4022, 0xC06A, 0, 0xC06B, 0, 0, -}; -static const unsigned short utf8_to_euc_E691_x0213[] = { - 0, 0, 0x405D, 0, 0, 0, 0, 0, - 0, 0, 0, 0xC059, 0, 0, 0x5977, 0xC05A, - 0, 0x7479, 0xC05C, 0xC05D, 0xC05E, 0, 0, 0, - 0x4526, 0, 0xAD49, 0xAD4A, 0xC061, 0xAD4B, 0, 0xC063, - 0x747A, 0xC065, 0, 0xC066, 0, 0, 0, 0x5974, - 0, 0x4B60, 0, 0, 0, 0x747B, 0, 0x5975, - 0, 0, 0, 0xAD4C, 0xC069, 0, 0x5976, 0, - 0x4C4E, 0x7478, 0x4022, 0xC06A, 0, 0xAD4D, 0, 0, -}; -static const unsigned short utf8_to_euc_E692[] = { - 0, 0, 0, 0x3762, 0, 0xC06C, 0, 0xC06D, - 0x597D, 0, 0, 0, 0, 0, 0, 0xC06E, - 0xC06F, 0xC070, 0x3B35, 0x597A, 0, 0x5979, 0, 0, - 0xC071, 0xC072, 0x4732, 0xC073, 0, 0xC074, 0x4635, 0xC075, - 0, 0xC076, 0, 0xC077, 0x4531, 0x597B, 0xC078, 0, - 0xC079, 0x597C, 0, 0x496F, 0xC07A, 0x4745, 0x3B23, 0, - 0x4071, 0, 0x4B50, 0xC07B, 0, 0, 0, 0, - 0, 0x3349, 0, 0x5A25, 0x597E, 0xC07C, 0xC07D, 0xC07E, -}; -static const unsigned short utf8_to_euc_E692_x0213[] = { - 0, 0, 0, 0x3762, 0, 0xC06C, 0, 0xAD4E, - 0x597D, 0, 0, 0, 0, 0, 0, 0xC06E, - 0xC06F, 0xAD4F, 0x3B35, 0x597A, 0, 0x5979, 0, 0, - 0xC071, 0xC072, 0x4732, 0xC073, 0, 0xAD50, 0x4635, 0xAD51, - 0, 0xC076, 0, 0xC077, 0x4531, 0x597B, 0xC078, 0, - 0xC079, 0x597C, 0, 0x496F, 0xC07A, 0x4745, 0x3B23, 0, - 0x4071, 0, 0x4B50, 0xC07B, 0, 0, 0, 0, - 0, 0x3349, 0, 0x5A25, 0x597E, 0xC07C, 0x747D, 0x747E, -}; -static const unsigned short utf8_to_euc_E693[] = { - 0, 0x4D4A, 0x5A27, 0, 0xC121, 0x5A23, 0, 0x5A24, - 0, 0xC122, 0xC123, 0xC124, 0xC125, 0x4160, 0xC126, 0, - 0xC127, 0xC128, 0x5A22, 0, 0x593F, 0xC129, 0, 0xC12A, - 0x5A26, 0, 0x5A21, 0, 0, 0, 0, 0, - 0x5A2B, 0x5A2C, 0x4527, 0x5A2E, 0xC12B, 0xC12C, 0x3B24, 0x5A29, - 0, 0xC12D, 0xC12E, 0, 0x353C, 0xC12F, 0, 0x5A2F, - 0xC130, 0x5A28, 0x5A33, 0, 0x5A32, 0xC131, 0x5A31, 0xC132, - 0, 0, 0x5A34, 0xC133, 0, 0x5A36, 0x3E71, 0xC134, -}; -static const unsigned short utf8_to_euc_E693_x0213[] = { - 0, 0x4D4A, 0x5A27, 0, 0x7521, 0x5A23, 0, 0x5A24, - 0, 0xC122, 0x7522, 0xAD52, 0xAD53, 0x4160, 0x747C, 0, - 0x7523, 0xC128, 0x5A22, 0, 0x593F, 0xAD54, 0, 0xAD55, - 0x5A26, 0, 0x5A21, 0, 0, 0, 0, 0, - 0x5A2B, 0x5A2C, 0x4527, 0x5A2E, 0xAD57, 0xAD58, 0x3B24, 0x5A29, - 0, 0xC12D, 0xC12E, 0, 0x353C, 0xC12F, 0, 0x5A2F, - 0xC130, 0x5A28, 0x5A33, 0, 0x5A32, 0xC131, 0x5A31, 0x7524, - 0, 0, 0x5A34, 0x7525, 0, 0x5A36, 0x3E71, 0xAD59, -}; -static const unsigned short utf8_to_euc_E694[] = { - 0x5A35, 0xC135, 0, 0, 0xC136, 0x5A39, 0, 0, - 0xC137, 0xC138, 0xC139, 0, 0, 0, 0, 0xC13A, - 0, 0, 0, 0xC13B, 0xC13C, 0, 0xC13D, 0, - 0x5A37, 0xC13E, 0, 0xC13F, 0x5A38, 0x5970, 0xC140, 0xC141, - 0, 0, 0xC142, 0x5A3B, 0x5A3A, 0, 0xC143, 0, - 0, 0xC144, 0x5978, 0x5A3C, 0x5A30, 0, 0xC145, 0x3B59, - 0, 0xC146, 0, 0, 0x5A3D, 0x5A3E, 0x5A40, 0x5A3F, - 0x5A41, 0x327E, 0xC147, 0x3936, 0xC148, 0xC149, 0x4A7C, 0x402F, -}; -static const unsigned short utf8_to_euc_E694_x0213[] = { - 0x5A35, 0xC135, 0, 0, 0xAD5A, 0x5A39, 0, 0, - 0xC137, 0xC138, 0xC139, 0, 0, 0, 0, 0xAD5C, - 0, 0, 0, 0xC13B, 0xAD5D, 0, 0xAD5E, 0, - 0x5A37, 0xC13E, 0, 0xC13F, 0x5A38, 0x5970, 0xAD60, 0xC141, - 0, 0, 0x7526, 0x5A3B, 0x5A3A, 0, 0xC143, 0, - 0, 0x7527, 0x5978, 0x5A3C, 0x5A30, 0, 0xC145, 0x3B59, - 0, 0xC146, 0xAD61, 0, 0x5A3D, 0x5A3E, 0x5A40, 0x5A3F, - 0x5A41, 0x327E, 0xC147, 0x3936, 0xC148, 0xC149, 0x4A7C, 0x402F, -}; -static const unsigned short utf8_to_euc_E695[] = { - 0, 0, 0, 0xC14A, 0, 0x384E, 0, 0xC14B, - 0x5A43, 0xC14C, 0, 0, 0, 0x5A46, 0xF441, 0x4952, - 0xC14D, 0x355F, 0xC14E, 0, 0xC14F, 0x5A45, 0x5A44, 0x4754, - 0x5A47, 0x3635, 0, 0, 0, 0x5A49, 0x5A48, 0xC150, - 0xC151, 0, 0x343A, 0x3B36, 0, 0, 0x4658, 0xC152, - 0, 0, 0, 0xC153, 0x3749, 0, 0, 0, - 0x3F74, 0, 0x5A4A, 0, 0x4030, 0x4528, 0, 0x495F, - 0x5A4B, 0, 0xC154, 0, 0, 0xC155, 0, 0, -}; -static const unsigned short utf8_to_euc_E695_x0213[] = { - 0, 0, 0, 0xC14A, 0xAD62, 0x384E, 0, 0xC14B, - 0x5A43, 0xC14C, 0, 0, 0, 0x5A46, 0, 0x4952, - 0xC14D, 0x355F, 0xC14E, 0, 0xAD63, 0x5A45, 0x5A44, 0x4754, - 0x5A47, 0x3635, 0, 0, 0, 0x5A49, 0x5A48, 0xC150, - 0xC151, 0, 0x343A, 0x3B36, 0, 0, 0x4658, 0x7529, - 0, 0, 0, 0xAD64, 0x3749, 0, 0, 0, - 0x3F74, 0, 0x5A4A, 0, 0x4030, 0x4528, 0, 0x495F, - 0x5A4B, 0, 0xAD65, 0, 0, 0xC155, 0, 0, -}; -static const unsigned short utf8_to_euc_E696[] = { - 0, 0xC156, 0x5A4C, 0x5A4D, 0, 0xC157, 0, 0x4A38, - 0x555D, 0x4046, 0xC158, 0, 0x494C, 0, 0x3A58, 0, - 0x4865, 0x4843, 0xC159, 0, 0, 0xC15A, 0, 0x454D, - 0xC15B, 0x4E41, 0, 0x5A4F, 0x3C50, 0xC15C, 0, 0x5A50, - 0xC15D, 0x3036, 0, 0xC15E, 0x3654, 0x404D, 0xC15F, 0x4960, - 0, 0, 0, 0x5A51, 0x3B42, 0x4347, 0xC160, 0x3B5B, - 0x3F37, 0, 0xC161, 0xC162, 0xC163, 0, 0, 0x5A52, - 0, 0x4A7D, 0, 0, 0x3177, 0x3B5C, 0, 0xC164, -}; -static const unsigned short utf8_to_euc_E696_x0213[] = { - 0, 0xAD66, 0x5A4C, 0x5A4D, 0xAD67, 0xAD68, 0, 0x4A38, - 0x555D, 0x4046, 0xAD69, 0, 0x494C, 0, 0x3A58, 0, - 0x4865, 0x4843, 0xC159, 0, 0, 0xC15A, 0, 0x454D, - 0xC15B, 0x4E41, 0, 0x5A4F, 0x3C50, 0x752A, 0, 0x5A50, - 0xC15D, 0x3036, 0, 0xC15E, 0x3654, 0x404D, 0xC15F, 0x4960, - 0, 0, 0, 0x5A51, 0x3B42, 0x4347, 0xC160, 0x3B5B, - 0x3F37, 0, 0xAD6A, 0xC162, 0xC163, 0xAD6B, 0, 0x5A52, - 0xAD6C, 0x4A7D, 0, 0, 0x3177, 0x3B5C, 0, 0xAD6D, -}; -static const unsigned short utf8_to_euc_E697[] = { - 0, 0x5A55, 0xC165, 0x5A53, 0x5A56, 0x4E39, 0x5A54, 0, - 0xC166, 0xC167, 0, 0x407B, 0x5A57, 0, 0xC168, 0x4232, - 0xC169, 0, 0x5A58, 0, 0xC16A, 0, 0xC16B, 0x347A, - 0xC16C, 0x5A5A, 0, 0x5A59, 0, 0, 0, 0xC16D, - 0x5A5B, 0x5A5C, 0x347B, 0, 0, 0x467C, 0x4336, 0x356C, - 0x3B5D, 0x4161, 0, 0, 0x3D5C, 0x3030, 0, 0, - 0xC16E, 0x5A5D, 0xC16F, 0, 0xC170, 0xC171, 0, 0, - 0, 0xC172, 0x3222, 0x5A61, 0, 0, 0xC173, 0xC174, -}; -static const unsigned short utf8_to_euc_E697_x0213[] = { - 0, 0x5A55, 0xAD6E, 0x5A53, 0x5A56, 0x4E39, 0x5A54, 0, - 0xC166, 0xAD6F, 0, 0x407B, 0x5A57, 0, 0xC168, 0x4232, - 0xC169, 0, 0x5A58, 0, 0xAD70, 0, 0xC16B, 0x347A, - 0xC16C, 0x5A5A, 0, 0x5A59, 0, 0, 0, 0xC16D, - 0x5A5B, 0x5A5C, 0x347B, 0, 0, 0x467C, 0x4336, 0x356C, - 0x3B5D, 0x4161, 0, 0, 0x3D5C, 0x3030, 0, 0, - 0xC16E, 0x5A5D, 0xAD72, 0, 0xC170, 0xC171, 0, 0, - 0, 0xAD73, 0x3222, 0x5A61, 0xAD74, 0, 0xC173, 0xC174, -}; -static const unsigned short utf8_to_euc_E698[] = { - 0xC175, 0, 0x3937, 0x5A60, 0xC176, 0, 0x3A2B, 0x3E3A, - 0xC177, 0xC178, 0x5A5F, 0, 0x3E3B, 0xC179, 0x4C40, 0x3A2A, - 0, 0xC17A, 0xC17B, 0x3057, 0x404E, 0xC17C, 0xC17D, 0, - 0, 0, 0, 0, 0x5A66, 0xC17E, 0xC221, 0x4031, - 0x3147, 0xC222, 0xC223, 0xC224, 0xC225, 0x3D55, 0xC226, 0x4B66, - 0x3A72, 0xC227, 0xC228, 0xC229, 0xC22A, 0x3E3C, 0xC22B, 0x4027, - 0xC22C, 0xC22D, 0, 0xC22E, 0x5A65, 0x5A63, 0x5A64, 0xC230, - 0, 0xC22F, 0, 0xF442, 0x436B, 0, 0, 0x5B26, -}; -static const unsigned short utf8_to_euc_E698_x0213[] = { - 0x752C, 0, 0x3937, 0x5A60, 0xAD75, 0, 0x3A2B, 0x3E3A, - 0xAD76, 0x752D, 0x5A5F, 0, 0x3E3B, 0xC179, 0x4C40, 0x3A2A, - 0, 0xC17A, 0xC17B, 0x3057, 0x404E, 0x752E, 0xC17D, 0, - 0, 0, 0, 0, 0x5A66, 0xC17E, 0x752F, 0x4031, - 0x3147, 0xAD77, 0x7531, 0xC224, 0x7532, 0x3D55, 0xC226, 0x4B66, - 0x3A72, 0xC227, 0xAD78, 0x7533, 0xC22A, 0x3E3C, 0, 0x4027, - 0x7534, 0x7535, 0, 0x7536, 0x5A65, 0x5A63, 0x5A64, 0xC230, - 0, 0xC22F, 0x7530, 0, 0x436B, 0, 0, 0x5B26, -}; -static const unsigned short utf8_to_euc_E699[] = { - 0xC231, 0x5A6A, 0x3B7E, 0x3938, 0x5A68, 0xC232, 0xC233, 0, - 0, 0x5A69, 0xC234, 0x3F38, 0xC235, 0, 0xC237, 0x5A67, - 0, 0xC236, 0x3B2F, 0, 0, 0, 0, 0xC238, - 0xC239, 0xC23A, 0, 0xC23B, 0xC23C, 0x5A6C, 0x5A6B, 0x5A70, - 0xC23D, 0xC23E, 0x5A71, 0, 0x5A6D, 0xF443, 0x3322, 0x5A6E, - 0x5A6F, 0x4855, 0xC240, 0xC241, 0xC242, 0, 0x4961, 0x374A, - 0x5A72, 0, 0, 0xC244, 0x4032, 0xC245, 0x3E3D, 0xC247, - 0xC248, 0xC249, 0x4352, 0xC24A, 0xC24C, 0, 0xC243, 0xC246, -}; -static const unsigned short utf8_to_euc_E699_x0213[] = { - 0xC231, 0x5A6A, 0x3B7E, 0x3938, 0x5A68, 0xAD79, 0xC233, 0, - 0x7538, 0x5A69, 0xC234, 0x3F38, 0x7539, 0, 0xAD7B, 0x5A67, - 0, 0xAD7A, 0x3B2F, 0, 0, 0, 0, 0xAD7E, - 0xC239, 0x753B, 0x753C, 0xAE21, 0xC23C, 0x5A6C, 0x5A6B, 0x5A70, - 0xC23D, 0x753D, 0x5A71, 0xAE22, 0x5A6D, 0x753E, 0x3322, 0x5A6E, - 0x5A6F, 0x4855, 0xAE25, 0xAE26, 0xAE27, 0xAE28, 0x4961, 0x374A, - 0x5A72, 0, 0, 0x753F, 0x4032, 0xC245, 0x3E3D, 0x7540, - 0x7541, 0xC249, 0x4352, 0xAE29, 0xC24C, 0, 0xC243, 0xC246, -}; -static const unsigned short utf8_to_euc_E69A[] = { - 0xC24B, 0x3647, 0, 0x5A73, 0x5A77, 0, 0, 0x324B, - 0x5A74, 0x5A76, 0, 0xC24D, 0xC24E, 0xC24F, 0x5A75, 0, - 0xC250, 0x3D6B, 0xC251, 0, 0, 0, 0x4348, 0x3045, - 0x5A78, 0xC252, 0xC253, 0xC254, 0xC255, 0x5A79, 0, 0xC256, - 0xC257, 0, 0x442A, 0, 0xC258, 0, 0x4E71, 0, - 0, 0, 0, 0x3B43, 0, 0xC259, 0x4A6B, 0, - 0, 0xC25A, 0xC25B, 0, 0x4B3D, 0xC25C, 0, 0, - 0x5B22, 0x5A7B, 0, 0xC25D, 0x5A7E, 0, 0x5A7D, 0xC25E, -}; -static const unsigned short utf8_to_euc_E69A_x0213[] = { - 0xAE2A, 0x3647, 0, 0x5A73, 0x5A77, 0, 0, 0x324B, - 0x5A74, 0x5A76, 0, 0xC24D, 0xC24E, 0x7542, 0x5A75, 0, - 0xAE2B, 0x3D6B, 0xAE2C, 0, 0, 0, 0x4348, 0x3045, - 0x5A78, 0xAE2D, 0xC253, 0xC254, 0xC255, 0x5A79, 0, 0xC256, - 0x7544, 0, 0x442A, 0, 0xC258, 0, 0x4E71, 0, - 0, 0, 0, 0x3B43, 0, 0xAE2F, 0x4A6B, 0, - 0, 0xAE30, 0x7545, 0, 0x4B3D, 0xAE31, 0, 0, - 0x5B22, 0x5A7B, 0, 0x7546, 0x5A7E, 0, 0x5A7D, 0xAE33, -}; -static const unsigned short utf8_to_euc_E69B[] = { - 0xC25F, 0x5A7A, 0xC260, 0xC261, 0x5B21, 0, 0, 0x465E, - 0xC262, 0x5A7C, 0, 0, 0xC263, 0, 0xC264, 0xC265, - 0, 0, 0, 0, 0xC266, 0, 0x5B23, 0, - 0, 0x3D6C, 0x5B24, 0xC267, 0x4D4B, 0x4778, 0, 0xC268, - 0x5B25, 0, 0, 0, 0, 0, 0x5B27, 0, - 0xC269, 0x5B28, 0, 0xC26A, 0xC26B, 0, 0xC26C, 0, - 0x5B29, 0, 0x364A, 0x3148, 0x3939, 0x5B2A, 0, 0x5B2B, - 0x3D71, 0x4162, 0xC26D, 0xC23F, 0x5258, 0x413E, 0x413D, 0x4258, -}; -static const unsigned short utf8_to_euc_E69B_x0213[] = { - 0xC25F, 0x5A7A, 0xC260, 0xC261, 0x5B21, 0, 0x7547, 0x465E, - 0x7548, 0x5A7C, 0, 0, 0xC263, 0, 0xC264, 0xC265, - 0, 0, 0, 0, 0xC266, 0, 0x5B23, 0, - 0, 0x3D6C, 0x5B24, 0x754A, 0x4D4B, 0x4778, 0, 0xC268, - 0x5B25, 0, 0, 0, 0, 0, 0x5B27, 0, - 0x754B, 0x5B28, 0, 0xC26A, 0xAE35, 0, 0xC26C, 0, - 0x5B29, 0, 0x364A, 0x3148, 0x3939, 0x5B2A, 0, 0x5B2B, - 0x3D71, 0x4162, 0x754C, 0x7537, 0x5258, 0x413E, 0x413D, 0x4258, -}; -static const unsigned short utf8_to_euc_E69C[] = { - 0x3A47, 0, 0, 0x5072, 0, 0xC26E, 0, 0xC26F, - 0x376E, 0x4D2D, 0, 0x4A7E, 0, 0x497E, 0xC270, 0x5B2C, - 0, 0, 0, 0xC271, 0x3A73, 0x443F, 0x5B2D, 0x4F2F, - 0, 0xC272, 0, 0x4B3E, 0xC273, 0x442B, 0x5B2E, 0x347C, - 0xC274, 0, 0xC275, 0, 0, 0, 0x5B2F, 0x5B30, - 0x4C5A, 0, 0x4C24, 0x4B76, 0x4B5C, 0x3B25, 0x5B32, 0, - 0, 0x3C6B, 0, 0xC276, 0x4B51, 0, 0x5B34, 0x5B37, - 0x5B36, 0, 0x3479, 0, 0, 0x3560, 0xC277, 0x5B33, -}; -static const unsigned short utf8_to_euc_E69C_x0213[] = { - 0x3A47, 0xAE37, 0, 0x5072, 0, 0xAE38, 0, 0xC26F, - 0x376E, 0x4D2D, 0, 0x4A7E, 0, 0x497E, 0, 0x5B2C, - 0, 0, 0xAE39, 0x754D, 0x3A73, 0x443F, 0x5B2D, 0x4F2F, - 0, 0xAE3B, 0, 0x4B3E, 0xC273, 0x442B, 0x5B2E, 0x347C, - 0xC274, 0, 0xC275, 0, 0, 0, 0x5B2F, 0x5B30, - 0x4C5A, 0, 0x4C24, 0x4B76, 0x4B5C, 0x3B25, 0x5B32, 0, - 0, 0x3C6B, 0, 0x754F, 0x4B51, 0, 0x5B34, 0x5B37, - 0x5B36, 0, 0x3479, 0, 0, 0x3560, 0xC277, 0x5B33, -}; -static const unsigned short utf8_to_euc_E69D[] = { - 0, 0x5B35, 0, 0, 0, 0xC278, 0x5B38, 0xC279, - 0xC27A, 0x3F79, 0, 0, 0xC27B, 0, 0x4D7B, 0x3049, - 0x3A60, 0x423C, 0, 0x3C5D, 0xC27C, 0xC27D, 0x3E73, 0, - 0, 0x5B3B, 0, 0, 0x454E, 0xC27E, 0x5B39, 0x422B, - 0x5B3A, 0x3E72, 0x4C5D, 0x5B3C, 0x5B3D, 0x4D68, 0xC321, 0, - 0, 0, 0x5B42, 0, 0xC322, 0x393A, 0xC323, 0x4755, - 0x5B3F, 0x456C, 0x5A5E, 0x5A62, 0xC324, 0x354F, 0xC325, 0x4747, - 0, 0, 0, 0xC326, 0x5B41, 0, 0x3E3E, 0x4844, -}; -static const unsigned short utf8_to_euc_E69D_x0213[] = { - 0, 0x5B35, 0, 0, 0, 0xC278, 0x5B38, 0x7551, - 0x7552, 0x3F79, 0, 0, 0xAE3E, 0xAE3F, 0x4D7B, 0x3049, - 0x3A60, 0x423C, 0, 0x3C5D, 0xAE40, 0xC27D, 0x3E73, 0, - 0, 0x5B3B, 0, 0, 0x454E, 0xAE41, 0x5B39, 0x422B, - 0x5B3A, 0x3E72, 0x4C5D, 0x5B3C, 0x5B3D, 0x4D68, 0x7550, 0, - 0, 0, 0x5B42, 0, 0xC322, 0x393A, 0xC323, 0x4755, - 0x5B3F, 0x456C, 0x5A5E, 0x5A62, 0xAE45, 0x354F, 0xAE46, 0x4747, - 0, 0, 0, 0x7553, 0x5B41, 0, 0x3E3E, 0x4844, -}; -static const unsigned short utf8_to_euc_E69E[] = { - 0, 0xC327, 0, 0, 0xC328, 0x5B47, 0, 0x487A, - 0, 0x5B3E, 0, 0x5B44, 0x5B43, 0, 0xC329, 0xC32A, - 0x404F, 0xC32B, 0, 0xC32C, 0, 0x4B6D, 0xC32D, 0x4E53, - 0xC32E, 0xC32F, 0x4B67, 0xC330, 0x324C, 0x3B5E, 0, 0, - 0x4F48, 0x5B46, 0x3F75, 0, 0, 0, 0x5B45, 0, - 0, 0x5B40, 0, 0, 0, 0, 0, 0x384F, - 0xC331, 0xC332, 0xC333, 0x5B4C, 0x5B4A, 0xC334, 0x324D, 0x5B48, - 0x5B4E, 0x5B54, 0, 0xC335, 0xC336, 0xC337, 0, 0, -}; -static const unsigned short utf8_to_euc_E69E_x0213[] = { - 0, 0x7554, 0, 0, 0xC328, 0x5B47, 0, 0x487A, - 0, 0x5B3E, 0, 0x5B44, 0x5B43, 0, 0xC329, 0xC32A, - 0x404F, 0xC32B, 0xAE48, 0x7555, 0, 0x4B6D, 0xC32D, 0x4E53, - 0x7556, 0xC32F, 0x4B67, 0x7557, 0x324C, 0x3B5E, 0, 0, - 0x4F48, 0x5B46, 0x3F75, 0, 0, 0, 0x5B45, 0, - 0, 0x5B40, 0, 0, 0, 0, 0, 0x384F, - 0xAE4C, 0xC332, 0xAE4D, 0x5B4C, 0x5B4A, 0xC334, 0x324D, 0x5B48, - 0x5B4E, 0x5B54, 0, 0x7558, 0xC336, 0xC337, 0, 0, -}; -static const unsigned short utf8_to_euc_E69F[] = { - 0xC339, 0x4248, 0xC33A, 0xC33B, 0x4A41, 0xC33C, 0x5B56, 0, - 0xC33D, 0xC33E, 0x4922, 0, 0, 0, 0x5B55, 0x4770, - 0x4B3F, 0x343B, 0xC33F, 0x4077, 0x3D40, 0, 0, 0xC340, - 0x4453, 0xC341, 0x4D2E, 0, 0xC342, 0x5B51, 0x5B50, 0, - 0, 0xC343, 0x5B52, 0, 0x5B4F, 0, 0xC344, 0x5B57, - 0, 0x5B4D, 0, 0, 0x5B4B, 0, 0x5B53, 0x5B49, - 0xC345, 0x436C, 0xC346, 0x4C78, 0x3C46, 0x3A74, 0xC347, 0xC348, - 0, 0xC338, 0, 0x3A3A, 0, 0, 0x4B6F, 0x3341, -}; -static const unsigned short utf8_to_euc_E69F_x0213[] = { - 0x755A, 0x4248, 0xC33A, 0xAE4E, 0x4A41, 0xC33C, 0x5B56, 0, - 0xAE4F, 0xC33E, 0x4922, 0, 0, 0, 0x5B55, 0x4770, - 0x4B3F, 0x343B, 0xAE50, 0x4077, 0x3D40, 0, 0, 0x755B, - 0x4453, 0xAE51, 0x4D2E, 0xAE52, 0xC342, 0x5B51, 0x5B50, 0, - 0, 0xC343, 0x5B52, 0, 0x5B4F, 0, 0xC344, 0x5B57, - 0, 0x5B4D, 0, 0, 0x5B4B, 0, 0x5B53, 0x5B49, - 0xAE53, 0x436C, 0xC346, 0x4C78, 0x3C46, 0x3A74, 0xC347, 0xAE54, - 0, 0x7559, 0, 0x3A3A, 0x755C, 0, 0x4B6F, 0x3341, -}; -static const unsigned short utf8_to_euc_E6A0[] = { - 0, 0xF446, 0x444E, 0x464A, 0x3149, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0x4072, 0xC34A, 0, 0x4034, 0x372A, - 0, 0xC34B, 0, 0, 0, 0xC34C, 0x5B59, 0xC34D, - 0, 0x393B, 0x337C, 0, 0, 0, 0, 0xC34F, - 0xC34E, 0x5B5B, 0x3374, 0x5B61, 0xC350, 0xC351, 0, 0xC352, - 0xC353, 0xC354, 0x5B5E, 0xC355, 0x4073, 0, 0, 0, - 0x334B, 0x3A2C, 0, 0xC356, 0x334A, 0x3A4F, 0, 0xC357, -}; -static const unsigned short utf8_to_euc_E6A0_x0213[] = { - 0, 0x755D, 0x444E, 0x464A, 0x3149, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0xAE4B, 0, 0, 0x4072, 0xC34A, 0, 0x4034, 0x372A, - 0xAE58, 0xC34B, 0, 0, 0, 0x755F, 0x5B59, 0xAE59, - 0, 0x393B, 0x337C, 0, 0, 0, 0, 0xC34F, - 0xC34E, 0x5B5B, 0x3374, 0x5B61, 0x7560, 0xAE5A, 0, 0xC352, - 0xC353, 0x7561, 0x5B5E, 0xAE5C, 0x4073, 0, 0, 0, - 0x334B, 0x3A2C, 0, 0xAE5D, 0x334A, 0x3A4F, 0xAE5E, 0xC357, -}; -static const unsigned short utf8_to_euc_E6A1[] = { - 0x5B5C, 0x3765, 0x374B, 0x456D, 0xC358, 0xC359, 0x5B5A, 0, - 0x3046, 0, 0xC35A, 0, 0xC35B, 0x5B5D, 0x5B5F, 0, - 0x364D, 0x372C, 0xC349, 0x343C, 0x354B, 0xC35C, 0, 0xC35D, - 0xC35E, 0x5B62, 0, 0xC35F, 0x3A79, 0x4B71, 0, 0x3B37, - 0, 0, 0, 0x5B63, 0, 0, 0, 0x4930, - 0, 0, 0, 0xC360, 0, 0, 0xC361, 0xC362, - 0xC363, 0xC364, 0xC365, 0, 0x5B6F, 0xC366, 0x3233, 0x5B64, - 0, 0xC367, 0xC368, 0xC369, 0xC36A, 0, 0x5B75, 0x5B65, -}; -static const unsigned short utf8_to_euc_E6A1_x0213[] = { - 0x5B5C, 0x3765, 0x374B, 0x456D, 0xAE5F, 0xAE60, 0x5B5A, 0, - 0x3046, 0xAE61, 0xC35A, 0, 0xAE62, 0x5B5D, 0x5B5F, 0, - 0x364D, 0x372C, 0x755E, 0x343C, 0x354B, 0xAE63, 0, 0xAE64, - 0xC35E, 0x5B62, 0, 0x7562, 0x3A79, 0x4B71, 0, 0x3B37, - 0, 0, 0, 0x5B63, 0, 0, 0, 0x4930, - 0, 0, 0, 0xAE66, 0, 0, 0xAE67, 0xC362, - 0xC363, 0xC364, 0x7563, 0, 0x5B6F, 0x7564, 0x3233, 0x5B64, - 0, 0xC367, 0xAE68, 0xC369, 0xAE69, 0, 0x5B75, 0x5B65, -}; -static const unsigned short utf8_to_euc_E6A2[] = { - 0, 0x4E42, 0xC36B, 0x5B6C, 0xC36C, 0x475F, 0xC36D, 0, - 0xC36E, 0, 0, 0, 0, 0x5B74, 0, 0x5B67, - 0, 0, 0, 0x3034, 0x5B69, 0, 0xC36F, 0x393C, - 0xC370, 0, 0xC371, 0x5B6B, 0xC372, 0x5B6A, 0, 0x5B66, - 0x5B71, 0xC373, 0x3E3F, 0xC374, 0, 0xC375, 0x546D, 0x3868, - 0x4D7C, 0xC376, 0xC377, 0, 0, 0x5B68, 0xC378, 0x4474, - 0x3323, 0x3A2D, 0xC379, 0x5B60, 0, 0x5B70, 0x3361, 0, - 0, 0x5B6E, 0x5B72, 0xC37A, 0x456E, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E6A2_x0213[] = { - 0, 0x4E42, 0xAE6A, 0x5B6C, 0xC36C, 0x475F, 0xC36D, 0, - 0xC36E, 0, 0, 0, 0, 0x5B74, 0, 0x5B67, - 0xAE6B, 0, 0, 0x3034, 0x5B69, 0, 0xAE6C, 0x393C, - 0xAE6E, 0xAE6F, 0xAE70, 0x5B6B, 0xAE71, 0x5B6A, 0, 0x5B66, - 0x5B71, 0xC373, 0x3E3F, 0x7566, 0, 0x7567, 0x546D, 0x3868, - 0x4D7C, 0xC376, 0xAE72, 0xAE73, 0, 0x5B68, 0xC378, 0x4474, - 0x3323, 0x3A2D, 0x7568, 0x5B60, 0xAE74, 0x5B70, 0x3361, 0, - 0, 0x5B6E, 0x5B72, 0xAE75, 0x456E, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E6A3[] = { - 0, 0, 0, 0, 0x347E, 0xC37B, 0x5C32, 0, - 0xC37C, 0x4C49, 0x5B77, 0x347D, 0xC37D, 0x5B7E, 0, 0xC37E, - 0xC421, 0xC422, 0x4B40, 0xC423, 0x5C21, 0x5C23, 0xC424, 0x5C27, - 0x5B79, 0xC425, 0x432A, 0, 0xC426, 0xC427, 0, 0x456F, - 0x5C2B, 0x5B7C, 0, 0x5C28, 0, 0xC428, 0, 0x5C22, - 0xC429, 0, 0xC42A, 0xC42B, 0xC42C, 0xC42D, 0x3F39, 0x5C2C, - 0xC42E, 0xC42F, 0x4033, 0, 0, 0xC430, 0xC431, 0, - 0, 0x5C2A, 0x343D, 0xC432, 0xC433, 0xC434, 0, 0, -}; -static const unsigned short utf8_to_euc_E6A3_x0213[] = { - 0, 0, 0, 0xAE7A, 0x347E, 0xAE7B, 0x5C32, 0, - 0x7569, 0x4C49, 0x5B77, 0x347D, 0xAE7C, 0x5B7E, 0, 0xAE7D, - 0x756A, 0xC422, 0x4B40, 0xC423, 0x5C21, 0x5C23, 0xAE7E, 0x5C27, - 0x5B79, 0xAF21, 0x432A, 0, 0xC426, 0xC427, 0, 0x456F, - 0x5C2B, 0x5B7C, 0, 0x5C28, 0xAF22, 0xAF23, 0, 0x5C22, - 0x756B, 0, 0xC42A, 0xC42B, 0xAF24, 0x756C, 0x3F39, 0x5C2C, - 0x756D, 0x756E, 0x4033, 0, 0, 0xC430, 0xC431, 0xAF25, - 0, 0x5C2A, 0x343D, 0xAE76, 0x756F, 0xC434, 0, 0, -}; -static const unsigned short utf8_to_euc_E6A4[] = { - 0x4F50, 0x5B76, 0, 0, 0x5C26, 0x3058, 0xC435, 0, - 0x5B78, 0xC436, 0xC437, 0x4C3A, 0x5B7D, 0x3F22, 0x4447, 0x5B73, - 0xC438, 0xC439, 0x5C25, 0xC43A, 0, 0, 0xC43B, 0xC43C, - 0, 0x3F7A, 0x5C2F, 0x3371, 0x3821, 0, 0, 0, - 0, 0x5C31, 0x5B7A, 0x5C30, 0, 0x5C29, 0x5B7B, 0, - 0x5C2D, 0, 0x5C2E, 0, 0, 0, 0, 0, - 0x5C3F, 0xC43D, 0, 0xC43E, 0x464E, 0xC43F, 0x5C24, 0, - 0xC440, 0x5C3B, 0, 0xC441, 0, 0x5C3D, 0, 0x4458, -}; -static const unsigned short utf8_to_euc_E6A4_x0213[] = { - 0x4F50, 0x5B76, 0, 0xAF26, 0x5C26, 0x3058, 0xC435, 0xAF27, - 0x5B78, 0xC436, 0x7570, 0x4C3A, 0x5B7D, 0x3F22, 0x4447, 0x5B73, - 0xC438, 0xC439, 0x5C25, 0xC43A, 0, 0, 0xC43B, 0xC43C, - 0, 0x3F7A, 0x5C2F, 0x3371, 0x3821, 0, 0, 0, - 0, 0x5C31, 0x5B7A, 0x5C30, 0, 0x5C29, 0x5B7B, 0, - 0x5C2D, 0, 0x5C2E, 0, 0, 0, 0, 0, - 0x5C3F, 0xC43D, 0, 0xC43E, 0x464E, 0x7573, 0x5C24, 0, - 0xC440, 0x5C3B, 0, 0xAF2B, 0, 0x5C3D, 0, 0x4458, -}; -static const unsigned short utf8_to_euc_E6A5[] = { - 0, 0, 0xC442, 0, 0, 0xC443, 0, 0, - 0, 0xC444, 0x4D4C, 0, 0, 0, 0xC445, 0, - 0, 0, 0, 0x4976, 0x5C38, 0x424A, 0, 0xC446, - 0, 0x5C3E, 0x413F, 0xC447, 0x5C35, 0x5C42, 0x5C41, 0, - 0x466F, 0x5C40, 0x466A, 0xC448, 0xC449, 0xC44A, 0xC44B, 0, - 0xC44C, 0xC44D, 0x5C44, 0x5C37, 0xC44E, 0x3648, 0x5C3A, 0x3D5D, - 0xC44F, 0xC450, 0xC451, 0x4760, 0x5C3C, 0x364B, 0, 0x5C34, - 0x5C36, 0x5C33, 0xC452, 0xC453, 0x4F30, 0x335A, 0x5C39, 0xC454, -}; -static const unsigned short utf8_to_euc_E6A5_x0213[] = { - 0, 0, 0x7574, 0, 0, 0xC443, 0xAF2D, 0, - 0, 0x7571, 0x4D4C, 0, 0, 0, 0xC445, 0, - 0, 0, 0, 0x4976, 0x5C38, 0x424A, 0, 0x7575, - 0, 0x5C3E, 0x413F, 0xC447, 0x5C35, 0x5C42, 0x5C41, 0, - 0x466F, 0x5C40, 0x466A, 0x7576, 0x7577, 0xC44A, 0xC44B, 0, - 0x7578, 0xAF2E, 0x5C44, 0x5C37, 0xAF2F, 0x3648, 0x5C3A, 0x3D5D, - 0xC44F, 0xC450, 0xAF30, 0x4760, 0x5C3C, 0x364B, 0, 0x5C34, - 0x5C36, 0x5C33, 0xAF31, 0xC453, 0x4F30, 0x335A, 0x5C39, 0xAF32, -}; -static const unsigned short utf8_to_euc_E6A6[] = { - 0xC455, 0x5C43, 0x3335, 0, 0, 0, 0, 0, - 0, 0, 0x3A67, 0, 0, 0xC456, 0x315D, 0, - 0, 0x5C54, 0xC457, 0, 0x4F31, 0x5C57, 0xC458, 0, - 0xC459, 0, 0, 0x3F3A, 0x5C56, 0, 0, 0, - 0x5C55, 0xC45A, 0, 0, 0, 0xC45B, 0xC45C, 0x5C52, - 0xC45D, 0, 0, 0xC45E, 0, 0xC45F, 0x5C46, 0xC460, - 0, 0x5C63, 0x5C45, 0, 0x5C58, 0, 0, 0xC461, - 0xC462, 0, 0xC463, 0x5C50, 0xC464, 0, 0x5C4B, 0x5C48, -}; -static const unsigned short utf8_to_euc_E6A6_x0213[] = { - 0x7579, 0x5C43, 0x3335, 0, 0, 0, 0, 0, - 0, 0, 0x3A67, 0, 0, 0xC456, 0x315D, 0, - 0, 0x5C54, 0xAF33, 0, 0x4F31, 0x5C57, 0xAF35, 0, - 0xAF36, 0, 0, 0x3F3A, 0x5C56, 0, 0, 0, - 0x5C55, 0xC45A, 0, 0, 0, 0x757B, 0xAF37, 0x5C52, - 0xC45D, 0, 0, 0xC45E, 0, 0x757C, 0x5C46, 0xC460, - 0xAF38, 0x5C63, 0x5C45, 0, 0x5C58, 0, 0, 0xAF39, - 0xC462, 0, 0xAF3A, 0x5C50, 0xAF3B, 0, 0x5C4B, 0x5C48, -}; -static const unsigned short utf8_to_euc_E6A7[] = { - 0, 0x5C49, 0, 0x5C51, 0, 0xC465, 0, 0x7422, - 0xC466, 0, 0x5C4E, 0x393D, 0x4448, 0x4164, 0x5C4C, 0, - 0x5C47, 0xC467, 0, 0x5C4A, 0, 0, 0xC468, 0xC469, - 0x4D4D, 0x4B6A, 0, 0, 0, 0x5C4F, 0x5C59, 0, - 0, 0, 0xC46A, 0, 0, 0xC46B, 0, 0x5C61, - 0x5C5A, 0, 0, 0x5C67, 0, 0x5C65, 0xC46C, 0xC46D, - 0, 0xC46E, 0x5C60, 0xC46F, 0, 0xC470, 0, 0, - 0, 0x5C5F, 0, 0x4450, 0, 0x4165, 0xC471, 0x5C5D, -}; -static const unsigned short utf8_to_euc_E6A7_x0213[] = { - 0xAF3C, 0x5C49, 0, 0x5C51, 0, 0xC465, 0, 0x7422, - 0xC466, 0, 0x5C4E, 0x393D, 0x4448, 0x4164, 0x5C4C, 0x757D, - 0x5C47, 0xAF3D, 0, 0x5C4A, 0, 0, 0xAF3E, 0xC469, - 0x4D4D, 0x4B6A, 0, 0, 0, 0x5C4F, 0x5C59, 0, - 0, 0, 0x7622, 0xAF44, 0, 0xC46B, 0, 0x5C61, - 0x5C5A, 0x7623, 0x7624, 0x5C67, 0, 0x5C65, 0xAF45, 0xAF46, - 0, 0xC46E, 0x5C60, 0xAF47, 0xAF49, 0x7625, 0x7626, 0, - 0, 0x5C5F, 0, 0x4450, 0, 0x4165, 0xAF4A, 0x5C5D, -}; -static const unsigned short utf8_to_euc_E6A8[] = { - 0xC472, 0xC473, 0x5C5B, 0xC474, 0, 0x5C62, 0, 0, - 0, 0, 0x5C68, 0x4875, 0x5C6E, 0, 0, 0xC475, - 0, 0xC476, 0x5C69, 0x5C6C, 0x5C66, 0xC477, 0, 0x4374, - 0, 0x4938, 0xC478, 0x5C5C, 0, 0xC479, 0x5C64, 0x3E40, - 0xC47A, 0x4C4F, 0x5C78, 0x5C6B, 0xC47B, 0, 0, 0, - 0xC47C, 0x3822, 0x3223, 0x335F, 0, 0, 0x5C53, 0, - 0xC47D, 0, 0xC47E, 0, 0xC521, 0x3E41, 0x5C70, 0xC522, - 0x5C77, 0x3C79, 0x3372, 0xC523, 0, 0x432E, 0xC524, 0xC525, -}; -static const unsigned short utf8_to_euc_E6A8_x0213[] = { - 0xC472, 0xC473, 0x5C5B, 0xC474, 0, 0x5C62, 0, 0, - 0, 0, 0x5C68, 0x4875, 0x5C6E, 0, 0, 0x7627, - 0, 0xAF4B, 0x5C69, 0x5C6C, 0x5C66, 0x7628, 0, 0x4374, - 0, 0x4938, 0xAF4C, 0x5C5C, 0, 0xAF4D, 0x5C64, 0x3E40, - 0xC47A, 0x4C4F, 0x5C78, 0x5C6B, 0xC47B, 0, 0, 0, - 0xC47C, 0x3822, 0x3223, 0x335F, 0, 0, 0x5C53, 0, - 0xAF41, 0, 0xAF4F, 0xAF50, 0xAF51, 0x3E41, 0x5C70, 0xC522, - 0x5C77, 0x3C79, 0x3372, 0x762A, 0, 0x432E, 0x762B, 0xAF52, -}; -static const unsigned short utf8_to_euc_E6A9[] = { - 0, 0, 0, 0, 0x5C6D, 0xC526, 0xC527, 0x5C72, - 0x5C76, 0xC528, 0xC529, 0x3636, 0, 0, 0xC52A, 0, - 0xC52B, 0xC52C, 0xC52D, 0, 0, 0xC52E, 0xC52F, 0, - 0x354C, 0x5C74, 0, 0xC530, 0, 0, 0, 0x3521, - 0, 0x464B, 0x5C73, 0, 0xC531, 0, 0x5C75, 0xC532, - 0, 0, 0xC533, 0xF449, 0, 0, 0, 0, - 0, 0xC534, 0x5C6F, 0xC535, 0, 0, 0, 0, - 0x5C71, 0, 0, 0, 0, 0, 0xC536, 0x3360, -}; -static const unsigned short utf8_to_euc_E6A9_x0213[] = { - 0, 0, 0, 0, 0x5C6D, 0x762C, 0xAF53, 0x5C72, - 0x5C76, 0xAF54, 0xC529, 0x3636, 0, 0, 0xAF56, 0, - 0x762D, 0xC52C, 0xAF57, 0, 0, 0xC52E, 0x762E, 0, - 0x354C, 0x5C74, 0, 0x762F, 0, 0, 0, 0x3521, - 0, 0x464B, 0x5C73, 0, 0xAF58, 0, 0x5C75, 0xC532, - 0, 0, 0xC533, 0x7630, 0, 0, 0, 0, - 0, 0xC534, 0x5C6F, 0x7631, 0, 0, 0, 0, - 0x5C71, 0, 0xAF55, 0, 0, 0, 0xAF5A, 0x3360, -}; -static const unsigned short utf8_to_euc_E6AA[] = { - 0x4349, 0xC537, 0, 0xC538, 0x5C7C, 0, 0xC539, 0xC53A, - 0, 0xC53B, 0, 0xC53C, 0, 0x5C7A, 0x3869, 0, - 0x5C79, 0xC53D, 0, 0, 0, 0, 0, 0x5D21, - 0, 0, 0, 0xC53E, 0x5B58, 0xC53F, 0xC540, 0xC541, - 0x5C7B, 0, 0x5C7D, 0x5C7E, 0, 0xC542, 0, 0, - 0, 0, 0x5D2C, 0xC543, 0x5D28, 0, 0x5B6D, 0xC544, - 0xC545, 0xC546, 0, 0x5D27, 0xC547, 0, 0, 0, - 0x5D26, 0, 0, 0x5D23, 0, 0xC548, 0xC549, 0xC54A, -}; -static const unsigned short utf8_to_euc_E6AA_x0213[] = { - 0x4349, 0xC537, 0, 0xAF5B, 0x5C7C, 0, 0xC539, 0xC53A, - 0, 0x7633, 0, 0xAF5C, 0, 0x5C7A, 0x3869, 0, - 0x5C79, 0xAF5E, 0, 0, 0x7634, 0, 0, 0x5D21, - 0, 0, 0, 0xC53E, 0x5B58, 0x7635, 0x7636, 0xAF5F, - 0x5C7B, 0xAF60, 0x5C7D, 0x5C7E, 0, 0x7637, 0, 0, - 0, 0, 0x5D2C, 0xAF62, 0x5D28, 0, 0x5B6D, 0xC544, - 0xC545, 0xC546, 0, 0x5D27, 0xC547, 0, 0, 0, - 0x5D26, 0, 0, 0x5D23, 0, 0xAF63, 0xC549, 0xC54A, -}; -static const unsigned short utf8_to_euc_E6AB[] = { - 0, 0x5C6A, 0x5D25, 0x5D24, 0, 0, 0xC54B, 0, - 0xC54D, 0xC54C, 0, 0, 0xC54E, 0, 0, 0, - 0xC54F, 0x5D2A, 0, 0x4F26, 0xC550, 0xC551, 0xC552, 0, - 0, 0, 0x5D2D, 0x367B, 0xC553, 0xC554, 0x5D29, 0x5D2B, - 0, 0, 0xF44A, 0, 0xC555, 0, 0, 0xC556, - 0x4827, 0, 0x5D2E, 0, 0xC557, 0, 0, 0, - 0xC558, 0xC559, 0xC55A, 0, 0, 0, 0, 0, - 0, 0, 0x5D32, 0x5D2F, 0xC55B, 0xC55C, 0, 0, -}; -static const unsigned short utf8_to_euc_E6AB_x0213[] = { - 0, 0x5C6A, 0x5D25, 0x5D24, 0, 0, 0xAF64, 0, - 0xC54D, 0xC54C, 0, 0, 0xC54E, 0, 0, 0, - 0xAF66, 0x5D2A, 0, 0x4F26, 0xAF65, 0xC551, 0xC552, 0, - 0, 0, 0x5D2D, 0x367B, 0xAF67, 0xAF68, 0x5D29, 0x5D2B, - 0, 0, 0, 0, 0x7638, 0, 0, 0x7639, - 0x4827, 0, 0x5D2E, 0, 0xAF6B, 0, 0, 0, - 0xC558, 0xAF6C, 0xAF6D, 0xAF6E, 0, 0, 0, 0, - 0, 0, 0x5D32, 0x5D2F, 0xC55B, 0xAF6F, 0, 0, -}; -static const unsigned short utf8_to_euc_E6AC[] = { - 0, 0, 0xC55D, 0xC55E, 0x4D73, 0x5D30, 0xC55F, 0xC560, - 0, 0xC561, 0x5C5E, 0, 0, 0, 0, 0xC562, - 0xC563, 0xC564, 0x5D33, 0, 0, 0, 0x5D34, 0xC565, - 0, 0, 0, 0xC566, 0, 0x3135, 0xC567, 0x5D36, - 0x3767, 0x3C21, 0, 0x3655, 0xC568, 0, 0, 0x3224, - 0xC569, 0, 0, 0xC56A, 0xC56B, 0, 0, 0xC56C, - 0, 0, 0x4D5F, 0, 0, 0xC56D, 0xC56E, 0x5D38, - 0x5D37, 0x5D3A, 0x353D, 0xC56F, 0, 0x3656, 0x343E, 0xC570, -}; -static const unsigned short utf8_to_euc_E6AC_x0213[] = { - 0, 0, 0xC55D, 0xC55E, 0x4D73, 0x5D30, 0xC55F, 0xC560, - 0, 0xC561, 0x5C5E, 0xAF71, 0, 0, 0, 0xAF72, - 0xAF73, 0xAF74, 0x5D33, 0, 0, 0, 0x5D34, 0xAF76, - 0, 0, 0, 0x763C, 0, 0x3135, 0x763D, 0x5D36, - 0x3767, 0x3C21, 0, 0x3655, 0xC568, 0, 0, 0x3224, - 0xC569, 0, 0, 0xC56A, 0x763E, 0, 0, 0xAF78, - 0, 0, 0x4D5F, 0, 0, 0x763F, 0xC56E, 0x5D38, - 0x5D37, 0x5D3A, 0x353D, 0xC56F, 0, 0x3656, 0x343E, 0xC570, -}; -static const unsigned short utf8_to_euc_E6AD[] = { - 0, 0, 0, 0x5D3D, 0, 0, 0xC571, 0x5D3C, - 0, 0x5D3E, 0xC572, 0, 0x324E, 0xC573, 0x4337, 0, - 0x5D3F, 0, 0xC574, 0x343F, 0x5D41, 0, 0xC575, 0, - 0xC576, 0x5D40, 0, 0x5D42, 0, 0xC577, 0, 0x5D43, - 0xC578, 0x5D44, 0x3B5F, 0x4035, 0x3A21, 0, 0x4970, 0xC579, - 0, 0x4A62, 0x4F44, 0xC57A, 0, 0, 0xC57B, 0x3B75, - 0xC57C, 0, 0, 0x3A50, 0x4E72, 0xC57D, 0, 0, - 0x5D45, 0x5D46, 0, 0x3B60, 0, 0xC57E, 0xC621, 0x5D47, -}; -static const unsigned short utf8_to_euc_E6AD_x0213[] = { - 0, 0, 0, 0x5D3D, 0, 0, 0x7640, 0x5D3C, - 0, 0x5D3E, 0xAF79, 0, 0x324E, 0xC573, 0x4337, 0, - 0x5D3F, 0, 0xC574, 0x343F, 0x5D41, 0, 0x7641, 0, - 0xAF7A, 0x5D40, 0, 0x5D42, 0, 0xC577, 0, 0x5D43, - 0x7642, 0x5D44, 0x3B5F, 0x4035, 0x3A21, 0x7643, 0x4970, 0x7644, - 0, 0x4A62, 0x4F44, 0xC57A, 0xAF7B, 0, 0xC57B, 0x3B75, - 0xC57C, 0, 0, 0x3A50, 0x4E72, 0xAF7C, 0, 0x7645, - 0x5D45, 0x5D46, 0xAF7D, 0x3B60, 0, 0xC57E, 0xC621, 0x5D47, -}; -static const unsigned short utf8_to_euc_E6AE[] = { - 0x5D48, 0, 0xC622, 0x5D4A, 0x5D49, 0xC623, 0x4B58, 0, - 0, 0x3D5E, 0x3C6C, 0x3B44, 0, 0x5D4B, 0, 0, - 0, 0, 0, 0, 0, 0x5D4D, 0x3F23, 0xC624, - 0x5D4C, 0, 0, 0xC625, 0, 0, 0x5D4E, 0xC626, - 0xC627, 0, 0xC628, 0xC629, 0x5D4F, 0, 0, 0, - 0xC62A, 0xC62B, 0x5D50, 0x5D51, 0xC62C, 0xC62D, 0xC62E, 0x5D52, - 0xC62F, 0x5D54, 0x5D53, 0x5D55, 0x3225, 0x434A, 0, 0x5D56, - 0xC630, 0xC631, 0x3B26, 0x334C, 0x5D57, 0xC632, 0xC633, 0x4542, -}; -static const unsigned short utf8_to_euc_E6AE_x0213[] = { - 0x5D48, 0xAF7E, 0x7646, 0x5D4A, 0x5D49, 0xC623, 0x4B58, 0, - 0, 0x3D5E, 0x3C6C, 0x3B44, 0, 0x5D4B, 0, 0, - 0, 0, 0, 0, 0, 0x5D4D, 0x3F23, 0xC624, - 0x5D4C, 0, 0, 0xEE21, 0, 0, 0x5D4E, 0xC626, - 0xC627, 0, 0xC628, 0xC629, 0x5D4F, 0, 0, 0, - 0xC62A, 0x7647, 0x5D50, 0x5D51, 0xC62C, 0x7648, 0xEE22, 0x5D52, - 0xC62F, 0x5D54, 0x5D53, 0x5D55, 0x3225, 0x434A, 0, 0x5D56, - 0xC630, 0xC631, 0x3B26, 0x334C, 0x5D57, 0xEE24, 0xEE25, 0x4542, -}; -static const unsigned short utf8_to_euc_E6AF[] = { - 0x544C, 0, 0, 0xC634, 0xC635, 0x3523, 0x5D58, 0, - 0, 0xC636, 0, 0x5D59, 0xC637, 0x4A6C, 0x4B68, 0, - 0, 0, 0x4647, 0x5D5A, 0x4866, 0, 0xC638, 0, - 0x487B, 0, 0xC639, 0x4C53, 0, 0, 0, 0x5D5B, - 0, 0xC63A, 0, 0xC63B, 0, 0, 0xC63C, 0xC63D, - 0, 0, 0, 0x5D5D, 0x5D5C, 0, 0xC63E, 0x5D5F, - 0, 0xC63F, 0, 0x5D5E, 0, 0, 0, 0xC640, - 0, 0xC641, 0, 0, 0, 0, 0, 0xC642, -}; -static const unsigned short utf8_to_euc_E6AF_x0213[] = { - 0x544C, 0, 0, 0xC634, 0xC635, 0x3523, 0x5D58, 0xEE26, - 0xEE27, 0xEE28, 0, 0x5D59, 0xC637, 0x4A6C, 0x4B68, 0x764A, - 0, 0, 0x4647, 0x5D5A, 0x4866, 0, 0x764B, 0x764C, - 0x487B, 0, 0xEE29, 0x4C53, 0, 0, 0, 0x5D5B, - 0, 0xC63A, 0, 0xC63B, 0, 0, 0xEE2A, 0xEE2B, - 0, 0, 0, 0x5D5D, 0x5D5C, 0, 0xEE2C, 0x5D5F, - 0, 0xEE2D, 0, 0x5D5E, 0, 0, 0, 0xC640, - 0, 0xC641, 0, 0, 0, 0, 0, 0x764D, -}; -static const unsigned short utf8_to_euc_E6B0[] = { - 0, 0, 0xC643, 0, 0xC644, 0xC645, 0, 0, - 0x5D61, 0xC646, 0, 0, 0, 0xC647, 0xC648, 0x3B61, - 0xC649, 0x4C31, 0xC64A, 0x5D62, 0x5D63, 0, 0, 0x3524, - 0, 0xC64B, 0, 0x5D64, 0, 0, 0, 0xC64C, - 0, 0, 0, 0x5D66, 0x5D65, 0, 0xC64D, 0xC64E, - 0xC64F, 0, 0, 0, 0xC650, 0, 0xC651, 0, - 0, 0, 0, 0xC652, 0x3F65, 0xC653, 0xC654, 0x4939, - 0x314A, 0, 0xC655, 0xC656, 0, 0, 0x4845, 0xC657, -}; -static const unsigned short utf8_to_euc_E6B0_x0213[] = { - 0, 0, 0xEE2E, 0, 0xC644, 0x764E, 0, 0, - 0x5D61, 0xC646, 0xEE2F, 0, 0, 0xC647, 0xEE30, 0x3B61, - 0x764F, 0x4C31, 0xC64A, 0x5D62, 0x5D63, 0, 0, 0x3524, - 0, 0xC64B, 0, 0x5D64, 0, 0, 0, 0xC64C, - 0, 0, 0, 0x5D66, 0x5D65, 0, 0xC64D, 0xC64E, - 0xC64F, 0, 0, 0, 0xC650, 0, 0xC651, 0, - 0, 0, 0, 0x7650, 0x3F65, 0xEE31, 0xEE32, 0x4939, - 0x314A, 0, 0xEE33, 0xC656, 0, 0, 0x4845, 0xEE35, -}; -static const unsigned short utf8_to_euc_E6B1[] = { - 0x4475, 0x3D41, 0x3561, 0, 0, 0, 0, 0, - 0, 0, 0xC658, 0xC659, 0, 0xC65A, 0x4846, 0xC65B, - 0x3C2E, 0, 0xC65C, 0, 0xC65D, 0x5D68, 0, 0x3440, - 0, 0xC65E, 0x3178, 0xC65F, 0xC660, 0x4672, 0x5D67, 0x393E, - 0x4353, 0, 0x5D69, 0, 0, 0, 0, 0xC736, - 0x5D71, 0, 0x5D6A, 0xC661, 0, 0xC662, 0, 0xC663, - 0x4241, 0, 0x3562, 0x5D72, 0xC664, 0, 0xC665, 0, - 0xC666, 0xC667, 0x3768, 0xC668, 0, 0x3525, 0x5D70, 0, -}; -static const unsigned short utf8_to_euc_E6B1_x0213[] = { - 0x4475, 0x3D41, 0x3561, 0, 0, 0, 0, 0, - 0, 0, 0xC658, 0xC659, 0, 0xEE36, 0x4846, 0xC65B, - 0x3C2E, 0, 0xC65C, 0, 0xC65D, 0x5D68, 0, 0x3440, - 0, 0x7651, 0x3178, 0xEE37, 0x7652, 0x4672, 0x5D67, 0x393E, - 0x4353, 0, 0x5D69, 0, 0, 0, 0, 0xEE4F, - 0x5D71, 0, 0x5D6A, 0xC661, 0, 0xEE38, 0, 0, - 0x4241, 0, 0x3562, 0x5D72, 0x7654, 0, 0x7655, 0, - 0xC666, 0xC667, 0x3768, 0xC668, 0, 0x3525, 0x5D70, 0, -}; -static const unsigned short utf8_to_euc_E6B2[] = { - 0, 0x5D6E, 0x5D6B, 0x4D60, 0, 0xC669, 0xC66A, 0xC66B, - 0x4440, 0xC66C, 0, 0, 0x4659, 0x5D6C, 0, 0, - 0x5D74, 0, 0x5D73, 0x3723, 0xC66D, 0xC66E, 0x322D, 0xC66F, - 0xC670, 0x3A3B, 0x5D6D, 0x5D6F, 0xC671, 0, 0, 0xC672, - 0, 0x4B57, 0x4274, 0, 0, 0, 0, 0, - 0, 0, 0, 0x4B77, 0, 0, 0x5D7C, 0, - 0xC673, 0x5D7D, 0xC674, 0x324F, 0xC675, 0, 0, 0, - 0x4A28, 0x4C7D, 0x5E21, 0x3C23, 0x3E42, 0x5D78, 0x5D7E, 0x3168, -}; -static const unsigned short utf8_to_euc_E6B2_x0213[] = { - 0, 0x5D6E, 0x5D6B, 0x4D60, 0xEE39, 0x7656, 0x7657, 0xC66B, - 0x4440, 0xEE3A, 0, 0, 0x4659, 0x5D6C, 0, 0, - 0x5D74, 0, 0x5D73, 0x3723, 0xEE3C, 0xEE3D, 0x322D, 0xEE3E, - 0x7658, 0x3A3B, 0x5D6D, 0x5D6F, 0x7659, 0, 0, 0xC672, - 0, 0x4B57, 0x4274, 0, 0, 0, 0, 0, - 0, 0, 0x7653, 0x4B77, 0, 0xEE3F, 0x5D7C, 0, - 0xC673, 0x5D7D, 0xC674, 0x324F, 0xC675, 0, 0, 0, - 0x4A28, 0x4C7D, 0x5E21, 0x3C23, 0x3E42, 0x5D78, 0x5D7E, 0x3168, -}; -static const unsigned short utf8_to_euc_E6B3[] = { - 0, 0x3637, 0xC676, 0, 0x5D75, 0x5D7A, 0xC677, 0, - 0, 0x4074, 0x4771, 0, 0x4867, 0xC678, 0, 0xC679, - 0xC67A, 0xC67B, 0xC67C, 0x5D77, 0xC67D, 0x4B21, 0xC67E, 0x5D79, - 0, 0x5E24, 0xC721, 0x5E22, 0xC722, 0x5D7B, 0, 0, - 0xC723, 0x4B22, 0x4748, 0x3563, 0, 0x4525, 0, 0xC724, - 0x436D, 0xC725, 0x5E25, 0xC726, 0xC727, 0, 0xC728, 0x5E23, - 0x4259, 0x5D76, 0xC729, 0x314B, 0xC72A, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E6B3_x0213[] = { - 0, 0x3637, 0xEE40, 0, 0x5D75, 0x5D7A, 0x765B, 0, - 0, 0x4074, 0x4771, 0, 0x4867, 0xC678, 0, 0xC679, - 0xEE41, 0xC67B, 0xC67C, 0x5D77, 0x765C, 0x4B21, 0xEE43, 0x5D79, - 0, 0x5E24, 0xEE44, 0x5E22, 0xEE45, 0x5D7B, 0, 0, - 0x765D, 0x4B22, 0x4748, 0x3563, 0, 0x4525, 0, 0xC724, - 0x436D, 0xEE46, 0x5E25, 0x765E, 0xEE47, 0xEE48, 0x765F, 0x5E23, - 0x4259, 0x5D76, 0xC729, 0x314B, 0xC72A, 0, 0, 0, - 0, 0, 0, 0x765A, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E6B4[] = { - 0, 0, 0, 0, 0xC72B, 0, 0, 0xC72C, - 0, 0, 0xC72D, 0x4D4E, 0x5E30, 0, 0xC72E, 0xC72F, - 0, 0xC730, 0x5E2F, 0xC731, 0, 0, 0, 0x4076, - 0, 0x5E2C, 0xC732, 0x4D6C, 0, 0, 0x4636, 0x5E26, - 0, 0, 0, 0, 0, 0x4445, 0xC733, 0xC734, - 0xC735, 0x314C, 0x393F, 0x5E29, 0, 0, 0xC737, 0xC738, - 0, 0xC739, 0x3D27, 0x5E2E, 0, 0x5E2D, 0x5E28, 0, - 0x5E2B, 0xC73A, 0, 0x3368, 0xC73B, 0x5E2A, 0x4749, 0xC73C, -}; -static const unsigned short utf8_to_euc_E6B4_x0213[] = { - 0xEE4A, 0, 0, 0, 0x7661, 0, 0, 0xC72C, - 0, 0, 0xEE4B, 0x4D4E, 0x5E30, 0, 0x7662, 0xC72F, - 0, 0xC730, 0x5E2F, 0xC731, 0, 0, 0, 0x4076, - 0, 0x5E2C, 0xC732, 0x4D6C, 0, 0, 0x4636, 0x5E26, - 0, 0, 0, 0, 0xEE4C, 0x4445, 0xEE4D, 0xEE4E, - 0xC735, 0x314C, 0x393F, 0x5E29, 0, 0, 0x7663, 0xEE50, - 0, 0x7664, 0x3D27, 0x5E2E, 0xEE65, 0x5E2D, 0x5E28, 0, - 0x5E2B, 0x7665, 0, 0x3368, 0xEE51, 0x5E2A, 0x4749, 0x7666, -}; -static const unsigned short utf8_to_euc_E6B5[] = { - 0, 0x4E2E, 0, 0, 0x3E74, 0x4075, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0xC73D, - 0, 0x5E36, 0x5E34, 0, 0x494D, 0, 0xC73E, 0xC73F, - 0, 0xC740, 0, 0x5E31, 0x5E33, 0xC741, 0x313A, 0xC742, - 0, 0x3940, 0x4F32, 0, 0x333D, 0, 0x4962, 0xC743, - 0xC744, 0, 0, 0, 0x4D61, 0, 0, 0x3324, - 0x3F3B, 0x5E35, 0, 0, 0xC745, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E6B5_x0213[] = { - 0, 0x4E2E, 0, 0, 0x3E74, 0x4075, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0xC73D, - 0x7667, 0x5E36, 0x5E34, 0xEE52, 0x494D, 0, 0xEE53, 0xC73F, - 0xEE54, 0xC740, 0, 0x5E31, 0x5E33, 0x7668, 0x313A, 0xC742, - 0, 0x3940, 0x4F32, 0, 0x333D, 0, 0x4962, 0, - 0xEE55, 0, 0, 0, 0x4D61, 0, 0, 0x3324, - 0x3F3B, 0x5E35, 0, 0, 0xC745, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E6B6[] = { - 0, 0, 0xC746, 0, 0, 0x5E3A, 0, 0xC747, - 0x3E43, 0, 0, 0, 0x4D30, 0, 0x5E37, 0, - 0, 0xC748, 0xC749, 0x5E32, 0xC74A, 0x5E38, 0xC74B, 0xC74C, - 0xC74D, 0x4E5E, 0, 0x4573, 0x4642, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0xC74E, 0, 0xC74F, 0, 0, 0x3336, - 0, 0, 0x3155, 0, 0xC750, 0x5E3E, 0, 0xC751, - 0x5E41, 0xC752, 0, 0, 0x4E43, 0xC753, 0, 0xC754, -}; -static const unsigned short utf8_to_euc_E6B6_x0213[] = { - 0xEE56, 0xEE57, 0x766A, 0, 0, 0x5E3A, 0, 0x766B, - 0x3E43, 0x766C, 0xEE58, 0, 0x4D30, 0xEE59, 0x5E37, 0, - 0, 0xEE5A, 0xC749, 0x5E32, 0x766D, 0x5E38, 0, 0xC74C, - 0xEE5B, 0x4E5E, 0, 0x4573, 0x4642, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0x766E, 0xEE61, 0x766F, 0, 0xEE62, 0x3336, - 0, 0, 0x3155, 0, 0xEE63, 0x5E3E, 0, 0xC751, - 0x5E41, 0xC752, 0, 0, 0x4E43, 0xC753, 0, 0x7670, -}; -static const unsigned short utf8_to_euc_E6B7[] = { - 0x4D64, 0, 0, 0, 0xC755, 0x5E48, 0x5E42, 0x5E3F, - 0xC756, 0, 0xC757, 0x4E54, 0x5E45, 0, 0xC758, 0xC759, - 0, 0x3D4A, 0x5E47, 0, 0, 0x5E4C, 0xC75A, 0, - 0x4571, 0x5E4A, 0, 0xC75B, 0, 0xC75C, 0x5E44, 0xC75D, - 0xC75E, 0x4338, 0xC75F, 0, 0x5E4B, 0xC760, 0x5E40, 0, - 0x5E46, 0xC761, 0x5E4D, 0x307C, 0x5E43, 0, 0x5E4E, 0xC762, - 0xC763, 0x3F3C, 0xF44C, 0x3D5F, 0xC764, 0x4A25, 0xC765, 0x3A2E, - 0xF44B, 0x5E3B, 0x5E49, 0x453A, 0xC766, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E6B7_x0213[] = { - 0x4D64, 0, 0xEE64, 0, 0x7671, 0x5E48, 0x5E42, 0x5E3F, - 0xEE66, 0, 0xC757, 0x4E54, 0x5E45, 0, 0xEE67, 0xEE68, - 0xEE69, 0x3D4A, 0x5E47, 0, 0, 0x5E4C, 0x7672, 0, - 0x4571, 0x5E4A, 0x7673, 0x7674, 0, 0x7675, 0x5E44, 0xEE6A, - 0xC75E, 0x4338, 0xC75F, 0, 0x5E4B, 0xC760, 0x5E40, 0, - 0x5E46, 0xEE6B, 0x5E4D, 0x307C, 0x5E43, 0, 0x5E4E, 0xC762, - 0xC763, 0x3F3C, 0, 0x3D5F, 0xC764, 0x4A25, 0xEE6C, 0x3A2E, - 0, 0x5E3B, 0x5E49, 0x453A, 0x7676, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E6B8[] = { - 0xC767, 0, 0, 0, 0xC768, 0x4036, 0, 0x3369, - 0x3A51, 0x3E44, 0x5E3D, 0x3D42, 0, 0, 0, 0, - 0, 0, 0, 0x374C, 0, 0x5E3C, 0, 0, - 0, 0x5E52, 0x3D6D, 0x383A, 0, 0x5E61, 0xC769, 0x5E5B, - 0x3574, 0x454F, 0xC76A, 0x5E56, 0x5E5F, 0x302F, 0x3132, 0xC76B, - 0, 0x3239, 0, 0x5E58, 0x422C, 0x5E4F, 0x5E51, 0x3941, - 0, 0, 0xC76C, 0, 0, 0, 0xC76D, 0, - 0x5E62, 0xC76E, 0x5E5D, 0xC76F, 0xC770, 0, 0x5E55, 0, -}; -static const unsigned short utf8_to_euc_E6B8_x0213[] = { - 0xC767, 0, 0, 0, 0xC768, 0x4036, 0, 0x3369, - 0x3A51, 0x3E44, 0x5E3D, 0x3D42, 0, 0, 0, 0, - 0, 0, 0, 0x374C, 0, 0x5E3C, 0, 0xEE5D, - 0, 0x5E52, 0x3D6D, 0x383A, 0, 0x5E61, 0xEE6E, 0x5E5B, - 0x3574, 0x454F, 0xEE6F, 0x5E56, 0x5E5F, 0x302F, 0x3132, 0xEE70, - 0, 0x3239, 0, 0x5E58, 0x422C, 0x5E4F, 0x5E51, 0x3941, - 0, 0, 0xEE72, 0, 0x7678, 0, 0xEE6D, 0, - 0x5E62, 0, 0x5E5D, 0xC76F, 0xEE73, 0, 0x5E55, 0, -}; -static const unsigned short utf8_to_euc_E6B9[] = { - 0, 0, 0, 0x5E5C, 0xC771, 0xC772, 0, 0, - 0xC773, 0xC774, 0x4C2B, 0xC775, 0, 0x5E5A, 0x5E5E, 0xC776, - 0, 0xC777, 0xC778, 0xC779, 0xC77A, 0, 0x3850, 0xC77B, - 0x3E45, 0, 0, 0x4339, 0xC77C, 0xC77D, 0xC77E, 0x5E54, - 0, 0, 0xC821, 0xC822, 0, 0, 0, 0x4D2F, - 0xC823, 0, 0, 0x5E57, 0, 0, 0x5E50, 0x4572, - 0, 0, 0x5E53, 0xC824, 0, 0, 0x5E59, 0, - 0, 0, 0, 0xC825, 0, 0xC826, 0x4F51, 0x3C3E, -}; -static const unsigned short utf8_to_euc_E6B9_x0213[] = { - 0, 0, 0, 0x5E5C, 0x7679, 0xC772, 0, 0, - 0xEE74, 0xEE75, 0x4C2B, 0xEE76, 0xEE77, 0x5E5A, 0x5E5E, 0xEE78, - 0, 0xEE79, 0xC778, 0xEE7A, 0xEE7B, 0, 0x3850, 0xEE7C, - 0x3E45, 0, 0, 0x4339, 0x767A, 0xC77D, 0x767B, 0x5E54, - 0, 0, 0xC821, 0xEE7D, 0, 0, 0, 0x4D2F, - 0xC823, 0, 0, 0x5E57, 0, 0, 0x5E50, 0x4572, - 0, 0, 0x5E53, 0xC824, 0, 0, 0x5E59, 0, - 0, 0, 0, 0xC825, 0, 0xC826, 0x4F51, 0x3C3E, -}; -static const unsigned short utf8_to_euc_E6BA[] = { - 0x4B7E, 0, 0x5E63, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0x482E, 0xC827, 0, 0x5E6F, - 0x383B, 0, 0, 0xC828, 0, 0, 0x3D60, 0, - 0x5E65, 0xC829, 0, 0, 0x4E2F, 0x3942, 0, 0x5E72, - 0xC82A, 0, 0x306E, 0, 0, 0x5E70, 0, 0xC82B, - 0, 0, 0x5E64, 0, 0, 0xC82C, 0xC82D, 0x5E6A, - 0, 0xC82E, 0x5E6C, 0xC82F, 0, 0, 0x4D4F, 0x5E67, - 0, 0, 0x452E, 0xC830, 0, 0x5E69, 0, 0xC831, -}; -static const unsigned short utf8_to_euc_E6BA_x0213[] = { - 0x4B7E, 0, 0x5E63, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0x482E, 0xC827, 0, 0x5E6F, - 0x383B, 0, 0, 0xEF21, 0, 0, 0x3D60, 0, - 0x5E65, 0xC829, 0, 0, 0x4E2F, 0x3942, 0, 0x5E72, - 0xC82A, 0, 0x306E, 0, 0, 0x5E70, 0, 0xEF22, - 0, 0, 0x5E64, 0x767C, 0, 0xC82C, 0xC82D, 0x5E6A, - 0, 0x767D, 0x5E6C, 0xC82F, 0xEF23, 0, 0x4D4F, 0x5E67, - 0, 0, 0x452E, 0xC830, 0, 0x5E69, 0, 0xEF24, -}; -static const unsigned short utf8_to_euc_E6BB[] = { - 0xC832, 0xC833, 0x5E71, 0xC834, 0x5E6B, 0x4C47, 0, 0xC835, - 0xC836, 0x5E66, 0xC837, 0x3C22, 0x5E7E, 0xC838, 0xC839, 0xC83A, - 0, 0x336A, 0, 0x5E68, 0x5E6D, 0x5E6E, 0, 0, - 0, 0, 0, 0, 0, 0x426C, 0x425A, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0xC83B, 0x5E76, 0xC83C, 0xC83D, 0x5E7C, - 0, 0, 0x5E7A, 0, 0x4529, 0, 0, 0x5F23, - 0x5E77, 0xC83E, 0, 0xC83F, 0, 0xC840, 0x5E78, 0x5E60, -}; -static const unsigned short utf8_to_euc_E6BB_x0213[] = { - 0xC832, 0x767E, 0x5E71, 0xEF25, 0x5E6B, 0x4C47, 0, 0x7721, - 0xC836, 0x5E66, 0xEF26, 0x3C22, 0x5E7E, 0xC838, 0x7722, 0xC83A, - 0, 0x336A, 0, 0x5E68, 0x5E6D, 0x5E6E, 0, 0, - 0, 0xEF27, 0, 0, 0, 0x426C, 0x425A, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0xEF29, 0x5E76, 0xC83C, 0xC83D, 0x5E7C, - 0, 0, 0x5E7A, 0, 0x4529, 0, 0, 0x5F23, - 0x5E77, 0xEF2A, 0, 0xEF2B, 0, 0xC840, 0x5E78, 0x5E60, -}; -static const unsigned short utf8_to_euc_E6BC[] = { - 0, 0x3579, 0x493A, 0, 0xC841, 0, 0x3C3F, 0, - 0xC842, 0x3977, 0xC843, 0, 0xC844, 0xC845, 0, 0x4F33, - 0, 0x5E74, 0, 0x5F22, 0x3169, 0x4166, 0xC846, 0, - 0xC847, 0, 0xC848, 0xC849, 0, 0, 0, 0, - 0x4779, 0, 0x3441, 0x4E7A, 0, 0, 0xC84A, 0, - 0, 0xC84B, 0xC84C, 0x4C21, 0x4452, 0xC853, 0, 0xC84D, - 0xC84E, 0x5E7B, 0x5E7D, 0xC84F, 0, 0, 0xC850, 0, - 0x4132, 0, 0, 0xC851, 0xC852, 0, 0x5F21, 0x5E79, -}; -static const unsigned short utf8_to_euc_E6BC_x0213[] = { - 0, 0x3579, 0x493A, 0, 0xC841, 0, 0x3C3F, 0, - 0xC842, 0x3977, 0xEF2C, 0, 0xEF2D, 0xC845, 0, 0x4F33, - 0x7723, 0x5E74, 0, 0x5F22, 0x3169, 0x4166, 0xC846, 0, - 0xEF2E, 0, 0x7724, 0xC849, 0, 0, 0, 0, - 0x4779, 0, 0x3441, 0x4E7A, 0, 0xEF2F, 0xC84A, 0, - 0, 0xC84B, 0x7726, 0x4C21, 0x4452, 0xC853, 0, 0x7727, - 0xC84E, 0x5E7B, 0x5E7D, 0x7728, 0, 0xEF28, 0xEF30, 0, - 0x4132, 0, 0, 0xC851, 0xEF31, 0, 0x5F21, 0x5E79, -}; -static const unsigned short utf8_to_euc_E6BD[] = { - 0, 0x5E73, 0, 0, 0, 0x3443, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0xC854, - 0, 0xC855, 0xC856, 0xC857, 0x3769, 0, 0, 0xC858, - 0x5F2F, 0xC859, 0xC85A, 0x5F2A, 0x4078, 0xC85B, 0xC85C, 0x3363, - 0, 0xC85D, 0xC85E, 0, 0x3D61, 0, 0x5F33, 0, - 0xC85F, 0, 0, 0, 0xC860, 0x5F2C, 0x442C, 0x5F29, - 0x4459, 0, 0, 0, 0x5F4C, 0, 0, 0, - 0x5F26, 0, 0x5F25, 0, 0x5F2E, 0xC861, 0xC862, 0, -}; -static const unsigned short utf8_to_euc_E6BD_x0213[] = { - 0, 0x5E73, 0, 0, 0, 0x3443, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0xC854, - 0, 0x7729, 0xEF33, 0xC857, 0x3769, 0, 0, 0xEF34, - 0x5F2F, 0x772A, 0xEF35, 0x5F2A, 0x4078, 0xC85B, 0x772B, 0x3363, - 0xEF36, 0x772C, 0x772D, 0, 0x3D61, 0, 0x5F33, 0, - 0xEF37, 0, 0, 0, 0xC860, 0x5F2C, 0x442C, 0x5F29, - 0x4459, 0, 0, 0, 0x5F4C, 0, 0, 0, - 0x5F26, 0, 0x5F25, 0, 0x5F2E, 0xEF39, 0x772E, 0, -}; -static const unsigned short utf8_to_euc_E6BE[] = { - 0x5F28, 0x5F27, 0x5F2D, 0xC863, 0x4021, 0, 0x5F24, 0xC864, - 0xC865, 0, 0, 0xC866, 0xC867, 0xC868, 0x5F30, 0, - 0xC869, 0x5F31, 0xC86A, 0xC86B, 0xC86C, 0, 0xC86D, 0x3442, - 0, 0, 0xC86E, 0, 0, 0, 0, 0xC86F, - 0xC870, 0x5F36, 0, 0x5F35, 0x5F37, 0xC871, 0xC872, 0xC873, - 0xC874, 0, 0x5F3A, 0, 0, 0, 0xC875, 0xC876, - 0xC877, 0x4543, 0, 0x5F34, 0, 0xC878, 0xC879, 0, - 0, 0x5F38, 0, 0, 0xC87A, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E6BE_x0213[] = { - 0x5F28, 0x5F27, 0x5F2D, 0xC863, 0x4021, 0, 0x5F24, 0xC864, - 0x772F, 0, 0, 0xC866, 0x7730, 0x7731, 0x5F30, 0, - 0xEF3A, 0x5F31, 0xC86A, 0xC86B, 0x7732, 0, 0xEF3B, 0x3442, - 0xEF38, 0, 0xC86E, 0, 0, 0, 0, 0xEF3D, - 0x7733, 0x5F36, 0, 0x5F35, 0x5F37, 0xEF3E, 0xC872, 0x7734, - 0xC874, 0, 0x5F3A, 0, 0, 0, 0xC875, 0xEF3F, - 0xC877, 0x4543, 0, 0x5F34, 0, 0xEF41, 0x7735, 0, - 0, 0x5F38, 0, 0, 0x7736, 0, 0xEF3C, 0, -}; -static const unsigned short utf8_to_euc_E6BF[] = { - 0x3763, 0x4279, 0x5F32, 0x473B, 0, 0xC87B, 0x5F39, 0xC87C, - 0xC87D, 0, 0xC87E, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0x5F3E, 0x5F3C, 0, 0, - 0x5F3F, 0, 0xC921, 0x5F42, 0, 0, 0xC922, 0x5F3B, - 0x396A, 0x4728, 0, 0, 0x5E39, 0, 0, 0, - 0xC923, 0xC924, 0, 0x4D74, 0x5F3D, 0, 0x5F41, 0x4275, - 0xC925, 0x5F40, 0, 0x5F2B, 0, 0xC926, 0x6F69, 0, - 0, 0xC927, 0x5F45, 0, 0xC928, 0xC929, 0x5F49, 0, -}; -static const unsigned short utf8_to_euc_E6BF_x0213[] = { - 0x3763, 0x4279, 0x5F32, 0x473B, 0, 0xC87B, 0x5F39, 0x7737, - 0xEF42, 0xEF43, 0x7738, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0x5F3E, 0x5F3C, 0, 0, - 0x5F3F, 0, 0xEF44, 0x5F42, 0, 0, 0xEF45, 0x5F3B, - 0x396A, 0x4728, 0, 0, 0x5E39, 0, 0, 0, - 0xC923, 0xEF46, 0, 0x4D74, 0x5F3D, 0, 0x5F41, 0x4275, - 0x773A, 0x5F40, 0, 0x5F2B, 0, 0x773B, 0x6F69, 0, - 0, 0x7739, 0x5F45, 0, 0xEF48, 0xC929, 0x5F49, 0, -}; -static const unsigned short utf8_to_euc_E780[] = { - 0xC92A, 0x5F47, 0, 0, 0, 0xC92B, 0xC92C, 0xC92D, - 0, 0x5F43, 0, 0x5F44, 0, 0xC92E, 0, 0x5F48, - 0, 0x5F46, 0, 0, 0, 0x494E, 0, 0xC92F, - 0x5F4E, 0, 0x5F4B, 0x5F4A, 0, 0x5F4D, 0x4654, 0x5F4F, - 0xC930, 0, 0, 0xC931, 0, 0, 0x4375, 0x426D, - 0xF44D, 0, 0, 0, 0x4025, 0, 0, 0xC932, - 0x5F50, 0, 0x5F52, 0, 0xC933, 0, 0, 0xC934, - 0, 0xC935, 0, 0, 0xC936, 0, 0x5F51, 0, -}; -static const unsigned short utf8_to_euc_E780_x0213[] = { - 0xEF49, 0x5F47, 0, 0, 0, 0x773C, 0x773D, 0xEF4A, - 0, 0x5F43, 0xEF4B, 0x5F44, 0, 0xC92E, 0, 0x5F48, - 0, 0x5F46, 0, 0, 0, 0x494E, 0, 0xC92F, - 0x5F4E, 0, 0x5F4B, 0x5F4A, 0, 0x5F4D, 0x4654, 0x5F4F, - 0xC930, 0, 0, 0xEF4C, 0, 0, 0x4375, 0x426D, - 0x773E, 0, 0, 0, 0x4025, 0, 0, 0xC932, - 0x5F50, 0, 0x5F52, 0, 0xC933, 0, 0, 0xC934, - 0, 0xEF4E, 0xEF4F, 0, 0xEF50, 0, 0x5F51, 0, -}; -static const unsigned short utf8_to_euc_E781[] = { - 0, 0, 0, 0xC937, 0xC938, 0, 0, 0, - 0xC939, 0xC93A, 0xC93B, 0xC93C, 0x5E75, 0, 0xC941, 0, - 0, 0x5F53, 0, 0, 0xC93D, 0xC93E, 0, 0, - 0x4667, 0, 0, 0, 0, 0xC93F, 0xC940, 0, - 0, 0, 0, 0x5F54, 0xC942, 0xC943, 0, 0, - 0, 0, 0, 0x3250, 0xC944, 0, 0xC945, 0x4574, - 0x3325, 0, 0, 0, 0, 0xC946, 0xC947, 0, - 0x3564, 0, 0, 0, 0x3C5E, 0x3A52, 0xC948, 0, -}; -static const unsigned short utf8_to_euc_E781_x0213[] = { - 0, 0, 0, 0xEF51, 0xC938, 0, 0, 0xEF52, - 0xC939, 0xC93A, 0x773F, 0xEF53, 0x5E75, 0, 0x7742, 0, - 0, 0x5F53, 0, 0, 0xEF55, 0xC93E, 0, 0, - 0x4667, 0, 0, 0, 0, 0x7740, 0x7741, 0, - 0, 0, 0, 0x5F54, 0x7743, 0xEF56, 0, 0, - 0, 0xEF57, 0, 0x3250, 0xEF58, 0, 0xEF59, 0x4574, - 0x3325, 0, 0, 0, 0, 0x7744, 0xEF5A, 0, - 0x3564, 0, 0, 0, 0x3C5E, 0x3A52, 0xEF5B, 0, -}; -static const unsigned short utf8_to_euc_E782[] = { - 0, 0xC949, 0, 0, 0, 0xC94A, 0xC94B, 0, - 0, 0x4F27, 0x3F66, 0, 0, 0, 0x316A, 0, - 0, 0, 0x5F56, 0, 0xC94C, 0xC94D, 0xC94E, 0xC94F, - 0xC950, 0x5F55, 0, 0xC951, 0, 0, 0, 0, - 0, 0, 0, 0, 0xC952, 0, 0, 0, - 0, 0, 0, 0xC953, 0x5F59, 0x433A, 0x5F5C, 0x5F57, - 0xC954, 0xC955, 0, 0x5F5B, 0xC956, 0, 0, 0xC957, - 0x5F5A, 0x4540, 0x3059, 0xF42E, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E782_x0213[] = { - 0, 0xEF5C, 0, 0, 0, 0x7745, 0xEF5D, 0, - 0, 0x4F27, 0x3F66, 0, 0, 0, 0x316A, 0, - 0, 0, 0x5F56, 0, 0xC94C, 0xEF5E, 0xC94E, 0xEF5F, - 0xC950, 0x5F55, 0, 0xC951, 0, 0, 0, 0xEF62, - 0, 0, 0, 0, 0x7746, 0, 0, 0, - 0, 0, 0, 0x7747, 0x5F59, 0x433A, 0x5F5C, 0x5F57, - 0xC954, 0xEF63, 0, 0x5F5B, 0xC956, 0, 0, 0x7748, - 0x5F5A, 0x4540, 0x3059, 0xEF60, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E783[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0x4E75, 0, 0xC958, 0x5F5E, 0, 0, 0, 0x3128, - 0, 0xC959, 0, 0xC95A, 0xC95B, 0xC95C, 0xC95D, 0, - 0xC95E, 0x5F60, 0, 0, 0xC95F, 0x5F5F, 0, 0x5F5D, - 0, 0, 0, 0, 0xC960, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0x5F58, 0, 0, 0, 0, 0, 0, - 0, 0x4B23, 0xC961, 0, 0, 0x5F62, 0, 0, -}; -static const unsigned short utf8_to_euc_E783_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0x4E75, 0, 0xEF66, 0x5F5E, 0, 0, 0, 0x3128, - 0, 0xEF67, 0, 0xEF68, 0x7749, 0xC95C, 0xC95D, 0, - 0x774A, 0x5F60, 0, 0, 0xEF69, 0x5F5F, 0, 0x5F5D, - 0, 0, 0, 0, 0x774B, 0, 0, 0, - 0, 0, 0, 0, 0xEF65, 0, 0, 0, - 0, 0x5F58, 0, 0, 0, 0, 0, 0, - 0, 0x4B23, 0xC961, 0, 0, 0x5F62, 0, 0, -}; -static const unsigned short utf8_to_euc_E784[] = { - 0, 0, 0, 0xC962, 0xC963, 0xC964, 0xC965, 0xC966, - 0, 0x5F61, 0, 0xC967, 0xC968, 0, 0, 0xC969, - 0, 0, 0, 0, 0x316B, 0, 0, 0, - 0, 0x5F64, 0x4A32, 0, 0x5F63, 0, 0xC96A, 0, - 0xC96B, 0x4C35, 0, 0, 0, 0, 0x3E47, 0, - 0, 0, 0, 0xC96C, 0, 0xC96D, 0, 0xC96E, - 0xC96F, 0xC970, 0, 0, 0, 0, 0x4133, 0, - 0xC971, 0, 0, 0, 0x3E46, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E784_x0213[] = { - 0, 0, 0, 0xEF6A, 0xEF6B, 0xC964, 0xEF6C, 0xEF6D, - 0xEF6E, 0x5F61, 0, 0xC967, 0xEF6F, 0, 0, 0x774C, - 0, 0, 0, 0, 0x316B, 0, 0, 0, - 0, 0x5F64, 0x4A32, 0, 0x5F63, 0, 0x774E, 0, - 0x774F, 0x4C35, 0, 0, 0, 0, 0x3E47, 0, - 0, 0, 0, 0x774D, 0, 0xC96D, 0x7750, 0xEF71, - 0x7751, 0xEF72, 0, 0, 0, 0, 0x4133, 0, - 0xC971, 0, 0, 0, 0x3E46, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E785[] = { - 0, 0xC972, 0, 0, 0, 0xC973, 0xC974, 0xC975, - 0, 0x4E7B, 0xC976, 0xC977, 0x5F6A, 0, 0x4079, 0, - 0xC978, 0, 0xC979, 0, 0, 0x5F66, 0x5F6B, 0xC97A, - 0, 0x316C, 0xC97B, 0, 0xC97C, 0, 0xC97D, 0, - 0xC97E, 0, 0x5F69, 0, 0x4761, 0x5F65, 0x5F68, 0x3E48, - 0xCA21, 0x4851, 0, 0, 0x5F6C, 0, 0x3C51, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0xCA22, 0, 0, 0, 0x407A, 0, 0, -}; -static const unsigned short utf8_to_euc_E785_x0213[] = { - 0, 0xC972, 0, 0, 0, 0xC973, 0x7752, 0x7753, - 0, 0x4E7B, 0xEF74, 0xC977, 0x5F6A, 0, 0x4079, 0, - 0xEF73, 0x7754, 0x7756, 0xEF75, 0, 0x5F66, 0x5F6B, 0xC97A, - 0, 0x316C, 0xC97B, 0, 0x7757, 0, 0xEF76, 0, - 0x7758, 0, 0x5F69, 0, 0x4761, 0x5F65, 0x5F68, 0x3E48, - 0x7759, 0x4851, 0, 0, 0x5F6C, 0, 0x3C51, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0xCA22, 0, 0, 0, 0x407A, 0, 0, -}; -static const unsigned short utf8_to_euc_E786[] = { - 0xCA23, 0, 0, 0, 0x5F6F, 0xCA24, 0, 0xCA25, - 0x5F67, 0, 0x3727, 0, 0xCA26, 0, 0, 0x5F6D, - 0, 0, 0xCA27, 0, 0x4D50, 0x5F70, 0, 0, - 0, 0x7426, 0xCA28, 0xCA29, 0, 0, 0, 0x3D4F, - 0xCA2A, 0, 0xCA2B, 0, 0, 0, 0, 0, - 0x5F71, 0, 0, 0, 0x5F72, 0, 0, 0xCA2C, - 0xCA2D, 0x472E, 0xCA2E, 0xCA2F, 0, 0, 0, 0, - 0, 0x5F74, 0xCA30, 0, 0, 0, 0x5F75, 0xCA31, -}; -static const unsigned short utf8_to_euc_E786_x0213[] = { - 0xEF79, 0, 0, 0, 0x5F6F, 0x775B, 0, 0x775C, - 0x5F67, 0, 0x3727, 0, 0xCA26, 0, 0, 0x5F6D, - 0, 0, 0x775D, 0, 0x4D50, 0x5F70, 0xEF78, 0, - 0, 0x7426, 0xCA28, 0xEF7A, 0, 0, 0, 0x3D4F, - 0xEF7B, 0, 0xEF7C, 0, 0, 0, 0, 0, - 0x5F71, 0, 0, 0, 0x5F72, 0, 0xEF7D, 0xEF7E, - 0xCA2D, 0x472E, 0xCA2E, 0xF021, 0, 0, 0, 0, - 0, 0x5F74, 0x775F, 0, 0, 0, 0x5F75, 0xCA31, -}; -static const unsigned short utf8_to_euc_E787[] = { - 0xCA32, 0xCA33, 0, 0x4733, 0xCA34, 0, 0, 0, - 0x4575, 0x5F77, 0, 0xCA35, 0xCA36, 0, 0x5F79, 0, - 0x4E55, 0, 0x5F76, 0xCA37, 0x5F78, 0x316D, 0xCA38, 0x5F73, - 0, 0xCA39, 0xCA3A, 0, 0xCA3B, 0, 0, 0x535B, - 0x5F7A, 0, 0, 0, 0, 0x4167, 0x3B38, 0x5F7C, - 0, 0, 0, 0, 0x5F7B, 0x3F24, 0x5259, 0, - 0, 0, 0, 0, 0, 0x5F7D, 0, 0, - 0xCA3C, 0x6021, 0, 0x5F6E, 0x5F7E, 0, 0xCA3D, 0x6022, -}; -static const unsigned short utf8_to_euc_E787_x0213[] = { - 0xCA32, 0x775E, 0, 0x4733, 0x7760, 0, 0, 0, - 0x4575, 0x5F77, 0, 0xF023, 0xCA36, 0, 0x5F79, 0, - 0x4E55, 0, 0x5F76, 0xF024, 0x5F78, 0x316D, 0xCA38, 0x5F73, - 0, 0xF025, 0xCA3A, 0, 0xF026, 0, 0, 0x535B, - 0x5F7A, 0, 0, 0, 0, 0x4167, 0x3B38, 0x5F7C, - 0, 0, 0, 0, 0x5F7B, 0x3F24, 0x5259, 0, - 0, 0, 0, 0, 0, 0x5F7D, 0, 0, - 0xCA3C, 0x6021, 0, 0x5F6E, 0x5F7E, 0, 0x7761, 0x6022, -}; -static const unsigned short utf8_to_euc_E788[] = { - 0xCA3E, 0, 0, 0, 0, 0, 0x477A, 0xCA3F, - 0xCA40, 0xCA41, 0, 0, 0, 0x6023, 0, 0, - 0x6024, 0, 0, 0xCA42, 0, 0, 0, 0xCA43, - 0, 0, 0xCA44, 0x6025, 0, 0xCA45, 0, 0xCA46, - 0, 0, 0, 0, 0xCA47, 0, 0, 0, - 0x6026, 0, 0x445E, 0xCA48, 0x6028, 0x6027, 0, 0xCA49, - 0x6029, 0, 0x602A, 0, 0xCA4A, 0x3C5F, 0x4963, 0, - 0xCA4B, 0xCA4C, 0x4C6C, 0x602B, 0x602C, 0x4156, 0x3C24, 0x602D, -}; -static const unsigned short utf8_to_euc_E788_x0213[] = { - 0x7762, 0, 0, 0, 0, 0, 0x477A, 0xF027, - 0xCA40, 0xCA41, 0, 0, 0, 0x6023, 0, 0, - 0x6024, 0, 0, 0xCA42, 0, 0x7763, 0, 0xCA43, - 0, 0, 0xCA44, 0x6025, 0, 0xCA45, 0, 0xCA46, - 0, 0, 0, 0, 0xCA47, 0, 0, 0, - 0x6026, 0, 0x445E, 0xF02A, 0x6028, 0x6027, 0, 0xCA49, - 0x6029, 0, 0x602A, 0, 0xF02B, 0x3C5F, 0x4963, 0, - 0xF02C, 0xF02D, 0x4C6C, 0x602B, 0x602C, 0x4156, 0x3C24, 0x602D, -}; -static const unsigned short utf8_to_euc_E789[] = { - 0x602E, 0xCA4D, 0xCA4E, 0xCA4F, 0, 0xCA50, 0x602F, 0x4A52, - 0x4847, 0, 0, 0x6030, 0x4757, 0, 0xCA51, 0xCA52, - 0xCA53, 0, 0x442D, 0xCA54, 0, 0xCA55, 0xCA56, 0, - 0x6031, 0x3267, 0xCA57, 0x356D, 0xCA58, 0x4C46, 0xCA59, 0x4C36, - 0xCA5A, 0x3234, 0x4F34, 0xCA5B, 0, 0, 0, 0x4B52, - 0xCA5C, 0x4A2A, 0, 0xCA5D, 0, 0, 0xCA5E, 0xCA5F, - 0, 0xCA60, 0x4037, 0, 0x6032, 0, 0, 0xCA61, - 0xCA62, 0x4643, 0, 0xCA63, 0xCA64, 0x3823, 0x6033, 0xCA65, -}; -static const unsigned short utf8_to_euc_E789_x0213[] = { - 0x602E, 0xCA4D, 0xF02F, 0xCA4F, 0, 0xCA50, 0x602F, 0x4A52, - 0x4847, 0, 0, 0x6030, 0x4757, 0, 0xCA51, 0xCA52, - 0xCA53, 0, 0x442D, 0xF030, 0, 0x7764, 0x7765, 0xF031, - 0x6031, 0x3267, 0xCA57, 0x356D, 0xCA58, 0x4C46, 0xCA59, 0x4C36, - 0xCA5A, 0x3234, 0x4F34, 0xF032, 0, 0, 0, 0x4B52, - 0xCA5C, 0x4A2A, 0, 0xCA5D, 0, 0, 0xF034, 0xF035, - 0, 0xCA60, 0x4037, 0, 0x6032, 0, 0, 0xCA61, - 0xF036, 0x4643, 0, 0xCA63, 0xCA64, 0x3823, 0x6033, 0xF037, -}; -static const unsigned short utf8_to_euc_E78A[] = { - 0x3A54, 0x6035, 0x6034, 0, 0xCA66, 0, 0, 0x6036, - 0, 0xCA67, 0, 0, 0, 0xCA68, 0xCA69, 0, - 0, 0, 0x6037, 0xCA6A, 0, 0, 0x6038, 0, - 0, 0, 0, 0xCA6B, 0, 0, 0, 0, - 0x353E, 0, 0x6039, 0, 0, 0, 0, 0x603A, - 0xCA6C, 0, 0, 0, 0x3824, 0xCA6D, 0xCA6E, 0x4848, - 0, 0xCA6F, 0x603C, 0, 0xCA70, 0, 0x3E75, 0, - 0, 0x603B, 0, 0, 0, 0, 0xCA71, 0, -}; -static const unsigned short utf8_to_euc_E78A_x0213[] = { - 0x3A54, 0x6035, 0x6034, 0, 0xCA66, 0, 0, 0x6036, - 0, 0xCA67, 0, 0, 0, 0x7767, 0xF038, 0, - 0, 0, 0x6037, 0xCA6A, 0, 0, 0x6038, 0, - 0, 0, 0, 0x7768, 0, 0, 0, 0, - 0x353E, 0, 0x6039, 0, 0, 0, 0, 0x603A, - 0xCA6C, 0, 0, 0, 0x3824, 0xF03A, 0xF03B, 0x4848, - 0xF03C, 0xF03D, 0x603C, 0, 0xCA70, 0, 0x3E75, 0, - 0, 0x603B, 0, 0, 0, 0, 0x7769, 0, -}; -static const unsigned short utf8_to_euc_E78B[] = { - 0, 0xCA72, 0x3638, 0x603D, 0x603F, 0, 0x603E, 0xCA73, - 0, 0xCA74, 0, 0, 0xCA75, 0, 0x6040, 0, - 0x3851, 0, 0x6041, 0, 0, 0xCA76, 0xCA77, 0x3669, - 0xCA78, 0x4140, 0, 0x397D, 0, 0, 0, 0xCA79, - 0x6043, 0x6044, 0x6042, 0, 0, 0xCA7A, 0, 0, - 0, 0x3C6D, 0, 0, 0x4648, 0x3639, 0, 0, - 0, 0, 0, 0xCA7B, 0xCA7C, 0, 0, 0x6046, - 0x432C, 0x6045, 0xCA7D, 0xCA7E, 0x4F35, 0x4762, 0xCB21, 0, -}; -static const unsigned short utf8_to_euc_E78B_x0213[] = { - 0x776A, 0xF03E, 0x3638, 0x603D, 0x603F, 0, 0x603E, 0xCA73, - 0, 0xCA74, 0, 0, 0xF040, 0, 0x6040, 0, - 0x3851, 0, 0x6041, 0, 0, 0xCA76, 0xCA77, 0x3669, - 0xCA78, 0x4140, 0, 0x397D, 0, 0, 0, 0xCA79, - 0x6043, 0x6044, 0x6042, 0, 0, 0xCA7A, 0, 0, - 0, 0x3C6D, 0, 0, 0x4648, 0x3639, 0, 0, - 0, 0, 0, 0xF043, 0xCA7C, 0, 0, 0x6046, - 0x432C, 0x6045, 0xF044, 0x776B, 0x4F35, 0x4762, 0xCB21, 0, -}; -static const unsigned short utf8_to_euc_E78C[] = { - 0, 0, 0xCB22, 0, 0xCB23, 0xCB24, 0, 0xCB25, - 0, 0, 0x6049, 0xCB26, 0, 0xCB27, 0, 0, - 0, 0, 0xCB28, 0xCB29, 0, 0, 0x604B, 0x6048, - 0xCB2A, 0xCB2B, 0, 0x4C54, 0x604A, 0x604C, 0xCB2C, 0x4E44, - 0, 0, 0xCB2D, 0, 0xCB2E, 0x6050, 0, 0xCB2F, - 0xCB30, 0x604F, 0x4376, 0x472D, 0xCB31, 0, 0x3825, 0x604E, - 0, 0xCB32, 0xCB33, 0, 0x604D, 0xCB34, 0x4D31, 0x4D32, - 0, 0, 0xCB35, 0xCB36, 0, 0xCB37, 0x6051, 0x316E, -}; -static const unsigned short utf8_to_euc_E78C_x0213[] = { - 0, 0, 0xCB22, 0, 0xCB23, 0xCB24, 0, 0xF045, - 0, 0, 0x6049, 0xCB26, 0, 0xCB27, 0, 0, - 0, 0, 0xF046, 0xCB29, 0, 0, 0x604B, 0x6048, - 0xF047, 0xF048, 0, 0x4C54, 0x604A, 0x604C, 0xCB2C, 0x4E44, - 0, 0, 0xCB2D, 0, 0, 0x6050, 0, 0x776D, - 0x776E, 0x604F, 0x4376, 0x472D, 0xF04B, 0, 0x3825, 0x604E, - 0, 0xF04C, 0xCB33, 0xF04D, 0x604D, 0xCB34, 0x4D31, 0x4D32, - 0, 0xF04A, 0xCB35, 0xCB36, 0, 0xF04E, 0x6051, 0x316E, -}; -static const unsigned short utf8_to_euc_E78D[] = { - 0, 0, 0, 0xCB38, 0x3976, 0x3B62, 0, 0, - 0, 0, 0, 0, 0, 0xCB39, 0x6052, 0x6053, - 0xCB3A, 0, 0xCB3B, 0, 0, 0, 0xCB3C, 0x6055, - 0xCB3D, 0, 0, 0, 0, 0xCB3E, 0xCB3F, 0xCB40, - 0xCB41, 0, 0, 0x3D43, 0, 0, 0xCB42, 0xCB43, - 0x6057, 0xCB44, 0x6056, 0xCB45, 0xCB46, 0, 0xCB47, 0xCB48, - 0x6058, 0xCB49, 0x334D, 0, 0, 0x605A, 0, 0xCB4A, - 0x6059, 0xCB4B, 0x605C, 0x605B, 0xCB4C, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E78D_x0213[] = { - 0, 0, 0, 0xCB38, 0x3976, 0x3B62, 0, 0, - 0, 0, 0, 0, 0, 0xCB39, 0x6052, 0x6053, - 0x7770, 0, 0xF04F, 0, 0, 0, 0xCB3C, 0x6055, - 0xCB3D, 0, 0, 0, 0, 0xCB3E, 0xCB3F, 0xCB40, - 0xCB41, 0, 0, 0x3D43, 0, 0, 0x7771, 0xCB43, - 0x6057, 0xCB44, 0x6056, 0xF051, 0xF052, 0, 0xF054, 0xF055, - 0x6058, 0xF056, 0x334D, 0, 0, 0x605A, 0, 0xF057, - 0x6059, 0xCB4B, 0x605C, 0x605B, 0x7772, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E78E[] = { - 0xCB4D, 0xCB4E, 0, 0xCB4F, 0x383C, 0xCB50, 0xCB51, 0x4E28, - 0, 0x364C, 0, 0x3226, 0, 0, 0xCB52, 0, - 0xCB53, 0, 0, 0xCB54, 0, 0xCB55, 0x366A, 0xCB56, - 0xCB57, 0, 0, 0, 0xCB58, 0, 0xCB59, 0xCB5A, - 0xCB5B, 0, 0xCB5C, 0, 0, 0xCB5D, 0xCB5E, 0, - 0, 0x3461, 0xCB5F, 0xCB60, 0, 0xCB61, 0, 0, - 0, 0, 0x4E68, 0x605E, 0, 0xCB62, 0, 0xCB63, - 0, 0xCB64, 0, 0x6060, 0xCB65, 0xCB66, 0, 0xCB67, -}; -static const unsigned short utf8_to_euc_E78E_x0213[] = { - 0xCB4D, 0xF058, 0, 0xCB4F, 0x383C, 0xF059, 0xCB51, 0x4E28, - 0, 0x364C, 0xF05A, 0x3226, 0, 0, 0xCB52, 0, - 0xCB53, 0, 0, 0xCB54, 0xF05B, 0x7773, 0x366A, 0xCB56, - 0xF05C, 0, 0, 0, 0xF05D, 0, 0xF05E, 0x7774, - 0x7775, 0, 0x7776, 0, 0, 0xF05F, 0x7777, 0, - 0xF060, 0x3461, 0xCB5F, 0x7778, 0, 0xCB61, 0, 0, - 0, 0, 0x4E68, 0x605E, 0, 0xF061, 0, 0xF062, - 0, 0xF063, 0, 0x6060, 0xF064, 0, 0, 0xF065, -}; -static const unsigned short utf8_to_euc_E78F[] = { - 0x6061, 0, 0x3251, 0, 0, 0xCB68, 0xCB69, 0, - 0x605D, 0xCB6A, 0x3B39, 0xCB6B, 0xCB6C, 0x4441, 0x605F, 0xCB6D, - 0, 0, 0xCB6E, 0xCB6F, 0, 0, 0xCB70, 0, - 0, 0xCB71, 0, 0, 0, 0xCB72, 0x6064, 0, - 0x3C6E, 0xCB73, 0, 0xCB74, 0, 0x6062, 0xCB75, 0xCB76, - 0, 0xCB77, 0x373E, 0, 0, 0x4849, 0x6063, 0, - 0, 0x607E, 0, 0, 0xCB78, 0xCB79, 0, 0xCB7A, - 0x6069, 0xCB7B, 0xCB7C, 0xCB7D, 0, 0xCB7E, 0x383D, 0xCC21, -}; -static const unsigned short utf8_to_euc_E78F_x0213[] = { - 0x6061, 0, 0x3251, 0, 0, 0xF066, 0xCB69, 0, - 0x605D, 0x7779, 0x3B39, 0xF067, 0xCB6C, 0x4441, 0x605F, 0x777A, - 0, 0, 0, 0xCB6F, 0, 0, 0x777B, 0, - 0, 0x777C, 0, 0, 0, 0xCB72, 0x6064, 0, - 0x3C6E, 0xF068, 0, 0x777D, 0, 0x6062, 0xCB75, 0xF069, - 0, 0x777E, 0x373E, 0, 0, 0x4849, 0x6063, 0, - 0, 0x607E, 0, 0, 0xCB78, 0, 0, 0xCB7A, - 0x6069, 0xF06A, 0xF06C, 0xCB7D, 0, 0xCB7E, 0x383D, 0xCC21, -}; -static const unsigned short utf8_to_euc_E790[] = { - 0xCC22, 0xCC23, 0, 0x3565, 0xCC24, 0x6066, 0x4D7D, 0xCC25, - 0, 0x4E30, 0xCC26, 0, 0, 0, 0, 0, - 0, 0xCC27, 0, 0, 0, 0, 0, 0, - 0, 0, 0xCC28, 0xCC29, 0, 0, 0, 0, - 0, 0, 0x4276, 0, 0xCC2A, 0x6068, 0xCC2B, 0, - 0xCC2C, 0xCC2D, 0xCC2E, 0xCC2F, 0xCC30, 0xCC31, 0xCC32, 0xCC33, - 0xCC34, 0xCC35, 0x606A, 0x4E56, 0x3657, 0x487C, 0x474A, 0, - 0, 0xCC36, 0x606B, 0, 0, 0, 0, 0x606D, -}; -static const unsigned short utf8_to_euc_E790_x0213[] = { - 0xCC22, 0xF06D, 0, 0x3565, 0xCC24, 0x6066, 0x4D7D, 0x7821, - 0, 0x4E30, 0x7822, 0, 0, 0, 0, 0, - 0, 0xCC27, 0, 0xF06B, 0, 0, 0, 0, - 0, 0, 0x7823, 0x7824, 0, 0, 0, 0, - 0, 0, 0x4276, 0, 0xF06E, 0x6068, 0x7826, 0, - 0x7827, 0, 0x7828, 0x7829, 0x782A, 0xCC31, 0x782B, 0x782C, - 0x782D, 0xF06F, 0x606A, 0x4E56, 0x3657, 0x487C, 0x474A, 0, - 0, 0xF070, 0x606B, 0, 0, 0, 0, 0x606D, -}; -static const unsigned short utf8_to_euc_E791[] = { - 0xCC37, 0x6070, 0, 0xCC38, 0xCC39, 0, 0xCC3A, 0xCC3B, - 0, 0, 0, 0xCC3C, 0, 0xCC3D, 0, 0, - 0, 0xCC3E, 0xCC3F, 0, 0, 0x606C, 0, 0xCC40, - 0, 0x606F, 0x386A, 0x314D, 0x6071, 0xCC41, 0x3F70, 0x606E, - 0x4E5C, 0, 0xCC42, 0x6074, 0x7424, 0, 0xCC43, 0xCC44, - 0xCC45, 0x6072, 0x6075, 0xCC46, 0, 0xCC47, 0xCC48, 0x6067, - 0x6073, 0xCC49, 0xCC4A, 0x3A3C, 0, 0, 0x6076, 0, - 0, 0, 0, 0, 0, 0, 0x6077, 0, -}; -static const unsigned short utf8_to_euc_E791_x0213[] = { - 0xF072, 0x6070, 0, 0xF073, 0x782E, 0, 0x782F, 0x7830, - 0, 0, 0, 0x7831, 0, 0xF074, 0, 0, - 0, 0xCC3E, 0xF075, 0xF071, 0, 0x606C, 0, 0x7832, - 0, 0x606F, 0x386A, 0x314D, 0x6071, 0xF076, 0x3F70, 0x606E, - 0x4E5C, 0, 0x7833, 0x6074, 0x7424, 0, 0xCC43, 0xCC44, - 0xCC45, 0x6072, 0x6075, 0x7834, 0, 0x7835, 0xCC48, 0x6067, - 0x6073, 0xF077, 0xCC4A, 0x3A3C, 0, 0, 0x6076, 0, - 0, 0, 0, 0, 0, 0, 0x6077, 0, -}; -static const unsigned short utf8_to_euc_E792[] = { - 0xCC4B, 0xCC4C, 0, 0x4D7E, 0, 0xCC4D, 0xCC4E, 0xCC4F, - 0, 0xCC50, 0, 0x6078, 0, 0, 0, 0xCC51, - 0xCC52, 0xCC53, 0xCC54, 0, 0, 0, 0, 0, - 0xCC55, 0xCC56, 0xCC57, 0, 0xCC58, 0, 0x6079, 0xCC59, - 0xCC5A, 0xCC5B, 0x6065, 0xCC5C, 0, 0, 0xCC5D, 0x607A, - 0xCC5E, 0xCC5F, 0xCC60, 0xCC61, 0, 0, 0xCC62, 0xCC63, - 0x3444, 0xCC64, 0xCC65, 0, 0, 0xCC66, 0, 0, - 0, 0xCC67, 0, 0xCC68, 0, 0x3C25, 0, 0xCC69, -}; -static const unsigned short utf8_to_euc_E792_x0213[] = { - 0xCC4B, 0xF078, 0, 0x4D7E, 0, 0xF079, 0x7836, 0x7837, - 0xF07A, 0x7838, 0, 0x6078, 0, 0, 0, 0xCC51, - 0x783D, 0xCC53, 0xF07C, 0, 0, 0, 0, 0xF07D, - 0x7839, 0xF07E, 0xCC57, 0, 0x783A, 0, 0x6079, 0x783B, - 0xF121, 0xF122, 0x6065, 0x783C, 0, 0xF123, 0x783E, 0x607A, - 0x783F, 0x7840, 0xF124, 0xF125, 0, 0, 0xCC62, 0xCC63, - 0x3444, 0xCC64, 0xCC65, 0, 0, 0x7841, 0, 0, - 0, 0xF126, 0xF128, 0xF127, 0, 0x3C25, 0, 0x7842, -}; -static const unsigned short utf8_to_euc_E793[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0xCC6A, 0xCC6B, 0x607B, 0, 0xCC6C, 0, 0, 0x607C, - 0xCC6D, 0, 0, 0xCC6E, 0x607D, 0, 0, 0, - 0xCC6F, 0, 0xCC70, 0xCC71, 0x313B, 0, 0xCC72, 0xCC73, - 0x6121, 0, 0x493B, 0x6122, 0xCC74, 0, 0x3424, 0x6123, - 0xCC75, 0x6124, 0xCC76, 0xCC77, 0, 0, 0x6125, 0xCC78, - 0x6127, 0x6128, 0x6126, 0, 0xCC79, 0, 0x4953, 0x612A, - 0x6129, 0, 0xCC7A, 0xCC7B, 0xCC7C, 0, 0, 0xCC7D, -}; -static const unsigned short utf8_to_euc_E793_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0x7843, 0x7844, 0x607B, 0, 0xCC6C, 0, 0, 0x607C, - 0xCC6D, 0, 0, 0xCC6E, 0x607D, 0, 0xF129, 0, - 0xF12A, 0, 0x7845, 0xCC71, 0x313B, 0, 0xF12B, 0xCC73, - 0x6121, 0, 0x493B, 0x6122, 0xCC74, 0, 0x3424, 0x6123, - 0xCC75, 0x6124, 0xCC76, 0xF12D, 0, 0, 0x6125, 0xF12C, - 0x6127, 0x6128, 0x6126, 0, 0xCC79, 0, 0x4953, 0x612A, - 0x6129, 0, 0xF12F, 0xCC7B, 0xCC7C, 0, 0, 0x7846, -}; -static const unsigned short utf8_to_euc_E794[] = { - 0, 0xF450, 0, 0x612C, 0x612B, 0x612D, 0xCC7E, 0, - 0, 0, 0, 0, 0x612E, 0x6130, 0x612F, 0, - 0, 0x3979, 0xCD21, 0x6132, 0, 0x6131, 0xCD22, 0xCD23, - 0x3445, 0, 0x3F53, 0, 0x453C, 0, 0x6133, 0x4038, - 0xCD24, 0xCD25, 0, 0x3B3A, 0xCD26, 0x3179, 0x6134, 0xCD27, - 0x4D51, 0xCD28, 0xCD29, 0x4A63, 0x6135, 0, 0, 0xCD2A, - 0x4544, 0x4D33, 0x3943, 0x3F3D, 0, 0, 0xCD2B, 0x434B, - 0x5234, 0xCD2C, 0x442E, 0x3268, 0x6136, 0xCD2D, 0xCD2E, 0xCD2F, -}; -static const unsigned short utf8_to_euc_E794_x0213[] = { - 0, 0x7847, 0, 0x612C, 0x612B, 0x612D, 0xCC7E, 0, - 0, 0, 0, 0, 0x612E, 0x6130, 0x612F, 0, - 0, 0x3979, 0xCD21, 0x6132, 0, 0x6131, 0xCD22, 0x7848, - 0x3445, 0, 0x3F53, 0, 0x453C, 0, 0x6133, 0x4038, - 0xF131, 0xCD25, 0, 0x3B3A, 0xF132, 0x3179, 0x6134, 0xCD27, - 0x4D51, 0xCD28, 0xF133, 0x4A63, 0x6135, 0, 0, 0x7849, - 0x4544, 0x4D33, 0x3943, 0x3F3D, 0, 0, 0xCD2B, 0x434B, - 0x5234, 0xCD2C, 0x442E, 0x3268, 0x6136, 0xF136, 0xF137, 0xCD2F, -}; -static const unsigned short utf8_to_euc_E795[] = { - 0xCD30, 0, 0, 0xCD31, 0x6137, 0, 0x613C, 0xCD32, - 0xCD33, 0x613A, 0x6139, 0x5A42, 0x3326, 0x6138, 0xCD34, 0x305A, - 0xCD35, 0x482A, 0xCD36, 0, 0x484A, 0, 0, 0xCD37, - 0, 0x4E31, 0x613D, 0x613B, 0x435C, 0x4026, 0xCD38, 0xCD39, - 0x482B, 0xCD3A, 0x492D, 0, 0x613F, 0x4E2C, 0x374D, 0x6140, - 0, 0x613E, 0x4856, 0x6141, 0, 0x6142, 0, 0xCD3B, - 0x305B, 0xCD3C, 0, 0x3E76, 0x6147, 0, 0x6144, 0x466D, - 0x6143, 0xCD3D, 0xCD3E, 0xCD3F, 0xCD40, 0xCD41, 0xCD42, 0x3526, -}; -static const unsigned short utf8_to_euc_E795_x0213[] = { - 0xF138, 0, 0, 0xCD31, 0x6137, 0, 0x613C, 0xCD32, - 0xF139, 0x613A, 0x6139, 0x5A42, 0x3326, 0x6138, 0xF13A, 0x305A, - 0xF13B, 0x482A, 0xF13C, 0, 0x484A, 0, 0, 0xCD37, - 0, 0x4E31, 0x613D, 0x613B, 0x435C, 0x4026, 0xCD38, 0xCD39, - 0x482B, 0xCD3A, 0x492D, 0, 0x613F, 0x4E2C, 0x374D, 0x6140, - 0, 0x613E, 0x4856, 0x6141, 0xF13D, 0x6142, 0, 0x784A, - 0x305B, 0xF13F, 0xF13E, 0x3E76, 0x6147, 0, 0x6144, 0x466D, - 0x6143, 0x784B, 0xF140, 0xCD3F, 0xCD40, 0xF141, 0xF142, 0x3526, -}; -static const unsigned short utf8_to_euc_E796[] = { - 0, 0xCD43, 0x614A, 0, 0, 0xCD44, 0x6145, 0x6146, - 0, 0x6149, 0x6148, 0x4925, 0, 0, 0x4142, 0x4141, - 0xCD45, 0x353F, 0xCD46, 0xCD47, 0x614B, 0xCD48, 0, 0, - 0, 0xCD49, 0x614C, 0, 0xCD4A, 0x614D, 0, 0, - 0, 0, 0xCD4B, 0x614F, 0xCD4C, 0x614E, 0, 0, - 0, 0, 0, 0x3156, 0, 0, 0, 0, - 0, 0x6157, 0x4868, 0x6151, 0xCD4D, 0x6153, 0, 0, - 0x6155, 0x3F3E, 0xCD4E, 0, 0x6156, 0x6154, 0x3C40, 0xCD4F, -}; -static const unsigned short utf8_to_euc_E796_x0213[] = { - 0, 0xF143, 0x614A, 0, 0, 0xCD44, 0x6145, 0x6146, - 0, 0x6149, 0x6148, 0x4925, 0xF145, 0, 0x4142, 0x4141, - 0xCD45, 0x353F, 0x784C, 0xCD47, 0x614B, 0xCD48, 0, 0, - 0, 0xCD49, 0x614C, 0, 0xCD4A, 0x614D, 0, 0, - 0, 0, 0xF147, 0x614F, 0xCD4C, 0x614E, 0, 0, - 0, 0, 0, 0x3156, 0, 0, 0, 0, - 0xF149, 0x6157, 0x4868, 0x6151, 0xCD4D, 0x6153, 0, 0xF14A, - 0x6155, 0x3F3E, 0xCD4E, 0, 0x6156, 0x6154, 0x3C40, 0xF14B, -}; -static const unsigned short utf8_to_euc_E797[] = { - 0xCD50, 0xCD51, 0x6150, 0x6152, 0xCD52, 0x4942, 0xCD53, 0x3E49, - 0, 0, 0x6159, 0, 0xCD54, 0x6158, 0xCD55, 0xCD56, - 0, 0, 0x615A, 0, 0x3C26, 0x3A2F, 0, 0xCD57, - 0x4577, 0x615B, 0, 0x444B, 0xCD58, 0, 0x615D, 0xCD59, - 0xCD5A, 0xCD5B, 0x4E21, 0x615C, 0xCD5C, 0, 0, 0xCD5D, - 0, 0x4169, 0, 0, 0xCD5E, 0, 0xCD5F, 0xCD60, - 0x6162, 0xCD61, 0x6164, 0x6165, 0x4354, 0, 0, 0, - 0, 0xCD62, 0x6163, 0, 0x6160, 0, 0x615E, 0x615F, -}; -static const unsigned short utf8_to_euc_E797_x0213[] = { - 0xF14C, 0xCD51, 0x6150, 0x6152, 0xCD52, 0x4942, 0xF14D, 0x3E49, - 0, 0, 0x6159, 0, 0xCD54, 0x6158, 0x784E, 0xF14E, - 0, 0, 0x615A, 0xF14F, 0x3C26, 0x3A2F, 0, 0xCD57, - 0x4577, 0x615B, 0, 0x444B, 0xCD58, 0xF150, 0x615D, 0xF151, - 0xF152, 0xCD5B, 0x4E21, 0x615C, 0x784F, 0, 0, 0xF153, - 0, 0x4169, 0, 0, 0xF154, 0, 0xF155, 0xCD60, - 0x6162, 0xF156, 0x6164, 0x6165, 0x4354, 0, 0, 0, - 0, 0xF157, 0x6163, 0, 0x6160, 0, 0x615E, 0x615F, -}; -static const unsigned short utf8_to_euc_E798[] = { - 0xCD63, 0x6161, 0xCD64, 0xCD65, 0xCD66, 0, 0, 0xCD67, - 0xCD68, 0x6168, 0xCD69, 0x6166, 0xCD6A, 0x6167, 0, 0xCD6B, - 0, 0, 0xCD6C, 0xCD6D, 0, 0xCD6E, 0xCD6F, 0, - 0, 0xCD70, 0, 0xCD71, 0xCD72, 0xCD73, 0xCD74, 0x6169, - 0x616B, 0x616C, 0x616D, 0xCD75, 0x616E, 0xCD76, 0xCD77, 0x616A, - 0, 0xCD78, 0, 0, 0, 0xCD79, 0, 0, - 0x6170, 0, 0xCD7A, 0xCD7B, 0x616F, 0xCD7C, 0, 0, - 0xCD7D, 0xCD7E, 0xCE21, 0x6171, 0xCE22, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E798_x0213[] = { - 0x7850, 0x6161, 0x7851, 0xF158, 0xCD66, 0, 0, 0xF15A, - 0x7852, 0x6168, 0xCD69, 0x6166, 0xCD6A, 0x6167, 0, 0xF15B, - 0, 0, 0xCD6C, 0xF15E, 0, 0x7853, 0x7854, 0, - 0xF159, 0x7855, 0, 0xF15F, 0xF160, 0xCD73, 0x7856, 0x6169, - 0x616B, 0x616C, 0x616D, 0xCD75, 0x616E, 0xF162, 0x7E7D, 0x616A, - 0xF163, 0xCD78, 0, 0, 0, 0x7857, 0, 0, - 0x6170, 0, 0xCD7A, 0xF165, 0x616F, 0x7858, 0, 0, - 0xCD7D, 0xCD7E, 0xCE21, 0x6171, 0xF164, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E799[] = { - 0xCE24, 0xCE25, 0x4E45, 0xCE26, 0xCE27, 0xCE28, 0x6174, 0x6172, - 0x6173, 0xCE29, 0xCE23, 0xCE2A, 0x3462, 0, 0, 0, - 0, 0, 0x4C7E, 0, 0, 0xCE2B, 0x4A4A, 0, - 0x6176, 0xCE2C, 0, 0, 0x6175, 0, 0, 0xCE2D, - 0, 0x6177, 0x6178, 0, 0xCE2E, 0xCE2F, 0, 0x617C, - 0x6179, 0x617A, 0x617B, 0, 0x617D, 0xCE30, 0xCE31, 0xCE32, - 0x617E, 0xCE33, 0x6221, 0, 0xCE34, 0, 0x6222, 0, - 0x6223, 0, 0x482F, 0x4550, 0x6224, 0x4772, 0x4934, 0, -}; -static const unsigned short utf8_to_euc_E799_x0213[] = { - 0xCE24, 0xF168, 0x4E45, 0x7859, 0xCE27, 0xCE28, 0x6174, 0x6172, - 0x6173, 0xF16A, 0xCE23, 0x785A, 0x3462, 0, 0, 0, - 0, 0, 0x4C7E, 0, 0, 0xF16B, 0x4A4A, 0, - 0x6176, 0xCE2C, 0, 0, 0x6175, 0, 0, 0xCE2D, - 0, 0x6177, 0x6178, 0, 0x785B, 0x785C, 0, 0x617C, - 0x6179, 0x617A, 0x617B, 0, 0x617D, 0x785D, 0xF16D, 0x785E, - 0x617E, 0x785F, 0x6221, 0, 0xCE34, 0, 0x6222, 0, - 0x6223, 0, 0x482F, 0x4550, 0x6224, 0x4772, 0x4934, 0, -}; -static const unsigned short utf8_to_euc_E79A[] = { - 0x6225, 0xCE35, 0xF451, 0x6226, 0x452A, 0xCE36, 0x3327, 0x3944, - 0x6227, 0, 0, 0x6228, 0xCE37, 0xCE38, 0x6229, 0, - 0x3B29, 0, 0, 0x622B, 0, 0xCE39, 0x622A, 0, - 0, 0x622C, 0x622D, 0xCE3A, 0xCE3B, 0xCE3C, 0xF452, 0xCE3D, - 0xCE3E, 0, 0xCE3F, 0xCE40, 0xCE41, 0xCE42, 0xCE43, 0xCE44, - 0xCE45, 0, 0xCE46, 0, 0, 0xCE47, 0x4869, 0, - 0x622E, 0, 0, 0, 0x622F, 0, 0, 0x7369, - 0x6230, 0x6231, 0x6232, 0, 0, 0xCE48, 0, 0x3B2E, -}; -static const unsigned short utf8_to_euc_E79A_x0213[] = { - 0x6225, 0x7860, 0, 0x6226, 0x452A, 0xCE36, 0x3327, 0x3944, - 0x6227, 0, 0, 0x6228, 0xCE37, 0xCE38, 0x6229, 0, - 0x3B29, 0, 0, 0x622B, 0, 0xF16E, 0x622A, 0, - 0, 0x622C, 0x622D, 0x7861, 0xF16F, 0x7862, 0x7863, 0xCE3D, - 0xF171, 0xF170, 0xCE3F, 0xCE40, 0xCE41, 0xCE42, 0x7864, 0xF172, - 0xF173, 0, 0x7865, 0, 0, 0xCE47, 0x4869, 0xF174, - 0x622E, 0, 0, 0, 0x622F, 0, 0x7866, 0x7369, - 0x6230, 0x6231, 0x6232, 0, 0, 0xCE48, 0, 0x3B2E, -}; -static const unsigned short utf8_to_euc_E79B[] = { - 0, 0xCE49, 0x6233, 0x4756, 0, 0xCE4A, 0x4B5F, 0, - 0x314E, 0xCE4B, 0x3157, 0xCE4C, 0xCE4D, 0x6234, 0xCE4E, 0, - 0, 0, 0x6236, 0, 0xCE4F, 0, 0x6235, 0x4570, - 0, 0xCE50, 0, 0x4039, 0x5D39, 0, 0x6237, 0x4C41, - 0xCE51, 0x6238, 0, 0x3446, 0x4857, 0x6239, 0xCE52, 0x623A, - 0xCE53, 0, 0x623B, 0, 0xCE54, 0, 0x4C5C, 0, - 0xCE55, 0xCE56, 0x4C55, 0, 0x443E, 0, 0xCE57, 0, - 0x416A, 0xCE58, 0, 0x623D, 0xCE59, 0, 0x3D62, 0, -}; -static const unsigned short utf8_to_euc_E79B_x0213[] = { - 0, 0xCE49, 0x6233, 0x4756, 0, 0x7867, 0x4B5F, 0, - 0x314E, 0xF176, 0x3157, 0xCE4C, 0x7868, 0x6234, 0x7869, 0, - 0, 0, 0x6236, 0, 0x786A, 0, 0x6235, 0x4570, - 0, 0xCE50, 0, 0x4039, 0x5D39, 0, 0x6237, 0x4C41, - 0xCE51, 0x6238, 0, 0x3446, 0x4857, 0x6239, 0x786B, 0x623A, - 0xF178, 0, 0x623B, 0, 0xF179, 0, 0x4C5C, 0, - 0xCE55, 0x786C, 0x4C55, 0, 0x443E, 0, 0xCE57, 0, - 0x416A, 0xCE58, 0, 0x623D, 0x786D, 0, 0x3D62, 0, -}; -static const unsigned short utf8_to_euc_E79C[] = { - 0xCE5A, 0x3E4A, 0, 0, 0x6240, 0, 0xCE5B, 0x623F, - 0x623E, 0x487D, 0xCE5C, 0x3447, 0x3829, 0, 0xCE5D, 0, - 0, 0, 0xCE5E, 0, 0xCE5F, 0xCE60, 0, 0xCE61, - 0, 0xCE62, 0xCE63, 0x6246, 0xCE64, 0, 0x6243, 0x3F3F, - 0x4C32, 0, 0xCE65, 0, 0x6242, 0x6244, 0x6245, 0, - 0xCE66, 0x6241, 0, 0, 0, 0xCE67, 0xCE68, 0xCE69, - 0, 0, 0, 0, 0xCE6A, 0xCE6B, 0xCE6C, 0x6247, - 0x6248, 0xCE6D, 0x442F, 0, 0x3463, 0xCE6E, 0xCE6F, 0, -}; -static const unsigned short utf8_to_euc_E79C_x0213[] = { - 0xCE5A, 0x3E4A, 0, 0, 0x6240, 0, 0xCE5B, 0x623F, - 0x623E, 0x487D, 0x786E, 0x3447, 0x3829, 0, 0xCE5D, 0, - 0, 0, 0xCE5E, 0, 0xCE5F, 0xCE60, 0, 0xF17B, - 0, 0x786F, 0xF17C, 0x6246, 0xCE64, 0, 0x6243, 0x3F3F, - 0x4C32, 0, 0xCE65, 0, 0x6242, 0x6244, 0x6245, 0, - 0xCE66, 0x6241, 0, 0, 0, 0xF17D, 0xCE68, 0xCE69, - 0, 0, 0, 0, 0x7870, 0xF17E, 0x7871, 0x6247, - 0x6248, 0xCE6D, 0x442F, 0, 0x3463, 0xCE6E, 0xCE6F, 0, -}; -static const unsigned short utf8_to_euc_E79D[] = { - 0x4365, 0, 0xCE70, 0, 0, 0xCE71, 0xCE72, 0x6249, - 0, 0, 0xCE73, 0, 0, 0xCE74, 0xCE75, 0xCE76, - 0, 0, 0xCE77, 0, 0, 0, 0xCE78, 0xCE79, - 0, 0, 0x624A, 0x624D, 0xCE7A, 0, 0xCE7B, 0xCE7C, - 0xCE7D, 0x3F67, 0xCE7E, 0x4644, 0xCF21, 0x624E, 0x4B53, 0xCF22, - 0x624B, 0, 0xCF23, 0x624C, 0xCF24, 0, 0, 0, - 0xCF25, 0, 0xCF26, 0xCF27, 0xCF28, 0, 0, 0, - 0, 0x6251, 0xCF29, 0, 0, 0xCF2A, 0x6250, 0x624F, -}; -static const unsigned short utf8_to_euc_E79D_x0213[] = { - 0x4365, 0, 0xCE70, 0, 0, 0xCE71, 0x7872, 0x6249, - 0, 0, 0xCE73, 0, 0, 0x7873, 0x7874, 0xCE76, - 0, 0, 0xCE77, 0, 0, 0, 0xCE78, 0xCE79, - 0xF225, 0, 0x624A, 0x624D, 0x7875, 0, 0xCE7B, 0x7876, - 0xF226, 0x3F67, 0x7877, 0x4644, 0xCF21, 0x624E, 0x4B53, 0xCF22, - 0x624B, 0, 0xF227, 0x624C, 0xCF24, 0, 0, 0, - 0xCF25, 0, 0xF229, 0xCF27, 0xCF28, 0, 0, 0, - 0, 0x6251, 0x7878, 0, 0xF22A, 0xF22B, 0x6250, 0x624F, -}; -static const unsigned short utf8_to_euc_E79E[] = { - 0xCF2B, 0, 0, 0, 0xCF2C, 0, 0, 0, - 0, 0, 0, 0x6253, 0xCF2D, 0xCF2E, 0x6252, 0, - 0, 0x6254, 0, 0, 0xCF2F, 0xCF30, 0xCF31, 0, - 0, 0, 0xCF32, 0, 0, 0, 0x6256, 0xCF33, - 0x6255, 0, 0xCF34, 0, 0, 0x4A4D, 0, 0xCF35, - 0, 0, 0xCF36, 0, 0x3D56, 0x4E46, 0xCF37, 0xCF38, - 0x6257, 0xCF39, 0, 0x4637, 0, 0xCF3A, 0x6258, 0, - 0, 0x6259, 0, 0x625D, 0x625B, 0x625C, 0xCF3B, 0x625A, -}; -static const unsigned short utf8_to_euc_E79E_x0213[] = { - 0x7879, 0, 0, 0, 0xCF2C, 0, 0, 0, - 0, 0, 0, 0x6253, 0xCF2D, 0xCF2E, 0x6252, 0, - 0, 0x6254, 0, 0, 0x787A, 0xCF30, 0xCF31, 0, - 0, 0, 0xF22E, 0, 0, 0, 0x6256, 0xF22F, - 0x6255, 0, 0xF230, 0, 0xF231, 0x4A4D, 0, 0xCF35, - 0, 0xF232, 0x787B, 0, 0x3D56, 0x4E46, 0xCF37, 0xCF38, - 0x6257, 0xCF39, 0, 0x4637, 0, 0xCF3A, 0x6258, 0, - 0, 0x6259, 0, 0x625D, 0x625B, 0x625C, 0xCF3B, 0x625A, -}; -static const unsigned short utf8_to_euc_E79F[] = { - 0, 0, 0, 0xCF3C, 0, 0, 0, 0x625E, - 0, 0xCF3D, 0, 0, 0, 0x625F, 0, 0, - 0, 0xCF3E, 0xCF3F, 0, 0, 0xCF40, 0, 0x6260, - 0, 0xCF41, 0x6261, 0x4C37, 0x6262, 0, 0xCF42, 0xCF43, - 0xCF44, 0, 0x4C70, 0x6263, 0xCF45, 0x434E, 0xCF46, 0x476A, - 0, 0x366B, 0xCF47, 0, 0xCF48, 0x433B, 0x6264, 0x363A, - 0xCF49, 0xCF4A, 0, 0x4050, 0xCF4B, 0, 0, 0, - 0xCF4C, 0, 0, 0xCF4D, 0x6265, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E79F_x0213[] = { - 0, 0, 0, 0xCF3C, 0, 0, 0, 0x625E, - 0, 0xCF3D, 0, 0, 0, 0x625F, 0, 0, - 0, 0xCF3E, 0xCF3F, 0, 0, 0xCF40, 0, 0x6260, - 0, 0xCF41, 0x6261, 0x4C37, 0x6262, 0, 0xF233, 0xF234, - 0x787C, 0, 0x4C70, 0x6263, 0xF235, 0x434E, 0xF236, 0x476A, - 0, 0x366B, 0xF237, 0, 0xF238, 0x433B, 0x6264, 0x363A, - 0xF23A, 0xCF4A, 0, 0x4050, 0xF23B, 0, 0, 0, - 0xCF4C, 0, 0, 0xF23C, 0x6265, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E7A0[] = { - 0, 0, 0x3A3D, 0, 0, 0xCF4E, 0xCF4F, 0, - 0, 0xCF50, 0, 0, 0x6266, 0xCF51, 0xCF52, 0, - 0, 0xCF53, 0x6267, 0, 0x3826, 0x3A55, 0, 0, - 0, 0, 0, 0, 0, 0xCF54, 0, 0, - 0x6269, 0xCF55, 0xCF56, 0xCF57, 0, 0x4556, 0x3A56, 0x354E, - 0, 0, 0, 0, 0, 0xCF58, 0xCF59, 0, - 0xCF5A, 0, 0x4B24, 0, 0x474B, 0xCF5B, 0, 0xCF5C, - 0, 0, 0x4557, 0, 0, 0, 0, 0x395C, -}; -static const unsigned short utf8_to_euc_E7A0_x0213[] = { - 0, 0, 0x3A3D, 0, 0, 0xF23E, 0xF23F, 0, - 0, 0xF240, 0, 0, 0x6266, 0xF241, 0xCF52, 0, - 0, 0xCF53, 0x6267, 0, 0x3826, 0x3A55, 0, 0, - 0, 0xF242, 0, 0, 0, 0xCF54, 0, 0, - 0x6269, 0xF243, 0xCF56, 0xCF57, 0, 0x4556, 0x3A56, 0x354E, - 0, 0, 0, 0, 0xF244, 0x787D, 0xCF59, 0, - 0xCF5A, 0, 0x4B24, 0, 0x474B, 0xCF5B, 0, 0xCF5C, - 0, 0, 0x4557, 0, 0, 0, 0, 0x395C, -}; -static const unsigned short utf8_to_euc_E7A1[] = { - 0, 0, 0, 0xCF5D, 0xCF5E, 0x626B, 0, 0xCF5F, - 0xCF60, 0, 0, 0, 0xCF61, 0, 0xCF62, 0, - 0, 0, 0xCF63, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0xCF64, 0x3E4B, 0xCF65, 0, - 0xCF66, 0xCF67, 0, 0xCF68, 0xCF69, 0, 0, 0, - 0xCF6A, 0, 0xCF6B, 0x4E32, 0x3945, 0, 0xCF6C, 0x3827, - 0, 0, 0x4823, 0, 0x626D, 0, 0, 0, - 0, 0, 0xCF6D, 0, 0x626F, 0, 0xCF6E, 0, -}; -static const unsigned short utf8_to_euc_E7A1_x0213[] = { - 0, 0, 0, 0x7921, 0xCF5E, 0x626B, 0, 0xF245, - 0xCF60, 0, 0, 0, 0xCF61, 0, 0x7922, 0x7923, - 0, 0x7924, 0xCF63, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0xCF64, 0x3E4B, 0xCF65, 0, - 0xCF66, 0xCF67, 0, 0xCF68, 0xF246, 0, 0, 0, - 0x7925, 0, 0xF247, 0x4E32, 0x3945, 0, 0x7926, 0x3827, - 0, 0, 0x4823, 0, 0x626D, 0, 0, 0, - 0, 0, 0, 0, 0x626F, 0, 0xCF6E, 0, -}; -static const unsigned short utf8_to_euc_E7A2[] = { - 0, 0x386B, 0, 0, 0, 0, 0x626E, 0x4476, - 0, 0, 0xCF6F, 0, 0x6271, 0x3337, 0x626C, 0xCF70, - 0, 0x486A, 0, 0x3130, 0xCF71, 0x3A6C, 0, 0x4F52, - 0xCF72, 0, 0x6270, 0, 0, 0xCF74, 0xCF75, 0xCF76, - 0, 0xCF73, 0, 0x6272, 0xCF77, 0, 0, 0x4A4B, - 0xCF78, 0x4059, 0x6274, 0, 0xCF79, 0xCF7A, 0, 0x6275, - 0xCF7B, 0xCF7C, 0xCF7D, 0xCF7E, 0, 0x6273, 0, 0, - 0, 0, 0x334E, 0xD021, 0x627B, 0xD022, 0x627A, 0xD023, -}; -static const unsigned short utf8_to_euc_E7A2_x0213[] = { - 0, 0x386B, 0, 0, 0, 0, 0x626E, 0x4476, - 0, 0, 0xF249, 0, 0x6271, 0x3337, 0x626C, 0xCF70, - 0, 0x486A, 0, 0x3130, 0xF24A, 0x3A6C, 0, 0x4F52, - 0xCF72, 0, 0x6270, 0, 0, 0xF24C, 0xF24D, 0xF24E, - 0, 0xCF73, 0, 0x6272, 0xF24B, 0, 0, 0x4A4B, - 0xCF78, 0x4059, 0x6274, 0, 0xCF79, 0x792A, 0, 0x6275, - 0x7928, 0xCF7C, 0xCF7D, 0xCF7E, 0, 0x6273, 0, 0, - 0, 0, 0x334E, 0xF24F, 0x627B, 0xD022, 0x627A, 0xD023, -}; -static const unsigned short utf8_to_euc_E7A3[] = { - 0, 0x3C27, 0, 0, 0, 0x627C, 0x6277, 0xD024, - 0xD025, 0xD026, 0x627D, 0x6278, 0xD027, 0, 0xD028, 0, - 0x4858, 0x6276, 0xD029, 0xD02A, 0x6279, 0xD02B, 0xD02C, 0, - 0, 0, 0x6322, 0xD02E, 0, 0, 0, 0xD02F, - 0xD030, 0xD031, 0, 0, 0xD02D, 0, 0xD032, 0x6321, - 0x4B61, 0, 0xD033, 0, 0x627E, 0, 0, 0x306B, - 0, 0, 0xD034, 0xD035, 0x6324, 0, 0xD037, 0xD038, - 0, 0, 0xD039, 0xD03A, 0, 0x6323, 0, 0xD03B, -}; -static const unsigned short utf8_to_euc_E7A3_x0213[] = { - 0, 0x3C27, 0, 0, 0, 0x627C, 0x6277, 0xD024, - 0xF250, 0xD026, 0x627D, 0x6278, 0xF251, 0, 0xF252, 0, - 0x4858, 0x6276, 0xD029, 0xD02A, 0x6279, 0xF253, 0xD02C, 0, - 0, 0, 0x6322, 0xD02E, 0, 0, 0, 0xD02F, - 0xF254, 0xF255, 0, 0, 0x792B, 0, 0xF256, 0x6321, - 0x4B61, 0, 0xD033, 0, 0x627E, 0, 0, 0x306B, - 0, 0, 0x792C, 0xD035, 0x6324, 0, 0xD037, 0x792E, - 0, 0xF257, 0xF258, 0xF259, 0, 0x6323, 0xF25A, 0xD03B, -}; -static const unsigned short utf8_to_euc_E7A4[] = { - 0xD036, 0x3E4C, 0, 0, 0, 0, 0xD03C, 0x6325, - 0, 0, 0, 0, 0xD03D, 0, 0x4143, 0, - 0xD03E, 0x6327, 0x6326, 0, 0, 0, 0, 0, - 0, 0x6328, 0xD03F, 0, 0xD040, 0, 0xD041, 0xD042, - 0xD043, 0, 0, 0, 0, 0xD044, 0x6268, 0xD045, - 0, 0xD046, 0x626A, 0x632A, 0x6329, 0xD047, 0, 0, - 0xF454, 0xD048, 0, 0, 0xD049, 0xD04A, 0, 0, - 0, 0, 0x3C28, 0xD04B, 0x4E69, 0xD04C, 0x3C52, 0xD04D, -}; -static const unsigned short utf8_to_euc_E7A4_x0213[] = { - 0x792D, 0x3E4C, 0, 0, 0, 0, 0xD03C, 0x6325, - 0, 0, 0, 0, 0xD03D, 0, 0x4143, 0, - 0xF25C, 0x6327, 0x6326, 0, 0, 0, 0, 0, - 0, 0x6328, 0xD03F, 0xF25D, 0x792F, 0, 0xD041, 0xD042, - 0xD043, 0, 0, 0, 0, 0xF25F, 0x6268, 0xD045, - 0, 0xD046, 0x626A, 0x632A, 0x6329, 0xD047, 0x7930, 0, - 0xF25E, 0x7931, 0, 0, 0x7932, 0xD04A, 0, 0, - 0, 0, 0x3C28, 0xF260, 0x4E69, 0xD04C, 0x3C52, 0xD04D, -}; -static const unsigned short utf8_to_euc_E7A5[] = { - 0x632B, 0x3737, 0, 0, 0xD04E, 0xD04F, 0xD050, 0x3540, - 0x3527, 0x3B63, 0xD051, 0xD052, 0, 0, 0, 0xD053, - 0x4D34, 0xD054, 0, 0x6331, 0xD055, 0x6330, 0x4144, 0x632D, - 0xD056, 0, 0x632F, 0xD057, 0xD058, 0x3D4B, 0x3F40, 0x632E, - 0x632C, 0, 0x472A, 0, 0, 0x3E4D, 0, 0xD059, - 0x493C, 0xD05A, 0, 0xD05B, 0, 0x3A57, 0, 0, - 0, 0, 0xD05C, 0, 0, 0, 0, 0x4578, - 0, 0xD05D, 0x6332, 0xD05E, 0xD05F, 0, 0xD060, 0x6333, -}; -static const unsigned short utf8_to_euc_E7A5_x0213[] = { - 0x632B, 0x3737, 0, 0, 0xD04E, 0x7935, 0x7936, 0x3540, - 0x3527, 0x3B63, 0xF261, 0xD052, 0, 0, 0, 0xD053, - 0x4D34, 0xD054, 0, 0x6331, 0xD055, 0x6330, 0x4144, 0x632D, - 0xF262, 0, 0x632F, 0xF263, 0x793A, 0x3D4B, 0x3F40, 0x632E, - 0x632C, 0, 0x472A, 0, 0, 0x3E4D, 0, 0xF265, - 0x493C, 0xD05A, 0, 0xD05B, 0, 0x3A57, 0, 0, - 0, 0, 0xF266, 0, 0, 0, 0, 0x4578, - 0, 0x793E, 0x6332, 0xD05E, 0xD05F, 0, 0xD060, 0x6333, -}; -static const unsigned short utf8_to_euc_E7A6[] = { - 0x6349, 0x3658, 0, 0, 0x4F3D, 0x4135, 0, 0, - 0, 0, 0x6334, 0xD061, 0xD062, 0x3252, 0x4477, 0x4A21, - 0, 0xD063, 0, 0xD064, 0xD065, 0xD066, 0xD067, 0, - 0xD068, 0, 0, 0xD069, 0xD06A, 0x6335, 0, 0, - 0, 0xD06B, 0, 0, 0, 0, 0x357A, 0x6336, - 0xD06C, 0xD06D, 0x6338, 0xD06E, 0, 0, 0x6339, 0xD06F, - 0x4729, 0xD070, 0, 0x633A, 0xD071, 0, 0, 0, - 0xD072, 0x633B, 0x633C, 0xD073, 0, 0x3659, 0x3253, 0x4645, -}; -static const unsigned short utf8_to_euc_E7A6_x0213[] = { - 0x6349, 0x3658, 0, 0, 0x4F3D, 0x4135, 0, 0, - 0, 0, 0x6334, 0xD061, 0xD062, 0x3252, 0x4477, 0x4A21, - 0, 0xD063, 0, 0xD064, 0xF267, 0xF268, 0xF269, 0, - 0x7942, 0, 0, 0xF26A, 0xD06A, 0x6335, 0, 0, - 0, 0xF26B, 0, 0, 0, 0, 0x357A, 0x6336, - 0xD06C, 0xF26C, 0x6338, 0xD06E, 0, 0, 0x6339, 0xD06F, - 0x4729, 0x7943, 0, 0x633A, 0xF26D, 0, 0, 0, - 0x7944, 0x633B, 0x633C, 0xF26E, 0, 0x3659, 0x3253, 0x4645, -}; -static const unsigned short utf8_to_euc_E7A7[] = { - 0x3D28, 0x3B64, 0xD074, 0, 0xD075, 0, 0, 0xD076, - 0xD077, 0x633D, 0xD078, 0x3D29, 0, 0, 0, 0xD079, - 0, 0x324A, 0x4943, 0, 0xD07A, 0x633E, 0xD07B, 0, - 0x486B, 0, 0xD07C, 0, 0, 0xD07D, 0xD07E, 0x4145, - 0xD121, 0x6341, 0xD122, 0x6342, 0x4769, 0xD123, 0x3F41, 0x633F, - 0, 0x4361, 0xD124, 0xD125, 0x6340, 0xD126, 0, 0, - 0x3E4E, 0xD127, 0, 0, 0, 0, 0, 0, - 0xD128, 0, 0, 0x305C, 0xD129, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E7A7_x0213[] = { - 0x3D28, 0x3B64, 0xF26F, 0, 0xD075, 0, 0, 0xF270, - 0x7945, 0x633D, 0x7946, 0x3D29, 0xF271, 0xF272, 0, 0xD079, - 0, 0x324A, 0x4943, 0, 0x7948, 0x633E, 0xF273, 0, - 0x486B, 0, 0xD07C, 0, 0, 0xD07D, 0x7949, 0x4145, - 0xD121, 0x6341, 0xD122, 0x6342, 0x4769, 0xD123, 0x3F41, 0x633F, - 0, 0x4361, 0xD124, 0x794A, 0x6340, 0x794B, 0, 0, - 0x3E4E, 0xD127, 0, 0, 0, 0, 0, 0, - 0xD128, 0, 0, 0x305C, 0xD129, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E7A8[] = { - 0x3529, 0, 0xD12A, 0xD12B, 0, 0, 0, 0xD12C, - 0x6343, 0xD12D, 0xD12E, 0x4478, 0xD12F, 0x6344, 0x4047, 0, - 0, 0xD130, 0, 0, 0x4C2D, 0xD131, 0, 0x4923, - 0x6345, 0x6346, 0x4355, 0xD132, 0x4E47, 0, 0xD133, 0x6348, - 0x6347, 0xD134, 0, 0, 0, 0, 0, 0xD135, - 0, 0, 0, 0xD136, 0, 0xD137, 0x3C6F, 0xD138, - 0xD139, 0x634A, 0x3070, 0, 0xD13A, 0xD13B, 0, 0x634D, - 0xD13C, 0xD13D, 0xD13E, 0x634B, 0x3254, 0x374E, 0x634C, 0x3946, -}; -static const unsigned short utf8_to_euc_E7A8_x0213[] = { - 0x3529, 0, 0xD12A, 0x794C, 0, 0, 0, 0xD12C, - 0x6343, 0xD12D, 0xF278, 0x4478, 0xD12F, 0x6344, 0x4047, 0, - 0, 0xF279, 0, 0, 0x4C2D, 0xF27A, 0, 0x4923, - 0x6345, 0x6346, 0x4355, 0xF27B, 0x4E47, 0, 0xF27C, 0x6348, - 0x6347, 0xD134, 0, 0, 0, 0, 0, 0xD135, - 0, 0, 0, 0xD136, 0, 0xF27E, 0x3C6F, 0xD138, - 0xD139, 0x634A, 0x3070, 0, 0xD13A, 0xD13B, 0, 0x634D, - 0xF321, 0x794E, 0xD13E, 0x634B, 0x3254, 0x374E, 0x634C, 0x3946, -}; -static const unsigned short utf8_to_euc_E7A9[] = { - 0x3972, 0, 0x4A66, 0x634E, 0xD13F, 0xD140, 0x4B54, 0xD141, - 0xD142, 0x6350, 0, 0, 0xD143, 0x4051, 0x314F, 0x323A, - 0x302C, 0, 0, 0, 0, 0xD144, 0xD145, 0x634F, - 0, 0xD146, 0, 0, 0xD147, 0xD148, 0, 0xD149, - 0xD14A, 0x6351, 0x6352, 0x3E77, 0, 0xD14B, 0, 0xD14C, - 0, 0x6353, 0xD14D, 0x334F, 0, 0xD14E, 0, 0, - 0x6355, 0, 0, 0, 0x376A, 0xD14F, 0x3566, 0, - 0xD150, 0x6356, 0x3675, 0, 0, 0x6357, 0xD151, 0x407C, -}; -static const unsigned short utf8_to_euc_E7A9_x0213[] = { - 0x3972, 0, 0x4A66, 0x634E, 0xD13F, 0xD140, 0x4B54, 0xF322, - 0xD142, 0x6350, 0, 0, 0xF323, 0x4051, 0x314F, 0x323A, - 0x302C, 0, 0, 0, 0, 0xD144, 0xF324, 0x634F, - 0, 0xF325, 0, 0, 0xF326, 0x794F, 0, 0xF327, - 0xF328, 0x6351, 0x6352, 0x3E77, 0, 0xD14B, 0, 0xF329, - 0, 0x6353, 0xF32A, 0x334F, 0, 0x7950, 0, 0, - 0x6355, 0, 0, 0, 0x376A, 0xF32B, 0x3566, 0, - 0xF32C, 0x6356, 0x3675, 0, 0, 0x6357, 0xD151, 0x407C, -}; -static const unsigned short utf8_to_euc_E7AA[] = { - 0xD152, 0x464D, 0xD153, 0x4060, 0x3A75, 0xD154, 0xD155, 0, - 0x6358, 0, 0xD156, 0xD157, 0, 0, 0, 0, - 0xD158, 0xD159, 0x4362, 0x416B, 0xD15A, 0x635A, 0x635C, 0x6359, - 0x635B, 0, 0, 0, 0, 0, 0xD15B, 0x3722, - 0xD15C, 0, 0, 0xD15D, 0, 0, 0, 0, - 0, 0x635D, 0x3726, 0, 0xD15E, 0, 0x3567, 0x4D52, - 0x635F, 0, 0, 0xD15F, 0, 0xD160, 0x6360, 0, - 0, 0xD161, 0x312E, 0xD162, 0xD163, 0, 0, 0x6363, -}; -static const unsigned short utf8_to_euc_E7AA_x0213[] = { - 0xD152, 0x464D, 0xF32D, 0x4060, 0x3A75, 0x7952, 0xD155, 0, - 0x6358, 0, 0xF32E, 0xD157, 0, 0, 0, 0, - 0xF32F, 0xD159, 0x4362, 0x416B, 0xD15A, 0x635A, 0x635C, 0x6359, - 0x635B, 0, 0, 0, 0, 0, 0xD15B, 0x3722, - 0x7953, 0, 0, 0xF330, 0, 0, 0, 0, - 0, 0x635D, 0x3726, 0, 0xF331, 0, 0x3567, 0x4D52, - 0x635F, 0, 0, 0x7955, 0, 0xD160, 0x6360, 0, - 0, 0xF334, 0x312E, 0x7956, 0xF335, 0, 0xF336, 0x6363, -}; -static const unsigned short utf8_to_euc_E7AB[] = { - 0, 0, 0, 0x3376, 0x6362, 0x6361, 0xD164, 0x6365, - 0x635E, 0xD165, 0x6366, 0x4E29, 0xD166, 0x6367, 0xD167, 0x6368, - 0, 0xD168, 0x5474, 0x636A, 0, 0x6369, 0, 0, - 0, 0x636B, 0x636C, 0xD169, 0x4E35, 0x636D, 0, 0x706F, - 0x3E4F, 0x636E, 0x636F, 0x3D57, 0, 0x4638, 0x6370, 0xF459, - 0xD16A, 0xD16B, 0x4328, 0xD16C, 0xD16D, 0x6371, 0, 0x433C, - 0x6372, 0xD16E, 0, 0, 0xD16F, 0, 0x3625, 0, - 0x513F, 0x435D, 0x3C33, 0xD170, 0, 0xD171, 0xD172, 0x3448, -}; -static const unsigned short utf8_to_euc_E7AB_x0213[] = { - 0, 0, 0, 0x3376, 0x6362, 0x6361, 0xD164, 0x6365, - 0x635E, 0xD165, 0x6366, 0x4E29, 0xF338, 0x6367, 0x7957, 0x6368, - 0, 0xF339, 0x5474, 0x636A, 0, 0x6369, 0, 0, - 0, 0x636B, 0x636C, 0xD169, 0x4E35, 0x636D, 0, 0x706F, - 0x3E4F, 0x636E, 0x636F, 0x3D57, 0, 0x4638, 0x6370, 0xF33A, - 0xF33B, 0xD16B, 0x4328, 0x7958, 0xD16D, 0x6371, 0, 0x433C, - 0x6372, 0xD16E, 0, 0, 0xF33C, 0, 0x3625, 0, - 0x513F, 0x435D, 0x3C33, 0xD170, 0, 0x7959, 0xD172, 0x3448, -}; -static const unsigned short utf8_to_euc_E7AC[] = { - 0, 0, 0x6373, 0, 0x6422, 0, 0x6376, 0xD173, - 0x3568, 0, 0x6375, 0x6424, 0, 0, 0, 0x6374, - 0, 0x3E50, 0, 0, 0xD174, 0, 0, 0, - 0x6378, 0x6379, 0, 0x452B, 0, 0, 0x637A, 0xD175, - 0x335E, 0, 0, 0xD176, 0, 0x3F5A, 0x4964, 0xD177, - 0x637C, 0xD178, 0xD179, 0xD17A, 0x4268, 0xD17B, 0xD17C, 0xD17D, - 0xD17E, 0xD221, 0, 0x6377, 0xD222, 0x637B, 0x637D, 0, - 0, 0x3A7B, 0, 0, 0, 0xD223, 0, 0xD224, -}; -static const unsigned short utf8_to_euc_E7AC_x0213[] = { - 0, 0, 0x6373, 0, 0x6422, 0, 0x6376, 0xF33F, - 0x3568, 0, 0x6375, 0x6424, 0, 0, 0, 0x6374, - 0, 0x3E50, 0x795A, 0, 0xD174, 0, 0, 0, - 0x6378, 0x6379, 0, 0x452B, 0, 0, 0x637A, 0xD175, - 0x335E, 0, 0, 0xD176, 0, 0x3F5A, 0x4964, 0xF342, - 0x637C, 0xD178, 0xF343, 0xD17A, 0x4268, 0x795B, 0xF344, 0xF345, - 0xD17E, 0xF346, 0, 0x6377, 0xD222, 0x637B, 0x637D, 0, - 0, 0x3A7B, 0, 0x795C, 0, 0xF341, 0, 0xD224, -}; -static const unsigned short utf8_to_euc_E7AD[] = { - 0xD225, 0xD226, 0, 0, 0, 0x6426, 0x492E, 0xD227, - 0x4826, 0x4579, 0, 0x365A, 0x6425, 0x6423, 0xD228, 0x4835, - 0x637E, 0x435E, 0x457B, 0, 0x457A, 0xD229, 0x3A76, 0, - 0, 0, 0, 0, 0, 0x6438, 0, 0, - 0xD22A, 0, 0, 0, 0xD22B, 0x6428, 0xD22C, 0x642A, - 0, 0xD22D, 0xD22E, 0, 0x642D, 0xD22F, 0x642E, 0xD230, - 0x642B, 0x642C, 0xD231, 0xD232, 0x6429, 0x6427, 0, 0xD233, - 0, 0, 0x6421, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E7AD_x0213[] = { - 0xD225, 0xF34A, 0, 0, 0, 0x6426, 0x492E, 0x795D, - 0x4826, 0x4579, 0, 0x365A, 0x6425, 0x6423, 0x795E, 0x4835, - 0x637E, 0x435E, 0x457B, 0, 0x457A, 0xF34C, 0x3A76, 0, - 0, 0, 0, 0, 0, 0x6438, 0, 0, - 0x795F, 0, 0, 0, 0xF34E, 0x6428, 0xF34F, 0x642A, - 0, 0xF350, 0xD22E, 0, 0x642D, 0x7960, 0x642E, 0x7961, - 0x642B, 0x642C, 0x7962, 0xF351, 0x6429, 0x6427, 0, 0xD233, - 0, 0xF34D, 0x6421, 0, 0, 0, 0, 0xF349, -}; -static const unsigned short utf8_to_euc_E7AE[] = { - 0, 0, 0, 0, 0xD234, 0, 0x4A4F, 0x3255, - 0, 0xD235, 0, 0x6435, 0, 0x6432, 0xD236, 0x6437, - 0xD237, 0xD238, 0x6436, 0, 0x4773, 0x4C27, 0xD239, 0x3B3B, - 0x6430, 0x6439, 0x6434, 0xD23A, 0x6433, 0x642F, 0xD23B, 0x6431, - 0xD23C, 0x3449, 0, 0, 0, 0xD23D, 0, 0, - 0, 0, 0x433D, 0, 0xD23E, 0x407D, 0, 0xD23F, - 0xD240, 0x4822, 0xD241, 0, 0x643E, 0xD242, 0xD243, 0, - 0x4824, 0, 0xD244, 0xD245, 0xD246, 0xD247, 0, 0, -}; -static const unsigned short utf8_to_euc_E7AE_x0213[] = { - 0, 0, 0, 0, 0xD234, 0, 0x4A4F, 0x3255, - 0, 0xD235, 0, 0x6435, 0, 0x6432, 0xD236, 0x6437, - 0xF354, 0xF355, 0x6436, 0, 0x4773, 0x4C27, 0xD239, 0x3B3B, - 0x6430, 0x6439, 0x6434, 0xF356, 0x6433, 0x642F, 0x7963, 0x6431, - 0xD23C, 0x3449, 0, 0, 0, 0xD23D, 0, 0, - 0, 0, 0x433D, 0, 0xD23E, 0x407D, 0, 0xF358, - 0xD240, 0x4822, 0xD241, 0, 0x643E, 0xF359, 0xD243, 0, - 0x4824, 0, 0xD244, 0xD245, 0xF35A, 0xD247, 0, 0, -}; -static const unsigned short utf8_to_euc_E7AF[] = { - 0x4061, 0x643B, 0xD248, 0, 0x484F, 0xD249, 0x643F, 0x4A53, - 0xD24A, 0x435B, 0xD24B, 0x643A, 0x643C, 0, 0, 0x643D, - 0, 0, 0, 0, 0xD24C, 0, 0xD24D, 0xD24E, - 0, 0xD24F, 0xD250, 0xD251, 0, 0x6440, 0, 0, - 0x3C44, 0, 0, 0, 0x4646, 0x6445, 0x6444, 0, - 0xD252, 0x6441, 0xD253, 0, 0, 0x4F36, 0, 0, - 0, 0, 0xD254, 0x644A, 0xD255, 0xD256, 0x644E, 0x644B, - 0xD257, 0xD258, 0xD259, 0, 0xD25A, 0, 0xD25B, 0, -}; -static const unsigned short utf8_to_euc_E7AF_x0213[] = { - 0x4061, 0x643B, 0xD248, 0, 0x484F, 0xF35B, 0x643F, 0x4A53, - 0xD24A, 0x435B, 0xF35C, 0x643A, 0x643C, 0, 0, 0x643D, - 0, 0, 0, 0, 0xF35F, 0, 0xF360, 0x7965, - 0, 0x7966, 0xF361, 0xD251, 0, 0x6440, 0, 0, - 0x3C44, 0, 0, 0, 0x4646, 0x6445, 0x6444, 0, - 0xD252, 0x6441, 0xF362, 0, 0, 0x4F36, 0, 0, - 0xF363, 0, 0xD254, 0x644A, 0xD255, 0xD256, 0x644E, 0x644B, - 0xD257, 0xD258, 0xD259, 0, 0xD25A, 0, 0xD25B, 0, -}; -static const unsigned short utf8_to_euc_E7B0[] = { - 0x6447, 0xD25C, 0xD25D, 0xD25E, 0xD25F, 0, 0xD260, 0x6448, - 0, 0xD261, 0, 0xD262, 0xD263, 0x644D, 0xD264, 0xD265, - 0, 0x6442, 0x5255, 0x6449, 0x6443, 0, 0, 0x644C, - 0, 0xD266, 0, 0xD267, 0, 0, 0, 0x6452, - 0xD268, 0x344A, 0, 0x644F, 0, 0xD269, 0xD26A, 0x6450, - 0xD26B, 0, 0x6451, 0x6454, 0xD26C, 0, 0, 0, - 0, 0xD26D, 0, 0xD26E, 0xD26F, 0, 0xD270, 0x6453, - 0x4876, 0xD271, 0xD272, 0, 0, 0x6455, 0x4E7C, 0x4A6D, -}; -static const unsigned short utf8_to_euc_E7B0_x0213[] = { - 0x6447, 0x7967, 0xD25D, 0xF364, 0xD25F, 0, 0xD260, 0x6448, - 0, 0xD261, 0, 0xF365, 0xD263, 0x644D, 0xF366, 0xF367, - 0, 0x6442, 0x5255, 0x6449, 0x6443, 0, 0, 0x644C, - 0, 0xD266, 0, 0xD267, 0, 0, 0x7969, 0x6452, - 0x796A, 0x344A, 0, 0x644F, 0, 0xD269, 0xF368, 0x6450, - 0xD26B, 0, 0x6451, 0x6454, 0xD26C, 0, 0, 0, - 0, 0x7968, 0, 0x796B, 0xD26F, 0, 0x796C, 0x6453, - 0x4876, 0xD271, 0xD272, 0, 0, 0x6455, 0x4E7C, 0x4A6D, -}; -static const unsigned short utf8_to_euc_E7B1[] = { - 0x645A, 0, 0, 0x6457, 0, 0, 0xD273, 0, - 0, 0, 0xD274, 0, 0x6456, 0x4052, 0, 0x6459, - 0x645B, 0xD276, 0xD277, 0xD278, 0x6458, 0xD275, 0x645F, 0, - 0x645C, 0xD279, 0xD27A, 0xD27B, 0xD27C, 0xD27D, 0xD27E, 0x645D, - 0x6446, 0xD321, 0, 0xD322, 0x645E, 0x6460, 0, 0xD323, - 0, 0xD324, 0, 0, 0x6461, 0xD325, 0xD326, 0, - 0xD327, 0, 0xD328, 0x4A46, 0, 0x6462, 0, 0, - 0, 0xD329, 0, 0, 0xD32A, 0xD32B, 0x4C62, 0, -}; -static const unsigned short utf8_to_euc_E7B1_x0213[] = { - 0x645A, 0, 0, 0x6457, 0, 0xF369, 0xD273, 0, - 0, 0, 0xF36A, 0, 0x6456, 0x4052, 0, 0x6459, - 0x645B, 0xF36B, 0xD277, 0xD278, 0x6458, 0xD275, 0x645F, 0xF36C, - 0x645C, 0x796F, 0xD27A, 0xD27B, 0xD27C, 0xD27D, 0xF36D, 0x645D, - 0x6446, 0xF36E, 0, 0xD322, 0x645E, 0x6460, 0, 0xD323, - 0, 0xF36F, 0, 0, 0x6461, 0x7970, 0xF370, 0xF371, - 0xF372, 0, 0xD328, 0x4A46, 0, 0x6462, 0, 0, - 0, 0x7971, 0, 0, 0xD32A, 0xD32B, 0x4C62, 0, -}; -static const unsigned short utf8_to_euc_E7B2[] = { - 0, 0x364E, 0x3729, 0x6463, 0, 0, 0xD32C, 0xD32D, - 0, 0x4A34, 0, 0x3F68, 0, 0x4C30, 0, 0xD32E, - 0x6464, 0, 0x4E33, 0, 0xD32F, 0x4774, 0, 0x4146, - 0x4734, 0, 0, 0x3D4D, 0, 0, 0xD330, 0x3040, - 0xD331, 0x6469, 0x6467, 0, 0x6465, 0x3421, 0xD332, 0x3E51, - 0x646A, 0, 0, 0x6468, 0, 0x6466, 0x646E, 0, - 0xD333, 0x646D, 0x646C, 0x646B, 0, 0, 0xD334, 0xD335, - 0, 0x646F, 0xD336, 0xD337, 0xD338, 0x6470, 0x403A, 0xD339, -}; -static const unsigned short utf8_to_euc_E7B2_x0213[] = { - 0, 0x364E, 0x3729, 0x6463, 0, 0, 0xD32C, 0xD32D, - 0, 0x4A34, 0, 0x3F68, 0, 0x4C30, 0, 0x7972, - 0x6464, 0, 0x4E33, 0, 0x7973, 0x4774, 0, 0x4146, - 0x4734, 0, 0, 0x3D4D, 0, 0, 0xD330, 0x3040, - 0x7974, 0x6469, 0x6467, 0, 0x6465, 0x3421, 0xF376, 0x3E51, - 0x646A, 0, 0, 0x6468, 0, 0x6466, 0x646E, 0, - 0xD333, 0x646D, 0x646C, 0x646B, 0, 0, 0xF378, 0xF379, - 0, 0x646F, 0xD336, 0xD337, 0x7975, 0x6470, 0x403A, 0xF37A, -}; -static const unsigned short utf8_to_euc_E7B3[] = { - 0x6471, 0, 0x6473, 0, 0xD33A, 0x6472, 0, 0xD33B, - 0xD33C, 0xD33D, 0x3852, 0, 0, 0xD33E, 0x4138, 0xD33F, - 0, 0, 0x6475, 0xD340, 0xD341, 0xD342, 0x457C, 0xD343, - 0x6474, 0xD344, 0xD345, 0, 0x6476, 0xD346, 0x4A35, 0x416C, - 0x3947, 0, 0x6477, 0, 0, 0, 0xD347, 0x4E48, - 0, 0xD348, 0, 0xD349, 0, 0, 0, 0x6479, - 0, 0, 0x647A, 0, 0x647B, 0xD34A, 0x647C, 0, - 0x3B65, 0, 0x647D, 0x374F, 0, 0, 0x356A, 0, -}; -static const unsigned short utf8_to_euc_E7B3_x0213[] = { - 0x6471, 0, 0x6473, 0, 0xF37C, 0x6472, 0, 0xD33B, - 0xF37E, 0xD33D, 0x3852, 0, 0, 0xF421, 0x4138, 0xD33F, - 0, 0, 0x6475, 0xD340, 0xD341, 0x7976, 0x457C, 0xF423, - 0x6474, 0x7977, 0xD345, 0, 0x6476, 0x7978, 0x4A35, 0x416C, - 0x3947, 0, 0x6477, 0, 0, 0, 0xF425, 0x4E48, - 0, 0xD348, 0, 0xF426, 0, 0, 0, 0x6479, - 0, 0, 0x647A, 0, 0x647B, 0xF428, 0x647C, 0, - 0x3B65, 0, 0x647D, 0x374F, 0, 0, 0x356A, 0, -}; -static const unsigned short utf8_to_euc_E7B4[] = { - 0x352A, 0, 0x6521, 0xD34B, 0x4C73, 0x3948, 0x647E, 0xD34C, - 0xD34D, 0xD34E, 0x6524, 0x4C66, 0, 0x473C, 0, 0xD34F, - 0x4933, 0xD350, 0xD351, 0xD352, 0x3D63, 0x6523, 0xD353, 0x3C53, - 0x3949, 0x3B66, 0x3569, 0x4A36, 0x6522, 0xD354, 0xD355, 0, - 0x4147, 0x4B42, 0x3A77, 0xD356, 0, 0, 0xD357, 0, - 0, 0, 0xD358, 0x3B67, 0x445D, 0xD359, 0x6527, 0x4E5F, - 0x3A59, 0xD35A, 0x6528, 0x3F42, 0, 0x652A, 0, 0, - 0, 0x3E52, 0x3A30, 0, 0xD35B, 0xD35C, 0xD35D, 0x6529, -}; -static const unsigned short utf8_to_euc_E7B4_x0213[] = { - 0x352A, 0, 0x6521, 0xF429, 0x4C73, 0x3948, 0x647E, 0x7979, - 0x797A, 0xF42A, 0x6524, 0x4C66, 0, 0x473C, 0, 0xD34F, - 0x4933, 0xD350, 0xF42C, 0x797B, 0x3D63, 0x6523, 0xD353, 0x3C53, - 0x3949, 0x3B66, 0x3569, 0x4A36, 0x6522, 0x797C, 0xF42D, 0, - 0x4147, 0x4B42, 0x3A77, 0x797D, 0, 0, 0xD357, 0, - 0, 0, 0xD358, 0x3B67, 0x445D, 0xD359, 0x6527, 0x4E5F, - 0x3A59, 0x797E, 0x6528, 0x3F42, 0, 0x652A, 0, 0, - 0, 0x3E52, 0x3A30, 0, 0xD35B, 0xF430, 0xF431, 0x6529, -}; -static const unsigned short utf8_to_euc_E7B5[] = { - 0xD35E, 0xD35F, 0x3D2A, 0x383E, 0x4148, 0x6525, 0x652B, 0xD360, - 0xD361, 0, 0, 0x6526, 0x3750, 0xD362, 0x652E, 0x6532, - 0x376B, 0xD363, 0, 0xD364, 0, 0, 0x652D, 0xD365, - 0, 0xD366, 0xD367, 0x6536, 0xD368, 0xD369, 0x394A, 0, - 0, 0x4D6D, 0x303C, 0x6533, 0, 0xD36A, 0x356B, 0xD36B, - 0x6530, 0, 0xD36C, 0, 0, 0, 0x6531, 0, - 0xD36D, 0x457D, 0x652F, 0x652C, 0, 0x3328, 0x4064, 0, - 0xD36E, 0x3828, 0xD36F, 0xD370, 0, 0x6538, 0, 0xD371, -}; -static const unsigned short utf8_to_euc_E7B5_x0213[] = { - 0xF432, 0x7A21, 0x3D2A, 0x383E, 0x4148, 0x6525, 0x652B, 0xF433, - 0x7A22, 0, 0, 0x6526, 0x3750, 0xD362, 0x652E, 0x6532, - 0x376B, 0xD363, 0, 0x7A23, 0, 0, 0x652D, 0xD365, - 0, 0xF437, 0xF438, 0x6536, 0x7A24, 0xD369, 0x394A, 0, - 0, 0x4D6D, 0x303C, 0x6533, 0, 0xD36A, 0x356B, 0xD36B, - 0x6530, 0, 0xF439, 0, 0, 0, 0x6531, 0, - 0xF43A, 0x457D, 0x652F, 0x652C, 0, 0x3328, 0x4064, 0, - 0xD36E, 0x3828, 0x7A25, 0xD370, 0, 0x6538, 0, 0xF43C, -}; -static const unsigned short utf8_to_euc_E7B6[] = { - 0, 0xD372, 0xD373, 0xD374, 0, 0xD375, 0xD376, 0, - 0xD377, 0x6535, 0, 0xD378, 0xD379, 0xD37A, 0, 0x6537, - 0, 0xD37B, 0, 0x6534, 0, 0, 0xD37C, 0xD37D, - 0, 0x3751, 0x4233, 0x6539, 0x416E, 0xD37E, 0xD421, 0x6546, - 0xF45C, 0, 0x6542, 0x653C, 0, 0, 0xD422, 0xD423, - 0, 0, 0xD424, 0x6540, 0x3C7A, 0x305D, 0x653B, 0x6543, - 0x6547, 0x394B, 0x4C56, 0xD425, 0x4456, 0x653D, 0xD426, 0xD427, - 0x6545, 0xD428, 0x653A, 0x433E, 0, 0x653F, 0x303D, 0x4C4A, -}; -static const unsigned short utf8_to_euc_E7B6_x0213[] = { - 0, 0xD372, 0xD373, 0x7A26, 0, 0xD375, 0xF43E, 0, - 0xF43F, 0x6535, 0, 0x7A27, 0xF440, 0xD37A, 0, 0x6537, - 0, 0xD37B, 0, 0x6534, 0, 0, 0xD37C, 0xF441, - 0, 0x3751, 0x4233, 0x6539, 0x416E, 0xF443, 0xD421, 0x6546, - 0x7A28, 0, 0x6542, 0x653C, 0, 0, 0x7A29, 0xF444, - 0, 0, 0xF445, 0x6540, 0x3C7A, 0x305D, 0x653B, 0x6543, - 0x6547, 0x394B, 0x4C56, 0xD425, 0x4456, 0x653D, 0xF446, 0xF447, - 0x6545, 0xD428, 0x653A, 0x433E, 0, 0x653F, 0x303D, 0x4C4A, -}; -static const unsigned short utf8_to_euc_E7B7[] = { - 0, 0, 0xD429, 0xD42A, 0xD42B, 0xD42C, 0xD42D, 0x653E, - 0, 0, 0x365B, 0x486C, 0xD42E, 0xD42F, 0xD430, 0x416D, - 0, 0x4E50, 0x3D6F, 0, 0, 0x656E, 0xF45D, 0xD431, - 0x6548, 0xD432, 0x407E, 0, 0x6544, 0x6549, 0x654B, 0, - 0x4479, 0x654E, 0xD434, 0, 0x654A, 0xD435, 0xD436, 0, - 0x4A54, 0x344B, 0xD437, 0xD438, 0x4C4B, 0xD439, 0, 0x305E, - 0, 0xD43A, 0x654D, 0, 0x4E7D, 0xD43B, 0xD43C, 0, - 0, 0xD43D, 0xD43E, 0x654C, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E7B7_x0213[] = { - 0xF448, 0, 0x7A2A, 0xD42A, 0xD42B, 0xD42C, 0xD42D, 0x653E, - 0, 0, 0x365B, 0x486C, 0x7A2B, 0xD42F, 0xD430, 0x416D, - 0, 0x4E50, 0x3D6F, 0, 0, 0x656E, 0x7A2C, 0xF449, - 0x6548, 0xF44A, 0x407E, 0, 0x6544, 0x6549, 0x654B, 0, - 0x4479, 0x654E, 0xD434, 0x7A2D, 0x654A, 0xD435, 0xF44B, 0, - 0x4A54, 0x344B, 0xD437, 0xD438, 0x4C4B, 0xD439, 0, 0x305E, - 0, 0xF44C, 0x654D, 0, 0x4E7D, 0xD43B, 0xD43C, 0, - 0, 0xF44D, 0xD43E, 0x654C, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E7B8[] = { - 0xD433, 0x316F, 0, 0, 0x466C, 0x654F, 0, 0, - 0xD43F, 0x6556, 0x6550, 0x6557, 0, 0, 0, 0, - 0xD440, 0xD441, 0x6553, 0, 0, 0xD442, 0, 0xD443, - 0, 0, 0, 0x477B, 0xD444, 0xD445, 0x3C4A, 0x6555, - 0xD446, 0x6552, 0x6558, 0x6551, 0, 0, 0x3D44, 0xD447, - 0xD448, 0, 0, 0x4B25, 0xD449, 0xD44A, 0x3D4C, 0xD44B, - 0, 0x6554, 0x6560, 0xD44C, 0, 0x655C, 0xD44D, 0x655F, - 0, 0x655D, 0x6561, 0x655B, 0, 0x6541, 0x4053, 0xD44E, -}; -static const unsigned short utf8_to_euc_E7B8_x0213[] = { - 0xD433, 0x316F, 0, 0, 0x466C, 0x654F, 0, 0, - 0x7A30, 0x6556, 0x6550, 0x6557, 0, 0, 0, 0, - 0xF451, 0x7A31, 0x6553, 0, 0, 0x7A32, 0, 0xF452, - 0, 0, 0, 0x477B, 0xD444, 0xF453, 0x3C4A, 0x6555, - 0xF454, 0x6552, 0x6558, 0x6551, 0, 0, 0x3D44, 0xF455, - 0x7A2F, 0, 0, 0x4B25, 0xF456, 0xD44A, 0x3D4C, 0xD44B, - 0, 0x6554, 0x6560, 0xD44C, 0, 0x655C, 0xD44D, 0x655F, - 0, 0x655D, 0x6561, 0x655B, 0, 0x6541, 0x4053, 0xD44E, -}; -static const unsigned short utf8_to_euc_E7B9[] = { - 0, 0x484B, 0, 0x655E, 0xD44F, 0xD450, 0x6559, 0xD451, - 0, 0, 0x4121, 0x3752, 0, 0x3D2B, 0xD452, 0, - 0xD453, 0, 0xD454, 0, 0x3F25, 0x4136, 0x6564, 0, - 0xD455, 0x6566, 0x6567, 0, 0, 0x6563, 0x6565, 0xD456, - 0, 0xD457, 0xD458, 0, 0, 0xD459, 0x655A, 0x6562, - 0, 0x656A, 0x6569, 0xD45A, 0, 0x4B7A, 0xD45B, 0xD45C, - 0x372B, 0, 0, 0xD45D, 0, 0, 0, 0, - 0xD45E, 0x6568, 0, 0x656C, 0x656B, 0x656F, 0xD45F, 0x6571, -}; -static const unsigned short utf8_to_euc_E7B9_x0213[] = { - 0, 0x484B, 0, 0x655E, 0xD44F, 0xF457, 0x6559, 0x7A34, - 0, 0, 0x4121, 0x3752, 0, 0x3D2B, 0xD452, 0, - 0xD453, 0, 0x7A35, 0, 0x3F25, 0x4136, 0x6564, 0, - 0xD455, 0x6566, 0x6567, 0, 0, 0x6563, 0x6565, 0xD456, - 0, 0x7A36, 0xD458, 0, 0, 0xD459, 0x655A, 0x6562, - 0, 0x656A, 0x6569, 0x7E7E, 0, 0x4B7A, 0xD45B, 0xD45C, - 0x372B, 0, 0, 0xF458, 0, 0xF459, 0, 0, - 0xD45E, 0x6568, 0, 0x656C, 0x656B, 0x656F, 0xF45A, 0x6571, -}; -static const unsigned short utf8_to_euc_E7BA[] = { - 0, 0xD460, 0x3B3C, 0x656D, 0, 0, 0xD461, 0xD462, - 0x6572, 0x6573, 0xD463, 0, 0x6574, 0xD464, 0x657A, 0x453B, - 0x6576, 0xD465, 0x6575, 0x6577, 0x6578, 0xD466, 0x6579, 0, - 0xD467, 0, 0xD468, 0x657B, 0x657C, 0xD469, 0xD46A, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E7BA_x0213[] = { - 0, 0xD460, 0x3B3C, 0x656D, 0, 0, 0xF45B, 0xF45C, - 0x6572, 0x6573, 0x7A37, 0, 0x6574, 0x7A38, 0x657A, 0x453B, - 0x6576, 0xF45E, 0x6575, 0x6577, 0x6578, 0xD466, 0x6579, 0, - 0xF45F, 0, 0xF460, 0x657B, 0x657C, 0xD469, 0xD46A, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E7BC[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0x344C, 0, - 0x657D, 0, 0x657E, 0xD46C, 0xD46B, 0xD46D, 0xD46E, 0xD46F, -}; -static const unsigned short utf8_to_euc_E7BC_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0x344C, 0, - 0x657D, 0, 0x657E, 0xF463, 0xF462, 0xD46D, 0xF464, 0xD46F, -}; -static const unsigned short utf8_to_euc_E7BD[] = { - 0, 0, 0, 0xD470, 0xD471, 0x6621, 0, 0xD472, - 0, 0, 0, 0, 0x6622, 0x6623, 0x6624, 0xD473, - 0x6625, 0x6626, 0xD474, 0xD475, 0x6628, 0x6627, 0, 0, - 0x6629, 0, 0, 0xD476, 0xD477, 0xD478, 0, 0x662A, - 0x662B, 0xD479, 0, 0xD47A, 0xD47B, 0xD47C, 0xD47D, 0x662E, - 0x662C, 0x662D, 0x3A61, 0x3753, 0, 0xD47E, 0x4356, 0, - 0x4833, 0xD521, 0x3D70, 0, 0, 0x474D, 0, 0x486D, - 0x662F, 0x586D, 0, 0, 0, 0xD522, 0xD523, 0xD524, -}; -static const unsigned short utf8_to_euc_E7BD_x0213[] = { - 0, 0, 0, 0xF465, 0xF466, 0x6621, 0, 0x7A39, - 0, 0, 0, 0, 0x6622, 0x6623, 0x6624, 0xF467, - 0x6625, 0x6626, 0xF46A, 0xD475, 0x6628, 0x6627, 0, 0, - 0x6629, 0, 0, 0xD476, 0xD477, 0xD478, 0, 0x662A, - 0x662B, 0xF46C, 0, 0xF46D, 0xF46E, 0xD47C, 0xD47D, 0x662E, - 0x662C, 0x662D, 0x3A61, 0x3753, 0, 0xF46F, 0x4356, 0, - 0x4833, 0xD521, 0x3D70, 0, 0, 0x474D, 0, 0x486D, - 0x662F, 0x586D, 0, 0, 0, 0xF470, 0xF471, 0xD524, -}; -static const unsigned short utf8_to_euc_E7BE[] = { - 0xD525, 0, 0x6630, 0x6632, 0, 0x4D65, 0x6631, 0x6634, - 0x6633, 0, 0x4D53, 0xD526, 0x6635, 0xD527, 0x487E, 0xD528, - 0xD529, 0xD52A, 0, 0, 0x6636, 0, 0xD52B, 0xD52C, - 0, 0, 0x6639, 0, 0xD52D, 0x6638, 0x6637, 0, - 0, 0xD52E, 0xD52F, 0x663A, 0x3732, 0, 0xD530, 0, - 0x4122, 0x3541, 0xD531, 0, 0, 0xD532, 0x663E, 0x663B, - 0, 0, 0x663C, 0, 0xD533, 0, 0x663F, 0, - 0x6640, 0x663D, 0, 0, 0xD534, 0x3129, 0, 0xD535, -}; -static const unsigned short utf8_to_euc_E7BE_x0213[] = { - 0xD525, 0, 0x6630, 0x6632, 0, 0x4D65, 0x6631, 0x6634, - 0x6633, 0, 0x4D53, 0xD526, 0x6635, 0xD527, 0x487E, 0xD528, - 0xF473, 0x7A3B, 0, 0, 0x6636, 0, 0xF476, 0x7A3C, - 0, 0, 0x6639, 0, 0xF477, 0x6638, 0x6637, 0, - 0, 0, 0xD52F, 0x663A, 0x3732, 0, 0xD530, 0, - 0x4122, 0x3541, 0xD531, 0, 0, 0xF478, 0x663E, 0x663B, - 0, 0, 0x663C, 0, 0xD533, 0, 0x663F, 0, - 0x6640, 0x663D, 0, 0, 0xD534, 0x3129, 0, 0x7A3D, -}; -static const unsigned short utf8_to_euc_E7BF[] = { - 0xD536, 0x3227, 0, 0xD537, 0, 0x6642, 0x6643, 0, - 0xD538, 0, 0x6644, 0, 0x4D62, 0, 0xD539, 0xD53A, - 0, 0, 0x3D2C, 0, 0x6646, 0x6645, 0, 0, - 0, 0, 0, 0xD53B, 0, 0, 0, 0xD53C, - 0x3F69, 0x6647, 0, 0xD53D, 0, 0xD53E, 0x6648, 0, - 0xD53F, 0x6649, 0, 0x3465, 0xD540, 0, 0xD541, 0xD542, - 0x344D, 0, 0xD543, 0x664A, 0, 0, 0, 0, - 0, 0x664B, 0xD544, 0x4B5D, 0x4D63, 0xD545, 0xD546, 0xD547, -}; -static const unsigned short utf8_to_euc_E7BF_x0213[] = { - 0xD536, 0x3227, 0, 0xF47A, 0, 0x6642, 0x6643, 0, - 0xD538, 0, 0x6644, 0, 0x4D62, 0, 0x7A3E, 0xF47B, - 0, 0, 0x3D2C, 0, 0x6646, 0x6645, 0, 0, - 0, 0, 0, 0x7A3F, 0, 0, 0, 0x7A40, - 0x3F69, 0x6647, 0, 0xF47C, 0, 0xF47D, 0x6648, 0, - 0xD53F, 0x6649, 0, 0x3465, 0x7A41, 0, 0x7A42, 0xF47E, - 0x344D, 0, 0xF521, 0x664A, 0, 0, 0, 0, - 0, 0x664B, 0x7A43, 0x4B5D, 0x4D63, 0xD545, 0xD546, 0xD547, -}; -static const unsigned short utf8_to_euc_E880[] = { - 0x4D54, 0x4F37, 0, 0x394D, 0x664E, 0x3C54, 0x664D, 0xD548, - 0xD549, 0, 0xD54A, 0x664F, 0x3C29, 0xD54B, 0xD54C, 0xD54D, - 0x4251, 0xD54E, 0x6650, 0xD54F, 0xD550, 0x394C, 0xD551, 0x4C57, - 0x6651, 0x6652, 0, 0, 0x6653, 0xD552, 0xD553, 0xD554, - 0xD555, 0x6654, 0, 0, 0xD556, 0, 0xD557, 0, - 0x6655, 0, 0, 0, 0xD558, 0, 0xD559, 0, - 0xD55A, 0, 0, 0x3C2A, 0xD55B, 0xD55C, 0x4C6D, 0xD55D, - 0, 0xD55E, 0xD55F, 0x6657, 0xD560, 0x433F, 0xD561, 0x6656, -}; -static const unsigned short utf8_to_euc_E880_x0213[] = { - 0x4D54, 0x4F37, 0xF522, 0x394D, 0x664E, 0x3C54, 0x664D, 0xD548, - 0xF524, 0, 0xF523, 0x664F, 0x3C29, 0xD54B, 0xF525, 0xD54D, - 0x4251, 0xF526, 0x6650, 0xD54F, 0x7A45, 0x394C, 0xF527, 0x4C57, - 0x6651, 0x6652, 0, 0, 0x6653, 0xD552, 0xD553, 0xD554, - 0xD555, 0x6654, 0, 0, 0xF528, 0, 0x7A46, 0, - 0x6655, 0, 0, 0, 0xF529, 0, 0xD559, 0, - 0xF52A, 0, 0, 0x3C2A, 0xD55B, 0x7A47, 0x4C6D, 0x7A48, - 0, 0xD55E, 0xD55F, 0x6657, 0x7A49, 0x433F, 0xD561, 0x6656, -}; -static const unsigned short utf8_to_euc_E881[] = { - 0xD562, 0, 0, 0, 0xD563, 0, 0x6659, 0, - 0, 0, 0x6658, 0, 0, 0, 0, 0, - 0, 0, 0x665A, 0, 0, 0, 0x403B, 0, - 0x665B, 0, 0x665C, 0, 0, 0, 0x4A39, 0x665D, - 0xD564, 0x416F, 0x665E, 0, 0xD565, 0, 0xD566, 0, - 0x665F, 0, 0, 0, 0, 0xD567, 0, 0x4E7E, - 0x6662, 0xD568, 0x6661, 0x6660, 0x4430, 0xD569, 0x6663, 0x3F26, - 0, 0x6664, 0, 0, 0, 0x6665, 0x4F38, 0x6666, -}; -static const unsigned short utf8_to_euc_E881_x0213[] = { - 0xD562, 0, 0, 0xF52B, 0xD563, 0, 0x6659, 0, - 0, 0, 0x6658, 0, 0, 0, 0, 0, - 0, 0, 0x665A, 0, 0, 0, 0x403B, 0, - 0x665B, 0, 0x665C, 0, 0, 0, 0x4A39, 0x665D, - 0xD564, 0x416F, 0x665E, 0, 0xD565, 0, 0xF52C, 0, - 0x665F, 0, 0, 0, 0, 0xD567, 0, 0x4E7E, - 0x6662, 0xF52D, 0x6661, 0x6660, 0x4430, 0xF52E, 0x6663, 0x3F26, - 0, 0x6664, 0, 0xF52F, 0, 0x6665, 0x4F38, 0x6666, -}; -static const unsigned short utf8_to_euc_E882[] = { - 0, 0xD56A, 0, 0, 0x6667, 0x6669, 0x6668, 0x4825, - 0xD56B, 0x4679, 0, 0x4F3E, 0x4829, 0, 0xD56C, 0, - 0, 0, 0, 0x666B, 0, 0, 0x3E53, 0, - 0x492A, 0, 0x666C, 0x666A, 0xD56D, 0x344E, 0xD56E, 0, - 0, 0x3854, 0x3B68, 0, 0, 0x486E, 0xD56F, 0xD570, - 0, 0x382A, 0x4B43, 0xD571, 0x666F, 0x666D, 0, 0x394E, - 0, 0x394F, 0x3069, 0, 0x3A68, 0, 0, 0, - 0xD572, 0xD573, 0x4759, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E882_x0213[] = { - 0, 0xD56A, 0, 0, 0x6667, 0x6669, 0x6668, 0x4825, - 0xD56B, 0x4679, 0, 0x4F3E, 0x4829, 0, 0xD56C, 0, - 0, 0, 0, 0x666B, 0, 0, 0x3E53, 0, - 0x492A, 0xF530, 0x666C, 0x666A, 0xF531, 0x344E, 0xD56E, 0, - 0, 0x3854, 0x3B68, 0, 0xF532, 0x486E, 0xD56F, 0xF533, - 0, 0x382A, 0x4B43, 0xD571, 0x666F, 0x666D, 0, 0x394E, - 0, 0x394F, 0x3069, 0, 0x3A68, 0, 0, 0, - 0xF534, 0xD573, 0x4759, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E883[] = { - 0, 0, 0, 0x305F, 0x6674, 0, 0x4340, 0, - 0xD574, 0, 0, 0, 0x4758, 0xD575, 0x425B, 0xD576, - 0, 0, 0xD577, 0, 0xD578, 0xD579, 0x6676, 0xD57A, - 0xD57B, 0x6672, 0x6675, 0x6670, 0, 0x6673, 0x4B26, 0, - 0xD57C, 0x3855, 0, 0, 0x307D, 0x6671, 0, 0, - 0, 0, 0, 0, 0, 0xD57D, 0xD57E, 0x6678, - 0xD621, 0x6679, 0xD622, 0xD623, 0x4639, 0, 0xD624, 0, - 0x363B, 0xD625, 0xD626, 0, 0x6726, 0x473D, 0xD627, 0, -}; -static const unsigned short utf8_to_euc_E883_x0213[] = { - 0, 0, 0, 0x305F, 0x6674, 0xF536, 0x4340, 0, - 0xD574, 0, 0x7A4A, 0, 0x4758, 0xD575, 0x425B, 0xD576, - 0, 0, 0xD577, 0, 0xD578, 0xF537, 0x6676, 0x7A4B, - 0xF538, 0x6672, 0x6675, 0x6670, 0, 0x6673, 0x4B26, 0, - 0x7A4C, 0x3855, 0, 0, 0x307D, 0x6671, 0xF539, 0, - 0, 0, 0, 0, 0, 0xD57D, 0xD57E, 0x6678, - 0xD621, 0x6679, 0xD622, 0x7A4D, 0x4639, 0xF53C, 0xD624, 0, - 0x363B, 0xD625, 0xD626, 0xF53D, 0x6726, 0x473D, 0xD627, 0, -}; -static const unsigned short utf8_to_euc_E884[] = { - 0, 0, 0x3B69, 0xD628, 0, 0x363C, 0x4048, 0x4F46, - 0x4C2E, 0x6677, 0x4054, 0xD629, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0xD62A, 0xD62B, - 0xD62C, 0, 0x3553, 0x667A, 0xD62D, 0, 0xD62E, 0, - 0xD62F, 0, 0, 0x667C, 0xD630, 0, 0, 0xD631, - 0, 0x667B, 0, 0, 0xD632, 0, 0, 0x667D, - 0xD633, 0x4326, 0, 0x473E, 0, 0xD634, 0, 0, - 0, 0x4431, 0xD635, 0, 0xD636, 0, 0x6723, 0, -}; -static const unsigned short utf8_to_euc_E884_x0213[] = { - 0, 0, 0x3B69, 0xD628, 0, 0x363C, 0x4048, 0x4F46, - 0x4C2E, 0x6677, 0x4054, 0xD629, 0, 0xF53B, 0, 0, - 0, 0, 0, 0, 0, 0, 0xF540, 0xD62B, - 0x7A4E, 0, 0x3553, 0x667A, 0xD62D, 0, 0xF541, 0, - 0xD62F, 0, 0, 0x667C, 0xF543, 0, 0, 0xF544, - 0, 0x667B, 0, 0, 0xF545, 0, 0, 0x667D, - 0xD633, 0x4326, 0, 0x473E, 0, 0xF53F, 0, 0, - 0, 0x4431, 0xD635, 0, 0xD636, 0xF547, 0x6723, 0, -}; -static const unsigned short utf8_to_euc_E885[] = { - 0, 0, 0, 0, 0, 0xD637, 0x6722, 0xD638, - 0, 0, 0xD639, 0x667E, 0xD63A, 0, 0x3F55, 0, - 0x4965, 0x6725, 0xD63B, 0x6724, 0x3950, 0x4F53, 0, 0xD63C, - 0, 0, 0, 0, 0, 0, 0, 0x6735, - 0xD63D, 0xD63E, 0, 0, 0, 0x6729, 0x672A, 0xD63F, - 0xD640, 0xD641, 0, 0x3C70, 0, 0xD642, 0x6728, 0xD643, - 0x3978, 0x6727, 0, 0, 0x672B, 0, 0, 0xD644, - 0x4432, 0x4A22, 0x4123, 0, 0, 0, 0, 0x425C, -}; -static const unsigned short utf8_to_euc_E885_x0213[] = { - 0, 0, 0, 0, 0, 0xD637, 0x6722, 0xD638, - 0, 0, 0x7A4F, 0x667E, 0xD63A, 0, 0x3F55, 0, - 0x4965, 0x6725, 0xD63B, 0x6724, 0x3950, 0x4F53, 0, 0xD63C, - 0, 0, 0, 0, 0, 0, 0, 0x6735, - 0x7A50, 0xD63E, 0, 0, 0, 0x6729, 0x672A, 0x7A51, - 0x7A52, 0xF549, 0, 0x3C70, 0, 0x7A53, 0x6728, 0xD643, - 0x3978, 0x6727, 0, 0, 0x672B, 0, 0, 0xD644, - 0x4432, 0x4A22, 0x4123, 0, 0, 0, 0, 0x425C, -}; -static const unsigned short utf8_to_euc_E886[] = { - 0x672F, 0xD645, 0x6730, 0x672C, 0xD647, 0xD648, 0xD649, 0, - 0x672D, 0, 0x672E, 0xD64A, 0, 0, 0xD64B, 0x3951, - 0xD646, 0, 0, 0x6736, 0, 0x6732, 0xD64C, 0, - 0xD64D, 0, 0x4966, 0xD64E, 0x4B6C, 0x4928, 0xD64F, 0, - 0x6731, 0, 0xD650, 0x6734, 0x6733, 0, 0, 0, - 0x4B44, 0x6737, 0, 0, 0, 0, 0xD651, 0, - 0x6738, 0, 0xD652, 0x4137, 0xD653, 0x6739, 0, 0, - 0x673B, 0, 0x673F, 0xD654, 0, 0x673C, 0x673A, 0x473F, -}; -static const unsigned short utf8_to_euc_E886_x0213[] = { - 0x672F, 0xF54B, 0x6730, 0x672C, 0xF54D, 0xF54E, 0xD649, 0, - 0x672D, 0, 0x672E, 0xD64A, 0, 0, 0xD64B, 0x3951, - 0xD646, 0, 0, 0x6736, 0, 0x6732, 0xD64C, 0, - 0xF550, 0, 0x4966, 0xD64E, 0x4B6C, 0x4928, 0xD64F, 0, - 0x6731, 0, 0xD650, 0x6734, 0x6733, 0, 0, 0, - 0x4B44, 0x6737, 0, 0, 0, 0, 0xD651, 0, - 0x6738, 0, 0xF551, 0x4137, 0xD653, 0x6739, 0, 0, - 0x673B, 0, 0x673F, 0x7A54, 0, 0x673C, 0x673A, 0x473F, -}; -static const unsigned short utf8_to_euc_E887[] = { - 0x673D, 0, 0x673E, 0xD656, 0, 0xD657, 0x3232, 0, - 0x6745, 0x6740, 0xD658, 0xD655, 0, 0x6741, 0xD659, 0xD65A, - 0, 0x6742, 0, 0x4221, 0, 0xD65B, 0, 0xD65C, - 0x6744, 0x6743, 0x6746, 0xD65D, 0, 0xD65E, 0xD65F, 0x6747, - 0x6748, 0xD660, 0, 0x3F43, 0xD661, 0x3269, 0, 0x6749, - 0x4E57, 0, 0x3C2B, 0xD662, 0xD663, 0x3D2D, 0, 0, - 0xD664, 0xD665, 0xD666, 0x3B6A, 0x4357, 0xD667, 0xD668, 0, - 0xD669, 0xD66A, 0x674A, 0x674B, 0x3131, 0xD66B, 0x674C, 0xD66C, -}; -static const unsigned short utf8_to_euc_E887_x0213[] = { - 0x673D, 0xF552, 0x673E, 0xF553, 0, 0xD657, 0x3232, 0, - 0x6745, 0x6740, 0x7A55, 0xD655, 0, 0x6741, 0xD659, 0x7A56, - 0, 0x6742, 0, 0x4221, 0, 0xD65B, 0xF554, 0x7A57, - 0x6744, 0x6743, 0x6746, 0xF555, 0, 0xD65E, 0xD65F, 0x6747, - 0x6748, 0xD660, 0, 0x3F43, 0xF557, 0x3269, 0, 0x6749, - 0x4E57, 0, 0x3C2B, 0xD662, 0xF559, 0x3D2D, 0, 0, - 0xD664, 0xD665, 0xD666, 0x3B6A, 0x4357, 0xD667, 0xD668, 0, - 0xD669, 0xD66A, 0x674A, 0x674B, 0x3131, 0xF55B, 0x674C, 0xF55C, -}; -static const unsigned short utf8_to_euc_E888[] = { - 0xD66D, 0x674D, 0x674E, 0xD66E, 0, 0x674F, 0, 0x6750, - 0x363D, 0x5A2A, 0x6751, 0, 0x4065, 0x6752, 0x3C4B, 0xD66F, - 0x6753, 0, 0x5030, 0xD670, 0xD671, 0, 0x6754, 0x4A5E, - 0x345C, 0xD672, 0xD673, 0x4124, 0x3D58, 0xD674, 0x4971, 0x3D2E, - 0, 0xD675, 0xD676, 0, 0, 0, 0, 0, - 0xD677, 0x6755, 0x3952, 0x6756, 0x484C, 0, 0x6764, 0, - 0, 0, 0xD678, 0x6758, 0xD679, 0x4249, 0x4775, 0x383F, - 0x6757, 0x4125, 0xD67A, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E888_x0213[] = { - 0xD66D, 0x674D, 0x674E, 0xD66E, 0xF55E, 0x674F, 0, 0x6750, - 0x363D, 0x5A2A, 0x6751, 0, 0x4065, 0x6752, 0x3C4B, 0xD66F, - 0x6753, 0, 0x5030, 0xD670, 0xD671, 0, 0x6754, 0x4A5E, - 0x345C, 0xF560, 0xD673, 0x4124, 0x3D58, 0xD674, 0x4971, 0x3D2E, - 0, 0xF561, 0xF562, 0, 0, 0, 0, 0, - 0xD677, 0x6755, 0x3952, 0x6756, 0x484C, 0, 0x6764, 0, - 0, 0, 0xF564, 0x6758, 0xF565, 0x4249, 0x4775, 0x383F, - 0x6757, 0x4125, 0xD67A, 0, 0xF566, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E889[] = { - 0x6759, 0, 0, 0xD67B, 0xD67C, 0xD67D, 0xD67E, 0x447A, - 0, 0, 0, 0xD721, 0, 0, 0xD722, 0xD723, - 0, 0xD724, 0, 0, 0, 0, 0xD725, 0, - 0x675B, 0x675A, 0x675D, 0, 0xD726, 0x675C, 0, 0x675E, - 0xD727, 0, 0x6760, 0xD728, 0x675F, 0, 0x344F, 0xD729, - 0x6761, 0, 0x6762, 0x6763, 0, 0xD72A, 0x3A31, 0x4E49, - 0, 0x6765, 0x3F27, 0, 0xD72B, 0, 0x3170, 0x6766, - 0x6767, 0, 0, 0xD72C, 0, 0xD72D, 0x6768, 0xD72E, -}; -static const unsigned short utf8_to_euc_E889_x0213[] = { - 0x6759, 0, 0, 0xD67B, 0xD67C, 0xF569, 0xF567, 0x447A, - 0, 0xF568, 0, 0xF56B, 0, 0, 0xD722, 0xF56D, - 0, 0xD724, 0, 0, 0, 0, 0xD725, 0xF56F, - 0x675B, 0x675A, 0x675D, 0, 0xF571, 0x675C, 0, 0x675E, - 0x7A5B, 0, 0x6760, 0xF572, 0x675F, 0, 0x344F, 0xD729, - 0x6761, 0, 0x6762, 0x6763, 0, 0xD72A, 0x3A31, 0x4E49, - 0, 0x6765, 0x3F27, 0, 0x7A5C, 0, 0x3170, 0x6766, - 0x6767, 0xF576, 0, 0xD72C, 0, 0xF578, 0x6768, 0xF579, -}; -static const unsigned short utf8_to_euc_E88A[] = { - 0xD72F, 0xD730, 0, 0xD731, 0xD732, 0, 0, 0xD733, - 0, 0xD734, 0xD735, 0x3072, 0, 0x6769, 0xD736, 0, - 0, 0xD737, 0x676A, 0, 0xD738, 0, 0xD739, 0, - 0xD73A, 0x4967, 0xD73B, 0xD73C, 0, 0x3C47, 0, 0x676C, - 0xD73D, 0xD73E, 0, 0xD73F, 0xD740, 0x3329, 0x3032, 0xD741, - 0xD742, 0xD743, 0xD744, 0x676B, 0x676E, 0x474E, 0xD745, 0x3F44, - 0xD746, 0x3256, 0xD747, 0x4B27, 0xD748, 0, 0, 0xD749, - 0x375D, 0x365C, 0xD74A, 0x676D, 0xD74B, 0x326A, 0xD74C, 0xD74D, -}; -static const unsigned short utf8_to_euc_E88A_x0213[] = { - 0xD72F, 0xD730, 0, 0xF57A, 0xD732, 0, 0, 0xD733, - 0, 0xD734, 0xF57B, 0x3072, 0, 0x6769, 0x7A5E, 0, - 0, 0xD737, 0x676A, 0xF57C, 0xD738, 0, 0xD739, 0, - 0xD73A, 0x4967, 0xD73B, 0xD73C, 0, 0x3C47, 0, 0x676C, - 0xD73D, 0x7A5F, 0, 0x7A60, 0x7A61, 0x3329, 0x3032, 0xF57D, - 0xF57E, 0x7A62, 0xD744, 0x676B, 0x676E, 0x474E, 0x7A63, 0x3F44, - 0xD746, 0x3256, 0xF621, 0x4B27, 0xF622, 0, 0, 0x7A64, - 0x375D, 0x365C, 0xF623, 0x676D, 0xF624, 0x326A, 0x7A65, 0x7A66, -}; -static const unsigned short utf8_to_euc_E88B[] = { - 0, 0, 0, 0, 0, 0x3423, 0xD74E, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0xD74F, 0x3171, 0x6772, 0x4E6A, 0x425D, 0xD750, 0, 0x4944, - 0, 0x677E, 0xD751, 0x3257, 0x677C, 0, 0x677A, 0x6771, - 0xD752, 0x676F, 0xD753, 0x6770, 0xD754, 0x3C63, 0x366C, 0x4377, - 0xD755, 0, 0xD756, 0x4651, 0, 0xD757, 0, 0xD758, - 0, 0x3151, 0, 0x6774, 0x6773, 0, 0xD759, 0xD75A, - 0, 0x6779, 0x6775, 0x6778, 0, 0xD75B, 0xD75C, 0, -}; -static const unsigned short utf8_to_euc_E88B_x0213[] = { - 0, 0, 0, 0, 0, 0x3423, 0x7A67, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0xD74F, 0x3171, 0x6772, 0x4E6A, 0x425D, 0x7A68, 0, 0x4944, - 0, 0x677E, 0xD751, 0x3257, 0x677C, 0, 0x677A, 0x6771, - 0xD752, 0x676F, 0xF625, 0x6770, 0xD754, 0x3C63, 0x366C, 0x4377, - 0xF626, 0, 0xD756, 0x4651, 0, 0xD757, 0, 0xD758, - 0, 0x3151, 0, 0x6774, 0x6773, 0, 0xD759, 0xF627, - 0, 0x6779, 0x6775, 0x6778, 0, 0x7A69, 0x7A6A, 0, -}; -static const unsigned short utf8_to_euc_E88C[] = { - 0xD75D, 0xD75E, 0x4C50, 0x6777, 0x3258, 0x337D, 0x677B, 0xD75F, - 0xD760, 0x677D, 0xD761, 0xD762, 0, 0, 0x3754, 0, - 0, 0, 0, 0, 0, 0, 0x6823, 0x682C, - 0x682D, 0, 0, 0xD764, 0x302B, 0xD765, 0xD766, 0xD767, - 0, 0xD768, 0xD769, 0x6834, 0, 0, 0, 0, - 0x3071, 0, 0, 0x682B, 0xD76A, 0xD76B, 0xD76C, 0x682A, - 0xD76D, 0x6825, 0x6824, 0xD76E, 0x6822, 0x6821, 0x4363, 0xD76F, - 0x427B, 0x6827, 0xD770, 0, 0xD771, 0xD772, 0, 0, -}; -static const unsigned short utf8_to_euc_E88C_x0213[] = { - 0x7A6B, 0x7A6C, 0x4C50, 0x6777, 0x3258, 0x337D, 0x677B, 0xF628, - 0xF629, 0x677D, 0xD761, 0xD762, 0xF62A, 0, 0x3754, 0, - 0, 0, 0, 0, 0, 0, 0x6823, 0x682C, - 0x682D, 0, 0, 0xF62C, 0x302B, 0xF62D, 0xD766, 0xD767, - 0, 0xD768, 0x7A6E, 0x6834, 0, 0, 0, 0, - 0x3071, 0, 0, 0x682B, 0xD76A, 0x7A6F, 0xD76C, 0x682A, - 0xF62E, 0x6825, 0x6824, 0xD76E, 0x6822, 0x6821, 0x4363, 0xD76F, - 0x427B, 0x6827, 0x7A70, 0, 0xF62F, 0xD772, 0, 0, -}; -static const unsigned short utf8_to_euc_E88D[] = { - 0x6826, 0, 0xD773, 0xD774, 0xD775, 0x6829, 0, 0xD776, - 0, 0x4170, 0x3755, 0, 0, 0xD777, 0xD778, 0x3141, - 0x6828, 0xD779, 0x3953, 0xD83E, 0xD763, 0xD77A, 0xD77B, 0xD77C, - 0x4171, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0xF45F, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0xD77D, 0, 0, 0x683A, 0, 0x683B, 0, 0x3259, - 0xD77E, 0, 0, 0x322E, 0x6838, 0xD821, 0, 0xD822, -}; -static const unsigned short utf8_to_euc_E88D_x0213[] = { - 0x6826, 0, 0xD773, 0x7A71, 0xF630, 0x6829, 0, 0x7A72, - 0, 0x4170, 0x3755, 0, 0, 0xD777, 0xD778, 0x3141, - 0x6828, 0x7A73, 0x3953, 0xD83E, 0xF62B, 0x7A74, 0xD77B, 0xF631, - 0x4171, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0x7A6D, 0xAE4A, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0xD77D, 0, 0, 0x683A, 0, 0x683B, 0, 0x3259, - 0xD77E, 0, 0, 0x322E, 0x6838, 0x7A75, 0, 0xF633, -}; -static const unsigned short utf8_to_euc_E88E[] = { - 0xD823, 0, 0xD824, 0, 0xD825, 0x682E, 0xD826, 0x6836, - 0, 0x683D, 0x6837, 0, 0, 0xD827, 0x6835, 0, - 0, 0, 0xD828, 0x6776, 0xD829, 0xD82A, 0x6833, 0, - 0xD82B, 0xD82C, 0x682F, 0xD82D, 0xD82E, 0xD82F, 0x3450, 0x6831, - 0x683C, 0, 0x6832, 0, 0, 0, 0xD830, 0xD831, - 0x683E, 0xD832, 0x6830, 0x477C, 0xD833, 0xD84C, 0, 0, - 0, 0x4D69, 0, 0, 0, 0x6839, 0, 0, - 0, 0, 0, 0, 0, 0x684F, 0xD834, 0xD835, -}; -static const unsigned short utf8_to_euc_E88E_x0213[] = { - 0xD823, 0, 0xD824, 0, 0xD825, 0x682E, 0x7A76, 0x6836, - 0, 0x683D, 0x6837, 0, 0, 0xF636, 0x6835, 0, - 0, 0, 0x7A77, 0x6776, 0xF637, 0xF638, 0x6833, 0, - 0x7A78, 0xD82C, 0x682F, 0xF639, 0xD82E, 0xF63A, 0x3450, 0x6831, - 0x683C, 0, 0x6832, 0, 0, 0, 0xD830, 0x7A79, - 0x683E, 0x7A7A, 0x6830, 0x477C, 0xD833, 0xD84C, 0, 0, - 0, 0x4D69, 0, 0, 0, 0x6839, 0, 0, - 0, 0, 0, 0, 0, 0x684F, 0xD834, 0x7A7B, -}; -static const unsigned short utf8_to_euc_E88F[] = { - 0xD836, 0x6847, 0, 0, 0, 0x3F7B, 0, 0xD837, - 0, 0xD838, 0x3546, 0, 0x365D, 0, 0x6842, 0xD839, - 0xD83A, 0xD83B, 0, 0x325B, 0xD83C, 0, 0x3E54, 0, - 0x6845, 0, 0, 0, 0x3A5A, 0xD83D, 0, 0x4551, - 0x684A, 0, 0, 0, 0, 0, 0, 0, - 0xD83F, 0x4A6E, 0xD840, 0x6841, 0, 0, 0, 0x325A, - 0x3856, 0x4929, 0x684B, 0, 0x683F, 0, 0xD841, 0x6848, - 0xD842, 0xD843, 0, 0x6852, 0xD844, 0x6843, 0, 0, -}; -static const unsigned short utf8_to_euc_E88F_x0213[] = { - 0x7A7C, 0x6847, 0, 0, 0, 0x3F7B, 0, 0x7A7D, - 0, 0xF63B, 0x3546, 0, 0x365D, 0, 0x6842, 0x7A7E, - 0xF63C, 0x7B21, 0, 0x325B, 0xF63D, 0, 0x3E54, 0, - 0x6845, 0, 0, 0, 0x3A5A, 0xF63E, 0, 0x4551, - 0x684A, 0x7B22, 0, 0, 0, 0xF63F, 0, 0, - 0xD83F, 0x4A6E, 0x7B23, 0x6841, 0, 0, 0, 0x325A, - 0x3856, 0x4929, 0x684B, 0, 0x683F, 0, 0, 0x6848, - 0xD842, 0xF640, 0, 0x6852, 0xD844, 0x6843, 0, 0, -}; -static const unsigned short utf8_to_euc_E890[] = { - 0, 0xD845, 0, 0x6844, 0x463A, 0, 0xD846, 0x6849, - 0, 0, 0xD847, 0x6846, 0x4B28, 0x684C, 0x3060, 0xD848, - 0, 0xD849, 0, 0x6840, 0, 0xD84A, 0, 0, - 0, 0xD84B, 0, 0, 0, 0, 0, 0, - 0x684E, 0, 0x684D, 0, 0, 0, 0, 0, - 0, 0x476B, 0x6854, 0, 0x685F, 0, 0, 0xD84D, - 0, 0x337E, 0, 0, 0, 0x6862, 0, 0, - 0x6850, 0xD84E, 0, 0, 0x6855, 0x4D6E, 0, 0, -}; -static const unsigned short utf8_to_euc_E890_x0213[] = { - 0, 0x7B24, 0, 0x6844, 0x463A, 0, 0x7B25, 0x6849, - 0, 0, 0x7B26, 0x6846, 0x4B28, 0x684C, 0x3060, 0xF641, - 0, 0xF642, 0, 0x6840, 0, 0xF643, 0, 0xF645, - 0, 0xD84B, 0, 0, 0, 0, 0, 0, - 0x684E, 0, 0x684D, 0, 0, 0, 0, 0, - 0, 0x476B, 0x6854, 0, 0x685F, 0, 0, 0xD84D, - 0, 0x337E, 0, 0, 0, 0x6862, 0, 0, - 0x6850, 0xF646, 0, 0, 0x6855, 0x4D6E, 0, 0, -}; -static const unsigned short utf8_to_euc_E891[] = { - 0, 0, 0, 0, 0, 0xD84F, 0x685E, 0xD850, - 0xD851, 0x4D55, 0xD852, 0, 0, 0xD853, 0x4E2A, 0xD854, - 0, 0xD855, 0xD856, 0, 0, 0, 0xD857, 0x4378, - 0xD858, 0xD859, 0xD85A, 0x336B, 0xD85B, 0, 0, 0, - 0xD85C, 0x4972, 0x6864, 0x4621, 0xD85D, 0xD85E, 0x3031, 0xD85F, - 0, 0x685D, 0xD860, 0x6859, 0x4172, 0x6853, 0x685B, 0x6860, - 0xD861, 0x472C, 0, 0xD862, 0xD863, 0x302A, 0xD864, 0x6858, - 0xD865, 0x6861, 0x4978, 0, 0xD866, 0xD867, 0, 0, -}; -static const unsigned short utf8_to_euc_E891_x0213[] = { - 0, 0, 0, 0, 0, 0xD84F, 0x685E, 0xD850, - 0x7B28, 0x4D55, 0xF647, 0, 0, 0xD853, 0x4E2A, 0xF648, - 0, 0xF649, 0xF64A, 0, 0, 0, 0xD857, 0x4378, - 0xD858, 0xF64B, 0xF64C, 0x336B, 0xF64D, 0, 0, 0x7B29, - 0xD85C, 0x4972, 0x6864, 0x4621, 0xD85D, 0xF64F, 0x3031, 0xD85F, - 0, 0x685D, 0xD860, 0x6859, 0x4172, 0x6853, 0x685B, 0x6860, - 0x7B2A, 0x472C, 0, 0x7B2B, 0xD863, 0x302A, 0xF650, 0x6858, - 0xF651, 0x6861, 0x4978, 0, 0xF652, 0xD867, 0, 0, -}; -static const unsigned short utf8_to_euc_E892[] = { - 0, 0xD868, 0x685C, 0, 0x6857, 0xD869, 0, 0, - 0, 0, 0, 0x3E55, 0, 0, 0, 0, - 0x3D2F, 0, 0xD86A, 0xD86B, 0x3C2C, 0xD86C, 0, 0, - 0, 0x4C58, 0, 0, 0x4947, 0, 0xD86D, 0x6867, - 0, 0x6870, 0, 0, 0, 0, 0xD86E, 0, - 0xD86F, 0xD870, 0xD871, 0, 0, 0x685A, 0, 0xD872, - 0, 0xD873, 0x3377, 0, 0xD874, 0, 0, 0, - 0x3E78, 0x6865, 0xD875, 0x686A, 0x4173, 0xD876, 0xD877, 0x6866, -}; -static const unsigned short utf8_to_euc_E892_x0213[] = { - 0, 0xF653, 0x685C, 0, 0x6857, 0x7B2C, 0, 0, - 0, 0, 0, 0x3E55, 0, 0, 0, 0, - 0x3D2F, 0, 0xD86A, 0xD86B, 0x3C2C, 0xD86C, 0, 0xF656, - 0, 0x4C58, 0, 0, 0x4947, 0, 0x7B2D, 0x6867, - 0, 0x6870, 0, 0, 0, 0, 0xF657, 0, - 0xD86F, 0xD870, 0xD871, 0, 0, 0x685A, 0, 0x7B2E, - 0, 0xD873, 0x3377, 0, 0x7B2F, 0, 0, 0, - 0x3E78, 0x6865, 0x7B30, 0x686A, 0x4173, 0xD876, 0xF658, 0x6866, -}; -static const unsigned short utf8_to_euc_E893[] = { - 0xD878, 0x686D, 0xD879, 0, 0x435F, 0, 0x686E, 0xD87A, - 0xD87B, 0x4D56, 0x6863, 0x3338, 0xD87C, 0x6869, 0, 0xD87D, - 0x686C, 0x4C2C, 0, 0xD87E, 0, 0, 0x686F, 0, - 0, 0x6868, 0x686B, 0, 0xD921, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0xD922, - 0, 0, 0xD923, 0, 0x4B29, 0, 0x4F21, 0xD924, - 0xD925, 0xD926, 0xD927, 0, 0x6873, 0, 0, 0xD928, - 0, 0, 0xD92A, 0xD92B, 0x687A, 0xD92C, 0, 0x6872, -}; -static const unsigned short utf8_to_euc_E893_x0213[] = { - 0x7B31, 0x686D, 0x7B32, 0, 0x435F, 0, 0x686E, 0xD87A, - 0xD87B, 0x4D56, 0x6863, 0x3338, 0xD87C, 0x6869, 0xF65A, 0xF65B, - 0x686C, 0x4C2C, 0, 0xF65C, 0, 0, 0x686F, 0, - 0, 0x6868, 0x686B, 0, 0xF655, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0xF65E, - 0, 0, 0xF65F, 0, 0x4B29, 0, 0x4F21, 0xF660, - 0xF661, 0xF662, 0xD927, 0, 0x6873, 0, 0, 0xD928, - 0, 0, 0xF663, 0xD92B, 0x687A, 0xF664, 0, 0x6872, -}; -static const unsigned short utf8_to_euc_E894[] = { - 0x3C43, 0, 0xD92D, 0xD92E, 0, 0, 0x6851, 0xD92F, - 0, 0, 0, 0, 0xD930, 0, 0xD931, 0, - 0xD932, 0x4A4E, 0, 0x4C22, 0x6879, 0x6878, 0, 0x6874, - 0x6875, 0, 0x3136, 0, 0xD933, 0, 0xD934, 0x6877, - 0, 0x6871, 0xD935, 0xD936, 0xD937, 0xD938, 0x4455, 0xD939, - 0, 0, 0xD93A, 0xD93B, 0x6876, 0x307E, 0, 0xD93C, - 0, 0, 0xD929, 0xD93D, 0xD93E, 0x4222, 0xD93F, 0, - 0, 0, 0, 0, 0, 0x4A43, 0, 0xD940, -}; -static const unsigned short utf8_to_euc_E894_x0213[] = { - 0x3C43, 0, 0xD92D, 0xD92E, 0, 0, 0x6851, 0xD92F, - 0, 0, 0, 0, 0xF665, 0, 0xD931, 0, - 0xD932, 0x4A4E, 0, 0x4C22, 0x6879, 0x6878, 0, 0x6874, - 0x6875, 0, 0x3136, 0xF666, 0xD933, 0, 0x7B35, 0x6877, - 0, 0x6871, 0xD935, 0x7B36, 0xF667, 0xF668, 0x4455, 0xD939, - 0, 0, 0xD93A, 0xF669, 0x6876, 0x307E, 0, 0x7B37, - 0, 0, 0x7B34, 0xD93D, 0xF66A, 0x4222, 0xD93F, 0, - 0, 0, 0, 0, 0, 0x4A43, 0xF66F, 0xD940, -}; -static const unsigned short utf8_to_euc_E895[] = { - 0x687B, 0x6921, 0, 0x4859, 0, 0, 0xD941, 0, - 0x687E, 0x3E56, 0x3C49, 0x6923, 0, 0, 0x363E, 0xD942, - 0xD943, 0xD944, 0xD945, 0xD946, 0, 0x6924, 0xD947, 0x4979, - 0x687D, 0xD948, 0x6856, 0, 0xD949, 0xD94A, 0xD94B, 0xD94C, - 0xD94D, 0xD94E, 0xD94F, 0x687C, 0xD950, 0, 0, 0, - 0x4F4F, 0x4622, 0x4973, 0xD951, 0, 0x692B, 0, 0xD952, - 0, 0, 0, 0, 0, 0, 0, 0x6931, - 0, 0xD953, 0xD954, 0xD955, 0, 0xD956, 0x6932, 0xD957, -}; -static const unsigned short utf8_to_euc_E895_x0213[] = { - 0x687B, 0x6921, 0, 0x4859, 0, 0, 0xD941, 0, - 0x687E, 0x3E56, 0x3C49, 0x6923, 0, 0, 0x363E, 0xF66B, - 0xD943, 0xF670, 0xD945, 0xF671, 0, 0x6924, 0xD947, 0x4979, - 0x687D, 0x7B38, 0x6856, 0, 0xD949, 0xD94A, 0xF672, 0xD94C, - 0xD94D, 0xF673, 0xF674, 0x687C, 0x7B39, 0, 0, 0, - 0x4F4F, 0x4622, 0x4973, 0, 0, 0x692B, 0, 0xF66C, - 0, 0, 0, 0, 0, 0, 0, 0x6931, - 0, 0xD953, 0x7B3C, 0xF676, 0, 0xF677, 0x6932, 0xF678, -}; -static const unsigned short utf8_to_euc_E896[] = { - 0x6925, 0xD958, 0, 0, 0x4776, 0xD959, 0xD95A, 0x692F, - 0x6927, 0xD95B, 0x6929, 0xD95C, 0xD95D, 0, 0, 0xD95E, - 0x6933, 0x6928, 0, 0xD95F, 0x692C, 0, 0, 0x3172, - 0xD960, 0x4665, 0, 0x692D, 0x6930, 0xD961, 0, 0xD962, - 0xD963, 0, 0xD964, 0, 0x6926, 0xD965, 0x4126, 0xD966, - 0x692A, 0x3B27, 0x3F45, 0x3730, 0x4C74, 0xD974, 0x4C79, 0x3D72, - 0xF461, 0, 0, 0, 0xD967, 0, 0xD968, 0xD969, - 0xD96A, 0x6937, 0x6935, 0, 0xD96B, 0xD96C, 0xD96D, 0xD96E, -}; -static const unsigned short utf8_to_euc_E896_x0213[] = { - 0x6925, 0xF679, 0, 0, 0x4776, 0xD959, 0xF67A, 0x692F, - 0x6927, 0xD95B, 0x6929, 0xD95C, 0x7B3D, 0, 0, 0x7B3E, - 0x6933, 0x6928, 0, 0xF67B, 0x692C, 0, 0, 0x3172, - 0xD960, 0x4665, 0, 0x692D, 0x6930, 0xF67C, 0, 0xF67D, - 0xD963, 0, 0x7B3F, 0, 0x6926, 0xD965, 0x4126, 0xD966, - 0x692A, 0x3B27, 0x3F45, 0x3730, 0x4C74, 0x7B3B, 0x4C79, 0x3D72, - 0x7B40, 0, 0, 0, 0xD967, 0, 0xD968, 0xF723, - 0xD96A, 0x6937, 0x6935, 0, 0xF724, 0xD96C, 0xD96D, 0xD96E, -}; -static const unsigned short utf8_to_euc_E897[] = { - 0, 0x4F4E, 0xD96F, 0, 0, 0, 0, 0xD970, - 0, 0x6934, 0xD971, 0xD972, 0, 0x4D75, 0xD973, 0x6936, - 0x6938, 0, 0, 0, 0, 0x6939, 0, 0, - 0xD975, 0, 0xD976, 0, 0x693C, 0x693A, 0, 0xD977, - 0xD978, 0, 0, 0, 0x4623, 0x693B, 0xD979, 0, - 0xD97A, 0x484D, 0x692E, 0, 0, 0xD97B, 0, 0, - 0, 0, 0, 0xD97C, 0, 0, 0xD97D, 0x3D73, - 0, 0x693D, 0x6942, 0x4174, 0xD97E, 0, 0x6941, 0xDA21, -}; -static const unsigned short utf8_to_euc_E897_x0213[] = { - 0, 0x4F4E, 0xD96F, 0, 0, 0, 0, 0xF725, - 0, 0x6934, 0xF726, 0x7B41, 0, 0x4D75, 0x7B42, 0x6936, - 0x6938, 0, 0, 0, 0, 0x6939, 0, 0, - 0xF727, 0xF728, 0xD976, 0, 0x693C, 0x693A, 0, 0xF729, - 0xD978, 0xF72A, 0, 0, 0x4623, 0x693B, 0xF72B, 0, - 0xD97A, 0x484D, 0x692E, 0, 0, 0x7B43, 0, 0, - 0, 0, 0, 0xD97C, 0, 0, 0xF72C, 0x3D73, - 0, 0x693D, 0x6942, 0x4174, 0xD97E, 0, 0x6941, 0x7B45, -}; -static const unsigned short utf8_to_euc_E898[] = { - 0xDA22, 0, 0x6922, 0, 0xDA23, 0xDA24, 0x6943, 0x4149, - 0, 0, 0x693E, 0x6940, 0, 0xDA25, 0xDA26, 0, - 0xDA27, 0xDA28, 0xDA29, 0x693F, 0, 0, 0x5D31, 0x5D22, - 0xDA2A, 0xDA2B, 0x6945, 0xDA2C, 0, 0, 0xDA2D, 0, - 0, 0xDA2E, 0x6944, 0, 0, 0, 0, 0xDA2F, - 0, 0xDA30, 0, 0, 0, 0x4D76, 0, 0x623C, - 0x6946, 0, 0, 0, 0, 0, 0xDA31, 0, - 0xDA32, 0, 0xDA33, 0, 0xDA34, 0xDA35, 0, 0x6947, -}; -static const unsigned short utf8_to_euc_E898_x0213[] = { - 0xF72D, 0, 0x6922, 0, 0x7B46, 0x7B47, 0x6943, 0x4149, - 0, 0, 0x693E, 0x6940, 0, 0xDA25, 0xDA26, 0, - 0x7B48, 0xF72E, 0x7B44, 0x693F, 0, 0, 0x5D31, 0x5D22, - 0x7B4A, 0xDA2B, 0x6945, 0xDA2C, 0, 0, 0xF72F, 0, - 0, 0xF730, 0x6944, 0, 0xF731, 0, 0, 0xF732, - 0, 0x7B4B, 0, 0, 0, 0x4D76, 0, 0x623C, - 0x6946, 0, 0, 0, 0, 0, 0xDA31, 0, - 0x7B4C, 0xF734, 0xDA33, 0, 0xF735, 0xDA35, 0, 0x6947, -}; -static const unsigned short utf8_to_euc_E899[] = { - 0xDA36, 0xB866, 0xDA37, 0, 0, 0, 0xDA38, 0, - 0, 0, 0, 0, 0, 0x6948, 0x3857, 0, - 0x3554, 0, 0xDA39, 0xDA3A, 0x694A, 0x515D, 0xDA3B, 0xDA3C, - 0xDA3D, 0xDA3E, 0x3575, 0, 0x4E3A, 0xDA3F, 0x3673, 0x694B, - 0xDA40, 0xDA41, 0xDA42, 0xDA43, 0xDA44, 0, 0, 0x694C, - 0, 0xDA45, 0, 0x436E, 0xDA46, 0, 0, 0xDA47, - 0, 0x694D, 0, 0, 0, 0xDA48, 0xDA49, 0xDA4A, - 0, 0x467A, 0xDA4B, 0x303A, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E899_x0213[] = { - 0xF737, 0x2F68, 0xDA37, 0, 0, 0, 0xDA38, 0, - 0, 0, 0, 0, 0, 0x6948, 0x3857, 0, - 0x3554, 0, 0xDA39, 0xF739, 0x694A, 0x515D, 0xF73A, 0x7B4D, - 0xDA3D, 0xDA3E, 0x3575, 0x7B4E, 0x4E3A, 0xDA3F, 0x3673, 0x694B, - 0xDA40, 0xDA41, 0x7B50, 0xDA43, 0xDA44, 0, 0, 0x694C, - 0, 0xDA45, 0, 0x436E, 0x7B52, 0, 0, 0xF73B, - 0, 0x694D, 0, 0, 0, 0x7B53, 0xDA49, 0xF73C, - 0, 0x467A, 0xF73D, 0x303A, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E89A[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0xDA6D, 0, 0x3263, 0x6952, 0x6953, 0xDA4C, 0, 0, - 0, 0xDA4D, 0, 0x694E, 0, 0x3B3D, 0xDA4E, 0, - 0xDA4F, 0, 0xDA50, 0, 0xDA51, 0, 0, 0, - 0, 0xDA52, 0, 0x694F, 0x4742, 0, 0xDA53, 0xDA54, - 0xDA55, 0x6950, 0x6951, 0x695B, 0, 0xDA56, 0, 0x6955, - 0x6958, 0xDA57, 0, 0xDA58, 0xDA59, 0xDA5A, 0x6954, 0xDA5B, - 0xDA5C, 0xDA5D, 0, 0, 0, 0, 0, 0xDA5E, -}; -static const unsigned short utf8_to_euc_E89A_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0xF73E, - 0xDA6D, 0xF73F, 0x3263, 0x6952, 0x6953, 0xF740, 0, 0, - 0, 0xF741, 0, 0x694E, 0, 0x3B3D, 0xDA4E, 0, - 0x7B54, 0, 0xDA50, 0, 0xF742, 0xF743, 0, 0, - 0, 0xDA52, 0, 0x694F, 0x4742, 0, 0xDA53, 0xDA54, - 0xF744, 0x6950, 0x6951, 0x695B, 0, 0xDA56, 0, 0x6955, - 0x6958, 0xF746, 0, 0xF747, 0xDA59, 0xDA5A, 0x6954, 0xDA5B, - 0x7B55, 0xDA5D, 0, 0, 0, 0, 0, 0xDA5E, -}; -static const unsigned short utf8_to_euc_E89B[] = { - 0xDA5F, 0xDA60, 0, 0xDA61, 0x6956, 0xDA62, 0x6957, 0x3C58, - 0, 0x6959, 0, 0x4341, 0, 0x3756, 0x3342, 0, - 0, 0xDA63, 0xDA64, 0, 0x695C, 0xDA65, 0, 0xDA66, - 0, 0x333F, 0xDA67, 0x6961, 0xDA68, 0, 0x695D, 0x6960, - 0xDA69, 0, 0, 0xDA6A, 0x483A, 0xDA6B, 0, 0xDA6C, - 0, 0x695E, 0, 0, 0x695F, 0x4948, 0x485A, 0x6962, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x427D, 0x696C, 0xDA6E, 0x6968, 0xDA6F, 0xDA70, 0x326B, 0, -}; -static const unsigned short utf8_to_euc_E89B_x0213[] = { - 0xDA5F, 0xF748, 0, 0xF749, 0x6956, 0xDA62, 0x6957, 0x3C58, - 0, 0x6959, 0, 0x4341, 0, 0x3756, 0x3342, 0, - 0, 0xF74A, 0xDA64, 0, 0x695C, 0xF74B, 0, 0xF74C, - 0, 0x333F, 0xDA67, 0x6961, 0xDA68, 0, 0x695D, 0x6960, - 0xDA69, 0, 0, 0xF74D, 0x483A, 0xDA6B, 0xF74E, 0xDA6C, - 0, 0x695E, 0, 0, 0x695F, 0x4948, 0x485A, 0x6962, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x427D, 0x696C, 0x7B56, 0x6968, 0x7B57, 0x7B58, 0x326B, 0, -}; -static const unsigned short utf8_to_euc_E89C[] = { - 0x6966, 0, 0x4B2A, 0x6967, 0xDA71, 0xDA72, 0x6964, 0xDA73, - 0x6965, 0x696A, 0x696D, 0xDA74, 0, 0x696B, 0xDA75, 0xDA76, - 0xDA77, 0x6969, 0x6963, 0xDA78, 0xDA79, 0, 0, 0, - 0x4358, 0xDA7A, 0x6974, 0, 0x4C2A, 0, 0xDA7B, 0xDA7C, - 0, 0xDA7D, 0, 0xDA7E, 0, 0x6972, 0, 0, - 0xDB21, 0x6973, 0, 0, 0, 0, 0xDB22, 0xDB23, - 0, 0xDB24, 0xDB25, 0, 0x696E, 0, 0, 0x6970, - 0, 0xDB26, 0xDB27, 0x6971, 0xDB28, 0xDB29, 0xDB2A, 0x696F, -}; -static const unsigned short utf8_to_euc_E89C_x0213[] = { - 0x6966, 0, 0x4B2A, 0x6967, 0xDA71, 0xF750, 0x6964, 0xF751, - 0x6965, 0x696A, 0x696D, 0x7B59, 0, 0x696B, 0xF752, 0xDA76, - 0xF753, 0x6969, 0x6963, 0xF754, 0xDA79, 0, 0, 0, - 0x4358, 0xF755, 0x6974, 0, 0x4C2A, 0, 0xDA7B, 0xF756, - 0, 0xF757, 0, 0xF758, 0, 0x6972, 0, 0, - 0xDB21, 0x6973, 0, 0, 0, 0, 0xDB22, 0xDB23, - 0, 0xF759, 0xDB25, 0, 0x696E, 0, 0, 0x6970, - 0, 0xDB26, 0xF75A, 0x6971, 0xDB28, 0xDB29, 0xF75B, 0x696F, -}; -static const unsigned short utf8_to_euc_E89D[] = { - 0xDB2B, 0, 0, 0xDB2C, 0, 0xDB2D, 0, 0, - 0, 0x4066, 0, 0x4F39, 0x6978, 0xDB2E, 0x6979, 0, - 0, 0, 0, 0x6A21, 0, 0x3F2A, 0, 0x697B, - 0xDB2F, 0x697E, 0, 0, 0, 0xDB30, 0, 0x6976, - 0x6975, 0xDB31, 0, 0x6A22, 0xDB32, 0xDB33, 0x325C, 0, - 0x697C, 0, 0x6A23, 0, 0, 0, 0x697D, 0xDB34, - 0, 0xDB35, 0xDB36, 0, 0x697A, 0, 0x4433, 0, - 0x6977, 0, 0, 0xDB37, 0, 0, 0, 0x4768, -}; -static const unsigned short utf8_to_euc_E89D_x0213[] = { - 0xF75C, 0, 0, 0xF75D, 0, 0xDB2D, 0, 0, - 0, 0x4066, 0, 0x4F39, 0x6978, 0xDB2E, 0x6979, 0, - 0, 0xF75E, 0, 0x6A21, 0, 0x3F2A, 0, 0x697B, - 0xF75F, 0x697E, 0, 0, 0, 0xDB30, 0, 0x6976, - 0x6975, 0xDB31, 0, 0x6A22, 0xF760, 0xF761, 0x325C, 0, - 0x697C, 0, 0x6A23, 0, 0, 0, 0x697D, 0xDB34, - 0, 0x7B5A, 0xF762, 0, 0x697A, 0, 0x4433, 0, - 0x6977, 0, 0, 0xDB37, 0xF763, 0, 0, 0x4768, -}; -static const unsigned short utf8_to_euc_E89E[] = { - 0, 0, 0x6A27, 0xDB38, 0xDB39, 0xDB3A, 0xDB3B, 0xDB3C, - 0xDB3D, 0xDB3E, 0, 0xDB3F, 0xDB40, 0x4D3B, 0, 0, - 0xDB41, 0, 0, 0xDB42, 0, 0xDB43, 0, 0xDB44, - 0xDB45, 0xDB46, 0, 0, 0, 0, 0xDB47, 0x6A26, - 0xDB48, 0, 0x6A25, 0xDB49, 0, 0, 0, 0xDB4A, - 0, 0, 0, 0x6A2E, 0xDB4B, 0xDB4C, 0xDB4D, 0x6A28, - 0, 0xDB4E, 0, 0x6A30, 0, 0xDB4F, 0, 0, - 0, 0, 0x4D66, 0x6A33, 0, 0x6A2A, 0xDB50, 0xDB51, -}; -static const unsigned short utf8_to_euc_E89E_x0213[] = { - 0, 0, 0x6A27, 0xDB38, 0xDB39, 0xDB3A, 0xDB3B, 0x7B5B, - 0x7B5C, 0xF767, 0, 0xF768, 0xDB40, 0x4D3B, 0, 0, - 0xDB41, 0, 0, 0xF769, 0, 0xDB43, 0, 0xDB44, - 0xDB45, 0xDB46, 0, 0, 0, 0, 0xDB47, 0x6A26, - 0xF76A, 0, 0x6A25, 0xDB49, 0, 0, 0, 0xF766, - 0, 0, 0, 0x6A2E, 0x7B5D, 0x7B5E, 0xDB4D, 0x6A28, - 0, 0xDB4E, 0, 0x6A30, 0, 0x7B5F, 0, 0, - 0, 0, 0x4D66, 0x6A33, 0, 0x6A2A, 0xF76D, 0xDB51, -}; -static const unsigned short utf8_to_euc_E89F[] = { - 0x6A2B, 0xDB52, 0, 0, 0x6A2F, 0, 0x6A32, 0x6A31, - 0xDB53, 0xDB54, 0xDB55, 0x6A29, 0, 0, 0xDB56, 0, - 0x6A2C, 0, 0x6A3D, 0, 0, 0xDB57, 0xDB58, 0, - 0, 0xDB59, 0xDB5A, 0, 0xDB5B, 0, 0, 0xDB5C, - 0x6A36, 0, 0xDB5D, 0xDB5E, 0xDB5F, 0, 0, 0, - 0, 0, 0xDB60, 0xDB61, 0, 0xDB62, 0, 0x6A34, - 0, 0xDB63, 0x6A35, 0xDB64, 0, 0, 0x6A3A, 0x6A3B, - 0xDB65, 0x332A, 0xDB66, 0x3542, 0, 0, 0x6A39, 0xDB67, -}; -static const unsigned short utf8_to_euc_E89F_x0213[] = { - 0x6A2B, 0xF76F, 0, 0, 0x6A2F, 0, 0x6A32, 0x6A31, - 0xDB53, 0xDB54, 0xDB55, 0x6A29, 0, 0, 0xF770, 0, - 0x6A2C, 0, 0x6A3D, 0, 0, 0xDB57, 0x7B61, 0, - 0, 0xDB59, 0xDB5A, 0, 0xDB5B, 0, 0, 0xF772, - 0x6A36, 0, 0xDB5D, 0xF774, 0xDB5F, 0xF775, 0xF776, 0, - 0, 0, 0xF777, 0xF778, 0x7B62, 0xF779, 0, 0x6A34, - 0, 0xDB63, 0x6A35, 0xDB64, 0, 0xF771, 0x6A3A, 0x6A3B, - 0xDB65, 0x332A, 0xDB66, 0x3542, 0, 0, 0x6A39, 0xDB67, -}; -static const unsigned short utf8_to_euc_E8A0[] = { - 0, 0xDB68, 0, 0xDB69, 0, 0x6A24, 0xDB6A, 0xF464, - 0, 0xDB6B, 0xDB6C, 0xDB6D, 0, 0x6A38, 0x6A3C, 0x6A37, - 0xDB6E, 0x6A3E, 0xDB70, 0xDB71, 0xDB72, 0x6A40, 0x6A3F, 0, - 0xDB73, 0xDB6F, 0xDB74, 0xDB75, 0xDB76, 0, 0xDB77, 0xDB78, - 0, 0x6A42, 0x6A41, 0x695A, 0, 0, 0, 0x6A46, - 0xDB79, 0, 0, 0, 0, 0xDB7A, 0xDB7B, 0, - 0xDB7C, 0x6A43, 0xDB7D, 0, 0, 0xDB7E, 0x6A44, 0, - 0, 0x6A45, 0xDC21, 0x6A47, 0xDC22, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E8A0_x0213[] = { - 0, 0xF77A, 0, 0xF77B, 0, 0x6A24, 0x7B63, 0, - 0, 0xDB6B, 0x7B64, 0xF77C, 0, 0x6A38, 0x6A3C, 0x6A37, - 0x7B65, 0x6A3E, 0xDB70, 0xF77D, 0x7B66, 0x6A40, 0x6A3F, 0, - 0xDB73, 0xDB6F, 0xDB74, 0xDB75, 0xDB76, 0, 0xDB77, 0x7B67, - 0, 0x6A42, 0x6A41, 0x695A, 0, 0, 0, 0x6A46, - 0xF77E, 0, 0, 0, 0, 0xDB7A, 0xF821, 0, - 0xDB7C, 0x6A43, 0xF822, 0, 0, 0xDB7E, 0x6A44, 0, - 0, 0x6A45, 0xDC21, 0x6A47, 0xF823, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E8A1[] = { - 0x376C, 0xDC23, 0x6A49, 0xDC24, 0x6A48, 0xDC25, 0x3D30, 0, - 0xDC26, 0xDC27, 0xDC28, 0xDC29, 0x3954, 0x5E27, 0xDC2A, 0, - 0, 0xDC2B, 0x6A4A, 0x3D51, 0, 0xDC2C, 0xDC2D, 0x3339, - 0xDC2E, 0x6A4B, 0xDC2F, 0x3152, 0xDC30, 0x3E57, 0x6A4C, 0xDC31, - 0xDC32, 0x3955, 0x6A4D, 0x3061, 0xDC33, 0, 0, 0, - 0x493D, 0xDC34, 0, 0x6A4E, 0, 0, 0, 0, - 0x3F6A, 0xDC35, 0x6A55, 0, 0, 0x6A52, 0, 0x436F, - 0, 0xDC36, 0, 0xDC37, 0, 0x6A53, 0x6A50, 0x365E, -}; -static const unsigned short utf8_to_euc_E8A1_x0213[] = { - 0x376C, 0xDC23, 0x6A49, 0xDC24, 0x6A48, 0xDC25, 0x3D30, 0, - 0xDC26, 0xDC27, 0xF825, 0xDC29, 0x3954, 0x5E27, 0xDC2A, 0, - 0, 0xDC2B, 0x6A4A, 0x3D51, 0, 0xDC2C, 0xDC2D, 0x3339, - 0xF826, 0x6A4B, 0xDC2F, 0x3152, 0xDC30, 0x3E57, 0x6A4C, 0xF827, - 0xDC32, 0x3955, 0x6A4D, 0x3061, 0xF828, 0, 0, 0, - 0x493D, 0xF82B, 0, 0x6A4E, 0, 0, 0, 0xF82D, - 0x3F6A, 0xDC35, 0x6A55, 0, 0, 0x6A52, 0, 0x436F, - 0, 0xDC36, 0, 0xDC37, 0, 0x6A53, 0x6A50, 0x365E, -}; -static const unsigned short utf8_to_euc_E8A2[] = { - 0xDC38, 0x6A4F, 0x6A56, 0, 0, 0, 0, 0, - 0x3736, 0, 0, 0x425E, 0, 0x6A5C, 0, 0, - 0, 0, 0x6A58, 0, 0, 0, 0x4235, 0x6A57, - 0xDC39, 0x6A5A, 0xDC3A, 0xDC3B, 0xDC3C, 0, 0x6A51, 0xDC3D, - 0xDC3E, 0, 0x6A5B, 0, 0x6A5D, 0, 0, 0, - 0xDC3F, 0, 0xDC40, 0x486F, 0, 0, 0x6A59, 0, - 0x6A5E, 0x6A60, 0, 0, 0x3853, 0x6A54, 0, 0x3041, - 0, 0, 0xDC41, 0, 0, 0xDC42, 0xDC43, 0x6A5F, -}; -static const unsigned short utf8_to_euc_E8A2_x0213[] = { - 0xDC38, 0x6A4F, 0x6A56, 0, 0, 0, 0, 0, - 0x3736, 0, 0, 0x425E, 0, 0x6A5C, 0, 0, - 0, 0, 0x6A58, 0, 0, 0, 0x4235, 0x6A57, - 0x7B68, 0x6A5A, 0xDC3A, 0xDC3B, 0xDC3C, 0, 0x6A51, 0xDC3D, - 0xF82E, 0, 0x6A5B, 0, 0x6A5D, 0, 0, 0, - 0xDC3F, 0, 0x7B69, 0x486F, 0, 0, 0x6A59, 0, - 0x6A5E, 0x6A60, 0, 0, 0x3853, 0x6A54, 0, 0x3041, - 0, 0, 0xDC41, 0, 0xF82F, 0xF830, 0xF831, 0x6A5F, -}; -static const unsigned short utf8_to_euc_E8A3[] = { - 0xDC44, 0x3A5B, 0x4E76, 0x6A61, 0x6A62, 0x4175, 0, 0, - 0, 0, 0xDC45, 0xDC46, 0xDC47, 0xDC48, 0xDC49, 0x4E22, - 0, 0xDC4A, 0xDC4B, 0xDC4C, 0x6A63, 0x4D35, 0, 0, - 0x6A64, 0x6A65, 0, 0xDC4D, 0x4A64, 0x6A66, 0xDC4E, 0x3A40, - 0, 0x4E23, 0, 0, 0, 0, 0, 0xDC4F, - 0x6A6B, 0, 0, 0, 0, 0, 0, 0xDC50, - 0xDC51, 0xDC52, 0x6A6C, 0x3E58, 0x6A6A, 0xDC53, 0, 0xDC54, - 0x4D67, 0x6A67, 0, 0, 0x6A69, 0x403D, 0x3F7E, 0, -}; -static const unsigned short utf8_to_euc_E8A3_x0213[] = { - 0xF832, 0x3A5B, 0x4E76, 0x6A61, 0x6A62, 0x4175, 0, 0, - 0, 0, 0x7B6A, 0xDC46, 0xDC47, 0xDC48, 0x7B6B, 0x4E22, - 0, 0xF835, 0xF833, 0xF836, 0x6A63, 0x4D35, 0, 0, - 0x6A64, 0x6A65, 0, 0xF837, 0x4A64, 0x6A66, 0xDC4E, 0x3A40, - 0, 0x4E23, 0, 0, 0, 0, 0, 0xDC4F, - 0x6A6B, 0, 0, 0, 0, 0, 0, 0xDC50, - 0xF838, 0xF839, 0x6A6C, 0x3E58, 0x6A6A, 0x7B6D, 0, 0xDC54, - 0x4D67, 0x6A67, 0, 0, 0x6A69, 0x403D, 0x3F7E, 0, -}; -static const unsigned short utf8_to_euc_E8A4[] = { - 0, 0xDC55, 0x6A68, 0, 0x6A6D, 0, 0xDC56, 0x4A23, - 0, 0, 0x6A6F, 0, 0x6A6E, 0xDC57, 0xDC58, 0xDC59, - 0x336C, 0, 0x4B2B, 0x6A70, 0, 0xDC5A, 0xDC5B, 0, - 0xDC5C, 0xDC5D, 0xDC5E, 0, 0xDC5F, 0x6A7C, 0x6A72, 0, - 0xDC60, 0, 0, 0, 0, 0x6A73, 0xDC61, 0xDC62, - 0xDC63, 0, 0x6A74, 0x6A75, 0, 0, 0, 0, - 0xDC64, 0xDC65, 0xDC66, 0, 0, 0xDC67, 0x6A79, 0, - 0x6A7A, 0xDC68, 0xDC69, 0x6A78, 0, 0, 0xDC6A, 0, -}; -static const unsigned short utf8_to_euc_E8A4_x0213[] = { - 0, 0xF83B, 0x6A68, 0, 0x6A6D, 0, 0xDC56, 0x4A23, - 0, 0, 0x6A6F, 0, 0x6A6E, 0xDC57, 0xDC58, 0xDC59, - 0x336C, 0, 0x4B2B, 0x6A70, 0, 0xDC5A, 0xDC5B, 0, - 0x7B70, 0x7B71, 0x7B72, 0, 0x7B6E, 0x6A7C, 0x6A72, 0, - 0xDC60, 0, 0, 0, 0, 0x6A73, 0xDC61, 0x7B73, - 0xDC63, 0, 0x6A74, 0x6A75, 0, 0, 0, 0, - 0x7B74, 0xDC65, 0x7B75, 0, 0, 0xDC67, 0x6A79, 0xF83D, - 0x6A7A, 0x7B76, 0xDC69, 0x6A78, 0, 0, 0xDC6A, 0, -}; -static const unsigned short utf8_to_euc_E8A5[] = { - 0xDC6B, 0x6A76, 0xDC6C, 0x6A71, 0x6A77, 0xDC6D, 0xDC6E, 0, - 0, 0xDC6F, 0, 0, 0x6A7B, 0x7037, 0, 0xDC70, - 0, 0, 0xDC71, 0, 0, 0, 0x3228, 0xDC72, - 0, 0, 0xDC73, 0xDC74, 0xDC75, 0, 0x6A7E, 0x365F, - 0x6A7D, 0xDC76, 0xDC77, 0xDC78, 0x6B22, 0, 0x6B21, 0, - 0, 0, 0x6B24, 0xDC79, 0, 0x6B23, 0xDC7A, 0x6B25, - 0xDC7B, 0, 0x3D31, 0xDC7C, 0x6B26, 0xDC7D, 0, 0x6B27, - 0, 0, 0xDC7E, 0xDD21, 0xDD22, 0xDD23, 0x6B28, 0x403E, -}; -static const unsigned short utf8_to_euc_E8A5_x0213[] = { - 0x7B77, 0x6A76, 0xF83F, 0x6A71, 0x6A77, 0xF840, 0xDC6E, 0, - 0, 0xF841, 0, 0, 0x6A7B, 0x7037, 0, 0xDC70, - 0, 0, 0xDC71, 0, 0, 0, 0x3228, 0xDC72, - 0, 0, 0xDC73, 0xDC74, 0xDC75, 0, 0x6A7E, 0x365F, - 0x6A7D, 0xDC76, 0xF844, 0xDC78, 0x6B22, 0, 0x6B21, 0, - 0, 0, 0x6B24, 0xDC79, 0, 0x6B23, 0xDC7A, 0x6B25, - 0xDC7B, 0, 0x3D31, 0xDC7C, 0x6B26, 0xDC7D, 0, 0x6B27, - 0, 0, 0xDC7E, 0xDD21, 0xDD22, 0xDD23, 0x6B28, 0x403E, -}; -static const unsigned short utf8_to_euc_E8A6[] = { - 0, 0x4D57, 0, 0x6B29, 0, 0, 0x4A24, 0x4746, - 0x6B2A, 0xDD24, 0x6B2B, 0x382B, 0, 0xDD25, 0, 0x352C, - 0xDD26, 0, 0, 0x6B2C, 0xDD27, 0xDD28, 0x3B6B, 0x4741, - 0x6B2D, 0, 0x3350, 0xDD29, 0xDD2A, 0, 0, 0xDD2B, - 0xDD2C, 0x6B2E, 0, 0, 0, 0xDD2D, 0x6B30, 0x4D77, - 0, 0x6B2F, 0x3F46, 0, 0x6B31, 0, 0, 0x6B32, - 0xDD2E, 0, 0x6B33, 0x3451, 0xDD2F, 0xDD30, 0xDD31, 0xDD32, - 0, 0, 0x6B34, 0, 0xDD33, 0x6B35, 0, 0x6B36, -}; -static const unsigned short utf8_to_euc_E8A6_x0213[] = { - 0xF845, 0x4D57, 0, 0x6B29, 0, 0, 0x4A24, 0x4746, - 0x6B2A, 0xF846, 0x6B2B, 0x382B, 0, 0xDD25, 0, 0x352C, - 0xF847, 0, 0, 0x6B2C, 0x7B78, 0xDD28, 0x3B6B, 0x4741, - 0x6B2D, 0, 0x3350, 0xDD29, 0xDD2A, 0, 0, 0xF848, - 0xDD2C, 0x6B2E, 0, 0, 0, 0xDD2D, 0x6B30, 0x4D77, - 0, 0x6B2F, 0x3F46, 0, 0x6B31, 0, 0, 0x6B32, - 0xF849, 0, 0x6B33, 0x3451, 0xDD2F, 0xDD30, 0xDD31, 0xF84A, - 0, 0, 0x6B34, 0, 0xDD33, 0x6B35, 0, 0x6B36, -}; -static const unsigned short utf8_to_euc_E8A7[] = { - 0x6B37, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0x3351, 0, 0xDD34, 0xDD35, 0xDD36, 0xDD37, - 0xDD38, 0, 0x6B38, 0, 0x6B39, 0x6B3A, 0, 0, - 0, 0, 0, 0x3272, 0, 0xDD39, 0x3F28, 0x6B3B, - 0, 0xDD3A, 0, 0xDD3B, 0, 0xDD3C, 0, 0, - 0, 0xDD3D, 0, 0xDD3E, 0x6B3C, 0, 0xDD3F, 0, - 0x6B3D, 0xDD40, 0, 0, 0, 0xDD41, 0, 0xDD42, -}; -static const unsigned short utf8_to_euc_E8A7_x0213[] = { - 0x6B37, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0x3351, 0, 0x7B7A, 0xDD35, 0xF84B, 0xDD37, - 0xF84C, 0, 0x6B38, 0, 0x6B39, 0x6B3A, 0, 0, - 0, 0, 0, 0x3272, 0, 0x7B7B, 0x3F28, 0x6B3B, - 0, 0xDD3A, 0, 0xF84D, 0, 0xDD3C, 0, 0, - 0, 0xF84F, 0, 0xF850, 0x6B3C, 0, 0x7B7C, 0, - 0x6B3D, 0xDD40, 0, 0, 0, 0xF851, 0, 0xF852, -}; -static const unsigned short utf8_to_euc_E8A8[] = { - 0x3840, 0, 0x447B, 0x6B3E, 0xDD43, 0xDD44, 0, 0xDD45, - 0x3757, 0, 0x3F56, 0, 0x6B41, 0, 0x4624, 0xDD46, - 0x6B40, 0xDD47, 0xDD48, 0x3731, 0xDD49, 0xDD4A, 0x6B3F, 0x4277, - 0x352D, 0, 0, 0x6B42, 0, 0x6B43, 0xDD4B, 0x3E59, - 0xDD4C, 0, 0xDD4D, 0x376D, 0xDD4E, 0x6B44, 0xDD4F, 0, - 0, 0, 0x4B2C, 0xDD50, 0xDD51, 0x405F, 0, 0xDD52, - 0, 0x3576, 0, 0x4C75, 0x414A, 0xDD53, 0x6B45, 0xDD54, - 0, 0, 0x3F47, 0x4370, 0x3E5A, 0xDD55, 0xDD56, 0, -}; -static const unsigned short utf8_to_euc_E8A8_x0213[] = { - 0x3840, 0, 0x447B, 0x6B3E, 0xDD43, 0xDD44, 0, 0xDD45, - 0x3757, 0, 0x3F56, 0, 0x6B41, 0, 0x4624, 0xDD46, - 0x6B40, 0xF854, 0x7B7D, 0x3731, 0xF855, 0x7B7E, 0x6B3F, 0x4277, - 0x352D, 0, 0, 0x6B42, 0, 0x6B43, 0xDD4B, 0x3E59, - 0xDD4C, 0xF857, 0x7C21, 0x376D, 0xDD4E, 0x6B44, 0xDD4F, 0, - 0, 0, 0x4B2C, 0xDD50, 0xDD51, 0x405F, 0, 0xDD52, - 0, 0x3576, 0, 0x4C75, 0x414A, 0xF858, 0x6B45, 0x7C22, - 0, 0, 0x3F47, 0x4370, 0x3E5A, 0xDD55, 0xF859, 0, -}; -static const unsigned short utf8_to_euc_E8A9[] = { - 0xDD57, 0x6B46, 0, 0xDD58, 0, 0xDD59, 0x6B49, 0xDD5A, - 0x6B4A, 0xDD5B, 0, 0, 0, 0xDD5C, 0xDD5D, 0, - 0x3A3E, 0x4242, 0x6B48, 0xDD5E, 0x3E5B, 0x493E, 0xDD5F, 0xDD60, - 0xDD61, 0, 0, 0x6B47, 0xDD62, 0xDD63, 0x3B6C, 0, - 0x3153, 0xDD64, 0x6B4E, 0x3758, 0, 0xDD65, 0x3B6E, 0xDD66, - 0, 0x3B6D, 0, 0x4F4D, 0x6B4D, 0x6B4C, 0x4127, 0, - 0x354D, 0x4F43, 0x333A, 0x3E5C, 0, 0xDD67, 0xDD68, 0xDD69, - 0, 0xDD6A, 0xDD6B, 0xDD6C, 0x6B4B, 0, 0xDD6D, 0xDD6E, -}; -static const unsigned short utf8_to_euc_E8A9_x0213[] = { - 0xDD57, 0x6B46, 0, 0xDD58, 0, 0xF85A, 0x6B49, 0x7C23, - 0x6B4A, 0xDD5B, 0, 0, 0, 0xF85B, 0x7C24, 0, - 0x3A3E, 0x4242, 0x6B48, 0xDD5E, 0x3E5B, 0x493E, 0xDD5F, 0xDD60, - 0xF85C, 0, 0, 0x6B47, 0xDD62, 0x7C25, 0x3B6C, 0, - 0x3153, 0x7C26, 0x6B4E, 0x3758, 0, 0xDD65, 0x3B6E, 0xDD66, - 0, 0x3B6D, 0, 0x4F4D, 0x6B4D, 0x6B4C, 0x4127, 0, - 0x354D, 0x4F43, 0x333A, 0x3E5C, 0, 0x7C27, 0xDD68, 0xDD69, - 0, 0x7C28, 0xDD6B, 0xDD6C, 0x6B4B, 0, 0xDD6D, 0xDD6E, -}; -static const unsigned short utf8_to_euc_E8AA[] = { - 0xDD6F, 0, 0x6B50, 0xDD70, 0x6B51, 0x6B4F, 0xDD71, 0x3858, - 0, 0x4D40, 0, 0xDD72, 0x3B6F, 0x4727, 0, 0xDD73, - 0xDD74, 0x6B54, 0xDD75, 0x4040, 0, 0x4342, 0xDD76, 0xDD77, - 0x4D36, 0xDD78, 0x6B57, 0, 0, 0, 0x386C, 0xDD79, - 0x403F, 0x6B53, 0, 0x6B58, 0x386D, 0x6B55, 0x6B56, 0xDD7A, - 0x6B52, 0xDD7B, 0, 0, 0x4062, 0x4649, 0xDD7C, 0xDD7D, - 0x432F, 0, 0x325D, 0xDD7E, 0, 0, 0xDE21, 0xDE22, - 0, 0x4870, 0, 0xDE23, 0x3543, 0, 0xDE24, 0x4434, -}; -static const unsigned short utf8_to_euc_E8AA_x0213[] = { - 0xDD6F, 0, 0x6B50, 0xDD70, 0x6B51, 0x6B4F, 0xDD71, 0x3858, - 0, 0x4D40, 0, 0xDD72, 0x3B6F, 0x4727, 0, 0xDD73, - 0xF85E, 0x6B54, 0xDD75, 0x4040, 0, 0x4342, 0xDD76, 0xDD77, - 0x4D36, 0xDD78, 0x6B57, 0, 0, 0, 0x386C, 0xDD79, - 0x403F, 0x6B53, 0, 0x6B58, 0x386D, 0x6B55, 0x6B56, 0x7C29, - 0x6B52, 0xDD7B, 0, 0, 0x4062, 0x4649, 0xF85D, 0xDD7D, - 0x432F, 0, 0x325D, 0xDD7E, 0, 0, 0xDE21, 0xF85F, - 0, 0x4870, 0, 0xDE23, 0x3543, 0, 0xF860, 0x4434, -}; -static const unsigned short utf8_to_euc_E8AB[] = { - 0, 0, 0x6B5B, 0xDE25, 0x6B59, 0, 0xDE26, 0x434C, - 0xDE27, 0xDE28, 0xDE29, 0x4041, 0x3452, 0x6B5A, 0, 0x3F5B, - 0, 0xDE2A, 0x4E4A, 0xDE2B, 0xDE2C, 0xDE2D, 0x4F40, 0xDE2E, - 0, 0, 0x6B5C, 0x6B67, 0x4435, 0xDE2F, 0x6B66, 0xDE30, - 0x6B63, 0x6B6B, 0x6B64, 0, 0x6B60, 0, 0x447C, 0x6B5F, - 0, 0, 0, 0x6B5D, 0xDE31, 0x4D21, 0x3B70, 0, - 0xDE32, 0x6B61, 0, 0x6B5E, 0xDE33, 0xDE34, 0xDE35, 0x6B65, - 0x3D74, 0, 0x3841, 0, 0xDE36, 0, 0x427A, 0xDE37, -}; -static const unsigned short utf8_to_euc_E8AB_x0213[] = { - 0, 0, 0x6B5B, 0xDE25, 0x6B59, 0, 0xDE26, 0x434C, - 0xDE27, 0xDE28, 0xDE29, 0x4041, 0x3452, 0x6B5A, 0, 0x3F5B, - 0x7C2A, 0xDE2A, 0x4E4A, 0xDE2B, 0xDE2C, 0xDE2D, 0x4F40, 0xF861, - 0, 0, 0x6B5C, 0x6B67, 0x4435, 0xDE2F, 0x6B66, 0x7C2B, - 0x6B63, 0x6B6B, 0x6B64, 0, 0x6B60, 0, 0x447C, 0x6B5F, - 0, 0, 0, 0x6B5D, 0xDE31, 0x4D21, 0x3B70, 0, - 0xDE32, 0x6B61, 0, 0x6B5E, 0x7C2C, 0xDE34, 0x7C2D, 0x6B65, - 0x3D74, 0, 0x3841, 0, 0xF862, 0, 0x427A, 0xDE37, -}; -static const unsigned short utf8_to_euc_E8AC[] = { - 0x4B45, 0x315A, 0x3062, 0, 0x4625, 0xDE38, 0xDE39, 0x6B69, - 0, 0, 0xDE3F, 0xDE3A, 0x6B68, 0, 0x4666, 0, - 0x6B6D, 0xDE3B, 0, 0, 0x6B62, 0, 0x6B6C, 0x6B6E, - 0, 0x382C, 0x6B6A, 0x3956, 0xDE3C, 0x3C55, 0xDE3D, 0xDE3E, - 0x6B6F, 0x4D58, 0, 0, 0, 0, 0x6B72, 0, - 0x6B75, 0, 0, 0x6B73, 0x4935, 0xDE40, 0, 0, - 0xDE41, 0, 0, 0x6B70, 0, 0, 0, 0xDE42, - 0, 0x3660, 0, 0, 0xDE43, 0, 0x6B74, 0, -}; -static const unsigned short utf8_to_euc_E8AC_x0213[] = { - 0x4B45, 0x315A, 0x3062, 0, 0x4625, 0xF865, 0xDE39, 0x6B69, - 0, 0, 0xF864, 0xDE3A, 0x6B68, 0xF866, 0x4666, 0, - 0x6B6D, 0xDE3B, 0, 0, 0x6B62, 0, 0x6B6C, 0x6B6E, - 0, 0x382C, 0x6B6A, 0x3956, 0xF867, 0x3C55, 0xDE3D, 0xF868, - 0x6B6F, 0x4D58, 0, 0, 0, 0, 0x6B72, 0, - 0x6B75, 0, 0, 0x6B73, 0x4935, 0xF869, 0, 0, - 0xDE41, 0, 0, 0x6B70, 0, 0, 0, 0xDE42, - 0, 0x3660, 0, 0, 0xDE43, 0, 0x6B74, 0, -}; -static const unsigned short utf8_to_euc_E8AD[] = { - 0, 0x6B76, 0xDE44, 0xDE45, 0xDE46, 0xDE47, 0xDE48, 0, - 0xDE49, 0x6B7A, 0, 0, 0x6B77, 0xDE4E, 0x6B79, 0x6B78, - 0, 0, 0xDE4A, 0xDE4B, 0xDE4C, 0, 0x6B7B, 0, - 0x3C31, 0xDE4D, 0x6B7D, 0x6B7C, 0x4968, 0, 0xDE4F, 0x6C21, - 0, 0, 0, 0xDE50, 0, 0, 0x3759, 0, - 0, 0, 0, 0x6B7E, 0x6C22, 0xDE51, 0, 0x6C23, - 0x3544, 0x6641, 0x3E79, 0, 0x6C24, 0, 0xDE52, 0x386E, - 0xDE53, 0xDE54, 0, 0, 0xDE55, 0x6C25, 0xDE56, 0xF466, -}; -static const unsigned short utf8_to_euc_E8AD_x0213[] = { - 0, 0x6B76, 0xDE44, 0xF86A, 0xDE46, 0xDE47, 0x7C31, 0, - 0xDE49, 0x6B7A, 0, 0, 0x6B77, 0xDE4E, 0x6B79, 0x6B78, - 0, 0xF86C, 0xDE4A, 0, 0x7C32, 0, 0x6B7B, 0, - 0x3C31, 0x7C33, 0x6B7D, 0x6B7C, 0x4968, 0, 0xF86D, 0x6C21, - 0, 0, 0, 0xDE50, 0, 0, 0x3759, 0, - 0, 0x7C34, 0, 0x6B7E, 0x6C22, 0xDE51, 0, 0x6C23, - 0x3544, 0x6641, 0x3E79, 0, 0x6C24, 0, 0xF86E, 0x386E, - 0xDE53, 0xDE54, 0, 0, 0xDE55, 0x6C25, 0xDE56, 0xF86F, -}; -static const unsigned short utf8_to_euc_E8AE[] = { - 0x6C26, 0xDE57, 0, 0x3B3E, 0xDE58, 0xDE59, 0, 0, - 0, 0, 0x5A4E, 0xDE5A, 0x6C27, 0xDE5B, 0x6C28, 0xDE5C, - 0x3D32, 0, 0x6C29, 0x6C2A, 0xDE5D, 0xDE5E, 0x6C2B, 0, - 0, 0x6C2C, 0x6C2D, 0, 0xDE5F, 0, 0xDE60, 0xDE61, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E8AE_x0213[] = { - 0x6C26, 0xF870, 0, 0x3B3E, 0xDE58, 0xDE59, 0, 0, - 0, 0, 0x5A4E, 0xF871, 0x6C27, 0xDE5B, 0x6C28, 0xDE5C, - 0x3D32, 0, 0x6C29, 0x6C2A, 0xF872, 0xF873, 0x6C2B, 0, - 0, 0x6C2C, 0x6C2D, 0, 0xF874, 0x7C35, 0xF875, 0xDE61, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E8B0[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0x432B, - 0xDE62, 0xDE63, 0x6C2E, 0, 0, 0xDE64, 0xDE65, 0x6C30, -}; -static const unsigned short utf8_to_euc_E8B0_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0x432B, - 0xDE62, 0xF876, 0x6C2E, 0, 0, 0xF878, 0xDE65, 0x6C30, -}; -static const unsigned short utf8_to_euc_E8B1[] = { - 0, 0x6C2F, 0, 0, 0, 0xDE66, 0x4626, 0xDE67, - 0x6C31, 0xDE68, 0x4B2D, 0xDE69, 0x6C32, 0, 0x6C33, 0xDE6A, - 0x6C34, 0xDE6B, 0, 0xDE6C, 0xDE6D, 0x6C35, 0, 0xDE6E, - 0xDE6F, 0xDE72, 0x465A, 0xDE70, 0, 0xDE71, 0, 0, - 0, 0x3E5D, 0x6C36, 0xDE73, 0xDE74, 0, 0xDE75, 0, - 0xDE76, 0xDE77, 0x396B, 0x502E, 0x6C37, 0xDE78, 0, 0, - 0, 0, 0, 0xDE79, 0, 0xDE7A, 0xDE7B, 0, - 0x6C38, 0x493F, 0x6C39, 0xDE7C, 0x6C41, 0, 0xDE7D, 0, -}; -static const unsigned short utf8_to_euc_E8B1_x0213[] = { - 0, 0x6C2F, 0, 0, 0, 0xF87B, 0x4626, 0xF87C, - 0x6C31, 0x7C36, 0x4B2D, 0xDE69, 0x6C32, 0, 0x6C33, 0xF87D, - 0x6C34, 0xDE6B, 0, 0xDE6C, 0xF87E, 0x6C35, 0, 0xF921, - 0xDE6F, 0xDE72, 0x465A, 0xDE70, 0, 0xDE71, 0, 0, - 0, 0x3E5D, 0x6C36, 0xDE73, 0xDE74, 0, 0xDE75, 0, - 0x7C37, 0xF922, 0x396B, 0x502E, 0x6C37, 0xF923, 0, 0, - 0, 0, 0, 0xF924, 0, 0xDE7A, 0xDE7B, 0, - 0x6C38, 0x493F, 0x6C39, 0xDE7C, 0x6C41, 0, 0xDE7D, 0, -}; -static const unsigned short utf8_to_euc_E8B2[] = { - 0, 0, 0x6C3A, 0, 0, 0x6C3C, 0xDE7E, 0xDF21, - 0, 0x6C3B, 0x6C3D, 0xDF22, 0x4B46, 0x6C3E, 0x6C3F, 0, - 0xDF23, 0, 0xDF24, 0xDF25, 0x6C40, 0, 0, 0, - 0x6C42, 0xDF26, 0, 0xDF27, 0xDF28, 0x332D, 0x4467, 0, - 0x4969, 0x3A62, 0x3957, 0, 0xDF29, 0, 0, 0x494F, - 0x325F, 0x484E, 0x6C45, 0x3453, 0x4055, 0x6C44, 0x6C49, 0x4379, - 0x4C63, 0, 0x6C47, 0x6C48, 0x352E, 0, 0x6C4A, 0x4763, - 0x425F, 0xDF2A, 0xDF2B, 0x4871, 0x453D, 0x6C46, 0, 0x4B47, -}; -static const unsigned short utf8_to_euc_E8B2_x0213[] = { - 0, 0, 0x6C3A, 0, 0, 0x6C3C, 0xDE7E, 0xDF21, - 0, 0x6C3B, 0x6C3D, 0xDF22, 0x4B46, 0x6C3E, 0x6C3F, 0, - 0xDF23, 0, 0xF927, 0xF926, 0x6C40, 0, 0, 0, - 0x6C42, 0xF928, 0, 0xF92A, 0xDF28, 0x332D, 0x4467, 0, - 0x4969, 0x3A62, 0x3957, 0, 0xF92B, 0, 0, 0x494F, - 0x325F, 0x484E, 0x6C45, 0x3453, 0x4055, 0x6C44, 0x6C49, 0x4379, - 0x4C63, 0, 0x6C47, 0x6C48, 0x352E, 0, 0x6C4A, 0x4763, - 0x425F, 0xDF2A, 0xDF2B, 0x4871, 0x453D, 0x6C46, 0, 0x4B47, -}; -static const unsigned short utf8_to_euc_E8B3[] = { - 0x326C, 0x6C4C, 0x4F28, 0x4442, 0x4F45, 0xDF2C, 0xDF2D, 0x3B71, - 0x6C4B, 0xDF2E, 0x4231, 0xDF2F, 0, 0x6C5C, 0x4128, 0xDF30, - 0, 0x4678, 0, 0x4950, 0, 0xDF32, 0xDF31, 0, - 0, 0xDF33, 0x6C4F, 0x3B3F, 0x3B72, 0xDF34, 0x3E5E, 0, - 0x4765, 0xDF35, 0x382D, 0x6C4E, 0x6C4D, 0, 0x496A, 0, - 0xDF36, 0, 0x3C41, 0, 0xDF37, 0x4552, 0, 0xDF38, - 0xDF39, 0, 0xDF3A, 0, 0xF467, 0xDF3B, 0, 0xDF3C, - 0xDF3D, 0, 0x6C51, 0x6C52, 0x3958, 0x6C50, 0xDF3E, 0xDF3F, -}; -static const unsigned short utf8_to_euc_E8B3_x0213[] = { - 0x326C, 0x6C4C, 0x4F28, 0x4442, 0x4F45, 0xDF2C, 0xDF2D, 0x3B71, - 0x6C4B, 0xDF2E, 0x4231, 0xDF2F, 0, 0x6C5C, 0x4128, 0xDF30, - 0, 0x4678, 0, 0x4950, 0, 0xF92D, 0xF92C, 0, - 0, 0xF92E, 0x6C4F, 0x3B3F, 0x3B72, 0xDF34, 0x3E5E, 0, - 0x4765, 0x7C39, 0x382D, 0x6C4E, 0x6C4D, 0, 0x496A, 0, - 0xDF36, 0, 0x3C41, 0, 0xDF37, 0x4552, 0, 0xDF38, - 0xF930, 0xF931, 0xDF3A, 0, 0x7C3A, 0xDF3B, 0, 0xDF3C, - 0x7C3B, 0, 0x6C51, 0x6C52, 0x3958, 0x6C50, 0x7C3C, 0xDF3F, -}; -static const unsigned short utf8_to_euc_E8B4[] = { - 0, 0xDF40, 0, 0xDF41, 0x6C53, 0x6C54, 0, 0x6C56, - 0x4223, 0xDF42, 0x6C55, 0x3466, 0, 0x6C58, 0, 0x6C57, - 0x6C59, 0, 0xDF43, 0x6C5B, 0x6C5D, 0, 0x6C5E, 0xDF44, - 0, 0, 0, 0xDF45, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E8B4_x0213[] = { - 0, 0xDF40, 0, 0xDF41, 0x6C53, 0x6C54, 0, 0x6C56, - 0x4223, 0xF933, 0x6C55, 0x3466, 0, 0x6C58, 0xF934, 0x6C57, - 0x6C59, 0, 0x7C3E, 0x6C5B, 0x6C5D, 0, 0x6C5E, 0xDF44, - 0, 0, 0, 0x7C3F, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E8B5[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0x4056, 0xDF46, 0x3C4F, 0x6C5F, - 0, 0xDF47, 0, 0x3352, 0xDF48, 0x6C60, 0xDF49, 0, - 0x4176, 0x6C61, 0, 0x6C62, 0x496B, 0, 0xF468, 0x352F, - 0, 0, 0, 0, 0, 0, 0, 0xDF4A, -}; -static const unsigned short utf8_to_euc_E8B5_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0x4056, 0xDF46, 0x3C4F, 0x6C5F, - 0, 0xDF47, 0, 0x3352, 0xF935, 0x6C60, 0xDF49, 0, - 0x4176, 0x6C61, 0, 0x6C62, 0x496B, 0, 0, 0x352F, - 0, 0, 0, 0, 0, 0, 0, 0xDF4A, -}; -static const unsigned short utf8_to_euc_E8B6[] = { - 0, 0x6C63, 0xDF4B, 0, 0xDF4C, 0x4436, 0, 0, - 0xDF4D, 0, 0x315B, 0, 0, 0xDF4E, 0, 0, - 0xDF4F, 0xDF50, 0, 0, 0, 0xDF51, 0, 0, - 0, 0x6C64, 0, 0, 0, 0, 0xDF52, 0xDF53, - 0xDF54, 0, 0, 0x3C71, 0, 0, 0xDF55, 0, - 0x3F76, 0, 0, 0xDF56, 0xDF57, 0, 0, 0xDF58, - 0, 0, 0xDF59, 0x422D, 0, 0xDF5A, 0, 0xDF5B, - 0, 0xDF5C, 0x6C67, 0xDF5D, 0xDF6F, 0, 0x6C66, 0, -}; -static const unsigned short utf8_to_euc_E8B6_x0213[] = { - 0, 0x6C63, 0xDF4B, 0, 0xF936, 0x4436, 0, 0, - 0xDF4D, 0, 0x315B, 0, 0, 0xDF4E, 0, 0, - 0xDF4F, 0xDF50, 0, 0, 0, 0xF937, 0, 0, - 0, 0x6C64, 0, 0, 0, 0, 0xDF52, 0xDF53, - 0xDF54, 0, 0, 0x3C71, 0, 0, 0xF938, 0, - 0x3F76, 0, 0, 0xDF56, 0xDF57, 0, 0, 0x7C40, - 0, 0, 0xDF59, 0x422D, 0, 0xDF5A, 0, 0xDF5B, - 0, 0xDF5C, 0x6C67, 0xDF5D, 0xDF6F, 0, 0x6C66, 0, -}; -static const unsigned short utf8_to_euc_E8B7[] = { - 0xDF5E, 0, 0x6C65, 0, 0, 0xDF5F, 0xDF60, 0xDF61, - 0xDF62, 0, 0xDF63, 0x6C6D, 0x6C6B, 0, 0xDF64, 0x6C68, - 0, 0xDF65, 0, 0, 0xDF66, 0xDF67, 0x6C6A, 0xDF68, - 0, 0xDF69, 0x6C69, 0x6C6C, 0, 0x3577, 0, 0x6C70, - 0, 0x4057, 0, 0x6C71, 0xDF6A, 0xDF6B, 0, 0xDF6C, - 0x3859, 0, 0x6C6E, 0x6C6F, 0xDF6D, 0, 0, 0x4F29, - 0xDF6E, 0xDF70, 0xDF71, 0x4437, 0xDF72, 0x4129, 0, 0, - 0, 0, 0, 0, 0x6C72, 0xDF73, 0, 0x6C75, -}; -static const unsigned short utf8_to_euc_E8B7_x0213[] = { - 0xDF5E, 0, 0x6C65, 0, 0, 0xDF5F, 0xF93A, 0xDF61, - 0xF93B, 0, 0xDF63, 0x6C6D, 0x6C6B, 0, 0x7C41, 0x6C68, - 0, 0x7C42, 0, 0, 0xDF66, 0xDF67, 0x6C6A, 0x7C43, - 0, 0xF93C, 0x6C69, 0x6C6C, 0, 0x3577, 0, 0x6C70, - 0, 0x4057, 0, 0x6C71, 0xDF6A, 0xDF6B, 0, 0xDF6C, - 0x3859, 0, 0x6C6E, 0x6C6F, 0xF93D, 0, 0, 0x4F29, - 0xDF6E, 0xDF70, 0xDF71, 0x4437, 0xDF72, 0x4129, 0, 0, - 0, 0, 0, 0, 0x6C72, 0xF940, 0, 0x6C75, -}; -static const unsigned short utf8_to_euc_E8B8[] = { - 0, 0xDF74, 0, 0, 0xDF75, 0xDF76, 0xDF77, 0, - 0x6C73, 0x6C74, 0x4D59, 0xDF78, 0, 0, 0, 0x4627, - 0x6C78, 0xDF79, 0, 0, 0xDF7A, 0, 0xDF7B, 0, - 0, 0, 0, 0, 0, 0x6C76, 0x6C77, 0x6C79, - 0xDF7C, 0xDF7D, 0xDF7E, 0xE021, 0, 0, 0xE022, 0xE023, - 0, 0, 0x6D29, 0, 0, 0, 0, 0, - 0x6C7C, 0xE024, 0, 0xE025, 0x6C7D, 0x6C7B, 0xE026, 0xE027, - 0xE028, 0xE029, 0, 0, 0, 0xE02A, 0, 0, -}; -static const unsigned short utf8_to_euc_E8B8_x0213[] = { - 0, 0xDF74, 0, 0, 0xDF75, 0xDF76, 0xF941, 0, - 0x6C73, 0x6C74, 0x4D59, 0xDF78, 0xF93E, 0, 0, 0x4627, - 0x6C78, 0xDF79, 0, 0, 0xF943, 0, 0xF944, 0, - 0, 0, 0, 0, 0, 0x6C76, 0x6C77, 0x6C79, - 0x7C44, 0xF945, 0xF946, 0x7C45, 0, 0, 0xE022, 0xF947, - 0, 0, 0x6D29, 0, 0, 0, 0, 0, - 0x6C7C, 0xE024, 0, 0xE025, 0x6C7D, 0x6C7B, 0xF94A, 0xE027, - 0xE028, 0xF94B, 0, 0, 0, 0x7C46, 0, 0, -}; -static const unsigned short utf8_to_euc_E8B9[] = { - 0xE02B, 0xE02C, 0x6C7A, 0, 0x447D, 0, 0, 0x6D21, - 0x6D25, 0x6D22, 0x6C7E, 0xE02D, 0x6D23, 0xE02E, 0xE02F, 0xE030, - 0x6D24, 0, 0, 0, 0xE031, 0x6D2B, 0, 0, - 0, 0x6D26, 0, 0xE032, 0xE033, 0xE034, 0xE035, 0x4058, - 0x6D28, 0xE036, 0xE037, 0x6D2A, 0x6D27, 0, 0, 0, - 0, 0xE038, 0, 0, 0xE039, 0xE03A, 0, 0xE03B, - 0xE03C, 0xE03D, 0x6D2D, 0, 0x3D33, 0, 0x6D2C, 0, - 0, 0xE03E, 0xE03F, 0xE040, 0x6D2E, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E8B9_x0213[] = { - 0xE02B, 0xE02C, 0x6C7A, 0, 0x447D, 0, 0, 0x6D21, - 0x6D25, 0x6D22, 0x6C7E, 0xF94C, 0x6D23, 0xE02E, 0xE02F, 0xE030, - 0x6D24, 0, 0, 0, 0xF94D, 0x6D2B, 0, 0, - 0, 0x6D26, 0, 0xE032, 0xE033, 0xE034, 0xE035, 0x4058, - 0x6D28, 0xE036, 0xF94E, 0x6D2A, 0x6D27, 0, 0, 0, - 0, 0xE038, 0, 0, 0xF94F, 0xF950, 0, 0xF951, - 0x7C47, 0xE03D, 0x6D2D, 0, 0x3D33, 0, 0x6D2C, 0, - 0, 0xE03E, 0xE03F, 0x7C48, 0x6D2E, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E8BA[] = { - 0, 0x6D2F, 0xE041, 0xE042, 0x6D32, 0x6D31, 0, 0x6D30, - 0, 0xE043, 0x6D34, 0x6D33, 0, 0x4C76, 0, 0, - 0xE044, 0x6D36, 0xE045, 0x6D35, 0x6D37, 0xE046, 0, 0, - 0, 0x6D38, 0xE047, 0xE048, 0, 0xE049, 0xE04A, 0, - 0, 0x6D3A, 0xE04B, 0, 0, 0, 0, 0xE04C, - 0, 0xE04D, 0x6D39, 0x3F48, 0x6D3B, 0xE04E, 0xE04F, 0x366D, - 0x6D3C, 0x6D3E, 0, 0xE050, 0, 0xE051, 0, 0, - 0, 0, 0xE052, 0xE053, 0, 0, 0x6D3F, 0, -}; -static const unsigned short utf8_to_euc_E8BA_x0213[] = { - 0, 0x6D2F, 0xE041, 0xE042, 0x6D32, 0x6D31, 0, 0x6D30, - 0, 0xE043, 0x6D34, 0x6D33, 0, 0x4C76, 0, 0, - 0xE044, 0x6D36, 0xE045, 0x6D35, 0x6D37, 0xE046, 0, 0, - 0xF952, 0x6D38, 0xE047, 0xE048, 0, 0xE049, 0xF953, 0, - 0, 0x6D3A, 0xE04B, 0, 0, 0, 0, 0xE04C, - 0, 0xE04D, 0x6D39, 0x3F48, 0x6D3B, 0xE04E, 0xF954, 0x366D, - 0x6D3C, 0x6D3E, 0, 0xF955, 0, 0xF956, 0xF957, 0, - 0, 0, 0xE052, 0xF958, 0, 0, 0x6D3F, 0, -}; -static const unsigned short utf8_to_euc_E8BB[] = { - 0xE054, 0xE055, 0, 0xE056, 0xE057, 0x6D40, 0x6D3D, 0xE058, - 0x6D41, 0, 0x3C56, 0x6D42, 0x3530, 0x3733, 0, 0xE059, - 0, 0xE05A, 0x382E, 0, 0xE05B, 0, 0, 0, - 0, 0, 0, 0x6D43, 0xE05C, 0, 0, 0x4670, - 0, 0, 0x453E, 0x6D44, 0, 0, 0, 0, - 0xE05D, 0, 0, 0x6D47, 0, 0xE064, 0xE05E, 0, - 0xE05F, 0xE060, 0, 0, 0, 0, 0, 0xE061, - 0x3C34, 0xE062, 0xE063, 0x6D46, 0x6D45, 0x375A, 0x6D48, 0, -}; -static const unsigned short utf8_to_euc_E8BB_x0213[] = { - 0x7C4A, 0xE055, 0, 0xE056, 0xE057, 0x6D40, 0x6D3D, 0xE058, - 0x6D41, 0, 0x3C56, 0x6D42, 0x3530, 0x3733, 0, 0, - 0, 0xF95A, 0x382E, 0, 0xF95B, 0, 0, 0, - 0, 0, 0, 0x6D43, 0xE05C, 0, 0, 0x4670, - 0, 0, 0x453E, 0x6D44, 0, 0, 0, 0, - 0xE05D, 0, 0, 0x6D47, 0, 0xE064, 0xE05E, 0, - 0xE05F, 0xE060, 0, 0, 0, 0, 0, 0xE061, - 0x3C34, 0xF95D, 0x7C4C, 0x6D46, 0x6D45, 0x375A, 0x6D48, 0, -}; -static const unsigned short utf8_to_euc_E8BC[] = { - 0xE065, 0, 0xE066, 0x3353, 0, 0x6D4A, 0, 0xE067, - 0xE068, 0x3A5C, 0x6D49, 0, 0x6D52, 0, 0, 0xE069, - 0xE06A, 0, 0x6D4C, 0x6D4E, 0x4A65, 0x6D4B, 0xE06B, 0xE06C, - 0xE06D, 0x6D4D, 0, 0x6D51, 0x6D4F, 0x3531, 0xE06E, 0x6D50, - 0xE06F, 0xE070, 0, 0xE071, 0, 0xE072, 0x6D53, 0xE073, - 0xE074, 0x475A, 0x4E58, 0, 0xE075, 0xE076, 0xE077, 0x3D34, - 0, 0, 0, 0x6D54, 0xE078, 0xE079, 0xE07A, 0xE07B, - 0x4D22, 0x6D56, 0xE07C, 0x6D55, 0, 0, 0x6D59, 0x4D41, -}; -static const unsigned short utf8_to_euc_E8BC_x0213[] = { - 0xF95F, 0, 0xE066, 0x3353, 0, 0x6D4A, 0, 0xE067, - 0xF960, 0x3A5C, 0x6D49, 0, 0x6D52, 0, 0, 0xE069, - 0xE06A, 0, 0x6D4C, 0x6D4E, 0x4A65, 0x6D4B, 0xE06B, 0xF961, - 0xE06D, 0x6D4D, 0, 0x6D51, 0x6D4F, 0x3531, 0x7C4D, 0x6D50, - 0xE06F, 0xE070, 0, 0xE071, 0, 0xE072, 0x6D53, 0xE073, - 0xE074, 0x475A, 0x4E58, 0xF962, 0xE075, 0x7C4E, 0xE077, 0x3D34, - 0, 0, 0, 0x6D54, 0xE078, 0xE079, 0x7C4F, 0xE07B, - 0x4D22, 0x6D56, 0xE07C, 0x6D55, 0, 0, 0x6D59, 0x4D41, -}; -static const unsigned short utf8_to_euc_E8BD[] = { - 0xE07D, 0xE07E, 0x6D58, 0xE121, 0x336D, 0x6D57, 0x6D5C, 0xE122, - 0, 0x6D5B, 0, 0, 0x6D5A, 0x4532, 0x6D5D, 0xE123, - 0, 0xE124, 0xE125, 0xE126, 0xE127, 0xE128, 0, 0x6D5E, - 0xE129, 0, 0, 0, 0x6D5F, 0xE12A, 0xE12B, 0x396C, - 0, 0x3725, 0x6D60, 0x6D61, 0x6D62, 0xE12C, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E8BD_x0213[] = { - 0xF963, 0xE07E, 0x6D58, 0xE121, 0x336D, 0x6D57, 0x6D5C, 0xE122, - 0, 0x6D5B, 0xF964, 0, 0x6D5A, 0x4532, 0x6D5D, 0xE123, - 0, 0xE124, 0xE125, 0xE126, 0x7C50, 0xE128, 0, 0x6D5E, - 0xF965, 0, 0, 0, 0x6D5F, 0xE12A, 0xE12B, 0x396C, - 0, 0x3725, 0x6D60, 0x6D61, 0x6D62, 0xE12C, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E8BE[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0x3F49, 0x6D63, 0xE12D, 0x3C2D, 0x6D64, - 0xE12E, 0xE12F, 0, 0x6D65, 0xE130, 0xE131, 0xE132, 0x5221, - 0x517E, 0, 0, 0, 0, 0x6D66, 0x6570, 0x6D67, - 0x4324, 0x3F2B, 0x4740, 0, 0, 0xE133, 0xE134, 0x6D68, - 0xE135, 0, 0x4A55, 0x4454, 0x397E, 0, 0xE136, 0x4329, -}; -static const unsigned short utf8_to_euc_E8BE_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0x3F49, 0x6D63, 0xE12D, 0x3C2D, 0x6D64, - 0xE12E, 0xE12F, 0, 0x6D65, 0xF967, 0xE131, 0x7C52, 0x5221, - 0x517E, 0, 0, 0, 0, 0x6D66, 0x6570, 0x6D67, - 0x4324, 0x3F2B, 0x4740, 0, 0xF968, 0x7C53, 0xF96A, 0x6D68, - 0xE135, 0, 0x4A55, 0x4454, 0x397E, 0, 0xE136, 0x4329, -}; -static const unsigned short utf8_to_euc_E8BF[] = { - 0xE137, 0xE138, 0x312A, 0, 0x4B78, 0x3F57, 0xE139, 0, - 0, 0, 0xE13A, 0xE13B, 0, 0xE13C, 0x375E, 0, - 0xE13D, 0x3661, 0xE13E, 0xE13F, 0x4A56, 0xE140, 0, 0, - 0, 0, 0x6D69, 0, 0, 0, 0, 0, - 0xE141, 0, 0x6D6B, 0xE142, 0xE143, 0x6D6A, 0x3260, 0, - 0xE144, 0x4676, 0x6D6C, 0x4777, 0, 0x4533, 0xE145, 0x6D6D, - 0x3D52, 0xE146, 0, 0, 0x6D6F, 0xE147, 0xE148, 0x4C42, - 0x6D7E, 0x6D71, 0x6D72, 0xE149, 0, 0x4449, 0xE14A, 0, -}; -static const unsigned short utf8_to_euc_E8BF_x0213[] = { - 0xE137, 0xF96C, 0x312A, 0, 0x4B78, 0x3F57, 0xF96D, 0, - 0, 0, 0xF96F, 0xE13B, 0, 0xF970, 0x375E, 0, - 0xE13D, 0x3661, 0xE13E, 0xF971, 0x4A56, 0xF972, 0, 0, - 0, 0, 0x6D69, 0, 0, 0, 0, 0, - 0xF973, 0, 0x6D6B, 0xE142, 0x7C54, 0x6D6A, 0x3260, 0, - 0x7C55, 0x4676, 0x6D6C, 0x4777, 0, 0x4533, 0x7C56, 0x6D6D, - 0x3D52, 0xF974, 0, 0, 0x6D6F, 0xF975, 0xE148, 0x4C42, - 0x6D7E, 0x6D71, 0x6D72, 0xF976, 0, 0x4449, 0xE14A, 0, -}; -static const unsigned short utf8_to_euc_E980[] = { - 0x4260, 0x4177, 0xE14B, 0x4628, 0xE14C, 0x6D70, 0x3555, 0, - 0xE14D, 0, 0, 0x6D79, 0xE14E, 0x6D76, 0x6E25, 0x4629, - 0x4360, 0x6D73, 0, 0x447E, 0x4553, 0x6D74, 0x6D78, 0x3F60, - 0xE14F, 0x4767, 0x444C, 0xE150, 0, 0x4042, 0x6D77, 0x422E, - 0x4224, 0x6D75, 0x3029, 0x4F22, 0, 0, 0, 0x6D7A, - 0xE151, 0xE152, 0xE154, 0, 0xE155, 0xE156, 0x4261, 0xE153, - 0, 0x3D35, 0x3F4A, 0xE157, 0xE158, 0x6D7C, 0x6D7B, 0xE159, - 0x306F, 0x6D7D, 0, 0, 0x492F, 0, 0x6E27, 0xE15A, -}; -static const unsigned short utf8_to_euc_E980_x0213[] = { - 0x4260, 0x4177, 0xF977, 0x4628, 0xE14C, 0x6D70, 0x3555, 0, - 0x7C57, 0, 0, 0x6D79, 0xF978, 0x6D76, 0x6E25, 0x4629, - 0x4360, 0x6D73, 0, 0x447E, 0x4553, 0x6D74, 0x6D78, 0x3F60, - 0xE14F, 0x4767, 0x444C, 0xE150, 0, 0x4042, 0x6D77, 0x422E, - 0x4224, 0x6D75, 0x3029, 0x4F22, 0, 0, 0, 0x6D7A, - 0xE151, 0xE152, 0xE154, 0, 0xE155, 0x7C58, 0x4261, 0xE153, - 0, 0x3D35, 0x3F4A, 0xE157, 0xE158, 0x6D7C, 0x6D7B, 0xF979, - 0x306F, 0x6D7D, 0, 0, 0x492F, 0, 0x6E27, 0xE15A, -}; -static const unsigned short utf8_to_euc_E981[] = { - 0, 0x465B, 0x3F6B, 0xE15B, 0xE15C, 0x4359, 0, 0x3678, - 0, 0x6E26, 0x4D37, 0x313F, 0xE15D, 0x4A57, 0x3261, 0x6E21, - 0x6E22, 0x6E23, 0x6E24, 0x463B, 0x4323, 0x3063, 0x6E28, 0, - 0x6E29, 0x7423, 0, 0xE15E, 0x423D, 0xE15F, 0x6E2A, 0, - 0x3173, 0x414C, 0xE160, 0x382F, 0, 0x4D5A, 0xE161, 0xE162, - 0x6E2B, 0x452C, 0, 0, 0xE163, 0x4178, 0x3C57, 0x6E2C, - 0xE164, 0, 0x6E2F, 0, 0xE165, 0x3D65, 0x6E2D, 0x412B, - 0x412A, 0xE166, 0x3064, 0, 0x4E4B, 0x6E31, 0, 0x4872, -}; -static const unsigned short utf8_to_euc_E981_x0213[] = { - 0, 0x465B, 0x3F6B, 0xF97B, 0xF97C, 0x4359, 0, 0x3678, - 0, 0x6E26, 0x4D37, 0x313F, 0xE15D, 0x4A57, 0x3261, 0x6E21, - 0x6E22, 0x6E23, 0x6E24, 0x463B, 0x4323, 0x3063, 0x6E28, 0, - 0x6E29, 0x7423, 0, 0xE15E, 0x423D, 0xF97D, 0x6E2A, 0, - 0x3173, 0x414C, 0xE160, 0x382F, 0, 0x4D5A, 0xE161, 0, - 0x6E2B, 0x452C, 0, 0, 0xE163, 0x4178, 0x3C57, 0x6E2C, - 0xE164, 0, 0x6E2F, 0, 0xE165, 0x3D65, 0x6E2D, 0x412B, - 0x412A, 0xE166, 0x3064, 0, 0x4E4B, 0x6E31, 0, 0x4872, -}; -static const unsigned short utf8_to_euc_E982[] = { - 0x6E33, 0x6E32, 0x6E30, 0x6364, 0x3454, 0xE167, 0, 0x6D6E, - 0xE168, 0x6E35, 0x6E34, 0xE169, 0xE16A, 0, 0xE16B, 0x6E36, - 0xE16C, 0x4D38, 0, 0, 0, 0xE16D, 0, 0xE16E, - 0xE16F, 0xE170, 0, 0xE171, 0, 0, 0, 0, - 0xE172, 0xE173, 0xE174, 0x4661, 0, 0xE175, 0x4B2E, 0, - 0x6E37, 0, 0x3C59, 0, 0, 0, 0, 0x6E38, - 0xE176, 0x6E39, 0xE177, 0xE178, 0xE179, 0x6E3A, 0xE17A, 0, - 0x4521, 0, 0, 0, 0, 0xE17B, 0xE17D, 0, -}; -static const unsigned short utf8_to_euc_E982_x0213[] = { - 0x6E33, 0x6E32, 0x6E30, 0x6364, 0x3454, 0xFA22, 0, 0x6D6E, - 0x7C5A, 0x6E35, 0x6E34, 0xE169, 0xFA23, 0, 0xE16B, 0x6E36, - 0xFA24, 0x4D38, 0, 0, 0, 0x7C5B, 0, 0x7C5C, - 0xE16F, 0x7C5D, 0, 0x7C5E, 0, 0, 0, 0, - 0xE172, 0xFA26, 0x7C5F, 0x4661, 0, 0xE175, 0x4B2E, 0, - 0x6E37, 0, 0x3C59, 0, 0, 0, 0, 0x6E38, - 0xFA28, 0x6E39, 0xE177, 0x7C60, 0xE179, 0x6E3A, 0xFA29, 0, - 0x4521, 0, 0, 0, 0, 0xE17B, 0x7C61, 0, -}; -static const unsigned short utf8_to_euc_E983[] = { - 0, 0x306A, 0, 0xE17E, 0xE221, 0xE222, 0, 0xE223, - 0xE224, 0, 0x3959, 0, 0xE17C, 0, 0x4F3A, 0, - 0, 0, 0xE22D, 0, 0, 0xE225, 0, 0xE226, - 0xE227, 0xE228, 0, 0x6E3E, 0xE229, 0xE22A, 0xF46C, 0xE22B, - 0, 0x3734, 0x6E3B, 0, 0x6E3C, 0xE22C, 0, 0, - 0x4974, 0, 0, 0xE22F, 0, 0x3354, 0, 0xE230, - 0xE231, 0, 0, 0, 0xE232, 0x4D39, 0xE22E, 0x363F, - 0, 0, 0, 0, 0, 0x4554, 0xE233, 0xE234, -}; -static const unsigned short utf8_to_euc_E983_x0213[] = { - 0, 0x306A, 0, 0xFA2A, 0x7C62, 0x7C63, 0, 0x7C64, - 0xFA2B, 0, 0x3959, 0, 0xE17C, 0, 0x4F3A, 0, - 0, 0, 0xE22D, 0, 0, 0xE225, 0, 0x7C65, - 0xE227, 0xE228, 0, 0x6E3E, 0xFA2D, 0x7C66, 0x7C67, 0xFA2E, - 0, 0x3734, 0x6E3B, 0, 0x6E3C, 0xE22C, 0, 0, - 0x4974, 0, 0, 0xFA33, 0, 0x3354, 0, 0x7C68, - 0xE231, 0, 0xFA31, 0, 0x7C69, 0x4D39, 0xFA30, 0x363F, - 0, 0, 0, 0, 0, 0x4554, 0xFA34, 0xFA35, -}; -static const unsigned short utf8_to_euc_E984[] = { - 0xE235, 0, 0x6E3F, 0, 0xE236, 0xE237, 0xE238, 0, - 0xE239, 0, 0, 0, 0, 0xE23A, 0, 0, - 0xE23B, 0, 0x6E40, 0, 0xE23C, 0xF46E, 0xE23D, 0xE23E, - 0xE23F, 0x6E41, 0xE240, 0, 0xE241, 0, 0xE242, 0, - 0xE243, 0, 0xE245, 0xE246, 0, 0xE244, 0, 0xE247, - 0, 0xE248, 0, 0, 0, 0x4522, 0xE249, 0xE24A, - 0x6E43, 0xE24B, 0x6E42, 0, 0xE24C, 0, 0xE24D, 0xE24E, - 0, 0xE24F, 0xE250, 0, 0xE251, 0xE252, 0, 0, -}; -static const unsigned short utf8_to_euc_E984_x0213[] = { - 0xFA32, 0, 0x6E3F, 0, 0xFA36, 0xE237, 0xFA37, 0, - 0xE239, 0, 0, 0, 0, 0xE23A, 0, 0, - 0xE23B, 0, 0x6E40, 0, 0x7C6B, 0x7C6C, 0x7C6D, 0xE23E, - 0xFA38, 0x6E41, 0xE240, 0, 0xFA39, 0, 0xFA3A, 0, - 0xE243, 0, 0x7C6E, 0x7C6F, 0, 0xE244, 0, 0x7C70, - 0, 0xE248, 0, 0, 0, 0x4522, 0xE249, 0x7C71, - 0x6E43, 0x7C72, 0x6E42, 0, 0x7C73, 0, 0xE24D, 0xFA3B, - 0, 0xFA3C, 0xFA3D, 0, 0xE251, 0x7C74, 0, 0, -}; -static const unsigned short utf8_to_euc_E985[] = { - 0, 0, 0, 0xE253, 0, 0, 0, 0xE254, - 0xE255, 0x4653, 0x6E44, 0x3D36, 0x3C60, 0x475B, 0x4371, 0xE256, - 0, 0, 0x3C72, 0xE257, 0x3F6C, 0, 0x6E45, 0xE258, - 0x6E46, 0xE259, 0xE25A, 0xE25B, 0, 0, 0, 0, - 0, 0xE25C, 0x3F5D, 0x6E47, 0xE25D, 0x6E48, 0, 0xE25E, - 0, 0x6E49, 0x4D6F, 0, 0x3D37, 0xE25F, 0, 0, - 0, 0, 0x6E4B, 0x6E4A, 0xE260, 0x395A, 0, 0x3973, - 0x3B40, 0xE261, 0xE262, 0xE263, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E985_x0213[] = { - 0, 0, 0, 0xE253, 0, 0, 0xFA3E, 0xFA3F, - 0x7C75, 0x4653, 0x6E44, 0x3D36, 0x3C60, 0x475B, 0x4371, 0xE256, - 0, 0, 0x3C72, 0xE257, 0x3F6C, 0, 0x6E45, 0xFA40, - 0x6E46, 0xFA41, 0xE25A, 0x7C76, 0, 0, 0, 0, - 0, 0xFA42, 0x3F5D, 0x6E47, 0xFA43, 0x6E48, 0, 0xE25E, - 0, 0x6E49, 0x4D6F, 0, 0x3D37, 0xE25F, 0, 0, - 0, 0, 0x6E4B, 0x6E4A, 0xFA44, 0x395A, 0, 0x3973, - 0x3B40, 0xFA45, 0xE262, 0xE263, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E986[] = { - 0, 0xE264, 0x6E4E, 0xE265, 0, 0xE266, 0xE267, 0x3D66, - 0, 0x6E4D, 0xE268, 0x6E4C, 0, 0x4269, 0xE269, 0, - 0x386F, 0xE26A, 0x4043, 0xE26B, 0xE26C, 0xE26D, 0, 0x4830, - 0xE26E, 0, 0, 0, 0x3D39, 0, 0xE26F, 0, - 0, 0xE270, 0x6E4F, 0, 0x3E5F, 0, 0xE271, 0, - 0xE272, 0, 0x6E52, 0x6E50, 0xE273, 0xE274, 0xE275, 0x6E51, - 0xE276, 0xE277, 0xE278, 0xE279, 0x6E54, 0x6E53, 0xE27A, 0, - 0x3E7A, 0, 0x6E55, 0xE27B, 0xE27C, 0xE27D, 0, 0xE27E, -}; -static const unsigned short utf8_to_euc_E986_x0213[] = { - 0, 0xE264, 0x6E4E, 0x7C77, 0, 0xFA46, 0xE267, 0x3D66, - 0, 0x6E4D, 0xE268, 0x6E4C, 0, 0x4269, 0xFA47, 0, - 0x386F, 0xE26A, 0x4043, 0xE26B, 0xE26C, 0xE26D, 0, 0x4830, - 0xE26E, 0, 0, 0, 0x3D39, 0, 0x7C78, 0, - 0, 0xE270, 0x6E4F, 0, 0x3E5F, 0, 0xE271, 0, - 0xFA48, 0, 0x6E52, 0x6E50, 0x7C79, 0xE274, 0xFA49, 0x6E51, - 0xE276, 0x7C7A, 0xE278, 0xFA4A, 0x6E54, 0x6E53, 0xFA4B, 0, - 0x3E7A, 0, 0x6E55, 0xE27B, 0x7C7B, 0xE27D, 0, 0xE27E, -}; -static const unsigned short utf8_to_euc_E987[] = { - 0x6E56, 0x6E57, 0xE321, 0xE322, 0, 0xE323, 0x4850, 0x3A53, - 0x3C61, 0x6E58, 0, 0x6E59, 0x4E24, 0x3D45, 0x4C6E, 0x4E4C, - 0x6E5A, 0x3662, 0, 0xE324, 0xE325, 0, 0x6E5B, 0xE326, - 0x4523, 0xE327, 0xE328, 0x6E5E, 0x3378, 0x3F4B, 0xE329, 0x6E5C, - 0, 0x6E5D, 0, 0x4460, 0xE32A, 0xE32B, 0x4B55, 0x367C, - 0, 0xE32C, 0xE32D, 0, 0xE32E, 0xE32F, 0xE330, 0xE331, - 0xE332, 0xE333, 0, 0, 0, 0x6E60, 0x6E61, 0xE334, - 0, 0xE335, 0, 0xE336, 0x6E5F, 0xE337, 0, 0x6E63, -}; -static const unsigned short utf8_to_euc_E987_x0213[] = { - 0x6E56, 0x6E57, 0xE321, 0xFA4C, 0xFA4D, 0xE323, 0x4850, 0x3A53, - 0x3C61, 0x6E58, 0, 0x6E59, 0x4E24, 0x3D45, 0x4C6E, 0x4E4C, - 0x6E5A, 0x3662, 0, 0xE324, 0xE325, 0, 0x6E5B, 0x7C7C, - 0x4523, 0xE327, 0xFA4E, 0x6E5E, 0x3378, 0x3F4B, 0, 0x6E5C, - 0, 0x6E5D, 0, 0x4460, 0x7C7E, 0x7D21, 0x4B55, 0x367C, - 0, 0xE32C, 0xE32D, 0, 0xFA51, 0x7D22, 0xFA52, 0xE331, - 0xE332, 0x7D23, 0, 0, 0, 0x6E60, 0x6E61, 0xE334, - 0, 0xE335, 0, 0x7C7D, 0x6E5F, 0xE337, 0, 0x6E63, -}; -static const unsigned short utf8_to_euc_E988[] = { - 0xE338, 0xE339, 0, 0, 0xE33A, 0xE33B, 0xE33C, 0xE33D, - 0, 0xE33E, 0xE33F, 0, 0xE340, 0x465F, 0x3343, 0, - 0xE341, 0x6E67, 0xE342, 0xE343, 0x6E64, 0x6E66, 0xE344, 0, - 0xE345, 0, 0, 0, 0xE346, 0xE347, 0x6E62, 0, - 0, 0, 0, 0xE348, 0xE349, 0xE34A, 0xE34B, 0, - 0xE34C, 0x6F4F, 0, 0, 0x6E65, 0, 0xE34D, 0xE34E, - 0xE34F, 0, 0, 0xE350, 0x4E6B, 0xE351, 0xE352, 0x385A, - 0xE353, 0xE354, 0xE355, 0, 0xE356, 0, 0xE357, 0x6E6F, -}; -static const unsigned short utf8_to_euc_E988_x0213[] = { - 0xE338, 0xFA53, 0, 0, 0xE33A, 0xE33B, 0, 0x7D24, - 0, 0xE33E, 0xFA54, 0, 0xE340, 0x465F, 0x3343, 0, - 0x7D25, 0x6E67, 0xE342, 0xE343, 0x6E64, 0x6E66, 0xFA55, 0xFA56, - 0xE345, 0, 0, 0, 0xE346, 0xE347, 0x6E62, 0, - 0, 0, 0, 0xE348, 0xE349, 0xE34A, 0xE34B, 0, - 0xE34C, 0x6F4F, 0, 0, 0x6E65, 0, 0xE34D, 0xE34E, - 0xE34F, 0, 0, 0xFA58, 0x4E6B, 0xE351, 0xE352, 0x385A, - 0x7D26, 0x7D27, 0x7D28, 0, 0x7D29, 0, 0xE357, 0x6E6F, -}; -static const unsigned short utf8_to_euc_E989[] = { - 0xE358, 0, 0xE359, 0xE35A, 0x4534, 0x6E6A, 0xE35B, 0xE35C, - 0x6E6D, 0x6E6B, 0xE35D, 0x6E70, 0, 0xE35E, 0xE35F, 0xE360, - 0x6E71, 0xE361, 0, 0, 0, 0, 0, 0x6E69, - 0xE362, 0xE363, 0x6E76, 0x3174, 0xE364, 0xE365, 0x6E68, 0, - 0xE366, 0xE367, 0x482D, 0, 0x6E6C, 0xE368, 0x3E60, 0xE369, - 0xE36A, 0xE36B, 0, 0, 0, 0, 0xE36C, 0xE36D, - 0xE36E, 0x395B, 0, 0, 0, 0xE36F, 0xE370, 0xE371, - 0xE372, 0xE373, 0, 0xE374, 0xE375, 0xE376, 0x4B48, 0xE377, -}; -static const unsigned short utf8_to_euc_E989_x0213[] = { - 0x7D2A, 0, 0xFA59, 0x7D2B, 0x4534, 0x6E6A, 0xE35B, 0xFA5A, - 0x6E6D, 0x6E6B, 0xFA5B, 0x6E70, 0, 0xE35E, 0xFA5C, 0x7D2C, - 0x6E71, 0xFA5D, 0, 0, 0, 0, 0xFA5E, 0x6E69, - 0xE362, 0xFA5F, 0x6E76, 0x3174, 0xE364, 0xE365, 0x6E68, 0, - 0xFA60, 0xFA61, 0x482D, 0, 0x6E6C, 0xFA62, 0x3E60, 0xFA63, - 0xFA64, 0xE36B, 0, 0, 0, 0, 0xE36C, 0xE36D, - 0xE36E, 0x395B, 0, 0, 0, 0xE36F, 0xE370, 0, - 0x7D2D, 0xE373, 0, 0xE374, 0xFA67, 0xFA68, 0x4B48, 0xFA69, -}; -static const unsigned short utf8_to_euc_E98A[] = { - 0x3664, 0, 0, 0x3D46, 0, 0x463C, 0, 0, - 0xE378, 0xE379, 0xE37A, 0, 0, 0xE37B, 0xE37C, 0, - 0, 0x412D, 0xE37D, 0x6E74, 0, 0x6E6E, 0x6E73, 0xE37E, - 0x4C43, 0xE421, 0x4438, 0x6E75, 0x6E72, 0, 0, 0xE422, - 0xE423, 0, 0, 0, 0xE424, 0xE425, 0, 0xE426, - 0xE427, 0, 0, 0xE428, 0, 0x412C, 0, 0xE429, - 0, 0, 0xE42A, 0, 0, 0, 0xE42B, 0x6E79, - 0xE42C, 0x6E78, 0xE42D, 0xE42E, 0xE42F, 0xE430, 0, 0xE431, -}; -static const unsigned short utf8_to_euc_E98A_x0213[] = { - 0x3664, 0, 0, 0x3D46, 0, 0x463C, 0, 0, - 0x7D2E, 0xFA6A, 0xE37A, 0, 0, 0xFA6B, 0xE37C, 0, - 0, 0x412D, 0xE37D, 0x6E74, 0, 0x6E6E, 0x6E73, 0xFA6C, - 0x4C43, 0xFA6D, 0x4438, 0x6E75, 0x6E72, 0, 0, 0xFA6E, - 0xE423, 0, 0, 0, 0xE424, 0xE425, 0, 0xFA6F, - 0xE427, 0, 0, 0xFA70, 0, 0x412C, 0, 0xE429, - 0, 0, 0xFA73, 0, 0, 0, 0xE42B, 0x6E79, - 0xE42C, 0x6E78, 0xE42D, 0xE42E, 0xE42F, 0xE430, 0, 0xFA74, -}; -static const unsigned short utf8_to_euc_E98B[] = { - 0xE432, 0xE433, 0xE434, 0xE435, 0, 0xE436, 0xE437, 0xE438, - 0xE439, 0, 0, 0xE43A, 0xE43B, 0xE43C, 0xE43D, 0x6E77, - 0xE43E, 0, 0x4B2F, 0xE43F, 0, 0xE440, 0, 0xE441, - 0xE442, 0xE443, 0, 0, 0xE444, 0xE445, 0, 0xE446, - 0xE447, 0xE448, 0, 0xE449, 0x3D7B, 0xE44A, 0, 0xE44B, - 0xE44C, 0x6E7A, 0x4A5F, 0, 0xE44D, 0x3154, 0xE44E, 0, - 0xE44F, 0, 0x4946, 0x4372, 0, 0, 0, 0, - 0x3578, 0xE450, 0x6E7C, 0xE451, 0x395D, 0, 0, 0xE452, -}; -static const unsigned short utf8_to_euc_E98B_x0213[] = { - 0xFA75, 0xE433, 0x7D2F, 0xE435, 0, 0xE436, 0xFA76, 0xE438, - 0xE439, 0, 0, 0x7D30, 0x7D31, 0xE43C, 0xFA77, 0x6E77, - 0xFA78, 0, 0x4B2F, 0x7D32, 0, 0, 0, 0xFA79, - 0xE442, 0xFA7A, 0, 0, 0xE444, 0xE445, 0, 0xE446, - 0x7D33, 0xE448, 0, 0xE449, 0x3D7B, 0xFA7B, 0, 0xFA7C, - 0xE44C, 0x6E7A, 0x4A5F, 0, 0xE44D, 0x3154, 0xE44E, 0, - 0xE44F, 0, 0x4946, 0x4372, 0, 0, 0, 0xFB22, - 0x3578, 0xFB23, 0x6E7C, 0xFB24, 0x395D, 0, 0, 0x7D34, -}; -static const unsigned short utf8_to_euc_E98C[] = { - 0xE453, 0, 0xE454, 0, 0, 0, 0x3B2C, 0, - 0xE455, 0, 0, 0, 0, 0xE456, 0, 0x6E7B, - 0x3F6D, 0xE457, 0, 0, 0xE458, 0xE459, 0, 0, - 0x3F6E, 0x6F21, 0x6F23, 0, 0xE45A, 0xE45B, 0xE45C, 0xE45D, - 0x3E7B, 0xE45E, 0x6F22, 0x6F24, 0xE45F, 0xE460, 0x3653, 0xE461, - 0x4945, 0xE462, 0xE463, 0x3C62, 0x4F23, 0, 0x6E7E, 0x3A78, - 0, 0, 0x4F3F, 0xE464, 0xE465, 0x6F26, 0xE466, 0xE467, - 0, 0, 0x6F25, 0x6F27, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E98C_x0213[] = { - 0xE453, 0, 0xFB25, 0, 0x7D35, 0, 0x3B2C, 0, - 0xE455, 0, 0, 0, 0, 0xFB26, 0, 0x6E7B, - 0x3F6D, 0xFA7D, 0, 0, 0xE458, 0xFB27, 0, 0, - 0x3F6E, 0x6F21, 0x6F23, 0, 0xE45A, 0xFB28, 0xFB29, 0x7D36, - 0x3E7B, 0x7D37, 0x6F22, 0x6F24, 0xE45F, 0x7D38, 0x3653, 0xFB2A, - 0x4945, 0xFB2B, 0xE463, 0x3C62, 0x4F23, 0, 0x6E7E, 0x3A78, - 0, 0, 0x4F3F, 0xE464, 0xE465, 0x6F26, 0xE466, 0xE467, - 0, 0, 0x6F25, 0x6F27, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E98D[] = { - 0, 0, 0, 0, 0x6E7D, 0, 0, 0xE468, - 0xE469, 0xE46A, 0, 0x4669, 0, 0x4555, 0, 0, - 0xE46B, 0xE46C, 0xE46D, 0, 0x4457, 0xE46E, 0x6F2C, 0xE46F, - 0xE470, 0, 0xE471, 0x4343, 0x6F28, 0, 0xE472, 0, - 0x6F29, 0, 0, 0, 0xE473, 0xE474, 0, 0xE475, - 0, 0xE476, 0xE477, 0, 0x372D, 0xE478, 0x6F2B, 0xE479, - 0xE47A, 0xE47B, 0, 0xE47C, 0xE47D, 0x3830, 0xE47E, 0, - 0, 0, 0xE521, 0, 0x6F2A, 0xE522, 0x3E61, 0xE523, -}; -static const unsigned short utf8_to_euc_E98D_x0213[] = { - 0, 0, 0, 0, 0x6E7D, 0, 0, 0xFB2E, - 0x7D39, 0x7D3A, 0x7D3B, 0x4669, 0, 0x4555, 0, 0, - 0xE46B, 0xFB2F, 0xE46D, 0, 0x4457, 0xE46E, 0x6F2C, 0xFB30, - 0xE470, 0, 0xFB31, 0x4343, 0x6F28, 0, 0xE472, 0, - 0x6F29, 0, 0, 0, 0x7D3C, 0x7D3D, 0, 0xE475, - 0, 0xE476, 0x7D3E, 0xFB32, 0x372D, 0xE478, 0x6F2B, 0xE479, - 0x7D3F, 0xFB33, 0, 0xFB34, 0xE47D, 0x3830, 0xE47E, 0, - 0, 0, 0xE521, 0, 0x6F2A, 0xE522, 0x3E61, 0xE523, -}; -static const unsigned short utf8_to_euc_E98E[] = { - 0xE524, 0xE525, 0xE526, 0, 0, 0, 0, 0, - 0xE527, 0, 0xE528, 0xE529, 0x3379, 0xE52A, 0, 0xE52B, - 0, 0, 0xE52C, 0, 0x6F30, 0xE52D, 0x3A3F, 0x4179, - 0xE52E, 0, 0x444A, 0xE52F, 0, 0, 0xE530, 0, - 0, 0xE531, 0, 0xE532, 0xE533, 0, 0xE534, 0x333B, - 0xE535, 0xE53B, 0, 0xE536, 0x6F2E, 0x6F2F, 0x4443, 0, - 0x6F2D, 0, 0, 0, 0xE537, 0xE538, 0xE539, 0, - 0, 0x6F31, 0xE53A, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E98E_x0213[] = { - 0xE524, 0xE525, 0xE526, 0, 0, 0, 0, 0, - 0xFB38, 0, 0xE528, 0xFB39, 0x3379, 0xE52A, 0, 0xFB3A, - 0, 0, 0xE52C, 0, 0x6F30, 0xE52D, 0x3A3F, 0x4179, - 0xE52E, 0, 0x444A, 0x7D40, 0, 0, 0xFB3B, 0, - 0, 0xFB35, 0, 0x7D41, 0, 0, 0xE534, 0x333B, - 0xE535, 0xE53B, 0, 0xE536, 0x6F2E, 0x6F2F, 0x4443, 0, - 0x6F2D, 0, 0, 0, 0xE537, 0xE538, 0xE539, 0, - 0, 0x6F31, 0x7D42, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E98F[] = { - 0, 0xE53C, 0, 0x6F37, 0xE53D, 0xE53E, 0xE53F, 0xE540, - 0x6F3A, 0xE541, 0xE542, 0xE543, 0xE544, 0xE545, 0, 0, - 0x6F39, 0x452D, 0, 0xE546, 0, 0, 0x6F32, 0x6F33, - 0x6F36, 0xE547, 0, 0, 0xE548, 0x6F38, 0xE549, 0xE54A, - 0, 0x3640, 0xE54B, 0, 0x6F3B, 0x6F35, 0xE54C, 0xE54D, - 0x6F34, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0xE54F, - 0xE550, 0xE54E, 0xE551, 0xE552, 0, 0xE553, 0, 0, -}; -static const unsigned short utf8_to_euc_E98F_x0213[] = { - 0, 0xFB40, 0, 0x6F37, 0xE53D, 0xE53E, 0x7D43, 0xFB41, - 0x6F3A, 0xE541, 0xE542, 0xE543, 0xE544, 0xE545, 0, 0, - 0x6F39, 0x452D, 0, 0xE546, 0, 0, 0x6F32, 0x6F33, - 0x6F36, 0xE547, 0, 0, 0xFB42, 0x6F38, 0x7D44, 0x7D45, - 0, 0x3640, 0xFB43, 0, 0x6F3B, 0x6F35, 0xE54C, 0xFB44, - 0x6F34, 0, 0, 0, 0, 0, 0, 0, - 0, 0xFB3F, 0, 0, 0, 0xFB3C, 0, 0xE54F, - 0, 0xE54E, 0xE551, 0xFB49, 0, 0x7D47, 0, 0, -}; -static const unsigned short utf8_to_euc_E990[] = { - 0, 0xE554, 0xE555, 0x6F3F, 0xE556, 0, 0, 0x6F40, - 0xE557, 0xE558, 0, 0, 0, 0xE559, 0xE55A, 0xE55B, - 0x6F41, 0, 0, 0x6F3E, 0x6F3D, 0xE55C, 0xE55D, 0xE55E, - 0x3E62, 0x462A, 0x6F3C, 0, 0, 0, 0, 0xE55F, - 0, 0x6F45, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0x6F43, 0, 0, 0xE560, 0xE561, - 0, 0xE562, 0xE563, 0xE564, 0xE565, 0x6F44, 0x6F42, 0, - 0x4278, 0, 0x6F46, 0xE566, 0, 0xE568, 0, 0xE567, -}; -static const unsigned short utf8_to_euc_E990_x0213[] = { - 0, 0xE554, 0xE555, 0x6F3F, 0x7D46, 0, 0, 0x6F40, - 0xE557, 0xFB45, 0, 0, 0, 0xE559, 0xE55A, 0xFB46, - 0x6F41, 0, 0, 0x6F3E, 0x6F3D, 0xE55C, 0xFB47, 0xFB48, - 0x3E62, 0x462A, 0x6F3C, 0, 0, 0, 0, 0xE55F, - 0, 0x6F45, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0x6F43, 0, 0, 0xE560, 0xE561, - 0, 0, 0xFB4A, 0x7D48, 0xFB4B, 0x6F44, 0x6F42, 0, - 0x4278, 0, 0x6F46, 0xFB4C, 0, 0xE568, 0, 0xE567, -}; -static const unsigned short utf8_to_euc_E991[] = { - 0, 0x6F47, 0, 0xE569, 0x6F49, 0xE56A, 0, 0, - 0xE56B, 0, 0xE56C, 0, 0xE56D, 0, 0, 0, - 0, 0x3455, 0x6F48, 0x4C7A, 0, 0xE56E, 0, 0, - 0, 0xE56F, 0x6F54, 0x6F4A, 0xE570, 0, 0x6F4D, 0xE571, - 0x6F4B, 0xE572, 0x6F4C, 0xE573, 0, 0, 0, 0, - 0xE574, 0, 0x6F4E, 0xE575, 0, 0xE576, 0xE577, 0xE578, - 0x6F50, 0xE579, 0xE57A, 0, 0, 0x6F51, 0, 0x6F52, - 0, 0, 0, 0, 0x6F55, 0x6F53, 0x6F56, 0x6F58, -}; -static const unsigned short utf8_to_euc_E991_x0213[] = { - 0, 0x6F47, 0, 0xE569, 0x6F49, 0xFB4D, 0, 0, - 0, 0, 0x7D49, 0, 0xE56D, 0, 0, 0, - 0, 0x3455, 0x6F48, 0x4C7A, 0, 0xE56E, 0, 0, - 0, 0xE56F, 0x6F54, 0x6F4A, 0xE570, 0, 0x6F4D, 0xE571, - 0x6F4B, 0xE572, 0x6F4C, 0x7D4A, 0, 0, 0, 0, - 0xE574, 0, 0x6F4E, 0x7D4B, 0, 0xFB50, 0xE577, 0xFB51, - 0x6F50, 0x7D4C, 0x7D4D, 0, 0, 0x6F51, 0, 0x6F52, - 0, 0, 0, 0, 0x6F55, 0x6F53, 0x6F56, 0x6F58, -}; -static const unsigned short utf8_to_euc_E992[] = { - 0, 0x6F57, 0, 0xE57C, 0xE57B, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E995[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0x4439, - 0xE57D, 0xE57E, 0, 0, 0, 0, 0xE621, 0, -}; -static const unsigned short utf8_to_euc_E995_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0x4439, - 0xFB52, 0xFB53, 0, 0, 0, 0, 0xE621, 0, -}; -static const unsigned short utf8_to_euc_E996[] = { - 0x4C67, 0, 0x6F59, 0x412E, 0xE622, 0, 0, 0x6F5A, - 0xE623, 0x4A44, 0x6F5B, 0x332B, 0xE624, 0xE625, 0xE626, 0x313C, - 0, 0x3457, 0xF471, 0x3456, 0x6F5C, 0, 0x6F5D, 0, - 0x6F5E, 0x6F5F, 0, 0, 0, 0xE627, 0xE628, 0xE629, - 0x6F60, 0xE62A, 0x3458, 0x3355, 0x395E, 0x4836, 0xE62B, 0x6F62, - 0x6F61, 0xE62C, 0, 0xE62D, 0xE62E, 0x6F63, 0, 0, - 0, 0, 0x315C, 0, 0xE62F, 0, 0xE630, 0, - 0, 0x6F66, 0xE631, 0x6F65, 0x6F64, 0xE632, 0x6F67, 0xE633, -}; -static const unsigned short utf8_to_euc_E996_x0213[] = { - 0x4C67, 0, 0x6F59, 0x412E, 0xE622, 0, 0xFB54, 0x6F5A, - 0xE623, 0x4A44, 0x6F5B, 0x332B, 0xFB55, 0xFB56, 0x7D4E, 0x313C, - 0, 0x3457, 0, 0x3456, 0x6F5C, 0, 0x6F5D, 0, - 0x6F5E, 0x6F5F, 0, 0, 0, 0xE627, 0xE628, 0x7D4F, - 0x6F60, 0xE62A, 0x3458, 0x3355, 0x395E, 0x4836, 0x7D50, 0x6F62, - 0x6F61, 0x7D51, 0, 0xFB58, 0x7D52, 0x6F63, 0, 0, - 0, 0, 0x315C, 0, 0xFB59, 0, 0x7D53, 0, - 0, 0x6F66, 0xE631, 0x6F65, 0x6F64, 0x7D54, 0x6F67, 0xE633, -}; -static const unsigned short utf8_to_euc_E997[] = { - 0, 0, 0, 0x6F6A, 0, 0, 0xE634, 0x3047, - 0xE635, 0xE636, 0x6F68, 0xE637, 0x6F6C, 0x6F6B, 0, 0, - 0xE638, 0xE639, 0xE63A, 0xE63B, 0x6F6E, 0x6F6D, 0x6F6F, 0, - 0x462E, 0xE63C, 0xE63D, 0, 0x6F70, 0xE63E, 0xE63F, 0xE640, - 0xE641, 0x6F71, 0x6F73, 0, 0xE642, 0x6F72, 0xE643, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E997_x0213[] = { - 0, 0, 0, 0x6F6A, 0, 0, 0xE634, 0x3047, - 0xFB5B, 0xE636, 0x6F68, 0x7D55, 0x6F6C, 0x6F6B, 0, 0, - 0x7D56, 0xE639, 0xE63A, 0x7D57, 0x6F6E, 0x6F6D, 0x6F6F, 0, - 0x462E, 0xE63C, 0x7D59, 0, 0x6F70, 0xE63E, 0x7D5A, 0xE640, - 0xE641, 0x6F71, 0x6F73, 0, 0xE642, 0x6F72, 0xE643, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E998[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0x496C, 0xE644, 0xE645, 0, - 0, 0x6F74, 0xE646, 0, 0xE647, 0xE648, 0xE649, 0, - 0x6F75, 0, 0x3A65, 0, 0xE64A, 0, 0x6F76, 0x6F77, - 0, 0xE64B, 0x4B49, 0xE64C, 0, 0, 0, 0xE64D, - 0xE64E, 0xE64F, 0xE650, 0x414B, 0xE651, 0xE652, 0, 0x3024, -}; -static const unsigned short utf8_to_euc_E998_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0x496C, 0xFA25, 0xE645, 0, - 0, 0x6F74, 0xE646, 0, 0xE647, 0xE648, 0xE649, 0, - 0x6F75, 0, 0x3A65, 0, 0xFB5E, 0, 0x6F76, 0x6F77, - 0, 0xE64B, 0x4B49, 0xFB5F, 0xFB60, 0, 0, 0xE64D, - 0xE64E, 0xE64F, 0xE650, 0x414B, 0xFB62, 0xE652, 0, 0x3024, -}; -static const unsigned short utf8_to_euc_E999[] = { - 0x424B, 0xE653, 0x6F78, 0, 0x496D, 0, 0, 0, - 0, 0, 0, 0x6F7B, 0x6F79, 0x395F, 0, 0x6F7A, - 0x3842, 0, 0xE654, 0, 0xE655, 0, 0xE656, 0xE657, - 0xE658, 0, 0, 0x4A45, 0x6F7D, 0x7021, 0x6F7E, 0x7022, - 0, 0xE659, 0x3121, 0x3F58, 0x3D7C, 0x3459, 0x7023, 0, - 0, 0, 0x4766, 0, 0x7025, 0, 0xE65A, 0, - 0x3122, 0, 0x7024, 0x4444, 0xE65B, 0x4E4D, 0x462B, 0x6F7C, - 0x4E26, 0, 0x3831, 0xE65C, 0xE65D, 0x4D5B, 0xE65E, 0xE65F, -}; -static const unsigned short utf8_to_euc_E999_x0213[] = { - 0x424B, 0xFB63, 0x6F78, 0, 0x496D, 0, 0, 0, - 0, 0, 0, 0x6F7B, 0x6F79, 0x395F, 0, 0x6F7A, - 0x3842, 0, 0xE654, 0, 0xE655, 0, 0xE656, 0xE657, - 0x7D5B, 0, 0, 0x4A45, 0x6F7D, 0x7021, 0x6F7E, 0x7022, - 0, 0xFB64, 0x3121, 0x3F58, 0x3D7C, 0x3459, 0x7023, 0, - 0, 0, 0x4766, 0, 0x7025, 0, 0xE65A, 0, - 0x3122, 0, 0x7024, 0x4444, 0xE65B, 0x4E4D, 0x462B, 0x6F7C, - 0x4E26, 0, 0x3831, 0xE65C, 0xE65D, 0x4D5B, 0xE65E, 0xE65F, -}; -static const unsigned short utf8_to_euc_E99A[] = { - 0, 0xE660, 0xE661, 0xE662, 0xE663, 0x3679, 0x4E34, 0, - 0x3728, 0xE664, 0x4262, 0x6721, 0, 0x7026, 0x332C, 0x3F6F, - 0, 0xE665, 0, 0, 0x3356, 0x7028, 0xE666, 0x7029, - 0x7027, 0x3764, 0xE667, 0x3A5D, 0x3E63, 0xE668, 0, 0xE669, - 0x3123, 0, 0, 0x4E59, 0xE66A, 0xE66B, 0xE66C, 0x702B, - 0x6E2E, 0xE66D, 0x702A, 0, 0, 0, 0xE66E, 0xE66F, - 0x702E, 0x702C, 0x702D, 0xE670, 0x702F, 0, 0x7030, 0x4E6C, - 0x7031, 0x7032, 0xE671, 0x4049, 0x483B, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E99A_x0213[] = { - 0, 0xE660, 0xFB66, 0xE662, 0x7D5C, 0x3679, 0x4E34, 0, - 0x3728, 0xE664, 0x4262, 0x6721, 0, 0x7026, 0x332C, 0x3F6F, - 0, 0xE665, 0, 0, 0x3356, 0x7028, 0xE666, 0x7029, - 0x7027, 0x3764, 0xFB68, 0x3A5D, 0x3E63, 0x7D5E, 0, 0xE669, - 0x3123, 0, 0, 0x4E59, 0x7D5F, 0x7D60, 0xE66C, 0x702B, - 0x6E2E, 0xFB6B, 0x702A, 0, 0, 0, 0xE66E, 0xFB6C, - 0x702E, 0x702C, 0x702D, 0xFB6D, 0x702F, 0, 0x7030, 0x4E6C, - 0x7031, 0x7032, 0xFB6E, 0x4049, 0x483B, 0xFB6F, 0, 0, -}; -static const unsigned short utf8_to_euc_E99B[] = { - 0x3F7D, 0x3467, 0, 0, 0x4D3A, 0x326D, 0x3D38, 0x385B, - 0, 0x7035, 0xE672, 0x7034, 0x3B73, 0x7036, 0x7033, 0, - 0, 0x3B28, 0xE673, 0, 0, 0x703A, 0x6A2D, 0, - 0xE675, 0x5256, 0xE676, 0x3F77, 0x7038, 0xE677, 0xE678, 0xE679, - 0, 0, 0x4E25, 0x4671, 0, 0, 0, 0, - 0x312B, 0xE67A, 0x4063, 0x3C36, 0, 0, 0, 0xE67B, - 0x4A37, 0xE67C, 0x3140, 0, 0, 0, 0x4E6D, 0x4D6B, - 0, 0x703B, 0xE67D, 0x4545, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E99B_x0213[] = { - 0x3F7D, 0x3467, 0, 0, 0x4D3A, 0x326D, 0x3D38, 0x385B, - 0, 0x7035, 0xE672, 0x7034, 0x3B73, 0x7036, 0x7033, 0, - 0, 0x3B28, 0x7D61, 0, 0, 0x703A, 0x6A2D, 0, - 0xFB72, 0x5256, 0xFB73, 0x3F77, 0x7038, 0xFB74, 0x7D62, 0xE679, - 0, 0, 0x4E25, 0x4671, 0, 0, 0, 0, - 0x312B, 0x7D64, 0x4063, 0x3C36, 0, 0, 0, 0x7D65, - 0x4A37, 0xE67C, 0x3140, 0, 0, 0, 0x4E6D, 0x4D6B, - 0, 0x703B, 0xE67D, 0x4545, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E99C[] = { - 0x3C7B, 0, 0xE67E, 0xE721, 0x703C, 0xE722, 0x703D, 0x3F4C, - 0x703E, 0xE723, 0x4E6E, 0, 0, 0x7039, 0x7040, 0x7042, - 0, 0x7041, 0, 0x703F, 0, 0, 0x7043, 0, - 0, 0x7044, 0xE724, 0xE725, 0x417A, 0xE726, 0x3262, 0, - 0, 0xE727, 0xE728, 0xE729, 0x7045, 0, 0, 0x4C38, - 0xE72A, 0, 0x7046, 0, 0, 0, 0, 0, - 0x7047, 0xE72B, 0x4F2A, 0xE72C, 0, 0, 0, 0, - 0x5B31, 0x7048, 0, 0xF474, 0, 0x7049, 0x704A, 0, -}; -static const unsigned short utf8_to_euc_E99C_x0213[] = { - 0x3C7B, 0, 0xE67E, 0xE721, 0x703C, 0xE722, 0x703D, 0x3F4C, - 0x703E, 0xE723, 0x4E6E, 0, 0, 0x7039, 0x7040, 0x7042, - 0, 0x7041, 0, 0x703F, 0xFB76, 0, 0x7043, 0, - 0, 0x7044, 0xE724, 0xE725, 0x417A, 0xE726, 0x3262, 0, - 0, 0xE727, 0xE728, 0xFB77, 0x7045, 0, 0, 0x4C38, - 0xE72A, 0, 0x7046, 0, 0, 0, 0, 0, - 0x7047, 0xE72B, 0x4F2A, 0x7D66, 0, 0, 0xFB79, 0, - 0x5B31, 0x7048, 0, 0x7D67, 0, 0x7049, 0x704A, 0, -}; -static const unsigned short utf8_to_euc_E99D[] = { - 0, 0xE72D, 0x704E, 0xE72E, 0x704B, 0, 0x704C, 0, - 0x704D, 0x704F, 0xE72F, 0, 0, 0xF475, 0xE730, 0xE731, - 0, 0xF476, 0x4044, 0, 0, 0xE732, 0x4C77, 0xE733, - 0xE734, 0x4045, 0xE735, 0xE736, 0x7050, 0, 0x4873, 0, - 0x7051, 0x7353, 0x4C4C, 0xE737, 0x7052, 0, 0x7053, 0xE738, - 0x7054, 0x3357, 0xE739, 0x7056, 0, 0x3F59, 0xE73A, 0, - 0, 0x7057, 0, 0xE73B, 0x3724, 0, 0xE73C, 0xE73D, - 0xE73E, 0x7058, 0x705C, 0xE73F, 0x705A, 0xE740, 0, 0xE741, -}; -static const unsigned short utf8_to_euc_E99D_x0213[] = { - 0, 0xFB7A, 0x704E, 0, 0x704B, 0, 0x704C, 0xFB7B, - 0x704D, 0x704F, 0xE72F, 0, 0, 0x7D68, 0x7D69, 0x7D6A, - 0, 0, 0x4044, 0, 0, 0xFB7C, 0x4C77, 0xFB7D, - 0xE734, 0x4045, 0x7D6B, 0xFB7E, 0x7050, 0, 0x4873, 0, - 0x7051, 0x7353, 0x4C4C, 0xE737, 0x7052, 0, 0x7053, 0xE738, - 0x7054, 0x3357, 0xFC21, 0x7056, 0, 0x3F59, 0x7D6C, 0, - 0, 0x7057, 0, 0x7D6D, 0x3724, 0, 0xE73C, 0xE73D, - 0xE73E, 0x7058, 0x705C, 0xE73F, 0x705A, 0xE740, 0, 0xE741, -}; -static const unsigned short utf8_to_euc_E99E[] = { - 0xE742, 0x705B, 0, 0, 0x3373, 0x7059, 0x705D, 0, - 0, 0xE743, 0, 0x705E, 0, 0x3048, 0, 0x705F, - 0x7060, 0, 0, 0, 0, 0xE744, 0xE745, 0xE746, - 0x3E64, 0xE747, 0xE748, 0, 0x7061, 0, 0xE749, 0xE74A, - 0x3547, 0, 0xE74B, 0x7064, 0, 0, 0x7063, 0, - 0x7062, 0, 0, 0x6B71, 0xE74C, 0x4A5C, 0xE74D, 0, - 0, 0xE74E, 0xE74F, 0x7065, 0x7066, 0xE750, 0xE751, 0, - 0xE752, 0xE753, 0xE754, 0, 0xE755, 0, 0xE756, 0xE757, -}; -static const unsigned short utf8_to_euc_E99E_x0213[] = { - 0xE742, 0x705B, 0, 0, 0x3373, 0x7059, 0x705D, 0, - 0, 0xE743, 0, 0x705E, 0, 0x3048, 0, 0x705F, - 0x7060, 0, 0, 0, 0, 0x7D6E, 0xFC24, 0xE746, - 0x3E64, 0xE747, 0xFC25, 0, 0x7061, 0, 0xFC26, 0xE74A, - 0x3547, 0, 0xFC27, 0x7064, 0, 0, 0x7063, 0, - 0x7062, 0, 0, 0x6B71, 0xE74C, 0x4A5C, 0x7D6F, 0, - 0, 0xFC28, 0xFC29, 0x7065, 0x7066, 0xE750, 0xE751, 0, - 0xE752, 0xE753, 0x7D70, 0, 0xE755, 0, 0xFC2A, 0xE757, -}; -static const unsigned short utf8_to_euc_E99F[] = { - 0, 0xE758, 0, 0x7067, 0xE759, 0xE75A, 0x7068, 0xE75B, - 0x7069, 0xE75C, 0xE75D, 0x706A, 0xE75E, 0xE75F, 0xE760, 0, - 0xE761, 0xE762, 0, 0x345A, 0xE763, 0, 0, 0xE764, - 0xE765, 0xE766, 0, 0xE76A, 0x706B, 0xE767, 0xE768, 0, - 0xE769, 0xE76B, 0, 0, 0xE76C, 0, 0, 0, - 0, 0, 0, 0, 0, 0x706C, 0x4723, 0xE76D, - 0, 0xE76E, 0x706E, 0x323B, 0xE76F, 0x7071, 0x7070, 0xE770, - 0xE771, 0, 0xE772, 0x3124, 0, 0, 0, 0x3641, -}; -static const unsigned short utf8_to_euc_E99F_x0213[] = { - 0, 0x7D71, 0, 0x7067, 0xE759, 0xE75A, 0x7068, 0xE75B, - 0x7069, 0x7D72, 0xE75D, 0x706A, 0xFC2B, 0xE75F, 0xE760, 0, - 0xE761, 0xFC2C, 0, 0x345A, 0xFC2D, 0, 0, 0xE764, - 0xFC2E, 0xFC2F, 0, 0x7D74, 0x706B, 0xE767, 0x7D73, 0, - 0xE769, 0xFC30, 0, 0, 0xE76C, 0, 0, 0, - 0, 0, 0, 0, 0, 0x706C, 0x4723, 0xE76D, - 0, 0xFC31, 0x706E, 0x323B, 0x7D75, 0x7071, 0x7070, 0xE770, - 0xE771, 0, 0xE772, 0x3124, 0, 0, 0, 0x3641, -}; -static const unsigned short utf8_to_euc_E9A0[] = { - 0, 0x4A47, 0x443A, 0x3A22, 0, 0x3960, 0x3D67, 0xE773, - 0x3F5C, 0, 0xE774, 0, 0x7073, 0xE776, 0xE777, 0x7072, - 0x4D42, 0x3468, 0x4852, 0x465C, 0xE778, 0, 0xE779, 0x3F7C, - 0x4E4E, 0xE775, 0x375B, 0, 0xE77A, 0, 0xE77B, 0, - 0xE77C, 0x7076, 0, 0xE77D, 0x7075, 0xE828, 0xE77E, 0, - 0, 0, 0, 0xE821, 0x4B4B, 0x462C, 0xE822, 0xE823, - 0xE824, 0, 0xE825, 0xE826, 0x3150, 0xE827, 0, 0x7077, - 0x7074, 0, 0, 0x4951, 0x4D6A, 0x7078, 0xE829, 0, -}; -static const unsigned short utf8_to_euc_E9A0_x0213[] = { - 0, 0x4A47, 0x443A, 0x3A22, 0xFC32, 0x3960, 0x3D67, 0xE773, - 0x3F5C, 0, 0x7D77, 0, 0x7073, 0xFC33, 0xFC34, 0x7072, - 0x4D42, 0x3468, 0x4852, 0x465C, 0xFC35, 0, 0xFC36, 0x3F7C, - 0x4E4E, 0xE775, 0x375B, 0, 0xE77A, 0, 0x7D78, 0, - 0xE77C, 0x7076, 0, 0xFC39, 0x7075, 0xFC3C, 0xE77E, 0, - 0, 0, 0, 0x7D79, 0x4B4B, 0x462C, 0xE822, 0xE823, - 0x7D7A, 0, 0xFC3A, 0xFC3B, 0x3150, 0xE827, 0, 0x7077, - 0x7074, 0, 0, 0x4951, 0x4D6A, 0x7078, 0xE829, 0, -}; -static const unsigned short utf8_to_euc_E9A1[] = { - 0, 0, 0, 0, 0xE82A, 0, 0x7079, 0xE82B, - 0, 0, 0xE82C, 0x707B, 0x426A, 0x335B, 0x335C, 0x707A, - 0, 0xE82D, 0xE82E, 0xE82F, 0x3469, 0x3832, 0xE830, 0xE831, - 0x346A, 0xE832, 0xE833, 0x453F, 0, 0, 0x4E60, 0, - 0, 0, 0xE834, 0xE835, 0, 0xE836, 0xE837, 0x385C, - 0, 0, 0xE838, 0x707C, 0xE839, 0, 0, 0x707D, - 0x707E, 0x7121, 0, 0x7123, 0x7122, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E9A1_x0213[] = { - 0, 0, 0, 0, 0xE82A, 0, 0x7079, 0xFC3D, - 0, 0, 0xE82C, 0x707B, 0x426A, 0x335B, 0x335C, 0x707A, - 0, 0xE82D, 0x7D7C, 0x7D7D, 0x3469, 0x3832, 0x7D7E, 0x7E21, - 0x346A, 0x7E22, 0x7E23, 0x453F, 0, 0, 0x4E60, 0, - 0, 0, 0xE834, 0xE835, 0, 0x7E25, 0xFC3E, 0x385C, - 0, 0, 0xE838, 0x707C, 0x7E26, 0, 0, 0x707D, - 0x707E, 0x7121, 0, 0x7123, 0x7122, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E9A2[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x4977, 0, 0x7124, 0xE83A, 0, 0xE83B, 0xE83C, 0x7125, - 0xE83D, 0x7126, 0, 0, 0xE83E, 0, 0x7127, 0xE83F, - 0xE840, 0, 0xE841, 0xE842, 0, 0, 0, 0xE843, -}; -static const unsigned short utf8_to_euc_E9A2_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x4977, 0, 0x7124, 0xFC3F, 0, 0xFC40, 0xE83C, 0x7125, - 0xFC41, 0x7126, 0, 0, 0xE83E, 0, 0x7127, 0xFC43, - 0xFC44, 0, 0x7E27, 0xFC45, 0xFC46, 0, 0, 0xFC47, -}; -static const unsigned short utf8_to_euc_E9A3[] = { - 0, 0, 0xE844, 0x7129, 0x7128, 0xE845, 0x712A, 0, - 0xE846, 0, 0, 0, 0xE847, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0x4874, 0x664C, 0, 0, 0x3F29, - 0, 0xE848, 0x3532, 0xE849, 0, 0xE84A, 0xE84B, 0xE84C, - 0, 0x712B, 0xE84D, 0x712C, 0, 0x522C, 0x5D3B, 0x4853, - 0, 0, 0x307B, 0xE84E, 0x303B, 0, 0xE84F, 0, - 0, 0, 0, 0, 0x3B74, 0x4B30, 0x3E7E, 0, -}; -static const unsigned short utf8_to_euc_E9A3_x0213[] = { - 0, 0, 0xFC48, 0x7129, 0x7128, 0xE845, 0x712A, 0xFC49, - 0x7E28, 0, 0, 0xFC4A, 0xE847, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0x4874, 0x664C, 0, 0, 0x3F29, - 0xFC4B, 0xFC4D, 0x3532, 0xFC4E, 0, 0xFC4F, 0xE84B, 0x7E29, - 0, 0x712B, 0xFC50, 0x712C, 0, 0x522C, 0x5D3B, 0x4853, - 0xFC51, 0xFC52, 0x307B, 0xFC53, 0x303B, 0, 0xE84F, 0, - 0, 0, 0, 0, 0x3B74, 0x4B30, 0x3E7E, 0, -}; -static const unsigned short utf8_to_euc_E9A4[] = { - 0, 0, 0xE850, 0x712D, 0, 0x4C5F, 0, 0xE851, - 0xE852, 0x712E, 0x4D5C, 0, 0x3142, 0, 0, 0, - 0x3B41, 0xE853, 0x712F, 0x326E, 0x7130, 0xE854, 0xE855, 0xE856, - 0x7131, 0, 0xE857, 0xE858, 0xE859, 0x7133, 0x7134, 0xE85A, - 0x7136, 0x7132, 0xE85B, 0, 0x7135, 0, 0xE85C, 0xE85D, - 0x345B, 0, 0, 0xE85E, 0x7137, 0, 0x7138, 0, - 0, 0xE85F, 0xE860, 0xE861, 0xE862, 0xE863, 0, 0, - 0, 0xE864, 0xE865, 0xE866, 0xE867, 0x7139, 0x713A, 0, -}; -static const unsigned short utf8_to_euc_E9A4_x0213[] = { - 0, 0, 0xE850, 0x712D, 0, 0x4C5F, 0, 0xE851, - 0xFC54, 0x712E, 0x4D5C, 0, 0x3142, 0, 0, 0, - 0x3B41, 0xE853, 0x712F, 0x326E, 0x7130, 0xE854, 0xFC57, 0xFC58, - 0x7131, 0, 0xFC5A, 0xFC5B, 0xFC5C, 0x7133, 0x7134, 0xE85A, - 0x7136, 0x7132, 0xE85B, 0, 0x7135, 0, 0xE85C, 0, - 0x345B, 0, 0, 0xE85E, 0x7137, 0, 0x7138, 0, - 0, 0xFC5E, 0xFC5F, 0xFC60, 0xE862, 0xE863, 0, 0, - 0, 0xE864, 0xFC61, 0xFC62, 0xFC63, 0x7139, 0x713A, 0, -}; -static const unsigned short utf8_to_euc_E9A5[] = { - 0xE868, 0xE869, 0x713B, 0, 0, 0x713D, 0xE86A, 0xE86B, - 0xE86C, 0x713C, 0, 0x713F, 0x7142, 0xE86D, 0xE86E, 0, - 0x713E, 0x7140, 0x7141, 0, 0xE86F, 0x7143, 0, 0x3642, - 0xE870, 0xE871, 0, 0xE872, 0xE873, 0, 0xE874, 0xE875, - 0xE876, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E9A5_x0213[] = { - 0xFC64, 0xFC65, 0x713B, 0, 0, 0x713D, 0xFC66, 0xE86B, - 0xE86C, 0x713C, 0, 0x713F, 0x7142, 0xFC67, 0xFC68, 0, - 0x713E, 0x7140, 0x7141, 0, 0xE86F, 0x7143, 0, 0x3642, - 0x7E2A, 0xE871, 0, 0xE872, 0xFC69, 0, 0xE874, 0xFC6A, - 0xFC6B, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E9A6[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0x3C73, 0x7144, - 0x7145, 0x3961, 0, 0xE877, 0, 0xE878, 0xF47A, 0xE879, - 0, 0, 0, 0, 0, 0x7146, 0xE87A, 0, - 0x333E, 0, 0, 0, 0x474F, 0x7147, 0x7148, 0, - 0xE87B, 0xE87C, 0xE87D, 0x435A, 0x466B, 0xE87E, 0, 0, - 0, 0xE921, 0xE922, 0, 0x7149, 0xE923, 0, 0xE924, -}; -static const unsigned short utf8_to_euc_E9A6_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0x3C73, 0x7144, - 0x7145, 0x3961, 0, 0xE877, 0, 0xE878, 0x7E2B, 0xE879, - 0, 0, 0, 0xFC6C, 0, 0x7146, 0xFC6D, 0, - 0x333E, 0, 0, 0, 0x474F, 0x7147, 0x7148, 0, - 0xE87B, 0xE87C, 0xE87D, 0x435A, 0x466B, 0xE87E, 0, 0, - 0, 0xFC6E, 0xE922, 0, 0x7149, 0xFC6F, 0, 0xFC70, -}; -static const unsigned short utf8_to_euc_E9A7[] = { - 0, 0x477D, 0, 0xE925, 0x424C, 0x3158, 0x366E, 0, - 0x366F, 0xE926, 0, 0, 0, 0, 0, 0, - 0x4373, 0x714E, 0x3670, 0xE927, 0xE928, 0x326F, 0, 0, - 0x714D, 0xE929, 0xE92A, 0x714B, 0xE92B, 0x714C, 0xE92C, 0x714A, - 0, 0, 0x7158, 0, 0, 0, 0, 0xE92D, - 0, 0, 0xE92E, 0xE92F, 0xE930, 0x714F, 0x7150, 0, - 0xE931, 0x7151, 0x7152, 0, 0xE932, 0xE933, 0, 0, - 0x7154, 0xE934, 0, 0x7153, 0, 0xE935, 0xE936, 0x3D59, -}; -static const unsigned short utf8_to_euc_E9A7_x0213[] = { - 0, 0x477D, 0, 0xFC71, 0x424C, 0x3158, 0x366E, 0, - 0x366F, 0xFC72, 0, 0, 0, 0, 0, 0, - 0x4373, 0x714E, 0x3670, 0xE927, 0xFC73, 0x326F, 0, 0, - 0x714D, 0xFC74, 0xE92A, 0x714B, 0xE92B, 0x714C, 0xFC75, 0x714A, - 0, 0, 0x7158, 0, 0, 0, 0, 0xE92D, - 0, 0, 0xE92E, 0xE92F, 0xE930, 0x714F, 0x7150, 0, - 0xFC77, 0x7151, 0x7152, 0, 0xE932, 0xE933, 0, 0, - 0x7154, 0xFC78, 0, 0x7153, 0xFC79, 0xE935, 0xE936, 0x3D59, -}; -static const unsigned short utf8_to_euc_E9A8[] = { - 0, 0x7155, 0xE937, 0xE938, 0xE939, 0x7157, 0, 0, - 0, 0, 0, 0xE93A, 0xE93B, 0, 0x3533, 0x7156, - 0xE93C, 0xE93D, 0x417B, 0x3833, 0, 0, 0xE93E, 0, - 0, 0x7159, 0, 0, 0, 0, 0xE93F, 0, - 0xE940, 0, 0xE941, 0xE942, 0xE943, 0, 0, 0xE944, - 0x424D, 0, 0, 0x715A, 0, 0xE945, 0xE946, 0, - 0x462D, 0, 0, 0xE947, 0, 0xE948, 0xE949, 0x715B, - 0xE94A, 0, 0, 0, 0, 0, 0x7160, 0, -}; -static const unsigned short utf8_to_euc_E9A8_x0213[] = { - 0, 0x7155, 0x7E2C, 0x7E2D, 0xE939, 0x7157, 0, 0, - 0, 0, 0xFC7A, 0xE93A, 0xE93B, 0, 0x3533, 0x7156, - 0xE93C, 0xFC7B, 0x417B, 0x3833, 0, 0, 0xFC7C, 0, - 0, 0x7159, 0xFC7D, 0, 0, 0, 0xE93F, 0, - 0xFC7E, 0, 0xE941, 0xE942, 0x7E2E, 0, 0, 0xE944, - 0x424D, 0, 0, 0x715A, 0, 0x7E2F, 0x7E30, 0, - 0x462D, 0xFD21, 0, 0xE947, 0, 0xE948, 0xFD22, 0x715B, - 0x7E31, 0, 0, 0, 0, 0, 0x7160, 0, -}; -static const unsigned short utf8_to_euc_E9A9[] = { - 0x715E, 0xE94C, 0x715D, 0x715F, 0xE94D, 0x715C, 0, 0xE94B, - 0, 0, 0xE94E, 0xE94F, 0xE950, 0x7162, 0xE951, 0, - 0, 0xE952, 0, 0, 0xE953, 0x7161, 0xE954, 0x7164, - 0, 0, 0x3643, 0x7163, 0, 0xE955, 0, 0x7165, - 0, 0, 0x7166, 0, 0x7168, 0x7167, 0, 0, - 0, 0x7169, 0x716B, 0x716A, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E9A9_x0213[] = { - 0x715E, 0xE94C, 0x715D, 0x715F, 0xFD23, 0x715C, 0, 0xE94B, - 0, 0, 0x7E32, 0xE94F, 0xFD24, 0x7162, 0x7E33, 0, - 0, 0xE952, 0x7E34, 0, 0xE953, 0x7161, 0xE954, 0x7164, - 0xFD25, 0, 0x3643, 0x7163, 0, 0xE955, 0, 0x7165, - 0, 0, 0x7166, 0, 0x7168, 0x7167, 0, 0, - 0, 0x7169, 0x716B, 0x716A, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E9AA[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x397C, 0, 0xE956, 0, 0xE957, 0x716C, 0xE958, 0xE959, - 0x716D, 0, 0xE95A, 0, 0xE95B, 0xE95C, 0xE95D, 0, - 0x333C, 0xE95E, 0, 0xE95F, 0x716E, 0, 0xE960, 0xE961, -}; -static const unsigned short utf8_to_euc_E9AA_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x397C, 0, 0xE956, 0, 0xE957, 0x716C, 0xE958, 0xFD27, - 0x716D, 0, 0xE95A, 0, 0xE95B, 0xE95C, 0x7E35, 0xFD29, - 0x333C, 0xFD2B, 0, 0xE95F, 0x716E, 0, 0xE960, 0xE961, -}; -static const unsigned short utf8_to_euc_E9AB[] = { - 0x716F, 0xE962, 0, 0xE963, 0x3F71, 0, 0xE964, 0, - 0xE965, 0, 0, 0, 0, 0, 0xE966, 0x7170, - 0xE967, 0x7171, 0xE968, 0x7172, 0x7173, 0xE969, 0xE96A, 0xE96B, - 0x3962, 0xF47B, 0, 0xE96C, 0xE96D, 0, 0x7174, 0x7175, - 0xE96E, 0, 0x7176, 0x7177, 0xE96F, 0xE970, 0x7178, 0xE971, - 0, 0xE972, 0x4831, 0x717A, 0xE973, 0x4926, 0x717B, 0x7179, - 0, 0x717D, 0xE974, 0xE975, 0x717C, 0xE976, 0, 0x717E, - 0, 0xE977, 0xE978, 0x7221, 0, 0xE979, 0, 0xE97A, -}; -static const unsigned short utf8_to_euc_E9AB_x0213[] = { - 0x716F, 0x7E36, 0, 0x7E37, 0x3F71, 0, 0xFD2D, 0, - 0xE965, 0, 0, 0, 0, 0, 0x7E38, 0x7170, - 0xFD2E, 0x7171, 0xFD2F, 0x7172, 0x7173, 0xFD30, 0x7E39, 0xE96B, - 0x3962, 0, 0, 0xE96C, 0xFD32, 0, 0x7174, 0x7175, - 0xFD33, 0, 0x7176, 0x7177, 0xE96F, 0xFD34, 0x7178, 0xE971, - 0, 0xFD35, 0x4831, 0x717A, 0xE973, 0x4926, 0x717B, 0x7179, - 0, 0x717D, 0xE974, 0xE975, 0x717C, 0xE976, 0, 0x717E, - 0, 0x7E3A, 0xE978, 0x7221, 0, 0xE979, 0, 0xE97A, -}; -static const unsigned short utf8_to_euc_E9AC[] = { - 0xE97B, 0xE97C, 0xE97D, 0xE97E, 0xEA21, 0xEA22, 0x7222, 0, - 0xEA23, 0xEA24, 0, 0xEA25, 0xEA26, 0xEA27, 0xEA28, 0, - 0xEA29, 0, 0xEA2A, 0, 0, 0, 0xEA2B, 0, - 0x7223, 0xEA2C, 0x7224, 0xEA2D, 0xEA2E, 0, 0, 0x7225, - 0xEA2F, 0, 0x7226, 0x7227, 0, 0x7228, 0xEA30, 0x7229, - 0x722A, 0x722B, 0x722C, 0xEA31, 0, 0xEA32, 0x722D, 0x722E, - 0, 0x5D35, 0x722F, 0xEA33, 0xEA34, 0xEA35, 0, 0xEA36, - 0, 0xEA37, 0xEA38, 0x6478, 0x3534, 0xEA39, 0, 0, -}; -static const unsigned short utf8_to_euc_E9AC_x0213[] = { - 0xE97B, 0xE97C, 0x7E3B, 0xFD36, 0xEA21, 0xEA22, 0x7222, 0, - 0x7E3C, 0xEA24, 0, 0xEA25, 0xFD37, 0xEA27, 0xEA28, 0, - 0xFD38, 0, 0xFD39, 0, 0, 0, 0xFD3A, 0, - 0x7223, 0xEA2C, 0x7224, 0xEA2D, 0xFD3B, 0, 0, 0x7225, - 0x7E3D, 0, 0x7226, 0x7227, 0, 0x7228, 0xEA30, 0x7229, - 0x722A, 0x722B, 0x722C, 0xFD3C, 0, 0x7E3F, 0x722D, 0x722E, - 0, 0x5D35, 0x722F, 0xFD3D, 0xEA34, 0xEA35, 0, 0xEA36, - 0, 0xEA37, 0xEA38, 0x6478, 0x3534, 0xFD3E, 0, 0, -}; -static const unsigned short utf8_to_euc_E9AD[] = { - 0, 0x3321, 0x3A32, 0x7231, 0x7230, 0x4C25, 0, 0, - 0xEA3A, 0, 0, 0xEA3B, 0xEA3C, 0x7233, 0x7234, 0x7232, - 0, 0x7235, 0, 0, 0x4B62, 0xEA3D, 0xEA3E, 0xEA3F, - 0x7236, 0, 0x357B, 0xEA40, 0, 0, 0xEA41, 0, - 0, 0xEA42, 0, 0xEA43, 0, 0xEA44, 0xEA45, 0, - 0xEA46, 0, 0xEA47, 0xEA48, 0xEA49, 0xEA4A, 0xEA4B, 0x4F25, - 0, 0, 0xF47C, 0xEA4C, 0x7237, 0xEA4D, 0, 0xEA4E, - 0xEA4F, 0xEA50, 0, 0, 0, 0, 0, 0xEA51, -}; -static const unsigned short utf8_to_euc_E9AD_x0213[] = { - 0, 0x3321, 0x3A32, 0x7231, 0x7230, 0x4C25, 0, 0, - 0xEA3A, 0, 0, 0xFD40, 0xEA3C, 0x7233, 0x7234, 0x7232, - 0, 0x7235, 0, 0, 0x4B62, 0xEA3D, 0xEA3E, 0xEA3F, - 0x7236, 0, 0x357B, 0xEA40, 0, 0, 0x7E40, 0, - 0, 0xEA42, 0, 0xFD41, 0, 0xFD42, 0x7E42, 0, - 0xEA46, 0, 0xEA47, 0xFD43, 0xFD44, 0xEA4A, 0xEA4B, 0x4F25, - 0, 0, 0x7E43, 0xFD45, 0x7237, 0x7E44, 0xFD46, 0xFD47, - 0xEA4F, 0x7E41, 0, 0, 0, 0, 0, 0xEA51, -}; -static const unsigned short utf8_to_euc_E9AE[] = { - 0xEA52, 0, 0, 0x7239, 0xEA53, 0xEA54, 0xEA55, 0xEA56, - 0, 0xEA57, 0xEA58, 0xEA59, 0, 0xEA5A, 0x303E, 0xEA5B, - 0xEA5C, 0x723A, 0x4A2B, 0x7238, 0xEA5D, 0, 0x723B, 0x723C, - 0, 0, 0xEA5E, 0, 0, 0xEA5F, 0xEA60, 0x723D, - 0x723E, 0, 0, 0, 0, 0, 0xEA61, 0xEA62, - 0x723F, 0xEA63, 0x4B6E, 0x3B2D, 0xEA64, 0x3A7A, 0x412F, 0, - 0xEA65, 0xEA66, 0xEA67, 0, 0x7240, 0, 0, 0xEA68, - 0xEA69, 0x7243, 0, 0xEA6A, 0xEA6B, 0, 0xEA6C, 0xEA6D, -}; -static const unsigned short utf8_to_euc_E9AE_x0213[] = { - 0xEA52, 0, 0, 0x7239, 0x7E45, 0xEA54, 0xEA55, 0xEA56, - 0, 0xEA57, 0x7E46, 0xEA59, 0, 0xEA5A, 0x303E, 0x7E47, - 0xEA5C, 0x723A, 0x4A2B, 0x7238, 0xEA5D, 0, 0x723B, 0x723C, - 0, 0, 0xEA5E, 0, 0, 0xEA5F, 0x7E48, 0x723D, - 0x723E, 0, 0, 0, 0, 0, 0xFD48, 0x7E49, - 0x723F, 0xEA63, 0x4B6E, 0x3B2D, 0xFD49, 0x3A7A, 0x412F, 0, - 0xEA65, 0xFD4A, 0xFD4D, 0, 0x7240, 0, 0, 0xEA68, - 0xFD4E, 0x7243, 0, 0, 0xEA6B, 0, 0xFD4F, 0xEA6D, -}; -static const unsigned short utf8_to_euc_E9AF[] = { - 0x7241, 0xEA6E, 0, 0, 0, 0, 0x7244, 0xEA6F, - 0xEA70, 0x3871, 0x7242, 0, 0, 0, 0xEA71, 0x7245, - 0xEA72, 0x7246, 0x7247, 0, 0x724B, 0, 0x3B2A, 0xEA73, - 0xEA74, 0, 0, 0x4264, 0, 0xEA75, 0, 0xEA76, - 0, 0x724C, 0x7249, 0x7248, 0x724A, 0xEA77, 0, 0xEA78, - 0x375F, 0, 0xEA79, 0xEA7A, 0, 0, 0, 0xEA7B, - 0x7250, 0x724F, 0x724E, 0xEA7C, 0, 0x3033, 0, 0xEA7D, - 0xEA7E, 0xEB21, 0xEB22, 0, 0, 0xEB23, 0, 0xEB24, -}; -static const unsigned short utf8_to_euc_E9AF_x0213[] = { - 0x7241, 0x7E4A, 0, 0, 0, 0, 0x7244, 0xFD50, - 0xEA70, 0x3871, 0x7242, 0, 0, 0, 0x7E4B, 0x7245, - 0xEA72, 0x7246, 0x7247, 0, 0x724B, 0, 0x3B2A, 0xEA73, - 0xFD52, 0, 0, 0x4264, 0, 0xFD53, 0, 0xEA76, - 0, 0x724C, 0x7249, 0x7248, 0x724A, 0x7E4C, 0, 0xFD54, - 0x375F, 0, 0xFD55, 0xFD56, 0, 0, 0xFD58, 0xFD57, - 0x7250, 0x724F, 0x724E, 0xFD51, 0, 0x3033, 0, 0xFD5C, - 0x7E4D, 0xEB21, 0xFD5A, 0, 0, 0x7E4E, 0, 0xEB24, -}; -static const unsigned short utf8_to_euc_E9B0[] = { - 0xEB25, 0, 0xEB26, 0, 0x725A, 0, 0x7256, 0, - 0x7257, 0x7253, 0x7259, 0xEB27, 0x7255, 0x3362, 0, 0xEB28, - 0x4F4C, 0xEB29, 0x7258, 0x7254, 0x7252, 0x7251, 0xEB2A, 0, - 0xEB2B, 0xEB2C, 0xEB2D, 0x725C, 0xEB2E, 0, 0xEB2F, 0, - 0, 0x725F, 0xEB30, 0xEB31, 0x725E, 0x725D, 0xEB32, 0xEB33, - 0xEB34, 0xEB35, 0xEB36, 0, 0, 0x4949, 0x725B, 0x3073, - 0x7260, 0xEB37, 0x7262, 0, 0, 0xEB38, 0xEB39, 0xEB3A, - 0, 0x336F, 0x724D, 0x3137, 0, 0xEB3B, 0x7264, 0, -}; -static const unsigned short utf8_to_euc_E9B0_x0213[] = { - 0x7E4F, 0, 0xEB26, 0, 0x725A, 0, 0x7256, 0, - 0x7257, 0x7253, 0x7259, 0xEB27, 0x7255, 0x3362, 0, 0xEB28, - 0x4F4C, 0xEB29, 0x7258, 0x7254, 0x7252, 0x7251, 0xFD5E, 0, - 0xFD5F, 0xFD60, 0xFD61, 0x725C, 0xEB2E, 0xFD62, 0xEB2F, 0, - 0, 0x725F, 0xFD63, 0x7E50, 0x725E, 0x725D, 0xEB32, 0xFD64, - 0xEB34, 0xFD65, 0xFD66, 0, 0, 0x4949, 0x725B, 0x3073, - 0x7260, 0xFD68, 0x7262, 0, 0, 0xEB38, 0xFD69, 0xFD6A, - 0, 0x336F, 0x724D, 0x3137, 0, 0xEB3B, 0x7264, 0, -}; -static const unsigned short utf8_to_euc_E9B1[] = { - 0, 0xEB3C, 0, 0xEB3D, 0xEB3E, 0xEB3F, 0x7263, 0x7261, - 0x432D, 0xEB40, 0xEB41, 0, 0, 0, 0xEB42, 0xEB43, - 0xEB44, 0, 0x4B70, 0xEB45, 0xEB46, 0, 0xEB47, 0x4E5A, - 0xEB48, 0, 0x7265, 0xEB49, 0xEB50, 0xEB4A, 0xEB4B, 0xEB4C, - 0x7266, 0, 0, 0xEB4D, 0, 0, 0, 0x7267, - 0xEB52, 0xEB4E, 0xEB4F, 0xEB51, 0, 0, 0xEB53, 0, - 0xEB54, 0, 0xEB55, 0, 0, 0xEB56, 0x7268, 0xEB57, - 0x7269, 0, 0, 0xEB58, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E9B1_x0213[] = { - 0, 0x7E51, 0, 0xEB3D, 0xEB3E, 0xFD6B, 0x7263, 0x7261, - 0x432D, 0xFD6E, 0xFD6F, 0, 0, 0, 0xEB42, 0x7E52, - 0x7E53, 0, 0x4B70, 0x7E54, 0xFD71, 0, 0xEB47, 0x4E5A, - 0xFD72, 0, 0x7265, 0xFD73, 0xFD6C, 0xFD74, 0xEB4B, 0xFD75, - 0x7266, 0, 0, 0x7E55, 0, 0x7E56, 0, 0x7267, - 0xEB52, 0xFD76, 0xFD77, 0xFD78, 0, 0xFD79, 0xFD7A, 0, - 0xFD7B, 0, 0xFD7C, 0, 0, 0xFD7D, 0x7268, 0x7E57, - 0x7269, 0, 0xFD7E, 0xEB58, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E9B3[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0x443B, 0xEB59, 0x726A, - 0, 0x4837, 0, 0x726F, 0x726B, 0, 0, 0, - 0x726C, 0, 0xEB5A, 0x4B31, 0x4C44, 0, 0x4650, 0xEB5B, - 0, 0xEB5C, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E9B3_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0x443B, 0xFE21, 0x726A, - 0, 0x4837, 0, 0x726F, 0x726B, 0, 0, 0, - 0x726C, 0, 0xFE22, 0x4B31, 0x4C44, 0, 0x4650, 0xEB5B, - 0, 0xEB5C, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E9B4[] = { - 0, 0, 0xEB5E, 0x7270, 0, 0, 0x7271, 0x463E, - 0x726E, 0x726D, 0, 0xEB5D, 0, 0, 0x322A, 0, - 0, 0xEB5F, 0x7279, 0, 0, 0x7278, 0, 0xEB60, - 0xEB61, 0, 0, 0x3175, 0xEB62, 0xEB63, 0xEB64, 0x7276, - 0, 0, 0, 0x7275, 0, 0, 0x7273, 0, - 0x337B, 0, 0x7272, 0x3C32, 0x3229, 0, 0, 0xEB65, - 0xEB66, 0, 0xEB67, 0xEB68, 0xEB69, 0, 0, 0, - 0, 0, 0xEB6A, 0x3963, 0xEB6B, 0xEB6D, 0x727C, 0x727B, -}; -static const unsigned short utf8_to_euc_E9B4_x0213[] = { - 0, 0, 0xFE24, 0x7270, 0, 0, 0x7271, 0x463E, - 0x726E, 0x726D, 0, 0xFE23, 0, 0, 0x322A, 0, - 0, 0xFE26, 0x7279, 0, 0, 0x7278, 0, 0xFE27, - 0xFE28, 0, 0, 0x3175, 0xEB62, 0x7E58, 0x7E59, 0x7276, - 0, 0, 0, 0x7275, 0, 0, 0x7273, 0, - 0x337B, 0, 0x7272, 0x3C32, 0x3229, 0, 0, 0xEB65, - 0xEB66, 0, 0xFE2C, 0xEB68, 0xEB69, 0, 0, 0, - 0, 0, 0xEB6A, 0x3963, 0xEB6B, 0xEB6D, 0x727C, 0x727B, -}; -static const unsigned short utf8_to_euc_E9B5[] = { - 0, 0x727A, 0xEB6E, 0xEB6F, 0x7277, 0xEB6C, 0x727D, 0xEB70, - 0x727E, 0, 0xEB71, 0, 0, 0, 0, 0, - 0x7325, 0x7324, 0, 0xEB72, 0xEB73, 0, 0, 0, - 0, 0x7326, 0, 0, 0x312D, 0x7321, 0x7322, 0xEB74, - 0x3974, 0x4C39, 0xEB76, 0xEB75, 0x7323, 0xEB77, 0, 0, - 0, 0xEB78, 0xEB79, 0xEB7A, 0x4B32, 0, 0, 0x732B, - 0xEB7B, 0, 0x7327, 0, 0, 0, 0xEB7C, 0xEB7D, - 0, 0, 0x732C, 0xEB7E, 0xEC21, 0, 0xEC22, 0, -}; -static const unsigned short utf8_to_euc_E9B5_x0213[] = { - 0, 0x727A, 0xFE2E, 0x7E5A, 0x7277, 0xEB6C, 0x727D, 0x7E5B, - 0x727E, 0, 0xFE2F, 0, 0, 0, 0, 0, - 0x7325, 0x7324, 0x7E5C, 0xEB72, 0xEB73, 0, 0, 0, - 0, 0x7326, 0, 0, 0x312D, 0x7321, 0x7322, 0xFE30, - 0x3974, 0x4C39, 0xFE31, 0x7E5D, 0x7323, 0xEB77, 0, 0, - 0, 0xFE33, 0xEB79, 0xFE34, 0x4B32, 0, 0, 0x732B, - 0x7E5E, 0, 0x7327, 0xFE36, 0, 0, 0xFE37, 0xFE38, - 0, 0, 0x732C, 0xEB7E, 0x7E5F, 0, 0xFE39, 0, -}; -static const unsigned short utf8_to_euc_E9B6[] = { - 0, 0, 0, 0xEC23, 0xEC24, 0, 0xEC25, 0x7329, - 0, 0x7328, 0xEC26, 0, 0, 0xEC27, 0xEC28, 0x375C, - 0, 0, 0xEC29, 0xEC2A, 0, 0xEC2B, 0xEC2C, 0xEC2D, - 0xEC2E, 0, 0x732D, 0, 0, 0, 0, 0, - 0, 0xEC2F, 0, 0, 0x732E, 0, 0, 0, - 0, 0x732F, 0xEC30, 0x732A, 0xEC31, 0, 0xEC32, 0x7274, - 0, 0xEC33, 0x7330, 0, 0x4461, 0xEC34, 0, 0, - 0x7334, 0xEC35, 0x7335, 0x7333, 0xEC36, 0, 0, 0xEC37, -}; -static const unsigned short utf8_to_euc_E9B6_x0213[] = { - 0, 0, 0, 0xEC23, 0xFE3A, 0, 0xEC25, 0x7329, - 0, 0x7328, 0x7E60, 0, 0, 0xFE3B, 0xEC28, 0x375C, - 0, 0, 0xEC29, 0xEC2A, 0, 0xEC2B, 0x7E61, 0xEC2D, - 0xEC2E, 0xFE3C, 0x732D, 0, 0, 0, 0, 0, - 0, 0xFE3D, 0, 0, 0x732E, 0, 0, 0, - 0, 0x732F, 0xEC30, 0x732A, 0x7E63, 0, 0xEC32, 0x7274, - 0, 0xEC33, 0x7330, 0, 0x4461, 0xFE3F, 0, 0, - 0x7334, 0xFE40, 0x7335, 0x7333, 0x7E64, 0xFE41, 0, 0xFE3E, -}; -static const unsigned short utf8_to_euc_E9B7[] = { - 0, 0x7332, 0x7338, 0xEC38, 0x7331, 0, 0x7336, 0xEC39, - 0, 0xEC3A, 0xEC3B, 0, 0, 0, 0, 0x7337, - 0, 0, 0, 0x733A, 0xEC3C, 0xEC3D, 0xEC3E, 0xEC3F, - 0, 0x7339, 0xEC40, 0, 0, 0, 0xEC41, 0xEC42, - 0xEC43, 0, 0, 0, 0, 0xEC44, 0x733C, 0xEC45, - 0, 0xEC46, 0, 0xEC47, 0, 0x733D, 0xEC48, 0x733E, - 0xEC49, 0, 0x4F49, 0xEC4A, 0xEC4B, 0, 0, 0, - 0x733B, 0x426B, 0x3A6D, 0, 0, 0x733F, 0xEC4C, 0, -}; -static const unsigned short utf8_to_euc_E9B7_x0213[] = { - 0x7E62, 0x7332, 0x7338, 0xFE42, 0x7331, 0, 0x7336, 0xFE43, - 0, 0xFE44, 0xEC3B, 0, 0, 0, 0, 0x7337, - 0, 0, 0, 0x733A, 0xEC3C, 0xEC3D, 0xFE45, 0x7E65, - 0, 0x7339, 0xFE46, 0, 0, 0, 0xEC41, 0xFE47, - 0xFE48, 0, 0, 0xFE49, 0, 0xEC44, 0x733C, 0x7E67, - 0, 0xEC46, 0, 0xEC47, 0, 0x733D, 0xEC48, 0x733E, - 0xEC49, 0, 0x4F49, 0xEC4A, 0xFE4A, 0, 0, 0, - 0x733B, 0x426B, 0x3A6D, 0, 0, 0x733F, 0xEC4C, 0, -}; -static const unsigned short utf8_to_euc_E9B8[] = { - 0, 0, 0xEC4E, 0, 0, 0, 0, 0xEC4F, - 0, 0, 0xEC4D, 0, 0, 0, 0xEC50, 0, - 0xEC51, 0xEC52, 0xEC53, 0, 0, 0xEC54, 0xEC55, 0, - 0, 0xEC56, 0x7340, 0x7341, 0xEC57, 0xEC58, 0x7342, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E9B8_x0213[] = { - 0, 0, 0xFE4D, 0, 0, 0, 0, 0x7E68, - 0, 0, 0xFE4C, 0, 0, 0xFE4E, 0xEC50, 0, - 0xEC51, 0xEC52, 0xEC53, 0, 0, 0x7E69, 0xEC55, 0, - 0, 0xFE4F, 0x7340, 0x7341, 0xFE50, 0xFE51, 0x7342, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E9B9[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0x7343, 0, 0, - 0x3834, 0x7344, 0xEC59, 0xEC5A, 0xEC5B, 0x7345, 0, 0x3C2F, -}; -static const unsigned short utf8_to_euc_E9B9_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0x7343, 0, 0, - 0x3834, 0x7344, 0xEC59, 0xFE52, 0x7E6A, 0x7345, 0, 0x3C2F, -}; -static const unsigned short utf8_to_euc_E9BA[] = { - 0xEC5C, 0x7346, 0xEC5D, 0xEC5E, 0xEC5F, 0xEC60, 0, 0xEC61, - 0x7347, 0, 0, 0x7348, 0x7349, 0, 0xEC62, 0xEC63, - 0, 0x734C, 0x734A, 0x4F3C, 0, 0x734B, 0xEC64, 0x4E6F, - 0xEC65, 0, 0, 0xEC66, 0, 0x734D, 0xEC67, 0x4E5B, - 0, 0, 0, 0, 0xEC68, 0x734E, 0x477E, 0, - 0xEC69, 0x734F, 0x7351, 0, 0xEC6A, 0x7352, 0xEC6B, 0xEC6C, - 0xEC6D, 0, 0, 0xEC6E, 0xEC6F, 0xEC70, 0, 0, - 0x7350, 0x396D, 0x4C4D, 0x4B63, 0x5677, 0, 0x5D60, 0x4B7B, -}; -static const unsigned short utf8_to_euc_E9BA_x0213[] = { - 0xFE54, 0x7346, 0xEC5D, 0xEC5E, 0xEC5F, 0xFE55, 0, 0xEC61, - 0x7347, 0, 0, 0x7348, 0x7349, 0, 0xEC62, 0xEC63, - 0, 0x734C, 0x734A, 0x4F3C, 0, 0x734B, 0xEC64, 0x4E6F, - 0xEC65, 0, 0, 0xFE56, 0, 0x734D, 0x7E6B, 0x4E5B, - 0, 0, 0, 0, 0x7E6C, 0x734E, 0x477E, 0, - 0xFE57, 0x734F, 0x7351, 0, 0x7E6D, 0x7352, 0xEC6B, 0x7E6E, - 0xEC6D, 0, 0, 0xEC6E, 0x7E6F, 0x7E70, 0, 0, - 0x7350, 0x396D, 0x4C4D, 0x4B63, 0x5677, 0xFE59, 0x5D60, 0x4B7B, -}; -static const unsigned short utf8_to_euc_E9BB[] = { - 0, 0, 0, 0, 0x322B, 0, 0xEC71, 0, - 0xEC72, 0, 0, 0xEC73, 0x7354, 0x3550, 0x7355, 0x7356, - 0x7357, 0xF47E, 0x3975, 0, 0x7358, 0xEC74, 0, 0, - 0x6054, 0x4C5B, 0, 0x4263, 0x7359, 0x735B, 0x735A, 0xEC75, - 0x735C, 0, 0, 0, 0xEC76, 0x735D, 0, 0xEC77, - 0x735E, 0, 0, 0, 0xEC78, 0xEC79, 0xEC7A, 0x735F, - 0xEC7B, 0xEC7C, 0xEC7D, 0, 0x7360, 0xEC7E, 0x7361, 0x7362, - 0xED21, 0x7363, 0, 0x7364, 0x7365, 0x7366, 0, 0xED22, -}; -static const unsigned short utf8_to_euc_E9BB_x0213[] = { - 0, 0, 0, 0x7E71, 0x322B, 0, 0xEC71, 0, - 0xEC72, 0, 0, 0xEC73, 0x7354, 0x3550, 0x7355, 0x7356, - 0x7357, 0x7E72, 0x3975, 0, 0x7358, 0xEC74, 0, 0, - 0x6054, 0x4C5B, 0, 0x4263, 0x7359, 0x735B, 0x735A, 0xFE5B, - 0x735C, 0, 0, 0, 0xEC76, 0x735D, 0, 0xFE5C, - 0x735E, 0, 0, 0, 0xEC78, 0xEC79, 0xFE5D, 0x735F, - 0xEC7B, 0xEC7C, 0xEC7D, 0, 0x7360, 0xEC7E, 0x7361, 0x7362, - 0xED21, 0x7363, 0, 0x7364, 0x7365, 0x7366, 0, 0xFE5E, -}; -static const unsigned short utf8_to_euc_E9BC[] = { - 0, 0, 0xED23, 0xED24, 0, 0, 0, 0x7367, - 0x7368, 0xED25, 0, 0, 0, 0, 0x4524, 0xED26, - 0xED27, 0xED28, 0xED29, 0x385D, 0xED2A, 0x736A, 0xED2B, 0xED2C, - 0, 0xED2D, 0xED2E, 0xED2F, 0, 0, 0, 0xED30, - 0x414D, 0x736B, 0xED31, 0, 0, 0, 0xED32, 0, - 0, 0, 0xED33, 0xED34, 0x736C, 0, 0, 0xED35, - 0, 0xED36, 0xED37, 0, 0xED38, 0, 0, 0xED39, - 0, 0xED3A, 0xED3B, 0x4921, 0xED3C, 0xED3D, 0x736D, 0xED3E, -}; -static const unsigned short utf8_to_euc_E9BC_x0213[] = { - 0, 0, 0xFE5F, 0xFE61, 0, 0, 0, 0x7367, - 0x7368, 0xED25, 0, 0, 0, 0, 0x4524, 0xED26, - 0x7E73, 0xED28, 0xED29, 0x385D, 0xED2A, 0x736A, 0xED2B, 0xFE62, - 0, 0xFE63, 0xED2E, 0xED2F, 0, 0, 0, 0xED30, - 0x414D, 0x736B, 0xED31, 0, 0, 0, 0xED32, 0, - 0, 0, 0xED33, 0xED34, 0x736C, 0, 0, 0xFE64, - 0, 0xED36, 0xED37, 0, 0xED38, 0, 0, 0xFE65, - 0, 0x7E74, 0xFE66, 0x4921, 0xED3C, 0xFE67, 0x736D, 0xED3E, -}; -static const unsigned short utf8_to_euc_E9BD[] = { - 0, 0xED3F, 0, 0xED40, 0xED41, 0xED42, 0xED43, 0xED44, - 0, 0, 0x736E, 0x6337, 0, 0, 0x6C5A, 0x706D, - 0, 0, 0x736F, 0xED45, 0x7370, 0xED46, 0xED47, 0xED48, - 0xED49, 0, 0xED4A, 0, 0, 0xED4B, 0xED4C, 0x7372, - 0x7373, 0x7374, 0x4E70, 0x7371, 0, 0, 0x7375, 0x7376, - 0xED4D, 0xED4E, 0x7378, 0, 0x7377, 0xED4F, 0xED50, 0xED51, - 0xED52, 0xED53, 0x737A, 0xED54, 0, 0xED55, 0x737B, 0x7379, - 0, 0, 0xED56, 0, 0, 0xED57, 0, 0, -}; -static const unsigned short utf8_to_euc_E9BD_x0213[] = { - 0, 0xFE68, 0, 0xED40, 0xED41, 0xFE69, 0xFE6A, 0xED44, - 0, 0, 0x736E, 0x6337, 0, 0, 0x6C5A, 0x706D, - 0, 0, 0x736F, 0xFE6B, 0x7370, 0xFE6C, 0xED47, 0x7E75, - 0xFE6D, 0, 0xED4A, 0, 0, 0xFE6F, 0xED4C, 0x7372, - 0x7373, 0x7374, 0x4E70, 0x7371, 0, 0, 0x7375, 0x7376, - 0xED4D, 0xFE71, 0x7378, 0, 0x7377, 0xFE73, 0xED50, 0xED51, - 0xFE74, 0xED53, 0x737A, 0xED54, 0, 0xFE75, 0x737B, 0x7379, - 0, 0, 0xED56, 0, 0, 0xED57, 0, 0, -}; -static const unsigned short utf8_to_euc_E9BE[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0x4E36, 0, 0xED58, - 0xED59, 0xED5A, 0xED5B, 0, 0xED5C, 0x737C, 0xED5D, 0xED5E, - 0, 0, 0, 0, 0x737D, 0x6354, 0xED5F, 0, - 0x737E, 0xED60, 0xED61, 0xED62, 0, 0xED63, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_E9BE_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0x4E36, 0, 0xED58, - 0x7E76, 0xED5A, 0xED5B, 0, 0x7E77, 0x737C, 0xED5D, 0x7E78, - 0, 0, 0, 0, 0x737D, 0x6354, 0xED5F, 0, - 0x737E, 0xED60, 0x7E79, 0xED62, 0, 0xED63, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_EFA4[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0xF445, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_EFA4_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0x763B, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x742E, 0x754E, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0x7B4F, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_EFA5_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x7649, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_EFA7[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0xF472, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_EFA7_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x7E24, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0x7D5D, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_EFA8[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0xF434, 0xF437, - 0xF438, 0xF43D, 0xF444, 0xF447, 0xF448, 0xF44E, 0xF44F, 0xF453, - 0xF455, 0xF456, 0xF457, 0xF458, 0xF45A, 0xF45B, 0xF45E, 0xF460, - 0xF462, 0xF463, 0xF465, 0xF469, 0xF46A, 0xF46B, 0xF46D, 0xF46F, - 0xF470, 0xF473, 0xF477, 0xF478, 0xF479, 0xF47D, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_EFA8_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0x2F4B, - 0x2F57, 0x4F72, 0, 0xAE79, 0x757A, 0x775A, 0x776F, 0, - 0, 0x793C, 0x793D, 0x7941, 0, 0, 0, 0x7B3A, - 0xF738, 0xF745, 0x7C2E, 0, 0xF96E, 0, 0x7C6A, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x2E38, 0x2E49, 0x2E50, 0x2E63, 0x2E68, 0x2E6E, 0x2F2C, 0x2F2F, - 0x2F36, 0x2F5A, 0x2F5E, 0x4F61, 0x4F62, 0x7450, 0x745C, 0x745E, -}; -static const unsigned short utf8_to_euc_EFA9_x0213[] = { - 0x7461, 0x7528, 0x752B, 0x7543, 0x7565, 0x7669, 0x7677, 0x7725, - 0x7755, 0xF029, 0x7825, 0x7927, 0x7933, 0x7934, 0x7937, 0x7938, - 0x7939, 0x793B, 0x793F, 0x7940, 0x794D, 0x7951, 0x7964, 0x7A2E, - 0xF450, 0x7A33, 0x7A3A, 0x7A44, 0x7A58, 0xF574, 0xF575, 0x7B27, - 0x7B6F, 0x7B79, 0x7C2F, 0x7C30, 0x7C38, 0x7C3D, 0xF969, 0x7C59, - 0x7D63, 0x7D76, 0x7D7B, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_EFB9_x0213[] = { - 0, 0, 0, 0, 0, 0x233E, 0x233D, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_EFBC[] = { - 0, 0x212A, 0xF42A, 0x2174, 0x2170, 0x2173, 0x2175, 0xF429, - 0x214A, 0x214B, 0x2176, 0x215C, 0x2124, 0x215D, 0x2125, 0x213F, - 0x2330, 0x2331, 0x2332, 0x2333, 0x2334, 0x2335, 0x2336, 0x2337, - 0x2338, 0x2339, 0x2127, 0x2128, 0x2163, 0x2161, 0x2164, 0x2129, - 0x2177, 0x2341, 0x2342, 0x2343, 0x2344, 0x2345, 0x2346, 0x2347, - 0x2348, 0x2349, 0x234A, 0x234B, 0x234C, 0x234D, 0x234E, 0x234F, - 0x2350, 0x2351, 0x2352, 0x2353, 0x2354, 0x2355, 0x2356, 0x2357, - 0x2358, 0x2359, 0x235A, 0x214E, 0x2140, 0x214F, 0x2130, 0x2132, -}; -static const unsigned short utf8_to_euc_EFBC_x0213[] = { - 0, 0x212A, 0x2230, 0x2174, 0x2170, 0x2173, 0x2175, 0x222F, - 0x214A, 0x214B, 0x2176, 0x215C, 0x2124, 0x2231, 0x2125, 0x213F, - 0x2330, 0x2331, 0x2332, 0x2333, 0x2334, 0x2335, 0x2336, 0x2337, - 0x2338, 0x2339, 0x2127, 0x2128, 0x2163, 0x2161, 0x2164, 0x2129, - 0x2177, 0x2341, 0x2342, 0x2343, 0x2344, 0x2345, 0x2346, 0x2347, - 0x2348, 0x2349, 0x234A, 0x234B, 0x234C, 0x234D, 0x234E, 0x234F, - 0x2350, 0x2351, 0x2352, 0x2353, 0x2354, 0x2355, 0x2356, 0x2357, - 0x2358, 0x2359, 0x235A, 0x214E, 0x2140, 0x214F, 0x2130, 0x2132, -}; -static const unsigned short utf8_to_euc_EFBD[] = { - 0x212E, 0x2361, 0x2362, 0x2363, 0x2364, 0x2365, 0x2366, 0x2367, - 0x2368, 0x2369, 0x236A, 0x236B, 0x236C, 0x236D, 0x236E, 0x236F, - 0x2370, 0x2371, 0x2372, 0x2373, 0x2374, 0x2375, 0x2376, 0x2377, - 0x2378, 0x2379, 0x237A, 0x2150, 0x2143, 0x2151, 0xA237, 0, - 0, 0x0E21, 0x0E22, 0x0E23, 0x0E24, 0x0E25, 0x0E26, 0x0E27, - 0x0E28, 0x0E29, 0x0E2A, 0x0E2B, 0x0E2C, 0x0E2D, 0x0E2E, 0x0E2F, - 0x0E30, 0x0E31, 0x0E32, 0x0E33, 0x0E34, 0x0E35, 0x0E36, 0x0E37, - 0x0E38, 0x0E39, 0x0E3A, 0x0E3B, 0x0E3C, 0x0E3D, 0x0E3E, 0x0E3F, -}; -static const unsigned short utf8_to_euc_EFBD_ms[] = { - 0x212E, 0x2361, 0x2362, 0x2363, 0x2364, 0x2365, 0x2366, 0x2367, - 0x2368, 0x2369, 0x236A, 0x236B, 0x236C, 0x236D, 0x236E, 0x236F, - 0x2370, 0x2371, 0x2372, 0x2373, 0x2374, 0x2375, 0x2376, 0x2377, - 0x2378, 0x2379, 0x237A, 0x2150, 0x2143, 0x2151, 0x2141, 0, - 0, 0x0E21, 0x0E22, 0x0E23, 0x0E24, 0x0E25, 0x0E26, 0x0E27, - 0x0E28, 0x0E29, 0x0E2A, 0x0E2B, 0x0E2C, 0x0E2D, 0x0E2E, 0x0E2F, - 0x0E30, 0x0E31, 0x0E32, 0x0E33, 0x0E34, 0x0E35, 0x0E36, 0x0E37, - 0x0E38, 0x0E39, 0x0E3A, 0x0E3B, 0x0E3C, 0x0E3D, 0x0E3E, 0x0E3F, -}; -static const unsigned short utf8_to_euc_EFBD_x0213[] = { - 0x212E, 0x2361, 0x2362, 0x2363, 0x2364, 0x2365, 0x2366, 0x2367, - 0x2368, 0x2369, 0x236A, 0x236B, 0x236C, 0x236D, 0x236E, 0x236F, - 0x2370, 0x2371, 0x2372, 0x2373, 0x2374, 0x2375, 0x2376, 0x2377, - 0x2378, 0x2379, 0x237A, 0x2150, 0x2143, 0x2151, 0x2232, 0x2256, - 0x2257, 0x0E21, 0x0E22, 0x0E23, 0x0E24, 0x0E25, 0x0E26, 0x0E27, - 0x0E28, 0x0E29, 0x0E2A, 0x0E2B, 0x0E2C, 0x0E2D, 0x0E2E, 0x0E2F, - 0x0E30, 0x0E31, 0x0E32, 0x0E33, 0x0E34, 0x0E35, 0x0E36, 0x0E37, - 0x0E38, 0x0E39, 0x0E3A, 0x0E3B, 0x0E3C, 0x0E3D, 0x0E3E, 0x0E3F, -}; -static const unsigned short utf8_to_euc_EFBE[] = { - 0x0E40, 0x0E41, 0x0E42, 0x0E43, 0x0E44, 0x0E45, 0x0E46, 0x0E47, - 0x0E48, 0x0E49, 0x0E4A, 0x0E4B, 0x0E4C, 0x0E4D, 0x0E4E, 0x0E4F, - 0x0E50, 0x0E51, 0x0E52, 0x0E53, 0x0E54, 0x0E55, 0x0E56, 0x0E57, - 0x0E58, 0x0E59, 0x0E5A, 0x0E5B, 0x0E5C, 0x0E5D, 0x0E5E, 0x0E5F, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_EFBF[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0x2171, 0x2172, 0x224C, 0x2131, 0xA243, 0x216F, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short utf8_to_euc_EFBF_x0213[] = { - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0x2131, 0, 0x216F, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short *const utf8_to_euc_E1_x0213[] = { - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - utf8_to_euc_E1B8_x0213, 0, 0, 0, - 0, utf8_to_euc_E1BD_x0213, 0, 0, -}; -static const unsigned short *const utf8_to_euc_E2[] = { - utf8_to_euc_E280, 0, 0, 0, - utf8_to_euc_E284, utf8_to_euc_E285, utf8_to_euc_E286, utf8_to_euc_E287, - utf8_to_euc_E288, utf8_to_euc_E289, utf8_to_euc_E28A, 0, - utf8_to_euc_E28C, 0, 0, 0, - 0, utf8_to_euc_E291, 0, 0, - utf8_to_euc_E294, utf8_to_euc_E295, utf8_to_euc_E296, utf8_to_euc_E297, - utf8_to_euc_E298, utf8_to_euc_E299, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, -}; -static const unsigned short *const utf8_to_euc_E2_ms[] = { - utf8_to_euc_E280_ms, 0, 0, 0, - utf8_to_euc_E284, utf8_to_euc_E285, utf8_to_euc_E286, utf8_to_euc_E287, - utf8_to_euc_E288, utf8_to_euc_E289, utf8_to_euc_E28A, 0, - utf8_to_euc_E28C, 0, 0, 0, - 0, utf8_to_euc_E291, 0, 0, - utf8_to_euc_E294, utf8_to_euc_E295, utf8_to_euc_E296, utf8_to_euc_E297, - utf8_to_euc_E298, utf8_to_euc_E299, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, -}; -static const unsigned short *const utf8_to_euc_E2_932[] = { - utf8_to_euc_E280_932, 0, 0, 0, - utf8_to_euc_E284, utf8_to_euc_E285, utf8_to_euc_E286, utf8_to_euc_E287, - utf8_to_euc_E288_932, utf8_to_euc_E289, utf8_to_euc_E28A, 0, - utf8_to_euc_E28C, 0, 0, 0, - 0, utf8_to_euc_E291, 0, 0, - utf8_to_euc_E294, utf8_to_euc_E295, utf8_to_euc_E296, utf8_to_euc_E297, - utf8_to_euc_E298, utf8_to_euc_E299, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, -}; -static const unsigned short *const utf8_to_euc_E2_mac[] = { - utf8_to_euc_E280_932, 0, 0, 0, - utf8_to_euc_E284_mac, utf8_to_euc_E285_mac, utf8_to_euc_E286, utf8_to_euc_E287, - utf8_to_euc_E288_mac, utf8_to_euc_E289, utf8_to_euc_E28A_mac, 0, - utf8_to_euc_E28C, 0, 0, 0, - 0, utf8_to_euc_E291_mac, 0, 0, - utf8_to_euc_E294, utf8_to_euc_E295, utf8_to_euc_E296, utf8_to_euc_E297, - utf8_to_euc_E298, utf8_to_euc_E299, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, -}; -static const unsigned short *const utf8_to_euc_E2_x0213[] = { - utf8_to_euc_E280_x0213, utf8_to_euc_E281_x0213, utf8_to_euc_E282_x0213, 0, - utf8_to_euc_E284_x0213, utf8_to_euc_E285_x0213, utf8_to_euc_E286_x0213, utf8_to_euc_E287_x0213, - utf8_to_euc_E288_x0213, utf8_to_euc_E289_x0213, utf8_to_euc_E28A_x0213, utf8_to_euc_E28B_x0213, - utf8_to_euc_E28C_x0213, 0, utf8_to_euc_E28E_x0213, utf8_to_euc_E28F_x0213, - utf8_to_euc_E290_x0213, utf8_to_euc_E291, 0, utf8_to_euc_E293_x0213, - utf8_to_euc_E294, utf8_to_euc_E295, utf8_to_euc_E296_x0213, utf8_to_euc_E297_x0213, - utf8_to_euc_E298_x0213, utf8_to_euc_E299_x0213, 0, 0, - utf8_to_euc_E29C_x0213, utf8_to_euc_E29D_x0213, 0, 0, - 0, 0, 0, 0, - utf8_to_euc_E2A4_x0213, 0, utf8_to_euc_E2A6_x0213, utf8_to_euc_E2A7_x0213, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, -}; -static const unsigned short *const utf8_to_euc_E3[] = { - utf8_to_euc_E380, utf8_to_euc_E381, utf8_to_euc_E382, utf8_to_euc_E383, - 0, 0, 0, 0, - utf8_to_euc_E388, 0, utf8_to_euc_E38A, 0, - utf8_to_euc_E38C, utf8_to_euc_E38D, utf8_to_euc_E38E, utf8_to_euc_E38F, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, -}; -static const unsigned short *const utf8_to_euc_E3_932[] = { - utf8_to_euc_E380_932, utf8_to_euc_E381, utf8_to_euc_E382_932, utf8_to_euc_E383, - 0, 0, 0, 0, - utf8_to_euc_E388, 0, utf8_to_euc_E38A, 0, - utf8_to_euc_E38C, utf8_to_euc_E38D, utf8_to_euc_E38E, utf8_to_euc_E38F, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, -}; -static const unsigned short *const utf8_to_euc_E3_mac[] = { - utf8_to_euc_E380_932, utf8_to_euc_E381, utf8_to_euc_E382_932, utf8_to_euc_E383, - 0, 0, 0, 0, - utf8_to_euc_E388_mac, 0, utf8_to_euc_E38A_mac, 0, - utf8_to_euc_E38C_mac, utf8_to_euc_E38D_mac, utf8_to_euc_E38E_mac, utf8_to_euc_E38F_mac, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, -}; -static const unsigned short *const utf8_to_euc_E3_x0213[] = { - utf8_to_euc_E380_x0213, utf8_to_euc_E381, utf8_to_euc_E382_x0213, utf8_to_euc_E383_x0213, - 0, 0, 0, utf8_to_euc_E387_x0213, - utf8_to_euc_E388, utf8_to_euc_E389_x0213, utf8_to_euc_E38A_x0213, utf8_to_euc_E38B_x0213, - utf8_to_euc_E38C, utf8_to_euc_E38D, utf8_to_euc_E38E, utf8_to_euc_E38F_x0213, - utf8_to_euc_E390_x0213, utf8_to_euc_E391_x0213, utf8_to_euc_E392_x0213, utf8_to_euc_E393_x0213, - utf8_to_euc_E394_x0213, utf8_to_euc_E395_x0213, utf8_to_euc_E396_x0213, utf8_to_euc_E397_x0213, - utf8_to_euc_E398_x0213, utf8_to_euc_E399_x0213, utf8_to_euc_E39A_x0213, utf8_to_euc_E39B_x0213, - 0, utf8_to_euc_E39D_x0213, utf8_to_euc_E39E_x0213, utf8_to_euc_E39F_x0213, - utf8_to_euc_E3A0_x0213, utf8_to_euc_E3A1_x0213, 0, utf8_to_euc_E3A3_x0213, - utf8_to_euc_E3A4_x0213, utf8_to_euc_E3A5_x0213, 0, 0, - 0, utf8_to_euc_E3A9_x0213, 0, utf8_to_euc_E3AB_x0213, - utf8_to_euc_E3AC_x0213, utf8_to_euc_E3AD_x0213, utf8_to_euc_E3AE_x0213, utf8_to_euc_E3AF_x0213, - utf8_to_euc_E3B0_x0213, 0, 0, utf8_to_euc_E3B3_x0213, - utf8_to_euc_E3B4_x0213, utf8_to_euc_E3B5_x0213, utf8_to_euc_E3B6_x0213, utf8_to_euc_E3B7_x0213, - utf8_to_euc_E3B8_x0213, utf8_to_euc_E3B9_x0213, utf8_to_euc_E3BA_x0213, 0, - 0, utf8_to_euc_E3BD_x0213, utf8_to_euc_E3BE_x0213, utf8_to_euc_E3BF_x0213, -}; -static const unsigned short *const utf8_to_euc_E4[] = { - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - utf8_to_euc_E4B8, utf8_to_euc_E4B9, utf8_to_euc_E4BA, utf8_to_euc_E4BB, - utf8_to_euc_E4BC, utf8_to_euc_E4BD, utf8_to_euc_E4BE, utf8_to_euc_E4BF, -}; -static const unsigned short *const utf8_to_euc_E4_x0213[] = { - utf8_to_euc_E480_x0213, utf8_to_euc_E481_x0213, utf8_to_euc_E482_x0213, 0, - utf8_to_euc_E484_x0213, utf8_to_euc_E485_x0213, utf8_to_euc_E486_x0213, utf8_to_euc_E487_x0213, - utf8_to_euc_E488_x0213, utf8_to_euc_E489_x0213, 0, utf8_to_euc_E48B_x0213, - utf8_to_euc_E48C_x0213, utf8_to_euc_E48D_x0213, 0, utf8_to_euc_E48F_x0213, - utf8_to_euc_E490_x0213, utf8_to_euc_E491_x0213, utf8_to_euc_E492_x0213, utf8_to_euc_E493_x0213, - utf8_to_euc_E494_x0213, utf8_to_euc_E495_x0213, utf8_to_euc_E496_x0213, utf8_to_euc_E497_x0213, - utf8_to_euc_E498_x0213, utf8_to_euc_E499_x0213, utf8_to_euc_E49A_x0213, 0, - utf8_to_euc_E49C_x0213, utf8_to_euc_E49D_x0213, 0, utf8_to_euc_E49F_x0213, - utf8_to_euc_E4A0_x0213, utf8_to_euc_E4A1_x0213, utf8_to_euc_E4A2_x0213, 0, - 0, 0, utf8_to_euc_E4A6_x0213, utf8_to_euc_E4A7_x0213, - utf8_to_euc_E4A8_x0213, 0, utf8_to_euc_E4AA_x0213, 0, - utf8_to_euc_E4AC_x0213, 0, 0, utf8_to_euc_E4AF_x0213, - utf8_to_euc_E4B0_x0213, 0, 0, utf8_to_euc_E4B3_x0213, - utf8_to_euc_E4B4_x0213, utf8_to_euc_E4B5_x0213, 0, 0, - utf8_to_euc_E4B8_x0213, utf8_to_euc_E4B9_x0213, utf8_to_euc_E4BA_x0213, utf8_to_euc_E4BB_x0213, - utf8_to_euc_E4BC_x0213, utf8_to_euc_E4BD_x0213, utf8_to_euc_E4BE_x0213, utf8_to_euc_E4BF_x0213, -}; -static const unsigned short *const utf8_to_euc_E5[] = { - utf8_to_euc_E580, utf8_to_euc_E581, utf8_to_euc_E582, utf8_to_euc_E583, - utf8_to_euc_E584, utf8_to_euc_E585, utf8_to_euc_E586, utf8_to_euc_E587, - utf8_to_euc_E588, utf8_to_euc_E589, utf8_to_euc_E58A, utf8_to_euc_E58B, - utf8_to_euc_E58C, utf8_to_euc_E58D, utf8_to_euc_E58E, utf8_to_euc_E58F, - utf8_to_euc_E590, utf8_to_euc_E591, utf8_to_euc_E592, utf8_to_euc_E593, - utf8_to_euc_E594, utf8_to_euc_E595, utf8_to_euc_E596, utf8_to_euc_E597, - utf8_to_euc_E598, utf8_to_euc_E599, utf8_to_euc_E59A, utf8_to_euc_E59B, - utf8_to_euc_E59C, utf8_to_euc_E59D, utf8_to_euc_E59E, utf8_to_euc_E59F, - utf8_to_euc_E5A0, utf8_to_euc_E5A1, utf8_to_euc_E5A2, utf8_to_euc_E5A3, - utf8_to_euc_E5A4, utf8_to_euc_E5A5, utf8_to_euc_E5A6, utf8_to_euc_E5A7, - utf8_to_euc_E5A8, utf8_to_euc_E5A9, utf8_to_euc_E5AA, utf8_to_euc_E5AB, - utf8_to_euc_E5AC, utf8_to_euc_E5AD, utf8_to_euc_E5AE, utf8_to_euc_E5AF, - utf8_to_euc_E5B0, utf8_to_euc_E5B1, utf8_to_euc_E5B2, utf8_to_euc_E5B3, - utf8_to_euc_E5B4, utf8_to_euc_E5B5, utf8_to_euc_E5B6, utf8_to_euc_E5B7, - utf8_to_euc_E5B8, utf8_to_euc_E5B9, utf8_to_euc_E5BA, utf8_to_euc_E5BB, - utf8_to_euc_E5BC, utf8_to_euc_E5BD, utf8_to_euc_E5BE, utf8_to_euc_E5BF, -}; -static const unsigned short *const utf8_to_euc_E5_x0213[] = { - utf8_to_euc_E580_x0213, utf8_to_euc_E581_x0213, utf8_to_euc_E582_x0213, utf8_to_euc_E583_x0213, - utf8_to_euc_E584_x0213, utf8_to_euc_E585_x0213, utf8_to_euc_E586_x0213, utf8_to_euc_E587_x0213, - utf8_to_euc_E588_x0213, utf8_to_euc_E589_x0213, utf8_to_euc_E58A_x0213, utf8_to_euc_E58B_x0213, - utf8_to_euc_E58C_x0213, utf8_to_euc_E58D_x0213, utf8_to_euc_E58E_x0213, utf8_to_euc_E58F_x0213, - utf8_to_euc_E590_x0213, utf8_to_euc_E591_x0213, utf8_to_euc_E592_x0213, utf8_to_euc_E593_x0213, - utf8_to_euc_E594_x0213, utf8_to_euc_E595_x0213, utf8_to_euc_E596_x0213, utf8_to_euc_E597_x0213, - utf8_to_euc_E598_x0213, utf8_to_euc_E599_x0213, utf8_to_euc_E59A_x0213, utf8_to_euc_E59B_x0213, - utf8_to_euc_E59C_x0213, utf8_to_euc_E59D_x0213, utf8_to_euc_E59E_x0213, utf8_to_euc_E59F_x0213, - utf8_to_euc_E5A0_x0213, utf8_to_euc_E5A1_x0213, utf8_to_euc_E5A2_x0213, utf8_to_euc_E5A3_x0213, - utf8_to_euc_E5A4_x0213, utf8_to_euc_E5A5_x0213, utf8_to_euc_E5A6_x0213, utf8_to_euc_E5A7_x0213, - utf8_to_euc_E5A8_x0213, utf8_to_euc_E5A9_x0213, utf8_to_euc_E5AA_x0213, utf8_to_euc_E5AB_x0213, - utf8_to_euc_E5AC_x0213, utf8_to_euc_E5AD_x0213, utf8_to_euc_E5AE_x0213, utf8_to_euc_E5AF_x0213, - utf8_to_euc_E5B0_x0213, utf8_to_euc_E5B1_x0213, utf8_to_euc_E5B2_x0213, utf8_to_euc_E5B3_x0213, - utf8_to_euc_E5B4_x0213, utf8_to_euc_E5B5_x0213, utf8_to_euc_E5B6_x0213, utf8_to_euc_E5B7_x0213, - utf8_to_euc_E5B8_x0213, utf8_to_euc_E5B9_x0213, utf8_to_euc_E5BA_x0213, utf8_to_euc_E5BB_x0213, - utf8_to_euc_E5BC_x0213, utf8_to_euc_E5BD_x0213, utf8_to_euc_E5BE_x0213, utf8_to_euc_E5BF_x0213, -}; -static const unsigned short *const utf8_to_euc_E6[] = { - utf8_to_euc_E680, utf8_to_euc_E681, utf8_to_euc_E682, utf8_to_euc_E683, - utf8_to_euc_E684, utf8_to_euc_E685, utf8_to_euc_E686, utf8_to_euc_E687, - utf8_to_euc_E688, utf8_to_euc_E689, utf8_to_euc_E68A, utf8_to_euc_E68B, - utf8_to_euc_E68C, utf8_to_euc_E68D, utf8_to_euc_E68E, utf8_to_euc_E68F, - utf8_to_euc_E690, utf8_to_euc_E691, utf8_to_euc_E692, utf8_to_euc_E693, - utf8_to_euc_E694, utf8_to_euc_E695, utf8_to_euc_E696, utf8_to_euc_E697, - utf8_to_euc_E698, utf8_to_euc_E699, utf8_to_euc_E69A, utf8_to_euc_E69B, - utf8_to_euc_E69C, utf8_to_euc_E69D, utf8_to_euc_E69E, utf8_to_euc_E69F, - utf8_to_euc_E6A0, utf8_to_euc_E6A1, utf8_to_euc_E6A2, utf8_to_euc_E6A3, - utf8_to_euc_E6A4, utf8_to_euc_E6A5, utf8_to_euc_E6A6, utf8_to_euc_E6A7, - utf8_to_euc_E6A8, utf8_to_euc_E6A9, utf8_to_euc_E6AA, utf8_to_euc_E6AB, - utf8_to_euc_E6AC, utf8_to_euc_E6AD, utf8_to_euc_E6AE, utf8_to_euc_E6AF, - utf8_to_euc_E6B0, utf8_to_euc_E6B1, utf8_to_euc_E6B2, utf8_to_euc_E6B3, - utf8_to_euc_E6B4, utf8_to_euc_E6B5, utf8_to_euc_E6B6, utf8_to_euc_E6B7, - utf8_to_euc_E6B8, utf8_to_euc_E6B9, utf8_to_euc_E6BA, utf8_to_euc_E6BB, - utf8_to_euc_E6BC, utf8_to_euc_E6BD, utf8_to_euc_E6BE, utf8_to_euc_E6BF, -}; -static const unsigned short *const utf8_to_euc_E6_x0213[] = { - utf8_to_euc_E680_x0213, utf8_to_euc_E681_x0213, utf8_to_euc_E682_x0213, utf8_to_euc_E683_x0213, - utf8_to_euc_E684_x0213, utf8_to_euc_E685_x0213, utf8_to_euc_E686_x0213, utf8_to_euc_E687_x0213, - utf8_to_euc_E688_x0213, utf8_to_euc_E689_x0213, utf8_to_euc_E68A_x0213, utf8_to_euc_E68B_x0213, - utf8_to_euc_E68C_x0213, utf8_to_euc_E68D_x0213, utf8_to_euc_E68E_x0213, utf8_to_euc_E68F_x0213, - utf8_to_euc_E690_x0213, utf8_to_euc_E691_x0213, utf8_to_euc_E692_x0213, utf8_to_euc_E693_x0213, - utf8_to_euc_E694_x0213, utf8_to_euc_E695_x0213, utf8_to_euc_E696_x0213, utf8_to_euc_E697_x0213, - utf8_to_euc_E698_x0213, utf8_to_euc_E699_x0213, utf8_to_euc_E69A_x0213, utf8_to_euc_E69B_x0213, - utf8_to_euc_E69C_x0213, utf8_to_euc_E69D_x0213, utf8_to_euc_E69E_x0213, utf8_to_euc_E69F_x0213, - utf8_to_euc_E6A0_x0213, utf8_to_euc_E6A1_x0213, utf8_to_euc_E6A2_x0213, utf8_to_euc_E6A3_x0213, - utf8_to_euc_E6A4_x0213, utf8_to_euc_E6A5_x0213, utf8_to_euc_E6A6_x0213, utf8_to_euc_E6A7_x0213, - utf8_to_euc_E6A8_x0213, utf8_to_euc_E6A9_x0213, utf8_to_euc_E6AA_x0213, utf8_to_euc_E6AB_x0213, - utf8_to_euc_E6AC_x0213, utf8_to_euc_E6AD_x0213, utf8_to_euc_E6AE_x0213, utf8_to_euc_E6AF_x0213, - utf8_to_euc_E6B0_x0213, utf8_to_euc_E6B1_x0213, utf8_to_euc_E6B2_x0213, utf8_to_euc_E6B3_x0213, - utf8_to_euc_E6B4_x0213, utf8_to_euc_E6B5_x0213, utf8_to_euc_E6B6_x0213, utf8_to_euc_E6B7_x0213, - utf8_to_euc_E6B8_x0213, utf8_to_euc_E6B9_x0213, utf8_to_euc_E6BA_x0213, utf8_to_euc_E6BB_x0213, - utf8_to_euc_E6BC_x0213, utf8_to_euc_E6BD_x0213, utf8_to_euc_E6BE_x0213, utf8_to_euc_E6BF_x0213, -}; -static const unsigned short *const utf8_to_euc_E7[] = { - utf8_to_euc_E780, utf8_to_euc_E781, utf8_to_euc_E782, utf8_to_euc_E783, - utf8_to_euc_E784, utf8_to_euc_E785, utf8_to_euc_E786, utf8_to_euc_E787, - utf8_to_euc_E788, utf8_to_euc_E789, utf8_to_euc_E78A, utf8_to_euc_E78B, - utf8_to_euc_E78C, utf8_to_euc_E78D, utf8_to_euc_E78E, utf8_to_euc_E78F, - utf8_to_euc_E790, utf8_to_euc_E791, utf8_to_euc_E792, utf8_to_euc_E793, - utf8_to_euc_E794, utf8_to_euc_E795, utf8_to_euc_E796, utf8_to_euc_E797, - utf8_to_euc_E798, utf8_to_euc_E799, utf8_to_euc_E79A, utf8_to_euc_E79B, - utf8_to_euc_E79C, utf8_to_euc_E79D, utf8_to_euc_E79E, utf8_to_euc_E79F, - utf8_to_euc_E7A0, utf8_to_euc_E7A1, utf8_to_euc_E7A2, utf8_to_euc_E7A3, - utf8_to_euc_E7A4, utf8_to_euc_E7A5, utf8_to_euc_E7A6, utf8_to_euc_E7A7, - utf8_to_euc_E7A8, utf8_to_euc_E7A9, utf8_to_euc_E7AA, utf8_to_euc_E7AB, - utf8_to_euc_E7AC, utf8_to_euc_E7AD, utf8_to_euc_E7AE, utf8_to_euc_E7AF, - utf8_to_euc_E7B0, utf8_to_euc_E7B1, utf8_to_euc_E7B2, utf8_to_euc_E7B3, - utf8_to_euc_E7B4, utf8_to_euc_E7B5, utf8_to_euc_E7B6, utf8_to_euc_E7B7, - utf8_to_euc_E7B8, utf8_to_euc_E7B9, utf8_to_euc_E7BA, 0, - utf8_to_euc_E7BC, utf8_to_euc_E7BD, utf8_to_euc_E7BE, utf8_to_euc_E7BF, -}; -static const unsigned short *const utf8_to_euc_E7_x0213[] = { - utf8_to_euc_E780_x0213, utf8_to_euc_E781_x0213, utf8_to_euc_E782_x0213, utf8_to_euc_E783_x0213, - utf8_to_euc_E784_x0213, utf8_to_euc_E785_x0213, utf8_to_euc_E786_x0213, utf8_to_euc_E787_x0213, - utf8_to_euc_E788_x0213, utf8_to_euc_E789_x0213, utf8_to_euc_E78A_x0213, utf8_to_euc_E78B_x0213, - utf8_to_euc_E78C_x0213, utf8_to_euc_E78D_x0213, utf8_to_euc_E78E_x0213, utf8_to_euc_E78F_x0213, - utf8_to_euc_E790_x0213, utf8_to_euc_E791_x0213, utf8_to_euc_E792_x0213, utf8_to_euc_E793_x0213, - utf8_to_euc_E794_x0213, utf8_to_euc_E795_x0213, utf8_to_euc_E796_x0213, utf8_to_euc_E797_x0213, - utf8_to_euc_E798_x0213, utf8_to_euc_E799_x0213, utf8_to_euc_E79A_x0213, utf8_to_euc_E79B_x0213, - utf8_to_euc_E79C_x0213, utf8_to_euc_E79D_x0213, utf8_to_euc_E79E_x0213, utf8_to_euc_E79F_x0213, - utf8_to_euc_E7A0_x0213, utf8_to_euc_E7A1_x0213, utf8_to_euc_E7A2_x0213, utf8_to_euc_E7A3_x0213, - utf8_to_euc_E7A4_x0213, utf8_to_euc_E7A5_x0213, utf8_to_euc_E7A6_x0213, utf8_to_euc_E7A7_x0213, - utf8_to_euc_E7A8_x0213, utf8_to_euc_E7A9_x0213, utf8_to_euc_E7AA_x0213, utf8_to_euc_E7AB_x0213, - utf8_to_euc_E7AC_x0213, utf8_to_euc_E7AD_x0213, utf8_to_euc_E7AE_x0213, utf8_to_euc_E7AF_x0213, - utf8_to_euc_E7B0_x0213, utf8_to_euc_E7B1_x0213, utf8_to_euc_E7B2_x0213, utf8_to_euc_E7B3_x0213, - utf8_to_euc_E7B4_x0213, utf8_to_euc_E7B5_x0213, utf8_to_euc_E7B6_x0213, utf8_to_euc_E7B7_x0213, - utf8_to_euc_E7B8_x0213, utf8_to_euc_E7B9_x0213, utf8_to_euc_E7BA_x0213, 0, - utf8_to_euc_E7BC_x0213, utf8_to_euc_E7BD_x0213, utf8_to_euc_E7BE_x0213, utf8_to_euc_E7BF_x0213, -}; -static const unsigned short *const utf8_to_euc_E8[] = { - utf8_to_euc_E880, utf8_to_euc_E881, utf8_to_euc_E882, utf8_to_euc_E883, - utf8_to_euc_E884, utf8_to_euc_E885, utf8_to_euc_E886, utf8_to_euc_E887, - utf8_to_euc_E888, utf8_to_euc_E889, utf8_to_euc_E88A, utf8_to_euc_E88B, - utf8_to_euc_E88C, utf8_to_euc_E88D, utf8_to_euc_E88E, utf8_to_euc_E88F, - utf8_to_euc_E890, utf8_to_euc_E891, utf8_to_euc_E892, utf8_to_euc_E893, - utf8_to_euc_E894, utf8_to_euc_E895, utf8_to_euc_E896, utf8_to_euc_E897, - utf8_to_euc_E898, utf8_to_euc_E899, utf8_to_euc_E89A, utf8_to_euc_E89B, - utf8_to_euc_E89C, utf8_to_euc_E89D, utf8_to_euc_E89E, utf8_to_euc_E89F, - utf8_to_euc_E8A0, utf8_to_euc_E8A1, utf8_to_euc_E8A2, utf8_to_euc_E8A3, - utf8_to_euc_E8A4, utf8_to_euc_E8A5, utf8_to_euc_E8A6, utf8_to_euc_E8A7, - utf8_to_euc_E8A8, utf8_to_euc_E8A9, utf8_to_euc_E8AA, utf8_to_euc_E8AB, - utf8_to_euc_E8AC, utf8_to_euc_E8AD, utf8_to_euc_E8AE, 0, - utf8_to_euc_E8B0, utf8_to_euc_E8B1, utf8_to_euc_E8B2, utf8_to_euc_E8B3, - utf8_to_euc_E8B4, utf8_to_euc_E8B5, utf8_to_euc_E8B6, utf8_to_euc_E8B7, - utf8_to_euc_E8B8, utf8_to_euc_E8B9, utf8_to_euc_E8BA, utf8_to_euc_E8BB, - utf8_to_euc_E8BC, utf8_to_euc_E8BD, utf8_to_euc_E8BE, utf8_to_euc_E8BF, -}; -static const unsigned short *const utf8_to_euc_E8_x0213[] = { - utf8_to_euc_E880_x0213, utf8_to_euc_E881_x0213, utf8_to_euc_E882_x0213, utf8_to_euc_E883_x0213, - utf8_to_euc_E884_x0213, utf8_to_euc_E885_x0213, utf8_to_euc_E886_x0213, utf8_to_euc_E887_x0213, - utf8_to_euc_E888_x0213, utf8_to_euc_E889_x0213, utf8_to_euc_E88A_x0213, utf8_to_euc_E88B_x0213, - utf8_to_euc_E88C_x0213, utf8_to_euc_E88D_x0213, utf8_to_euc_E88E_x0213, utf8_to_euc_E88F_x0213, - utf8_to_euc_E890_x0213, utf8_to_euc_E891_x0213, utf8_to_euc_E892_x0213, utf8_to_euc_E893_x0213, - utf8_to_euc_E894_x0213, utf8_to_euc_E895_x0213, utf8_to_euc_E896_x0213, utf8_to_euc_E897_x0213, - utf8_to_euc_E898_x0213, utf8_to_euc_E899_x0213, utf8_to_euc_E89A_x0213, utf8_to_euc_E89B_x0213, - utf8_to_euc_E89C_x0213, utf8_to_euc_E89D_x0213, utf8_to_euc_E89E_x0213, utf8_to_euc_E89F_x0213, - utf8_to_euc_E8A0_x0213, utf8_to_euc_E8A1_x0213, utf8_to_euc_E8A2_x0213, utf8_to_euc_E8A3_x0213, - utf8_to_euc_E8A4_x0213, utf8_to_euc_E8A5_x0213, utf8_to_euc_E8A6_x0213, utf8_to_euc_E8A7_x0213, - utf8_to_euc_E8A8_x0213, utf8_to_euc_E8A9_x0213, utf8_to_euc_E8AA_x0213, utf8_to_euc_E8AB_x0213, - utf8_to_euc_E8AC_x0213, utf8_to_euc_E8AD_x0213, utf8_to_euc_E8AE_x0213, 0, - utf8_to_euc_E8B0_x0213, utf8_to_euc_E8B1_x0213, utf8_to_euc_E8B2_x0213, utf8_to_euc_E8B3_x0213, - utf8_to_euc_E8B4_x0213, utf8_to_euc_E8B5_x0213, utf8_to_euc_E8B6_x0213, utf8_to_euc_E8B7_x0213, - utf8_to_euc_E8B8_x0213, utf8_to_euc_E8B9_x0213, utf8_to_euc_E8BA_x0213, utf8_to_euc_E8BB_x0213, - utf8_to_euc_E8BC_x0213, utf8_to_euc_E8BD_x0213, utf8_to_euc_E8BE_x0213, utf8_to_euc_E8BF_x0213, -}; -static const unsigned short *const utf8_to_euc_E9[] = { - utf8_to_euc_E980, utf8_to_euc_E981, utf8_to_euc_E982, utf8_to_euc_E983, - utf8_to_euc_E984, utf8_to_euc_E985, utf8_to_euc_E986, utf8_to_euc_E987, - utf8_to_euc_E988, utf8_to_euc_E989, utf8_to_euc_E98A, utf8_to_euc_E98B, - utf8_to_euc_E98C, utf8_to_euc_E98D, utf8_to_euc_E98E, utf8_to_euc_E98F, - utf8_to_euc_E990, utf8_to_euc_E991, utf8_to_euc_E992, 0, - 0, utf8_to_euc_E995, utf8_to_euc_E996, utf8_to_euc_E997, - utf8_to_euc_E998, utf8_to_euc_E999, utf8_to_euc_E99A, utf8_to_euc_E99B, - utf8_to_euc_E99C, utf8_to_euc_E99D, utf8_to_euc_E99E, utf8_to_euc_E99F, - utf8_to_euc_E9A0, utf8_to_euc_E9A1, utf8_to_euc_E9A2, utf8_to_euc_E9A3, - utf8_to_euc_E9A4, utf8_to_euc_E9A5, utf8_to_euc_E9A6, utf8_to_euc_E9A7, - utf8_to_euc_E9A8, utf8_to_euc_E9A9, utf8_to_euc_E9AA, utf8_to_euc_E9AB, - utf8_to_euc_E9AC, utf8_to_euc_E9AD, utf8_to_euc_E9AE, utf8_to_euc_E9AF, - utf8_to_euc_E9B0, utf8_to_euc_E9B1, 0, utf8_to_euc_E9B3, - utf8_to_euc_E9B4, utf8_to_euc_E9B5, utf8_to_euc_E9B6, utf8_to_euc_E9B7, - utf8_to_euc_E9B8, utf8_to_euc_E9B9, utf8_to_euc_E9BA, utf8_to_euc_E9BB, - utf8_to_euc_E9BC, utf8_to_euc_E9BD, utf8_to_euc_E9BE, 0, -}; -static const unsigned short *const utf8_to_euc_E9_x0213[] = { - utf8_to_euc_E980_x0213, utf8_to_euc_E981_x0213, utf8_to_euc_E982_x0213, utf8_to_euc_E983_x0213, - utf8_to_euc_E984_x0213, utf8_to_euc_E985_x0213, utf8_to_euc_E986_x0213, utf8_to_euc_E987_x0213, - utf8_to_euc_E988_x0213, utf8_to_euc_E989_x0213, utf8_to_euc_E98A_x0213, utf8_to_euc_E98B_x0213, - utf8_to_euc_E98C_x0213, utf8_to_euc_E98D_x0213, utf8_to_euc_E98E_x0213, utf8_to_euc_E98F_x0213, - utf8_to_euc_E990_x0213, utf8_to_euc_E991_x0213, utf8_to_euc_E992, 0, - 0, utf8_to_euc_E995_x0213, utf8_to_euc_E996_x0213, utf8_to_euc_E997_x0213, - utf8_to_euc_E998_x0213, utf8_to_euc_E999_x0213, utf8_to_euc_E99A_x0213, utf8_to_euc_E99B_x0213, - utf8_to_euc_E99C_x0213, utf8_to_euc_E99D_x0213, utf8_to_euc_E99E_x0213, utf8_to_euc_E99F_x0213, - utf8_to_euc_E9A0_x0213, utf8_to_euc_E9A1_x0213, utf8_to_euc_E9A2_x0213, utf8_to_euc_E9A3_x0213, - utf8_to_euc_E9A4_x0213, utf8_to_euc_E9A5_x0213, utf8_to_euc_E9A6_x0213, utf8_to_euc_E9A7_x0213, - utf8_to_euc_E9A8_x0213, utf8_to_euc_E9A9_x0213, utf8_to_euc_E9AA_x0213, utf8_to_euc_E9AB_x0213, - utf8_to_euc_E9AC_x0213, utf8_to_euc_E9AD_x0213, utf8_to_euc_E9AE_x0213, utf8_to_euc_E9AF_x0213, - utf8_to_euc_E9B0_x0213, utf8_to_euc_E9B1_x0213, 0, utf8_to_euc_E9B3_x0213, - utf8_to_euc_E9B4_x0213, utf8_to_euc_E9B5_x0213, utf8_to_euc_E9B6_x0213, utf8_to_euc_E9B7_x0213, - utf8_to_euc_E9B8_x0213, utf8_to_euc_E9B9_x0213, utf8_to_euc_E9BA_x0213, utf8_to_euc_E9BB_x0213, - utf8_to_euc_E9BC_x0213, utf8_to_euc_E9BD_x0213, utf8_to_euc_E9BE_x0213, 0, -}; -static const unsigned short *const utf8_to_euc_EF[] = { - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - utf8_to_euc_EFA4, 0, 0, utf8_to_euc_EFA7, - utf8_to_euc_EFA8, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - utf8_to_euc_EFBC, utf8_to_euc_EFBD, utf8_to_euc_EFBE, utf8_to_euc_EFBF, -}; -static const unsigned short *const utf8_to_euc_EF_ms[] = { - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - utf8_to_euc_EFA4, 0, 0, utf8_to_euc_EFA7, - utf8_to_euc_EFA8, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - utf8_to_euc_EFBC, utf8_to_euc_EFBD_ms, utf8_to_euc_EFBE, utf8_to_euc_EFBF, -}; -static const unsigned short *const utf8_to_euc_EF_x0213[] = { - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - utf8_to_euc_EFA4_x0213, utf8_to_euc_EFA5_x0213, 0, utf8_to_euc_EFA7_x0213, - utf8_to_euc_EFA8_x0213, utf8_to_euc_EFA9_x0213, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, utf8_to_euc_EFB9_x0213, 0, 0, - utf8_to_euc_EFBC_x0213, utf8_to_euc_EFBD_x0213, utf8_to_euc_EFBE, utf8_to_euc_EFBF_x0213, -}; -const unsigned short *const utf8_to_euc_2bytes[] = { - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, utf8_to_euc_C2, utf8_to_euc_C3, - utf8_to_euc_C4, utf8_to_euc_C5, 0, utf8_to_euc_C7, - 0, 0, 0, utf8_to_euc_CB, - 0, 0, utf8_to_euc_CE, utf8_to_euc_CF, - utf8_to_euc_D0, utf8_to_euc_D1, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, -}; -const unsigned short *const utf8_to_euc_2bytes_ms[] = { - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, utf8_to_euc_C2_ms, utf8_to_euc_C3, - utf8_to_euc_C4, utf8_to_euc_C5, 0, utf8_to_euc_C7, - 0, 0, 0, utf8_to_euc_CB, - 0, 0, utf8_to_euc_CE, utf8_to_euc_CF, - utf8_to_euc_D0, utf8_to_euc_D1, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, -}; -const unsigned short *const utf8_to_euc_2bytes_932[] = { - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, utf8_to_euc_C2_932, utf8_to_euc_C3_932, - utf8_to_euc_C4, utf8_to_euc_C5, 0, utf8_to_euc_C7, - 0, 0, 0, utf8_to_euc_CB, - 0, 0, utf8_to_euc_CE, utf8_to_euc_CF, - utf8_to_euc_D0, utf8_to_euc_D1, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, -}; -const unsigned short *const utf8_to_euc_2bytes_mac[] = { - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, utf8_to_euc_C2_mac, utf8_to_euc_C3, - utf8_to_euc_C4, utf8_to_euc_C5, 0, utf8_to_euc_C7, - 0, 0, 0, utf8_to_euc_CB, - 0, 0, utf8_to_euc_CE, utf8_to_euc_CF, - utf8_to_euc_D0, utf8_to_euc_D1, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, -}; -const unsigned short *const utf8_to_euc_2bytes_x0213[] = { - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, utf8_to_euc_C2_x0213, utf8_to_euc_C3_x0213, - utf8_to_euc_C4_x0213, utf8_to_euc_C5_x0213, utf8_to_euc_C6_x0213, utf8_to_euc_C7_x0213, - 0, utf8_to_euc_C9_x0213, utf8_to_euc_CA_x0213, utf8_to_euc_CB_x0213, - utf8_to_euc_CC_x0213, utf8_to_euc_CD_x0213, utf8_to_euc_CE, utf8_to_euc_CF_x0213, - utf8_to_euc_D0, utf8_to_euc_D1, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, -}; -const unsigned short *const *const utf8_to_euc_3bytes[] = { - 0, 0, utf8_to_euc_E2, utf8_to_euc_E3, - utf8_to_euc_E4, utf8_to_euc_E5, utf8_to_euc_E6, utf8_to_euc_E7, - utf8_to_euc_E8, utf8_to_euc_E9, 0, 0, - 0, 0, 0, utf8_to_euc_EF, -}; -const unsigned short *const *const utf8_to_euc_3bytes_ms[] = { - 0, 0, utf8_to_euc_E2_ms, utf8_to_euc_E3, - utf8_to_euc_E4, utf8_to_euc_E5, utf8_to_euc_E6, utf8_to_euc_E7, - utf8_to_euc_E8, utf8_to_euc_E9, 0, 0, - 0, 0, 0, utf8_to_euc_EF_ms, -}; -const unsigned short *const *const utf8_to_euc_3bytes_932[] = { - 0, 0, utf8_to_euc_E2_932, utf8_to_euc_E3_932, - utf8_to_euc_E4, utf8_to_euc_E5, utf8_to_euc_E6, utf8_to_euc_E7, - utf8_to_euc_E8, utf8_to_euc_E9, 0, 0, - 0, 0, 0, utf8_to_euc_EF_ms, -}; -const unsigned short *const *const utf8_to_euc_3bytes_mac[] = { - 0, 0, utf8_to_euc_E2_mac, utf8_to_euc_E3_mac, - utf8_to_euc_E4, utf8_to_euc_E5, utf8_to_euc_E6, utf8_to_euc_E7, - utf8_to_euc_E8, utf8_to_euc_E9, 0, 0, - 0, 0, 0, utf8_to_euc_EF_ms, -}; -const unsigned short *const *const utf8_to_euc_3bytes_x0213[] = { - 0, utf8_to_euc_E1_x0213, utf8_to_euc_E2_x0213, utf8_to_euc_E3_x0213, - utf8_to_euc_E4_x0213, utf8_to_euc_E5_x0213, utf8_to_euc_E6_x0213, utf8_to_euc_E7_x0213, - utf8_to_euc_E8_x0213, utf8_to_euc_E9_x0213, 0, 0, - 0, 0, 0, utf8_to_euc_EF_x0213, -}; - -#ifdef UNICODE_NORMALIZATION - -/* Normalization Table by Apple */ -/* http://developer.apple.com/technotes/tn/tn1150table.html */ - -const struct normalization_pair normalization_table[] = { - {{0xcd,0xbe}, {0x3b}}, - {{0xc3,0x80}, {0x41,0xcc,0x80,0x00}}, - {{0xc3,0x81}, {0x41,0xcc,0x81}}, - {{0xc3,0x82}, {0x41,0xcc,0x82}}, - {{0xe1,0xba,0xa6}, {0x41,0xcc,0x82,0xcc,0x80}}, - {{0xe1,0xba,0xa4}, {0x41,0xcc,0x82,0xcc,0x81}}, - {{0xe1,0xba,0xaa}, {0x41,0xcc,0x82,0xcc,0x83}}, - {{0xe1,0xba,0xa8}, {0x41,0xcc,0x82,0xcc,0x89}}, - {{0xc3,0x83}, {0x41,0xcc,0x83}}, - {{0xc4,0x80}, {0x41,0xcc,0x84}}, - {{0xc4,0x82}, {0x41,0xcc,0x86}}, - {{0xe1,0xba,0xb0}, {0x41,0xcc,0x86,0xcc,0x80}}, - {{0xe1,0xba,0xae}, {0x41,0xcc,0x86,0xcc,0x81}}, - {{0xe1,0xba,0xb4}, {0x41,0xcc,0x86,0xcc,0x83}}, - {{0xe1,0xba,0xb2}, {0x41,0xcc,0x86,0xcc,0x89}}, - {{0xc7,0xa0}, {0x41,0xcc,0x87,0xcc,0x84}}, - {{0xc3,0x84}, {0x41,0xcc,0x88}}, - {{0xc7,0x9e}, {0x41,0xcc,0x88,0xcc,0x84}}, - {{0xe1,0xba,0xa2}, {0x41,0xcc,0x89}}, - {{0xc3,0x85}, {0x41,0xcc,0x8a}}, - {{0xc7,0xba}, {0x41,0xcc,0x8a,0xcc,0x81}}, - {{0xc7,0x8d}, {0x41,0xcc,0x8c}}, - {{0xc8,0x80}, {0x41,0xcc,0x8f}}, - {{0xc8,0x82}, {0x41,0xcc,0x91}}, - {{0xe1,0xba,0xa0}, {0x41,0xcc,0xa3}}, - {{0xe1,0xba,0xac}, {0x41,0xcc,0xa3,0xcc,0x82}}, - {{0xe1,0xba,0xb6}, {0x41,0xcc,0xa3,0xcc,0x86}}, - {{0xe1,0xb8,0x80}, {0x41,0xcc,0xa5}}, - {{0xc4,0x84}, {0x41,0xcc,0xa8}}, - {{0xe1,0xb8,0x82}, {0x42,0xcc,0x87}}, - {{0xe1,0xb8,0x84}, {0x42,0xcc,0xa3}}, - {{0xe1,0xb8,0x86}, {0x42,0xcc,0xb1}}, - {{0xc4,0x86}, {0x43,0xcc,0x81}}, - {{0xc4,0x88}, {0x43,0xcc,0x82}}, - {{0xc4,0x8a}, {0x43,0xcc,0x87}}, - {{0xc4,0x8c}, {0x43,0xcc,0x8c}}, - {{0xc3,0x87}, {0x43,0xcc,0xa7}}, - {{0xe1,0xb8,0x88}, {0x43,0xcc,0xa7,0xcc,0x81}}, - {{0xe1,0xb8,0x8a}, {0x44,0xcc,0x87}}, - {{0xc4,0x8e}, {0x44,0xcc,0x8c}}, - {{0xe1,0xb8,0x8c}, {0x44,0xcc,0xa3}}, - {{0xe1,0xb8,0x90}, {0x44,0xcc,0xa7}}, - {{0xe1,0xb8,0x92}, {0x44,0xcc,0xad}}, - {{0xe1,0xb8,0x8e}, {0x44,0xcc,0xb1}}, - {{0xc3,0x88}, {0x45,0xcc,0x80}}, - {{0xc3,0x89}, {0x45,0xcc,0x81}}, - {{0xc3,0x8a}, {0x45,0xcc,0x82}}, - {{0xe1,0xbb,0x80}, {0x45,0xcc,0x82,0xcc,0x80}}, - {{0xe1,0xba,0xbe}, {0x45,0xcc,0x82,0xcc,0x81}}, - {{0xe1,0xbb,0x84}, {0x45,0xcc,0x82,0xcc,0x83}}, - {{0xe1,0xbb,0x82}, {0x45,0xcc,0x82,0xcc,0x89}}, - {{0xe1,0xba,0xbc}, {0x45,0xcc,0x83}}, - {{0xc4,0x92}, {0x45,0xcc,0x84}}, - {{0xe1,0xb8,0x94}, {0x45,0xcc,0x84,0xcc,0x80}}, - {{0xe1,0xb8,0x96}, {0x45,0xcc,0x84,0xcc,0x81}}, - {{0xc4,0x94}, {0x45,0xcc,0x86}}, - {{0xc4,0x96}, {0x45,0xcc,0x87}}, - {{0xc3,0x8b}, {0x45,0xcc,0x88}}, - {{0xe1,0xba,0xba}, {0x45,0xcc,0x89}}, - {{0xc4,0x9a}, {0x45,0xcc,0x8c}}, - {{0xc8,0x84}, {0x45,0xcc,0x8f}}, - {{0xc8,0x86}, {0x45,0xcc,0x91}}, - {{0xe1,0xba,0xb8}, {0x45,0xcc,0xa3}}, - {{0xe1,0xbb,0x86}, {0x45,0xcc,0xa3,0xcc,0x82}}, - {{0xe1,0xb8,0x9c}, {0x45,0xcc,0xa7,0xcc,0x86}}, - {{0xc4,0x98}, {0x45,0xcc,0xa8}}, - {{0xe1,0xb8,0x98}, {0x45,0xcc,0xad}}, - {{0xe1,0xb8,0x9a}, {0x45,0xcc,0xb0}}, - {{0xe1,0xb8,0x9e}, {0x46,0xcc,0x87}}, - {{0xc7,0xb4}, {0x47,0xcc,0x81}}, - {{0xc4,0x9c}, {0x47,0xcc,0x82}}, - {{0xe1,0xb8,0xa0}, {0x47,0xcc,0x84}}, - {{0xc4,0x9e}, {0x47,0xcc,0x86}}, - {{0xc4,0xa0}, {0x47,0xcc,0x87}}, - {{0xc7,0xa6}, {0x47,0xcc,0x8c}}, - {{0xc4,0xa2}, {0x47,0xcc,0xa7}}, - {{0xc4,0xa4}, {0x48,0xcc,0x82}}, - {{0xe1,0xb8,0xa2}, {0x48,0xcc,0x87}}, - {{0xe1,0xb8,0xa6}, {0x48,0xcc,0x88}}, - {{0xe1,0xb8,0xa4}, {0x48,0xcc,0xa3}}, - {{0xe1,0xb8,0xa8}, {0x48,0xcc,0xa7}}, - {{0xe1,0xb8,0xaa}, {0x48,0xcc,0xae}}, - {{0xc3,0x8c}, {0x49,0xcc,0x80}}, - {{0xc3,0x8d}, {0x49,0xcc,0x81}}, - {{0xc3,0x8e}, {0x49,0xcc,0x82}}, - {{0xc4,0xa8}, {0x49,0xcc,0x83}}, - {{0xc4,0xaa}, {0x49,0xcc,0x84}}, - {{0xc4,0xac}, {0x49,0xcc,0x86}}, - {{0xc4,0xb0}, {0x49,0xcc,0x87}}, - {{0xc3,0x8f}, {0x49,0xcc,0x88}}, - {{0xe1,0xb8,0xae}, {0x49,0xcc,0x88,0xcc,0x81}}, - {{0xe1,0xbb,0x88}, {0x49,0xcc,0x89}}, - {{0xc7,0x8f}, {0x49,0xcc,0x8c}}, - {{0xc8,0x88}, {0x49,0xcc,0x8f}}, - {{0xc8,0x8a}, {0x49,0xcc,0x91}}, - {{0xe1,0xbb,0x8a}, {0x49,0xcc,0xa3}}, - {{0xc4,0xae}, {0x49,0xcc,0xa8}}, - {{0xe1,0xb8,0xac}, {0x49,0xcc,0xb0}}, - {{0xc4,0xb4}, {0x4a,0xcc,0x82}}, - {{0xe1,0xb8,0xb0}, {0x4b,0xcc,0x81}}, - {{0xc7,0xa8}, {0x4b,0xcc,0x8c}}, - {{0xe1,0xb8,0xb2}, {0x4b,0xcc,0xa3}}, - {{0xc4,0xb6}, {0x4b,0xcc,0xa7}}, - {{0xe1,0xb8,0xb4}, {0x4b,0xcc,0xb1}}, - {{0xc4,0xb9}, {0x4c,0xcc,0x81}}, - {{0xc4,0xbd}, {0x4c,0xcc,0x8c}}, - {{0xe1,0xb8,0xb6}, {0x4c,0xcc,0xa3}}, - {{0xe1,0xb8,0xb8}, {0x4c,0xcc,0xa3,0xcc,0x84}}, - {{0xc4,0xbb}, {0x4c,0xcc,0xa7}}, - {{0xe1,0xb8,0xbc}, {0x4c,0xcc,0xad}}, - {{0xe1,0xb8,0xba}, {0x4c,0xcc,0xb1}}, - {{0xe1,0xb8,0xbe}, {0x4d,0xcc,0x81}}, - {{0xe1,0xb9,0x80}, {0x4d,0xcc,0x87}}, - {{0xe1,0xb9,0x82}, {0x4d,0xcc,0xa3}}, - {{0xc5,0x83}, {0x4e,0xcc,0x81}}, - {{0xc3,0x91}, {0x4e,0xcc,0x83}}, - {{0xe1,0xb9,0x84}, {0x4e,0xcc,0x87}}, - {{0xc5,0x87}, {0x4e,0xcc,0x8c}}, - {{0xe1,0xb9,0x86}, {0x4e,0xcc,0xa3}}, - {{0xc5,0x85}, {0x4e,0xcc,0xa7}}, - {{0xe1,0xb9,0x8a}, {0x4e,0xcc,0xad}}, - {{0xe1,0xb9,0x88}, {0x4e,0xcc,0xb1}}, - {{0xc3,0x92}, {0x4f,0xcc,0x80}}, - {{0xc3,0x93}, {0x4f,0xcc,0x81}}, - {{0xc3,0x94}, {0x4f,0xcc,0x82}}, - {{0xe1,0xbb,0x92}, {0x4f,0xcc,0x82,0xcc,0x80}}, - {{0xe1,0xbb,0x90}, {0x4f,0xcc,0x82,0xcc,0x81}}, - {{0xe1,0xbb,0x96}, {0x4f,0xcc,0x82,0xcc,0x83}}, - {{0xe1,0xbb,0x94}, {0x4f,0xcc,0x82,0xcc,0x89}}, - {{0xc3,0x95}, {0x4f,0xcc,0x83}}, - {{0xe1,0xb9,0x8c}, {0x4f,0xcc,0x83,0xcc,0x81}}, - {{0xe1,0xb9,0x8e}, {0x4f,0xcc,0x83,0xcc,0x88}}, - {{0xc5,0x8c}, {0x4f,0xcc,0x84}}, - {{0xe1,0xb9,0x90}, {0x4f,0xcc,0x84,0xcc,0x80}}, - {{0xe1,0xb9,0x92}, {0x4f,0xcc,0x84,0xcc,0x81}}, - {{0xc5,0x8e}, {0x4f,0xcc,0x86}}, - {{0xc3,0x96}, {0x4f,0xcc,0x88}}, - {{0xe1,0xbb,0x8e}, {0x4f,0xcc,0x89}}, - {{0xc5,0x90}, {0x4f,0xcc,0x8b}}, - {{0xc7,0x91}, {0x4f,0xcc,0x8c}}, - {{0xc8,0x8c}, {0x4f,0xcc,0x8f}}, - {{0xc8,0x8e}, {0x4f,0xcc,0x91}}, - {{0xc6,0xa0}, {0x4f,0xcc,0x9b}}, - {{0xe1,0xbb,0x9c}, {0x4f,0xcc,0x9b,0xcc,0x80}}, - {{0xe1,0xbb,0x9a}, {0x4f,0xcc,0x9b,0xcc,0x81}}, - {{0xe1,0xbb,0xa0}, {0x4f,0xcc,0x9b,0xcc,0x83}}, - {{0xe1,0xbb,0x9e}, {0x4f,0xcc,0x9b,0xcc,0x89}}, - {{0xe1,0xbb,0xa2}, {0x4f,0xcc,0x9b,0xcc,0xa3}}, - {{0xe1,0xbb,0x8c}, {0x4f,0xcc,0xa3}}, - {{0xe1,0xbb,0x98}, {0x4f,0xcc,0xa3,0xcc,0x82}}, - {{0xc7,0xaa}, {0x4f,0xcc,0xa8}}, - {{0xc7,0xac}, {0x4f,0xcc,0xa8,0xcc,0x84}}, - {{0xe1,0xb9,0x94}, {0x50,0xcc,0x81}}, - {{0xe1,0xb9,0x96}, {0x50,0xcc,0x87}}, - {{0xc5,0x94}, {0x52,0xcc,0x81}}, - {{0xe1,0xb9,0x98}, {0x52,0xcc,0x87}}, - {{0xc5,0x98}, {0x52,0xcc,0x8c}}, - {{0xc8,0x90}, {0x52,0xcc,0x8f}}, - {{0xc8,0x92}, {0x52,0xcc,0x91}}, - {{0xe1,0xb9,0x9a}, {0x52,0xcc,0xa3}}, - {{0xe1,0xb9,0x9c}, {0x52,0xcc,0xa3,0xcc,0x84}}, - {{0xc5,0x96}, {0x52,0xcc,0xa7}}, - {{0xe1,0xb9,0x9e}, {0x52,0xcc,0xb1}}, - {{0xc5,0x9a}, {0x53,0xcc,0x81}}, - {{0xe1,0xb9,0xa4}, {0x53,0xcc,0x81,0xcc,0x87}}, - {{0xc5,0x9c}, {0x53,0xcc,0x82}}, - {{0xe1,0xb9,0xa0}, {0x53,0xcc,0x87}}, - {{0xc5,0xa0}, {0x53,0xcc,0x8c}}, - {{0xe1,0xb9,0xa6}, {0x53,0xcc,0x8c,0xcc,0x87}}, - {{0xe1,0xb9,0xa2}, {0x53,0xcc,0xa3}}, - {{0xe1,0xb9,0xa8}, {0x53,0xcc,0xa3,0xcc,0x87}}, - {{0xc5,0x9e}, {0x53,0xcc,0xa7}}, - {{0xe1,0xb9,0xaa}, {0x54,0xcc,0x87}}, - {{0xc5,0xa4}, {0x54,0xcc,0x8c}}, - {{0xe1,0xb9,0xac}, {0x54,0xcc,0xa3}}, - {{0xc5,0xa2}, {0x54,0xcc,0xa7}}, - {{0xe1,0xb9,0xb0}, {0x54,0xcc,0xad}}, - {{0xe1,0xb9,0xae}, {0x54,0xcc,0xb1}}, - {{0xc3,0x99}, {0x55,0xcc,0x80}}, - {{0xc3,0x9a}, {0x55,0xcc,0x81}}, - {{0xc3,0x9b}, {0x55,0xcc,0x82}}, - {{0xc5,0xa8}, {0x55,0xcc,0x83}}, - {{0xe1,0xb9,0xb8}, {0x55,0xcc,0x83,0xcc,0x81}}, - {{0xc5,0xaa}, {0x55,0xcc,0x84}}, - {{0xe1,0xb9,0xba}, {0x55,0xcc,0x84,0xcc,0x88}}, - {{0xc5,0xac}, {0x55,0xcc,0x86}}, - {{0xc3,0x9c}, {0x55,0xcc,0x88}}, - {{0xc7,0x9b}, {0x55,0xcc,0x88,0xcc,0x80}}, - {{0xc7,0x97}, {0x55,0xcc,0x88,0xcc,0x81}}, - {{0xc7,0x95}, {0x55,0xcc,0x88,0xcc,0x84}}, - {{0xc7,0x99}, {0x55,0xcc,0x88,0xcc,0x8c}}, - {{0xe1,0xbb,0xa6}, {0x55,0xcc,0x89}}, - {{0xc5,0xae}, {0x55,0xcc,0x8a}}, - {{0xc5,0xb0}, {0x55,0xcc,0x8b}}, - {{0xc7,0x93}, {0x55,0xcc,0x8c}}, - {{0xc8,0x94}, {0x55,0xcc,0x8f}}, - {{0xc8,0x96}, {0x55,0xcc,0x91}}, - {{0xc6,0xaf}, {0x55,0xcc,0x9b}}, - {{0xe1,0xbb,0xaa}, {0x55,0xcc,0x9b,0xcc,0x80}}, - {{0xe1,0xbb,0xa8}, {0x55,0xcc,0x9b,0xcc,0x81}}, - {{0xe1,0xbb,0xae}, {0x55,0xcc,0x9b,0xcc,0x83}}, - {{0xe1,0xbb,0xac}, {0x55,0xcc,0x9b,0xcc,0x89}}, - {{0xe1,0xbb,0xb0}, {0x55,0xcc,0x9b,0xcc,0xa3}}, - {{0xe1,0xbb,0xa4}, {0x55,0xcc,0xa3}}, - {{0xe1,0xb9,0xb2}, {0x55,0xcc,0xa4}}, - {{0xc5,0xb2}, {0x55,0xcc,0xa8}}, - {{0xe1,0xb9,0xb6}, {0x55,0xcc,0xad}}, - {{0xe1,0xb9,0xb4}, {0x55,0xcc,0xb0}}, - {{0xe1,0xb9,0xbc}, {0x56,0xcc,0x83}}, - {{0xe1,0xb9,0xbe}, {0x56,0xcc,0xa3}}, - {{0xe1,0xba,0x80}, {0x57,0xcc,0x80}}, - {{0xe1,0xba,0x82}, {0x57,0xcc,0x81}}, - {{0xc5,0xb4}, {0x57,0xcc,0x82}}, - {{0xe1,0xba,0x86}, {0x57,0xcc,0x87}}, - {{0xe1,0xba,0x84}, {0x57,0xcc,0x88}}, - {{0xe1,0xba,0x88}, {0x57,0xcc,0xa3}}, - {{0xe1,0xba,0x8a}, {0x58,0xcc,0x87}}, - {{0xe1,0xba,0x8c}, {0x58,0xcc,0x88}}, - {{0xe1,0xbb,0xb2}, {0x59,0xcc,0x80}}, - {{0xc3,0x9d}, {0x59,0xcc,0x81}}, - {{0xc5,0xb6}, {0x59,0xcc,0x82}}, - {{0xe1,0xbb,0xb8}, {0x59,0xcc,0x83}}, - {{0xe1,0xba,0x8e}, {0x59,0xcc,0x87}}, - {{0xc5,0xb8}, {0x59,0xcc,0x88}}, - {{0xe1,0xbb,0xb6}, {0x59,0xcc,0x89}}, - {{0xe1,0xbb,0xb4}, {0x59,0xcc,0xa3}}, - {{0xc5,0xb9}, {0x5a,0xcc,0x81}}, - {{0xe1,0xba,0x90}, {0x5a,0xcc,0x82}}, - {{0xc5,0xbb}, {0x5a,0xcc,0x87}}, - {{0xc5,0xbd}, {0x5a,0xcc,0x8c}}, - {{0xe1,0xba,0x92}, {0x5a,0xcc,0xa3}}, - {{0xe1,0xba,0x94}, {0x5a,0xcc,0xb1}}, - {{0xe1,0xbf,0xaf}, {0x60}}, - {{0xc3,0xa0}, {0x61,0xcc,0x80}}, - {{0xc3,0xa1}, {0x61,0xcc,0x81}}, - {{0xc3,0xa2}, {0x61,0xcc,0x82}}, - {{0xe1,0xba,0xa7}, {0x61,0xcc,0x82,0xcc,0x80}}, - {{0xe1,0xba,0xa5}, {0x61,0xcc,0x82,0xcc,0x81}}, - {{0xe1,0xba,0xab}, {0x61,0xcc,0x82,0xcc,0x83}}, - {{0xe1,0xba,0xa9}, {0x61,0xcc,0x82,0xcc,0x89}}, - {{0xc3,0xa3}, {0x61,0xcc,0x83}}, - {{0xc4,0x81}, {0x61,0xcc,0x84}}, - {{0xc4,0x83}, {0x61,0xcc,0x86}}, - {{0xe1,0xba,0xb1}, {0x61,0xcc,0x86,0xcc,0x80}}, - {{0xe1,0xba,0xaf}, {0x61,0xcc,0x86,0xcc,0x81}}, - {{0xe1,0xba,0xb5}, {0x61,0xcc,0x86,0xcc,0x83}}, - {{0xe1,0xba,0xb3}, {0x61,0xcc,0x86,0xcc,0x89}}, - {{0xc7,0xa1}, {0x61,0xcc,0x87,0xcc,0x84}}, - {{0xc3,0xa4}, {0x61,0xcc,0x88}}, - {{0xc7,0x9f}, {0x61,0xcc,0x88,0xcc,0x84}}, - {{0xe1,0xba,0xa3}, {0x61,0xcc,0x89}}, - {{0xc3,0xa5}, {0x61,0xcc,0x8a}}, - {{0xc7,0xbb}, {0x61,0xcc,0x8a,0xcc,0x81}}, - {{0xc7,0x8e}, {0x61,0xcc,0x8c}}, - {{0xc8,0x81}, {0x61,0xcc,0x8f}}, - {{0xc8,0x83}, {0x61,0xcc,0x91}}, - {{0xe1,0xba,0xa1}, {0x61,0xcc,0xa3}}, - {{0xe1,0xba,0xad}, {0x61,0xcc,0xa3,0xcc,0x82}}, - {{0xe1,0xba,0xb7}, {0x61,0xcc,0xa3,0xcc,0x86}}, - {{0xe1,0xb8,0x81}, {0x61,0xcc,0xa5}}, - {{0xc4,0x85}, {0x61,0xcc,0xa8}}, - {{0xe1,0xb8,0x83}, {0x62,0xcc,0x87}}, - {{0xe1,0xb8,0x85}, {0x62,0xcc,0xa3}}, - {{0xe1,0xb8,0x87}, {0x62,0xcc,0xb1}}, - {{0xc4,0x87}, {0x63,0xcc,0x81}}, - {{0xc4,0x89}, {0x63,0xcc,0x82}}, - {{0xc4,0x8b}, {0x63,0xcc,0x87}}, - {{0xc4,0x8d}, {0x63,0xcc,0x8c}}, - {{0xc3,0xa7}, {0x63,0xcc,0xa7}}, - {{0xe1,0xb8,0x89}, {0x63,0xcc,0xa7,0xcc,0x81}}, - {{0xe1,0xb8,0x8b}, {0x64,0xcc,0x87}}, - {{0xc4,0x8f}, {0x64,0xcc,0x8c}}, - {{0xe1,0xb8,0x8d}, {0x64,0xcc,0xa3}}, - {{0xe1,0xb8,0x91}, {0x64,0xcc,0xa7}}, - {{0xe1,0xb8,0x93}, {0x64,0xcc,0xad}}, - {{0xe1,0xb8,0x8f}, {0x64,0xcc,0xb1}}, - {{0xc3,0xa8}, {0x65,0xcc,0x80}}, - {{0xc3,0xa9}, {0x65,0xcc,0x81}}, - {{0xc3,0xaa}, {0x65,0xcc,0x82}}, - {{0xe1,0xbb,0x81}, {0x65,0xcc,0x82,0xcc,0x80}}, - {{0xe1,0xba,0xbf}, {0x65,0xcc,0x82,0xcc,0x81}}, - {{0xe1,0xbb,0x85}, {0x65,0xcc,0x82,0xcc,0x83}}, - {{0xe1,0xbb,0x83}, {0x65,0xcc,0x82,0xcc,0x89}}, - {{0xe1,0xba,0xbd}, {0x65,0xcc,0x83}}, - {{0xc4,0x93}, {0x65,0xcc,0x84}}, - {{0xe1,0xb8,0x95}, {0x65,0xcc,0x84,0xcc,0x80}}, - {{0xe1,0xb8,0x97}, {0x65,0xcc,0x84,0xcc,0x81}}, - {{0xc4,0x95}, {0x65,0xcc,0x86}}, - {{0xc4,0x97}, {0x65,0xcc,0x87}}, - {{0xc3,0xab}, {0x65,0xcc,0x88}}, - {{0xe1,0xba,0xbb}, {0x65,0xcc,0x89}}, - {{0xc4,0x9b}, {0x65,0xcc,0x8c}}, - {{0xc8,0x85}, {0x65,0xcc,0x8f}}, - {{0xc8,0x87}, {0x65,0xcc,0x91}}, - {{0xe1,0xba,0xb9}, {0x65,0xcc,0xa3}}, - {{0xe1,0xbb,0x87}, {0x65,0xcc,0xa3,0xcc,0x82}}, - {{0xe1,0xb8,0x9d}, {0x65,0xcc,0xa7,0xcc,0x86}}, - {{0xc4,0x99}, {0x65,0xcc,0xa8}}, - {{0xe1,0xb8,0x99}, {0x65,0xcc,0xad}}, - {{0xe1,0xb8,0x9b}, {0x65,0xcc,0xb0}}, - {{0xe1,0xb8,0x9f}, {0x66,0xcc,0x87}}, - {{0xc7,0xb5}, {0x67,0xcc,0x81}}, - {{0xc4,0x9d}, {0x67,0xcc,0x82}}, - {{0xe1,0xb8,0xa1}, {0x67,0xcc,0x84}}, - {{0xc4,0x9f}, {0x67,0xcc,0x86}}, - {{0xc4,0xa1}, {0x67,0xcc,0x87}}, - {{0xc7,0xa7}, {0x67,0xcc,0x8c}}, - {{0xc4,0xa3}, {0x67,0xcc,0xa7}}, - {{0xc4,0xa5}, {0x68,0xcc,0x82}}, - {{0xe1,0xb8,0xa3}, {0x68,0xcc,0x87}}, - {{0xe1,0xb8,0xa7}, {0x68,0xcc,0x88}}, - {{0xe1,0xb8,0xa5}, {0x68,0xcc,0xa3}}, - {{0xe1,0xb8,0xa9}, {0x68,0xcc,0xa7}}, - {{0xe1,0xb8,0xab}, {0x68,0xcc,0xae}}, - {{0xe1,0xba,0x96}, {0x68,0xcc,0xb1}}, - {{0xc3,0xac}, {0x69,0xcc,0x80}}, - {{0xc3,0xad}, {0x69,0xcc,0x81}}, - {{0xc3,0xae}, {0x69,0xcc,0x82}}, - {{0xc4,0xa9}, {0x69,0xcc,0x83}}, - {{0xc4,0xab}, {0x69,0xcc,0x84}}, - {{0xc4,0xad}, {0x69,0xcc,0x86}}, - {{0xc3,0xaf}, {0x69,0xcc,0x88}}, - {{0xe1,0xb8,0xaf}, {0x69,0xcc,0x88,0xcc,0x81}}, - {{0xe1,0xbb,0x89}, {0x69,0xcc,0x89}}, - {{0xc7,0x90}, {0x69,0xcc,0x8c}}, - {{0xc8,0x89}, {0x69,0xcc,0x8f}}, - {{0xc8,0x8b}, {0x69,0xcc,0x91}}, - {{0xe1,0xbb,0x8b}, {0x69,0xcc,0xa3}}, - {{0xc4,0xaf}, {0x69,0xcc,0xa8}}, - {{0xe1,0xb8,0xad}, {0x69,0xcc,0xb0}}, - {{0xc4,0xb5}, {0x6a,0xcc,0x82}}, - {{0xc7,0xb0}, {0x6a,0xcc,0x8c}}, - {{0xe1,0xb8,0xb1}, {0x6b,0xcc,0x81}}, - {{0xc7,0xa9}, {0x6b,0xcc,0x8c}}, - {{0xe1,0xb8,0xb3}, {0x6b,0xcc,0xa3}}, - {{0xc4,0xb7}, {0x6b,0xcc,0xa7}}, - {{0xe1,0xb8,0xb5}, {0x6b,0xcc,0xb1}}, - {{0xc4,0xba}, {0x6c,0xcc,0x81}}, - {{0xc4,0xbe}, {0x6c,0xcc,0x8c}}, - {{0xe1,0xb8,0xb7}, {0x6c,0xcc,0xa3}}, - {{0xe1,0xb8,0xb9}, {0x6c,0xcc,0xa3,0xcc,0x84}}, - {{0xc4,0xbc}, {0x6c,0xcc,0xa7}}, - {{0xe1,0xb8,0xbd}, {0x6c,0xcc,0xad}}, - {{0xe1,0xb8,0xbb}, {0x6c,0xcc,0xb1}}, - {{0xe1,0xb8,0xbf}, {0x6d,0xcc,0x81}}, - {{0xe1,0xb9,0x81}, {0x6d,0xcc,0x87}}, - {{0xe1,0xb9,0x83}, {0x6d,0xcc,0xa3}}, - {{0xc5,0x84}, {0x6e,0xcc,0x81}}, - {{0xc3,0xb1}, {0x6e,0xcc,0x83}}, - {{0xe1,0xb9,0x85}, {0x6e,0xcc,0x87}}, - {{0xc5,0x88}, {0x6e,0xcc,0x8c}}, - {{0xe1,0xb9,0x87}, {0x6e,0xcc,0xa3}}, - {{0xc5,0x86}, {0x6e,0xcc,0xa7}}, - {{0xe1,0xb9,0x8b}, {0x6e,0xcc,0xad}}, - {{0xe1,0xb9,0x89}, {0x6e,0xcc,0xb1}}, - {{0xc3,0xb2}, {0x6f,0xcc,0x80}}, - {{0xc3,0xb3}, {0x6f,0xcc,0x81}}, - {{0xc3,0xb4}, {0x6f,0xcc,0x82}}, - {{0xe1,0xbb,0x93}, {0x6f,0xcc,0x82,0xcc,0x80}}, - {{0xe1,0xbb,0x91}, {0x6f,0xcc,0x82,0xcc,0x81}}, - {{0xe1,0xbb,0x97}, {0x6f,0xcc,0x82,0xcc,0x83}}, - {{0xe1,0xbb,0x95}, {0x6f,0xcc,0x82,0xcc,0x89}}, - {{0xc3,0xb5}, {0x6f,0xcc,0x83}}, - {{0xe1,0xb9,0x8d}, {0x6f,0xcc,0x83,0xcc,0x81}}, - {{0xe1,0xb9,0x8f}, {0x6f,0xcc,0x83,0xcc,0x88}}, - {{0xc5,0x8d}, {0x6f,0xcc,0x84}}, - {{0xe1,0xb9,0x91}, {0x6f,0xcc,0x84,0xcc,0x80}}, - {{0xe1,0xb9,0x93}, {0x6f,0xcc,0x84,0xcc,0x81}}, - {{0xc5,0x8f}, {0x6f,0xcc,0x86}}, - {{0xc3,0xb6}, {0x6f,0xcc,0x88}}, - {{0xe1,0xbb,0x8f}, {0x6f,0xcc,0x89}}, - {{0xc5,0x91}, {0x6f,0xcc,0x8b}}, - {{0xc7,0x92}, {0x6f,0xcc,0x8c}}, - {{0xc8,0x8d}, {0x6f,0xcc,0x8f}}, - {{0xc8,0x8f}, {0x6f,0xcc,0x91}}, - {{0xc6,0xa1}, {0x6f,0xcc,0x9b}}, - {{0xe1,0xbb,0x9d}, {0x6f,0xcc,0x9b,0xcc,0x80}}, - {{0xe1,0xbb,0x9b}, {0x6f,0xcc,0x9b,0xcc,0x81}}, - {{0xe1,0xbb,0xa1}, {0x6f,0xcc,0x9b,0xcc,0x83}}, - {{0xe1,0xbb,0x9f}, {0x6f,0xcc,0x9b,0xcc,0x89}}, - {{0xe1,0xbb,0xa3}, {0x6f,0xcc,0x9b,0xcc,0xa3}}, - {{0xe1,0xbb,0x8d}, {0x6f,0xcc,0xa3}}, - {{0xe1,0xbb,0x99}, {0x6f,0xcc,0xa3,0xcc,0x82}}, - {{0xc7,0xab}, {0x6f,0xcc,0xa8}}, - {{0xc7,0xad}, {0x6f,0xcc,0xa8,0xcc,0x84}}, - {{0xe1,0xb9,0x95}, {0x70,0xcc,0x81}}, - {{0xe1,0xb9,0x97}, {0x70,0xcc,0x87}}, - {{0xc5,0x95}, {0x72,0xcc,0x81}}, - {{0xe1,0xb9,0x99}, {0x72,0xcc,0x87}}, - {{0xc5,0x99}, {0x72,0xcc,0x8c}}, - {{0xc8,0x91}, {0x72,0xcc,0x8f}}, - {{0xc8,0x93}, {0x72,0xcc,0x91}}, - {{0xe1,0xb9,0x9b}, {0x72,0xcc,0xa3}}, - {{0xe1,0xb9,0x9d}, {0x72,0xcc,0xa3,0xcc,0x84}}, - {{0xc5,0x97}, {0x72,0xcc,0xa7}}, - {{0xe1,0xb9,0x9f}, {0x72,0xcc,0xb1}}, - {{0xc5,0x9b}, {0x73,0xcc,0x81}}, - {{0xe1,0xb9,0xa5}, {0x73,0xcc,0x81,0xcc,0x87}}, - {{0xc5,0x9d}, {0x73,0xcc,0x82}}, - {{0xe1,0xb9,0xa1}, {0x73,0xcc,0x87}}, - {{0xc5,0xa1}, {0x73,0xcc,0x8c}}, - {{0xe1,0xb9,0xa7}, {0x73,0xcc,0x8c,0xcc,0x87}}, - {{0xe1,0xb9,0xa3}, {0x73,0xcc,0xa3}}, - {{0xe1,0xb9,0xa9}, {0x73,0xcc,0xa3,0xcc,0x87}}, - {{0xc5,0x9f}, {0x73,0xcc,0xa7}}, - {{0xe1,0xb9,0xab}, {0x74,0xcc,0x87}}, - {{0xe1,0xba,0x97}, {0x74,0xcc,0x88}}, - {{0xc5,0xa5}, {0x74,0xcc,0x8c}}, - {{0xe1,0xb9,0xad}, {0x74,0xcc,0xa3}}, - {{0xc5,0xa3}, {0x74,0xcc,0xa7}}, - {{0xe1,0xb9,0xb1}, {0x74,0xcc,0xad}}, - {{0xe1,0xb9,0xaf}, {0x74,0xcc,0xb1}}, - {{0xc3,0xb9}, {0x75,0xcc,0x80}}, - {{0xc3,0xba}, {0x75,0xcc,0x81}}, - {{0xc3,0xbb}, {0x75,0xcc,0x82}}, - {{0xc5,0xa9}, {0x75,0xcc,0x83}}, - {{0xe1,0xb9,0xb9}, {0x75,0xcc,0x83,0xcc,0x81}}, - {{0xc5,0xab}, {0x75,0xcc,0x84}}, - {{0xe1,0xb9,0xbb}, {0x75,0xcc,0x84,0xcc,0x88}}, - {{0xc5,0xad}, {0x75,0xcc,0x86}}, - {{0xc3,0xbc}, {0x75,0xcc,0x88}}, - {{0xc7,0x9c}, {0x75,0xcc,0x88,0xcc,0x80}}, - {{0xc7,0x98}, {0x75,0xcc,0x88,0xcc,0x81}}, - {{0xc7,0x96}, {0x75,0xcc,0x88,0xcc,0x84}}, - {{0xc7,0x9a}, {0x75,0xcc,0x88,0xcc,0x8c}}, - {{0xe1,0xbb,0xa7}, {0x75,0xcc,0x89}}, - {{0xc5,0xaf}, {0x75,0xcc,0x8a}}, - {{0xc5,0xb1}, {0x75,0xcc,0x8b}}, - {{0xc7,0x94}, {0x75,0xcc,0x8c}}, - {{0xc8,0x95}, {0x75,0xcc,0x8f}}, - {{0xc8,0x97}, {0x75,0xcc,0x91}}, - {{0xc6,0xb0}, {0x75,0xcc,0x9b}}, - {{0xe1,0xbb,0xab}, {0x75,0xcc,0x9b,0xcc,0x80}}, - {{0xe1,0xbb,0xa9}, {0x75,0xcc,0x9b,0xcc,0x81}}, - {{0xe1,0xbb,0xaf}, {0x75,0xcc,0x9b,0xcc,0x83}}, - {{0xe1,0xbb,0xad}, {0x75,0xcc,0x9b,0xcc,0x89}}, - {{0xe1,0xbb,0xb1}, {0x75,0xcc,0x9b,0xcc,0xa3}}, - {{0xe1,0xbb,0xa5}, {0x75,0xcc,0xa3}}, - {{0xe1,0xb9,0xb3}, {0x75,0xcc,0xa4}}, - {{0xc5,0xb3}, {0x75,0xcc,0xa8}}, - {{0xe1,0xb9,0xb7}, {0x75,0xcc,0xad}}, - {{0xe1,0xb9,0xb5}, {0x75,0xcc,0xb0}}, - {{0xe1,0xb9,0xbd}, {0x76,0xcc,0x83}}, - {{0xe1,0xb9,0xbf}, {0x76,0xcc,0xa3}}, - {{0xe1,0xba,0x81}, {0x77,0xcc,0x80}}, - {{0xe1,0xba,0x83}, {0x77,0xcc,0x81}}, - {{0xc5,0xb5}, {0x77,0xcc,0x82}}, - {{0xe1,0xba,0x87}, {0x77,0xcc,0x87}}, - {{0xe1,0xba,0x85}, {0x77,0xcc,0x88}}, - {{0xe1,0xba,0x98}, {0x77,0xcc,0x8a}}, - {{0xe1,0xba,0x89}, {0x77,0xcc,0xa3}}, - {{0xe1,0xba,0x8b}, {0x78,0xcc,0x87}}, - {{0xe1,0xba,0x8d}, {0x78,0xcc,0x88}}, - {{0xe1,0xbb,0xb3}, {0x79,0xcc,0x80}}, - {{0xc3,0xbd}, {0x79,0xcc,0x81}}, - {{0xc5,0xb7}, {0x79,0xcc,0x82}}, - {{0xe1,0xbb,0xb9}, {0x79,0xcc,0x83}}, - {{0xe1,0xba,0x8f}, {0x79,0xcc,0x87}}, - {{0xc3,0xbf}, {0x79,0xcc,0x88}}, - {{0xe1,0xbb,0xb7}, {0x79,0xcc,0x89}}, - {{0xe1,0xba,0x99}, {0x79,0xcc,0x8a}}, - {{0xe1,0xbb,0xb5}, {0x79,0xcc,0xa3}}, - {{0xc5,0xba}, {0x7a,0xcc,0x81}}, - {{0xe1,0xba,0x91}, {0x7a,0xcc,0x82}}, - {{0xc5,0xbc}, {0x7a,0xcc,0x87}}, - {{0xc5,0xbe}, {0x7a,0xcc,0x8c}}, - {{0xe1,0xba,0x93}, {0x7a,0xcc,0xa3}}, - {{0xe1,0xba,0x95}, {0x7a,0xcc,0xb1}}, - {{0xe1,0xbf,0xad}, {0xc2,0xa8,0xcc,0x80}}, - {{0xe1,0xbf,0xae}, {0xc2,0xa8,0xcc,0x81}}, - {{0xce,0x85}, {0xc2,0xa8,0xcc,0x8d}}, - {{0xe1,0xbf,0x81}, {0xc2,0xa8,0xcd,0x82}}, - {{0xe1,0xbf,0xbd}, {0xc2,0xb4}}, - {{0xce,0x87}, {0xc2,0xb7}}, - {{0xd3,0x94}, {0xc3,0x86}}, - {{0xc7,0xbc}, {0xc3,0x86,0xcc,0x81}}, - {{0xc7,0xa2}, {0xc3,0x86,0xcc,0x84}}, - {{0xc7,0xbe}, {0xc3,0x98,0xcc,0x81}}, - {{0xd3,0x95}, {0xc3,0xa6}}, - {{0xc7,0xbd}, {0xc3,0xa6,0xcc,0x81}}, - {{0xc7,0xa3}, {0xc3,0xa6,0xcc,0x84}}, - {{0xc7,0xbf}, {0xc3,0xb8,0xcc,0x81}}, - {{0xe1,0xba,0x9b}, {0xc5,0xbf,0xcc,0x87}}, - {{0xd3,0x98}, {0xc6,0x8f}}, - {{0xd3,0x9a}, {0xc6,0x8f,0xcc,0x88}}, - {{0xd3,0xa8}, {0xc6,0x9f}}, - {{0xd3,0xaa}, {0xc6,0x9f,0xcc,0x88}}, - {{0xd3,0xa0}, {0xc6,0xb7}}, - {{0xc7,0xae}, {0xc6,0xb7,0xcc,0x8c}}, - {{0xd3,0x99}, {0xc9,0x99}}, - {{0xd3,0x9b}, {0xc9,0x99,0xcc,0x88}}, - {{0xd3,0xa9}, {0xc9,0xb5}}, - {{0xd3,0xab}, {0xc9,0xb5,0xcc,0x88}}, - {{0xd3,0xa1}, {0xca,0x92}}, - {{0xc7,0xaf}, {0xca,0x92,0xcc,0x8c}}, - {{0xcd,0xb4}, {0xca,0xb9}}, - {{0xcd,0x80}, {0xcc,0x80}}, - {{0xcd,0x81}, {0xcc,0x81}}, - {{0xcc,0x90}, {0xcc,0x86,0xcc,0x87}}, - {{0xcd,0x84}, {0xcc,0x88,0xcc,0x8d}}, - {{0xcd,0x83}, {0xcc,0x93}}, - {{0xe1,0xbe,0xba}, {0xce,0x91,0xcc,0x80}}, - {{0xe1,0xbe,0xbb}, {0xce,0x91,0xcc,0x81}}, - {{0xe1,0xbe,0xb9}, {0xce,0x91,0xcc,0x84}}, - {{0xe1,0xbe,0xb8}, {0xce,0x91,0xcc,0x86}}, - {{0xce,0x86}, {0xce,0x91,0xcc,0x8d}}, - {{0xe1,0xbc,0x88}, {0xce,0x91,0xcc,0x93}}, - {{0xe1,0xbc,0x8a}, {0xce,0x91,0xcc,0x93,0xcc,0x80}}, - {{0xe1,0xbc,0x8c}, {0xce,0x91,0xcc,0x93,0xcc,0x81}}, - {{0xe1,0xbc,0x8e}, {0xce,0x91,0xcc,0x93,0xcd,0x82}}, - {{0xe1,0xbc,0x89}, {0xce,0x91,0xcc,0x94}}, - {{0xe1,0xbc,0x8b}, {0xce,0x91,0xcc,0x94,0xcc,0x80}}, - {{0xe1,0xbc,0x8d}, {0xce,0x91,0xcc,0x94,0xcc,0x81}}, - {{0xe1,0xbc,0x8f}, {0xce,0x91,0xcc,0x94,0xcd,0x82}}, - {{0xe1,0xbe,0xbc}, {0xce,0x91,0xcd,0x85}}, - {{0xe1,0xbe,0x88}, {0xce,0x91,0xcd,0x85,0xcc,0x93}}, - {{0xe1,0xbe,0x8a}, {0xce,0x91,0xcd,0x85,0xcc,0x93,0xcc,0x80}}, - {{0xe1,0xbe,0x8c}, {0xce,0x91,0xcd,0x85,0xcc,0x93,0xcc,0x81}}, - {{0xe1,0xbe,0x8e}, {0xce,0x91,0xcd,0x85,0xcc,0x93,0xcd,0x82}}, - {{0xe1,0xbe,0x89}, {0xce,0x91,0xcd,0x85,0xcc,0x94}}, - {{0xe1,0xbe,0x8b}, {0xce,0x91,0xcd,0x85,0xcc,0x94,0xcc,0x80}}, - {{0xe1,0xbe,0x8d}, {0xce,0x91,0xcd,0x85,0xcc,0x94,0xcc,0x81}}, - {{0xe1,0xbe,0x8f}, {0xce,0x91,0xcd,0x85,0xcc,0x94,0xcd,0x82}}, - {{0xe1,0xbf,0x88}, {0xce,0x95,0xcc,0x80}}, - {{0xe1,0xbf,0x89}, {0xce,0x95,0xcc,0x81}}, - {{0xce,0x88}, {0xce,0x95,0xcc,0x8d}}, - {{0xe1,0xbc,0x98}, {0xce,0x95,0xcc,0x93}}, - {{0xe1,0xbc,0x9a}, {0xce,0x95,0xcc,0x93,0xcc,0x80}}, - {{0xe1,0xbc,0x9c}, {0xce,0x95,0xcc,0x93,0xcc,0x81}}, - {{0xe1,0xbc,0x99}, {0xce,0x95,0xcc,0x94}}, - {{0xe1,0xbc,0x9b}, {0xce,0x95,0xcc,0x94,0xcc,0x80}}, - {{0xe1,0xbc,0x9d}, {0xce,0x95,0xcc,0x94,0xcc,0x81}}, - {{0xe1,0xbf,0x8a}, {0xce,0x97,0xcc,0x80}}, - {{0xe1,0xbf,0x8b}, {0xce,0x97,0xcc,0x81}}, - {{0xce,0x89}, {0xce,0x97,0xcc,0x8d}}, - {{0xe1,0xbc,0xa8}, {0xce,0x97,0xcc,0x93}}, - {{0xe1,0xbc,0xaa}, {0xce,0x97,0xcc,0x93,0xcc,0x80}}, - {{0xe1,0xbc,0xac}, {0xce,0x97,0xcc,0x93,0xcc,0x81}}, - {{0xe1,0xbc,0xae}, {0xce,0x97,0xcc,0x93,0xcd,0x82}}, - {{0xe1,0xbc,0xa9}, {0xce,0x97,0xcc,0x94}}, - {{0xe1,0xbc,0xab}, {0xce,0x97,0xcc,0x94,0xcc,0x80}}, - {{0xe1,0xbc,0xad}, {0xce,0x97,0xcc,0x94,0xcc,0x81}}, - {{0xe1,0xbc,0xaf}, {0xce,0x97,0xcc,0x94,0xcd,0x82}}, - {{0xe1,0xbf,0x8c}, {0xce,0x97,0xcd,0x85}}, - {{0xe1,0xbe,0x98}, {0xce,0x97,0xcd,0x85,0xcc,0x93}}, - {{0xe1,0xbe,0x9a}, {0xce,0x97,0xcd,0x85,0xcc,0x93,0xcc,0x80}}, - {{0xe1,0xbe,0x9c}, {0xce,0x97,0xcd,0x85,0xcc,0x93,0xcc,0x81}}, - {{0xe1,0xbe,0x9e}, {0xce,0x97,0xcd,0x85,0xcc,0x93,0xcd,0x82}}, - {{0xe1,0xbe,0x99}, {0xce,0x97,0xcd,0x85,0xcc,0x94}}, - {{0xe1,0xbe,0x9b}, {0xce,0x97,0xcd,0x85,0xcc,0x94,0xcc,0x80}}, - {{0xe1,0xbe,0x9d}, {0xce,0x97,0xcd,0x85,0xcc,0x94,0xcc,0x81}}, - {{0xe1,0xbe,0x9f}, {0xce,0x97,0xcd,0x85,0xcc,0x94,0xcd,0x82}}, - {{0xe1,0xbf,0x9a}, {0xce,0x99,0xcc,0x80}}, - {{0xe1,0xbf,0x9b}, {0xce,0x99,0xcc,0x81}}, - {{0xe1,0xbf,0x99}, {0xce,0x99,0xcc,0x84}}, - {{0xe1,0xbf,0x98}, {0xce,0x99,0xcc,0x86}}, - {{0xce,0xaa}, {0xce,0x99,0xcc,0x88}}, - {{0xce,0x8a}, {0xce,0x99,0xcc,0x8d}}, - {{0xe1,0xbc,0xb8}, {0xce,0x99,0xcc,0x93}}, - {{0xe1,0xbc,0xba}, {0xce,0x99,0xcc,0x93,0xcc,0x80}}, - {{0xe1,0xbc,0xbc}, {0xce,0x99,0xcc,0x93,0xcc,0x81}}, - {{0xe1,0xbc,0xbe}, {0xce,0x99,0xcc,0x93,0xcd,0x82}}, - {{0xe1,0xbc,0xb9}, {0xce,0x99,0xcc,0x94}}, - {{0xe1,0xbc,0xbb}, {0xce,0x99,0xcc,0x94,0xcc,0x80}}, - {{0xe1,0xbc,0xbd}, {0xce,0x99,0xcc,0x94,0xcc,0x81}}, - {{0xe1,0xbc,0xbf}, {0xce,0x99,0xcc,0x94,0xcd,0x82}}, - {{0xe1,0xbf,0xb8}, {0xce,0x9f,0xcc,0x80}}, - {{0xe1,0xbf,0xb9}, {0xce,0x9f,0xcc,0x81}}, - {{0xce,0x8c}, {0xce,0x9f,0xcc,0x8d}}, - {{0xe1,0xbd,0x88}, {0xce,0x9f,0xcc,0x93}}, - {{0xe1,0xbd,0x8a}, {0xce,0x9f,0xcc,0x93,0xcc,0x80}}, - {{0xe1,0xbd,0x8c}, {0xce,0x9f,0xcc,0x93,0xcc,0x81}}, - {{0xe1,0xbd,0x89}, {0xce,0x9f,0xcc,0x94}}, - {{0xe1,0xbd,0x8b}, {0xce,0x9f,0xcc,0x94,0xcc,0x80}}, - {{0xe1,0xbd,0x8d}, {0xce,0x9f,0xcc,0x94,0xcc,0x81}}, - {{0xe1,0xbf,0xac}, {0xce,0xa1,0xcc,0x94}}, - {{0xe1,0xbf,0xaa}, {0xce,0xa5,0xcc,0x80}}, - {{0xe1,0xbf,0xab}, {0xce,0xa5,0xcc,0x81}}, - {{0xe1,0xbf,0xa9}, {0xce,0xa5,0xcc,0x84}}, - {{0xe1,0xbf,0xa8}, {0xce,0xa5,0xcc,0x86}}, - {{0xce,0xab}, {0xce,0xa5,0xcc,0x88}}, - {{0xce,0x8e}, {0xce,0xa5,0xcc,0x8d}}, - {{0xe1,0xbd,0x99}, {0xce,0xa5,0xcc,0x94}}, - {{0xe1,0xbd,0x9b}, {0xce,0xa5,0xcc,0x94,0xcc,0x80}}, - {{0xe1,0xbd,0x9d}, {0xce,0xa5,0xcc,0x94,0xcc,0x81}}, - {{0xe1,0xbd,0x9f}, {0xce,0xa5,0xcc,0x94,0xcd,0x82}}, - {{0xe1,0xbf,0xba}, {0xce,0xa9,0xcc,0x80}}, - {{0xe1,0xbf,0xbb}, {0xce,0xa9,0xcc,0x81}}, - {{0xce,0x8f}, {0xce,0xa9,0xcc,0x8d}}, - {{0xe1,0xbd,0xa8}, {0xce,0xa9,0xcc,0x93}}, - {{0xe1,0xbd,0xaa}, {0xce,0xa9,0xcc,0x93,0xcc,0x80}}, - {{0xe1,0xbd,0xac}, {0xce,0xa9,0xcc,0x93,0xcc,0x81}}, - {{0xe1,0xbd,0xae}, {0xce,0xa9,0xcc,0x93,0xcd,0x82}}, - {{0xe1,0xbd,0xa9}, {0xce,0xa9,0xcc,0x94}}, - {{0xe1,0xbd,0xab}, {0xce,0xa9,0xcc,0x94,0xcc,0x80}}, - {{0xe1,0xbd,0xad}, {0xce,0xa9,0xcc,0x94,0xcc,0x81}}, - {{0xe1,0xbd,0xaf}, {0xce,0xa9,0xcc,0x94,0xcd,0x82}}, - {{0xe1,0xbf,0xbc}, {0xce,0xa9,0xcd,0x85}}, - {{0xe1,0xbe,0xa8}, {0xce,0xa9,0xcd,0x85,0xcc,0x93}}, - {{0xe1,0xbe,0xaa}, {0xce,0xa9,0xcd,0x85,0xcc,0x93,0xcc,0x80}}, - {{0xe1,0xbe,0xac}, {0xce,0xa9,0xcd,0x85,0xcc,0x93,0xcc,0x81}}, - {{0xe1,0xbe,0xae}, {0xce,0xa9,0xcd,0x85,0xcc,0x93,0xcd,0x82}}, - {{0xe1,0xbe,0xa9}, {0xce,0xa9,0xcd,0x85,0xcc,0x94}}, - {{0xe1,0xbe,0xab}, {0xce,0xa9,0xcd,0x85,0xcc,0x94,0xcc,0x80}}, - {{0xe1,0xbe,0xad}, {0xce,0xa9,0xcd,0x85,0xcc,0x94,0xcc,0x81}}, - {{0xe1,0xbe,0xaf}, {0xce,0xa9,0xcd,0x85,0xcc,0x94,0xcd,0x82}}, - {{0xe1,0xbd,0xb0}, {0xce,0xb1,0xcc,0x80}}, - {{0xe1,0xbd,0xb1}, {0xce,0xb1,0xcc,0x81}}, - {{0xe1,0xbe,0xb1}, {0xce,0xb1,0xcc,0x84}}, - {{0xe1,0xbe,0xb0}, {0xce,0xb1,0xcc,0x86}}, - {{0xce,0xac}, {0xce,0xb1,0xcc,0x8d}}, - {{0xe1,0xbc,0x80}, {0xce,0xb1,0xcc,0x93}}, - {{0xe1,0xbc,0x82}, {0xce,0xb1,0xcc,0x93,0xcc,0x80}}, - {{0xe1,0xbc,0x84}, {0xce,0xb1,0xcc,0x93,0xcc,0x81}}, - {{0xe1,0xbc,0x86}, {0xce,0xb1,0xcc,0x93,0xcd,0x82}}, - {{0xe1,0xbc,0x81}, {0xce,0xb1,0xcc,0x94}}, - {{0xe1,0xbc,0x83}, {0xce,0xb1,0xcc,0x94,0xcc,0x80}}, - {{0xe1,0xbc,0x85}, {0xce,0xb1,0xcc,0x94,0xcc,0x81}}, - {{0xe1,0xbc,0x87}, {0xce,0xb1,0xcc,0x94,0xcd,0x82}}, - {{0xe1,0xbe,0xb6}, {0xce,0xb1,0xcd,0x82}}, - {{0xe1,0xbe,0xb3}, {0xce,0xb1,0xcd,0x85}}, - {{0xe1,0xbe,0xb2}, {0xce,0xb1,0xcd,0x85,0xcc,0x80}}, - {{0xe1,0xbe,0xb4}, {0xce,0xb1,0xcd,0x85,0xcc,0x81}}, - {{0xe1,0xbe,0x80}, {0xce,0xb1,0xcd,0x85,0xcc,0x93}}, - {{0xe1,0xbe,0x82}, {0xce,0xb1,0xcd,0x85,0xcc,0x93,0xcc,0x80}}, - {{0xe1,0xbe,0x84}, {0xce,0xb1,0xcd,0x85,0xcc,0x93,0xcc,0x81}}, - {{0xe1,0xbe,0x86}, {0xce,0xb1,0xcd,0x85,0xcc,0x93,0xcd,0x82}}, - {{0xe1,0xbe,0x81}, {0xce,0xb1,0xcd,0x85,0xcc,0x94}}, - {{0xe1,0xbe,0x83}, {0xce,0xb1,0xcd,0x85,0xcc,0x94,0xcc,0x80}}, - {{0xe1,0xbe,0x85}, {0xce,0xb1,0xcd,0x85,0xcc,0x94,0xcc,0x81}}, - {{0xe1,0xbe,0x87}, {0xce,0xb1,0xcd,0x85,0xcc,0x94,0xcd,0x82}}, - {{0xe1,0xbe,0xb7}, {0xce,0xb1,0xcd,0x85,0xcd,0x82}}, - {{0xe1,0xbd,0xb2}, {0xce,0xb5,0xcc,0x80}}, - {{0xe1,0xbd,0xb3}, {0xce,0xb5,0xcc,0x81}}, - {{0xce,0xad}, {0xce,0xb5,0xcc,0x8d}}, - {{0xe1,0xbc,0x90}, {0xce,0xb5,0xcc,0x93}}, - {{0xe1,0xbc,0x92}, {0xce,0xb5,0xcc,0x93,0xcc,0x80}}, - {{0xe1,0xbc,0x94}, {0xce,0xb5,0xcc,0x93,0xcc,0x81}}, - {{0xe1,0xbc,0x91}, {0xce,0xb5,0xcc,0x94}}, - {{0xe1,0xbc,0x93}, {0xce,0xb5,0xcc,0x94,0xcc,0x80}}, - {{0xe1,0xbc,0x95}, {0xce,0xb5,0xcc,0x94,0xcc,0x81}}, - {{0xe1,0xbd,0xb4}, {0xce,0xb7,0xcc,0x80}}, - {{0xe1,0xbd,0xb5}, {0xce,0xb7,0xcc,0x81}}, - {{0xce,0xae}, {0xce,0xb7,0xcc,0x8d}}, - {{0xe1,0xbc,0xa0}, {0xce,0xb7,0xcc,0x93}}, - {{0xe1,0xbc,0xa2}, {0xce,0xb7,0xcc,0x93,0xcc,0x80}}, - {{0xe1,0xbc,0xa4}, {0xce,0xb7,0xcc,0x93,0xcc,0x81}}, - {{0xe1,0xbc,0xa6}, {0xce,0xb7,0xcc,0x93,0xcd,0x82}}, - {{0xe1,0xbc,0xa1}, {0xce,0xb7,0xcc,0x94}}, - {{0xe1,0xbc,0xa3}, {0xce,0xb7,0xcc,0x94,0xcc,0x80}}, - {{0xe1,0xbc,0xa5}, {0xce,0xb7,0xcc,0x94,0xcc,0x81}}, - {{0xe1,0xbc,0xa7}, {0xce,0xb7,0xcc,0x94,0xcd,0x82}}, - {{0xe1,0xbf,0x86}, {0xce,0xb7,0xcd,0x82}}, - {{0xe1,0xbf,0x83}, {0xce,0xb7,0xcd,0x85}}, - {{0xe1,0xbf,0x82}, {0xce,0xb7,0xcd,0x85,0xcc,0x80}}, - {{0xe1,0xbf,0x84}, {0xce,0xb7,0xcd,0x85,0xcc,0x81}}, - {{0xe1,0xbe,0x90}, {0xce,0xb7,0xcd,0x85,0xcc,0x93}}, - {{0xe1,0xbe,0x92}, {0xce,0xb7,0xcd,0x85,0xcc,0x93,0xcc,0x80}}, - {{0xe1,0xbe,0x94}, {0xce,0xb7,0xcd,0x85,0xcc,0x93,0xcc,0x81}}, - {{0xe1,0xbe,0x96}, {0xce,0xb7,0xcd,0x85,0xcc,0x93,0xcd,0x82}}, - {{0xe1,0xbe,0x91}, {0xce,0xb7,0xcd,0x85,0xcc,0x94}}, - {{0xe1,0xbe,0x93}, {0xce,0xb7,0xcd,0x85,0xcc,0x94,0xcc,0x80}}, - {{0xe1,0xbe,0x95}, {0xce,0xb7,0xcd,0x85,0xcc,0x94,0xcc,0x81}}, - {{0xe1,0xbe,0x97}, {0xce,0xb7,0xcd,0x85,0xcc,0x94,0xcd,0x82}}, - {{0xe1,0xbf,0x87}, {0xce,0xb7,0xcd,0x85,0xcd,0x82}}, - {{0xe1,0xbe,0xbe}, {0xce,0xb9}}, - {{0xe1,0xbd,0xb6}, {0xce,0xb9,0xcc,0x80}}, - {{0xe1,0xbd,0xb7}, {0xce,0xb9,0xcc,0x81}}, - {{0xe1,0xbf,0x91}, {0xce,0xb9,0xcc,0x84}}, - {{0xe1,0xbf,0x90}, {0xce,0xb9,0xcc,0x86}}, - {{0xcf,0x8a}, {0xce,0xb9,0xcc,0x88}}, - {{0xe1,0xbf,0x92}, {0xce,0xb9,0xcc,0x88,0xcc,0x80}}, - {{0xe1,0xbf,0x93}, {0xce,0xb9,0xcc,0x88,0xcc,0x81}}, - {{0xce,0x90}, {0xce,0xb9,0xcc,0x88,0xcc,0x8d}}, - {{0xe1,0xbf,0x97}, {0xce,0xb9,0xcc,0x88,0xcd,0x82}}, - {{0xce,0xaf}, {0xce,0xb9,0xcc,0x8d}}, - {{0xe1,0xbc,0xb0}, {0xce,0xb9,0xcc,0x93}}, - {{0xe1,0xbc,0xb2}, {0xce,0xb9,0xcc,0x93,0xcc,0x80}}, - {{0xe1,0xbc,0xb4}, {0xce,0xb9,0xcc,0x93,0xcc,0x81}}, - {{0xe1,0xbc,0xb6}, {0xce,0xb9,0xcc,0x93,0xcd,0x82}}, - {{0xe1,0xbc,0xb1}, {0xce,0xb9,0xcc,0x94}}, - {{0xe1,0xbc,0xb3}, {0xce,0xb9,0xcc,0x94,0xcc,0x80}}, - {{0xe1,0xbc,0xb5}, {0xce,0xb9,0xcc,0x94,0xcc,0x81}}, - {{0xe1,0xbc,0xb7}, {0xce,0xb9,0xcc,0x94,0xcd,0x82}}, - {{0xe1,0xbf,0x96}, {0xce,0xb9,0xcd,0x82}}, - {{0xe1,0xbd,0xb8}, {0xce,0xbf,0xcc,0x80}}, - {{0xe1,0xbd,0xb9}, {0xce,0xbf,0xcc,0x81}}, - {{0xcf,0x8c}, {0xce,0xbf,0xcc,0x8d}}, - {{0xe1,0xbd,0x80}, {0xce,0xbf,0xcc,0x93}}, - {{0xe1,0xbd,0x82}, {0xce,0xbf,0xcc,0x93,0xcc,0x80}}, - {{0xe1,0xbd,0x84}, {0xce,0xbf,0xcc,0x93,0xcc,0x81}}, - {{0xe1,0xbd,0x81}, {0xce,0xbf,0xcc,0x94}}, - {{0xe1,0xbd,0x83}, {0xce,0xbf,0xcc,0x94,0xcc,0x80}}, - {{0xe1,0xbd,0x85}, {0xce,0xbf,0xcc,0x94,0xcc,0x81}}, - {{0xe1,0xbf,0xb4}, {0xce,0xbf,0xcd,0x85,0xcc,0x81}}, - {{0xe1,0xbf,0xa4}, {0xcf,0x81,0xcc,0x93}}, - {{0xe1,0xbf,0xa5}, {0xcf,0x81,0xcc,0x94}}, - {{0xe1,0xbd,0xba}, {0xcf,0x85,0xcc,0x80}}, - {{0xe1,0xbd,0xbb}, {0xcf,0x85,0xcc,0x81}}, - {{0xe1,0xbf,0xa1}, {0xcf,0x85,0xcc,0x84}}, - {{0xe1,0xbf,0xa0}, {0xcf,0x85,0xcc,0x86}}, - {{0xcf,0x8b}, {0xcf,0x85,0xcc,0x88}}, - {{0xe1,0xbf,0xa2}, {0xcf,0x85,0xcc,0x88,0xcc,0x80}}, - {{0xe1,0xbf,0xa3}, {0xcf,0x85,0xcc,0x88,0xcc,0x81}}, - {{0xce,0xb0}, {0xcf,0x85,0xcc,0x88,0xcc,0x8d}}, - {{0xe1,0xbf,0xa7}, {0xcf,0x85,0xcc,0x88,0xcd,0x82}}, - {{0xcf,0x8d}, {0xcf,0x85,0xcc,0x8d}}, - {{0xe1,0xbd,0x90}, {0xcf,0x85,0xcc,0x93}}, - {{0xe1,0xbd,0x92}, {0xcf,0x85,0xcc,0x93,0xcc,0x80}}, - {{0xe1,0xbd,0x94}, {0xcf,0x85,0xcc,0x93,0xcc,0x81}}, - {{0xe1,0xbd,0x96}, {0xcf,0x85,0xcc,0x93,0xcd,0x82}}, - {{0xe1,0xbd,0x91}, {0xcf,0x85,0xcc,0x94}}, - {{0xe1,0xbd,0x93}, {0xcf,0x85,0xcc,0x94,0xcc,0x80}}, - {{0xe1,0xbd,0x95}, {0xcf,0x85,0xcc,0x94,0xcc,0x81}}, - {{0xe1,0xbd,0x97}, {0xcf,0x85,0xcc,0x94,0xcd,0x82}}, - {{0xe1,0xbf,0xa6}, {0xcf,0x85,0xcd,0x82}}, - {{0xe1,0xbd,0xbc}, {0xcf,0x89,0xcc,0x80}}, - {{0xe1,0xbd,0xbd}, {0xcf,0x89,0xcc,0x81}}, - {{0xcf,0x8e}, {0xcf,0x89,0xcc,0x8d}}, - {{0xe1,0xbd,0xa0}, {0xcf,0x89,0xcc,0x93}}, - {{0xe1,0xbd,0xa2}, {0xcf,0x89,0xcc,0x93,0xcc,0x80}}, - {{0xe1,0xbd,0xa4}, {0xcf,0x89,0xcc,0x93,0xcc,0x81}}, - {{0xe1,0xbd,0xa6}, {0xcf,0x89,0xcc,0x93,0xcd,0x82}}, - {{0xe1,0xbd,0xa1}, {0xcf,0x89,0xcc,0x94}}, - {{0xe1,0xbd,0xa3}, {0xcf,0x89,0xcc,0x94,0xcc,0x80}}, - {{0xe1,0xbd,0xa5}, {0xcf,0x89,0xcc,0x94,0xcc,0x81}}, - {{0xe1,0xbd,0xa7}, {0xcf,0x89,0xcc,0x94,0xcd,0x82}}, - {{0xe1,0xbf,0xb6}, {0xcf,0x89,0xcd,0x82}}, - {{0xe1,0xbf,0xb3}, {0xcf,0x89,0xcd,0x85}}, - {{0xe1,0xbf,0xb2}, {0xcf,0x89,0xcd,0x85,0xcc,0x80}}, - {{0xe1,0xbe,0xa0}, {0xcf,0x89,0xcd,0x85,0xcc,0x93}}, - {{0xe1,0xbe,0xa2}, {0xcf,0x89,0xcd,0x85,0xcc,0x93,0xcc,0x80}}, - {{0xe1,0xbe,0xa4}, {0xcf,0x89,0xcd,0x85,0xcc,0x93,0xcc,0x81}}, - {{0xe1,0xbe,0xa6}, {0xcf,0x89,0xcd,0x85,0xcc,0x93,0xcd,0x82}}, - {{0xe1,0xbe,0xa1}, {0xcf,0x89,0xcd,0x85,0xcc,0x94}}, - {{0xe1,0xbe,0xa3}, {0xcf,0x89,0xcd,0x85,0xcc,0x94,0xcc,0x80}}, - {{0xe1,0xbe,0xa5}, {0xcf,0x89,0xcd,0x85,0xcc,0x94,0xcc,0x81}}, - {{0xe1,0xbe,0xa7}, {0xcf,0x89,0xcd,0x85,0xcc,0x94,0xcd,0x82}}, - {{0xe1,0xbf,0xb7}, {0xcf,0x89,0xcd,0x85,0xcd,0x82}}, - {{0xcf,0x94}, {0xcf,0x92,0xcc,0x88}}, - {{0xcf,0x93}, {0xcf,0x92,0xcc,0x8d}}, - {{0xd0,0x87}, {0xd0,0x86,0xcc,0x88}}, - {{0xd3,0x90}, {0xd0,0x90,0xcc,0x86}}, - {{0xd3,0x92}, {0xd0,0x90,0xcc,0x88}}, - {{0xd0,0x83}, {0xd0,0x93,0xcc,0x81}}, - {{0xd3,0x96}, {0xd0,0x95,0xcc,0x86}}, - {{0xd0,0x81}, {0xd0,0x95,0xcc,0x88}}, - {{0xd3,0x81}, {0xd0,0x96,0xcc,0x86}}, - {{0xd3,0x9c}, {0xd0,0x96,0xcc,0x88}}, - {{0xd3,0x9e}, {0xd0,0x97,0xcc,0x88}}, - {{0xd3,0xa2}, {0xd0,0x98,0xcc,0x84}}, - {{0xd0,0x99}, {0xd0,0x98,0xcc,0x86}}, - {{0xd3,0xa4}, {0xd0,0x98,0xcc,0x88}}, - {{0xd0,0x8c}, {0xd0,0x9a,0xcc,0x81}}, - {{0xd3,0xa6}, {0xd0,0x9e,0xcc,0x88}}, - {{0xd3,0xae}, {0xd0,0xa3,0xcc,0x84}}, - {{0xd0,0x8e}, {0xd0,0xa3,0xcc,0x86}}, - {{0xd3,0xb0}, {0xd0,0xa3,0xcc,0x88}}, - {{0xd3,0xb2}, {0xd0,0xa3,0xcc,0x8b}}, - {{0xd3,0xb4}, {0xd0,0xa7,0xcc,0x88}}, - {{0xd3,0xb8}, {0xd0,0xab,0xcc,0x88}}, - {{0xd3,0x91}, {0xd0,0xb0,0xcc,0x86}}, - {{0xd3,0x93}, {0xd0,0xb0,0xcc,0x88}}, - {{0xd1,0x93}, {0xd0,0xb3,0xcc,0x81}}, - {{0xd3,0x97}, {0xd0,0xb5,0xcc,0x86}}, - {{0xd1,0x91}, {0xd0,0xb5,0xcc,0x88}}, - {{0xd3,0x82}, {0xd0,0xb6,0xcc,0x86}}, - {{0xd3,0x9d}, {0xd0,0xb6,0xcc,0x88}}, - {{0xd3,0x9f}, {0xd0,0xb7,0xcc,0x88}}, - {{0xd3,0xa3}, {0xd0,0xb8,0xcc,0x84}}, - {{0xd0,0xb9}, {0xd0,0xb8,0xcc,0x86}}, - {{0xd3,0xa5}, {0xd0,0xb8,0xcc,0x88}}, - {{0xd1,0x9c}, {0xd0,0xba,0xcc,0x81}}, - {{0xd3,0xa7}, {0xd0,0xbe,0xcc,0x88}}, - {{0xd3,0xaf}, {0xd1,0x83,0xcc,0x84}}, - {{0xd1,0x9e}, {0xd1,0x83,0xcc,0x86}}, - {{0xd3,0xb1}, {0xd1,0x83,0xcc,0x88}}, - {{0xd3,0xb3}, {0xd1,0x83,0xcc,0x8b}}, - {{0xd3,0xb5}, {0xd1,0x87,0xcc,0x88}}, - {{0xd3,0xb9}, {0xd1,0x8b,0xcc,0x88}}, - {{0xd1,0x97}, {0xd1,0x96,0xcc,0x88}}, - {{0xd1,0xb6}, {0xd1,0xb4,0xcc,0x8f}}, - {{0xd1,0xb7}, {0xd1,0xb5,0xcc,0x8f}}, - {{0xef,0xac,0xae}, {0xd7,0x90,0xd6,0xb7}}, - {{0xef,0xac,0xaf}, {0xd7,0x90,0xd6,0xb8}}, - {{0xef,0xac,0xb0}, {0xd7,0x90,0xd6,0xbc}}, - {{0xef,0xac,0xb1}, {0xd7,0x91,0xd6,0xbc}}, - {{0xef,0xad,0x8c}, {0xd7,0x91,0xd6,0xbf}}, - {{0xef,0xac,0xb2}, {0xd7,0x92,0xd6,0xbc}}, - {{0xef,0xac,0xb3}, {0xd7,0x93,0xd6,0xbc}}, - {{0xef,0xac,0xb4}, {0xd7,0x94,0xd6,0xbc}}, - {{0xef,0xad,0x8b}, {0xd7,0x95,0xd6,0xb9}}, - {{0xef,0xac,0xb5}, {0xd7,0x95,0xd6,0xbc}}, - {{0xef,0xac,0xb6}, {0xd7,0x96,0xd6,0xbc}}, - {{0xef,0xac,0xb8}, {0xd7,0x98,0xd6,0xbc}}, - {{0xef,0xac,0xb9}, {0xd7,0x99,0xd6,0xbc}}, - {{0xef,0xac,0xba}, {0xd7,0x9a,0xd6,0xbc}}, - {{0xef,0xac,0xbb}, {0xd7,0x9b,0xd6,0xbc}}, - {{0xef,0xad,0x8d}, {0xd7,0x9b,0xd6,0xbf}}, - {{0xef,0xac,0xbc}, {0xd7,0x9c,0xd6,0xbc}}, - {{0xef,0xac,0xbe}, {0xd7,0x9e,0xd6,0xbc}}, - {{0xef,0xad,0x80}, {0xd7,0xa0,0xd6,0xbc}}, - {{0xef,0xad,0x81}, {0xd7,0xa1,0xd6,0xbc}}, - {{0xef,0xad,0x83}, {0xd7,0xa3,0xd6,0xbc}}, - {{0xef,0xad,0x84}, {0xd7,0xa4,0xd6,0xbc}}, - {{0xef,0xad,0x8e}, {0xd7,0xa4,0xd6,0xbf}}, - {{0xef,0xad,0x86}, {0xd7,0xa6,0xd6,0xbc}}, - {{0xef,0xad,0x87}, {0xd7,0xa7,0xd6,0xbc}}, - {{0xef,0xad,0x88}, {0xd7,0xa8,0xd6,0xbc}}, - {{0xef,0xad,0x89}, {0xd7,0xa9,0xd6,0xbc}}, - {{0xef,0xac,0xac}, {0xd7,0xa9,0xd6,0xbc,0xd7,0x81}}, - {{0xef,0xac,0xad}, {0xd7,0xa9,0xd6,0xbc,0xd7,0x82}}, - {{0xef,0xac,0xaa}, {0xd7,0xa9,0xd7,0x81}}, - {{0xef,0xac,0xab}, {0xd7,0xa9,0xd7,0x82}}, - {{0xef,0xad,0x8a}, {0xd7,0xaa,0xd6,0xbc}}, - {{0xef,0xac,0x9f}, {0xd7,0xb2,0xd6,0xb7}}, - {{0xe0,0xa5,0x98}, {0xe0,0xa4,0x95,0xe0,0xa4,0xbc}}, - {{0xe0,0xa5,0x99}, {0xe0,0xa4,0x96,0xe0,0xa4,0xbc}}, - {{0xe0,0xa5,0x9a}, {0xe0,0xa4,0x97,0xe0,0xa4,0xbc}}, - {{0xe0,0xa5,0x9b}, {0xe0,0xa4,0x9c,0xe0,0xa4,0xbc}}, - {{0xe0,0xa5,0x9c}, {0xe0,0xa4,0xa1,0xe0,0xa4,0xbc}}, - {{0xe0,0xa5,0x9d}, {0xe0,0xa4,0xa2,0xe0,0xa4,0xbc}}, - {{0xe0,0xa4,0xa9}, {0xe0,0xa4,0xa8,0xe0,0xa4,0xbc}}, - {{0xe0,0xa5,0x9e}, {0xe0,0xa4,0xab,0xe0,0xa4,0xbc}}, - {{0xe0,0xa5,0x9f}, {0xe0,0xa4,0xaf,0xe0,0xa4,0xbc}}, - {{0xe0,0xa4,0xb1}, {0xe0,0xa4,0xb0,0xe0,0xa4,0xbc}}, - {{0xe0,0xa4,0xb4}, {0xe0,0xa4,0xb3,0xe0,0xa4,0xbc}}, - {{0xe0,0xa7,0x9c}, {0xe0,0xa6,0xa1,0xe0,0xa6,0xbc}}, - {{0xe0,0xa7,0x9d}, {0xe0,0xa6,0xa2,0xe0,0xa6,0xbc}}, - {{0xe0,0xa6,0xb0}, {0xe0,0xa6,0xac,0xe0,0xa6,0xbc}}, - {{0xe0,0xa7,0x9f}, {0xe0,0xa6,0xaf,0xe0,0xa6,0xbc}}, - {{0xe0,0xa7,0x8b}, {0xe0,0xa7,0x87,0xe0,0xa6,0xbe}}, - {{0xe0,0xa7,0x8c}, {0xe0,0xa7,0x87,0xe0,0xa7,0x97}}, - {{0xe0,0xa9,0x99}, {0xe0,0xa8,0x96,0xe0,0xa8,0xbc}}, - {{0xe0,0xa9,0x9a}, {0xe0,0xa8,0x97,0xe0,0xa8,0xbc}}, - {{0xe0,0xa9,0x9b}, {0xe0,0xa8,0x9c,0xe0,0xa8,0xbc}}, - {{0xe0,0xa9,0x9c}, {0xe0,0xa8,0xa1,0xe0,0xa8,0xbc}}, - {{0xe0,0xa9,0x9e}, {0xe0,0xa8,0xab,0xe0,0xa8,0xbc}}, - {{0xe0,0xad,0x9c}, {0xe0,0xac,0xa1,0xe0,0xac,0xbc}}, - {{0xe0,0xad,0x9d}, {0xe0,0xac,0xa2,0xe0,0xac,0xbc}}, - {{0xe0,0xad,0x9f}, {0xe0,0xac,0xaf,0xe0,0xac,0xbc}}, - {{0xe0,0xad,0x8b}, {0xe0,0xad,0x87,0xe0,0xac,0xbe}}, - {{0xe0,0xad,0x88}, {0xe0,0xad,0x87,0xe0,0xad,0x96}}, - {{0xe0,0xad,0x8c}, {0xe0,0xad,0x87,0xe0,0xad,0x97}}, - {{0xe0,0xae,0x94}, {0xe0,0xae,0x92,0xe0,0xaf,0x97}}, - {{0xe0,0xaf,0x8a}, {0xe0,0xaf,0x86,0xe0,0xae,0xbe}}, - {{0xe0,0xaf,0x8c}, {0xe0,0xaf,0x86,0xe0,0xaf,0x97}}, - {{0xe0,0xaf,0x8b}, {0xe0,0xaf,0x87,0xe0,0xae,0xbe}}, - {{0xe0,0xb1,0x88}, {0xe0,0xb1,0x86,0xe0,0xb1,0x96}}, - {{0xe0,0xb3,0x80}, {0xe0,0xb2,0xbf,0xe0,0xb3,0x95}}, - {{0xe0,0xb3,0x8a}, {0xe0,0xb3,0x86,0xe0,0xb3,0x82}}, - {{0xe0,0xb3,0x8b}, {0xe0,0xb3,0x86,0xe0,0xb3,0x82,0xe0,0xb3,0x95}}, - {{0xe0,0xb3,0x87}, {0xe0,0xb3,0x86,0xe0,0xb3,0x95}}, - {{0xe0,0xb3,0x88}, {0xe0,0xb3,0x86,0xe0,0xb3,0x96}}, - {{0xe0,0xb5,0x8a}, {0xe0,0xb5,0x86,0xe0,0xb4,0xbe}}, - {{0xe0,0xb5,0x8c}, {0xe0,0xb5,0x86,0xe0,0xb5,0x97}}, - {{0xe0,0xb5,0x8b}, {0xe0,0xb5,0x87,0xe0,0xb4,0xbe}}, - {{0xe0,0xb8,0xb3}, {0xe0,0xb9,0x8d,0xe0,0xb8,0xb2}}, - {{0xe0,0xba,0xb3}, {0xe0,0xbb,0x8d,0xe0,0xba,0xb2}}, - {{0xe0,0xbd,0xa9}, {0xe0,0xbd,0x80,0xe0,0xbe,0xb5}}, - {{0xe0,0xbd,0x83}, {0xe0,0xbd,0x82,0xe0,0xbe,0xb7}}, - {{0xe0,0xbd,0x8d}, {0xe0,0xbd,0x8c,0xe0,0xbe,0xb7}}, - {{0xe0,0xbd,0x92}, {0xe0,0xbd,0x91,0xe0,0xbe,0xb7}}, - {{0xe0,0xbd,0x97}, {0xe0,0xbd,0x96,0xe0,0xbe,0xb7}}, - {{0xe0,0xbd,0x9c}, {0xe0,0xbd,0x9b,0xe0,0xbe,0xb7}}, - {{0xe0,0xbd,0xb3}, {0xe0,0xbd,0xb2,0xe0,0xbd,0xb1}}, - {{0xe0,0xbd,0xb5}, {0xe0,0xbd,0xb4,0xe0,0xbd,0xb1}}, - {{0xe0,0xbe,0x81}, {0xe0,0xbe,0x80,0xe0,0xbd,0xb1}}, - {{0xe0,0xbe,0xb9}, {0xe0,0xbe,0x90,0xe0,0xbe,0xb5}}, - {{0xe0,0xbe,0x93}, {0xe0,0xbe,0x92,0xe0,0xbe,0xb7}}, - {{0xe0,0xbe,0x9d}, {0xe0,0xbe,0x9c,0xe0,0xbe,0xb7}}, - {{0xe0,0xbe,0xa2}, {0xe0,0xbe,0xa1,0xe0,0xbe,0xb7}}, - {{0xe0,0xbe,0xa7}, {0xe0,0xbe,0xa6,0xe0,0xbe,0xb7}}, - {{0xe0,0xbe,0xac}, {0xe0,0xbe,0xab,0xe0,0xbe,0xb7}}, - {{0xe0,0xbd,0xb6}, {0xe0,0xbe,0xb2,0xe0,0xbe,0x80}}, - {{0xe0,0xbd,0xb7}, {0xe0,0xbe,0xb2,0xe0,0xbe,0x80,0xe0,0xbd,0xb1}}, - {{0xe0,0xbd,0xb8}, {0xe0,0xbe,0xb3,0xe0,0xbe,0x80}}, - {{0xe0,0xbd,0xb9}, {0xe0,0xbe,0xb3,0xe0,0xbe,0x80,0xe0,0xbd,0xb1}}, - {{0xe1,0xbf,0x8d}, {0xe1,0xbe,0xbf,0xcc,0x80}}, - {{0xe1,0xbf,0x8e}, {0xe1,0xbe,0xbf,0xcc,0x81}}, - {{0xe1,0xbf,0x8f}, {0xe1,0xbe,0xbf,0xcd,0x82}}, - {{0xe1,0xbf,0x9d}, {0xe1,0xbf,0xbe,0xcc,0x80}}, - {{0xe1,0xbf,0x9e}, {0xe1,0xbf,0xbe,0xcc,0x81}}, - {{0xe1,0xbf,0x9f}, {0xe1,0xbf,0xbe,0xcd,0x82}}, - {{0xe3,0x82,0x94}, {0xe3,0x81,0x86,0xe3,0x82,0x99}}, - {{0xe3,0x81,0x8c}, {0xe3,0x81,0x8b,0xe3,0x82,0x99}}, - {{0xe3,0x81,0x8e}, {0xe3,0x81,0x8d,0xe3,0x82,0x99}}, - {{0xe3,0x81,0x90}, {0xe3,0x81,0x8f,0xe3,0x82,0x99}}, - {{0xe3,0x81,0x92}, {0xe3,0x81,0x91,0xe3,0x82,0x99}}, - {{0xe3,0x81,0x94}, {0xe3,0x81,0x93,0xe3,0x82,0x99}}, - {{0xe3,0x81,0x96}, {0xe3,0x81,0x95,0xe3,0x82,0x99}}, - {{0xe3,0x81,0x98}, {0xe3,0x81,0x97,0xe3,0x82,0x99}}, - {{0xe3,0x81,0x9a}, {0xe3,0x81,0x99,0xe3,0x82,0x99}}, - {{0xe3,0x81,0x9c}, {0xe3,0x81,0x9b,0xe3,0x82,0x99}}, - {{0xe3,0x81,0x9e}, {0xe3,0x81,0x9d,0xe3,0x82,0x99}}, - {{0xe3,0x81,0xa0}, {0xe3,0x81,0x9f,0xe3,0x82,0x99}}, - {{0xe3,0x81,0xa2}, {0xe3,0x81,0xa1,0xe3,0x82,0x99}}, - {{0xe3,0x81,0xa5}, {0xe3,0x81,0xa4,0xe3,0x82,0x99}}, - {{0xe3,0x81,0xa7}, {0xe3,0x81,0xa6,0xe3,0x82,0x99}}, - {{0xe3,0x81,0xa9}, {0xe3,0x81,0xa8,0xe3,0x82,0x99}}, - {{0xe3,0x81,0xb0}, {0xe3,0x81,0xaf,0xe3,0x82,0x99}}, - {{0xe3,0x81,0xb1}, {0xe3,0x81,0xaf,0xe3,0x82,0x9a}}, - {{0xe3,0x81,0xb3}, {0xe3,0x81,0xb2,0xe3,0x82,0x99}}, - {{0xe3,0x81,0xb4}, {0xe3,0x81,0xb2,0xe3,0x82,0x9a}}, - {{0xe3,0x81,0xb6}, {0xe3,0x81,0xb5,0xe3,0x82,0x99}}, - {{0xe3,0x81,0xb7}, {0xe3,0x81,0xb5,0xe3,0x82,0x9a}}, - {{0xe3,0x81,0xb9}, {0xe3,0x81,0xb8,0xe3,0x82,0x99}}, - {{0xe3,0x81,0xba}, {0xe3,0x81,0xb8,0xe3,0x82,0x9a}}, - {{0xe3,0x81,0xbc}, {0xe3,0x81,0xbb,0xe3,0x82,0x99}}, - {{0xe3,0x81,0xbd}, {0xe3,0x81,0xbb,0xe3,0x82,0x9a}}, - {{0xe3,0x82,0x9e}, {0xe3,0x82,0x9d,0xe3,0x82,0x99}}, - {{0xe3,0x83,0xb4}, {0xe3,0x82,0xa6,0xe3,0x82,0x99}}, - {{0xe3,0x82,0xac}, {0xe3,0x82,0xab,0xe3,0x82,0x99}}, - {{0xe3,0x82,0xae}, {0xe3,0x82,0xad,0xe3,0x82,0x99}}, - {{0xe3,0x82,0xb0}, {0xe3,0x82,0xaf,0xe3,0x82,0x99}}, - {{0xe3,0x82,0xb2}, {0xe3,0x82,0xb1,0xe3,0x82,0x99}}, - {{0xe3,0x82,0xb4}, {0xe3,0x82,0xb3,0xe3,0x82,0x99}}, - {{0xe3,0x82,0xb6}, {0xe3,0x82,0xb5,0xe3,0x82,0x99}}, - {{0xe3,0x82,0xb8}, {0xe3,0x82,0xb7,0xe3,0x82,0x99}}, - {{0xe3,0x82,0xba}, {0xe3,0x82,0xb9,0xe3,0x82,0x99}}, - {{0xe3,0x82,0xbc}, {0xe3,0x82,0xbb,0xe3,0x82,0x99}}, - {{0xe3,0x82,0xbe}, {0xe3,0x82,0xbd,0xe3,0x82,0x99}}, - {{0xe3,0x83,0x80}, {0xe3,0x82,0xbf,0xe3,0x82,0x99}}, - {{0xe3,0x83,0x82}, {0xe3,0x83,0x81,0xe3,0x82,0x99}}, - {{0xe3,0x83,0x85}, {0xe3,0x83,0x84,0xe3,0x82,0x99}}, - {{0xe3,0x83,0x87}, {0xe3,0x83,0x86,0xe3,0x82,0x99}}, - {{0xe3,0x83,0x89}, {0xe3,0x83,0x88,0xe3,0x82,0x99}}, - {{0xe3,0x83,0x90}, {0xe3,0x83,0x8f,0xe3,0x82,0x99}}, - {{0xe3,0x83,0x91}, {0xe3,0x83,0x8f,0xe3,0x82,0x9a}}, - {{0xe3,0x83,0x93}, {0xe3,0x83,0x92,0xe3,0x82,0x99}}, - {{0xe3,0x83,0x94}, {0xe3,0x83,0x92,0xe3,0x82,0x9a}}, - {{0xe3,0x83,0x96}, {0xe3,0x83,0x95,0xe3,0x82,0x99}}, - {{0xe3,0x83,0x97}, {0xe3,0x83,0x95,0xe3,0x82,0x9a}}, - {{0xe3,0x83,0x99}, {0xe3,0x83,0x98,0xe3,0x82,0x99}}, - {{0xe3,0x83,0x9a}, {0xe3,0x83,0x98,0xe3,0x82,0x9a}}, - {{0xe3,0x83,0x9c}, {0xe3,0x83,0x9b,0xe3,0x82,0x99}}, - {{0xe3,0x83,0x9d}, {0xe3,0x83,0x9b,0xe3,0x82,0x9a}}, - {{0xe3,0x83,0xb7}, {0xe3,0x83,0xaf,0xe3,0x82,0x99}}, - {{0xe3,0x83,0xb8}, {0xe3,0x83,0xb0,0xe3,0x82,0x99}}, - {{0xe3,0x83,0xb9}, {0xe3,0x83,0xb1,0xe3,0x82,0x99}}, - {{0xe3,0x83,0xba}, {0xe3,0x83,0xb2,0xe3,0x82,0x99}}, - {{0xe3,0x83,0xbe}, {0xe3,0x83,0xbd,0xe3,0x82,0x99}}, -}; -#endif /* UNICODE_NORMALIZATION */ -#endif /* UTF8_INPUT_ENABLE */ - -#ifdef SHIFTJIS_CP932 -const unsigned short shiftjis_cp932[3][189] = { - { - 0xEEEF, 0xEEF0, 0xEEF1, 0xEEF2, 0xEEF3, 0xEEF4, 0xEEF5, 0xEEF6, - 0xEEF7, 0xEEF8, 0x8754, 0x8755, 0x8756, 0x8757, 0x8758, 0x8759, - 0x875A, 0x875B, 0x875C, 0x875D, 0x81CA, 0xEEFA, 0xEEFB, 0xEEFC, - 0x878A, 0x8782, 0x8784, 0x81E6, 0xED40, 0xED41, 0xED42, 0xED43, - 0xED44, 0xED45, 0xED46, 0xED47, 0xED48, 0xED49, 0xED4A, 0xED4B, - 0xED4C, 0xED4D, 0xED4E, 0xED4F, 0xED50, 0xED51, 0xED52, 0xED53, - 0xED54, 0xED55, 0xED56, 0xED57, 0xED58, 0xED59, 0xED5A, 0xED5B, - 0xED5C, 0xED5D, 0xED5E, 0xED5F, 0xED60, 0xED61, 0xED62, 0, - 0xED63, 0xED64, 0xED65, 0xED66, 0xED67, 0xED68, 0xED69, 0xED6A, - 0xED6B, 0xED6C, 0xED6D, 0xED6E, 0xED6F, 0xED70, 0xED71, 0xED72, - 0xED73, 0xED74, 0xED75, 0xED76, 0xED77, 0xED78, 0xED79, 0xED7A, - 0xED7B, 0xED7C, 0xED7D, 0xED7E, 0xED80, 0xED81, 0xED82, 0xED83, - 0xED84, 0xED85, 0xED86, 0xED87, 0xED88, 0xED89, 0xED8A, 0xED8B, - 0xED8C, 0xED8D, 0xED8E, 0xED8F, 0xED90, 0xED91, 0xED92, 0xED93, - 0xED94, 0xED95, 0xED96, 0xED97, 0xED98, 0xED99, 0xED9A, 0xED9B, - 0xED9C, 0xED9D, 0xED9E, 0xED9F, 0xEDA0, 0xEDA1, 0xEDA2, 0xEDA3, - 0xEDA4, 0xEDA5, 0xEDA6, 0xEDA7, 0xEDA8, 0xEDA9, 0xEDAA, 0xEDAB, - 0xEDAC, 0xEDAD, 0xEDAE, 0xEDAF, 0xEDB0, 0xEDB1, 0xEDB2, 0xEDB3, - 0xEDB4, 0xEDB5, 0xEDB6, 0xEDB7, 0xEDB8, 0xEDB9, 0xEDBA, 0xEDBB, - 0xEDBC, 0xEDBD, 0xEDBE, 0xEDBF, 0xEDC0, 0xEDC1, 0xEDC2, 0xEDC3, - 0xEDC4, 0xEDC5, 0xEDC6, 0xEDC7, 0xEDC8, 0xEDC9, 0xEDCA, 0xEDCB, - 0xEDCC, 0xEDCD, 0xEDCE, 0xEDCF, 0xEDD0, 0xEDD1, 0xEDD2, 0xEDD3, - 0xEDD4, 0xEDD5, 0xEDD6, 0xEDD7, 0xEDD8, 0xEDD9, 0xEDDA, 0xEDDB, - 0xEDDC, 0xEDDD, 0xEDDE, 0xEDDF, 0xEDE0, - }, - { - 0xEDE1, 0xEDE2, 0xEDE3, 0xEDE4, 0xEDE5, 0xEDE6, 0xEDE7, 0xEDE8, - 0xEDE9, 0xEDEA, 0xEDEB, 0xEDEC, 0xEDED, 0xEDEE, 0xEDEF, 0xEDF0, - 0xEDF1, 0xEDF2, 0xEDF3, 0xEDF4, 0xEDF5, 0xEDF6, 0xEDF7, 0xEDF8, - 0xEDF9, 0xEDFA, 0xEDFB, 0xEDFC, 0xEE40, 0xEE41, 0xEE42, 0xEE43, - 0xEE44, 0xEE45, 0xEE46, 0xEE47, 0xEE48, 0xEE49, 0xEE4A, 0xEE4B, - 0xEE4C, 0xEE4D, 0xEE4E, 0xEE4F, 0xEE50, 0xEE51, 0xEE52, 0xEE53, - 0xEE54, 0xEE55, 0xEE56, 0xEE57, 0xEE58, 0xEE59, 0xEE5A, 0xEE5B, - 0xEE5C, 0xEE5D, 0xEE5E, 0xEE5F, 0xEE60, 0xEE61, 0xEE62, 0, - 0xEE63, 0xEE64, 0xEE65, 0xEE66, 0xEE67, 0xEE68, 0xEE69, 0xEE6A, - 0xEE6B, 0xEE6C, 0xEE6D, 0xEE6E, 0xEE6F, 0xEE70, 0xEE71, 0xEE72, - 0xEE73, 0xEE74, 0xEE75, 0xEE76, 0xEE77, 0xEE78, 0xEE79, 0xEE7A, - 0xEE7B, 0xEE7C, 0xEE7D, 0xEE7E, 0xEE80, 0xEE81, 0xEE82, 0xEE83, - 0xEE84, 0xEE85, 0xEE86, 0xEE87, 0xEE88, 0xEE89, 0xEE8A, 0xEE8B, - 0xEE8C, 0xEE8D, 0xEE8E, 0xEE8F, 0xEE90, 0xEE91, 0xEE92, 0xEE93, - 0xEE94, 0xEE95, 0xEE96, 0xEE97, 0xEE98, 0xEE99, 0xEE9A, 0xEE9B, - 0xEE9C, 0xEE9D, 0xEE9E, 0xEE9F, 0xEEA0, 0xEEA1, 0xEEA2, 0xEEA3, - 0xEEA4, 0xEEA5, 0xEEA6, 0xEEA7, 0xEEA8, 0xEEA9, 0xEEAA, 0xEEAB, - 0xEEAC, 0xEEAD, 0xEEAE, 0xEEAF, 0xEEB0, 0xEEB1, 0xEEB2, 0xEEB3, - 0xEEB4, 0xEEB5, 0xEEB6, 0xEEB7, 0xEEB8, 0xEEB9, 0xEEBA, 0xEEBB, - 0xEEBC, 0xEEBD, 0xEEBE, 0xEEBF, 0xEEC0, 0xEEC1, 0xEEC2, 0xEEC3, - 0xEEC4, 0xEEC5, 0xEEC6, 0xEEC7, 0xEEC8, 0xEEC9, 0xEECA, 0xEECB, - 0xEECC, 0xEECD, 0xEECE, 0xEECF, 0xEED0, 0xEED1, 0xEED2, 0xEED3, - 0xEED4, 0xEED5, 0xEED6, 0xEED7, 0xEED8, 0xEED9, 0xEEDA, 0xEEDB, - 0xEEDC, 0xEEDD, 0xEEDE, 0xEEDF, 0xEEE0, - }, - { - 0xEEE1, 0xEEE2, 0xEEE3, 0xEEE4, 0xEEE5, 0xEEE6, 0xEEE7, 0xEEE8, - 0xEEE9, 0xEEEA, 0xEEEB, 0xEEEC, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - }, -}; -const unsigned short cp932inv[2][189] = { - { - 0xFA5C, 0xFA5D, 0xFA5E, 0xFA5F, 0xFA60, 0xFA61, 0xFA62, 0xFA63, - 0xFA64, 0xFA65, 0xFA66, 0xFA67, 0xFA68, 0xFA69, 0xFA6A, 0xFA6B, - 0xFA6C, 0xFA6D, 0xFA6E, 0xFA6F, 0xFA70, 0xFA71, 0xFA72, 0xFA73, - 0xFA74, 0xFA75, 0xFA76, 0xFA77, 0xFA78, 0xFA79, 0xFA7A, 0xFA7B, - 0xFA7C, 0xFA7D, 0xFA7E, 0xFA80, 0xFA81, 0xFA82, 0xFA83, 0xFA84, - 0xFA85, 0xFA86, 0xFA87, 0xFA88, 0xFA89, 0xFA8A, 0xFA8B, 0xFA8C, - 0xFA8D, 0xFA8E, 0xFA8F, 0xFA90, 0xFA91, 0xFA92, 0xFA93, 0xFA94, - 0xFA95, 0xFA96, 0xFA97, 0xFA98, 0xFA99, 0xFA9A, 0xFA9B, 0, - 0xFA9C, 0xFA9D, 0xFA9E, 0xFA9F, 0xFAA0, 0xFAA1, 0xFAA2, 0xFAA3, - 0xFAA4, 0xFAA5, 0xFAA6, 0xFAA7, 0xFAA8, 0xFAA9, 0xFAAA, 0xFAAB, - 0xFAAC, 0xFAAD, 0xFAAE, 0xFAAF, 0xFAB0, 0xFAB1, 0xFAB2, 0xFAB3, - 0xFAB4, 0xFAB5, 0xFAB6, 0xFAB7, 0xFAB8, 0xFAB9, 0xFABA, 0xFABB, - 0xFABC, 0xFABD, 0xFABE, 0xFABF, 0xFAC0, 0xFAC1, 0xFAC2, 0xFAC3, - 0xFAC4, 0xFAC5, 0xFAC6, 0xFAC7, 0xFAC8, 0xFAC9, 0xFACA, 0xFACB, - 0xFACC, 0xFACD, 0xFACE, 0xFACF, 0xFAD0, 0xFAD1, 0xFAD2, 0xFAD3, - 0xFAD4, 0xFAD5, 0xFAD6, 0xFAD7, 0xFAD8, 0xFAD9, 0xFADA, 0xFADB, - 0xFADC, 0xFADD, 0xFADE, 0xFADF, 0xFAE0, 0xFAE1, 0xFAE2, 0xFAE3, - 0xFAE4, 0xFAE5, 0xFAE6, 0xFAE7, 0xFAE8, 0xFAE9, 0xFAEA, 0xFAEB, - 0xFAEC, 0xFAED, 0xFAEE, 0xFAEF, 0xFAF0, 0xFAF1, 0xFAF2, 0xFAF3, - 0xFAF4, 0xFAF5, 0xFAF6, 0xFAF7, 0xFAF8, 0xFAF9, 0xFAFA, 0xFAFB, - 0xFAFC, 0xFB40, 0xFB41, 0xFB42, 0xFB43, 0xFB44, 0xFB45, 0xFB46, - 0xFB47, 0xFB48, 0xFB49, 0xFB4A, 0xFB4B, 0xFB4C, 0xFB4D, 0xFB4E, - 0xFB4F, 0xFB50, 0xFB51, 0xFB52, 0xFB53, 0xFB54, 0xFB55, 0xFB56, - 0xFB57, 0xFB58, 0xFB59, 0xFB5A, 0xFB5B, - }, - { - 0xFB5C, 0xFB5D, 0xFB5E, 0xFB5F, 0xFB60, 0xFB61, 0xFB62, 0xFB63, - 0xFB64, 0xFB65, 0xFB66, 0xFB67, 0xFB68, 0xFB69, 0xFB6A, 0xFB6B, - 0xFB6C, 0xFB6D, 0xFB6E, 0xFB6F, 0xFB70, 0xFB71, 0xFB72, 0xFB73, - 0xFB74, 0xFB75, 0xFB76, 0xFB77, 0xFB78, 0xFB79, 0xFB7A, 0xFB7B, - 0xFB7C, 0xFB7D, 0xFB7E, 0xFB80, 0xFB81, 0xFB82, 0xFB83, 0xFB84, - 0xFB85, 0xFB86, 0xFB87, 0xFB88, 0xFB89, 0xFB8A, 0xFB8B, 0xFB8C, - 0xFB8D, 0xFB8E, 0xFB8F, 0xFB90, 0xFB91, 0xFB92, 0xFB93, 0xFB94, - 0xFB95, 0xFB96, 0xFB97, 0xFB98, 0xFB99, 0xFB9A, 0xFB9B, 0, - 0xFB9C, 0xFB9D, 0xFB9E, 0xFB9F, 0xFBA0, 0xFBA1, 0xFBA2, 0xFBA3, - 0xFBA4, 0xFBA5, 0xFBA6, 0xFBA7, 0xFBA8, 0xFBA9, 0xFBAA, 0xFBAB, - 0xFBAC, 0xFBAD, 0xFBAE, 0xFBAF, 0xFBB0, 0xFBB1, 0xFBB2, 0xFBB3, - 0xFBB4, 0xFBB5, 0xFBB6, 0xFBB7, 0xFBB8, 0xFBB9, 0xFBBA, 0xFBBB, - 0xFBBC, 0xFBBD, 0xFBBE, 0xFBBF, 0xFBC0, 0xFBC1, 0xFBC2, 0xFBC3, - 0xFBC4, 0xFBC5, 0xFBC6, 0xFBC7, 0xFBC8, 0xFBC9, 0xFBCA, 0xFBCB, - 0xFBCC, 0xFBCD, 0xFBCE, 0xFBCF, 0xFBD0, 0xFBD1, 0xFBD2, 0xFBD3, - 0xFBD4, 0xFBD5, 0xFBD6, 0xFBD7, 0xFBD8, 0xFBD9, 0xFBDA, 0xFBDB, - 0xFBDC, 0xFBDD, 0xFBDE, 0xFBDF, 0xFBE0, 0xFBE1, 0xFBE2, 0xFBE3, - 0xFBE4, 0xFBE5, 0xFBE6, 0xFBE7, 0xFBE8, 0xFBE9, 0xFBEA, 0xFBEB, - 0xFBEC, 0xFBED, 0xFBEE, 0xFBEF, 0xFBF0, 0xFBF1, 0xFBF2, 0xFBF3, - 0xFBF4, 0xFBF5, 0xFBF6, 0xFBF7, 0xFBF8, 0xFBF9, 0xFBFA, 0xFBFB, - 0xFBFC, 0xFC40, 0xFC41, 0xFC42, 0xFC43, 0xFC44, 0xFC45, 0xFC46, - 0xFC47, 0xFC48, 0xFC49, 0xFC4A, 0xFC4B, 0, 0, 0xFA40, - 0xFA41, 0xFA42, 0xFA43, 0xFA44, 0xFA45, 0xFA46, 0xFA47, 0xFA48, - 0xFA49, 0x81CA, 0xFA55, 0xFA56, 0xFA57, - }, -}; -#endif /* SHIFTJIS_CP932 */ - -#ifdef X0212_ENABLE -const unsigned short shiftjis_x0212[3][189] = { - { - 0xF373, 0xF374, 0xF375, 0xF376, 0xF377, 0xF378, 0xF379, 0xF37A, - 0xF37B, 0xF37C, 0xF37D, 0xF37E, 0xF421, 0xF422, 0xF423, 0xF424, - 0xF425, 0xF426, 0xF427, 0xF428, 0x224C, 0xA243, 0xF429, 0xF42A, - 0xF42B, 0xF42C, 0xF42D, 0x2268, 0xD463, 0xDC5F, 0xE469, 0xE378, - 0xD921, 0xB13B, 0xF42E, 0xC22D, 0xC37C, 0xE450, 0xC23F, 0xBC74, - 0xB029, 0xB048, 0xF42F, 0xB052, 0xB054, 0xB063, 0xB06E, 0xB127, - 0xB123, 0xB12C, 0xB129, 0xB13E, 0xB15F, 0xB158, 0xB148, 0xB157, - 0xB163, 0xB174, 0xB161, 0xB223, 0xF430, 0xB23B, 0xB266, 0, - 0xB26D, 0xB275, 0xB27C, 0xF431, 0xB335, 0xB358, 0xB35B, 0xB365, - 0xB36E, 0xB37B, 0xF432, 0xF433, 0xB440, 0xB447, 0xB450, 0xB45E, - 0xF434, 0xB52A, 0xF435, 0xB52F, 0xB544, 0xB568, 0xF436, 0xB742, - 0xB764, 0xB768, 0xB767, 0xF437, 0xF438, 0xF439, 0xB84E, 0xB861, - 0xB875, 0xB877, 0xB878, 0xB87C, 0xB92F, 0xB937, 0xBA3E, 0xBA5B, - 0xCD2A, 0xBA61, 0xF43A, 0xBA6B, 0xBB33, 0xBB38, 0xF43B, 0xBB4A, - 0xF43C, 0xF43D, 0xBB50, 0xBB5E, 0xBB74, 0xBB75, 0xBB79, 0xBC64, - 0xBC6D, 0xBC7E, 0xF43E, 0xBD42, 0xBD67, 0xF43F, 0xBD70, 0xBE30, - 0xBE2C, 0xF440, 0xBE33, 0xBE3D, 0xBE4D, 0xBE49, 0xBE64, 0xBF28, - 0xBF49, 0xC044, 0xC064, 0xC074, 0xC126, 0xF441, 0xC175, 0xC17C, - 0xF442, 0xC178, 0xC22B, 0xC221, 0xC225, 0xF443, 0xC238, 0xC23A, - 0xF444, 0xC244, 0xC252, 0xC257, 0xC25B, 0xC25E, 0xC26D, 0xC270, - 0xF445, 0xC321, 0xC335, 0xC349, 0xC339, 0xF446, 0xC358, 0xC37E, - 0xF447, 0xC44C, 0xF448, 0xC459, 0xC46A, 0xC47D, 0xF449, 0xC527, - 0xC535, 0xC536, 0xF44A, 0xC555, 0xC638, 0xC657, 0xC660, 0xC66A, - 0xC663, 0xC721, 0xC72B, 0xC747, 0xC743, - }, - { - 0xC74B, 0xC74F, 0xC759, 0xF44B, 0xF44C, 0xC766, 0xC76E, 0xC77C, - 0xC76B, 0xC770, 0xC831, 0xC865, 0xC878, 0xC926, 0xC92B, 0xC92D, - 0xF44D, 0xC94A, 0xC953, 0xC969, 0xC963, 0xC97C, 0xC974, 0xC975, - 0xF44E, 0xCA33, 0xCA3D, 0xCA6F, 0xCA71, 0xCB2E, 0xF44F, 0xCB4A, - 0xCB66, 0xCB6A, 0xCB70, 0xCB74, 0xCB6E, 0xCC25, 0xCB79, 0xCC2B, - 0xCC2E, 0xCC2D, 0xCC32, 0xCC42, 0xCC50, 0xCC59, 0xF450, 0xCD3B, - 0xF451, 0xCE3B, 0xF452, 0xCE3A, 0xCE43, 0xF453, 0xCE72, 0xB35D, - 0xCF55, 0xCF62, 0xCF69, 0xCF6D, 0xF454, 0xF455, 0xF456, 0, - 0xF457, 0xD065, 0xF458, 0xD069, 0xD168, 0xF459, 0xF45A, 0xD16C, - 0xD23B, 0xF45B, 0xD361, 0xD368, 0xD427, 0xF45C, 0xF45D, 0xD454, - 0xD472, 0xD52E, 0xF45E, 0xD75E, 0xF45F, 0xD822, 0xD837, 0xD841, - 0xD851, 0xD874, 0xD946, 0xD948, 0xD951, 0xF460, 0xF461, 0xF462, - 0xF463, 0xF464, 0xDC53, 0xDD48, 0xDD54, 0xDD6A, 0xDD7A, 0xDE24, - 0xDE30, 0xF465, 0xDE35, 0xDE4B, 0xF466, 0xDF39, 0xF467, 0xDF43, - 0xF468, 0xF469, 0xE059, 0xF46A, 0xF46B, 0xE162, 0xF46C, 0xF46D, - 0xF46E, 0xE247, 0xE328, 0xE326, 0xE329, 0xE32F, 0xE330, 0xE32A, - 0xE32B, 0xE33C, 0xE341, 0xE33F, 0xE355, 0xE358, 0xE356, 0xE35F, - 0xE363, 0xE361, 0xE354, 0xE369, 0xE426, 0xE371, 0xE372, 0xE44B, - 0xE441, 0xE443, 0xE43E, 0xF46F, 0xE440, 0xE447, 0xE43F, 0xE460, - 0xE45E, 0xE451, 0xF470, 0xE45C, 0xE452, 0xE45B, 0xE454, 0xE47A, - 0xE46F, 0xE533, 0xE53F, 0xE549, 0xE550, 0xE562, 0xE56A, 0xE56B, - 0xF471, 0xF472, 0xF473, 0xE668, 0xE66F, 0xE72C, 0xF474, 0xE72E, - 0xF475, 0xE731, 0xF476, 0xE732, 0xE831, 0xE836, 0xF477, 0xF478, - 0xE85D, 0xF479, 0xF47A, 0xE951, 0xF47B, - }, - { - 0xE96D, 0xEA4D, 0xF47C, 0xEA5B, 0xEA66, 0xEA6A, 0xEB25, 0xEB7B, - 0xEB7A, 0xF47D, 0xEC56, 0xF47E, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, - }, -}; - -static const unsigned short x0212_shiftjis_A2[] = { - 0x819F, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0x8143, 0, 0, 0x8150, 0, 0, 0x8160, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0xFA55, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short x0212_shiftjis_B0[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0xFA68, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0xFA69, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0xFA6B, 0, 0xFA6C, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0xFA6D, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0xFA6E, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short x0212_shiftjis_B1[] = { - 0, 0, 0xFA70, 0, 0, 0, 0xFA6F, - 0, 0xFA72, 0, 0, 0xFA71, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0xFA61, 0, 0, 0xFA73, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0xFA76, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0xFA77, - 0xFA75, 0, 0, 0, 0, 0, 0, 0xFA74, - 0, 0xFA7A, 0, 0xFA78, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0xFA79, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short x0212_shiftjis_B2[] = { - 0, 0, 0xFA7B, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0xFA7D, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0xFA7E, 0, - 0, 0, 0, 0, 0, 0xFA80, 0, 0, - 0, 0, 0, 0, 0, 0xFA81, 0, 0, - 0, 0, 0, 0, 0xFA82, 0, 0, -}; -static const unsigned short x0212_shiftjis_B3[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0xFA84, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0xFA85, 0, 0, 0xFA86, 0, 0xFB77, 0, 0, - 0, 0, 0, 0, 0, 0xFA87, 0, 0, - 0, 0, 0, 0, 0, 0, 0xFA88, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0xFA89, 0, 0, 0, -}; -static const unsigned short x0212_shiftjis_B4[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0xFA8C, 0, 0, 0, 0, 0, 0, 0xFA8D, - 0, 0, 0, 0, 0, 0, 0, 0, - 0xFA8E, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0xFA8F, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short x0212_shiftjis_B5[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0xFA91, 0, 0, 0, 0, 0xFA93, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0xFA94, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0xFA95, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short x0212_shiftjis_B7[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0xFA97, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0xFA98, 0, 0, 0xFA9A, - 0xFA99, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short x0212_shiftjis_B8[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0xFA9E, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0xFA9F, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0xFAA0, 0, 0xFAA1, - 0xFAA2, 0, 0, 0, 0xFAA3, 0, 0, -}; -static const unsigned short x0212_shiftjis_B9[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0xFAA4, - 0, 0, 0, 0, 0, 0, 0, 0xFAA5, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short x0212_shiftjis_BA[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0xFAA6, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0xFAA7, 0, 0, 0, 0, - 0, 0xFAA9, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0xFAAB, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short x0212_shiftjis_BB[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0xFAAC, 0, 0, 0, 0, - 0xFAAD, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0xFAAF, 0, 0, 0, 0, 0, - 0xFAB2, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0xFAB3, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0xFAB4, 0xFAB5, 0, 0, - 0, 0xFAB6, 0, 0, 0, 0, 0, -}; -static const unsigned short x0212_shiftjis_BC[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0xFAB7, 0, 0, 0, - 0, 0, 0, 0, 0, 0xFAB8, 0, 0, - 0, 0, 0, 0, 0xFA67, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0xFAB9, -}; -static const unsigned short x0212_shiftjis_BD[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0xFABB, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0xFABC, - 0, 0, 0, 0, 0, 0, 0, 0, - 0xFABE, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short x0212_shiftjis_BE[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0xFAC0, 0, 0, 0, - 0xFABF, 0, 0, 0xFAC2, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0xFAC3, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0xFAC5, 0, 0, 0, 0xFAC4, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0xFAC6, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short x0212_shiftjis_BF[] = { - 0, 0, 0, 0, 0, 0, 0, - 0xFAC7, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0xFAC8, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short x0212_shiftjis_C0[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0xFAC9, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0xFACA, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0xFACB, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short x0212_shiftjis_C1[] = { - 0, 0, 0, 0, 0, 0xFACC, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0xFACE, 0, 0, - 0xFAD1, 0, 0, 0, 0xFACF, 0, 0, -}; -static const unsigned short x0212_shiftjis_C2[] = { - 0xFAD3, 0, 0, 0, 0xFAD4, 0, 0, - 0, 0, 0, 0xFAD2, 0, 0xFA63, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0xFAD6, 0, 0xFAD7, 0, 0, 0, 0, 0xFA66, - 0, 0, 0, 0, 0xFAD9, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0xFADA, 0, 0, 0, 0, 0xFADB, - 0, 0, 0, 0xFADC, 0, 0, 0xFADD, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0xFADE, 0, 0, - 0xFADF, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short x0212_shiftjis_C3[] = { - 0xFAE1, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0xFAE2, 0, 0, - 0, 0xFAE4, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0xFAE3, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0xFAE6, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0xFA64, 0, 0xFAE7, -}; -static const unsigned short x0212_shiftjis_C4[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0xFAE9, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0xFAEB, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0xFAEC, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0xFAED, 0, -}; -static const unsigned short x0212_shiftjis_C5[] = { - 0, 0, 0, 0, 0, 0, 0xFAEF, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0xFAF0, 0xFAF1, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0xFAF3, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short x0212_shiftjis_C6[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0xFAF4, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0xFAF5, - 0, 0, 0, 0, 0, 0, 0, 0, - 0xFAF6, 0, 0, 0xFAF8, 0, 0, 0, 0, - 0, 0, 0xFAF7, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short x0212_shiftjis_C7[] = { - 0xFAF9, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0xFAFA, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0xFAFC, 0, 0, 0, 0xFAFB, - 0, 0, 0, 0xFB40, 0, 0, 0, 0xFB41, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0xFB42, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0xFB45, 0, - 0, 0, 0, 0xFB48, 0, 0, 0xFB46, 0, - 0xFB49, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0xFB47, 0, 0, -}; -static const unsigned short x0212_shiftjis_C8[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0xFB4A, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0xFB4B, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0xFB4C, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short x0212_shiftjis_C9[] = { - 0, 0, 0, 0, 0, 0xFB4D, 0, - 0, 0, 0, 0xFB4E, 0, 0xFB4F, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0xFB51, 0, 0, 0, 0, 0, - 0, 0, 0, 0xFB52, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0xFB54, 0, 0, 0, 0, - 0, 0xFB53, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0xFB56, 0xFB57, 0, 0, - 0, 0, 0, 0, 0xFB55, 0, 0, -}; -static const unsigned short x0212_shiftjis_CA[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0xFB59, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0xFB5A, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0xFB5B, - 0, 0xFB5C, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short x0212_shiftjis_CB[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0xFB5D, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0xFB5F, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0xFB60, 0, - 0, 0, 0xFB61, 0, 0, 0, 0xFB64, 0, - 0xFB62, 0, 0, 0, 0xFB63, 0, 0, 0, - 0, 0xFB66, 0, 0, 0, 0, 0, -}; -static const unsigned short x0212_shiftjis_CC[] = { - 0, 0, 0, 0, 0xFB65, 0, 0, - 0, 0, 0, 0xFB67, 0, 0xFB69, 0xFB68, 0, - 0, 0, 0xFB6A, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0xFB6B, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0xFB6C, 0, 0, 0, 0, 0, 0, 0, - 0, 0xFB6D, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short x0212_shiftjis_CD[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0xFAA8, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0xFB6F, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short x0212_shiftjis_CE[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0xFB73, 0xFB71, 0, 0, 0, 0, - 0, 0, 0, 0xFB74, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0xFB76, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short x0212_shiftjis_CF[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0xFB78, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0xFB79, 0, 0, 0, 0, 0, - 0, 0xFB7A, 0, 0, 0, 0xFB7B, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short x0212_shiftjis_D0[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0xFB81, 0, 0, - 0, 0xFB83, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short x0212_shiftjis_D1[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0xFB84, 0, 0, 0, 0xFB87, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short x0212_shiftjis_D2[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0xFB88, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short x0212_shiftjis_D3[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0xFB8A, 0, 0, 0, 0, 0, 0, - 0xFB8B, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short x0212_shiftjis_D4[] = { - 0, 0, 0, 0, 0, 0, 0xFB8C, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0xFB8F, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0xFA5C, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0xFB90, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short x0212_shiftjis_D5[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0xFB91, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short x0212_shiftjis_D7[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0xFB93, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short x0212_shiftjis_D8[] = { - 0, 0xFB95, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0xFB96, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0xFB97, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0xFB98, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0xFB99, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short x0212_shiftjis_D9[] = { - 0xFA60, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0xFB9A, 0, - 0xFB9B, 0, 0, 0, 0, 0, 0, 0, - 0, 0xFB9C, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short x0212_shiftjis_DC[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0xFBA2, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0xFA5D, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short x0212_shiftjis_DD[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0xFBA3, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0xFBA4, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0xFBA5, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0xFBA6, 0, 0, 0, 0, -}; -static const unsigned short x0212_shiftjis_DE[] = { - 0, 0, 0, 0xFBA7, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0xFBA8, 0, 0, 0, 0, 0xFBAA, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0xFBAB, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short x0212_shiftjis_DF[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0xFBAD, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0xFBAF, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short x0212_shiftjis_E0[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0xFBB2, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short x0212_shiftjis_E1[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0xFBB5, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short x0212_shiftjis_E2[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0xFBB9, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short x0212_shiftjis_E3[] = { - 0, 0, 0, 0, 0, 0xFBBB, 0, - 0xFBBA, 0xFBBC, 0xFBBF, 0xFBC0, 0, 0, 0, 0xFBBD, - 0xFBBE, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0xFBC1, 0, 0, 0xFBC3, - 0, 0xFBC2, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0xFBCA, 0xFBC4, 0xFBC6, 0, - 0xFBC5, 0, 0, 0, 0, 0, 0, 0xFBC7, - 0, 0xFBC9, 0, 0xFBC8, 0, 0, 0, 0, - 0, 0xFBCB, 0, 0, 0, 0, 0, 0, - 0, 0xFBCD, 0xFBCE, 0, 0, 0, 0, 0, - 0xFA5F, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short x0212_shiftjis_E4[] = { - 0, 0, 0, 0, 0, 0xFBCC, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0xFBD2, 0xFBD6, - 0xFBD4, 0xFBD0, 0, 0xFBD1, 0, 0, 0, 0xFBD5, - 0, 0, 0, 0xFBCF, 0, 0, 0, 0, - 0xFA65, 0xFBD9, 0xFBDC, 0, 0xFBDE, 0, 0, 0, - 0, 0, 0, 0xFBDD, 0xFBDB, 0, 0xFBD8, 0, - 0xFBD7, 0, 0, 0, 0, 0, 0, 0, - 0, 0xFA5E, 0, 0, 0, 0, 0, 0xFBE0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0xFBDF, 0, 0, 0, 0, -}; -static const unsigned short x0212_shiftjis_E5[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0xFBE1, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0xFBE2, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0xFBE3, 0, 0, 0, 0, 0, 0, - 0xFBE4, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0xFBE5, 0, 0, 0, 0, 0, - 0, 0, 0xFBE6, 0xFBE7, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short x0212_shiftjis_E6[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0xFBEB, 0, 0, 0, 0, 0, 0, 0xFBEC, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short x0212_shiftjis_E7[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0xFBED, 0, 0xFBEF, 0, - 0, 0xFBF1, 0xFBF3, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short x0212_shiftjis_E8[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0xFBF4, 0, 0, 0, 0, 0xFBF5, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0xFBF8, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short x0212_shiftjis_E9[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0xFBFB, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0xFC40, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short x0212_shiftjis_EA[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0xFC41, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0xFC43, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0xFC44, 0, - 0, 0, 0xFC45, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short x0212_shiftjis_EB[] = { - 0, 0, 0, 0, 0xFC46, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0xFC48, 0xFC47, 0, 0, 0, -}; -static const unsigned short x0212_shiftjis_EC[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0xFC4A, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, -}; -static const unsigned short x0212_shiftjis_F3[] = { - 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0xFA40, 0xFA41, 0xFA42, 0xFA43, 0xFA44, - 0xFA45, 0xFA46, 0xFA47, 0xFA48, 0xFA49, 0xFA4A, 0xFA4B, -}; -static const unsigned short x0212_shiftjis_F4[] = { - 0xFA4C, 0xFA4D, 0xFA4E, 0xFA4F, 0xFA50, 0xFA51, 0xFA52, - 0xFA53, 0xFA56, 0xFA57, 0xFA58, 0xFA59, 0xFA5A, 0xFA62, 0xFA6A, - 0xFA7C, 0xFA83, 0xFA8A, 0xFA8B, 0xFA90, 0xFA92, 0xFA96, 0xFA9B, - 0xFA9C, 0xFA9D, 0xFAAA, 0xFAAE, 0xFAB0, 0xFAB1, 0xFABA, 0xFABD, - 0xFAC1, 0xFACD, 0xFAD0, 0xFAD5, 0xFAD8, 0xFAE0, 0xFAE5, 0xFAE8, - 0xFAEA, 0xFAEE, 0xFAF2, 0xFB43, 0xFB44, 0xFB50, 0xFB58, 0xFB5E, - 0xFB6E, 0xFB70, 0xFB72, 0xFB75, 0xFB7C, 0xFB7D, 0xFB7E, 0xFB80, - 0xFB82, 0xFB85, 0xFB86, 0xFB89, 0xFB8D, 0xFB8E, 0xFB92, 0xFB94, - 0xFB9D, 0xFB9E, 0xFB9F, 0xFBA0, 0xFBA1, 0xFBA9, 0xFBAC, 0xFBAE, - 0xFBB0, 0xFBB1, 0xFBB3, 0xFBB4, 0xFBB6, 0xFBB7, 0xFBB8, 0xFBD3, - 0xFBDA, 0xFBE8, 0xFBE9, 0xFBEA, 0xFBEE, 0xFBF0, 0xFBF2, 0xFBF6, - 0xFBF7, 0xFBF9, 0xFBFA, 0xFBFC, 0xFC42, 0xFC49, 0xFC4B, -}; -const unsigned short *const x0212_shiftjis[] = { - 0, x0212_shiftjis_A2, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, 0, - x0212_shiftjis_B0, x0212_shiftjis_B1, x0212_shiftjis_B2, x0212_shiftjis_B3, - x0212_shiftjis_B4, x0212_shiftjis_B5, 0, x0212_shiftjis_B7, - x0212_shiftjis_B8, x0212_shiftjis_B9, x0212_shiftjis_BA, x0212_shiftjis_BB, - x0212_shiftjis_BC, x0212_shiftjis_BD, x0212_shiftjis_BE, x0212_shiftjis_BF, - x0212_shiftjis_C0, x0212_shiftjis_C1, x0212_shiftjis_C2, x0212_shiftjis_C3, - x0212_shiftjis_C4, x0212_shiftjis_C5, x0212_shiftjis_C6, x0212_shiftjis_C7, - x0212_shiftjis_C8, x0212_shiftjis_C9, x0212_shiftjis_CA, x0212_shiftjis_CB, - x0212_shiftjis_CC, x0212_shiftjis_CD, x0212_shiftjis_CE, x0212_shiftjis_CF, - x0212_shiftjis_D0, x0212_shiftjis_D1, x0212_shiftjis_D2, x0212_shiftjis_D3, - x0212_shiftjis_D4, x0212_shiftjis_D5, 0, x0212_shiftjis_D7, - x0212_shiftjis_D8, x0212_shiftjis_D9, 0, 0, - x0212_shiftjis_DC, x0212_shiftjis_DD, x0212_shiftjis_DE, x0212_shiftjis_DF, - x0212_shiftjis_E0, x0212_shiftjis_E1, x0212_shiftjis_E2, x0212_shiftjis_E3, - x0212_shiftjis_E4, x0212_shiftjis_E5, x0212_shiftjis_E6, x0212_shiftjis_E7, - x0212_shiftjis_E8, x0212_shiftjis_E9, x0212_shiftjis_EA, x0212_shiftjis_EB, - x0212_shiftjis_EC, 0, 0, 0, - 0, 0, 0, x0212_shiftjis_F3, - x0212_shiftjis_F4, 0, 0, 0, - 0, 0, 0, 0, - 0, 0, 0, -}; -#endif /* X0212_ENABLE */ diff --git a/ext/nkf/nkf-utf8/utf8tbl.h b/ext/nkf/nkf-utf8/utf8tbl.h deleted file mode 100644 index 54a34271ddc02c..00000000000000 --- a/ext/nkf/nkf-utf8/utf8tbl.h +++ /dev/null @@ -1,72 +0,0 @@ -/* - * utf8tbl.h - Header file for Conversion Table - * - */ - -#ifndef _UTF8TBL_H_ -#define _UTF8TBL_H_ - -#ifdef UTF8_OUTPUT_ENABLE -#define sizeof_euc_to_utf8_1byte 94 -#define sizeof_euc_to_utf8_2bytes 94 -extern const unsigned short euc_to_utf8_1byte[]; -extern const unsigned short *const euc_to_utf8_2bytes[]; -extern const unsigned short *const euc_to_utf8_2bytes_ms[]; -extern const unsigned short *const euc_to_utf8_2bytes_mac[]; -extern const unsigned short *const euc_to_utf8_2bytes_x0213[]; -extern const unsigned short *const x0212_to_utf8_2bytes[]; -extern const unsigned short *const x0212_to_utf8_2bytes_x0213[]; -#define sizeof_x0213_combining_chars 5 -#define sizeof_x0213_combining_table 25 -#define sizeof_x0213_1_surrogate_table 26 -#define sizeof_x0213_2_surrogate_table 277 -extern const unsigned short x0213_combining_chars[sizeof_x0213_combining_chars]; -extern const unsigned short x0213_combining_table[sizeof_x0213_combining_table][3]; -extern const unsigned short x0213_1_surrogate_table[sizeof_x0213_1_surrogate_table][3]; -extern const unsigned short x0213_2_surrogate_table[sizeof_x0213_2_surrogate_table][3]; -#endif /* UTF8_OUTPUT_ENABLE */ - -#ifdef UTF8_INPUT_ENABLE -#define sizeof_utf8_to_euc_C2 64 -#define sizeof_utf8_to_euc_E5B8 64 -#define sizeof_utf8_to_euc_2bytes 112 -#define sizeof_utf8_to_euc_3bytes 16 -extern const unsigned short *const utf8_to_euc_2bytes[]; -extern const unsigned short *const utf8_to_euc_2bytes_ms[]; -extern const unsigned short *const utf8_to_euc_2bytes_932[]; -extern const unsigned short *const utf8_to_euc_2bytes_mac[]; -extern const unsigned short *const utf8_to_euc_2bytes_x0213[]; -extern const unsigned short *const *const utf8_to_euc_3bytes[]; -extern const unsigned short *const *const utf8_to_euc_3bytes_ms[]; -extern const unsigned short *const *const utf8_to_euc_3bytes_932[]; -extern const unsigned short *const *const utf8_to_euc_3bytes_mac[]; -extern const unsigned short *const *const utf8_to_euc_3bytes_x0213[]; -#endif /* UTF8_INPUT_ENABLE */ - -#ifdef UNICODE_NORMALIZATION - -#define NORMALIZATION_TABLE_LENGTH 942 -#define NORMALIZATION_TABLE_NFC_LENGTH 3 -#define NORMALIZATION_TABLE_NFD_LENGTH 9 -struct normalization_pair { - const unsigned char nfc[NORMALIZATION_TABLE_NFC_LENGTH]; - const unsigned char nfd[NORMALIZATION_TABLE_NFD_LENGTH]; -}; -extern const struct normalization_pair normalization_table[]; -#endif - -#ifdef SHIFTJIS_CP932 -#define CP932_TABLE_BEGIN 0xFA -#define CP932_TABLE_END 0xFC -extern const unsigned short shiftjis_cp932[3][189]; -#define CP932INV_TABLE_BEGIN 0xED -#define CP932INV_TABLE_END 0xEE -extern const unsigned short cp932inv[2][189]; -#endif /* SHIFTJIS_CP932 */ - -#ifdef X0212_ENABLE -extern const unsigned short shiftjis_x0212[3][189]; -extern const unsigned short *const x0212_shiftjis[]; -#endif /* X0212_ENABLE */ - -#endif diff --git a/ext/nkf/nkf.c b/ext/nkf/nkf.c deleted file mode 100644 index 73b616a54fd0bb..00000000000000 --- a/ext/nkf/nkf.c +++ /dev/null @@ -1,506 +0,0 @@ -/* - * NKF - Ruby extension for Network Kanji Filter - * - * original nkf2.x is maintained at http://sourceforge.jp/projects/nkf/ - * - * $Id$ - * - */ - -#define RUBY_NKF_REVISION "$Revision$" -#define RUBY_NKF_VERSION NKF_VERSION " (" NKF_RELEASE_DATE ")" -#define NKF_GEM_VERSION "0.1.3" - -#include "ruby/ruby.h" -#include "ruby/encoding.h" - -/* Replace nkf's getchar/putchar for variable modification */ -/* we never use getc, ungetc */ - -#undef getc -#undef ungetc -#define getc(f) (input_ctr>=i_len?-1:input[input_ctr++]) -#define ungetc(c,f) input_ctr-- - -#define INCSIZE 32 -#undef putchar -#undef TRUE -#undef FALSE -#define putchar(c) rb_nkf_putchar(c) - -/* Input/Output pointers */ - -static unsigned char *output; -static unsigned char *input; -static int input_ctr; -static int i_len; -static int output_ctr; -static int o_len; -static int incsize; - -static VALUE result; - -static int -rb_nkf_putchar(unsigned int c) -{ - if (output_ctr >= o_len) { - o_len += incsize; - rb_str_resize(result, o_len); - incsize *= 2; - output = (unsigned char *)RSTRING_PTR(result); - } - output[output_ctr++] = c; - - return c; -} - -/* Include kanji filter main part */ -/* getchar and putchar will be replaced during inclusion */ - -#define PERL_XS 1 -#include "nkf-utf8/config.h" -#include "nkf-utf8/utf8tbl.c" -#include "nkf-utf8/nkf.c" - -rb_encoding* rb_nkf_enc_get(const char *name) -{ - int idx = rb_enc_find_index(name); - if (idx < 0) { - nkf_encoding *nkf_enc = nkf_enc_find(name); - idx = rb_enc_find_index(nkf_enc_name(nkf_enc_to_base_encoding(nkf_enc))); - if (idx < 0) { - idx = rb_define_dummy_encoding(name); - } - } - return rb_enc_from_index(idx); -} - -int nkf_split_options(const char *arg) -{ - int count = 0; - unsigned char option[256]; - int i = 0, j = 0; - int is_escaped = FALSE; - int is_single_quoted = FALSE; - int is_double_quoted = FALSE; - for(i = 0; arg[i]; i++){ - if(j == 255){ - return -1; - }else if(is_single_quoted){ - if(arg[i] == '\''){ - is_single_quoted = FALSE; - }else{ - option[j++] = arg[i]; - } - }else if(is_escaped){ - is_escaped = FALSE; - option[j++] = arg[i]; - }else if(arg[i] == '\\'){ - is_escaped = TRUE; - }else if(is_double_quoted){ - if(arg[i] == '"'){ - is_double_quoted = FALSE; - }else{ - option[j++] = arg[i]; - } - }else if(arg[i] == '\''){ - is_single_quoted = TRUE; - }else if(arg[i] == '"'){ - is_double_quoted = TRUE; - }else if(arg[i] == ' '){ - option[j] = '\0'; - options(option); - j = 0; - }else{ - option[j++] = arg[i]; - } - } - if(j){ - option[j] = '\0'; - options(option); - } - return count; -} - -/* - * call-seq: - * NKF.nkf(opt, str) => string - * - * Convert _str_ and return converted result. - * Conversion details are specified by _opt_ as String. - * - * require 'nkf' - * output = NKF.nkf("-s", input) - */ - -static VALUE -rb_nkf_convert(VALUE obj, VALUE opt, VALUE src) -{ - VALUE tmp; - reinit(); - nkf_split_options(StringValueCStr(opt)); - if (!output_encoding) rb_raise(rb_eArgError, "no output encoding given"); - - switch (nkf_enc_to_index(output_encoding)) { - case UTF_8_BOM: output_encoding = nkf_enc_from_index(UTF_8); break; - case UTF_16BE_BOM: output_encoding = nkf_enc_from_index(UTF_16BE); break; - case UTF_16LE_BOM: output_encoding = nkf_enc_from_index(UTF_16LE); break; - case UTF_32BE_BOM: output_encoding = nkf_enc_from_index(UTF_32BE); break; - case UTF_32LE_BOM: output_encoding = nkf_enc_from_index(UTF_32LE); break; - } - output_bom_f = FALSE; - - incsize = INCSIZE; - - input_ctr = 0; - input = (unsigned char *)StringValuePtr(src); - i_len = RSTRING_LENINT(src); - tmp = rb_str_new(0, i_len*3 + 10); - - output_ctr = 0; - output = (unsigned char *)RSTRING_PTR(tmp); - o_len = RSTRING_LENINT(tmp); - *output = '\0'; - - /* use _result_ begin*/ - result = tmp; - kanji_convert(NULL); - result = Qnil; - /* use _result_ end */ - - rb_str_set_len(tmp, output_ctr); - - if (mimeout_f) - rb_enc_associate(tmp, rb_usascii_encoding()); - else - rb_enc_associate(tmp, rb_nkf_enc_get(nkf_enc_name(output_encoding))); - - return tmp; -} - - -/* - * call-seq: - * NKF.guess(str) => encoding - * - * Returns guessed encoding of _str_ by nkf routine. - * - */ - -static VALUE -rb_nkf_guess(VALUE obj, VALUE src) -{ - reinit(); - - input_ctr = 0; - input = (unsigned char *)StringValuePtr(src); - i_len = RSTRING_LENINT(src); - - guess_f = TRUE; - kanji_convert( NULL ); - guess_f = FALSE; - - return rb_enc_from_encoding(rb_nkf_enc_get(get_guessed_code())); -} - - -/* - * NKF - Ruby extension for Network Kanji Filter - * - * == Description - * - * This is a Ruby Extension version of nkf (Network Kanji Filter). - * It converts the first argument and returns converted result. Conversion - * details are specified by flags as the first argument. - * - * *Nkf* is a yet another kanji code converter among networks, hosts and terminals. - * It converts input kanji code to designated kanji code - * such as ISO-2022-JP, Shift_JIS, EUC-JP, UTF-8 or UTF-16. - * - * One of the most unique faculty of *nkf* is the guess of the input kanji encodings. - * It currently recognizes ISO-2022-JP, Shift_JIS, EUC-JP, UTF-8 and UTF-16. - * So users needn't set the input kanji code explicitly. - * - * By default, X0201 kana is converted into X0208 kana. - * For X0201 kana, SO/SI, SSO and ESC-(-I methods are supported. - * For automatic code detection, nkf assumes no X0201 kana in Shift_JIS. - * To accept X0201 in Shift_JIS, use -X, -x or -S. - * - * == Flags - * - * === -b -u - * - * Output is buffered (DEFAULT), Output is unbuffered. - * - * === -j -s -e -w -w16 -w32 - * - * Output code is ISO-2022-JP (7bit JIS), Shift_JIS, EUC-JP, - * UTF-8N, UTF-16BE, UTF-32BE. - * Without this option and compile option, ISO-2022-JP is assumed. - * - * === -J -S -E -W -W16 -W32 - * - * Input assumption is JIS 7 bit, Shift_JIS, EUC-JP, - * UTF-8, UTF-16, UTF-32. - * - * ==== -J - * - * Assume JIS input. It also accepts EUC-JP. - * This is the default. This flag does not exclude Shift_JIS. - * - * ==== -S - * - * Assume Shift_JIS and X0201 kana input. It also accepts JIS. - * EUC-JP is recognized as X0201 kana. Without -x flag, - * X0201 kana (halfwidth kana) is converted into X0208. - * - * ==== -E - * - * Assume EUC-JP input. It also accepts JIS. - * Same as -J. - * - * === -t - * - * No conversion. - * - * === -i_ - * - * Output sequence to designate JIS-kanji. (DEFAULT B) - * - * === -o_ - * - * Output sequence to designate ASCII. (DEFAULT B) - * - * === -r - * - * {de/en}crypt ROT13/47 - * - * === \-h[123] --hiragana --katakana --katakana-hiragana - * - * [-h1 --hiragana] Katakana to Hiragana conversion. - * - * [-h2 --katakana] Hiragana to Katakana conversion. - * - * [-h3 --katakana-hiragana] Katakana to Hiragana and Hiragana to Katakana conversion. - * - * === -T - * - * Text mode output (MS-DOS) - * - * === -l - * - * ISO8859-1 (Latin-1) support - * - * === -f[m [- n]] - * - * Folding on m length with n margin in a line. - * Without this option, fold length is 60 and fold margin is 10. - * - * === -F - * - * New line preserving line folding. - * - * === \-Z[0-3] - * - * Convert X0208 alphabet (Fullwidth Alphabets) to ASCII. - * - * [-Z -Z0] Convert X0208 alphabet to ASCII. - * - * [-Z1] Converts X0208 kankaku to single ASCII space. - * - * [-Z2] Converts X0208 kankaku to double ASCII spaces. - * - * [-Z3] Replacing Fullwidth >, <, ", & into '>', '<', '"', '&' as in HTML. - * - * === -X -x - * - * Assume X0201 kana in MS-Kanji. - * With -X or without this option, X0201 is converted into X0208 Kana. - * With -x, try to preserve X0208 kana and do not convert X0201 kana to X0208. - * In JIS output, ESC-(-I is used. In EUC output, SSO is used. - * - * === \-B[0-2] - * - * Assume broken JIS-Kanji input, which lost ESC. - * Useful when your site is using old B-News Nihongo patch. - * - * [-B1] allows any char after ESC-( or ESC-$. - * - * [-B2] forces ASCII after NL. - * - * === -I - * - * Replacing non iso-2022-jp char into a geta character - * (substitute character in Japanese). - * - * === -d -c - * - * Delete \r in line feed, Add \r in line feed. - * - * === \-m[BQN0] - * - * MIME ISO-2022-JP/ISO8859-1 decode. (DEFAULT) - * To see ISO8859-1 (Latin-1) -l is necessary. - * - * [-mB] Decode MIME base64 encoded stream. Remove header or other part before - * conversion. - * - * [-mQ] Decode MIME quoted stream. '_' in quoted stream is converted to space. - * - * [-mN] Non-strict decoding. - * It allows line break in the middle of the base64 encoding. - * - * [-m0] No MIME decode. - * - * === -M - * - * MIME encode. Header style. All ASCII code and control characters are intact. - * Kanji conversion is performed before encoding, so this cannot be used as a picture encoder. - * - * [-MB] MIME encode Base64 stream. - * - * [-MQ] Perform quoted encoding. - * - * === -l - * - * Input and output code is ISO8859-1 (Latin-1) and ISO-2022-JP. - * -s, -e and -x are not compatible with this option. - * - * === \-L[uwm] - * - * new line mode - * Without this option, nkf doesn't convert line breaks. - * - * [-Lu] unix (LF) - * - * [-Lw] windows (CRLF) - * - * [-Lm] mac (CR) - * - * === --fj --unix --mac --msdos --windows - * - * convert for these system - * - * === --jis --euc --sjis --mime --base64 - * - * convert for named code - * - * === --jis-input --euc-input --sjis-input --mime-input --base64-input - * - * assume input system - * - * === --ic=input codeset --oc=output codeset - * - * Set the input or output codeset. - * NKF supports following codesets and those codeset name are case insensitive. - * - * [ISO-2022-JP] a.k.a. RFC1468, 7bit JIS, JUNET - * - * [EUC-JP (eucJP-nkf)] a.k.a. AT&T JIS, Japanese EUC, UJIS - * - * [eucJP-ascii] a.k.a. x-eucjp-open-19970715-ascii - * - * [eucJP-ms] a.k.a. x-eucjp-open-19970715-ms - * - * [CP51932] Microsoft Version of EUC-JP. - * - * [Shift_JIS] SJIS, MS-Kanji - * - * [Windows-31J] a.k.a. CP932 - * - * [UTF-8] same as UTF-8N - * - * [UTF-8N] UTF-8 without BOM - * - * [UTF-8-BOM] UTF-8 with BOM - * - * [UTF-16] same as UTF-16BE - * - * [UTF-16BE] UTF-16 Big Endian without BOM - * - * [UTF-16BE-BOM] UTF-16 Big Endian with BOM - * - * [UTF-16LE] UTF-16 Little Endian without BOM - * - * [UTF-16LE-BOM] UTF-16 Little Endian with BOM - * - * [UTF-32] same as UTF-32BE - * - * [UTF-32BE] UTF-32 Big Endian without BOM - * - * [UTF-32BE-BOM] UTF-32 Big Endian with BOM - * - * [UTF-32LE] UTF-32 Little Endian without BOM - * - * [UTF-32LE-BOM] UTF-32 Little Endian with BOM - * - * [UTF8-MAC] NKDed UTF-8, a.k.a. UTF8-NFD (input only) - * - * === --fb-{skip, html, xml, perl, java, subchar} - * - * Specify the way that nkf handles unassigned characters. - * Without this option, --fb-skip is assumed. - * - * === --prefix= escape character target character .. - * - * When nkf converts to Shift_JIS, - * nkf adds a specified escape character to specified 2nd byte of Shift_JIS characters. - * 1st byte of argument is the escape character and following bytes are target characters. - * - * === --no-cp932ext - * - * Handle the characters extended in CP932 as unassigned characters. - * - * == --no-best-fit-chars - * - * When Unicode to Encoded byte conversion, - * don't convert characters which is not round trip safe. - * When Unicode to Unicode conversion, - * with this and -x option, nkf can be used as UTF converter. - * (In other words, without this and -x option, nkf doesn't save some characters) - * - * When nkf convert string which related to path, you should use this option. - * - * === --cap-input - * - * Decode hex encoded characters. - * - * === --url-input - * - * Unescape percent escaped characters. - * - * === -- - * - * Ignore rest of -option. - */ - -void -Init_nkf(void) -{ - VALUE mNKF = rb_define_module("NKF"); - - rb_define_module_function(mNKF, "nkf", rb_nkf_convert, 2); - rb_define_module_function(mNKF, "guess", rb_nkf_guess, 1); - rb_define_alias(rb_singleton_class(mNKF), "guess", "guess"); - - rb_define_const(mNKF, "AUTO", Qnil); - rb_define_const(mNKF, "NOCONV", Qnil); - rb_define_const(mNKF, "UNKNOWN", Qnil); - rb_define_const(mNKF, "BINARY", rb_enc_from_encoding(rb_nkf_enc_get("BINARY"))); - rb_define_const(mNKF, "ASCII", rb_enc_from_encoding(rb_nkf_enc_get("US-ASCII"))); - rb_define_const(mNKF, "JIS", rb_enc_from_encoding(rb_nkf_enc_get("ISO-2022-JP"))); - rb_define_const(mNKF, "EUC", rb_enc_from_encoding(rb_nkf_enc_get("EUC-JP"))); - rb_define_const(mNKF, "SJIS", rb_enc_from_encoding(rb_nkf_enc_get("Shift_JIS"))); - rb_define_const(mNKF, "UTF8", rb_enc_from_encoding(rb_utf8_encoding())); - rb_define_const(mNKF, "UTF16", rb_enc_from_encoding(rb_nkf_enc_get("UTF-16BE"))); - rb_define_const(mNKF, "UTF32", rb_enc_from_encoding(rb_nkf_enc_get("UTF-32BE"))); - - /* Full version string of nkf */ - rb_define_const(mNKF, "VERSION", rb_str_new2(RUBY_NKF_VERSION)); - /* Version of nkf */ - rb_define_const(mNKF, "NKF_VERSION", rb_str_new2(NKF_VERSION)); - /* Release date of nkf */ - rb_define_const(mNKF, "NKF_RELEASE_DATE", rb_str_new2(NKF_RELEASE_DATE)); - /* Version of nkf library */ - rb_define_const(mNKF, "GEM_VERSION", rb_str_new_cstr(NKF_GEM_VERSION)); -} diff --git a/ext/nkf/nkf.gemspec b/ext/nkf/nkf.gemspec deleted file mode 100644 index 097a9485ed7a6d..00000000000000 --- a/ext/nkf/nkf.gemspec +++ /dev/null @@ -1,35 +0,0 @@ -source_version = ["", "ext/nkf/"].find do |dir| - begin - break File.open(File.join(__dir__, "#{dir}nkf.c")) {|f| - f.gets("\n#define NKF_GEM_VERSION ") - f.gets[/\s*"(.+)"/, 1] - } - rescue Errno::ENOENT - end -end - -Gem::Specification.new do |spec| - spec.name = "nkf" - spec.version = source_version - spec.authors = ["NARUSE Yui"] - spec.email = ["naruse@airemix.jp"] - - spec.summary = %q{Ruby extension for Network Kanji Filter} - spec.description = %q{Ruby extension for Network Kanji Filter} - spec.homepage = "https://github.com/ruby/nkf" - spec.required_ruby_version = Gem::Requirement.new(">= 2.3.0") - spec.licenses = ["Ruby", "BSD-2-Clause"] - - spec.metadata["homepage_uri"] = spec.homepage - spec.metadata["source_code_uri"] = spec.homepage - - # Specify which files should be added to the gem when it is released. - # The `git ls-files -z` loads the files in the RubyGem that have been added into git. - spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do - `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) } - end - spec.bindir = "exe" - spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } - spec.require_paths = ["lib"] - spec.extensions = ["ext/nkf/extconf.rb"] -end diff --git a/ext/objspace/depend b/ext/objspace/depend index 9e9cce0fc2c163..3c11511575ff52 100644 --- a/ext/objspace/depend +++ b/ext/objspace/depend @@ -140,6 +140,7 @@ object_tracing.o: $(hdrdir)/ruby/internal/intern/re.h object_tracing.o: $(hdrdir)/ruby/internal/intern/ruby.h object_tracing.o: $(hdrdir)/ruby/internal/intern/select.h object_tracing.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +object_tracing.o: $(hdrdir)/ruby/internal/intern/set.h object_tracing.o: $(hdrdir)/ruby/internal/intern/signal.h object_tracing.o: $(hdrdir)/ruby/internal/intern/sprintf.h object_tracing.o: $(hdrdir)/ruby/internal/intern/string.h @@ -159,6 +160,7 @@ object_tracing.o: $(hdrdir)/ruby/internal/special_consts.h object_tracing.o: $(hdrdir)/ruby/internal/static_assert.h object_tracing.o: $(hdrdir)/ruby/internal/stdalign.h object_tracing.o: $(hdrdir)/ruby/internal/stdbool.h +object_tracing.o: $(hdrdir)/ruby/internal/stdckdint.h object_tracing.o: $(hdrdir)/ruby/internal/symbol.h object_tracing.o: $(hdrdir)/ruby/internal/value.h object_tracing.o: $(hdrdir)/ruby/internal/value_type.h @@ -176,13 +178,17 @@ object_tracing.o: $(top_srcdir)/ccan/check_type/check_type.h object_tracing.o: $(top_srcdir)/ccan/container_of/container_of.h object_tracing.o: $(top_srcdir)/ccan/list/list.h object_tracing.o: $(top_srcdir)/ccan/str/str.h +object_tracing.o: $(top_srcdir)/id_table.h object_tracing.o: $(top_srcdir)/internal.h object_tracing.o: $(top_srcdir)/internal/array.h object_tracing.o: $(top_srcdir)/internal/basic_operators.h object_tracing.o: $(top_srcdir)/internal/compilers.h object_tracing.o: $(top_srcdir)/internal/gc.h object_tracing.o: $(top_srcdir)/internal/imemo.h +object_tracing.o: $(top_srcdir)/internal/namespace.h +object_tracing.o: $(top_srcdir)/internal/sanitizers.h object_tracing.o: $(top_srcdir)/internal/serial.h +object_tracing.o: $(top_srcdir)/internal/set_table.h object_tracing.o: $(top_srcdir)/internal/static_assert.h object_tracing.o: $(top_srcdir)/internal/vm.h object_tracing.o: $(top_srcdir)/internal/warnings.h @@ -338,6 +344,7 @@ objspace.o: $(hdrdir)/ruby/internal/intern/re.h objspace.o: $(hdrdir)/ruby/internal/intern/ruby.h objspace.o: $(hdrdir)/ruby/internal/intern/select.h objspace.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +objspace.o: $(hdrdir)/ruby/internal/intern/set.h objspace.o: $(hdrdir)/ruby/internal/intern/signal.h objspace.o: $(hdrdir)/ruby/internal/intern/sprintf.h objspace.o: $(hdrdir)/ruby/internal/intern/string.h @@ -357,6 +364,7 @@ objspace.o: $(hdrdir)/ruby/internal/special_consts.h objspace.o: $(hdrdir)/ruby/internal/static_assert.h objspace.o: $(hdrdir)/ruby/internal/stdalign.h objspace.o: $(hdrdir)/ruby/internal/stdbool.h +objspace.o: $(hdrdir)/ruby/internal/stdckdint.h objspace.o: $(hdrdir)/ruby/internal/symbol.h objspace.o: $(hdrdir)/ruby/internal/value.h objspace.o: $(hdrdir)/ruby/internal/value_type.h @@ -378,6 +386,7 @@ objspace.o: $(top_srcdir)/ccan/container_of/container_of.h objspace.o: $(top_srcdir)/ccan/list/list.h objspace.o: $(top_srcdir)/ccan/str/str.h objspace.o: $(top_srcdir)/constant.h +objspace.o: $(top_srcdir)/debug_counter.h objspace.o: $(top_srcdir)/id_table.h objspace.o: $(top_srcdir)/internal.h objspace.o: $(top_srcdir)/internal/array.h @@ -387,8 +396,10 @@ objspace.o: $(top_srcdir)/internal/compilers.h objspace.o: $(top_srcdir)/internal/gc.h objspace.o: $(top_srcdir)/internal/hash.h objspace.o: $(top_srcdir)/internal/imemo.h +objspace.o: $(top_srcdir)/internal/namespace.h objspace.o: $(top_srcdir)/internal/sanitizers.h objspace.o: $(top_srcdir)/internal/serial.h +objspace.o: $(top_srcdir)/internal/set_table.h objspace.o: $(top_srcdir)/internal/static_assert.h objspace.o: $(top_srcdir)/internal/variable.h objspace.o: $(top_srcdir)/internal/vm.h @@ -402,7 +413,9 @@ objspace.o: $(top_srcdir)/shape.h objspace.o: $(top_srcdir)/symbol.h objspace.o: $(top_srcdir)/thread_pthread.h objspace.o: $(top_srcdir)/vm_core.h +objspace.o: $(top_srcdir)/vm_debug.h objspace.o: $(top_srcdir)/vm_opts.h +objspace.o: $(top_srcdir)/vm_sync.h objspace.o: objspace.c objspace.o: {$(VPATH)}id.h objspace_dump.o: $(RUBY_EXTCONF_H) @@ -546,6 +559,7 @@ objspace_dump.o: $(hdrdir)/ruby/internal/intern/re.h objspace_dump.o: $(hdrdir)/ruby/internal/intern/ruby.h objspace_dump.o: $(hdrdir)/ruby/internal/intern/select.h objspace_dump.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +objspace_dump.o: $(hdrdir)/ruby/internal/intern/set.h objspace_dump.o: $(hdrdir)/ruby/internal/intern/signal.h objspace_dump.o: $(hdrdir)/ruby/internal/intern/sprintf.h objspace_dump.o: $(hdrdir)/ruby/internal/intern/string.h @@ -565,6 +579,7 @@ objspace_dump.o: $(hdrdir)/ruby/internal/special_consts.h objspace_dump.o: $(hdrdir)/ruby/internal/static_assert.h objspace_dump.o: $(hdrdir)/ruby/internal/stdalign.h objspace_dump.o: $(hdrdir)/ruby/internal/stdbool.h +objspace_dump.o: $(hdrdir)/ruby/internal/stdckdint.h objspace_dump.o: $(hdrdir)/ruby/internal/symbol.h objspace_dump.o: $(hdrdir)/ruby/internal/value.h objspace_dump.o: $(hdrdir)/ruby/internal/value_type.h @@ -585,6 +600,7 @@ objspace_dump.o: $(top_srcdir)/ccan/container_of/container_of.h objspace_dump.o: $(top_srcdir)/ccan/list/list.h objspace_dump.o: $(top_srcdir)/ccan/str/str.h objspace_dump.o: $(top_srcdir)/constant.h +objspace_dump.o: $(top_srcdir)/debug_counter.h objspace_dump.o: $(top_srcdir)/id_table.h objspace_dump.o: $(top_srcdir)/internal.h objspace_dump.o: $(top_srcdir)/internal/array.h @@ -595,8 +611,10 @@ objspace_dump.o: $(top_srcdir)/internal/gc.h objspace_dump.o: $(top_srcdir)/internal/hash.h objspace_dump.o: $(top_srcdir)/internal/imemo.h objspace_dump.o: $(top_srcdir)/internal/io.h +objspace_dump.o: $(top_srcdir)/internal/namespace.h objspace_dump.o: $(top_srcdir)/internal/sanitizers.h objspace_dump.o: $(top_srcdir)/internal/serial.h +objspace_dump.o: $(top_srcdir)/internal/set_table.h objspace_dump.o: $(top_srcdir)/internal/static_assert.h objspace_dump.o: $(top_srcdir)/internal/string.h objspace_dump.o: $(top_srcdir)/internal/variable.h @@ -610,8 +628,11 @@ objspace_dump.o: $(top_srcdir)/rubyparser.h objspace_dump.o: $(top_srcdir)/shape.h objspace_dump.o: $(top_srcdir)/symbol.h objspace_dump.o: $(top_srcdir)/thread_pthread.h +objspace_dump.o: $(top_srcdir)/vm_callinfo.h objspace_dump.o: $(top_srcdir)/vm_core.h +objspace_dump.o: $(top_srcdir)/vm_debug.h objspace_dump.o: $(top_srcdir)/vm_opts.h +objspace_dump.o: $(top_srcdir)/vm_sync.h objspace_dump.o: objspace.h objspace_dump.o: objspace_dump.c objspace_dump.o: {$(VPATH)}id.h diff --git a/ext/objspace/object_tracing.c b/ext/objspace/object_tracing.c index c1c93c51f5fe9c..0156642ef25897 100644 --- a/ext/objspace/object_tracing.c +++ b/ext/objspace/object_tracing.c @@ -53,6 +53,14 @@ make_unique_str(st_table *tbl, const char *str, long len) } } +static int +delete_unique_str_dec(st_data_t *key, st_data_t *value, st_data_t arg, int existing) +{ + assert(existing); + *value = arg; + return ST_CONTINUE; +} + static void delete_unique_str(st_table *tbl, const char *str) { @@ -66,7 +74,7 @@ delete_unique_str(st_table *tbl, const char *str) ruby_xfree((char *)n); } else { - st_insert(tbl, (st_data_t)str, n-1); + st_update(tbl, (st_data_t)str, delete_unique_str_dec, (st_data_t)(n-1)); } } } @@ -190,22 +198,23 @@ allocation_info_tracer_memsize(const void *ptr) } static int -hash_foreach_should_replace_key(st_data_t key, st_data_t value, st_data_t argp, int error) +allocation_info_tracer_compact_update_object_table_i(st_data_t key, st_data_t value, st_data_t data) { - VALUE allocated_object; + st_table *table = (st_table *)data; - allocated_object = (VALUE)value; - if (allocated_object != rb_gc_location(allocated_object)) { - return ST_REPLACE; + if (!rb_gc_pointer_to_heap_p(key)) { + return ST_DELETE; } - return ST_CONTINUE; -} + if (key != rb_gc_location(key)) { + DURING_GC_COULD_MALLOC_REGION_START(); + { + st_insert(table, rb_gc_location(key), value); + } + DURING_GC_COULD_MALLOC_REGION_END(); -static int -hash_replace_key(st_data_t *key, st_data_t *value, st_data_t argp, int existing) -{ - *key = rb_gc_location((VALUE)*key); + return ST_DELETE; + } return ST_CONTINUE; } @@ -216,7 +225,10 @@ allocation_info_tracer_compact(void *ptr) struct traceobj_arg *trace_arg = (struct traceobj_arg *)ptr; if (trace_arg->object_table && - st_foreach_with_replace(trace_arg->object_table, hash_foreach_should_replace_key, hash_replace_key, 0)) { + st_foreach( + trace_arg->object_table, + allocation_info_tracer_compact_update_object_table_i, + (st_data_t)trace_arg->object_table)) { rb_raise(rb_eRuntimeError, "hash modified during iteration"); } } diff --git a/ext/objspace/objspace.c b/ext/objspace/objspace.c index e8762d1be6f5bb..5e183e78ed5352 100644 --- a/ext/objspace/objspace.c +++ b/ext/objspace/objspace.c @@ -19,7 +19,6 @@ #include "internal/hash.h" #include "internal/imemo.h" #include "internal/sanitizers.h" -#include "node.h" #include "ruby/io.h" #include "ruby/re.h" #include "ruby/st.h" @@ -82,15 +81,15 @@ heap_iter(void *vstart, void *vend, size_t stride, void *ptr) VALUE v; for (v = (VALUE)vstart; v != (VALUE)vend; v += stride) { - void *poisoned = asan_poisoned_object_p(v); - asan_unpoison_object(v, false); + void *poisoned = rb_asan_poisoned_object_p(v); + rb_asan_unpoison_object(v, false); if (RBASIC(v)->flags) { (*ctx->cb)(v, ctx->data); } if (poisoned) { - asan_poison_object(v); + rb_asan_poison_object(v); } } @@ -170,8 +169,7 @@ setup_hash(int argc, VALUE *argv) hash = rb_hash_new(); } else if (!RHASH_EMPTY_P(hash)) { - /* WB: no new reference */ - st_foreach(RHASH_TBL_RAW(hash), set_zero_i, hash); + rb_hash_foreach(hash, set_zero_i, (st_data_t)hash); } return hash; @@ -337,17 +335,6 @@ count_symbols(int argc, VALUE *argv, VALUE os) return hash; } -static void -cn_i(VALUE v, void *n) -{ - size_t *nodes = (size_t *)n; - - if (BUILTIN_TYPE(v) == T_NODE) { - size_t s = nd_type((NODE *)v); - nodes[s]++; - } -} - /* * call-seq: * ObjectSpace.count_nodes([result_hash]) -> hash @@ -374,135 +361,7 @@ cn_i(VALUE v, void *n) static VALUE count_nodes(int argc, VALUE *argv, VALUE os) { - size_t nodes[NODE_LAST+1]; - enum node_type i; - VALUE hash = setup_hash(argc, argv); - - for (i = 0; i <= NODE_LAST; i++) { - nodes[i] = 0; - } - - each_object_with_flags(cn_i, &nodes[0]); - - for (i=0; irefs, key))) { rb_hash_aset(data->refs, key, Qtrue); @@ -764,7 +624,7 @@ collect_values(st_data_t key, st_data_t value, st_data_t data) * * With this method, you can find memory leaks. * - * This method is only expected to work except with C Ruby. + * This method is only expected to work with C Ruby. * * Example: * ObjectSpace.reachable_objects_from(['a', 'b', 'c']) @@ -784,7 +644,7 @@ collect_values(st_data_t key, st_data_t value, st_data_t data) static VALUE reachable_objects_from(VALUE self, VALUE obj) { - if (rb_objspace_markable_object_p(obj)) { + if (!RB_SPECIAL_CONST_P(obj)) { struct rof_data data; if (rb_typeddata_is_kind_of(obj, &iow_data_type)) { @@ -831,7 +691,7 @@ reachable_object_from_root_i(const char *category, VALUE obj, void *ptr) rb_hash_aset(data->categories, category_str, category_objects); } - if (rb_objspace_markable_object_p(obj) && + if (!rb_objspace_garbage_object_p(obj) && obj != data->categories && obj != data->last_category_objects) { if (rb_objspace_internal_object_p(obj)) { @@ -933,7 +793,7 @@ objspace_internal_super_of(VALUE self, VALUE obj) case T_MODULE: case T_CLASS: case T_ICLASS: - super = RCLASS_SUPER(obj); + super = rb_class_super_of(obj); break; default: rb_raise(rb_eArgError, "class or module is expected"); diff --git a/ext/objspace/objspace_dump.c b/ext/objspace/objspace_dump.c index 39584e03b8c11b..80732d0282d384 100644 --- a/ext/objspace/objspace_dump.c +++ b/ext/objspace/objspace_dump.c @@ -28,6 +28,7 @@ #include "ruby/debug.h" #include "ruby/util.h" #include "ruby/io.h" +#include "vm_callinfo.h" #include "vm_core.h" RUBY_EXTERN const char ruby_hexdigits[]; @@ -35,9 +36,10 @@ RUBY_EXTERN const char ruby_hexdigits[]; #define BUFFER_CAPACITY 4096 struct dump_config { - VALUE type; - VALUE stream; + VALUE given_output; + VALUE output_io; VALUE string; + FILE *stream; const char *root_category; VALUE cur_obj; VALUE cur_obj_klass; @@ -57,7 +59,7 @@ dump_flush(struct dump_config *dc) { if (dc->buffer_len) { if (dc->stream) { - size_t written = rb_io_bufwrite(dc->stream, dc->buffer, dc->buffer_len); + size_t written = fwrite(dc->buffer, sizeof(dc->buffer[0]), dc->buffer_len, dc->stream); if (written < dc->buffer_len) { MEMMOVE(dc->buffer, dc->buffer + written, char, dc->buffer_len - written); dc->buffer_len -= written; @@ -167,10 +169,8 @@ dump_append_c(struct dump_config *dc, unsigned char c) } static void -dump_append_ref(struct dump_config *dc, VALUE ref) +dump_append_ptr(struct dump_config *dc, VALUE ref) { - RUBY_ASSERT(ref > 0); - char buffer[roomof(sizeof(VALUE) * CHAR_BIT, 4) + rb_strlen_lit("\"0x\"")]; char *buffer_start, *buffer_end; @@ -186,6 +186,14 @@ dump_append_ref(struct dump_config *dc, VALUE ref) buffer_append(dc, buffer_start, buffer_end - buffer_start); } +static void +dump_append_ref(struct dump_config *dc, VALUE ref) +{ + RUBY_ASSERT(ref > 0); + dump_append_ptr(dc, ref); +} + + static void dump_append_string_value(struct dump_config *dc, VALUE obj) { @@ -359,8 +367,9 @@ dump_append_string_content(struct dump_config *dc, VALUE obj) static inline void dump_append_id(struct dump_config *dc, ID id) { - if (is_instance_id(id)) { - dump_append_string_value(dc, rb_sym2str(ID2SYM(id))); + VALUE str = rb_sym2str(ID2SYM(id)); + if (RTEST(str)) { + dump_append_string_value(dc, str); } else { dump_append(dc, "\"ID_INTERNAL("); @@ -376,8 +385,7 @@ dump_object(VALUE obj, struct dump_config *dc) size_t memsize; struct allocation_info *ainfo = objspace_lookup_allocation_info(obj); rb_io_t *fptr; - ID flags[RB_OBJ_GC_FLAGS_MAX]; - size_t n, i; + ID mid; if (SPECIAL_CONST_P(obj)) { dump_append_special_const(dc, obj); @@ -386,9 +394,10 @@ dump_object(VALUE obj, struct dump_config *dc) dc->cur_obj = obj; dc->cur_obj_references = 0; - if (BUILTIN_TYPE(obj) == T_NODE || BUILTIN_TYPE(obj) == T_IMEMO) { + if (BUILTIN_TYPE(obj) == T_NODE || (BUILTIN_TYPE(obj) == T_IMEMO && !IMEMO_TYPE_P(obj, imemo_fields))) { dc->cur_obj_klass = 0; - } else { + } + else { dc->cur_obj_klass = RBASIC_CLASS(obj); } @@ -406,9 +415,11 @@ dump_object(VALUE obj, struct dump_config *dc) dump_append(dc, obj_type(obj)); dump_append(dc, "\""); - size_t shape_id = rb_shape_get_shape_id(obj); - dump_append(dc, ", \"shape_id\":"); - dump_append_sizet(dc, shape_id); + if (BUILTIN_TYPE(obj) != T_IMEMO || IMEMO_TYPE_P(obj, imemo_fields)) { + size_t shape_id = rb_obj_shape_id(obj) & SHAPE_ID_OFFSET_MASK; + dump_append(dc, ", \"shape_id\":"); + dump_append_sizet(dc, shape_id); + } dump_append(dc, ", \"slot_size\":"); dump_append_sizet(dc, dc->cur_page_slot_size); @@ -429,6 +440,33 @@ dump_object(VALUE obj, struct dump_config *dc) dump_append(dc, ", \"imemo_type\":\""); dump_append(dc, rb_imemo_name(imemo_type(obj))); dump_append(dc, "\""); + + switch (imemo_type(obj)) { + case imemo_callinfo: + mid = vm_ci_mid((const struct rb_callinfo *)obj); + if (mid != 0) { + dump_append(dc, ", \"mid\":"); + dump_append_id(dc, mid); + } + break; + + case imemo_callcache: + mid = vm_cc_cme((const struct rb_callcache *)obj)->called_id; + if (mid != 0) { + dump_append(dc, ", \"called_id\":"); + dump_append_id(dc, mid); + + VALUE klass = ((const struct rb_callcache *)obj)->klass; + if (klass != 0) { + dump_append(dc, ", \"receiver_class\":"); + dump_append_ref(dc, klass); + } + } + break; + + default: + break; + } break; case T_SYMBOL: @@ -440,6 +478,8 @@ dump_object(VALUE obj, struct dump_config *dc) dump_append(dc, ", \"embedded\":true"); if (FL_TEST(obj, RSTRING_FSTR)) dump_append(dc, ", \"fstring\":true"); + if (CHILLED_STRING_P(obj)) + dump_append(dc, ", \"chilled\":true"); if (STR_SHARED_P(obj)) dump_append(dc, ", \"shared\":true"); else @@ -500,7 +540,7 @@ dump_object(VALUE obj, struct dump_config *dc) case T_CLASS: dump_append(dc, ", \"variation_count\":"); - dump_append_d(dc, RCLASS_EXT(obj)->variation_count); + dump_append_d(dc, rb_class_variation_count(obj)); case T_MODULE: if (rb_class_get_superclass(obj)) { @@ -511,9 +551,8 @@ dump_object(VALUE obj, struct dump_config *dc) if (dc->cur_obj_klass) { VALUE mod_name = rb_mod_name(obj); if (!NIL_P(mod_name)) { - dump_append(dc, ", \"name\":\""); - dump_append(dc, RSTRING_PTR(mod_name)); - dump_append(dc, "\""); + dump_append(dc, ", \"name\":"); + dump_append_string_value(dc, mod_name); } else { VALUE real_mod_name = rb_mod_name(rb_class_real(obj)); @@ -524,7 +563,7 @@ dump_object(VALUE obj, struct dump_config *dc) } } - if (FL_TEST(obj, FL_SINGLETON)) { + if (rb_class_singleton_p(obj)) { dump_append(dc, ", \"singleton\":true"); } } @@ -550,8 +589,8 @@ dump_object(VALUE obj, struct dump_config *dc) } dump_append(dc, ", \"ivars\":"); - dump_append_lu(dc, ROBJECT_IV_COUNT(obj)); - if (rb_shape_obj_too_complex(obj)) { + dump_append_lu(dc, ROBJECT_FIELDS_COUNT(obj)); + if (rb_shape_obj_too_complex_p(obj)) { dump_append(dc, ", \"too_complex_shape\":true"); } break; @@ -600,14 +639,24 @@ dump_object(VALUE obj, struct dump_config *dc) dump_append_sizet(dc, memsize); } - if ((n = rb_obj_gc_flags(obj, flags, sizeof(flags))) > 0) { - dump_append(dc, ", \"flags\":{"); - for (i=0; icur_page_slot_size = stride; if (dc->full_heap || RBASIC(v)->flags) dump_object(v, dc); if (ptr) { - asan_poison_object(v); + rb_asan_poison_object(v); } } return 0; @@ -659,16 +708,34 @@ root_obj_i(const char *category, VALUE obj, void *data) static void dump_output(struct dump_config *dc, VALUE output, VALUE full, VALUE since, VALUE shapes) { - + dc->given_output = output; dc->full_heap = 0; dc->buffer_len = 0; if (TYPE(output) == T_STRING) { - dc->stream = Qfalse; + dc->stream = NULL; dc->string = output; } else { - dc->stream = output; + rb_io_t *fptr; + // Output should be an IO, typecheck and get a FILE* for writing. + // We cannot write with the usual IO code here because writes + // interleave with calls to rb_gc_mark(). The usual IO code can + // cause a thread switch, raise exceptions, and even run arbitrary + // ruby code through the fiber scheduler. + // + // Mark functions generally can't handle these possibilities so + // the usual IO code is unsafe in this context. (For example, + // there are many ways to crash when ruby code runs and mutates + // the execution context while rb_execution_context_mark() is in + // progress.) + // + // Using FILE* isn't perfect, but it avoids the most acute problems. + output = rb_io_get_io(output); + dc->output_io = rb_io_get_write_io(output); + rb_io_flush(dc->output_io); + GetOpenFile(dc->output_io, fptr); + dc->stream = rb_io_stdio_file(fptr); dc->string = Qfalse; } @@ -692,13 +759,13 @@ dump_result(struct dump_config *dc) { dump_flush(dc); + if (dc->stream) { + fflush(dc->stream); + } if (dc->string) { return dc->string; } - else { - rb_io_flush(dc->stream); - return dc->stream; - } + return dc->given_output; } /* :nodoc: */ @@ -718,69 +785,49 @@ objspace_dump(VALUE os, VALUE obj, VALUE output) } static void -shape_i(rb_shape_t *shape, void *data) +shape_id_i(shape_id_t shape_id, void *data) { struct dump_config *dc = (struct dump_config *)data; - size_t shape_id = rb_shape_id(shape); if (shape_id < dc->shapes_since) { return; } dump_append(dc, "{\"address\":"); - dump_append_ref(dc, (VALUE)shape); + dump_append_ref(dc, (VALUE)RSHAPE(shape_id)); dump_append(dc, ", \"type\":\"SHAPE\", \"id\":"); dump_append_sizet(dc, shape_id); - if (shape->type != SHAPE_ROOT) { + if (RSHAPE_TYPE(shape_id) != SHAPE_ROOT) { dump_append(dc, ", \"parent_id\":"); - dump_append_lu(dc, shape->parent_id); + dump_append_lu(dc, RSHAPE_PARENT(shape_id)); } dump_append(dc, ", \"depth\":"); - dump_append_sizet(dc, rb_shape_depth(shape)); + dump_append_sizet(dc, rb_shape_depth(shape_id)); - dump_append(dc, ", \"shape_type\":"); - switch((enum shape_type)shape->type) { + switch (RSHAPE_TYPE(shape_id)) { case SHAPE_ROOT: - dump_append(dc, "\"ROOT\""); + dump_append(dc, ", \"shape_type\":\"ROOT\""); break; case SHAPE_IVAR: - dump_append(dc, "\"IVAR\""); + dump_append(dc, ", \"shape_type\":\"IVAR\""); dump_append(dc, ",\"edge_name\":"); - dump_append_id(dc, shape->edge_name); + dump_append_id(dc, RSHAPE_EDGE_NAME(shape_id)); break; - case SHAPE_FROZEN: - dump_append(dc, "\"FROZEN\""); + case SHAPE_OBJ_ID: + dump_append(dc, ", \"shape_type\":\"OBJ_ID\""); break; - case SHAPE_CAPACITY_CHANGE: - dump_append(dc, "\"CAPACITY_CHANGE\""); - dump_append(dc, ", \"capacity\":"); - dump_append_sizet(dc, shape->capacity); - break; - case SHAPE_INITIAL_CAPACITY: - dump_append(dc, "\"INITIAL_CAPACITY\""); - dump_append(dc, ", \"capacity\":"); - dump_append_sizet(dc, shape->capacity); - break; - case SHAPE_T_OBJECT: - dump_append(dc, "\"T_OBJECT\""); - break; - case SHAPE_OBJ_TOO_COMPLEX: - dump_append(dc, "\"OBJ_TOO_COMPLEX\""); - break; - default: - rb_bug("[objspace] unexpected shape type"); } dump_append(dc, ", \"edges\":"); - dump_append_sizet(dc, rb_shape_edges_count(shape)); + dump_append_sizet(dc, rb_shape_edges_count(shape_id)); dump_append(dc, ", \"memsize\":"); - dump_append_sizet(dc, rb_shape_memsize(shape)); + dump_append_sizet(dc, rb_shape_memsize(shape_id)); dump_append(dc, "}\n"); } @@ -799,7 +846,7 @@ objspace_dump_all(VALUE os, VALUE output, VALUE full, VALUE since, VALUE shapes) } if (RTEST(shapes)) { - rb_shape_each_shape(shape_i, &dc); + rb_shape_each_shape_id(shape_id_i, &dc); } /* dump all objects */ @@ -816,7 +863,7 @@ objspace_dump_shapes(VALUE os, VALUE output, VALUE shapes) dump_output(&dc, output, Qfalse, Qnil, shapes); if (RTEST(shapes)) { - rb_shape_each_shape(shape_i, &dc); + rb_shape_each_shape_id(shape_id_i, &dc); } return dump_result(&dc); } @@ -832,7 +879,4 @@ Init_objspace_dump(VALUE rb_mObjSpace) rb_define_module_function(rb_mObjSpace, "_dump", objspace_dump, 2); rb_define_module_function(rb_mObjSpace, "_dump_all", objspace_dump_all, 4); rb_define_module_function(rb_mObjSpace, "_dump_shapes", objspace_dump_shapes, 2); - - /* force create static IDs */ - rb_obj_gc_flags(rb_mObjSpace, 0, 0); } diff --git a/ext/openssl/History.md b/ext/openssl/History.md index 1e0df7dd8739c0..ad3417f9d0f859 100644 --- a/ext/openssl/History.md +++ b/ext/openssl/History.md @@ -1,3 +1,131 @@ +Version 3.3.0 +============= + +Compatibility +------------- + +* Ruby version: 2.7 or later +* OpenSSL version: OpenSSL 1.0.2 or later, and LibreSSL 3.1 or later + +Notable changes +--------------- + +* `OpenSSL::SSL` + - `OpenSSL::SSL::SSLSocket#set_params` no longer sets `#min_version=` to TLS + 1.0 except when OpenSSL 1.0.2 is used. This has been done to disable + SSL 3.0, which is not supported by default in OpenSSL 1.1.0 or later, or in + LibreSSL. This lets it respect the system default if the system-wide + configuration file specifies a higher minimum protocol version. + [[GitHub #710]](https://github.com/ruby/openssl/pull/710) + - `OpenSSL::SSL::SSLSocket.new` no longer enables the `OpenSSL::SSL::OP_ALL` + SSL options by default and follows the system default. + [[GitHub #767]](https://github.com/ruby/openssl/pull/767) + - Add the following IO methods to `OpenSSL::SSL::SSLSocket`, which will pass + along to the underlying socket: `#local_address`, `#remote_address`, + `#close_on_exec=`, `#close_on_exec?`, `#wait`, `#wait_readable`, and + `#wait_writable`. + [[GitHub #708]](https://github.com/ruby/openssl/pull/708) + - Update `OpenSSL::SSL::SSLSocket#gets` to take the `chomp` keyword argument. + [[GitHub #708]](https://github.com/ruby/openssl/pull/708) + - Make `OpenSSL::SSL::SSLSocket` respect the `IO#timeout` value of the + underlying socket on Ruby 3.2 or later. `#timeout` and `#timeout=` methods + are also added. + [[GitHub #714]](https://github.com/ruby/openssl/pull/714) + - Add `OpenSSL::SSL::SSLSocket#close_read` and `#close_write`. + [[GitHub #743]](https://github.com/ruby/openssl/pull/743) + - Add `OpenSSL::Digest.digests` to get a list of all available digest + algorithms. + [[GitHub #726]](https://github.com/ruby/openssl/pull/726) + - Fix `OpenSSL::SSL::SSLSocket#read_nonblock` clearing the passed String + buffer when nothing can be read from the connection. + [[GitHub #739]](https://github.com/ruby/openssl/pull/739) +* Add `#to_text` methods to `OpenSSL::Timestamp::Response`, + `OpenSSL::Timestamp::Request`, `OpenSSL::Timestamp::TokenInfo`, and + `OpenSSL::PKCS7` to get a human-readable representation of the object. + [[GitHub #756]](https://github.com/ruby/openssl/pull/756) +* Add `OpenSSL::X509::Certificate#tbs_bytes` to get the DER encoding of the + TBSCertificate. + [[GitHub #753]](https://github.com/ruby/openssl/pull/753) +* Allow passing `nil` as the digest algorithm to `#sign` methods on + `OpenSSL::X509::Certificate`, `OpenSSL::X509::Request`, and + `OpenSSL::X509::CRL`. This adds supports for signing with EdDSA keys. + [[GitHub #761]](https://github.com/ruby/openssl/pull/761) + [[GitHub #804]](https://github.com/ruby/openssl/pull/804) +* Add `OpenSSL::SSL::SSLSocket#readbyte`. + [[GitHub #771]](https://github.com/ruby/openssl/pull/771) +* Change `OpenSSL::X509::Store#time=` to set the time to the `X509_VERIFY_PARAM` + in the `X509_STORE`. This allows `OpenSSL::Timestamp::Response#verify` to + verify a signature with the specified timestamp. + [[GitHub #770]](https://github.com/ruby/openssl/pull/770) +* Make `OpenSSL::PKCS7.encrypt`'s third parameter `cipher` mandatory. It had + an undocumented default value "RC2-40-CBC", which is not only insecure, but + also not supported in OpenSSL 3.0 or later. + [[GitHub #796]](https://github.com/ruby/openssl/pull/796) +* Make `OpenSSL::BN` shareable between ractors when frozen. + [[GitHub #808]](https://github.com/ruby/openssl/pull/808) +* Make `OpenSSL::Config` instances frozen by default, and make it shareable + between ractors. `OpenSSL::Config::DEFAULT_CONFIG_FILE` is also frozen. + [[GitHub #809]](https://github.com/ruby/openssl/pull/809) +* Add `OpenSSL::PKCS12#set_mac` to configure the MAC parameters and recalculate + a MAC for the content. + [[GitHub #788]](https://github.com/ruby/openssl/pull/788) + +And various non-user-visible changes and bug fixes. Please see the commit +history for more details. + + +Version 3.2.1 +============= + +Merged changes in 3.0.3. + + +Version 3.2.0 +============= + +Compatibility +------------- + +* Ruby >= 2.7 + - Support for Ruby 2.6 has been removed. Note that Ruby 2.6 reached the + end-of-life in 2022-04. + [[GitHub #639]](https://github.com/ruby/openssl/pull/639) +* OpenSSL >= 1.0.2 or LibreSSL >= 3.1 + +Notable changes +--------------- + +* Add a stub gemspec for JRuby, which depends on the `jruby-openssl` gem. + [[GitHub #598]](https://github.com/ruby/openssl/pull/598) +* Add support for the FIPS module in OpenSSL 3.0/3.1. + [[GitHub #608]](https://github.com/ruby/openssl/pull/608) +* Rework `OpenSSL::PKey` routines for loading DER or PEM encoded keys for better + compatibility with OpenSSL 3.0/3.1 with the FIPS module. + [[GitHub #615]](https://github.com/ruby/openssl/pull/615) + [[GitHub #669]](https://github.com/ruby/openssl/pull/669) +* Add `OpenSSL::Provider` module for loading and unloading OpenSSL 3 providers. + [[GitHub #635]](https://github.com/ruby/openssl/pull/635) +* Add `OpenSSL::PKey.new_raw_private_key`, `.new_raw_public_key`, + `OpenSSL::PKey::PKey#raw_private_key`, and `#raw_public_key` for public key + algorithms that use "raw private/public key", such as X25519 and Ed25519. + [[GitHub #646]](https://github.com/ruby/openssl/pull/646) +* Improve OpenSSL error messages to include additional information when + it is available in OpenSSL's error queue. + [[GitHub #648]](https://github.com/ruby/openssl/pull/648) +* Change `OpenSSL::SSL::SSLContext#ca_file=` and `#ca_path=` to raise + `OpenSSL::SSL::SSLError` instead of printing a warning message. + [[GitHub #659]](https://github.com/ruby/openssl/pull/659) +* Allow `OpenSSL::X509::ExtensionFactory#create_extension` to take OIDs in the + dotted-decimal notation. + [[GitHub #141]](https://github.com/ruby/openssl/pull/141) + + +Version 3.1.1 +============= + +Merged changes in 3.0.3. + + Version 3.1.0 ============= @@ -34,6 +162,31 @@ Notable changes LibreSSL 3.6 and Ed25519 support in LibreSSL 3.7. +Version 3.0.3 +============= + +Bug fixes +--------- + +* Fix a performance regression introduced in v2.1.3 on a buffered write to + `SSLSocket`. + [[GitHub #706]](https://github.com/ruby/openssl/pull/706) +* Fix `OpenSSL::PKCS7` to handle PKCS#7 structures without content. + [[GitHub #690]](https://github.com/ruby/openssl/pull/690) + [[GitHub #752]](https://github.com/ruby/openssl/pull/752) +* Fix `OpenSSL::ASN1::ObjectId#==` with OIDs without a known name. + [[GitHub #791]](https://github.com/ruby/openssl/issues/791) + [[GitHub #792]](https://github.com/ruby/openssl/pull/792) +* Fix `OpenSSL::X509::Certificate#crl_uris` to handle CDP with multiple CRL + URIs. + [[GitHub #775]](https://github.com/ruby/openssl/issues/775) + [[GitHub #776]](https://github.com/ruby/openssl/pull/776) +* Fix `OpenSSL::Cipher#update` to always make the output buffer `String` + independent. + [[Bug #20937]](https://bugs.ruby-lang.org/issues/20937) + [[GitHub #824]](https://github.com/ruby/openssl/pull/824) + + Version 3.0.2 ============= @@ -417,7 +570,7 @@ Security fixes Bug fixes --------- -* Fixed OpenSSL::PKey::*.{new,generate} immediately aborting if the thread is +* Fixed OpenSSL::PKey::\*.{new,generate} immediately aborting if the thread is interrupted. [[Bug #14882]](https://bugs.ruby-lang.org/issues/14882) [[GitHub #205]](https://github.com/ruby/openssl/pull/205) diff --git a/ext/openssl/depend b/ext/openssl/depend index 0d03c85b806e9d..435f4a1c68266e 100644 --- a/ext/openssl/depend +++ b/ext/openssl/depend @@ -142,6 +142,7 @@ ossl.o: $(hdrdir)/ruby/internal/intern/re.h ossl.o: $(hdrdir)/ruby/internal/intern/ruby.h ossl.o: $(hdrdir)/ruby/internal/intern/select.h ossl.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +ossl.o: $(hdrdir)/ruby/internal/intern/set.h ossl.o: $(hdrdir)/ruby/internal/intern/signal.h ossl.o: $(hdrdir)/ruby/internal/intern/sprintf.h ossl.o: $(hdrdir)/ruby/internal/intern/string.h @@ -161,6 +162,7 @@ ossl.o: $(hdrdir)/ruby/internal/special_consts.h ossl.o: $(hdrdir)/ruby/internal/static_assert.h ossl.o: $(hdrdir)/ruby/internal/stdalign.h ossl.o: $(hdrdir)/ruby/internal/stdbool.h +ossl.o: $(hdrdir)/ruby/internal/stdckdint.h ossl.o: $(hdrdir)/ruby/internal/symbol.h ossl.o: $(hdrdir)/ruby/internal/value.h ossl.o: $(hdrdir)/ruby/internal/value_type.h @@ -171,6 +173,7 @@ ossl.o: $(hdrdir)/ruby/io.h ossl.o: $(hdrdir)/ruby/missing.h ossl.o: $(hdrdir)/ruby/onigmo.h ossl.o: $(hdrdir)/ruby/oniguruma.h +ossl.o: $(hdrdir)/ruby/ractor.h ossl.o: $(hdrdir)/ruby/ruby.h ossl.o: $(hdrdir)/ruby/st.h ossl.o: $(hdrdir)/ruby/subst.h @@ -336,6 +339,7 @@ ossl_asn1.o: $(hdrdir)/ruby/internal/intern/re.h ossl_asn1.o: $(hdrdir)/ruby/internal/intern/ruby.h ossl_asn1.o: $(hdrdir)/ruby/internal/intern/select.h ossl_asn1.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +ossl_asn1.o: $(hdrdir)/ruby/internal/intern/set.h ossl_asn1.o: $(hdrdir)/ruby/internal/intern/signal.h ossl_asn1.o: $(hdrdir)/ruby/internal/intern/sprintf.h ossl_asn1.o: $(hdrdir)/ruby/internal/intern/string.h @@ -355,6 +359,7 @@ ossl_asn1.o: $(hdrdir)/ruby/internal/special_consts.h ossl_asn1.o: $(hdrdir)/ruby/internal/static_assert.h ossl_asn1.o: $(hdrdir)/ruby/internal/stdalign.h ossl_asn1.o: $(hdrdir)/ruby/internal/stdbool.h +ossl_asn1.o: $(hdrdir)/ruby/internal/stdckdint.h ossl_asn1.o: $(hdrdir)/ruby/internal/symbol.h ossl_asn1.o: $(hdrdir)/ruby/internal/value.h ossl_asn1.o: $(hdrdir)/ruby/internal/value_type.h @@ -365,6 +370,7 @@ ossl_asn1.o: $(hdrdir)/ruby/io.h ossl_asn1.o: $(hdrdir)/ruby/missing.h ossl_asn1.o: $(hdrdir)/ruby/onigmo.h ossl_asn1.o: $(hdrdir)/ruby/oniguruma.h +ossl_asn1.o: $(hdrdir)/ruby/ractor.h ossl_asn1.o: $(hdrdir)/ruby/ruby.h ossl_asn1.o: $(hdrdir)/ruby/st.h ossl_asn1.o: $(hdrdir)/ruby/subst.h @@ -530,6 +536,7 @@ ossl_bio.o: $(hdrdir)/ruby/internal/intern/re.h ossl_bio.o: $(hdrdir)/ruby/internal/intern/ruby.h ossl_bio.o: $(hdrdir)/ruby/internal/intern/select.h ossl_bio.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +ossl_bio.o: $(hdrdir)/ruby/internal/intern/set.h ossl_bio.o: $(hdrdir)/ruby/internal/intern/signal.h ossl_bio.o: $(hdrdir)/ruby/internal/intern/sprintf.h ossl_bio.o: $(hdrdir)/ruby/internal/intern/string.h @@ -549,6 +556,7 @@ ossl_bio.o: $(hdrdir)/ruby/internal/special_consts.h ossl_bio.o: $(hdrdir)/ruby/internal/static_assert.h ossl_bio.o: $(hdrdir)/ruby/internal/stdalign.h ossl_bio.o: $(hdrdir)/ruby/internal/stdbool.h +ossl_bio.o: $(hdrdir)/ruby/internal/stdckdint.h ossl_bio.o: $(hdrdir)/ruby/internal/symbol.h ossl_bio.o: $(hdrdir)/ruby/internal/value.h ossl_bio.o: $(hdrdir)/ruby/internal/value_type.h @@ -559,6 +567,7 @@ ossl_bio.o: $(hdrdir)/ruby/io.h ossl_bio.o: $(hdrdir)/ruby/missing.h ossl_bio.o: $(hdrdir)/ruby/onigmo.h ossl_bio.o: $(hdrdir)/ruby/oniguruma.h +ossl_bio.o: $(hdrdir)/ruby/ractor.h ossl_bio.o: $(hdrdir)/ruby/ruby.h ossl_bio.o: $(hdrdir)/ruby/st.h ossl_bio.o: $(hdrdir)/ruby/subst.h @@ -724,6 +733,7 @@ ossl_bn.o: $(hdrdir)/ruby/internal/intern/re.h ossl_bn.o: $(hdrdir)/ruby/internal/intern/ruby.h ossl_bn.o: $(hdrdir)/ruby/internal/intern/select.h ossl_bn.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +ossl_bn.o: $(hdrdir)/ruby/internal/intern/set.h ossl_bn.o: $(hdrdir)/ruby/internal/intern/signal.h ossl_bn.o: $(hdrdir)/ruby/internal/intern/sprintf.h ossl_bn.o: $(hdrdir)/ruby/internal/intern/string.h @@ -743,6 +753,7 @@ ossl_bn.o: $(hdrdir)/ruby/internal/special_consts.h ossl_bn.o: $(hdrdir)/ruby/internal/static_assert.h ossl_bn.o: $(hdrdir)/ruby/internal/stdalign.h ossl_bn.o: $(hdrdir)/ruby/internal/stdbool.h +ossl_bn.o: $(hdrdir)/ruby/internal/stdckdint.h ossl_bn.o: $(hdrdir)/ruby/internal/symbol.h ossl_bn.o: $(hdrdir)/ruby/internal/value.h ossl_bn.o: $(hdrdir)/ruby/internal/value_type.h @@ -919,6 +930,7 @@ ossl_cipher.o: $(hdrdir)/ruby/internal/intern/re.h ossl_cipher.o: $(hdrdir)/ruby/internal/intern/ruby.h ossl_cipher.o: $(hdrdir)/ruby/internal/intern/select.h ossl_cipher.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +ossl_cipher.o: $(hdrdir)/ruby/internal/intern/set.h ossl_cipher.o: $(hdrdir)/ruby/internal/intern/signal.h ossl_cipher.o: $(hdrdir)/ruby/internal/intern/sprintf.h ossl_cipher.o: $(hdrdir)/ruby/internal/intern/string.h @@ -938,6 +950,7 @@ ossl_cipher.o: $(hdrdir)/ruby/internal/special_consts.h ossl_cipher.o: $(hdrdir)/ruby/internal/static_assert.h ossl_cipher.o: $(hdrdir)/ruby/internal/stdalign.h ossl_cipher.o: $(hdrdir)/ruby/internal/stdbool.h +ossl_cipher.o: $(hdrdir)/ruby/internal/stdckdint.h ossl_cipher.o: $(hdrdir)/ruby/internal/symbol.h ossl_cipher.o: $(hdrdir)/ruby/internal/value.h ossl_cipher.o: $(hdrdir)/ruby/internal/value_type.h @@ -948,6 +961,7 @@ ossl_cipher.o: $(hdrdir)/ruby/io.h ossl_cipher.o: $(hdrdir)/ruby/missing.h ossl_cipher.o: $(hdrdir)/ruby/onigmo.h ossl_cipher.o: $(hdrdir)/ruby/oniguruma.h +ossl_cipher.o: $(hdrdir)/ruby/ractor.h ossl_cipher.o: $(hdrdir)/ruby/ruby.h ossl_cipher.o: $(hdrdir)/ruby/st.h ossl_cipher.o: $(hdrdir)/ruby/subst.h @@ -1113,6 +1127,7 @@ ossl_config.o: $(hdrdir)/ruby/internal/intern/re.h ossl_config.o: $(hdrdir)/ruby/internal/intern/ruby.h ossl_config.o: $(hdrdir)/ruby/internal/intern/select.h ossl_config.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +ossl_config.o: $(hdrdir)/ruby/internal/intern/set.h ossl_config.o: $(hdrdir)/ruby/internal/intern/signal.h ossl_config.o: $(hdrdir)/ruby/internal/intern/sprintf.h ossl_config.o: $(hdrdir)/ruby/internal/intern/string.h @@ -1132,6 +1147,7 @@ ossl_config.o: $(hdrdir)/ruby/internal/special_consts.h ossl_config.o: $(hdrdir)/ruby/internal/static_assert.h ossl_config.o: $(hdrdir)/ruby/internal/stdalign.h ossl_config.o: $(hdrdir)/ruby/internal/stdbool.h +ossl_config.o: $(hdrdir)/ruby/internal/stdckdint.h ossl_config.o: $(hdrdir)/ruby/internal/symbol.h ossl_config.o: $(hdrdir)/ruby/internal/value.h ossl_config.o: $(hdrdir)/ruby/internal/value_type.h @@ -1142,6 +1158,7 @@ ossl_config.o: $(hdrdir)/ruby/io.h ossl_config.o: $(hdrdir)/ruby/missing.h ossl_config.o: $(hdrdir)/ruby/onigmo.h ossl_config.o: $(hdrdir)/ruby/oniguruma.h +ossl_config.o: $(hdrdir)/ruby/ractor.h ossl_config.o: $(hdrdir)/ruby/ruby.h ossl_config.o: $(hdrdir)/ruby/st.h ossl_config.o: $(hdrdir)/ruby/subst.h @@ -1307,6 +1324,7 @@ ossl_digest.o: $(hdrdir)/ruby/internal/intern/re.h ossl_digest.o: $(hdrdir)/ruby/internal/intern/ruby.h ossl_digest.o: $(hdrdir)/ruby/internal/intern/select.h ossl_digest.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +ossl_digest.o: $(hdrdir)/ruby/internal/intern/set.h ossl_digest.o: $(hdrdir)/ruby/internal/intern/signal.h ossl_digest.o: $(hdrdir)/ruby/internal/intern/sprintf.h ossl_digest.o: $(hdrdir)/ruby/internal/intern/string.h @@ -1326,6 +1344,7 @@ ossl_digest.o: $(hdrdir)/ruby/internal/special_consts.h ossl_digest.o: $(hdrdir)/ruby/internal/static_assert.h ossl_digest.o: $(hdrdir)/ruby/internal/stdalign.h ossl_digest.o: $(hdrdir)/ruby/internal/stdbool.h +ossl_digest.o: $(hdrdir)/ruby/internal/stdckdint.h ossl_digest.o: $(hdrdir)/ruby/internal/symbol.h ossl_digest.o: $(hdrdir)/ruby/internal/value.h ossl_digest.o: $(hdrdir)/ruby/internal/value_type.h @@ -1336,6 +1355,7 @@ ossl_digest.o: $(hdrdir)/ruby/io.h ossl_digest.o: $(hdrdir)/ruby/missing.h ossl_digest.o: $(hdrdir)/ruby/onigmo.h ossl_digest.o: $(hdrdir)/ruby/oniguruma.h +ossl_digest.o: $(hdrdir)/ruby/ractor.h ossl_digest.o: $(hdrdir)/ruby/ruby.h ossl_digest.o: $(hdrdir)/ruby/st.h ossl_digest.o: $(hdrdir)/ruby/subst.h @@ -1501,6 +1521,7 @@ ossl_engine.o: $(hdrdir)/ruby/internal/intern/re.h ossl_engine.o: $(hdrdir)/ruby/internal/intern/ruby.h ossl_engine.o: $(hdrdir)/ruby/internal/intern/select.h ossl_engine.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +ossl_engine.o: $(hdrdir)/ruby/internal/intern/set.h ossl_engine.o: $(hdrdir)/ruby/internal/intern/signal.h ossl_engine.o: $(hdrdir)/ruby/internal/intern/sprintf.h ossl_engine.o: $(hdrdir)/ruby/internal/intern/string.h @@ -1520,6 +1541,7 @@ ossl_engine.o: $(hdrdir)/ruby/internal/special_consts.h ossl_engine.o: $(hdrdir)/ruby/internal/static_assert.h ossl_engine.o: $(hdrdir)/ruby/internal/stdalign.h ossl_engine.o: $(hdrdir)/ruby/internal/stdbool.h +ossl_engine.o: $(hdrdir)/ruby/internal/stdckdint.h ossl_engine.o: $(hdrdir)/ruby/internal/symbol.h ossl_engine.o: $(hdrdir)/ruby/internal/value.h ossl_engine.o: $(hdrdir)/ruby/internal/value_type.h @@ -1530,6 +1552,7 @@ ossl_engine.o: $(hdrdir)/ruby/io.h ossl_engine.o: $(hdrdir)/ruby/missing.h ossl_engine.o: $(hdrdir)/ruby/onigmo.h ossl_engine.o: $(hdrdir)/ruby/oniguruma.h +ossl_engine.o: $(hdrdir)/ruby/ractor.h ossl_engine.o: $(hdrdir)/ruby/ruby.h ossl_engine.o: $(hdrdir)/ruby/st.h ossl_engine.o: $(hdrdir)/ruby/subst.h @@ -1695,6 +1718,7 @@ ossl_hmac.o: $(hdrdir)/ruby/internal/intern/re.h ossl_hmac.o: $(hdrdir)/ruby/internal/intern/ruby.h ossl_hmac.o: $(hdrdir)/ruby/internal/intern/select.h ossl_hmac.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +ossl_hmac.o: $(hdrdir)/ruby/internal/intern/set.h ossl_hmac.o: $(hdrdir)/ruby/internal/intern/signal.h ossl_hmac.o: $(hdrdir)/ruby/internal/intern/sprintf.h ossl_hmac.o: $(hdrdir)/ruby/internal/intern/string.h @@ -1714,6 +1738,7 @@ ossl_hmac.o: $(hdrdir)/ruby/internal/special_consts.h ossl_hmac.o: $(hdrdir)/ruby/internal/static_assert.h ossl_hmac.o: $(hdrdir)/ruby/internal/stdalign.h ossl_hmac.o: $(hdrdir)/ruby/internal/stdbool.h +ossl_hmac.o: $(hdrdir)/ruby/internal/stdckdint.h ossl_hmac.o: $(hdrdir)/ruby/internal/symbol.h ossl_hmac.o: $(hdrdir)/ruby/internal/value.h ossl_hmac.o: $(hdrdir)/ruby/internal/value_type.h @@ -1724,6 +1749,7 @@ ossl_hmac.o: $(hdrdir)/ruby/io.h ossl_hmac.o: $(hdrdir)/ruby/missing.h ossl_hmac.o: $(hdrdir)/ruby/onigmo.h ossl_hmac.o: $(hdrdir)/ruby/oniguruma.h +ossl_hmac.o: $(hdrdir)/ruby/ractor.h ossl_hmac.o: $(hdrdir)/ruby/ruby.h ossl_hmac.o: $(hdrdir)/ruby/st.h ossl_hmac.o: $(hdrdir)/ruby/subst.h @@ -1889,6 +1915,7 @@ ossl_kdf.o: $(hdrdir)/ruby/internal/intern/re.h ossl_kdf.o: $(hdrdir)/ruby/internal/intern/ruby.h ossl_kdf.o: $(hdrdir)/ruby/internal/intern/select.h ossl_kdf.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +ossl_kdf.o: $(hdrdir)/ruby/internal/intern/set.h ossl_kdf.o: $(hdrdir)/ruby/internal/intern/signal.h ossl_kdf.o: $(hdrdir)/ruby/internal/intern/sprintf.h ossl_kdf.o: $(hdrdir)/ruby/internal/intern/string.h @@ -1908,6 +1935,7 @@ ossl_kdf.o: $(hdrdir)/ruby/internal/special_consts.h ossl_kdf.o: $(hdrdir)/ruby/internal/static_assert.h ossl_kdf.o: $(hdrdir)/ruby/internal/stdalign.h ossl_kdf.o: $(hdrdir)/ruby/internal/stdbool.h +ossl_kdf.o: $(hdrdir)/ruby/internal/stdckdint.h ossl_kdf.o: $(hdrdir)/ruby/internal/symbol.h ossl_kdf.o: $(hdrdir)/ruby/internal/value.h ossl_kdf.o: $(hdrdir)/ruby/internal/value_type.h @@ -1918,6 +1946,7 @@ ossl_kdf.o: $(hdrdir)/ruby/io.h ossl_kdf.o: $(hdrdir)/ruby/missing.h ossl_kdf.o: $(hdrdir)/ruby/onigmo.h ossl_kdf.o: $(hdrdir)/ruby/oniguruma.h +ossl_kdf.o: $(hdrdir)/ruby/ractor.h ossl_kdf.o: $(hdrdir)/ruby/ruby.h ossl_kdf.o: $(hdrdir)/ruby/st.h ossl_kdf.o: $(hdrdir)/ruby/subst.h @@ -2083,6 +2112,7 @@ ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/re.h ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/ruby.h ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/select.h ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/set.h ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/signal.h ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/sprintf.h ossl_ns_spki.o: $(hdrdir)/ruby/internal/intern/string.h @@ -2102,6 +2132,7 @@ ossl_ns_spki.o: $(hdrdir)/ruby/internal/special_consts.h ossl_ns_spki.o: $(hdrdir)/ruby/internal/static_assert.h ossl_ns_spki.o: $(hdrdir)/ruby/internal/stdalign.h ossl_ns_spki.o: $(hdrdir)/ruby/internal/stdbool.h +ossl_ns_spki.o: $(hdrdir)/ruby/internal/stdckdint.h ossl_ns_spki.o: $(hdrdir)/ruby/internal/symbol.h ossl_ns_spki.o: $(hdrdir)/ruby/internal/value.h ossl_ns_spki.o: $(hdrdir)/ruby/internal/value_type.h @@ -2112,6 +2143,7 @@ ossl_ns_spki.o: $(hdrdir)/ruby/io.h ossl_ns_spki.o: $(hdrdir)/ruby/missing.h ossl_ns_spki.o: $(hdrdir)/ruby/onigmo.h ossl_ns_spki.o: $(hdrdir)/ruby/oniguruma.h +ossl_ns_spki.o: $(hdrdir)/ruby/ractor.h ossl_ns_spki.o: $(hdrdir)/ruby/ruby.h ossl_ns_spki.o: $(hdrdir)/ruby/st.h ossl_ns_spki.o: $(hdrdir)/ruby/subst.h @@ -2277,6 +2309,7 @@ ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/re.h ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/ruby.h ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/select.h ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/set.h ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/signal.h ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/sprintf.h ossl_ocsp.o: $(hdrdir)/ruby/internal/intern/string.h @@ -2296,6 +2329,7 @@ ossl_ocsp.o: $(hdrdir)/ruby/internal/special_consts.h ossl_ocsp.o: $(hdrdir)/ruby/internal/static_assert.h ossl_ocsp.o: $(hdrdir)/ruby/internal/stdalign.h ossl_ocsp.o: $(hdrdir)/ruby/internal/stdbool.h +ossl_ocsp.o: $(hdrdir)/ruby/internal/stdckdint.h ossl_ocsp.o: $(hdrdir)/ruby/internal/symbol.h ossl_ocsp.o: $(hdrdir)/ruby/internal/value.h ossl_ocsp.o: $(hdrdir)/ruby/internal/value_type.h @@ -2306,6 +2340,7 @@ ossl_ocsp.o: $(hdrdir)/ruby/io.h ossl_ocsp.o: $(hdrdir)/ruby/missing.h ossl_ocsp.o: $(hdrdir)/ruby/onigmo.h ossl_ocsp.o: $(hdrdir)/ruby/oniguruma.h +ossl_ocsp.o: $(hdrdir)/ruby/ractor.h ossl_ocsp.o: $(hdrdir)/ruby/ruby.h ossl_ocsp.o: $(hdrdir)/ruby/st.h ossl_ocsp.o: $(hdrdir)/ruby/subst.h @@ -2471,6 +2506,7 @@ ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/re.h ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/ruby.h ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/select.h ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/set.h ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/signal.h ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/sprintf.h ossl_pkcs12.o: $(hdrdir)/ruby/internal/intern/string.h @@ -2490,6 +2526,7 @@ ossl_pkcs12.o: $(hdrdir)/ruby/internal/special_consts.h ossl_pkcs12.o: $(hdrdir)/ruby/internal/static_assert.h ossl_pkcs12.o: $(hdrdir)/ruby/internal/stdalign.h ossl_pkcs12.o: $(hdrdir)/ruby/internal/stdbool.h +ossl_pkcs12.o: $(hdrdir)/ruby/internal/stdckdint.h ossl_pkcs12.o: $(hdrdir)/ruby/internal/symbol.h ossl_pkcs12.o: $(hdrdir)/ruby/internal/value.h ossl_pkcs12.o: $(hdrdir)/ruby/internal/value_type.h @@ -2500,6 +2537,7 @@ ossl_pkcs12.o: $(hdrdir)/ruby/io.h ossl_pkcs12.o: $(hdrdir)/ruby/missing.h ossl_pkcs12.o: $(hdrdir)/ruby/onigmo.h ossl_pkcs12.o: $(hdrdir)/ruby/oniguruma.h +ossl_pkcs12.o: $(hdrdir)/ruby/ractor.h ossl_pkcs12.o: $(hdrdir)/ruby/ruby.h ossl_pkcs12.o: $(hdrdir)/ruby/st.h ossl_pkcs12.o: $(hdrdir)/ruby/subst.h @@ -2665,6 +2703,7 @@ ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/re.h ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/ruby.h ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/select.h ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/set.h ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/signal.h ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/sprintf.h ossl_pkcs7.o: $(hdrdir)/ruby/internal/intern/string.h @@ -2684,6 +2723,7 @@ ossl_pkcs7.o: $(hdrdir)/ruby/internal/special_consts.h ossl_pkcs7.o: $(hdrdir)/ruby/internal/static_assert.h ossl_pkcs7.o: $(hdrdir)/ruby/internal/stdalign.h ossl_pkcs7.o: $(hdrdir)/ruby/internal/stdbool.h +ossl_pkcs7.o: $(hdrdir)/ruby/internal/stdckdint.h ossl_pkcs7.o: $(hdrdir)/ruby/internal/symbol.h ossl_pkcs7.o: $(hdrdir)/ruby/internal/value.h ossl_pkcs7.o: $(hdrdir)/ruby/internal/value_type.h @@ -2694,6 +2734,7 @@ ossl_pkcs7.o: $(hdrdir)/ruby/io.h ossl_pkcs7.o: $(hdrdir)/ruby/missing.h ossl_pkcs7.o: $(hdrdir)/ruby/onigmo.h ossl_pkcs7.o: $(hdrdir)/ruby/oniguruma.h +ossl_pkcs7.o: $(hdrdir)/ruby/ractor.h ossl_pkcs7.o: $(hdrdir)/ruby/ruby.h ossl_pkcs7.o: $(hdrdir)/ruby/st.h ossl_pkcs7.o: $(hdrdir)/ruby/subst.h @@ -2859,6 +2900,7 @@ ossl_pkey.o: $(hdrdir)/ruby/internal/intern/re.h ossl_pkey.o: $(hdrdir)/ruby/internal/intern/ruby.h ossl_pkey.o: $(hdrdir)/ruby/internal/intern/select.h ossl_pkey.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +ossl_pkey.o: $(hdrdir)/ruby/internal/intern/set.h ossl_pkey.o: $(hdrdir)/ruby/internal/intern/signal.h ossl_pkey.o: $(hdrdir)/ruby/internal/intern/sprintf.h ossl_pkey.o: $(hdrdir)/ruby/internal/intern/string.h @@ -2878,6 +2920,7 @@ ossl_pkey.o: $(hdrdir)/ruby/internal/special_consts.h ossl_pkey.o: $(hdrdir)/ruby/internal/static_assert.h ossl_pkey.o: $(hdrdir)/ruby/internal/stdalign.h ossl_pkey.o: $(hdrdir)/ruby/internal/stdbool.h +ossl_pkey.o: $(hdrdir)/ruby/internal/stdckdint.h ossl_pkey.o: $(hdrdir)/ruby/internal/symbol.h ossl_pkey.o: $(hdrdir)/ruby/internal/value.h ossl_pkey.o: $(hdrdir)/ruby/internal/value_type.h @@ -2888,6 +2931,7 @@ ossl_pkey.o: $(hdrdir)/ruby/io.h ossl_pkey.o: $(hdrdir)/ruby/missing.h ossl_pkey.o: $(hdrdir)/ruby/onigmo.h ossl_pkey.o: $(hdrdir)/ruby/oniguruma.h +ossl_pkey.o: $(hdrdir)/ruby/ractor.h ossl_pkey.o: $(hdrdir)/ruby/ruby.h ossl_pkey.o: $(hdrdir)/ruby/st.h ossl_pkey.o: $(hdrdir)/ruby/subst.h @@ -3053,6 +3097,7 @@ ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/re.h ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/ruby.h ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/select.h ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/set.h ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/signal.h ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/sprintf.h ossl_pkey_dh.o: $(hdrdir)/ruby/internal/intern/string.h @@ -3072,6 +3117,7 @@ ossl_pkey_dh.o: $(hdrdir)/ruby/internal/special_consts.h ossl_pkey_dh.o: $(hdrdir)/ruby/internal/static_assert.h ossl_pkey_dh.o: $(hdrdir)/ruby/internal/stdalign.h ossl_pkey_dh.o: $(hdrdir)/ruby/internal/stdbool.h +ossl_pkey_dh.o: $(hdrdir)/ruby/internal/stdckdint.h ossl_pkey_dh.o: $(hdrdir)/ruby/internal/symbol.h ossl_pkey_dh.o: $(hdrdir)/ruby/internal/value.h ossl_pkey_dh.o: $(hdrdir)/ruby/internal/value_type.h @@ -3082,6 +3128,7 @@ ossl_pkey_dh.o: $(hdrdir)/ruby/io.h ossl_pkey_dh.o: $(hdrdir)/ruby/missing.h ossl_pkey_dh.o: $(hdrdir)/ruby/onigmo.h ossl_pkey_dh.o: $(hdrdir)/ruby/oniguruma.h +ossl_pkey_dh.o: $(hdrdir)/ruby/ractor.h ossl_pkey_dh.o: $(hdrdir)/ruby/ruby.h ossl_pkey_dh.o: $(hdrdir)/ruby/st.h ossl_pkey_dh.o: $(hdrdir)/ruby/subst.h @@ -3247,6 +3294,7 @@ ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/re.h ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/ruby.h ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/select.h ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/set.h ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/signal.h ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/sprintf.h ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/intern/string.h @@ -3266,6 +3314,7 @@ ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/special_consts.h ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/static_assert.h ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/stdalign.h ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/stdbool.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/stdckdint.h ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/symbol.h ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/value.h ossl_pkey_dsa.o: $(hdrdir)/ruby/internal/value_type.h @@ -3276,6 +3325,7 @@ ossl_pkey_dsa.o: $(hdrdir)/ruby/io.h ossl_pkey_dsa.o: $(hdrdir)/ruby/missing.h ossl_pkey_dsa.o: $(hdrdir)/ruby/onigmo.h ossl_pkey_dsa.o: $(hdrdir)/ruby/oniguruma.h +ossl_pkey_dsa.o: $(hdrdir)/ruby/ractor.h ossl_pkey_dsa.o: $(hdrdir)/ruby/ruby.h ossl_pkey_dsa.o: $(hdrdir)/ruby/st.h ossl_pkey_dsa.o: $(hdrdir)/ruby/subst.h @@ -3441,6 +3491,7 @@ ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/re.h ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/ruby.h ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/select.h ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/set.h ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/signal.h ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/sprintf.h ossl_pkey_ec.o: $(hdrdir)/ruby/internal/intern/string.h @@ -3460,6 +3511,7 @@ ossl_pkey_ec.o: $(hdrdir)/ruby/internal/special_consts.h ossl_pkey_ec.o: $(hdrdir)/ruby/internal/static_assert.h ossl_pkey_ec.o: $(hdrdir)/ruby/internal/stdalign.h ossl_pkey_ec.o: $(hdrdir)/ruby/internal/stdbool.h +ossl_pkey_ec.o: $(hdrdir)/ruby/internal/stdckdint.h ossl_pkey_ec.o: $(hdrdir)/ruby/internal/symbol.h ossl_pkey_ec.o: $(hdrdir)/ruby/internal/value.h ossl_pkey_ec.o: $(hdrdir)/ruby/internal/value_type.h @@ -3470,6 +3522,7 @@ ossl_pkey_ec.o: $(hdrdir)/ruby/io.h ossl_pkey_ec.o: $(hdrdir)/ruby/missing.h ossl_pkey_ec.o: $(hdrdir)/ruby/onigmo.h ossl_pkey_ec.o: $(hdrdir)/ruby/oniguruma.h +ossl_pkey_ec.o: $(hdrdir)/ruby/ractor.h ossl_pkey_ec.o: $(hdrdir)/ruby/ruby.h ossl_pkey_ec.o: $(hdrdir)/ruby/st.h ossl_pkey_ec.o: $(hdrdir)/ruby/subst.h @@ -3635,6 +3688,7 @@ ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/re.h ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/ruby.h ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/select.h ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/set.h ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/signal.h ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/sprintf.h ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/intern/string.h @@ -3654,6 +3708,7 @@ ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/special_consts.h ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/static_assert.h ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/stdalign.h ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/stdbool.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/stdckdint.h ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/symbol.h ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/value.h ossl_pkey_rsa.o: $(hdrdir)/ruby/internal/value_type.h @@ -3664,6 +3719,7 @@ ossl_pkey_rsa.o: $(hdrdir)/ruby/io.h ossl_pkey_rsa.o: $(hdrdir)/ruby/missing.h ossl_pkey_rsa.o: $(hdrdir)/ruby/onigmo.h ossl_pkey_rsa.o: $(hdrdir)/ruby/oniguruma.h +ossl_pkey_rsa.o: $(hdrdir)/ruby/ractor.h ossl_pkey_rsa.o: $(hdrdir)/ruby/ruby.h ossl_pkey_rsa.o: $(hdrdir)/ruby/st.h ossl_pkey_rsa.o: $(hdrdir)/ruby/subst.h @@ -3829,6 +3885,7 @@ ossl_provider.o: $(hdrdir)/ruby/internal/intern/re.h ossl_provider.o: $(hdrdir)/ruby/internal/intern/ruby.h ossl_provider.o: $(hdrdir)/ruby/internal/intern/select.h ossl_provider.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +ossl_provider.o: $(hdrdir)/ruby/internal/intern/set.h ossl_provider.o: $(hdrdir)/ruby/internal/intern/signal.h ossl_provider.o: $(hdrdir)/ruby/internal/intern/sprintf.h ossl_provider.o: $(hdrdir)/ruby/internal/intern/string.h @@ -3848,6 +3905,7 @@ ossl_provider.o: $(hdrdir)/ruby/internal/special_consts.h ossl_provider.o: $(hdrdir)/ruby/internal/static_assert.h ossl_provider.o: $(hdrdir)/ruby/internal/stdalign.h ossl_provider.o: $(hdrdir)/ruby/internal/stdbool.h +ossl_provider.o: $(hdrdir)/ruby/internal/stdckdint.h ossl_provider.o: $(hdrdir)/ruby/internal/symbol.h ossl_provider.o: $(hdrdir)/ruby/internal/value.h ossl_provider.o: $(hdrdir)/ruby/internal/value_type.h @@ -3858,6 +3916,7 @@ ossl_provider.o: $(hdrdir)/ruby/io.h ossl_provider.o: $(hdrdir)/ruby/missing.h ossl_provider.o: $(hdrdir)/ruby/onigmo.h ossl_provider.o: $(hdrdir)/ruby/oniguruma.h +ossl_provider.o: $(hdrdir)/ruby/ractor.h ossl_provider.o: $(hdrdir)/ruby/ruby.h ossl_provider.o: $(hdrdir)/ruby/st.h ossl_provider.o: $(hdrdir)/ruby/subst.h @@ -4023,6 +4082,7 @@ ossl_rand.o: $(hdrdir)/ruby/internal/intern/re.h ossl_rand.o: $(hdrdir)/ruby/internal/intern/ruby.h ossl_rand.o: $(hdrdir)/ruby/internal/intern/select.h ossl_rand.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +ossl_rand.o: $(hdrdir)/ruby/internal/intern/set.h ossl_rand.o: $(hdrdir)/ruby/internal/intern/signal.h ossl_rand.o: $(hdrdir)/ruby/internal/intern/sprintf.h ossl_rand.o: $(hdrdir)/ruby/internal/intern/string.h @@ -4042,6 +4102,7 @@ ossl_rand.o: $(hdrdir)/ruby/internal/special_consts.h ossl_rand.o: $(hdrdir)/ruby/internal/static_assert.h ossl_rand.o: $(hdrdir)/ruby/internal/stdalign.h ossl_rand.o: $(hdrdir)/ruby/internal/stdbool.h +ossl_rand.o: $(hdrdir)/ruby/internal/stdckdint.h ossl_rand.o: $(hdrdir)/ruby/internal/symbol.h ossl_rand.o: $(hdrdir)/ruby/internal/value.h ossl_rand.o: $(hdrdir)/ruby/internal/value_type.h @@ -4052,6 +4113,7 @@ ossl_rand.o: $(hdrdir)/ruby/io.h ossl_rand.o: $(hdrdir)/ruby/missing.h ossl_rand.o: $(hdrdir)/ruby/onigmo.h ossl_rand.o: $(hdrdir)/ruby/oniguruma.h +ossl_rand.o: $(hdrdir)/ruby/ractor.h ossl_rand.o: $(hdrdir)/ruby/ruby.h ossl_rand.o: $(hdrdir)/ruby/st.h ossl_rand.o: $(hdrdir)/ruby/subst.h @@ -4217,6 +4279,7 @@ ossl_ssl.o: $(hdrdir)/ruby/internal/intern/re.h ossl_ssl.o: $(hdrdir)/ruby/internal/intern/ruby.h ossl_ssl.o: $(hdrdir)/ruby/internal/intern/select.h ossl_ssl.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +ossl_ssl.o: $(hdrdir)/ruby/internal/intern/set.h ossl_ssl.o: $(hdrdir)/ruby/internal/intern/signal.h ossl_ssl.o: $(hdrdir)/ruby/internal/intern/sprintf.h ossl_ssl.o: $(hdrdir)/ruby/internal/intern/string.h @@ -4236,6 +4299,7 @@ ossl_ssl.o: $(hdrdir)/ruby/internal/special_consts.h ossl_ssl.o: $(hdrdir)/ruby/internal/static_assert.h ossl_ssl.o: $(hdrdir)/ruby/internal/stdalign.h ossl_ssl.o: $(hdrdir)/ruby/internal/stdbool.h +ossl_ssl.o: $(hdrdir)/ruby/internal/stdckdint.h ossl_ssl.o: $(hdrdir)/ruby/internal/symbol.h ossl_ssl.o: $(hdrdir)/ruby/internal/value.h ossl_ssl.o: $(hdrdir)/ruby/internal/value_type.h @@ -4246,6 +4310,7 @@ ossl_ssl.o: $(hdrdir)/ruby/io.h ossl_ssl.o: $(hdrdir)/ruby/missing.h ossl_ssl.o: $(hdrdir)/ruby/onigmo.h ossl_ssl.o: $(hdrdir)/ruby/oniguruma.h +ossl_ssl.o: $(hdrdir)/ruby/ractor.h ossl_ssl.o: $(hdrdir)/ruby/ruby.h ossl_ssl.o: $(hdrdir)/ruby/st.h ossl_ssl.o: $(hdrdir)/ruby/subst.h @@ -4411,6 +4476,7 @@ ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/re.h ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/ruby.h ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/select.h ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/set.h ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/signal.h ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/sprintf.h ossl_ssl_session.o: $(hdrdir)/ruby/internal/intern/string.h @@ -4430,6 +4496,7 @@ ossl_ssl_session.o: $(hdrdir)/ruby/internal/special_consts.h ossl_ssl_session.o: $(hdrdir)/ruby/internal/static_assert.h ossl_ssl_session.o: $(hdrdir)/ruby/internal/stdalign.h ossl_ssl_session.o: $(hdrdir)/ruby/internal/stdbool.h +ossl_ssl_session.o: $(hdrdir)/ruby/internal/stdckdint.h ossl_ssl_session.o: $(hdrdir)/ruby/internal/symbol.h ossl_ssl_session.o: $(hdrdir)/ruby/internal/value.h ossl_ssl_session.o: $(hdrdir)/ruby/internal/value_type.h @@ -4440,6 +4507,7 @@ ossl_ssl_session.o: $(hdrdir)/ruby/io.h ossl_ssl_session.o: $(hdrdir)/ruby/missing.h ossl_ssl_session.o: $(hdrdir)/ruby/onigmo.h ossl_ssl_session.o: $(hdrdir)/ruby/oniguruma.h +ossl_ssl_session.o: $(hdrdir)/ruby/ractor.h ossl_ssl_session.o: $(hdrdir)/ruby/ruby.h ossl_ssl_session.o: $(hdrdir)/ruby/st.h ossl_ssl_session.o: $(hdrdir)/ruby/subst.h @@ -4605,6 +4673,7 @@ ossl_ts.o: $(hdrdir)/ruby/internal/intern/re.h ossl_ts.o: $(hdrdir)/ruby/internal/intern/ruby.h ossl_ts.o: $(hdrdir)/ruby/internal/intern/select.h ossl_ts.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +ossl_ts.o: $(hdrdir)/ruby/internal/intern/set.h ossl_ts.o: $(hdrdir)/ruby/internal/intern/signal.h ossl_ts.o: $(hdrdir)/ruby/internal/intern/sprintf.h ossl_ts.o: $(hdrdir)/ruby/internal/intern/string.h @@ -4624,6 +4693,7 @@ ossl_ts.o: $(hdrdir)/ruby/internal/special_consts.h ossl_ts.o: $(hdrdir)/ruby/internal/static_assert.h ossl_ts.o: $(hdrdir)/ruby/internal/stdalign.h ossl_ts.o: $(hdrdir)/ruby/internal/stdbool.h +ossl_ts.o: $(hdrdir)/ruby/internal/stdckdint.h ossl_ts.o: $(hdrdir)/ruby/internal/symbol.h ossl_ts.o: $(hdrdir)/ruby/internal/value.h ossl_ts.o: $(hdrdir)/ruby/internal/value_type.h @@ -4634,6 +4704,7 @@ ossl_ts.o: $(hdrdir)/ruby/io.h ossl_ts.o: $(hdrdir)/ruby/missing.h ossl_ts.o: $(hdrdir)/ruby/onigmo.h ossl_ts.o: $(hdrdir)/ruby/oniguruma.h +ossl_ts.o: $(hdrdir)/ruby/ractor.h ossl_ts.o: $(hdrdir)/ruby/ruby.h ossl_ts.o: $(hdrdir)/ruby/st.h ossl_ts.o: $(hdrdir)/ruby/subst.h @@ -4799,6 +4870,7 @@ ossl_x509.o: $(hdrdir)/ruby/internal/intern/re.h ossl_x509.o: $(hdrdir)/ruby/internal/intern/ruby.h ossl_x509.o: $(hdrdir)/ruby/internal/intern/select.h ossl_x509.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +ossl_x509.o: $(hdrdir)/ruby/internal/intern/set.h ossl_x509.o: $(hdrdir)/ruby/internal/intern/signal.h ossl_x509.o: $(hdrdir)/ruby/internal/intern/sprintf.h ossl_x509.o: $(hdrdir)/ruby/internal/intern/string.h @@ -4818,6 +4890,7 @@ ossl_x509.o: $(hdrdir)/ruby/internal/special_consts.h ossl_x509.o: $(hdrdir)/ruby/internal/static_assert.h ossl_x509.o: $(hdrdir)/ruby/internal/stdalign.h ossl_x509.o: $(hdrdir)/ruby/internal/stdbool.h +ossl_x509.o: $(hdrdir)/ruby/internal/stdckdint.h ossl_x509.o: $(hdrdir)/ruby/internal/symbol.h ossl_x509.o: $(hdrdir)/ruby/internal/value.h ossl_x509.o: $(hdrdir)/ruby/internal/value_type.h @@ -4828,6 +4901,7 @@ ossl_x509.o: $(hdrdir)/ruby/io.h ossl_x509.o: $(hdrdir)/ruby/missing.h ossl_x509.o: $(hdrdir)/ruby/onigmo.h ossl_x509.o: $(hdrdir)/ruby/oniguruma.h +ossl_x509.o: $(hdrdir)/ruby/ractor.h ossl_x509.o: $(hdrdir)/ruby/ruby.h ossl_x509.o: $(hdrdir)/ruby/st.h ossl_x509.o: $(hdrdir)/ruby/subst.h @@ -4993,6 +5067,7 @@ ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/re.h ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/ruby.h ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/select.h ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/set.h ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/signal.h ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/sprintf.h ossl_x509attr.o: $(hdrdir)/ruby/internal/intern/string.h @@ -5012,6 +5087,7 @@ ossl_x509attr.o: $(hdrdir)/ruby/internal/special_consts.h ossl_x509attr.o: $(hdrdir)/ruby/internal/static_assert.h ossl_x509attr.o: $(hdrdir)/ruby/internal/stdalign.h ossl_x509attr.o: $(hdrdir)/ruby/internal/stdbool.h +ossl_x509attr.o: $(hdrdir)/ruby/internal/stdckdint.h ossl_x509attr.o: $(hdrdir)/ruby/internal/symbol.h ossl_x509attr.o: $(hdrdir)/ruby/internal/value.h ossl_x509attr.o: $(hdrdir)/ruby/internal/value_type.h @@ -5022,6 +5098,7 @@ ossl_x509attr.o: $(hdrdir)/ruby/io.h ossl_x509attr.o: $(hdrdir)/ruby/missing.h ossl_x509attr.o: $(hdrdir)/ruby/onigmo.h ossl_x509attr.o: $(hdrdir)/ruby/oniguruma.h +ossl_x509attr.o: $(hdrdir)/ruby/ractor.h ossl_x509attr.o: $(hdrdir)/ruby/ruby.h ossl_x509attr.o: $(hdrdir)/ruby/st.h ossl_x509attr.o: $(hdrdir)/ruby/subst.h @@ -5187,6 +5264,7 @@ ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/re.h ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/ruby.h ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/select.h ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/set.h ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/signal.h ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/sprintf.h ossl_x509cert.o: $(hdrdir)/ruby/internal/intern/string.h @@ -5206,6 +5284,7 @@ ossl_x509cert.o: $(hdrdir)/ruby/internal/special_consts.h ossl_x509cert.o: $(hdrdir)/ruby/internal/static_assert.h ossl_x509cert.o: $(hdrdir)/ruby/internal/stdalign.h ossl_x509cert.o: $(hdrdir)/ruby/internal/stdbool.h +ossl_x509cert.o: $(hdrdir)/ruby/internal/stdckdint.h ossl_x509cert.o: $(hdrdir)/ruby/internal/symbol.h ossl_x509cert.o: $(hdrdir)/ruby/internal/value.h ossl_x509cert.o: $(hdrdir)/ruby/internal/value_type.h @@ -5216,6 +5295,7 @@ ossl_x509cert.o: $(hdrdir)/ruby/io.h ossl_x509cert.o: $(hdrdir)/ruby/missing.h ossl_x509cert.o: $(hdrdir)/ruby/onigmo.h ossl_x509cert.o: $(hdrdir)/ruby/oniguruma.h +ossl_x509cert.o: $(hdrdir)/ruby/ractor.h ossl_x509cert.o: $(hdrdir)/ruby/ruby.h ossl_x509cert.o: $(hdrdir)/ruby/st.h ossl_x509cert.o: $(hdrdir)/ruby/subst.h @@ -5381,6 +5461,7 @@ ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/re.h ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/ruby.h ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/select.h ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/set.h ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/signal.h ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/sprintf.h ossl_x509crl.o: $(hdrdir)/ruby/internal/intern/string.h @@ -5400,6 +5481,7 @@ ossl_x509crl.o: $(hdrdir)/ruby/internal/special_consts.h ossl_x509crl.o: $(hdrdir)/ruby/internal/static_assert.h ossl_x509crl.o: $(hdrdir)/ruby/internal/stdalign.h ossl_x509crl.o: $(hdrdir)/ruby/internal/stdbool.h +ossl_x509crl.o: $(hdrdir)/ruby/internal/stdckdint.h ossl_x509crl.o: $(hdrdir)/ruby/internal/symbol.h ossl_x509crl.o: $(hdrdir)/ruby/internal/value.h ossl_x509crl.o: $(hdrdir)/ruby/internal/value_type.h @@ -5410,6 +5492,7 @@ ossl_x509crl.o: $(hdrdir)/ruby/io.h ossl_x509crl.o: $(hdrdir)/ruby/missing.h ossl_x509crl.o: $(hdrdir)/ruby/onigmo.h ossl_x509crl.o: $(hdrdir)/ruby/oniguruma.h +ossl_x509crl.o: $(hdrdir)/ruby/ractor.h ossl_x509crl.o: $(hdrdir)/ruby/ruby.h ossl_x509crl.o: $(hdrdir)/ruby/st.h ossl_x509crl.o: $(hdrdir)/ruby/subst.h @@ -5575,6 +5658,7 @@ ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/re.h ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/ruby.h ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/select.h ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/set.h ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/signal.h ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/sprintf.h ossl_x509ext.o: $(hdrdir)/ruby/internal/intern/string.h @@ -5594,6 +5678,7 @@ ossl_x509ext.o: $(hdrdir)/ruby/internal/special_consts.h ossl_x509ext.o: $(hdrdir)/ruby/internal/static_assert.h ossl_x509ext.o: $(hdrdir)/ruby/internal/stdalign.h ossl_x509ext.o: $(hdrdir)/ruby/internal/stdbool.h +ossl_x509ext.o: $(hdrdir)/ruby/internal/stdckdint.h ossl_x509ext.o: $(hdrdir)/ruby/internal/symbol.h ossl_x509ext.o: $(hdrdir)/ruby/internal/value.h ossl_x509ext.o: $(hdrdir)/ruby/internal/value_type.h @@ -5604,6 +5689,7 @@ ossl_x509ext.o: $(hdrdir)/ruby/io.h ossl_x509ext.o: $(hdrdir)/ruby/missing.h ossl_x509ext.o: $(hdrdir)/ruby/onigmo.h ossl_x509ext.o: $(hdrdir)/ruby/oniguruma.h +ossl_x509ext.o: $(hdrdir)/ruby/ractor.h ossl_x509ext.o: $(hdrdir)/ruby/ruby.h ossl_x509ext.o: $(hdrdir)/ruby/st.h ossl_x509ext.o: $(hdrdir)/ruby/subst.h @@ -5769,6 +5855,7 @@ ossl_x509name.o: $(hdrdir)/ruby/internal/intern/re.h ossl_x509name.o: $(hdrdir)/ruby/internal/intern/ruby.h ossl_x509name.o: $(hdrdir)/ruby/internal/intern/select.h ossl_x509name.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +ossl_x509name.o: $(hdrdir)/ruby/internal/intern/set.h ossl_x509name.o: $(hdrdir)/ruby/internal/intern/signal.h ossl_x509name.o: $(hdrdir)/ruby/internal/intern/sprintf.h ossl_x509name.o: $(hdrdir)/ruby/internal/intern/string.h @@ -5788,6 +5875,7 @@ ossl_x509name.o: $(hdrdir)/ruby/internal/special_consts.h ossl_x509name.o: $(hdrdir)/ruby/internal/static_assert.h ossl_x509name.o: $(hdrdir)/ruby/internal/stdalign.h ossl_x509name.o: $(hdrdir)/ruby/internal/stdbool.h +ossl_x509name.o: $(hdrdir)/ruby/internal/stdckdint.h ossl_x509name.o: $(hdrdir)/ruby/internal/symbol.h ossl_x509name.o: $(hdrdir)/ruby/internal/value.h ossl_x509name.o: $(hdrdir)/ruby/internal/value_type.h @@ -5798,6 +5886,7 @@ ossl_x509name.o: $(hdrdir)/ruby/io.h ossl_x509name.o: $(hdrdir)/ruby/missing.h ossl_x509name.o: $(hdrdir)/ruby/onigmo.h ossl_x509name.o: $(hdrdir)/ruby/oniguruma.h +ossl_x509name.o: $(hdrdir)/ruby/ractor.h ossl_x509name.o: $(hdrdir)/ruby/ruby.h ossl_x509name.o: $(hdrdir)/ruby/st.h ossl_x509name.o: $(hdrdir)/ruby/subst.h @@ -5963,6 +6052,7 @@ ossl_x509req.o: $(hdrdir)/ruby/internal/intern/re.h ossl_x509req.o: $(hdrdir)/ruby/internal/intern/ruby.h ossl_x509req.o: $(hdrdir)/ruby/internal/intern/select.h ossl_x509req.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +ossl_x509req.o: $(hdrdir)/ruby/internal/intern/set.h ossl_x509req.o: $(hdrdir)/ruby/internal/intern/signal.h ossl_x509req.o: $(hdrdir)/ruby/internal/intern/sprintf.h ossl_x509req.o: $(hdrdir)/ruby/internal/intern/string.h @@ -5982,6 +6072,7 @@ ossl_x509req.o: $(hdrdir)/ruby/internal/special_consts.h ossl_x509req.o: $(hdrdir)/ruby/internal/static_assert.h ossl_x509req.o: $(hdrdir)/ruby/internal/stdalign.h ossl_x509req.o: $(hdrdir)/ruby/internal/stdbool.h +ossl_x509req.o: $(hdrdir)/ruby/internal/stdckdint.h ossl_x509req.o: $(hdrdir)/ruby/internal/symbol.h ossl_x509req.o: $(hdrdir)/ruby/internal/value.h ossl_x509req.o: $(hdrdir)/ruby/internal/value_type.h @@ -5992,6 +6083,7 @@ ossl_x509req.o: $(hdrdir)/ruby/io.h ossl_x509req.o: $(hdrdir)/ruby/missing.h ossl_x509req.o: $(hdrdir)/ruby/onigmo.h ossl_x509req.o: $(hdrdir)/ruby/oniguruma.h +ossl_x509req.o: $(hdrdir)/ruby/ractor.h ossl_x509req.o: $(hdrdir)/ruby/ruby.h ossl_x509req.o: $(hdrdir)/ruby/st.h ossl_x509req.o: $(hdrdir)/ruby/subst.h @@ -6157,6 +6249,7 @@ ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/re.h ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/ruby.h ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/select.h ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/set.h ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/signal.h ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/sprintf.h ossl_x509revoked.o: $(hdrdir)/ruby/internal/intern/string.h @@ -6176,6 +6269,7 @@ ossl_x509revoked.o: $(hdrdir)/ruby/internal/special_consts.h ossl_x509revoked.o: $(hdrdir)/ruby/internal/static_assert.h ossl_x509revoked.o: $(hdrdir)/ruby/internal/stdalign.h ossl_x509revoked.o: $(hdrdir)/ruby/internal/stdbool.h +ossl_x509revoked.o: $(hdrdir)/ruby/internal/stdckdint.h ossl_x509revoked.o: $(hdrdir)/ruby/internal/symbol.h ossl_x509revoked.o: $(hdrdir)/ruby/internal/value.h ossl_x509revoked.o: $(hdrdir)/ruby/internal/value_type.h @@ -6186,6 +6280,7 @@ ossl_x509revoked.o: $(hdrdir)/ruby/io.h ossl_x509revoked.o: $(hdrdir)/ruby/missing.h ossl_x509revoked.o: $(hdrdir)/ruby/onigmo.h ossl_x509revoked.o: $(hdrdir)/ruby/oniguruma.h +ossl_x509revoked.o: $(hdrdir)/ruby/ractor.h ossl_x509revoked.o: $(hdrdir)/ruby/ruby.h ossl_x509revoked.o: $(hdrdir)/ruby/st.h ossl_x509revoked.o: $(hdrdir)/ruby/subst.h @@ -6351,6 +6446,7 @@ ossl_x509store.o: $(hdrdir)/ruby/internal/intern/re.h ossl_x509store.o: $(hdrdir)/ruby/internal/intern/ruby.h ossl_x509store.o: $(hdrdir)/ruby/internal/intern/select.h ossl_x509store.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +ossl_x509store.o: $(hdrdir)/ruby/internal/intern/set.h ossl_x509store.o: $(hdrdir)/ruby/internal/intern/signal.h ossl_x509store.o: $(hdrdir)/ruby/internal/intern/sprintf.h ossl_x509store.o: $(hdrdir)/ruby/internal/intern/string.h @@ -6370,6 +6466,7 @@ ossl_x509store.o: $(hdrdir)/ruby/internal/special_consts.h ossl_x509store.o: $(hdrdir)/ruby/internal/static_assert.h ossl_x509store.o: $(hdrdir)/ruby/internal/stdalign.h ossl_x509store.o: $(hdrdir)/ruby/internal/stdbool.h +ossl_x509store.o: $(hdrdir)/ruby/internal/stdckdint.h ossl_x509store.o: $(hdrdir)/ruby/internal/symbol.h ossl_x509store.o: $(hdrdir)/ruby/internal/value.h ossl_x509store.o: $(hdrdir)/ruby/internal/value_type.h @@ -6380,6 +6477,7 @@ ossl_x509store.o: $(hdrdir)/ruby/io.h ossl_x509store.o: $(hdrdir)/ruby/missing.h ossl_x509store.o: $(hdrdir)/ruby/onigmo.h ossl_x509store.o: $(hdrdir)/ruby/oniguruma.h +ossl_x509store.o: $(hdrdir)/ruby/ractor.h ossl_x509store.o: $(hdrdir)/ruby/ruby.h ossl_x509store.o: $(hdrdir)/ruby/st.h ossl_x509store.o: $(hdrdir)/ruby/subst.h diff --git a/ext/openssl/extconf.rb b/ext/openssl/extconf.rb index 56f4a1c3ab0ea6..afbed10b54bd06 100644 --- a/ext/openssl/extconf.rb +++ b/ext/openssl/extconf.rb @@ -8,19 +8,12 @@ = Licence This program is licensed under the same licence as Ruby. - (See the file 'LICENCE'.) + (See the file 'COPYING'.) =end require "mkmf" -ssl_dirs = nil -if defined?(::TruffleRuby) - # Always respect the openssl prefix chosen by truffle/openssl-prefix - require 'truffle/openssl-prefix' - ssl_dirs = dir_config("openssl", ENV["OPENSSL_PREFIX"]) -else - ssl_dirs = dir_config("openssl") -end +ssl_dirs = dir_config("openssl") dir_config_given = ssl_dirs.any? _, ssl_ldir = ssl_dirs @@ -41,14 +34,13 @@ "library directories." end -dir_config("kerberos") - Logging::message "=== OpenSSL for Ruby configurator ===\n" $defs.push("-D""OPENSSL_SUPPRESS_DEPRECATED") -have_func("rb_io_descriptor") +have_func("rb_io_descriptor", "ruby/io.h") have_func("rb_io_maybe_wait(0, Qnil, Qnil, Qnil)", "ruby/io.h") # Ruby 3.1 +have_func("rb_io_timeout", "ruby/io.h") Logging::message "=== Checking for system dependent stuff... ===\n" have_library("nsl", "t_open") @@ -66,7 +58,6 @@ def find_openssl_library if $mswin || $mingw # required for static OpenSSL libraries - have_library("gdi32") # OpenSSL <= 1.0.2 (for RAND_screen()) have_library("crypt32") end @@ -83,12 +74,6 @@ def find_openssl_library return true end - # OpenSSL <= 1.0.2: libeay32.lib and ssleay32.lib. - if have_library("libeay32", "CRYPTO_malloc") && - have_library("ssleay32", "SSL_new") - return true - end - # LibreSSL: libcrypto-##.lib and libssl-##.lib, where ## is the ABI version # number. We have to find the version number out by scanning libpath. libpath = $LIBPATH.dup @@ -126,14 +111,15 @@ def find_openssl_library version_ok = if have_macro("LIBRESSL_VERSION_NUMBER", "openssl/opensslv.h") is_libressl = true - checking_for("LibreSSL version >= 3.1.0") { - try_static_assert("LIBRESSL_VERSION_NUMBER >= 0x30100000L", "openssl/opensslv.h") } + checking_for("LibreSSL version >= 3.9.0") { + try_static_assert("LIBRESSL_VERSION_NUMBER >= 0x30900000L", "openssl/opensslv.h") } else - checking_for("OpenSSL version >= 1.0.2") { - try_static_assert("OPENSSL_VERSION_NUMBER >= 0x10002000L", "openssl/opensslv.h") } + is_openssl = true + checking_for("OpenSSL version >= 1.1.1") { + try_static_assert("OPENSSL_VERSION_NUMBER >= 0x10101000L", "openssl/opensslv.h") } end unless version_ok - raise "OpenSSL >= 1.0.2 or LibreSSL >= 3.1.0 is required" + raise "OpenSSL >= 1.1.1 or LibreSSL >= 3.9.0 is required" end # Prevent wincrypt.h from being included, which defines conflicting macro with openssl/x509.h @@ -143,66 +129,26 @@ def find_openssl_library Logging::message "=== Checking for OpenSSL features... ===\n" evp_h = "openssl/evp.h".freeze -x509_h = "openssl/x509.h".freeze ts_h = "openssl/ts.h".freeze ssl_h = "openssl/ssl.h".freeze # compile options have_func("RAND_egd()", "openssl/rand.h") -engines = %w{dynamic 4758cca aep atalla chil - cswift nuron sureware ubsec padlock capi gmp gost cryptodev} -engines.each { |name| - have_func("ENGINE_load_#{name}()", "openssl/engine.h") -} - -# added in 1.1.0 -if !have_struct_member("SSL", "ctx", "openssl/ssl.h") || is_libressl - $defs.push("-DHAVE_OPAQUE_OPENSSL") -end -have_func("EVP_MD_CTX_new()", evp_h) -have_func("EVP_MD_CTX_free(NULL)", evp_h) -have_func("EVP_MD_CTX_pkey_ctx(NULL)", evp_h) -have_func("X509_STORE_get_ex_data(NULL, 0)", x509_h) -have_func("X509_STORE_set_ex_data(NULL, 0, NULL)", x509_h) -have_func("X509_STORE_get_ex_new_index(0, NULL, NULL, NULL, NULL)", x509_h) -have_func("X509_CRL_get0_signature(NULL, NULL, NULL)", x509_h) -have_func("X509_REQ_get0_signature(NULL, NULL, NULL)", x509_h) -have_func("X509_REVOKED_get0_serialNumber(NULL)", x509_h) -have_func("X509_REVOKED_get0_revocationDate(NULL)", x509_h) -have_func("X509_get0_tbs_sigalg(NULL)", x509_h) -have_func("X509_STORE_CTX_get0_untrusted(NULL)", x509_h) -have_func("X509_STORE_CTX_get0_cert(NULL)", x509_h) -have_func("X509_STORE_CTX_get0_chain(NULL)", x509_h) -have_func("OCSP_SINGLERESP_get0_id(NULL)", "openssl/ocsp.h") -have_func("SSL_CTX_get_ciphers(NULL)", ssl_h) -have_func("X509_up_ref(NULL)", x509_h) -have_func("X509_CRL_up_ref(NULL)", x509_h) -have_func("X509_STORE_up_ref(NULL)", x509_h) -have_func("SSL_SESSION_up_ref(NULL)", ssl_h) -have_func("EVP_PKEY_up_ref(NULL)", evp_h) -have_func("SSL_CTX_set_min_proto_version(NULL, 0)", ssl_h) -have_func("SSL_CTX_get_security_level(NULL)", ssl_h) -have_func("X509_get0_notBefore(NULL)", x509_h) -have_func("SSL_SESSION_get_protocol_version(NULL)", ssl_h) -have_func("TS_STATUS_INFO_get0_status(NULL)", ts_h) -have_func("TS_STATUS_INFO_get0_text(NULL)", ts_h) -have_func("TS_STATUS_INFO_get0_failure_info(NULL)", ts_h) -have_func("TS_VERIFY_CTS_set_certs(NULL, NULL)", ts_h) -have_func("TS_VERIFY_CTX_set_store(NULL, NULL)", ts_h) -have_func("TS_VERIFY_CTX_add_flags(NULL, 0)", ts_h) -have_func("TS_RESP_CTX_set_time_cb(NULL, NULL, NULL)", ts_h) + +# added in OpenSSL 1.0.2, not in LibreSSL yet +have_func("SSL_CTX_set1_sigalgs_list(NULL, NULL)", ssl_h) +# added in OpenSSL 1.0.2, not in LibreSSL or AWS-LC yet +have_func("SSL_CTX_set1_client_sigalgs_list(NULL, NULL)", ssl_h) + +# added in 1.1.0, currently not in LibreSSL have_func("EVP_PBE_scrypt(\"\", 0, (unsigned char *)\"\", 0, 0, 0, 0, 0, NULL, 0)", evp_h) -have_func("SSL_CTX_set_post_handshake_auth(NULL, 0)", ssl_h) -# added in 1.1.1 +# added in OpenSSL 1.1.1 and LibreSSL 3.5.0, then removed in LibreSSL 4.0.0 have_func("EVP_PKEY_check(NULL)", evp_h) -have_func("EVP_PKEY_new_raw_private_key(0, NULL, (unsigned char *)\"\", 0)", evp_h) -have_func("SSL_CTX_set_ciphersuites(NULL, \"\")", ssl_h) # added in 3.0.0 have_func("SSL_set0_tmp_dh_pkey(NULL, NULL)", ssl_h) have_func("ERR_get_error_all(NULL, NULL, NULL, NULL, NULL)", "openssl/err.h") -have_func("TS_VERIFY_CTX_set_certs(NULL, NULL)", ts_h) have_func("SSL_CTX_load_verify_file(NULL, \"\")", ssl_h) have_func("BN_check_prime(NULL, NULL, NULL)", "openssl/bn.h") have_func("EVP_MD_CTX_get0_md(NULL)", evp_h) @@ -210,6 +156,9 @@ def find_openssl_library have_func("EVP_PKEY_eq(NULL, NULL)", evp_h) have_func("EVP_PKEY_dup(NULL)", evp_h) +# added in 3.4.0 +have_func("TS_VERIFY_CTX_set0_certs(NULL, NULL)", ts_h) + Logging::message "=== Checking done. ===\n" # Append flags from environment variables. diff --git a/ext/openssl/lib/openssl.rb b/ext/openssl/lib/openssl.rb index 8a342f15b659eb..08899238903fbb 100644 --- a/ext/openssl/lib/openssl.rb +++ b/ext/openssl/lib/openssl.rb @@ -7,12 +7,13 @@ = Licence This program is licensed under the same licence as Ruby. - (See the file 'LICENCE'.) + (See the file 'COPYING'.) =end require 'openssl.so' require_relative 'openssl/bn' +require_relative 'openssl/asn1' require_relative 'openssl/pkey' require_relative 'openssl/cipher' require_relative 'openssl/digest' diff --git a/ext/openssl/lib/openssl/asn1.rb b/ext/openssl/lib/openssl/asn1.rb new file mode 100644 index 00000000000000..89fa28e1fb0b4a --- /dev/null +++ b/ext/openssl/lib/openssl/asn1.rb @@ -0,0 +1,188 @@ +# frozen_string_literal: true +#-- +# +# = Ruby-space definitions that completes C-space funcs for ASN.1 +# +# = Licence +# This program is licensed under the same licence as Ruby. +# (See the file 'COPYING'.) +#++ + +module OpenSSL + module ASN1 + class ASN1Data + # + # Carries the value of a ASN.1 type. + # Please confer Constructive and Primitive for the mappings between + # ASN.1 data types and Ruby classes. + # + attr_accessor :value + + # An Integer representing the tag number of this ASN1Data. Never +nil+. + attr_accessor :tag + + # A Symbol representing the tag class of this ASN1Data. Never +nil+. + # See ASN1Data for possible values. + attr_accessor :tag_class + + # + # Never +nil+. A boolean value indicating whether the encoding uses + # indefinite length (in the case of parsing) or whether an indefinite + # length form shall be used (in the encoding case). + # In DER, every value uses definite length form. But in scenarios where + # large amounts of data need to be transferred it might be desirable to + # have some kind of streaming support available. + # For example, huge OCTET STRINGs are preferably sent in smaller-sized + # chunks, each at a time. + # This is possible in BER by setting the length bytes of an encoding + # to zero and by this indicating that the following value will be + # sent in chunks. Indefinite length encodings are always constructed. + # The end of such a stream of chunks is indicated by sending a EOC + # (End of Content) tag. SETs and SEQUENCEs may use an indefinite length + # encoding, but also primitive types such as e.g. OCTET STRINGS or + # BIT STRINGS may leverage this functionality (cf. ITU-T X.690). + # + attr_accessor :indefinite_length + + alias infinite_length indefinite_length + alias infinite_length= indefinite_length= + + # + # :call-seq: + # OpenSSL::ASN1::ASN1Data.new(value, tag, tag_class) => ASN1Data + # + # _value_: Please have a look at Constructive and Primitive to see how Ruby + # types are mapped to ASN.1 types and vice versa. + # + # _tag_: An Integer indicating the tag number. + # + # _tag_class_: A Symbol indicating the tag class. Please cf. ASN1 for + # possible values. + # + # == Example + # asn1_int = OpenSSL::ASN1Data.new(42, 2, :UNIVERSAL) # => Same as OpenSSL::ASN1::Integer.new(42) + # tagged_int = OpenSSL::ASN1Data.new(42, 0, :CONTEXT_SPECIFIC) # implicitly 0-tagged INTEGER + # + def initialize(value, tag, tag_class) + raise ASN1Error, "invalid tag class" unless tag_class.is_a?(Symbol) + + @tag = tag + @value = value + @tag_class = tag_class + @indefinite_length = false + end + end + + module TaggedASN1Data + # + # May be used as a hint for encoding a value either implicitly or + # explicitly by setting it either to +:IMPLICIT+ or to +:EXPLICIT+. + # _tagging_ is not set when a ASN.1 structure is parsed using + # OpenSSL::ASN1.decode. + # + attr_accessor :tagging + + # :call-seq: + # OpenSSL::ASN1::Primitive.new(value [, tag, tagging, tag_class ]) => Primitive + # + # _value_: is mandatory. + # + # _tag_: optional, may be specified for tagged values. If no _tag_ is + # specified, the UNIVERSAL tag corresponding to the Primitive sub-class + # is used by default. + # + # _tagging_: may be used as an encoding hint to encode a value either + # explicitly or implicitly, see ASN1 for possible values. + # + # _tag_class_: if _tag_ and _tagging_ are +nil+ then this is set to + # +:UNIVERSAL+ by default. If either _tag_ or _tagging_ are set then + # +:CONTEXT_SPECIFIC+ is used as the default. For possible values please + # cf. ASN1. + # + # == Example + # int = OpenSSL::ASN1::Integer.new(42) + # zero_tagged_int = OpenSSL::ASN1::Integer.new(42, 0, :IMPLICIT) + # private_explicit_zero_tagged_int = OpenSSL::ASN1::Integer.new(42, 0, :EXPLICIT, :PRIVATE) + # + def initialize(value, tag = nil, tagging = nil, tag_class = nil) + tag ||= ASN1.take_default_tag(self.class) + + raise ASN1Error, "must specify tag number" unless tag + + if tagging + raise ASN1Error, "invalid tagging method" unless tagging.is_a?(Symbol) + end + + tag_class ||= tagging ? :CONTEXT_SPECIFIC : :UNIVERSAL + + raise ASN1Error, "invalid tag class" unless tag_class.is_a?(Symbol) + + @tagging = tagging + super(value ,tag, tag_class) + end + end + + class Primitive < ASN1Data + include TaggedASN1Data + + undef_method :indefinite_length= + undef_method :infinite_length= + end + + class Constructive < ASN1Data + include TaggedASN1Data + include Enumerable + + # :call-seq: + # asn1_ary.each { |asn1| block } => asn1_ary + # + # Calls the given block once for each element in self, passing that element + # as parameter _asn1_. If no block is given, an enumerator is returned + # instead. + # + # == Example + # asn1_ary.each do |asn1| + # puts asn1 + # end + # + def each(&blk) + @value.each(&blk) + + self + end + end + + class Boolean < Primitive ; end + class Integer < Primitive ; end + class Enumerated < Primitive ; end + + class BitString < Primitive + attr_accessor :unused_bits + + def initialize(*) + super + + @unused_bits = 0 + end + end + + class EndOfContent < ASN1Data + def initialize + super("", 0, :UNIVERSAL) + end + end + + # :nodoc: + def self.take_default_tag(klass) + tag = CLASS_TAG_MAP[klass] + + return tag if tag + + sklass = klass.superclass + + return unless sklass + + take_default_tag(sklass) + end + end +end diff --git a/ext/openssl/lib/openssl/bn.rb b/ext/openssl/lib/openssl/bn.rb index 0a5e11b4c2e269..e4889a140c90b3 100644 --- a/ext/openssl/lib/openssl/bn.rb +++ b/ext/openssl/lib/openssl/bn.rb @@ -10,7 +10,7 @@ # # = Licence # This program is licensed under the same licence as Ruby. -# (See the file 'LICENCE'.) +# (See the file 'COPYING'.) #++ module OpenSSL diff --git a/ext/openssl/lib/openssl/buffering.rb b/ext/openssl/lib/openssl/buffering.rb index 9570f14f375632..1464a4292d5c02 100644 --- a/ext/openssl/lib/openssl/buffering.rb +++ b/ext/openssl/lib/openssl/buffering.rb @@ -8,7 +8,7 @@ # #= Licence # This program is licensed under the same licence as Ruby. -# (See the file 'LICENCE'.) +# (See the file 'COPYING'.) #++ ## @@ -24,25 +24,21 @@ module OpenSSL::Buffering # A buffer which will retain binary encoding. class Buffer < String - BINARY = Encoding::BINARY - - def initialize - super - - force_encoding(BINARY) - end + unless String.method_defined?(:append_as_bytes) + alias_method :_append, :<< + def append_as_bytes(string) + if string.encoding == Encoding::BINARY + _append(string) + else + _append(string.b) + end - def << string - if string.encoding == BINARY - super(string) - else - super(string.b) + self end - - return self end - alias concat << + undef_method :concat + undef_method :<< end ## @@ -77,7 +73,7 @@ def initialize(*) def fill_rbuff begin - @rbuffer << self.sysread(BLOCK_SIZE) + @rbuffer.append_as_bytes(self.sysread(BLOCK_SIZE)) rescue Errno::EAGAIN retry rescue EOFError @@ -107,6 +103,12 @@ def getbyte read(1)&.ord end + # Get the next 8bit byte. Raises EOFError on EOF + def readbyte + raise EOFError if eof? + getbyte + end + ## # Reads _size_ bytes from the stream. If _buf_ is provided it must # reference a string which will receive the data. @@ -229,7 +231,7 @@ def read_nonblock(maxlen, buf=nil, exception: true) # # Unlike IO#gets the separator must be provided if a limit is provided. - def gets(eol=$/, limit=nil) + def gets(eol=$/, limit=nil, chomp: false) idx = @rbuffer.index(eol) until @eof break if idx @@ -244,7 +246,11 @@ def gets(eol=$/, limit=nil) if size && limit && limit >= 0 size = [size, limit].min end - consume_rbuff(size) + line = consume_rbuff(size) + if chomp && line + line.chomp!(eol) + end + line end ## @@ -342,17 +348,32 @@ def eof? def do_write(s) @wbuffer = Buffer.new unless defined? @wbuffer - @wbuffer << s - @wbuffer.force_encoding(Encoding::BINARY) + @wbuffer.append_as_bytes(s) + @sync ||= false - if @sync or @wbuffer.size > BLOCK_SIZE - until @wbuffer.empty? - begin - nwrote = syswrite(@wbuffer) - rescue Errno::EAGAIN - retry + buffer_size = @wbuffer.bytesize + if @sync or buffer_size > BLOCK_SIZE + nwrote = 0 + begin + while nwrote < buffer_size do + begin + chunk = if nwrote > 0 + @wbuffer.byteslice(nwrote, @wbuffer.bytesize) + else + @wbuffer + end + + nwrote += syswrite(chunk) + rescue Errno::EAGAIN + retry + end + end + ensure + if nwrote < @wbuffer.bytesize + @wbuffer[0, nwrote] = "" + else + @wbuffer.clear end - @wbuffer[0, nwrote] = "" end end end @@ -429,10 +450,10 @@ def <<(s) def puts(*args) s = Buffer.new if args.empty? - s << "\n" + s.append_as_bytes("\n") end args.each{|arg| - s << arg.to_s + s.append_as_bytes(arg.to_s) s.sub!(/(? hash + # + # Stores all parameters of key to a Hash. + # + # The hash has keys 'p', 'q', 'g', 'pub_key', and 'priv_key'. + def params + %w{p q g pub_key priv_key}.map { |name| + [name, send(name)] + }.to_h + end + # :call-seq: # dh.compute_key(pub_bn) -> string # @@ -154,6 +166,18 @@ def public_key OpenSSL::PKey.read(public_to_der) end + # :call-seq: + # dsa.params -> hash + # + # Stores all parameters of key to a Hash. + # + # The hash has keys 'p', 'q', 'g', 'pub_key', and 'priv_key'. + def params + %w{p q g pub_key priv_key}.map { |name| + [name, send(name)] + }.to_h + end + class << self # :call-seq: # DSA.generate(size) -> dsa @@ -328,6 +352,18 @@ def public_key OpenSSL::PKey.read(public_to_der) end + # :call-seq: + # rsa.params -> hash + # + # Stores all parameters of key to a Hash. + # + # The hash has keys 'n', 'e', 'd', 'p', 'q', 'dmp1', 'dmq1', and 'iqmp'. + def params + %w{n e d p q dmp1 dmq1 iqmp}.map { |name| + [name, send(name)] + }.to_h + end + class << self # :call-seq: # RSA.generate(size, exponent = 65537) -> RSA diff --git a/ext/openssl/lib/openssl/ssl.rb b/ext/openssl/lib/openssl/ssl.rb index e557b8b483f77e..a0ad5dc3a670dc 100644 --- a/ext/openssl/lib/openssl/ssl.rb +++ b/ext/openssl/lib/openssl/ssl.rb @@ -7,7 +7,7 @@ = Licence This program is licensed under the same licence as Ruby. - (See the file 'LICENCE'.) + (See the file 'COPYING'.) =end require "openssl/buffering" @@ -22,7 +22,6 @@ module OpenSSL module SSL class SSLContext DEFAULT_PARAMS = { # :nodoc: - :min_version => OpenSSL::SSL::TLS1_VERSION, :verify_mode => OpenSSL::SSL::VERIFY_PEER, :verify_hostname => true, :options => -> { @@ -52,9 +51,9 @@ class SSLContext } end - if !(OpenSSL::OPENSSL_VERSION.start_with?("OpenSSL") && - OpenSSL::OPENSSL_VERSION_NUMBER >= 0x10100000) + if !OpenSSL::OPENSSL_VERSION.start_with?("OpenSSL") DEFAULT_PARAMS.merge!( + min_version: OpenSSL::SSL::TLS1_VERSION, ciphers: %w{ ECDHE-ECDSA-AES128-GCM-SHA256 ECDHE-RSA-AES128-GCM-SHA256 @@ -125,7 +124,6 @@ class SSLContext # that this form is deprecated. New applications should use #min_version= # and #max_version= as necessary. def initialize(version = nil) - self.options |= OpenSSL::SSL::OP_ALL self.ssl_version = version if version self.verify_mode = OpenSSL::SSL::VERIFY_NONE self.verify_hostname = false @@ -145,7 +143,7 @@ def initialize(version = nil) # used. def set_params(params={}) params = DEFAULT_PARAMS.merge(params) - self.options = params.delete(:options) # set before min_version/max_version + self.options |= params.delete(:options) # set before min_version/max_version params.each{|name, value| self.__send__("#{name}=", value) } if self.verify_mode != OpenSSL::SSL::VERIFY_NONE unless self.ca_file or self.ca_path or self.cert_store @@ -155,43 +153,6 @@ def set_params(params={}) return params end - # call-seq: - # ctx.min_version = OpenSSL::SSL::TLS1_2_VERSION - # ctx.min_version = :TLS1_2 - # ctx.min_version = nil - # - # Sets the lower bound on the supported SSL/TLS protocol version. The - # version may be specified by an integer constant named - # OpenSSL::SSL::*_VERSION, a Symbol, or +nil+ which means "any version". - # - # Be careful that you don't overwrite OpenSSL::SSL::OP_NO_{SSL,TLS}v* - # options by #options= once you have called #min_version= or - # #max_version=. - # - # === Example - # ctx = OpenSSL::SSL::SSLContext.new - # ctx.min_version = OpenSSL::SSL::TLS1_1_VERSION - # ctx.max_version = OpenSSL::SSL::TLS1_2_VERSION - # - # sock = OpenSSL::SSL::SSLSocket.new(tcp_sock, ctx) - # sock.connect # Initiates a connection using either TLS 1.1 or TLS 1.2 - def min_version=(version) - set_minmax_proto_version(version, @max_proto_version ||= nil) - @min_proto_version = version - end - - # call-seq: - # ctx.max_version = OpenSSL::SSL::TLS1_2_VERSION - # ctx.max_version = :TLS1_2 - # ctx.max_version = nil - # - # Sets the upper bound of the supported SSL/TLS protocol version. See - # #min_version= for the possible values. - def max_version=(version) - set_minmax_proto_version(@min_proto_version ||= nil, version) - @max_proto_version = version - end - # call-seq: # ctx.ssl_version = :TLSv1 # ctx.ssl_version = "SSLv23" @@ -216,8 +177,7 @@ def ssl_version=(meth) end version = METHODS_MAP[meth.intern] or raise ArgumentError, "unknown SSL method `%s'" % meth - set_minmax_proto_version(version, version) - @min_proto_version = @max_proto_version = version + self.min_version = self.max_version = version end METHODS_MAP = { @@ -252,6 +212,14 @@ def peeraddr to_io.peeraddr end + def local_address + to_io.local_address + end + + def remote_address + to_io.remote_address + end + def setsockopt(level, optname, optval) to_io.setsockopt(level, optname, optval) end @@ -271,6 +239,36 @@ def closed? def do_not_reverse_lookup=(flag) to_io.do_not_reverse_lookup = flag end + + def close_on_exec=(value) + to_io.close_on_exec = value + end + + def close_on_exec? + to_io.close_on_exec? + end + + def wait(*args) + to_io.wait(*args) + end + + def wait_readable(*args) + to_io.wait_readable(*args) + end + + def wait_writable(*args) + to_io.wait_writable(*args) + end + + if IO.method_defined?(:timeout) + def timeout + to_io.timeout + end + + def timeout=(value) + to_io.timeout=(value) + end + end end def verify_certificate_identity(cert, hostname) @@ -421,6 +419,32 @@ def session nil end + # Close the stream for reading. + # This method is ignored by OpenSSL as there is no reasonable way to + # implement it, but exists for compatibility with IO. + def close_read + # Unsupported and ignored. + # Just don't read any more. + end + + # Closes the stream for writing. The behavior of this method depends on + # the version of OpenSSL and the TLS protocol in use. + # + # - Sends a 'close_notify' alert to the peer. + # - Does not wait for the peer's 'close_notify' alert in response. + # + # In TLS 1.2 and earlier: + # - On receipt of a 'close_notify' alert, responds with a 'close_notify' + # alert of its own and close down the connection immediately, + # discarding any pending writes. + # + # Therefore, on TLS 1.2, this method will cause the connection to be + # completely shut down. On TLS 1.3, the connection will remain open for + # reading only. + def close_write + stop + end + private def using_anon_cipher? diff --git a/ext/openssl/lib/openssl/version.rb b/ext/openssl/lib/openssl/version.rb index 4163f550642b49..3398fe39ccc8c6 100644 --- a/ext/openssl/lib/openssl/version.rb +++ b/ext/openssl/lib/openssl/version.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true module OpenSSL - VERSION = "3.1.0" + VERSION = "3.3.0" end diff --git a/ext/openssl/lib/openssl/x509.rb b/ext/openssl/lib/openssl/x509.rb index f973f4f4dc6ca3..6459d37b12766e 100644 --- a/ext/openssl/lib/openssl/x509.rb +++ b/ext/openssl/lib/openssl/x509.rb @@ -9,7 +9,7 @@ # # = Licence # This program is licensed under the same licence as Ruby. -# (See the file 'LICENCE'.) +# (See the file 'COPYING'.) #++ require_relative 'marshal' @@ -122,8 +122,8 @@ module CRLDistributionPoints include Helpers # Get the distributionPoint fullName URI from the certificate's CRL - # distribution points extension, as described in RFC5280 Section - # 4.2.1.13 + # distribution points extension, as described in RFC 5280 Section + # 4.2.1.13. # # Returns an array of strings or nil or raises ASN1::ASN1Error. def crl_uris @@ -135,19 +135,19 @@ def crl_uris raise ASN1::ASN1Error, "invalid extension" end - crl_uris = cdp_asn1.map do |crl_distribution_point| + crl_uris = cdp_asn1.flat_map do |crl_distribution_point| distribution_point = crl_distribution_point.value.find do |v| v.tag_class == :CONTEXT_SPECIFIC && v.tag == 0 end full_name = distribution_point&.value&.find do |v| v.tag_class == :CONTEXT_SPECIFIC && v.tag == 0 end - full_name&.value&.find do |v| + full_name&.value&.select do |v| v.tag_class == :CONTEXT_SPECIFIC && v.tag == 6 # uniformResourceIdentifier end end - crl_uris&.map(&:value) + crl_uris.empty? ? nil : crl_uris.map(&:value) end end diff --git a/ext/openssl/openssl.gemspec b/ext/openssl/openssl.gemspec index 674dc20debf05b..2ec1551885b201 100644 --- a/ext/openssl/openssl.gemspec +++ b/ext/openssl/openssl.gemspec @@ -1,19 +1,20 @@ Gem::Specification.new do |spec| spec.name = "openssl" - spec.version = "3.1.0" + spec.version = "3.3.0" spec.authors = ["Martin Bosslet", "SHIBATA Hiroshi", "Zachary Scott", "Kazuki Yamaguchi"] spec.email = ["ruby-core@ruby-lang.org"] - spec.summary = %q{OpenSSL provides SSL, TLS and general purpose cryptography.} - spec.description = %q{It wraps the OpenSSL library.} + spec.summary = %q{SSL/TLS and general-purpose cryptography for Ruby} + spec.description = %q{OpenSSL for Ruby provides access to SSL/TLS and general-purpose cryptography based on the OpenSSL library.} spec.homepage = "https://github.com/ruby/openssl" - spec.license = "Ruby" + spec.licenses = ["Ruby", "BSD-2-Clause"] if Gem::Platform === spec.platform and spec.platform =~ 'java' or RUBY_ENGINE == 'jruby' spec.platform = "java" spec.files = [] spec.add_runtime_dependency('jruby-openssl', '~> 0.14') else - spec.files = Dir["lib/**/*.rb", "ext/**/*.{c,h,rb}", "*.md", "BSDL", "LICENSE.txt"] + spec.files = Dir.glob(["lib/**/*.rb", "ext/**/*.{c,h,rb}", "*.md"], base: File.expand_path("..", __FILE__)) + + ["BSDL", "COPYING"] spec.require_paths = ["lib"] spec.extensions = ["ext/openssl/extconf.rb"] end diff --git a/ext/openssl/openssl_missing.c b/ext/openssl/openssl_missing.c deleted file mode 100644 index 4415703db4d072..00000000000000 --- a/ext/openssl/openssl_missing.c +++ /dev/null @@ -1,40 +0,0 @@ -/* - * 'OpenSSL for Ruby' project - * Copyright (C) 2001-2002 Michal Rokos - * All rights reserved. - */ -/* - * This program is licensed under the same licence as Ruby. - * (See the file 'LICENCE'.) - */ -#include RUBY_EXTCONF_H - -#include /* memcpy() */ -#include - -#include "openssl_missing.h" - -/*** added in 1.1.0 ***/ -#if !defined(HAVE_X509_CRL_GET0_SIGNATURE) -void -ossl_X509_CRL_get0_signature(const X509_CRL *crl, const ASN1_BIT_STRING **psig, - const X509_ALGOR **palg) -{ - if (psig != NULL) - *psig = crl->signature; - if (palg != NULL) - *palg = crl->sig_alg; -} -#endif - -#if !defined(HAVE_X509_REQ_GET0_SIGNATURE) -void -ossl_X509_REQ_get0_signature(const X509_REQ *req, const ASN1_BIT_STRING **psig, - const X509_ALGOR **palg) -{ - if (psig != NULL) - *psig = req->signature; - if (palg != NULL) - *palg = req->sig_alg; -} -#endif diff --git a/ext/openssl/openssl_missing.h b/ext/openssl/openssl_missing.h index 8629bfe505cb09..6592f9cceaf714 100644 --- a/ext/openssl/openssl_missing.h +++ b/ext/openssl/openssl_missing.h @@ -5,216 +5,14 @@ */ /* * This program is licensed under the same licence as Ruby. - * (See the file 'LICENCE'.) + * (See the file 'COPYING'.) */ #if !defined(_OSSL_OPENSSL_MISSING_H_) #define _OSSL_OPENSSL_MISSING_H_ #include "ruby/config.h" -/* added in 1.1.0 */ -#if !defined(HAVE_EVP_MD_CTX_NEW) -# define EVP_MD_CTX_new EVP_MD_CTX_create -#endif - -#if !defined(HAVE_EVP_MD_CTX_FREE) -# define EVP_MD_CTX_free EVP_MD_CTX_destroy -#endif - -#if !defined(HAVE_X509_STORE_GET_EX_DATA) -# define X509_STORE_get_ex_data(x, idx) \ - CRYPTO_get_ex_data(&(x)->ex_data, (idx)) -#endif - -#if !defined(HAVE_X509_STORE_SET_EX_DATA) -# define X509_STORE_set_ex_data(x, idx, data) \ - CRYPTO_set_ex_data(&(x)->ex_data, (idx), (data)) -#endif - -#if !defined(HAVE_X509_STORE_GET_EX_NEW_INDEX) && !defined(X509_STORE_get_ex_new_index) -# define X509_STORE_get_ex_new_index(l, p, newf, dupf, freef) \ - CRYPTO_get_ex_new_index(CRYPTO_EX_INDEX_X509_STORE, (l), (p), \ - (newf), (dupf), (freef)) -#endif - -#if !defined(HAVE_X509_CRL_GET0_SIGNATURE) -void ossl_X509_CRL_get0_signature(const X509_CRL *, const ASN1_BIT_STRING **, const X509_ALGOR **); -# define X509_CRL_get0_signature ossl_X509_CRL_get0_signature -#endif - -#if !defined(HAVE_X509_REQ_GET0_SIGNATURE) -void ossl_X509_REQ_get0_signature(const X509_REQ *, const ASN1_BIT_STRING **, const X509_ALGOR **); -# define X509_REQ_get0_signature ossl_X509_REQ_get0_signature -#endif - -#if !defined(HAVE_X509_REVOKED_GET0_SERIALNUMBER) -# define X509_REVOKED_get0_serialNumber(x) ((x)->serialNumber) -#endif - -#if !defined(HAVE_X509_REVOKED_GET0_REVOCATIONDATE) -# define X509_REVOKED_get0_revocationDate(x) ((x)->revocationDate) -#endif - -#if !defined(HAVE_X509_GET0_TBS_SIGALG) -# define X509_get0_tbs_sigalg(x) ((x)->cert_info->signature) -#endif - -#if !defined(HAVE_X509_STORE_CTX_GET0_UNTRUSTED) -# define X509_STORE_CTX_get0_untrusted(x) ((x)->untrusted) -#endif - -#if !defined(HAVE_X509_STORE_CTX_GET0_CERT) -# define X509_STORE_CTX_get0_cert(x) ((x)->cert) -#endif - -#if !defined(HAVE_X509_STORE_CTX_GET0_CHAIN) -# define X509_STORE_CTX_get0_chain(ctx) X509_STORE_CTX_get_chain(ctx) -#endif - -#if !defined(HAVE_OCSP_SINGLERESP_GET0_ID) -# define OCSP_SINGLERESP_get0_id(s) ((s)->certId) -#endif - -#if !defined(HAVE_SSL_CTX_GET_CIPHERS) -# define SSL_CTX_get_ciphers(ctx) ((ctx)->cipher_list) -#endif - -#if !defined(HAVE_X509_UP_REF) -# define X509_up_ref(x) \ - CRYPTO_add(&(x)->references, 1, CRYPTO_LOCK_X509) -#endif - -#if !defined(HAVE_X509_CRL_UP_REF) -# define X509_CRL_up_ref(x) \ - CRYPTO_add(&(x)->references, 1, CRYPTO_LOCK_X509_CRL); -#endif - -#if !defined(HAVE_X509_STORE_UP_REF) -# define X509_STORE_up_ref(x) \ - CRYPTO_add(&(x)->references, 1, CRYPTO_LOCK_X509_STORE); -#endif - -#if !defined(HAVE_SSL_SESSION_UP_REF) -# define SSL_SESSION_up_ref(x) \ - CRYPTO_add(&(x)->references, 1, CRYPTO_LOCK_SSL_SESSION); -#endif - -#if !defined(HAVE_EVP_PKEY_UP_REF) -# define EVP_PKEY_up_ref(x) \ - CRYPTO_add(&(x)->references, 1, CRYPTO_LOCK_EVP_PKEY); -#endif - -#if !defined(HAVE_OPAQUE_OPENSSL) -#define IMPL_PKEY_GETTER(_type, _name) \ -static inline _type *EVP_PKEY_get0_##_type(EVP_PKEY *pkey) { \ - return pkey->pkey._name; } -#define IMPL_KEY_ACCESSOR2(_type, _group, a1, a2, _fail_cond) \ -static inline void _type##_get0_##_group(const _type *obj, const BIGNUM **a1, const BIGNUM **a2) { \ - if (a1) *a1 = obj->a1; \ - if (a2) *a2 = obj->a2; } \ -static inline int _type##_set0_##_group(_type *obj, BIGNUM *a1, BIGNUM *a2) { \ - if (_fail_cond) return 0; \ - BN_clear_free(obj->a1); obj->a1 = a1; \ - BN_clear_free(obj->a2); obj->a2 = a2; \ - return 1; } -#define IMPL_KEY_ACCESSOR3(_type, _group, a1, a2, a3, _fail_cond) \ -static inline void _type##_get0_##_group(const _type *obj, const BIGNUM **a1, const BIGNUM **a2, const BIGNUM **a3) { \ - if (a1) *a1 = obj->a1; \ - if (a2) *a2 = obj->a2; \ - if (a3) *a3 = obj->a3; } \ -static inline int _type##_set0_##_group(_type *obj, BIGNUM *a1, BIGNUM *a2, BIGNUM *a3) { \ - if (_fail_cond) return 0; \ - BN_clear_free(obj->a1); obj->a1 = a1; \ - BN_clear_free(obj->a2); obj->a2 = a2; \ - BN_clear_free(obj->a3); obj->a3 = a3; \ - return 1; } - -#if !defined(OPENSSL_NO_RSA) -IMPL_PKEY_GETTER(RSA, rsa) -IMPL_KEY_ACCESSOR3(RSA, key, n, e, d, (n == obj->n || e == obj->e || (obj->d && d == obj->d))) -IMPL_KEY_ACCESSOR2(RSA, factors, p, q, (p == obj->p || q == obj->q)) -IMPL_KEY_ACCESSOR3(RSA, crt_params, dmp1, dmq1, iqmp, (dmp1 == obj->dmp1 || dmq1 == obj->dmq1 || iqmp == obj->iqmp)) -#endif - -#if !defined(OPENSSL_NO_DSA) -IMPL_PKEY_GETTER(DSA, dsa) -IMPL_KEY_ACCESSOR2(DSA, key, pub_key, priv_key, (pub_key == obj->pub_key || (obj->priv_key && priv_key == obj->priv_key))) -IMPL_KEY_ACCESSOR3(DSA, pqg, p, q, g, (p == obj->p || q == obj->q || g == obj->g)) -#endif - -#if !defined(OPENSSL_NO_DH) -IMPL_PKEY_GETTER(DH, dh) -IMPL_KEY_ACCESSOR2(DH, key, pub_key, priv_key, (pub_key == obj->pub_key || (obj->priv_key && priv_key == obj->priv_key))) -IMPL_KEY_ACCESSOR3(DH, pqg, p, q, g, (p == obj->p || (obj->q && q == obj->q) || g == obj->g)) -static inline ENGINE *DH_get0_engine(DH *dh) { return dh->engine; } -#endif - -#if !defined(OPENSSL_NO_EC) -IMPL_PKEY_GETTER(EC_KEY, ec) -#endif - -#undef IMPL_PKEY_GETTER -#undef IMPL_KEY_ACCESSOR2 -#undef IMPL_KEY_ACCESSOR3 -#endif /* HAVE_OPAQUE_OPENSSL */ - -#if !defined(EVP_CTRL_AEAD_GET_TAG) -# define EVP_CTRL_AEAD_GET_TAG EVP_CTRL_GCM_GET_TAG -# define EVP_CTRL_AEAD_SET_TAG EVP_CTRL_GCM_SET_TAG -# define EVP_CTRL_AEAD_SET_IVLEN EVP_CTRL_GCM_SET_IVLEN -#endif - -#if !defined(HAVE_X509_GET0_NOTBEFORE) -# define X509_get0_notBefore(x) X509_get_notBefore(x) -# define X509_get0_notAfter(x) X509_get_notAfter(x) -# define X509_CRL_get0_lastUpdate(x) X509_CRL_get_lastUpdate(x) -# define X509_CRL_get0_nextUpdate(x) X509_CRL_get_nextUpdate(x) -# define X509_set1_notBefore(x, t) X509_set_notBefore(x, t) -# define X509_set1_notAfter(x, t) X509_set_notAfter(x, t) -# define X509_CRL_set1_lastUpdate(x, t) X509_CRL_set_lastUpdate(x, t) -# define X509_CRL_set1_nextUpdate(x, t) X509_CRL_set_nextUpdate(x, t) -#endif - -#if !defined(HAVE_SSL_SESSION_GET_PROTOCOL_VERSION) -# define SSL_SESSION_get_protocol_version(s) ((s)->ssl_version) -#endif - -#if !defined(HAVE_TS_STATUS_INFO_GET0_STATUS) -# define TS_STATUS_INFO_get0_status(a) ((a)->status) -#endif - -#if !defined(HAVE_TS_STATUS_INFO_GET0_TEXT) -# define TS_STATUS_INFO_get0_text(a) ((a)->text) -#endif - -#if !defined(HAVE_TS_STATUS_INFO_GET0_FAILURE_INFO) -# define TS_STATUS_INFO_get0_failure_info(a) ((a)->failure_info) -#endif - -#if !defined(HAVE_TS_VERIFY_CTS_SET_CERTS) -# define TS_VERIFY_CTS_set_certs(ctx, crts) ((ctx)->certs=(crts)) -#endif - -#if !defined(HAVE_TS_VERIFY_CTX_SET_STORE) -# define TS_VERIFY_CTX_set_store(ctx, str) ((ctx)->store=(str)) -#endif - -#if !defined(HAVE_TS_VERIFY_CTX_ADD_FLAGS) -# define TS_VERIFY_CTX_add_flags(ctx, f) ((ctx)->flags |= (f)) -#endif - -#if !defined(HAVE_TS_RESP_CTX_SET_TIME_CB) -# define TS_RESP_CTX_set_time_cb(ctx, callback, dta) do { \ - (ctx)->time_cb = (callback); \ - (ctx)->time_cb_data = (dta); \ - } while (0) -#endif - /* added in 3.0.0 */ -#if !defined(HAVE_TS_VERIFY_CTX_SET_CERTS) -# define TS_VERIFY_CTX_set_certs(ctx, crts) TS_VERIFY_CTS_set_certs(ctx, crts) -#endif - #ifndef HAVE_EVP_MD_CTX_GET0_MD # define EVP_MD_CTX_get0_md(ctx) EVP_MD_CTX_md(ctx) #endif @@ -224,11 +22,7 @@ IMPL_PKEY_GETTER(EC_KEY, ec) * EVP_MD_CTX_get_pkey_ctx(x) in OpenSSL 3.0. */ #ifndef HAVE_EVP_MD_CTX_GET_PKEY_CTX -# ifdef HAVE_EVP_MD_CTX_PKEY_CTX # define EVP_MD_CTX_get_pkey_ctx(x) EVP_MD_CTX_pkey_ctx(x) -# else -# define EVP_MD_CTX_get_pkey_ctx(x) (x)->pctx -# endif #endif #ifndef HAVE_EVP_PKEY_EQ diff --git a/ext/openssl/ossl.c b/ext/openssl/ossl.c index 00eded55cb9ad6..60780790b02d1d 100644 --- a/ext/openssl/ossl.c +++ b/ext/openssl/ossl.c @@ -5,18 +5,11 @@ */ /* * This program is licensed under the same licence as Ruby. - * (See the file 'LICENCE'.) + * (See the file 'COPYING'.) */ #include "ossl.h" #include /* for ossl_raise */ -/* OpenSSL >= 1.1.0 and LibreSSL >= 2.9.0 */ -#if defined(LIBRESSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER >= 0x10100000 -# define HAVE_OPENSSL_110_THREADING_API -#else -# include -#endif - /* * Data Conversion */ @@ -76,16 +69,9 @@ ossl_##name##_sk2ary(const STACK_OF(type) *sk) \ int i, num; \ VALUE ary; \ \ - if (!sk) { \ - OSSL_Debug("empty sk!"); \ - return Qnil; \ - } \ + RUBY_ASSERT(sk != NULL); \ num = sk_##type##_num(sk); \ - if (num < 0) { \ - OSSL_Debug("items in sk < -1???"); \ - return rb_ary_new(); \ - } \ - ary = rb_ary_new2(num); \ + ary = rb_ary_new_capa(num); \ \ for (i=0; ilock); - l->count = 0; -} - -static void -ossl_lock_unlock(int mode, struct CRYPTO_dynlock_value *l) -{ - if (mode & CRYPTO_LOCK) { - /* TODO: rb_nativethread_id_t is not necessarily compared with ==. */ - rb_nativethread_id_t tid = rb_nativethread_self(); - if (l->count && l->owner == tid) { - l->count++; - return; - } - rb_nativethread_lock_lock(&l->lock); - l->owner = tid; - l->count = 1; - } else { - if (!--l->count) - rb_nativethread_lock_unlock(&l->lock); - } -} - -static struct CRYPTO_dynlock_value * -ossl_dyn_create_callback(const char *file, int line) -{ - /* Do not use xmalloc() here, since it may raise NoMemoryError */ - struct CRYPTO_dynlock_value *dynlock = - OPENSSL_malloc(sizeof(struct CRYPTO_dynlock_value)); - if (dynlock) - ossl_lock_init(dynlock); - return dynlock; -} - -static void -ossl_dyn_lock_callback(int mode, struct CRYPTO_dynlock_value *l, const char *file, int line) -{ - ossl_lock_unlock(mode, l); -} - -static void -ossl_dyn_destroy_callback(struct CRYPTO_dynlock_value *l, const char *file, int line) -{ - rb_nativethread_lock_destroy(&l->lock); - OPENSSL_free(l); -} - -static void ossl_threadid_func(CRYPTO_THREADID *id) -{ - /* register native thread id */ - CRYPTO_THREADID_set_pointer(id, (void *)rb_nativethread_self()); -} - -static struct CRYPTO_dynlock_value *ossl_locks; - -static void -ossl_lock_callback(int mode, int type, const char *file, int line) -{ - ossl_lock_unlock(mode, &ossl_locks[type]); -} - -static void Init_ossl_locks(void) -{ - int i; - int num_locks = CRYPTO_num_locks(); - - ossl_locks = ALLOC_N(struct CRYPTO_dynlock_value, num_locks); - for (i = 0; i < num_locks; i++) - ossl_lock_init(&ossl_locks[i]); - - CRYPTO_THREADID_set_callback(ossl_threadid_func); - CRYPTO_set_locking_callback(ossl_lock_callback); - CRYPTO_set_dynlock_create_callback(ossl_dyn_create_callback); - CRYPTO_set_dynlock_lock_callback(ossl_dyn_lock_callback); - CRYPTO_set_dynlock_destroy_callback(ossl_dyn_destroy_callback); -} -#endif /* !HAVE_OPENSSL_110_THREADING_API */ - /* * call-seq: * OpenSSL.fixed_length_secure_compare(string, string) -> boolean @@ -1050,15 +945,8 @@ Init_openssl(void) /* * Init all digests, ciphers */ -#if !defined(LIBRESSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000 if (!OPENSSL_init_ssl(0, NULL)) rb_raise(rb_eRuntimeError, "OPENSSL_init_ssl"); -#else - OpenSSL_add_ssl_algorithms(); - OpenSSL_add_all_algorithms(); - ERR_load_crypto_strings(); - SSL_load_error_strings(); -#endif /* * Init main module @@ -1075,11 +963,7 @@ Init_openssl(void) /* * Version of OpenSSL the ruby OpenSSL extension is running with */ -#if !defined(LIBRESSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000 rb_define_const(mOSSL, "OPENSSL_LIBRARY_VERSION", rb_str_new2(OpenSSL_version(OPENSSL_VERSION))); -#else - rb_define_const(mOSSL, "OPENSSL_LIBRARY_VERSION", rb_str_new2(SSLeay_version(SSLEAY_VERSION))); -#endif /* * Version number of OpenSSL the ruby OpenSSL extension was built with @@ -1113,6 +997,8 @@ Init_openssl(void) Qtrue #elif defined(OPENSSL_FIPS) Qtrue +#elif defined(OPENSSL_IS_AWSLC) // AWS-LC FIPS can only be enabled during compile time. + FIPS_mode() ? Qtrue : Qfalse #else Qfalse #endif @@ -1143,31 +1029,25 @@ Init_openssl(void) */ ossl_s_to_der = rb_intern("to_der"); -#if !defined(HAVE_OPENSSL_110_THREADING_API) - Init_ossl_locks(); -#endif - /* * Init components */ + Init_ossl_asn1(); Init_ossl_bn(); Init_ossl_cipher(); Init_ossl_config(); Init_ossl_digest(); + Init_ossl_engine(); Init_ossl_hmac(); + Init_ossl_kdf(); Init_ossl_ns_spki(); + Init_ossl_ocsp(); Init_ossl_pkcs12(); Init_ossl_pkcs7(); Init_ossl_pkey(); + Init_ossl_provider(); Init_ossl_rand(); Init_ossl_ssl(); -#ifndef OPENSSL_NO_TS Init_ossl_ts(); -#endif Init_ossl_x509(); - Init_ossl_ocsp(); - Init_ossl_engine(); - Init_ossl_provider(); - Init_ossl_asn1(); - Init_ossl_kdf(); } diff --git a/ext/openssl/ossl.h b/ext/openssl/ossl.h index 68d42b71e2285e..22471d2085fa69 100644 --- a/ext/openssl/ossl.h +++ b/ext/openssl/ossl.h @@ -5,7 +5,7 @@ */ /* * This program is licensed under the same licence as Ruby. - * (See the file 'LICENCE'.) + * (See the file 'COPYING'.) */ #if !defined(_OSSL_H_) #define _OSSL_H_ @@ -17,6 +17,12 @@ #include #include #include +#ifdef HAVE_RUBY_RACTOR_H +#include +#else +#define RUBY_TYPED_FROZEN_SHAREABLE 0 +#endif + #include #include @@ -39,6 +45,7 @@ #include #include #include +#include "openssl_missing.h" #ifndef LIBRESSL_VERSION_NUMBER # define OSSL_IS_LIBRESSL 0 @@ -64,6 +71,7 @@ #if OSSL_OPENSSL_PREREQ(3, 0, 0) # define OSSL_USE_PROVIDER +# include #endif /* @@ -172,28 +180,25 @@ extern VALUE dOSSL; /* * Include all parts */ -#include "openssl_missing.h" #include "ossl_asn1.h" #include "ossl_bio.h" #include "ossl_bn.h" #include "ossl_cipher.h" #include "ossl_config.h" #include "ossl_digest.h" +#include "ossl_engine.h" #include "ossl_hmac.h" +#include "ossl_kdf.h" #include "ossl_ns_spki.h" #include "ossl_ocsp.h" #include "ossl_pkcs12.h" #include "ossl_pkcs7.h" #include "ossl_pkey.h" +#include "ossl_provider.h" #include "ossl_rand.h" #include "ossl_ssl.h" -#ifndef OPENSSL_NO_TS - #include "ossl_ts.h" -#endif +#include "ossl_ts.h" #include "ossl_x509.h" -#include "ossl_engine.h" -#include "ossl_provider.h" -#include "ossl_kdf.h" void Init_openssl(void); diff --git a/ext/openssl/ossl_asn1.c b/ext/openssl/ossl_asn1.c index 71c452c88af26f..186679da4c6b55 100644 --- a/ext/openssl/ossl_asn1.c +++ b/ext/openssl/ossl_asn1.c @@ -5,13 +5,12 @@ */ /* * This program is licensed under the same licence as Ruby. - * (See the file 'LICENCE'.) + * (See the file 'COPYING'.) */ #include "ossl.h" static VALUE ossl_asn1_decode0(unsigned char **pp, long length, long *offset, int depth, int yield, long *num_read); -static VALUE ossl_asn1_initialize(int argc, VALUE *argv, VALUE self); /* * DATE conversion @@ -37,7 +36,7 @@ asn1time_to_time(const ASN1_TIME *time) ossl_raise(rb_eTypeError, "bad UTCTIME format: \"%s\"", time->data); } - if (tm.tm_year < 69) { + if (tm.tm_year < 50) { tm.tm_year += 2000; } else { tm.tm_year += 1900; @@ -158,38 +157,33 @@ asn1integer_to_num_i(VALUE arg) #define ossl_asn1_get_tag_class(o) rb_attr_get((o),sivTAG_CLASS) #define ossl_asn1_get_indefinite_length(o) rb_attr_get((o),sivINDEFINITE_LENGTH) -#define ossl_asn1_set_value(o,v) rb_ivar_set((o),sivVALUE,(v)) -#define ossl_asn1_set_tag(o,v) rb_ivar_set((o),sivTAG,(v)) -#define ossl_asn1_set_tagging(o,v) rb_ivar_set((o),sivTAGGING,(v)) -#define ossl_asn1_set_tag_class(o,v) rb_ivar_set((o),sivTAG_CLASS,(v)) #define ossl_asn1_set_indefinite_length(o,v) rb_ivar_set((o),sivINDEFINITE_LENGTH,(v)) VALUE mASN1; VALUE eASN1Error; VALUE cASN1Data; -VALUE cASN1Primitive; -VALUE cASN1Constructive; - -VALUE cASN1EndOfContent; -VALUE cASN1Boolean; /* BOOLEAN */ -VALUE cASN1Integer, cASN1Enumerated; /* INTEGER */ -VALUE cASN1BitString; /* BIT STRING */ -VALUE cASN1OctetString, cASN1UTF8String; /* STRINGs */ -VALUE cASN1NumericString, cASN1PrintableString; -VALUE cASN1T61String, cASN1VideotexString; -VALUE cASN1IA5String, cASN1GraphicString; -VALUE cASN1ISO64String, cASN1GeneralString; -VALUE cASN1UniversalString, cASN1BMPString; -VALUE cASN1Null; /* NULL */ -VALUE cASN1ObjectId; /* OBJECT IDENTIFIER */ -VALUE cASN1UTCTime, cASN1GeneralizedTime; /* TIME */ -VALUE cASN1Sequence, cASN1Set; /* CONSTRUCTIVE */ +static VALUE cASN1Primitive; +static VALUE cASN1Constructive; + +static VALUE cASN1EndOfContent; +static VALUE cASN1Boolean; /* BOOLEAN */ +static VALUE cASN1Integer, cASN1Enumerated; /* INTEGER */ +static VALUE cASN1BitString; /* BIT STRING */ +static VALUE cASN1OctetString, cASN1UTF8String; /* STRINGs */ +static VALUE cASN1NumericString, cASN1PrintableString; +static VALUE cASN1T61String, cASN1VideotexString; +static VALUE cASN1IA5String, cASN1GraphicString; +static VALUE cASN1ISO64String, cASN1GeneralString; +static VALUE cASN1UniversalString, cASN1BMPString; +static VALUE cASN1Null; /* NULL */ +static VALUE cASN1ObjectId; /* OBJECT IDENTIFIER */ +static VALUE cASN1UTCTime, cASN1GeneralizedTime; /* TIME */ +static VALUE cASN1Sequence, cASN1Set; /* CONSTRUCTIVE */ static VALUE sym_IMPLICIT, sym_EXPLICIT; static VALUE sym_UNIVERSAL, sym_APPLICATION, sym_CONTEXT_SPECIFIC, sym_PRIVATE; static ID sivVALUE, sivTAG, sivTAG_CLASS, sivTAGGING, sivINDEFINITE_LENGTH, sivUNUSED_BITS; -static ID id_each; /* * Ruby to ASN1 converters @@ -503,7 +497,7 @@ static VALUE class_tag_map; static int ossl_asn1_default_tag(VALUE obj); -ASN1_TYPE* +static ASN1_TYPE * ossl_asn1_get_asn1type(VALUE obj) { ASN1_TYPE *ret; @@ -638,35 +632,6 @@ ossl_asn1_class2sym(int tc) return sym_UNIVERSAL; } -/* - * call-seq: - * OpenSSL::ASN1::ASN1Data.new(value, tag, tag_class) => ASN1Data - * - * _value_: Please have a look at Constructive and Primitive to see how Ruby - * types are mapped to ASN.1 types and vice versa. - * - * _tag_: An Integer indicating the tag number. - * - * _tag_class_: A Symbol indicating the tag class. Please cf. ASN1 for - * possible values. - * - * == Example - * asn1_int = OpenSSL::ASN1Data.new(42, 2, :UNIVERSAL) # => Same as OpenSSL::ASN1::Integer.new(42) - * tagged_int = OpenSSL::ASN1Data.new(42, 0, :CONTEXT_SPECIFIC) # implicitly 0-tagged INTEGER - */ -static VALUE -ossl_asn1data_initialize(VALUE self, VALUE value, VALUE tag, VALUE tag_class) -{ - if(!SYMBOL_P(tag_class)) - ossl_raise(eASN1Error, "invalid tag class"); - ossl_asn1_set_tag(self, tag); - ossl_asn1_set_value(self, value); - ossl_asn1_set_tag_class(self, tag_class); - ossl_asn1_set_indefinite_length(self, Qfalse); - - return self; -} - static VALUE to_der_internal(VALUE self, int constructed, int indef_len, VALUE body) { @@ -795,20 +760,19 @@ int_ossl_asn1_decode0_prim(unsigned char **pp, long length, long hlen, int tag, if (tc == sym_UNIVERSAL && tag < ossl_asn1_info_size && ossl_asn1_info[tag].klass) { VALUE klass = *ossl_asn1_info[tag].klass; - VALUE args[4]; - args[0] = value; - args[1] = INT2NUM(tag); - args[2] = Qnil; - args[3] = tc; - asn1data = rb_obj_alloc(klass); - ossl_asn1_initialize(4, args, asn1data); + if (tag == V_ASN1_EOC) + asn1data = rb_funcall(cASN1EndOfContent, rb_intern("new"), 0); + else { + VALUE args[4] = { value, INT2NUM(tag), Qnil, tc }; + asn1data = rb_funcallv_public(klass, rb_intern("new"), 4, args); + } if(tag == V_ASN1_BIT_STRING){ rb_ivar_set(asn1data, sivUNUSED_BITS, LONG2NUM(flag)); } } else { - asn1data = rb_obj_alloc(cASN1Data); - ossl_asn1data_initialize(asn1data, value, INT2NUM(tag), tc); + VALUE args[3] = { value, INT2NUM(tag), tc }; + asn1data = rb_funcallv_public(cASN1Data, rb_intern("new"), 3, args); } return asn1data; @@ -833,29 +797,31 @@ int_ossl_asn1_decode0_cons(unsigned char **pp, long max_len, long length, *num_read += inner_read; available_len -= inner_read; - if (indefinite && - ossl_asn1_tag(value) == V_ASN1_EOC && - ossl_asn1_get_tag_class(value) == sym_UNIVERSAL) { - break; + if (indefinite) { + if (ossl_asn1_tag(value) == V_ASN1_EOC && + ossl_asn1_get_tag_class(value) == sym_UNIVERSAL) + break; + if (available_len == 0) + ossl_raise(eASN1Error, "EOC missing in indefinite length encoding"); } rb_ary_push(ary, value); } if (tc == sym_UNIVERSAL) { - VALUE args[4]; - if (tag == V_ASN1_SEQUENCE || tag == V_ASN1_SET) - asn1data = rb_obj_alloc(*ossl_asn1_info[tag].klass); - else - asn1data = rb_obj_alloc(cASN1Constructive); - args[0] = ary; - args[1] = INT2NUM(tag); - args[2] = Qnil; - args[3] = tc; - ossl_asn1_initialize(4, args, asn1data); + if (tag == V_ASN1_SEQUENCE) { + VALUE args[4] = { ary, INT2NUM(tag), Qnil, tc }; + asn1data = rb_funcallv_public(cASN1Sequence, rb_intern("new"), 4, args); + } else if (tag == V_ASN1_SET) { + VALUE args[4] = { ary, INT2NUM(tag), Qnil, tc }; + asn1data = rb_funcallv_public(cASN1Set, rb_intern("new"), 4, args); + } else { + VALUE args[4] = { ary, INT2NUM(tag), Qnil, tc }; + asn1data = rb_funcallv_public(cASN1Constructive, rb_intern("new"), 4, args); + } } else { - asn1data = rb_obj_alloc(cASN1Data); - ossl_asn1data_initialize(asn1data, ary, INT2NUM(tag), tc); + VALUE args[3] = {ary, INT2NUM(tag), tc}; + asn1data = rb_funcallv_public(cASN1Data, rb_intern("new"), 3, args); } if (indefinite) @@ -1048,83 +1014,6 @@ ossl_asn1_decode_all(VALUE self, VALUE obj) return ary; } -/* - * call-seq: - * OpenSSL::ASN1::Primitive.new(value [, tag, tagging, tag_class ]) => Primitive - * - * _value_: is mandatory. - * - * _tag_: optional, may be specified for tagged values. If no _tag_ is - * specified, the UNIVERSAL tag corresponding to the Primitive sub-class - * is used by default. - * - * _tagging_: may be used as an encoding hint to encode a value either - * explicitly or implicitly, see ASN1 for possible values. - * - * _tag_class_: if _tag_ and _tagging_ are +nil+ then this is set to - * +:UNIVERSAL+ by default. If either _tag_ or _tagging_ are set then - * +:CONTEXT_SPECIFIC+ is used as the default. For possible values please - * cf. ASN1. - * - * == Example - * int = OpenSSL::ASN1::Integer.new(42) - * zero_tagged_int = OpenSSL::ASN1::Integer.new(42, 0, :IMPLICIT) - * private_explicit_zero_tagged_int = OpenSSL::ASN1::Integer.new(42, 0, :EXPLICIT, :PRIVATE) - */ -static VALUE -ossl_asn1_initialize(int argc, VALUE *argv, VALUE self) -{ - VALUE value, tag, tagging, tag_class; - int default_tag; - - rb_scan_args(argc, argv, "13", &value, &tag, &tagging, &tag_class); - default_tag = ossl_asn1_default_tag(self); - - if (default_tag == -1 || argc > 1) { - if(NIL_P(tag)) - ossl_raise(eASN1Error, "must specify tag number"); - if(!NIL_P(tagging) && !SYMBOL_P(tagging)) - ossl_raise(eASN1Error, "invalid tagging method"); - if(NIL_P(tag_class)) { - if (NIL_P(tagging)) - tag_class = sym_UNIVERSAL; - else - tag_class = sym_CONTEXT_SPECIFIC; - } - if(!SYMBOL_P(tag_class)) - ossl_raise(eASN1Error, "invalid tag class"); - } - else{ - tag = INT2NUM(default_tag); - tagging = Qnil; - tag_class = sym_UNIVERSAL; - } - ossl_asn1_set_tag(self, tag); - ossl_asn1_set_value(self, value); - ossl_asn1_set_tagging(self, tagging); - ossl_asn1_set_tag_class(self, tag_class); - ossl_asn1_set_indefinite_length(self, Qfalse); - if (default_tag == V_ASN1_BIT_STRING) - rb_ivar_set(self, sivUNUSED_BITS, INT2FIX(0)); - - return self; -} - -static VALUE -ossl_asn1eoc_initialize(VALUE self) { - VALUE tag, tagging, tag_class, value; - tag = INT2FIX(0); - tagging = Qnil; - tag_class = sym_UNIVERSAL; - value = rb_str_new("", 0); - ossl_asn1_set_tag(self, tag); - ossl_asn1_set_value(self, value); - ossl_asn1_set_tagging(self, tagging); - ossl_asn1_set_tag_class(self, tag_class); - ossl_asn1_set_indefinite_length(self, Qfalse); - return self; -} - static VALUE ossl_asn1eoc_to_der(VALUE self) { @@ -1163,9 +1052,12 @@ ossl_asn1prim_to_der(VALUE self) rb_jump_tag(state); } p0 = p1 = (unsigned char *)RSTRING_PTR(str); - i2d_ASN1_TYPE(asn1, &p0); + if (i2d_ASN1_TYPE(asn1, &p0) < 0) { + ASN1_TYPE_free(asn1); + ossl_raise(eASN1Error, "i2d_ASN1_TYPE"); + } ASN1_TYPE_free(asn1); - assert(p0 - p1 == alllen); + ossl_str_adjust(str, p0); /* Strip header since to_der_internal() wants only the payload */ j = ASN1_get_object((const unsigned char **)&p1, &bodylen, &tag, &tc, alllen); @@ -1213,27 +1105,6 @@ ossl_asn1cons_to_der(VALUE self) return to_der_internal(self, 1, indef_len, str); } -/* - * call-seq: - * asn1_ary.each { |asn1| block } => asn1_ary - * - * Calls the given block once for each element in self, passing that element - * as parameter _asn1_. If no block is given, an enumerator is returned - * instead. - * - * == Example - * asn1_ary.each do |asn1| - * puts asn1 - * end - */ -static VALUE -ossl_asn1cons_each(VALUE self) -{ - rb_block_call(ossl_asn1_get_value(self), id_each, 0, 0, 0, 0); - - return self; -} - /* * call-seq: * OpenSSL::ASN1::ObjectId.register(object_id, short_name, long_name) @@ -1298,30 +1169,6 @@ ossl_asn1obj_get_ln(VALUE self) return ret; } -/* - * call-seq: - * oid == other_oid => true or false - * - * Returns +true+ if _other_oid_ is the same as _oid_ - */ -static VALUE -ossl_asn1obj_eq(VALUE self, VALUE other) -{ - VALUE valSelf, valOther; - int nidSelf, nidOther; - - valSelf = ossl_asn1_get_value(self); - valOther = ossl_asn1_get_value(other); - - if ((nidSelf = OBJ_txt2nid(StringValueCStr(valSelf))) == NID_undef) - ossl_raise(eASN1Error, "OBJ_txt2nid"); - - if ((nidOther = OBJ_txt2nid(StringValueCStr(valOther))) == NID_undef) - ossl_raise(eASN1Error, "OBJ_txt2nid"); - - return nidSelf == nidOther ? Qtrue : Qfalse; -} - static VALUE asn1obj_get_oid_i(VALUE vobj) { @@ -1366,9 +1213,28 @@ ossl_asn1obj_get_oid(VALUE self) return str; } +/* + * call-seq: + * oid == other_oid => true or false + * + * Returns +true+ if _other_oid_ is the same as _oid_. + */ +static VALUE +ossl_asn1obj_eq(VALUE self, VALUE other) +{ + VALUE oid1, oid2; + + if (!rb_obj_is_kind_of(other, cASN1ObjectId)) + return Qfalse; + + oid1 = ossl_asn1obj_get_oid(self); + oid2 = ossl_asn1obj_get_oid(other); + return rb_str_equal(oid1, oid2); +} + #define OSSL_ASN1_IMPL_FACTORY_METHOD(klass) \ static VALUE ossl_asn1_##klass(int argc, VALUE *argv, VALUE self)\ -{ return rb_funcall3(cASN1##klass, rb_intern("new"), argc, argv); } +{ return rb_funcallv_public(cASN1##klass, rb_intern("new"), argc, argv); } OSSL_ASN1_IMPL_FACTORY_METHOD(Boolean) OSSL_ASN1_IMPL_FACTORY_METHOD(Integer) @@ -1654,42 +1520,6 @@ Init_ossl_asn1(void) * puts int2.value # => 1 */ cASN1Data = rb_define_class_under(mASN1, "ASN1Data", rb_cObject); - /* - * Carries the value of a ASN.1 type. - * Please confer Constructive and Primitive for the mappings between - * ASN.1 data types and Ruby classes. - */ - rb_attr(cASN1Data, rb_intern("value"), 1, 1, 0); - /* - * An Integer representing the tag number of this ASN1Data. Never +nil+. - */ - rb_attr(cASN1Data, rb_intern("tag"), 1, 1, 0); - /* - * A Symbol representing the tag class of this ASN1Data. Never +nil+. - * See ASN1Data for possible values. - */ - rb_attr(cASN1Data, rb_intern("tag_class"), 1, 1, 0); - /* - * Never +nil+. A boolean value indicating whether the encoding uses - * indefinite length (in the case of parsing) or whether an indefinite - * length form shall be used (in the encoding case). - * In DER, every value uses definite length form. But in scenarios where - * large amounts of data need to be transferred it might be desirable to - * have some kind of streaming support available. - * For example, huge OCTET STRINGs are preferably sent in smaller-sized - * chunks, each at a time. - * This is possible in BER by setting the length bytes of an encoding - * to zero and by this indicating that the following value will be - * sent in chunks. Indefinite length encodings are always constructed. - * The end of such a stream of chunks is indicated by sending a EOC - * (End of Content) tag. SETs and SEQUENCEs may use an indefinite length - * encoding, but also primitive types such as e.g. OCTET STRINGS or - * BIT STRINGS may leverage this functionality (cf. ITU-T X.690). - */ - rb_attr(cASN1Data, rb_intern("indefinite_length"), 1, 1, 0); - rb_define_alias(cASN1Data, "infinite_length", "indefinite_length"); - rb_define_alias(cASN1Data, "infinite_length=", "indefinite_length="); - rb_define_method(cASN1Data, "initialize", ossl_asn1data_initialize, 3); rb_define_method(cASN1Data, "to_der", ossl_asn1data_to_der, 0); /* Document-class: OpenSSL::ASN1::Primitive @@ -1757,16 +1587,6 @@ Init_ossl_asn1(void) * prim_zero_tagged_explicit = .new(value, 0, :EXPLICIT) */ cASN1Primitive = rb_define_class_under(mASN1, "Primitive", cASN1Data); - /* - * May be used as a hint for encoding a value either implicitly or - * explicitly by setting it either to +:IMPLICIT+ or to +:EXPLICIT+. - * _tagging_ is not set when a ASN.1 structure is parsed using - * OpenSSL::ASN1.decode. - */ - rb_attr(cASN1Primitive, rb_intern("tagging"), 1, 1, Qtrue); - rb_undef_method(cASN1Primitive, "indefinite_length="); - rb_undef_method(cASN1Primitive, "infinite_length="); - rb_define_method(cASN1Primitive, "initialize", ossl_asn1_initialize, -1); rb_define_method(cASN1Primitive, "to_der", ossl_asn1prim_to_der, 0); /* Document-class: OpenSSL::ASN1::Constructive @@ -1797,17 +1617,7 @@ Init_ossl_asn1(void) * set = OpenSSL::ASN1::Set.new( [ int, str ] ) */ cASN1Constructive = rb_define_class_under(mASN1,"Constructive", cASN1Data); - rb_include_module(cASN1Constructive, rb_mEnumerable); - /* - * May be used as a hint for encoding a value either implicitly or - * explicitly by setting it either to +:IMPLICIT+ or to +:EXPLICIT+. - * _tagging_ is not set when a ASN.1 structure is parsed using - * OpenSSL::ASN1.decode. - */ - rb_attr(cASN1Constructive, rb_intern("tagging"), 1, 1, Qtrue); - rb_define_method(cASN1Constructive, "initialize", ossl_asn1_initialize, -1); rb_define_method(cASN1Constructive, "to_der", ossl_asn1cons_to_der, 0); - rb_define_method(cASN1Constructive, "each", ossl_asn1cons_each, 0); #define OSSL_ASN1_DEFINE_CLASS(name, super) \ do{\ @@ -1856,13 +1666,10 @@ do{\ rb_define_alias(cASN1ObjectId, "short_name", "sn"); rb_define_alias(cASN1ObjectId, "long_name", "ln"); rb_define_method(cASN1ObjectId, "==", ossl_asn1obj_eq, 1); - rb_attr(cASN1BitString, rb_intern("unused_bits"), 1, 1, 0); - rb_define_method(cASN1EndOfContent, "initialize", ossl_asn1eoc_initialize, 0); rb_define_method(cASN1EndOfContent, "to_der", ossl_asn1eoc_to_der, 0); class_tag_map = rb_hash_new(); - rb_gc_register_mark_object(class_tag_map); rb_hash_aset(class_tag_map, cASN1EndOfContent, INT2NUM(V_ASN1_EOC)); rb_hash_aset(class_tag_map, cASN1Boolean, INT2NUM(V_ASN1_BOOLEAN)); rb_hash_aset(class_tag_map, cASN1Integer, INT2NUM(V_ASN1_INTEGER)); @@ -1886,6 +1693,5 @@ do{\ rb_hash_aset(class_tag_map, cASN1GeneralString, INT2NUM(V_ASN1_GENERALSTRING)); rb_hash_aset(class_tag_map, cASN1UniversalString, INT2NUM(V_ASN1_UNIVERSALSTRING)); rb_hash_aset(class_tag_map, cASN1BMPString, INT2NUM(V_ASN1_BMPSTRING)); - - id_each = rb_intern_const("each"); + rb_define_const(mASN1, "CLASS_TAG_MAP", class_tag_map); } diff --git a/ext/openssl/ossl_asn1.h b/ext/openssl/ossl_asn1.h index 939a96ce7483c0..3b689c0ee7ded5 100644 --- a/ext/openssl/ossl_asn1.h +++ b/ext/openssl/ossl_asn1.h @@ -5,7 +5,7 @@ */ /* * This program is licensed under the same licence as Ruby. - * (See the file 'LICENCE'.) + * (See the file 'COPYING'.) */ #if !defined(_OSSL_ASN1_H_) #define _OSSL_ASN1_H_ @@ -38,24 +38,6 @@ extern VALUE mASN1; extern VALUE eASN1Error; extern VALUE cASN1Data; -extern VALUE cASN1Primitive; -extern VALUE cASN1Constructive; - -extern VALUE cASN1Boolean; /* BOOLEAN */ -extern VALUE cASN1Integer, cASN1Enumerated; /* INTEGER */ -extern VALUE cASN1BitString; /* BIT STRING */ -extern VALUE cASN1OctetString, cASN1UTF8String; /* STRINGs */ -extern VALUE cASN1NumericString, cASN1PrintableString; -extern VALUE cASN1T61String, cASN1VideotexString; -extern VALUE cASN1IA5String, cASN1GraphicString; -extern VALUE cASN1ISO64String, cASN1GeneralString; -extern VALUE cASN1UniversalString, cASN1BMPString; -extern VALUE cASN1Null; /* NULL */ -extern VALUE cASN1ObjectId; /* OBJECT IDENTIFIER */ -extern VALUE cASN1UTCTime, cASN1GeneralizedTime; /* TIME */ -extern VALUE cASN1Sequence, cASN1Set; /* CONSTRUCTIVE */ - -ASN1_TYPE *ossl_asn1_get_asn1type(VALUE); void Init_ossl_asn1(void); diff --git a/ext/openssl/ossl_bio.c b/ext/openssl/ossl_bio.c index 42833d901acffa..2ef2080507b709 100644 --- a/ext/openssl/ossl_bio.c +++ b/ext/openssl/ossl_bio.c @@ -5,7 +5,7 @@ */ /* * This program is licensed under the same licence as Ruby. - * (See the file 'LICENCE'.) + * (See the file 'COPYING'.) */ #include "ossl.h" diff --git a/ext/openssl/ossl_bio.h b/ext/openssl/ossl_bio.h index da68c5e5a29f13..1b871f1cd7ab0c 100644 --- a/ext/openssl/ossl_bio.h +++ b/ext/openssl/ossl_bio.h @@ -5,7 +5,7 @@ */ /* * This program is licensed under the same licence as Ruby. - * (See the file 'LICENCE'.) + * (See the file 'COPYING'.) */ #if !defined(_OSSL_BIO_H_) #define _OSSL_BIO_H_ diff --git a/ext/openssl/ossl_bn.c b/ext/openssl/ossl_bn.c index ce0d3ec7eed144..8699ce8ec5665b 100644 --- a/ext/openssl/ossl_bn.c +++ b/ext/openssl/ossl_bn.c @@ -5,15 +5,11 @@ */ /* * This program is licensed under the same licence as Ruby. - * (See the file 'LICENCE'.) + * (See the file 'COPYING'.) */ /* modified by Michal Rokos */ #include "ossl.h" -#ifdef HAVE_RB_EXT_RACTOR_SAFE -#include -#endif - #define NewBN(klass) \ TypedData_Wrap_Struct((klass), &ossl_bn_type, 0) #define SetBN(obj, bn) do { \ @@ -41,7 +37,7 @@ static const rb_data_type_t ossl_bn_type = { { 0, ossl_bn_free, }, - 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED, + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FROZEN_SHAREABLE, }; /* @@ -53,7 +49,7 @@ VALUE cBN; * * Generic Error for all of OpenSSL::BN (big num) */ -VALUE eBNError; +static VALUE eBNError; /* * Public @@ -156,19 +152,19 @@ ossl_bn_value_ptr(volatile VALUE *ptr) */ #ifdef HAVE_RB_EXT_RACTOR_SAFE -void +static void ossl_bn_ctx_free(void *ptr) { BN_CTX *ctx = (BN_CTX *)ptr; BN_CTX_free(ctx); } -struct rb_ractor_local_storage_type ossl_bn_ctx_key_type = { +static struct rb_ractor_local_storage_type ossl_bn_ctx_key_type = { NULL, // mark ossl_bn_ctx_free, }; -rb_ractor_local_key_t ossl_bn_ctx_key; +static rb_ractor_local_key_t ossl_bn_ctx_key; BN_CTX * ossl_bn_ctx_get(void) @@ -244,7 +240,7 @@ ossl_bn_alloc(VALUE klass) * number. * - +10+ - Decimal number representation, with a leading '-' for a negative * number. - * - +16+ - Hexadeciaml number representation, with a leading '-' for a + * - +16+ - Hexadecimal number representation, with a leading '-' for a * negative number. */ static VALUE @@ -263,6 +259,7 @@ ossl_bn_initialize(int argc, VALUE *argv, VALUE self) ossl_raise(rb_eArgError, "invalid argument"); } + rb_check_frozen(self); if (RB_INTEGER_TYPE_P(str)) { GetBN(self, bn); integer_to_bnptr(str, bn); @@ -326,7 +323,7 @@ ossl_bn_initialize(int argc, VALUE *argv, VALUE self) * the bignum is ignored. * - +10+ - Decimal number representation, with a leading '-' for a negative * bignum. - * - +16+ - Hexadeciaml number representation, with a leading '-' for a + * - +16+ - Hexadecimal number representation, with a leading '-' for a * negative bignum. */ static VALUE @@ -693,6 +690,7 @@ BIGNUM_3c(mod_exp) ossl_bn_##func(VALUE self, VALUE bit) \ { \ BIGNUM *bn; \ + rb_check_frozen(self); \ GetBN(self, bn); \ if (BN_##func(bn, NUM2INT(bit)) <= 0) { \ ossl_raise(eBNError, NULL); \ @@ -782,6 +780,7 @@ BIGNUM_SHIFT(rshift) { \ BIGNUM *bn; \ int b; \ + rb_check_frozen(self); \ b = NUM2INT(bits); \ GetBN(self, bn); \ if (BN_##func(bn, bn, b) <= 0) \ @@ -930,6 +929,7 @@ BIGNUM_NUM(num_bytes) */ BIGNUM_NUM(num_bits) +/* :nodoc: */ static VALUE ossl_bn_copy(VALUE self, VALUE other) { @@ -1191,6 +1191,7 @@ ossl_bn_set_flags(VALUE self, VALUE arg) BIGNUM *bn; GetBN(self, bn); + rb_check_frozen(self); BN_set_flags(bn, NUM2INT(arg)); return Qnil; } diff --git a/ext/openssl/ossl_bn.h b/ext/openssl/ossl_bn.h index 1cc041fc22faff..0c186bd1c5dd1f 100644 --- a/ext/openssl/ossl_bn.h +++ b/ext/openssl/ossl_bn.h @@ -5,13 +5,12 @@ */ /* * This program is licensed under the same licence as Ruby. - * (See the file 'LICENCE'.) + * (See the file 'COPYING'.) */ #if !defined(_OSSL_BN_H_) #define _OSSL_BN_H_ extern VALUE cBN; -extern VALUE eBNError; BN_CTX *ossl_bn_ctx_get(void); #define ossl_bn_ctx ossl_bn_ctx_get() diff --git a/ext/openssl/ossl_cipher.c b/ext/openssl/ossl_cipher.c index 110610e1f920a4..07e651335d53e1 100644 --- a/ext/openssl/ossl_cipher.c +++ b/ext/openssl/ossl_cipher.c @@ -5,7 +5,7 @@ */ /* * This program is licensed under the same licence as Ruby. - * (See the file 'LICENCE'.) + * (See the file 'COPYING'.) */ #include "ossl.h" @@ -30,8 +30,8 @@ /* * Classes */ -VALUE cCipher; -VALUE eCipherError; +static VALUE cCipher; +static VALUE eCipherError; static ID id_auth_tag_len, id_key_set; static VALUE ossl_cipher_alloc(VALUE klass); @@ -130,6 +130,7 @@ ossl_cipher_initialize(VALUE self, VALUE str) return self; } +/* :nodoc: */ static VALUE ossl_cipher_copy(VALUE self, VALUE other) { @@ -197,47 +198,16 @@ ossl_cipher_reset(VALUE self) } static VALUE -ossl_cipher_init(int argc, VALUE *argv, VALUE self, int mode) +ossl_cipher_init(VALUE self, int enc) { EVP_CIPHER_CTX *ctx; - unsigned char key[EVP_MAX_KEY_LENGTH], *p_key = NULL; - unsigned char iv[EVP_MAX_IV_LENGTH], *p_iv = NULL; - VALUE pass, init_v; - - if(rb_scan_args(argc, argv, "02", &pass, &init_v) > 0){ - /* - * oops. this code mistakes salt for IV. - * We deprecated the arguments for this method, but we decided - * keeping this behaviour for backward compatibility. - */ - VALUE cname = rb_class_path(rb_obj_class(self)); - rb_warn("arguments for %"PRIsVALUE"#encrypt and %"PRIsVALUE"#decrypt were deprecated; " - "use %"PRIsVALUE"#pkcs5_keyivgen to derive key and IV", - cname, cname, cname); - StringValue(pass); - GetCipher(self, ctx); - if (NIL_P(init_v)) memcpy(iv, "OpenSSL for Ruby rulez!", sizeof(iv)); - else{ - StringValue(init_v); - if (EVP_MAX_IV_LENGTH > RSTRING_LEN(init_v)) { - memset(iv, 0, EVP_MAX_IV_LENGTH); - memcpy(iv, RSTRING_PTR(init_v), RSTRING_LEN(init_v)); - } - else memcpy(iv, RSTRING_PTR(init_v), sizeof(iv)); - } - EVP_BytesToKey(EVP_CIPHER_CTX_cipher(ctx), EVP_md5(), iv, - (unsigned char *)RSTRING_PTR(pass), RSTRING_LENINT(pass), 1, key, NULL); - p_key = key; - p_iv = iv; - } - else { - GetCipher(self, ctx); - } - if (EVP_CipherInit_ex(ctx, NULL, NULL, p_key, p_iv, mode) != 1) { - ossl_raise(eCipherError, NULL); + + GetCipher(self, ctx); + if (EVP_CipherInit_ex(ctx, NULL, NULL, NULL, NULL, enc) != 1) { + ossl_raise(eCipherError, "EVP_CipherInit_ex"); } - rb_ivar_set(self, id_key_set, p_key ? Qtrue : Qfalse); + rb_ivar_set(self, id_key_set, Qfalse); return self; } @@ -255,9 +225,9 @@ ossl_cipher_init(int argc, VALUE *argv, VALUE self, int mode) * Internally calls EVP_CipherInit_ex(ctx, NULL, NULL, NULL, NULL, 1). */ static VALUE -ossl_cipher_encrypt(int argc, VALUE *argv, VALUE self) +ossl_cipher_encrypt(VALUE self) { - return ossl_cipher_init(argc, argv, self, 1); + return ossl_cipher_init(self, 1); } /* @@ -273,9 +243,9 @@ ossl_cipher_encrypt(int argc, VALUE *argv, VALUE self) * Internally calls EVP_CipherInit_ex(ctx, NULL, NULL, NULL, NULL, 0). */ static VALUE -ossl_cipher_decrypt(int argc, VALUE *argv, VALUE self) +ossl_cipher_decrypt(VALUE self) { - return ossl_cipher_init(argc, argv, self, 0); + return ossl_cipher_init(self, 0); } /* @@ -386,22 +356,37 @@ ossl_cipher_update(int argc, VALUE *argv, VALUE self) in = (unsigned char *)RSTRING_PTR(data); in_len = RSTRING_LEN(data); GetCipher(self, ctx); - out_len = in_len+EVP_CIPHER_CTX_block_size(ctx); - if (out_len <= 0) { + + /* + * As of OpenSSL 3.2, there is no reliable way to determine the required + * output buffer size for arbitrary cipher modes. + * https://github.com/openssl/openssl/issues/22628 + * + * in_len+block_size is usually sufficient, but AES key wrap with padding + * ciphers require in_len+15 even though they have a block size of 8 bytes. + * + * Using EVP_MAX_BLOCK_LENGTH (32) as a safe upper bound for ciphers + * currently implemented in OpenSSL, but this can change in the future. + */ + if (in_len > LONG_MAX - EVP_MAX_BLOCK_LENGTH) { ossl_raise(rb_eRangeError, "data too big to make output buffer: %ld bytes", in_len); } + out_len = in_len + EVP_MAX_BLOCK_LENGTH; if (NIL_P(str)) { str = rb_str_new(0, out_len); } else { StringValue(str); - rb_str_resize(str, out_len); + if ((long)rb_str_capacity(str) >= out_len) + rb_str_modify(str); + else + rb_str_modify_expand(str, out_len - RSTRING_LEN(str)); } if (!ossl_cipher_update_long(ctx, (unsigned char *)RSTRING_PTR(str), &out_len, in, in_len)) ossl_raise(eCipherError, NULL); - assert(out_len < RSTRING_LEN(str)); + assert(out_len <= RSTRING_LEN(str)); rb_str_set_len(str, out_len); return str; @@ -442,8 +427,8 @@ ossl_cipher_final(VALUE self) * call-seq: * cipher.name -> string * - * Returns the name of the cipher which may differ slightly from the original - * name provided. + * Returns the short name of the cipher which may differ slightly from the + * original name provided. */ static VALUE ossl_cipher_name(VALUE self) @@ -1048,8 +1033,8 @@ Init_ossl_cipher(void) rb_define_module_function(cCipher, "ciphers", ossl_s_ciphers, 0); rb_define_method(cCipher, "initialize", ossl_cipher_initialize, 1); rb_define_method(cCipher, "reset", ossl_cipher_reset, 0); - rb_define_method(cCipher, "encrypt", ossl_cipher_encrypt, -1); - rb_define_method(cCipher, "decrypt", ossl_cipher_decrypt, -1); + rb_define_method(cCipher, "encrypt", ossl_cipher_encrypt, 0); + rb_define_method(cCipher, "decrypt", ossl_cipher_decrypt, 0); rb_define_method(cCipher, "pkcs5_keyivgen", ossl_cipher_pkcs5_keyivgen, -1); rb_define_method(cCipher, "update", ossl_cipher_update, -1); rb_define_method(cCipher, "final", ossl_cipher_final, 0); diff --git a/ext/openssl/ossl_cipher.h b/ext/openssl/ossl_cipher.h index 2392d41c6a9df8..12da68ca3e9cd5 100644 --- a/ext/openssl/ossl_cipher.h +++ b/ext/openssl/ossl_cipher.h @@ -5,14 +5,11 @@ */ /* * This program is licensed under the same licence as Ruby. - * (See the file 'LICENCE'.) + * (See the file 'COPYING'.) */ #if !defined(_OSSL_CIPHER_H_) #define _OSSL_CIPHER_H_ -extern VALUE cCipher; -extern VALUE eCipherError; - const EVP_CIPHER *ossl_evp_get_cipherbyname(VALUE); VALUE ossl_cipher_new(const EVP_CIPHER *); void Init_ossl_cipher(void); diff --git a/ext/openssl/ossl_config.c b/ext/openssl/ossl_config.c index 0e598b4d518cf0..ee2ff6786fbb28 100644 --- a/ext/openssl/ossl_config.c +++ b/ext/openssl/ossl_config.c @@ -5,7 +5,7 @@ */ /* * This program is licensed under the same licence as Ruby. - * (See the file 'LICENCE'.) + * (See the file 'COPYING'.) */ #include "ossl.h" @@ -22,7 +22,7 @@ static const rb_data_type_t ossl_config_type = { { 0, nconf_free, }, - 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED, + 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED | RUBY_TYPED_FROZEN_SHAREABLE, }; CONF * @@ -87,6 +87,7 @@ config_s_parse(VALUE klass, VALUE str) bio = ossl_obj2bio(&str); config_load_bio(conf, bio); /* Consumes BIO */ + rb_obj_freeze(obj); return obj; } @@ -144,6 +145,7 @@ config_initialize(int argc, VALUE *argv, VALUE self) ossl_raise(eConfigError, "BIO_new_file"); config_load_bio(conf, bio); /* Consumes BIO */ } + rb_obj_freeze(self); return self; } @@ -158,6 +160,7 @@ config_initialize_copy(VALUE self, VALUE other) rb_check_frozen(self); bio = ossl_obj2bio(&str); config_load_bio(conf, bio); /* Consumes BIO */ + rb_obj_freeze(self); return self; } @@ -305,18 +308,16 @@ static IMPLEMENT_LHASH_DOALL_ARG_FN(dump_conf_value, CONF_VALUE, VALUE) * * Gets the parsable form of the current configuration. * - * Given the following configuration being created: + * Given the following configuration file being loaded: * - * config = OpenSSL::Config.new - * #=> # - * config['default'] = {"foo"=>"bar","baz"=>"buz"} - * #=> {"foo"=>"bar", "baz"=>"buz"} + * config = OpenSSL::Config.load('baz.cnf') + * #=> # * puts config.to_s * #=> [ default ] * # foo=bar * # baz=buz * - * You can parse get the serialized configuration using #to_s and then parse + * You can get the serialized configuration using #to_s and then parse * it later: * * serialized_config = config.to_s @@ -455,6 +456,6 @@ Init_ossl_config(void) * The default system configuration file for OpenSSL. */ path = CONF_get1_default_config_file(); - path_str = ossl_buf2str(path, rb_long2int(strlen(path))); + path_str = rb_obj_freeze(ossl_buf2str(path, rb_long2int(strlen(path)))); rb_define_const(cConfig, "DEFAULT_CONFIG_FILE", path_str); } diff --git a/ext/openssl/ossl_config.h b/ext/openssl/ossl_config.h index 4e604f1aed36e2..a254360c2c81ef 100644 --- a/ext/openssl/ossl_config.h +++ b/ext/openssl/ossl_config.h @@ -5,7 +5,7 @@ */ /* * This program is licensed under the same licence as Ruby. - * (See the file 'LICENCE'.) + * (See the file 'COPYING'.) */ #ifndef OSSL_CONFIG_H #define OSSL_CONFIG_H diff --git a/ext/openssl/ossl_digest.c b/ext/openssl/ossl_digest.c index 16aeeb81069446..329de6c1bab078 100644 --- a/ext/openssl/ossl_digest.c +++ b/ext/openssl/ossl_digest.c @@ -5,7 +5,7 @@ */ /* * This program is licensed under the same licence as Ruby. - * (See the file 'LICENCE'.) + * (See the file 'COPYING'.) */ #include "ossl.h" @@ -19,8 +19,8 @@ /* * Classes */ -VALUE cDigest; -VALUE eDigestError; +static VALUE cDigest; +static VALUE eDigestError; static VALUE ossl_digest_alloc(VALUE klass); @@ -96,14 +96,15 @@ ossl_digest_alloc(VALUE klass) return TypedData_Wrap_Struct(klass, &ossl_digest_type, 0); } -VALUE ossl_digest_update(VALUE, VALUE); +static VALUE ossl_digest_update(VALUE, VALUE); /* * call-seq: * Digest.new(string [, data]) -> Digest * * Creates a Digest instance based on _string_, which is either the ln - * (long name) or sn (short name) of a supported digest algorithm. + * (long name) or sn (short name) of a supported digest algorithm. A list of + * supported algorithms can be obtained by calling OpenSSL::Digest.digests. * * If _data_ (a String) is given, it is used as the initial input to the * Digest instance, i.e. @@ -140,6 +141,7 @@ ossl_digest_initialize(int argc, VALUE *argv, VALUE self) return self; } +/* :nodoc: */ static VALUE ossl_digest_copy(VALUE self, VALUE other) { @@ -162,6 +164,32 @@ ossl_digest_copy(VALUE self, VALUE other) return self; } +static void +add_digest_name_to_ary(const OBJ_NAME *name, void *arg) +{ + VALUE ary = (VALUE)arg; + rb_ary_push(ary, rb_str_new2(name->name)); +} + +/* + * call-seq: + * OpenSSL::Digest.digests -> array[string...] + * + * Returns the names of all available digests in an array. + */ +static VALUE +ossl_s_digests(VALUE self) +{ + VALUE ary; + + ary = rb_ary_new(); + OBJ_NAME_do_all_sorted(OBJ_NAME_TYPE_MD_METH, + add_digest_name_to_ary, + (void*)ary); + + return ary; +} + /* * call-seq: * digest.reset -> self @@ -198,7 +226,7 @@ ossl_digest_reset(VALUE self) * result = digest.digest * */ -VALUE +static VALUE ossl_digest_update(VALUE self, VALUE data) { EVP_MD_CTX *ctx; @@ -218,23 +246,13 @@ ossl_digest_update(VALUE self, VALUE data) * */ static VALUE -ossl_digest_finish(int argc, VALUE *argv, VALUE self) +ossl_digest_finish(VALUE self) { EVP_MD_CTX *ctx; VALUE str; - int out_len; GetDigest(self, ctx); - rb_scan_args(argc, argv, "01", &str); - out_len = EVP_MD_CTX_size(ctx); - - if (NIL_P(str)) { - str = rb_str_new(NULL, out_len); - } else { - StringValue(str); - rb_str_resize(str, out_len); - } - + str = rb_str_new(NULL, EVP_MD_CTX_size(ctx)); if (!EVP_DigestFinal_ex(ctx, (unsigned char *)RSTRING_PTR(str), NULL)) ossl_raise(eDigestError, "EVP_DigestFinal_ex"); @@ -245,7 +263,8 @@ ossl_digest_finish(int argc, VALUE *argv, VALUE self) * call-seq: * digest.name -> string * - * Returns the sn of this Digest algorithm. + * Returns the short name of this Digest algorithm which may differ slightly + * from the original name provided. * * === Example * digest = OpenSSL::Digest.new('SHA512') @@ -412,12 +431,13 @@ Init_ossl_digest(void) rb_define_alloc_func(cDigest, ossl_digest_alloc); + rb_define_module_function(cDigest, "digests", ossl_s_digests, 0); rb_define_method(cDigest, "initialize", ossl_digest_initialize, -1); rb_define_method(cDigest, "initialize_copy", ossl_digest_copy, 1); rb_define_method(cDigest, "reset", ossl_digest_reset, 0); rb_define_method(cDigest, "update", ossl_digest_update, 1); rb_define_alias(cDigest, "<<", "update"); - rb_define_private_method(cDigest, "finish", ossl_digest_finish, -1); + rb_define_private_method(cDigest, "finish", ossl_digest_finish, 0); rb_define_method(cDigest, "digest_length", ossl_digest_size, 0); rb_define_method(cDigest, "block_length", ossl_digest_block_length, 0); diff --git a/ext/openssl/ossl_digest.h b/ext/openssl/ossl_digest.h index 50bf5666a37346..588a0c6f578a63 100644 --- a/ext/openssl/ossl_digest.h +++ b/ext/openssl/ossl_digest.h @@ -5,14 +5,11 @@ */ /* * This program is licensed under the same licence as Ruby. - * (See the file 'LICENCE'.) + * (See the file 'COPYING'.) */ #if !defined(_OSSL_DIGEST_H_) #define _OSSL_DIGEST_H_ -extern VALUE cDigest; -extern VALUE eDigestError; - const EVP_MD *ossl_evp_get_digestbyname(VALUE); VALUE ossl_digest_new(const EVP_MD *); void Init_ossl_digest(void); diff --git a/ext/openssl/ossl_engine.c b/ext/openssl/ossl_engine.c index 9e86321d062a93..cb08049a8214b7 100644 --- a/ext/openssl/ossl_engine.c +++ b/ext/openssl/ossl_engine.c @@ -5,7 +5,7 @@ */ /* * This program is licensed under the same licence as Ruby. - * (See the file 'LICENCE'.) + * (See the file 'COPYING'.) */ #include "ossl.h" @@ -37,17 +37,16 @@ * * See also, https://www.openssl.org/docs/crypto/engine.html */ -VALUE cEngine; +static VALUE cEngine; /* Document-class: OpenSSL::Engine::EngineError * * This is the generic exception for OpenSSL::Engine related errors */ -VALUE eEngineError; +static VALUE eEngineError; /* * Private */ -#if !defined(LIBRESSL_VERSION_NUMBER) && OPENSSL_VERSION_NUMBER >= 0x10100000 #define OSSL_ENGINE_LOAD_IF_MATCH(engine_name, x) \ do{\ if(!strcmp(#engine_name, RSTRING_PTR(name))){\ @@ -57,15 +56,6 @@ do{\ ossl_raise(eEngineError, "OPENSSL_init_crypto"); \ }\ }while(0) -#else -#define OSSL_ENGINE_LOAD_IF_MATCH(engine_name, x) \ -do{\ - if(!strcmp(#engine_name, RSTRING_PTR(name))){\ - ENGINE_load_##engine_name();\ - return Qtrue;\ - }\ -}while(0) -#endif static void ossl_engine_free(void *engine) @@ -102,50 +92,10 @@ ossl_engine_s_load(int argc, VALUE *argv, VALUE klass) return Qtrue; } StringValueCStr(name); -#ifdef HAVE_ENGINE_LOAD_DYNAMIC OSSL_ENGINE_LOAD_IF_MATCH(dynamic, DYNAMIC); -#endif -#ifndef OPENSSL_NO_STATIC_ENGINE -#ifdef HAVE_ENGINE_LOAD_4758CCA - OSSL_ENGINE_LOAD_IF_MATCH(4758cca, 4758CCA); -#endif -#ifdef HAVE_ENGINE_LOAD_AEP - OSSL_ENGINE_LOAD_IF_MATCH(aep, AEP); -#endif -#ifdef HAVE_ENGINE_LOAD_ATALLA - OSSL_ENGINE_LOAD_IF_MATCH(atalla, ATALLA); -#endif -#ifdef HAVE_ENGINE_LOAD_CHIL - OSSL_ENGINE_LOAD_IF_MATCH(chil, CHIL); -#endif -#ifdef HAVE_ENGINE_LOAD_CSWIFT - OSSL_ENGINE_LOAD_IF_MATCH(cswift, CSWIFT); -#endif -#ifdef HAVE_ENGINE_LOAD_NURON - OSSL_ENGINE_LOAD_IF_MATCH(nuron, NURON); -#endif -#ifdef HAVE_ENGINE_LOAD_SUREWARE - OSSL_ENGINE_LOAD_IF_MATCH(sureware, SUREWARE); -#endif -#ifdef HAVE_ENGINE_LOAD_UBSEC - OSSL_ENGINE_LOAD_IF_MATCH(ubsec, UBSEC); -#endif -#ifdef HAVE_ENGINE_LOAD_PADLOCK OSSL_ENGINE_LOAD_IF_MATCH(padlock, PADLOCK); -#endif -#ifdef HAVE_ENGINE_LOAD_CAPI OSSL_ENGINE_LOAD_IF_MATCH(capi, CAPI); -#endif -#ifdef HAVE_ENGINE_LOAD_GMP - OSSL_ENGINE_LOAD_IF_MATCH(gmp, GMP); -#endif -#ifdef HAVE_ENGINE_LOAD_GOST - OSSL_ENGINE_LOAD_IF_MATCH(gost, GOST); -#endif -#endif -#ifdef HAVE_ENGINE_LOAD_CRYPTODEV OSSL_ENGINE_LOAD_IF_MATCH(cryptodev, CRYPTODEV); -#endif OSSL_ENGINE_LOAD_IF_MATCH(openssl, OPENSSL); rb_warning("no such builtin loader for `%"PRIsVALUE"'", name); return Qnil; @@ -163,9 +113,6 @@ ossl_engine_s_load(int argc, VALUE *argv, VALUE klass) static VALUE ossl_engine_s_cleanup(VALUE self) { -#if defined(LIBRESSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER < 0x10100000 - ENGINE_cleanup(); -#endif return Qnil; } @@ -549,12 +496,6 @@ Init_ossl_engine(void) DefEngineConst(METHOD_DSA); DefEngineConst(METHOD_DH); DefEngineConst(METHOD_RAND); -#ifdef ENGINE_METHOD_BN_MOD_EXP - DefEngineConst(METHOD_BN_MOD_EXP); -#endif -#ifdef ENGINE_METHOD_BN_MOD_EXP_CRT - DefEngineConst(METHOD_BN_MOD_EXP_CRT); -#endif DefEngineConst(METHOD_CIPHERS); DefEngineConst(METHOD_DIGESTS); DefEngineConst(METHOD_ALL); diff --git a/ext/openssl/ossl_engine.h b/ext/openssl/ossl_engine.h index cd548beea3192a..cedcebb77227bb 100644 --- a/ext/openssl/ossl_engine.h +++ b/ext/openssl/ossl_engine.h @@ -6,14 +6,11 @@ */ /* * This program is licensed under the same licence as Ruby. - * (See the file 'LICENCE'.) + * (See the file 'COPYING'.) */ #if !defined(OSSL_ENGINE_H) #define OSSL_ENGINE_H -extern VALUE cEngine; -extern VALUE eEngineError; - void Init_ossl_engine(void); #endif /* OSSL_ENGINE_H */ diff --git a/ext/openssl/ossl_hmac.c b/ext/openssl/ossl_hmac.c index c485ba7e678a50..b30482757997b6 100644 --- a/ext/openssl/ossl_hmac.c +++ b/ext/openssl/ossl_hmac.c @@ -5,7 +5,7 @@ */ /* * This program is licensed under the same licence as Ruby. - * (See the file 'LICENCE'.) + * (See the file 'COPYING'.) */ #include "ossl.h" @@ -21,8 +21,8 @@ /* * Classes */ -VALUE cHMAC; -VALUE eHMACError; +static VALUE cHMAC; +static VALUE eHMACError; /* * Public @@ -97,19 +97,11 @@ ossl_hmac_initialize(VALUE self, VALUE key, VALUE digest) GetHMAC(self, ctx); StringValue(key); -#ifdef HAVE_EVP_PKEY_NEW_RAW_PRIVATE_KEY pkey = EVP_PKEY_new_raw_private_key(EVP_PKEY_HMAC, NULL, (unsigned char *)RSTRING_PTR(key), RSTRING_LENINT(key)); if (!pkey) ossl_raise(eHMACError, "EVP_PKEY_new_raw_private_key"); -#else - pkey = EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, - (unsigned char *)RSTRING_PTR(key), - RSTRING_LENINT(key)); - if (!pkey) - ossl_raise(eHMACError, "EVP_PKEY_new_mac_key"); -#endif if (EVP_DigestSignInit(ctx, NULL, ossl_evp_get_digestbyname(digest), NULL, pkey) != 1) { EVP_PKEY_free(pkey); @@ -121,6 +113,7 @@ ossl_hmac_initialize(VALUE self, VALUE key, VALUE digest) return self; } +/* :nodoc: */ static VALUE ossl_hmac_copy(VALUE self, VALUE other) { diff --git a/ext/openssl/ossl_hmac.h b/ext/openssl/ossl_hmac.h index 7c51f4722d059a..e5bed37c9fc552 100644 --- a/ext/openssl/ossl_hmac.h +++ b/ext/openssl/ossl_hmac.h @@ -5,14 +5,11 @@ */ /* * This program is licensed under the same licence as Ruby. - * (See the file 'LICENCE'.) + * (See the file 'COPYING'.) */ #if !defined(_OSSL_HMAC_H_) #define _OSSL_HMAC_H_ -extern VALUE cHMAC; -extern VALUE eHMACError; - void Init_ossl_hmac(void); #endif /* _OSSL_HMAC_H_ */ diff --git a/ext/openssl/ossl_kdf.c b/ext/openssl/ossl_kdf.c index 48b161d4f47749..f349939a80475e 100644 --- a/ext/openssl/ossl_kdf.c +++ b/ext/openssl/ossl_kdf.c @@ -3,9 +3,7 @@ * Copyright (C) 2007, 2017 Ruby/OpenSSL Project Authors */ #include "ossl.h" -#if OSSL_OPENSSL_PREREQ(1, 1, 0) || OSSL_LIBRESSL_PREREQ(3, 6, 0) -# include -#endif +#include static VALUE mKDF, eKDF; @@ -18,7 +16,7 @@ static VALUE mKDF, eKDF; * of _length_ bytes. * * For more information about PBKDF2, see RFC 2898 Section 5.2 - * (https://tools.ietf.org/html/rfc2898#section-5.2). + * (https://www.rfc-editor.org/rfc/rfc2898#section-5.2). * * === Parameters * pass :: The password. @@ -81,10 +79,10 @@ kdf_pbkdf2_hmac(int argc, VALUE *argv, VALUE self) * bcrypt. * * The keyword arguments _N_, _r_ and _p_ can be used to tune scrypt. RFC 7914 - * (published on 2016-08, https://tools.ietf.org/html/rfc7914#section-2) states + * (published on 2016-08, https://www.rfc-editor.org/rfc/rfc7914#section-2) states * that using values r=8 and p=1 appears to yield good results. * - * See RFC 7914 (https://tools.ietf.org/html/rfc7914) for more information. + * See RFC 7914 (https://www.rfc-editor.org/rfc/rfc7914) for more information. * * === Parameters * pass :: Passphrase. @@ -141,13 +139,12 @@ kdf_scrypt(int argc, VALUE *argv, VALUE self) } #endif -#if OSSL_OPENSSL_PREREQ(1, 1, 0) || OSSL_LIBRESSL_PREREQ(3, 6, 0) /* * call-seq: * KDF.hkdf(ikm, salt:, info:, length:, hash:) -> String * * HMAC-based Extract-and-Expand Key Derivation Function (HKDF) as specified in - * {RFC 5869}[https://tools.ietf.org/html/rfc5869]. + * {RFC 5869}[https://www.rfc-editor.org/rfc/rfc5869]. * * New in OpenSSL 1.1.0. * @@ -165,7 +162,7 @@ kdf_scrypt(int argc, VALUE *argv, VALUE self) * The hash function. * * === Example - * # The values from https://datatracker.ietf.org/doc/html/rfc5869#appendix-A.1 + * # The values from https://www.rfc-editor.org/rfc/rfc5869#appendix-A.1 * ikm = ["0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b"].pack("H*") * salt = ["000102030405060708090a0b0c"].pack("H*") * info = ["f0f1f2f3f4f5f6f7f8f9"].pack("H*") @@ -238,7 +235,6 @@ kdf_hkdf(int argc, VALUE *argv, VALUE self) return str; } -#endif void Init_ossl_kdf(void) @@ -305,7 +301,5 @@ Init_ossl_kdf(void) #if defined(HAVE_EVP_PBE_SCRYPT) rb_define_module_function(mKDF, "scrypt", kdf_scrypt, -1); #endif -#if OSSL_OPENSSL_PREREQ(1, 1, 0) || OSSL_LIBRESSL_PREREQ(3, 6, 0) rb_define_module_function(mKDF, "hkdf", kdf_hkdf, -1); -#endif } diff --git a/ext/openssl/ossl_ns_spki.c b/ext/openssl/ossl_ns_spki.c index 9bed1f330ec5e2..445aeeba152fa4 100644 --- a/ext/openssl/ossl_ns_spki.c +++ b/ext/openssl/ossl_ns_spki.c @@ -5,7 +5,7 @@ */ /* * This program is licensed under the same licence as Ruby. - * (See the file 'LICENCE'.) + * (See the file 'COPYING'.) */ #include "ossl.h" @@ -27,9 +27,9 @@ /* * Classes */ -VALUE mNetscape; -VALUE cSPKI; -VALUE eSPKIError; +static VALUE mNetscape; +static VALUE cSPKI; +static VALUE eSPKIError; /* * Public functions @@ -115,11 +115,11 @@ ossl_spki_to_der(VALUE self) GetSPKI(self, spki); if ((len = i2d_NETSCAPE_SPKI(spki, NULL)) <= 0) - ossl_raise(eX509CertError, NULL); + ossl_raise(eSPKIError, "i2d_NETSCAPE_SPKI"); str = rb_str_new(0, len); p = (unsigned char *)RSTRING_PTR(str); if (i2d_NETSCAPE_SPKI(spki, &p) <= 0) - ossl_raise(eX509CertError, NULL); + ossl_raise(eSPKIError, "i2d_NETSCAPE_SPKI"); ossl_str_adjust(str, p); return str; @@ -365,8 +365,8 @@ ossl_spki_verify(VALUE self, VALUE key) * * OpenSSL::Netscape is a namespace for SPKI (Simple Public Key * Infrastructure) which implements Signed Public Key and Challenge. - * See {RFC 2692}[http://tools.ietf.org/html/rfc2692] and {RFC - * 2693}[http://tools.ietf.org/html/rfc2692] for details. + * See {RFC 2692}[https://www.rfc-editor.org/rfc/rfc2692] and {RFC + * 2693}[https://www.rfc-editor.org/rfc/rfc2692] for details. */ /* Document-class: OpenSSL::Netscape::SPKIError diff --git a/ext/openssl/ossl_ns_spki.h b/ext/openssl/ossl_ns_spki.h index 62ba8cb16327bf..043b6cdb660b30 100644 --- a/ext/openssl/ossl_ns_spki.h +++ b/ext/openssl/ossl_ns_spki.h @@ -5,15 +5,11 @@ */ /* * This program is licensed under the same licence as Ruby. - * (See the file 'LICENCE'.) + * (See the file 'COPYING'.) */ #if !defined(_OSSL_NS_SPKI_H_) #define _OSSL_NS_SPKI_H_ -extern VALUE mNetscape; -extern VALUE cSPKI; -extern VALUE eSPKIError; - void Init_ossl_ns_spki(void); #endif /* _OSSL_NS_SPKI_H_ */ diff --git a/ext/openssl/ossl_ocsp.c b/ext/openssl/ossl_ocsp.c index df986bb3eeb0e2..cb2f1a62d0aa69 100644 --- a/ext/openssl/ossl_ocsp.c +++ b/ext/openssl/ossl_ocsp.c @@ -6,7 +6,7 @@ */ /* * This program is licensed under the same licence as Ruby. - * (See the file 'LICENCE'.) + * (See the file 'COPYING'.) */ #include "ossl.h" @@ -67,13 +67,13 @@ if(!(cid)) ossl_raise(rb_eRuntimeError, "Cert ID wasn't initialized!"); \ } while (0) -VALUE mOCSP; -VALUE eOCSPError; -VALUE cOCSPReq; -VALUE cOCSPRes; -VALUE cOCSPBasicRes; -VALUE cOCSPSingleRes; -VALUE cOCSPCertId; +static VALUE mOCSP; +static VALUE eOCSPError; +static VALUE cOCSPReq; +static VALUE cOCSPRes; +static VALUE cOCSPBasicRes; +static VALUE cOCSPSingleRes; +static VALUE cOCSPCertId; static void ossl_ocsp_request_free(void *ptr) @@ -173,6 +173,7 @@ ossl_ocspreq_alloc(VALUE klass) return obj; } +/* :nodoc: */ static VALUE ossl_ocspreq_initialize_copy(VALUE self, VALUE other) { @@ -513,6 +514,7 @@ ossl_ocspres_alloc(VALUE klass) return obj; } +/* :nodoc: */ static VALUE ossl_ocspres_initialize_copy(VALUE self, VALUE other) { @@ -669,6 +671,7 @@ ossl_ocspbres_alloc(VALUE klass) return obj; } +/* :nodoc: */ static VALUE ossl_ocspbres_initialize_copy(VALUE self, VALUE other) { @@ -1157,6 +1160,7 @@ ossl_ocspsres_initialize(VALUE self, VALUE arg) return self; } +/* :nodoc: */ static VALUE ossl_ocspsres_initialize_copy(VALUE self, VALUE other) { @@ -1418,6 +1422,7 @@ ossl_ocspcid_alloc(VALUE klass) return obj; } +/* :nodoc: */ static VALUE ossl_ocspcid_initialize_copy(VALUE self, VALUE other) { diff --git a/ext/openssl/ossl_ocsp.h b/ext/openssl/ossl_ocsp.h index 6d2aac8657c9d3..becd70ffedb832 100644 --- a/ext/openssl/ossl_ocsp.h +++ b/ext/openssl/ossl_ocsp.h @@ -6,18 +6,11 @@ */ /* * This program is licensed under the same licence as Ruby. - * (See the file 'LICENCE'.) + * (See the file 'COPYING'.) */ #if !defined(_OSSL_OCSP_H_) #define _OSSL_OCSP_H_ -#if !defined(OPENSSL_NO_OCSP) -extern VALUE mOCSP; -extern VALUE cOCSPReq; -extern VALUE cOCSPRes; -extern VALUE cOCSPBasicRes; -#endif - void Init_ossl_ocsp(void); #endif /* _OSSL_OCSP_H_ */ diff --git a/ext/openssl/ossl_pkcs12.c b/ext/openssl/ossl_pkcs12.c index 164b2da465fba8..be09eb2071c125 100644 --- a/ext/openssl/ossl_pkcs12.c +++ b/ext/openssl/ossl_pkcs12.c @@ -1,6 +1,6 @@ /* * This program is licensed under the same licence as Ruby. - * (See the file 'LICENCE'.) + * (See the file 'COPYING'.) */ #include "ossl.h" @@ -27,8 +27,8 @@ /* * Classes */ -VALUE cPKCS12; -VALUE ePKCS12Error; +static VALUE cPKCS12; +static VALUE ePKCS12Error; /* * Private @@ -60,6 +60,7 @@ ossl_pkcs12_s_allocate(VALUE klass) return obj; } +/* :nodoc: */ static VALUE ossl_pkcs12_initialize_copy(VALUE self, VALUE other) { @@ -134,6 +135,16 @@ ossl_pkcs12_s_create(int argc, VALUE *argv, VALUE self) if (!NIL_P(keytype)) ktype = NUM2INT(keytype); +#if defined(OPENSSL_IS_AWSLC) + if (ktype != 0) { + ossl_raise(rb_eArgError, "Unknown key usage type %"PRIsVALUE, INT2NUM(ktype)); + } +#else + if (ktype != 0 && ktype != KEY_SIG && ktype != KEY_EX) { + ossl_raise(rb_eArgError, "Unknown key usage type %"PRIsVALUE, INT2NUM(ktype)); + } +#endif + obj = NewPKCS12(cPKCS12); x509s = NIL_P(ca) ? NULL : ossl_x509_ary2sk(ca); p12 = PKCS12_create(passphrase, friendlyname, key, x509, x509s, @@ -197,12 +208,8 @@ ossl_pkcs12_initialize(int argc, VALUE *argv, VALUE self) BIO_free(in); pkey = cert = ca = Qnil; - /* OpenSSL's bug; PKCS12_parse() puts errors even if it succeeds. - * Fixed in OpenSSL 1.0.0t, 1.0.1p, 1.0.2d */ - ERR_set_mark(); if(!PKCS12_parse(pkcs, passphrase, &key, &x509, &x509s)) ossl_raise(ePKCS12Error, "PKCS12_parse"); - ERR_pop_to_mark(); if (key) { pkey = rb_protect(ossl_pkey_new_i, (VALUE)key, &st); if (st) goto err; @@ -247,6 +254,48 @@ ossl_pkcs12_to_der(VALUE self) return str; } +/* + * call-seq: + * pkcs12.set_mac(pass, salt = nil, iter = nil, md_type = nil) + * + * Sets MAC parameters and generates MAC over the PKCS #12 structure. + * + * This method uses HMAC and the PKCS #12 specific password-based KDF as + * specified in the original PKCS #12. + * + * See also the man page PKCS12_set_mac(3). + * + * Added in version 3.3.0. + */ +static VALUE +pkcs12_set_mac(int argc, VALUE *argv, VALUE self) +{ + PKCS12 *p12; + VALUE pass, salt, iter, md_name; + int iter_i = 0; + const EVP_MD *md_type = NULL; + + rb_scan_args(argc, argv, "13", &pass, &salt, &iter, &md_name); + rb_check_frozen(self); + GetPKCS12(self, p12); + + StringValue(pass); + if (!NIL_P(salt)) + StringValue(salt); + if (!NIL_P(iter)) + iter_i = NUM2INT(iter); + if (!NIL_P(md_name)) + md_type = ossl_evp_get_digestbyname(md_name); + + if (!PKCS12_set_mac(p12, RSTRING_PTR(pass), RSTRING_LENINT(pass), + !NIL_P(salt) ? (unsigned char *)RSTRING_PTR(salt) : NULL, + !NIL_P(salt) ? RSTRING_LENINT(salt) : 0, + iter_i, md_type)) + ossl_raise(ePKCS12Error, "PKCS12_set_mac"); + + return Qnil; +} + void Init_ossl_pkcs12(void) { @@ -272,4 +321,11 @@ Init_ossl_pkcs12(void) rb_attr(cPKCS12, rb_intern("ca_certs"), 1, 0, Qfalse); rb_define_method(cPKCS12, "initialize", ossl_pkcs12_initialize, -1); rb_define_method(cPKCS12, "to_der", ossl_pkcs12_to_der, 0); + rb_define_method(cPKCS12, "set_mac", pkcs12_set_mac, -1); + +#if !defined(OPENSSL_IS_AWSLC) + /* MSIE specific PKCS12 key usage extensions */ + rb_define_const(cPKCS12, "KEY_EX", INT2NUM(KEY_EX)); + rb_define_const(cPKCS12, "KEY_SIG", INT2NUM(KEY_SIG)); +#endif } diff --git a/ext/openssl/ossl_pkcs12.h b/ext/openssl/ossl_pkcs12.h index fe4f15ef60a109..6d2cd901cbceff 100644 --- a/ext/openssl/ossl_pkcs12.h +++ b/ext/openssl/ossl_pkcs12.h @@ -1,13 +1,10 @@ /* * This program is licensed under the same licence as Ruby. - * (See the file 'LICENCE'.) + * (See the file 'COPYING'.) */ #if !defined(_OSSL_PKCS12_H_) #define _OSSL_PKCS12_H_ -extern VALUE cPKCS12; -extern VALUE ePKCS12Error; - void Init_ossl_pkcs12(void); #endif /* _OSSL_PKCS12_H_ */ diff --git a/ext/openssl/ossl_pkcs7.c b/ext/openssl/ossl_pkcs7.c index 78dcbd667a78ea..4d719c96da141c 100644 --- a/ext/openssl/ossl_pkcs7.c +++ b/ext/openssl/ossl_pkcs7.c @@ -5,10 +5,25 @@ */ /* * This program is licensed under the same licence as Ruby. - * (See the file 'LICENCE'.) + * (See the file 'COPYING'.) */ #include "ossl.h" +#define NewPKCS7(klass) \ + TypedData_Wrap_Struct((klass), &ossl_pkcs7_type, 0) +#define SetPKCS7(obj, pkcs7) do { \ + if (!(pkcs7)) { \ + ossl_raise(rb_eRuntimeError, "PKCS7 wasn't initialized."); \ + } \ + RTYPEDDATA_DATA(obj) = (pkcs7); \ +} while (0) +#define GetPKCS7(obj, pkcs7) do { \ + TypedData_Get_Struct((obj), PKCS7, &ossl_pkcs7_type, (pkcs7)); \ + if (!(pkcs7)) { \ + ossl_raise(rb_eRuntimeError, "PKCS7 wasn't initialized."); \ + } \ +} while (0) + #define NewPKCS7si(klass) \ TypedData_Wrap_Struct((klass), &ossl_pkcs7_signer_info_type, 0) #define SetPKCS7si(obj, p7si) do { \ @@ -49,10 +64,10 @@ /* * Classes */ -VALUE cPKCS7; -VALUE cPKCS7Signer; -VALUE cPKCS7Recipient; -VALUE ePKCS7Error; +static VALUE cPKCS7; +static VALUE cPKCS7Signer; +static VALUE cPKCS7Recipient; +static VALUE ePKCS7Error; static void ossl_pkcs7_free(void *ptr) @@ -60,7 +75,7 @@ ossl_pkcs7_free(void *ptr) PKCS7_free(ptr); } -const rb_data_type_t ossl_pkcs7_type = { +static const rb_data_type_t ossl_pkcs7_type = { "OpenSSL/PKCS7", { 0, ossl_pkcs7_free, @@ -68,6 +83,20 @@ const rb_data_type_t ossl_pkcs7_type = { 0, 0, RUBY_TYPED_FREE_IMMEDIATELY | RUBY_TYPED_WB_PROTECTED, }; +VALUE +ossl_pkcs7_new(PKCS7 *p7) +{ + PKCS7 *new; + VALUE obj = NewPKCS7(cPKCS7); + + new = PKCS7_dup(p7); + if (!new) + ossl_raise(ePKCS7Error, "PKCS7_dup"); + SetPKCS7(obj, new); + + return obj; +} + static void ossl_pkcs7_signer_info_free(void *ptr) { @@ -165,7 +194,13 @@ ossl_pkcs7_s_read_smime(VALUE klass, VALUE arg) out = NULL; pkcs7 = SMIME_read_PKCS7(in, &out); BIO_free(in); - if(!pkcs7) ossl_raise(ePKCS7Error, NULL); + if (!pkcs7) + ossl_raise(ePKCS7Error, "Could not parse the PKCS7"); + if (!pkcs7->d.ptr) { + PKCS7_free(pkcs7); + ossl_raise(ePKCS7Error, "No content in PKCS7"); + } + data = out ? ossl_membio2str(out) : Qnil; SetPKCS7(ret, pkcs7); ossl_pkcs7_set_data(ret, data); @@ -255,7 +290,14 @@ ossl_pkcs7_s_sign(int argc, VALUE *argv, VALUE klass) /* * call-seq: - * PKCS7.encrypt(certs, data, [, cipher [, flags]]) => pkcs7 + * PKCS7.encrypt(certs, data, cipher, flags = 0) => pkcs7 + * + * Creates a PKCS #7 enveloped-data structure. + * + * Before version 3.3.0, +cipher+ was optional and defaulted to + * "RC2-40-CBC". + * + * See also the man page PKCS7_encrypt(3). */ static VALUE ossl_pkcs7_s_encrypt(int argc, VALUE *argv, VALUE klass) @@ -269,21 +311,12 @@ ossl_pkcs7_s_encrypt(int argc, VALUE *argv, VALUE klass) PKCS7 *p7; rb_scan_args(argc, argv, "22", &certs, &data, &cipher, &flags); - if(NIL_P(cipher)){ -#if !defined(OPENSSL_NO_RC2) - ciph = EVP_rc2_40_cbc(); -#elif !defined(OPENSSL_NO_DES) - ciph = EVP_des_ede3_cbc(); -#elif !defined(OPENSSL_NO_RC2) - ciph = EVP_rc2_40_cbc(); -#elif !defined(OPENSSL_NO_AES) - ciph = EVP_EVP_aes_128_cbc(); -#else - ossl_raise(ePKCS7Error, "Must specify cipher"); -#endif - + if (NIL_P(cipher)) { + rb_raise(rb_eArgError, + "cipher must be specified. Before version 3.3, " \ + "the default cipher was RC2-40-CBC."); } - else ciph = ossl_evp_get_cipherbyname(cipher); + ciph = ossl_evp_get_cipherbyname(cipher); flg = NIL_P(flags) ? 0 : NUM2INT(flags); ret = NewPKCS7(cPKCS7); in = ossl_obj2bio(&data); @@ -292,7 +325,7 @@ ossl_pkcs7_s_encrypt(int argc, VALUE *argv, VALUE klass) BIO_free(in); rb_jump_tag(status); } - if(!(p7 = PKCS7_encrypt(x509s, in, (EVP_CIPHER*)ciph, flg))){ + if (!(p7 = PKCS7_encrypt(x509s, in, ciph, flg))) { BIO_free(in); sk_X509_pop_free(x509s, X509_free); ossl_raise(ePKCS7Error, NULL); @@ -346,6 +379,10 @@ ossl_pkcs7_initialize(int argc, VALUE *argv, VALUE self) BIO_free(in); if (!p7) ossl_raise(rb_eArgError, "Could not parse the PKCS7"); + if (!p7->d.ptr) { + PKCS7_free(p7); + ossl_raise(rb_eArgError, "No content in PKCS7"); + } RTYPEDDATA_DATA(self) = p7; PKCS7_free(p7_orig); @@ -355,6 +392,7 @@ ossl_pkcs7_initialize(int argc, VALUE *argv, VALUE self) return self; } +/* :nodoc: */ static VALUE ossl_pkcs7_copy(VALUE self, VALUE other) { @@ -520,21 +558,16 @@ ossl_pkcs7_get_signer(VALUE self) { PKCS7 *pkcs7; STACK_OF(PKCS7_SIGNER_INFO) *sk; - PKCS7_SIGNER_INFO *si; int num, i; VALUE ary; GetPKCS7(self, pkcs7); - if (!(sk = PKCS7_get_signer_info(pkcs7))) { - OSSL_Debug("OpenSSL::PKCS7#get_signer_info == NULL!"); - return rb_ary_new(); - } - if ((num = sk_PKCS7_SIGNER_INFO_num(sk)) < 0) { - ossl_raise(ePKCS7Error, "Negative number of signers!"); - } - ary = rb_ary_new2(num); + if (!(sk = PKCS7_get_signer_info(pkcs7))) + return rb_ary_new(); + num = sk_PKCS7_SIGNER_INFO_num(sk); + ary = rb_ary_new_capa(num); for (i=0; id.signed_and_enveloped->recipientinfo; else sk = NULL; if (!sk) return rb_ary_new(); - if ((num = sk_PKCS7_RECIP_INFO_num(sk)) < 0) { - ossl_raise(ePKCS7Error, "Negative number of recipient!"); - } - ary = rb_ary_new2(num); + num = sk_PKCS7_RECIP_INFO_num(sk); + ary = rb_ary_new_capa(num); for (i=0; i PKey @@ -647,28 +669,27 @@ static VALUE ossl_pkey_new_raw_private_key(VALUE self, VALUE type, VALUE key) { EVP_PKEY *pkey; - const EVP_PKEY_ASN1_METHOD *ameth; - int pkey_id; size_t keylen; - StringValue(type); StringValue(key); - ameth = EVP_PKEY_asn1_find_str(NULL, RSTRING_PTR(type), RSTRING_LENINT(type)); - if (!ameth) - ossl_raise(ePKeyError, "algorithm %"PRIsVALUE" not found", type); - EVP_PKEY_asn1_get0_info(&pkey_id, NULL, NULL, NULL, NULL, ameth); - keylen = RSTRING_LEN(key); +#ifdef OSSL_USE_PROVIDER + pkey = EVP_PKEY_new_raw_private_key_ex(NULL, StringValueCStr(type), NULL, + (unsigned char *)RSTRING_PTR(key), + keylen); + if (!pkey) + ossl_raise(ePKeyError, "EVP_PKEY_new_raw_private_key_ex"); +#else + int pkey_id = lookup_pkey_type(type); pkey = EVP_PKEY_new_raw_private_key(pkey_id, NULL, (unsigned char *)RSTRING_PTR(key), keylen); if (!pkey) ossl_raise(ePKeyError, "EVP_PKEY_new_raw_private_key"); +#endif return ossl_pkey_new(pkey); } -#endif -#ifdef HAVE_EVP_PKEY_NEW_RAW_PRIVATE_KEY /* * call-seq: * OpenSSL::PKey.new_raw_public_key(algo, string) -> PKey @@ -680,26 +701,26 @@ static VALUE ossl_pkey_new_raw_public_key(VALUE self, VALUE type, VALUE key) { EVP_PKEY *pkey; - const EVP_PKEY_ASN1_METHOD *ameth; - int pkey_id; size_t keylen; - StringValue(type); StringValue(key); - ameth = EVP_PKEY_asn1_find_str(NULL, RSTRING_PTR(type), RSTRING_LENINT(type)); - if (!ameth) - ossl_raise(ePKeyError, "algorithm %"PRIsVALUE" not found", type); - EVP_PKEY_asn1_get0_info(&pkey_id, NULL, NULL, NULL, NULL, ameth); - keylen = RSTRING_LEN(key); +#ifdef OSSL_USE_PROVIDER + pkey = EVP_PKEY_new_raw_public_key_ex(NULL, StringValueCStr(type), NULL, + (unsigned char *)RSTRING_PTR(key), + keylen); + if (!pkey) + ossl_raise(ePKeyError, "EVP_PKEY_new_raw_public_key_ex"); +#else + int pkey_id = lookup_pkey_type(type); pkey = EVP_PKEY_new_raw_public_key(pkey_id, NULL, (unsigned char *)RSTRING_PTR(key), keylen); if (!pkey) ossl_raise(ePKeyError, "EVP_PKEY_new_raw_public_key"); +#endif return ossl_pkey_new(pkey); } -#endif /* * call-seq: @@ -715,6 +736,10 @@ ossl_pkey_oid(VALUE self) GetPKey(self, pkey); nid = EVP_PKEY_id(pkey); +#ifdef OSSL_USE_PROVIDER + if (nid == EVP_PKEY_KEYMGMT) + ossl_raise(ePKeyError, "EVP_PKEY_id"); +#endif return rb_str_new_cstr(OBJ_nid2sn(nid)); } @@ -728,13 +753,23 @@ static VALUE ossl_pkey_inspect(VALUE self) { EVP_PKEY *pkey; - int nid; GetPKey(self, pkey); - nid = EVP_PKEY_id(pkey); - return rb_sprintf("#<%"PRIsVALUE":%p oid=%s>", - rb_class_name(CLASS_OF(self)), (void *)self, - OBJ_nid2sn(nid)); + VALUE str = rb_sprintf("#<%"PRIsVALUE":%p", + rb_obj_class(self), (void *)self); + int nid = EVP_PKEY_id(pkey); +#ifdef OSSL_USE_PROVIDER + if (nid != EVP_PKEY_KEYMGMT) +#endif + rb_str_catf(str, " oid=%s", OBJ_nid2sn(nid)); +#ifdef OSSL_USE_PROVIDER + rb_str_catf(str, " type_name=%s", EVP_PKEY_get0_type_name(pkey)); + const OSSL_PROVIDER *prov = EVP_PKEY_get0_provider(pkey); + if (prov) + rb_str_catf(str, " provider=%s", OSSL_PROVIDER_get0_name(prov)); +#endif + rb_str_catf(str, ">"); + return str; } /* @@ -799,20 +834,9 @@ ossl_pkey_export_traditional(int argc, VALUE *argv, VALUE self, int to_der) } } else { -#if OSSL_OPENSSL_PREREQ(1, 1, 0) || OSSL_LIBRESSL_PREREQ(3, 5, 0) if (!PEM_write_bio_PrivateKey_traditional(bio, pkey, enc, NULL, 0, ossl_pem_passwd_cb, (void *)pass)) { -#else - char pem_str[80]; - const char *aname; - - EVP_PKEY_asn1_get0_info(NULL, NULL, NULL, NULL, &aname, pkey->ameth); - snprintf(pem_str, sizeof(pem_str), "%s PRIVATE KEY", aname); - if (!PEM_ASN1_write_bio((i2d_of_void *)i2d_PrivateKey, pem_str, bio, - pkey, enc, NULL, 0, ossl_pem_passwd_cb, - (void *)pass)) { -#endif BIO_free(bio); ossl_raise(ePKeyError, "PEM_write_bio_PrivateKey_traditional"); } @@ -901,7 +925,6 @@ ossl_pkey_private_to_pem(int argc, VALUE *argv, VALUE self) return do_pkcs8_export(argc, argv, self, 0); } -#ifdef HAVE_EVP_PKEY_NEW_RAW_PRIVATE_KEY /* * call-seq: * pkey.raw_private_key => string @@ -928,7 +951,6 @@ ossl_pkey_raw_private_key(VALUE self) return str; } -#endif VALUE ossl_pkey_export_spki(VALUE self, int to_der) @@ -937,6 +959,7 @@ ossl_pkey_export_spki(VALUE self, int to_der) BIO *bio; GetPKey(self, pkey); + ossl_pkey_check_public_key(pkey); bio = BIO_new(BIO_s_mem()); if (!bio) ossl_raise(ePKeyError, "BIO_new"); @@ -985,7 +1008,6 @@ ossl_pkey_public_to_pem(VALUE self) return ossl_pkey_export_spki(self, 0); } -#ifdef HAVE_EVP_PKEY_NEW_RAW_PRIVATE_KEY /* * call-seq: * pkey.raw_public_key => string @@ -1012,7 +1034,6 @@ ossl_pkey_raw_public_key(VALUE self) return str; } -#endif /* * call-seq: @@ -1116,7 +1137,6 @@ ossl_pkey_sign(int argc, VALUE *argv, VALUE self) rb_jump_tag(state); } } -#if OSSL_OPENSSL_PREREQ(1, 1, 1) || OSSL_LIBRESSL_PREREQ(3, 4, 0) if (EVP_DigestSign(ctx, NULL, &siglen, (unsigned char *)RSTRING_PTR(data), RSTRING_LEN(data)) < 1) { EVP_MD_CTX_free(ctx); @@ -1137,30 +1157,6 @@ ossl_pkey_sign(int argc, VALUE *argv, VALUE self) EVP_MD_CTX_free(ctx); ossl_raise(ePKeyError, "EVP_DigestSign"); } -#else - if (EVP_DigestSignUpdate(ctx, RSTRING_PTR(data), RSTRING_LEN(data)) < 1) { - EVP_MD_CTX_free(ctx); - ossl_raise(ePKeyError, "EVP_DigestSignUpdate"); - } - if (EVP_DigestSignFinal(ctx, NULL, &siglen) < 1) { - EVP_MD_CTX_free(ctx); - ossl_raise(ePKeyError, "EVP_DigestSignFinal"); - } - if (siglen > LONG_MAX) { - EVP_MD_CTX_free(ctx); - rb_raise(ePKeyError, "signature would be too large"); - } - sig = ossl_str_new(NULL, (long)siglen, &state); - if (state) { - EVP_MD_CTX_free(ctx); - rb_jump_tag(state); - } - if (EVP_DigestSignFinal(ctx, (unsigned char *)RSTRING_PTR(sig), - &siglen) < 1) { - EVP_MD_CTX_free(ctx); - ossl_raise(ePKeyError, "EVP_DigestSignFinal"); - } -#endif EVP_MD_CTX_free(ctx); rb_str_set_len(sig, siglen); return sig; @@ -1221,24 +1217,12 @@ ossl_pkey_verify(int argc, VALUE *argv, VALUE self) rb_jump_tag(state); } } -#if OSSL_OPENSSL_PREREQ(1, 1, 1) || OSSL_LIBRESSL_PREREQ(3, 4, 0) ret = EVP_DigestVerify(ctx, (unsigned char *)RSTRING_PTR(sig), RSTRING_LEN(sig), (unsigned char *)RSTRING_PTR(data), RSTRING_LEN(data)); EVP_MD_CTX_free(ctx); if (ret < 0) ossl_raise(ePKeyError, "EVP_DigestVerify"); -#else - if (EVP_DigestVerifyUpdate(ctx, RSTRING_PTR(data), RSTRING_LEN(data)) < 1) { - EVP_MD_CTX_free(ctx); - ossl_raise(ePKeyError, "EVP_DigestVerifyUpdate"); - } - ret = EVP_DigestVerifyFinal(ctx, (unsigned char *)RSTRING_PTR(sig), - RSTRING_LEN(sig)); - EVP_MD_CTX_free(ctx); - if (ret < 0) - ossl_raise(ePKeyError, "EVP_DigestVerifyFinal"); -#endif if (ret) return Qtrue; else { @@ -1751,10 +1735,8 @@ Init_ossl_pkey(void) rb_define_module_function(mPKey, "read", ossl_pkey_new_from_data, -1); rb_define_module_function(mPKey, "generate_parameters", ossl_pkey_s_generate_parameters, -1); rb_define_module_function(mPKey, "generate_key", ossl_pkey_s_generate_key, -1); -#ifdef HAVE_EVP_PKEY_NEW_RAW_PRIVATE_KEY rb_define_module_function(mPKey, "new_raw_private_key", ossl_pkey_new_raw_private_key, 2); rb_define_module_function(mPKey, "new_raw_public_key", ossl_pkey_new_raw_public_key, 2); -#endif rb_define_alloc_func(cPKey, ossl_pkey_alloc); rb_define_method(cPKey, "initialize", ossl_pkey_initialize, 0); @@ -1770,10 +1752,8 @@ Init_ossl_pkey(void) rb_define_method(cPKey, "private_to_pem", ossl_pkey_private_to_pem, -1); rb_define_method(cPKey, "public_to_der", ossl_pkey_public_to_der, 0); rb_define_method(cPKey, "public_to_pem", ossl_pkey_public_to_pem, 0); -#ifdef HAVE_EVP_PKEY_NEW_RAW_PRIVATE_KEY rb_define_method(cPKey, "raw_private_key", ossl_pkey_raw_private_key, 0); rb_define_method(cPKey, "raw_public_key", ossl_pkey_raw_public_key, 0); -#endif rb_define_method(cPKey, "compare?", ossl_pkey_compare, 1); rb_define_method(cPKey, "sign", ossl_pkey_sign, -1); diff --git a/ext/openssl/ossl_pkey.h b/ext/openssl/ossl_pkey.h index 10669b824c8814..fdc5e94aed0e8c 100644 --- a/ext/openssl/ossl_pkey.h +++ b/ext/openssl/ossl_pkey.h @@ -5,7 +5,7 @@ */ /* * This program is licensed under the same licence as Ruby. - * (See the file 'LICENCE'.) + * (See the file 'COPYING'.) */ #if !defined(OSSL_PKEY_H) #define OSSL_PKEY_H @@ -53,35 +53,24 @@ void Init_ossl_pkey(void); * RSA */ extern VALUE cRSA; -extern VALUE eRSAError; - void Init_ossl_rsa(void); /* * DSA */ extern VALUE cDSA; -extern VALUE eDSAError; - void Init_ossl_dsa(void); /* * DH */ extern VALUE cDH; -extern VALUE eDHError; - void Init_ossl_dh(void); /* * EC */ extern VALUE cEC; -extern VALUE eECError; -extern VALUE cEC_GROUP; -extern VALUE eEC_GROUP; -extern VALUE cEC_POINT; -extern VALUE eEC_POINT; VALUE ossl_ec_new(EVP_PKEY *); void Init_ossl_ec(void); @@ -136,7 +125,7 @@ static VALUE ossl_##_keytype##_set_##_group(VALUE self, VALUE v1, VALUE v2, VALU BN_clear_free(bn1); \ BN_clear_free(bn2); \ BN_clear_free(bn3); \ - ossl_raise(eBNError, NULL); \ + ossl_raise(ePKeyError, "BN_dup"); \ } \ \ if (!_type##_set0_##_group(obj, bn1, bn2, bn3)) { \ @@ -164,7 +153,7 @@ static VALUE ossl_##_keytype##_set_##_group(VALUE self, VALUE v1, VALUE v2) \ (orig_bn2 && !(bn2 = BN_dup(orig_bn2)))) { \ BN_clear_free(bn1); \ BN_clear_free(bn2); \ - ossl_raise(eBNError, NULL); \ + ossl_raise(ePKeyError, "BN_dup"); \ } \ \ if (!_type##_set0_##_group(obj, bn1, bn2)) { \ diff --git a/ext/openssl/ossl_pkey_dh.c b/ext/openssl/ossl_pkey_dh.c index a231814a99b875..118d29f04fffed 100644 --- a/ext/openssl/ossl_pkey_dh.c +++ b/ext/openssl/ossl_pkey_dh.c @@ -5,7 +5,7 @@ */ /* * This program is licensed under the same licence as Ruby. - * (See the file 'LICENCE'.) + * (See the file 'COPYING'.) */ #include "ossl.h" @@ -27,7 +27,7 @@ * Classes */ VALUE cDH; -VALUE eDHError; +static VALUE eDHError; /* * Private @@ -128,6 +128,7 @@ ossl_dh_initialize(int argc, VALUE *argv, VALUE self) } #ifndef HAVE_EVP_PKEY_DUP +/* :nodoc: */ static VALUE ossl_dh_initialize_copy(VALUE self, VALUE other) { @@ -284,35 +285,6 @@ ossl_dh_to_der(VALUE self) return str; } -/* - * call-seq: - * dh.params -> hash - * - * Stores all parameters of key to the hash - * INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!! - * Don't use :-)) (I's up to you) - */ -static VALUE -ossl_dh_get_params(VALUE self) -{ - OSSL_3_const DH *dh; - VALUE hash; - const BIGNUM *p, *q, *g, *pub_key, *priv_key; - - GetDH(self, dh); - DH_get0_pqg(dh, &p, &q, &g); - DH_get0_key(dh, &pub_key, &priv_key); - - hash = rb_hash_new(); - rb_hash_aset(hash, rb_str_new2("p"), ossl_bn_new(p)); - rb_hash_aset(hash, rb_str_new2("q"), ossl_bn_new(q)); - rb_hash_aset(hash, rb_str_new2("g"), ossl_bn_new(g)); - rb_hash_aset(hash, rb_str_new2("pub_key"), ossl_bn_new(pub_key)); - rb_hash_aset(hash, rb_str_new2("priv_key"), ossl_bn_new(priv_key)); - - return hash; -} - /* * call-seq: * dh.params_ok? -> true | false @@ -443,8 +415,6 @@ Init_ossl_dh(void) DEF_OSSL_PKEY_BN(cDH, dh, priv_key); rb_define_method(cDH, "set_pqg", ossl_dh_set_pqg, 3); rb_define_method(cDH, "set_key", ossl_dh_set_key, 2); - - rb_define_method(cDH, "params", ossl_dh_get_params, 0); } #else /* defined NO_DH */ diff --git a/ext/openssl/ossl_pkey_dsa.c b/ext/openssl/ossl_pkey_dsa.c index 058ce738882adb..9f4f012cfe1686 100644 --- a/ext/openssl/ossl_pkey_dsa.c +++ b/ext/openssl/ossl_pkey_dsa.c @@ -5,7 +5,7 @@ */ /* * This program is licensed under the same licence as Ruby. - * (See the file 'LICENCE'.) + * (See the file 'COPYING'.) */ #include "ossl.h" @@ -41,7 +41,7 @@ DSA_PRIVATE(VALUE obj, OSSL_3_const DSA *dsa) * Classes */ VALUE cDSA; -VALUE eDSAError; +static VALUE eDSAError; /* * Private @@ -140,6 +140,7 @@ ossl_dsa_initialize(int argc, VALUE *argv, VALUE self) } #ifndef HAVE_EVP_PKEY_DUP +/* :nodoc: */ static VALUE ossl_dsa_initialize_copy(VALUE self, VALUE other) { @@ -303,35 +304,6 @@ ossl_dsa_to_der(VALUE self) } -/* - * call-seq: - * dsa.params -> hash - * - * Stores all parameters of key to the hash - * INSECURE: PRIVATE INFORMATIONS CAN LEAK OUT!!! - * Don't use :-)) (I's up to you) - */ -static VALUE -ossl_dsa_get_params(VALUE self) -{ - OSSL_3_const DSA *dsa; - VALUE hash; - const BIGNUM *p, *q, *g, *pub_key, *priv_key; - - GetDSA(self, dsa); - DSA_get0_pqg(dsa, &p, &q, &g); - DSA_get0_key(dsa, &pub_key, &priv_key); - - hash = rb_hash_new(); - rb_hash_aset(hash, rb_str_new2("p"), ossl_bn_new(p)); - rb_hash_aset(hash, rb_str_new2("q"), ossl_bn_new(q)); - rb_hash_aset(hash, rb_str_new2("g"), ossl_bn_new(g)); - rb_hash_aset(hash, rb_str_new2("pub_key"), ossl_bn_new(pub_key)); - rb_hash_aset(hash, rb_str_new2("priv_key"), ossl_bn_new(priv_key)); - - return hash; -} - /* * Document-method: OpenSSL::PKey::DSA#set_pqg * call-seq: @@ -396,8 +368,6 @@ Init_ossl_dsa(void) DEF_OSSL_PKEY_BN(cDSA, dsa, priv_key); rb_define_method(cDSA, "set_pqg", ossl_dsa_set_pqg, 3); rb_define_method(cDSA, "set_key", ossl_dsa_set_key, 2); - - rb_define_method(cDSA, "params", ossl_dsa_get_params, 0); } #else /* defined NO_DSA */ diff --git a/ext/openssl/ossl_pkey_ec.c b/ext/openssl/ossl_pkey_ec.c index 4b3a1fd0febb09..45e8bf19b246e7 100644 --- a/ext/openssl/ossl_pkey_ec.c +++ b/ext/openssl/ossl_pkey_ec.c @@ -41,17 +41,14 @@ static const rb_data_type_t ossl_ec_point_type; } while (0) VALUE cEC; -VALUE eECError; -VALUE cEC_GROUP; -VALUE eEC_GROUP; -VALUE cEC_POINT; -VALUE eEC_POINT; +static VALUE eECError; +static VALUE cEC_GROUP; +static VALUE eEC_GROUP; +static VALUE cEC_POINT; +static VALUE eEC_POINT; -static ID s_GFp, s_GF2m; - -static ID ID_uncompressed; -static ID ID_compressed; -static ID ID_hybrid; +static VALUE sym_GFp, sym_GF2m; +static VALUE sym_uncompressed, sym_compressed, sym_hybrid; static ID id_i_group; @@ -174,7 +171,7 @@ static VALUE ossl_ec_key_initialize(int argc, VALUE *argv, VALUE self) type = EVP_PKEY_base_id(pkey); if (type != EVP_PKEY_EC) { EVP_PKEY_free(pkey); - rb_raise(eDSAError, "incorrect pkey type: %s", OBJ_nid2sn(type)); + rb_raise(eECError, "incorrect pkey type: %s", OBJ_nid2sn(type)); } RTYPEDDATA_DATA(self) = pkey; return self; @@ -191,6 +188,7 @@ static VALUE ossl_ec_key_initialize(int argc, VALUE *argv, VALUE self) } #ifndef HAVE_EVP_PKEY_DUP +/* :nodoc: */ static VALUE ossl_ec_key_initialize_copy(VALUE self, VALUE other) { @@ -657,8 +655,11 @@ static VALUE ossl_ec_group_initialize(int argc, VALUE *argv, VALUE self) ossl_clear_error(); /* ignore errors in d2i_ECPKParameters_bio() */ if (nid == NID_undef) ossl_raise(eEC_GROUP, "unknown curve name (%"PRIsVALUE")", arg1); - +#if !defined(OPENSSL_IS_AWSLC) group = EC_GROUP_new_by_curve_name(nid); +#else /* EC_GROUPs are static and immutable by default in AWS-LC. */ + group = EC_GROUP_new_by_curve_name_mutable(nid); +#endif if (group == NULL) ossl_raise(eEC_GROUP, "unable to create curve (%"PRIsVALUE")", arg1); @@ -670,19 +671,20 @@ static VALUE ossl_ec_group_initialize(int argc, VALUE *argv, VALUE self) break; case 4: if (SYMBOL_P(arg1)) { - ID id = SYM2ID(arg1); EC_GROUP *(*new_curve)(const BIGNUM *, const BIGNUM *, const BIGNUM *, BN_CTX *) = NULL; const BIGNUM *p = GetBNPtr(arg2); const BIGNUM *a = GetBNPtr(arg3); const BIGNUM *b = GetBNPtr(arg4); - if (id == s_GFp) { + if (arg1 == sym_GFp) { new_curve = EC_GROUP_new_curve_GFp; + } #if !defined(OPENSSL_NO_EC2M) - } else if (id == s_GF2m) { + else if (arg1 == sym_GF2m) { new_curve = EC_GROUP_new_curve_GF2m; + } #endif - } else { + else { ossl_raise(rb_eArgError, "unknown symbol, must be :GFp or :GF2m"); } @@ -703,6 +705,7 @@ static VALUE ossl_ec_group_initialize(int argc, VALUE *argv, VALUE self) return self; } +/* :nodoc: */ static VALUE ossl_ec_group_initialize_copy(VALUE self, VALUE other) { @@ -953,37 +956,36 @@ static VALUE ossl_ec_group_set_asn1_flag(VALUE self, VALUE flag_v) */ static VALUE ossl_ec_group_get_point_conversion_form(VALUE self) { - EC_GROUP *group = NULL; + EC_GROUP *group; point_conversion_form_t form; - VALUE ret; GetECGroup(self, group); form = EC_GROUP_get_point_conversion_form(group); switch (form) { - case POINT_CONVERSION_UNCOMPRESSED: ret = ID_uncompressed; break; - case POINT_CONVERSION_COMPRESSED: ret = ID_compressed; break; - case POINT_CONVERSION_HYBRID: ret = ID_hybrid; break; - default: ossl_raise(eEC_GROUP, "unsupported point conversion form: %d, this module should be updated", form); + case POINT_CONVERSION_UNCOMPRESSED: + return sym_uncompressed; + case POINT_CONVERSION_COMPRESSED: + return sym_compressed; + case POINT_CONVERSION_HYBRID: + return sym_hybrid; + default: + ossl_raise(eEC_GROUP, "unsupported point conversion form: %d, " \ + "this module should be updated", form); } - - return ID2SYM(ret); } static point_conversion_form_t parse_point_conversion_form_symbol(VALUE sym) { - ID id = SYM2ID(sym); - - if (id == ID_uncompressed) + if (sym == sym_uncompressed) return POINT_CONVERSION_UNCOMPRESSED; - else if (id == ID_compressed) + if (sym == sym_compressed) return POINT_CONVERSION_COMPRESSED; - else if (id == ID_hybrid) + if (sym == sym_hybrid) return POINT_CONVERSION_HYBRID; - else - ossl_raise(rb_eArgError, "unsupported point conversion form %+"PRIsVALUE - " (expected :compressed, :uncompressed, or :hybrid)", sym); + ossl_raise(rb_eArgError, "unsupported point conversion form %+"PRIsVALUE + " (expected :compressed, :uncompressed, or :hybrid)", sym); } /* @@ -1258,6 +1260,7 @@ static VALUE ossl_ec_point_initialize(int argc, VALUE *argv, VALUE self) return self; } +/* :nodoc: */ static VALUE ossl_ec_point_initialize_copy(VALUE self, VALUE other) { @@ -1367,7 +1370,7 @@ static VALUE ossl_ec_point_make_affine(VALUE self) GetECPointGroup(self, group); rb_warn("OpenSSL::PKey::EC::Point#make_affine! is deprecated"); -#if !OSSL_OPENSSL_PREREQ(3, 0, 0) +#if !OSSL_OPENSSL_PREREQ(3, 0, 0) && !defined(OPENSSL_IS_AWSLC) if (EC_POINT_make_affine(group, point, ossl_bn_ctx) != 1) ossl_raise(eEC_POINT, "EC_POINT_make_affine"); #endif @@ -1478,7 +1481,6 @@ static VALUE ossl_ec_point_add(VALUE self, VALUE other) /* * call-seq: * point.mul(bn1 [, bn2]) => point - * point.mul(bns, points [, bn2]) => point * * Performs elliptic curve point multiplication. * @@ -1486,11 +1488,9 @@ static VALUE ossl_ec_point_add(VALUE self, VALUE other) * generator of the group of _point_. _bn2_ may be omitted, and in that case, * the result is just bn1 * point. * - * The second form calculates bns[0] * point + bns[1] * points[0] + ... - * + bns[-1] * points[-1] + bn2 * G. _bn2_ may be omitted. _bns_ must be - * an array of OpenSSL::BN. _points_ must be an array of - * OpenSSL::PKey::EC::Point. Please note that points[0] is not - * multiplied by bns[0], but bns[1]. + * Before version 4.0.0, and when compiled with OpenSSL 1.1.1 or older, this + * method allowed another form: + * point.mul(bns, points [, bn2]) => point */ static VALUE ossl_ec_point_mul(int argc, VALUE *argv, VALUE self) { @@ -1508,62 +1508,15 @@ static VALUE ossl_ec_point_mul(int argc, VALUE *argv, VALUE self) GetECPoint(result, point_result); rb_scan_args(argc, argv, "12", &arg1, &arg2, &arg3); - if (!RB_TYPE_P(arg1, T_ARRAY)) { - BIGNUM *bn = GetBNPtr(arg1); + if (RB_TYPE_P(arg1, T_ARRAY) || argc > 2) + rb_raise(rb_eNotImpError, "OpenSSL::PKey::EC::Point#mul with arrays " \ + "is no longer supported"); - if (!NIL_P(arg2)) - bn_g = GetBNPtr(arg2); - if (EC_POINT_mul(group, point_result, bn_g, point_self, bn, ossl_bn_ctx) != 1) - ossl_raise(eEC_POINT, NULL); - } else { -#if (defined(OPENSSL_VERSION_MAJOR) && OPENSSL_VERSION_MAJOR >= 3) || defined(LIBRESSL_VERSION_NUMBER) - rb_raise(rb_eNotImpError, "calling #mul with arrays is not" \ - "supported by this OpenSSL version"); -#else - /* - * bignums | arg1[0] | arg1[1] | arg1[2] | ... - * points | self | arg2[0] | arg2[1] | ... - */ - long i, num; - VALUE bns_tmp, tmp_p, tmp_b; - const EC_POINT **points; - const BIGNUM **bignums; - - Check_Type(arg1, T_ARRAY); - Check_Type(arg2, T_ARRAY); - if (RARRAY_LEN(arg1) != RARRAY_LEN(arg2) + 1) /* arg2 must be 1 larger */ - ossl_raise(rb_eArgError, "bns must be 1 longer than points; see the documentation"); - - rb_warning("OpenSSL::PKey::EC::Point#mul(ary, ary) is deprecated; " \ - "use #mul(bn) form instead"); - - num = RARRAY_LEN(arg1); - bns_tmp = rb_ary_tmp_new(num); - bignums = ALLOCV_N(const BIGNUM *, tmp_b, num); - for (i = 0; i < num; i++) { - VALUE item = RARRAY_AREF(arg1, i); - bignums[i] = GetBNPtr(item); - rb_ary_push(bns_tmp, item); - } - - points = ALLOCV_N(const EC_POINT *, tmp_p, num); - points[0] = point_self; /* self */ - for (i = 0; i < num - 1; i++) - GetECPoint(RARRAY_AREF(arg2, i), points[i + 1]); - - if (!NIL_P(arg3)) - bn_g = GetBNPtr(arg3); - - if (EC_POINTs_mul(group, point_result, bn_g, num, points, bignums, ossl_bn_ctx) != 1) { - ALLOCV_END(tmp_b); - ALLOCV_END(tmp_p); - ossl_raise(eEC_POINT, NULL); - } - - ALLOCV_END(tmp_b); - ALLOCV_END(tmp_p); -#endif - } + BIGNUM *bn = GetBNPtr(arg1); + if (!NIL_P(arg2)) + bn_g = GetBNPtr(arg2); + if (EC_POINT_mul(group, point_result, bn_g, point_self, bn, ossl_bn_ctx) != 1) + ossl_raise(eEC_POINT, NULL); return result; } @@ -1601,17 +1554,15 @@ void Init_ossl_ec(void) eEC_GROUP = rb_define_class_under(cEC_GROUP, "Error", eOSSLError); eEC_POINT = rb_define_class_under(cEC_POINT, "Error", eOSSLError); - s_GFp = rb_intern("GFp"); - s_GF2m = rb_intern("GF2m"); + sym_GFp = ID2SYM(rb_intern_const("GFp")); + sym_GF2m = ID2SYM(rb_intern_const("GF2m")); - ID_uncompressed = rb_intern("uncompressed"); - ID_compressed = rb_intern("compressed"); - ID_hybrid = rb_intern("hybrid"); + sym_uncompressed = ID2SYM(rb_intern_const("uncompressed")); + sym_compressed = ID2SYM(rb_intern_const("compressed")); + sym_hybrid = ID2SYM(rb_intern_const("hybrid")); rb_define_const(cEC, "NAMED_CURVE", INT2NUM(OPENSSL_EC_NAMED_CURVE)); -#if defined(OPENSSL_EC_EXPLICIT_CURVE) rb_define_const(cEC, "EXPLICIT_CURVE", INT2NUM(OPENSSL_EC_EXPLICIT_CURVE)); -#endif rb_define_singleton_method(cEC, "builtin_curves", ossl_s_builtin_curves, 0); diff --git a/ext/openssl/ossl_pkey_rsa.c b/ext/openssl/ossl_pkey_rsa.c index 389f76f309e3b4..185b47cbfb6561 100644 --- a/ext/openssl/ossl_pkey_rsa.c +++ b/ext/openssl/ossl_pkey_rsa.c @@ -5,7 +5,7 @@ */ /* * This program is licensed under the same licence as Ruby. - * (See the file 'LICENCE'.) + * (See the file 'COPYING'.) */ #include "ossl.h" @@ -42,7 +42,7 @@ RSA_PRIVATE(VALUE obj, OSSL_3_const RSA *rsa) * Classes */ VALUE cRSA; -VALUE eRSAError; +static VALUE eRSAError; /* * Private @@ -136,6 +136,7 @@ ossl_rsa_initialize(int argc, VALUE *argv, VALUE self) } #ifndef HAVE_EVP_PKEY_DUP +/* :nodoc: */ static VALUE ossl_rsa_initialize_copy(VALUE self, VALUE other) { @@ -494,42 +495,6 @@ ossl_rsa_verify_pss(int argc, VALUE *argv, VALUE self) ossl_raise(eRSAError, NULL); } -/* - * call-seq: - * rsa.params => hash - * - * THIS METHOD IS INSECURE, PRIVATE INFORMATION CAN LEAK OUT!!! - * - * Stores all parameters of key to the hash. The hash has keys 'n', 'e', 'd', - * 'p', 'q', 'dmp1', 'dmq1', 'iqmp'. - * - * Don't use :-)) (It's up to you) - */ -static VALUE -ossl_rsa_get_params(VALUE self) -{ - OSSL_3_const RSA *rsa; - VALUE hash; - const BIGNUM *n, *e, *d, *p, *q, *dmp1, *dmq1, *iqmp; - - GetRSA(self, rsa); - RSA_get0_key(rsa, &n, &e, &d); - RSA_get0_factors(rsa, &p, &q); - RSA_get0_crt_params(rsa, &dmp1, &dmq1, &iqmp); - - hash = rb_hash_new(); - rb_hash_aset(hash, rb_str_new2("n"), ossl_bn_new(n)); - rb_hash_aset(hash, rb_str_new2("e"), ossl_bn_new(e)); - rb_hash_aset(hash, rb_str_new2("d"), ossl_bn_new(d)); - rb_hash_aset(hash, rb_str_new2("p"), ossl_bn_new(p)); - rb_hash_aset(hash, rb_str_new2("q"), ossl_bn_new(q)); - rb_hash_aset(hash, rb_str_new2("dmp1"), ossl_bn_new(dmp1)); - rb_hash_aset(hash, rb_str_new2("dmq1"), ossl_bn_new(dmq1)); - rb_hash_aset(hash, rb_str_new2("iqmp"), ossl_bn_new(iqmp)); - - return hash; -} - /* * Document-method: OpenSSL::PKey::RSA#set_key * call-seq: @@ -617,8 +582,6 @@ Init_ossl_rsa(void) rb_define_method(cRSA, "set_factors", ossl_rsa_set_factors, 2); rb_define_method(cRSA, "set_crt_params", ossl_rsa_set_crt_params, 3); - rb_define_method(cRSA, "params", ossl_rsa_get_params, 0); - /* * TODO: Test it rb_define_method(cRSA, "blinding_on!", ossl_rsa_blinding_on, 0); diff --git a/ext/openssl/ossl_provider.c b/ext/openssl/ossl_provider.c index 981c6ccdc7aa5e..529a5e1c72ab0a 100644 --- a/ext/openssl/ossl_provider.c +++ b/ext/openssl/ossl_provider.c @@ -1,12 +1,10 @@ /* * This program is licensed under the same licence as Ruby. - * (See the file 'LICENCE'.) + * (See the file 'COPYING'.) */ #include "ossl.h" #ifdef OSSL_USE_PROVIDER -# include - #define NewProvider(klass) \ TypedData_Wrap_Struct((klass), &ossl_provider_type, 0) #define SetProvider(obj, provider) do { \ diff --git a/ext/openssl/ossl_rand.c b/ext/openssl/ossl_rand.c index 659dc818b6eda2..764900dfc656ba 100644 --- a/ext/openssl/ossl_rand.c +++ b/ext/openssl/ossl_rand.c @@ -5,12 +5,12 @@ * All rights reserved. * * This program is licensed under the same licence as Ruby. - * (See the file 'LICENCE'.) + * (See the file 'COPYING'.) */ #include "ossl.h" -VALUE mRandom; -VALUE eRandomError; +static VALUE mRandom; +static VALUE eRandomError; /* * call-seq: @@ -189,9 +189,7 @@ Init_ossl_rand(void) rb_define_module_function(mRandom, "load_random_file", ossl_rand_load_file, 1); rb_define_module_function(mRandom, "write_random_file", ossl_rand_write_file, 1); rb_define_module_function(mRandom, "random_bytes", ossl_rand_bytes, 1); -#if OPENSSL_VERSION_NUMBER < 0x10101000 || defined(LIBRESSL_VERSION_NUMBER) rb_define_alias(rb_singleton_class(mRandom), "pseudo_bytes", "random_bytes"); -#endif #ifdef HAVE_RAND_EGD rb_define_module_function(mRandom, "egd", ossl_rand_egd, 1); rb_define_module_function(mRandom, "egd_bytes", ossl_rand_egd_bytes, 2); diff --git a/ext/openssl/ossl_rand.h b/ext/openssl/ossl_rand.h index 8f77a3b239cfa7..294986d0173266 100644 --- a/ext/openssl/ossl_rand.h +++ b/ext/openssl/ossl_rand.h @@ -5,14 +5,11 @@ */ /* * This program is licensed under the same licence as Ruby. - * (See the file 'LICENCE'.) + * (See the file 'COPYING'.) */ #if !defined(_OSSL_RAND_H_) #define _OSSL_RAND_H_ -extern VALUE mRandom; -extern VALUE eRandomError; - void Init_ossl_rand(void); #endif /* _OSSL_RAND_H_ */ diff --git a/ext/openssl/ossl_ssl.c b/ext/openssl/ossl_ssl.c index 236d455ff2a48e..b5872f588125c2 100644 --- a/ext/openssl/ossl_ssl.c +++ b/ext/openssl/ossl_ssl.c @@ -7,7 +7,7 @@ */ /* * This program is licensed under the same licence as Ruby. - * (See the file 'LICENCE'.) + * (See the file 'COPYING'.) */ #include "ossl.h" @@ -18,11 +18,6 @@ # define OSSL_USE_NEXTPROTONEG #endif -#if !defined(TLS1_3_VERSION) && \ - OSSL_LIBRESSL_PREREQ(3, 2, 0) && !OSSL_LIBRESSL_PREREQ(3, 4, 0) -# define TLS1_3_VERSION 0x0304 -#endif - #ifdef _WIN32 # define TO_SOCKET(s) _get_osfhandle(s) #else @@ -35,7 +30,7 @@ VALUE mSSL; static VALUE eSSLError; -VALUE cSSLContext; +static VALUE cSSLContext; VALUE cSSLSocket; static VALUE eSSLErrorWaitReadable; @@ -55,7 +50,6 @@ static ID id_i_cert_store, id_i_ca_file, id_i_ca_path, id_i_verify_mode, id_i_verify_hostname, id_i_keylog_cb; static ID id_i_io, id_i_context, id_i_hostname; -static int ossl_ssl_ex_vcb_idx; static int ossl_ssl_ex_ptr_idx; static int ossl_sslctx_ex_ptr_idx; @@ -91,11 +85,7 @@ ossl_sslctx_s_alloc(VALUE klass) VALUE obj; obj = TypedData_Wrap_Struct(klass, &ossl_sslctx_type, 0); -#if OPENSSL_VERSION_NUMBER >= 0x10100000 || defined(LIBRESSL_VERSION_NUMBER) ctx = SSL_CTX_new(TLS_method()); -#else - ctx = SSL_CTX_new(SSLv23_method()); -#endif if (!ctx) { ossl_raise(eSSLError, "SSL_CTX_new"); } @@ -103,109 +93,9 @@ ossl_sslctx_s_alloc(VALUE klass) RTYPEDDATA_DATA(obj) = ctx; SSL_CTX_set_ex_data(ctx, ossl_sslctx_ex_ptr_idx, (void *)obj); -#if !defined(OPENSSL_NO_EC) && OPENSSL_VERSION_NUMBER < 0x10100000 && \ - !defined(LIBRESSL_VERSION_NUMBER) - /* We use SSL_CTX_set1_curves_list() to specify the curve used in ECDH. It - * allows to specify multiple curve names and OpenSSL will select - * automatically from them. In OpenSSL 1.0.2, the automatic selection has to - * be enabled explicitly. OpenSSL 1.1.0 and LibreSSL 2.6.1 removed the knob - * and it is always enabled. To uniform the behavior, we enable the - * automatic selection also in 1.0.2. Users can still disable ECDH by - * removing ECDH cipher suites by SSLContext#ciphers=. */ - if (!SSL_CTX_set_ecdh_auto(ctx, 1)) - ossl_raise(eSSLError, "SSL_CTX_set_ecdh_auto"); -#endif - return obj; } -static int -parse_proto_version(VALUE str) -{ - int i; - static const struct { - const char *name; - int version; - } map[] = { - { "SSL2", SSL2_VERSION }, - { "SSL3", SSL3_VERSION }, - { "TLS1", TLS1_VERSION }, - { "TLS1_1", TLS1_1_VERSION }, - { "TLS1_2", TLS1_2_VERSION }, -#ifdef TLS1_3_VERSION - { "TLS1_3", TLS1_3_VERSION }, -#endif - }; - - if (NIL_P(str)) - return 0; - if (RB_INTEGER_TYPE_P(str)) - return NUM2INT(str); - - if (SYMBOL_P(str)) - str = rb_sym2str(str); - StringValue(str); - for (i = 0; i < numberof(map); i++) - if (!strncmp(map[i].name, RSTRING_PTR(str), RSTRING_LEN(str))) - return map[i].version; - rb_raise(rb_eArgError, "unrecognized version %+"PRIsVALUE, str); -} - -/* - * call-seq: - * ctx.set_minmax_proto_version(min, max) -> nil - * - * Sets the minimum and maximum supported protocol versions. See #min_version= - * and #max_version=. - */ -static VALUE -ossl_sslctx_set_minmax_proto_version(VALUE self, VALUE min_v, VALUE max_v) -{ - SSL_CTX *ctx; - int min, max; - - GetSSLCTX(self, ctx); - min = parse_proto_version(min_v); - max = parse_proto_version(max_v); - -#ifdef HAVE_SSL_CTX_SET_MIN_PROTO_VERSION - if (!SSL_CTX_set_min_proto_version(ctx, min)) - ossl_raise(eSSLError, "SSL_CTX_set_min_proto_version"); - if (!SSL_CTX_set_max_proto_version(ctx, max)) - ossl_raise(eSSLError, "SSL_CTX_set_max_proto_version"); -#else - { - unsigned long sum = 0, opts = 0; - int i; - static const struct { - int ver; - unsigned long opts; - } options_map[] = { - { SSL2_VERSION, SSL_OP_NO_SSLv2 }, - { SSL3_VERSION, SSL_OP_NO_SSLv3 }, - { TLS1_VERSION, SSL_OP_NO_TLSv1 }, - { TLS1_1_VERSION, SSL_OP_NO_TLSv1_1 }, - { TLS1_2_VERSION, SSL_OP_NO_TLSv1_2 }, -# if defined(TLS1_3_VERSION) - { TLS1_3_VERSION, SSL_OP_NO_TLSv1_3 }, -# endif - }; - - for (i = 0; i < numberof(options_map); i++) { - sum |= options_map[i].opts; - if ((min && min > options_map[i].ver) || - (max && max < options_map[i].ver)) { - opts |= options_map[i].opts; - } - } - SSL_CTX_clear_options(ctx, sum); - SSL_CTX_set_options(ctx, opts); - } -#endif - - return Qnil; -} - static VALUE ossl_call_client_cert_cb(VALUE obj) { @@ -327,9 +217,9 @@ ossl_ssl_verify_callback(int preverify_ok, X509_STORE_CTX *ctx) int status; ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx()); - cb = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_vcb_idx); ssl_obj = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx); sslctx_obj = rb_attr_get(ssl_obj, id_i_context); + cb = rb_attr_get(sslctx_obj, id_i_verify_callback); verify_hostname = rb_attr_get(sslctx_obj, id_i_verify_hostname); if (preverify_ok && RTEST(verify_hostname) && !SSL_is_server(ssl) && @@ -341,11 +231,7 @@ ossl_ssl_verify_callback(int preverify_ok, X509_STORE_CTX *ctx) } if (ret != Qtrue) { preverify_ok = 0; -#if defined(X509_V_ERR_HOSTNAME_MISMATCH) X509_STORE_CTX_set_error(ctx, X509_V_ERR_HOSTNAME_MISMATCH); -#else - X509_STORE_CTX_set_error(ctx, X509_V_ERR_CERT_REJECTED); -#endif } } @@ -367,11 +253,7 @@ ossl_call_session_get_cb(VALUE ary) } static SSL_SESSION * -#if defined(LIBRESSL_VERSION_NUMBER) || OPENSSL_VERSION_NUMBER >= 0x10100000 ossl_sslctx_session_get_cb(SSL *ssl, const unsigned char *buf, int len, int *copy) -#else -ossl_sslctx_session_get_cb(SSL *ssl, unsigned char *buf, int len, int *copy) -#endif { VALUE ary, ssl_obj, ret_obj; SSL_SESSION *sess; @@ -444,7 +326,7 @@ ossl_sslctx_session_new_cb(SSL *ssl, SSL_SESSION *sess) return 0; } -#if OPENSSL_VERSION_NUMBER >= 0x10101000 && !defined(LIBRESSL_VERSION_NUMBER) +#if !OSSL_IS_LIBRESSL /* * It is only compatible with OpenSSL >= 1.1.1. Even if LibreSSL implements * SSL_CTX_set_keylog_callback() from v3.4.2, it does nothing (see @@ -548,8 +430,9 @@ ossl_sslctx_add_extra_chain_cert_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, arg)) GetSSLCTX(arg, ctx); x509 = DupX509CertPtr(i); - if(!SSL_CTX_add_extra_chain_cert(ctx, x509)){ - ossl_raise(eSSLError, NULL); + if (!SSL_CTX_add_extra_chain_cert(ctx, x509)) { + X509_free(x509); + ossl_raise(eSSLError, "SSL_CTX_add_extra_chain_cert"); } return i; @@ -558,52 +441,42 @@ ossl_sslctx_add_extra_chain_cert_i(RB_BLOCK_CALL_FUNC_ARGLIST(i, arg)) static VALUE ossl_sslctx_setup(VALUE self); static VALUE -ossl_call_servername_cb(VALUE ary) +ossl_call_servername_cb(VALUE arg) { - VALUE ssl_obj, sslctx_obj, cb, ret_obj; - - Check_Type(ary, T_ARRAY); - ssl_obj = rb_ary_entry(ary, 0); + SSL *ssl = (void *)arg; + const char *servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name); + if (!servername) + return Qnil; - sslctx_obj = rb_attr_get(ssl_obj, id_i_context); - cb = rb_attr_get(sslctx_obj, id_i_servername_cb); - if (NIL_P(cb)) return Qnil; + VALUE ssl_obj = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx); + VALUE sslctx_obj = rb_attr_get(ssl_obj, id_i_context); + VALUE cb = rb_attr_get(sslctx_obj, id_i_servername_cb); + VALUE ary = rb_assoc_new(ssl_obj, rb_str_new_cstr(servername)); - ret_obj = rb_funcallv(cb, id_call, 1, &ary); + VALUE ret_obj = rb_funcallv(cb, id_call, 1, &ary); if (rb_obj_is_kind_of(ret_obj, cSSLContext)) { - SSL *ssl; SSL_CTX *ctx2; - ossl_sslctx_setup(ret_obj); - GetSSL(ssl_obj, ssl); GetSSLCTX(ret_obj, ctx2); - SSL_set_SSL_CTX(ssl, ctx2); + if (!SSL_set_SSL_CTX(ssl, ctx2)) + ossl_raise(eSSLError, "SSL_set_SSL_CTX"); rb_ivar_set(ssl_obj, id_i_context, ret_obj); } else if (!NIL_P(ret_obj)) { ossl_raise(rb_eArgError, "servername_cb must return an " "OpenSSL::SSL::SSLContext object or nil"); } - return ret_obj; + return Qnil; } static int ssl_servername_cb(SSL *ssl, int *ad, void *arg) { - VALUE ary, ssl_obj; - int state = 0; - const char *servername = SSL_get_servername(ssl, TLSEXT_NAMETYPE_host_name); - - if (!servername) - return SSL_TLSEXT_ERR_OK; - - ssl_obj = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx); - ary = rb_ary_new2(2); - rb_ary_push(ary, ssl_obj); - rb_ary_push(ary, rb_str_new2(servername)); + int state; - rb_protect(ossl_call_servername_cb, ary, &state); + rb_protect(ossl_call_servername_cb, (VALUE)ssl, &state); if (state) { + VALUE ssl_obj = (VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx); rb_ivar_set(ssl_obj, ID_callback_state, INT2NUM(state)); return SSL_TLSEXT_ERR_ALERT_FATAL; } @@ -757,7 +630,10 @@ ssl_info_cb(const SSL *ssl, int where, int val) } /* - * Gets various OpenSSL options. + * call-seq: + * ctx.options -> integer + * + * Gets various \OpenSSL options. */ static VALUE ossl_sslctx_get_options(VALUE self) @@ -772,7 +648,17 @@ ossl_sslctx_get_options(VALUE self) } /* - * Sets various OpenSSL options. + * call-seq: + * ctx.options = integer + * + * Sets various \OpenSSL options. The options are a bit field and can be + * combined with the bitwise OR operator (|). Available options are + * defined as constants in OpenSSL::SSL that begin with +OP_+. + * + * For backwards compatibility, passing +nil+ has the same effect as passing + * OpenSSL::SSL::OP_ALL. + * + * See also man page SSL_CTX_set_options(3). */ static VALUE ossl_sslctx_set_options(VALUE self, VALUE options) @@ -820,7 +706,7 @@ ossl_sslctx_setup(VALUE self) SSL_CTX_set_tmp_dh_callback(ctx, ossl_tmp_dh_callback); #endif -#ifdef HAVE_SSL_CTX_SET_POST_HANDSHAKE_AUTH +#if !defined(OPENSSL_IS_AWSLC) /* AWS-LC has no support for TLS 1.3 PHA. */ SSL_CTX_set_post_handshake_auth(ctx, 1); #endif @@ -962,7 +848,7 @@ ossl_sslctx_setup(VALUE self) OSSL_Debug("SSL TLSEXT servername callback added"); } -#if OPENSSL_VERSION_NUMBER >= 0x10101000 && !defined(LIBRESSL_VERSION_NUMBER) +#if !OSSL_IS_LIBRESSL /* * It is only compatible with OpenSSL >= 1.1.1. Even if LibreSSL implements * SSL_CTX_set_keylog_callback() from v3.4.2, it does nothing (see @@ -977,6 +863,93 @@ ossl_sslctx_setup(VALUE self) return Qtrue; } +static int +parse_proto_version(VALUE str) +{ + int i; + static const struct { + const char *name; + int version; + } map[] = { + { "SSL2", SSL2_VERSION }, + { "SSL3", SSL3_VERSION }, + { "TLS1", TLS1_VERSION }, + { "TLS1_1", TLS1_1_VERSION }, + { "TLS1_2", TLS1_2_VERSION }, + { "TLS1_3", TLS1_3_VERSION }, + }; + + if (NIL_P(str)) + return 0; + if (RB_INTEGER_TYPE_P(str)) + return NUM2INT(str); + + if (SYMBOL_P(str)) + str = rb_sym2str(str); + StringValue(str); + for (i = 0; i < numberof(map); i++) + if (!strncmp(map[i].name, RSTRING_PTR(str), RSTRING_LEN(str))) + return map[i].version; + rb_raise(rb_eArgError, "unrecognized version %+"PRIsVALUE, str); +} + +/* + * call-seq: + * ctx.min_version = OpenSSL::SSL::TLS1_2_VERSION + * ctx.min_version = :TLS1_2 + * ctx.min_version = nil + * + * Sets the lower bound on the supported SSL/TLS protocol version. The + * version may be specified by an integer constant named + * OpenSSL::SSL::*_VERSION, a Symbol, or +nil+ which means "any version". + * + * === Example + * ctx = OpenSSL::SSL::SSLContext.new + * ctx.min_version = OpenSSL::SSL::TLS1_1_VERSION + * ctx.max_version = OpenSSL::SSL::TLS1_2_VERSION + * + * sock = OpenSSL::SSL::SSLSocket.new(tcp_sock, ctx) + * sock.connect # Initiates a connection using either TLS 1.1 or TLS 1.2 + */ +static VALUE +ossl_sslctx_set_min_version(VALUE self, VALUE v) +{ + SSL_CTX *ctx; + int version; + + rb_check_frozen(self); + GetSSLCTX(self, ctx); + version = parse_proto_version(v); + + if (!SSL_CTX_set_min_proto_version(ctx, version)) + ossl_raise(eSSLError, "SSL_CTX_set_min_proto_version"); + return v; +} + +/* + * call-seq: + * ctx.max_version = OpenSSL::SSL::TLS1_2_VERSION + * ctx.max_version = :TLS1_2 + * ctx.max_version = nil + * + * Sets the upper bound of the supported SSL/TLS protocol version. See + * #min_version= for the possible values. + */ +static VALUE +ossl_sslctx_set_max_version(VALUE self, VALUE v) +{ + SSL_CTX *ctx; + int version; + + rb_check_frozen(self); + GetSSLCTX(self, ctx); + version = parse_proto_version(v); + + if (!SSL_CTX_set_max_proto_version(ctx, version)) + ossl_raise(eSSLError, "SSL_CTX_set_max_proto_version"); + return v; +} + static VALUE ossl_ssl_cipher_to_ary(const SSL_CIPHER *cipher) { @@ -1026,11 +999,10 @@ static VALUE build_cipher_string(VALUE v) { VALUE str, elem; - int i; if (RB_TYPE_P(v, T_ARRAY)) { str = rb_str_new(0, 0); - for (i = 0; i < RARRAY_LEN(v); i++) { + for (long i = 0; i < RARRAY_LEN(v); i++) { elem = rb_ary_entry(v, i); if (RB_TYPE_P(elem, T_ARRAY)) elem = rb_ary_entry(elem, 0); elem = rb_String(elem); @@ -1051,9 +1023,14 @@ build_cipher_string(VALUE v) * ctx.ciphers = [name, ...] * ctx.ciphers = [[name, version, bits, alg_bits], ...] * - * Sets the list of available cipher suites for this context. Note in a server - * context some ciphers require the appropriate certificates. For example, an - * RSA cipher suite can only be chosen when an RSA certificate is available. + * Sets the list of available cipher suites for TLS 1.2 and below for this + * context. + * + * Note in a server context some ciphers require the appropriate certificates. + * For example, an RSA cipher suite can only be chosen when an RSA certificate + * is available. + * + * This method does not affect TLS 1.3 connections. See also #ciphersuites=. */ static VALUE ossl_sslctx_set_ciphers(VALUE self, VALUE v) @@ -1062,6 +1039,7 @@ ossl_sslctx_set_ciphers(VALUE self, VALUE v) VALUE str; rb_check_frozen(self); + // Assigning nil is a no-op for compatibility if (NIL_P(v)) return v; @@ -1074,14 +1052,12 @@ ossl_sslctx_set_ciphers(VALUE self, VALUE v) return v; } -#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES /* * call-seq: * ctx.ciphersuites = "cipher1:cipher2:..." * ctx.ciphersuites = [name, ...] - * ctx.ciphersuites = [[name, version, bits, alg_bits], ...] * - * Sets the list of available TLSv1.3 cipher suites for this context. + * Sets the list of available TLS 1.3 cipher suites for this context. */ static VALUE ossl_sslctx_set_ciphersuites(VALUE self, VALUE v) @@ -1090,6 +1066,7 @@ ossl_sslctx_set_ciphersuites(VALUE self, VALUE v) VALUE str; rb_check_frozen(self); + // Assigning nil is a no-op for compatibility if (NIL_P(v)) return v; @@ -1101,6 +1078,62 @@ ossl_sslctx_set_ciphersuites(VALUE self, VALUE v) return v; } + +#ifdef HAVE_SSL_CTX_SET1_SIGALGS_LIST +/* + * call-seq: + * ctx.sigalgs = "sigalg1:sigalg2:..." + * + * Sets the list of "supported signature algorithms" for this context. + * + * For a TLS client, the list is used in the "signature_algorithms" extension + * in the ClientHello message. For a server, the list is used by OpenSSL to + * determine the set of shared signature algorithms. OpenSSL will pick the most + * appropriate one from it. + * + * See also #client_sigalgs= for the client authentication equivalent. + */ +static VALUE +ossl_sslctx_set_sigalgs(VALUE self, VALUE v) +{ + SSL_CTX *ctx; + + rb_check_frozen(self); + GetSSLCTX(self, ctx); + + if (!SSL_CTX_set1_sigalgs_list(ctx, StringValueCStr(v))) + ossl_raise(eSSLError, "SSL_CTX_set1_sigalgs_list"); + + return v; +} +#endif + +#ifdef HAVE_SSL_CTX_SET1_CLIENT_SIGALGS_LIST +/* + * call-seq: + * ctx.client_sigalgs = "sigalg1:sigalg2:..." + * + * Sets the list of "supported signature algorithms" for client authentication + * for this context. + * + * For a TLS server, the list is sent to the client as part of the + * CertificateRequest message. + * + * See also #sigalgs= for the server authentication equivalent. + */ +static VALUE +ossl_sslctx_set_client_sigalgs(VALUE self, VALUE v) +{ + SSL_CTX *ctx; + + rb_check_frozen(self); + GetSSLCTX(self, ctx); + + if (!SSL_CTX_set1_client_sigalgs_list(ctx, StringValueCStr(v))) + ossl_raise(eSSLError, "SSL_CTX_set1_client_sigalgs_list"); + + return v; +} #endif #ifndef OPENSSL_NO_DH @@ -1149,25 +1182,29 @@ ossl_sslctx_set_tmp_dh(VALUE self, VALUE arg) } #endif -#if !defined(OPENSSL_NO_EC) /* * call-seq: - * ctx.ecdh_curves = curve_list -> curve_list + * ctx.groups = groups_list + * ctx.ecdh_curves = groups_list + * + * Sets the list of supported groups for key agreement for this context. * - * Sets the list of "supported elliptic curves" for this context. + * For a TLS client, the list is directly used in the "supported_groups" + * extension. For a server, the list is used by OpenSSL to determine the set of + * shared supported groups. OpenSSL will pick the most appropriate one from it. * - * For a TLS client, the list is directly used in the Supported Elliptic Curves - * Extension. For a server, the list is used by OpenSSL to determine the set of - * shared curves. OpenSSL will pick the most appropriate one from it. + * #ecdh_curves= is a deprecated alias for #groups=. + * + * See also the man page SSL_CTX_set1_groups_list(3). * * === Example * ctx1 = OpenSSL::SSL::SSLContext.new - * ctx1.ecdh_curves = "X25519:P-256:P-224" + * ctx1.groups = "X25519:P-256:P-224" * svr = OpenSSL::SSL::SSLServer.new(tcp_svr, ctx1) * Thread.new { svr.accept } * * ctx2 = OpenSSL::SSL::SSLContext.new - * ctx2.ecdh_curves = "P-256" + * ctx2.groups = "P-256" * cli = OpenSSL::SSL::SSLSocket.new(tcp_sock, ctx2) * cli.connect * @@ -1175,7 +1212,7 @@ ossl_sslctx_set_tmp_dh(VALUE self, VALUE arg) * # => "prime256v1" (is an alias for NIST P-256) */ static VALUE -ossl_sslctx_set_ecdh_curves(VALUE self, VALUE arg) +ossl_sslctx_set_groups(VALUE self, VALUE arg) { SSL_CTX *ctx; @@ -1183,13 +1220,10 @@ ossl_sslctx_set_ecdh_curves(VALUE self, VALUE arg) GetSSLCTX(self, ctx); StringValueCStr(arg); - if (!SSL_CTX_set1_curves_list(ctx, RSTRING_PTR(arg))) - ossl_raise(eSSLError, NULL); + if (!SSL_CTX_set1_groups_list(ctx, RSTRING_PTR(arg))) + ossl_raise(eSSLError, "SSL_CTX_set1_groups_list"); return arg; } -#else -#define ossl_sslctx_set_ecdh_curves rb_f_notimplement -#endif /* * call-seq: @@ -1206,12 +1240,7 @@ ossl_sslctx_get_security_level(VALUE self) GetSSLCTX(self, ctx); -#if defined(HAVE_SSL_CTX_GET_SECURITY_LEVEL) return INT2NUM(SSL_CTX_get_security_level(ctx)); -#else - (void)ctx; - return INT2FIX(0); -#endif } /* @@ -1241,14 +1270,7 @@ ossl_sslctx_set_security_level(VALUE self, VALUE value) rb_check_frozen(self); GetSSLCTX(self, ctx); -#if defined(HAVE_SSL_CTX_GET_SECURITY_LEVEL) SSL_CTX_set_security_level(ctx, NUM2INT(value)); -#else - (void)ctx; - if (NUM2INT(value) != 0) - ossl_raise(rb_eNotImpError, "setting security level to other than 0 is " - "not supported in this version of OpenSSL"); -#endif return value; } @@ -1553,11 +1575,6 @@ ossl_ssl_mark(void *ptr) { SSL *ssl = ptr; rb_gc_mark((VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_ptr_idx)); - - // Note: this reference is stored as @verify_callback so we don't need to mark it. - // However we do need to ensure GC compaction won't move it, hence why - // we call rb_gc_mark here. - rb_gc_mark((VALUE)SSL_get_ex_data(ssl, ossl_ssl_ex_vcb_idx)); } static void @@ -1622,7 +1639,7 @@ peeraddr_ip_str(VALUE self) static VALUE ossl_ssl_initialize(int argc, VALUE *argv, VALUE self) { - VALUE io, v_ctx, verify_cb; + VALUE io, v_ctx; SSL *ssl; SSL_CTX *ctx; @@ -1649,10 +1666,6 @@ ossl_ssl_initialize(int argc, VALUE *argv, VALUE self) SSL_set_ex_data(ssl, ossl_ssl_ex_ptr_idx, (void *)self); SSL_set_info_callback(ssl, ssl_info_cb); - verify_cb = rb_attr_get(v_ctx, id_i_verify_callback); - // We don't need to trigger a write barrier because it's already - // an instance variable of this object. - SSL_set_ex_data(ssl, ossl_ssl_ex_vcb_idx, (void *)verify_cb); rb_call_super(0, NULL); @@ -1725,11 +1738,20 @@ no_exception_p(VALUE opts) #define RUBY_IO_TIMEOUT_DEFAULT Qnil #endif +#ifdef HAVE_RB_IO_TIMEOUT +#define IO_TIMEOUT_ERROR rb_eIOTimeoutError +#else +#define IO_TIMEOUT_ERROR rb_eIOError +#endif + + static void io_wait_writable(VALUE io) { #ifdef HAVE_RB_IO_MAYBE_WAIT - rb_io_maybe_wait_writable(errno, io, RUBY_IO_TIMEOUT_DEFAULT); + if (!rb_io_maybe_wait_writable(errno, io, RUBY_IO_TIMEOUT_DEFAULT)) { + rb_raise(IO_TIMEOUT_ERROR, "Timed out while waiting to become writable!"); + } #else rb_io_t *fptr; GetOpenFile(io, fptr); @@ -1741,7 +1763,9 @@ static void io_wait_readable(VALUE io) { #ifdef HAVE_RB_IO_MAYBE_WAIT - rb_io_maybe_wait_readable(errno, io, RUBY_IO_TIMEOUT_DEFAULT); + if (!rb_io_maybe_wait_readable(errno, io, RUBY_IO_TIMEOUT_DEFAULT)) { + rb_raise(IO_TIMEOUT_ERROR, "Timed out while waiting to become readable!"); + } #else rb_io_t *fptr; GetOpenFile(io, fptr); @@ -1925,7 +1949,7 @@ ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock) { SSL *ssl; int ilen; - VALUE len, str; + VALUE len, str, cb_state; VALUE opts = Qnil; if (nonblock) { @@ -1947,43 +1971,49 @@ ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock) else rb_str_modify_expand(str, ilen - RSTRING_LEN(str)); } - rb_str_set_len(str, 0); - if (ilen == 0) - return str; + + if (ilen == 0) { + rb_str_set_len(str, 0); + return str; + } VALUE io = rb_attr_get(self, id_i_io); - rb_str_locktmp(str); for (;;) { + rb_str_locktmp(str); int nread = SSL_read(ssl, RSTRING_PTR(str), ilen); + rb_str_unlocktmp(str); + + cb_state = rb_attr_get(self, ID_callback_state); + if (!NIL_P(cb_state)) { + rb_ivar_set(self, ID_callback_state, Qnil); + ossl_clear_error(); + rb_jump_tag(NUM2INT(cb_state)); + } + switch (ssl_get_error(ssl, nread)) { case SSL_ERROR_NONE: - rb_str_unlocktmp(str); rb_str_set_len(str, nread); return str; case SSL_ERROR_ZERO_RETURN: - rb_str_unlocktmp(str); if (no_exception_p(opts)) { return Qnil; } rb_eof_error(); case SSL_ERROR_WANT_WRITE: if (nonblock) { - rb_str_unlocktmp(str); if (no_exception_p(opts)) { return sym_wait_writable; } write_would_block(nonblock); } io_wait_writable(io); - continue; + break; case SSL_ERROR_WANT_READ: if (nonblock) { - rb_str_unlocktmp(str); if (no_exception_p(opts)) { return sym_wait_readable; } read_would_block(nonblock); } io_wait_readable(io); - continue; + break; case SSL_ERROR_SYSCALL: if (!ERR_peek_error()) { - rb_str_unlocktmp(str); if (errno) rb_sys_fail(0); else { @@ -2000,9 +2030,13 @@ ossl_ssl_read_internal(int argc, VALUE *argv, VALUE self, int nonblock) } /* fall through */ default: - rb_str_unlocktmp(str); ossl_raise(eSSLError, "SSL_read"); } + + // Ensure the buffer is not modified during io_wait_*able() + rb_str_modify(str); + if (rb_str_capacity(str) < (size_t)ilen) + rb_raise(eSSLError, "read buffer was modified"); } } @@ -2040,28 +2074,40 @@ ossl_ssl_read_nonblock(int argc, VALUE *argv, VALUE self) } static VALUE -ossl_ssl_write_internal(VALUE self, VALUE str, VALUE opts) +ossl_ssl_write_internal_safe(VALUE _args) { + VALUE *args = (VALUE*)_args; + VALUE self = args[0]; + VALUE str = args[1]; + VALUE opts = args[2]; + SSL *ssl; rb_io_t *fptr; int num, nonblock = opts != Qfalse; - VALUE tmp; + VALUE cb_state; GetSSL(self, ssl); if (!ssl_started(ssl)) rb_raise(eSSLError, "SSL session is not started yet"); - tmp = rb_str_new_frozen(StringValue(str)); VALUE io = rb_attr_get(self, id_i_io); GetOpenFile(io, fptr); /* SSL_write(3ssl) manpage states num == 0 is undefined */ - num = RSTRING_LENINT(tmp); + num = RSTRING_LENINT(str); if (num == 0) return INT2FIX(0); for (;;) { - int nwritten = SSL_write(ssl, RSTRING_PTR(tmp), num); + int nwritten = SSL_write(ssl, RSTRING_PTR(str), num); + + cb_state = rb_attr_get(self, ID_callback_state); + if (!NIL_P(cb_state)) { + rb_ivar_set(self, ID_callback_state, Qnil); + ossl_clear_error(); + rb_jump_tag(NUM2INT(cb_state)); + } + switch (ssl_get_error(ssl, nwritten)) { case SSL_ERROR_NONE: return INT2NUM(nwritten); @@ -2094,6 +2140,28 @@ ossl_ssl_write_internal(VALUE self, VALUE str, VALUE opts) } } + +static VALUE +ossl_ssl_write_internal(VALUE self, VALUE str, VALUE opts) +{ + StringValue(str); + int frozen = RB_OBJ_FROZEN(str); + if (!frozen) { + rb_str_locktmp(str); + } + int state; + VALUE args[3] = {self, str, opts}; + VALUE result = rb_protect(ossl_ssl_write_internal_safe, (VALUE)args, &state); + if (!frozen) { + rb_str_unlocktmp(str); + } + + if (state) { + rb_jump_tag(state); + } + return result; +} + /* * call-seq: * ssl.syswrite(string) => Integer @@ -2445,7 +2513,7 @@ ossl_ssl_get_peer_finished(VALUE self) /* * call-seq: - * ssl.client_ca => [x509name, ...] + * ssl.client_ca => [x509name, ...] or nil * * Returns the list of client CAs. Please note that in contrast to * SSLContext#client_ca= no array of X509::Certificate is returned but @@ -2463,6 +2531,8 @@ ossl_ssl_get_client_ca_list(VALUE self) GetSSL(self, ssl); ca = SSL_get_client_CA_list(ssl); + if (!ca) + return Qnil; return ossl_x509name_sk2ary(ca); } @@ -2590,9 +2660,6 @@ Init_ossl_ssl(void) id_call = rb_intern_const("call"); ID_callback_state = rb_intern_const("callback_state"); - ossl_ssl_ex_vcb_idx = SSL_get_ex_new_index(0, (void *)"ossl_ssl_ex_vcb_idx", 0, 0, 0); - if (ossl_ssl_ex_vcb_idx < 0) - ossl_raise(rb_eRuntimeError, "SSL_get_ex_new_index"); ossl_ssl_ex_ptr_idx = SSL_get_ex_new_index(0, (void *)"ossl_ssl_ex_ptr_idx", 0, 0, 0); if (ossl_ssl_ex_ptr_idx < 0) ossl_raise(rb_eRuntimeError, "SSL_get_ex_new_index"); @@ -2878,17 +2945,22 @@ Init_ossl_ssl(void) rb_define_alias(cSSLContext, "ssl_timeout", "timeout"); rb_define_alias(cSSLContext, "ssl_timeout=", "timeout="); - rb_define_private_method(cSSLContext, "set_minmax_proto_version", - ossl_sslctx_set_minmax_proto_version, 2); + rb_define_method(cSSLContext, "min_version=", ossl_sslctx_set_min_version, 1); + rb_define_method(cSSLContext, "max_version=", ossl_sslctx_set_max_version, 1); rb_define_method(cSSLContext, "ciphers", ossl_sslctx_get_ciphers, 0); rb_define_method(cSSLContext, "ciphers=", ossl_sslctx_set_ciphers, 1); -#ifdef HAVE_SSL_CTX_SET_CIPHERSUITES rb_define_method(cSSLContext, "ciphersuites=", ossl_sslctx_set_ciphersuites, 1); +#ifdef HAVE_SSL_CTX_SET1_SIGALGS_LIST // Not in LibreSSL yet + rb_define_method(cSSLContext, "sigalgs=", ossl_sslctx_set_sigalgs, 1); +#endif +#ifdef HAVE_SSL_CTX_SET1_CLIENT_SIGALGS_LIST // Not in LibreSSL or AWS-LC yet + rb_define_method(cSSLContext, "client_sigalgs=", ossl_sslctx_set_client_sigalgs, 1); #endif #ifndef OPENSSL_NO_DH rb_define_method(cSSLContext, "tmp_dh=", ossl_sslctx_set_tmp_dh, 1); #endif - rb_define_method(cSSLContext, "ecdh_curves=", ossl_sslctx_set_ecdh_curves, 1); + rb_define_method(cSSLContext, "groups=", ossl_sslctx_set_groups, 1); + rb_define_alias(cSSLContext, "ecdh_curves=", "groups="); rb_define_method(cSSLContext, "security_level", ossl_sslctx_get_security_level, 0); rb_define_method(cSSLContext, "security_level=", ossl_sslctx_set_security_level, 1); #ifdef SSL_MODE_SEND_FALLBACK_SCSV @@ -3020,7 +3092,7 @@ Init_ossl_ssl(void) #ifdef SSL_OP_DISABLE_TLSEXT_CA_NAMES /* OpenSSL 3.0 */ rb_define_const(mSSL, "OP_DISABLE_TLSEXT_CA_NAMES", ULONG2NUM(SSL_OP_DISABLE_TLSEXT_CA_NAMES)); #endif -#ifdef SSL_OP_ALLOW_NO_DHE_KEX /* OpenSSL 1.1.1 */ +#ifdef SSL_OP_ALLOW_NO_DHE_KEX /* OpenSSL 1.1.1, missing in LibreSSL */ rb_define_const(mSSL, "OP_ALLOW_NO_DHE_KEX", ULONG2NUM(SSL_OP_ALLOW_NO_DHE_KEX)); #endif rb_define_const(mSSL, "OP_DONT_INSERT_EMPTY_FRAGMENTS", ULONG2NUM(SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS)); @@ -3028,28 +3100,26 @@ Init_ossl_ssl(void) rb_define_const(mSSL, "OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION", ULONG2NUM(SSL_OP_NO_SESSION_RESUMPTION_ON_RENEGOTIATION)); rb_define_const(mSSL, "OP_NO_COMPRESSION", ULONG2NUM(SSL_OP_NO_COMPRESSION)); rb_define_const(mSSL, "OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION", ULONG2NUM(SSL_OP_ALLOW_UNSAFE_LEGACY_RENEGOTIATION)); -#ifdef SSL_OP_NO_ENCRYPT_THEN_MAC /* OpenSSL 1.1.1 */ +#ifdef SSL_OP_NO_ENCRYPT_THEN_MAC /* OpenSSL 1.1.1, missing in LibreSSL */ rb_define_const(mSSL, "OP_NO_ENCRYPT_THEN_MAC", ULONG2NUM(SSL_OP_NO_ENCRYPT_THEN_MAC)); #endif -#ifdef SSL_OP_ENABLE_MIDDLEBOX_COMPAT /* OpenSSL 1.1.1 */ +#ifdef SSL_OP_ENABLE_MIDDLEBOX_COMPAT /* OpenSSL 1.1.1, missing in LibreSSL */ rb_define_const(mSSL, "OP_ENABLE_MIDDLEBOX_COMPAT", ULONG2NUM(SSL_OP_ENABLE_MIDDLEBOX_COMPAT)); #endif -#ifdef SSL_OP_PRIORITIZE_CHACHA /* OpenSSL 1.1.1 */ +#ifdef SSL_OP_PRIORITIZE_CHACHA /* OpenSSL 1.1.1, missing in LibreSSL */ rb_define_const(mSSL, "OP_PRIORITIZE_CHACHA", ULONG2NUM(SSL_OP_PRIORITIZE_CHACHA)); #endif -#ifdef SSL_OP_NO_ANTI_REPLAY /* OpenSSL 1.1.1 */ +#ifdef SSL_OP_NO_ANTI_REPLAY /* OpenSSL 1.1.1, missing in LibreSSL */ rb_define_const(mSSL, "OP_NO_ANTI_REPLAY", ULONG2NUM(SSL_OP_NO_ANTI_REPLAY)); #endif rb_define_const(mSSL, "OP_NO_SSLv3", ULONG2NUM(SSL_OP_NO_SSLv3)); rb_define_const(mSSL, "OP_NO_TLSv1", ULONG2NUM(SSL_OP_NO_TLSv1)); rb_define_const(mSSL, "OP_NO_TLSv1_1", ULONG2NUM(SSL_OP_NO_TLSv1_1)); rb_define_const(mSSL, "OP_NO_TLSv1_2", ULONG2NUM(SSL_OP_NO_TLSv1_2)); -#ifdef SSL_OP_NO_TLSv1_3 /* OpenSSL 1.1.1 */ rb_define_const(mSSL, "OP_NO_TLSv1_3", ULONG2NUM(SSL_OP_NO_TLSv1_3)); -#endif rb_define_const(mSSL, "OP_CIPHER_SERVER_PREFERENCE", ULONG2NUM(SSL_OP_CIPHER_SERVER_PREFERENCE)); rb_define_const(mSSL, "OP_TLS_ROLLBACK_BUG", ULONG2NUM(SSL_OP_TLS_ROLLBACK_BUG)); -#ifdef SSL_OP_NO_RENEGOTIATION /* OpenSSL 1.1.1 */ +#ifdef SSL_OP_NO_RENEGOTIATION /* OpenSSL 1.1.1, missing in LibreSSL */ rb_define_const(mSSL, "OP_NO_RENEGOTIATION", ULONG2NUM(SSL_OP_NO_RENEGOTIATION)); #endif rb_define_const(mSSL, "OP_CRYPTOPRO_TLSEXT_BUG", ULONG2NUM(SSL_OP_CRYPTOPRO_TLSEXT_BUG)); @@ -3111,10 +3181,8 @@ Init_ossl_ssl(void) rb_define_const(mSSL, "TLS1_1_VERSION", INT2NUM(TLS1_1_VERSION)); /* TLS 1.2 */ rb_define_const(mSSL, "TLS1_2_VERSION", INT2NUM(TLS1_2_VERSION)); -#ifdef TLS1_3_VERSION /* OpenSSL 1.1.1 */ /* TLS 1.3 */ rb_define_const(mSSL, "TLS1_3_VERSION", INT2NUM(TLS1_3_VERSION)); -#endif sym_exception = ID2SYM(rb_intern_const("exception")); diff --git a/ext/openssl/ossl_ssl.h b/ext/openssl/ossl_ssl.h index 535c56097ce437..a92985c601ebf3 100644 --- a/ext/openssl/ossl_ssl.h +++ b/ext/openssl/ossl_ssl.h @@ -5,7 +5,7 @@ */ /* * This program is licensed under the same licence as Ruby. - * (See the file 'LICENCE'.) + * (See the file 'COPYING'.) */ #if !defined(_OSSL_SSL_H_) #define _OSSL_SSL_H_ diff --git a/ext/openssl/ossl_ssl_session.c b/ext/openssl/ossl_ssl_session.c index c5df902c60e8f4..55b9d6c6d57e88 100644 --- a/ext/openssl/ossl_ssl_session.c +++ b/ext/openssl/ossl_ssl_session.c @@ -69,6 +69,7 @@ ossl_ssl_session_initialize(VALUE self, VALUE arg1) return self; } +/* :nodoc: */ static VALUE ossl_ssl_session_initialize_copy(VALUE self, VALUE other) { diff --git a/ext/openssl/ossl_ts.c b/ext/openssl/ossl_ts.c index f698bdc7ffb048..c7d2bd271b94c4 100644 --- a/ext/openssl/ossl_ts.c +++ b/ext/openssl/ossl_ts.c @@ -5,7 +5,7 @@ */ /* * This program is licenced under the same licence as Ruby. - * (See the file 'LICENCE'.) + * (See the file 'COPYING'.) */ #include "ossl.h" @@ -152,7 +152,7 @@ obj_to_asn1obj_i(VALUE obj) } static VALUE -get_asn1obj(ASN1_OBJECT *obj) +get_asn1obj(const ASN1_OBJECT *obj) { BIO *out; VALUE ret; @@ -161,8 +161,11 @@ get_asn1obj(ASN1_OBJECT *obj) ret = rb_str_new2(OBJ_nid2sn(nid)); else{ if (!(out = BIO_new(BIO_s_mem()))) - ossl_raise(eX509AttrError, NULL); - i2a_ASN1_OBJECT(out, obj); + ossl_raise(eTimestampError, "BIO_new(BIO_s_mem())"); + if (i2a_ASN1_OBJECT(out, obj) <= 0) { + BIO_free(out); + ossl_raise(eTimestampError, "i2a_ASN1_OBJECT"); + } ret = ossl_membio2str(out); } @@ -233,11 +236,13 @@ ossl_ts_req_get_algorithm(VALUE self) TS_REQ *req; TS_MSG_IMPRINT *mi; X509_ALGOR *algor; + const ASN1_OBJECT *obj; GetTSRequest(self, req); mi = TS_REQ_get_msg_imprint(req); algor = TS_MSG_IMPRINT_get_algo(mi); - return get_asn1obj(algor->algorithm); + X509_ALGOR_get0(&obj, NULL, NULL, algor); + return get_asn1obj(obj); } /* @@ -487,13 +492,15 @@ ossl_ts_req_to_der(VALUE self) TS_REQ *req; TS_MSG_IMPRINT *mi; X509_ALGOR *algo; + const ASN1_OBJECT *obj; ASN1_OCTET_STRING *hashed_msg; GetTSRequest(self, req); mi = TS_REQ_get_msg_imprint(req); algo = TS_MSG_IMPRINT_get_algo(mi); - if (OBJ_obj2nid(algo->algorithm) == NID_undef) + X509_ALGOR_get0(&obj, NULL, NULL, algo); + if (OBJ_obj2nid(obj) == NID_undef) ossl_raise(eTimestampError, "Message imprint missing algorithm"); hashed_msg = TS_MSG_IMPRINT_get_msg(mi); @@ -503,6 +510,25 @@ ossl_ts_req_to_der(VALUE self) return asn1_to_der((void *)req, (int (*)(void *, unsigned char **))i2d_TS_REQ); } +static VALUE +ossl_ts_req_to_text(VALUE self) +{ + TS_REQ *req; + BIO *out; + + GetTSRequest(self, req); + + out = BIO_new(BIO_s_mem()); + if (!out) ossl_raise(eTimestampError, NULL); + + if (!TS_REQ_print_bio(out, req)) { + BIO_free(out); + ossl_raise(eTimestampError, NULL); + } + + return ossl_membio2str(out); +} + static VALUE ossl_ts_resp_alloc(VALUE klass) { @@ -598,14 +624,7 @@ ossl_ts_resp_get_failure_info(VALUE self) { TS_RESP *resp; TS_STATUS_INFO *si; - - /* The ASN1_BIT_STRING_get_bit changed from 1.0.0. to 1.1.0, making this - * const. */ - #if defined(HAVE_TS_STATUS_INFO_GET0_FAILURE_INFO) const ASN1_BIT_STRING *fi; - #else - ASN1_BIT_STRING *fi; - #endif GetTSResponse(self, resp); si = TS_RESP_get_status_info(resp); @@ -672,21 +691,12 @@ static VALUE ossl_ts_resp_get_token(VALUE self) { TS_RESP *resp; - PKCS7 *p7, *copy; - VALUE obj; + PKCS7 *p7; GetTSResponse(self, resp); if (!(p7 = TS_RESP_get_token(resp))) return Qnil; - - obj = NewPKCS7(cPKCS7); - - if (!(copy = PKCS7_dup(p7))) - ossl_raise(eTimestampError, NULL); - - SetPKCS7(obj, copy); - - return obj; + return ossl_pkcs7_new(p7); } /* @@ -757,6 +767,25 @@ ossl_ts_resp_to_der(VALUE self) return asn1_to_der((void *)resp, (int (*)(void *, unsigned char **))i2d_TS_RESP); } +static VALUE +ossl_ts_resp_to_text(VALUE self) +{ + TS_RESP *resp; + BIO *out; + + GetTSResponse(self, resp); + + out = BIO_new(BIO_s_mem()); + if (!out) ossl_raise(eTimestampError, NULL); + + if (!TS_RESP_print_bio(out, resp)) { + BIO_free(out); + ossl_raise(eTimestampError, NULL); + } + + return ossl_membio2str(out); +} + /* * Verifies a timestamp token by checking the signature, validating the * certificate chain implied by tsa_certificate and by checking conformance to @@ -826,16 +855,26 @@ ossl_ts_resp_verify(int argc, VALUE *argv, VALUE self) X509_up_ref(cert); } + if (!X509_STORE_up_ref(x509st)) { + sk_X509_pop_free(x509inter, X509_free); + TS_VERIFY_CTX_free(ctx); + ossl_raise(eTimestampError, "X509_STORE_up_ref"); + } + +#ifdef HAVE_TS_VERIFY_CTX_SET0_CERTS + TS_VERIFY_CTX_set0_certs(ctx, x509inter); + TS_VERIFY_CTX_set0_store(ctx, x509st); +#else +# if OSSL_OPENSSL_PREREQ(3, 0, 0) || OSSL_IS_LIBRESSL TS_VERIFY_CTX_set_certs(ctx, x509inter); - TS_VERIFY_CTX_add_flags(ctx, TS_VFY_SIGNATURE); +# else + TS_VERIFY_CTS_set_certs(ctx, x509inter); +# endif TS_VERIFY_CTX_set_store(ctx, x509st); +#endif + TS_VERIFY_CTX_add_flags(ctx, TS_VFY_SIGNATURE); ok = TS_RESP_verify_response(ctx, resp); - /* - * TS_VERIFY_CTX_set_store() call above does not increment the reference - * counter, so it must be unset before TS_VERIFY_CTX_free() is called. - */ - TS_VERIFY_CTX_set_store(ctx, NULL); TS_VERIFY_CTX_free(ctx); if (!ok) @@ -944,11 +983,13 @@ ossl_ts_token_info_get_algorithm(VALUE self) TS_TST_INFO *info; TS_MSG_IMPRINT *mi; X509_ALGOR *algo; + const ASN1_OBJECT *obj; GetTSTokenInfo(self, info); mi = TS_TST_INFO_get_msg_imprint(info); algo = TS_MSG_IMPRINT_get_algo(mi); - return get_asn1obj(algo->algorithm); + X509_ALGOR_get0(&obj, NULL, NULL, algo); + return get_asn1obj(obj); } /* @@ -1073,6 +1114,25 @@ ossl_ts_token_info_to_der(VALUE self) return asn1_to_der((void *)info, (int (*)(void *, unsigned char **))i2d_TS_TST_INFO); } +static VALUE +ossl_ts_token_info_to_text(VALUE self) +{ + TS_TST_INFO *info; + BIO *out; + + GetTSTokenInfo(self, info); + + out = BIO_new(BIO_s_mem()); + if (!out) ossl_raise(eTimestampError, NULL); + + if (!TS_TST_INFO_print_bio(out, info)) { + BIO_free(out); + ossl_raise(eTimestampError, NULL); + } + + return ossl_membio2str(out); +} + static ASN1_INTEGER * ossl_tsfac_serial_cb(struct TS_resp_ctx *ctx, void *data) { @@ -1356,6 +1416,7 @@ Init_ossl_ts(void) rb_define_method(cTimestampResponse, "token_info", ossl_ts_resp_get_token_info, 0); rb_define_method(cTimestampResponse, "tsa_certificate", ossl_ts_resp_get_tsa_certificate, 0); rb_define_method(cTimestampResponse, "to_der", ossl_ts_resp_to_der, 0); + rb_define_method(cTimestampResponse, "to_text", ossl_ts_resp_to_text, 0); rb_define_method(cTimestampResponse, "verify", ossl_ts_resp_verify, -1); /* Document-class: OpenSSL::Timestamp::TokenInfo @@ -1374,6 +1435,7 @@ Init_ossl_ts(void) rb_define_method(cTimestampTokenInfo, "ordering", ossl_ts_token_info_get_ordering, 0); rb_define_method(cTimestampTokenInfo, "nonce", ossl_ts_token_info_get_nonce, 0); rb_define_method(cTimestampTokenInfo, "to_der", ossl_ts_token_info_to_der, 0); + rb_define_method(cTimestampTokenInfo, "to_text", ossl_ts_token_info_to_text, 0); /* Document-class: OpenSSL::Timestamp::Request * Allows to create timestamp requests or parse existing ones. A Request is @@ -1399,6 +1461,7 @@ Init_ossl_ts(void) rb_define_method(cTimestampRequest, "cert_requested=", ossl_ts_req_set_cert_requested, 1); rb_define_method(cTimestampRequest, "cert_requested?", ossl_ts_req_get_cert_requested, 0); rb_define_method(cTimestampRequest, "to_der", ossl_ts_req_to_der, 0); + rb_define_method(cTimestampRequest, "to_text", ossl_ts_req_to_text, 0); /* * Indicates a successful response. Equal to +0+. @@ -1535,5 +1598,9 @@ Init_ossl_ts(void) rb_attr(cTimestampFactory, rb_intern_const("additional_certs"), 1, 1, 0); rb_define_method(cTimestampFactory, "create_timestamp", ossl_tsfac_create_ts, 3); } - +#else /* OPENSSL_NO_TS */ +void +Init_ossl_ts(void) +{ +} #endif diff --git a/ext/openssl/ossl_ts.h b/ext/openssl/ossl_ts.h index 25fb0e1d6459ce..eeca3046eb7ab1 100644 --- a/ext/openssl/ossl_ts.h +++ b/ext/openssl/ossl_ts.h @@ -5,7 +5,7 @@ */ /* * This program is licenced under the same licence as Ruby. - * (See the file 'LICENCE'.) + * (See the file 'COPYING'.) */ #if !defined(_OSSL_TS_H_) diff --git a/ext/openssl/ossl_x509.c b/ext/openssl/ossl_x509.c index f8470703fcd177..2d552d78478b5b 100644 --- a/ext/openssl/ossl_x509.c +++ b/ext/openssl/ossl_x509.c @@ -5,7 +5,7 @@ */ /* * This program is licensed under the same licence as Ruby. - * (See the file 'LICENCE'.) + * (See the file 'COPYING'.) */ #include "ossl.h" @@ -48,9 +48,7 @@ Init_ossl_x509(void) /* Certificate verification error code */ DefX509Const(V_OK); -#if defined(X509_V_ERR_UNSPECIFIED) /* 1.0.1r, 1.0.2f, 1.1.0 */ DefX509Const(V_ERR_UNSPECIFIED); -#endif DefX509Const(V_ERR_UNABLE_TO_GET_ISSUER_CERT); DefX509Const(V_ERR_UNABLE_TO_GET_CRL); DefX509Const(V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE); @@ -104,10 +102,10 @@ Init_ossl_x509(void) DefX509Const(V_ERR_UNSUPPORTED_CONSTRAINT_SYNTAX); DefX509Const(V_ERR_UNSUPPORTED_NAME_SYNTAX); DefX509Const(V_ERR_CRL_PATH_VALIDATION_ERROR); -#if defined(X509_V_ERR_PATH_LOOP) +#if defined(X509_V_ERR_PATH_LOOP) /* OpenSSL 1.1.0, missing in LibreSSL */ DefX509Const(V_ERR_PATH_LOOP); #endif -#if defined(X509_V_ERR_SUITE_B_INVALID_VERSION) +#if defined(X509_V_ERR_SUITE_B_INVALID_VERSION) /* OpenSSL 1.1.0, missing in LibreSSL */ DefX509Const(V_ERR_SUITE_B_INVALID_VERSION); DefX509Const(V_ERR_SUITE_B_INVALID_ALGORITHM); DefX509Const(V_ERR_SUITE_B_INVALID_CURVE); @@ -118,27 +116,21 @@ Init_ossl_x509(void) DefX509Const(V_ERR_HOSTNAME_MISMATCH); DefX509Const(V_ERR_EMAIL_MISMATCH); DefX509Const(V_ERR_IP_ADDRESS_MISMATCH); -#if defined(X509_V_ERR_DANE_NO_MATCH) +#if defined(X509_V_ERR_DANE_NO_MATCH) /* OpenSSL 1.1.0, missing in LibreSSL */ DefX509Const(V_ERR_DANE_NO_MATCH); #endif -#if defined(X509_V_ERR_EE_KEY_TOO_SMALL) DefX509Const(V_ERR_EE_KEY_TOO_SMALL); DefX509Const(V_ERR_CA_KEY_TOO_SMALL); DefX509Const(V_ERR_CA_MD_TOO_WEAK); -#endif -#if defined(X509_V_ERR_INVALID_CALL) DefX509Const(V_ERR_INVALID_CALL); -#endif -#if defined(X509_V_ERR_STORE_LOOKUP) DefX509Const(V_ERR_STORE_LOOKUP); -#endif -#if defined(X509_V_ERR_NO_VALID_SCTS) +#if defined(X509_V_ERR_NO_VALID_SCTS) /* OpenSSL 1.1.0, missing in LibreSSL */ DefX509Const(V_ERR_NO_VALID_SCTS); #endif -#if defined(X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION) +#if defined(X509_V_ERR_PROXY_SUBJECT_NAME_VIOLATION) /* OpenSSL 1.1.0, missing in LibreSSL */ DefX509Const(V_ERR_PROXY_SUBJECT_NAME_VIOLATION); #endif -#if defined(X509_V_ERR_OCSP_VERIFY_NEEDED) +#if defined(X509_V_ERR_OCSP_VERIFY_NEEDED) /* OpenSSL 1.1.1, missing in LibreSSL */ DefX509Const(V_ERR_OCSP_VERIFY_NEEDED); DefX509Const(V_ERR_OCSP_VERIFY_FAILED); DefX509Const(V_ERR_OCSP_CERT_UNKNOWN); @@ -189,17 +181,13 @@ Init_ossl_x509(void) * certificate chain, search the Store first for the issuer certificate. * Enabled by default in OpenSSL >= 1.1.0. */ DefX509Const(V_FLAG_TRUSTED_FIRST); -#if defined(X509_V_FLAG_SUITEB_128_LOS_ONLY) +#if defined(X509_V_FLAG_SUITEB_128_LOS_ONLY) /* OpenSSL 1.1.0, missing in LibreSSL */ /* Set by Store#flags= and StoreContext#flags=. * Enables Suite B 128 bit only mode. */ DefX509Const(V_FLAG_SUITEB_128_LOS_ONLY); -#endif -#if defined(X509_V_FLAG_SUITEB_192_LOS) /* Set by Store#flags= and StoreContext#flags=. * Enables Suite B 192 bit only mode. */ DefX509Const(V_FLAG_SUITEB_192_LOS); -#endif -#if defined(X509_V_FLAG_SUITEB_128_LOS) /* Set by Store#flags= and StoreContext#flags=. * Enables Suite B 128 bit mode allowing 192 bit algorithms. */ DefX509Const(V_FLAG_SUITEB_128_LOS); @@ -207,17 +195,13 @@ Init_ossl_x509(void) /* Set by Store#flags= and StoreContext#flags=. * Allows partial chains if at least one certificate is in trusted store. */ DefX509Const(V_FLAG_PARTIAL_CHAIN); -#if defined(X509_V_FLAG_NO_ALT_CHAINS) /* Set by Store#flags= and StoreContext#flags=. Suppresses searching for * a alternative chain. No effect in OpenSSL >= 1.1.0. */ DefX509Const(V_FLAG_NO_ALT_CHAINS); -#endif -#if defined(X509_V_FLAG_NO_CHECK_TIME) /* Set by Store#flags= and StoreContext#flags=. Suppresses checking the * validity period of certificates and CRLs. No effect when the current * time is explicitly set by Store#time= or StoreContext#time=. */ DefX509Const(V_FLAG_NO_CHECK_TIME); -#endif /* Set by Store#purpose=. SSL/TLS client. */ DefX509Const(PURPOSE_SSL_CLIENT); diff --git a/ext/openssl/ossl_x509.h b/ext/openssl/ossl_x509.h index 4fadfa6b823188..d25167ee7b0868 100644 --- a/ext/openssl/ossl_x509.h +++ b/ext/openssl/ossl_x509.h @@ -5,7 +5,7 @@ */ /* * This program is licensed under the same licence as Ruby. - * (See the file 'LICENCE'.) + * (See the file 'COPYING'.) */ #if !defined(_OSSL_X509_H_) #define _OSSL_X509_H_ @@ -28,7 +28,6 @@ void Init_ossl_x509(void); * X509Attr */ extern VALUE cX509Attr; -extern VALUE eX509AttrError; VALUE ossl_x509attr_new(X509_ATTRIBUTE *); X509_ATTRIBUTE *GetX509AttrPtr(VALUE); @@ -38,7 +37,6 @@ void Init_ossl_x509attr(void); * X509Cert */ extern VALUE cX509Cert; -extern VALUE eX509CertError; VALUE ossl_x509_new(X509 *); X509 *GetX509CertPtr(VALUE); @@ -48,9 +46,6 @@ void Init_ossl_x509cert(void); /* * X509CRL */ -extern VALUE cX509CRL; -extern VALUE eX509CRLError; - VALUE ossl_x509crl_new(X509_CRL *); X509_CRL *GetX509CRLPtr(VALUE); void Init_ossl_x509crl(void); @@ -59,8 +54,6 @@ void Init_ossl_x509crl(void); * X509Extension */ extern VALUE cX509Ext; -extern VALUE cX509ExtFactory; -extern VALUE eX509ExtError; VALUE ossl_x509ext_new(X509_EXTENSION *); X509_EXTENSION *GetX509ExtPtr(VALUE); @@ -69,9 +62,6 @@ void Init_ossl_x509ext(void); /* * X509Name */ -extern VALUE cX509Name; -extern VALUE eX509NameError; - VALUE ossl_x509name_new(X509_NAME *); X509_NAME *GetX509NamePtr(VALUE); void Init_ossl_x509name(void); @@ -79,9 +69,6 @@ void Init_ossl_x509name(void); /* * X509Request */ -extern VALUE cX509Req; -extern VALUE eX509ReqError; - X509_REQ *GetX509ReqPtr(VALUE); void Init_ossl_x509req(void); @@ -89,7 +76,6 @@ void Init_ossl_x509req(void); * X509Revoked */ extern VALUE cX509Rev; -extern VALUE eX509RevError; VALUE ossl_x509revoked_new(X509_REVOKED *); X509_REVOKED *DupX509RevokedPtr(VALUE); @@ -98,12 +84,7 @@ void Init_ossl_x509revoked(void); /* * X509Store and X509StoreContext */ -extern VALUE cX509Store; -extern VALUE cX509StoreContext; -extern VALUE eX509StoreError; - X509_STORE *GetX509StorePtr(VALUE); - void Init_ossl_x509store(void); /* diff --git a/ext/openssl/ossl_x509attr.c b/ext/openssl/ossl_x509attr.c index d1d8bb5e95e695..3f6b89bdde5af3 100644 --- a/ext/openssl/ossl_x509attr.c +++ b/ext/openssl/ossl_x509attr.c @@ -5,7 +5,7 @@ */ /* * This program is licensed under the same licence as Ruby. - * (See the file 'LICENCE'.) + * (See the file 'COPYING'.) */ #include "ossl.h" @@ -28,7 +28,7 @@ * Classes */ VALUE cX509Attr; -VALUE eX509AttrError; +static VALUE eX509AttrError; static void ossl_x509attr_free(void *ptr) @@ -123,6 +123,7 @@ ossl_x509attr_initialize(int argc, VALUE *argv, VALUE self) return self; } +/* :nodoc: */ static VALUE ossl_x509attr_initialize_copy(VALUE self, VALUE other) { @@ -201,37 +202,36 @@ static VALUE ossl_x509attr_set_value(VALUE self, VALUE value) { X509_ATTRIBUTE *attr; - VALUE asn1_value; - int i, asn1_tag; + GetX509Attr(self, attr); OSSL_Check_Kind(value, cASN1Data); - asn1_tag = NUM2INT(rb_attr_get(value, rb_intern("@tag"))); - asn1_value = rb_attr_get(value, rb_intern("@value")); - if (asn1_tag != V_ASN1_SET) - ossl_raise(eASN1Error, "argument must be ASN1::Set"); - if (!RB_TYPE_P(asn1_value, T_ARRAY)) - ossl_raise(eASN1Error, "ASN1::Set has non-array value"); + VALUE der = ossl_to_der(value); + const unsigned char *p = (const unsigned char *)RSTRING_PTR(der); + STACK_OF(ASN1_TYPE) *sk = d2i_ASN1_SET_ANY(NULL, &p, RSTRING_LEN(der)); + if (!sk) + ossl_raise(eX509AttrError, "attribute value must be ASN1::Set"); - GetX509Attr(self, attr); if (X509_ATTRIBUTE_count(attr)) { /* populated, reset first */ - ASN1_OBJECT *obj = X509_ATTRIBUTE_get0_object(attr); - X509_ATTRIBUTE *new_attr = X509_ATTRIBUTE_create_by_OBJ(NULL, obj, 0, NULL, -1); - if (!new_attr) - ossl_raise(eX509AttrError, NULL); - SetX509Attr(self, new_attr); - X509_ATTRIBUTE_free(attr); - attr = new_attr; + ASN1_OBJECT *obj = X509_ATTRIBUTE_get0_object(attr); + X509_ATTRIBUTE *new_attr = X509_ATTRIBUTE_create_by_OBJ(NULL, obj, 0, NULL, -1); + if (!new_attr) { + sk_ASN1_TYPE_pop_free(sk, ASN1_TYPE_free); + ossl_raise(eX509AttrError, "X509_ATTRIBUTE_create_by_OBJ"); + } + SetX509Attr(self, new_attr); + X509_ATTRIBUTE_free(attr); + attr = new_attr; } - for (i = 0; i < RARRAY_LEN(asn1_value); i++) { - ASN1_TYPE *a1type = ossl_asn1_get_asn1type(RARRAY_AREF(asn1_value, i)); - if (!X509_ATTRIBUTE_set1_data(attr, ASN1_TYPE_get(a1type), - a1type->value.ptr, -1)) { - ASN1_TYPE_free(a1type); - ossl_raise(eX509AttrError, NULL); - } - ASN1_TYPE_free(a1type); + for (int i = 0; i < sk_ASN1_TYPE_num(sk); i++) { + ASN1_TYPE *a1type = sk_ASN1_TYPE_value(sk, i); + if (!X509_ATTRIBUTE_set1_data(attr, ASN1_TYPE_get(a1type), + a1type->value.ptr, -1)) { + sk_ASN1_TYPE_pop_free(sk, ASN1_TYPE_free); + ossl_raise(eX509AttrError, "X509_ATTRIBUTE_set1_data"); + } } + sk_ASN1_TYPE_pop_free(sk, ASN1_TYPE_free); return value; } diff --git a/ext/openssl/ossl_x509cert.c b/ext/openssl/ossl_x509cert.c index aa6b9bb7ce2cd8..4734602bef187c 100644 --- a/ext/openssl/ossl_x509cert.c +++ b/ext/openssl/ossl_x509cert.c @@ -5,7 +5,7 @@ */ /* * This program is licensed under the same licence as Ruby. - * (See the file 'LICENCE'.) + * (See the file 'COPYING'.) */ #include "ossl.h" @@ -28,7 +28,7 @@ * Classes */ VALUE cX509Cert; -VALUE eX509CertError; +static VALUE eX509CertError; static void ossl_x509_free(void *ptr) @@ -140,6 +140,7 @@ ossl_x509_initialize(int argc, VALUE *argv, VALUE self) return self; } +/* :nodoc: */ static VALUE ossl_x509_copy(VALUE self, VALUE other) { @@ -328,13 +329,15 @@ ossl_x509_get_signature_algorithm(VALUE self) { X509 *x509; BIO *out; + const ASN1_OBJECT *obj; VALUE str; GetX509(self, x509); out = BIO_new(BIO_s_mem()); if (!out) ossl_raise(eX509CertError, NULL); - if (!i2a_ASN1_OBJECT(out, X509_get0_tbs_sigalg(x509)->algorithm)) { + X509_ALGOR_get0(&obj, NULL, NULL, X509_get0_tbs_sigalg(x509)); + if (!i2a_ASN1_OBJECT(out, obj)) { BIO_free(out); ossl_raise(eX509CertError, NULL); } @@ -539,7 +542,11 @@ ossl_x509_sign(VALUE self, VALUE key, VALUE digest) const EVP_MD *md; pkey = GetPrivPKeyPtr(key); /* NO NEED TO DUP */ - md = ossl_evp_get_digestbyname(digest); + if (NIL_P(digest)) { + md = NULL; /* needed for some key types, e.g. Ed25519 */ + } else { + md = ossl_evp_get_digestbyname(digest); + } GetX509(self, x509); if (!X509_sign(x509, pkey, md)) { ossl_raise(eX509CertError, NULL); @@ -613,10 +620,7 @@ ossl_x509_get_extensions(VALUE self) GetX509(self, x509); count = X509_get_ext_count(x509); - if (count < 0) { - return rb_ary_new(); - } - ary = rb_ary_new2(count); + ary = rb_ary_new_capa(count); for (i=0; i string + * + * Returns the DER-encoded bytes of the certificate's to be signed certificate. + * This is mainly useful for validating embedded certificate transparency signatures. + */ +static VALUE +ossl_x509_tbs_bytes(VALUE self) +{ + X509 *x509; + int len; + unsigned char *p0; + VALUE str; + + GetX509(self, x509); + len = i2d_re_X509_tbs(x509, NULL); + if (len <= 0) { + ossl_raise(eX509CertError, "i2d_re_X509_tbs"); + } + str = rb_str_new(NULL, len); + p0 = (unsigned char *)RSTRING_PTR(str); + if (i2d_re_X509_tbs(x509, &p0) <= 0) { + ossl_raise(eX509CertError, "i2d_re_X509_tbs"); + } + ossl_str_adjust(str, p0); + + return str; +} + struct load_chained_certificates_arguments { VALUE certificates; X509 *certificate; @@ -999,4 +1033,5 @@ Init_ossl_x509cert(void) rb_define_method(cX509Cert, "add_extension", ossl_x509_add_extension, 1); rb_define_method(cX509Cert, "inspect", ossl_x509_inspect, 0); rb_define_method(cX509Cert, "==", ossl_x509_eq, 1); + rb_define_method(cX509Cert, "tbs_bytes", ossl_x509_tbs_bytes, 0); } diff --git a/ext/openssl/ossl_x509crl.c b/ext/openssl/ossl_x509crl.c index 80e29f9df2dfab..135dfe3d758d18 100644 --- a/ext/openssl/ossl_x509crl.c +++ b/ext/openssl/ossl_x509crl.c @@ -5,7 +5,7 @@ */ /* * This program is licensed under the same licence as Ruby. - * (See the file 'LICENCE'.) + * (See the file 'COPYING'.) */ #include "ossl.h" @@ -27,8 +27,8 @@ /* * Classes */ -VALUE cX509CRL; -VALUE eX509CRLError; +static VALUE cX509CRL; +static VALUE eX509CRLError; static void ossl_x509crl_free(void *ptr) @@ -117,6 +117,7 @@ ossl_x509crl_initialize(int argc, VALUE *argv, VALUE self) return self; } +/* :nodoc: */ static VALUE ossl_x509crl_copy(VALUE self, VALUE other) { @@ -169,6 +170,7 @@ ossl_x509crl_get_signature_algorithm(VALUE self) { X509_CRL *crl; const X509_ALGOR *alg; + const ASN1_OBJECT *obj; BIO *out; GetX509CRL(self, crl); @@ -176,7 +178,8 @@ ossl_x509crl_get_signature_algorithm(VALUE self) ossl_raise(eX509CRLError, NULL); } X509_CRL_get0_signature(crl, NULL, &alg); - if (!i2a_ASN1_OBJECT(out, alg->algorithm)) { + X509_ALGOR_get0(&obj, NULL, NULL, alg); + if (!i2a_ASN1_OBJECT(out, obj)) { BIO_free(out); ossl_raise(eX509CRLError, NULL); } @@ -274,21 +277,19 @@ ossl_x509crl_get_revoked(VALUE self) { X509_CRL *crl; int i, num; - X509_REVOKED *rev; - VALUE ary, revoked; + STACK_OF(X509_REVOKED) *sk; + VALUE ary; GetX509CRL(self, crl); - num = sk_X509_REVOKED_num(X509_CRL_get_REVOKED(crl)); - if (num < 0) { - OSSL_Debug("num < 0???"); - return rb_ary_new(); - } - ary = rb_ary_new2(num); + sk = X509_CRL_get_REVOKED(crl); + if (!sk) + return rb_ary_new(); + + num = sk_X509_REVOKED_num(sk); + ary = rb_ary_new_capa(num); for(i=0; ialgorithm)) { + X509_ALGOR_get0(&obj, NULL, NULL, alg); + if (!i2a_ASN1_OBJECT(out, obj)) { BIO_free(out); ossl_raise(eX509ReqError, NULL); } @@ -312,7 +315,11 @@ ossl_x509req_sign(VALUE self, VALUE key, VALUE digest) GetX509Req(self, req); pkey = GetPrivPKeyPtr(key); /* NO NEED TO DUP */ - md = ossl_evp_get_digestbyname(digest); + if (NIL_P(digest)) { + md = NULL; /* needed for some key types, e.g. Ed25519 */ + } else { + md = ossl_evp_get_digestbyname(digest); + } if (!X509_REQ_sign(req, pkey, md)) { ossl_raise(eX509ReqError, NULL); } diff --git a/ext/openssl/ossl_x509revoked.c b/ext/openssl/ossl_x509revoked.c index 108447c868f9d0..1eff5dd3556d57 100644 --- a/ext/openssl/ossl_x509revoked.c +++ b/ext/openssl/ossl_x509revoked.c @@ -5,7 +5,7 @@ */ /* * This program is licensed under the same licence as Ruby. - * (See the file 'LICENCE'.) + * (See the file 'COPYING'.) */ #include "ossl.h" @@ -28,7 +28,7 @@ * Classes */ VALUE cX509Rev; -VALUE eX509RevError; +static VALUE eX509RevError; static void ossl_x509rev_free(void *ptr) @@ -105,6 +105,7 @@ ossl_x509revoked_initialize(int argc, VALUE *argv, VALUE self) return self; } +/* :nodoc: */ static VALUE ossl_x509revoked_initialize_copy(VALUE self, VALUE other) { @@ -194,11 +195,7 @@ ossl_x509revoked_get_extensions(VALUE self) GetX509Rev(self, rev); count = X509_REVOKED_get_ext_count(rev); - if (count < 0) { - OSSL_Debug("count < 0???"); - return rb_ary_new(); - } - ary = rb_ary_new2(count); + ary = rb_ary_new_capa(count); for (i=0; iex_data.sk = NULL; -#endif X509_STORE_set_verify_cb(store, x509store_verify_cb); ossl_x509store_set_vfy_cb(self, Qnil); @@ -223,7 +219,6 @@ ossl_x509store_initialize(int argc, VALUE *argv, VALUE self) rb_iv_set(self, "@error", Qnil); rb_iv_set(self, "@error_string", Qnil); rb_iv_set(self, "@chain", Qnil); - rb_iv_set(self, "@time", Qnil); return self; } @@ -329,7 +324,12 @@ ossl_x509store_set_trust(VALUE self, VALUE trust) static VALUE ossl_x509store_set_time(VALUE self, VALUE time) { - rb_iv_set(self, "@time", time); + X509_STORE *store; + X509_VERIFY_PARAM *param; + + GetX509Store(self, store); + param = X509_STORE_get0_param(store); + X509_VERIFY_PARAM_set_time(param, NUM2LONG(rb_Integer(time))); return time; } @@ -357,15 +357,6 @@ ossl_x509store_add_file(VALUE self, VALUE file) ossl_raise(eX509StoreError, "X509_STORE_add_lookup"); if (X509_LOOKUP_load_file(lookup, path, X509_FILETYPE_PEM) != 1) ossl_raise(eX509StoreError, "X509_LOOKUP_load_file"); -#if OPENSSL_VERSION_NUMBER < 0x10101000 || defined(LIBRESSL_VERSION_NUMBER) - /* - * X509_load_cert_crl_file() which is called from X509_LOOKUP_load_file() - * did not check the return value of X509_STORE_add_{cert,crl}(), leaking - * "cert already in hash table" errors on the error queue, if duplicate - * certificates are found. This will be fixed by OpenSSL 1.1.1. - */ - ossl_clear_error(); -#endif return self; } @@ -564,7 +555,6 @@ ossl_x509stctx_new(X509_STORE_CTX *ctx) static VALUE ossl_x509stctx_set_flags(VALUE, VALUE); static VALUE ossl_x509stctx_set_purpose(VALUE, VALUE); static VALUE ossl_x509stctx_set_trust(VALUE, VALUE); -static VALUE ossl_x509stctx_set_time(VALUE, VALUE); /* * call-seq: @@ -575,7 +565,7 @@ static VALUE ossl_x509stctx_set_time(VALUE, VALUE); static VALUE ossl_x509stctx_initialize(int argc, VALUE *argv, VALUE self) { - VALUE store, cert, chain, t; + VALUE store, cert, chain; X509_STORE_CTX *ctx; X509_STORE *x509st; X509 *x509 = NULL; @@ -599,8 +589,6 @@ ossl_x509stctx_initialize(int argc, VALUE *argv, VALUE self) sk_X509_pop_free(x509s, X509_free); ossl_raise(eX509StoreError, "X509_STORE_CTX_init"); } - if (!NIL_P(t = rb_iv_get(store, "@time"))) - ossl_x509stctx_set_time(self, t); rb_iv_set(self, "@verify_callback", rb_iv_get(store, "@verify_callback")); rb_iv_set(self, "@cert", cert); @@ -631,7 +619,7 @@ ossl_x509stctx_verify(VALUE self) ossl_clear_error(); return Qfalse; default: - ossl_raise(eX509CertError, "X509_verify_cert"); + ossl_raise(eX509StoreError, "X509_verify_cert"); } } diff --git a/ext/pathname/depend b/ext/pathname/depend index 5dd8b042dec55e..585b9e47c3cb0d 100644 --- a/ext/pathname/depend +++ b/ext/pathname/depend @@ -138,6 +138,7 @@ pathname.o: $(hdrdir)/ruby/internal/intern/re.h pathname.o: $(hdrdir)/ruby/internal/intern/ruby.h pathname.o: $(hdrdir)/ruby/internal/intern/select.h pathname.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +pathname.o: $(hdrdir)/ruby/internal/intern/set.h pathname.o: $(hdrdir)/ruby/internal/intern/signal.h pathname.o: $(hdrdir)/ruby/internal/intern/sprintf.h pathname.o: $(hdrdir)/ruby/internal/intern/string.h @@ -157,6 +158,7 @@ pathname.o: $(hdrdir)/ruby/internal/special_consts.h pathname.o: $(hdrdir)/ruby/internal/static_assert.h pathname.o: $(hdrdir)/ruby/internal/stdalign.h pathname.o: $(hdrdir)/ruby/internal/stdbool.h +pathname.o: $(hdrdir)/ruby/internal/stdckdint.h pathname.o: $(hdrdir)/ruby/internal/symbol.h pathname.o: $(hdrdir)/ruby/internal/value.h pathname.o: $(hdrdir)/ruby/internal/value_type.h diff --git a/ext/pathname/extconf.rb b/ext/pathname/extconf.rb index 84e68277aae84e..b4e1617b9e6b7f 100644 --- a/ext/pathname/extconf.rb +++ b/ext/pathname/extconf.rb @@ -1,4 +1,3 @@ # frozen_string_literal: false require 'mkmf' -have_func("rb_file_s_birthtime") create_makefile('pathname') diff --git a/ext/pathname/lib/pathname.rb b/ext/pathname/lib/pathname.rb index e0f38b2b37fa02..35fd77856162a4 100644 --- a/ext/pathname/lib/pathname.rb +++ b/ext/pathname/lib/pathname.rb @@ -14,7 +14,7 @@ class Pathname - VERSION = "0.2.1" + VERSION = "0.4.0" # :stopdoc: @@ -572,7 +572,7 @@ def find(ignore_error: true) # :yield: pathname return to_enum(__method__, ignore_error: ignore_error) unless block_given? require 'find' if @path == '.' - Find.find(@path, ignore_error: ignore_error) {|f| yield self.class.new(f.sub(%r{\A\./}, '')) } + Find.find(@path, ignore_error: ignore_error) {|f| yield self.class.new(f.delete_prefix('./')) } else Find.find(@path, ignore_error: ignore_error) {|f| yield self.class.new(f) } end @@ -580,16 +580,15 @@ def find(ignore_error: true) # :yield: pathname end -autoload(:FileUtils, 'fileutils') - class Pathname # * FileUtils * # Creates a full path, including any intermediate directories that don't yet # exist. # # See FileUtils.mkpath and FileUtils.mkdir_p def mkpath(mode: nil) + require 'fileutils' FileUtils.mkpath(@path, mode: mode) - nil + self end # Recursively deletes a directory, including all directories beneath it. @@ -600,7 +599,23 @@ def rmtree(noop: nil, verbose: nil, secure: nil) # File::Path provides "mkpath" and "rmtree". require 'fileutils' FileUtils.rm_rf(@path, noop: noop, verbose: verbose, secure: secure) - nil + self end end +class Pathname # * tmpdir * + # Creates a tmp directory and wraps the returned path in a Pathname object. + # + # See Dir.mktmpdir + def self.mktmpdir + require 'tmpdir' unless defined?(Dir.mktmpdir) + if block_given? + Dir.mktmpdir do |dir| + dir = self.new(dir) + yield dir + end + else + self.new(Dir.mktmpdir) + end + end +end diff --git a/ext/pathname/pathname.c b/ext/pathname/pathname.c index 878f216fb5cad7..cdecb3f897ee68 100644 --- a/ext/pathname/pathname.c +++ b/ext/pathname/pathname.c @@ -479,7 +479,6 @@ path_atime(VALUE self) return rb_funcall(rb_cFile, id_atime, 1, get_strpath(self)); } -#if defined(HAVE_RB_FILE_S_BIRTHTIME) /* * call-seq: * pathname.birthtime -> time @@ -494,10 +493,6 @@ path_birthtime(VALUE self) { return rb_funcall(rb_cFile, id_birthtime, 1, get_strpath(self)); } -#else -/* check at compilation time for `respond_to?` */ -# define path_birthtime rb_f_notimplement -#endif /* * call-seq: diff --git a/ext/psych/depend b/ext/psych/depend index 13fbe3fb1927ca..95175841a2e541 100644 --- a/ext/psych/depend +++ b/ext/psych/depend @@ -152,6 +152,7 @@ psych.o: $(hdrdir)/ruby/internal/intern/re.h psych.o: $(hdrdir)/ruby/internal/intern/ruby.h psych.o: $(hdrdir)/ruby/internal/intern/select.h psych.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +psych.o: $(hdrdir)/ruby/internal/intern/set.h psych.o: $(hdrdir)/ruby/internal/intern/signal.h psych.o: $(hdrdir)/ruby/internal/intern/sprintf.h psych.o: $(hdrdir)/ruby/internal/intern/string.h @@ -171,6 +172,7 @@ psych.o: $(hdrdir)/ruby/internal/special_consts.h psych.o: $(hdrdir)/ruby/internal/static_assert.h psych.o: $(hdrdir)/ruby/internal/stdalign.h psych.o: $(hdrdir)/ruby/internal/stdbool.h +psych.o: $(hdrdir)/ruby/internal/stdckdint.h psych.o: $(hdrdir)/ruby/internal/symbol.h psych.o: $(hdrdir)/ruby/internal/value.h psych.o: $(hdrdir)/ruby/internal/value_type.h @@ -328,6 +330,7 @@ psych_emitter.o: $(hdrdir)/ruby/internal/intern/re.h psych_emitter.o: $(hdrdir)/ruby/internal/intern/ruby.h psych_emitter.o: $(hdrdir)/ruby/internal/intern/select.h psych_emitter.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +psych_emitter.o: $(hdrdir)/ruby/internal/intern/set.h psych_emitter.o: $(hdrdir)/ruby/internal/intern/signal.h psych_emitter.o: $(hdrdir)/ruby/internal/intern/sprintf.h psych_emitter.o: $(hdrdir)/ruby/internal/intern/string.h @@ -347,6 +350,7 @@ psych_emitter.o: $(hdrdir)/ruby/internal/special_consts.h psych_emitter.o: $(hdrdir)/ruby/internal/static_assert.h psych_emitter.o: $(hdrdir)/ruby/internal/stdalign.h psych_emitter.o: $(hdrdir)/ruby/internal/stdbool.h +psych_emitter.o: $(hdrdir)/ruby/internal/stdckdint.h psych_emitter.o: $(hdrdir)/ruby/internal/symbol.h psych_emitter.o: $(hdrdir)/ruby/internal/value.h psych_emitter.o: $(hdrdir)/ruby/internal/value_type.h @@ -504,6 +508,7 @@ psych_parser.o: $(hdrdir)/ruby/internal/intern/re.h psych_parser.o: $(hdrdir)/ruby/internal/intern/ruby.h psych_parser.o: $(hdrdir)/ruby/internal/intern/select.h psych_parser.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +psych_parser.o: $(hdrdir)/ruby/internal/intern/set.h psych_parser.o: $(hdrdir)/ruby/internal/intern/signal.h psych_parser.o: $(hdrdir)/ruby/internal/intern/sprintf.h psych_parser.o: $(hdrdir)/ruby/internal/intern/string.h @@ -523,6 +528,7 @@ psych_parser.o: $(hdrdir)/ruby/internal/special_consts.h psych_parser.o: $(hdrdir)/ruby/internal/static_assert.h psych_parser.o: $(hdrdir)/ruby/internal/stdalign.h psych_parser.o: $(hdrdir)/ruby/internal/stdbool.h +psych_parser.o: $(hdrdir)/ruby/internal/stdckdint.h psych_parser.o: $(hdrdir)/ruby/internal/symbol.h psych_parser.o: $(hdrdir)/ruby/internal/value.h psych_parser.o: $(hdrdir)/ruby/internal/value_type.h @@ -680,6 +686,7 @@ psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/re.h psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/ruby.h psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/select.h psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/set.h psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/signal.h psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/sprintf.h psych_to_ruby.o: $(hdrdir)/ruby/internal/intern/string.h @@ -699,6 +706,7 @@ psych_to_ruby.o: $(hdrdir)/ruby/internal/special_consts.h psych_to_ruby.o: $(hdrdir)/ruby/internal/static_assert.h psych_to_ruby.o: $(hdrdir)/ruby/internal/stdalign.h psych_to_ruby.o: $(hdrdir)/ruby/internal/stdbool.h +psych_to_ruby.o: $(hdrdir)/ruby/internal/stdckdint.h psych_to_ruby.o: $(hdrdir)/ruby/internal/symbol.h psych_to_ruby.o: $(hdrdir)/ruby/internal/value.h psych_to_ruby.o: $(hdrdir)/ruby/internal/value_type.h @@ -856,6 +864,7 @@ psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/re.h psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/ruby.h psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/select.h psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/set.h psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/signal.h psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/sprintf.h psych_yaml_tree.o: $(hdrdir)/ruby/internal/intern/string.h @@ -875,6 +884,7 @@ psych_yaml_tree.o: $(hdrdir)/ruby/internal/special_consts.h psych_yaml_tree.o: $(hdrdir)/ruby/internal/static_assert.h psych_yaml_tree.o: $(hdrdir)/ruby/internal/stdalign.h psych_yaml_tree.o: $(hdrdir)/ruby/internal/stdbool.h +psych_yaml_tree.o: $(hdrdir)/ruby/internal/stdckdint.h psych_yaml_tree.o: $(hdrdir)/ruby/internal/symbol.h psych_yaml_tree.o: $(hdrdir)/ruby/internal/value.h psych_yaml_tree.o: $(hdrdir)/ruby/internal/value_type.h diff --git a/ext/psych/lib/psych.rb b/ext/psych/lib/psych.rb index ae167472f2aee9..0c158c9ff329b1 100644 --- a/ext/psych/lib/psych.rb +++ b/ext/psych/lib/psych.rb @@ -1,4 +1,6 @@ # frozen_string_literal: true +require 'date' + require_relative 'psych/versions' case RUBY_ENGINE when 'jruby' @@ -21,7 +23,6 @@ require_relative 'psych/omap' require_relative 'psych/set' require_relative 'psych/coder' -require_relative 'psych/core_ext' require_relative 'psych/stream' require_relative 'psych/json/tree_builder' require_relative 'psych/json/stream' @@ -84,7 +85,7 @@ # Psych.safe_load_file("data.yml", permitted_classes: [Date]) # Psych.load_file("trusted_database.yml") # -# ==== Exception handling +# ==== \Exception handling # # begin # # The second argument changes only the exception contents @@ -148,7 +149,7 @@ # # Returns Psych::Nodes::Document # Psych.parse_file('database.yml') # -# ==== Exception handling +# ==== \Exception handling # # begin # # The second argument changes only the exception contents @@ -340,7 +341,7 @@ def self.safe_load yaml, permitted_classes: [], permitted_symbols: [], aliases: # provided, the object contained in the first document will be returned. # +filename+ will be used in the exception message if any exception # is raised while parsing. If +yaml+ is empty, it returns - # the specified +fallback+ return value, which defaults to +false+. + # the specified +fallback+ return value, which defaults to +nil+. # # Raises a Psych::SyntaxError when a YAML syntax error is detected. # @@ -479,6 +480,7 @@ def self.parse_stream yaml, filename: nil, &block # # Default: 2. # [:line_width] Max character to wrap line at. + # For unlimited line width use -1. # # Default: 0 (meaning "wrap at 81"). # [:canonical] Write "canonical" YAML form (very verbose, yet @@ -489,6 +491,10 @@ def self.parse_stream yaml, filename: nil, &block # # Default: false. # + # [:stringify_names] Dump symbol keys in Hash objects as string. + # + # Default: false. + # # Example: # # # Dump an array, get back a YAML string @@ -502,6 +508,9 @@ def self.parse_stream yaml, filename: nil, &block # # # Dump an array to an IO with indentation set # Psych.dump(['a', ['b']], StringIO.new, indentation: 3) + # + # # Dump hash with symbol keys as string + # Psych.dump({a: "b"}, stringify_names: true) # => "---\na: b\n" def self.dump o, io = nil, options = {} if Hash === io options = io @@ -552,6 +561,7 @@ def self.dump o, io = nil, options = {} # # Default: 2. # [:line_width] Max character to wrap line at. + # For unlimited line width use -1. # # Default: 0 (meaning "wrap at 81"). # [:canonical] Write "canonical" YAML form (very verbose, yet @@ -562,6 +572,10 @@ def self.dump o, io = nil, options = {} # # Default: false. # + # [:stringify_names] Dump symbol keys in Hash objects as string. + # + # Default: false. + # # Example: # # # Dump an array, get back a YAML string @@ -575,6 +589,9 @@ def self.dump o, io = nil, options = {} # # # Dump an array to an IO with indentation set # Psych.safe_dump(['a', ['b']], StringIO.new, indentation: 3) + # + # # Dump hash with symbol keys as string + # Psych.dump({a: "b"}, stringify_names: true) # => "---\na: b\n" def self.safe_dump o, io = nil, options = {} if Hash === io options = io @@ -636,6 +653,35 @@ def self.load_stream yaml, filename: nil, fallback: [], **kwargs result end + ### + # Load multiple documents given in +yaml+. Returns the parsed documents + # as a list. + # + # Example: + # + # Psych.safe_load_stream("--- foo\n...\n--- bar\n...") # => ['foo', 'bar'] + # + # list = [] + # Psych.safe_load_stream("--- foo\n...\n--- bar\n...") do |ruby| + # list << ruby + # end + # list # => ['foo', 'bar'] + # + def self.safe_load_stream yaml, filename: nil, permitted_classes: [], aliases: false + documents = parse_stream(yaml, filename: filename).children.map do |child| + stream = Psych::Nodes::Stream.new + stream.children << child + safe_load(stream.to_yaml, permitted_classes: permitted_classes, aliases: aliases) + end + + if block_given? + documents.each { |doc| yield doc } + nil + else + documents + end + end + ### # Load the document contained in +filename+. Returns the yaml contained in # +filename+ as a Ruby object, or if the file is empty, it returns @@ -653,7 +699,7 @@ def self.unsafe_load_file filename, **kwargs ### # Safely loads the document contained in +filename+. Returns the yaml contained in # +filename+ as a Ruby object, or if the file is empty, it returns - # the specified +fallback+ return value, which defaults to +false+. + # the specified +fallback+ return value, which defaults to +nil+. # See safe_load for options. def self.safe_load_file filename, **kwargs File.open(filename, 'r:bom|utf-8') { |f| @@ -664,7 +710,7 @@ def self.safe_load_file filename, **kwargs ### # Loads the document contained in +filename+. Returns the yaml contained in # +filename+ as a Ruby object, or if the file is empty, it returns - # the specified +fallback+ return value, which defaults to +false+. + # the specified +fallback+ return value, which defaults to +nil+. # See load for options. def self.load_file filename, **kwargs File.open(filename, 'r:bom|utf-8') { |f| @@ -743,3 +789,5 @@ def domain_types=(value) self.domain_types = {} # :startdoc: end + +require_relative 'psych/core_ext' diff --git a/ext/psych/lib/psych/class_loader.rb b/ext/psych/lib/psych/class_loader.rb index 50efc35ee28fcd..c8f509720af6a8 100644 --- a/ext/psych/lib/psych/class_loader.rb +++ b/ext/psych/lib/psych/class_loader.rb @@ -6,6 +6,7 @@ module Psych class ClassLoader # :nodoc: BIG_DECIMAL = 'BigDecimal' COMPLEX = 'Complex' + DATA = 'Data' unless RUBY_VERSION < "3.2" DATE = 'Date' DATE_TIME = 'DateTime' EXCEPTION = 'Exception' diff --git a/ext/psych/lib/psych/core_ext.rb b/ext/psych/lib/psych/core_ext.rb index 0721a133c3ae59..fc259fd4a2f771 100644 --- a/ext/psych/lib/psych/core_ext.rb +++ b/ext/psych/lib/psych/core_ext.rb @@ -17,3 +17,24 @@ def to_yaml options = {} if defined?(::IRB) require_relative 'y' end + +# Up to Ruby 3.4, Set was a regular object and was dumped as such +# by Pysch. +# Starting from Ruby 3.5 it's a core class written in C, so we have to implement +# #encode_with / #init_with to preserve backward compatibility. +if defined?(::Set) && Set.new.instance_variables.empty? + class Set + def encode_with(coder) + hash = {} + each do |m| + hash[m] = true + end + coder["hash"] = hash + coder + end + + def init_with(coder) + replace(coder["hash"].keys) + end + end +end diff --git a/ext/psych/lib/psych/nodes/node.rb b/ext/psych/lib/psych/nodes/node.rb index f44fce5f053a5f..6ae5c591484539 100644 --- a/ext/psych/lib/psych/nodes/node.rb +++ b/ext/psych/lib/psych/nodes/node.rb @@ -1,5 +1,4 @@ # frozen_string_literal: true -require 'stringio' require_relative '../class_loader' require_relative '../scalar_scanner' @@ -56,6 +55,8 @@ def to_ruby(symbolize_names: false, freeze: false, strict_integer: false) # # See also Psych::Visitors::Emitter def yaml io = nil, options = {} + require "stringio" unless defined?(StringIO) + real_io = io || StringIO.new(''.encode('utf-8')) Visitors::Emitter.new(real_io, options).accept self diff --git a/ext/psych/lib/psych/scalar_scanner.rb b/ext/psych/lib/psych/scalar_scanner.rb index 3cb4bf3c7e89da..8cf868f8638e9e 100644 --- a/ext/psych/lib/psych/scalar_scanner.rb +++ b/ext/psych/lib/psych/scalar_scanner.rb @@ -11,18 +11,18 @@ class ScalarScanner # Base 60, [-+]inf and NaN are handled separately FLOAT = /^(?:[-+]?([0-9][0-9_,]*)?\.[0-9]*([eE][-+][0-9]+)?(?# base 10))$/x - # Taken from http://yaml.org/type/int.html - INTEGER_STRICT = /^(?:[-+]?0b[0-1_]+ (?# base 2) - |[-+]?0[0-7_]+ (?# base 8) - |[-+]?(0|[1-9][0-9_]*) (?# base 10) - |[-+]?0x[0-9a-fA-F_]+ (?# base 16))$/x + # Taken from http://yaml.org/type/int.html and modified to ensure at least one numerical symbol exists + INTEGER_STRICT = /^(?:[-+]?0b[_]*[0-1][0-1_]* (?# base 2) + |[-+]?0[_]*[0-7][0-7_]* (?# base 8) + |[-+]?(0|[1-9][0-9_]*) (?# base 10) + |[-+]?0x[_]*[0-9a-fA-F][0-9a-fA-F_]* (?# base 16))$/x # Same as above, but allows commas. # Not to YML spec, but kept for backwards compatibility - INTEGER_LEGACY = /^(?:[-+]?0b[0-1_,]+ (?# base 2) - |[-+]?0[0-7_,]+ (?# base 8) + INTEGER_LEGACY = /^(?:[-+]?0b[_,]*[0-1][0-1_,]* (?# base 2) + |[-+]?0[_,]*[0-7][0-7_,]* (?# base 8) |[-+]?(?:0|[1-9](?:[0-9]|,[0-9]|_[0-9])*) (?# base 10) - |[-+]?0x[0-9a-fA-F_,]+ (?# base 16))$/x + |[-+]?0x[_,]*[0-9a-fA-F][0-9a-fA-F_,]* (?# base 16))$/x attr_reader :class_loader @@ -61,7 +61,6 @@ def tokenize string string end elsif string.match?(/^\d{4}-(?:1[012]|0\d|\d)-(?:[12]\d|3[01]|0\d|\d)$/) - require 'date' begin class_loader.date.strptime(string, '%F', Date::GREGORIAN) rescue ArgumentError diff --git a/ext/psych/lib/psych/versions.rb b/ext/psych/lib/psych/versions.rb index 57b7659b571a85..3202b10296f549 100644 --- a/ext/psych/lib/psych/versions.rb +++ b/ext/psych/lib/psych/versions.rb @@ -2,9 +2,9 @@ module Psych # The version of Psych you are using - VERSION = '5.1.0' + VERSION = '5.2.6' if RUBY_ENGINE == 'jruby' - DEFAULT_SNAKEYAML_VERSION = '2.6'.freeze + DEFAULT_SNAKEYAML_VERSION = '2.9'.freeze end end diff --git a/ext/psych/lib/psych/visitors/to_ruby.rb b/ext/psych/lib/psych/visitors/to_ruby.rb index 8614251ca9e6c3..580a74e9fb034d 100644 --- a/ext/psych/lib/psych/visitors/to_ruby.rb +++ b/ext/psych/lib/psych/visitors/to_ruby.rb @@ -36,7 +36,7 @@ def accept target unless @domain_types.empty? || !target.tag key = target.tag.sub(/^[!\/]*/, '').sub(/(,\d+)\//, '\1:') - key = "tag:#{key}" unless key =~ /^(?:tag:|x-private)/ + key = "tag:#{key}" unless key.match?(/^(?:tag:|x-private)/) if @domain_types.key? key value, block = @domain_types[key] @@ -79,7 +79,6 @@ def deserialize o class_loader.big_decimal._load o.value when "!ruby/object:DateTime" class_loader.date_time - require 'date' unless defined? DateTime t = @ss.parse_time(o.value) DateTime.civil(*t.to_a[0, 6].reverse, Rational(t.utc_offset, 86400)) + (t.subsec/86400) @@ -97,11 +96,11 @@ def deserialize o Float(@ss.tokenize(o.value)) when "!ruby/regexp" klass = class_loader.regexp - o.value =~ /^\/(.*)\/([mixn]*)$/m - source = $1 + matches = /^\/(?.*)\/(?[mixn]*)$/m.match(o.value) + source = matches[:string].gsub('\/', '/') options = 0 lang = nil - ($2 || '').split('').each do |option| + matches[:options].each_char do |option| case option when 'x' then options |= Regexp::EXTENDED when 'i' then options |= Regexp::IGNORECASE @@ -198,6 +197,32 @@ def visit_Psych_Nodes_Mapping o s end + when /^!ruby\/data(-with-ivars)?(?::(.*))?$/ + data = register(o, resolve_class($2).allocate) if $2 + members = {} + + if $1 # data-with-ivars + ivars = {} + o.children.each_slice(2) do |type, vars| + case accept(type) + when 'members' + revive_data_members(members, vars) + data ||= allocate_anon_data(o, members) + when 'ivars' + revive_hash(ivars, vars) + end + end + ivars.each do |ivar, v| + data.instance_variable_set ivar, v + end + else + revive_data_members(members, o) + end + data ||= allocate_anon_data(o, members) + init_struct(data, **members) + data.freeze + data + when /^!ruby\/object:?(.*)?$/ name = $1 || 'Object' @@ -341,6 +366,20 @@ def register_empty object list end + def allocate_anon_data node, members + klass = class_loader.data.define(*members.keys) + register(node, klass.allocate) + end + + def revive_data_members hash, o + o.children.each_slice(2) do |k,v| + name = accept(k) + value = accept(v) + hash[class_loader.symbolize(name)] = value + end + hash + end + def revive_hash hash, o, tagged= false o.children.each_slice(2) { |k,v| key = accept(k) diff --git a/ext/psych/lib/psych/visitors/yaml_tree.rb b/ext/psych/lib/psych/visitors/yaml_tree.rb index 51491783c314c7..b6c86f4c94046f 100644 --- a/ext/psych/lib/psych/visitors/yaml_tree.rb +++ b/ext/psych/lib/psych/visitors/yaml_tree.rb @@ -15,30 +15,25 @@ module Visitors class YAMLTree < Psych::Visitors::Visitor class Registrar # :nodoc: def initialize - @obj_to_id = {} - @obj_to_node = {} - @targets = [] + @obj_to_id = {}.compare_by_identity + @obj_to_node = {}.compare_by_identity @counter = 0 end def register target, node - return unless target.respond_to? :object_id - @targets << target - @obj_to_node[target.object_id] = node + @obj_to_node[target] = node end def key? target - @obj_to_node.key? target.object_id - rescue NoMethodError - false + @obj_to_node.key? target end def id_for target - @obj_to_id[target.object_id] ||= (@counter += 1) + @obj_to_id[target] ||= (@counter += 1) end def node_for target - @obj_to_node[target.object_id] + @obj_to_node[target] end end @@ -70,6 +65,7 @@ def initialize emitter, ss, options fail(ArgumentError, "Invalid line_width #{@line_width}, must be non-negative or -1 for unlimited.") end end + @stringify_names = options[:stringify_names] @coders = [] @dispatch_cache = Hash.new do |h,klass| @@ -77,7 +73,7 @@ def initialize emitter, ss, options method = respond_to?(method) ? method : h[klass.superclass] - raise(TypeError, "Can't dump #{target.class}") unless method + raise(TypeError, "can't dump #{klass.name}") unless method h[klass] = method end.compare_by_identity @@ -166,6 +162,44 @@ def visit_Object o alias :visit_Delegator :visit_Object + def visit_Data o + ivars = o.instance_variables + if ivars.empty? + tag = ['!ruby/data', o.class.name].compact.join(':') + register o, @emitter.start_mapping(nil, tag, false, Nodes::Mapping::BLOCK) + o.members.each do |member| + @emitter.scalar member.to_s, nil, nil, true, false, Nodes::Scalar::ANY + accept o.send member + end + @emitter.end_mapping + + else + tag = ['!ruby/data-with-ivars', o.class.name].compact.join(':') + node = @emitter.start_mapping(nil, tag, false, Psych::Nodes::Mapping::BLOCK) + register(o, node) + + # Dump the members + accept 'members' + @emitter.start_mapping nil, nil, true, Nodes::Mapping::BLOCK + o.members.each do |member| + @emitter.scalar member.to_s, nil, nil, true, false, Nodes::Scalar::ANY + accept o.send member + end + @emitter.end_mapping + + # Dump the ivars + accept 'ivars' + @emitter.start_mapping nil, nil, true, Nodes::Mapping::BLOCK + ivars.each do |ivar| + accept ivar.to_s + accept o.instance_variable_get ivar + end + @emitter.end_mapping + + @emitter.end_mapping + end + end unless RUBY_VERSION < "3.2" + def visit_Struct o tag = ['!ruby/struct', o.class.name].compact.join(':') @@ -193,7 +227,8 @@ def visit_Regexp o end def visit_Date o - register o, visit_Integer(o.gregorian) + formatted = format_date o + register o, @emitter.scalar(formatted, nil, nil, true, false, Nodes::Scalar::ANY) end def visit_DateTime o @@ -265,20 +300,20 @@ def visit_String o style = Nodes::Scalar::LITERAL plain = false quote = false - elsif o =~ /\n(?!\Z)/ # match \n except blank line at the end of string + elsif o.match?(/\n(?!\Z)/) # match \n except blank line at the end of string style = Nodes::Scalar::LITERAL elsif o == '<<' style = Nodes::Scalar::SINGLE_QUOTED tag = 'tag:yaml.org,2002:str' plain = false quote = false - elsif o == 'y' || o == 'n' + elsif o == 'y' || o == 'Y' || o == 'n' || o == 'N' style = Nodes::Scalar::DOUBLE_QUOTED elsif @line_width && o.length > @line_width style = Nodes::Scalar::FOLDED - elsif o =~ /^[^[:word:]][^"]*$/ + elsif o.match?(/^[^[:word:]][^"]*$/) style = Nodes::Scalar::DOUBLE_QUOTED - elsif not String === @ss.tokenize(o) or /\A0[0-7]*[89]/ =~ o + elsif not String === @ss.tokenize(o) or /\A0[0-7]*[89]/.match?(o) style = Nodes::Scalar::SINGLE_QUOTED end @@ -328,7 +363,7 @@ def visit_Hash o if o.class == ::Hash register(o, @emitter.start_mapping(nil, nil, true, Psych::Nodes::Mapping::BLOCK)) o.each do |k,v| - accept k + accept(@stringify_names && Symbol === k ? k.to_s : k) accept v end @emitter.end_mapping @@ -341,7 +376,7 @@ def visit_Psych_Set o register(o, @emitter.start_mapping(nil, '!set', false, Psych::Nodes::Mapping::BLOCK)) o.each do |k,v| - accept k + accept(@stringify_names && Symbol === k ? k.to_s : k) accept v end @@ -490,6 +525,10 @@ def format_time time, utc = time.utc? end end + def format_date date + date.strftime("%Y-%m-%d") + end + def register target, yaml_obj @st.register target, yaml_obj yaml_obj diff --git a/ext/psych/psych.c b/ext/psych/psych.c index 8af0bb6a5a2c57..afbd7a35714f9d 100644 --- a/ext/psych/psych.c +++ b/ext/psych/psych.c @@ -23,7 +23,7 @@ VALUE mPsych; void Init_psych(void) { #ifdef HAVE_RB_EXT_RACTOR_SAFE - RB_EXT_RACTOR_SAFE(true); + RB_EXT_RACTOR_SAFE(true); #endif mPsych = rb_define_module("Psych"); @@ -34,4 +34,3 @@ void Init_psych(void) Init_psych_to_ruby(); Init_psych_yaml_tree(); } -/* vim: set noet sws=4 sw=4: */ diff --git a/ext/psych/psych.gemspec b/ext/psych/psych.gemspec index 34f70095d32d1d..a32f79bc16ff88 100644 --- a/ext/psych/psych.gemspec +++ b/ext/psych/psych.gemspec @@ -75,6 +75,8 @@ DESCRIPTION s.add_dependency 'stringio' end - s.metadata['msys2_mingw_dependencies'] = 'libyaml' + s.add_dependency 'date' + s.metadata['msys2_mingw_dependencies'] = 'libyaml' + s.metadata['changelog_uri'] = s.homepage + '/releases' end diff --git a/ext/psych/psych_emitter.c b/ext/psych/psych_emitter.c index 022ffa0946708a..624ab7c528f864 100644 --- a/ext/psych/psych_emitter.c +++ b/ext/psych/psych_emitter.c @@ -17,7 +17,7 @@ static ID id_canonical; static void emit(yaml_emitter_t * emitter, yaml_event_t * event) { if(!yaml_emitter_emit(emitter, event)) - rb_raise(rb_eRuntimeError, "%s", emitter->problem); + rb_raise(rb_eRuntimeError, "%s", emitter->problem); } static int writer(void *ctx, unsigned char *buffer, size_t size) @@ -82,13 +82,13 @@ static VALUE initialize(int argc, VALUE *argv, VALUE self) TypedData_Get_Struct(self, yaml_emitter_t, &psych_emitter_type, emitter); if (rb_scan_args(argc, argv, "11", &io, &options) == 2) { - line_width = rb_funcall(options, id_line_width, 0); - indent = rb_funcall(options, id_indentation, 0); - canonical = rb_funcall(options, id_canonical, 0); + line_width = rb_funcall(options, id_line_width, 0); + indent = rb_funcall(options, id_indentation, 0); + canonical = rb_funcall(options, id_canonical, 0); - yaml_emitter_set_width(emitter, NUM2INT(line_width)); - yaml_emitter_set_indent(emitter, NUM2INT(indent)); - yaml_emitter_set_canonical(emitter, Qtrue == canonical ? 1 : 0); + yaml_emitter_set_width(emitter, NUM2INT(line_width)); + yaml_emitter_set_indent(emitter, NUM2INT(indent)); + yaml_emitter_set_canonical(emitter, Qtrue == canonical ? 1 : 0); } rb_ivar_set(self, id_io, io); @@ -136,84 +136,118 @@ static VALUE end_stream(VALUE self) return self; } -/* call-seq: emitter.start_document(version, tags, implicit) - * - * Start a document emission with YAML +version+, +tags+, and an +implicit+ - * start. - * - * See Psych::Handler#start_document - */ -static VALUE start_document(VALUE self, VALUE version, VALUE tags, VALUE imp) +struct start_document_data { + VALUE self; + VALUE version; + VALUE tags; + VALUE imp; + + yaml_tag_directive_t * head; +}; + +static VALUE start_document_try(VALUE d) { + struct start_document_data * data = (struct start_document_data *)d; + VALUE self = data->self; + VALUE version = data->version; + VALUE tags = data->tags; + VALUE imp = data->imp; + yaml_emitter_t * emitter; - yaml_tag_directive_t * head = NULL; yaml_tag_directive_t * tail = NULL; yaml_event_t event; yaml_version_directive_t version_directive; TypedData_Get_Struct(self, yaml_emitter_t, &psych_emitter_type, emitter); - Check_Type(version, T_ARRAY); if(RARRAY_LEN(version) > 0) { - VALUE major = rb_ary_entry(version, (long)0); - VALUE minor = rb_ary_entry(version, (long)1); + VALUE major = rb_ary_entry(version, (long)0); + VALUE minor = rb_ary_entry(version, (long)1); - version_directive.major = NUM2INT(major); - version_directive.minor = NUM2INT(minor); + version_directive.major = NUM2INT(major); + version_directive.minor = NUM2INT(minor); } if(RTEST(tags)) { - long i = 0; - long len; - rb_encoding * encoding = rb_utf8_encoding(); - - Check_Type(tags, T_ARRAY); - - len = RARRAY_LEN(tags); - head = xcalloc((size_t)len, sizeof(yaml_tag_directive_t)); - tail = head; - - for(i = 0; i < len && i < RARRAY_LEN(tags); i++) { - VALUE tuple = RARRAY_AREF(tags, i); - VALUE name; - VALUE value; - - Check_Type(tuple, T_ARRAY); - - if(RARRAY_LEN(tuple) < 2) { - xfree(head); - rb_raise(rb_eRuntimeError, "tag tuple must be of length 2"); - } - name = RARRAY_AREF(tuple, 0); - value = RARRAY_AREF(tuple, 1); - StringValue(name); - StringValue(value); - name = rb_str_export_to_enc(name, encoding); - value = rb_str_export_to_enc(value, encoding); - - tail->handle = (yaml_char_t *)StringValueCStr(name); - tail->prefix = (yaml_char_t *)StringValueCStr(value); - - tail++; - } + long i = 0; + long len; + rb_encoding * encoding = rb_utf8_encoding(); + + Check_Type(tags, T_ARRAY); + + len = RARRAY_LEN(tags); + data->head = xcalloc((size_t)len, sizeof(yaml_tag_directive_t)); + tail = data->head; + + for(i = 0; i < len && i < RARRAY_LEN(tags); i++) { + VALUE tuple = RARRAY_AREF(tags, i); + VALUE name; + VALUE value; + + Check_Type(tuple, T_ARRAY); + + if(RARRAY_LEN(tuple) < 2) { + rb_raise(rb_eRuntimeError, "tag tuple must be of length 2"); + } + + name = RARRAY_AREF(tuple, 0); + value = RARRAY_AREF(tuple, 1); + StringValue(name); + StringValue(value); + name = rb_str_export_to_enc(name, encoding); + value = rb_str_export_to_enc(value, encoding); + + tail->handle = (yaml_char_t *)StringValueCStr(name); + tail->prefix = (yaml_char_t *)StringValueCStr(value); + + tail++; + } } yaml_document_start_event_initialize( - &event, - (RARRAY_LEN(version) > 0) ? &version_directive : NULL, - head, - tail, - imp ? 1 : 0 - ); + &event, + (RARRAY_LEN(version) > 0) ? &version_directive : NULL, + data->head, + tail, + imp ? 1 : 0 + ); emit(emitter, &event); - if(head) xfree(head); - return self; } +static VALUE start_document_ensure(VALUE d) +{ + struct start_document_data * data = (struct start_document_data *)d; + + xfree(data->head); + + return Qnil; +} + +/* call-seq: emitter.start_document(version, tags, implicit) + * + * Start a document emission with YAML +version+, +tags+, and an +implicit+ + * start. + * + * See Psych::Handler#start_document + */ +static VALUE start_document(VALUE self, VALUE version, VALUE tags, VALUE imp) +{ + struct start_document_data data = { + .self = self, + .version = version, + .tags = tags, + .imp = imp, + + .head = NULL, + }; + + return rb_ensure(start_document_try, (VALUE)&data, start_document_ensure, (VALUE)&data); +} + /* call-seq: emitter.end_document(implicit) * * End a document emission with an +implicit+ ending. @@ -241,14 +275,14 @@ static VALUE end_document(VALUE self, VALUE imp) * See Psych::Handler#scalar */ static VALUE scalar( - VALUE self, - VALUE value, - VALUE anchor, - VALUE tag, - VALUE plain, - VALUE quoted, - VALUE style - ) { + VALUE self, + VALUE value, + VALUE anchor, + VALUE tag, + VALUE plain, + VALUE quoted, + VALUE style + ) { yaml_emitter_t * emitter; yaml_event_t event; rb_encoding *encoding; @@ -261,25 +295,26 @@ static VALUE scalar( value = rb_str_export_to_enc(value, encoding); if(!NIL_P(anchor)) { - Check_Type(anchor, T_STRING); - anchor = rb_str_export_to_enc(anchor, encoding); + Check_Type(anchor, T_STRING); + anchor = rb_str_export_to_enc(anchor, encoding); } if(!NIL_P(tag)) { - Check_Type(tag, T_STRING); - tag = rb_str_export_to_enc(tag, encoding); + Check_Type(tag, T_STRING); + tag = rb_str_export_to_enc(tag, encoding); } + const char *value_ptr = StringValuePtr(value); yaml_scalar_event_initialize( - &event, - (yaml_char_t *)(NIL_P(anchor) ? NULL : StringValueCStr(anchor)), - (yaml_char_t *)(NIL_P(tag) ? NULL : StringValueCStr(tag)), - (yaml_char_t*)StringValuePtr(value), - (int)RSTRING_LEN(value), - plain ? 1 : 0, - quoted ? 1 : 0, - (yaml_scalar_style_t)NUM2INT(style) - ); + &event, + (yaml_char_t *)(NIL_P(anchor) ? NULL : StringValueCStr(anchor)), + (yaml_char_t *)(NIL_P(tag) ? NULL : StringValueCStr(tag)), + (yaml_char_t*)value_ptr, + (int)RSTRING_LEN(value), + plain ? 1 : 0, + quoted ? 1 : 0, + (yaml_scalar_style_t)NUM2INT(style) + ); emit(emitter, &event); @@ -294,36 +329,36 @@ static VALUE scalar( * See Psych::Handler#start_sequence */ static VALUE start_sequence( - VALUE self, - VALUE anchor, - VALUE tag, - VALUE implicit, - VALUE style - ) { + VALUE self, + VALUE anchor, + VALUE tag, + VALUE implicit, + VALUE style + ) { yaml_emitter_t * emitter; yaml_event_t event; rb_encoding * encoding = rb_utf8_encoding(); if(!NIL_P(anchor)) { - Check_Type(anchor, T_STRING); - anchor = rb_str_export_to_enc(anchor, encoding); + Check_Type(anchor, T_STRING); + anchor = rb_str_export_to_enc(anchor, encoding); } if(!NIL_P(tag)) { - Check_Type(tag, T_STRING); - tag = rb_str_export_to_enc(tag, encoding); + Check_Type(tag, T_STRING); + tag = rb_str_export_to_enc(tag, encoding); } TypedData_Get_Struct(self, yaml_emitter_t, &psych_emitter_type, emitter); yaml_sequence_start_event_initialize( - &event, - (yaml_char_t *)(NIL_P(anchor) ? NULL : StringValueCStr(anchor)), - (yaml_char_t *)(NIL_P(tag) ? NULL : StringValueCStr(tag)), - implicit ? 1 : 0, - (yaml_sequence_style_t)NUM2INT(style) - ); + &event, + (yaml_char_t *)(NIL_P(anchor) ? NULL : StringValueCStr(anchor)), + (yaml_char_t *)(NIL_P(tag) ? NULL : StringValueCStr(tag)), + implicit ? 1 : 0, + (yaml_sequence_style_t)NUM2INT(style) + ); emit(emitter, &event); @@ -357,12 +392,12 @@ static VALUE end_sequence(VALUE self) * See Psych::Handler#start_mapping */ static VALUE start_mapping( - VALUE self, - VALUE anchor, - VALUE tag, - VALUE implicit, - VALUE style - ) { + VALUE self, + VALUE anchor, + VALUE tag, + VALUE implicit, + VALUE style + ) { yaml_emitter_t * emitter; yaml_event_t event; rb_encoding *encoding; @@ -372,22 +407,22 @@ static VALUE start_mapping( encoding = rb_utf8_encoding(); if(!NIL_P(anchor)) { - Check_Type(anchor, T_STRING); - anchor = rb_str_export_to_enc(anchor, encoding); + Check_Type(anchor, T_STRING); + anchor = rb_str_export_to_enc(anchor, encoding); } if(!NIL_P(tag)) { - Check_Type(tag, T_STRING); - tag = rb_str_export_to_enc(tag, encoding); + Check_Type(tag, T_STRING); + tag = rb_str_export_to_enc(tag, encoding); } yaml_mapping_start_event_initialize( - &event, - (yaml_char_t *)(NIL_P(anchor) ? NULL : StringValueCStr(anchor)), - (yaml_char_t *)(NIL_P(tag) ? NULL : StringValueCStr(tag)), - implicit ? 1 : 0, - (yaml_mapping_style_t)NUM2INT(style) - ); + &event, + (yaml_char_t *)(NIL_P(anchor) ? NULL : StringValueCStr(anchor)), + (yaml_char_t *)(NIL_P(tag) ? NULL : StringValueCStr(tag)), + implicit ? 1 : 0, + (yaml_mapping_style_t)NUM2INT(style) + ); emit(emitter, &event); @@ -426,14 +461,14 @@ static VALUE alias(VALUE self, VALUE anchor) TypedData_Get_Struct(self, yaml_emitter_t, &psych_emitter_type, emitter); if(!NIL_P(anchor)) { - Check_Type(anchor, T_STRING); - anchor = rb_str_export_to_enc(anchor, rb_utf8_encoding()); + Check_Type(anchor, T_STRING); + anchor = rb_str_export_to_enc(anchor, rb_utf8_encoding()); } yaml_alias_event_initialize( - &event, - (yaml_char_t *)(NIL_P(anchor) ? NULL : StringValueCStr(anchor)) - ); + &event, + (yaml_char_t *)(NIL_P(anchor) ? NULL : StringValueCStr(anchor)) + ); emit(emitter, &event); @@ -552,4 +587,3 @@ void Init_psych_emitter(void) id_indentation = rb_intern("indentation"); id_canonical = rb_intern("canonical"); } -/* vim: set noet sws=4 sw=4: */ diff --git a/ext/psych/psych_parser.c b/ext/psych/psych_parser.c index 9c5179cc44398d..d973496284f1d6 100644 --- a/ext/psych/psych_parser.c +++ b/ext/psych/psych_parser.c @@ -32,9 +32,9 @@ static int io_reader(void * data, unsigned char *buf, size_t size, size_t *read) *read = 0; if(! NIL_P(string)) { - void * str = (void *)StringValuePtr(string); - *read = (size_t)RSTRING_LEN(string); - memcpy(buf, str, *read); + void * str = (void *)StringValuePtr(string); + *read = (size_t)RSTRING_LEN(string); + memcpy(buf, str, *read); } return 1; @@ -80,23 +80,23 @@ static VALUE allocate(VALUE klass) static VALUE make_exception(yaml_parser_t * parser, VALUE path) { if (parser->error == YAML_MEMORY_ERROR) { - return rb_eNoMemError; + return rb_eNoMemError; } else { - size_t line, column; - VALUE ePsychSyntaxError; + size_t line, column; + VALUE ePsychSyntaxError; - line = parser->context_mark.line + 1; - column = parser->context_mark.column + 1; + line = parser->context_mark.line + 1; + column = parser->context_mark.column + 1; - ePsychSyntaxError = rb_const_get(mPsych, rb_intern("SyntaxError")); + ePsychSyntaxError = rb_const_get(mPsych, rb_intern("SyntaxError")); - return rb_funcall(ePsychSyntaxError, rb_intern("new"), 6, - path, - SIZET2NUM(line), - SIZET2NUM(column), - SIZET2NUM(parser->problem_offset), - parser->problem ? rb_usascii_str_new2(parser->problem) : Qnil, - parser->context ? rb_usascii_str_new2(parser->context) : Qnil); + return rb_funcall(ePsychSyntaxError, rb_intern("new"), 6, + path, + SIZET2NUM(line), + SIZET2NUM(column), + SIZET2NUM(parser->problem_offset), + parser->problem ? rb_usascii_str_new2(parser->problem) : Qnil, + parser->context ? rb_usascii_str_new2(parser->context) : Qnil); } } @@ -108,18 +108,18 @@ static VALUE transcode_string(VALUE src, int * parser_encoding) int source_encoding = rb_enc_get_index(src); if (source_encoding == utf8) { - *parser_encoding = YAML_UTF8_ENCODING; - return src; + *parser_encoding = YAML_UTF8_ENCODING; + return src; } if (source_encoding == utf16le) { - *parser_encoding = YAML_UTF16LE_ENCODING; - return src; + *parser_encoding = YAML_UTF16LE_ENCODING; + return src; } if (source_encoding == utf16be) { - *parser_encoding = YAML_UTF16BE_ENCODING; - return src; + *parser_encoding = YAML_UTF16BE_ENCODING; + return src; } src = rb_str_export_to_enc(src, rb_utf8_encoding()); @@ -138,36 +138,36 @@ static VALUE transcode_io(VALUE src, int * parser_encoding) /* if no encoding is returned, assume ascii8bit. */ if (NIL_P(io_external_encoding)) { - io_external_enc_index = rb_ascii8bit_encindex(); + io_external_enc_index = rb_ascii8bit_encindex(); } else { - io_external_enc_index = rb_to_encoding_index(io_external_encoding); + io_external_enc_index = rb_to_encoding_index(io_external_encoding); } /* Treat US-ASCII as utf_8 */ if (io_external_enc_index == rb_usascii_encindex()) { - *parser_encoding = YAML_UTF8_ENCODING; - return src; + *parser_encoding = YAML_UTF8_ENCODING; + return src; } if (io_external_enc_index == rb_utf8_encindex()) { - *parser_encoding = YAML_UTF8_ENCODING; - return src; + *parser_encoding = YAML_UTF8_ENCODING; + return src; } if (io_external_enc_index == rb_enc_find_index("UTF-16LE")) { - *parser_encoding = YAML_UTF16LE_ENCODING; - return src; + *parser_encoding = YAML_UTF16LE_ENCODING; + return src; } if (io_external_enc_index == rb_enc_find_index("UTF-16BE")) { - *parser_encoding = YAML_UTF16BE_ENCODING; - return src; + *parser_encoding = YAML_UTF16BE_ENCODING; + return src; } /* Just guess on ASCII-8BIT */ if (io_external_enc_index == rb_ascii8bit_encindex()) { - *parser_encoding = YAML_ANY_ENCODING; - return src; + *parser_encoding = YAML_ANY_ENCODING; + return src; } /* If the external encoding is something we don't know how to handle, @@ -261,238 +261,238 @@ static VALUE parse(VALUE self, VALUE handler, VALUE yaml, VALUE path) yaml_parser_initialize(parser); if (rb_respond_to(yaml, id_read)) { - yaml = transcode_io(yaml, &parser_encoding); - yaml_parser_set_encoding(parser, parser_encoding); - yaml_parser_set_input(parser, io_reader, (void *)yaml); + yaml = transcode_io(yaml, &parser_encoding); + yaml_parser_set_encoding(parser, parser_encoding); + yaml_parser_set_input(parser, io_reader, (void *)yaml); } else { - StringValue(yaml); - yaml = transcode_string(yaml, &parser_encoding); - yaml_parser_set_encoding(parser, parser_encoding); - yaml_parser_set_input_string( - parser, - (const unsigned char *)RSTRING_PTR(yaml), - (size_t)RSTRING_LEN(yaml) - ); + StringValue(yaml); + yaml = transcode_string(yaml, &parser_encoding); + yaml_parser_set_encoding(parser, parser_encoding); + yaml_parser_set_input_string( + parser, + (const unsigned char *)RSTRING_PTR(yaml), + (size_t)RSTRING_LEN(yaml) + ); } while(!done) { - VALUE event_args[5]; - VALUE start_line, start_column, end_line, end_column; - - if(parser->error || !yaml_parser_parse(parser, &event)) { - VALUE exception; - - exception = make_exception(parser, path); - yaml_parser_delete(parser); - yaml_parser_initialize(parser); - - rb_exc_raise(exception); - } - - start_line = SIZET2NUM(event.start_mark.line); - start_column = SIZET2NUM(event.start_mark.column); - end_line = SIZET2NUM(event.end_mark.line); - end_column = SIZET2NUM(event.end_mark.column); - - event_args[0] = handler; - event_args[1] = start_line; - event_args[2] = start_column; - event_args[3] = end_line; - event_args[4] = end_column; - rb_protect(protected_event_location, (VALUE)event_args, &state); - - switch(event.type) { - case YAML_STREAM_START_EVENT: - { - VALUE args[2]; - - args[0] = handler; - args[1] = INT2NUM(event.data.stream_start.encoding); - rb_protect(protected_start_stream, (VALUE)args, &state); - } - break; - case YAML_DOCUMENT_START_EVENT: - { - VALUE args[4]; - /* Get a list of tag directives (if any) */ - VALUE tag_directives = rb_ary_new(); - /* Grab the document version */ - VALUE version = event.data.document_start.version_directive ? - rb_ary_new3( - (long)2, - INT2NUM(event.data.document_start.version_directive->major), - INT2NUM(event.data.document_start.version_directive->minor) - ) : rb_ary_new(); - - if(event.data.document_start.tag_directives.start) { - yaml_tag_directive_t *start = - event.data.document_start.tag_directives.start; - yaml_tag_directive_t *end = - event.data.document_start.tag_directives.end; - for(; start != end; start++) { - VALUE handle = Qnil; - VALUE prefix = Qnil; - if(start->handle) { - handle = rb_str_new2((const char *)start->handle); - PSYCH_TRANSCODE(handle, encoding, internal_enc); - } - - if(start->prefix) { - prefix = rb_str_new2((const char *)start->prefix); - PSYCH_TRANSCODE(prefix, encoding, internal_enc); - } - - rb_ary_push(tag_directives, rb_ary_new3((long)2, handle, prefix)); - } - } - args[0] = handler; - args[1] = version; - args[2] = tag_directives; - args[3] = event.data.document_start.implicit == 1 ? Qtrue : Qfalse; - rb_protect(protected_start_document, (VALUE)args, &state); - } - break; - case YAML_DOCUMENT_END_EVENT: - { - VALUE args[2]; - - args[0] = handler; - args[1] = event.data.document_end.implicit == 1 ? Qtrue : Qfalse; - rb_protect(protected_end_document, (VALUE)args, &state); - } - break; - case YAML_ALIAS_EVENT: - { - VALUE args[2]; - VALUE alias = Qnil; - if(event.data.alias.anchor) { - alias = rb_str_new2((const char *)event.data.alias.anchor); - PSYCH_TRANSCODE(alias, encoding, internal_enc); - } - - args[0] = handler; - args[1] = alias; - rb_protect(protected_alias, (VALUE)args, &state); - } - break; - case YAML_SCALAR_EVENT: - { - VALUE args[7]; - VALUE anchor = Qnil; - VALUE tag = Qnil; - VALUE plain_implicit, quoted_implicit, style; - VALUE val = rb_str_new( - (const char *)event.data.scalar.value, - (long)event.data.scalar.length - ); - - PSYCH_TRANSCODE(val, encoding, internal_enc); - - if(event.data.scalar.anchor) { - anchor = rb_str_new2((const char *)event.data.scalar.anchor); - PSYCH_TRANSCODE(anchor, encoding, internal_enc); - } - - if(event.data.scalar.tag) { - tag = rb_str_new2((const char *)event.data.scalar.tag); - PSYCH_TRANSCODE(tag, encoding, internal_enc); - } - - plain_implicit = - event.data.scalar.plain_implicit == 0 ? Qfalse : Qtrue; - - quoted_implicit = - event.data.scalar.quoted_implicit == 0 ? Qfalse : Qtrue; - - style = INT2NUM(event.data.scalar.style); - - args[0] = handler; - args[1] = val; - args[2] = anchor; - args[3] = tag; - args[4] = plain_implicit; - args[5] = quoted_implicit; - args[6] = style; - rb_protect(protected_scalar, (VALUE)args, &state); - } - break; - case YAML_SEQUENCE_START_EVENT: - { - VALUE args[5]; - VALUE anchor = Qnil; - VALUE tag = Qnil; - VALUE implicit, style; - if(event.data.sequence_start.anchor) { - anchor = rb_str_new2((const char *)event.data.sequence_start.anchor); - PSYCH_TRANSCODE(anchor, encoding, internal_enc); - } - - tag = Qnil; - if(event.data.sequence_start.tag) { - tag = rb_str_new2((const char *)event.data.sequence_start.tag); - PSYCH_TRANSCODE(tag, encoding, internal_enc); - } - - implicit = - event.data.sequence_start.implicit == 0 ? Qfalse : Qtrue; - - style = INT2NUM(event.data.sequence_start.style); - - args[0] = handler; - args[1] = anchor; - args[2] = tag; - args[3] = implicit; - args[4] = style; - - rb_protect(protected_start_sequence, (VALUE)args, &state); - } - break; - case YAML_SEQUENCE_END_EVENT: - rb_protect(protected_end_sequence, handler, &state); - break; - case YAML_MAPPING_START_EVENT: - { - VALUE args[5]; - VALUE anchor = Qnil; - VALUE tag = Qnil; - VALUE implicit, style; - if(event.data.mapping_start.anchor) { - anchor = rb_str_new2((const char *)event.data.mapping_start.anchor); - PSYCH_TRANSCODE(anchor, encoding, internal_enc); - } - - if(event.data.mapping_start.tag) { - tag = rb_str_new2((const char *)event.data.mapping_start.tag); - PSYCH_TRANSCODE(tag, encoding, internal_enc); - } - - implicit = - event.data.mapping_start.implicit == 0 ? Qfalse : Qtrue; - - style = INT2NUM(event.data.mapping_start.style); - - args[0] = handler; - args[1] = anchor; - args[2] = tag; - args[3] = implicit; - args[4] = style; - - rb_protect(protected_start_mapping, (VALUE)args, &state); - } - break; - case YAML_MAPPING_END_EVENT: - rb_protect(protected_end_mapping, handler, &state); - break; - case YAML_NO_EVENT: - rb_protect(protected_empty, handler, &state); - break; - case YAML_STREAM_END_EVENT: - rb_protect(protected_end_stream, handler, &state); - done = 1; - break; - } - yaml_event_delete(&event); - if (state) rb_jump_tag(state); + VALUE event_args[5]; + VALUE start_line, start_column, end_line, end_column; + + if(parser->error || !yaml_parser_parse(parser, &event)) { + VALUE exception; + + exception = make_exception(parser, path); + yaml_parser_delete(parser); + yaml_parser_initialize(parser); + + rb_exc_raise(exception); + } + + start_line = SIZET2NUM(event.start_mark.line); + start_column = SIZET2NUM(event.start_mark.column); + end_line = SIZET2NUM(event.end_mark.line); + end_column = SIZET2NUM(event.end_mark.column); + + event_args[0] = handler; + event_args[1] = start_line; + event_args[2] = start_column; + event_args[3] = end_line; + event_args[4] = end_column; + rb_protect(protected_event_location, (VALUE)event_args, &state); + + switch(event.type) { + case YAML_STREAM_START_EVENT: + { + VALUE args[2]; + + args[0] = handler; + args[1] = INT2NUM(event.data.stream_start.encoding); + rb_protect(protected_start_stream, (VALUE)args, &state); + } + break; + case YAML_DOCUMENT_START_EVENT: + { + VALUE args[4]; + /* Get a list of tag directives (if any) */ + VALUE tag_directives = rb_ary_new(); + /* Grab the document version */ + VALUE version = event.data.document_start.version_directive ? + rb_ary_new3( + (long)2, + INT2NUM(event.data.document_start.version_directive->major), + INT2NUM(event.data.document_start.version_directive->minor) + ) : rb_ary_new(); + + if(event.data.document_start.tag_directives.start) { + yaml_tag_directive_t *start = + event.data.document_start.tag_directives.start; + yaml_tag_directive_t *end = + event.data.document_start.tag_directives.end; + for(; start != end; start++) { + VALUE handle = Qnil; + VALUE prefix = Qnil; + if(start->handle) { + handle = rb_str_new2((const char *)start->handle); + PSYCH_TRANSCODE(handle, encoding, internal_enc); + } + + if(start->prefix) { + prefix = rb_str_new2((const char *)start->prefix); + PSYCH_TRANSCODE(prefix, encoding, internal_enc); + } + + rb_ary_push(tag_directives, rb_ary_new3((long)2, handle, prefix)); + } + } + args[0] = handler; + args[1] = version; + args[2] = tag_directives; + args[3] = event.data.document_start.implicit == 1 ? Qtrue : Qfalse; + rb_protect(protected_start_document, (VALUE)args, &state); + } + break; + case YAML_DOCUMENT_END_EVENT: + { + VALUE args[2]; + + args[0] = handler; + args[1] = event.data.document_end.implicit == 1 ? Qtrue : Qfalse; + rb_protect(protected_end_document, (VALUE)args, &state); + } + break; + case YAML_ALIAS_EVENT: + { + VALUE args[2]; + VALUE alias = Qnil; + if(event.data.alias.anchor) { + alias = rb_str_new2((const char *)event.data.alias.anchor); + PSYCH_TRANSCODE(alias, encoding, internal_enc); + } + + args[0] = handler; + args[1] = alias; + rb_protect(protected_alias, (VALUE)args, &state); + } + break; + case YAML_SCALAR_EVENT: + { + VALUE args[7]; + VALUE anchor = Qnil; + VALUE tag = Qnil; + VALUE plain_implicit, quoted_implicit, style; + VALUE val = rb_str_new( + (const char *)event.data.scalar.value, + (long)event.data.scalar.length + ); + + PSYCH_TRANSCODE(val, encoding, internal_enc); + + if(event.data.scalar.anchor) { + anchor = rb_str_new2((const char *)event.data.scalar.anchor); + PSYCH_TRANSCODE(anchor, encoding, internal_enc); + } + + if(event.data.scalar.tag) { + tag = rb_str_new2((const char *)event.data.scalar.tag); + PSYCH_TRANSCODE(tag, encoding, internal_enc); + } + + plain_implicit = + event.data.scalar.plain_implicit == 0 ? Qfalse : Qtrue; + + quoted_implicit = + event.data.scalar.quoted_implicit == 0 ? Qfalse : Qtrue; + + style = INT2NUM(event.data.scalar.style); + + args[0] = handler; + args[1] = val; + args[2] = anchor; + args[3] = tag; + args[4] = plain_implicit; + args[5] = quoted_implicit; + args[6] = style; + rb_protect(protected_scalar, (VALUE)args, &state); + } + break; + case YAML_SEQUENCE_START_EVENT: + { + VALUE args[5]; + VALUE anchor = Qnil; + VALUE tag = Qnil; + VALUE implicit, style; + if(event.data.sequence_start.anchor) { + anchor = rb_str_new2((const char *)event.data.sequence_start.anchor); + PSYCH_TRANSCODE(anchor, encoding, internal_enc); + } + + tag = Qnil; + if(event.data.sequence_start.tag) { + tag = rb_str_new2((const char *)event.data.sequence_start.tag); + PSYCH_TRANSCODE(tag, encoding, internal_enc); + } + + implicit = + event.data.sequence_start.implicit == 0 ? Qfalse : Qtrue; + + style = INT2NUM(event.data.sequence_start.style); + + args[0] = handler; + args[1] = anchor; + args[2] = tag; + args[3] = implicit; + args[4] = style; + + rb_protect(protected_start_sequence, (VALUE)args, &state); + } + break; + case YAML_SEQUENCE_END_EVENT: + rb_protect(protected_end_sequence, handler, &state); + break; + case YAML_MAPPING_START_EVENT: + { + VALUE args[5]; + VALUE anchor = Qnil; + VALUE tag = Qnil; + VALUE implicit, style; + if(event.data.mapping_start.anchor) { + anchor = rb_str_new2((const char *)event.data.mapping_start.anchor); + PSYCH_TRANSCODE(anchor, encoding, internal_enc); + } + + if(event.data.mapping_start.tag) { + tag = rb_str_new2((const char *)event.data.mapping_start.tag); + PSYCH_TRANSCODE(tag, encoding, internal_enc); + } + + implicit = + event.data.mapping_start.implicit == 0 ? Qfalse : Qtrue; + + style = INT2NUM(event.data.mapping_start.style); + + args[0] = handler; + args[1] = anchor; + args[2] = tag; + args[3] = implicit; + args[4] = style; + + rb_protect(protected_start_mapping, (VALUE)args, &state); + } + break; + case YAML_MAPPING_END_EVENT: + rb_protect(protected_end_mapping, handler, &state); + break; + case YAML_NO_EVENT: + rb_protect(protected_empty, handler, &state); + break; + case YAML_STREAM_END_EVENT: + rb_protect(protected_end_stream, handler, &state); + done = 1; + break; + } + yaml_event_delete(&event); + if (state) rb_jump_tag(state); } return self; @@ -562,4 +562,3 @@ void Init_psych_parser(void) id_end_mapping = rb_intern("end_mapping"); id_event_location = rb_intern("event_location"); } -/* vim: set noet sws=4 sw=4: */ diff --git a/ext/psych/psych_to_ruby.c b/ext/psych/psych_to_ruby.c index b388ff77545e5b..d473a5f840a1d7 100644 --- a/ext/psych/psych_to_ruby.c +++ b/ext/psych/psych_to_ruby.c @@ -24,6 +24,15 @@ static VALUE path2class(VALUE self, VALUE path) return rb_path_to_class(path); } +static VALUE init_struct(VALUE self, VALUE data, VALUE attrs) +{ + VALUE args = rb_ary_new2(1); + rb_ary_push(args, attrs); + rb_struct_initialize(data, args); + + return data; +} + void Init_psych_to_ruby(void) { VALUE psych = rb_define_module("Psych"); @@ -33,7 +42,7 @@ void Init_psych_to_ruby(void) VALUE visitor = rb_define_class_under(visitors, "Visitor", rb_cObject); cPsychVisitorsToRuby = rb_define_class_under(visitors, "ToRuby", visitor); + rb_define_private_method(cPsychVisitorsToRuby, "init_struct", init_struct, 2); rb_define_private_method(cPsychVisitorsToRuby, "build_exception", build_exception, 2); rb_define_private_method(class_loader, "path2class", path2class, 1); } -/* vim: set noet sws=4 sw=4: */ diff --git a/ext/psych/psych_yaml_tree.c b/ext/psych/psych_yaml_tree.c index 225655d127063e..bbd93f874dd71c 100644 --- a/ext/psych/psych_yaml_tree.c +++ b/ext/psych/psych_yaml_tree.c @@ -9,4 +9,3 @@ void Init_psych_yaml_tree(void) VALUE visitor = rb_define_class_under(visitors, "Visitor", rb_cObject); cPsychVisitorsYamlTree = rb_define_class_under(visitors, "YAMLTree", visitor); } -/* vim: set noet sws=4 sw=4: */ diff --git a/ext/pty/depend b/ext/pty/depend index d4d0d558eff6fc..8fa018d084cbc7 100644 --- a/ext/pty/depend +++ b/ext/pty/depend @@ -138,6 +138,7 @@ pty.o: $(hdrdir)/ruby/internal/intern/re.h pty.o: $(hdrdir)/ruby/internal/intern/ruby.h pty.o: $(hdrdir)/ruby/internal/intern/select.h pty.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +pty.o: $(hdrdir)/ruby/internal/intern/set.h pty.o: $(hdrdir)/ruby/internal/intern/signal.h pty.o: $(hdrdir)/ruby/internal/intern/sprintf.h pty.o: $(hdrdir)/ruby/internal/intern/string.h @@ -157,6 +158,7 @@ pty.o: $(hdrdir)/ruby/internal/special_consts.h pty.o: $(hdrdir)/ruby/internal/static_assert.h pty.o: $(hdrdir)/ruby/internal/stdalign.h pty.o: $(hdrdir)/ruby/internal/stdbool.h +pty.o: $(hdrdir)/ruby/internal/stdckdint.h pty.o: $(hdrdir)/ruby/internal/symbol.h pty.o: $(hdrdir)/ruby/internal/value.h pty.o: $(hdrdir)/ruby/internal/value_type.h @@ -171,6 +173,7 @@ pty.o: $(hdrdir)/ruby/ruby.h pty.o: $(hdrdir)/ruby/st.h pty.o: $(hdrdir)/ruby/subst.h pty.o: $(hdrdir)/ruby/util.h +pty.o: $(top_srcdir)/id_table.h pty.o: $(top_srcdir)/internal.h pty.o: $(top_srcdir)/internal/array.h pty.o: $(top_srcdir)/internal/compilers.h diff --git a/ext/pty/extconf.rb b/ext/pty/extconf.rb index ba0c4286fd31d1..da3655cf4d7118 100644 --- a/ext/pty/extconf.rb +++ b/ext/pty/extconf.rb @@ -13,10 +13,13 @@ have_header("util.h") # OpenBSD openpty util = have_library("util", "openpty") end - if have_func("posix_openpt") or + openpt = have_func("posix_openpt") + if openpt + have_func("ptsname_r") or have_func("ptsname") + end + if openpt or (util or have_func("openpty")) or have_func("_getpty") or - have_func("ptsname") or have_func("ioctl") create_makefile('pty') end diff --git a/ext/pty/pty.c b/ext/pty/pty.c index 0aca10bfa070b5..7c79f81e338019 100644 --- a/ext/pty/pty.c +++ b/ext/pty/pty.c @@ -92,9 +92,13 @@ struct pty_info { static void getDevice(int*, int*, char [DEVICELEN], int); +static int start_new_session(char *errbuf, size_t errbuf_len); +static int obtain_ctty(int master, int slave, const char *slavename, char *errbuf, size_t errbuf_len); +static int drop_privilege(char *errbuf, size_t errbuf_len); + struct child_info { int master, slave; - char *slavename; + const char *slavename; VALUE execarg_obj; struct rb_execarg *eargp; }; @@ -102,26 +106,42 @@ struct child_info { static int chfunc(void *data, char *errbuf, size_t errbuf_len) { - struct child_info *carg = data; + const struct child_info *carg = data; int master = carg->master; int slave = carg->slave; + const char *slavename = carg->slavename; + + if (start_new_session(errbuf, errbuf_len)) + return -1; + + if (obtain_ctty(master, slave, slavename, errbuf, errbuf_len)) + return -1; + + if (drop_privilege(errbuf, errbuf_len)) + return -1; + + return rb_exec_async_signal_safe(carg->eargp, errbuf, errbuf_len); +} #define ERROR_EXIT(str) do { \ strlcpy(errbuf, (str), errbuf_len); \ return -1; \ } while (0) - /* - * Set free from process group and controlling terminal - */ +/* + * Set free from process group and controlling terminal + */ +static int +start_new_session(char *errbuf, size_t errbuf_len) +{ #ifdef HAVE_SETSID (void) setsid(); #else /* HAS_SETSID */ # ifdef HAVE_SETPGRP -# ifdef SETGRP_VOID +# ifdef SETPGRP_VOID if (setpgrp() == -1) ERROR_EXIT("setpgrp()"); -# else /* SETGRP_VOID */ +# else /* SETPGRP_VOID */ if (setpgrp(0, getpid()) == -1) ERROR_EXIT("setpgrp()"); { @@ -132,20 +152,25 @@ chfunc(void *data, char *errbuf, size_t errbuf_len) ERROR_EXIT("ioctl(TIOCNOTTY)"); close(i); } -# endif /* SETGRP_VOID */ +# endif /* SETPGRP_VOID */ # endif /* HAVE_SETPGRP */ #endif /* HAS_SETSID */ + return 0; +} - /* - * obtain new controlling terminal - */ +/* + * obtain new controlling terminal + */ +static int +obtain_ctty(int master, int slave, const char *slavename, char *errbuf, size_t errbuf_len) +{ #if defined(TIOCSCTTY) close(master); (void) ioctl(slave, TIOCSCTTY, (char *)0); /* errors ignored for sun */ #else close(slave); - slave = rb_cloexec_open(carg->slavename, O_RDWR, 0); + slave = rb_cloexec_open(slavename, O_RDWR, 0); if (slave < 0) { ERROR_EXIT("open: pty slave"); } @@ -155,14 +180,20 @@ chfunc(void *data, char *errbuf, size_t errbuf_len) dup2(slave,0); dup2(slave,1); dup2(slave,2); - if (slave < 0 || slave > 2) (void)!close(slave); + if (slave > 2) (void)!close(slave); + return 0; +} + +static int +drop_privilege(char *errbuf, size_t errbuf_len) +{ #if defined(HAVE_SETEUID) || defined(HAVE_SETREUID) || defined(HAVE_SETRESUID) if (seteuid(getuid())) ERROR_EXIT("seteuid()"); #endif + return 0; +} - return rb_exec_async_signal_safe(carg->eargp, errbuf, sizeof(errbuf_len)); #undef ERROR_EXIT -} static void establishShell(int argc, VALUE *argv, struct pty_info *info, @@ -184,9 +215,13 @@ establishShell(int argc, VALUE *argv, struct pty_info *info, else { #if defined HAVE_PWD_H const char *username = getenv("USER"); - struct passwd *pwent = getpwnam(username ? username : getlogin()); - if (pwent && pwent->pw_shell) - shellname = pwent->pw_shell; + if (username == NULL) + username = getlogin(); + if (username != NULL) { + struct passwd *pwent = getpwnam(username); + if (pwent && pwent->pw_shell) + shellname = pwent->pw_shell; + } #endif } v = rb_str_new2(shellname); @@ -225,7 +260,21 @@ establishShell(int argc, VALUE *argv, struct pty_info *info, RB_GC_GUARD(carg.execarg_obj); } -#if defined(HAVE_POSIX_OPENPT) || defined(HAVE_OPENPTY) || defined(HAVE_PTSNAME) +#if (defined(HAVE_POSIX_OPENPT) || defined(HAVE_PTSNAME)) && !defined(HAVE_PTSNAME_R) +/* glibc only, not obsolete interface on Tru64 or HP-UX */ +static int +ptsname_r(int fd, char *buf, size_t buflen) +{ + extern char *ptsname(int); + char *name = ptsname(fd); + if (!name) return -1; + strlcpy(buf, name, buflen); + return 0; +} +# define HAVE_PTSNAME_R 1 +#endif + +#if defined(HAVE_POSIX_OPENPT) || defined(HAVE_OPENPTY) || defined(HAVE_PTSNAME_R) static int no_mesg(char *slavedevice, int nomesg) { @@ -258,13 +307,19 @@ get_device_once(int *master, int *slave, char SlaveName[DEVICELEN], int nomesg, /* Unix98 PTY */ int masterfd = -1, slavefd = -1; char *slavedevice; + struct sigaction dfl, old; + + dfl.sa_handler = SIG_DFL; + dfl.sa_flags = 0; + sigemptyset(&dfl.sa_mask); #if defined(__sun) || defined(__OpenBSD__) || (defined(__FreeBSD__) && __FreeBSD_version < 902000) /* workaround for Solaris 10: grantpt() doesn't work if FD_CLOEXEC is set. [ruby-dev:44688] */ /* FreeBSD 9.2 or later supports O_CLOEXEC * http://www.freebsd.org/cgi/query-pr.cgi?pr=162374 */ if ((masterfd = posix_openpt(O_RDWR|O_NOCTTY)) == -1) goto error; - if (rb_grantpt(masterfd) == -1) goto error; + if (sigaction(SIGCHLD, &dfl, &old) == -1) goto error; + if (grantpt(masterfd) == -1) goto grantpt_error; rb_fd_fix_cloexec(masterfd); #else { @@ -278,10 +333,13 @@ get_device_once(int *master, int *slave, char SlaveName[DEVICELEN], int nomesg, if ((masterfd = posix_openpt(flags)) == -1) goto error; } rb_fd_fix_cloexec(masterfd); - if (rb_grantpt(masterfd) == -1) goto error; + if (sigaction(SIGCHLD, &dfl, &old) == -1) goto error; + if (grantpt(masterfd) == -1) goto grantpt_error; #endif + if (sigaction(SIGCHLD, &old, NULL) == -1) goto error; if (unlockpt(masterfd) == -1) goto error; - if ((slavedevice = ptsname(masterfd)) == NULL) goto error; + if (ptsname_r(masterfd, SlaveName, DEVICELEN) != 0) goto error; + slavedevice = SlaveName; if (no_mesg(slavedevice, nomesg) == -1) goto error; if ((slavefd = rb_cloexec_open(slavedevice, O_RDWR|O_NOCTTY, 0)) == -1) goto error; rb_update_max_fd(slavefd); @@ -294,9 +352,10 @@ get_device_once(int *master, int *slave, char SlaveName[DEVICELEN], int nomesg, *master = masterfd; *slave = slavefd; - strlcpy(SlaveName, slavedevice, DEVICELEN); return 0; + grantpt_error: + sigaction(SIGCHLD, &old, NULL); error: if (slavefd != -1) close(slavefd); if (masterfd != -1) close(masterfd); @@ -346,21 +405,25 @@ get_device_once(int *master, int *slave, char SlaveName[DEVICELEN], int nomesg, char *slavedevice; void (*s)(); - extern char *ptsname(int); extern int unlockpt(int); + extern int grantpt(int); #if defined(__sun) /* workaround for Solaris 10: grantpt() doesn't work if FD_CLOEXEC is set. [ruby-dev:44688] */ if((masterfd = open("/dev/ptmx", O_RDWR, 0)) == -1) goto error; - if(rb_grantpt(masterfd) == -1) goto error; + s = signal(SIGCHLD, SIG_DFL); + if(grantpt(masterfd) == -1) goto error; rb_fd_fix_cloexec(masterfd); #else if((masterfd = rb_cloexec_open("/dev/ptmx", O_RDWR, 0)) == -1) goto error; rb_update_max_fd(masterfd); - if(rb_grantpt(masterfd) == -1) goto error; + s = signal(SIGCHLD, SIG_DFL); + if(grantpt(masterfd) == -1) goto error; #endif + signal(SIGCHLD, s); if(unlockpt(masterfd) == -1) goto error; - if((slavedevice = ptsname(masterfd)) == NULL) goto error; + if (ptsname_r(masterfd, SlaveName, DEVICELEN) != 0) goto error; + slavedevice = SlaveName; if (no_mesg(slavedevice, nomesg) == -1) goto error; if((slavefd = rb_cloexec_open(slavedevice, O_RDWR, 0)) == -1) goto error; rb_update_max_fd(slavefd); @@ -371,7 +434,6 @@ get_device_once(int *master, int *slave, char SlaveName[DEVICELEN], int nomesg, #endif *master = masterfd; *slave = slavefd; - strlcpy(SlaveName, slavedevice, DEVICELEN); return 0; error: @@ -548,9 +610,17 @@ pty_detach_process(VALUE v) * +env+ is an optional hash that provides additional environment variables to the spawned pty. * * # sets FOO to "bar" - * PTY.spawn({"FOO"=>"bar"}, "printenv", "FOO") { |r,w,pid| p r.read } #=> "bar\r\n" + * PTY.spawn({"FOO"=>"bar"}, "printenv", "FOO") do |r, w, pid| + * p r.read #=> "bar\r\n" + * ensure + * r.close; w.close; Process.wait(pid) + * end * # unsets FOO - * PTY.spawn({"FOO"=>nil}, "printenv", "FOO") { |r,w,pid| p r.read } #=> "" + * PTY.spawn({"FOO"=>nil}, "printenv", "FOO") do |r, w, pid| + * p r.read #=> "" + * ensure + * r.close; w.close; Process.wait(pid) + * end * * +command+ and +command_line+ are the full commands to run, given a String. * Any additional +arguments+ will be passed to the command. @@ -566,6 +636,15 @@ pty_detach_process(VALUE v) * standard output and standard error * +w+:: A writable IO that is the command's standard input * +pid+:: The process identifier for the command. + * + * === Clean up + * + * This method does not clean up like closing IOs or waiting for child + * process, except that the process is detached in the block form to + * prevent it from becoming a zombie (see Process.detach). Any other + * cleanup is the responsibility of the caller. If waiting for +pid+, + * be sure to close both +r+ and +w+ before doing so; doing it in the + * reverse order may cause deadlock on some OSes. */ static VALUE pty_getpty(int argc, VALUE *argv, VALUE self) @@ -745,8 +824,13 @@ void Init_pty(void) { cPTY = rb_define_module("PTY"); - /* :nodoc: */ - rb_define_module_function(cPTY,"getpty",pty_getpty,-1); +#if 1 + rb_define_module_function(cPTY,"get""pty",pty_getpty,-1); +#else /* for RDoc */ + /* show getpty as an alias of spawn */ + VALUE sPTY = rb_singleton_class(cPTY); + rb_define_alias(sPTY, "getpty", "spawn"); +#endif rb_define_module_function(cPTY,"spawn",pty_getpty,-1); rb_define_singleton_method(cPTY,"check",pty_check,-1); rb_define_singleton_method(cPTY,"open",pty_open,0); diff --git a/ext/rbconfig/sizeof/depend b/ext/rbconfig/sizeof/depend index 4e4ebd4ae51a39..7e6c950769f759 100644 --- a/ext/rbconfig/sizeof/depend +++ b/ext/rbconfig/sizeof/depend @@ -142,6 +142,7 @@ limits.o: $(hdrdir)/ruby/internal/intern/re.h limits.o: $(hdrdir)/ruby/internal/intern/ruby.h limits.o: $(hdrdir)/ruby/internal/intern/select.h limits.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +limits.o: $(hdrdir)/ruby/internal/intern/set.h limits.o: $(hdrdir)/ruby/internal/intern/signal.h limits.o: $(hdrdir)/ruby/internal/intern/sprintf.h limits.o: $(hdrdir)/ruby/internal/intern/string.h @@ -161,6 +162,7 @@ limits.o: $(hdrdir)/ruby/internal/special_consts.h limits.o: $(hdrdir)/ruby/internal/static_assert.h limits.o: $(hdrdir)/ruby/internal/stdalign.h limits.o: $(hdrdir)/ruby/internal/stdbool.h +limits.o: $(hdrdir)/ruby/internal/stdckdint.h limits.o: $(hdrdir)/ruby/internal/symbol.h limits.o: $(hdrdir)/ruby/internal/value.h limits.o: $(hdrdir)/ruby/internal/value_type.h @@ -300,6 +302,7 @@ sizes.o: $(hdrdir)/ruby/internal/intern/re.h sizes.o: $(hdrdir)/ruby/internal/intern/ruby.h sizes.o: $(hdrdir)/ruby/internal/intern/select.h sizes.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +sizes.o: $(hdrdir)/ruby/internal/intern/set.h sizes.o: $(hdrdir)/ruby/internal/intern/signal.h sizes.o: $(hdrdir)/ruby/internal/intern/sprintf.h sizes.o: $(hdrdir)/ruby/internal/intern/string.h @@ -319,6 +322,7 @@ sizes.o: $(hdrdir)/ruby/internal/special_consts.h sizes.o: $(hdrdir)/ruby/internal/static_assert.h sizes.o: $(hdrdir)/ruby/internal/stdalign.h sizes.o: $(hdrdir)/ruby/internal/stdbool.h +sizes.o: $(hdrdir)/ruby/internal/stdckdint.h sizes.o: $(hdrdir)/ruby/internal/symbol.h sizes.o: $(hdrdir)/ruby/internal/value.h sizes.o: $(hdrdir)/ruby/internal/value_type.h diff --git a/ext/ripper/depend b/ext/ripper/depend index 19a7986f0a3d89..c8ba34962c6da2 100644 --- a/ext/ripper/depend +++ b/ext/ripper/depend @@ -1,7 +1,7 @@ GEN = $(srcdir)/tools/generate.rb SRC1 = $(top_srcdir)/parse.y SRC2 = $(srcdir)/eventids2.c -BISON = $(BASERUBY) $(top_srcdir)/tool/lrama/exe/lrama +LRAMA = $(BASERUBY) $(top_srcdir)/tool/lrama/exe/lrama .SUFFIXES: .y @@ -12,7 +12,7 @@ ripper.o: ripper.c .y.c: $(ECHO) compiling compiler $< - $(Q) $(BISON) -t -v -o$@ -h$*.h - $< < $< + $(Q) $(LRAMA) -o$@ - $< < $< all: check static: check @@ -181,6 +181,7 @@ eventids1.o: $(hdrdir)/ruby/internal/intern/re.h eventids1.o: $(hdrdir)/ruby/internal/intern/ruby.h eventids1.o: $(hdrdir)/ruby/internal/intern/select.h eventids1.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +eventids1.o: $(hdrdir)/ruby/internal/intern/set.h eventids1.o: $(hdrdir)/ruby/internal/intern/signal.h eventids1.o: $(hdrdir)/ruby/internal/intern/sprintf.h eventids1.o: $(hdrdir)/ruby/internal/intern/string.h @@ -200,6 +201,7 @@ eventids1.o: $(hdrdir)/ruby/internal/special_consts.h eventids1.o: $(hdrdir)/ruby/internal/static_assert.h eventids1.o: $(hdrdir)/ruby/internal/stdalign.h eventids1.o: $(hdrdir)/ruby/internal/stdbool.h +eventids1.o: $(hdrdir)/ruby/internal/stdckdint.h eventids1.o: $(hdrdir)/ruby/internal/symbol.h eventids1.o: $(hdrdir)/ruby/internal/value.h eventids1.o: $(hdrdir)/ruby/internal/value_type.h @@ -351,6 +353,7 @@ eventids2.o: $(hdrdir)/ruby/internal/intern/re.h eventids2.o: $(hdrdir)/ruby/internal/intern/ruby.h eventids2.o: $(hdrdir)/ruby/internal/intern/select.h eventids2.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +eventids2.o: $(hdrdir)/ruby/internal/intern/set.h eventids2.o: $(hdrdir)/ruby/internal/intern/signal.h eventids2.o: $(hdrdir)/ruby/internal/intern/sprintf.h eventids2.o: $(hdrdir)/ruby/internal/intern/string.h @@ -370,6 +373,7 @@ eventids2.o: $(hdrdir)/ruby/internal/special_consts.h eventids2.o: $(hdrdir)/ruby/internal/static_assert.h eventids2.o: $(hdrdir)/ruby/internal/stdalign.h eventids2.o: $(hdrdir)/ruby/internal/stdbool.h +eventids2.o: $(hdrdir)/ruby/internal/stdckdint.h eventids2.o: $(hdrdir)/ruby/internal/symbol.h eventids2.o: $(hdrdir)/ruby/internal/value.h eventids2.o: $(hdrdir)/ruby/internal/value_type.h @@ -530,6 +534,7 @@ ripper.o: $(hdrdir)/ruby/internal/intern/re.h ripper.o: $(hdrdir)/ruby/internal/intern/ruby.h ripper.o: $(hdrdir)/ruby/internal/intern/select.h ripper.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +ripper.o: $(hdrdir)/ruby/internal/intern/set.h ripper.o: $(hdrdir)/ruby/internal/intern/signal.h ripper.o: $(hdrdir)/ruby/internal/intern/sprintf.h ripper.o: $(hdrdir)/ruby/internal/intern/string.h @@ -549,6 +554,7 @@ ripper.o: $(hdrdir)/ruby/internal/special_consts.h ripper.o: $(hdrdir)/ruby/internal/static_assert.h ripper.o: $(hdrdir)/ruby/internal/stdalign.h ripper.o: $(hdrdir)/ruby/internal/stdbool.h +ripper.o: $(hdrdir)/ruby/internal/stdckdint.h ripper.o: $(hdrdir)/ruby/internal/symbol.h ripper.o: $(hdrdir)/ruby/internal/value.h ripper.o: $(hdrdir)/ruby/internal/value_type.h @@ -566,6 +572,7 @@ ripper.o: $(hdrdir)/ruby/st.h ripper.o: $(hdrdir)/ruby/subst.h ripper.o: $(hdrdir)/ruby/thread_native.h ripper.o: $(hdrdir)/ruby/util.h +ripper.o: $(hdrdir)/ruby/version.h ripper.o: $(top_srcdir)/ccan/check_type/check_type.h ripper.o: $(top_srcdir)/ccan/container_of/container_of.h ripper.o: $(top_srcdir)/ccan/list/list.h @@ -587,12 +594,15 @@ ripper.o: $(top_srcdir)/internal/gc.h ripper.o: $(top_srcdir)/internal/hash.h ripper.o: $(top_srcdir)/internal/imemo.h ripper.o: $(top_srcdir)/internal/io.h +ripper.o: $(top_srcdir)/internal/namespace.h ripper.o: $(top_srcdir)/internal/numeric.h ripper.o: $(top_srcdir)/internal/parse.h ripper.o: $(top_srcdir)/internal/rational.h ripper.o: $(top_srcdir)/internal/re.h ripper.o: $(top_srcdir)/internal/ruby_parser.h +ripper.o: $(top_srcdir)/internal/sanitizers.h ripper.o: $(top_srcdir)/internal/serial.h +ripper.o: $(top_srcdir)/internal/set_table.h ripper.o: $(top_srcdir)/internal/static_assert.h ripper.o: $(top_srcdir)/internal/string.h ripper.o: $(top_srcdir)/internal/symbol.h @@ -633,6 +643,7 @@ ripper_init.o: $(hdrdir)/ruby/backward.h ripper_init.o: $(hdrdir)/ruby/backward/2/assume.h ripper_init.o: $(hdrdir)/ruby/backward/2/attributes.h ripper_init.o: $(hdrdir)/ruby/backward/2/bool.h +ripper_init.o: $(hdrdir)/ruby/backward/2/gcc_version_since.h ripper_init.o: $(hdrdir)/ruby/backward/2/inttypes.h ripper_init.o: $(hdrdir)/ruby/backward/2/limits.h ripper_init.o: $(hdrdir)/ruby/backward/2/long_long.h @@ -764,6 +775,7 @@ ripper_init.o: $(hdrdir)/ruby/internal/intern/re.h ripper_init.o: $(hdrdir)/ruby/internal/intern/ruby.h ripper_init.o: $(hdrdir)/ruby/internal/intern/select.h ripper_init.o: $(hdrdir)/ruby/internal/intern/select/largesize.h +ripper_init.o: $(hdrdir)/ruby/internal/intern/set.h ripper_init.o: $(hdrdir)/ruby/internal/intern/signal.h ripper_init.o: $(hdrdir)/ruby/internal/intern/sprintf.h ripper_init.o: $(hdrdir)/ruby/internal/intern/string.h @@ -783,6 +795,7 @@ ripper_init.o: $(hdrdir)/ruby/internal/special_consts.h ripper_init.o: $(hdrdir)/ruby/internal/static_assert.h ripper_init.o: $(hdrdir)/ruby/internal/stdalign.h ripper_init.o: $(hdrdir)/ruby/internal/stdbool.h +ripper_init.o: $(hdrdir)/ruby/internal/stdckdint.h ripper_init.o: $(hdrdir)/ruby/internal/symbol.h ripper_init.o: $(hdrdir)/ruby/internal/value.h ripper_init.o: $(hdrdir)/ruby/internal/value_type.h @@ -797,13 +810,21 @@ ripper_init.o: $(hdrdir)/ruby/st.h ripper_init.o: $(hdrdir)/ruby/subst.h ripper_init.o: $(top_srcdir)/internal.h ripper_init.o: $(top_srcdir)/internal/array.h +ripper_init.o: $(top_srcdir)/internal/bignum.h +ripper_init.o: $(top_srcdir)/internal/bits.h +ripper_init.o: $(top_srcdir)/internal/compilers.h +ripper_init.o: $(top_srcdir)/internal/complex.h +ripper_init.o: $(top_srcdir)/internal/fixnum.h ripper_init.o: $(top_srcdir)/internal/imemo.h +ripper_init.o: $(top_srcdir)/internal/numeric.h ripper_init.o: $(top_srcdir)/internal/parse.h +ripper_init.o: $(top_srcdir)/internal/rational.h ripper_init.o: $(top_srcdir)/internal/ruby_parser.h ripper_init.o: $(top_srcdir)/internal/serial.h ripper_init.o: $(top_srcdir)/internal/static_assert.h ripper_init.o: $(top_srcdir)/internal/vm.h ripper_init.o: $(top_srcdir)/node.h +ripper_init.o: $(top_srcdir)/ruby_assert.h ripper_init.o: $(top_srcdir)/rubyparser.h ripper_init.o: eventids1.h ripper_init.o: eventids2.h diff --git a/ext/ripper/eventids2.c b/ext/ripper/eventids2.c index ac5495585780e0..87f2f588eccf89 100644 --- a/ext/ripper/eventids2.c +++ b/ext/ripper/eventids2.c @@ -65,6 +65,8 @@ static ripper_scanner_ids_t ripper_scanner_ids; #include "eventids2table.c" +STATIC_ASSERT(eventids2_table_size, RIPPER_EVENTIDS2_TABLE_SIZE == sizeof(ripper_scanner_ids)/sizeof(ID)); + void ripper_init_eventids2(void) { @@ -253,7 +255,6 @@ ripper_token2eventid(enum yytokentype tok) [tRATIONAL] = O(rational), [tREGEXP_BEG] = O(regexp_beg), [tREGEXP_END] = O(regexp_end), - [tRPAREN] = O(rparen), [tRSHFT] = O(op), [tSTAR] = O(op), [tDSTAR] = O(op), diff --git a/ext/ripper/extconf.rb b/ext/ripper/extconf.rb index 8eb7a921484c6c..c3c56c27c56c8d 100644 --- a/ext/ripper/extconf.rb +++ b/ext/ripper/extconf.rb @@ -6,7 +6,7 @@ def main $objs = %w(eventids1.o eventids2.o ripper.o ripper_init.o) - $distcleanfiles.concat %w(ripper.y ripper.c ripper.h eventids1.c eventids1.h eventids2table.c ripper_init.c) + $distcleanfiles.concat %w(ripper.y ripper.c eventids1.c eventids1.h eventids2table.c ripper_init.c) $cleanfiles.concat %w(ripper.E ripper.output y.output .eventids2-check) $defs << '-DRIPPER' $defs << '-DRIPPER_DEBUG' if $debug diff --git a/ext/ripper/lib/ripper/lexer.rb b/ext/ripper/lib/ripper/lexer.rb index 6a3c04af302545..870c79857bd670 100644 --- a/ext/ripper/lib/ripper/lexer.rb +++ b/ext/ripper/lib/ripper/lexer.rb @@ -53,6 +53,7 @@ def Ripper.lex(src, filename = '-', lineno = 1, **kw) end class Lexer < ::Ripper #:nodoc: internal use only + # :stopdoc: class State attr_reader :to_int, :to_s @@ -242,7 +243,12 @@ def on_error1(mesg) end def on_error2(mesg, elem) - @errors.push Elem.new(elem.pos, __callee__, elem.tok, elem.state, mesg) + if elem + elem = Elem.new(elem.pos, __callee__, elem.tok, elem.state, mesg) + else + elem = Elem.new([lineno(), column()], __callee__, token(), state(), mesg) + end + @errors.push elem end PARSER_EVENTS.grep(/_error\z/) do |e| arity = PARSER_EVENT_TABLE.fetch(e) @@ -253,6 +259,7 @@ def on_error2(mesg, elem) (SCANNER_EVENTS.map {|event|:"on_#{event}"} - private_instance_methods(false)).each do |event| alias_method event, :_push_token end + # :startdoc: end # [EXPERIMENTAL] diff --git a/ext/ripper/ripper_init.c.tmpl b/ext/ripper/ripper_init.c.tmpl index 40c583eeaebcb4..11e432423db208 100644 --- a/ext/ripper/ripper_init.c.tmpl +++ b/ext/ripper/ripper_init.c.tmpl @@ -1,32 +1,56 @@ +%# -*- c -*- #include "ruby/ruby.h" #include "ruby/encoding.h" #include "internal.h" -#include "internal/imemo.h" /* needed by ruby_parser.h */ +#include "rubyparser.h" +#define YYSTYPE_IS_DECLARED +#include "parse.h" #include "internal/parse.h" #include "internal/ruby_parser.h" #include "node.h" -#include "rubyparser.h" #include "eventids1.h" -#define YYSTYPE_IS_DECLARED -#include "parse.h" #include "eventids2.h" #include "ripper_init.h" #define STR_NEW2(ptr) rb_enc_str_new((ptr),strlen(ptr),rb_ruby_parser_enc(p)) -#define NODE_RIPPER NODE_CDECL #define RIPPER_VERSION "0.1.0" ID id_warn, id_warning, id_gets, id_assoc; +enum lex_type { + lex_type_str, + lex_type_io, + lex_type_generic, +}; + struct ripper { rb_parser_t *p; + enum lex_type type; + union { + struct lex_pointer_string ptr_str; + VALUE val; + } data; }; static void ripper_parser_mark2(void *ptr) { struct ripper *r = (struct ripper*)ptr; - if (r->p) ripper_parser_mark(r->p); + if (r->p) { + ripper_parser_mark(r->p); + + switch (r->type) { + case lex_type_str: + rb_gc_mark(r->data.ptr_str.str); + break; + case lex_type_io: + rb_gc_mark(r->data.val); + break; + case lex_type_generic: + rb_gc_mark(r->data.val); + break; + } + } } static void @@ -54,37 +78,18 @@ static const rb_data_type_t parser_data_type = { 0, 0, RUBY_TYPED_FREE_IMMEDIATELY }; -ID -ripper_get_id(VALUE v) -{ - NODE *nd; - if (!RB_TYPE_P(v, T_NODE)) return 0; - nd = (NODE *)v; - if (!nd_type_p(nd, NODE_RIPPER)) return 0; - return nd->nd_vid; -} - -VALUE -ripper_get_value(VALUE v) -{ - NODE *nd; - if (UNDEF_P(v)) return Qnil; - if (!RB_TYPE_P(v, T_NODE)) return v; - nd = (NODE *)v; - if (!nd_type_p(nd, NODE_RIPPER)) return Qnil; - return nd->nd_rval; -} - -static VALUE -ripper_lex_get_generic(struct parser_params *p, VALUE src) +static rb_parser_string_t * +ripper_lex_get_generic(struct parser_params *p, rb_parser_input_data input, int line_count) { + VALUE src = (VALUE)input; VALUE line = rb_funcallv_public(src, id_gets, 0, 0); - if (!NIL_P(line) && !RB_TYPE_P(line, T_STRING)) { + if (NIL_P(line)) return 0; + if (!RB_TYPE_P(line, T_STRING)) { rb_raise(rb_eTypeError, "gets returned %"PRIsVALUE" (expected String or nil)", rb_obj_class(line)); } - return line; + return rb_str_to_parser_string(p, line); } void @@ -100,10 +105,19 @@ ripper_compile_error(struct parser_params *p, const char *fmt, ...) ripper_error(p); } -static VALUE -ripper_lex_io_get(struct parser_params *p, VALUE src) +static rb_parser_string_t * +ripper_lex_io_get(struct parser_params *p, rb_parser_input_data input, int line_count) +{ + VALUE src = (VALUE)input; + VALUE line = rb_io_gets(src); + if (NIL_P(line)) return 0; + return rb_str_to_parser_string(p, line); +} + +static rb_parser_string_t * +ripper_lex_get_str(struct parser_params *p, rb_parser_input_data input, int line_count) { - return rb_io_gets(src); + return rb_parser_lex_get_str(p, (struct lex_pointer_string *)input); } static VALUE @@ -115,10 +129,8 @@ ripper_s_allocate(VALUE klass) &parser_data_type, r); #ifdef UNIVERSAL_PARSER - rb_parser_config_t *config; - config = rb_ruby_parser_config_new(ruby_xmalloc); - rb_parser_config_initialize(config); - r->p = rb_ruby_parser_allocate(config); + const rb_parser_config_t *config = rb_ruby_parser_config(); + r->p = rb_ripper_parser_params_allocate(config); #else r->p = rb_ruby_ripper_parser_allocate(); #endif @@ -126,6 +138,20 @@ ripper_s_allocate(VALUE klass) return self; } +static struct parser_params * +ripper_parser_params(VALUE self, bool initialized) +{ + struct ripper *r; + struct parser_params *p; + + TypedData_Get_Struct(self, struct ripper, &parser_data_type, r); + p = r->p; + if (initialized && !rb_ruby_ripper_initialized_p(p)) { + rb_raise(rb_eArgError, "method called for uninitialized object"); + } + return p; +} + /* * call-seq: * ripper.error? -> Boolean @@ -135,10 +161,9 @@ ripper_s_allocate(VALUE klass) static VALUE ripper_error_p(VALUE vparser) { - struct ripper *r; + struct parser_params *p = ripper_parser_params(vparser, false); - TypedData_Get_Struct(vparser, struct ripper, &parser_data_type, r); - return RBOOL(rb_ruby_parser_error_p(r->p)); + return RBOOL(rb_ruby_parser_error_p(p)); } /* @@ -150,10 +175,9 @@ ripper_error_p(VALUE vparser) static VALUE ripper_parser_end_seen_p(VALUE vparser) { - struct ripper *r; + struct parser_params *p = ripper_parser_params(vparser, false); - TypedData_Get_Struct(vparser, struct ripper, &parser_data_type, r); - return RBOOL(rb_ruby_parser_end_seen_p(r->p)); + return RBOOL(rb_ruby_parser_end_seen_p(p)); } /* @@ -165,10 +189,9 @@ ripper_parser_end_seen_p(VALUE vparser) static VALUE ripper_parser_encoding(VALUE vparser) { - struct ripper *r; + struct parser_params *p = ripper_parser_params(vparser, false); - TypedData_Get_Struct(vparser, struct ripper, &parser_data_type, r); - return rb_ruby_parser_encoding(r->p); + return rb_enc_from_encoding(rb_ruby_parser_encoding(p)); } /* @@ -180,10 +203,9 @@ ripper_parser_encoding(VALUE vparser) static VALUE ripper_parser_get_yydebug(VALUE self) { - struct ripper *r; + struct parser_params *p = ripper_parser_params(self, false); - TypedData_Get_Struct(self, struct ripper, &parser_data_type, r); - return RBOOL(rb_ruby_parser_get_yydebug(r->p)); + return RBOOL(rb_ruby_parser_get_yydebug(p)); } /* @@ -195,10 +217,9 @@ ripper_parser_get_yydebug(VALUE self) static VALUE ripper_parser_set_yydebug(VALUE self, VALUE flag) { - struct ripper *r; + struct parser_params *p = ripper_parser_params(self, false); - TypedData_Get_Struct(self, struct ripper, &parser_data_type, r); - rb_ruby_parser_set_yydebug(r->p, RTEST(flag)); + rb_ruby_parser_set_yydebug(p, RTEST(flag)); return flag; } @@ -211,10 +232,9 @@ ripper_parser_set_yydebug(VALUE self, VALUE flag) static VALUE ripper_parser_get_debug_output(VALUE self) { - struct ripper *r; + struct parser_params *p = ripper_parser_params(self, false); - TypedData_Get_Struct(self, struct ripper, &parser_data_type, r); - return rb_ruby_parser_debug_output(r->p); + return rb_ruby_parser_debug_output(p); } /* @@ -226,13 +246,24 @@ ripper_parser_get_debug_output(VALUE self) static VALUE ripper_parser_set_debug_output(VALUE self, VALUE output) { - struct ripper *r; + struct parser_params *p = ripper_parser_params(self, false); - TypedData_Get_Struct(self, struct ripper, &parser_data_type, r); - rb_ruby_parser_set_debug_output(r->p, output); + rb_ruby_parser_set_debug_output(p, output); return output; } +static int +ripper_parser_dedent_string(struct parser_params *p, VALUE string, int width) +{ + int col; + rb_parser_string_t *str; + str = rb_str_to_parser_string(p, string); + col = rb_ruby_ripper_dedent_string(p, str, width); + rb_str_replace(string, rb_str_new_parser_string(str)); + rb_parser_string_free(p, str); + return col; +} + #ifdef UNIVERSAL_PARSER struct dedent_string_arg { struct parser_params *p; @@ -248,16 +279,16 @@ parser_dedent_string0(VALUE a) StringValue(arg->input); wid = NUM2UINT(arg->width); - col = rb_ruby_ripper_dedent_string(arg->p, arg->input, wid); + col = ripper_parser_dedent_string(arg->p, arg->input, wid); return INT2NUM(col); } static VALUE -parser_config_free(VALUE a) +parser_free(VALUE a) { - rb_parser_config_t *config = (void *)a; + struct parser_params *p = (void *)a; - rb_ruby_parser_config_free(config); + rb_ruby_parser_free(p); return Qnil; } #endif @@ -276,17 +307,14 @@ static VALUE parser_dedent_string(VALUE self, VALUE input, VALUE width) { struct parser_params *p; - rb_parser_config_t *config; struct dedent_string_arg args; - config = rb_ruby_parser_config_new(ruby_xmalloc); - rb_parser_config_initialize(config); - p = rb_ruby_parser_new(config); + p = rb_parser_params_new(); args.p = p; args.input = input; args.width = width; - return rb_ensure(parser_dedent_string0, (VALUE)&args, parser_config_free, (VALUE)config); + return rb_ensure(parser_dedent_string0, (VALUE)&args, parser_free, (VALUE)p); } #else static VALUE @@ -296,7 +324,7 @@ parser_dedent_string(VALUE self, VALUE input, VALUE width) StringValue(input); wid = NUM2UINT(width); - col = rb_ruby_ripper_dedent_string(0, input, wid); + col = ripper_parser_dedent_string(0, input, wid); return INT2NUM(col); } #endif @@ -317,25 +345,35 @@ ripper_initialize(int argc, VALUE *argv, VALUE self) struct ripper *r; struct parser_params *p; VALUE src, fname, lineno; - VALUE (*gets)(struct parser_params*,VALUE); - VALUE input, sourcefile_string; + rb_parser_lex_gets_func *gets; + VALUE sourcefile_string; const char *sourcefile; int sourceline; + rb_parser_input_data input; + p = ripper_parser_params(self, false); TypedData_Get_Struct(self, struct ripper, &parser_data_type, r); - p = r->p; rb_scan_args(argc, argv, "12", &src, &fname, &lineno); if (RB_TYPE_P(src, T_FILE)) { gets = ripper_lex_io_get; + r->type = lex_type_io; + r->data.val = src; + input = (rb_parser_input_data)src; } else if (rb_respond_to(src, id_gets)) { gets = ripper_lex_get_generic; + r->type = lex_type_generic; + r->data.val = src; + input = (rb_parser_input_data)src; } else { StringValue(src); - gets = rb_ruby_ripper_lex_get_str; + gets = ripper_lex_get_str; + r->type = lex_type_str; + r->data.ptr_str.str = src; + r->data.ptr_str.ptr = 0; + input = (rb_parser_input_data)&r->data.ptr_str; } - input = src; if (NIL_P(fname)) { fname = STR_NEW2("(ripper)"); OBJ_FREEZE(fname); @@ -358,12 +396,8 @@ ripper_initialize(int argc, VALUE *argv, VALUE self) static VALUE ripper_parse0(VALUE vparser) { - struct ripper *r; - struct parser_params *p; + struct parser_params *p = ripper_parser_params(vparser, false); - TypedData_Get_Struct(vparser, struct ripper, &parser_data_type, r); - p = r->p; - // RB_GC_GUARD(vparser); rb_ruby_ripper_parse0(p); return rb_ruby_parser_result(p); } @@ -371,10 +405,9 @@ ripper_parse0(VALUE vparser) static VALUE ripper_ensure(VALUE vparser) { - struct ripper *r; + struct parser_params *p = ripper_parser_params(vparser, false); - TypedData_Get_Struct(vparser, struct ripper, &parser_data_type, r); - rb_ruby_parser_set_parsing_thread(r->p, Qnil); + rb_ruby_parser_set_parsing_thread(p, Qnil); return Qnil; } @@ -387,14 +420,9 @@ ripper_ensure(VALUE vparser) static VALUE ripper_parse(VALUE self) { - struct ripper *r; - struct parser_params *p; + struct parser_params *p = ripper_parser_params(self, true); + VALUE result; - TypedData_Get_Struct(self, struct ripper, &parser_data_type, r); - p = r->p; - if (!rb_ruby_ripper_initialized_p(p)) { - rb_raise(rb_eArgError, "method called for uninitialized object"); - } if (!NIL_P(rb_ruby_parser_parsing_thread(p))) { if (rb_ruby_parser_parsing_thread(p) == rb_thread_current()) rb_raise(rb_eArgError, "Ripper#parse is not reentrant"); @@ -402,9 +430,10 @@ ripper_parse(VALUE self) rb_raise(rb_eArgError, "Ripper#parse is not multithread-safe"); } rb_ruby_parser_set_parsing_thread(p, rb_thread_current()); - rb_ensure(ripper_parse0, self, ripper_ensure, self); + result = rb_ensure(ripper_parse0, self, ripper_ensure, self); + RB_GC_GUARD(self); - return rb_ruby_parser_result(p); + return result; } /* @@ -417,15 +446,9 @@ ripper_parse(VALUE self) static VALUE ripper_column(VALUE self) { - struct ripper *r; - struct parser_params *p; + struct parser_params *p = ripper_parser_params(self, true); long col; - TypedData_Get_Struct(self, struct ripper, &parser_data_type, r); - p = r->p; - if (!rb_ruby_ripper_initialized_p(p)) { - rb_raise(rb_eArgError, "method called for uninitialized object"); - } if (NIL_P(rb_ruby_parser_parsing_thread(p))) return Qnil; col = rb_ruby_ripper_column(p); return LONG2NUM(col); @@ -440,14 +463,8 @@ ripper_column(VALUE self) static VALUE ripper_filename(VALUE self) { - struct ripper *r; - struct parser_params *p; + struct parser_params *p = ripper_parser_params(self, true); - TypedData_Get_Struct(self, struct ripper, &parser_data_type, r); - p = r->p; - if (!rb_ruby_ripper_initialized_p(p)) { - rb_raise(rb_eArgError, "method called for uninitialized object"); - } return rb_ruby_parser_ruby_sourcefile_string(p); } @@ -461,14 +478,8 @@ ripper_filename(VALUE self) static VALUE ripper_lineno(VALUE self) { - struct ripper *r; - struct parser_params *p; + struct parser_params *p = ripper_parser_params(self, true); - TypedData_Get_Struct(self, struct ripper, &parser_data_type, r); - p = r->p; - if (!rb_ruby_ripper_initialized_p(p)) { - rb_raise(rb_eArgError, "method called for uninitialized object"); - } if (NIL_P(rb_ruby_parser_parsing_thread(p))) return Qnil; return INT2NUM(rb_ruby_parser_ruby_sourceline(p)); } @@ -482,14 +493,8 @@ ripper_lineno(VALUE self) static VALUE ripper_state(VALUE self) { - struct ripper *r; - struct parser_params *p; + struct parser_params *p = ripper_parser_params(self, true); - TypedData_Get_Struct(self, struct ripper, &parser_data_type, r); - p = r->p; - if (!rb_ruby_ripper_initialized_p(p)) { - rb_raise(rb_eArgError, "method called for uninitialized object"); - } if (NIL_P(rb_ruby_parser_parsing_thread(p))) return Qnil; return INT2NUM(rb_ruby_parser_lex_state(p)); } @@ -503,19 +508,15 @@ ripper_state(VALUE self) static VALUE ripper_token(VALUE self) { - struct ripper *r; - struct parser_params *p; + struct parser_params *p = ripper_parser_params(self, true); long pos, len; + VALUE str; - TypedData_Get_Struct(self, struct ripper, &parser_data_type, r); - p = r->p; - if (!rb_ruby_ripper_initialized_p(p)) { - rb_raise(rb_eArgError, "method called for uninitialized object"); - } if (NIL_P(rb_ruby_parser_parsing_thread(p))) return Qnil; pos = rb_ruby_ripper_column(p); len = rb_ruby_ripper_token_len(p); - return rb_str_subseq(rb_ruby_ripper_lex_lastline(p), pos, len); + str = rb_str_new_parser_string(rb_ruby_ripper_lex_lastline(p)); + return rb_str_subseq(str, pos, len); } #ifdef RIPPER_DEBUG @@ -536,6 +537,37 @@ ripper_raw_value(VALUE self, VALUE obj) { return ULONG2NUM(obj); } + +/* :nodoc: */ +static VALUE +ripper_validate_object(VALUE self, VALUE x) +{ + if (x == Qfalse) return x; + if (x == Qtrue) return x; + if (NIL_P(x)) return x; + if (UNDEF_P(x)) + rb_raise(rb_eArgError, "Qundef given"); + if (FIXNUM_P(x)) return x; + if (SYMBOL_P(x)) return x; + switch (BUILTIN_TYPE(x)) { + case T_STRING: + case T_OBJECT: + case T_ARRAY: + case T_BIGNUM: + case T_FLOAT: + case T_COMPLEX: + case T_RATIONAL: + break; + default: + rb_raise(rb_eArgError, "wrong type of ruby object: %p (%s)", + (void *)x, rb_obj_classname(x)); + } + if (!RBASIC_CLASS(x)) { + rb_raise(rb_eArgError, "hidden ruby object: %p (%s)", + (void *)x, rb_builtin_type_name(TYPE(x))); + } + return x; +} #endif #ifdef UNIVERSAL_PARSER @@ -564,17 +596,14 @@ static VALUE ripper_lex_state_name(VALUE self, VALUE state) { struct parser_params *p; - rb_parser_config_t *config; struct lex_state_name_arg args; - config = rb_ruby_parser_config_new(ruby_xmalloc); - rb_parser_config_initialize(config); - p = rb_ruby_parser_new(config); + p = rb_parser_params_new(); args.p = p; args.state = state; - return rb_ensure(lex_state_name0, (VALUE)&args, parser_config_free, (VALUE)config); + return rb_ensure(lex_state_name0, (VALUE)&args, parser_free, (VALUE)p); } #else static VALUE @@ -648,5 +677,4 @@ InitVM_ripper(void) */ rb_define_global_const("SCRIPT_LINES__", Qnil); #endif - } diff --git a/ext/ripper/ripper_init.h b/ext/ripper/ripper_init.h index 82ff13b95f8958..9d228107d1b172 100644 --- a/ext/ripper/ripper_init.h +++ b/ext/ripper/ripper_init.h @@ -1,8 +1,6 @@ #ifndef RIPPER_INIT_H #define RIPPER_INIT_H -VALUE ripper_get_value(VALUE v); -ID ripper_get_id(VALUE v); PRINTF_ARGS(void ripper_compile_error(struct parser_params*, const char *fmt, ...), 2, 3); #endif /* RIPPER_INIT_H */ diff --git a/ext/ripper/tools/dsl.rb b/ext/ripper/tools/dsl.rb index 49ff51711f00ff..38f859dd97ed61 100644 --- a/ext/ripper/tools/dsl.rb +++ b/ext/ripper/tools/dsl.rb @@ -1,83 +1,177 @@ +# frozen_string_literal: true + # Simple DSL implementation for Ripper code generation # -# input: /*% ripper: stmts_add(stmts_new, void_stmt) %*/ +# input: /*% ripper: stmts_add!(stmts_new!, void_stmt!) %*/ # output: # VALUE v1, v2; # v1 = dispatch0(stmts_new); # v2 = dispatch0(void_stmt); # $$ = dispatch2(stmts_add, v1, v2); - -$dollar = "$$" -alias $$ $dollar +# +# - The code must be a single line. +# +# - The code is basically Ruby code, even if it appears like in C and +# the result will be processed as C. e.g., comments need to be in +# Ruby style. class DSL - def initialize(code, options) + TAG_PATTERN = /(?><[a-zA-Z0-9_]+>)/.source + NAME_PATTERN = /(?>\$|\d+|[a-zA-Z_][a-zA-Z0-9_]*|\[[a-zA-Z_.][-a-zA-Z0-9_.]*\])(?>(?:\.|->)[a-zA-Z_][a-zA-Z0-9_]*)*/.source + NOT_REF_PATTERN = /(?>\#.*|[^\"$@]*|"(?>\\.|[^\"])*")/.source + + def self.line?(line, lineno = nil, indent: nil) + if %r<(?\s*)/\*% *ripper(?:\[(?
- def caption(align = {}) # :yield: - attributes = if align.kind_of?(String) - { "ALIGN" => align } - else - align - end - super(attributes) - end - - - # Generate a Checkbox Input element as a string. - # - # The attributes of the element can be specified as three arguments, - # +name+, +value+, and +checked+. +checked+ is a boolean value; - # if true, the CHECKED attribute will be included in the element. - # - # Alternatively, the attributes can be specified as a hash. - # - # checkbox("name") - # # = checkbox("NAME" => "name") - # - # checkbox("name", "value") - # # = checkbox("NAME" => "name", "VALUE" => "value") - # - # checkbox("name", "value", true) - # # = checkbox("NAME" => "name", "VALUE" => "value", "CHECKED" => true) - def checkbox(name = "", value = nil, checked = nil) - attributes = if name.kind_of?(String) - { "TYPE" => "checkbox", "NAME" => name, - "VALUE" => value, "CHECKED" => checked } - else - name["TYPE"] = "checkbox" - name - end - input(attributes) - end - - # Generate a sequence of checkbox elements, as a String. - # - # The checkboxes will all have the same +name+ attribute. - # Each checkbox is followed by a label. - # There will be one checkbox for each value. Each value - # can be specified as a String, which will be used both - # as the value of the VALUE attribute and as the label - # for that checkbox. A single-element array has the - # same effect. - # - # Each value can also be specified as a three-element array. - # The first element is the VALUE attribute; the second is the - # label; and the third is a boolean specifying whether this - # checkbox is CHECKED. - # - # Each value can also be specified as a two-element - # array, by omitting either the value element (defaults - # to the same as the label), or the boolean checked element - # (defaults to false). - # - # checkbox_group("name", "foo", "bar", "baz") - # # foo - # # bar - # # baz - # - # checkbox_group("name", ["foo"], ["bar", true], "baz") - # # foo - # # bar - # # baz - # - # checkbox_group("name", ["1", "Foo"], ["2", "Bar", true], "Baz") - # # Foo - # # Bar - # # Baz - # - # checkbox_group("NAME" => "name", - # "VALUES" => ["foo", "bar", "baz"]) - # - # checkbox_group("NAME" => "name", - # "VALUES" => [["foo"], ["bar", true], "baz"]) - # - # checkbox_group("NAME" => "name", - # "VALUES" => [["1", "Foo"], ["2", "Bar", true], "Baz"]) - def checkbox_group(name = "", *values) - if name.kind_of?(Hash) - values = name["VALUES"] - name = name["NAME"] - end - values.collect{|value| - if value.kind_of?(String) - checkbox(name, value) + value - else - if value[-1] == true || value[-1] == false - checkbox(name, value[0], value[-1]) + - value[-2] - else - checkbox(name, value[0]) + - value[-1] - end - end - }.join - end - - - # Generate an File Upload Input element as a string. - # - # The attributes of the element can be specified as three arguments, - # +name+, +size+, and +maxlength+. +maxlength+ is the maximum length - # of the file's _name_, not of the file's _contents_. - # - # Alternatively, the attributes can be specified as a hash. - # - # See #multipart_form() for forms that include file uploads. - # - # file_field("name") - # # - # - # file_field("name", 40) - # # - # - # file_field("name", 40, 100) - # # - # - # file_field("NAME" => "name", "SIZE" => 40) - # # - def file_field(name = "", size = 20, maxlength = nil) - attributes = if name.kind_of?(String) - { "TYPE" => "file", "NAME" => name, - "SIZE" => size.to_s } - else - name["TYPE"] = "file" - name - end - attributes["MAXLENGTH"] = maxlength.to_s if maxlength - input(attributes) - end - - - # Generate a Form element as a string. - # - # +method+ should be either "get" or "post", and defaults to the latter. - # +action+ defaults to the current CGI script name. +enctype+ - # defaults to "application/x-www-form-urlencoded". - # - # Alternatively, the attributes can be specified as a hash. - # - # See also #multipart_form() for forms that include file uploads. - # - # form{ "string" } - # #
string - # - # form("get") { "string" } - # #
string - # - # form("get", "url") { "string" } - # #
string - # - # form("METHOD" => "post", "ENCTYPE" => "enctype") { "string" } - # #
string - def form(method = "post", action = script_name, enctype = "application/x-www-form-urlencoded") - attributes = if method.kind_of?(String) - { "METHOD" => method, "ACTION" => action, - "ENCTYPE" => enctype } - else - unless method.has_key?("METHOD") - method["METHOD"] = "post" - end - unless method.has_key?("ENCTYPE") - method["ENCTYPE"] = enctype - end - method - end - if block_given? - body = yield - else - body = "" - end - if @output_hidden - body << @output_hidden.collect{|k,v| - "" - }.join - end - super(attributes){body} - end - - # Generate a Hidden Input element as a string. - # - # The attributes of the element can be specified as two arguments, - # +name+ and +value+. - # - # Alternatively, the attributes can be specified as a hash. - # - # hidden("name") - # # - # - # hidden("name", "value") - # # - # - # hidden("NAME" => "name", "VALUE" => "reset", "ID" => "foo") - # # - def hidden(name = "", value = nil) - attributes = if name.kind_of?(String) - { "TYPE" => "hidden", "NAME" => name, "VALUE" => value } - else - name["TYPE"] = "hidden" - name - end - input(attributes) - end - - # Generate a top-level HTML element as a string. - # - # The attributes of the element are specified as a hash. The - # pseudo-attribute "PRETTY" can be used to specify that the generated - # HTML string should be indented. "PRETTY" can also be specified as - # a string as the sole argument to this method. The pseudo-attribute - # "DOCTYPE", if given, is used as the leading DOCTYPE SGML tag; it - # should include the entire text of this tag, including angle brackets. - # - # The body of the html element is supplied as a block. - # - # html{ "string" } - # # string - # - # html("LANG" => "ja") { "string" } - # # string - # - # html("DOCTYPE" => false) { "string" } - # # string - # - # html("DOCTYPE" => '') { "string" } - # # string - # - # html("PRETTY" => " ") { "" } - # # - # # - # # - # # - # # - # - # html("PRETTY" => "\t") { "" } - # # - # # - # # - # # - # # - # - # html("PRETTY") { "" } - # # = html("PRETTY" => " ") { "" } - # - # html(if $VERBOSE then "PRETTY" end) { "HTML string" } - # - def html(attributes = {}) # :yield: - if nil == attributes - attributes = {} - elsif "PRETTY" == attributes - attributes = { "PRETTY" => true } - end - pretty = attributes.delete("PRETTY") - pretty = " " if true == pretty - buf = "".dup - - if attributes.has_key?("DOCTYPE") - if attributes["DOCTYPE"] - buf << attributes.delete("DOCTYPE") - else - attributes.delete("DOCTYPE") - end - else - buf << doctype - end - - buf << super(attributes) - - if pretty - CGI.pretty(buf, pretty) - else - buf - end - - end - - # Generate an Image Button Input element as a string. - # - # +src+ is the URL of the image to use for the button. +name+ - # is the input name. +alt+ is the alternative text for the image. - # - # Alternatively, the attributes can be specified as a hash. - # - # image_button("url") - # # - # - # image_button("url", "name", "string") - # # - # - # image_button("SRC" => "url", "ALT" => "string") - # # - def image_button(src = "", name = nil, alt = nil) - attributes = if src.kind_of?(String) - { "TYPE" => "image", "SRC" => src, "NAME" => name, - "ALT" => alt } - else - src["TYPE"] = "image" - src["SRC"] ||= "" - src - end - input(attributes) - end - - - # Generate an Image element as a string. - # - # +src+ is the URL of the image. +alt+ is the alternative text for - # the image. +width+ is the width of the image, and +height+ is - # its height. - # - # Alternatively, the attributes can be specified as a hash. - # - # img("src", "alt", 100, 50) - # # alt - # - # img("SRC" => "src", "ALT" => "alt", "WIDTH" => 100, "HEIGHT" => 50) - # # alt - def img(src = "", alt = "", width = nil, height = nil) - attributes = if src.kind_of?(String) - { "SRC" => src, "ALT" => alt } - else - src - end - attributes["WIDTH"] = width.to_s if width - attributes["HEIGHT"] = height.to_s if height - super(attributes) - end - - - # Generate a Form element with multipart encoding as a String. - # - # Multipart encoding is used for forms that include file uploads. - # - # +action+ is the action to perform. +enctype+ is the encoding - # type, which defaults to "multipart/form-data". - # - # Alternatively, the attributes can be specified as a hash. - # - # multipart_form{ "string" } - # #
string - # - # multipart_form("url") { "string" } - # #
string - def multipart_form(action = nil, enctype = "multipart/form-data") - attributes = if action == nil - { "METHOD" => "post", "ENCTYPE" => enctype } - elsif action.kind_of?(String) - { "METHOD" => "post", "ACTION" => action, - "ENCTYPE" => enctype } - else - unless action.has_key?("METHOD") - action["METHOD"] = "post" - end - unless action.has_key?("ENCTYPE") - action["ENCTYPE"] = enctype - end - action - end - if block_given? - form(attributes){ yield } - else - form(attributes) - end - end - - - # Generate a Password Input element as a string. - # - # +name+ is the name of the input field. +value+ is its default - # value. +size+ is the size of the input field display. +maxlength+ - # is the maximum length of the inputted password. - # - # Alternatively, attributes can be specified as a hash. - # - # password_field("name") - # # - # - # password_field("name", "value") - # # - # - # password_field("password", "value", 80, 200) - # # - # - # password_field("NAME" => "name", "VALUE" => "value") - # # - def password_field(name = "", value = nil, size = 40, maxlength = nil) - attributes = if name.kind_of?(String) - { "TYPE" => "password", "NAME" => name, - "VALUE" => value, "SIZE" => size.to_s } - else - name["TYPE"] = "password" - name - end - attributes["MAXLENGTH"] = maxlength.to_s if maxlength - input(attributes) - end - - # Generate a Select element as a string. - # - # +name+ is the name of the element. The +values+ are the options that - # can be selected from the Select menu. Each value can be a String or - # a one, two, or three-element Array. If a String or a one-element - # Array, this is both the value of that option and the text displayed for - # it. If a three-element Array, the elements are the option value, displayed - # text, and a boolean value specifying whether this option starts as selected. - # The two-element version omits either the option value (defaults to the same - # as the display text) or the boolean selected specifier (defaults to false). - # - # The attributes and options can also be specified as a hash. In this - # case, options are specified as an array of values as described above, - # with the hash key of "VALUES". - # - # popup_menu("name", "foo", "bar", "baz") - # # - # - # popup_menu("name", ["foo"], ["bar", true], "baz") - # # - # - # popup_menu("name", ["1", "Foo"], ["2", "Bar", true], "Baz") - # # - # - # popup_menu("NAME" => "name", "SIZE" => 2, "MULTIPLE" => true, - # "VALUES" => [["1", "Foo"], ["2", "Bar", true], "Baz"]) - # # - def popup_menu(name = "", *values) - - if name.kind_of?(Hash) - values = name["VALUES"] - size = name["SIZE"].to_s if name["SIZE"] - multiple = name["MULTIPLE"] - name = name["NAME"] - else - size = nil - multiple = nil - end - - select({ "NAME" => name, "SIZE" => size, - "MULTIPLE" => multiple }){ - values.collect{|value| - if value.kind_of?(String) - option({ "VALUE" => value }){ value } - else - if value[value.size - 1] == true - option({ "VALUE" => value[0], "SELECTED" => true }){ - value[value.size - 2] - } - else - option({ "VALUE" => value[0] }){ - value[value.size - 1] - } - end - end - }.join - } - - end - - # Generates a radio-button Input element. - # - # +name+ is the name of the input field. +value+ is the value of - # the field if checked. +checked+ specifies whether the field - # starts off checked. - # - # Alternatively, the attributes can be specified as a hash. - # - # radio_button("name", "value") - # # - # - # radio_button("name", "value", true) - # # - # - # radio_button("NAME" => "name", "VALUE" => "value", "ID" => "foo") - # # - def radio_button(name = "", value = nil, checked = nil) - attributes = if name.kind_of?(String) - { "TYPE" => "radio", "NAME" => name, - "VALUE" => value, "CHECKED" => checked } - else - name["TYPE"] = "radio" - name - end - input(attributes) - end - - # Generate a sequence of radio button Input elements, as a String. - # - # This works the same as #checkbox_group(). However, it is not valid - # to have more than one radiobutton in a group checked. - # - # radio_group("name", "foo", "bar", "baz") - # # foo - # # bar - # # baz - # - # radio_group("name", ["foo"], ["bar", true], "baz") - # # foo - # # bar - # # baz - # - # radio_group("name", ["1", "Foo"], ["2", "Bar", true], "Baz") - # # Foo - # # Bar - # # Baz - # - # radio_group("NAME" => "name", - # "VALUES" => ["foo", "bar", "baz"]) - # - # radio_group("NAME" => "name", - # "VALUES" => [["foo"], ["bar", true], "baz"]) - # - # radio_group("NAME" => "name", - # "VALUES" => [["1", "Foo"], ["2", "Bar", true], "Baz"]) - def radio_group(name = "", *values) - if name.kind_of?(Hash) - values = name["VALUES"] - name = name["NAME"] - end - values.collect{|value| - if value.kind_of?(String) - radio_button(name, value) + value - else - if value[-1] == true || value[-1] == false - radio_button(name, value[0], value[-1]) + - value[-2] - else - radio_button(name, value[0]) + - value[-1] - end - end - }.join - end - - # Generate a reset button Input element, as a String. - # - # This resets the values on a form to their initial values. +value+ - # is the text displayed on the button. +name+ is the name of this button. - # - # Alternatively, the attributes can be specified as a hash. - # - # reset - # # - # - # reset("reset") - # # - # - # reset("VALUE" => "reset", "ID" => "foo") - # # - def reset(value = nil, name = nil) - attributes = if (not value) or value.kind_of?(String) - { "TYPE" => "reset", "VALUE" => value, "NAME" => name } - else - value["TYPE"] = "reset" - value - end - input(attributes) - end - - alias scrolling_list popup_menu - - # Generate a submit button Input element, as a String. - # - # +value+ is the text to display on the button. +name+ is the name - # of the input. - # - # Alternatively, the attributes can be specified as a hash. - # - # submit - # # - # - # submit("ok") - # # - # - # submit("ok", "button1") - # # - # - # submit("VALUE" => "ok", "NAME" => "button1", "ID" => "foo") - # # - def submit(value = nil, name = nil) - attributes = if (not value) or value.kind_of?(String) - { "TYPE" => "submit", "VALUE" => value, "NAME" => name } - else - value["TYPE"] = "submit" - value - end - input(attributes) - end - - # Generate a text field Input element, as a String. - # - # +name+ is the name of the input field. +value+ is its initial - # value. +size+ is the size of the input area. +maxlength+ - # is the maximum length of input accepted. - # - # Alternatively, the attributes can be specified as a hash. - # - # text_field("name") - # # - # - # text_field("name", "value") - # # - # - # text_field("name", "value", 80) - # # - # - # text_field("name", "value", 80, 200) - # # - # - # text_field("NAME" => "name", "VALUE" => "value") - # # - def text_field(name = "", value = nil, size = 40, maxlength = nil) - attributes = if name.kind_of?(String) - { "TYPE" => "text", "NAME" => name, "VALUE" => value, - "SIZE" => size.to_s } - else - name["TYPE"] = "text" - name - end - attributes["MAXLENGTH"] = maxlength.to_s if maxlength - input(attributes) - end - - # Generate a TextArea element, as a String. - # - # +name+ is the name of the textarea. +cols+ is the number of - # columns and +rows+ is the number of rows in the display. - # - # Alternatively, the attributes can be specified as a hash. - # - # The body is provided by the passed-in no-argument block - # - # textarea("name") - # # = textarea("NAME" => "name", "COLS" => 70, "ROWS" => 10) - # - # textarea("name", 40, 5) - # # = textarea("NAME" => "name", "COLS" => 40, "ROWS" => 5) - def textarea(name = "", cols = 70, rows = 10) # :yield: - attributes = if name.kind_of?(String) - { "NAME" => name, "COLS" => cols.to_s, - "ROWS" => rows.to_s } - else - name - end - super(attributes) - end - - end # HtmlExtension - - - # Mixin module for HTML version 3 generation methods. - module Html3 # :nodoc: - include TagMaker - - # The DOCTYPE declaration for this version of HTML - def doctype - %|| - end - - instance_method(:nn_element_def).tap do |m| - # - - - for element in %w[ A TT I B U STRIKE BIG SMALL SUB SUP EM STRONG - DFN CODE SAMP KBD VAR CITE FONT ADDRESS DIV CENTER MAP - APPLET PRE XMP LISTING DL OL UL DIR MENU SELECT TABLE TITLE - STYLE SCRIPT H1 H2 H3 H4 H5 H6 TEXTAREA FORM BLOCKQUOTE - CAPTION ] - define_method(element.downcase, m) - end - end - - instance_method(:nOE_element_def).tap do |m| - # - O EMPTY - for element in %w[ IMG BASE BASEFONT BR AREA LINK PARAM HR INPUT - ISINDEX META ] - define_method(element.downcase, m) - end - end - - instance_method(:nO_element_def).tap do |m| - # O O or - O - for element in %w[ HTML HEAD BODY P PLAINTEXT DT DD LI OPTION TR - TH TD ] - define_method(element.downcase, m) - end - end - - end # Html3 - - - # Mixin module for HTML version 4 generation methods. - module Html4 # :nodoc: - include TagMaker - - # The DOCTYPE declaration for this version of HTML - def doctype - %|| - end - - # Initialize the HTML generation methods for this version. - # - - - instance_method(:nn_element_def).tap do |m| - for element in %w[ TT I B BIG SMALL EM STRONG DFN CODE SAMP KBD - VAR CITE ABBR ACRONYM SUB SUP SPAN BDO ADDRESS DIV MAP OBJECT - H1 H2 H3 H4 H5 H6 PRE Q INS DEL DL OL UL LABEL SELECT OPTGROUP - FIELDSET LEGEND BUTTON TABLE TITLE STYLE SCRIPT NOSCRIPT - TEXTAREA FORM A BLOCKQUOTE CAPTION ] - define_method(element.downcase, m) - end - end - - # - O EMPTY - instance_method(:nOE_element_def).tap do |m| - for element in %w[ IMG BASE BR AREA LINK PARAM HR INPUT COL META ] - define_method(element.downcase, m) - end - end - - # O O or - O - instance_method(:nO_element_def).tap do |m| - for element in %w[ HTML BODY P DT DD LI OPTION THEAD TFOOT TBODY - COLGROUP TR TH TD HEAD ] - define_method(element.downcase, m) - end - end - - end # Html4 - - - # Mixin module for HTML version 4 transitional generation methods. - module Html4Tr # :nodoc: - include TagMaker - - # The DOCTYPE declaration for this version of HTML - def doctype - %|| - end - - # Initialise the HTML generation methods for this version. - # - - - instance_method(:nn_element_def).tap do |m| - for element in %w[ TT I B U S STRIKE BIG SMALL EM STRONG DFN - CODE SAMP KBD VAR CITE ABBR ACRONYM FONT SUB SUP SPAN BDO - ADDRESS DIV CENTER MAP OBJECT APPLET H1 H2 H3 H4 H5 H6 PRE Q - INS DEL DL OL UL DIR MENU LABEL SELECT OPTGROUP FIELDSET - LEGEND BUTTON TABLE IFRAME NOFRAMES TITLE STYLE SCRIPT - NOSCRIPT TEXTAREA FORM A BLOCKQUOTE CAPTION ] - define_method(element.downcase, m) - end - end - - # - O EMPTY - instance_method(:nOE_element_def).tap do |m| - for element in %w[ IMG BASE BASEFONT BR AREA LINK PARAM HR INPUT - COL ISINDEX META ] - define_method(element.downcase, m) - end - end - - # O O or - O - instance_method(:nO_element_def).tap do |m| - for element in %w[ HTML BODY P DT DD LI OPTION THEAD TFOOT TBODY - COLGROUP TR TH TD HEAD ] - define_method(element.downcase, m) - end - end - - end # Html4Tr - - - # Mixin module for generating HTML version 4 with framesets. - module Html4Fr # :nodoc: - include TagMaker - - # The DOCTYPE declaration for this version of HTML - def doctype - %|| - end - - # Initialise the HTML generation methods for this version. - # - - - instance_method(:nn_element_def).tap do |m| - for element in %w[ FRAMESET ] - define_method(element.downcase, m) - end - end - - # - O EMPTY - instance_method(:nOE_element_def).tap do |m| - for element in %w[ FRAME ] - define_method(element.downcase, m) - end - end - - end # Html4Fr - - - # Mixin module for HTML version 5 generation methods. - module Html5 # :nodoc: - include TagMaker - - # The DOCTYPE declaration for this version of HTML - def doctype - %|| - end - - # Initialise the HTML generation methods for this version. - # - - - instance_method(:nn_element_def).tap do |m| - for element in %w[ SECTION NAV ARTICLE ASIDE HGROUP HEADER - FOOTER FIGURE FIGCAPTION S TIME U MARK RUBY BDI IFRAME - VIDEO AUDIO CANVAS DATALIST OUTPUT PROGRESS METER DETAILS - SUMMARY MENU DIALOG I B SMALL EM STRONG DFN CODE SAMP KBD - VAR CITE ABBR SUB SUP SPAN BDO ADDRESS DIV MAP OBJECT - H1 H2 H3 H4 H5 H6 PRE Q INS DEL DL OL UL LABEL SELECT - FIELDSET LEGEND BUTTON TABLE TITLE STYLE SCRIPT NOSCRIPT - TEXTAREA FORM A BLOCKQUOTE CAPTION ] - define_method(element.downcase, m) - end - end - - # - O EMPTY - instance_method(:nOE_element_def).tap do |m| - for element in %w[ IMG BASE BR AREA LINK PARAM HR INPUT COL META - COMMAND EMBED KEYGEN SOURCE TRACK WBR ] - define_method(element.downcase, m) - end - end - - # O O or - O - instance_method(:nO_element_def).tap do |m| - for element in %w[ HTML HEAD BODY P DT DD LI OPTION THEAD TFOOT TBODY - OPTGROUP COLGROUP RT RP TR TH TD ] - define_method(element.downcase, m) - end - end - - end # Html5 - - class HTML3 - include Html3 - include HtmlExtension - end - - class HTML4 - include Html4 - include HtmlExtension - end - - class HTML4Tr - include Html4Tr - include HtmlExtension - end - - class HTML4Fr - include Html4Tr - include Html4Fr - include HtmlExtension - end - - class HTML5 - include Html5 - include HtmlExtension - end - -end diff --git a/lib/cgi/session.rb b/lib/cgi/session.rb deleted file mode 100644 index aab60869bbd882..00000000000000 --- a/lib/cgi/session.rb +++ /dev/null @@ -1,562 +0,0 @@ -# frozen_string_literal: true -# -# cgi/session.rb - session support for cgi scripts -# -# Copyright (C) 2001 Yukihiro "Matz" Matsumoto -# Copyright (C) 2000 Network Applied Communication Laboratory, Inc. -# Copyright (C) 2000 Information-technology Promotion Agency, Japan -# -# Author: Yukihiro "Matz" Matsumoto -# -# Documentation: William Webber (william@williamwebber.com) - -require 'cgi' -require 'tmpdir' - -class CGI - - # == Overview - # - # This file provides the CGI::Session class, which provides session - # support for CGI scripts. A session is a sequence of HTTP requests - # and responses linked together and associated with a single client. - # Information associated with the session is stored - # on the server between requests. A session id is passed between client - # and server with every request and response, transparently - # to the user. This adds state information to the otherwise stateless - # HTTP request/response protocol. - # - # == Lifecycle - # - # A CGI::Session instance is created from a CGI object. By default, - # this CGI::Session instance will start a new session if none currently - # exists, or continue the current session for this client if one does - # exist. The +new_session+ option can be used to either always or - # never create a new session. See #new() for more details. - # - # #delete() deletes a session from session storage. It - # does not however remove the session id from the client. If the client - # makes another request with the same id, the effect will be to start - # a new session with the old session's id. - # - # == Setting and retrieving session data. - # - # The Session class associates data with a session as key-value pairs. - # This data can be set and retrieved by indexing the Session instance - # using '[]', much the same as hashes (although other hash methods - # are not supported). - # - # When session processing has been completed for a request, the - # session should be closed using the close() method. This will - # store the session's state to persistent storage. If you want - # to store the session's state to persistent storage without - # finishing session processing for this request, call the update() - # method. - # - # == Storing session state - # - # The caller can specify what form of storage to use for the session's - # data with the +database_manager+ option to CGI::Session::new. The - # following storage classes are provided as part of the standard library: - # - # CGI::Session::FileStore:: stores data as plain text in a flat file. Only - # works with String data. This is the default - # storage type. - # CGI::Session::MemoryStore:: stores data in an in-memory hash. The data - # only persists for as long as the current Ruby - # interpreter instance does. - # CGI::Session::PStore:: stores data in Marshalled format. Provided by - # cgi/session/pstore.rb. Supports data of any type, - # and provides file-locking and transaction support. - # - # Custom storage types can also be created by defining a class with - # the following methods: - # - # new(session, options) - # restore # returns hash of session data. - # update - # close - # delete - # - # Changing storage type mid-session does not work. Note in particular - # that by default the FileStore and PStore session data files have the - # same name. If your application switches from one to the other without - # making sure that filenames will be different - # and clients still have old sessions lying around in cookies, then - # things will break nastily! - # - # == Maintaining the session id. - # - # Most session state is maintained on the server. However, a session - # id must be passed backwards and forwards between client and server - # to maintain a reference to this session state. - # - # The simplest way to do this is via cookies. The CGI::Session class - # provides transparent support for session id communication via cookies - # if the client has cookies enabled. - # - # If the client has cookies disabled, the session id must be included - # as a parameter of all requests sent by the client to the server. The - # CGI::Session class in conjunction with the CGI class will transparently - # add the session id as a hidden input field to all forms generated - # using the CGI#form() HTML generation method. No built-in support is - # provided for other mechanisms, such as URL re-writing. The caller is - # responsible for extracting the session id from the session_id - # attribute and manually encoding it in URLs and adding it as a hidden - # input to HTML forms created by other mechanisms. Also, session expiry - # is not automatically handled. - # - # == Examples of use - # - # === Setting the user's name - # - # require 'cgi' - # require 'cgi/session' - # require 'cgi/session/pstore' # provides CGI::Session::PStore - # - # cgi = CGI.new("html4") - # - # session = CGI::Session.new(cgi, - # 'database_manager' => CGI::Session::PStore, # use PStore - # 'session_key' => '_rb_sess_id', # custom session key - # 'session_expires' => Time.now + 30 * 60, # 30 minute timeout - # 'prefix' => 'pstore_sid_') # PStore option - # if cgi.has_key?('user_name') and cgi['user_name'] != '' - # # coerce to String: cgi[] returns the - # # string-like CGI::QueryExtension::Value - # session['user_name'] = cgi['user_name'].to_s - # elsif !session['user_name'] - # session['user_name'] = "guest" - # end - # session.close - # - # === Creating a new session safely - # - # require 'cgi' - # require 'cgi/session' - # - # cgi = CGI.new("html4") - # - # # We make sure to delete an old session if one exists, - # # not just to free resources, but to prevent the session - # # from being maliciously hijacked later on. - # begin - # session = CGI::Session.new(cgi, 'new_session' => false) - # session.delete - # rescue ArgumentError # if no old session - # end - # session = CGI::Session.new(cgi, 'new_session' => true) - # session.close - # - class Session - - class NoSession < RuntimeError #:nodoc: - end - - # The id of this session. - attr_reader :session_id, :new_session - - def Session::callback(dbman) #:nodoc: - Proc.new{ - dbman[0].close unless dbman.empty? - } - end - - # Create a new session id. - # - # The session id is a secure random number by SecureRandom - # if possible, otherwise an SHA512 hash based upon the time, - # a random number, and a constant string. This routine is - # used internally for automatically generated session ids. - def create_new_id - require 'securerandom' - begin - # by OpenSSL, or system provided entropy pool - session_id = SecureRandom.hex(16) - rescue NotImplementedError - # never happens on modern systems - require 'digest' - d = Digest('SHA512').new - now = Time::now - d.update(now.to_s) - d.update(String(now.usec)) - d.update(String(rand(0))) - d.update(String($$)) - d.update('foobar') - session_id = d.hexdigest[0, 32] - end - session_id - end - private :create_new_id - - - # Create a new file to store the session data. - # - # This file will be created if it does not exist, or opened if it - # does. - # - # This path is generated under _tmpdir_ from _prefix_, the - # digested session id, and _suffix_. - # - # +option+ is a hash of options for the initializer. The - # following options are recognised: - # - # tmpdir:: the directory to use for storing the FileStore - # file. Defaults to Dir::tmpdir (generally "/tmp" - # on Unix systems). - # prefix:: the prefix to add to the session id when generating - # the filename for this session's FileStore file. - # Defaults to "cgi_sid_". - # suffix:: the prefix to add to the session id when generating - # the filename for this session's FileStore file. - # Defaults to the empty string. - def new_store_file(option={}) # :nodoc: - dir = option['tmpdir'] || Dir::tmpdir - prefix = option['prefix'] - suffix = option['suffix'] - require 'digest/md5' - md5 = Digest::MD5.hexdigest(session_id)[0,16] - path = dir+"/" - path << prefix if prefix - path << md5 - path << suffix if suffix - if File::exist? path - hash = nil - elsif new_session - hash = {} - else - raise NoSession, "uninitialized session" - end - return path, hash - end - - # Create a new CGI::Session object for +request+. - # - # +request+ is an instance of the +CGI+ class (see cgi.rb). - # +option+ is a hash of options for initialising this - # CGI::Session instance. The following options are - # recognised: - # - # session_key:: the parameter name used for the session id. - # Defaults to '_session_id'. - # session_id:: the session id to use. If not provided, then - # it is retrieved from the +session_key+ parameter - # of the request, or automatically generated for - # a new session. - # new_session:: if true, force creation of a new session. If not set, - # a new session is only created if none currently - # exists. If false, a new session is never created, - # and if none currently exists and the +session_id+ - # option is not set, an ArgumentError is raised. - # database_manager:: the name of the class providing storage facilities - # for session state persistence. Built-in support - # is provided for +FileStore+ (the default), - # +MemoryStore+, and +PStore+ (from - # cgi/session/pstore.rb). See the documentation for - # these classes for more details. - # - # The following options are also recognised, but only apply if the - # session id is stored in a cookie. - # - # session_expires:: the time the current session expires, as a - # +Time+ object. If not set, the session will terminate - # when the user's browser is closed. - # session_domain:: the hostname domain for which this session is valid. - # If not set, defaults to the hostname of the server. - # session_secure:: if +true+, this session will only work over HTTPS. - # session_path:: the path for which this session applies. Defaults - # to the directory of the CGI script. - # - # +option+ is also passed on to the session storage class initializer; see - # the documentation for each session storage class for the options - # they support. - # - # The retrieved or created session is automatically added to +request+ - # as a cookie, and also to its +output_hidden+ table, which is used - # to add hidden input elements to forms. - # - # *WARNING* the +output_hidden+ - # fields are surrounded by a
tag in HTML 4 generation, which - # is _not_ invisible on many browsers; you may wish to disable the - # use of fieldsets with code similar to the following - # (see https://blade.ruby-lang.org/ruby-list/37805) - # - # cgi = CGI.new("html4") - # class << cgi - # undef_method :fieldset - # end - # - def initialize(request, option={}) - @new_session = false - session_key = option['session_key'] || '_session_id' - session_id = option['session_id'] - unless session_id - if option['new_session'] - session_id = create_new_id - @new_session = true - end - end - unless session_id - if request.key?(session_key) - session_id = request[session_key] - session_id = session_id.read if session_id.respond_to?(:read) - end - unless session_id - session_id, = request.cookies[session_key] - end - unless session_id - unless option.fetch('new_session', true) - raise ArgumentError, "session_key `%s' should be supplied"%session_key - end - session_id = create_new_id - @new_session = true - end - end - @session_id = session_id - dbman = option['database_manager'] || FileStore - begin - @dbman = dbman::new(self, option) - rescue NoSession - unless option.fetch('new_session', true) - raise ArgumentError, "invalid session_id `%s'"%session_id - end - session_id = @session_id = create_new_id unless session_id - @new_session=true - retry - end - request.instance_eval do - @output_hidden = {session_key => session_id} unless option['no_hidden'] - @output_cookies = [ - Cookie::new("name" => session_key, - "value" => session_id, - "expires" => option['session_expires'], - "domain" => option['session_domain'], - "secure" => option['session_secure'], - "path" => - if option['session_path'] - option['session_path'] - elsif ENV["SCRIPT_NAME"] - File::dirname(ENV["SCRIPT_NAME"]) - else - "" - end) - ] unless option['no_cookies'] - end - @dbprot = [@dbman] - ObjectSpace::define_finalizer(self, Session::callback(@dbprot)) - end - - # Retrieve the session data for key +key+. - def [](key) - @data ||= @dbman.restore - @data[key] - end - - # Set the session data for key +key+. - def []=(key, val) - @write_lock ||= true - @data ||= @dbman.restore - @data[key] = val - end - - # Store session data on the server. For some session storage types, - # this is a no-op. - def update - @dbman.update - end - - # Store session data on the server and close the session storage. - # For some session storage types, this is a no-op. - def close - @dbman.close - @dbprot.clear - end - - # Delete the session from storage. Also closes the storage. - # - # Note that the session's data is _not_ automatically deleted - # upon the session expiring. - def delete - @dbman.delete - @dbprot.clear - end - - # File-based session storage class. - # - # Implements session storage as a flat file of 'key=value' values. - # This storage type only works directly with String values; the - # user is responsible for converting other types to Strings when - # storing and from Strings when retrieving. - class FileStore - # Create a new FileStore instance. - # - # This constructor is used internally by CGI::Session. The - # user does not generally need to call it directly. - # - # +session+ is the session for which this instance is being - # created. The session id must only contain alphanumeric - # characters; automatically generated session ids observe - # this requirement. - # - # +option+ is a hash of options for the initializer. The - # following options are recognised: - # - # tmpdir:: the directory to use for storing the FileStore - # file. Defaults to Dir::tmpdir (generally "/tmp" - # on Unix systems). - # prefix:: the prefix to add to the session id when generating - # the filename for this session's FileStore file. - # Defaults to "cgi_sid_". - # suffix:: the prefix to add to the session id when generating - # the filename for this session's FileStore file. - # Defaults to the empty string. - # - # This session's FileStore file will be created if it does - # not exist, or opened if it does. - def initialize(session, option={}) - option = {'prefix' => 'cgi_sid_'}.update(option) - @path, @hash = session.new_store_file(option) - end - - # Restore session state from the session's FileStore file. - # - # Returns the session state as a hash. - def restore - unless @hash - @hash = {} - begin - lockf = File.open(@path+".lock", "r") - lockf.flock File::LOCK_SH - f = File.open(@path, 'r') - for line in f - line.chomp! - k, v = line.split('=',2) - @hash[CGI.unescape(k)] = Marshal.restore(CGI.unescape(v)) - end - ensure - f&.close - lockf&.close - end - end - @hash - end - - # Save session state to the session's FileStore file. - def update - return unless @hash - begin - lockf = File.open(@path+".lock", File::CREAT|File::RDWR, 0600) - lockf.flock File::LOCK_EX - f = File.open(@path+".new", File::CREAT|File::TRUNC|File::WRONLY, 0600) - for k,v in @hash - f.printf "%s=%s\n", CGI.escape(k), CGI.escape(String(Marshal.dump(v))) - end - f.close - File.rename @path+".new", @path - ensure - f&.close - lockf&.close - end - end - - # Update and close the session's FileStore file. - def close - update - end - - # Close and delete the session's FileStore file. - def delete - File::unlink @path+".lock" rescue nil - File::unlink @path+".new" rescue nil - File::unlink @path rescue nil - end - end - - # In-memory session storage class. - # - # Implements session storage as a global in-memory hash. Session - # data will only persist for as long as the Ruby interpreter - # instance does. - class MemoryStore - GLOBAL_HASH_TABLE = {} #:nodoc: - - # Create a new MemoryStore instance. - # - # +session+ is the session this instance is associated with. - # +option+ is a list of initialisation options. None are - # currently recognized. - def initialize(session, option=nil) - @session_id = session.session_id - unless GLOBAL_HASH_TABLE.key?(@session_id) - unless session.new_session - raise CGI::Session::NoSession, "uninitialized session" - end - GLOBAL_HASH_TABLE[@session_id] = {} - end - end - - # Restore session state. - # - # Returns session data as a hash. - def restore - GLOBAL_HASH_TABLE[@session_id] - end - - # Update session state. - # - # A no-op. - def update - # don't need to update; hash is shared - end - - # Close session storage. - # - # A no-op. - def close - # don't need to close - end - - # Delete the session state. - def delete - GLOBAL_HASH_TABLE.delete(@session_id) - end - end - - # Dummy session storage class. - # - # Implements session storage place holder. No actual storage - # will be done. - class NullStore - # Create a new NullStore instance. - # - # +session+ is the session this instance is associated with. - # +option+ is a list of initialisation options. None are - # currently recognised. - def initialize(session, option=nil) - end - - # Restore (empty) session state. - def restore - {} - end - - # Update session state. - # - # A no-op. - def update - end - - # Close session storage. - # - # A no-op. - def close - end - - # Delete the session state. - # - # A no-op. - def delete - end - end - end -end diff --git a/lib/cgi/session/pstore.rb b/lib/cgi/session/pstore.rb deleted file mode 100644 index 45d0d8ae2cb17b..00000000000000 --- a/lib/cgi/session/pstore.rb +++ /dev/null @@ -1,88 +0,0 @@ -# frozen_string_literal: true -# -# cgi/session/pstore.rb - persistent storage of marshalled session data -# -# Documentation: William Webber (william@williamwebber.com) -# -# == Overview -# -# This file provides the CGI::Session::PStore class, which builds -# persistent of session data on top of the pstore library. See -# cgi/session.rb for more details on session storage managers. - -require_relative '../session' -require 'pstore' - -class CGI - class Session - # PStore-based session storage class. - # - # This builds upon the top-level PStore class provided by the - # library file pstore.rb. Session data is marshalled and stored - # in a file. File locking and transaction services are provided. - class PStore - # Create a new CGI::Session::PStore instance - # - # This constructor is used internally by CGI::Session. The - # user does not generally need to call it directly. - # - # +session+ is the session for which this instance is being - # created. The session id must only contain alphanumeric - # characters; automatically generated session ids observe - # this requirement. - # - # +option+ is a hash of options for the initializer. The - # following options are recognised: - # - # tmpdir:: the directory to use for storing the PStore - # file. Defaults to Dir::tmpdir (generally "/tmp" - # on Unix systems). - # prefix:: the prefix to add to the session id when generating - # the filename for this session's PStore file. - # Defaults to the empty string. - # - # This session's PStore file will be created if it does - # not exist, or opened if it does. - def initialize(session, option={}) - option = {'suffix'=>''}.update(option) - path, @hash = session.new_store_file(option) - @p = ::PStore.new(path) - @p.transaction do |p| - File.chmod(0600, p.path) - end - end - - # Restore session state from the session's PStore file. - # - # Returns the session state as a hash. - def restore - unless @hash - @p.transaction do - @hash = @p['hash'] || {} - end - end - @hash - end - - # Save session state to the session's PStore file. - def update - @p.transaction do - @p['hash'] = @hash - end - end - - # Update and close the session's PStore file. - def close - update - end - - # Close and delete the session's PStore file. - def delete - path = @p.path - File::unlink path - end - - end - end -end -# :enddoc: diff --git a/lib/cgi/util.rb b/lib/cgi/util.rb index 5f335898dc84a7..389a04acd21f05 100644 --- a/lib/cgi/util.rb +++ b/lib/cgi/util.rb @@ -1,255 +1,7 @@ # frozen_string_literal: true -class CGI - module Util; end - include Util - extend Util -end -module CGI::Util - @@accept_charset = Encoding::UTF_8 unless defined?(@@accept_charset) - # URL-encode a string into application/x-www-form-urlencoded. - # Space characters (+" "+) are encoded with plus signs (+"+"+) - # url_encoded_string = CGI.escape("'Stop!' said Fred") - # # => "%27Stop%21%27+said+Fred" - def escape(string) - encoding = string.encoding - buffer = string.b - buffer.gsub!(/([^ a-zA-Z0-9_.\-~]+)/) do |m| - '%' + m.unpack('H2' * m.bytesize).join('%').upcase - end - buffer.tr!(' ', '+') - buffer.force_encoding(encoding) - end - - # URL-decode an application/x-www-form-urlencoded string with encoding(optional). - # string = CGI.unescape("%27Stop%21%27+said+Fred") - # # => "'Stop!' said Fred" - def unescape(string, encoding = @@accept_charset) - str = string.tr('+', ' ') - str = str.b - str.gsub!(/((?:%[0-9a-fA-F]{2})+)/) do |m| - [m.delete('%')].pack('H*') - end - str.force_encoding(encoding) - str.valid_encoding? ? str : str.force_encoding(string.encoding) - end - - # URL-encode a string following RFC 3986 - # Space characters (+" "+) are encoded with (+"%20"+) - # url_encoded_string = CGI.escape("'Stop!' said Fred") - # # => "%27Stop%21%27%20said%20Fred" - def escapeURIComponent(string) - encoding = string.encoding - buffer = string.b - buffer.gsub!(/([^a-zA-Z0-9_.\-~]+)/) do |m| - '%' + m.unpack('H2' * m.bytesize).join('%').upcase - end - buffer.force_encoding(encoding) - end - - # URL-decode a string following RFC 3986 with encoding(optional). - # string = CGI.unescape("%27Stop%21%27+said%20Fred") - # # => "'Stop!'+said Fred" - def unescapeURIComponent(string, encoding = @@accept_charset) - str = string.b - str.gsub!(/((?:%[0-9a-fA-F]{2})+)/) do |m| - [m.delete('%')].pack('H*') - end - str.force_encoding(encoding) - str.valid_encoding? ? str : str.force_encoding(string.encoding) - end - - # The set of special characters and their escaped values - TABLE_FOR_ESCAPE_HTML__ = { - "'" => ''', - '&' => '&', - '"' => '"', - '<' => '<', - '>' => '>', - } - - # Escape special characters in HTML, namely '&\"<> - # CGI.escapeHTML('Usage: foo "bar" ') - # # => "Usage: foo "bar" <baz>" - def escapeHTML(string) - enc = string.encoding - unless enc.ascii_compatible? - if enc.dummy? - origenc = enc - enc = Encoding::Converter.asciicompat_encoding(enc) - string = enc ? string.encode(enc) : string.b - end - table = Hash[TABLE_FOR_ESCAPE_HTML__.map {|pair|pair.map {|s|s.encode(enc)}}] - string = string.gsub(/#{"['&\"<>]".encode(enc)}/, table) - string.encode!(origenc) if origenc - string - else - string = string.b - string.gsub!(/['&\"<>]/, TABLE_FOR_ESCAPE_HTML__) - string.force_encoding(enc) - end - end - - # TruffleRuby runs the pure-Ruby variant faster, do not use the C extension there - unless RUBY_ENGINE == 'truffleruby' - begin - require 'cgi/escape' - rescue LoadError - end - end - - # Unescape a string that has been HTML-escaped - # CGI.unescapeHTML("Usage: foo "bar" <baz>") - # # => "Usage: foo \"bar\" " - def unescapeHTML(string) - enc = string.encoding - unless enc.ascii_compatible? - if enc.dummy? - origenc = enc - enc = Encoding::Converter.asciicompat_encoding(enc) - string = enc ? string.encode(enc) : string.b - end - string = string.gsub(Regexp.new('&(apos|amp|quot|gt|lt|#[0-9]+|#x[0-9A-Fa-f]+);'.encode(enc))) do - case $1.encode(Encoding::US_ASCII) - when 'apos' then "'".encode(enc) - when 'amp' then '&'.encode(enc) - when 'quot' then '"'.encode(enc) - when 'gt' then '>'.encode(enc) - when 'lt' then '<'.encode(enc) - when /\A#0*(\d+)\z/ then $1.to_i.chr(enc) - when /\A#x([0-9a-f]+)\z/i then $1.hex.chr(enc) - end - end - string.encode!(origenc) if origenc - return string - end - return string unless string.include? '&' - charlimit = case enc - when Encoding::UTF_8; 0x10ffff - when Encoding::ISO_8859_1; 256 - else 128 - end - string = string.b - string.gsub!(/&(apos|amp|quot|gt|lt|\#[0-9]+|\#[xX][0-9A-Fa-f]+);/) do - match = $1.dup - case match - when 'apos' then "'" - when 'amp' then '&' - when 'quot' then '"' - when 'gt' then '>' - when 'lt' then '<' - when /\A#0*(\d+)\z/ - n = $1.to_i - if n < charlimit - n.chr(enc) - else - "&##{$1};" - end - when /\A#x([0-9a-f]+)\z/i - n = $1.hex - if n < charlimit - n.chr(enc) - else - "&#x#{$1};" - end - else - "&#{match};" - end - end - string.force_encoding enc - end - - # Synonym for CGI.escapeHTML(str) - alias escape_html escapeHTML - - # Synonym for CGI.unescapeHTML(str) - alias unescape_html unescapeHTML - - # Escape only the tags of certain HTML elements in +string+. - # - # Takes an element or elements or array of elements. Each element - # is specified by the name of the element, without angle brackets. - # This matches both the start and the end tag of that element. - # The attribute list of the open tag will also be escaped (for - # instance, the double-quotes surrounding attribute values). - # - # print CGI.escapeElement('
', "A", "IMG") - # # "
<A HREF="url"></A>" - # - # print CGI.escapeElement('
', ["A", "IMG"]) - # # "
<A HREF="url"></A>" - def escapeElement(string, *elements) - elements = elements[0] if elements[0].kind_of?(Array) - unless elements.empty? - string.gsub(/<\/?(?:#{elements.join("|")})(?!\w)(?:.|\n)*?>/i) do - CGI.escapeHTML($&) - end - else - string - end - end - - # Undo escaping such as that done by CGI.escapeElement() - # - # print CGI.unescapeElement( - # CGI.escapeHTML('
'), "A", "IMG") - # # "<BR>" - # - # print CGI.unescapeElement( - # CGI.escapeHTML('
'), ["A", "IMG"]) - # # "<BR>" - def unescapeElement(string, *elements) - elements = elements[0] if elements[0].kind_of?(Array) - unless elements.empty? - string.gsub(/<\/?(?:#{elements.join("|")})(?!\w)(?:.|\n)*?>/i) do - unescapeHTML($&) - end - else - string - end - end - - # Synonym for CGI.escapeElement(str) - alias escape_element escapeElement - - # Synonym for CGI.unescapeElement(str) - alias unescape_element unescapeElement - - # Format a +Time+ object as a String using the format specified by RFC 1123. - # - # CGI.rfc1123_date(Time.now) - # # Sat, 01 Jan 2000 00:00:00 GMT - def rfc1123_date(time) - time.getgm.strftime("%a, %d %b %Y %T GMT") - end - - # Prettify (indent) an HTML string. - # - # +string+ is the HTML string to indent. +shift+ is the indentation - # unit to use; it defaults to two spaces. - # - # print CGI.pretty("") - # # - # # - # # - # # - # - # print CGI.pretty("", "\t") - # # - # # - # # - # # - # - def pretty(string, shift = " ") - lines = string.gsub(/(?!\A)<.*?>/m, "\n\\0").gsub(/<.*?>(?!\n)/m, "\\0\n") - end_pos = 0 - while end_pos = lines.index(/^<\/(\w+)/, end_pos) - element = $1.dup - start_pos = lines.rindex(/^\s*<#{element}/i, end_pos) - lines[start_pos ... end_pos] = "__" + lines[start_pos ... end_pos].gsub(/\n(?!\z)/, "\n" + shift) + "__" - end - lines.gsub(/^((?:#{Regexp::quote(shift)})*)__(?=<\/?\w)/, '\1') - end - - alias h escapeHTML -end +require "cgi/escape" +warn <<-WARNING, uplevel: Gem::BUNDLED_GEMS.uplevel if $VERBOSE +CGI::Util is removed from Ruby 3.5. Please use cgi/escape instead for CGI.escape and CGI.unescape features. +If you are using CGI.parse, please install and use the cgi gem instead. +WARNING diff --git a/lib/csv.rb b/lib/csv.rb deleted file mode 100644 index d4dc569b838f40..00000000000000 --- a/lib/csv.rb +++ /dev/null @@ -1,2881 +0,0 @@ -# encoding: US-ASCII -# frozen_string_literal: true -# = csv.rb -- CSV Reading and Writing -# -# Created by James Edward Gray II on 2005-10-31. -# -# See CSV for documentation. -# -# == Description -# -# Welcome to the new and improved CSV. -# -# This version of the CSV library began its life as FasterCSV. FasterCSV was -# intended as a replacement to Ruby's then standard CSV library. It was -# designed to address concerns users of that library had and it had three -# primary goals: -# -# 1. Be significantly faster than CSV while remaining a pure Ruby library. -# 2. Use a smaller and easier to maintain code base. (FasterCSV eventually -# grew larger, was also but considerably richer in features. The parsing -# core remains quite small.) -# 3. Improve on the CSV interface. -# -# Obviously, the last one is subjective. I did try to defer to the original -# interface whenever I didn't have a compelling reason to change it though, so -# hopefully this won't be too radically different. -# -# We must have met our goals because FasterCSV was renamed to CSV and replaced -# the original library as of Ruby 1.9. If you are migrating code from 1.8 or -# earlier, you may have to change your code to comply with the new interface. -# -# == What's the Different From the Old CSV? -# -# I'm sure I'll miss something, but I'll try to mention most of the major -# differences I am aware of, to help others quickly get up to speed: -# -# === \CSV Parsing -# -# * This parser is m17n aware. See CSV for full details. -# * This library has a stricter parser and will throw MalformedCSVErrors on -# problematic data. -# * This library has a less liberal idea of a line ending than CSV. What you -# set as the :row_sep is law. It can auto-detect your line endings -# though. -# * The old library returned empty lines as [nil]. This library calls -# them []. -# * This library has a much faster parser. -# -# === Interface -# -# * CSV now uses keyword parameters to set options. -# * CSV no longer has generate_row() or parse_row(). -# * The old CSV's Reader and Writer classes have been dropped. -# * CSV::open() is now more like Ruby's open(). -# * CSV objects now support most standard IO methods. -# * CSV now has a new() method used to wrap objects like String and IO for -# reading and writing. -# * CSV::generate() is different from the old method. -# * CSV no longer supports partial reads. It works line-by-line. -# * CSV no longer allows the instance methods to override the separators for -# performance reasons. They must be set in the constructor. -# -# If you use this library and find yourself missing any functionality I have -# trimmed, please {let me know}[mailto:james@grayproductions.net]. -# -# == Documentation -# -# See CSV for documentation. -# -# == What is CSV, really? -# -# CSV maintains a pretty strict definition of CSV taken directly from -# {the RFC}[https://www.ietf.org/rfc/rfc4180.txt]. I relax the rules in only one -# place and that is to make using this library easier. CSV will parse all valid -# CSV. -# -# What you don't want to do is to feed CSV invalid data. Because of the way the -# CSV format works, it's common for a parser to need to read until the end of -# the file to be sure a field is invalid. This consumes a lot of time and memory. -# -# Luckily, when working with invalid CSV, Ruby's built-in methods will almost -# always be superior in every way. For example, parsing non-quoted fields is as -# easy as: -# -# data.split(",") -# -# == Questions and/or Comments -# -# Feel free to email {James Edward Gray II}[mailto:james@grayproductions.net] -# with any questions. - -require "forwardable" -require "date" -require "stringio" - -require_relative "csv/fields_converter" -require_relative "csv/input_record_separator" -require_relative "csv/parser" -require_relative "csv/row" -require_relative "csv/table" -require_relative "csv/writer" - -# == \CSV -# -# === In a Hurry? -# -# If you are familiar with \CSV data and have a particular task in mind, -# you may want to go directly to the: -# - {Recipes for CSV}[doc/csv/recipes/recipes_rdoc.html]. -# -# Otherwise, read on here, about the API: classes, methods, and constants. -# -# === \CSV Data -# -# \CSV (comma-separated values) data is a text representation of a table: -# - A _row_ _separator_ delimits table rows. -# A common row separator is the newline character "\n". -# - A _column_ _separator_ delimits fields in a row. -# A common column separator is the comma character ",". -# -# This \CSV \String, with row separator "\n" -# and column separator ",", -# has three rows and two columns: -# "foo,0\nbar,1\nbaz,2\n" -# -# Despite the name \CSV, a \CSV representation can use different separators. -# -# For more about tables, see the Wikipedia article -# "{Table (information)}[https://en.wikipedia.org/wiki/Table_(information)]", -# especially its section -# "{Simple table}[https://en.wikipedia.org/wiki/Table_(information)#Simple_table]" -# -# == \Class \CSV -# -# Class \CSV provides methods for: -# - Parsing \CSV data from a \String object, a \File (via its file path), or an \IO object. -# - Generating \CSV data to a \String object. -# -# To make \CSV available: -# require 'csv' -# -# All examples here assume that this has been done. -# -# == Keeping It Simple -# -# A \CSV object has dozens of instance methods that offer fine-grained control -# of parsing and generating \CSV data. -# For many needs, though, simpler approaches will do. -# -# This section summarizes the singleton methods in \CSV -# that allow you to parse and generate without explicitly -# creating \CSV objects. -# For details, follow the links. -# -# === Simple Parsing -# -# Parsing methods commonly return either of: -# - An \Array of Arrays of Strings: -# - The outer \Array is the entire "table". -# - Each inner \Array is a row. -# - Each \String is a field. -# - A CSV::Table object. For details, see -# {\CSV with Headers}[#class-CSV-label-CSV+with+Headers]. -# -# ==== Parsing a \String -# -# The input to be parsed can be a string: -# string = "foo,0\nbar,1\nbaz,2\n" -# -# \Method CSV.parse returns the entire \CSV data: -# CSV.parse(string) # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] -# -# \Method CSV.parse_line returns only the first row: -# CSV.parse_line(string) # => ["foo", "0"] -# -# \CSV extends class \String with instance method String#parse_csv, -# which also returns only the first row: -# string.parse_csv # => ["foo", "0"] -# -# ==== Parsing Via a \File Path -# -# The input to be parsed can be in a file: -# string = "foo,0\nbar,1\nbaz,2\n" -# path = 't.csv' -# File.write(path, string) -# -# \Method CSV.read returns the entire \CSV data: -# CSV.read(path) # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] -# -# \Method CSV.foreach iterates, passing each row to the given block: -# CSV.foreach(path) do |row| -# p row -# end -# Output: -# ["foo", "0"] -# ["bar", "1"] -# ["baz", "2"] -# -# \Method CSV.table returns the entire \CSV data as a CSV::Table object: -# CSV.table(path) # => # -# -# ==== Parsing from an Open \IO Stream -# -# The input to be parsed can be in an open \IO stream: -# -# \Method CSV.read returns the entire \CSV data: -# File.open(path) do |file| -# CSV.read(file) -# end # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] -# -# As does method CSV.parse: -# File.open(path) do |file| -# CSV.parse(file) -# end # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] -# -# \Method CSV.parse_line returns only the first row: -# File.open(path) do |file| -# CSV.parse_line(file) -# end # => ["foo", "0"] -# -# \Method CSV.foreach iterates, passing each row to the given block: -# File.open(path) do |file| -# CSV.foreach(file) do |row| -# p row -# end -# end -# Output: -# ["foo", "0"] -# ["bar", "1"] -# ["baz", "2"] -# -# \Method CSV.table returns the entire \CSV data as a CSV::Table object: -# File.open(path) do |file| -# CSV.table(file) -# end # => # -# -# === Simple Generating -# -# \Method CSV.generate returns a \String; -# this example uses method CSV#<< to append the rows -# that are to be generated: -# output_string = CSV.generate do |csv| -# csv << ['foo', 0] -# csv << ['bar', 1] -# csv << ['baz', 2] -# end -# output_string # => "foo,0\nbar,1\nbaz,2\n" -# -# \Method CSV.generate_line returns a \String containing the single row -# constructed from an \Array: -# CSV.generate_line(['foo', '0']) # => "foo,0\n" -# -# \CSV extends class \Array with instance method Array#to_csv, -# which forms an \Array into a \String: -# ['foo', '0'].to_csv # => "foo,0\n" -# -# === "Filtering" \CSV -# -# \Method CSV.filter provides a Unix-style filter for \CSV data. -# The input data is processed to form the output data: -# in_string = "foo,0\nbar,1\nbaz,2\n" -# out_string = '' -# CSV.filter(in_string, out_string) do |row| -# row[0] = row[0].upcase -# row[1] *= 4 -# end -# out_string # => "FOO,0000\nBAR,1111\nBAZ,2222\n" -# -# == \CSV Objects -# -# There are three ways to create a \CSV object: -# - \Method CSV.new returns a new \CSV object. -# - \Method CSV.instance returns a new or cached \CSV object. -# - \Method \CSV() also returns a new or cached \CSV object. -# -# === Instance Methods -# -# \CSV has three groups of instance methods: -# - Its own internally defined instance methods. -# - Methods included by module Enumerable. -# - Methods delegated to class IO. See below. -# -# ==== Delegated Methods -# -# For convenience, a CSV object will delegate to many methods in class IO. -# (A few have wrapper "guard code" in \CSV.) You may call: -# * IO#binmode -# * #binmode? -# * IO#close -# * IO#close_read -# * IO#close_write -# * IO#closed? -# * #eof -# * #eof? -# * IO#external_encoding -# * IO#fcntl -# * IO#fileno -# * #flock -# * IO#flush -# * IO#fsync -# * IO#internal_encoding -# * #ioctl -# * IO#isatty -# * #path -# * IO#pid -# * IO#pos -# * IO#pos= -# * IO#reopen -# * #rewind -# * IO#seek -# * #stat -# * IO#string -# * IO#sync -# * IO#sync= -# * IO#tell -# * #to_i -# * #to_io -# * IO#truncate -# * IO#tty? -# -# === Options -# -# The default values for options are: -# DEFAULT_OPTIONS = { -# # For both parsing and generating. -# col_sep: ",", -# row_sep: :auto, -# quote_char: '"', -# # For parsing. -# field_size_limit: nil, -# converters: nil, -# unconverted_fields: nil, -# headers: false, -# return_headers: false, -# header_converters: nil, -# skip_blanks: false, -# skip_lines: nil, -# liberal_parsing: false, -# nil_value: nil, -# empty_value: "", -# strip: false, -# # For generating. -# write_headers: nil, -# quote_empty: true, -# force_quotes: false, -# write_converters: nil, -# write_nil_value: nil, -# write_empty_value: "", -# } -# -# ==== Options for Parsing -# -# Options for parsing, described in detail below, include: -# - +row_sep+: Specifies the row separator; used to delimit rows. -# - +col_sep+: Specifies the column separator; used to delimit fields. -# - +quote_char+: Specifies the quote character; used to quote fields. -# - +field_size_limit+: Specifies the maximum field size + 1 allowed. -# Deprecated since 3.2.3. Use +max_field_size+ instead. -# - +max_field_size+: Specifies the maximum field size allowed. -# - +converters+: Specifies the field converters to be used. -# - +unconverted_fields+: Specifies whether unconverted fields are to be available. -# - +headers+: Specifies whether data contains headers, -# or specifies the headers themselves. -# - +return_headers+: Specifies whether headers are to be returned. -# - +header_converters+: Specifies the header converters to be used. -# - +skip_blanks+: Specifies whether blanks lines are to be ignored. -# - +skip_lines+: Specifies how comments lines are to be recognized. -# - +strip+: Specifies whether leading and trailing whitespace are to be -# stripped from fields. This must be compatible with +col_sep+; if it is not, -# then an +ArgumentError+ exception will be raised. -# - +liberal_parsing+: Specifies whether \CSV should attempt to parse -# non-compliant data. -# - +nil_value+: Specifies the object that is to be substituted for each null (no-text) field. -# - +empty_value+: Specifies the object that is to be substituted for each empty field. -# -# :include: ../doc/csv/options/common/row_sep.rdoc -# -# :include: ../doc/csv/options/common/col_sep.rdoc -# -# :include: ../doc/csv/options/common/quote_char.rdoc -# -# :include: ../doc/csv/options/parsing/field_size_limit.rdoc -# -# :include: ../doc/csv/options/parsing/converters.rdoc -# -# :include: ../doc/csv/options/parsing/unconverted_fields.rdoc -# -# :include: ../doc/csv/options/parsing/headers.rdoc -# -# :include: ../doc/csv/options/parsing/return_headers.rdoc -# -# :include: ../doc/csv/options/parsing/header_converters.rdoc -# -# :include: ../doc/csv/options/parsing/skip_blanks.rdoc -# -# :include: ../doc/csv/options/parsing/skip_lines.rdoc -# -# :include: ../doc/csv/options/parsing/strip.rdoc -# -# :include: ../doc/csv/options/parsing/liberal_parsing.rdoc -# -# :include: ../doc/csv/options/parsing/nil_value.rdoc -# -# :include: ../doc/csv/options/parsing/empty_value.rdoc -# -# ==== Options for Generating -# -# Options for generating, described in detail below, include: -# - +row_sep+: Specifies the row separator; used to delimit rows. -# - +col_sep+: Specifies the column separator; used to delimit fields. -# - +quote_char+: Specifies the quote character; used to quote fields. -# - +write_headers+: Specifies whether headers are to be written. -# - +force_quotes+: Specifies whether each output field is to be quoted. -# - +quote_empty+: Specifies whether each empty output field is to be quoted. -# - +write_converters+: Specifies the field converters to be used in writing. -# - +write_nil_value+: Specifies the object that is to be substituted for each +nil+-valued field. -# - +write_empty_value+: Specifies the object that is to be substituted for each empty field. -# -# :include: ../doc/csv/options/common/row_sep.rdoc -# -# :include: ../doc/csv/options/common/col_sep.rdoc -# -# :include: ../doc/csv/options/common/quote_char.rdoc -# -# :include: ../doc/csv/options/generating/write_headers.rdoc -# -# :include: ../doc/csv/options/generating/force_quotes.rdoc -# -# :include: ../doc/csv/options/generating/quote_empty.rdoc -# -# :include: ../doc/csv/options/generating/write_converters.rdoc -# -# :include: ../doc/csv/options/generating/write_nil_value.rdoc -# -# :include: ../doc/csv/options/generating/write_empty_value.rdoc -# -# === \CSV with Headers -# -# CSV allows to specify column names of CSV file, whether they are in data, or -# provided separately. If headers are specified, reading methods return an instance -# of CSV::Table, consisting of CSV::Row. -# -# # Headers are part of data -# data = CSV.parse(<<~ROWS, headers: true) -# Name,Department,Salary -# Bob,Engineering,1000 -# Jane,Sales,2000 -# John,Management,5000 -# ROWS -# -# data.class #=> CSV::Table -# data.first #=> # -# data.first.to_h #=> {"Name"=>"Bob", "Department"=>"Engineering", "Salary"=>"1000"} -# -# # Headers provided by developer -# data = CSV.parse('Bob,Engineering,1000', headers: %i[name department salary]) -# data.first #=> # -# -# === \Converters -# -# By default, each value (field or header) parsed by \CSV is formed into a \String. -# You can use a _field_ _converter_ or _header_ _converter_ -# to intercept and modify the parsed values: -# - See {Field Converters}[#class-CSV-label-Field+Converters]. -# - See {Header Converters}[#class-CSV-label-Header+Converters]. -# -# Also by default, each value to be written during generation is written 'as-is'. -# You can use a _write_ _converter_ to modify values before writing. -# - See {Write Converters}[#class-CSV-label-Write+Converters]. -# -# ==== Specifying \Converters -# -# You can specify converters for parsing or generating in the +options+ -# argument to various \CSV methods: -# - Option +converters+ for converting parsed field values. -# - Option +header_converters+ for converting parsed header values. -# - Option +write_converters+ for converting values to be written (generated). -# -# There are three forms for specifying converters: -# - A converter proc: executable code to be used for conversion. -# - A converter name: the name of a stored converter. -# - A converter list: an array of converter procs, converter names, and converter lists. -# -# ===== Converter Procs -# -# This converter proc, +strip_converter+, accepts a value +field+ -# and returns field.strip: -# strip_converter = proc {|field| field.strip } -# In this call to CSV.parse, -# the keyword argument converters: string_converter -# specifies that: -# - \Proc +string_converter+ is to be called for each parsed field. -# - The converter's return value is to replace the +field+ value. -# Example: -# string = " foo , 0 \n bar , 1 \n baz , 2 \n" -# array = CSV.parse(string, converters: strip_converter) -# array # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] -# -# A converter proc can receive a second argument, +field_info+, -# that contains details about the field. -# This modified +strip_converter+ displays its arguments: -# strip_converter = proc do |field, field_info| -# p [field, field_info] -# field.strip -# end -# string = " foo , 0 \n bar , 1 \n baz , 2 \n" -# array = CSV.parse(string, converters: strip_converter) -# array # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] -# Output: -# [" foo ", #] -# [" 0 ", #] -# [" bar ", #] -# [" 1 ", #] -# [" baz ", #] -# [" 2 ", #] -# Each CSV::FieldInfo object shows: -# - The 0-based field index. -# - The 1-based line index. -# - The field header, if any. -# -# ===== Stored \Converters -# -# A converter may be given a name and stored in a structure where -# the parsing methods can find it by name. -# -# The storage structure for field converters is the \Hash CSV::Converters. -# It has several built-in converter procs: -# - :integer: converts each \String-embedded integer into a true \Integer. -# - :float: converts each \String-embedded float into a true \Float. -# - :date: converts each \String-embedded date into a true \Date. -# - :date_time: converts each \String-embedded date-time into a true \DateTime -# . -# This example creates a converter proc, then stores it: -# strip_converter = proc {|field| field.strip } -# CSV::Converters[:strip] = strip_converter -# Then the parsing method call can refer to the converter -# by its name, :strip: -# string = " foo , 0 \n bar , 1 \n baz , 2 \n" -# array = CSV.parse(string, converters: :strip) -# array # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] -# -# The storage structure for header converters is the \Hash CSV::HeaderConverters, -# which works in the same way. -# It also has built-in converter procs: -# - :downcase: Downcases each header. -# - :symbol: Converts each header to a \Symbol. -# -# There is no such storage structure for write headers. -# -# In order for the parsing methods to access stored converters in non-main-Ractors, the -# storage structure must be made shareable first. -# Therefore, Ractor.make_shareable(CSV::Converters) and -# Ractor.make_shareable(CSV::HeaderConverters) must be called before the creation -# of Ractors that use the converters stored in these structures. (Since making the storage -# structures shareable involves freezing them, any custom converters that are to be used -# must be added first.) -# -# ===== Converter Lists -# -# A _converter_ _list_ is an \Array that may include any assortment of: -# - Converter procs. -# - Names of stored converters. -# - Nested converter lists. -# -# Examples: -# numeric_converters = [:integer, :float] -# date_converters = [:date, :date_time] -# [numeric_converters, strip_converter] -# [strip_converter, date_converters, :float] -# -# Like a converter proc, a converter list may be named and stored in either -# \CSV::Converters or CSV::HeaderConverters: -# CSV::Converters[:custom] = [strip_converter, date_converters, :float] -# CSV::HeaderConverters[:custom] = [:downcase, :symbol] -# -# There are two built-in converter lists: -# CSV::Converters[:numeric] # => [:integer, :float] -# CSV::Converters[:all] # => [:date_time, :numeric] -# -# ==== Field \Converters -# -# With no conversion, all parsed fields in all rows become Strings: -# string = "foo,0\nbar,1\nbaz,2\n" -# ary = CSV.parse(string) -# ary # => # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] -# -# When you specify a field converter, each parsed field is passed to the converter; -# its return value becomes the stored value for the field. -# A converter might, for example, convert an integer embedded in a \String -# into a true \Integer. -# (In fact, that's what built-in field converter +:integer+ does.) -# -# There are three ways to use field \converters. -# -# - Using option {converters}[#class-CSV-label-Option+converters] with a parsing method: -# ary = CSV.parse(string, converters: :integer) -# ary # => [0, 1, 2] # => [["foo", 0], ["bar", 1], ["baz", 2]] -# - Using option {converters}[#class-CSV-label-Option+converters] with a new \CSV instance: -# csv = CSV.new(string, converters: :integer) -# # Field converters in effect: -# csv.converters # => [:integer] -# csv.read # => [["foo", 0], ["bar", 1], ["baz", 2]] -# - Using method #convert to add a field converter to a \CSV instance: -# csv = CSV.new(string) -# # Add a converter. -# csv.convert(:integer) -# csv.converters # => [:integer] -# csv.read # => [["foo", 0], ["bar", 1], ["baz", 2]] -# -# Installing a field converter does not affect already-read rows: -# csv = CSV.new(string) -# csv.shift # => ["foo", "0"] -# # Add a converter. -# csv.convert(:integer) -# csv.converters # => [:integer] -# csv.read # => [["bar", 1], ["baz", 2]] -# -# There are additional built-in \converters, and custom \converters are also supported. -# -# ===== Built-In Field \Converters -# -# The built-in field converters are in \Hash CSV::Converters: -# - Each key is a field converter name. -# - Each value is one of: -# - A \Proc field converter. -# - An \Array of field converter names. -# -# Display: -# CSV::Converters.each_pair do |name, value| -# if value.kind_of?(Proc) -# p [name, value.class] -# else -# p [name, value] -# end -# end -# Output: -# [:integer, Proc] -# [:float, Proc] -# [:numeric, [:integer, :float]] -# [:date, Proc] -# [:date_time, Proc] -# [:all, [:date_time, :numeric]] -# -# Each of these converters transcodes values to UTF-8 before attempting conversion. -# If a value cannot be transcoded to UTF-8 the conversion will -# fail and the value will remain unconverted. -# -# Converter +:integer+ converts each field that Integer() accepts: -# data = '0,1,2,x' -# # Without the converter -# csv = CSV.parse_line(data) -# csv # => ["0", "1", "2", "x"] -# # With the converter -# csv = CSV.parse_line(data, converters: :integer) -# csv # => [0, 1, 2, "x"] -# -# Converter +:float+ converts each field that Float() accepts: -# data = '1.0,3.14159,x' -# # Without the converter -# csv = CSV.parse_line(data) -# csv # => ["1.0", "3.14159", "x"] -# # With the converter -# csv = CSV.parse_line(data, converters: :float) -# csv # => [1.0, 3.14159, "x"] -# -# Converter +:numeric+ converts with both +:integer+ and +:float+.. -# -# Converter +:date+ converts each field that Date::parse accepts: -# data = '2001-02-03,x' -# # Without the converter -# csv = CSV.parse_line(data) -# csv # => ["2001-02-03", "x"] -# # With the converter -# csv = CSV.parse_line(data, converters: :date) -# csv # => [#, "x"] -# -# Converter +:date_time+ converts each field that DateTime::parse accepts: -# data = '2020-05-07T14:59:00-05:00,x' -# # Without the converter -# csv = CSV.parse_line(data) -# csv # => ["2020-05-07T14:59:00-05:00", "x"] -# # With the converter -# csv = CSV.parse_line(data, converters: :date_time) -# csv # => [#, "x"] -# -# Converter +:numeric+ converts with both +:date_time+ and +:numeric+.. -# -# As seen above, method #convert adds \converters to a \CSV instance, -# and method #converters returns an \Array of the \converters in effect: -# csv = CSV.new('0,1,2') -# csv.converters # => [] -# csv.convert(:integer) -# csv.converters # => [:integer] -# csv.convert(:date) -# csv.converters # => [:integer, :date] -# -# ===== Custom Field \Converters -# -# You can define a custom field converter: -# strip_converter = proc {|field| field.strip } -# string = " foo , 0 \n bar , 1 \n baz , 2 \n" -# array = CSV.parse(string, converters: strip_converter) -# array # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] -# You can register the converter in \Converters \Hash, -# which allows you to refer to it by name: -# CSV::Converters[:strip] = strip_converter -# string = " foo , 0 \n bar , 1 \n baz , 2 \n" -# array = CSV.parse(string, converters: :strip) -# array # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] -# -# ==== Header \Converters -# -# Header converters operate only on headers (and not on other rows). -# -# There are three ways to use header \converters; -# these examples use built-in header converter +:downcase+, -# which downcases each parsed header. -# -# - Option +header_converters+ with a singleton parsing method: -# string = "Name,Count\nFoo,0\n,Bar,1\nBaz,2" -# tbl = CSV.parse(string, headers: true, header_converters: :downcase) -# tbl.class # => CSV::Table -# tbl.headers # => ["name", "count"] -# -# - Option +header_converters+ with a new \CSV instance: -# csv = CSV.new(string, header_converters: :downcase) -# # Header converters in effect: -# csv.header_converters # => [:downcase] -# tbl = CSV.parse(string, headers: true) -# tbl.headers # => ["Name", "Count"] -# -# - Method #header_convert adds a header converter to a \CSV instance: -# csv = CSV.new(string) -# # Add a header converter. -# csv.header_convert(:downcase) -# csv.header_converters # => [:downcase] -# tbl = CSV.parse(string, headers: true) -# tbl.headers # => ["Name", "Count"] -# -# ===== Built-In Header \Converters -# -# The built-in header \converters are in \Hash CSV::HeaderConverters. -# The keys there are the names of the \converters: -# CSV::HeaderConverters.keys # => [:downcase, :symbol] -# -# Converter +:downcase+ converts each header by downcasing it: -# string = "Name,Count\nFoo,0\n,Bar,1\nBaz,2" -# tbl = CSV.parse(string, headers: true, header_converters: :downcase) -# tbl.class # => CSV::Table -# tbl.headers # => ["name", "count"] -# -# Converter +:symbol+ converts each header by making it into a \Symbol: -# string = "Name,Count\nFoo,0\n,Bar,1\nBaz,2" -# tbl = CSV.parse(string, headers: true, header_converters: :symbol) -# tbl.headers # => [:name, :count] -# Details: -# - Strips leading and trailing whitespace. -# - Downcases the header. -# - Replaces embedded spaces with underscores. -# - Removes non-word characters. -# - Makes the string into a \Symbol. -# -# ===== Custom Header \Converters -# -# You can define a custom header converter: -# upcase_converter = proc {|header| header.upcase } -# string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" -# table = CSV.parse(string, headers: true, header_converters: upcase_converter) -# table # => # -# table.headers # => ["NAME", "VALUE"] -# You can register the converter in \HeaderConverters \Hash, -# which allows you to refer to it by name: -# CSV::HeaderConverters[:upcase] = upcase_converter -# table = CSV.parse(string, headers: true, header_converters: :upcase) -# table # => # -# table.headers # => ["NAME", "VALUE"] -# -# ===== Write \Converters -# -# When you specify a write converter for generating \CSV, -# each field to be written is passed to the converter; -# its return value becomes the new value for the field. -# A converter might, for example, strip whitespace from a field. -# -# Using no write converter (all fields unmodified): -# output_string = CSV.generate do |csv| -# csv << [' foo ', 0] -# csv << [' bar ', 1] -# csv << [' baz ', 2] -# end -# output_string # => " foo ,0\n bar ,1\n baz ,2\n" -# Using option +write_converters+ with two custom write converters: -# strip_converter = proc {|field| field.respond_to?(:strip) ? field.strip : field } -# upcase_converter = proc {|field| field.respond_to?(:upcase) ? field.upcase : field } -# write_converters = [strip_converter, upcase_converter] -# output_string = CSV.generate(write_converters: write_converters) do |csv| -# csv << [' foo ', 0] -# csv << [' bar ', 1] -# csv << [' baz ', 2] -# end -# output_string # => "FOO,0\nBAR,1\nBAZ,2\n" -# -# === Character Encodings (M17n or Multilingualization) -# -# This new CSV parser is m17n savvy. The parser works in the Encoding of the IO -# or String object being read from or written to. Your data is never transcoded -# (unless you ask Ruby to transcode it for you) and will literally be parsed in -# the Encoding it is in. Thus CSV will return Arrays or Rows of Strings in the -# Encoding of your data. This is accomplished by transcoding the parser itself -# into your Encoding. -# -# Some transcoding must take place, of course, to accomplish this multiencoding -# support. For example, :col_sep, :row_sep, and -# :quote_char must be transcoded to match your data. Hopefully this -# makes the entire process feel transparent, since CSV's defaults should just -# magically work for your data. However, you can set these values manually in -# the target Encoding to avoid the translation. -# -# It's also important to note that while all of CSV's core parser is now -# Encoding agnostic, some features are not. For example, the built-in -# converters will try to transcode data to UTF-8 before making conversions. -# Again, you can provide custom converters that are aware of your Encodings to -# avoid this translation. It's just too hard for me to support native -# conversions in all of Ruby's Encodings. -# -# Anyway, the practical side of this is simple: make sure IO and String objects -# passed into CSV have the proper Encoding set and everything should just work. -# CSV methods that allow you to open IO objects (CSV::foreach(), CSV::open(), -# CSV::read(), and CSV::readlines()) do allow you to specify the Encoding. -# -# One minor exception comes when generating CSV into a String with an Encoding -# that is not ASCII compatible. There's no existing data for CSV to use to -# prepare itself and thus you will probably need to manually specify the desired -# Encoding for most of those cases. It will try to guess using the fields in a -# row of output though, when using CSV::generate_line() or Array#to_csv(). -# -# I try to point out any other Encoding issues in the documentation of methods -# as they come up. -# -# This has been tested to the best of my ability with all non-"dummy" Encodings -# Ruby ships with. However, it is brave new code and may have some bugs. -# Please feel free to {report}[mailto:james@grayproductions.net] any issues you -# find with it. -# -class CSV - - # The error thrown when the parser encounters illegal CSV formatting. - class MalformedCSVError < RuntimeError - attr_reader :line_number - alias_method :lineno, :line_number - def initialize(message, line_number) - @line_number = line_number - super("#{message} in line #{line_number}.") - end - end - - # - # A FieldInfo Struct contains details about a field's position in the data - # source it was read from. CSV will pass this Struct to some blocks that make - # decisions based on field structure. See CSV.convert_fields() for an - # example. - # - # index:: The zero-based index of the field in its row. - # line:: The line of the data source this row is from. - # header:: The header for the column, when available. - # quoted?:: True or false, whether the original value is quoted or not. - # - FieldInfo = Struct.new(:index, :line, :header, :quoted?) - - # A Regexp used to find and convert some common Date formats. - DateMatcher = / \A(?: (\w+,?\s+)?\w+\s+\d{1,2},?\s+\d{2,4} | - \d{4}-\d{2}-\d{2} )\z /x - # A Regexp used to find and convert some common DateTime formats. - DateTimeMatcher = - / \A(?: (\w+,?\s+)?\w+\s+\d{1,2}\s+\d{1,2}:\d{1,2}:\d{1,2},?\s+\d{2,4} | - # ISO-8601 and RFC-3339 (space instead of T) recognized by DateTime.parse - \d{4}-\d{2}-\d{2} - (?:[T\s]\d{2}:\d{2}(?::\d{2}(?:\.\d+)?(?:[+-]\d{2}(?::\d{2})|Z)?)?)? - )\z /x - - # The encoding used by all converters. - ConverterEncoding = Encoding.find("UTF-8") - - # A \Hash containing the names and \Procs for the built-in field converters. - # See {Built-In Field Converters}[#class-CSV-label-Built-In+Field+Converters]. - # - # This \Hash is intentionally left unfrozen, and may be extended with - # custom field converters. - # See {Custom Field Converters}[#class-CSV-label-Custom+Field+Converters]. - Converters = { - integer: lambda { |f| - Integer(f.encode(ConverterEncoding)) rescue f - }, - float: lambda { |f| - Float(f.encode(ConverterEncoding)) rescue f - }, - numeric: [:integer, :float], - date: lambda { |f| - begin - e = f.encode(ConverterEncoding) - e.match?(DateMatcher) ? Date.parse(e) : f - rescue # encoding conversion or date parse errors - f - end - }, - date_time: lambda { |f| - begin - e = f.encode(ConverterEncoding) - e.match?(DateTimeMatcher) ? DateTime.parse(e) : f - rescue # encoding conversion or date parse errors - f - end - }, - all: [:date_time, :numeric], - } - - # A \Hash containing the names and \Procs for the built-in header converters. - # See {Built-In Header Converters}[#class-CSV-label-Built-In+Header+Converters]. - # - # This \Hash is intentionally left unfrozen, and may be extended with - # custom field converters. - # See {Custom Header Converters}[#class-CSV-label-Custom+Header+Converters]. - HeaderConverters = { - downcase: lambda { |h| h.encode(ConverterEncoding).downcase }, - symbol: lambda { |h| - h.encode(ConverterEncoding).downcase.gsub(/[^\s\w]+/, "").strip. - gsub(/\s+/, "_").to_sym - }, - symbol_raw: lambda { |h| h.encode(ConverterEncoding).to_sym } - } - - # Default values for method options. - DEFAULT_OPTIONS = { - # For both parsing and generating. - col_sep: ",", - row_sep: :auto, - quote_char: '"', - # For parsing. - field_size_limit: nil, - max_field_size: nil, - converters: nil, - unconverted_fields: nil, - headers: false, - return_headers: false, - header_converters: nil, - skip_blanks: false, - skip_lines: nil, - liberal_parsing: false, - nil_value: nil, - empty_value: "", - strip: false, - # For generating. - write_headers: nil, - quote_empty: true, - force_quotes: false, - write_converters: nil, - write_nil_value: nil, - write_empty_value: "", - }.freeze - - class << self - # :call-seq: - # instance(string, **options) - # instance(io = $stdout, **options) - # instance(string, **options) {|csv| ... } - # instance(io = $stdout, **options) {|csv| ... } - # - # Creates or retrieves cached \CSV objects. - # For arguments and options, see CSV.new. - # - # This API is not Ractor-safe. - # - # --- - # - # With no block given, returns a \CSV object. - # - # The first call to +instance+ creates and caches a \CSV object: - # s0 = 's0' - # csv0 = CSV.instance(s0) - # csv0.class # => CSV - # - # Subsequent calls to +instance+ with that _same_ +string+ or +io+ - # retrieve that same cached object: - # csv1 = CSV.instance(s0) - # csv1.class # => CSV - # csv1.equal?(csv0) # => true # Same CSV object - # - # A subsequent call to +instance+ with a _different_ +string+ or +io+ - # creates and caches a _different_ \CSV object. - # s1 = 's1' - # csv2 = CSV.instance(s1) - # csv2.equal?(csv0) # => false # Different CSV object - # - # All the cached objects remains available: - # csv3 = CSV.instance(s0) - # csv3.equal?(csv0) # true # Same CSV object - # csv4 = CSV.instance(s1) - # csv4.equal?(csv2) # true # Same CSV object - # - # --- - # - # When a block is given, calls the block with the created or retrieved - # \CSV object; returns the block's return value: - # CSV.instance(s0) {|csv| :foo } # => :foo - def instance(data = $stdout, **options) - # create a _signature_ for this method call, data object and options - sig = [data.object_id] + - options.values_at(*DEFAULT_OPTIONS.keys) - - # fetch or create the instance for this signature - @@instances ||= Hash.new - instance = (@@instances[sig] ||= new(data, **options)) - - if block_given? - yield instance # run block, if given, returning result - else - instance # or return the instance - end - end - - # :call-seq: - # filter(in_string_or_io, **options) {|row| ... } -> array_of_arrays or csv_table - # filter(in_string_or_io, out_string_or_io, **options) {|row| ... } -> array_of_arrays or csv_table - # filter(**options) {|row| ... } -> array_of_arrays or csv_table - # - # - Parses \CSV from a source (\String, \IO stream, or ARGF). - # - Calls the given block with each parsed row: - # - Without headers, each row is an \Array. - # - With headers, each row is a CSV::Row. - # - Generates \CSV to an output (\String, \IO stream, or STDOUT). - # - Returns the parsed source: - # - Without headers, an \Array of \Arrays. - # - With headers, a CSV::Table. - # - # When +in_string_or_io+ is given, but not +out_string_or_io+, - # parses from the given +in_string_or_io+ - # and generates to STDOUT. - # - # \String input without headers: - # - # in_string = "foo,0\nbar,1\nbaz,2" - # CSV.filter(in_string) do |row| - # row[0].upcase! - # row[1] = - row[1].to_i - # end # => [["FOO", 0], ["BAR", -1], ["BAZ", -2]] - # - # Output (to STDOUT): - # - # FOO,0 - # BAR,-1 - # BAZ,-2 - # - # \String input with headers: - # - # in_string = "Name,Value\nfoo,0\nbar,1\nbaz,2" - # CSV.filter(in_string, headers: true) do |row| - # row[0].upcase! - # row[1] = - row[1].to_i - # end # => # - # - # Output (to STDOUT): - # - # Name,Value - # FOO,0 - # BAR,-1 - # BAZ,-2 - # - # \IO stream input without headers: - # - # File.write('t.csv', "foo,0\nbar,1\nbaz,2") - # File.open('t.csv') do |in_io| - # CSV.filter(in_io) do |row| - # row[0].upcase! - # row[1] = - row[1].to_i - # end - # end # => [["FOO", 0], ["BAR", -1], ["BAZ", -2]] - # - # Output (to STDOUT): - # - # FOO,0 - # BAR,-1 - # BAZ,-2 - # - # \IO stream input with headers: - # - # File.write('t.csv', "Name,Value\nfoo,0\nbar,1\nbaz,2") - # File.open('t.csv') do |in_io| - # CSV.filter(in_io, headers: true) do |row| - # row[0].upcase! - # row[1] = - row[1].to_i - # end - # end # => # - # - # Output (to STDOUT): - # - # Name,Value - # FOO,0 - # BAR,-1 - # BAZ,-2 - # - # When both +in_string_or_io+ and +out_string_or_io+ are given, - # parses from +in_string_or_io+ and generates to +out_string_or_io+. - # - # \String output without headers: - # - # in_string = "foo,0\nbar,1\nbaz,2" - # out_string = '' - # CSV.filter(in_string, out_string) do |row| - # row[0].upcase! - # row[1] = - row[1].to_i - # end # => [["FOO", 0], ["BAR", -1], ["BAZ", -2]] - # out_string # => "FOO,0\nBAR,-1\nBAZ,-2\n" - # - # \String output with headers: - # - # in_string = "Name,Value\nfoo,0\nbar,1\nbaz,2" - # out_string = '' - # CSV.filter(in_string, out_string, headers: true) do |row| - # row[0].upcase! - # row[1] = - row[1].to_i - # end # => # - # out_string # => "Name,Value\nFOO,0\nBAR,-1\nBAZ,-2\n" - # - # \IO stream output without headers: - # - # in_string = "foo,0\nbar,1\nbaz,2" - # File.open('t.csv', 'w') do |out_io| - # CSV.filter(in_string, out_io) do |row| - # row[0].upcase! - # row[1] = - row[1].to_i - # end - # end # => [["FOO", 0], ["BAR", -1], ["BAZ", -2]] - # File.read('t.csv') # => "FOO,0\nBAR,-1\nBAZ,-2\n" - # - # \IO stream output with headers: - # - # in_string = "Name,Value\nfoo,0\nbar,1\nbaz,2" - # File.open('t.csv', 'w') do |out_io| - # CSV.filter(in_string, out_io, headers: true) do |row| - # row[0].upcase! - # row[1] = - row[1].to_i - # end - # end # => # - # File.read('t.csv') # => "Name,Value\nFOO,0\nBAR,-1\nBAZ,-2\n" - # - # When neither +in_string_or_io+ nor +out_string_or_io+ given, - # parses from {ARGF}[rdoc-ref:ARGF] - # and generates to STDOUT. - # - # Without headers: - # - # # Put Ruby code into a file. - # ruby = <<-EOT - # require 'csv' - # CSV.filter do |row| - # row[0].upcase! - # row[1] = - row[1].to_i - # end - # EOT - # File.write('t.rb', ruby) - # # Put some CSV into a file. - # File.write('t.csv', "foo,0\nbar,1\nbaz,2") - # # Run the Ruby code with CSV filename as argument. - # system(Gem.ruby, "t.rb", "t.csv") - # - # Output (to STDOUT): - # - # FOO,0 - # BAR,-1 - # BAZ,-2 - # - # With headers: - # - # # Put Ruby code into a file. - # ruby = <<-EOT - # require 'csv' - # CSV.filter(headers: true) do |row| - # row[0].upcase! - # row[1] = - row[1].to_i - # end - # EOT - # File.write('t.rb', ruby) - # # Put some CSV into a file. - # File.write('t.csv', "Name,Value\nfoo,0\nbar,1\nbaz,2") - # # Run the Ruby code with CSV filename as argument. - # system(Gem.ruby, "t.rb", "t.csv") - # - # Output (to STDOUT): - # - # Name,Value - # FOO,0 - # BAR,-1 - # BAZ,-2 - # - # Arguments: - # - # * Argument +in_string_or_io+ must be a \String or an \IO stream. - # * Argument +out_string_or_io+ must be a \String or an \IO stream. - # * Arguments **options must be keyword options. - # See {Options for Parsing}[#class-CSV-label-Options+for+Parsing]. - def filter(input=nil, output=nil, **options) - # parse options for input, output, or both - in_options, out_options = Hash.new, {row_sep: InputRecordSeparator.value} - options.each do |key, value| - case key - when /\Ain(?:put)?_(.+)\Z/ - in_options[$1.to_sym] = value - when /\Aout(?:put)?_(.+)\Z/ - out_options[$1.to_sym] = value - else - in_options[key] = value - out_options[key] = value - end - end - - # build input and output wrappers - input = new(input || ARGF, **in_options) - output = new(output || $stdout, **out_options) - - # process headers - need_manual_header_output = - (in_options[:headers] and - out_options[:headers] == true and - out_options[:write_headers]) - if need_manual_header_output - first_row = input.shift - if first_row - if first_row.is_a?(Row) - headers = first_row.headers - yield headers - output << headers - end - yield first_row - output << first_row - end - end - - # read, yield, write - input.each do |row| - yield row - output << row - end - end - - # - # :call-seq: - # foreach(path_or_io, mode='r', **options) {|row| ... ) - # foreach(path_or_io, mode='r', **options) -> new_enumerator - # - # Calls the block with each row read from source +path_or_io+. - # - # \Path input without headers: - # - # string = "foo,0\nbar,1\nbaz,2\n" - # in_path = 't.csv' - # File.write(in_path, string) - # CSV.foreach(in_path) {|row| p row } - # - # Output: - # - # ["foo", "0"] - # ["bar", "1"] - # ["baz", "2"] - # - # \Path input with headers: - # - # string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # in_path = 't.csv' - # File.write(in_path, string) - # CSV.foreach(in_path, headers: true) {|row| p row } - # - # Output: - # - # - # - # - # - # \IO stream input without headers: - # - # string = "foo,0\nbar,1\nbaz,2\n" - # path = 't.csv' - # File.write(path, string) - # File.open('t.csv') do |in_io| - # CSV.foreach(in_io) {|row| p row } - # end - # - # Output: - # - # ["foo", "0"] - # ["bar", "1"] - # ["baz", "2"] - # - # \IO stream input with headers: - # - # string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # path = 't.csv' - # File.write(path, string) - # File.open('t.csv') do |in_io| - # CSV.foreach(in_io, headers: true) {|row| p row } - # end - # - # Output: - # - # - # - # - # - # With no block given, returns an \Enumerator: - # - # string = "foo,0\nbar,1\nbaz,2\n" - # path = 't.csv' - # File.write(path, string) - # CSV.foreach(path) # => # - # - # Arguments: - # * Argument +path_or_io+ must be a file path or an \IO stream. - # * Argument +mode+, if given, must be a \File mode - # See {Open Mode}[https://ruby-doc.org/core/IO.html#method-c-new-label-Open+Mode]. - # * Arguments **options must be keyword options. - # See {Options for Parsing}[#class-CSV-label-Options+for+Parsing]. - # * This method optionally accepts an additional :encoding option - # that you can use to specify the Encoding of the data read from +path+ or +io+. - # You must provide this unless your data is in the encoding - # given by Encoding::default_external. - # Parsing will use this to determine how to parse the data. - # You may provide a second Encoding to - # have the data transcoded as it is read. For example, - # encoding: 'UTF-32BE:UTF-8' - # would read +UTF-32BE+ data from the file - # but transcode it to +UTF-8+ before parsing. - def foreach(path, mode="r", **options, &block) - return to_enum(__method__, path, mode, **options) unless block_given? - open(path, mode, **options) do |csv| - csv.each(&block) - end - end - - # - # :call-seq: - # generate(csv_string, **options) {|csv| ... } - # generate(**options) {|csv| ... } - # - # * Argument +csv_string+, if given, must be a \String object; - # defaults to a new empty \String. - # * Arguments +options+, if given, should be generating options. - # See {Options for Generating}[#class-CSV-label-Options+for+Generating]. - # - # --- - # - # Creates a new \CSV object via CSV.new(csv_string, **options); - # calls the block with the \CSV object, which the block may modify; - # returns the \String generated from the \CSV object. - # - # Note that a passed \String *is* modified by this method. - # Pass csv_string.dup if the \String must be preserved. - # - # This method has one additional option: :encoding, - # which sets the base Encoding for the output if no no +str+ is specified. - # CSV needs this hint if you plan to output non-ASCII compatible data. - # - # --- - # - # Add lines: - # input_string = "foo,0\nbar,1\nbaz,2\n" - # output_string = CSV.generate(input_string) do |csv| - # csv << ['bat', 3] - # csv << ['bam', 4] - # end - # output_string # => "foo,0\nbar,1\nbaz,2\nbat,3\nbam,4\n" - # input_string # => "foo,0\nbar,1\nbaz,2\nbat,3\nbam,4\n" - # output_string.equal?(input_string) # => true # Same string, modified - # - # Add lines into new string, preserving old string: - # input_string = "foo,0\nbar,1\nbaz,2\n" - # output_string = CSV.generate(input_string.dup) do |csv| - # csv << ['bat', 3] - # csv << ['bam', 4] - # end - # output_string # => "foo,0\nbar,1\nbaz,2\nbat,3\nbam,4\n" - # input_string # => "foo,0\nbar,1\nbaz,2\n" - # output_string.equal?(input_string) # => false # Different strings - # - # Create lines from nothing: - # output_string = CSV.generate do |csv| - # csv << ['foo', 0] - # csv << ['bar', 1] - # csv << ['baz', 2] - # end - # output_string # => "foo,0\nbar,1\nbaz,2\n" - # - # --- - # - # Raises an exception if +csv_string+ is not a \String object: - # # Raises TypeError (no implicit conversion of Integer into String) - # CSV.generate(0) - # - def generate(str=nil, **options) - encoding = options[:encoding] - # add a default empty String, if none was given - if str - str = StringIO.new(str) - str.seek(0, IO::SEEK_END) - str.set_encoding(encoding) if encoding - else - str = +"" - str.force_encoding(encoding) if encoding - end - csv = new(str, **options) # wrap - yield csv # yield for appending - csv.string # return final String - end - - # :call-seq: - # CSV.generate_line(ary) - # CSV.generate_line(ary, **options) - # - # Returns the \String created by generating \CSV from +ary+ - # using the specified +options+. - # - # Argument +ary+ must be an \Array. - # - # Special options: - # * Option :row_sep defaults to "\n"> on Ruby 3.0 or later - # and $INPUT_RECORD_SEPARATOR ($/) otherwise.: - # $INPUT_RECORD_SEPARATOR # => "\n" - # * This method accepts an additional option, :encoding, which sets the base - # Encoding for the output. This method will try to guess your Encoding from - # the first non-+nil+ field in +row+, if possible, but you may need to use - # this parameter as a backup plan. - # - # For other +options+, - # see {Options for Generating}[#class-CSV-label-Options+for+Generating]. - # - # --- - # - # Returns the \String generated from an \Array: - # CSV.generate_line(['foo', '0']) # => "foo,0\n" - # - # --- - # - # Raises an exception if +ary+ is not an \Array: - # # Raises NoMethodError (undefined method `find' for :foo:Symbol) - # CSV.generate_line(:foo) - # - def generate_line(row, **options) - options = {row_sep: InputRecordSeparator.value}.merge(options) - str = +"" - if options[:encoding] - str.force_encoding(options[:encoding]) - else - fallback_encoding = nil - output_encoding = nil - row.each do |field| - next unless field.is_a?(String) - fallback_encoding ||= field.encoding - next if field.ascii_only? - output_encoding = field.encoding - break - end - output_encoding ||= fallback_encoding - if output_encoding - str.force_encoding(output_encoding) - end - end - (new(str, **options) << row).string - end - - # :call-seq: - # CSV.generate_lines(rows) - # CSV.generate_lines(rows, **options) - # - # Returns the \String created by generating \CSV from - # using the specified +options+. - # - # Argument +rows+ must be an \Array of row. Row is \Array of \String or \CSV::Row. - # - # Special options: - # * Option :row_sep defaults to "\n" on Ruby 3.0 or later - # and $INPUT_RECORD_SEPARATOR ($/) otherwise.: - # $INPUT_RECORD_SEPARATOR # => "\n" - # * This method accepts an additional option, :encoding, which sets the base - # Encoding for the output. This method will try to guess your Encoding from - # the first non-+nil+ field in +row+, if possible, but you may need to use - # this parameter as a backup plan. - # - # For other +options+, - # see {Options for Generating}[#class-CSV-label-Options+for+Generating]. - # - # --- - # - # Returns the \String generated from an - # CSV.generate_lines([['foo', '0'], ['bar', '1'], ['baz', '2']]) # => "foo,0\nbar,1\nbaz,2\n" - # - # --- - # - # Raises an exception - # # Raises NoMethodError (undefined method `each' for :foo:Symbol) - # CSV.generate_lines(:foo) - # - def generate_lines(rows, **options) - self.generate(**options) do |csv| - rows.each do |row| - csv << row - end - end - end - - # - # :call-seq: - # open(file_path, mode = "rb", **options ) -> new_csv - # open(io, mode = "rb", **options ) -> new_csv - # open(file_path, mode = "rb", **options ) { |csv| ... } -> object - # open(io, mode = "rb", **options ) { |csv| ... } -> object - # - # possible options elements: - # keyword form: - # :invalid => nil # raise error on invalid byte sequence (default) - # :invalid => :replace # replace invalid byte sequence - # :undef => :replace # replace undefined conversion - # :replace => string # replacement string ("?" or "\uFFFD" if not specified) - # - # * Argument +path+, if given, must be the path to a file. - # :include: ../doc/csv/arguments/io.rdoc - # * Argument +mode+, if given, must be a \File mode - # See {Open Mode}[IO.html#method-c-new-label-Open+Mode]. - # * Arguments **options must be keyword options. - # See {Options for Generating}[#class-CSV-label-Options+for+Generating]. - # * This method optionally accepts an additional :encoding option - # that you can use to specify the Encoding of the data read from +path+ or +io+. - # You must provide this unless your data is in the encoding - # given by Encoding::default_external. - # Parsing will use this to determine how to parse the data. - # You may provide a second Encoding to - # have the data transcoded as it is read. For example, - # encoding: 'UTF-32BE:UTF-8' - # would read +UTF-32BE+ data from the file - # but transcode it to +UTF-8+ before parsing. - # - # --- - # - # These examples assume prior execution of: - # string = "foo,0\nbar,1\nbaz,2\n" - # path = 't.csv' - # File.write(path, string) - # - # --- - # - # With no block given, returns a new \CSV object. - # - # Create a \CSV object using a file path: - # csv = CSV.open(path) - # csv # => # - # - # Create a \CSV object using an open \File: - # csv = CSV.open(File.open(path)) - # csv # => # - # - # --- - # - # With a block given, calls the block with the created \CSV object; - # returns the block's return value: - # - # Using a file path: - # csv = CSV.open(path) {|csv| p csv} - # csv # => # - # Output: - # # - # - # Using an open \File: - # csv = CSV.open(File.open(path)) {|csv| p csv} - # csv # => # - # Output: - # # - # - # --- - # - # Raises an exception if the argument is not a \String object or \IO object: - # # Raises TypeError (no implicit conversion of Symbol into String) - # CSV.open(:foo) - def open(filename, mode="r", **options) - # wrap a File opened with the remaining +args+ with no newline - # decorator - file_opts = options.dup - unless file_opts.key?(:newline) - file_opts[:universal_newline] ||= false - end - options.delete(:invalid) - options.delete(:undef) - options.delete(:replace) - options.delete_if {|k, _| /newline\z/.match?(k)} - - begin - f = File.open(filename, mode, **file_opts) - rescue ArgumentError => e - raise unless /needs binmode/.match?(e.message) and mode == "r" - mode = "rb" - file_opts = {encoding: Encoding.default_external}.merge(file_opts) - retry - end - begin - csv = new(f, **options) - rescue Exception - f.close - raise - end - - # handle blocks like Ruby's open(), not like the CSV library - if block_given? - begin - yield csv - ensure - csv.close - end - else - csv - end - end - - # - # :call-seq: - # parse(string) -> array_of_arrays - # parse(io) -> array_of_arrays - # parse(string, headers: ..., **options) -> csv_table - # parse(io, headers: ..., **options) -> csv_table - # parse(string, **options) {|row| ... } - # parse(io, **options) {|row| ... } - # - # Parses +string+ or +io+ using the specified +options+. - # - # - Argument +string+ should be a \String object; - # it will be put into a new StringIO object positioned at the beginning. - # :include: ../doc/csv/arguments/io.rdoc - # - Argument +options+: see {Options for Parsing}[#class-CSV-label-Options+for+Parsing] - # - # ====== Without Option +headers+ - # - # Without {option +headers+}[#class-CSV-label-Option+headers] case. - # - # These examples assume prior execution of: - # string = "foo,0\nbar,1\nbaz,2\n" - # path = 't.csv' - # File.write(path, string) - # - # --- - # - # With no block given, returns an \Array of Arrays formed from the source. - # - # Parse a \String: - # a_of_a = CSV.parse(string) - # a_of_a # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] - # - # Parse an open \File: - # a_of_a = File.open(path) do |file| - # CSV.parse(file) - # end - # a_of_a # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] - # - # --- - # - # With a block given, calls the block with each parsed row: - # - # Parse a \String: - # CSV.parse(string) {|row| p row } - # - # Output: - # ["foo", "0"] - # ["bar", "1"] - # ["baz", "2"] - # - # Parse an open \File: - # File.open(path) do |file| - # CSV.parse(file) {|row| p row } - # end - # - # Output: - # ["foo", "0"] - # ["bar", "1"] - # ["baz", "2"] - # - # ====== With Option +headers+ - # - # With {option +headers+}[#class-CSV-label-Option+headers] case. - # - # These examples assume prior execution of: - # string = "Name,Count\nfoo,0\nbar,1\nbaz,2\n" - # path = 't.csv' - # File.write(path, string) - # - # --- - # - # With no block given, returns a CSV::Table object formed from the source. - # - # Parse a \String: - # csv_table = CSV.parse(string, headers: ['Name', 'Count']) - # csv_table # => # - # - # Parse an open \File: - # csv_table = File.open(path) do |file| - # CSV.parse(file, headers: ['Name', 'Count']) - # end - # csv_table # => # - # - # --- - # - # With a block given, calls the block with each parsed row, - # which has been formed into a CSV::Row object: - # - # Parse a \String: - # CSV.parse(string, headers: ['Name', 'Count']) {|row| p row } - # - # Output: - # # - # # - # # - # - # Parse an open \File: - # File.open(path) do |file| - # CSV.parse(file, headers: ['Name', 'Count']) {|row| p row } - # end - # - # Output: - # # - # # - # # - # - # --- - # - # Raises an exception if the argument is not a \String object or \IO object: - # # Raises NoMethodError (undefined method `close' for :foo:Symbol) - # CSV.parse(:foo) - def parse(str, **options, &block) - csv = new(str, **options) - - return csv.each(&block) if block_given? - - # slurp contents, if no block is given - begin - csv.read - ensure - csv.close - end - end - - # :call-seq: - # CSV.parse_line(string) -> new_array or nil - # CSV.parse_line(io) -> new_array or nil - # CSV.parse_line(string, **options) -> new_array or nil - # CSV.parse_line(io, **options) -> new_array or nil - # CSV.parse_line(string, headers: true, **options) -> csv_row or nil - # CSV.parse_line(io, headers: true, **options) -> csv_row or nil - # - # Returns the data created by parsing the first line of +string+ or +io+ - # using the specified +options+. - # - # - Argument +string+ should be a \String object; - # it will be put into a new StringIO object positioned at the beginning. - # :include: ../doc/csv/arguments/io.rdoc - # - Argument +options+: see {Options for Parsing}[#class-CSV-label-Options+for+Parsing] - # - # ====== Without Option +headers+ - # - # Without option +headers+, returns the first row as a new \Array. - # - # These examples assume prior execution of: - # string = "foo,0\nbar,1\nbaz,2\n" - # path = 't.csv' - # File.write(path, string) - # - # Parse the first line from a \String object: - # CSV.parse_line(string) # => ["foo", "0"] - # - # Parse the first line from a File object: - # File.open(path) do |file| - # CSV.parse_line(file) # => ["foo", "0"] - # end # => ["foo", "0"] - # - # Returns +nil+ if the argument is an empty \String: - # CSV.parse_line('') # => nil - # - # ====== With Option +headers+ - # - # With {option +headers+}[#class-CSV-label-Option+headers], - # returns the first row as a CSV::Row object. - # - # These examples assume prior execution of: - # string = "Name,Count\nfoo,0\nbar,1\nbaz,2\n" - # path = 't.csv' - # File.write(path, string) - # - # Parse the first line from a \String object: - # CSV.parse_line(string, headers: true) # => # - # - # Parse the first line from a File object: - # File.open(path) do |file| - # CSV.parse_line(file, headers: true) - # end # => # - # - # --- - # - # Raises an exception if the argument is +nil+: - # # Raises ArgumentError (Cannot parse nil as CSV): - # CSV.parse_line(nil) - # - def parse_line(line, **options) - new(line, **options).each.first - end - - # - # :call-seq: - # read(source, **options) -> array_of_arrays - # read(source, headers: true, **options) -> csv_table - # - # Opens the given +source+ with the given +options+ (see CSV.open), - # reads the source (see CSV#read), and returns the result, - # which will be either an \Array of Arrays or a CSV::Table. - # - # Without headers: - # string = "foo,0\nbar,1\nbaz,2\n" - # path = 't.csv' - # File.write(path, string) - # CSV.read(path) # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] - # - # With headers: - # string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # path = 't.csv' - # File.write(path, string) - # CSV.read(path, headers: true) # => # - def read(path, **options) - open(path, **options) { |csv| csv.read } - end - - # :call-seq: - # CSV.readlines(source, **options) - # - # Alias for CSV.read. - def readlines(path, **options) - read(path, **options) - end - - # :call-seq: - # CSV.table(source, **options) - # - # Calls CSV.read with +source+, +options+, and certain default options: - # - +headers+: +true+ - # - +converters+: +:numeric+ - # - +header_converters+: +:symbol+ - # - # Returns a CSV::Table object. - # - # Example: - # string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # path = 't.csv' - # File.write(path, string) - # CSV.table(path) # => # - def table(path, **options) - default_options = { - headers: true, - converters: :numeric, - header_converters: :symbol, - } - options = default_options.merge(options) - read(path, **options) - end - end - - # :call-seq: - # CSV.new(string) - # CSV.new(io) - # CSV.new(string, **options) - # CSV.new(io, **options) - # - # Returns the new \CSV object created using +string+ or +io+ - # and the specified +options+. - # - # - Argument +string+ should be a \String object; - # it will be put into a new StringIO object positioned at the beginning. - # :include: ../doc/csv/arguments/io.rdoc - # - Argument +options+: See: - # * {Options for Parsing}[#class-CSV-label-Options+for+Parsing] - # * {Options for Generating}[#class-CSV-label-Options+for+Generating] - # For performance reasons, the options cannot be overridden - # in a \CSV object, so those specified here will endure. - # - # In addition to the \CSV instance methods, several \IO methods are delegated. - # See {Delegated Methods}[#class-CSV-label-Delegated+Methods]. - # - # --- - # - # Create a \CSV object from a \String object: - # csv = CSV.new('foo,0') - # csv # => # - # - # Create a \CSV object from a \File object: - # File.write('t.csv', 'foo,0') - # csv = CSV.new(File.open('t.csv')) - # csv # => # - # - # --- - # - # Raises an exception if the argument is +nil+: - # # Raises ArgumentError (Cannot parse nil as CSV): - # CSV.new(nil) - # - def initialize(data, - col_sep: ",", - row_sep: :auto, - quote_char: '"', - field_size_limit: nil, - max_field_size: nil, - converters: nil, - unconverted_fields: nil, - headers: false, - return_headers: false, - write_headers: nil, - header_converters: nil, - skip_blanks: false, - force_quotes: false, - skip_lines: nil, - liberal_parsing: false, - internal_encoding: nil, - external_encoding: nil, - encoding: nil, - nil_value: nil, - empty_value: "", - strip: false, - quote_empty: true, - write_converters: nil, - write_nil_value: nil, - write_empty_value: "") - raise ArgumentError.new("Cannot parse nil as CSV") if data.nil? - - if data.is_a?(String) - if encoding - if encoding.is_a?(String) - data_external_encoding, data_internal_encoding = encoding.split(":", 2) - if data_internal_encoding - data = data.encode(data_internal_encoding, data_external_encoding) - else - data = data.dup.force_encoding(data_external_encoding) - end - else - data = data.dup.force_encoding(encoding) - end - end - @io = StringIO.new(data) - else - @io = data - end - @encoding = determine_encoding(encoding, internal_encoding) - - @base_fields_converter_options = { - nil_value: nil_value, - empty_value: empty_value, - } - @write_fields_converter_options = { - nil_value: write_nil_value, - empty_value: write_empty_value, - } - @initial_converters = converters - @initial_header_converters = header_converters - @initial_write_converters = write_converters - - if max_field_size.nil? and field_size_limit - max_field_size = field_size_limit - 1 - end - @parser_options = { - column_separator: col_sep, - row_separator: row_sep, - quote_character: quote_char, - max_field_size: max_field_size, - unconverted_fields: unconverted_fields, - headers: headers, - return_headers: return_headers, - skip_blanks: skip_blanks, - skip_lines: skip_lines, - liberal_parsing: liberal_parsing, - encoding: @encoding, - nil_value: nil_value, - empty_value: empty_value, - strip: strip, - } - @parser = nil - @parser_enumerator = nil - @eof_error = nil - - @writer_options = { - encoding: @encoding, - force_encoding: (not encoding.nil?), - force_quotes: force_quotes, - headers: headers, - write_headers: write_headers, - column_separator: col_sep, - row_separator: row_sep, - quote_character: quote_char, - quote_empty: quote_empty, - } - - @writer = nil - writer if @writer_options[:write_headers] - end - - # :call-seq: - # csv.col_sep -> string - # - # Returns the encoded column separator; used for parsing and writing; - # see {Option +col_sep+}[#class-CSV-label-Option+col_sep]: - # CSV.new('').col_sep # => "," - def col_sep - parser.column_separator - end - - # :call-seq: - # csv.row_sep -> string - # - # Returns the encoded row separator; used for parsing and writing; - # see {Option +row_sep+}[#class-CSV-label-Option+row_sep]: - # CSV.new('').row_sep # => "\n" - def row_sep - parser.row_separator - end - - # :call-seq: - # csv.quote_char -> character - # - # Returns the encoded quote character; used for parsing and writing; - # see {Option +quote_char+}[#class-CSV-label-Option+quote_char]: - # CSV.new('').quote_char # => "\"" - def quote_char - parser.quote_character - end - - # :call-seq: - # csv.field_size_limit -> integer or nil - # - # Returns the limit for field size; used for parsing; - # see {Option +field_size_limit+}[#class-CSV-label-Option+field_size_limit]: - # CSV.new('').field_size_limit # => nil - # - # Deprecated since 3.2.3. Use +max_field_size+ instead. - def field_size_limit - parser.field_size_limit - end - - # :call-seq: - # csv.max_field_size -> integer or nil - # - # Returns the limit for field size; used for parsing; - # see {Option +max_field_size+}[#class-CSV-label-Option+max_field_size]: - # CSV.new('').max_field_size # => nil - # - # Since 3.2.3. - def max_field_size - parser.max_field_size - end - - # :call-seq: - # csv.skip_lines -> regexp or nil - # - # Returns the \Regexp used to identify comment lines; used for parsing; - # see {Option +skip_lines+}[#class-CSV-label-Option+skip_lines]: - # CSV.new('').skip_lines # => nil - def skip_lines - parser.skip_lines - end - - # :call-seq: - # csv.converters -> array - # - # Returns an \Array containing field converters; - # see {Field Converters}[#class-CSV-label-Field+Converters]: - # csv = CSV.new('') - # csv.converters # => [] - # csv.convert(:integer) - # csv.converters # => [:integer] - # csv.convert(proc {|x| x.to_s }) - # csv.converters - # - # Notes that you need to call - # +Ractor.make_shareable(CSV::Converters)+ on the main Ractor to use - # this method. - def converters - parser_fields_converter.map do |converter| - name = Converters.rassoc(converter) - name ? name.first : converter - end - end - - # :call-seq: - # csv.unconverted_fields? -> object - # - # Returns the value that determines whether unconverted fields are to be - # available; used for parsing; - # see {Option +unconverted_fields+}[#class-CSV-label-Option+unconverted_fields]: - # CSV.new('').unconverted_fields? # => nil - def unconverted_fields? - parser.unconverted_fields? - end - - # :call-seq: - # csv.headers -> object - # - # Returns the value that determines whether headers are used; used for parsing; - # see {Option +headers+}[#class-CSV-label-Option+headers]: - # CSV.new('').headers # => nil - def headers - if @writer - @writer.headers - else - parsed_headers = parser.headers - return parsed_headers if parsed_headers - raw_headers = @parser_options[:headers] - raw_headers = nil if raw_headers == false - raw_headers - end - end - - # :call-seq: - # csv.return_headers? -> true or false - # - # Returns the value that determines whether headers are to be returned; used for parsing; - # see {Option +return_headers+}[#class-CSV-label-Option+return_headers]: - # CSV.new('').return_headers? # => false - def return_headers? - parser.return_headers? - end - - # :call-seq: - # csv.write_headers? -> true or false - # - # Returns the value that determines whether headers are to be written; used for generating; - # see {Option +write_headers+}[#class-CSV-label-Option+write_headers]: - # CSV.new('').write_headers? # => nil - def write_headers? - @writer_options[:write_headers] - end - - # :call-seq: - # csv.header_converters -> array - # - # Returns an \Array containing header converters; used for parsing; - # see {Header Converters}[#class-CSV-label-Header+Converters]: - # CSV.new('').header_converters # => [] - # - # Notes that you need to call - # +Ractor.make_shareable(CSV::HeaderConverters)+ on the main Ractor - # to use this method. - def header_converters - header_fields_converter.map do |converter| - name = HeaderConverters.rassoc(converter) - name ? name.first : converter - end - end - - # :call-seq: - # csv.skip_blanks? -> true or false - # - # Returns the value that determines whether blank lines are to be ignored; used for parsing; - # see {Option +skip_blanks+}[#class-CSV-label-Option+skip_blanks]: - # CSV.new('').skip_blanks? # => false - def skip_blanks? - parser.skip_blanks? - end - - # :call-seq: - # csv.force_quotes? -> true or false - # - # Returns the value that determines whether all output fields are to be quoted; - # used for generating; - # see {Option +force_quotes+}[#class-CSV-label-Option+force_quotes]: - # CSV.new('').force_quotes? # => false - def force_quotes? - @writer_options[:force_quotes] - end - - # :call-seq: - # csv.liberal_parsing? -> true or false - # - # Returns the value that determines whether illegal input is to be handled; used for parsing; - # see {Option +liberal_parsing+}[#class-CSV-label-Option+liberal_parsing]: - # CSV.new('').liberal_parsing? # => false - def liberal_parsing? - parser.liberal_parsing? - end - - # :call-seq: - # csv.encoding -> encoding - # - # Returns the encoding used for parsing and generating; - # see {Character Encodings (M17n or Multilingualization)}[#class-CSV-label-Character+Encodings+-28M17n+or+Multilingualization-29]: - # CSV.new('').encoding # => # - attr_reader :encoding - - # :call-seq: - # csv.line_no -> integer - # - # Returns the count of the rows parsed or generated. - # - # Parsing: - # string = "foo,0\nbar,1\nbaz,2\n" - # path = 't.csv' - # File.write(path, string) - # CSV.open(path) do |csv| - # csv.each do |row| - # p [csv.lineno, row] - # end - # end - # Output: - # [1, ["foo", "0"]] - # [2, ["bar", "1"]] - # [3, ["baz", "2"]] - # - # Generating: - # CSV.generate do |csv| - # p csv.lineno; csv << ['foo', 0] - # p csv.lineno; csv << ['bar', 1] - # p csv.lineno; csv << ['baz', 2] - # end - # Output: - # 0 - # 1 - # 2 - def lineno - if @writer - @writer.lineno - else - parser.lineno - end - end - - # :call-seq: - # csv.line -> array - # - # Returns the line most recently read: - # string = "foo,0\nbar,1\nbaz,2\n" - # path = 't.csv' - # File.write(path, string) - # CSV.open(path) do |csv| - # csv.each do |row| - # p [csv.lineno, csv.line] - # end - # end - # Output: - # [1, "foo,0\n"] - # [2, "bar,1\n"] - # [3, "baz,2\n"] - def line - parser.line - end - - ### IO and StringIO Delegation ### - - extend Forwardable - def_delegators :@io, :binmode, :close, :close_read, :close_write, - :closed?, :external_encoding, :fcntl, - :fileno, :flush, :fsync, :internal_encoding, - :isatty, :pid, :pos, :pos=, :reopen, - :seek, :string, :sync, :sync=, :tell, - :truncate, :tty? - - def binmode? - if @io.respond_to?(:binmode?) - @io.binmode? - else - false - end - end - - def flock(*args) - raise NotImplementedError unless @io.respond_to?(:flock) - @io.flock(*args) - end - - def ioctl(*args) - raise NotImplementedError unless @io.respond_to?(:ioctl) - @io.ioctl(*args) - end - - def path - @io.path if @io.respond_to?(:path) - end - - def stat(*args) - raise NotImplementedError unless @io.respond_to?(:stat) - @io.stat(*args) - end - - def to_i - raise NotImplementedError unless @io.respond_to?(:to_i) - @io.to_i - end - - def to_io - @io.respond_to?(:to_io) ? @io.to_io : @io - end - - def eof? - return false if @eof_error - begin - parser_enumerator.peek - false - rescue MalformedCSVError => error - @eof_error = error - false - rescue StopIteration - true - end - end - alias_method :eof, :eof? - - # Rewinds the underlying IO object and resets CSV's lineno() counter. - def rewind - @parser = nil - @parser_enumerator = nil - @eof_error = nil - @writer.rewind if @writer - @io.rewind - end - - ### End Delegation ### - - # :call-seq: - # csv << row -> self - # - # Appends a row to +self+. - # - # - Argument +row+ must be an \Array object or a CSV::Row object. - # - The output stream must be open for writing. - # - # --- - # - # Append Arrays: - # CSV.generate do |csv| - # csv << ['foo', 0] - # csv << ['bar', 1] - # csv << ['baz', 2] - # end # => "foo,0\nbar,1\nbaz,2\n" - # - # Append CSV::Rows: - # headers = [] - # CSV.generate do |csv| - # csv << CSV::Row.new(headers, ['foo', 0]) - # csv << CSV::Row.new(headers, ['bar', 1]) - # csv << CSV::Row.new(headers, ['baz', 2]) - # end # => "foo,0\nbar,1\nbaz,2\n" - # - # Headers in CSV::Row objects are not appended: - # headers = ['Name', 'Count'] - # CSV.generate do |csv| - # csv << CSV::Row.new(headers, ['foo', 0]) - # csv << CSV::Row.new(headers, ['bar', 1]) - # csv << CSV::Row.new(headers, ['baz', 2]) - # end # => "foo,0\nbar,1\nbaz,2\n" - # - # --- - # - # Raises an exception if +row+ is not an \Array or \CSV::Row: - # CSV.generate do |csv| - # # Raises NoMethodError (undefined method `collect' for :foo:Symbol) - # csv << :foo - # end - # - # Raises an exception if the output stream is not opened for writing: - # path = 't.csv' - # File.write(path, '') - # File.open(path) do |file| - # CSV.open(file) do |csv| - # # Raises IOError (not opened for writing) - # csv << ['foo', 0] - # end - # end - def <<(row) - writer << row - self - end - alias_method :add_row, :<< - alias_method :puts, :<< - - # :call-seq: - # convert(converter_name) -> array_of_procs - # convert {|field, field_info| ... } -> array_of_procs - # - # - With no block, installs a field converter (a \Proc). - # - With a block, defines and installs a custom field converter. - # - Returns the \Array of installed field converters. - # - # - Argument +converter_name+, if given, should be the name - # of an existing field converter. - # - # See {Field Converters}[#class-CSV-label-Field+Converters]. - # --- - # - # With no block, installs a field converter: - # csv = CSV.new('') - # csv.convert(:integer) - # csv.convert(:float) - # csv.convert(:date) - # csv.converters # => [:integer, :float, :date] - # - # --- - # - # The block, if given, is called for each field: - # - Argument +field+ is the field value. - # - Argument +field_info+ is a CSV::FieldInfo object - # containing details about the field. - # - # The examples here assume the prior execution of: - # string = "foo,0\nbar,1\nbaz,2\n" - # path = 't.csv' - # File.write(path, string) - # - # Example giving a block: - # csv = CSV.open(path) - # csv.convert {|field, field_info| p [field, field_info]; field.upcase } - # csv.read # => [["FOO", "0"], ["BAR", "1"], ["BAZ", "2"]] - # - # Output: - # ["foo", #] - # ["0", #] - # ["bar", #] - # ["1", #] - # ["baz", #] - # ["2", #] - # - # The block need not return a \String object: - # csv = CSV.open(path) - # csv.convert {|field, field_info| field.to_sym } - # csv.read # => [[:foo, :"0"], [:bar, :"1"], [:baz, :"2"]] - # - # If +converter_name+ is given, the block is not called: - # csv = CSV.open(path) - # csv.convert(:integer) {|field, field_info| fail 'Cannot happen' } - # csv.read # => [["foo", 0], ["bar", 1], ["baz", 2]] - # - # --- - # - # Raises a parse-time exception if +converter_name+ is not the name of a built-in - # field converter: - # csv = CSV.open(path) - # csv.convert(:nosuch) => [nil] - # # Raises NoMethodError (undefined method `arity' for nil:NilClass) - # csv.read - def convert(name = nil, &converter) - parser_fields_converter.add_converter(name, &converter) - end - - # :call-seq: - # header_convert(converter_name) -> array_of_procs - # header_convert {|header, field_info| ... } -> array_of_procs - # - # - With no block, installs a header converter (a \Proc). - # - With a block, defines and installs a custom header converter. - # - Returns the \Array of installed header converters. - # - # - Argument +converter_name+, if given, should be the name - # of an existing header converter. - # - # See {Header Converters}[#class-CSV-label-Header+Converters]. - # --- - # - # With no block, installs a header converter: - # csv = CSV.new('') - # csv.header_convert(:symbol) - # csv.header_convert(:downcase) - # csv.header_converters # => [:symbol, :downcase] - # - # --- - # - # The block, if given, is called for each header: - # - Argument +header+ is the header value. - # - Argument +field_info+ is a CSV::FieldInfo object - # containing details about the header. - # - # The examples here assume the prior execution of: - # string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # path = 't.csv' - # File.write(path, string) - # - # Example giving a block: - # csv = CSV.open(path, headers: true) - # csv.header_convert {|header, field_info| p [header, field_info]; header.upcase } - # table = csv.read - # table # => # - # table.headers # => ["NAME", "VALUE"] - # - # Output: - # ["Name", #] - # ["Value", #] - - # The block need not return a \String object: - # csv = CSV.open(path, headers: true) - # csv.header_convert {|header, field_info| header.to_sym } - # table = csv.read - # table.headers # => [:Name, :Value] - # - # If +converter_name+ is given, the block is not called: - # csv = CSV.open(path, headers: true) - # csv.header_convert(:downcase) {|header, field_info| fail 'Cannot happen' } - # table = csv.read - # table.headers # => ["name", "value"] - # --- - # - # Raises a parse-time exception if +converter_name+ is not the name of a built-in - # field converter: - # csv = CSV.open(path, headers: true) - # csv.header_convert(:nosuch) - # # Raises NoMethodError (undefined method `arity' for nil:NilClass) - # csv.read - def header_convert(name = nil, &converter) - header_fields_converter.add_converter(name, &converter) - end - - include Enumerable - - # :call-seq: - # csv.each -> enumerator - # csv.each {|row| ...} - # - # Calls the block with each successive row. - # The data source must be opened for reading. - # - # Without headers: - # string = "foo,0\nbar,1\nbaz,2\n" - # csv = CSV.new(string) - # csv.each do |row| - # p row - # end - # Output: - # ["foo", "0"] - # ["bar", "1"] - # ["baz", "2"] - # - # With headers: - # string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # csv = CSV.new(string, headers: true) - # csv.each do |row| - # p row - # end - # Output: - # - # - # - # - # --- - # - # Raises an exception if the source is not opened for reading: - # string = "foo,0\nbar,1\nbaz,2\n" - # csv = CSV.new(string) - # csv.close - # # Raises IOError (not opened for reading) - # csv.each do |row| - # p row - # end - def each(&block) - return to_enum(__method__) unless block_given? - begin - while true - yield(parser_enumerator.next) - end - rescue StopIteration - end - end - - # :call-seq: - # csv.read -> array or csv_table - # - # Forms the remaining rows from +self+ into: - # - A CSV::Table object, if headers are in use. - # - An \Array of Arrays, otherwise. - # - # The data source must be opened for reading. - # - # Without headers: - # string = "foo,0\nbar,1\nbaz,2\n" - # path = 't.csv' - # File.write(path, string) - # csv = CSV.open(path) - # csv.read # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] - # - # With headers: - # string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # path = 't.csv' - # File.write(path, string) - # csv = CSV.open(path, headers: true) - # csv.read # => # - # - # --- - # - # Raises an exception if the source is not opened for reading: - # string = "foo,0\nbar,1\nbaz,2\n" - # csv = CSV.new(string) - # csv.close - # # Raises IOError (not opened for reading) - # csv.read - def read - rows = to_a - if parser.use_headers? - Table.new(rows, headers: parser.headers) - else - rows - end - end - alias_method :readlines, :read - - # :call-seq: - # csv.header_row? -> true or false - # - # Returns +true+ if the next row to be read is a header row\; - # +false+ otherwise. - # - # Without headers: - # string = "foo,0\nbar,1\nbaz,2\n" - # csv = CSV.new(string) - # csv.header_row? # => false - # - # With headers: - # string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # csv = CSV.new(string, headers: true) - # csv.header_row? # => true - # csv.shift # => # - # csv.header_row? # => false - # - # --- - # - # Raises an exception if the source is not opened for reading: - # string = "foo,0\nbar,1\nbaz,2\n" - # csv = CSV.new(string) - # csv.close - # # Raises IOError (not opened for reading) - # csv.header_row? - def header_row? - parser.header_row? - end - - # :call-seq: - # csv.shift -> array, csv_row, or nil - # - # Returns the next row of data as: - # - An \Array if no headers are used. - # - A CSV::Row object if headers are used. - # - # The data source must be opened for reading. - # - # Without headers: - # string = "foo,0\nbar,1\nbaz,2\n" - # csv = CSV.new(string) - # csv.shift # => ["foo", "0"] - # csv.shift # => ["bar", "1"] - # csv.shift # => ["baz", "2"] - # csv.shift # => nil - # - # With headers: - # string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # csv = CSV.new(string, headers: true) - # csv.shift # => # - # csv.shift # => # - # csv.shift # => # - # csv.shift # => nil - # - # --- - # - # Raises an exception if the source is not opened for reading: - # string = "foo,0\nbar,1\nbaz,2\n" - # csv = CSV.new(string) - # csv.close - # # Raises IOError (not opened for reading) - # csv.shift - def shift - if @eof_error - eof_error, @eof_error = @eof_error, nil - raise eof_error - end - begin - parser_enumerator.next - rescue StopIteration - nil - end - end - alias_method :gets, :shift - alias_method :readline, :shift - - # :call-seq: - # csv.inspect -> string - # - # Returns a \String showing certain properties of +self+: - # string = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # csv = CSV.new(string, headers: true) - # s = csv.inspect - # s # => "#" - def inspect - str = ["#<", self.class.to_s, " io_type:"] - # show type of wrapped IO - if @io == $stdout then str << "$stdout" - elsif @io == $stdin then str << "$stdin" - elsif @io == $stderr then str << "$stderr" - else str << @io.class.to_s - end - # show IO.path(), if available - if @io.respond_to?(:path) and (p = @io.path) - str << " io_path:" << p.inspect - end - # show encoding - str << " encoding:" << @encoding.name - # show other attributes - ["lineno", "col_sep", "row_sep", "quote_char"].each do |attr_name| - if a = __send__(attr_name) - str << " " << attr_name << ":" << a.inspect - end - end - ["skip_blanks", "liberal_parsing"].each do |attr_name| - if a = __send__("#{attr_name}?") - str << " " << attr_name << ":" << a.inspect - end - end - _headers = headers - str << " headers:" << _headers.inspect if _headers - str << ">" - begin - str.join('') - rescue # any encoding error - str.map do |s| - e = Encoding::Converter.asciicompat_encoding(s.encoding) - e ? s.encode(e) : s.force_encoding("ASCII-8BIT") - end.join('') - end - end - - private - - def determine_encoding(encoding, internal_encoding) - # honor the IO encoding if we can, otherwise default to ASCII-8BIT - io_encoding = raw_encoding - return io_encoding if io_encoding - - return Encoding.find(internal_encoding) if internal_encoding - - if encoding - encoding, = encoding.split(":", 2) if encoding.is_a?(String) - return Encoding.find(encoding) - end - - Encoding.default_internal || Encoding.default_external - end - - def normalize_converters(converters) - converters ||= [] - unless converters.is_a?(Array) - converters = [converters] - end - converters.collect do |converter| - case converter - when Proc # custom code block - [nil, converter] - else # by name - [converter, nil] - end - end - end - - # - # Processes +fields+ with @converters, or @header_converters - # if +headers+ is passed as +true+, returning the converted field set. Any - # converter that changes the field into something other than a String halts - # the pipeline of conversion for that field. This is primarily an efficiency - # shortcut. - # - def convert_fields(fields, headers = false) - if headers - header_fields_converter.convert(fields, nil, 0) - else - parser_fields_converter.convert(fields, @headers, lineno) - end - end - - # - # Returns the encoding of the internal IO object. - # - def raw_encoding - if @io.respond_to? :internal_encoding - @io.internal_encoding || @io.external_encoding - elsif @io.respond_to? :encoding - @io.encoding - else - nil - end - end - - def parser_fields_converter - @parser_fields_converter ||= build_parser_fields_converter - end - - def build_parser_fields_converter - specific_options = { - builtin_converters_name: :Converters, - } - options = @base_fields_converter_options.merge(specific_options) - build_fields_converter(@initial_converters, options) - end - - def header_fields_converter - @header_fields_converter ||= build_header_fields_converter - end - - def build_header_fields_converter - specific_options = { - builtin_converters_name: :HeaderConverters, - accept_nil: true, - } - options = @base_fields_converter_options.merge(specific_options) - build_fields_converter(@initial_header_converters, options) - end - - def writer_fields_converter - @writer_fields_converter ||= build_writer_fields_converter - end - - def build_writer_fields_converter - build_fields_converter(@initial_write_converters, - @write_fields_converter_options) - end - - def build_fields_converter(initial_converters, options) - fields_converter = FieldsConverter.new(options) - normalize_converters(initial_converters).each do |name, converter| - fields_converter.add_converter(name, &converter) - end - fields_converter - end - - def parser - @parser ||= Parser.new(@io, parser_options) - end - - def parser_options - @parser_options.merge(header_fields_converter: header_fields_converter, - fields_converter: parser_fields_converter) - end - - def parser_enumerator - @parser_enumerator ||= parser.parse - end - - def writer - @writer ||= Writer.new(@io, writer_options) - end - - def writer_options - @writer_options.merge(header_fields_converter: header_fields_converter, - fields_converter: writer_fields_converter) - end -end - -# Passes +args+ to CSV::instance. -# -# CSV("CSV,data").read -# #=> [["CSV", "data"]] -# -# If a block is given, the instance is passed the block and the return value -# becomes the return value of the block. -# -# CSV("CSV,data") { |c| -# c.read.any? { |a| a.include?("data") } -# } #=> true -# -# CSV("CSV,data") { |c| -# c.read.any? { |a| a.include?("zombies") } -# } #=> false -# -# CSV options may also be given. -# -# io = StringIO.new -# CSV(io, col_sep: ";") { |csv| csv << ["a", "b", "c"] } -# -# This API is not Ractor-safe. -# -def CSV(*args, **options, &block) - CSV.instance(*args, **options, &block) -end - -require_relative "csv/version" -require_relative "csv/core_ext/array" -require_relative "csv/core_ext/string" diff --git a/lib/csv/core_ext/array.rb b/lib/csv/core_ext/array.rb deleted file mode 100644 index 8beb06b082b522..00000000000000 --- a/lib/csv/core_ext/array.rb +++ /dev/null @@ -1,9 +0,0 @@ -class Array # :nodoc: - # Equivalent to CSV::generate_line(self, options) - # - # ["CSV", "data"].to_csv - # #=> "CSV,data\n" - def to_csv(**options) - CSV.generate_line(self, **options) - end -end diff --git a/lib/csv/core_ext/string.rb b/lib/csv/core_ext/string.rb deleted file mode 100644 index 9b1d31c2a4087f..00000000000000 --- a/lib/csv/core_ext/string.rb +++ /dev/null @@ -1,9 +0,0 @@ -class String # :nodoc: - # Equivalent to CSV::parse_line(self, options) - # - # "CSV,data".parse_csv - # #=> ["CSV", "data"] - def parse_csv(**options) - CSV.parse_line(self, **options) - end -end diff --git a/lib/csv/csv.gemspec b/lib/csv/csv.gemspec deleted file mode 100644 index 11c5b0f2a6e558..00000000000000 --- a/lib/csv/csv.gemspec +++ /dev/null @@ -1,64 +0,0 @@ -# frozen_string_literal: true - -begin - require_relative "lib/csv/version" -rescue LoadError - # for Ruby core repository - require_relative "version" -end - -Gem::Specification.new do |spec| - spec.name = "csv" - spec.version = CSV::VERSION - spec.authors = ["James Edward Gray II", "Kouhei Sutou"] - spec.email = [nil, "kou@cozmixng.org"] - - spec.summary = "CSV Reading and Writing" - spec.description = "The CSV library provides a complete interface to CSV files and data. It offers tools to enable you to read and write to and from Strings or IO objects, as needed." - spec.homepage = "https://github.com/ruby/csv" - spec.licenses = ["Ruby", "BSD-2-Clause"] - - lib_path = "lib" - spec.require_paths = [lib_path] - files = [] - lib_dir = File.join(__dir__, lib_path) - if File.exist?(lib_dir) - Dir.chdir(lib_dir) do - Dir.glob("**/*.rb").each do |file| - files << "lib/#{file}" - end - end - end - doc_dir = File.join(__dir__, "doc") - if File.exist?(doc_dir) - Dir.chdir(doc_dir) do - Dir.glob("**/*.rdoc").each do |rdoc_file| - files << "doc/#{rdoc_file}" - end - end - end - spec.files = files - spec.rdoc_options.concat(["--main", "README.md"]) - rdoc_files = [ - "LICENSE.txt", - "NEWS.md", - "README.md", - ] - recipes_dir = File.join(doc_dir, "csv", "recipes") - if File.exist?(recipes_dir) - Dir.chdir(recipes_dir) do - Dir.glob("**/*.rdoc").each do |recipe_file| - rdoc_files << "doc/csv/recipes/#{recipe_file}" - end - end - end - spec.extra_rdoc_files = rdoc_files - - spec.required_ruby_version = ">= 2.5.0" - - # spec.add_dependency "stringio", ">= 0.1.3" - spec.add_development_dependency "bundler" - spec.add_development_dependency "rake" - spec.add_development_dependency "benchmark_driver" - spec.add_development_dependency "test-unit", ">= 3.4.8" -end diff --git a/lib/csv/fields_converter.rb b/lib/csv/fields_converter.rb deleted file mode 100644 index d15977d3795f0a..00000000000000 --- a/lib/csv/fields_converter.rb +++ /dev/null @@ -1,89 +0,0 @@ -# frozen_string_literal: true - -class CSV - # Note: Don't use this class directly. This is an internal class. - class FieldsConverter - include Enumerable - # - # A CSV::FieldsConverter is a data structure for storing the - # fields converter properties to be passed as a parameter - # when parsing a new file (e.g. CSV::Parser.new(@io, parser_options)) - # - - def initialize(options={}) - @converters = [] - @nil_value = options[:nil_value] - @empty_value = options[:empty_value] - @empty_value_is_empty_string = (@empty_value == "") - @accept_nil = options[:accept_nil] - @builtin_converters_name = options[:builtin_converters_name] - @need_static_convert = need_static_convert? - end - - def add_converter(name=nil, &converter) - if name.nil? # custom converter - @converters << converter - else # named converter - combo = builtin_converters[name] - case combo - when Array # combo converter - combo.each do |sub_name| - add_converter(sub_name) - end - else # individual named converter - @converters << combo - end - end - end - - def each(&block) - @converters.each(&block) - end - - def empty? - @converters.empty? - end - - def convert(fields, headers, lineno, quoted_fields) - return fields unless need_convert? - - fields.collect.with_index do |field, index| - if field.nil? - field = @nil_value - elsif field.is_a?(String) and field.empty? - field = @empty_value unless @empty_value_is_empty_string - end - @converters.each do |converter| - break if field.nil? and @accept_nil - if converter.arity == 1 # straight field converter - field = converter[field] - else # FieldInfo converter - if headers - header = headers[index] - else - header = nil - end - quoted = quoted_fields[index] - field = converter[field, FieldInfo.new(index, lineno, header, quoted)] - end - break unless field.is_a?(String) # short-circuit pipeline for speed - end - field # final state of each field, converted or original - end - end - - private - def need_static_convert? - not (@nil_value.nil? and @empty_value_is_empty_string) - end - - def need_convert? - @need_static_convert or - (not @converters.empty?) - end - - def builtin_converters - @builtin_converters ||= ::CSV.const_get(@builtin_converters_name) - end - end -end diff --git a/lib/csv/input_record_separator.rb b/lib/csv/input_record_separator.rb deleted file mode 100644 index 7a99343c0cfbe7..00000000000000 --- a/lib/csv/input_record_separator.rb +++ /dev/null @@ -1,18 +0,0 @@ -require "English" -require "stringio" - -class CSV - module InputRecordSeparator - class << self - if RUBY_VERSION >= "3.0.0" - def value - "\n" - end - else - def value - $INPUT_RECORD_SEPARATOR - end - end - end - end -end diff --git a/lib/csv/parser.rb b/lib/csv/parser.rb deleted file mode 100644 index ed9297fe305ac6..00000000000000 --- a/lib/csv/parser.rb +++ /dev/null @@ -1,1290 +0,0 @@ -# frozen_string_literal: true - -require "strscan" - -require_relative "input_record_separator" -require_relative "row" -require_relative "table" - -class CSV - # Note: Don't use this class directly. This is an internal class. - class Parser - # - # A CSV::Parser is m17n aware. The parser works in the Encoding of the IO - # or String object being read from or written to. Your data is never transcoded - # (unless you ask Ruby to transcode it for you) and will literally be parsed in - # the Encoding it is in. Thus CSV will return Arrays or Rows of Strings in the - # Encoding of your data. This is accomplished by transcoding the parser itself - # into your Encoding. - # - - # Raised when encoding is invalid. - class InvalidEncoding < StandardError - end - - # Raised when unexpected case is happen. - class UnexpectedError < StandardError - end - - # - # CSV::Scanner receives a CSV output, scans it and return the content. - # It also controls the life cycle of the object with its methods +keep_start+, - # +keep_end+, +keep_back+, +keep_drop+. - # - # Uses StringScanner (the official strscan gem). Strscan provides lexical - # scanning operations on a String. We inherit its object and take advantage - # on the methods. For more information, please visit: - # https://ruby-doc.org/stdlib-2.6.1/libdoc/strscan/rdoc/StringScanner.html - # - class Scanner < StringScanner - alias_method :scan_all, :scan - - def initialize(*args) - super - @keeps = [] - end - - def each_line(row_separator) - position = pos - rest.each_line(row_separator) do |line| - position += line.bytesize - self.pos = position - yield(line) - end - end - - def keep_start - @keeps.push(pos) - end - - def keep_end - start = @keeps.pop - string.byteslice(start, pos - start) - end - - def keep_back - self.pos = @keeps.pop - end - - def keep_drop - @keeps.pop - end - end - - # - # CSV::InputsScanner receives IO inputs, encoding and the chunk_size. - # It also controls the life cycle of the object with its methods +keep_start+, - # +keep_end+, +keep_back+, +keep_drop+. - # - # CSV::InputsScanner.scan() tries to match with pattern at the current position. - # If there's a match, the scanner advances the "scan pointer" and returns the matched string. - # Otherwise, the scanner returns nil. - # - # CSV::InputsScanner.rest() returns the "rest" of the string (i.e. everything after the scan pointer). - # If there is no more data (eos? = true), it returns "". - # - class InputsScanner - def initialize(inputs, encoding, row_separator, chunk_size: 8192) - @inputs = inputs.dup - @encoding = encoding - @row_separator = row_separator - @chunk_size = chunk_size - @last_scanner = @inputs.empty? - @keeps = [] - read_chunk - end - - def each_line(row_separator) - return enum_for(__method__, row_separator) unless block_given? - buffer = nil - input = @scanner.rest - position = @scanner.pos - offset = 0 - n_row_separator_chars = row_separator.size - # trace(__method__, :start, input) - while true - input.each_line(row_separator) do |line| - @scanner.pos += line.bytesize - if buffer - if n_row_separator_chars == 2 and - buffer.end_with?(row_separator[0]) and - line.start_with?(row_separator[1]) - buffer << line[0] - line = line[1..-1] - position += buffer.bytesize + offset - @scanner.pos = position - offset = 0 - yield(buffer) - buffer = nil - next if line.empty? - else - buffer << line - line = buffer - buffer = nil - end - end - if line.end_with?(row_separator) - position += line.bytesize + offset - @scanner.pos = position - offset = 0 - yield(line) - else - buffer = line - end - end - break unless read_chunk - input = @scanner.rest - position = @scanner.pos - offset = -buffer.bytesize if buffer - end - yield(buffer) if buffer - end - - def scan(pattern) - # trace(__method__, pattern, :start) - value = @scanner.scan(pattern) - # trace(__method__, pattern, :done, :last, value) if @last_scanner - return value if @last_scanner - - read_chunk if value and @scanner.eos? - # trace(__method__, pattern, :done, value) - value - end - - def scan_all(pattern) - # trace(__method__, pattern, :start) - value = @scanner.scan(pattern) - # trace(__method__, pattern, :done, :last, value) if @last_scanner - return value if @last_scanner - - # trace(__method__, pattern, :done, :nil) if value.nil? - return nil if value.nil? - while @scanner.eos? and read_chunk and (sub_value = @scanner.scan(pattern)) - # trace(__method__, pattern, :sub, sub_value) - value << sub_value - end - # trace(__method__, pattern, :done, value) - value - end - - def eos? - @scanner.eos? - end - - def keep_start - # trace(__method__, :start) - adjust_last_keep - @keeps.push([@scanner, @scanner.pos, nil]) - # trace(__method__, :done) - end - - def keep_end - # trace(__method__, :start) - scanner, start, buffer = @keeps.pop - if scanner == @scanner - keep = @scanner.string.byteslice(start, @scanner.pos - start) - else - keep = @scanner.string.byteslice(0, @scanner.pos) - end - if buffer - buffer << keep - keep = buffer - end - # trace(__method__, :done, keep) - keep - end - - def keep_back - # trace(__method__, :start) - scanner, start, buffer = @keeps.pop - if buffer - # trace(__method__, :rescan, start, buffer) - string = @scanner.string - if scanner == @scanner - keep = string.byteslice(start, - string.bytesize - @scanner.pos - start) - else - keep = string - end - if keep and not keep.empty? - @inputs.unshift(StringIO.new(keep)) - @last_scanner = false - end - @scanner = StringScanner.new(buffer) - else - if @scanner != scanner - message = "scanners are different but no buffer: " - message += "#{@scanner.inspect}(#{@scanner.object_id}): " - message += "#{scanner.inspect}(#{scanner.object_id})" - raise UnexpectedError, message - end - # trace(__method__, :repos, start, buffer) - @scanner.pos = start - end - read_chunk if @scanner.eos? - end - - def keep_drop - _, _, buffer = @keeps.pop - # trace(__method__, :done, :empty) unless buffer - return unless buffer - - last_keep = @keeps.last - # trace(__method__, :done, :no_last_keep) unless last_keep - return unless last_keep - - if last_keep[2] - last_keep[2] << buffer - else - last_keep[2] = buffer - end - # trace(__method__, :done) - end - - def rest - @scanner.rest - end - - def check(pattern) - @scanner.check(pattern) - end - - private - def trace(*args) - pp([*args, @scanner, @scanner&.string, @scanner&.pos, @keeps]) - end - - def adjust_last_keep - # trace(__method__, :start) - - keep = @keeps.last - # trace(__method__, :done, :empty) if keep.nil? - return if keep.nil? - - scanner, start, buffer = keep - string = @scanner.string - if @scanner != scanner - start = 0 - end - if start == 0 and @scanner.eos? - keep_data = string - else - keep_data = string.byteslice(start, @scanner.pos - start) - end - if keep_data - if buffer - buffer << keep_data - else - keep[2] = keep_data.dup - end - end - - # trace(__method__, :done) - end - - def read_chunk - return false if @last_scanner - - adjust_last_keep - - input = @inputs.first - case input - when StringIO - string = input.read - raise InvalidEncoding unless string.valid_encoding? - # trace(__method__, :stringio, string) - @scanner = StringScanner.new(string) - @inputs.shift - @last_scanner = @inputs.empty? - true - else - chunk = input.gets(@row_separator, @chunk_size) - if chunk - raise InvalidEncoding unless chunk.valid_encoding? - # trace(__method__, :chunk, chunk) - @scanner = StringScanner.new(chunk) - if input.respond_to?(:eof?) and input.eof? - @inputs.shift - @last_scanner = @inputs.empty? - end - true - else - # trace(__method__, :no_chunk) - @scanner = StringScanner.new("".encode(@encoding)) - @inputs.shift - @last_scanner = @inputs.empty? - if @last_scanner - false - else - read_chunk - end - end - end - end - end - - def initialize(input, options) - @input = input - @options = options - @samples = [] - - prepare - end - - def column_separator - @column_separator - end - - def row_separator - @row_separator - end - - def quote_character - @quote_character - end - - def field_size_limit - @max_field_size&.succ - end - - def max_field_size - @max_field_size - end - - def skip_lines - @skip_lines - end - - def unconverted_fields? - @unconverted_fields - end - - def headers - @headers - end - - def header_row? - @use_headers and @headers.nil? - end - - def return_headers? - @return_headers - end - - def skip_blanks? - @skip_blanks - end - - def liberal_parsing? - @liberal_parsing - end - - def lineno - @lineno - end - - def line - last_line - end - - def parse(&block) - return to_enum(__method__) unless block_given? - - if @return_headers and @headers and @raw_headers - headers = Row.new(@headers, @raw_headers, true) - if @unconverted_fields - headers = add_unconverted_fields(headers, []) - end - yield headers - end - - begin - @scanner ||= build_scanner - if quote_character.nil? - parse_no_quote(&block) - elsif @need_robust_parsing - parse_quotable_robust(&block) - else - parse_quotable_loose(&block) - end - rescue InvalidEncoding - if @scanner - ignore_broken_line - lineno = @lineno - else - lineno = @lineno + 1 - end - message = "Invalid byte sequence in #{@encoding}" - raise MalformedCSVError.new(message, lineno) - rescue UnexpectedError => error - if @scanner - ignore_broken_line - lineno = @lineno - else - lineno = @lineno + 1 - end - message = "This should not be happen: #{error.message}: " - message += "Please report this to https://github.com/ruby/csv/issues" - raise MalformedCSVError.new(message, lineno) - end - end - - def use_headers? - @use_headers - end - - private - # A set of tasks to prepare the file in order to parse it - def prepare - prepare_variable - prepare_quote_character - prepare_backslash - prepare_skip_lines - prepare_strip - prepare_separators - validate_strip_and_col_sep_options - prepare_quoted - prepare_unquoted - prepare_line - prepare_header - prepare_parser - end - - def prepare_variable - @need_robust_parsing = false - @encoding = @options[:encoding] - liberal_parsing = @options[:liberal_parsing] - if liberal_parsing - @liberal_parsing = true - if liberal_parsing.is_a?(Hash) - @double_quote_outside_quote = - liberal_parsing[:double_quote_outside_quote] - @backslash_quote = liberal_parsing[:backslash_quote] - else - @double_quote_outside_quote = false - @backslash_quote = false - end - @need_robust_parsing = true - else - @liberal_parsing = false - @backslash_quote = false - end - @unconverted_fields = @options[:unconverted_fields] - @max_field_size = @options[:max_field_size] - @skip_blanks = @options[:skip_blanks] - @fields_converter = @options[:fields_converter] - @header_fields_converter = @options[:header_fields_converter] - end - - def prepare_quote_character - @quote_character = @options[:quote_character] - if @quote_character.nil? - @escaped_quote_character = nil - @escaped_quote = nil - else - @quote_character = @quote_character.to_s.encode(@encoding) - if @quote_character.length != 1 - message = ":quote_char has to be nil or a single character String" - raise ArgumentError, message - end - @escaped_quote_character = Regexp.escape(@quote_character) - @escaped_quote = Regexp.new(@escaped_quote_character) - end - end - - def prepare_backslash - return unless @backslash_quote - - @backslash_character = "\\".encode(@encoding) - - @escaped_backslash_character = Regexp.escape(@backslash_character) - @escaped_backslash = Regexp.new(@escaped_backslash_character) - if @quote_character.nil? - @backslash_quote_character = nil - else - @backslash_quote_character = - @backslash_character + @escaped_quote_character - end - end - - def prepare_skip_lines - skip_lines = @options[:skip_lines] - case skip_lines - when String - @skip_lines = skip_lines.encode(@encoding) - when Regexp, nil - @skip_lines = skip_lines - else - unless skip_lines.respond_to?(:match) - message = - ":skip_lines has to respond to \#match: #{skip_lines.inspect}" - raise ArgumentError, message - end - @skip_lines = skip_lines - end - end - - def prepare_strip - @strip = @options[:strip] - @escaped_strip = nil - @strip_value = nil - @rstrip_value = nil - if @strip.is_a?(String) - case @strip.length - when 0 - raise ArgumentError, ":strip must not be an empty String" - when 1 - # ok - else - raise ArgumentError, ":strip doesn't support 2 or more characters yet" - end - @strip = @strip.encode(@encoding) - @escaped_strip = Regexp.escape(@strip) - if @quote_character - @strip_value = Regexp.new(@escaped_strip + - "+".encode(@encoding)) - @rstrip_value = Regexp.new(@escaped_strip + - "+\\z".encode(@encoding)) - end - @need_robust_parsing = true - elsif @strip - strip_values = " \t\f\v" - @escaped_strip = strip_values.encode(@encoding) - if @quote_character - @strip_value = Regexp.new("[#{strip_values}]+".encode(@encoding)) - @rstrip_value = Regexp.new("[#{strip_values}]+\\z".encode(@encoding)) - end - @need_robust_parsing = true - end - end - - begin - StringScanner.new("x").scan("x") - rescue TypeError - STRING_SCANNER_SCAN_ACCEPT_STRING = false - else - STRING_SCANNER_SCAN_ACCEPT_STRING = true - end - - def prepare_separators - column_separator = @options[:column_separator] - @column_separator = column_separator.to_s.encode(@encoding) - if @column_separator.size < 1 - message = ":col_sep must be 1 or more characters: " - message += column_separator.inspect - raise ArgumentError, message - end - @row_separator = - resolve_row_separator(@options[:row_separator]).encode(@encoding) - - @escaped_column_separator = Regexp.escape(@column_separator) - @escaped_first_column_separator = Regexp.escape(@column_separator[0]) - if @column_separator.size > 1 - @column_end = Regexp.new(@escaped_column_separator) - @column_ends = @column_separator.each_char.collect do |char| - Regexp.new(Regexp.escape(char)) - end - @first_column_separators = Regexp.new(@escaped_first_column_separator + - "+".encode(@encoding)) - else - if STRING_SCANNER_SCAN_ACCEPT_STRING - @column_end = @column_separator - else - @column_end = Regexp.new(@escaped_column_separator) - end - @column_ends = nil - @first_column_separators = nil - end - - escaped_row_separator = Regexp.escape(@row_separator) - @row_end = Regexp.new(escaped_row_separator) - if @row_separator.size > 1 - @row_ends = @row_separator.each_char.collect do |char| - Regexp.new(Regexp.escape(char)) - end - else - @row_ends = nil - end - - @cr = "\r".encode(@encoding) - @lf = "\n".encode(@encoding) - @line_end = Regexp.new("\r\n|\n|\r".encode(@encoding)) - @not_line_end = Regexp.new("[^\r\n]+".encode(@encoding)) - end - - # This method verifies that there are no (obvious) ambiguities with the - # provided +col_sep+ and +strip+ parsing options. For example, if +col_sep+ - # and +strip+ were both equal to +\t+, then there would be no clear way to - # parse the input. - def validate_strip_and_col_sep_options - return unless @strip - - if @strip.is_a?(String) - if @column_separator.start_with?(@strip) || @column_separator.end_with?(@strip) - raise ArgumentError, - "The provided strip (#{@escaped_strip}) and " \ - "col_sep (#{@escaped_column_separator}) options are incompatible." - end - else - if Regexp.new("\\A[#{@escaped_strip}]|[#{@escaped_strip}]\\z").match?(@column_separator) - raise ArgumentError, - "The provided strip (true) and " \ - "col_sep (#{@escaped_column_separator}) options are incompatible." - end - end - end - - def prepare_quoted - if @quote_character - @quotes = Regexp.new(@escaped_quote_character + - "+".encode(@encoding)) - no_quoted_values = @escaped_quote_character.dup - if @backslash_quote - no_quoted_values << @escaped_backslash_character - end - @quoted_value = Regexp.new("[^".encode(@encoding) + - no_quoted_values + - "]+".encode(@encoding)) - end - if @escaped_strip - @split_column_separator = Regexp.new(@escaped_strip + - "*".encode(@encoding) + - @escaped_column_separator + - @escaped_strip + - "*".encode(@encoding)) - else - if @column_separator == " ".encode(@encoding) - @split_column_separator = Regexp.new(@escaped_column_separator) - else - @split_column_separator = @column_separator - end - end - end - - def prepare_unquoted - return if @quote_character.nil? - - no_unquoted_values = "\r\n".encode(@encoding) - no_unquoted_values << @escaped_first_column_separator - unless @liberal_parsing - no_unquoted_values << @escaped_quote_character - end - @unquoted_value = Regexp.new("[^".encode(@encoding) + - no_unquoted_values + - "]+".encode(@encoding)) - end - - def resolve_row_separator(separator) - if separator == :auto - cr = "\r".encode(@encoding) - lf = "\n".encode(@encoding) - if @input.is_a?(StringIO) - pos = @input.pos - separator = detect_row_separator(@input.read, cr, lf) - @input.seek(pos) - elsif @input.respond_to?(:gets) - if @input.is_a?(File) - chunk_size = 32 * 1024 - else - chunk_size = 1024 - end - begin - while separator == :auto - # - # if we run out of data, it's probably a single line - # (ensure will set default value) - # - break unless sample = @input.gets(nil, chunk_size) - - # extend sample if we're unsure of the line ending - if sample.end_with?(cr) - sample << (@input.gets(nil, 1) || "") - end - - @samples << sample - - separator = detect_row_separator(sample, cr, lf) - end - rescue IOError - # do nothing: ensure will set default - end - end - separator = InputRecordSeparator.value if separator == :auto - end - separator.to_s.encode(@encoding) - end - - def detect_row_separator(sample, cr, lf) - lf_index = sample.index(lf) - if lf_index - cr_index = sample[0, lf_index].index(cr) - else - cr_index = sample.index(cr) - end - if cr_index and lf_index - if cr_index + 1 == lf_index - cr + lf - elsif cr_index < lf_index - cr - else - lf - end - elsif cr_index - cr - elsif lf_index - lf - else - :auto - end - end - - def prepare_line - @lineno = 0 - @last_line = nil - @scanner = nil - end - - def last_line - if @scanner - @last_line ||= @scanner.keep_end - else - @last_line - end - end - - def prepare_header - @return_headers = @options[:return_headers] - - headers = @options[:headers] - case headers - when Array - @raw_headers = headers - quoted_fields = [false] * @raw_headers.size - @use_headers = true - when String - @raw_headers, quoted_fields = parse_headers(headers) - @use_headers = true - when nil, false - @raw_headers = nil - @use_headers = false - else - @raw_headers = nil - @use_headers = true - end - if @raw_headers - @headers = adjust_headers(@raw_headers, quoted_fields) - else - @headers = nil - end - end - - def parse_headers(row) - quoted_fields = [] - converter = lambda do |field, info| - quoted_fields << info.quoted? - field - end - headers = CSV.parse_line(row, - col_sep: @column_separator, - row_sep: @row_separator, - quote_char: @quote_character, - converters: [converter]) - [headers, quoted_fields] - end - - def adjust_headers(headers, quoted_fields) - adjusted_headers = @header_fields_converter.convert(headers, nil, @lineno, quoted_fields) - adjusted_headers.each {|h| h.freeze if h.is_a? String} - adjusted_headers - end - - def prepare_parser - @may_quoted = may_quoted? - end - - def may_quoted? - return false if @quote_character.nil? - - if @input.is_a?(StringIO) - pos = @input.pos - sample = @input.read - @input.seek(pos) - else - return false if @samples.empty? - sample = @samples.first - end - sample[0, 128].index(@quote_character) - end - - class UnoptimizedStringIO # :nodoc: - def initialize(string) - @io = StringIO.new(string, "rb:#{string.encoding}") - end - - def gets(*args) - @io.gets(*args) - end - - def each_line(*args, &block) - @io.each_line(*args, &block) - end - - def eof? - @io.eof? - end - end - - SCANNER_TEST = (ENV["CSV_PARSER_SCANNER_TEST"] == "yes") - if SCANNER_TEST - SCANNER_TEST_CHUNK_SIZE_NAME = "CSV_PARSER_SCANNER_TEST_CHUNK_SIZE" - SCANNER_TEST_CHUNK_SIZE_VALUE = ENV[SCANNER_TEST_CHUNK_SIZE_NAME] - def build_scanner - inputs = @samples.collect do |sample| - UnoptimizedStringIO.new(sample) - end - if @input.is_a?(StringIO) - inputs << UnoptimizedStringIO.new(@input.read) - else - inputs << @input - end - begin - chunk_size_value = ENV[SCANNER_TEST_CHUNK_SIZE_NAME] - rescue # Ractor::IsolationError - # Ractor on Ruby 3.0 can't read ENV value. - chunk_size_value = SCANNER_TEST_CHUNK_SIZE_VALUE - end - chunk_size = Integer((chunk_size_value || "1"), 10) - InputsScanner.new(inputs, - @encoding, - @row_separator, - chunk_size: chunk_size) - end - else - def build_scanner - string = nil - if @samples.empty? and @input.is_a?(StringIO) - string = @input.read - elsif @samples.size == 1 and - @input != ARGF and - @input.respond_to?(:eof?) and - @input.eof? - string = @samples[0] - end - if string - unless string.valid_encoding? - index = string.lines(@row_separator).index do |line| - !line.valid_encoding? - end - if index - message = "Invalid byte sequence in #{@encoding}" - raise MalformedCSVError.new(message, @lineno + index + 1) - end - end - Scanner.new(string) - else - inputs = @samples.collect do |sample| - StringIO.new(sample) - end - inputs << @input - InputsScanner.new(inputs, @encoding, @row_separator) - end - end - end - - def skip_needless_lines - return unless @skip_lines - - until @scanner.eos? - @scanner.keep_start - line = @scanner.scan_all(@not_line_end) || "".encode(@encoding) - line << @row_separator if parse_row_end - if skip_line?(line) - @lineno += 1 - @scanner.keep_drop - else - @scanner.keep_back - return - end - end - end - - def skip_line?(line) - line = line.delete_suffix(@row_separator) - case @skip_lines - when String - line.include?(@skip_lines) - when Regexp - @skip_lines.match?(line) - else - @skip_lines.match(line) - end - end - - def validate_field_size(field) - return unless @max_field_size - return if field.size <= @max_field_size - ignore_broken_line - message = "Field size exceeded: #{field.size} > #{@max_field_size}" - raise MalformedCSVError.new(message, @lineno) - end - - def parse_no_quote(&block) - @scanner.each_line(@row_separator) do |line| - next if @skip_lines and skip_line?(line) - original_line = line - line = line.delete_suffix(@row_separator) - - if line.empty? - next if @skip_blanks - row = [] - quoted_fields = [] - else - line = strip_value(line) - row = line.split(@split_column_separator, -1) - quoted_fields = [false] * row.size - if @max_field_size - row.each do |column| - validate_field_size(column) - end - end - n_columns = row.size - i = 0 - while i < n_columns - row[i] = nil if row[i].empty? - i += 1 - end - end - @last_line = original_line - emit_row(row, quoted_fields, &block) - end - end - - def parse_quotable_loose(&block) - @scanner.keep_start - @scanner.each_line(@row_separator) do |line| - if @skip_lines and skip_line?(line) - @scanner.keep_drop - @scanner.keep_start - next - end - original_line = line - line = line.delete_suffix(@row_separator) - - if line.empty? - if @skip_blanks - @scanner.keep_drop - @scanner.keep_start - next - end - row = [] - quoted_fields = [] - elsif line.include?(@cr) or line.include?(@lf) - @scanner.keep_back - @need_robust_parsing = true - return parse_quotable_robust(&block) - else - row = line.split(@split_column_separator, -1) - quoted_fields = [] - n_columns = row.size - i = 0 - while i < n_columns - column = row[i] - if column.empty? - quoted_fields << false - row[i] = nil - else - n_quotes = column.count(@quote_character) - if n_quotes.zero? - quoted_fields << false - # no quote - elsif n_quotes == 2 and - column.start_with?(@quote_character) and - column.end_with?(@quote_character) - quoted_fields << true - row[i] = column[1..-2] - else - @scanner.keep_back - @need_robust_parsing = true - return parse_quotable_robust(&block) - end - validate_field_size(row[i]) - end - i += 1 - end - end - @scanner.keep_drop - @scanner.keep_start - @last_line = original_line - emit_row(row, quoted_fields, &block) - end - @scanner.keep_drop - end - - def parse_quotable_robust(&block) - row = [] - quoted_fields = [] - skip_needless_lines - start_row - while true - @quoted_column_value = false - @unquoted_column_value = false - @scanner.scan_all(@strip_value) if @strip_value - value = parse_column_value - if value - @scanner.scan_all(@strip_value) if @strip_value - validate_field_size(value) - end - if parse_column_end - row << value - quoted_fields << @quoted_column_value - elsif parse_row_end - if row.empty? and value.nil? - emit_row([], [], &block) unless @skip_blanks - else - row << value - quoted_fields << @quoted_column_value - emit_row(row, quoted_fields, &block) - row = [] - quoted_fields = [] - end - skip_needless_lines - start_row - elsif @scanner.eos? - break if row.empty? and value.nil? - row << value - quoted_fields << @quoted_column_value - emit_row(row, quoted_fields, &block) - break - else - if @quoted_column_value - if liberal_parsing? and (new_line = @scanner.check(@line_end)) - message = - "Illegal end-of-line sequence outside of a quoted field " + - "<#{new_line.inspect}>" - else - message = "Any value after quoted field isn't allowed" - end - ignore_broken_line - raise MalformedCSVError.new(message, @lineno) - elsif @unquoted_column_value and - (new_line = @scanner.scan(@line_end)) - ignore_broken_line - message = "Unquoted fields do not allow new line " + - "<#{new_line.inspect}>" - raise MalformedCSVError.new(message, @lineno) - elsif @scanner.rest.start_with?(@quote_character) - ignore_broken_line - message = "Illegal quoting" - raise MalformedCSVError.new(message, @lineno) - elsif (new_line = @scanner.scan(@line_end)) - ignore_broken_line - message = "New line must be <#{@row_separator.inspect}> " + - "not <#{new_line.inspect}>" - raise MalformedCSVError.new(message, @lineno) - else - ignore_broken_line - raise MalformedCSVError.new("TODO: Meaningful message", - @lineno) - end - end - end - end - - def parse_column_value - if @liberal_parsing - quoted_value = parse_quoted_column_value - if quoted_value - @scanner.scan_all(@strip_value) if @strip_value - unquoted_value = parse_unquoted_column_value - if unquoted_value - if @double_quote_outside_quote - unquoted_value = unquoted_value.gsub(@quote_character * 2, - @quote_character) - if quoted_value.empty? # %Q{""...} case - return @quote_character + unquoted_value - end - end - @quote_character + quoted_value + @quote_character + unquoted_value - else - quoted_value - end - else - parse_unquoted_column_value - end - elsif @may_quoted - parse_quoted_column_value || - parse_unquoted_column_value - else - parse_unquoted_column_value || - parse_quoted_column_value - end - end - - def parse_unquoted_column_value - value = @scanner.scan_all(@unquoted_value) - return nil unless value - - @unquoted_column_value = true - if @first_column_separators - while true - @scanner.keep_start - is_column_end = @column_ends.all? do |column_end| - @scanner.scan(column_end) - end - @scanner.keep_back - break if is_column_end - sub_separator = @scanner.scan_all(@first_column_separators) - break if sub_separator.nil? - value << sub_separator - sub_value = @scanner.scan_all(@unquoted_value) - break if sub_value.nil? - value << sub_value - end - end - value.gsub!(@backslash_quote_character, @quote_character) if @backslash_quote - if @rstrip_value - value.gsub!(@rstrip_value, "") - end - value - end - - def parse_quoted_column_value - quotes = @scanner.scan_all(@quotes) - return nil unless quotes - - @quoted_column_value = true - n_quotes = quotes.size - if (n_quotes % 2).zero? - quotes[0, (n_quotes - 2) / 2] - else - value = quotes[0, n_quotes / 2] - while true - quoted_value = @scanner.scan_all(@quoted_value) - value << quoted_value if quoted_value - if @backslash_quote - if @scanner.scan(@escaped_backslash) - if @scanner.scan(@escaped_quote) - value << @quote_character - else - value << @backslash_character - end - next - end - end - - quotes = @scanner.scan_all(@quotes) - unless quotes - ignore_broken_line - message = "Unclosed quoted field" - raise MalformedCSVError.new(message, @lineno) - end - n_quotes = quotes.size - if n_quotes == 1 - break - else - value << quotes[0, n_quotes / 2] - break if (n_quotes % 2) == 1 - end - end - value - end - end - - def parse_column_end - return true if @scanner.scan(@column_end) - return false unless @column_ends - - @scanner.keep_start - if @column_ends.all? {|column_end| @scanner.scan(column_end)} - @scanner.keep_drop - true - else - @scanner.keep_back - false - end - end - - def parse_row_end - return true if @scanner.scan(@row_end) - return false unless @row_ends - @scanner.keep_start - if @row_ends.all? {|row_end| @scanner.scan(row_end)} - @scanner.keep_drop - true - else - @scanner.keep_back - false - end - end - - def strip_value(value) - return value unless @strip - return value if value.nil? - - case @strip - when String - while value.delete_prefix!(@strip) - # do nothing - end - while value.delete_suffix!(@strip) - # do nothing - end - else - value.strip! - end - value - end - - def ignore_broken_line - @scanner.scan_all(@not_line_end) - @scanner.scan_all(@line_end) - @lineno += 1 - end - - def start_row - if @last_line - @last_line = nil - else - @scanner.keep_drop - end - @scanner.keep_start - end - - def emit_row(row, quoted_fields, &block) - @lineno += 1 - - raw_row = row - if @use_headers - if @headers.nil? - @headers = adjust_headers(row, quoted_fields) - return unless @return_headers - row = Row.new(@headers, row, true) - else - row = Row.new(@headers, - @fields_converter.convert(raw_row, @headers, @lineno, quoted_fields)) - end - else - # convert fields, if needed... - row = @fields_converter.convert(raw_row, nil, @lineno, quoted_fields) - end - - # inject unconverted fields and accessor, if requested... - if @unconverted_fields and not row.respond_to?(:unconverted_fields) - add_unconverted_fields(row, raw_row) - end - - yield(row) - end - - # This method injects an instance variable unconverted_fields into - # +row+ and an accessor method for +row+ called unconverted_fields(). The - # variable is set to the contents of +fields+. - def add_unconverted_fields(row, fields) - class << row - attr_reader :unconverted_fields - end - row.instance_variable_set(:@unconverted_fields, fields) - row - end - end -end diff --git a/lib/csv/row.rb b/lib/csv/row.rb deleted file mode 100644 index 86323f7d0a7d4c..00000000000000 --- a/lib/csv/row.rb +++ /dev/null @@ -1,757 +0,0 @@ -# frozen_string_literal: true - -require "forwardable" - -class CSV - # = \CSV::Row - # A \CSV::Row instance represents a \CSV table row. - # (see {class CSV}[../CSV.html]). - # - # The instance may have: - # - Fields: each is an object, not necessarily a \String. - # - Headers: each serves a key, and also need not be a \String. - # - # === Instance Methods - # - # \CSV::Row has three groups of instance methods: - # - Its own internally defined instance methods. - # - Methods included by module Enumerable. - # - Methods delegated to class Array.: - # * Array#empty? - # * Array#length - # * Array#size - # - # == Creating a \CSV::Row Instance - # - # Commonly, a new \CSV::Row instance is created by parsing \CSV source - # that has headers: - # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # table = CSV.parse(source, headers: true) - # table.each {|row| p row } - # Output: - # # - # # - # # - # - # You can also create a row directly. See ::new. - # - # == Headers - # - # Like a \CSV::Table, a \CSV::Row has headers. - # - # A \CSV::Row that was created by parsing \CSV source - # inherits its headers from the table: - # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # table = CSV.parse(source, headers: true) - # row = table.first - # row.headers # => ["Name", "Value"] - # - # You can also create a new row with headers; - # like the keys in a \Hash, the headers need not be Strings: - # row = CSV::Row.new([:name, :value], ['foo', 0]) - # row.headers # => [:name, :value] - # - # The new row retains its headers even if added to a table - # that has headers: - # table << row # => # - # row.headers # => [:name, :value] - # row[:name] # => "foo" - # row['Name'] # => nil - # - # - # - # == Accessing Fields - # - # You may access a field in a \CSV::Row with either its \Integer index - # (\Array-style) or its header (\Hash-style). - # - # Fetch a field using method #[]: - # row = CSV::Row.new(['Name', 'Value'], ['foo', 0]) - # row[1] # => 0 - # row['Value'] # => 0 - # - # Set a field using method #[]=: - # row = CSV::Row.new(['Name', 'Value'], ['foo', 0]) - # row # => # - # row[0] = 'bar' - # row['Value'] = 1 - # row # => # - # - class Row - # :call-seq: - # CSV::Row.new(headers, fields, header_row = false) -> csv_row - # - # Returns the new \CSV::Row instance constructed from - # arguments +headers+ and +fields+; both should be Arrays; - # note that the fields need not be Strings: - # row = CSV::Row.new(['Name', 'Value'], ['foo', 0]) - # row # => # - # - # If the \Array lengths are different, the shorter is +nil+-filled: - # row = CSV::Row.new(['Name', 'Value', 'Date', 'Size'], ['foo', 0]) - # row # => # - # - # Each \CSV::Row object is either a field row or a header row; - # by default, a new row is a field row; for the row created above: - # row.field_row? # => true - # row.header_row? # => false - # - # If the optional argument +header_row+ is given as +true+, - # the created row is a header row: - # row = CSV::Row.new(['Name', 'Value'], ['foo', 0], header_row = true) - # row # => # - # row.field_row? # => false - # row.header_row? # => true - def initialize(headers, fields, header_row = false) - @header_row = header_row - headers.each { |h| h.freeze if h.is_a? String } - - # handle extra headers or fields - @row = if headers.size >= fields.size - headers.zip(fields) - else - fields.zip(headers).each(&:reverse!) - end - end - - # Internal data format used to compare equality. - attr_reader :row - protected :row - - ### Array Delegation ### - - extend Forwardable - def_delegators :@row, :empty?, :length, :size - - # :call-seq: - # row.initialize_copy(other_row) -> self - # - # Calls superclass method. - def initialize_copy(other) - super_return_value = super - @row = @row.collect(&:dup) - super_return_value - end - - # :call-seq: - # row.header_row? -> true or false - # - # Returns +true+ if this is a header row, +false+ otherwise. - def header_row? - @header_row - end - - # :call-seq: - # row.field_row? -> true or false - # - # Returns +true+ if this is a field row, +false+ otherwise. - def field_row? - not header_row? - end - - # :call-seq: - # row.headers -> array_of_headers - # - # Returns the headers for this row: - # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # table = CSV.parse(source, headers: true) - # row = table.first - # row.headers # => ["Name", "Value"] - def headers - @row.map(&:first) - end - - # :call-seq: - # field(index) -> value - # field(header) -> value - # field(header, offset) -> value - # - # Returns the field value for the given +index+ or +header+. - # - # --- - # - # Fetch field value by \Integer index: - # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # table = CSV.parse(source, headers: true) - # row = table[0] - # row.field(0) # => "foo" - # row.field(1) # => "bar" - # - # Counts backward from the last column if +index+ is negative: - # row.field(-1) # => "0" - # row.field(-2) # => "foo" - # - # Returns +nil+ if +index+ is out of range: - # row.field(2) # => nil - # row.field(-3) # => nil - # - # --- - # - # Fetch field value by header (first found): - # source = "Name,Name,Name\nFoo,Bar,Baz\n" - # table = CSV.parse(source, headers: true) - # row = table[0] - # row.field('Name') # => "Foo" - # - # Fetch field value by header, ignoring +offset+ leading fields: - # source = "Name,Name,Name\nFoo,Bar,Baz\n" - # table = CSV.parse(source, headers: true) - # row = table[0] - # row.field('Name', 2) # => "Baz" - # - # Returns +nil+ if the header does not exist. - def field(header_or_index, minimum_index = 0) - # locate the pair - finder = (header_or_index.is_a?(Integer) || header_or_index.is_a?(Range)) ? :[] : :assoc - pair = @row[minimum_index..-1].public_send(finder, header_or_index) - - # return the field if we have a pair - if pair.nil? - nil - else - header_or_index.is_a?(Range) ? pair.map(&:last) : pair.last - end - end - alias_method :[], :field - - # - # :call-seq: - # fetch(header) -> value - # fetch(header, default) -> value - # fetch(header) {|row| ... } -> value - # - # Returns the field value as specified by +header+. - # - # --- - # - # With the single argument +header+, returns the field value - # for that header (first found): - # source = "Name,Name,Name\nFoo,Bar,Baz\n" - # table = CSV.parse(source, headers: true) - # row = table[0] - # row.fetch('Name') # => "Foo" - # - # Raises exception +KeyError+ if the header does not exist. - # - # --- - # - # With arguments +header+ and +default+ given, - # returns the field value for the header (first found) - # if the header exists, otherwise returns +default+: - # source = "Name,Name,Name\nFoo,Bar,Baz\n" - # table = CSV.parse(source, headers: true) - # row = table[0] - # row.fetch('Name', '') # => "Foo" - # row.fetch(:nosuch, '') # => "" - # - # --- - # - # With argument +header+ and a block given, - # returns the field value for the header (first found) - # if the header exists; otherwise calls the block - # and returns its return value: - # source = "Name,Name,Name\nFoo,Bar,Baz\n" - # table = CSV.parse(source, headers: true) - # row = table[0] - # row.fetch('Name') {|header| fail 'Cannot happen' } # => "Foo" - # row.fetch(:nosuch) {|header| "Header '#{header} not found'" } # => "Header 'nosuch not found'" - def fetch(header, *varargs) - raise ArgumentError, "Too many arguments" if varargs.length > 1 - pair = @row.assoc(header) - if pair - pair.last - else - if block_given? - yield header - elsif varargs.empty? - raise KeyError, "key not found: #{header}" - else - varargs.first - end - end - end - - # :call-seq: - # row.has_key?(header) -> true or false - # - # Returns +true+ if there is a field with the given +header+, - # +false+ otherwise. - def has_key?(header) - !!@row.assoc(header) - end - alias_method :include?, :has_key? - alias_method :key?, :has_key? - alias_method :member?, :has_key? - alias_method :header?, :has_key? - - # - # :call-seq: - # row[index] = value -> value - # row[header, offset] = value -> value - # row[header] = value -> value - # - # Assigns the field value for the given +index+ or +header+; - # returns +value+. - # - # --- - # - # Assign field value by \Integer index: - # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # table = CSV.parse(source, headers: true) - # row = table[0] - # row[0] = 'Bat' - # row[1] = 3 - # row # => # - # - # Counts backward from the last column if +index+ is negative: - # row[-1] = 4 - # row[-2] = 'Bam' - # row # => # - # - # Extends the row with nil:nil if positive +index+ is not in the row: - # row[4] = 5 - # row # => # - # - # Raises IndexError if negative +index+ is too small (too far from zero). - # - # --- - # - # Assign field value by header (first found): - # source = "Name,Name,Name\nFoo,Bar,Baz\n" - # table = CSV.parse(source, headers: true) - # row = table[0] - # row['Name'] = 'Bat' - # row # => # - # - # Assign field value by header, ignoring +offset+ leading fields: - # source = "Name,Name,Name\nFoo,Bar,Baz\n" - # table = CSV.parse(source, headers: true) - # row = table[0] - # row['Name', 2] = 4 - # row # => # - # - # Append new field by (new) header: - # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # table = CSV.parse(source, headers: true) - # row = table[0] - # row['New'] = 6 - # row# => # - def []=(*args) - value = args.pop - - if args.first.is_a? Integer - if @row[args.first].nil? # extending past the end with index - @row[args.first] = [nil, value] - @row.map! { |pair| pair.nil? ? [nil, nil] : pair } - else # normal index assignment - @row[args.first][1] = value - end - else - index = index(*args) - if index.nil? # appending a field - self << [args.first, value] - else # normal header assignment - @row[index][1] = value - end - end - end - - # - # :call-seq: - # row << [header, value] -> self - # row << hash -> self - # row << value -> self - # - # Adds a field to +self+; returns +self+: - # - # If the argument is a 2-element \Array [header, value], - # a field is added with the given +header+ and +value+: - # source = "Name,Name,Name\nFoo,Bar,Baz\n" - # table = CSV.parse(source, headers: true) - # row = table[0] - # row << ['NAME', 'Bat'] - # row # => # - # - # If the argument is a \Hash, each key-value pair is added - # as a field with header +key+ and value +value+. - # source = "Name,Name,Name\nFoo,Bar,Baz\n" - # table = CSV.parse(source, headers: true) - # row = table[0] - # row << {NAME: 'Bat', name: 'Bam'} - # row # => # - # - # Otherwise, the given +value+ is added as a field with no header. - # source = "Name,Name,Name\nFoo,Bar,Baz\n" - # table = CSV.parse(source, headers: true) - # row = table[0] - # row << 'Bag' - # row # => # - def <<(arg) - if arg.is_a?(Array) and arg.size == 2 # appending a header and name - @row << arg - elsif arg.is_a?(Hash) # append header and name pairs - arg.each { |pair| @row << pair } - else # append field value - @row << [nil, arg] - end - - self # for chaining - end - - # :call-seq: - # row.push(*values) -> self - # - # Appends each of the given +values+ to +self+ as a field; returns +self+: - # source = "Name,Name,Name\nFoo,Bar,Baz\n" - # table = CSV.parse(source, headers: true) - # row = table[0] - # row.push('Bat', 'Bam') - # row # => # - def push(*args) - args.each { |arg| self << arg } - - self # for chaining - end - - # - # :call-seq: - # delete(index) -> [header, value] or nil - # delete(header) -> [header, value] or empty_array - # delete(header, offset) -> [header, value] or empty_array - # - # Removes a specified field from +self+; returns the 2-element \Array - # [header, value] if the field exists. - # - # If an \Integer argument +index+ is given, - # removes and returns the field at offset +index+, - # or returns +nil+ if the field does not exist: - # source = "Name,Name,Name\nFoo,Bar,Baz\n" - # table = CSV.parse(source, headers: true) - # row = table[0] - # row.delete(1) # => ["Name", "Bar"] - # row.delete(50) # => nil - # - # Otherwise, if the single argument +header+ is given, - # removes and returns the first-found field with the given header, - # of returns a new empty \Array if the field does not exist: - # source = "Name,Name,Name\nFoo,Bar,Baz\n" - # table = CSV.parse(source, headers: true) - # row = table[0] - # row.delete('Name') # => ["Name", "Foo"] - # row.delete('NAME') # => [] - # - # If argument +header+ and \Integer argument +offset+ are given, - # removes and returns the first-found field with the given header - # whose +index+ is at least as large as +offset+: - # source = "Name,Name,Name\nFoo,Bar,Baz\n" - # table = CSV.parse(source, headers: true) - # row = table[0] - # row.delete('Name', 1) # => ["Name", "Bar"] - # row.delete('NAME', 1) # => [] - def delete(header_or_index, minimum_index = 0) - if header_or_index.is_a? Integer # by index - @row.delete_at(header_or_index) - elsif i = index(header_or_index, minimum_index) # by header - @row.delete_at(i) - else - [ ] - end - end - - # :call-seq: - # row.delete_if {|header, value| ... } -> self - # - # Removes fields from +self+ as selected by the block; returns +self+. - # - # Removes each field for which the block returns a truthy value: - # source = "Name,Name,Name\nFoo,Bar,Baz\n" - # table = CSV.parse(source, headers: true) - # row = table[0] - # row.delete_if {|header, value| value.start_with?('B') } # => true - # row # => # - # row.delete_if {|header, value| header.start_with?('B') } # => false - # - # If no block is given, returns a new Enumerator: - # row.delete_if # => #:delete_if> - def delete_if(&block) - return enum_for(__method__) { size } unless block_given? - - @row.delete_if(&block) - - self # for chaining - end - - # :call-seq: - # self.fields(*specifiers) -> array_of_fields - # - # Returns field values per the given +specifiers+, which may be any mixture of: - # - \Integer index. - # - \Range of \Integer indexes. - # - 2-element \Array containing a header and offset. - # - Header. - # - \Range of headers. - # - # For +specifier+ in one of the first four cases above, - # returns the result of self.field(specifier); see #field. - # - # Although there may be any number of +specifiers+, - # the examples here will illustrate one at a time. - # - # When the specifier is an \Integer +index+, - # returns self.field(index)L - # source = "Name,Name,Name\nFoo,Bar,Baz\n" - # table = CSV.parse(source, headers: true) - # row = table[0] - # row.fields(1) # => ["Bar"] - # - # When the specifier is a \Range of \Integers +range+, - # returns self.field(range): - # row.fields(1..2) # => ["Bar", "Baz"] - # - # When the specifier is a 2-element \Array +array+, - # returns self.field(array)L - # row.fields('Name', 1) # => ["Foo", "Bar"] - # - # When the specifier is a header +header+, - # returns self.field(header)L - # row.fields('Name') # => ["Foo"] - # - # When the specifier is a \Range of headers +range+, - # forms a new \Range +new_range+ from the indexes of - # range.start and range.end, - # and returns self.field(new_range): - # source = "Name,NAME,name\nFoo,Bar,Baz\n" - # table = CSV.parse(source, headers: true) - # row = table[0] - # row.fields('Name'..'NAME') # => ["Foo", "Bar"] - # - # Returns all fields if no argument given: - # row.fields # => ["Foo", "Bar", "Baz"] - def fields(*headers_and_or_indices) - if headers_and_or_indices.empty? # return all fields--no arguments - @row.map(&:last) - else # or work like values_at() - all = [] - headers_and_or_indices.each do |h_or_i| - if h_or_i.is_a? Range - index_begin = h_or_i.begin.is_a?(Integer) ? h_or_i.begin : - index(h_or_i.begin) - index_end = h_or_i.end.is_a?(Integer) ? h_or_i.end : - index(h_or_i.end) - new_range = h_or_i.exclude_end? ? (index_begin...index_end) : - (index_begin..index_end) - all.concat(fields.values_at(new_range)) - else - all << field(*Array(h_or_i)) - end - end - return all - end - end - alias_method :values_at, :fields - - # :call-seq: - # index(header) -> index - # index(header, offset) -> index - # - # Returns the index for the given header, if it exists; - # otherwise returns +nil+. - # - # With the single argument +header+, returns the index - # of the first-found field with the given +header+: - # source = "Name,Name,Name\nFoo,Bar,Baz\n" - # table = CSV.parse(source, headers: true) - # row = table[0] - # row.index('Name') # => 0 - # row.index('NAME') # => nil - # - # With arguments +header+ and +offset+, - # returns the index of the first-found field with given +header+, - # but ignoring the first +offset+ fields: - # row.index('Name', 1) # => 1 - # row.index('Name', 3) # => nil - def index(header, minimum_index = 0) - # find the pair - index = headers[minimum_index..-1].index(header) - # return the index at the right offset, if we found one - index.nil? ? nil : index + minimum_index - end - - # :call-seq: - # row.field?(value) -> true or false - # - # Returns +true+ if +value+ is a field in this row, +false+ otherwise: - # source = "Name,Name,Name\nFoo,Bar,Baz\n" - # table = CSV.parse(source, headers: true) - # row = table[0] - # row.field?('Bar') # => true - # row.field?('BAR') # => false - def field?(data) - fields.include? data - end - - include Enumerable - - # :call-seq: - # row.each {|header, value| ... } -> self - # - # Calls the block with each header-value pair; returns +self+: - # source = "Name,Name,Name\nFoo,Bar,Baz\n" - # table = CSV.parse(source, headers: true) - # row = table[0] - # row.each {|header, value| p [header, value] } - # Output: - # ["Name", "Foo"] - # ["Name", "Bar"] - # ["Name", "Baz"] - # - # If no block is given, returns a new Enumerator: - # row.each # => #:each> - def each(&block) - return enum_for(__method__) { size } unless block_given? - - @row.each(&block) - - self # for chaining - end - - alias_method :each_pair, :each - - # :call-seq: - # row == other -> true or false - # - # Returns +true+ if +other+ is a /CSV::Row that has the same - # fields (headers and values) in the same order as +self+; - # otherwise returns +false+: - # source = "Name,Name,Name\nFoo,Bar,Baz\n" - # table = CSV.parse(source, headers: true) - # row = table[0] - # other_row = table[0] - # row == other_row # => true - # other_row = table[1] - # row == other_row # => false - def ==(other) - return @row == other.row if other.is_a? CSV::Row - @row == other - end - - # :call-seq: - # row.to_h -> hash - # - # Returns the new \Hash formed by adding each header-value pair in +self+ - # as a key-value pair in the \Hash. - # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # table = CSV.parse(source, headers: true) - # row = table[0] - # row.to_h # => {"Name"=>"foo", "Value"=>"0"} - # - # Header order is preserved, but repeated headers are ignored: - # source = "Name,Name,Name\nFoo,Bar,Baz\n" - # table = CSV.parse(source, headers: true) - # row = table[0] - # row.to_h # => {"Name"=>"Foo"} - def to_h - hash = {} - each do |key, _value| - hash[key] = self[key] unless hash.key?(key) - end - hash - end - alias_method :to_hash, :to_h - - # :call-seq: - # row.deconstruct_keys(keys) -> hash - # - # Returns the new \Hash suitable for pattern matching containing only the - # keys specified as an argument. - def deconstruct_keys(keys) - if keys.nil? - to_h - else - keys.to_h { |key| [key, self[key]] } - end - end - - alias_method :to_ary, :to_a - - # :call-seq: - # row.deconstruct -> array - # - # Returns the new \Array suitable for pattern matching containing the values - # of the row. - def deconstruct - fields - end - - # :call-seq: - # row.to_csv -> csv_string - # - # Returns the row as a \CSV String. Headers are not included: - # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # table = CSV.parse(source, headers: true) - # row = table[0] - # row.to_csv # => "foo,0\n" - def to_csv(**options) - fields.to_csv(**options) - end - alias_method :to_s, :to_csv - - # :call-seq: - # row.dig(index_or_header, *identifiers) -> object - # - # Finds and returns the object in nested object that is specified - # by +index_or_header+ and +specifiers+. - # - # The nested objects may be instances of various classes. - # See {Dig Methods}[rdoc-ref:dig_methods.rdoc]. - # - # Examples: - # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # table = CSV.parse(source, headers: true) - # row = table[0] - # row.dig(1) # => "0" - # row.dig('Value') # => "0" - # row.dig(5) # => nil - def dig(index_or_header, *indexes) - value = field(index_or_header) - if value.nil? - nil - elsif indexes.empty? - value - else - unless value.respond_to?(:dig) - raise TypeError, "#{value.class} does not have \#dig method" - end - value.dig(*indexes) - end - end - - # :call-seq: - # row.inspect -> string - # - # Returns an ASCII-compatible \String showing: - # - Class \CSV::Row. - # - Header-value pairs. - # Example: - # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # table = CSV.parse(source, headers: true) - # row = table[0] - # row.inspect # => "#" - def inspect - str = ["#<", self.class.to_s] - each do |header, field| - str << " " << (header.is_a?(Symbol) ? header.to_s : header.inspect) << - ":" << field.inspect - end - str << ">" - begin - str.join('') - rescue # any encoding error - str.map do |s| - e = Encoding::Converter.asciicompat_encoding(s.encoding) - e ? s.encode(e) : s.force_encoding("ASCII-8BIT") - end.join('') - end - end - end -end diff --git a/lib/csv/table.rb b/lib/csv/table.rb deleted file mode 100644 index fb19f5453f4435..00000000000000 --- a/lib/csv/table.rb +++ /dev/null @@ -1,1055 +0,0 @@ -# frozen_string_literal: true - -require "forwardable" - -class CSV - # = \CSV::Table - # A \CSV::Table instance represents \CSV data. - # (see {class CSV}[../CSV.html]). - # - # The instance may have: - # - Rows: each is a Table::Row object. - # - Headers: names for the columns. - # - # === Instance Methods - # - # \CSV::Table has three groups of instance methods: - # - Its own internally defined instance methods. - # - Methods included by module Enumerable. - # - Methods delegated to class Array.: - # * Array#empty? - # * Array#length - # * Array#size - # - # == Creating a \CSV::Table Instance - # - # Commonly, a new \CSV::Table instance is created by parsing \CSV source - # using headers: - # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # table = CSV.parse(source, headers: true) - # table.class # => CSV::Table - # - # You can also create an instance directly. See ::new. - # - # == Headers - # - # If a table has headers, the headers serve as labels for the columns of data. - # Each header serves as the label for its column. - # - # The headers for a \CSV::Table object are stored as an \Array of Strings. - # - # Commonly, headers are defined in the first row of \CSV source: - # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # table = CSV.parse(source, headers: true) - # table.headers # => ["Name", "Value"] - # - # If no headers are defined, the \Array is empty: - # table = CSV::Table.new([]) - # table.headers # => [] - # - # == Access Modes - # - # \CSV::Table provides three modes for accessing table data: - # - \Row mode. - # - Column mode. - # - Mixed mode (the default for a new table). - # - # The access mode for a\CSV::Table instance affects the behavior - # of some of its instance methods: - # - #[] - # - #[]= - # - #delete - # - #delete_if - # - #each - # - #values_at - # - # === \Row Mode - # - # Set a table to row mode with method #by_row!: - # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # table = CSV.parse(source, headers: true) - # table.by_row! # => # - # - # Specify a single row by an \Integer index: - # # Get a row. - # table[1] # => # - # # Set a row, then get it. - # table[1] = CSV::Row.new(['Name', 'Value'], ['bam', 3]) - # table[1] # => # - # - # Specify a sequence of rows by a \Range: - # # Get rows. - # table[1..2] # => [#, #] - # # Set rows, then get them. - # table[1..2] = [ - # CSV::Row.new(['Name', 'Value'], ['bat', 4]), - # CSV::Row.new(['Name', 'Value'], ['bad', 5]), - # ] - # table[1..2] # => [["Name", #], ["Value", #]] - # - # === Column Mode - # - # Set a table to column mode with method #by_col!: - # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # table = CSV.parse(source, headers: true) - # table.by_col! # => # - # - # Specify a column by an \Integer index: - # # Get a column. - # table[0] - # # Set a column, then get it. - # table[0] = ['FOO', 'BAR', 'BAZ'] - # table[0] # => ["FOO", "BAR", "BAZ"] - # - # Specify a column by its \String header: - # # Get a column. - # table['Name'] # => ["FOO", "BAR", "BAZ"] - # # Set a column, then get it. - # table['Name'] = ['Foo', 'Bar', 'Baz'] - # table['Name'] # => ["Foo", "Bar", "Baz"] - # - # === Mixed Mode - # - # In mixed mode, you can refer to either rows or columns: - # - An \Integer index refers to a row. - # - A \Range index refers to multiple rows. - # - A \String index refers to a column. - # - # Set a table to mixed mode with method #by_col_or_row!: - # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # table = CSV.parse(source, headers: true) - # table.by_col_or_row! # => # - # - # Specify a single row by an \Integer index: - # # Get a row. - # table[1] # => # - # # Set a row, then get it. - # table[1] = CSV::Row.new(['Name', 'Value'], ['bam', 3]) - # table[1] # => # - # - # Specify a sequence of rows by a \Range: - # # Get rows. - # table[1..2] # => [#, #] - # # Set rows, then get them. - # table[1] = CSV::Row.new(['Name', 'Value'], ['bat', 4]) - # table[2] = CSV::Row.new(['Name', 'Value'], ['bad', 5]) - # table[1..2] # => [["Name", #], ["Value", #]] - # - # Specify a column by its \String header: - # # Get a column. - # table['Name'] # => ["foo", "bat", "bad"] - # # Set a column, then get it. - # table['Name'] = ['Foo', 'Bar', 'Baz'] - # table['Name'] # => ["Foo", "Bar", "Baz"] - class Table - # :call-seq: - # CSV::Table.new(array_of_rows, headers = nil) -> csv_table - # - # Returns a new \CSV::Table object. - # - # - Argument +array_of_rows+ must be an \Array of CSV::Row objects. - # - Argument +headers+, if given, may be an \Array of Strings. - # - # --- - # - # Create an empty \CSV::Table object: - # table = CSV::Table.new([]) - # table # => # - # - # Create a non-empty \CSV::Table object: - # rows = [ - # CSV::Row.new([], []), - # CSV::Row.new([], []), - # CSV::Row.new([], []), - # ] - # table = CSV::Table.new(rows) - # table # => # - # - # --- - # - # If argument +headers+ is an \Array of Strings, - # those Strings become the table's headers: - # table = CSV::Table.new([], headers: ['Name', 'Age']) - # table.headers # => ["Name", "Age"] - # - # If argument +headers+ is not given and the table has rows, - # the headers are taken from the first row: - # rows = [ - # CSV::Row.new(['Foo', 'Bar'], []), - # CSV::Row.new(['foo', 'bar'], []), - # CSV::Row.new(['FOO', 'BAR'], []), - # ] - # table = CSV::Table.new(rows) - # table.headers # => ["Foo", "Bar"] - # - # If argument +headers+ is not given and the table is empty (has no rows), - # the headers are also empty: - # table = CSV::Table.new([]) - # table.headers # => [] - # - # --- - # - # Raises an exception if argument +array_of_rows+ is not an \Array object: - # # Raises NoMethodError (undefined method `first' for :foo:Symbol): - # CSV::Table.new(:foo) - # - # Raises an exception if an element of +array_of_rows+ is not a \CSV::Table object: - # # Raises NoMethodError (undefined method `headers' for :foo:Symbol): - # CSV::Table.new([:foo]) - def initialize(array_of_rows, headers: nil) - @table = array_of_rows - @headers = headers - unless @headers - if @table.empty? - @headers = [] - else - @headers = @table.first.headers - end - end - - @mode = :col_or_row - end - - # The current access mode for indexing and iteration. - attr_reader :mode - - # Internal data format used to compare equality. - attr_reader :table - protected :table - - ### Array Delegation ### - - extend Forwardable - def_delegators :@table, :empty?, :length, :size - - # :call-seq: - # table.by_col -> table_dup - # - # Returns a duplicate of +self+, in column mode - # (see {Column Mode}[#class-CSV::Table-label-Column+Mode]): - # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # table = CSV.parse(source, headers: true) - # table.mode # => :col_or_row - # dup_table = table.by_col - # dup_table.mode # => :col - # dup_table.equal?(table) # => false # It's a dup - # - # This may be used to chain method calls without changing the mode - # (but also will affect performance and memory usage): - # dup_table.by_col['Name'] - # - # Also note that changes to the duplicate table will not affect the original. - def by_col - self.class.new(@table.dup).by_col! - end - - # :call-seq: - # table.by_col! -> self - # - # Sets the mode for +self+ to column mode - # (see {Column Mode}[#class-CSV::Table-label-Column+Mode]); returns +self+: - # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # table = CSV.parse(source, headers: true) - # table.mode # => :col_or_row - # table1 = table.by_col! - # table.mode # => :col - # table1.equal?(table) # => true # Returned self - def by_col! - @mode = :col - - self - end - - # :call-seq: - # table.by_col_or_row -> table_dup - # - # Returns a duplicate of +self+, in mixed mode - # (see {Mixed Mode}[#class-CSV::Table-label-Mixed+Mode]): - # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # table = CSV.parse(source, headers: true).by_col! - # table.mode # => :col - # dup_table = table.by_col_or_row - # dup_table.mode # => :col_or_row - # dup_table.equal?(table) # => false # It's a dup - # - # This may be used to chain method calls without changing the mode - # (but also will affect performance and memory usage): - # dup_table.by_col_or_row['Name'] - # - # Also note that changes to the duplicate table will not affect the original. - def by_col_or_row - self.class.new(@table.dup).by_col_or_row! - end - - # :call-seq: - # table.by_col_or_row! -> self - # - # Sets the mode for +self+ to mixed mode - # (see {Mixed Mode}[#class-CSV::Table-label-Mixed+Mode]); returns +self+: - # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # table = CSV.parse(source, headers: true).by_col! - # table.mode # => :col - # table1 = table.by_col_or_row! - # table.mode # => :col_or_row - # table1.equal?(table) # => true # Returned self - def by_col_or_row! - @mode = :col_or_row - - self - end - - # :call-seq: - # table.by_row -> table_dup - # - # Returns a duplicate of +self+, in row mode - # (see {Row Mode}[#class-CSV::Table-label-Row+Mode]): - # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # table = CSV.parse(source, headers: true) - # table.mode # => :col_or_row - # dup_table = table.by_row - # dup_table.mode # => :row - # dup_table.equal?(table) # => false # It's a dup - # - # This may be used to chain method calls without changing the mode - # (but also will affect performance and memory usage): - # dup_table.by_row[1] - # - # Also note that changes to the duplicate table will not affect the original. - def by_row - self.class.new(@table.dup).by_row! - end - - # :call-seq: - # table.by_row! -> self - # - # Sets the mode for +self+ to row mode - # (see {Row Mode}[#class-CSV::Table-label-Row+Mode]); returns +self+: - # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # table = CSV.parse(source, headers: true) - # table.mode # => :col_or_row - # table1 = table.by_row! - # table.mode # => :row - # table1.equal?(table) # => true # Returned self - def by_row! - @mode = :row - - self - end - - # :call-seq: - # table.headers -> array_of_headers - # - # Returns a new \Array containing the \String headers for the table. - # - # If the table is not empty, returns the headers from the first row: - # rows = [ - # CSV::Row.new(['Foo', 'Bar'], []), - # CSV::Row.new(['FOO', 'BAR'], []), - # CSV::Row.new(['foo', 'bar'], []), - # ] - # table = CSV::Table.new(rows) - # table.headers # => ["Foo", "Bar"] - # table.delete(0) - # table.headers # => ["FOO", "BAR"] - # table.delete(0) - # table.headers # => ["foo", "bar"] - # - # If the table is empty, returns a copy of the headers in the table itself: - # table.delete(0) - # table.headers # => ["Foo", "Bar"] - def headers - if @table.empty? - @headers.dup - else - @table.first.headers - end - end - - # :call-seq: - # table[n] -> row or column_data - # table[range] -> array_of_rows or array_of_column_data - # table[header] -> array_of_column_data - # - # Returns data from the table; does not modify the table. - # - # --- - # - # Fetch a \Row by Its \Integer Index:: - # - Form: table[n], +n+ an integer. - # - Access mode: :row or :col_or_row. - # - Return value: _nth_ row of the table, if that row exists; - # otherwise +nil+. - # - # Returns the _nth_ row of the table if that row exists: - # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # table = CSV.parse(source, headers: true) - # table.by_row! # => # - # table[1] # => # - # table.by_col_or_row! # => # - # table[1] # => # - # - # Counts backward from the last row if +n+ is negative: - # table[-1] # => # - # - # Returns +nil+ if +n+ is too large or too small: - # table[4] # => nil - # table[-4] # => nil - # - # Raises an exception if the access mode is :row - # and +n+ is not an \Integer: - # table.by_row! # => # - # # Raises TypeError (no implicit conversion of String into Integer): - # table['Name'] - # - # --- - # - # Fetch a Column by Its \Integer Index:: - # - Form: table[n], +n+ an \Integer. - # - Access mode: :col. - # - Return value: _nth_ column of the table, if that column exists; - # otherwise an \Array of +nil+ fields of length self.size. - # - # Returns the _nth_ column of the table if that column exists: - # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # table = CSV.parse(source, headers: true) - # table.by_col! # => # - # table[1] # => ["0", "1", "2"] - # - # Counts backward from the last column if +n+ is negative: - # table[-2] # => ["foo", "bar", "baz"] - # - # Returns an \Array of +nil+ fields if +n+ is too large or too small: - # table[4] # => [nil, nil, nil] - # table[-4] # => [nil, nil, nil] - # - # --- - # - # Fetch Rows by \Range:: - # - Form: table[range], +range+ a \Range object. - # - Access mode: :row or :col_or_row. - # - Return value: rows from the table, beginning at row range.start, - # if those rows exists. - # - # Returns rows from the table, beginning at row range.first, - # if those rows exist: - # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # table = CSV.parse(source, headers: true) - # table.by_row! # => # - # rows = table[1..2] # => # - # rows # => [#, #] - # table.by_col_or_row! # => # - # rows = table[1..2] # => # - # rows # => [#, #] - # - # If there are too few rows, returns all from range.start to the end: - # rows = table[1..50] # => # - # rows # => [#, #] - # - # Special case: if range.start == table.size, returns an empty \Array: - # table[table.size..50] # => [] - # - # If range.end is negative, calculates the ending index from the end: - # rows = table[0..-1] - # rows # => [#, #, #] - # - # If range.start is negative, calculates the starting index from the end: - # rows = table[-1..2] - # rows # => [#] - # - # If range.start is larger than table.size, returns +nil+: - # table[4..4] # => nil - # - # --- - # - # Fetch Columns by \Range:: - # - Form: table[range], +range+ a \Range object. - # - Access mode: :col. - # - Return value: column data from the table, beginning at column range.start, - # if those columns exist. - # - # Returns column values from the table, if the column exists; - # the values are arranged by row: - # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # table = CSV.parse(source, headers: true) - # table.by_col! - # table[0..1] # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] - # - # Special case: if range.start == headers.size, - # returns an \Array (size: table.size) of empty \Arrays: - # table[table.headers.size..50] # => [[], [], []] - # - # If range.end is negative, calculates the ending index from the end: - # table[0..-1] # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] - # - # If range.start is negative, calculates the starting index from the end: - # table[-2..2] # => [["foo", "0"], ["bar", "1"], ["baz", "2"]] - # - # If range.start is larger than table.size, - # returns an \Array of +nil+ values: - # table[4..4] # => [nil, nil, nil] - # - # --- - # - # Fetch a Column by Its \String Header:: - # - Form: table[header], +header+ a \String header. - # - Access mode: :col or :col_or_row - # - Return value: column data from the table, if that +header+ exists. - # - # Returns column values from the table, if the column exists: - # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # table = CSV.parse(source, headers: true) - # table.by_col! # => # - # table['Name'] # => ["foo", "bar", "baz"] - # table.by_col_or_row! # => # - # col = table['Name'] - # col # => ["foo", "bar", "baz"] - # - # Modifying the returned column values does not modify the table: - # col[0] = 'bat' - # col # => ["bat", "bar", "baz"] - # table['Name'] # => ["foo", "bar", "baz"] - # - # Returns an \Array of +nil+ values if there is no such column: - # table['Nosuch'] # => [nil, nil, nil] - def [](index_or_header) - if @mode == :row or # by index - (@mode == :col_or_row and (index_or_header.is_a?(Integer) or index_or_header.is_a?(Range))) - @table[index_or_header] - else # by header - @table.map { |row| row[index_or_header] } - end - end - - # :call-seq: - # table[n] = row -> row - # table[n] = field_or_array_of_fields -> field_or_array_of_fields - # table[header] = field_or_array_of_fields -> field_or_array_of_fields - # - # Puts data onto the table. - # - # --- - # - # Set a \Row by Its \Integer Index:: - # - Form: table[n] = row, +n+ an \Integer, - # +row+ a \CSV::Row instance or an \Array of fields. - # - Access mode: :row or :col_or_row. - # - Return value: +row+. - # - # If the row exists, it is replaced: - # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # table = CSV.parse(source, headers: true) - # new_row = CSV::Row.new(['Name', 'Value'], ['bat', 3]) - # table.by_row! # => # - # return_value = table[0] = new_row - # return_value.equal?(new_row) # => true # Returned the row - # table[0].to_h # => {"Name"=>"bat", "Value"=>3} - # - # With access mode :col_or_row: - # table.by_col_or_row! # => # - # table[0] = CSV::Row.new(['Name', 'Value'], ['bam', 4]) - # table[0].to_h # => {"Name"=>"bam", "Value"=>4} - # - # With an \Array instead of a \CSV::Row, inherits headers from the table: - # array = ['bad', 5] - # return_value = table[0] = array - # return_value.equal?(array) # => true # Returned the array - # table[0].to_h # => {"Name"=>"bad", "Value"=>5} - # - # If the row does not exist, extends the table by adding rows: - # assigns rows with +nil+ as needed: - # table.size # => 3 - # table[5] = ['bag', 6] - # table.size # => 6 - # table[3] # => nil - # table[4]# => nil - # table[5].to_h # => {"Name"=>"bag", "Value"=>6} - # - # Note that the +nil+ rows are actually +nil+, not a row of +nil+ fields. - # - # --- - # - # Set a Column by Its \Integer Index:: - # - Form: table[n] = array_of_fields, +n+ an \Integer, - # +array_of_fields+ an \Array of \String fields. - # - Access mode: :col. - # - Return value: +array_of_fields+. - # - # If the column exists, it is replaced: - # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # table = CSV.parse(source, headers: true) - # new_col = [3, 4, 5] - # table.by_col! # => # - # return_value = table[1] = new_col - # return_value.equal?(new_col) # => true # Returned the column - # table[1] # => [3, 4, 5] - # # The rows, as revised: - # table.by_row! # => # - # table[0].to_h # => {"Name"=>"foo", "Value"=>3} - # table[1].to_h # => {"Name"=>"bar", "Value"=>4} - # table[2].to_h # => {"Name"=>"baz", "Value"=>5} - # table.by_col! # => # - # - # If there are too few values, fills with +nil+ values: - # table[1] = [0] - # table[1] # => [0, nil, nil] - # - # If there are too many values, ignores the extra values: - # table[1] = [0, 1, 2, 3, 4] - # table[1] # => [0, 1, 2] - # - # If a single value is given, replaces all fields in the column with that value: - # table[1] = 'bat' - # table[1] # => ["bat", "bat", "bat"] - # - # --- - # - # Set a Column by Its \String Header:: - # - Form: table[header] = field_or_array_of_fields, - # +header+ a \String header, +field_or_array_of_fields+ a field value - # or an \Array of \String fields. - # - Access mode: :col or :col_or_row. - # - Return value: +field_or_array_of_fields+. - # - # If the column exists, it is replaced: - # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # table = CSV.parse(source, headers: true) - # new_col = [3, 4, 5] - # table.by_col! # => # - # return_value = table['Value'] = new_col - # return_value.equal?(new_col) # => true # Returned the column - # table['Value'] # => [3, 4, 5] - # # The rows, as revised: - # table.by_row! # => # - # table[0].to_h # => {"Name"=>"foo", "Value"=>3} - # table[1].to_h # => {"Name"=>"bar", "Value"=>4} - # table[2].to_h # => {"Name"=>"baz", "Value"=>5} - # table.by_col! # => # - # - # If there are too few values, fills with +nil+ values: - # table['Value'] = [0] - # table['Value'] # => [0, nil, nil] - # - # If there are too many values, ignores the extra values: - # table['Value'] = [0, 1, 2, 3, 4] - # table['Value'] # => [0, 1, 2] - # - # If the column does not exist, extends the table by adding columns: - # table['Note'] = ['x', 'y', 'z'] - # table['Note'] # => ["x", "y", "z"] - # # The rows, as revised: - # table.by_row! - # table[0].to_h # => {"Name"=>"foo", "Value"=>0, "Note"=>"x"} - # table[1].to_h # => {"Name"=>"bar", "Value"=>1, "Note"=>"y"} - # table[2].to_h # => {"Name"=>"baz", "Value"=>2, "Note"=>"z"} - # table.by_col! - # - # If a single value is given, replaces all fields in the column with that value: - # table['Value'] = 'bat' - # table['Value'] # => ["bat", "bat", "bat"] - def []=(index_or_header, value) - if @mode == :row or # by index - (@mode == :col_or_row and index_or_header.is_a? Integer) - if value.is_a? Array - @table[index_or_header] = Row.new(headers, value) - else - @table[index_or_header] = value - end - else # set column - unless index_or_header.is_a? Integer - index = @headers.index(index_or_header) || @headers.size - @headers[index] = index_or_header - end - if value.is_a? Array # multiple values - @table.each_with_index do |row, i| - if row.header_row? - row[index_or_header] = index_or_header - else - row[index_or_header] = value[i] - end - end - else # repeated value - @table.each do |row| - if row.header_row? - row[index_or_header] = index_or_header - else - row[index_or_header] = value - end - end - end - end - end - - # :call-seq: - # table.values_at(*indexes) -> array_of_rows - # table.values_at(*headers) -> array_of_columns_data - # - # If the access mode is :row or :col_or_row, - # and each argument is either an \Integer or a \Range, - # returns rows. - # Otherwise, returns columns data. - # - # In either case, the returned values are in the order - # specified by the arguments. Arguments may be repeated. - # - # --- - # - # Returns rows as an \Array of \CSV::Row objects. - # - # No argument: - # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # table = CSV.parse(source, headers: true) - # table.values_at # => [] - # - # One index: - # values = table.values_at(0) - # values # => [#] - # - # Two indexes: - # values = table.values_at(2, 0) - # values # => [#, #] - # - # One \Range: - # values = table.values_at(1..2) - # values # => [#, #] - # - # \Ranges and indexes: - # values = table.values_at(0..1, 1..2, 0, 2) - # pp values - # Output: - # [#, - # #, - # #, - # #, - # #, - # #] - # - # --- - # - # Returns columns data as row Arrays, - # each consisting of the specified columns data for that row: - # values = table.values_at('Name') - # values # => [["foo"], ["bar"], ["baz"]] - # values = table.values_at('Value', 'Name') - # values # => [["0", "foo"], ["1", "bar"], ["2", "baz"]] - def values_at(*indices_or_headers) - if @mode == :row or # by indices - ( @mode == :col_or_row and indices_or_headers.all? do |index| - index.is_a?(Integer) or - ( index.is_a?(Range) and - index.first.is_a?(Integer) and - index.last.is_a?(Integer) ) - end ) - @table.values_at(*indices_or_headers) - else # by headers - @table.map { |row| row.values_at(*indices_or_headers) } - end - end - - # :call-seq: - # table << row_or_array -> self - # - # If +row_or_array+ is a \CSV::Row object, - # it is appended to the table: - # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # table = CSV.parse(source, headers: true) - # table << CSV::Row.new(table.headers, ['bat', 3]) - # table[3] # => # - # - # If +row_or_array+ is an \Array, it is used to create a new - # \CSV::Row object which is then appended to the table: - # table << ['bam', 4] - # table[4] # => # - def <<(row_or_array) - if row_or_array.is_a? Array # append Array - @table << Row.new(headers, row_or_array) - else # append Row - @table << row_or_array - end - - self # for chaining - end - - # - # :call-seq: - # table.push(*rows_or_arrays) -> self - # - # A shortcut for appending multiple rows. Equivalent to: - # rows.each {|row| self << row } - # - # Each argument may be either a \CSV::Row object or an \Array: - # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # table = CSV.parse(source, headers: true) - # rows = [ - # CSV::Row.new(table.headers, ['bat', 3]), - # ['bam', 4] - # ] - # table.push(*rows) - # table[3..4] # => [#, #] - def push(*rows) - rows.each { |row| self << row } - - self # for chaining - end - - # :call-seq: - # table.delete(*indexes) -> deleted_values - # table.delete(*headers) -> deleted_values - # - # If the access mode is :row or :col_or_row, - # and each argument is either an \Integer or a \Range, - # returns deleted rows. - # Otherwise, returns deleted columns data. - # - # In either case, the returned values are in the order - # specified by the arguments. Arguments may be repeated. - # - # --- - # - # Returns rows as an \Array of \CSV::Row objects. - # - # One index: - # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # table = CSV.parse(source, headers: true) - # deleted_values = table.delete(0) - # deleted_values # => [#] - # - # Two indexes: - # table = CSV.parse(source, headers: true) - # deleted_values = table.delete(2, 0) - # deleted_values # => [#, #] - # - # --- - # - # Returns columns data as column Arrays. - # - # One header: - # table = CSV.parse(source, headers: true) - # deleted_values = table.delete('Name') - # deleted_values # => ["foo", "bar", "baz"] - # - # Two headers: - # table = CSV.parse(source, headers: true) - # deleted_values = table.delete('Value', 'Name') - # deleted_values # => [["0", "1", "2"], ["foo", "bar", "baz"]] - def delete(*indexes_or_headers) - if indexes_or_headers.empty? - raise ArgumentError, "wrong number of arguments (given 0, expected 1+)" - end - deleted_values = indexes_or_headers.map do |index_or_header| - if @mode == :row or # by index - (@mode == :col_or_row and index_or_header.is_a? Integer) - @table.delete_at(index_or_header) - else # by header - if index_or_header.is_a? Integer - @headers.delete_at(index_or_header) - else - @headers.delete(index_or_header) - end - @table.map { |row| row.delete(index_or_header).last } - end - end - if indexes_or_headers.size == 1 - deleted_values[0] - else - deleted_values - end - end - - # :call-seq: - # table.delete_if {|row_or_column| ... } -> self - # - # Removes rows or columns for which the block returns a truthy value; - # returns +self+. - # - # Removes rows when the access mode is :row or :col_or_row; - # calls the block with each \CSV::Row object: - # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # table = CSV.parse(source, headers: true) - # table.by_row! # => # - # table.size # => 3 - # table.delete_if {|row| row['Name'].start_with?('b') } - # table.size # => 1 - # - # Removes columns when the access mode is :col; - # calls the block with each column as a 2-element array - # containing the header and an \Array of column fields: - # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # table = CSV.parse(source, headers: true) - # table.by_col! # => # - # table.headers.size # => 2 - # table.delete_if {|column_data| column_data[1].include?('2') } - # table.headers.size # => 1 - # - # Returns a new \Enumerator if no block is given: - # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # table = CSV.parse(source, headers: true) - # table.delete_if # => #:delete_if> - def delete_if(&block) - return enum_for(__method__) { @mode == :row or @mode == :col_or_row ? size : headers.size } unless block_given? - - if @mode == :row or @mode == :col_or_row # by index - @table.delete_if(&block) - else # by header - headers.each do |header| - delete(header) if yield([header, self[header]]) - end - end - - self # for chaining - end - - include Enumerable - - # :call-seq: - # table.each {|row_or_column| ... ) -> self - # - # Calls the block with each row or column; returns +self+. - # - # When the access mode is :row or :col_or_row, - # calls the block with each \CSV::Row object: - # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # table = CSV.parse(source, headers: true) - # table.by_row! # => # - # table.each {|row| p row } - # Output: - # # - # # - # # - # - # When the access mode is :col, - # calls the block with each column as a 2-element array - # containing the header and an \Array of column fields: - # table.by_col! # => # - # table.each {|column_data| p column_data } - # Output: - # ["Name", ["foo", "bar", "baz"]] - # ["Value", ["0", "1", "2"]] - # - # Returns a new \Enumerator if no block is given: - # table.each # => #:each> - def each(&block) - return enum_for(__method__) { @mode == :col ? headers.size : size } unless block_given? - - if @mode == :col - headers.each.with_index do |header, i| - yield([header, @table.map {|row| row[header, i]}]) - end - else - @table.each(&block) - end - - self # for chaining - end - - # :call-seq: - # table == other_table -> true or false - # - # Returns +true+ if all each row of +self+ == - # the corresponding row of +other_table+, otherwise, +false+. - # - # The access mode does no affect the result. - # - # Equal tables: - # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # table = CSV.parse(source, headers: true) - # other_table = CSV.parse(source, headers: true) - # table == other_table # => true - # - # Different row count: - # other_table.delete(2) - # table == other_table # => false - # - # Different last row: - # other_table << ['bat', 3] - # table == other_table # => false - def ==(other) - return @table == other.table if other.is_a? CSV::Table - @table == other - end - - # :call-seq: - # table.to_a -> array_of_arrays - # - # Returns the table as an \Array of \Arrays; - # the headers are in the first row: - # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # table = CSV.parse(source, headers: true) - # table.to_a # => [["Name", "Value"], ["foo", "0"], ["bar", "1"], ["baz", "2"]] - def to_a - array = [headers] - @table.each do |row| - array.push(row.fields) unless row.header_row? - end - - array - end - - # :call-seq: - # table.to_csv(**options) -> csv_string - # - # Returns the table as \CSV string. - # See {Options for Generating}[../CSV.html#class-CSV-label-Options+for+Generating]. - # - # Defaults option +write_headers+ to +true+: - # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # table = CSV.parse(source, headers: true) - # table.to_csv # => "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # - # Omits the headers if option +write_headers+ is given as +false+ - # (see {Option +write_headers+}[../CSV.html#class-CSV-label-Option+write_headers]): - # table.to_csv(write_headers: false) # => "foo,0\nbar,1\nbaz,2\n" - # - # Limit rows if option +limit+ is given like +2+: - # table.to_csv(limit: 2) # => "Name,Value\nfoo,0\nbar,1\n" - def to_csv(write_headers: true, limit: nil, **options) - array = write_headers ? [headers.to_csv(**options)] : [] - limit ||= @table.size - limit = @table.size + 1 + limit if limit < 0 - limit = 0 if limit < 0 - @table.first(limit).each do |row| - array.push(row.fields.to_csv(**options)) unless row.header_row? - end - - array.join("") - end - alias_method :to_s, :to_csv - - # - # Extracts the nested value specified by the sequence of +index+ or +header+ objects by calling dig at each step, - # returning nil if any intermediate step is nil. - # - def dig(index_or_header, *index_or_headers) - value = self[index_or_header] - if value.nil? - nil - elsif index_or_headers.empty? - value - else - unless value.respond_to?(:dig) - raise TypeError, "#{value.class} does not have \#dig method" - end - value.dig(*index_or_headers) - end - end - - # :call-seq: - # table.inspect => string - # - # Returns a US-ASCII-encoded \String showing table: - # - Class: CSV::Table. - # - Access mode: :row, :col, or :col_or_row. - # - Size: Row count, including the header row. - # - # Example: - # source = "Name,Value\nfoo,0\nbar,1\nbaz,2\n" - # table = CSV.parse(source, headers: true) - # table.inspect # => "#\nName,Value\nfoo,0\nbar,1\nbaz,2\n" - # - def inspect - inspected = +"#<#{self.class} mode:#{@mode} row_count:#{to_a.size}>" - summary = to_csv(limit: 5) - inspected << "\n" << summary if summary.encoding.ascii_compatible? - inspected - end - end -end diff --git a/lib/csv/version.rb b/lib/csv/version.rb deleted file mode 100644 index 9c65803a34e35c..00000000000000 --- a/lib/csv/version.rb +++ /dev/null @@ -1,6 +0,0 @@ -# frozen_string_literal: true - -class CSV - # The version of the installed library. - VERSION = "3.2.8" -end diff --git a/lib/csv/writer.rb b/lib/csv/writer.rb deleted file mode 100644 index 030a295bc9adc0..00000000000000 --- a/lib/csv/writer.rb +++ /dev/null @@ -1,210 +0,0 @@ -# frozen_string_literal: true - -require_relative "input_record_separator" -require_relative "row" - -class CSV - # Note: Don't use this class directly. This is an internal class. - class Writer - # - # A CSV::Writer receives an output, prepares the header, format and output. - # It allows us to write new rows in the object and rewind it. - # - attr_reader :lineno - attr_reader :headers - - def initialize(output, options) - @output = output - @options = options - @lineno = 0 - @fields_converter = nil - prepare - if @options[:write_headers] and @headers - self << @headers - end - @fields_converter = @options[:fields_converter] - end - - # - # Adds a new row - # - def <<(row) - case row - when Row - row = row.fields - when Hash - row = @headers.collect {|header| row[header]} - end - - @headers ||= row if @use_headers - @lineno += 1 - - if @fields_converter - quoted_fields = [false] * row.size - row = @fields_converter.convert(row, nil, lineno, quoted_fields) - end - - i = -1 - converted_row = row.collect do |field| - i += 1 - quote(field, i) - end - line = converted_row.join(@column_separator) + @row_separator - if @output_encoding - line = line.encode(@output_encoding) - end - @output << line - - self - end - - # - # Winds back to the beginning - # - def rewind - @lineno = 0 - @headers = nil if @options[:headers].nil? - end - - private - def prepare - @encoding = @options[:encoding] - - prepare_header - prepare_format - prepare_output - end - - def prepare_header - headers = @options[:headers] - case headers - when Array - @headers = headers - @use_headers = true - when String - @headers = CSV.parse_line(headers, - col_sep: @options[:column_separator], - row_sep: @options[:row_separator], - quote_char: @options[:quote_character]) - @use_headers = true - when true - @headers = nil - @use_headers = true - else - @headers = nil - @use_headers = false - end - return unless @headers - - converter = @options[:header_fields_converter] - @headers = converter.convert(@headers, nil, 0, []) - @headers.each do |header| - header.freeze if header.is_a?(String) - end - end - - def prepare_force_quotes_fields(force_quotes) - @force_quotes_fields = {} - force_quotes.each do |name_or_index| - case name_or_index - when Integer - index = name_or_index - @force_quotes_fields[index] = true - when String, Symbol - name = name_or_index.to_s - if @headers.nil? - message = ":headers is required when you use field name " + - "in :force_quotes: " + - "#{name_or_index.inspect}: #{force_quotes.inspect}" - raise ArgumentError, message - end - index = @headers.index(name) - next if index.nil? - @force_quotes_fields[index] = true - else - message = ":force_quotes element must be " + - "field index or field name: " + - "#{name_or_index.inspect}: #{force_quotes.inspect}" - raise ArgumentError, message - end - end - end - - def prepare_format - @column_separator = @options[:column_separator].to_s.encode(@encoding) - row_separator = @options[:row_separator] - if row_separator == :auto - @row_separator = InputRecordSeparator.value.encode(@encoding) - else - @row_separator = row_separator.to_s.encode(@encoding) - end - @quote_character = @options[:quote_character] - force_quotes = @options[:force_quotes] - if force_quotes.is_a?(Array) - prepare_force_quotes_fields(force_quotes) - @force_quotes = false - elsif force_quotes - @force_quotes_fields = nil - @force_quotes = true - else - @force_quotes_fields = nil - @force_quotes = false - end - unless @force_quotes - @quotable_pattern = - Regexp.new("[\r\n".encode(@encoding) + - Regexp.escape(@column_separator) + - Regexp.escape(@quote_character.encode(@encoding)) + - "]".encode(@encoding)) - end - @quote_empty = @options.fetch(:quote_empty, true) - end - - def prepare_output - @output_encoding = nil - return unless @output.is_a?(StringIO) - - output_encoding = @output.internal_encoding || @output.external_encoding - if @encoding != output_encoding - if @options[:force_encoding] - @output_encoding = output_encoding - else - compatible_encoding = Encoding.compatible?(@encoding, output_encoding) - if compatible_encoding - @output.set_encoding(compatible_encoding) - @output.seek(0, IO::SEEK_END) - end - end - end - end - - def quote_field(field) - field = String(field) - encoded_quote_character = @quote_character.encode(field.encoding) - encoded_quote_character + - field.gsub(encoded_quote_character, - encoded_quote_character * 2) + - encoded_quote_character - end - - def quote(field, i) - if @force_quotes - quote_field(field) - elsif @force_quotes_fields and @force_quotes_fields[i] - quote_field(field) - else - if field.nil? # represent +nil+ fields as empty unquoted fields - "" - else - field = String(field) # Stringify fields - # represent empty fields as empty quoted fields - if (@quote_empty and field.empty?) or (field.valid_encoding? and @quotable_pattern.match?(field)) - quote_field(field) - else - field # unquoted field - end - end - end - end - end -end diff --git a/lib/delegate.gemspec b/lib/delegate.gemspec index 6c3feac74b505a..f7fcc1ceb9d20e 100644 --- a/lib/delegate.gemspec +++ b/lib/delegate.gemspec @@ -25,5 +25,5 @@ Gem::Specification.new do |spec| `git ls-files -z 2>#{IO::NULL}`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) } end spec.require_paths = ["lib"] - spec.required_ruby_version = '>= 2.7' + spec.required_ruby_version = '>= 3.0' end diff --git a/lib/delegate.rb b/lib/delegate.rb index 387a5f063ddb84..824d02f28b0946 100644 --- a/lib/delegate.rb +++ b/lib/delegate.rb @@ -39,7 +39,7 @@ # Be advised, RDoc will not detect delegated methods. # class Delegator < BasicObject - VERSION = "0.3.0" + VERSION = "0.4.0" kernel = ::Kernel.dup kernel.class_eval do @@ -186,7 +186,7 @@ def ! # method calls are being delegated to. # def __getobj__ - __raise__ ::NotImplementedError, "need to define `__getobj__'" + __raise__ ::NotImplementedError, "need to define '__getobj__'" end # @@ -194,7 +194,7 @@ def __getobj__ # to _obj_. # def __setobj__(obj) - __raise__ ::NotImplementedError, "need to define `__setobj__'" + __raise__ ::NotImplementedError, "need to define '__setobj__'" end # diff --git a/lib/did_you_mean.rb b/lib/did_you_mean.rb index e177665099a3ee..74cd1760425510 100644 --- a/lib/did_you_mean.rb +++ b/lib/did_you_mean.rb @@ -113,30 +113,6 @@ def self.correct_error(error_class, spell_checker) correct_error LoadError, RequirePathChecker if RUBY_VERSION >= '2.8.0' correct_error NoMatchingPatternKeyError, PatternKeyNameChecker if defined?(::NoMatchingPatternKeyError) - # TODO: Remove on the 3.4 development start: - class DeprecatedMapping # :nodoc: - def []=(key, value) - warn "Calling `DidYouMean::SPELL_CHECKERS[#{key.to_s}] = #{value.to_s}' has been deprecated. " \ - "Please call `DidYouMean.correct_error(#{key.to_s}, #{value.to_s})' instead." - - DidYouMean.correct_error(key, value) - end - - def merge!(hash) - warn "Calling `DidYouMean::SPELL_CHECKERS.merge!(error_name => spell_checker)' has been deprecated. " \ - "Please call `DidYouMean.correct_error(error_name, spell_checker)' instead." - - hash.each do |error_class, spell_checker| - DidYouMean.correct_error(error_class, spell_checker) - end - end - end - - # TODO: Remove on the 3.4 development start: - SPELL_CHECKERS = DeprecatedMapping.new - deprecate_constant :SPELL_CHECKERS - private_constant :DeprecatedMapping - # Returns the currently set formatter. By default, it is set to +DidYouMean::Formatter+. def self.formatter if defined?(Ractor) diff --git a/lib/did_you_mean/did_you_mean.gemspec b/lib/did_you_mean/did_you_mean.gemspec index 8fe57231297dce..be4ac76b4beb84 100644 --- a/lib/did_you_mean/did_you_mean.gemspec +++ b/lib/did_you_mean/did_you_mean.gemspec @@ -22,6 +22,4 @@ Gem::Specification.new do |spec| spec.require_paths = ["lib"] spec.required_ruby_version = '>= 2.5.0' - - spec.add_development_dependency "rake" end diff --git a/lib/did_you_mean/jaro_winkler.rb b/lib/did_you_mean/jaro_winkler.rb index 56db130af45993..9a3e57f6d7214d 100644 --- a/lib/did_you_mean/jaro_winkler.rb +++ b/lib/did_you_mean/jaro_winkler.rb @@ -8,8 +8,7 @@ def distance(str1, str2) m = 0.0 t = 0.0 - range = (length2 / 2).floor - 1 - range = 0 if range < 0 + range = length2 > 3 ? length2 / 2 - 1 : 0 flags1 = 0 flags2 = 0 @@ -72,10 +71,8 @@ def distance(str1, str2) codepoints2 = str2.codepoints prefix_bonus = 0 - i = 0 str1.each_codepoint do |char1| - char1 == codepoints2[i] && i < 4 ? prefix_bonus += 1 : break - i += 1 + char1 == codepoints2[prefix_bonus] && prefix_bonus < 4 ? prefix_bonus += 1 : break end jaro_distance + (prefix_bonus * WEIGHT * (1 - jaro_distance)) diff --git a/lib/did_you_mean/spell_checkers/key_error_checker.rb b/lib/did_you_mean/spell_checkers/key_error_checker.rb index be4bea7789c379..955bff1be63fd0 100644 --- a/lib/did_you_mean/spell_checkers/key_error_checker.rb +++ b/lib/did_you_mean/spell_checkers/key_error_checker.rb @@ -14,7 +14,15 @@ def corrections private def exact_matches - @exact_matches ||= @keys.select { |word| @key == word.to_s }.map(&:inspect) + @exact_matches ||= @keys.select { |word| @key == word.to_s }.map { |obj| format_object(obj) } + end + + def format_object(symbol_or_object) + if symbol_or_object.is_a?(Symbol) + ":#{symbol_or_object}" + else + symbol_or_object.to_s + end end end end diff --git a/lib/did_you_mean/spell_checkers/pattern_key_name_checker.rb b/lib/did_you_mean/spell_checkers/pattern_key_name_checker.rb index ed263c8f937320..622d4dee258cb8 100644 --- a/lib/did_you_mean/spell_checkers/pattern_key_name_checker.rb +++ b/lib/did_you_mean/spell_checkers/pattern_key_name_checker.rb @@ -14,7 +14,15 @@ def corrections private def exact_matches - @exact_matches ||= @keys.select { |word| @key == word.to_s }.map(&:inspect) + @exact_matches ||= @keys.select { |word| @key == word.to_s }.map { |obj| format_object(obj) } + end + + def format_object(symbol_or_object) + if symbol_or_object.is_a?(Symbol) + ":#{symbol_or_object}" + else + symbol_or_object.to_s + end end end end diff --git a/lib/did_you_mean/version.rb b/lib/did_you_mean/version.rb index 5745ca1efd838e..85d80e423003dc 100644 --- a/lib/did_you_mean/version.rb +++ b/lib/did_you_mean/version.rb @@ -1,3 +1,3 @@ module DidYouMean - VERSION = "1.6.3".freeze + VERSION = "2.0.0".freeze end diff --git a/lib/drb.rb b/lib/drb.rb deleted file mode 100644 index 2bb4716fa22d2a..00000000000000 --- a/lib/drb.rb +++ /dev/null @@ -1,3 +0,0 @@ -# frozen_string_literal: false -require 'drb/drb' - diff --git a/lib/drb/acl.rb b/lib/drb/acl.rb deleted file mode 100644 index b004656f09dc44..00000000000000 --- a/lib/drb/acl.rb +++ /dev/null @@ -1,239 +0,0 @@ -# frozen_string_literal: false -# Copyright (c) 2000,2002,2003 Masatoshi SEKI -# -# acl.rb is copyrighted free software by Masatoshi SEKI. -# You can redistribute it and/or modify it under the same terms as Ruby. - -require 'ipaddr' - -## -# Simple Access Control Lists. -# -# Access control lists are composed of "allow" and "deny" halves to control -# access. Use "all" or "*" to match any address. To match a specific address -# use any address or address mask that IPAddr can understand. -# -# Example: -# -# list = %w[ -# deny all -# allow 192.168.1.1 -# allow ::ffff:192.168.1.2 -# allow 192.168.1.3 -# ] -# -# # From Socket#peeraddr, see also ACL#allow_socket? -# addr = ["AF_INET", 10, "lc630", "192.168.1.3"] -# -# acl = ACL.new -# p acl.allow_addr?(addr) # => true -# -# acl = ACL.new(list, ACL::DENY_ALLOW) -# p acl.allow_addr?(addr) # => true - -class ACL - - ## - # The current version of ACL - - VERSION=["2.0.0"] - - ## - # An entry in an ACL - - class ACLEntry - - ## - # Creates a new entry using +str+. - # - # +str+ may be "*" or "all" to match any address, an IP address string - # to match a specific address, an IP address mask per IPAddr, or one - # containing "*" to match part of an IPv4 address. - # - # IPAddr::InvalidPrefixError may be raised when an IP network - # address with an invalid netmask/prefix is given. - - def initialize(str) - if str == '*' or str == 'all' - @pat = [:all] - elsif str.include?('*') - @pat = [:name, dot_pat(str)] - else - begin - @pat = [:ip, IPAddr.new(str)] - rescue IPAddr::InvalidPrefixError - # In this case, `str` shouldn't be a host name pattern - # because it contains a slash. - raise - rescue ArgumentError - @pat = [:name, dot_pat(str)] - end - end - end - - private - - ## - # Creates a regular expression to match IPv4 addresses - - def dot_pat_str(str) - list = str.split('.').collect { |s| - (s == '*') ? '.+' : s - } - list.join("\\.") - end - - private - - ## - # Creates a Regexp to match an address. - - def dot_pat(str) - /\A#{dot_pat_str(str)}\z/ - end - - public - - ## - # Matches +addr+ against this entry. - - def match(addr) - case @pat[0] - when :all - true - when :ip - begin - ipaddr = IPAddr.new(addr[3]) - ipaddr = ipaddr.ipv4_mapped if @pat[1].ipv6? && ipaddr.ipv4? - rescue ArgumentError - return false - end - (@pat[1].include?(ipaddr)) ? true : false - when :name - (@pat[1] =~ addr[2]) ? true : false - else - false - end - end - end - - ## - # A list of ACLEntry objects. Used to implement the allow and deny halves - # of an ACL - - class ACLList - - ## - # Creates an empty ACLList - - def initialize - @list = [] - end - - public - - ## - # Matches +addr+ against each ACLEntry in this list. - - def match(addr) - @list.each do |e| - return true if e.match(addr) - end - false - end - - public - - ## - # Adds +str+ as an ACLEntry in this list - - def add(str) - @list.push(ACLEntry.new(str)) - end - - end - - ## - # Default to deny - - DENY_ALLOW = 0 - - ## - # Default to allow - - ALLOW_DENY = 1 - - ## - # Creates a new ACL from +list+ with an evaluation +order+ of DENY_ALLOW or - # ALLOW_DENY. - # - # An ACL +list+ is an Array of "allow" or "deny" and an address or address - # mask or "all" or "*" to match any address: - # - # %w[ - # deny all - # allow 192.0.2.2 - # allow 192.0.2.128/26 - # ] - - def initialize(list=nil, order = DENY_ALLOW) - @order = order - @deny = ACLList.new - @allow = ACLList.new - install_list(list) if list - end - - public - - ## - # Allow connections from Socket +soc+? - - def allow_socket?(soc) - allow_addr?(soc.peeraddr) - end - - public - - ## - # Allow connections from addrinfo +addr+? It must be formatted like - # Socket#peeraddr: - # - # ["AF_INET", 10, "lc630", "192.0.2.1"] - - def allow_addr?(addr) - case @order - when DENY_ALLOW - return true if @allow.match(addr) - return false if @deny.match(addr) - return true - when ALLOW_DENY - return false if @deny.match(addr) - return true if @allow.match(addr) - return false - else - false - end - end - - public - - ## - # Adds +list+ of ACL entries to this ACL. - - def install_list(list) - i = 0 - while i < list.size - permission, domain = list.slice(i,2) - case permission.downcase - when 'allow' - @allow.add(domain) - when 'deny' - @deny.add(domain) - else - raise "Invalid ACL entry #{list}" - end - i += 2 - end - end - -end diff --git a/lib/drb/drb.gemspec b/lib/drb/drb.gemspec deleted file mode 100644 index c9d7e40a514479..00000000000000 --- a/lib/drb/drb.gemspec +++ /dev/null @@ -1,43 +0,0 @@ -begin - require_relative "lib/drb/version" -rescue LoadError # Fallback to load version file in ruby core repository - require_relative "version" -end - -Gem::Specification.new do |spec| - spec.name = "drb" - spec.version = DRb::VERSION - spec.authors = ["Masatoshi SEKI"] - spec.email = ["seki@ruby-lang.org"] - - spec.summary = %q{Distributed object system for Ruby} - spec.description = %q{Distributed object system for Ruby} - spec.homepage = "https://github.com/ruby/drb" - spec.required_ruby_version = Gem::Requirement.new(">= 2.7.0") - spec.licenses = ["Ruby", "BSD-2-Clause"] - - spec.metadata["homepage_uri"] = spec.homepage - spec.metadata["source_code_uri"] = spec.homepage - - spec.files = %w[ - LICENSE.txt - drb.gemspec - lib/drb.rb - lib/drb/acl.rb - lib/drb/drb.rb - lib/drb/eq.rb - lib/drb/extserv.rb - lib/drb/extservm.rb - lib/drb/gw.rb - lib/drb/invokemethod.rb - lib/drb/observer.rb - lib/drb/ssl.rb - lib/drb/timeridconv.rb - lib/drb/unix.rb - lib/drb/version.rb - lib/drb/weakidconv.rb - ] - spec.require_paths = ["lib"] - - spec.add_dependency "ruby2_keywords" -end diff --git a/lib/drb/drb.rb b/lib/drb/drb.rb deleted file mode 100644 index 23181bb8342ba9..00000000000000 --- a/lib/drb/drb.rb +++ /dev/null @@ -1,1942 +0,0 @@ -# frozen_string_literal: false -# -# = drb/drb.rb -# -# Distributed Ruby: _dRuby_ version 2.0.4 -# -# Copyright (c) 1999-2003 Masatoshi SEKI. You can redistribute it and/or -# modify it under the same terms as Ruby. -# -# Author:: Masatoshi SEKI -# -# Documentation:: William Webber (william@williamwebber.com) -# -# == Overview -# -# dRuby is a distributed object system for Ruby. It allows an object in one -# Ruby process to invoke methods on an object in another Ruby process on the -# same or a different machine. -# -# The Ruby standard library contains the core classes of the dRuby package. -# However, the full package also includes access control lists and the -# Rinda tuple-space distributed task management system, as well as a -# large number of samples. The full dRuby package can be downloaded from -# the dRuby home page (see *References*). -# -# For an introduction and examples of usage see the documentation to the -# DRb module. -# -# == References -# -# [http://www2a.biglobe.ne.jp/~seki/ruby/druby.html] -# The dRuby home page, in Japanese. Contains the full dRuby package -# and links to other Japanese-language sources. -# -# [http://www2a.biglobe.ne.jp/~seki/ruby/druby.en.html] -# The English version of the dRuby home page. -# -# [http://pragprog.com/book/sidruby/the-druby-book] -# The dRuby Book: Distributed and Parallel Computing with Ruby -# by Masatoshi Seki and Makoto Inoue -# -# [http://www.ruby-doc.org/docs/ProgrammingRuby/html/ospace.html] -# The chapter from *Programming* *Ruby* by Dave Thomas and Andy Hunt -# which discusses dRuby. -# -# [http://www.clio.ne.jp/home/web-i31s/Flotuard/Ruby/PRC2K_seki/dRuby.en.html] -# Translation of presentation on Ruby by Masatoshi Seki. - -require 'socket' -require 'io/wait' -require 'monitor' -require_relative 'eq' - -# -# == Overview -# -# dRuby is a distributed object system for Ruby. It is written in -# pure Ruby and uses its own protocol. No add-in services are needed -# beyond those provided by the Ruby runtime, such as TCP sockets. It -# does not rely on or interoperate with other distributed object -# systems such as CORBA, RMI, or .NET. -# -# dRuby allows methods to be called in one Ruby process upon a Ruby -# object located in another Ruby process, even on another machine. -# References to objects can be passed between processes. Method -# arguments and return values are dumped and loaded in marshalled -# format. All of this is done transparently to both the caller of the -# remote method and the object that it is called upon. -# -# An object in a remote process is locally represented by a -# DRb::DRbObject instance. This acts as a sort of proxy for the -# remote object. Methods called upon this DRbObject instance are -# forwarded to its remote object. This is arranged dynamically at run -# time. There are no statically declared interfaces for remote -# objects, such as CORBA's IDL. -# -# dRuby calls made into a process are handled by a DRb::DRbServer -# instance within that process. This reconstitutes the method call, -# invokes it upon the specified local object, and returns the value to -# the remote caller. Any object can receive calls over dRuby. There -# is no need to implement a special interface, or mixin special -# functionality. Nor, in the general case, does an object need to -# explicitly register itself with a DRbServer in order to receive -# dRuby calls. -# -# One process wishing to make dRuby calls upon another process must -# somehow obtain an initial reference to an object in the remote -# process by some means other than as the return value of a remote -# method call, as there is initially no remote object reference it can -# invoke a method upon. This is done by attaching to the server by -# URI. Each DRbServer binds itself to a URI such as -# 'druby://example.com:8787'. A DRbServer can have an object attached -# to it that acts as the server's *front* *object*. A DRbObject can -# be explicitly created from the server's URI. This DRbObject's -# remote object will be the server's front object. This front object -# can then return references to other Ruby objects in the DRbServer's -# process. -# -# Method calls made over dRuby behave largely the same as normal Ruby -# method calls made within a process. Method calls with blocks are -# supported, as are raising exceptions. In addition to a method's -# standard errors, a dRuby call may also raise one of the -# dRuby-specific errors, all of which are subclasses of DRb::DRbError. -# -# Any type of object can be passed as an argument to a dRuby call or -# returned as its return value. By default, such objects are dumped -# or marshalled at the local end, then loaded or unmarshalled at the -# remote end. The remote end therefore receives a copy of the local -# object, not a distributed reference to it; methods invoked upon this -# copy are executed entirely in the remote process, not passed on to -# the local original. This has semantics similar to pass-by-value. -# -# However, if an object cannot be marshalled, a dRuby reference to it -# is passed or returned instead. This will turn up at the remote end -# as a DRbObject instance. All methods invoked upon this remote proxy -# are forwarded to the local object, as described in the discussion of -# DRbObjects. This has semantics similar to the normal Ruby -# pass-by-reference. -# -# The easiest way to signal that we want an otherwise marshallable -# object to be passed or returned as a DRbObject reference, rather -# than marshalled and sent as a copy, is to include the -# DRb::DRbUndumped mixin module. -# -# dRuby supports calling remote methods with blocks. As blocks (or -# rather the Proc objects that represent them) are not marshallable, -# the block executes in the local, not the remote, context. Each -# value yielded to the block is passed from the remote object to the -# local block, then the value returned by each block invocation is -# passed back to the remote execution context to be collected, before -# the collected values are finally returned to the local context as -# the return value of the method invocation. -# -# == Examples of usage -# -# For more dRuby samples, see the +samples+ directory in the full -# dRuby distribution. -# -# === dRuby in client/server mode -# -# This illustrates setting up a simple client-server drb -# system. Run the server and client code in different terminals, -# starting the server code first. -# -# ==== Server code -# -# require 'drb/drb' -# -# # The URI for the server to connect to -# URI="druby://localhost:8787" -# -# class TimeServer -# -# def get_current_time -# return Time.now -# end -# -# end -# -# # The object that handles requests on the server -# FRONT_OBJECT=TimeServer.new -# -# DRb.start_service(URI, FRONT_OBJECT) -# # Wait for the drb server thread to finish before exiting. -# DRb.thread.join -# -# ==== Client code -# -# require 'drb/drb' -# -# # The URI to connect to -# SERVER_URI="druby://localhost:8787" -# -# # Start a local DRbServer to handle callbacks. -# # -# # Not necessary for this small example, but will be required -# # as soon as we pass a non-marshallable object as an argument -# # to a dRuby call. -# # -# # Note: this must be called at least once per process to take any effect. -# # This is particularly important if your application forks. -# DRb.start_service -# -# timeserver = DRbObject.new_with_uri(SERVER_URI) -# puts timeserver.get_current_time -# -# === Remote objects under dRuby -# -# This example illustrates returning a reference to an object -# from a dRuby call. The Logger instances live in the server -# process. References to them are returned to the client process, -# where methods can be invoked upon them. These methods are -# executed in the server process. -# -# ==== Server code -# -# require 'drb/drb' -# -# URI="druby://localhost:8787" -# -# class Logger -# -# # Make dRuby send Logger instances as dRuby references, -# # not copies. -# include DRb::DRbUndumped -# -# def initialize(n, fname) -# @name = n -# @filename = fname -# end -# -# def log(message) -# File.open(@filename, "a") do |f| -# f.puts("#{Time.now}: #{@name}: #{message}") -# end -# end -# -# end -# -# # We have a central object for creating and retrieving loggers. -# # This retains a local reference to all loggers created. This -# # is so an existing logger can be looked up by name, but also -# # to prevent loggers from being garbage collected. A dRuby -# # reference to an object is not sufficient to prevent it being -# # garbage collected! -# class LoggerFactory -# -# def initialize(bdir) -# @basedir = bdir -# @loggers = {} -# end -# -# def get_logger(name) -# if !@loggers.has_key? name -# # make the filename safe, then declare it to be so -# fname = name.gsub(/[.\/\\\:]/, "_") -# @loggers[name] = Logger.new(name, @basedir + "/" + fname) -# end -# return @loggers[name] -# end -# -# end -# -# FRONT_OBJECT=LoggerFactory.new("/tmp/dlog") -# -# DRb.start_service(URI, FRONT_OBJECT) -# DRb.thread.join -# -# ==== Client code -# -# require 'drb/drb' -# -# SERVER_URI="druby://localhost:8787" -# -# DRb.start_service -# -# log_service=DRbObject.new_with_uri(SERVER_URI) -# -# ["loga", "logb", "logc"].each do |logname| -# -# logger=log_service.get_logger(logname) -# -# logger.log("Hello, world!") -# logger.log("Goodbye, world!") -# logger.log("=== EOT ===") -# -# end -# -# == Security -# -# As with all network services, security needs to be considered when -# using dRuby. By allowing external access to a Ruby object, you are -# not only allowing outside clients to call the methods you have -# defined for that object, but by default to execute arbitrary Ruby -# code on your server. Consider the following: -# -# # !!! UNSAFE CODE !!! -# ro = DRbObject::new_with_uri("druby://your.server.com:8989") -# class << ro -# undef :instance_eval # force call to be passed to remote object -# end -# ro.instance_eval("`rm -rf *`") -# -# The dangers posed by instance_eval and friends are such that a -# DRbServer should only be used when clients are trusted. -# -# A DRbServer can be configured with an access control list to -# selectively allow or deny access from specified IP addresses. The -# main druby distribution provides the ACL class for this purpose. In -# general, this mechanism should only be used alongside, rather than -# as a replacement for, a good firewall. -# -# == dRuby internals -# -# dRuby is implemented using three main components: a remote method -# call marshaller/unmarshaller; a transport protocol; and an -# ID-to-object mapper. The latter two can be directly, and the first -# indirectly, replaced, in order to provide different behaviour and -# capabilities. -# -# Marshalling and unmarshalling of remote method calls is performed by -# a DRb::DRbMessage instance. This uses the Marshal module to dump -# the method call before sending it over the transport layer, then -# reconstitute it at the other end. There is normally no need to -# replace this component, and no direct way is provided to do so. -# However, it is possible to implement an alternative marshalling -# scheme as part of an implementation of the transport layer. -# -# The transport layer is responsible for opening client and server -# network connections and forwarding dRuby request across them. -# Normally, it uses DRb::DRbMessage internally to manage marshalling -# and unmarshalling. The transport layer is managed by -# DRb::DRbProtocol. Multiple protocols can be installed in -# DRbProtocol at the one time; selection between them is determined by -# the scheme of a dRuby URI. The default transport protocol is -# selected by the scheme 'druby:', and implemented by -# DRb::DRbTCPSocket. This uses plain TCP/IP sockets for -# communication. An alternative protocol, using UNIX domain sockets, -# is implemented by DRb::DRbUNIXSocket in the file drb/unix.rb, and -# selected by the scheme 'drbunix:'. A sample implementation over -# HTTP can be found in the samples accompanying the main dRuby -# distribution. -# -# The ID-to-object mapping component maps dRuby object ids to the -# objects they refer to, and vice versa. The implementation to use -# can be specified as part of a DRb::DRbServer's configuration. The -# default implementation is provided by DRb::DRbIdConv. It uses an -# object's ObjectSpace id as its dRuby id. This means that the dRuby -# reference to that object only remains meaningful for the lifetime of -# the object's process and the lifetime of the object within that -# process. A modified implementation is provided by DRb::TimerIdConv -# in the file drb/timeridconv.rb. This implementation retains a local -# reference to all objects exported over dRuby for a configurable -# period of time (defaulting to ten minutes), to prevent them being -# garbage-collected within this time. Another sample implementation -# is provided in sample/name.rb in the main dRuby distribution. This -# allows objects to specify their own id or "name". A dRuby reference -# can be made persistent across processes by having each process -# register an object using the same dRuby name. -# -module DRb - - # Superclass of all errors raised in the DRb module. - class DRbError < RuntimeError; end - - # Error raised when an error occurs on the underlying communication - # protocol. - class DRbConnError < DRbError; end - - # Class responsible for converting between an object and its id. - # - # This, the default implementation, uses an object's local ObjectSpace - # __id__ as its id. This means that an object's identification over - # drb remains valid only while that object instance remains alive - # within the server runtime. - # - # For alternative mechanisms, see DRb::TimerIdConv in drb/timeridconv.rb - # and DRbNameIdConv in sample/name.rb in the full drb distribution. - class DRbIdConv - - # Convert an object reference id to an object. - # - # This implementation looks up the reference id in the local object - # space and returns the object it refers to. - def to_obj(ref) - ObjectSpace._id2ref(ref) - end - - # Convert an object into a reference id. - # - # This implementation returns the object's __id__ in the local - # object space. - def to_id(obj) - case obj - when Object - obj.nil? ? nil : obj.__id__ - when BasicObject - obj.__id__ - end - end - end - - # Mixin module making an object undumpable or unmarshallable. - # - # If an object which includes this module is returned by method - # called over drb, then the object remains in the server space - # and a reference to the object is returned, rather than the - # object being marshalled and moved into the client space. - module DRbUndumped - def _dump(dummy) # :nodoc: - raise TypeError, 'can\'t dump' - end - end - - # Error raised by the DRb module when an attempt is made to refer to - # the context's current drb server but the context does not have one. - # See #current_server. - class DRbServerNotFound < DRbError; end - - # Error raised by the DRbProtocol module when it cannot find any - # protocol implementation support the scheme specified in a URI. - class DRbBadURI < DRbError; end - - # Error raised by a dRuby protocol when it doesn't support the - # scheme specified in a URI. See DRb::DRbProtocol. - class DRbBadScheme < DRbError; end - - # An exception wrapping a DRb::DRbUnknown object - class DRbUnknownError < DRbError - - # Create a new DRbUnknownError for the DRb::DRbUnknown object +unknown+ - def initialize(unknown) - @unknown = unknown - super(unknown.name) - end - - # Get the wrapped DRb::DRbUnknown object. - attr_reader :unknown - - def self._load(s) # :nodoc: - Marshal::load(s) - end - - def _dump(lv) # :nodoc: - Marshal::dump(@unknown) - end - end - - # An exception wrapping an error object - class DRbRemoteError < DRbError - - # Creates a new remote error that wraps the Exception +error+ - def initialize(error) - @reason = error.class.to_s - super("#{error.message} (#{error.class})") - set_backtrace(error.backtrace) - end - - # the class of the error, as a string. - attr_reader :reason - end - - # Class wrapping a marshalled object whose type is unknown locally. - # - # If an object is returned by a method invoked over drb, but the - # class of the object is unknown in the client namespace, or - # the object is a constant unknown in the client namespace, then - # the still-marshalled object is returned wrapped in a DRbUnknown instance. - # - # If this object is passed as an argument to a method invoked over - # drb, then the wrapped object is passed instead. - # - # The class or constant name of the object can be read from the - # +name+ attribute. The marshalled object is held in the +buf+ - # attribute. - class DRbUnknown - - # Create a new DRbUnknown object. - # - # +buf+ is a string containing a marshalled object that could not - # be unmarshalled. +err+ is the error message that was raised - # when the unmarshalling failed. It is used to determine the - # name of the unmarshalled object. - def initialize(err, buf) - case err.to_s - when /uninitialized constant (\S+)/ - @name = $1 - when /undefined class\/module (\S+)/ - @name = $1 - else - @name = nil - end - @buf = buf - end - - # The name of the unknown thing. - # - # Class name for unknown objects; variable name for unknown - # constants. - attr_reader :name - - # Buffer contained the marshalled, unknown object. - attr_reader :buf - - def self._load(s) # :nodoc: - begin - Marshal::load(s) - rescue NameError, ArgumentError - DRbUnknown.new($!, s) - end - end - - def _dump(lv) # :nodoc: - @buf - end - - # Attempt to load the wrapped marshalled object again. - # - # If the class of the object is now known locally, the object - # will be unmarshalled and returned. Otherwise, a new - # but identical DRbUnknown object will be returned. - def reload - self.class._load(@buf) - end - - # Create a DRbUnknownError exception containing this object. - def exception - DRbUnknownError.new(self) - end - end - - # An Array wrapper that can be sent to another server via DRb. - # - # All entries in the array will be dumped or be references that point to - # the local server. - - class DRbArray - - # Creates a new DRbArray that either dumps or wraps all the items in the - # Array +ary+ so they can be loaded by a remote DRb server. - - def initialize(ary) - @ary = ary.collect { |obj| - if obj.kind_of? DRbUndumped - DRbObject.new(obj) - else - begin - Marshal.dump(obj) - obj - rescue - DRbObject.new(obj) - end - end - } - end - - def self._load(s) # :nodoc: - Marshal::load(s) - end - - def _dump(lv) # :nodoc: - Marshal.dump(@ary) - end - end - - # Handler for sending and receiving drb messages. - # - # This takes care of the low-level marshalling and unmarshalling - # of drb requests and responses sent over the wire between server - # and client. This relieves the implementor of a new drb - # protocol layer with having to deal with these details. - # - # The user does not have to directly deal with this object in - # normal use. - class DRbMessage - def initialize(config) # :nodoc: - @load_limit = config[:load_limit] - @argc_limit = config[:argc_limit] - end - - def dump(obj, error=false) # :nodoc: - case obj - when DRbUndumped - obj = make_proxy(obj, error) - when Object - # nothing - else - obj = make_proxy(obj, error) - end - begin - str = Marshal::dump(obj) - rescue - str = Marshal::dump(make_proxy(obj, error)) - end - [str.size].pack('N') + str - end - - def load(soc) # :nodoc: - begin - sz = soc.read(4) # sizeof (N) - rescue - raise(DRbConnError, $!.message, $!.backtrace) - end - raise(DRbConnError, 'connection closed') if sz.nil? - raise(DRbConnError, 'premature header') if sz.size < 4 - sz = sz.unpack('N')[0] - raise(DRbConnError, "too large packet #{sz}") if @load_limit < sz - begin - str = soc.read(sz) - rescue - raise(DRbConnError, $!.message, $!.backtrace) - end - raise(DRbConnError, 'connection closed') if str.nil? - raise(DRbConnError, 'premature marshal format(can\'t read)') if str.size < sz - DRb.mutex.synchronize do - begin - Marshal::load(str) - rescue NameError, ArgumentError - DRbUnknown.new($!, str) - end - end - end - - def send_request(stream, ref, msg_id, arg, b) # :nodoc: - ary = [] - ary.push(dump(ref.__drbref)) - ary.push(dump(msg_id.id2name)) - ary.push(dump(arg.length)) - arg.each do |e| - ary.push(dump(e)) - end - ary.push(dump(b)) - stream.write(ary.join('')) - rescue - raise(DRbConnError, $!.message, $!.backtrace) - end - - def recv_request(stream) # :nodoc: - ref = load(stream) - ro = DRb.to_obj(ref) - msg = load(stream) - argc = load(stream) - raise(DRbConnError, "too many arguments") if @argc_limit < argc - argv = Array.new(argc, nil) - argc.times do |n| - argv[n] = load(stream) - end - block = load(stream) - return ro, msg, argv, block - end - - def send_reply(stream, succ, result) # :nodoc: - stream.write(dump(succ) + dump(result, !succ)) - rescue - raise(DRbConnError, $!.message, $!.backtrace) - end - - def recv_reply(stream) # :nodoc: - succ = load(stream) - result = load(stream) - [succ, result] - end - - private - def make_proxy(obj, error=false) # :nodoc: - if error - DRbRemoteError.new(obj) - else - DRbObject.new(obj) - end - end - end - - # Module managing the underlying network protocol(s) used by drb. - # - # By default, drb uses the DRbTCPSocket protocol. Other protocols - # can be defined. A protocol must define the following class methods: - # - # [open(uri, config)] Open a client connection to the server at +uri+, - # using configuration +config+. Return a protocol - # instance for this connection. - # [open_server(uri, config)] Open a server listening at +uri+, - # using configuration +config+. Return a - # protocol instance for this listener. - # [uri_option(uri, config)] Take a URI, possibly containing an option - # component (e.g. a trailing '?param=val'), - # and return a [uri, option] tuple. - # - # All of these methods should raise a DRbBadScheme error if the URI - # does not identify the protocol they support (e.g. "druby:" for - # the standard Ruby protocol). This is how the DRbProtocol module, - # given a URI, determines which protocol implementation serves that - # protocol. - # - # The protocol instance returned by #open_server must have the - # following methods: - # - # [accept] Accept a new connection to the server. Returns a protocol - # instance capable of communicating with the client. - # [close] Close the server connection. - # [uri] Get the URI for this server. - # - # The protocol instance returned by #open must have the following methods: - # - # [send_request (ref, msg_id, arg, b)] - # Send a request to +ref+ with the given message id and arguments. - # This is most easily implemented by calling DRbMessage.send_request, - # providing a stream that sits on top of the current protocol. - # [recv_reply] - # Receive a reply from the server and return it as a [success-boolean, - # reply-value] pair. This is most easily implemented by calling - # DRb.recv_reply, providing a stream that sits on top of the - # current protocol. - # [alive?] - # Is this connection still alive? - # [close] - # Close this connection. - # - # The protocol instance returned by #open_server().accept() must have - # the following methods: - # - # [recv_request] - # Receive a request from the client and return a [object, message, - # args, block] tuple. This is most easily implemented by calling - # DRbMessage.recv_request, providing a stream that sits on top of - # the current protocol. - # [send_reply(succ, result)] - # Send a reply to the client. This is most easily implemented - # by calling DRbMessage.send_reply, providing a stream that sits - # on top of the current protocol. - # [close] - # Close this connection. - # - # A new protocol is registered with the DRbProtocol module using - # the add_protocol method. - # - # For examples of other protocols, see DRbUNIXSocket in drb/unix.rb, - # and HTTP0 in sample/http0.rb and sample/http0serv.rb in the full - # drb distribution. - module DRbProtocol - - # Add a new protocol to the DRbProtocol module. - def add_protocol(prot) - @protocol.push(prot) - end - module_function :add_protocol - - # Open a client connection to +uri+ with the configuration +config+. - # - # The DRbProtocol module asks each registered protocol in turn to - # try to open the URI. Each protocol signals that it does not handle that - # URI by raising a DRbBadScheme error. If no protocol recognises the - # URI, then a DRbBadURI error is raised. If a protocol accepts the - # URI, but an error occurs in opening it, a DRbConnError is raised. - def open(uri, config, first=true) - @protocol.each do |prot| - begin - return prot.open(uri, config) - rescue DRbBadScheme - rescue DRbConnError - raise($!) - rescue - raise(DRbConnError, "#{uri} - #{$!.inspect}") - end - end - if first && (config[:auto_load] != false) - auto_load(uri) - return open(uri, config, false) - end - raise DRbBadURI, 'can\'t parse uri:' + uri - end - module_function :open - - # Open a server listening for connections at +uri+ with - # configuration +config+. - # - # The DRbProtocol module asks each registered protocol in turn to - # try to open a server at the URI. Each protocol signals that it does - # not handle that URI by raising a DRbBadScheme error. If no protocol - # recognises the URI, then a DRbBadURI error is raised. If a protocol - # accepts the URI, but an error occurs in opening it, the underlying - # error is passed on to the caller. - def open_server(uri, config, first=true) - @protocol.each do |prot| - begin - return prot.open_server(uri, config) - rescue DRbBadScheme - end - end - if first && (config[:auto_load] != false) - auto_load(uri) - return open_server(uri, config, false) - end - raise DRbBadURI, 'can\'t parse uri:' + uri - end - module_function :open_server - - # Parse +uri+ into a [uri, option] pair. - # - # The DRbProtocol module asks each registered protocol in turn to - # try to parse the URI. Each protocol signals that it does not handle that - # URI by raising a DRbBadScheme error. If no protocol recognises the - # URI, then a DRbBadURI error is raised. - def uri_option(uri, config, first=true) - @protocol.each do |prot| - begin - uri, opt = prot.uri_option(uri, config) - # opt = nil if opt == '' - return uri, opt - rescue DRbBadScheme - end - end - if first && (config[:auto_load] != false) - auto_load(uri) - return uri_option(uri, config, false) - end - raise DRbBadURI, 'can\'t parse uri:' + uri - end - module_function :uri_option - - def auto_load(uri) # :nodoc: - if /\Adrb([a-z0-9]+):/ =~ uri - require("drb/#{$1}") rescue nil - end - end - module_function :auto_load - end - - # The default drb protocol which communicates over a TCP socket. - # - # The DRb TCP protocol URI looks like: - # druby://:?. The option is optional. - - class DRbTCPSocket - # :stopdoc: - private - def self.parse_uri(uri) - if /\Adruby:\/\/(.*?):(\d+)(\?(.*))?\z/ =~ uri - host = $1 - port = $2.to_i - option = $4 - [host, port, option] - else - raise(DRbBadScheme, uri) unless uri.start_with?('druby:') - raise(DRbBadURI, 'can\'t parse uri:' + uri) - end - end - - public - - # Open a client connection to +uri+ (DRb URI string) using configuration - # +config+. - # - # This can raise DRb::DRbBadScheme or DRb::DRbBadURI if +uri+ is not for a - # recognized protocol. See DRb::DRbServer.new for information on built-in - # URI protocols. - def self.open(uri, config) - host, port, = parse_uri(uri) - soc = TCPSocket.open(host, port) - self.new(uri, soc, config) - end - - # Returns the hostname of this server - def self.getservername - host = Socket::gethostname - begin - Socket::getaddrinfo(host, nil, - Socket::AF_UNSPEC, - Socket::SOCK_STREAM, - 0, - Socket::AI_PASSIVE)[0][3] - rescue - 'localhost' - end - end - - # For the families available for +host+, returns a TCPServer on +port+. - # If +port+ is 0 the first available port is used. IPv4 servers are - # preferred over IPv6 servers. - def self.open_server_inaddr_any(host, port) - infos = Socket::getaddrinfo(host, nil, - Socket::AF_UNSPEC, - Socket::SOCK_STREAM, - 0, - Socket::AI_PASSIVE) - families = Hash[*infos.collect { |af, *_| af }.uniq.zip([]).flatten] - return TCPServer.open('0.0.0.0', port) if families.has_key?('AF_INET') - return TCPServer.open('::', port) if families.has_key?('AF_INET6') - return TCPServer.open(port) - # :stopdoc: - end - - # Open a server listening for connections at +uri+ using - # configuration +config+. - def self.open_server(uri, config) - uri = 'druby://:0' unless uri - host, port, _ = parse_uri(uri) - config = {:tcp_original_host => host}.update(config) - if host.size == 0 - host = getservername - soc = open_server_inaddr_any(host, port) - else - soc = TCPServer.open(host, port) - end - port = soc.addr[1] if port == 0 - config[:tcp_port] = port - uri = "druby://#{host}:#{port}" - self.new(uri, soc, config) - end - - # Parse +uri+ into a [uri, option] pair. - def self.uri_option(uri, config) - host, port, option = parse_uri(uri) - return "druby://#{host}:#{port}", option - end - - # Create a new DRbTCPSocket instance. - # - # +uri+ is the URI we are connected to. - # +soc+ is the tcp socket we are bound to. +config+ is our - # configuration. - def initialize(uri, soc, config={}) - @uri = uri - @socket = soc - @config = config - @acl = config[:tcp_acl] - @msg = DRbMessage.new(config) - set_sockopt(@socket) - @shutdown_pipe_r, @shutdown_pipe_w = IO.pipe - end - - # Get the URI that we are connected to. - attr_reader :uri - - # Get the address of our TCP peer (the other end of the socket - # we are bound to. - def peeraddr - @socket.peeraddr - end - - # Get the socket. - def stream; @socket; end - - # On the client side, send a request to the server. - def send_request(ref, msg_id, arg, b) - @msg.send_request(stream, ref, msg_id, arg, b) - end - - # On the server side, receive a request from the client. - def recv_request - @msg.recv_request(stream) - end - - # On the server side, send a reply to the client. - def send_reply(succ, result) - @msg.send_reply(stream, succ, result) - end - - # On the client side, receive a reply from the server. - def recv_reply - @msg.recv_reply(stream) - end - - public - - # Close the connection. - # - # If this is an instance returned by #open_server, then this stops - # listening for new connections altogether. If this is an instance - # returned by #open or by #accept, then it closes this particular - # client-server session. - def close - shutdown - if @socket - @socket.close - @socket = nil - end - close_shutdown_pipe - end - - def close_shutdown_pipe - @shutdown_pipe_w.close - @shutdown_pipe_r.close - end - private :close_shutdown_pipe - - # On the server side, for an instance returned by #open_server, - # accept a client connection and return a new instance to handle - # the server's side of this client-server session. - def accept - while true - s = accept_or_shutdown - return nil unless s - break if (@acl ? @acl.allow_socket?(s) : true) - s.close - end - if @config[:tcp_original_host].to_s.size == 0 - uri = "druby://#{s.addr[3]}:#{@config[:tcp_port]}" - else - uri = @uri - end - self.class.new(uri, s, @config) - end - - def accept_or_shutdown - readables, = IO.select([@socket, @shutdown_pipe_r]) - if readables.include? @shutdown_pipe_r - return nil - end - @socket.accept - end - private :accept_or_shutdown - - # Graceful shutdown - def shutdown - @shutdown_pipe_w.close - end - - # Check to see if this connection is alive. - def alive? - return false unless @socket - if @socket.to_io.wait_readable(0) - close - return false - end - true - end - - def set_sockopt(soc) # :nodoc: - soc.setsockopt(Socket::IPPROTO_TCP, Socket::TCP_NODELAY, 1) - rescue IOError, Errno::ECONNRESET, Errno::EINVAL - # closed/shutdown socket, ignore error - end - end - - module DRbProtocol - @protocol = [DRbTCPSocket] # default - end - - class DRbURIOption # :nodoc: I don't understand the purpose of this class... - def initialize(option) - @option = option.to_s - end - attr_reader :option - def to_s; @option; end - - def ==(other) - return false unless DRbURIOption === other - @option == other.option - end - - def hash - @option.hash - end - - alias eql? == - end - - # Object wrapping a reference to a remote drb object. - # - # Method calls on this object are relayed to the remote - # object that this object is a stub for. - class DRbObject - - # Unmarshall a marshalled DRbObject. - # - # If the referenced object is located within the local server, then - # the object itself is returned. Otherwise, a new DRbObject is - # created to act as a stub for the remote referenced object. - def self._load(s) - uri, ref = Marshal.load(s) - - if DRb.here?(uri) - obj = DRb.to_obj(ref) - return obj - end - - self.new_with(uri, ref) - end - - # Creates a DRb::DRbObject given the reference information to the remote - # host +uri+ and object +ref+. - - def self.new_with(uri, ref) - it = self.allocate - it.instance_variable_set(:@uri, uri) - it.instance_variable_set(:@ref, ref) - it - end - - # Create a new DRbObject from a URI alone. - def self.new_with_uri(uri) - self.new(nil, uri) - end - - # Marshall this object. - # - # The URI and ref of the object are marshalled. - def _dump(lv) - Marshal.dump([@uri, @ref]) - end - - # Create a new remote object stub. - # - # +obj+ is the (local) object we want to create a stub for. Normally - # this is +nil+. +uri+ is the URI of the remote object that this - # will be a stub for. - def initialize(obj, uri=nil) - @uri = nil - @ref = nil - case obj - when Object - is_nil = obj.nil? - when BasicObject - is_nil = false - end - - if is_nil - return if uri.nil? - @uri, option = DRbProtocol.uri_option(uri, DRb.config) - @ref = DRbURIOption.new(option) unless option.nil? - else - @uri = uri ? uri : (DRb.uri rescue nil) - @ref = obj ? DRb.to_id(obj) : nil - end - end - - # Get the URI of the remote object. - def __drburi - @uri - end - - # Get the reference of the object, if local. - def __drbref - @ref - end - - undef :to_s - undef :to_a if respond_to?(:to_a) - - # Routes respond_to? to the referenced remote object. - def respond_to?(msg_id, priv=false) - case msg_id - when :_dump - true - when :marshal_dump - false - else - method_missing(:respond_to?, msg_id, priv) - end - end - - # Routes method calls to the referenced remote object. - ruby2_keywords def method_missing(msg_id, *a, &b) - if DRb.here?(@uri) - obj = DRb.to_obj(@ref) - DRb.current_server.check_insecure_method(obj, msg_id) - return obj.__send__(msg_id, *a, &b) - end - - succ, result = self.class.with_friend(@uri) do - DRbConn.open(@uri) do |conn| - conn.send_message(self, msg_id, a, b) - end - end - - if succ - return result - elsif DRbUnknown === result - raise result - else - bt = self.class.prepare_backtrace(@uri, result) - result.set_backtrace(bt + caller) - raise result - end - end - - # Given the +uri+ of another host executes the block provided. - def self.with_friend(uri) # :nodoc: - friend = DRb.fetch_server(uri) - return yield() unless friend - - save = Thread.current['DRb'] - Thread.current['DRb'] = { 'server' => friend } - return yield - ensure - Thread.current['DRb'] = save if friend - end - - # Returns a modified backtrace from +result+ with the +uri+ where each call - # in the backtrace came from. - def self.prepare_backtrace(uri, result) # :nodoc: - prefix = "(#{uri}) " - bt = [] - result.backtrace.each do |x| - break if /`__send__'$/ =~ x - if /\A\(druby:\/\// =~ x - bt.push(x) - else - bt.push(prefix + x) - end - end - bt - end - - def pretty_print(q) # :nodoc: - q.pp_object(self) - end - - def pretty_print_cycle(q) # :nodoc: - q.object_address_group(self) { - q.breakable - q.text '...' - } - end - end - - class ThreadObject - include MonitorMixin - - def initialize(&blk) - super() - @wait_ev = new_cond - @req_ev = new_cond - @res_ev = new_cond - @status = :wait - @req = nil - @res = nil - @thread = Thread.new(self, &blk) - end - - def alive? - @thread.alive? - end - - def kill - @thread.kill - @thread.join - end - - def method_missing(msg, *arg, &blk) - synchronize do - @wait_ev.wait_until { @status == :wait } - @req = [msg] + arg - @status = :req - @req_ev.broadcast - @res_ev.wait_until { @status == :res } - value = @res - @req = @res = nil - @status = :wait - @wait_ev.broadcast - return value - end - end - - def _execute() - synchronize do - @req_ev.wait_until { @status == :req } - @res = yield(@req) - @status = :res - @res_ev.signal - end - end - end - - # Class handling the connection between a DRbObject and the - # server the real object lives on. - # - # This class maintains a pool of connections, to reduce the - # overhead of starting and closing down connections for each - # method call. - # - # This class is used internally by DRbObject. The user does - # not normally need to deal with it directly. - class DRbConn - POOL_SIZE = 16 # :nodoc: - - def self.make_pool - ThreadObject.new do |queue| - pool = [] - while true - queue._execute do |message| - case(message[0]) - when :take then - remote_uri = message[1] - conn = nil - new_pool = [] - pool.each do |c| - if conn.nil? and c.uri == remote_uri - conn = c if c.alive? - else - new_pool.push c - end - end - pool = new_pool - conn - when :store then - conn = message[1] - pool.unshift(conn) - pool.pop.close while pool.size > POOL_SIZE - conn - else - nil - end - end - end - end - end - @pool_proxy = nil - - def self.stop_pool - @pool_proxy&.kill - @pool_proxy = nil - end - - def self.open(remote_uri) # :nodoc: - begin - @pool_proxy = make_pool unless @pool_proxy&.alive? - - conn = @pool_proxy.take(remote_uri) - conn = self.new(remote_uri) unless conn - succ, result = yield(conn) - return succ, result - - ensure - if conn - if succ - @pool_proxy.store(conn) - else - conn.close - end - end - end - end - - def initialize(remote_uri) # :nodoc: - @uri = remote_uri - @protocol = DRbProtocol.open(remote_uri, DRb.config) - end - attr_reader :uri # :nodoc: - - def send_message(ref, msg_id, arg, block) # :nodoc: - @protocol.send_request(ref, msg_id, arg, block) - @protocol.recv_reply - end - - def close # :nodoc: - @protocol.close - @protocol = nil - end - - def alive? # :nodoc: - return false unless @protocol - @protocol.alive? - end - end - - # Class representing a drb server instance. - # - # A DRbServer must be running in the local process before any incoming - # dRuby calls can be accepted, or any local objects can be passed as - # dRuby references to remote processes, even if those local objects are - # never actually called remotely. You do not need to start a DRbServer - # in the local process if you are only making outgoing dRuby calls - # passing marshalled parameters. - # - # Unless multiple servers are being used, the local DRbServer is normally - # started by calling DRb.start_service. - class DRbServer - @@acl = nil - @@idconv = DRbIdConv.new - @@secondary_server = nil - @@argc_limit = 256 - @@load_limit = 0xffffffff - @@verbose = false - - # Set the default value for the :argc_limit option. - # - # See #new(). The initial default value is 256. - def self.default_argc_limit(argc) - @@argc_limit = argc - end - - # Set the default value for the :load_limit option. - # - # See #new(). The initial default value is 25 MB. - def self.default_load_limit(sz) - @@load_limit = sz - end - - # Set the default access control list to +acl+. The default ACL is +nil+. - # - # See also DRb::ACL and #new() - def self.default_acl(acl) - @@acl = acl - end - - # Set the default value for the :id_conv option. - # - # See #new(). The initial default value is a DRbIdConv instance. - def self.default_id_conv(idconv) - @@idconv = idconv - end - - # Set the default value of the :verbose option. - # - # See #new(). The initial default value is false. - def self.verbose=(on) - @@verbose = on - end - - # Get the default value of the :verbose option. - def self.verbose - @@verbose - end - - def self.make_config(hash={}) # :nodoc: - default_config = { - :idconv => @@idconv, - :verbose => @@verbose, - :tcp_acl => @@acl, - :load_limit => @@load_limit, - :argc_limit => @@argc_limit, - } - default_config.update(hash) - end - - # Create a new DRbServer instance. - # - # +uri+ is the URI to bind to. This is normally of the form - # 'druby://:' where is a hostname of - # the local machine. If nil, then the system's default hostname - # will be bound to, on a port selected by the system; these value - # can be retrieved from the +uri+ attribute. 'druby:' specifies - # the default dRuby transport protocol: another protocol, such - # as 'drbunix:', can be specified instead. - # - # +front+ is the front object for the server, that is, the object - # to which remote method calls on the server will be passed. If - # nil, then the server will not accept remote method calls. - # - # If +config_or_acl+ is a hash, it is the configuration to - # use for this server. The following options are recognised: - # - # :idconv :: an id-to-object conversion object. This defaults - # to an instance of the class DRb::DRbIdConv. - # :verbose :: if true, all unsuccessful remote calls on objects - # in the server will be logged to $stdout. false - # by default. - # :tcp_acl :: the access control list for this server. See - # the ACL class from the main dRuby distribution. - # :load_limit :: the maximum message size in bytes accepted by - # the server. Defaults to 25 MB (26214400). - # :argc_limit :: the maximum number of arguments to a remote - # method accepted by the server. Defaults to - # 256. - # The default values of these options can be modified on - # a class-wide basis by the class methods #default_argc_limit, - # #default_load_limit, #default_acl, #default_id_conv, - # and #verbose= - # - # If +config_or_acl+ is not a hash, but is not nil, it is - # assumed to be the access control list for this server. - # See the :tcp_acl option for more details. - # - # If no other server is currently set as the primary server, - # this will become the primary server. - # - # The server will immediately start running in its own thread. - def initialize(uri=nil, front=nil, config_or_acl=nil) - if Hash === config_or_acl - config = config_or_acl.dup - else - acl = config_or_acl || @@acl - config = { - :tcp_acl => acl - } - end - - @config = self.class.make_config(config) - - @protocol = DRbProtocol.open_server(uri, @config) - @uri = @protocol.uri - @exported_uri = [@uri] - - @front = front - @idconv = @config[:idconv] - - @grp = ThreadGroup.new - @thread = run - - DRb.regist_server(self) - end - - # The URI of this DRbServer. - attr_reader :uri - - # The main thread of this DRbServer. - # - # This is the thread that listens for and accepts connections - # from clients, not that handles each client's request-response - # session. - attr_reader :thread - - # The front object of the DRbServer. - # - # This object receives remote method calls made on the server's - # URI alone, with an object id. - attr_reader :front - - # The configuration of this DRbServer - attr_reader :config - - # Set whether to operate in verbose mode. - # - # In verbose mode, failed calls are logged to stdout. - def verbose=(v); @config[:verbose]=v; end - - # Get whether the server is in verbose mode. - # - # In verbose mode, failed calls are logged to stdout. - def verbose; @config[:verbose]; end - - # Is this server alive? - def alive? - @thread.alive? - end - - # Is +uri+ the URI for this server? - def here?(uri) - @exported_uri.include?(uri) - end - - # Stop this server. - def stop_service - DRb.remove_server(self) - if Thread.current['DRb'] && Thread.current['DRb']['server'] == self - Thread.current['DRb']['stop_service'] = true - else - shutdown - end - end - - # Convert a dRuby reference to the local object it refers to. - def to_obj(ref) - return front if ref.nil? - return front[ref.to_s] if DRbURIOption === ref - @idconv.to_obj(ref) - end - - # Convert a local object to a dRuby reference. - def to_id(obj) - return nil if obj.__id__ == front.__id__ - @idconv.to_id(obj) - end - - private - - def shutdown - current = Thread.current - if @protocol.respond_to? :shutdown - @protocol.shutdown - else - [@thread, *@grp.list].each { |thread| - thread.kill unless thread == current # xxx: Thread#kill - } - end - @thread.join unless @thread == current - end - - ## - # Starts the DRb main loop in a new thread. - - def run - Thread.start do - begin - while main_loop - end - ensure - @protocol.close if @protocol - end - end - end - - # List of insecure methods. - # - # These methods are not callable via dRuby. - INSECURE_METHOD = [ - :__send__ - ] - - # Has a method been included in the list of insecure methods? - def insecure_method?(msg_id) - INSECURE_METHOD.include?(msg_id) - end - - # Coerce an object to a string, providing our own representation if - # to_s is not defined for the object. - def any_to_s(obj) - "#{obj}:#{obj.class}" - rescue - Kernel.instance_method(:to_s).bind_call(obj) - end - - # Check that a method is callable via dRuby. - # - # +obj+ is the object we want to invoke the method on. +msg_id+ is the - # method name, as a Symbol. - # - # If the method is an insecure method (see #insecure_method?) a - # SecurityError is thrown. If the method is private or undefined, - # a NameError is thrown. - def check_insecure_method(obj, msg_id) - return true if Proc === obj && msg_id == :__drb_yield - raise(ArgumentError, "#{any_to_s(msg_id)} is not a symbol") unless Symbol == msg_id.class - raise(SecurityError, "insecure method `#{msg_id}'") if insecure_method?(msg_id) - - case obj - when Object - if obj.private_methods.include?(msg_id) - desc = any_to_s(obj) - raise NoMethodError, "private method `#{msg_id}' called for #{desc}" - elsif obj.protected_methods.include?(msg_id) - desc = any_to_s(obj) - raise NoMethodError, "protected method `#{msg_id}' called for #{desc}" - else - true - end - else - if Kernel.instance_method(:private_methods).bind(obj).call.include?(msg_id) - desc = any_to_s(obj) - raise NoMethodError, "private method `#{msg_id}' called for #{desc}" - elsif Kernel.instance_method(:protected_methods).bind(obj).call.include?(msg_id) - desc = any_to_s(obj) - raise NoMethodError, "protected method `#{msg_id}' called for #{desc}" - else - true - end - end - end - public :check_insecure_method - - class InvokeMethod # :nodoc: - def initialize(drb_server, client) - @drb_server = drb_server - @client = client - end - - def perform - begin - setup_message - ensure - @result = nil - @succ = false - end - - if @block - @result = perform_with_block - else - @result = perform_without_block - end - @succ = true - case @result - when Array - if @msg_id == :to_ary - @result = DRbArray.new(@result) - end - end - return @succ, @result - rescue NoMemoryError, SystemExit, SystemStackError, SecurityError - raise - rescue Exception - @result = $! - return @succ, @result - end - - private - def init_with_client - obj, msg, argv, block = @client.recv_request - @obj = obj - @msg_id = msg.intern - @argv = argv - @block = block - end - - def check_insecure_method - @drb_server.check_insecure_method(@obj, @msg_id) - end - - def setup_message - init_with_client - check_insecure_method - end - - def perform_without_block - if Proc === @obj && @msg_id == :__drb_yield - if @argv.size == 1 - ary = @argv - else - ary = [@argv] - end - ary.collect(&@obj)[0] - else - @obj.__send__(@msg_id, *@argv) - end - end - - end - - require_relative 'invokemethod' - class InvokeMethod - include InvokeMethod18Mixin - end - - def error_print(exception) - exception.backtrace.inject(true) do |first, x| - if first - $stderr.puts "#{x}: #{exception} (#{exception.class})" - else - $stderr.puts "\tfrom #{x}" - end - false - end - end - - # The main loop performed by a DRbServer's internal thread. - # - # Accepts a connection from a client, and starts up its own - # thread to handle it. This thread loops, receiving requests - # from the client, invoking them on a local object, and - # returning responses, until the client closes the connection - # or a local method call fails. - def main_loop - client0 = @protocol.accept - return nil if !client0 - Thread.start(client0) do |client| - @grp.add Thread.current - Thread.current['DRb'] = { 'client' => client , - 'server' => self } - DRb.mutex.synchronize do - client_uri = client.uri - @exported_uri << client_uri unless @exported_uri.include?(client_uri) - end - _last_invoke_method = nil - loop do - begin - succ = false - invoke_method = InvokeMethod.new(self, client) - succ, result = invoke_method.perform - error_print(result) if !succ && verbose - unless DRbConnError === result && result.message == 'connection closed' - client.send_reply(succ, result) - end - rescue Exception => e - error_print(e) if verbose - ensure - _last_invoke_method = invoke_method - client.close unless succ - if Thread.current['DRb']['stop_service'] - shutdown - break - end - break unless succ - end - end - end - end - end - - @primary_server = nil - - # Start a dRuby server locally. - # - # The new dRuby server will become the primary server, even - # if another server is currently the primary server. - # - # +uri+ is the URI for the server to bind to. If nil, - # the server will bind to random port on the default local host - # name and use the default dRuby protocol. - # - # +front+ is the server's front object. This may be nil. - # - # +config+ is the configuration for the new server. This may - # be nil. - # - # See DRbServer::new. - def start_service(uri=nil, front=nil, config=nil) - @primary_server = DRbServer.new(uri, front, config) - end - module_function :start_service - - # The primary local dRuby server. - # - # This is the server created by the #start_service call. - attr_accessor :primary_server - module_function :primary_server=, :primary_server - - # Get the 'current' server. - # - # In the context of execution taking place within the main - # thread of a dRuby server (typically, as a result of a remote - # call on the server or one of its objects), the current - # server is that server. Otherwise, the current server is - # the primary server. - # - # If the above rule fails to find a server, a DRbServerNotFound - # error is raised. - def current_server - drb = Thread.current['DRb'] - server = (drb && drb['server']) ? drb['server'] : @primary_server - raise DRbServerNotFound unless server - return server - end - module_function :current_server - - # Stop the local dRuby server. - # - # This operates on the primary server. If there is no primary - # server currently running, it is a noop. - def stop_service - @primary_server.stop_service if @primary_server - @primary_server = nil - end - module_function :stop_service - - # Get the URI defining the local dRuby space. - # - # This is the URI of the current server. See #current_server. - def uri - drb = Thread.current['DRb'] - client = (drb && drb['client']) - if client - uri = client.uri - return uri if uri - end - current_server.uri - end - module_function :uri - - # Is +uri+ the URI for the current local server? - def here?(uri) - current_server.here?(uri) rescue false - # (current_server.uri rescue nil) == uri - end - module_function :here? - - # Get the configuration of the current server. - # - # If there is no current server, this returns the default configuration. - # See #current_server and DRbServer::make_config. - def config - current_server.config - rescue - DRbServer.make_config - end - module_function :config - - # Get the front object of the current server. - # - # This raises a DRbServerNotFound error if there is no current server. - # See #current_server. - def front - current_server.front - end - module_function :front - - # Convert a reference into an object using the current server. - # - # This raises a DRbServerNotFound error if there is no current server. - # See #current_server. - def to_obj(ref) - current_server.to_obj(ref) - end - - # Get a reference id for an object using the current server. - # - # This raises a DRbServerNotFound error if there is no current server. - # See #current_server. - def to_id(obj) - current_server.to_id(obj) - end - module_function :to_id - module_function :to_obj - - # Get the thread of the primary server. - # - # This returns nil if there is no primary server. See #primary_server. - def thread - @primary_server ? @primary_server.thread : nil - end - module_function :thread - - # Set the default id conversion object. - # - # This is expected to be an instance such as DRb::DRbIdConv that responds to - # #to_id and #to_obj that can convert objects to and from DRb references. - # - # See DRbServer#default_id_conv. - def install_id_conv(idconv) - DRbServer.default_id_conv(idconv) - end - module_function :install_id_conv - - # Set the default ACL to +acl+. - # - # See DRb::DRbServer.default_acl. - def install_acl(acl) - DRbServer.default_acl(acl) - end - module_function :install_acl - - @mutex = Thread::Mutex.new - def mutex # :nodoc: - @mutex - end - module_function :mutex - - @server = {} - # Registers +server+ with DRb. - # - # This is called when a new DRb::DRbServer is created. - # - # If there is no primary server then +server+ becomes the primary server. - # - # Example: - # - # require 'drb' - # - # s = DRb::DRbServer.new # automatically calls regist_server - # DRb.fetch_server s.uri #=> # - def regist_server(server) - @server[server.uri] = server - mutex.synchronize do - @primary_server = server unless @primary_server - end - end - module_function :regist_server - - # Removes +server+ from the list of registered servers. - def remove_server(server) - @server.delete(server.uri) - mutex.synchronize do - if @primary_server == server - @primary_server = nil - end - end - end - module_function :remove_server - - # Retrieves the server with the given +uri+. - # - # See also regist_server and remove_server. - def fetch_server(uri) - @server[uri] - end - module_function :fetch_server -end - -# :stopdoc: -DRbObject = DRb::DRbObject -DRbUndumped = DRb::DRbUndumped -DRbIdConv = DRb::DRbIdConv diff --git a/lib/drb/eq.rb b/lib/drb/eq.rb deleted file mode 100644 index 15ca5cae42aa32..00000000000000 --- a/lib/drb/eq.rb +++ /dev/null @@ -1,15 +0,0 @@ -# frozen_string_literal: false -module DRb - class DRbObject # :nodoc: - def ==(other) - return false unless DRbObject === other - (@ref == other.__drbref) && (@uri == other.__drburi) - end - - def hash - [@uri, @ref].hash - end - - alias eql? == - end -end diff --git a/lib/drb/extserv.rb b/lib/drb/extserv.rb deleted file mode 100644 index 9523fe84e35b81..00000000000000 --- a/lib/drb/extserv.rb +++ /dev/null @@ -1,44 +0,0 @@ -# frozen_string_literal: false -=begin - external service - Copyright (c) 2000,2002 Masatoshi SEKI -=end - -require_relative 'drb' -require 'monitor' - -module DRb - class ExtServ - include MonitorMixin - include DRbUndumped - - def initialize(there, name, server=nil) - super() - @server = server || DRb::primary_server - @name = name - ro = DRbObject.new(nil, there) - synchronize do - @invoker = ro.register(name, DRbObject.new(self, @server.uri)) - end - end - attr_reader :server - - def front - DRbObject.new(nil, @server.uri) - end - - def stop_service - synchronize do - @invoker.unregister(@name) - server = @server - @server = nil - server.stop_service - true - end - end - - def alive? - @server ? @server.alive? : false - end - end -end diff --git a/lib/drb/extservm.rb b/lib/drb/extservm.rb deleted file mode 100644 index 9333a108e5dfa8..00000000000000 --- a/lib/drb/extservm.rb +++ /dev/null @@ -1,94 +0,0 @@ -# frozen_string_literal: false -=begin - external service manager - Copyright (c) 2000 Masatoshi SEKI -=end - -require_relative 'drb' -require 'monitor' - -module DRb - class ExtServManager - include DRbUndumped - include MonitorMixin - - @@command = {} - - def self.command - @@command - end - - def self.command=(cmd) - @@command = cmd - end - - def initialize - super() - @cond = new_cond - @servers = {} - @waiting = [] - @queue = Thread::Queue.new - @thread = invoke_thread - @uri = nil - end - attr_accessor :uri - - def service(name) - synchronize do - while true - server = @servers[name] - return server if server && server.alive? # server may be `false' - invoke_service(name) - @cond.wait - end - end - end - - def register(name, ro) - synchronize do - @servers[name] = ro - @cond.signal - end - self - end - alias regist register - - def unregister(name) - synchronize do - @servers.delete(name) - end - end - alias unregist unregister - - private - def invoke_thread - Thread.new do - while name = @queue.pop - invoke_service_command(name, @@command[name]) - end - end - end - - def invoke_service(name) - @queue.push(name) - end - - def invoke_service_command(name, command) - raise "invalid command. name: #{name}" unless command - synchronize do - return if @servers.include?(name) - @servers[name] = false - end - uri = @uri || DRb.uri - if command.respond_to? :to_ary - command = command.to_ary + [uri, name] - pid = spawn(*command) - else - pid = spawn("#{command} #{uri} #{name}") - end - th = Process.detach(pid) - th[:drb_service] = name - th - end - end -end diff --git a/lib/drb/gw.rb b/lib/drb/gw.rb deleted file mode 100644 index 65a525476ec549..00000000000000 --- a/lib/drb/gw.rb +++ /dev/null @@ -1,161 +0,0 @@ -# frozen_string_literal: false -require_relative 'drb' -require 'monitor' - -module DRb - - # Gateway id conversion forms a gateway between different DRb protocols or - # networks. - # - # The gateway needs to install this id conversion and create servers for - # each of the protocols or networks it will be a gateway between. It then - # needs to create a server that attaches to each of these networks. For - # example: - # - # require 'drb/drb' - # require 'drb/unix' - # require 'drb/gw' - # - # DRb.install_id_conv DRb::GWIdConv.new - # gw = DRb::GW.new - # s1 = DRb::DRbServer.new 'drbunix:/path/to/gateway', gw - # s2 = DRb::DRbServer.new 'druby://example:10000', gw - # - # s1.thread.join - # s2.thread.join - # - # Each client must register services with the gateway, for example: - # - # DRb.start_service 'drbunix:', nil # an anonymous server - # gw = DRbObject.new nil, 'drbunix:/path/to/gateway' - # gw[:unix] = some_service - # DRb.thread.join - - class GWIdConv < DRbIdConv - def to_obj(ref) # :nodoc: - if Array === ref && ref[0] == :DRbObject - return DRbObject.new_with(ref[1], ref[2]) - end - super(ref) - end - end - - # The GW provides a synchronized store for participants in the gateway to - # communicate. - - class GW - include MonitorMixin - - # Creates a new GW - - def initialize - super() - @hash = {} - end - - # Retrieves +key+ from the GW - - def [](key) - synchronize do - @hash[key] - end - end - - # Stores value +v+ at +key+ in the GW - - def []=(key, v) - synchronize do - @hash[key] = v - end - end - end - - class DRbObject # :nodoc: - def self._load(s) - uri, ref = Marshal.load(s) - if DRb.uri == uri - return ref ? DRb.to_obj(ref) : DRb.front - end - - self.new_with(DRb.uri, [:DRbObject, uri, ref]) - end - - def _dump(lv) - if DRb.uri == @uri - if Array === @ref && @ref[0] == :DRbObject - Marshal.dump([@ref[1], @ref[2]]) - else - Marshal.dump([@uri, @ref]) # ?? - end - else - Marshal.dump([DRb.uri, [:DRbObject, @uri, @ref]]) - end - end - end -end - -=begin -DRb.install_id_conv(DRb::GWIdConv.new) - -front = DRb::GW.new - -s1 = DRb::DRbServer.new('drbunix:/tmp/gw_b_a', front) -s2 = DRb::DRbServer.new('drbunix:/tmp/gw_b_c', front) - -s1.thread.join -s2.thread.join -=end - -=begin -# foo.rb - -require 'drb/drb' - -class Foo - include DRbUndumped - def initialize(name, peer=nil) - @name = name - @peer = peer - end - - def ping(obj) - puts "#{@name}: ping: #{obj.inspect}" - @peer.ping(self) if @peer - end -end -=end - -=begin -# gw_a.rb -require 'drb/unix' -require 'foo' - -obj = Foo.new('a') -DRb.start_service("drbunix:/tmp/gw_a", obj) - -robj = DRbObject.new_with_uri('drbunix:/tmp/gw_b_a') -robj[:a] = obj - -DRb.thread.join -=end - -=begin -# gw_c.rb -require 'drb/unix' -require 'foo' - -foo = Foo.new('c', nil) - -DRb.start_service("drbunix:/tmp/gw_c", nil) - -robj = DRbObject.new_with_uri("drbunix:/tmp/gw_b_c") - -puts "c->b" -a = robj[:a] -sleep 2 - -a.ping(foo) - -DRb.thread.join -=end - diff --git a/lib/drb/invokemethod.rb b/lib/drb/invokemethod.rb deleted file mode 100644 index 0fae6d52b6a1c8..00000000000000 --- a/lib/drb/invokemethod.rb +++ /dev/null @@ -1,35 +0,0 @@ -# frozen_string_literal: false -# for ruby-1.8.0 - -module DRb # :nodoc: all - class DRbServer - module InvokeMethod18Mixin - def block_yield(x) - if x.size == 1 && x[0].class == Array - x[0] = DRbArray.new(x[0]) - end - @block.call(*x) - end - - def perform_with_block - @obj.__send__(@msg_id, *@argv) do |*x| - jump_error = nil - begin - block_value = block_yield(x) - rescue LocalJumpError - jump_error = $! - end - if jump_error - case jump_error.reason - when :break - break(jump_error.exit_value) - else - raise jump_error - end - end - block_value - end - end - end - end -end diff --git a/lib/drb/observer.rb b/lib/drb/observer.rb deleted file mode 100644 index 0fb7301edfb12f..00000000000000 --- a/lib/drb/observer.rb +++ /dev/null @@ -1,26 +0,0 @@ -# frozen_string_literal: false -require 'observer' - -module DRb - # The Observable module extended to DRb. See Observable for details. - module DRbObservable - include Observable - - # Notifies observers of a change in state. See also - # Observable#notify_observers - def notify_observers(*arg) - if defined? @observer_state and @observer_state - if defined? @observer_peers - @observer_peers.each do |observer, method| - begin - observer.__send__(method, *arg) - rescue - delete_observer(observer) - end - end - end - @observer_state = false - end - end - end -end diff --git a/lib/drb/ssl.rb b/lib/drb/ssl.rb deleted file mode 100644 index 54ab1ef395d825..00000000000000 --- a/lib/drb/ssl.rb +++ /dev/null @@ -1,344 +0,0 @@ -# frozen_string_literal: false -require 'socket' -require 'openssl' -require_relative 'drb' -require 'singleton' - -module DRb - - # The protocol for DRb over an SSL socket - # - # The URI for a DRb socket over SSL is: - # drbssl://:?. The option is optional - class DRbSSLSocket < DRbTCPSocket - - # SSLConfig handles the needed SSL information for establishing a - # DRbSSLSocket connection, including generating the X509 / RSA pair. - # - # An instance of this config can be passed to DRbSSLSocket.new, - # DRbSSLSocket.open and DRbSSLSocket.open_server - # - # See DRb::DRbSSLSocket::SSLConfig.new for more details - class SSLConfig - - # Default values for a SSLConfig instance. - # - # See DRb::DRbSSLSocket::SSLConfig.new for more details - DEFAULT = { - :SSLCertificate => nil, - :SSLPrivateKey => nil, - :SSLClientCA => nil, - :SSLCACertificatePath => nil, - :SSLCACertificateFile => nil, - :SSLTmpDhCallback => nil, - :SSLVerifyMode => ::OpenSSL::SSL::VERIFY_NONE, - :SSLVerifyDepth => nil, - :SSLVerifyCallback => nil, # custom verification - :SSLCertificateStore => nil, - # Must specify if you use auto generated certificate. - :SSLCertName => nil, # e.g. [["CN","fqdn.example.com"]] - :SSLCertComment => "Generated by Ruby/OpenSSL" - } - - # Create a new DRb::DRbSSLSocket::SSLConfig instance - # - # The DRb::DRbSSLSocket will take either a +config+ Hash or an instance - # of SSLConfig, and will setup the certificate for its session for the - # configuration. If want it to generate a generic certificate, the bare - # minimum is to provide the :SSLCertName - # - # === Config options - # - # From +config+ Hash: - # - # :SSLCertificate :: - # An instance of OpenSSL::X509::Certificate. If this is not provided, - # then a generic X509 is generated, with a correspond :SSLPrivateKey - # - # :SSLPrivateKey :: - # A private key instance, like OpenSSL::PKey::RSA. This key must be - # the key that signed the :SSLCertificate - # - # :SSLClientCA :: - # An OpenSSL::X509::Certificate, or Array of certificates that will - # used as ClientCAs in the SSL Context - # - # :SSLCACertificatePath :: - # A path to the directory of CA certificates. The certificates must - # be in PEM format. - # - # :SSLCACertificateFile :: - # A path to a CA certificate file, in PEM format. - # - # :SSLTmpDhCallback :: - # A DH callback. See OpenSSL::SSL::SSLContext.tmp_dh_callback - # - # :SSLVerifyMode :: - # This is the SSL verification mode. See OpenSSL::SSL::VERIFY_* for - # available modes. The default is OpenSSL::SSL::VERIFY_NONE - # - # :SSLVerifyDepth :: - # Number of CA certificates to walk, when verifying a certificate - # chain. - # - # :SSLVerifyCallback :: - # A callback to be used for additional verification. See - # OpenSSL::SSL::SSLContext.verify_callback - # - # :SSLCertificateStore :: - # A OpenSSL::X509::Store used for verification of certificates - # - # :SSLCertName :: - # Issuer name for the certificate. This is required when generating - # the certificate (if :SSLCertificate and :SSLPrivateKey were not - # given). The value of this is to be an Array of pairs: - # - # [["C", "Raleigh"], ["ST","North Carolina"], - # ["CN","fqdn.example.com"]] - # - # See also OpenSSL::X509::Name - # - # :SSLCertComment :: - # A comment to be used for generating the certificate. The default is - # "Generated by Ruby/OpenSSL" - # - # - # === Example - # - # These values can be added after the fact, like a Hash. - # - # require 'drb/ssl' - # c = DRb::DRbSSLSocket::SSLConfig.new {} - # c[:SSLCertificate] = - # OpenSSL::X509::Certificate.new(File.read('mycert.crt')) - # c[:SSLPrivateKey] = OpenSSL::PKey::RSA.new(File.read('mycert.key')) - # c[:SSLVerifyMode] = OpenSSL::SSL::VERIFY_PEER - # c[:SSLCACertificatePath] = "/etc/ssl/certs/" - # c.setup_certificate - # - # or - # - # require 'drb/ssl' - # c = DRb::DRbSSLSocket::SSLConfig.new({ - # :SSLCertName => [["CN" => DRb::DRbSSLSocket.getservername]] - # }) - # c.setup_certificate - # - def initialize(config) - @config = config - @cert = config[:SSLCertificate] - @pkey = config[:SSLPrivateKey] - @ssl_ctx = nil - end - - # A convenience method to access the values like a Hash - def [](key); - @config[key] || DEFAULT[key] - end - - # Connect to IO +tcp+, with context of the current certificate - # configuration - def connect(tcp) - ssl = ::OpenSSL::SSL::SSLSocket.new(tcp, @ssl_ctx) - ssl.sync = true - ssl.connect - ssl - end - - # Accept connection to IO +tcp+, with context of the current certificate - # configuration - def accept(tcp) - ssl = OpenSSL::SSL::SSLSocket.new(tcp, @ssl_ctx) - ssl.sync = true - ssl.accept - ssl - end - - # Ensures that :SSLCertificate and :SSLPrivateKey have been provided - # or that a new certificate is generated with the other parameters - # provided. - def setup_certificate - if @cert && @pkey - return - end - - rsa = OpenSSL::PKey::RSA.new(2048){|p, n| - next unless self[:verbose] - case p - when 0; $stderr.putc "." # BN_generate_prime - when 1; $stderr.putc "+" # BN_generate_prime - when 2; $stderr.putc "*" # searching good prime, - # n = #of try, - # but also data from BN_generate_prime - when 3; $stderr.putc "\n" # found good prime, n==0 - p, n==1 - q, - # but also data from BN_generate_prime - else; $stderr.putc "*" # BN_generate_prime - end - } - - cert = OpenSSL::X509::Certificate.new - cert.version = 3 - cert.serial = 0 - name = OpenSSL::X509::Name.new(self[:SSLCertName]) - cert.subject = name - cert.issuer = name - cert.not_before = Time.now - cert.not_after = Time.now + (365*24*60*60) - cert.public_key = rsa.public_key - - ef = OpenSSL::X509::ExtensionFactory.new(nil,cert) - cert.extensions = [ - ef.create_extension("basicConstraints","CA:FALSE"), - ef.create_extension("subjectKeyIdentifier", "hash") ] - ef.issuer_certificate = cert - cert.add_extension(ef.create_extension("authorityKeyIdentifier", - "keyid:always,issuer:always")) - if comment = self[:SSLCertComment] - cert.add_extension(ef.create_extension("nsComment", comment)) - end - cert.sign(rsa, "SHA256") - - @cert = cert - @pkey = rsa - end - - # Establish the OpenSSL::SSL::SSLContext with the configuration - # parameters provided. - def setup_ssl_context - ctx = ::OpenSSL::SSL::SSLContext.new - ctx.cert = @cert - ctx.key = @pkey - ctx.client_ca = self[:SSLClientCA] - ctx.ca_path = self[:SSLCACertificatePath] - ctx.ca_file = self[:SSLCACertificateFile] - ctx.tmp_dh_callback = self[:SSLTmpDhCallback] - ctx.verify_mode = self[:SSLVerifyMode] - ctx.verify_depth = self[:SSLVerifyDepth] - ctx.verify_callback = self[:SSLVerifyCallback] - ctx.cert_store = self[:SSLCertificateStore] - @ssl_ctx = ctx - end - end - - # Parse the dRuby +uri+ for an SSL connection. - # - # Expects drbssl://... - # - # Raises DRbBadScheme or DRbBadURI if +uri+ is not matching or malformed - def self.parse_uri(uri) # :nodoc: - if /\Adrbssl:\/\/(.*?):(\d+)(\?(.*))?\z/ =~ uri - host = $1 - port = $2.to_i - option = $4 - [host, port, option] - else - raise(DRbBadScheme, uri) unless uri.start_with?('drbssl:') - raise(DRbBadURI, 'can\'t parse uri:' + uri) - end - end - - # Return an DRb::DRbSSLSocket instance as a client-side connection, - # with the SSL connected. This is called from DRb::start_service or while - # connecting to a remote object: - # - # DRb.start_service 'drbssl://localhost:0', front, config - # - # +uri+ is the URI we are connected to, - # 'drbssl://localhost:0' above, +config+ is our - # configuration. Either a Hash or DRb::DRbSSLSocket::SSLConfig - def self.open(uri, config) - host, port, = parse_uri(uri) - soc = TCPSocket.open(host, port) - ssl_conf = SSLConfig::new(config) - ssl_conf.setup_ssl_context - ssl = ssl_conf.connect(soc) - self.new(uri, ssl, ssl_conf, true) - end - - # Returns a DRb::DRbSSLSocket instance as a server-side connection, with - # the SSL connected. This is called from DRb::start_service or while - # connecting to a remote object: - # - # DRb.start_service 'drbssl://localhost:0', front, config - # - # +uri+ is the URI we are connected to, - # 'drbssl://localhost:0' above, +config+ is our - # configuration. Either a Hash or DRb::DRbSSLSocket::SSLConfig - def self.open_server(uri, config) - uri = 'drbssl://:0' unless uri - host, port, = parse_uri(uri) - if host.size == 0 - host = getservername - soc = open_server_inaddr_any(host, port) - else - soc = TCPServer.open(host, port) - end - port = soc.addr[1] if port == 0 - @uri = "drbssl://#{host}:#{port}" - - ssl_conf = SSLConfig.new(config) - ssl_conf.setup_certificate - ssl_conf.setup_ssl_context - self.new(@uri, soc, ssl_conf, false) - end - - # This is a convenience method to parse +uri+ and separate out any - # additional options appended in the +uri+. - # - # Returns an option-less uri and the option => [uri,option] - # - # The +config+ is completely unused, so passing nil is sufficient. - def self.uri_option(uri, config) # :nodoc: - host, port, option = parse_uri(uri) - return "drbssl://#{host}:#{port}", option - end - - # Create a DRb::DRbSSLSocket instance. - # - # +uri+ is the URI we are connected to. - # +soc+ is the tcp socket we are bound to. - # +config+ is our configuration. Either a Hash or SSLConfig - # +is_established+ is a boolean of whether +soc+ is currently established - # - # This is called automatically based on the DRb protocol. - def initialize(uri, soc, config, is_established) - @ssl = is_established ? soc : nil - super(uri, soc.to_io, config) - end - - # Returns the SSL stream - def stream; @ssl; end # :nodoc: - - # Closes the SSL stream before closing the dRuby connection. - def close # :nodoc: - if @ssl - @ssl.close - @ssl = nil - end - super - end - - def accept # :nodoc: - begin - while true - soc = accept_or_shutdown - return nil unless soc - break if (@acl ? @acl.allow_socket?(soc) : true) - soc.close - end - begin - ssl = @config.accept(soc) - rescue Exception - soc.close - raise - end - self.class.new(uri, ssl, @config, true) - rescue OpenSSL::SSL::SSLError - warn("#{$!.message} (#{$!.class})", uplevel: 0) if @config[:verbose] - retry - end - end - end - - DRbProtocol.add_protocol(DRbSSLSocket) -end diff --git a/lib/drb/timeridconv.rb b/lib/drb/timeridconv.rb deleted file mode 100644 index 3ead98a7f24527..00000000000000 --- a/lib/drb/timeridconv.rb +++ /dev/null @@ -1,97 +0,0 @@ -# frozen_string_literal: false -require_relative 'drb' -require 'monitor' - -module DRb - - # Timer id conversion keeps objects alive for a certain amount of time after - # their last access. The default time period is 600 seconds and can be - # changed upon initialization. - # - # To use TimerIdConv: - # - # DRb.install_id_conv TimerIdConv.new 60 # one minute - - class TimerIdConv < DRbIdConv - class TimerHolder2 # :nodoc: - include MonitorMixin - - class InvalidIndexError < RuntimeError; end - - def initialize(keeping=600) - super() - @sentinel = Object.new - @gc = {} - @renew = {} - @keeping = keeping - @expires = nil - end - - def add(obj) - synchronize do - rotate - key = obj.__id__ - @renew[key] = obj - invoke_keeper - return key - end - end - - def fetch(key) - synchronize do - rotate - obj = peek(key) - raise InvalidIndexError if obj == @sentinel - @renew[key] = obj # KeepIt - return obj - end - end - - private - def peek(key) - return @renew.fetch(key) { @gc.fetch(key, @sentinel) } - end - - def invoke_keeper - return if @expires - @expires = Time.now + @keeping - on_gc - end - - def on_gc - return unless Thread.main.alive? - return if @expires.nil? - Thread.new { rotate } if @expires < Time.now - ObjectSpace.define_finalizer(Object.new) {on_gc} - end - - def rotate - synchronize do - if @expires &.< Time.now - @gc = @renew # GCed - @renew = {} - @expires = @gc.empty? ? nil : Time.now + @keeping - end - end - end - end - - # Creates a new TimerIdConv which will hold objects for +keeping+ seconds. - def initialize(keeping=600) - @holder = TimerHolder2.new(keeping) - end - - def to_obj(ref) # :nodoc: - return super if ref.nil? - @holder.fetch(ref) - rescue TimerHolder2::InvalidIndexError - raise "invalid reference" - end - - def to_id(obj) # :nodoc: - return @holder.add(obj) - end - end -end - -# DRb.install_id_conv(TimerIdConv.new) diff --git a/lib/drb/unix.rb b/lib/drb/unix.rb deleted file mode 100644 index 1629ad3bcd04b0..00000000000000 --- a/lib/drb/unix.rb +++ /dev/null @@ -1,118 +0,0 @@ -# frozen_string_literal: false -require 'socket' -require_relative 'drb' -require 'tmpdir' - -raise(LoadError, "UNIXServer is required") unless defined?(UNIXServer) - -module DRb - - # Implements DRb over a UNIX socket - # - # DRb UNIX socket URIs look like drbunix:?. The - # option is optional. - - class DRbUNIXSocket < DRbTCPSocket - # :stopdoc: - def self.parse_uri(uri) - if /\Adrbunix:(.*?)(\?(.*))?\z/ =~ uri - filename = $1 - option = $3 - [filename, option] - else - raise(DRbBadScheme, uri) unless uri.start_with?('drbunix:') - raise(DRbBadURI, 'can\'t parse uri:' + uri) - end - end - - def self.open(uri, config) - filename, = parse_uri(uri) - soc = UNIXSocket.open(filename) - self.new(uri, soc, config) - end - - def self.open_server(uri, config) - filename, = parse_uri(uri) - if filename.size == 0 - soc = temp_server - filename = soc.path - uri = 'drbunix:' + soc.path - else - soc = UNIXServer.open(filename) - end - owner = config[:UNIXFileOwner] - group = config[:UNIXFileGroup] - if owner || group - require 'etc' - owner = Etc.getpwnam( owner ).uid if owner - group = Etc.getgrnam( group ).gid if group - File.chown owner, group, filename - end - mode = config[:UNIXFileMode] - File.chmod(mode, filename) if mode - - self.new(uri, soc, config, true) - end - - def self.uri_option(uri, config) - filename, option = parse_uri(uri) - return "drbunix:#{filename}", option - end - - def initialize(uri, soc, config={}, server_mode = false) - super(uri, soc, config) - set_sockopt(@socket) - @server_mode = server_mode - @acl = nil - end - - # import from tempfile.rb - Max_try = 10 - private - def self.temp_server - tmpdir = Dir::tmpdir - n = 0 - while true - begin - tmpname = sprintf('%s/druby%d.%d', tmpdir, $$, n) - lock = tmpname + '.lock' - unless File.exist?(tmpname) or File.exist?(lock) - Dir.mkdir(lock) - break - end - rescue - raise "cannot generate tempfile `%s'" % tmpname if n >= Max_try - #sleep(1) - end - n += 1 - end - soc = UNIXServer.new(tmpname) - Dir.rmdir(lock) - soc - end - - public - def close - return unless @socket - shutdown # DRbProtocol#shutdown - path = @socket.path if @server_mode - @socket.close - File.unlink(path) if @server_mode - @socket = nil - close_shutdown_pipe - end - - def accept - s = accept_or_shutdown - return nil unless s - self.class.new(nil, s, @config) - end - - def set_sockopt(soc) - # no-op for now - end - end - - DRbProtocol.add_protocol(DRbUNIXSocket) - # :startdoc: -end diff --git a/lib/drb/version.rb b/lib/drb/version.rb deleted file mode 100644 index 10d33445b62b46..00000000000000 --- a/lib/drb/version.rb +++ /dev/null @@ -1,3 +0,0 @@ -module DRb - VERSION = "2.1.1" -end diff --git a/lib/drb/weakidconv.rb b/lib/drb/weakidconv.rb deleted file mode 100644 index ecf0bf515fb9f1..00000000000000 --- a/lib/drb/weakidconv.rb +++ /dev/null @@ -1,59 +0,0 @@ -# frozen_string_literal: false -require_relative 'drb' -require 'monitor' - -module DRb - - # To use WeakIdConv: - # - # DRb.start_service(nil, nil, {:idconv => DRb::WeakIdConv.new}) - - class WeakIdConv < DRbIdConv - class WeakSet - include MonitorMixin - def initialize - super() - @immutable = {} - @map = ObjectSpace::WeakMap.new - end - - def add(obj) - synchronize do - begin - @map[obj] = self - rescue ArgumentError - @immutable[obj.__id__] = obj - end - return obj.__id__ - end - end - - def fetch(ref) - synchronize do - @immutable.fetch(ref) { - @map.each { |key, _| - return key if key.__id__ == ref - } - raise RangeError.new("invalid reference") - } - end - end - end - - def initialize() - super() - @weak_set = WeakSet.new - end - - def to_obj(ref) # :nodoc: - return super if ref.nil? - @weak_set.fetch(ref) - end - - def to_id(obj) # :nodoc: - return @weak_set.add(obj) - end - end -end - -# DRb.install_id_conv(WeakIdConv.new) diff --git a/lib/erb.rb b/lib/erb.rb index bc1615d7da6e6d..ebf91e4792d67e 100644 --- a/lib/erb.rb +++ b/lib/erb.rb @@ -12,7 +12,6 @@ # # You can redistribute it and/or modify it under the same terms as Ruby. -require 'cgi/util' require 'erb/version' require 'erb/compiler' require 'erb/def_method' @@ -294,7 +293,7 @@ def self.version # # build data class # class Listings # PRODUCT = { :name => "Chicken Fried Steak", - # :desc => "A well messages pattie, breaded and fried.", + # :desc => "A well messaged pattie, breaded and fried.", # :cost => 9.95 } # # attr_reader :product, :price @@ -327,10 +326,10 @@ def self.version # _Generates_ # # Chicken Fried Steak - # A well messages pattie, breaded and fried. + # A well massaged pattie, breaded and fried. # # Chicken Fried Steak -- 9.95 - # A well messages pattie, breaded and fried. + # A well massaged pattie, breaded and fried. # def initialize(str, safe_level=NOT_GIVEN, legacy_trim_mode=NOT_GIVEN, legacy_eoutvar=NOT_GIVEN, trim_mode: nil, eoutvar: '_erbout') # Complex initializer for $SAFE deprecation at [Feature #14256]. Use keyword arguments to pass trim_mode or eoutvar. @@ -353,7 +352,7 @@ def initialize(str, safe_level=NOT_GIVEN, legacy_trim_mode=NOT_GIVEN, legacy_eou @lineno = 0 @_init = self.class.singleton_class end - NOT_GIVEN = Object.new + NOT_GIVEN = defined?(Ractor) ? Ractor.make_shareable(Object.new) : Object.new private_constant :NOT_GIVEN ## @@ -416,8 +415,7 @@ def run(b=new_toplevel) # # Executes the generated ERB code to produce a completed template, returning - # the results of that code. (See ERB::new for details on how this process - # can be affected by _safe_level_.) + # the results of that code. # # _b_ accepts a Binding object which is used to set the context of # code evaluation. diff --git a/lib/erb/compiler.rb b/lib/erb/compiler.rb index 7096c8dcea802c..08b5eb4ee1d220 100644 --- a/lib/erb/compiler.rb +++ b/lib/erb/compiler.rb @@ -80,10 +80,16 @@ def initialize(str) end class Scanner # :nodoc: - @scanner_map = {} + @scanner_map = defined?(Ractor) ? Ractor.make_shareable({}) : {} class << self - def register_scanner(klass, trim_mode, percent) - @scanner_map[[trim_mode, percent]] = klass + if defined?(Ractor) + def register_scanner(klass, trim_mode, percent) + @scanner_map = Ractor.make_shareable({ **@scanner_map, [trim_mode, percent] => klass }) + end + else + def register_scanner(klass, trim_mode, percent) + @scanner_map[[trim_mode, percent]] = klass + end end alias :regist_scanner :register_scanner end @@ -466,7 +472,17 @@ def detect_magic_comment(s, enc = nil) return enc, frozen end + # :stopdoc: + WARNING_UPLEVEL = Class.new { + attr_reader :c + def initialize from + @c = caller.length - from.length + end + }.new(caller(0)).c + private_constant :WARNING_UPLEVEL + # :startdoc: + def warn_invalid_trim_mode(mode, uplevel:) - warn "Invalid ERB trim mode: #{mode.inspect} (trim_mode: nil, 0, 1, 2, or String composed of '%' and/or '-', '>', '<>')", uplevel: uplevel + 1 + warn "Invalid ERB trim mode: #{mode.inspect} (trim_mode: nil, 0, 1, 2, or String composed of '%' and/or '-', '>', '<>')", uplevel: uplevel + WARNING_UPLEVEL end end diff --git a/lib/erb/def_method.rb b/lib/erb/def_method.rb index aee989a926ea94..e503b3714085b8 100644 --- a/lib/erb/def_method.rb +++ b/lib/erb/def_method.rb @@ -1,5 +1,5 @@ # frozen_string_literal: true -#-- + # ERB::DefMethod # # Utility module to define eRuby script as instance method. diff --git a/lib/erb.gemspec b/lib/erb/erb.gemspec similarity index 81% rename from lib/erb.gemspec rename to lib/erb/erb.gemspec index 94a8fd5c3ec795..94edc686825419 100644 --- a/lib/erb.gemspec +++ b/lib/erb/erb.gemspec @@ -2,19 +2,18 @@ begin require_relative 'lib/erb/version' rescue LoadError # for Ruby core repository - require_relative 'erb/version' + require_relative 'version' end Gem::Specification.new do |spec| spec.name = 'erb' - spec.version = ERB.const_get(:VERSION, false) + spec.version = ERB::VERSION spec.authors = ['Masatoshi SEKI', 'Takashi Kokubun'] spec.email = ['seki@ruby-lang.org', 'k0kubun@ruby-lang.org'] spec.summary = %q{An easy to use but powerful templating system for Ruby.} spec.description = %q{An easy to use but powerful templating system for Ruby.} spec.homepage = 'https://github.com/ruby/erb' - spec.required_ruby_version = Gem::Requirement.new('>= 2.5.0') spec.licenses = ['Ruby', 'BSD-2-Clause'] spec.metadata['homepage_uri'] = spec.homepage @@ -27,12 +26,11 @@ Gem::Specification.new do |spec| spec.executables = ['erb'] spec.require_paths = ['lib'] + spec.required_ruby_version = '>= 3.2.0' + if RUBY_ENGINE == 'jruby' spec.platform = 'java' else - spec.required_ruby_version = '>= 2.7.0' spec.extensions = ['ext/erb/escape/extconf.rb'] end - - spec.add_dependency 'cgi', '>= 0.3.3' end diff --git a/lib/erb/util.rb b/lib/erb/util.rb index 1d2a36275dbbeb..42c7a5762215b9 100644 --- a/lib/erb/util.rb +++ b/lib/erb/util.rb @@ -1,17 +1,23 @@ # frozen_string_literal: true -#-- -# ERB::Escape -# -# A subset of ERB::Util. Unlike ERB::Util#html_escape, we expect/hope -# Rails will not monkey-patch ERB::Escape#html_escape. + +# Load CGI.escapeHTML and CGI.escapeURIComponent. +# CRuby: +# cgi.gem v0.1.0+ (Ruby 2.7-3.4) and Ruby 3.5+ stdlib have 'cgi/escape' and CGI.escapeHTML. +# cgi.gem v0.3.3+ (Ruby 3.2-3.4) and Ruby 3.5+ stdlib have CGI.escapeURIComponent. +# JRuby: cgi.gem has a Java extension 'cgi/escape'. +# TruffleRuby: lib/truffle/cgi/escape.rb requires 'cgi/util'. +require 'cgi/escape' + +# Load or define ERB::Escape#html_escape. +# We don't build the C extention 'cgi/escape' for JRuby, TruffleRuby, and WASM. +# miniruby (used by CRuby build scripts) also fails to load erb/escape.so. begin - # We don't build the C extension for JRuby, TruffleRuby, and WASM - if $LOAD_PATH.resolve_feature_path('erb/escape') - require 'erb/escape' - end -rescue LoadError # resolve_feature_path raises LoadError on TruffleRuby 22.3.0 -end -unless defined?(ERB::Escape) + require 'erb/escape' +rescue LoadError + # ERB::Escape + # + # A subset of ERB::Util. Unlike ERB::Util#html_escape, we expect/hope + # Rails will not monkey-patch ERB::Escape#html_escape. module ERB::Escape def html_escape(s) CGI.escapeHTML(s.to_s) @@ -20,7 +26,6 @@ def html_escape(s) end end -#-- # ERB::Util # # A utility module for conversion routines, often handy in HTML generation. @@ -54,8 +59,16 @@ module ERB::Util # # Programming%20Ruby%3A%20%20The%20Pragmatic%20Programmer%27s%20Guide # - def url_encode(s) - CGI.escapeURIComponent(s.to_s) + if CGI.respond_to?(:escapeURIComponent) + def url_encode(s) + CGI.escapeURIComponent(s.to_s) + end + else # cgi.gem <= v0.3.2 + def url_encode(s) + s.to_s.b.gsub(/[^a-zA-Z0-9_\-.~]/n) do |m| + sprintf("%%%02X", m.unpack1("C")) + end + end end alias u url_encode module_function :u diff --git a/lib/erb/version.rb b/lib/erb/version.rb index 295fc5fa6f7964..3d0cedcd48475d 100644 --- a/lib/erb/version.rb +++ b/lib/erb/version.rb @@ -1,5 +1,4 @@ # frozen_string_literal: true class ERB - VERSION = '4.0.3' - private_constant :VERSION + VERSION = '5.0.1' end diff --git a/lib/error_highlight/base.rb b/lib/error_highlight/base.rb index 7d2ff0c889987a..14e0ce5785a354 100644 --- a/lib/error_highlight/base.rb +++ b/lib/error_highlight/base.rb @@ -54,11 +54,20 @@ def self.spot(obj, **opts) return nil unless Thread::Backtrace::Location === loc - node = RubyVM::AbstractSyntaxTree.of(loc, keep_script_lines: true) + node = + begin + RubyVM::AbstractSyntaxTree.of(loc, keep_script_lines: true) + rescue RuntimeError => error + # RubyVM::AbstractSyntaxTree.of raises an error with a message that + # includes "prism" when the ISEQ was compiled with the prism compiler. + # In this case, we'll try to parse again with prism instead. + raise unless error.message.include?("prism") + prism_find(loc) + end Spotter.new(node, **opts).spot - when RubyVM::AbstractSyntaxTree::Node + when RubyVM::AbstractSyntaxTree::Node, Prism::Node Spotter.new(obj, **opts).spot else @@ -72,6 +81,21 @@ def self.spot(obj, **opts) return nil end + # Accepts a Thread::Backtrace::Location object and returns a Prism::Node + # corresponding to the backtrace location in the source code. + def self.prism_find(location) + require "prism" + return nil if Prism::VERSION < "1.0.0" + + absolute_path = location.absolute_path + return unless absolute_path + + node_id = RubyVM::AbstractSyntaxTree.node_id_for_backtrace_location(location) + Prism.parse_file(absolute_path).value.breadth_first_search { |node| node.node_id == node_id } + end + + private_class_method :prism_find + class Spotter class NonAscii < Exception; end private_constant :NonAscii @@ -104,31 +128,49 @@ def initialize(node, point_type: :name, name: nil) def spot return nil unless @node - if OPT_GETCONSTANT_PATH && @node.type == :COLON2 + if OPT_GETCONSTANT_PATH # In Ruby 3.2 or later, a nested constant access (like `Foo::Bar::Baz`) # is compiled to one instruction (opt_getconstant_path). # @node points to the node of the whole `Foo::Bar::Baz` even if `Foo` # or `Foo::Bar` causes NameError. # So we try to spot the sub-node that causes the NameError by using # `NameError#name`. - subnodes = [] - node = @node - while node.type == :COLON2 - node2, const = node.children - subnodes << node if const == @name - node = node2 - end - if node.type == :CONST || node.type == :COLON3 - if node.children.first == @name + case @node.type + when :COLON2 + subnodes = [] + node = @node + while node.type == :COLON2 + node2, const = node.children + subnodes << node if const == @name + node = node2 + end + if node.type == :CONST || node.type == :COLON3 + if node.children.first == @name + subnodes << node + end + + # If we found only one sub-node whose name is equal to @name, use it + return nil if subnodes.size != 1 + @node = subnodes.first + else + # Do nothing; opt_getconstant_path is used only when the const base is + # NODE_CONST (`Foo`) or NODE_COLON3 (`::Foo`) + end + when :constant_path_node + subnodes = [] + node = @node + + begin + subnodes << node if node.name == @name + end while (node = node.parent).is_a?(Prism::ConstantPathNode) + + if node.is_a?(Prism::ConstantReadNode) && node.name == @name subnodes << node end # If we found only one sub-node whose name is equal to @name, use it return nil if subnodes.size != 1 @node = subnodes.first - else - # Do nothing; opt_getconstant_path is used only when the const base is - # NODE_CONST (`Foo`) or NODE_COLON3 (`::Foo`) end end @@ -196,6 +238,48 @@ def spot when :OP_CDECL spot_op_cdecl + + when :call_node + case @point_type + when :name + prism_spot_call_for_name + when :args + prism_spot_call_for_args + end + + when :local_variable_operator_write_node + case @point_type + when :name + prism_spot_local_variable_operator_write_for_name + when :args + prism_spot_local_variable_operator_write_for_args + end + + when :call_operator_write_node + case @point_type + when :name + prism_spot_call_operator_write_for_name + when :args + prism_spot_call_operator_write_for_args + end + + when :index_operator_write_node + case @point_type + when :name + prism_spot_index_operator_write_for_name + when :args + prism_spot_index_operator_write_for_args + end + + when :constant_read_node + prism_spot_constant_read + + when :constant_path_node + prism_spot_constant_path + + when :constant_path_operator_write_node + prism_spot_constant_path_operator_write + end if @snippet && @beg_column && @end_column && @beg_column < @end_column @@ -260,6 +344,7 @@ def spot_call_for_name end elsif mid.to_s =~ /\A\W+\z/ && lines.match(/\G\s*(#{ Regexp.quote(mid) })=.*\n/, nd_recv.last_column) @snippet = $` + $& + @beg_lineno = @end_lineno = lineno @beg_column = $~.begin(1) @end_column = $~.end(1) end @@ -498,8 +583,9 @@ def spot_colon2 @beg_column = nd_parent.last_column @end_column = @node.last_column else - @snippet = @fetch[@node.last_lineno] + fetch_line(@node.last_lineno) if @snippet[...@node.last_column].match(/#{ Regexp.quote(const) }\z/) + @beg_lineno = @end_lineno = @node.last_lineno @beg_column = $~.begin(0) @end_column = $~.end(0) end @@ -513,7 +599,7 @@ def spot_op_cdecl nd_lhs, op, _nd_rhs = @node.children *nd_parent_lhs, _const = nd_lhs.children if @name == op - @snippet = @fetch[nd_lhs.last_lineno] + fetch_line(nd_lhs.last_lineno) if @snippet.match(/\G\s*(#{ Regexp.quote(op) })=/, nd_lhs.last_column) @beg_column = $~.begin(1) @end_column = $~.end(1) @@ -523,12 +609,12 @@ def spot_op_cdecl @end_column = nd_lhs.last_column if nd_parent_lhs.empty? # example: ::C += 1 if nd_lhs.first_lineno == nd_lhs.last_lineno - @snippet = @fetch[nd_lhs.last_lineno] + fetch_line(nd_lhs.last_lineno) @beg_column = nd_lhs.first_column end else # example: Foo::Bar::C += 1 if nd_parent_lhs.last.last_lineno == nd_lhs.last_lineno - @snippet = @fetch[nd_lhs.last_lineno] + fetch_line(nd_lhs.last_lineno) @beg_column = nd_parent_lhs.last.last_column end end @@ -539,6 +625,207 @@ def fetch_line(lineno) @beg_lineno = @end_lineno = lineno @snippet = @fetch[lineno] end + + # Take a location from the prism parser and set the necessary instance + # variables. + def prism_location(location) + @beg_lineno = location.start_line + @beg_column = location.start_column + @end_lineno = location.end_line + @end_column = location.end_column + @snippet = @fetch[@beg_lineno, @end_lineno] + end + + # Example: + # x.foo + # ^^^^ + # x.foo(42) + # ^^^^ + # x&.foo + # ^^^^^ + # x[42] + # ^^^^ + # x.foo = 1 + # ^^^^^^ + # x[42] = 1 + # ^^^^^^ + # x + 1 + # ^ + # +x + # ^ + # foo(42) + # ^^^ + # foo 42 + # ^^^ + # foo + # ^^^ + def prism_spot_call_for_name + # Explicitly turn off foo.() syntax because error_highlight expects this + # to not work. + return nil if @node.name == :call && @node.message_loc.nil? + + location = @node.message_loc || @node.call_operator_loc || @node.location + location = @node.call_operator_loc.join(location) if @node.call_operator_loc&.start_line == location.start_line + + # If the method name ends with "=" but the message does not, then this is + # a method call using the "attribute assignment" syntax + # (e.g., foo.bar = 1). In this case we need to go retrieve the = sign and + # add it to the location. + if (name = @node.name).end_with?("=") && !@node.message.end_with?("=") + location = location.adjoin("=") + end + + prism_location(location) + + if !name.end_with?("=") && !name.match?(/[[:alpha:]_\[]/) + # If the method name is an operator, then error_highlight only + # highlights the first line. + fetch_line(location.start_line) + end + end + + # Example: + # x.foo(42) + # ^^ + # x[42] + # ^^ + # x.foo = 1 + # ^ + # x[42] = 1 + # ^^^^^^^ + # x[] = 1 + # ^^^^^ + # x + 1 + # ^ + # foo(42) + # ^^ + # foo 42 + # ^^ + def prism_spot_call_for_args + # Disallow highlighting arguments if there are no arguments. + return if @node.arguments.nil? + + # Explicitly turn off foo.() syntax because error_highlight expects this + # to not work. + return nil if @node.name == :call && @node.message_loc.nil? + + if @node.name == :[]= && @node.opening == "[" && (@node.arguments&.arguments || []).length == 1 + prism_location(@node.opening_loc.copy(start_offset: @node.opening_loc.start_offset + 1).join(@node.arguments.location)) + else + prism_location(@node.arguments.location) + end + end + + # Example: + # x += 1 + # ^ + def prism_spot_local_variable_operator_write_for_name + prism_location(@node.binary_operator_loc.chop) + end + + # Example: + # x += 1 + # ^ + def prism_spot_local_variable_operator_write_for_args + prism_location(@node.value.location) + end + + # Example: + # x.foo += 42 + # ^^^ (for foo) + # x.foo += 42 + # ^ (for +) + # x.foo += 42 + # ^^^^^^^ (for foo=) + def prism_spot_call_operator_write_for_name + if !@name.start_with?(/[[:alpha:]_]/) + prism_location(@node.binary_operator_loc.chop) + else + location = @node.message_loc + if @node.call_operator_loc.start_line == location.start_line + location = @node.call_operator_loc.join(location) + end + + location = location.adjoin("=") if @name.end_with?("=") + prism_location(location) + end + end + + # Example: + # x.foo += 42 + # ^^ + def prism_spot_call_operator_write_for_args + prism_location(@node.value.location) + end + + # Example: + # x[1] += 42 + # ^^^ (for []) + # x[1] += 42 + # ^ (for +) + # x[1] += 42 + # ^^^^^^ (for []=) + def prism_spot_index_operator_write_for_name + case @name + when :[] + prism_location(@node.opening_loc.join(@node.closing_loc)) + when :[]= + prism_location(@node.opening_loc.join(@node.closing_loc).adjoin("=")) + else + # Explicitly turn off foo[] += 1 syntax when the operator is not on + # the same line because error_highlight expects this to not work. + return nil if @node.binary_operator_loc.start_line != @node.opening_loc.start_line + + prism_location(@node.binary_operator_loc.chop) + end + end + + # Example: + # x[1] += 42 + # ^^^^^^^^ + def prism_spot_index_operator_write_for_args + opening_loc = + if @node.arguments.nil? + @node.opening_loc.copy(start_offset: @node.opening_loc.start_offset + 1) + else + @node.arguments.location + end + + prism_location(opening_loc.join(@node.value.location)) + end + + # Example: + # Foo + # ^^^ + def prism_spot_constant_read + prism_location(@node.location) + end + + # Example: + # Foo::Bar + # ^^^^^ + def prism_spot_constant_path + if @node.parent && @node.parent.location.end_line == @node.location.end_line + fetch_line(@node.parent.location.end_line) + prism_location(@node.delimiter_loc.join(@node.name_loc)) + else + fetch_line(@node.location.end_line) + location = @node.name_loc + location = @node.delimiter_loc.join(location) if @node.delimiter_loc.end_line == location.start_line + prism_location(location) + end + end + + # Example: + # Foo::Bar += 1 + # ^^^^^^^^ + def prism_spot_constant_path_operator_write + if @name == (target = @node.target).name + prism_location(target.delimiter_loc.join(target.name_loc)) + else + prism_location(@node.binary_operator_loc.chop) + end + end end private_constant :Spotter diff --git a/lib/error_highlight/formatter.rb b/lib/error_highlight/formatter.rb index 20ca78d468a78c..5180576405b17d 100644 --- a/lib/error_highlight/formatter.rb +++ b/lib/error_highlight/formatter.rb @@ -1,15 +1,66 @@ module ErrorHighlight class DefaultFormatter + MIN_SNIPPET_WIDTH = 20 + def self.message_for(spot) # currently only a one-line code snippet is supported - if spot[:first_lineno] == spot[:last_lineno] - indent = spot[:snippet][0...spot[:first_column]].gsub(/[^\t]/, " ") - marker = indent + "^" * (spot[:last_column] - spot[:first_column]) + return "" unless spot[:first_lineno] == spot[:last_lineno] + + snippet = spot[:snippet] + first_column = spot[:first_column] + last_column = spot[:last_column] + ellipsis = "..." + + # truncate snippet to fit in the viewport + if max_snippet_width && snippet.size > max_snippet_width + available_width = max_snippet_width - ellipsis.size + center = first_column - max_snippet_width / 2 + + visible_start = last_column < available_width ? 0 : [center, 0].max + visible_end = visible_start + max_snippet_width + visible_start = snippet.size - max_snippet_width if visible_end > snippet.size + + prefix = visible_start.positive? ? ellipsis : "" + suffix = visible_end < snippet.size ? ellipsis : "" - "\n\n#{ spot[:snippet] }#{ marker }" - else - "" + snippet = prefix + snippet[(visible_start + prefix.size)...(visible_end - suffix.size)] + suffix + snippet << "\n" unless snippet.end_with?("\n") + + first_column -= visible_start + last_column = [last_column - visible_start, snippet.size - 1].min end + + indent = snippet[0...first_column].gsub(/[^\t]/, " ") + marker = indent + "^" * (last_column - first_column) + + "\n\n#{ snippet }#{ marker }" + end + + def self.max_snippet_width + return if Ractor.current[:__error_highlight_max_snippet_width__] == :disabled + + Ractor.current[:__error_highlight_max_snippet_width__] ||= terminal_width + end + + def self.max_snippet_width=(width) + return Ractor.current[:__error_highlight_max_snippet_width__] = :disabled if width.nil? + + width = width.to_i + + if width < MIN_SNIPPET_WIDTH + warn "'max_snippet_width' adjusted to minimum value of #{MIN_SNIPPET_WIDTH}." + width = MIN_SNIPPET_WIDTH + end + + Ractor.current[:__error_highlight_max_snippet_width__] = width + end + + def self.terminal_width + # lazy load io/console, so it's not loaded when 'max_snippet_width' is set + require "io/console" + $stderr.winsize[1] if $stderr.tty? + rescue LoadError, NoMethodError, SystemCallError + # do not truncate when window size is not available end end diff --git a/lib/error_highlight/version.rb b/lib/error_highlight/version.rb index 5afe5f06d698e9..d7a29c7c1e68db 100644 --- a/lib/error_highlight/version.rb +++ b/lib/error_highlight/version.rb @@ -1,3 +1,3 @@ module ErrorHighlight - VERSION = "0.5.1" + VERSION = "0.7.0" end diff --git a/lib/fileutils.gemspec b/lib/fileutils.gemspec index 76baea30394647..2603d664da7255 100644 --- a/lib/fileutils.gemspec +++ b/lib/fileutils.gemspec @@ -17,7 +17,7 @@ Gem::Specification.new do |s| s.description = "Several file utility methods for copying, moving, removing, etc." s.require_path = %w{lib} - s.files = ["LICENSE.txt", "README.md", "Rakefile", "fileutils.gemspec", "lib/fileutils.rb"] + s.files = ["COPYING", "BSDL", "README.md", "Rakefile", "fileutils.gemspec", "lib/fileutils.rb"] s.required_ruby_version = ">= 2.5.0" s.authors = ["Minero Aoki"] diff --git a/lib/fileutils.rb b/lib/fileutils.rb index 6e7c3174cb48bb..b9d683797ab03b 100644 --- a/lib/fileutils.rb +++ b/lib/fileutils.rb @@ -180,7 +180,8 @@ # - {CVE-2004-0452}[https://cve.mitre.org/cgi-bin/cvename.cgi?name=CAN-2004-0452]. # module FileUtils - VERSION = "1.7.1" + # The version number. + VERSION = "1.7.3" def self.private_module_function(name) #:nodoc: module_function name @@ -1651,7 +1652,7 @@ def user_mask(target) #:nodoc: when "a" mask | 07777 else - raise ArgumentError, "invalid `who' symbol in file mode: #{chr}" + raise ArgumentError, "invalid 'who' symbol in file mode: #{chr}" end end end @@ -1705,7 +1706,7 @@ def symbolic_modes_to_i(mode_sym, path) #:nodoc: copy_mask = user_mask(chr) (current_mode & copy_mask) / (copy_mask & 0111) * (user_mask & 0111) else - raise ArgumentError, "invalid `perm' symbol in file mode: #{chr}" + raise ArgumentError, "invalid 'perm' symbol in file mode: #{chr}" end end @@ -2028,21 +2029,22 @@ def touch(list, noop: nil, verbose: nil, mtime: nil, nocreate: nil) private - module StreamUtils_ + module StreamUtils_ # :nodoc: + private case (defined?(::RbConfig) ? ::RbConfig::CONFIG['host_os'] : ::RUBY_PLATFORM) when /mswin|mingw/ - def fu_windows?; true end + def fu_windows?; true end #:nodoc: else - def fu_windows?; false end + def fu_windows?; false end #:nodoc: end def fu_copy_stream0(src, dest, blksize = nil) #:nodoc: IO.copy_stream(src, dest) end - def fu_stream_blksize(*streams) + def fu_stream_blksize(*streams) #:nodoc: streams.each do |s| next unless s.respond_to?(:stat) size = fu_blksize(s.stat) @@ -2051,14 +2053,14 @@ def fu_stream_blksize(*streams) fu_default_blksize() end - def fu_blksize(st) + def fu_blksize(st) #:nodoc: s = st.blksize return nil unless s return nil if s == 0 s end - def fu_default_blksize + def fu_default_blksize #:nodoc: 1024 end end @@ -2503,7 +2505,7 @@ def fu_output_message(msg) #:nodoc: end private_module_function :fu_output_message - def fu_split_path(path) + def fu_split_path(path) #:nodoc: path = File.path(path) list = [] until (parent, base = File.split(path); parent == path or parent == ".") @@ -2524,7 +2526,7 @@ def fu_relative_components_from(target, base) #:nodoc: end private_module_function :fu_relative_components_from - def fu_clean_components(*comp) + def fu_clean_components(*comp) #:nodoc: comp.shift while comp.first == "." return comp if comp.empty? clean = [comp.shift] @@ -2543,11 +2545,11 @@ def fu_clean_components(*comp) private_module_function :fu_clean_components if fu_windows? - def fu_starting_path?(path) + def fu_starting_path?(path) #:nodoc: path&.start_with?(%r(\w:|/)) end else - def fu_starting_path?(path) + def fu_starting_path?(path) #:nodoc: path&.start_with?("/") end end diff --git a/lib/find.gemspec b/lib/find.gemspec index cb845e940985e2..aef24a502844ca 100644 --- a/lib/find.gemspec +++ b/lib/find.gemspec @@ -25,7 +25,5 @@ Gem::Specification.new do |spec| spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) } end - spec.bindir = "exe" - spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } spec.require_paths = ["lib"] end diff --git a/lib/find.rb b/lib/find.rb index 79e2e2854d67ea..98a79cc76dad7c 100644 --- a/lib/find.rb +++ b/lib/find.rb @@ -27,7 +27,7 @@ # module Find - VERSION = "0.1.1" + VERSION = "0.2.0" # # Calls the associated block with the name of every file and directory listed diff --git a/lib/getoptlong.gemspec b/lib/getoptlong.gemspec deleted file mode 100644 index c2f65dcaab7317..00000000000000 --- a/lib/getoptlong.gemspec +++ /dev/null @@ -1,30 +0,0 @@ -# frozen_string_literal: true - -name = File.basename(__FILE__, ".gemspec") -version = ["lib", Array.new(name.count("-")+1, ".").join("/")].find do |dir| - break File.foreach(File.join(__dir__, dir, "#{name.tr('-', '/')}.rb")) do |line| - /^\s*VERSION\s*=\s*"(.*)"/ =~ line and break $1 - end rescue nil -end - -Gem::Specification.new do |spec| - spec.name = name - spec.version = version - spec.authors = ["Yukihiro Matsumoto"] - spec.email = ["matz@ruby-lang.org"] - - spec.summary = %q{GetoptLong for Ruby} - spec.description = spec.summary - spec.homepage = "https://github.com/ruby/getoptlong" - spec.licenses = ["Ruby", "BSD-2-Clause"] - - spec.metadata["homepage_uri"] = spec.homepage - spec.metadata["source_code_uri"] = spec.homepage - - # Specify which files should be added to the gem when it is released. - # The `git ls-files -z` loads the files in the RubyGem that have been added into git. - spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do - `git ls-files -z 2>#{IO::NULL}`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) } - end - spec.require_paths = ["lib"] -end diff --git a/lib/getoptlong.rb b/lib/getoptlong.rb deleted file mode 100644 index ec77272d2684bc..00000000000000 --- a/lib/getoptlong.rb +++ /dev/null @@ -1,867 +0,0 @@ -# frozen_string_literal: true -# -# GetoptLong for Ruby -# -# Copyright (C) 1998, 1999, 2000 Motoyuki Kasahara. -# -# You may redistribute and/or modify this library under the same license -# terms as Ruby. - -# \Class \GetoptLong provides parsing both for options -# and for regular arguments. -# -# Using \GetoptLong, you can define options for your program. -# The program can then capture and respond to whatever options -# are included in the command that executes the program. -# -# A simple example: file simple.rb: -# -# :include: ../sample/getoptlong/simple.rb -# -# If you are somewhat familiar with options, -# you may want to skip to this -# {full example}[#class-GetoptLong-label-Full+Example]. -# -# == Options -# -# A \GetoptLong option has: -# -# - A string option name. -# - Zero or more string aliases for the name. -# - An option type. -# -# Options may be defined by calling singleton method GetoptLong.new, -# which returns a new \GetoptLong object. -# Options may then be processed by calling other methods -# such as GetoptLong#each. -# -# === Option Name and Aliases -# -# In the array that defines an option, -# the first element is the string option name. -# Often the name takes the 'long' form, beginning with two hyphens. -# -# The option name may have any number of aliases, -# which are defined by additional string elements. -# -# The name and each alias must be of one of two forms: -# -# - Two hyphens, followed by one or more letters. -# - One hyphen, followed by a single letter. -# -# File aliases.rb: -# -# :include: ../sample/getoptlong/aliases.rb -# -# An option may be cited by its name, -# or by any of its aliases; -# the parsed option always reports the name, not an alias: -# -# $ ruby aliases.rb -a -p --xxx --aaa -x -# -# Output: -# -# ["--xxx", ""] -# ["--xxx", ""] -# ["--xxx", ""] -# ["--xxx", ""] -# ["--xxx", ""] -# -# -# An option may also be cited by an abbreviation of its name or any alias, -# as long as that abbreviation is unique among the options. -# -# File abbrev.rb: -# -# :include: ../sample/getoptlong/abbrev.rb -# -# Command line: -# -# $ ruby abbrev.rb --xxx --xx --xyz --xy -# -# Output: -# -# ["--xxx", ""] -# ["--xxx", ""] -# ["--xyz", ""] -# ["--xyz", ""] -# -# This command line raises GetoptLong::AmbiguousOption: -# -# $ ruby abbrev.rb --x -# -# === Repetition -# -# An option may be cited more than once: -# -# $ ruby abbrev.rb --xxx --xyz --xxx --xyz -# -# Output: -# -# ["--xxx", ""] -# ["--xyz", ""] -# ["--xxx", ""] -# ["--xyz", ""] -# -# === Treating Remaining Options as Arguments -# -# A option-like token that appears -# anywhere after the token -- is treated as an ordinary argument, -# and is not processed as an option: -# -# $ ruby abbrev.rb --xxx --xyz -- --xxx --xyz -# -# Output: -# -# ["--xxx", ""] -# ["--xyz", ""] -# -# === Option Types -# -# Each option definition includes an option type, -# which controls whether the option takes an argument. -# -# File types.rb: -# -# :include: ../sample/getoptlong/types.rb -# -# Note that an option type has to do with the option argument -# (whether it is required, optional, or forbidden), -# not with whether the option itself is required. -# -# ==== Option with Required Argument -# -# An option of type GetoptLong::REQUIRED_ARGUMENT -# must be followed by an argument, which is associated with that option: -# -# $ ruby types.rb --xxx foo -# -# Output: -# -# ["--xxx", "foo"] -# -# If the option is not last, its argument is whatever follows it -# (even if the argument looks like another option): -# -# $ ruby types.rb --xxx --yyy -# -# Output: -# -# ["--xxx", "--yyy"] -# -# If the option is last, an exception is raised: -# -# $ ruby types.rb -# # Raises GetoptLong::MissingArgument -# -# ==== Option with Optional Argument -# -# An option of type GetoptLong::OPTIONAL_ARGUMENT -# may be followed by an argument, which if given is associated with that option. -# -# If the option is last, it does not have an argument: -# -# $ ruby types.rb --yyy -# -# Output: -# -# ["--yyy", ""] -# -# If the option is followed by another option, it does not have an argument: -# -# $ ruby types.rb --yyy --zzz -# -# Output: -# -# ["--yyy", ""] -# ["--zzz", ""] -# -# Otherwise the option is followed by its argument, which is associated -# with that option: -# -# $ ruby types.rb --yyy foo -# -# Output: -# -# ["--yyy", "foo"] -# -# ==== Option with No Argument -# -# An option of type GetoptLong::NO_ARGUMENT takes no argument: -# -# ruby types.rb --zzz foo -# -# Output: -# -# ["--zzz", ""] -# -# === ARGV -# -# You can process options either with method #each and a block, -# or with method #get. -# -# During processing, each found option is removed, along with its argument -# if there is one. -# After processing, each remaining element was neither an option -# nor the argument for an option. -# -# File argv.rb: -# -# :include: ../sample/getoptlong/argv.rb -# -# Command line: -# -# $ ruby argv.rb --xxx Foo --yyy Bar Baz --zzz Bat Bam -# -# Output: -# -# Original ARGV: ["--xxx", "Foo", "--yyy", "Bar", "Baz", "--zzz", "Bat", "Bam"] -# ["--xxx", "Foo"] -# ["--yyy", "Bar"] -# ["--zzz", ""] -# Remaining ARGV: ["Baz", "Bat", "Bam"] -# -# === Ordering -# -# There are three settings that control the way the options -# are interpreted: -# -# - +PERMUTE+. -# - +REQUIRE_ORDER+. -# - +RETURN_IN_ORDER+. -# -# The initial setting for a new \GetoptLong object is +REQUIRE_ORDER+ -# if environment variable +POSIXLY_CORRECT+ is defined, +PERMUTE+ otherwise. -# -# ==== PERMUTE Ordering -# -# In the +PERMUTE+ ordering, options and other, non-option, -# arguments may appear in any order and any mixture. -# -# File permute.rb: -# -# :include: ../sample/getoptlong/permute.rb -# -# Command line: -# -# $ ruby permute.rb Foo --zzz Bar --xxx Baz --yyy Bat Bam --xxx Bag Bah -# -# Output: -# -# Original ARGV: ["Foo", "--zzz", "Bar", "--xxx", "Baz", "--yyy", "Bat", "Bam", "--xxx", "Bag", "Bah"] -# ["--zzz", ""] -# ["--xxx", "Baz"] -# ["--yyy", "Bat"] -# ["--xxx", "Bag"] -# Remaining ARGV: ["Foo", "Bar", "Bam", "Bah"] -# -# ==== REQUIRE_ORDER Ordering -# -# In the +REQUIRE_ORDER+ ordering, all options precede all non-options; -# that is, each word after the first non-option word -# is treated as a non-option word (even if it begins with a hyphen). -# -# File require_order.rb: -# -# :include: ../sample/getoptlong/require_order.rb -# -# Command line: -# -# $ ruby require_order.rb --xxx Foo Bar --xxx Baz --yyy Bat -zzz -# -# Output: -# -# Original ARGV: ["--xxx", "Foo", "Bar", "--xxx", "Baz", "--yyy", "Bat", "-zzz"] -# ["--xxx", "Foo"] -# Remaining ARGV: ["Bar", "--xxx", "Baz", "--yyy", "Bat", "-zzz"] -# -# ==== RETURN_IN_ORDER Ordering -# -# In the +RETURN_IN_ORDER+ ordering, every word is treated as an option. -# A word that begins with a hyphen (or two) is treated in the usual way; -# a word +word+ that does not so begin is treated as an option -# whose name is an empty string, and whose value is +word+. -# -# File return_in_order.rb: -# -# :include: ../sample/getoptlong/return_in_order.rb -# -# Command line: -# -# $ ruby return_in_order.rb Foo --xxx Bar Baz --zzz Bat Bam -# -# Output: -# -# Original ARGV: ["Foo", "--xxx", "Bar", "Baz", "--zzz", "Bat", "Bam"] -# ["", "Foo"] -# ["--xxx", "Bar"] -# ["", "Baz"] -# ["--zzz", ""] -# ["", "Bat"] -# ["", "Bam"] -# Remaining ARGV: [] -# -# === Full Example -# -# File fibonacci.rb: -# -# :include: ../sample/getoptlong/fibonacci.rb -# -# Command line: -# -# $ ruby fibonacci.rb -# -# Output: -# -# Option --number is required. -# Usage: -# -# -n n, --number n: -# Compute Fibonacci number for n. -# -v [boolean], --verbose [boolean]: -# Show intermediate results; default is 'false'. -# -h, --help: -# Show this help. -# -# Command line: -# -# $ ruby fibonacci.rb --number -# -# Raises GetoptLong::MissingArgument: -# -# fibonacci.rb: option `--number' requires an argument -# -# Command line: -# -# $ ruby fibonacci.rb --number 6 -# -# Output: -# -# 8 -# -# Command line: -# -# $ ruby fibonacci.rb --number 6 --verbose -# -# Output: -# 1 -# 2 -# 3 -# 5 -# 8 -# -# Command line: -# -# $ ruby fibonacci.rb --number 6 --verbose yes -# -# Output: -# -# --verbose argument must be true or false -# Usage: -# -# -n n, --number n: -# Compute Fibonacci number for n. -# -v [boolean], --verbose [boolean]: -# Show intermediate results; default is 'false'. -# -h, --help: -# Show this help. -# -class GetoptLong - # Version. - VERSION = "0.2.0" - - # - # Orderings. - # - ORDERINGS = [REQUIRE_ORDER = 0, PERMUTE = 1, RETURN_IN_ORDER = 2] - - # - # Argument flags. - # - ARGUMENT_FLAGS = [NO_ARGUMENT = 0, REQUIRED_ARGUMENT = 1, - OPTIONAL_ARGUMENT = 2] - - # - # Status codes. - # - STATUS_YET, STATUS_STARTED, STATUS_TERMINATED = 0, 1, 2 - - # - # Error types. - # - class Error < StandardError; end - class AmbiguousOption < Error; end - class NeedlessArgument < Error; end - class MissingArgument < Error; end - class InvalidOption < Error; end - - # - # Returns a new \GetoptLong object based on the given +arguments+. - # See {Options}[#class-GetoptLong-label-Options]. - # - # Example: - # - # :include: ../sample/getoptlong/simple.rb - # - # Raises an exception if: - # - # - Any of +arguments+ is not an array. - # - Any option name or alias is not a string. - # - Any option type is invalid. - # - def initialize(*arguments) - # - # Current ordering. - # - if ENV.include?('POSIXLY_CORRECT') - @ordering = REQUIRE_ORDER - else - @ordering = PERMUTE - end - - # - # Hash table of option names. - # Keys of the table are option names, and their values are canonical - # names of the options. - # - @canonical_names = Hash.new - - # - # Hash table of argument flags. - # Keys of the table are option names, and their values are argument - # flags of the options. - # - @argument_flags = Hash.new - - # - # Whether error messages are output to $stderr. - # - @quiet = false - - # - # Status code. - # - @status = STATUS_YET - - # - # Error code. - # - @error = nil - - # - # Error message. - # - @error_message = nil - - # - # Rest of catenated short options. - # - @rest_singles = '' - - # - # List of non-option-arguments. - # Append them to ARGV when option processing is terminated. - # - @non_option_arguments = Array.new - - if 0 < arguments.length - set_options(*arguments) - end - end - - # Sets the ordering; see {Ordering}[#class-GetoptLong-label-Ordering]; - # returns the new ordering. - # - # If the given +ordering+ is +PERMUTE+ and environment variable - # +POSIXLY_CORRECT+ is defined, sets the ordering to +REQUIRE_ORDER+; - # otherwise sets the ordering to +ordering+: - # - # options = GetoptLong.new - # options.ordering == GetoptLong::PERMUTE # => true - # options.ordering = GetoptLong::RETURN_IN_ORDER - # options.ordering == GetoptLong::RETURN_IN_ORDER # => true - # ENV['POSIXLY_CORRECT'] = 'true' - # options.ordering = GetoptLong::PERMUTE - # options.ordering == GetoptLong::REQUIRE_ORDER # => true - # - # Raises an exception if +ordering+ is invalid. - # - def ordering=(ordering) - # - # The method is failed if option processing has already started. - # - if @status != STATUS_YET - set_error(ArgumentError, "argument error") - raise RuntimeError, - "invoke ordering=, but option processing has already started" - end - - # - # Check ordering. - # - if !ORDERINGS.include?(ordering) - raise ArgumentError, "invalid ordering `#{ordering}'" - end - if ordering == PERMUTE && ENV.include?('POSIXLY_CORRECT') - @ordering = REQUIRE_ORDER - else - @ordering = ordering - end - end - - # - # Returns the ordering setting. - # - attr_reader :ordering - - # - # Replaces existing options with those given by +arguments+, - # which have the same form as the arguments to ::new; - # returns +self+. - # - # Raises an exception if option processing has begun. - # - def set_options(*arguments) - # - # The method is failed if option processing has already started. - # - if @status != STATUS_YET - raise RuntimeError, - "invoke set_options, but option processing has already started" - end - - # - # Clear tables of option names and argument flags. - # - @canonical_names.clear - @argument_flags.clear - - arguments.each do |arg| - if !arg.is_a?(Array) - raise ArgumentError, "the option list contains non-Array argument" - end - - # - # Find an argument flag and it set to `argument_flag'. - # - argument_flag = nil - arg.each do |i| - if ARGUMENT_FLAGS.include?(i) - if argument_flag != nil - raise ArgumentError, "too many argument-flags" - end - argument_flag = i - end - end - - raise ArgumentError, "no argument-flag" if argument_flag == nil - - canonical_name = nil - arg.each do |i| - # - # Check an option name. - # - next if i == argument_flag - begin - if !i.is_a?(String) || i !~ /\A-([^-]|-.+)\z/ - raise ArgumentError, "an invalid option `#{i}'" - end - if (@canonical_names.include?(i)) - raise ArgumentError, "option redefined `#{i}'" - end - rescue - @canonical_names.clear - @argument_flags.clear - raise - end - - # - # Register the option (`i') to the `@canonical_names' and - # `@canonical_names' Hashes. - # - if canonical_name == nil - canonical_name = i - end - @canonical_names[i] = canonical_name - @argument_flags[i] = argument_flag - end - raise ArgumentError, "no option name" if canonical_name == nil - end - return self - end - - # - # Sets quiet mode and returns the given argument: - # - # - When +false+ or +nil+, error messages are written to $stdout. - # - Otherwise, error messages are not written. - # - attr_writer :quiet - - # - # Returns the quiet mode setting. - # - attr_reader :quiet - alias quiet? quiet - - # - # Terminate option processing; - # returns +nil+ if processing has already terminated; - # otherwise returns +self+. - # - def terminate - return nil if @status == STATUS_TERMINATED - raise RuntimeError, "an error has occurred" if @error != nil - - @status = STATUS_TERMINATED - @non_option_arguments.reverse_each do |argument| - ARGV.unshift(argument) - end - - @canonical_names = nil - @argument_flags = nil - @rest_singles = nil - @non_option_arguments = nil - - return self - end - - # - # Returns +true+ if option processing has terminated, +false+ otherwise. - # - def terminated? - return @status == STATUS_TERMINATED - end - - # - # \Set an error (a protected method). - # - def set_error(type, message) - $stderr.print("#{$0}: #{message}\n") if !@quiet - - @error = type - @error_message = message - @canonical_names = nil - @argument_flags = nil - @rest_singles = nil - @non_option_arguments = nil - - raise type, message - end - protected :set_error - - # - # Returns whether option processing has failed. - # - attr_reader :error - alias error? error - - # Return the appropriate error message in POSIX-defined format. - # If no error has occurred, returns +nil+. - # - def error_message - return @error_message - end - - # - # Returns the next option as a 2-element array containing: - # - # - The option name (the name itself, not an alias). - # - The option value. - # - # Returns +nil+ if there are no more options. - # - def get - option_name, option_argument = nil, '' - - # - # Check status. - # - return nil if @error != nil - case @status - when STATUS_YET - @status = STATUS_STARTED - when STATUS_TERMINATED - return nil - end - - # - # Get next option argument. - # - if 0 < @rest_singles.length - argument = '-' + @rest_singles - elsif (ARGV.length == 0) - terminate - return nil - elsif @ordering == PERMUTE - while 0 < ARGV.length && ARGV[0] !~ /\A-./ - @non_option_arguments.push(ARGV.shift) - end - if ARGV.length == 0 - terminate - return nil - end - argument = ARGV.shift - elsif @ordering == REQUIRE_ORDER - if (ARGV[0] !~ /\A-./) - terminate - return nil - end - argument = ARGV.shift - else - argument = ARGV.shift - end - - # - # Check the special argument `--'. - # `--' indicates the end of the option list. - # - if argument == '--' && @rest_singles.length == 0 - terminate - return nil - end - - # - # Check for long and short options. - # - if argument =~ /\A(--[^=]+)/ && @rest_singles.length == 0 - # - # This is a long style option, which start with `--'. - # - pattern = $1 - if @canonical_names.include?(pattern) - option_name = pattern - else - # - # The option `option_name' is not registered in `@canonical_names'. - # It may be an abbreviated. - # - matches = [] - @canonical_names.each_key do |key| - if key.index(pattern) == 0 - option_name = key - matches << key - end - end - if 2 <= matches.length - set_error(AmbiguousOption, "option `#{argument}' is ambiguous between #{matches.join(', ')}") - elsif matches.length == 0 - set_error(InvalidOption, "unrecognized option `#{argument}'") - end - end - - # - # Check an argument to the option. - # - if @argument_flags[option_name] == REQUIRED_ARGUMENT - if argument =~ /=(.*)/m - option_argument = $1 - elsif 0 < ARGV.length - option_argument = ARGV.shift - else - set_error(MissingArgument, - "option `#{argument}' requires an argument") - end - elsif @argument_flags[option_name] == OPTIONAL_ARGUMENT - if argument =~ /=(.*)/m - option_argument = $1 - elsif 0 < ARGV.length && ARGV[0] !~ /\A-./ - option_argument = ARGV.shift - else - option_argument = '' - end - elsif argument =~ /=(.*)/m - set_error(NeedlessArgument, - "option `#{option_name}' doesn't allow an argument") - end - - elsif argument =~ /\A(-(.))(.*)/m - # - # This is a short style option, which start with `-' (not `--'). - # Short options may be catenated (e.g. `-l -g' is equivalent to - # `-lg'). - # - option_name, ch, @rest_singles = $1, $2, $3 - - if @canonical_names.include?(option_name) - # - # The option `option_name' is found in `@canonical_names'. - # Check its argument. - # - if @argument_flags[option_name] == REQUIRED_ARGUMENT - if 0 < @rest_singles.length - option_argument = @rest_singles - @rest_singles = '' - elsif 0 < ARGV.length - option_argument = ARGV.shift - else - # 1003.2 specifies the format of this message. - set_error(MissingArgument, "option requires an argument -- #{ch}") - end - elsif @argument_flags[option_name] == OPTIONAL_ARGUMENT - if 0 < @rest_singles.length - option_argument = @rest_singles - @rest_singles = '' - elsif 0 < ARGV.length && ARGV[0] !~ /\A-./ - option_argument = ARGV.shift - else - option_argument = '' - end - end - else - # - # This is an invalid option. - # 1003.2 specifies the format of this message. - # - if ENV.include?('POSIXLY_CORRECT') - set_error(InvalidOption, "invalid option -- #{ch}") - else - set_error(InvalidOption, "invalid option -- #{ch}") - end - end - else - # - # This is a non-option argument. - # Only RETURN_IN_ORDER fell into here. - # - return '', argument - end - - return @canonical_names[option_name], option_argument - end - alias get_option get - - # - # Calls the given block with each option; - # each option is a 2-element array containing: - # - # - The option name (the name itself, not an alias). - # - The option value. - # - # Example: - # - # :include: ../sample/getoptlong/each.rb - # - # Command line: - # - # ruby each.rb -xxx Foo -x Bar --yyy Baz -y Bat --zzz - # - # Output: - # - # Original ARGV: ["-xxx", "Foo", "-x", "Bar", "--yyy", "Baz", "-y", "Bat", "--zzz"] - # ["--xxx", "xx"] - # ["--xxx", "Bar"] - # ["--yyy", "Baz"] - # ["--yyy", "Bat"] - # ["--zzz", ""] - # Remaining ARGV: ["Foo"] - # - def each - loop do - option_name, option_argument = get_option - break if option_name == nil - yield option_name, option_argument - end - end - alias each_option each -end diff --git a/lib/ipaddr.gemspec b/lib/ipaddr.gemspec index 1f4798e43a9ba5..5719f83fc44c46 100644 --- a/lib/ipaddr.gemspec +++ b/lib/ipaddr.gemspec @@ -32,5 +32,5 @@ Both IPv4 and IPv6 are supported. spec.files = ["LICENSE.txt", "README.md", "ipaddr.gemspec", "lib/ipaddr.rb"] spec.require_paths = ["lib"] - spec.required_ruby_version = ">= 2.3" + spec.required_ruby_version = ">= 2.4" end diff --git a/lib/ipaddr.rb b/lib/ipaddr.rb index b7877970e4a7dc..525466bbd946ac 100644 --- a/lib/ipaddr.rb +++ b/lib/ipaddr.rb @@ -40,7 +40,7 @@ # p ipaddr3 #=> # class IPAddr - VERSION = "1.2.5" + VERSION = "1.2.7" # 32 bit mask for IPv4 IN4MASK = 0xffffffff @@ -52,7 +52,7 @@ class IPAddr # Regexp _internally_ used for parsing IPv4 address. RE_IPV4ADDRLIKE = %r{ \A - (\d+) \. (\d+) \. (\d+) \. (\d+) + \d+ \. \d+ \. \d+ \. \d+ \z }x @@ -110,8 +110,13 @@ def self.new_ntoh(addr) # Convert a network byte ordered string form of an IP address into # human readable form. + # It expects the string to be encoded in Encoding::ASCII_8BIT (BINARY). def self.ntop(addr) - case addr.size + if addr.is_a?(String) && addr.encoding != Encoding::BINARY + raise InvalidAddressError, "invalid encoding (given #{addr.encoding}, expected BINARY)" + end + + case addr.bytesize when 4 addr.unpack('C4').join('.') when 16 @@ -146,6 +151,16 @@ def ~ return self.clone.set(addr_mask(~@addr)) end + # Returns a new ipaddr greater than the original address by offset + def +(offset) + self.clone.set(@addr + offset, @family) + end + + # Returns a new ipaddr less than the original address by offset + def -(offset) + self.clone.set(@addr - offset, @family) + end + # Returns true if two ipaddrs are equal. def ==(other) other = coerce_other(other) @@ -176,9 +191,7 @@ def mask(prefixlen) def include?(other) other = coerce_other(other) return false unless other.family == family - range = to_range - other = other.to_range - range.begin <= other.begin && range.end >= other.end + begin_addr <= other.begin_addr && end_addr >= other.end_addr end alias === include? @@ -224,6 +237,28 @@ def to_string return str end + # Returns a string containing the IP address representation with prefix. + def as_json(*) + if ipv4? && prefix == 32 + to_s + elsif ipv6? && prefix == 128 + to_s + else + cidr + end + end + + # Returns a json string containing the IP address representation. + def to_json(*a) + %Q{"#{as_json(*a)}"} + end + + # Returns a string containing the IP address representation in + # cidr notation + def cidr + "#{to_s}/#{prefix}" + end + # Returns a network byte ordered string form of the IP address. def hton case @family @@ -249,12 +284,17 @@ def ipv6? end # Returns true if the ipaddr is a loopback address. + # Loopback IPv4 addresses in the IPv4-mapped IPv6 + # address range are also considered as loopback addresses. def loopback? case @family when Socket::AF_INET - @addr & 0xff000000 == 0x7f000000 + @addr & 0xff000000 == 0x7f000000 # 127.0.0.1/8 when Socket::AF_INET6 - @addr == 1 + @addr == 1 || # ::1 + (@addr & 0xffff_0000_0000 == 0xffff_0000_0000 && ( + @addr & 0xff000000 == 0x7f000000 # ::ffff:127.0.0.1/8 + )) else raise AddressFamilyError, "unsupported address family" end @@ -284,15 +324,19 @@ def private? end # Returns true if the ipaddr is a link-local address. IPv4 - # addresses in 169.254.0.0/16 reserved by RFC 3927 and Link-Local + # addresses in 169.254.0.0/16 reserved by RFC 3927 and link-local # IPv6 Unicast Addresses in fe80::/10 reserved by RFC 4291 are - # considered link-local. + # considered link-local. Link-local IPv4 addresses in the + # IPv4-mapped IPv6 address range are also considered link-local. def link_local? case @family when Socket::AF_INET @addr & 0xffff0000 == 0xa9fe0000 # 169.254.0.0/16 when Socket::AF_INET6 - @addr & 0xffc0_0000_0000_0000_0000_0000_0000_0000 == 0xfe80_0000_0000_0000_0000_0000_0000_0000 + @addr & 0xffc0_0000_0000_0000_0000_0000_0000_0000 == 0xfe80_0000_0000_0000_0000_0000_0000_0000 || # fe80::/10 + (@addr & 0xffff_0000_0000 == 0xffff_0000_0000 && ( + @addr & 0xffff0000 == 0xa9fe0000 # ::ffff:169.254.0.0/16 + )) else raise AddressFamilyError, "unsupported address family" end @@ -406,17 +450,6 @@ def hash # Creates a Range object for the network address. def to_range - begin_addr = (@addr & @mask_addr) - - case @family - when Socket::AF_INET - end_addr = (@addr | (IN4MASK ^ @mask_addr)) - when Socket::AF_INET6 - end_addr = (@addr | (IN6MASK ^ @mask_addr)) - else - raise AddressFamilyError, "unsupported address family" - end - self.class.new(begin_addr, @family)..self.class.new(end_addr, @family) end @@ -445,7 +478,7 @@ def prefix=(prefix) when Integer mask!(prefix) else - raise InvalidPrefixError, "prefix must be an integer: #{@addr}" + raise InvalidPrefixError, "prefix must be an integer" end end @@ -470,6 +503,20 @@ def netmask _to_string(@mask_addr) end + # Returns the wildcard mask in string format e.g. 0.0.255.255 + def wildcard_mask + case @family + when Socket::AF_INET + mask = IN4MASK ^ @mask_addr + when Socket::AF_INET6 + mask = IN6MASK ^ @mask_addr + else + raise AddressFamilyError, "unsupported address family" + end + + _to_string(mask) + end + # Returns the IPv6 zone identifier, if present. # Raises InvalidAddressError if not an IPv6 address. def zone_id @@ -497,6 +544,21 @@ def zone_id=(zid) protected + def begin_addr + @addr & @mask_addr + end + + def end_addr + case @family + when Socket::AF_INET + @addr | (IN4MASK ^ @mask_addr) + when Socket::AF_INET6 + @addr | (IN6MASK ^ @mask_addr) + else + raise AddressFamilyError, "unsupported address family" + end + end + # Set +@addr+, the internal stored ip address, to given +addr+. The # parameter +addr+ is validated using the first +family+ member, # which is +Socket::AF_INET+ or +Socket::AF_INET6+. @@ -504,11 +566,11 @@ def set(addr, *family) case family[0] ? family[0] : @family when Socket::AF_INET if addr < 0 || addr > IN4MASK - raise InvalidAddressError, "invalid address: #{@addr}" + raise InvalidAddressError, "invalid address: #{addr}" end when Socket::AF_INET6 if addr < 0 || addr > IN6MASK - raise InvalidAddressError, "invalid address: #{@addr}" + raise InvalidAddressError, "invalid address: #{addr}" end else raise AddressFamilyError, "unsupported address family" @@ -535,12 +597,12 @@ def mask!(mask) else m = IPAddr.new(mask) if m.family != @family - raise InvalidPrefixError, "address family is not same: #{@addr}" + raise InvalidPrefixError, "address family is not same" end @mask_addr = m.to_i n = @mask_addr ^ m.instance_variable_get(:@mask_addr) unless ((n + 1) & n).zero? - raise InvalidPrefixError, "invalid mask #{mask}: #{@addr}" + raise InvalidPrefixError, "invalid mask #{mask}" end @addr &= @mask_addr return self @@ -551,13 +613,13 @@ def mask!(mask) case @family when Socket::AF_INET if prefixlen < 0 || prefixlen > 32 - raise InvalidPrefixError, "invalid length: #{@addr}" + raise InvalidPrefixError, "invalid length" end masklen = 32 - prefixlen @mask_addr = ((IN4MASK >> masklen) << masklen) when Socket::AF_INET6 if prefixlen < 0 || prefixlen > 128 - raise InvalidPrefixError, "invalid length: #{@addr}" + raise InvalidPrefixError, "invalid length" end masklen = 128 - prefixlen @mask_addr = ((IN6MASK >> masklen) << masklen) @@ -653,12 +715,12 @@ def in_addr(addr) when Array octets = addr else - m = RE_IPV4ADDRLIKE.match(addr) or return nil - octets = m.captures + RE_IPV4ADDRLIKE.match?(addr) or return nil + octets = addr.split('.') end octets.inject(0) { |i, s| (n = s.to_i) < 256 or raise InvalidAddressError, "invalid address: #{@addr}" - s.match(/\A0./) and raise InvalidAddressError, "zero-filled number in IPv4 address is ambiguous: #{@addr}" + (s != '0') && s.start_with?('0') and raise InvalidAddressError, "zero-filled number in IPv4 address is ambiguous: #{@addr}" i << 8 | n } end diff --git a/lib/irb.rb b/lib/irb.rb deleted file mode 100644 index 57ec911f344b3e..00000000000000 --- a/lib/irb.rb +++ /dev/null @@ -1,1088 +0,0 @@ -# frozen_string_literal: false -# -# irb.rb - irb main module -# by Keiju ISHITSUKA(keiju@ruby-lang.org) -# - -require "ripper" -require "reline" - -require_relative "irb/init" -require_relative "irb/context" -require_relative "irb/extend-command" - -require_relative "irb/ruby-lex" -require_relative "irb/statement" -require_relative "irb/input-method" -require_relative "irb/locale" -require_relative "irb/color" - -require_relative "irb/version" -require_relative "irb/easter-egg" -require_relative "irb/debug" - -# IRB stands for "interactive Ruby" and is a tool to interactively execute Ruby -# expressions read from the standard input. -# -# The +irb+ command from your shell will start the interpreter. -# -# == Usage -# -# Use of irb is easy if you know Ruby. -# -# When executing irb, prompts are displayed as follows. Then, enter the Ruby -# expression. An input is executed when it is syntactically complete. -# -# $ irb -# irb(main):001:0> 1+2 -# #=> 3 -# irb(main):002:0> class Foo -# irb(main):003:1> def foo -# irb(main):004:2> print 1 -# irb(main):005:2> end -# irb(main):006:1> end -# #=> nil -# -# The singleline editor module or multiline editor module can be used with irb. -# Use of multiline editor is default if it's installed. -# -# == Command line options -# -# :include: ./irb/lc/help-message -# -# == Commands -# -# The following commands are available on IRB. -# -# * cwws -# * Show the current workspace. -# * cb, cws, chws -# * Change the current workspace to an object. -# * bindings, workspaces -# * Show workspaces. -# * pushb, pushws -# * Push an object to the workspace stack. -# * popb, popws -# * Pop a workspace from the workspace stack. -# * load -# * Load a Ruby file. -# * require -# * Require a Ruby file. -# * source -# * Loads a given file in the current session. -# * irb -# * Start a child IRB. -# * jobs -# * List of current sessions. -# * fg -# * Switches to the session of the given number. -# * kill -# * Kills the session with the given number. -# * help -# * Enter the mode to look up RI documents. -# * irb_info -# * Show information about IRB. -# * ls -# * Show methods, constants, and variables. -# -g [query] or -G [query] allows you to filter out the output. -# * measure -# * measure enables the mode to measure processing time. measure :off disables it. -# * $, show_source -# * Show the source code of a given method or constant. -# * @, whereami -# * Show the source code around binding.irb again. -# * debug -# * Start the debugger of debug.gem. -# * break, delete, next, step, continue, finish, backtrace, info, catch -# * Start the debugger of debug.gem and run the command on it. -# -# == Configuration -# -# IRB reads a personal initialization file when it's invoked. -# IRB searches a file in the following order and loads the first one found. -# -# * $IRBRC (if $IRBRC is set) -# * $XDG_CONFIG_HOME/irb/irbrc (if $XDG_CONFIG_HOME is set) -# * ~/.irbrc -# * +.config/irb/irbrc+ -# * +.irbrc+ -# * +irb.rc+ -# * +_irbrc+ -# * $irbrc -# -# The following are alternatives to the command line options. To use them type -# as follows in an +irb+ session: -# -# IRB.conf[:IRB_NAME]="irb" -# IRB.conf[:INSPECT_MODE]=nil -# IRB.conf[:IRB_RC] = nil -# IRB.conf[:BACK_TRACE_LIMIT]=16 -# IRB.conf[:USE_LOADER] = false -# IRB.conf[:USE_MULTILINE] = nil -# IRB.conf[:USE_SINGLELINE] = nil -# IRB.conf[:USE_COLORIZE] = true -# IRB.conf[:USE_TRACER] = false -# IRB.conf[:USE_AUTOCOMPLETE] = true -# IRB.conf[:IGNORE_SIGINT] = true -# IRB.conf[:IGNORE_EOF] = false -# IRB.conf[:PROMPT_MODE] = :DEFAULT -# IRB.conf[:PROMPT] = {...} -# -# === Auto indentation -# -# To disable auto-indent mode in irb, add the following to your +.irbrc+: -# -# IRB.conf[:AUTO_INDENT] = false -# -# === Autocompletion -# -# To disable autocompletion for irb, add the following to your +.irbrc+: -# -# IRB.conf[:USE_AUTOCOMPLETE] = false -# -# === History -# -# By default, irb will store the last 1000 commands you used in -# IRB.conf[:HISTORY_FILE] (~/.irb_history by default). -# -# If you want to disable history, add the following to your +.irbrc+: -# -# IRB.conf[:SAVE_HISTORY] = nil -# -# See IRB::Context#save_history= for more information. -# -# The history of _results_ of commands evaluated is not stored by default, -# but can be turned on to be stored with this +.irbrc+ setting: -# -# IRB.conf[:EVAL_HISTORY] = -# -# See IRB::Context#eval_history= and EvalHistory class. The history of command -# results is not permanently saved in any file. -# -# == Customizing the IRB Prompt -# -# In order to customize the prompt, you can change the following Hash: -# -# IRB.conf[:PROMPT] -# -# This example can be used in your +.irbrc+ -# -# IRB.conf[:PROMPT][:MY_PROMPT] = { # name of prompt mode -# :AUTO_INDENT => false, # disables auto-indent mode -# :PROMPT_I => ">> ", # simple prompt -# :PROMPT_S => nil, # prompt for continuated strings -# :PROMPT_C => nil, # prompt for continuated statement -# :RETURN => " ==>%s\n" # format to return value -# } -# -# IRB.conf[:PROMPT_MODE] = :MY_PROMPT -# -# Or, invoke irb with the above prompt mode by: -# -# irb --prompt my-prompt -# -# Constants +PROMPT_I+, +PROMPT_S+ and +PROMPT_C+ specify the format. In the -# prompt specification, some special strings are available: -# -# %N # command name which is running -# %m # to_s of main object (self) -# %M # inspect of main object (self) -# %l # type of string(", ', /, ]), `]' is inner %w[...] -# %NNi # indent level. NN is digits and means as same as printf("%NNd"). -# # It can be omitted -# %NNn # line number. -# %% # % -# -# For instance, the default prompt mode is defined as follows: -# -# IRB.conf[:PROMPT_MODE][:DEFAULT] = { -# :PROMPT_I => "%N(%m):%03n> ", -# :PROMPT_S => "%N(%m):%03n%l ", -# :PROMPT_C => "%N(%m):%03n* ", -# :RETURN => "%s\n" # used to printf -# } -# -# irb comes with a number of available modes: -# -# # :NULL: -# # :PROMPT_I: -# # :PROMPT_S: -# # :PROMPT_C: -# # :RETURN: | -# # %s -# # :DEFAULT: -# # :PROMPT_I: ! '%N(%m):%03n> ' -# # :PROMPT_S: ! '%N(%m):%03n%l ' -# # :PROMPT_C: ! '%N(%m):%03n* ' -# # :RETURN: | -# # => %s -# # :CLASSIC: -# # :PROMPT_I: ! '%N(%m):%03n:%i> ' -# # :PROMPT_S: ! '%N(%m):%03n:%i%l ' -# # :PROMPT_C: ! '%N(%m):%03n:%i* ' -# # :RETURN: | -# # %s -# # :SIMPLE: -# # :PROMPT_I: ! '>> ' -# # :PROMPT_S: -# # :PROMPT_C: ! '?> ' -# # :RETURN: | -# # => %s -# # :INF_RUBY: -# # :PROMPT_I: ! '%N(%m):%03n> ' -# # :PROMPT_S: -# # :PROMPT_C: -# # :RETURN: | -# # %s -# # :AUTO_INDENT: true -# # :XMP: -# # :PROMPT_I: -# # :PROMPT_S: -# # :PROMPT_C: -# # :RETURN: |2 -# # ==>%s -# -# == Restrictions -# -# Because irb evaluates input immediately after it is syntactically complete, -# the results may be slightly different than directly using Ruby. -# -# == IRB Sessions -# -# IRB has a special feature, that allows you to manage many sessions at once. -# -# You can create new sessions with Irb.irb, and get a list of current sessions -# with the +jobs+ command in the prompt. -# -# === Commands -# -# JobManager provides commands to handle the current sessions: -# -# jobs # List of current sessions -# fg # Switches to the session of the given number -# kill # Kills the session with the given number -# -# The +exit+ command, or ::irb_exit, will quit the current session and call any -# exit hooks with IRB.irb_at_exit. -# -# A few commands for loading files within the session are also available: -# -# +source+:: -# Loads a given file in the current session and displays the source lines, -# see IrbLoader#source_file -# +irb_load+:: -# Loads the given file similarly to Kernel#load, see IrbLoader#irb_load -# +irb_require+:: -# Loads the given file similarly to Kernel#require -# -# === Configuration -# -# The command line options, or IRB.conf, specify the default behavior of -# Irb.irb. -# -# On the other hand, each conf in IRB@Command+line+options is used to -# individually configure IRB.irb. -# -# If a proc is set for IRB.conf[:IRB_RC], its will be invoked after execution -# of that proc with the context of the current session as its argument. Each -# session can be configured using this mechanism. -# -# === Session variables -# -# There are a few variables in every Irb session that can come in handy: -# -# _:: -# The value command executed, as a local variable -# __:: -# The history of evaluated commands. Available only if -# IRB.conf[:EVAL_HISTORY] is not +nil+ (which is the default). -# See also IRB::Context#eval_history= and IRB::History. -# __[line_no]:: -# Returns the evaluation value at the given line number, +line_no+. -# If +line_no+ is a negative, the return value +line_no+ many lines before -# the most recent return value. -# -# === Example using IRB Sessions -# -# # invoke a new session -# irb(main):001:0> irb -# # list open sessions -# irb.1(main):001:0> jobs -# #0->irb on main (# : stop) -# #1->irb#1 on main (# : running) -# -# # change the active session -# irb.1(main):002:0> fg 0 -# # define class Foo in top-level session -# irb(main):002:0> class Foo;end -# # invoke a new session with the context of Foo -# irb(main):003:0> irb Foo -# # define Foo#foo -# irb.2(Foo):001:0> def foo -# irb.2(Foo):002:1> print 1 -# irb.2(Foo):003:1> end -# -# # change the active session -# irb.2(Foo):004:0> fg 0 -# # list open sessions -# irb(main):004:0> jobs -# #0->irb on main (# : running) -# #1->irb#1 on main (# : stop) -# #2->irb#2 on Foo (# : stop) -# # check if Foo#foo is available -# irb(main):005:0> Foo.instance_methods #=> [:foo, ...] -# -# # change the active session -# irb(main):006:0> fg 2 -# # define Foo#bar in the context of Foo -# irb.2(Foo):005:0> def bar -# irb.2(Foo):006:1> print "bar" -# irb.2(Foo):007:1> end -# irb.2(Foo):010:0> Foo.instance_methods #=> [:bar, :foo, ...] -# -# # change the active session -# irb.2(Foo):011:0> fg 0 -# irb(main):007:0> f = Foo.new #=> # -# # invoke a new session with the context of f (instance of Foo) -# irb(main):008:0> irb f -# # list open sessions -# irb.3():001:0> jobs -# #0->irb on main (# : stop) -# #1->irb#1 on main (# : stop) -# #2->irb#2 on Foo (# : stop) -# #3->irb#3 on # (# : running) -# # evaluate f.foo -# irb.3():002:0> foo #=> 1 => nil -# # evaluate f.bar -# irb.3():003:0> bar #=> bar => nil -# # kill jobs 1, 2, and 3 -# irb.3():004:0> kill 1, 2, 3 -# # list open sessions, should only include main session -# irb(main):009:0> jobs -# #0->irb on main (# : running) -# # quit irb -# irb(main):010:0> exit -module IRB - - # An exception raised by IRB.irb_abort - class Abort < Exception;end - - @CONF = {} - # Displays current configuration. - # - # Modifying the configuration is achieved by sending a message to IRB.conf. - # - # See IRB@Configuration for more information. - def IRB.conf - @CONF - end - - # Returns the current version of IRB, including release version and last - # updated date. - def IRB.version - if v = @CONF[:VERSION] then return v end - - @CONF[:VERSION] = format("irb %s (%s)", @RELEASE_VERSION, @LAST_UPDATE_DATE) - end - - # The current IRB::Context of the session, see IRB.conf - # - # irb - # irb(main):001:0> IRB.CurrentContext.irb_name = "foo" - # foo(main):002:0> IRB.conf[:MAIN_CONTEXT].irb_name #=> "foo" - def IRB.CurrentContext - IRB.conf[:MAIN_CONTEXT] - end - - # Initializes IRB and creates a new Irb.irb object at the +TOPLEVEL_BINDING+ - def IRB.start(ap_path = nil) - STDOUT.sync = true - $0 = File::basename(ap_path, ".rb") if ap_path - - IRB.setup(ap_path) - - if @CONF[:SCRIPT] - irb = Irb.new(nil, @CONF[:SCRIPT]) - else - irb = Irb.new - end - irb.run(@CONF) - end - - # Quits irb - def IRB.irb_exit(irb, ret) - throw :IRB_EXIT, ret - end - - # Aborts then interrupts irb. - # - # Will raise an Abort exception, or the given +exception+. - def IRB.irb_abort(irb, exception = Abort) - irb.context.thread.raise exception, "abort then interrupt!" - end - - class Irb - # Note: instance and index assignment expressions could also be written like: - # "foo.bar=(1)" and "foo.[]=(1, bar)", when expressed that way, the former - # be parsed as :assign and echo will be suppressed, but the latter is - # parsed as a :method_add_arg and the output won't be suppressed - - PROMPT_MAIN_TRUNCATE_LENGTH = 32 - PROMPT_MAIN_TRUNCATE_OMISSION = '...'.freeze - CONTROL_CHARACTERS_PATTERN = "\x00-\x1F".freeze - - # Creates a new irb session - def initialize(workspace = nil, input_method = nil) - @context = Context.new(self, workspace, input_method) - @context.workspace.load_commands_to_main - @signal_status = :IN_IRB - @scanner = RubyLex.new(@context) - end - - # A hook point for `debug` command's breakpoint after :IRB_EXIT as well as its clean-up - def debug_break - # it means the debug integration has been activated - if defined?(DEBUGGER__) && DEBUGGER__.respond_to?(:capture_frames_without_irb) - # after leaving this initial breakpoint, revert the capture_frames patch - DEBUGGER__.singleton_class.send(:alias_method, :capture_frames, :capture_frames_without_irb) - # and remove the redundant method - DEBUGGER__.singleton_class.send(:undef_method, :capture_frames_without_irb) - end - end - - def debug_readline(binding) - workspace = IRB::WorkSpace.new(binding) - context.workspace = workspace - context.workspace.load_commands_to_main - scanner.increase_line_no(1) - - # When users run: - # 1. Debugging commands, like `step 2` - # 2. Any input that's not irb-command, like `foo = 123` - # - # Irb#eval_input will simply return the input, and we need to pass it to the debugger. - input = if IRB.conf[:SAVE_HISTORY] && context.io.support_history_saving? - # Previous IRB session's history has been saved when `Irb#run` is exited - # We need to make sure the saved history is not saved again by reseting the counter - context.io.reset_history_counter - - begin - eval_input - ensure - context.io.save_history - end - else - eval_input - end - - if input&.include?("\n") - scanner.increase_line_no(input.count("\n") - 1) - end - - input - end - - def run(conf = IRB.conf) - in_nested_session = !!conf[:MAIN_CONTEXT] - conf[:IRB_RC].call(context) if conf[:IRB_RC] - conf[:MAIN_CONTEXT] = context - - save_history = !in_nested_session && conf[:SAVE_HISTORY] && context.io.support_history_saving? - - if save_history - context.io.load_history - end - - prev_trap = trap("SIGINT") do - signal_handle - end - - begin - catch(:IRB_EXIT) do - eval_input - end - ensure - trap("SIGINT", prev_trap) - conf[:AT_EXIT].each{|hook| hook.call} - context.io.save_history if save_history - end - end - - # Returns the current context of this irb session - attr_reader :context - # The lexer used by this irb session - attr_accessor :scanner - - # Evaluates input for this session. - def eval_input - @scanner.set_prompt do - |ltype, indent, continue, line_no| - if ltype - f = @context.prompt_s - elsif continue - f = @context.prompt_c - else - f = @context.prompt_i - end - f = "" unless f - if @context.prompting? - @context.io.prompt = p = prompt(f, ltype, indent, line_no) - else - @context.io.prompt = p = "" - end - if @context.auto_indent_mode and !@context.io.respond_to?(:auto_indent) - unless ltype - prompt_i = @context.prompt_i.nil? ? "" : @context.prompt_i - ind = prompt(prompt_i, ltype, indent, line_no)[/.*\z/].size + - indent * 2 - p.size - @context.io.prompt = p + " " * ind if ind > 0 - end - end - @context.io.prompt - end - - configure_io - - each_top_level_statement do |statement, line_no| - signal_status(:IN_EVAL) do - begin - # If the integration with debugger is activated, we return certain input if it should be dealt with by debugger - if @context.with_debugger && statement.should_be_handled_by_debugger? - return statement.code - end - - @context.evaluate(statement.evaluable_code, line_no) - - if @context.echo? && !statement.suppresses_echo? - if statement.is_assignment? - if @context.echo_on_assignment? - output_value(@context.echo_on_assignment? == :truncate) - end - else - output_value - end - end - rescue SystemExit, SignalException - raise - rescue Interrupt, Exception => exc - handle_exception(exc) - @context.workspace.local_variable_set(:_, exc) - end - end - end - end - - def read_input - signal_status(:IN_INPUT) do - if l = @context.io.gets - print l if @context.verbose? - else - if @context.ignore_eof? and @context.io.readable_after_eof? - l = "\n" - if @context.verbose? - printf "Use \"exit\" to leave %s\n", @context.ap_name - end - else - print "\n" if @context.prompting? - end - end - l - end - end - - def readmultiline - @scanner.save_prompt_to_context_io([], false, 0) - - # multiline - return read_input if @context.io.respond_to?(:check_termination) - - # nomultiline - code = '' - line_offset = 0 - loop do - line = read_input - unless line - return code.empty? ? nil : code - end - - code << line - - # Accept any single-line input for symbol aliases or commands that transform args - return code if single_line_command?(code) - - tokens, opens, terminated = @scanner.check_code_state(code) - return code if terminated - - line_offset += 1 - continue = @scanner.should_continue?(tokens) - @scanner.save_prompt_to_context_io(opens, continue, line_offset) - end - end - - def each_top_level_statement - loop do - code = readmultiline - break unless code - - if code != "\n" - yield build_statement(code), @scanner.line_no - end - @scanner.increase_line_no(code.count("\n")) - rescue RubyLex::TerminateLineInput - end - end - - def build_statement(code) - code.force_encoding(@context.io.encoding) - command_or_alias, arg = code.split(/\s/, 2) - # Transform a non-identifier alias (@, $) or keywords (next, break) - command_name = @context.command_aliases[command_or_alias.to_sym] - command = command_name || command_or_alias - command_class = ExtendCommandBundle.load_command(command) - - if command_class - Statement::Command.new(code, command, arg, command_class) - else - Statement::Expression.new(code, @scanner.assignment_expression?(code)) - end - end - - def single_line_command?(code) - command = code.split(/\s/, 2).first - @context.symbol_alias?(command) || @context.transform_args?(command) - end - - def configure_io - if @context.io.respond_to?(:check_termination) - @context.io.check_termination do |code| - if Reline::IOGate.in_pasting? - rest = @scanner.check_termination_in_prev_line(code) - if rest - Reline.delete_text - rest.bytes.reverse_each do |c| - Reline.ungetc(c) - end - true - else - false - end - else - # Accept any single-line input for symbol aliases or commands that transform args - next true if single_line_command?(code) - - _tokens, _opens, terminated = @scanner.check_code_state(code) - terminated - end - end - end - if @context.io.respond_to?(:dynamic_prompt) - @context.io.dynamic_prompt do |lines| - lines << '' if lines.empty? - tokens = RubyLex.ripper_lex_without_warning(lines.map{ |l| l + "\n" }.join, context: @context) - line_results = IRB::NestingParser.parse_by_line(tokens) - tokens_until_line = [] - line_results.map.with_index do |(line_tokens, _prev_opens, next_opens, _min_depth), line_num_offset| - line_tokens.each do |token, _s| - # Avoid appending duplicated token. Tokens that include "\n" like multiline tstring_content can exist in multiple lines. - tokens_until_line << token if token != tokens_until_line.last - end - continue = @scanner.should_continue?(tokens_until_line) - @scanner.prompt(next_opens, continue, line_num_offset) - end - end - end - - if @context.io.respond_to?(:auto_indent) and @context.auto_indent_mode - @context.io.auto_indent do |lines, line_index, byte_pointer, is_newline| - next nil if lines == [nil] # Workaround for exit IRB with CTRL+d - next nil if !is_newline && lines[line_index]&.byteslice(0, byte_pointer)&.match?(/\A\s*\z/) - - code = lines[0..line_index].map { |l| "#{l}\n" }.join - tokens = RubyLex.ripper_lex_without_warning(code, context: @context) - @scanner.process_indent_level(tokens, lines, line_index, is_newline) - end - end - end - - def convert_invalid_byte_sequence(str, enc) - str.force_encoding(enc) - str.scrub { |c| - c.bytes.map{ |b| "\\x#{b.to_s(16).upcase}" }.join - } - end - - def encode_with_invalid_byte_sequence(str, enc) - conv = Encoding::Converter.new(str.encoding, enc) - dst = String.new - begin - ret = conv.primitive_convert(str, dst) - case ret - when :invalid_byte_sequence - conv.insert_output(conv.primitive_errinfo[3].dump[1..-2]) - redo - when :undefined_conversion - c = conv.primitive_errinfo[3].dup.force_encoding(conv.primitive_errinfo[1]) - conv.insert_output(c.dump[1..-2]) - redo - when :incomplete_input - conv.insert_output(conv.primitive_errinfo[3].dump[1..-2]) - when :finished - end - break - end while nil - dst - end - - def handle_exception(exc) - if exc.backtrace && exc.backtrace[0] =~ /\/irb(2)?(\/.*|-.*|\.rb)?:/ && exc.class.to_s !~ /^IRB/ && - !(SyntaxError === exc) && !(EncodingError === exc) - # The backtrace of invalid encoding hash (ex. {"\xAE": 1}) raises EncodingError without lineno. - irb_bug = true - else - irb_bug = false - end - - if exc.backtrace - order = nil - if RUBY_VERSION < '3.0.0' - if STDOUT.tty? - message = exc.full_message(order: :bottom) - order = :bottom - else - message = exc.full_message(order: :top) - order = :top - end - else # '3.0.0' <= RUBY_VERSION - message = exc.full_message(order: :top) - order = :top - end - message = convert_invalid_byte_sequence(message, exc.message.encoding) - message = encode_with_invalid_byte_sequence(message, IRB.conf[:LC_MESSAGES].encoding) unless message.encoding.to_s.casecmp?(IRB.conf[:LC_MESSAGES].encoding.to_s) - message = message.gsub(/((?:^\t.+$\n)+)/) { |m| - case order - when :top - lines = m.split("\n") - when :bottom - lines = m.split("\n").reverse - end - unless irb_bug - lines = lines.map { |l| @context.workspace.filter_backtrace(l) }.compact - if lines.size > @context.back_trace_limit - omit = lines.size - @context.back_trace_limit - lines = lines[0..(@context.back_trace_limit - 1)] - lines << "\t... %d levels..." % omit - end - end - lines = lines.reverse if order == :bottom - lines.map{ |l| l + "\n" }.join - } - # The "" in "(irb)" may be the top level of IRB so imitate the main object. - message = message.gsub(/\(irb\):(?\d+):in `<(?top \(required\))>'/) { "(irb):#{$~[:num]}:in `
'" } - puts message - end - print "Maybe IRB bug!\n" if irb_bug - end - - # Evaluates the given block using the given +path+ as the Context#irb_path - # and +name+ as the Context#irb_name. - # - # Used by the irb command +source+, see IRB@IRB+Sessions for more - # information. - def suspend_name(path = nil, name = nil) - @context.irb_path, back_path = path, @context.irb_path if path - @context.irb_name, back_name = name, @context.irb_name if name - begin - yield back_path, back_name - ensure - @context.irb_path = back_path if path - @context.irb_name = back_name if name - end - end - - # Evaluates the given block using the given +workspace+ as the - # Context#workspace. - # - # Used by the irb command +irb_load+, see IRB@IRB+Sessions for more - # information. - def suspend_workspace(workspace) - @context.workspace, back_workspace = workspace, @context.workspace - begin - yield back_workspace - ensure - @context.workspace = back_workspace - end - end - - # Evaluates the given block using the given +input_method+ as the - # Context#io. - # - # Used by the irb commands +source+ and +irb_load+, see IRB@IRB+Sessions - # for more information. - def suspend_input_method(input_method) - back_io = @context.io - @context.instance_eval{@io = input_method} - begin - yield back_io - ensure - @context.instance_eval{@io = back_io} - end - end - - # Evaluates the given block using the given +context+ as the Context. - def suspend_context(context) - @context, back_context = context, @context - begin - yield back_context - ensure - @context = back_context - end - end - - # Handler for the signal SIGINT, see Kernel#trap for more information. - def signal_handle - unless @context.ignore_sigint? - print "\nabort!\n" if @context.verbose? - exit - end - - case @signal_status - when :IN_INPUT - print "^C\n" - raise RubyLex::TerminateLineInput - when :IN_EVAL - IRB.irb_abort(self) - when :IN_LOAD - IRB.irb_abort(self, LoadAbort) - when :IN_IRB - # ignore - else - # ignore other cases as well - end - end - - # Evaluates the given block using the given +status+. - def signal_status(status) - return yield if @signal_status == :IN_LOAD - - signal_status_back = @signal_status - @signal_status = status - begin - yield - ensure - @signal_status = signal_status_back - end - end - - def truncate_prompt_main(str) # :nodoc: - str = str.tr(CONTROL_CHARACTERS_PATTERN, ' ') - if str.size <= PROMPT_MAIN_TRUNCATE_LENGTH - str - else - str[0, PROMPT_MAIN_TRUNCATE_LENGTH - PROMPT_MAIN_TRUNCATE_OMISSION.size] + PROMPT_MAIN_TRUNCATE_OMISSION - end - end - - def prompt(prompt, ltype, indent, line_no) # :nodoc: - p = prompt.dup - p.gsub!(/%([0-9]+)?([a-zA-Z])/) do - case $2 - when "N" - @context.irb_name - when "m" - truncate_prompt_main(@context.main.to_s) - when "M" - truncate_prompt_main(@context.main.inspect) - when "l" - ltype - when "i" - if indent < 0 - if $1 - "-".rjust($1.to_i) - else - "-" - end - else - if $1 - format("%" + $1 + "d", indent) - else - indent.to_s - end - end - when "n" - if $1 - format("%" + $1 + "d", line_no) - else - line_no.to_s - end - when "%" - "%" - end - end - p - end - - def output_value(omit = false) # :nodoc: - str = @context.inspect_last_value - multiline_p = str.include?("\n") - if omit - winwidth = @context.io.winsize.last - if multiline_p - first_line = str.split("\n").first - result = @context.newline_before_multiline_output? ? (@context.return_format % first_line) : first_line - output_width = Reline::Unicode.calculate_width(result, true) - diff_size = output_width - Reline::Unicode.calculate_width(first_line, true) - if diff_size.positive? and output_width > winwidth - lines, _ = Reline::Unicode.split_by_width(first_line, winwidth - diff_size - 3) - str = "%s..." % lines.first - str += "\e[0m" if Color.colorable? - multiline_p = false - else - str = str.gsub(/(\A.*?\n).*/m, "\\1...") - str += "\e[0m" if Color.colorable? - end - else - output_width = Reline::Unicode.calculate_width(@context.return_format % str, true) - diff_size = output_width - Reline::Unicode.calculate_width(str, true) - if diff_size.positive? and output_width > winwidth - lines, _ = Reline::Unicode.split_by_width(str, winwidth - diff_size - 3) - str = "%s..." % lines.first - str += "\e[0m" if Color.colorable? - end - end - end - if multiline_p && @context.newline_before_multiline_output? - printf @context.return_format, "\n#{str}" - else - printf @context.return_format, str - end - end - - # Outputs the local variables to this current session, including - # #signal_status and #context, using IRB::Locale. - def inspect - ary = [] - for iv in instance_variables - case (iv = iv.to_s) - when "@signal_status" - ary.push format("%s=:%s", iv, @signal_status.id2name) - when "@context" - ary.push format("%s=%s", iv, eval(iv).__to_s__) - else - ary.push format("%s=%s", iv, eval(iv)) - end - end - format("#<%s: %s>", self.class, ary.join(", ")) - end - end - - def @CONF.inspect - IRB.version unless self[:VERSION] - - array = [] - for k, v in sort{|a1, a2| a1[0].id2name <=> a2[0].id2name} - case k - when :MAIN_CONTEXT, :__TMP__EHV__ - array.push format("CONF[:%s]=...myself...", k.id2name) - when :PROMPT - s = v.collect{ - |kk, vv| - ss = vv.collect{|kkk, vvv| ":#{kkk.id2name}=>#{vvv.inspect}"} - format(":%s=>{%s}", kk.id2name, ss.join(", ")) - } - array.push format("CONF[:%s]={%s}", k.id2name, s.join(", ")) - else - array.push format("CONF[:%s]=%s", k.id2name, v.inspect) - end - end - array.join("\n") - end -end - -class Binding - # Opens an IRB session where +binding.irb+ is called which allows for - # interactive debugging. You can call any methods or variables available in - # the current scope, and mutate state if you need to. - # - # - # Given a Ruby file called +potato.rb+ containing the following code: - # - # class Potato - # def initialize - # @cooked = false - # binding.irb - # puts "Cooked potato: #{@cooked}" - # end - # end - # - # Potato.new - # - # Running ruby potato.rb will open an IRB session where - # +binding.irb+ is called, and you will see the following: - # - # $ ruby potato.rb - # - # From: potato.rb @ line 4 : - # - # 1: class Potato - # 2: def initialize - # 3: @cooked = false - # => 4: binding.irb - # 5: puts "Cooked potato: #{@cooked}" - # 6: end - # 7: end - # 8: - # 9: Potato.new - # - # irb(#):001:0> - # - # You can type any valid Ruby code and it will be evaluated in the current - # context. This allows you to debug without having to run your code repeatedly: - # - # irb(#):001:0> @cooked - # => false - # irb(#):002:0> self.class - # => Potato - # irb(#):003:0> caller.first - # => ".../2.5.1/lib/ruby/2.5.0/irb/workspace.rb:85:in `eval'" - # irb(#):004:0> @cooked = true - # => true - # - # You can exit the IRB session with the +exit+ command. Note that exiting will - # resume execution where +binding.irb+ had paused it, as you can see from the - # output printed to standard output in this example: - # - # irb(#):005:0> exit - # Cooked potato: true - # - # - # See IRB@Usage for more information. - def irb(show_code: true) - # Setup IRB with the current file's path and no command line arguments - IRB.setup(source_location[0], argv: []) - # Create a new workspace using the current binding - workspace = IRB::WorkSpace.new(self) - # Print the code around the binding if show_code is true - STDOUT.print(workspace.code_around_binding) if show_code - # Get the original IRB instance - debugger_irb = IRB.instance_variable_get(:@debugger_irb) - - irb_path = File.expand_path(source_location[0]) - - if debugger_irb - # If we're already in a debugger session, set the workspace and irb_path for the original IRB instance - debugger_irb.context.workspace = workspace - debugger_irb.context.irb_path = irb_path - # If we've started a debugger session and hit another binding.irb, we don't want to start an IRB session - # instead, we want to resume the irb:rdbg session. - IRB::Debug.setup(debugger_irb) - IRB::Debug.insert_debug_break - debugger_irb.debug_break - else - # If we're not in a debugger session, create a new IRB instance with the current workspace - binding_irb = IRB::Irb.new(workspace) - binding_irb.context.irb_path = irb_path - binding_irb.run(IRB.conf) - binding_irb.debug_break - end - end -end diff --git a/lib/irb/.document b/lib/irb/.document deleted file mode 100644 index 3b0d6fa4ed6c1e..00000000000000 --- a/lib/irb/.document +++ /dev/null @@ -1 +0,0 @@ -**/*.rb diff --git a/lib/irb/cmd/backtrace.rb b/lib/irb/cmd/backtrace.rb deleted file mode 100644 index f632894618d341..00000000000000 --- a/lib/irb/cmd/backtrace.rb +++ /dev/null @@ -1,21 +0,0 @@ -# frozen_string_literal: true - -require_relative "debug" - -module IRB - # :stopdoc: - - module ExtendCommand - class Backtrace < DebugCommand - def self.transform_args(args) - args&.dump - end - - def execute(*args) - super(pre_cmds: ["backtrace", *args].join(" ")) - end - end - end - - # :startdoc: -end diff --git a/lib/irb/cmd/break.rb b/lib/irb/cmd/break.rb deleted file mode 100644 index df259a90ca80f1..00000000000000 --- a/lib/irb/cmd/break.rb +++ /dev/null @@ -1,21 +0,0 @@ -# frozen_string_literal: true - -require_relative "debug" - -module IRB - # :stopdoc: - - module ExtendCommand - class Break < DebugCommand - def self.transform_args(args) - args&.dump - end - - def execute(args = nil) - super(pre_cmds: "break #{args}") - end - end - end - - # :startdoc: -end diff --git a/lib/irb/cmd/catch.rb b/lib/irb/cmd/catch.rb deleted file mode 100644 index 40b62c7533695a..00000000000000 --- a/lib/irb/cmd/catch.rb +++ /dev/null @@ -1,21 +0,0 @@ -# frozen_string_literal: true - -require_relative "debug" - -module IRB - # :stopdoc: - - module ExtendCommand - class Catch < DebugCommand - def self.transform_args(args) - args&.dump - end - - def execute(*args) - super(pre_cmds: ["catch", *args].join(" ")) - end - end - end - - # :startdoc: -end diff --git a/lib/irb/cmd/chws.rb b/lib/irb/cmd/chws.rb deleted file mode 100644 index 31045f9bbbc3d7..00000000000000 --- a/lib/irb/cmd/chws.rb +++ /dev/null @@ -1,36 +0,0 @@ -# frozen_string_literal: false -# -# change-ws.rb - -# by Keiju ISHITSUKA(keiju@ruby-lang.org) -# - -require_relative "nop" -require_relative "../ext/change-ws" - -module IRB - # :stopdoc: - - module ExtendCommand - - class CurrentWorkingWorkspace < Nop - category "Workspace" - description "Show the current workspace." - - def execute(*obj) - irb_context.main - end - end - - class ChangeWorkspace < Nop - category "Workspace" - description "Change the current workspace to an object." - - def execute(*obj) - irb_context.change_workspace(*obj) - irb_context.main - end - end - end - - # :startdoc: -end diff --git a/lib/irb/cmd/continue.rb b/lib/irb/cmd/continue.rb deleted file mode 100644 index 9136177eef831c..00000000000000 --- a/lib/irb/cmd/continue.rb +++ /dev/null @@ -1,17 +0,0 @@ -# frozen_string_literal: true - -require_relative "debug" - -module IRB - # :stopdoc: - - module ExtendCommand - class Continue < DebugCommand - def execute(*args) - super(do_cmds: ["continue", *args].join(" ")) - end - end - end - - # :startdoc: -end diff --git a/lib/irb/cmd/debug.rb b/lib/irb/cmd/debug.rb deleted file mode 100644 index 9eca964218a116..00000000000000 --- a/lib/irb/cmd/debug.rb +++ /dev/null @@ -1,80 +0,0 @@ -require_relative "nop" -require_relative "../debug" - -module IRB - # :stopdoc: - - module ExtendCommand - class Debug < Nop - category "Debugging" - description "Start the debugger of debug.gem." - - BINDING_IRB_FRAME_REGEXPS = [ - '', - binding.method(:irb).source_location.first, - ].map { |file| /\A#{Regexp.escape(file)}:\d+:in `irb'\z/ } - - def execute(pre_cmds: nil, do_cmds: nil) - if irb_context.with_debugger - # If IRB is already running with a debug session, throw the command and IRB.debug_readline will pass it to the debugger. - if cmd = pre_cmds || do_cmds - throw :IRB_EXIT, cmd - else - puts "IRB is already running with a debug session." - return - end - else - # If IRB is not running with a debug session yet, then: - # 1. Check if the debugging command is run from a `binding.irb` call. - # 2. If so, try setting up the debug gem. - # 3. Insert a debug breakpoint at `Irb#debug_break` with the intended command. - # 4. Exit the current Irb#run call via `throw :IRB_EXIT`. - # 5. `Irb#debug_break` will be called and trigger the breakpoint, which will run the intended command. - unless binding_irb? - puts "`debug` command is only available when IRB is started with binding.irb" - return - end - - if IRB.respond_to?(:JobManager) - warn "Can't start the debugger when IRB is running in a multi-IRB session." - return - end - - unless IRB::Debug.setup(irb_context.irb) - puts <<~MSG - You need to install the debug gem before using this command. - If you use `bundle exec`, please add `gem "debug"` into your Gemfile. - MSG - return - end - - IRB::Debug.insert_debug_break(pre_cmds: pre_cmds, do_cmds: do_cmds) - - # exit current Irb#run call - throw :IRB_EXIT - end - end - - private - - def binding_irb? - caller.any? do |frame| - BINDING_IRB_FRAME_REGEXPS.any? do |regexp| - frame.match?(regexp) - end - end - end - end - - class DebugCommand < Debug - def self.category - "Debugging" - end - - def self.description - command_name = self.name.split("::").last.downcase - "Start the debugger of debug.gem and run its `#{command_name}` command." - end - end - end -end diff --git a/lib/irb/cmd/delete.rb b/lib/irb/cmd/delete.rb deleted file mode 100644 index aeb26d2572335b..00000000000000 --- a/lib/irb/cmd/delete.rb +++ /dev/null @@ -1,17 +0,0 @@ -# frozen_string_literal: true - -require_relative "debug" - -module IRB - # :stopdoc: - - module ExtendCommand - class Delete < DebugCommand - def execute(*args) - super(pre_cmds: ["delete", *args].join(" ")) - end - end - end - - # :startdoc: -end diff --git a/lib/irb/cmd/edit.rb b/lib/irb/cmd/edit.rb deleted file mode 100644 index 69606beea0db9a..00000000000000 --- a/lib/irb/cmd/edit.rb +++ /dev/null @@ -1,60 +0,0 @@ -require 'shellwords' -require_relative "nop" -require_relative "../source_finder" - -module IRB - # :stopdoc: - - module ExtendCommand - class Edit < Nop - category "Misc" - description 'Open a file with the editor command defined with `ENV["VISUAL"]` or `ENV["EDITOR"]`.' - - class << self - def transform_args(args) - # Return a string literal as is for backward compatibility - if args.nil? || args.empty? || string_literal?(args) - args - else # Otherwise, consider the input as a String for convenience - args.strip.dump - end - end - end - - def execute(*args) - path = args.first - - if path.nil? && (irb_path = @irb_context.irb_path) - path = irb_path - end - - if !File.exist?(path) - source = - begin - SourceFinder.new(@irb_context).find_source(path) - rescue NameError - # if user enters a path that doesn't exist, it'll cause NameError when passed here because find_source would try to evaluate it as well - # in this case, we should just ignore the error - end - - if source - path = source.file - else - puts "Can not find file: #{path}" - return - end - end - - if editor = (ENV['VISUAL'] || ENV['EDITOR']) - puts "command: '#{editor}'" - puts " path: #{path}" - system(*Shellwords.split(editor), path) - else - puts "Can not find editor setting: ENV['VISUAL'] or ENV['EDITOR']" - end - end - end - end - - # :startdoc: -end diff --git a/lib/irb/cmd/finish.rb b/lib/irb/cmd/finish.rb deleted file mode 100644 index 29f100feb55542..00000000000000 --- a/lib/irb/cmd/finish.rb +++ /dev/null @@ -1,17 +0,0 @@ -# frozen_string_literal: true - -require_relative "debug" - -module IRB - # :stopdoc: - - module ExtendCommand - class Finish < DebugCommand - def execute(*args) - super(do_cmds: ["finish", *args].join(" ")) - end - end - end - - # :startdoc: -end diff --git a/lib/irb/cmd/help.rb b/lib/irb/cmd/help.rb deleted file mode 100644 index 64b885c3835a45..00000000000000 --- a/lib/irb/cmd/help.rb +++ /dev/null @@ -1,23 +0,0 @@ -# frozen_string_literal: true - -require_relative "show_doc" - -module IRB - module ExtendCommand - class Help < ShowDoc - category "Context" - description "[DEPRECATED] Enter the mode to look up RI documents." - - DEPRECATION_MESSAGE = <<~MSG - [Deprecation] The `help` command will be repurposed to display command help in the future. - For RI document lookup, please use the `show_doc` command instead. - For command help, please use `show_cmds` for now. - MSG - - def execute(*names) - warn DEPRECATION_MESSAGE - super - end - end - end -end diff --git a/lib/irb/cmd/info.rb b/lib/irb/cmd/info.rb deleted file mode 100644 index 2c0a32b34fcf03..00000000000000 --- a/lib/irb/cmd/info.rb +++ /dev/null @@ -1,21 +0,0 @@ -# frozen_string_literal: true - -require_relative "debug" - -module IRB - # :stopdoc: - - module ExtendCommand - class Info < DebugCommand - def self.transform_args(args) - args&.dump - end - - def execute(*args) - super(pre_cmds: ["info", *args].join(" ")) - end - end - end - - # :startdoc: -end diff --git a/lib/irb/cmd/irb_info.rb b/lib/irb/cmd/irb_info.rb deleted file mode 100644 index 75fdc386760955..00000000000000 --- a/lib/irb/cmd/irb_info.rb +++ /dev/null @@ -1,33 +0,0 @@ -# frozen_string_literal: false - -require_relative "nop" - -module IRB - # :stopdoc: - - module ExtendCommand - class IrbInfo < Nop - category "IRB" - description "Show information about IRB." - - def execute - str = "Ruby version: #{RUBY_VERSION}\n" - str += "IRB version: #{IRB.version}\n" - str += "InputMethod: #{IRB.CurrentContext.io.inspect}\n" - str += ".irbrc path: #{IRB.rc_file}\n" if File.exist?(IRB.rc_file) - str += "RUBY_PLATFORM: #{RUBY_PLATFORM}\n" - str += "LANG env: #{ENV["LANG"]}\n" if ENV["LANG"] && !ENV["LANG"].empty? - str += "LC_ALL env: #{ENV["LC_ALL"]}\n" if ENV["LC_ALL"] && !ENV["LC_ALL"].empty? - str += "East Asian Ambiguous Width: #{Reline.ambiguous_width.inspect}\n" - if RbConfig::CONFIG['host_os'] =~ /mswin|msys|mingw|cygwin|bccwin|wince|emc/ - codepage = `chcp`.b.sub(/.*: (\d+)\n/, '\1') - str += "Code page: #{codepage}\n" - end - puts str - nil - end - end - end - - # :startdoc: -end diff --git a/lib/irb/cmd/load.rb b/lib/irb/cmd/load.rb deleted file mode 100644 index a3e797a7e0692a..00000000000000 --- a/lib/irb/cmd/load.rb +++ /dev/null @@ -1,76 +0,0 @@ -# frozen_string_literal: false -# -# load.rb - -# by Keiju ISHITSUKA(keiju@ruby-lang.org) -# - -require_relative "nop" -require_relative "../ext/loader" - -module IRB - # :stopdoc: - - module ExtendCommand - class LoaderCommand < Nop - include IrbLoader - - def raise_cmd_argument_error - raise CommandArgumentError.new("Please specify the file name.") - end - end - - class Load < LoaderCommand - category "IRB" - description "Load a Ruby file." - - def execute(file_name = nil, priv = nil) - raise_cmd_argument_error unless file_name - irb_load(file_name, priv) - end - end - - class Require < LoaderCommand - category "IRB" - description "Require a Ruby file." - def execute(file_name = nil) - raise_cmd_argument_error unless file_name - - rex = Regexp.new("#{Regexp.quote(file_name)}(\.o|\.rb)?") - return false if $".find{|f| f =~ rex} - - case file_name - when /\.rb$/ - begin - if irb_load(file_name) - $".push file_name - return true - end - rescue LoadError - end - when /\.(so|o|sl)$/ - return ruby_require(file_name) - end - - begin - irb_load(f = file_name + ".rb") - $".push f - return true - rescue LoadError - return ruby_require(file_name) - end - end - end - - class Source < LoaderCommand - category "IRB" - description "Loads a given file in the current session." - - def execute(file_name = nil) - raise_cmd_argument_error unless file_name - - source_file(file_name) - end - end - end - # :startdoc: -end diff --git a/lib/irb/cmd/ls.rb b/lib/irb/cmd/ls.rb deleted file mode 100644 index 791b1c1b218905..00000000000000 --- a/lib/irb/cmd/ls.rb +++ /dev/null @@ -1,139 +0,0 @@ -# frozen_string_literal: true - -require "reline" -require "stringio" -require_relative "nop" -require_relative "../pager" -require_relative "../color" - -module IRB - # :stopdoc: - - module ExtendCommand - class Ls < Nop - category "Context" - description "Show methods, constants, and variables. `-g [query]` or `-G [query]` allows you to filter out the output." - - def self.transform_args(args) - if match = args&.match(/\A(?.+\s|)(-g|-G)\s+(?[^\s]+)\s*\n\z/) - args = match[:args] - "#{args}#{',' unless args.chomp.empty?} grep: /#{match[:grep]}/" - else - args - end - end - - def execute(*arg, grep: nil) - o = Output.new(grep: grep) - - obj = arg.empty? ? irb_context.workspace.main : arg.first - locals = arg.empty? ? irb_context.workspace.binding.local_variables : [] - klass = (obj.class == Class || obj.class == Module ? obj : obj.class) - - o.dump("constants", obj.constants) if obj.respond_to?(:constants) - dump_methods(o, klass, obj) - o.dump("instance variables", obj.instance_variables) - o.dump("class variables", klass.class_variables) - o.dump("locals", locals) - o.print_result - end - - def dump_methods(o, klass, obj) - singleton_class = begin obj.singleton_class; rescue TypeError; nil end - dumped_mods = Array.new - ancestors = klass.ancestors - ancestors = ancestors.reject { |c| c >= Object } if klass < Object - singleton_ancestors = (singleton_class&.ancestors || []).reject { |c| c >= Class } - - # singleton_class' ancestors should be at the front - maps = class_method_map(singleton_ancestors, dumped_mods) + class_method_map(ancestors, dumped_mods) - maps.each do |mod, methods| - name = mod == singleton_class ? "#{klass}.methods" : "#{mod}#methods" - o.dump(name, methods) - end - end - - def class_method_map(classes, dumped_mods) - dumped_methods = Array.new - classes.map do |mod| - next if dumped_mods.include? mod - - dumped_mods << mod - - methods = mod.public_instance_methods(false).select do |method| - if dumped_methods.include? method - false - else - dumped_methods << method - true - end - end - - [mod, methods] - end.compact - end - - class Output - MARGIN = " " - - def initialize(grep: nil) - @grep = grep - @line_width = screen_width - MARGIN.length # right padding - @io = StringIO.new - end - - def print_result - Pager.page_content(@io.string) - end - - def dump(name, strs) - strs = strs.grep(@grep) if @grep - strs = strs.sort - return if strs.empty? - - # Attempt a single line - @io.print "#{Color.colorize(name, [:BOLD, :BLUE])}: " - if fits_on_line?(strs, cols: strs.size, offset: "#{name}: ".length) - @io.puts strs.join(MARGIN) - return - end - @io.puts - - # Dump with the largest # of columns that fits on a line - cols = strs.size - until fits_on_line?(strs, cols: cols, offset: MARGIN.length) || cols == 1 - cols -= 1 - end - widths = col_widths(strs, cols: cols) - strs.each_slice(cols) do |ss| - @io.puts ss.map.with_index { |s, i| "#{MARGIN}%-#{widths[i]}s" % s }.join - end - end - - private - - def fits_on_line?(strs, cols:, offset: 0) - width = col_widths(strs, cols: cols).sum + MARGIN.length * (cols - 1) - width <= @line_width - offset - end - - def col_widths(strs, cols:) - cols.times.map do |col| - (col...strs.size).step(cols).map do |i| - strs[i].length - end.max - end - end - - def screen_width - Reline.get_screen_size.last - rescue Errno::EINVAL # in `winsize': Invalid argument - - 80 - end - end - private_constant :Output - end - end - - # :startdoc: -end diff --git a/lib/irb/cmd/measure.rb b/lib/irb/cmd/measure.rb deleted file mode 100644 index 9122e2dac97be3..00000000000000 --- a/lib/irb/cmd/measure.rb +++ /dev/null @@ -1,48 +0,0 @@ -require_relative "nop" - -module IRB - # :stopdoc: - - module ExtendCommand - class Measure < Nop - category "Misc" - description "`measure` enables the mode to measure processing time. `measure :off` disables it." - - def initialize(*args) - super(*args) - end - - def execute(type = nil, arg = nil, &block) - # Please check IRB.init_config in lib/irb/init.rb that sets - # IRB.conf[:MEASURE_PROC] to register default "measure" methods, - # "measure :time" (abbreviated as "measure") and "measure :stackprof". - case type - when :off - IRB.conf[:MEASURE] = nil - IRB.unset_measure_callback(arg) - when :list - IRB.conf[:MEASURE_CALLBACKS].each do |type_name, _, arg_val| - puts "- #{type_name}" + (arg_val ? "(#{arg_val.inspect})" : '') - end - when :on - IRB.conf[:MEASURE] = true - added = IRB.set_measure_callback(type, arg) - puts "#{added[0]} is added." if added - else - if block_given? - IRB.conf[:MEASURE] = true - added = IRB.set_measure_callback(&block) - puts "#{added[0]} is added." if added - else - IRB.conf[:MEASURE] = true - added = IRB.set_measure_callback(type, arg) - puts "#{added[0]} is added." if added - end - end - nil - end - end - end - - # :startdoc: -end diff --git a/lib/irb/cmd/next.rb b/lib/irb/cmd/next.rb deleted file mode 100644 index d29c82e7fc0556..00000000000000 --- a/lib/irb/cmd/next.rb +++ /dev/null @@ -1,17 +0,0 @@ -# frozen_string_literal: true - -require_relative "debug" - -module IRB - # :stopdoc: - - module ExtendCommand - class Next < DebugCommand - def execute(*args) - super(do_cmds: ["next", *args].join(" ")) - end - end - end - - # :startdoc: -end diff --git a/lib/irb/cmd/nop.rb b/lib/irb/cmd/nop.rb deleted file mode 100644 index 7fb197c51f707e..00000000000000 --- a/lib/irb/cmd/nop.rb +++ /dev/null @@ -1,53 +0,0 @@ -# frozen_string_literal: false -# -# nop.rb - -# by Keiju ISHITSUKA(keiju@ruby-lang.org) -# - -module IRB - # :stopdoc: - - module ExtendCommand - class CommandArgumentError < StandardError; end - - class Nop - class << self - def category(category = nil) - @category = category if category - @category - end - - def description(description = nil) - @description = description if description - @description - end - - private - - def string_literal?(args) - sexp = Ripper.sexp(args) - sexp && sexp.size == 2 && sexp.last&.first&.first == :string_literal - end - end - - def self.execute(irb_context, *opts, **kwargs, &block) - command = new(irb_context) - command.execute(*opts, **kwargs, &block) - rescue CommandArgumentError => e - puts e.message - end - - def initialize(irb_context) - @irb_context = irb_context - end - - attr_reader :irb_context - - def execute(*opts) - #nop - end - end - end - - # :startdoc: -end diff --git a/lib/irb/cmd/pushws.rb b/lib/irb/cmd/pushws.rb deleted file mode 100644 index 59996ceb0c7dfa..00000000000000 --- a/lib/irb/cmd/pushws.rb +++ /dev/null @@ -1,45 +0,0 @@ -# frozen_string_literal: false -# -# change-ws.rb - -# by Keiju ISHITSUKA(keiju@ruby-lang.org) -# - -require_relative "nop" -require_relative "../ext/workspaces" - -module IRB - # :stopdoc: - - module ExtendCommand - class Workspaces < Nop - category "Workspace" - description "Show workspaces." - - def execute(*obj) - irb_context.workspaces.collect{|ws| ws.main} - end - end - - class PushWorkspace < Workspaces - category "Workspace" - description "Push an object to the workspace stack." - - def execute(*obj) - irb_context.push_workspace(*obj) - super - end - end - - class PopWorkspace < Workspaces - category "Workspace" - description "Pop a workspace from the workspace stack." - - def execute(*obj) - irb_context.pop_workspace(*obj) - super - end - end - end - - # :startdoc: -end diff --git a/lib/irb/cmd/show_cmds.rb b/lib/irb/cmd/show_cmds.rb deleted file mode 100644 index 7d6b3ec2668b6f..00000000000000 --- a/lib/irb/cmd/show_cmds.rb +++ /dev/null @@ -1,53 +0,0 @@ -# frozen_string_literal: true - -require "stringio" -require_relative "nop" -require_relative "../pager" - -module IRB - # :stopdoc: - - module ExtendCommand - class ShowCmds < Nop - category "IRB" - description "List all available commands and their description." - - def execute(*args) - commands_info = IRB::ExtendCommandBundle.all_commands_info - commands_grouped_by_categories = commands_info.group_by { |cmd| cmd[:category] } - - if irb_context.with_debugger - # Remove the original "Debugging" category - commands_grouped_by_categories.delete("Debugging") - # Remove the `help` command as it's delegated to the debugger - commands_grouped_by_categories["Context"].delete_if { |cmd| cmd[:display_name] == :help } - # Add an empty "Debugging (from debug.gem)" category at the end - commands_grouped_by_categories["Debugging (from debug.gem)"] = [] - end - - longest_cmd_name_length = commands_info.map { |c| c[:display_name].length }.max - - output = StringIO.new - - commands_grouped_by_categories.each do |category, cmds| - output.puts Color.colorize(category, [:BOLD]) - - cmds.each do |cmd| - output.puts " #{cmd[:display_name].to_s.ljust(longest_cmd_name_length)} #{cmd[:description]}" - end - - output.puts - end - - # Append the debugger help at the end - if irb_context.with_debugger - output.puts DEBUGGER__.help - end - - Pager.page_content(output.string) - end - end - end - - # :startdoc: -end diff --git a/lib/irb/cmd/show_doc.rb b/lib/irb/cmd/show_doc.rb deleted file mode 100644 index 99dd9ab95a4102..00000000000000 --- a/lib/irb/cmd/show_doc.rb +++ /dev/null @@ -1,48 +0,0 @@ -# frozen_string_literal: true - -require_relative "nop" - -module IRB - module ExtendCommand - class ShowDoc < Nop - class << self - def transform_args(args) - # Return a string literal as is for backward compatibility - if args.empty? || string_literal?(args) - args - else # Otherwise, consider the input as a String for convenience - args.strip.dump - end - end - end - - category "Context" - description "Enter the mode to look up RI documents." - - def execute(*names) - require 'rdoc/ri/driver' - - unless ShowDoc.const_defined?(:Ri) - opts = RDoc::RI::Driver.process_args([]) - ShowDoc.const_set(:Ri, RDoc::RI::Driver.new(opts)) - end - - if names.empty? - Ri.interactive - else - names.each do |name| - begin - Ri.display_name(name.to_s) - rescue RDoc::RI::Error - puts $!.message - end - end - end - - nil - rescue LoadError, SystemExit - warn "Can't display document because `rdoc` is not installed." - end - end - end -end diff --git a/lib/irb/cmd/show_source.rb b/lib/irb/cmd/show_source.rb deleted file mode 100644 index 10463ebf08ba6e..00000000000000 --- a/lib/irb/cmd/show_source.rb +++ /dev/null @@ -1,56 +0,0 @@ -# frozen_string_literal: true - -require_relative "nop" -require_relative "../source_finder" -require_relative "../color" - -module IRB - module ExtendCommand - class ShowSource < Nop - category "Context" - description "Show the source code of a given method or constant." - - class << self - def transform_args(args) - # Return a string literal as is for backward compatibility - if args.empty? || string_literal?(args) - args - else # Otherwise, consider the input as a String for convenience - args.strip.dump - end - end - end - - def execute(str = nil) - unless str.is_a?(String) - puts "Error: Expected a string but got #{str.inspect}" - return - end - - source = SourceFinder.new(@irb_context).find_source(str) - - if source - show_source(source) - else - puts "Error: Couldn't locate a definition for #{str}" - end - nil - end - - private - - def show_source(source) - puts - puts "#{bold("From")}: #{source.file}:#{source.first_line}" - puts - code = IRB::Color.colorize_code(File.read(source.file)) - puts code.lines[(source.first_line - 1)...source.last_line].join - puts - end - - def bold(str) - Color.colorize(str, [:BOLD]) - end - end - end -end diff --git a/lib/irb/cmd/step.rb b/lib/irb/cmd/step.rb deleted file mode 100644 index 2bc74a9d7922b7..00000000000000 --- a/lib/irb/cmd/step.rb +++ /dev/null @@ -1,17 +0,0 @@ -# frozen_string_literal: true - -require_relative "debug" - -module IRB - # :stopdoc: - - module ExtendCommand - class Step < DebugCommand - def execute(*args) - super(do_cmds: ["step", *args].join(" ")) - end - end - end - - # :startdoc: -end diff --git a/lib/irb/cmd/subirb.rb b/lib/irb/cmd/subirb.rb deleted file mode 100644 index 5ffd646416707f..00000000000000 --- a/lib/irb/cmd/subirb.rb +++ /dev/null @@ -1,109 +0,0 @@ -# frozen_string_literal: false -# -# multi.rb - -# by Keiju ISHITSUKA(keiju@ruby-lang.org) -# - -require_relative "nop" - -module IRB - # :stopdoc: - - module ExtendCommand - class MultiIRBCommand < Nop - def execute(*args) - extend_irb_context - end - - private - - def print_deprecated_warning - warn <<~MSG - Multi-irb commands are deprecated and will be removed in IRB 2.0.0. Please use workspace commands instead. - If you have any use case for multi-irb, please leave a comment at https://github.com/ruby/irb/issues/653 - MSG - end - - def extend_irb_context - # this extension patches IRB context like IRB.CurrentContext - require_relative "../ext/multi-irb" - end - - def print_debugger_warning - warn "Multi-IRB commands are not available when the debugger is enabled." - end - end - - class IrbCommand < MultiIRBCommand - category "Multi-irb (DEPRECATED)" - description "Start a child IRB." - - def execute(*obj) - print_deprecated_warning - - if irb_context.with_debugger - print_debugger_warning - return - end - - super - IRB.irb(nil, *obj) - end - end - - class Jobs < MultiIRBCommand - category "Multi-irb (DEPRECATED)" - description "List of current sessions." - - def execute - print_deprecated_warning - - if irb_context.with_debugger - print_debugger_warning - return - end - - super - IRB.JobManager - end - end - - class Foreground < MultiIRBCommand - category "Multi-irb (DEPRECATED)" - description "Switches to the session of the given number." - - def execute(key = nil) - print_deprecated_warning - - if irb_context.with_debugger - print_debugger_warning - return - end - - super - - raise CommandArgumentError.new("Please specify the id of target IRB job (listed in the `jobs` command).") unless key - IRB.JobManager.switch(key) - end - end - - class Kill < MultiIRBCommand - category "Multi-irb (DEPRECATED)" - description "Kills the session with the given number." - - def execute(*keys) - print_deprecated_warning - - if irb_context.with_debugger - print_debugger_warning - return - end - - super - IRB.JobManager.kill(*keys) - end - end - end - - # :startdoc: -end diff --git a/lib/irb/cmd/whereami.rb b/lib/irb/cmd/whereami.rb deleted file mode 100644 index 8f56ba073dc6d7..00000000000000 --- a/lib/irb/cmd/whereami.rb +++ /dev/null @@ -1,25 +0,0 @@ -# frozen_string_literal: true - -require_relative "nop" - -module IRB - # :stopdoc: - - module ExtendCommand - class Whereami < Nop - category "Context" - description "Show the source code around binding.irb again." - - def execute(*) - code = irb_context.workspace.code_around_binding - if code - puts code - else - puts "The current context doesn't have code." - end - end - end - end - - # :startdoc: -end diff --git a/lib/irb/color.rb b/lib/irb/color.rb deleted file mode 100644 index ad8670160c12ba..00000000000000 --- a/lib/irb/color.rb +++ /dev/null @@ -1,262 +0,0 @@ -# frozen_string_literal: true -require 'reline' -require 'ripper' -require_relative 'ruby-lex' - -module IRB # :nodoc: - module Color - CLEAR = 0 - BOLD = 1 - UNDERLINE = 4 - REVERSE = 7 - BLACK = 30 - RED = 31 - GREEN = 32 - YELLOW = 33 - BLUE = 34 - MAGENTA = 35 - CYAN = 36 - WHITE = 37 - - TOKEN_KEYWORDS = { - on_kw: ['nil', 'self', 'true', 'false', '__FILE__', '__LINE__', '__ENCODING__'], - on_const: ['ENV'], - } - private_constant :TOKEN_KEYWORDS - - # A constant of all-bit 1 to match any Ripper's state in #dispatch_seq - ALL = -1 - private_constant :ALL - - begin - # Following pry's colors where possible, but sometimes having a compromise like making - # backtick and regexp as red (string's color, because they're sharing tokens). - TOKEN_SEQ_EXPRS = { - on_CHAR: [[BLUE, BOLD], ALL], - on_backtick: [[RED, BOLD], ALL], - on_comment: [[BLUE, BOLD], ALL], - on_const: [[BLUE, BOLD, UNDERLINE], ALL], - on_embexpr_beg: [[RED], ALL], - on_embexpr_end: [[RED], ALL], - on_embvar: [[RED], ALL], - on_float: [[MAGENTA, BOLD], ALL], - on_gvar: [[GREEN, BOLD], ALL], - on_heredoc_beg: [[RED], ALL], - on_heredoc_end: [[RED], ALL], - on_ident: [[BLUE, BOLD], Ripper::EXPR_ENDFN], - on_imaginary: [[BLUE, BOLD], ALL], - on_int: [[BLUE, BOLD], ALL], - on_kw: [[GREEN], ALL], - on_label: [[MAGENTA], ALL], - on_label_end: [[RED, BOLD], ALL], - on_qsymbols_beg: [[RED, BOLD], ALL], - on_qwords_beg: [[RED, BOLD], ALL], - on_rational: [[BLUE, BOLD], ALL], - on_regexp_beg: [[RED, BOLD], ALL], - on_regexp_end: [[RED, BOLD], ALL], - on_symbeg: [[YELLOW], ALL], - on_symbols_beg: [[RED, BOLD], ALL], - on_tstring_beg: [[RED, BOLD], ALL], - on_tstring_content: [[RED], ALL], - on_tstring_end: [[RED, BOLD], ALL], - on_words_beg: [[RED, BOLD], ALL], - on_parse_error: [[RED, REVERSE], ALL], - compile_error: [[RED, REVERSE], ALL], - on_assign_error: [[RED, REVERSE], ALL], - on_alias_error: [[RED, REVERSE], ALL], - on_class_name_error:[[RED, REVERSE], ALL], - on_param_error: [[RED, REVERSE], ALL], - on___end__: [[GREEN], ALL], - } - rescue NameError - # Give up highlighting Ripper-incompatible older Ruby - TOKEN_SEQ_EXPRS = {} - end - private_constant :TOKEN_SEQ_EXPRS - - ERROR_TOKENS = TOKEN_SEQ_EXPRS.keys.select { |k| k.to_s.end_with?('error') } - private_constant :ERROR_TOKENS - - class << self - def colorable? - supported = $stdout.tty? && (/mswin|mingw/ =~ RUBY_PLATFORM || (ENV.key?('TERM') && ENV['TERM'] != 'dumb')) - - # because ruby/debug also uses irb's color module selectively, - # irb won't be activated in that case. - if IRB.respond_to?(:conf) - supported && IRB.conf.fetch(:USE_COLORIZE, true) - else - supported - end - end - - def inspect_colorable?(obj, seen: {}.compare_by_identity) - case obj - when String, Symbol, Regexp, Integer, Float, FalseClass, TrueClass, NilClass - true - when Hash - without_circular_ref(obj, seen: seen) do - obj.all? { |k, v| inspect_colorable?(k, seen: seen) && inspect_colorable?(v, seen: seen) } - end - when Array - without_circular_ref(obj, seen: seen) do - obj.all? { |o| inspect_colorable?(o, seen: seen) } - end - when Range - inspect_colorable?(obj.begin, seen: seen) && inspect_colorable?(obj.end, seen: seen) - when Module - !obj.name.nil? - else - false - end - end - - def clear(colorable: colorable?) - return '' unless colorable - "\e[#{CLEAR}m" - end - - def colorize(text, seq, colorable: colorable?) - return text unless colorable - seq = seq.map { |s| "\e[#{const_get(s)}m" }.join('') - "#{seq}#{text}#{clear(colorable: colorable)}" - end - - # If `complete` is false (code is incomplete), this does not warn compile_error. - # This option is needed to avoid warning a user when the compile_error is happening - # because the input is not wrong but just incomplete. - def colorize_code(code, complete: true, ignore_error: false, colorable: colorable?, local_variables: []) - return code unless colorable - - symbol_state = SymbolState.new - colored = +'' - lvars_code = RubyLex.generate_local_variables_assign_code(local_variables) - code_with_lvars = lvars_code ? "#{lvars_code}\n#{code}" : code - - scan(code_with_lvars, allow_last_error: !complete) do |token, str, expr| - # handle uncolorable code - if token.nil? - colored << Reline::Unicode.escape_for_print(str) - next - end - - # IRB::ColorPrinter skips colorizing fragments with any invalid token - if ignore_error && ERROR_TOKENS.include?(token) - return Reline::Unicode.escape_for_print(code) - end - - in_symbol = symbol_state.scan_token(token) - str.each_line do |line| - line = Reline::Unicode.escape_for_print(line) - if seq = dispatch_seq(token, expr, line, in_symbol: in_symbol) - colored << seq.map { |s| "\e[#{s}m" }.join('') - colored << line.sub(/\Z/, clear(colorable: colorable)) - else - colored << line - end - end - end - - if lvars_code - raise "#{lvars_code.dump} should have no \\n" if lvars_code.include?("\n") - colored.sub!(/\A.+\n/, '') # delete_prefix lvars_code with colors - end - colored - end - - private - - def without_circular_ref(obj, seen:, &block) - return false if seen.key?(obj) - seen[obj] = true - block.call - ensure - seen.delete(obj) - end - - def scan(code, allow_last_error:) - verbose, $VERBOSE = $VERBOSE, nil - RubyLex.compile_with_errors_suppressed(code) do |inner_code, line_no| - lexer = Ripper::Lexer.new(inner_code, '(ripper)', line_no) - byte_pos = 0 - line_positions = [0] - inner_code.lines.each do |line| - line_positions << line_positions.last + line.bytesize - end - - on_scan = proc do |elem| - start_pos = line_positions[elem.pos[0] - 1] + elem.pos[1] - - # yield uncolorable code - if byte_pos < start_pos - yield(nil, inner_code.byteslice(byte_pos...start_pos), nil) - end - - if byte_pos <= start_pos - str = elem.tok - yield(elem.event, str, elem.state) - byte_pos = start_pos + str.bytesize - end - end - - lexer.scan.each do |elem| - next if allow_last_error and /meets end of file|unexpected end-of-input/ =~ elem.message - on_scan.call(elem) - end - # yield uncolorable DATA section - yield(nil, inner_code.byteslice(byte_pos...inner_code.bytesize), nil) if byte_pos < inner_code.bytesize - end - ensure - $VERBOSE = verbose - end - - def dispatch_seq(token, expr, str, in_symbol:) - if ERROR_TOKENS.include?(token) - TOKEN_SEQ_EXPRS[token][0] - elsif in_symbol - [YELLOW] - elsif TOKEN_KEYWORDS.fetch(token, []).include?(str) - [CYAN, BOLD] - elsif (seq, exprs = TOKEN_SEQ_EXPRS[token]; (expr & (exprs || 0)) != 0) - seq - else - nil - end - end - end - - # A class to manage a state to know whether the current token is for Symbol or not. - class SymbolState - def initialize - # Push `true` to detect Symbol. `false` to increase the nest level for non-Symbol. - @stack = [] - end - - # Return true if the token is a part of Symbol. - def scan_token(token) - prev_state = @stack.last - case token - when :on_symbeg, :on_symbols_beg, :on_qsymbols_beg - @stack << true - when :on_ident, :on_op, :on_const, :on_ivar, :on_cvar, :on_gvar, :on_kw, :on_backtick - if @stack.last # Pop only when it's Symbol - @stack.pop - return prev_state - end - when :on_tstring_beg - @stack << false - when :on_embexpr_beg - @stack << false - return prev_state - when :on_tstring_end # :on_tstring_end may close Symbol - @stack.pop - return prev_state - when :on_embexpr_end - @stack.pop - end - @stack.last - end - end - private_constant :SymbolState - end -end diff --git a/lib/irb/color_printer.rb b/lib/irb/color_printer.rb deleted file mode 100644 index 31644aa7f9a417..00000000000000 --- a/lib/irb/color_printer.rb +++ /dev/null @@ -1,55 +0,0 @@ -# frozen_string_literal: true -require 'pp' -require_relative 'color' - -module IRB - class ColorPrinter < ::PP - METHOD_RESPOND_TO = Object.instance_method(:respond_to?) - METHOD_INSPECT = Object.instance_method(:inspect) - - class << self - def pp(obj, out = $>, width = screen_width) - q = ColorPrinter.new(out, width) - q.guard_inspect_key {q.pp obj} - q.flush - out << "\n" - end - - private - - def screen_width - Reline.get_screen_size.last - rescue Errno::EINVAL # in `winsize': Invalid argument - - 79 - end - end - - def pp(obj) - if String === obj - # Avoid calling Ruby 2.4+ String#pretty_print that splits a string by "\n" - text(obj.inspect) - elsif !METHOD_RESPOND_TO.bind(obj).call(:inspect) - text(METHOD_INSPECT.bind(obj).call) - else - super - end - end - - def text(str, width = nil) - unless str.is_a?(String) - str = str.inspect - end - width ||= str.length - - case str - when '' - when ',', '=>', '[', ']', '{', '}', '..', '...', /\A@\w+\z/ - super(str, width) - when /\A#' - super(Color.colorize(str, [:GREEN]), width) - else - super(Color.colorize_code(str, ignore_error: true), width) - end - end - end -end diff --git a/lib/irb/completion.rb b/lib/irb/completion.rb deleted file mode 100644 index a143d1b3e112e1..00000000000000 --- a/lib/irb/completion.rb +++ /dev/null @@ -1,446 +0,0 @@ -# frozen_string_literal: false -# -# irb/completion.rb - -# by Keiju ISHITSUKA(keiju@ishitsuka.com) -# From Original Idea of shugo@ruby-lang.org -# - -require_relative 'ruby-lex' - -module IRB - module InputCompletor # :nodoc: - using Module.new { - refine ::Binding do - def eval_methods - ::Kernel.instance_method(:methods).bind(eval("self")).call - end - - def eval_private_methods - ::Kernel.instance_method(:private_methods).bind(eval("self")).call - end - - def eval_instance_variables - ::Kernel.instance_method(:instance_variables).bind(eval("self")).call - end - - def eval_global_variables - ::Kernel.instance_method(:global_variables).bind(eval("self")).call - end - - def eval_class_constants - ::Module.instance_method(:constants).bind(eval("self.class")).call - end - end - } - - # Set of reserved words used by Ruby, you should not use these for - # constants or variables - ReservedWords = %w[ - __ENCODING__ __LINE__ __FILE__ - BEGIN END - alias and - begin break - case class - def defined? do - else elsif end ensure - false for - if in - module - next nil not - or - redo rescue retry return - self super - then true - undef unless until - when while - yield - ] - - BASIC_WORD_BREAK_CHARACTERS = " \t\n`><=;|&{(" - - GEM_PATHS = - if defined?(Gem::Specification) - Gem::Specification.latest_specs(true).map { |s| - s.require_paths.map { |p| - if File.absolute_path?(p) - p - else - File.join(s.full_gem_path, p) - end - } - }.flatten - else - [] - end.freeze - - def self.retrieve_gem_and_system_load_path - candidates = (GEM_PATHS | $LOAD_PATH) - candidates.map do |p| - if p.respond_to?(:to_path) - p.to_path - else - String(p) rescue nil - end - end.compact.sort - end - - def self.retrieve_files_to_require_from_load_path - @@files_from_load_path ||= - ( - shortest = [] - rest = retrieve_gem_and_system_load_path.each_with_object([]) { |path, result| - begin - names = Dir.glob("**/*.{rb,#{RbConfig::CONFIG['DLEXT']}}", base: path) - rescue Errno::ENOENT - nil - end - next if names.empty? - names.map! { |n| n.sub(/\.(rb|#{RbConfig::CONFIG['DLEXT']})\z/, '') }.sort! - shortest << names.shift - result.concat(names) - } - shortest.sort! | rest - ) - end - - def self.retrieve_files_to_require_relative_from_current_dir - @@files_from_current_dir ||= Dir.glob("**/*.{rb,#{RbConfig::CONFIG['DLEXT']}}", base: '.').map { |path| - path.sub(/\.(rb|#{RbConfig::CONFIG['DLEXT']})\z/, '') - } - end - - CompletionRequireProc = lambda { |target, preposing = nil, postposing = nil| - if target =~ /\A(['"])([^'"]+)\Z/ - quote = $1 - actual_target = $2 - else - return nil # It's not String literal - end - tokens = RubyLex.ripper_lex_without_warning(preposing.gsub(/\s*\z/, '')) - tok = nil - tokens.reverse_each do |t| - unless [:on_lparen, :on_sp, :on_ignored_sp, :on_nl, :on_ignored_nl, :on_comment].include?(t.event) - tok = t - break - end - end - result = [] - if tok && tok.event == :on_ident && tok.state == Ripper::EXPR_CMDARG - case tok.tok - when 'require' - result = retrieve_files_to_require_from_load_path.select { |path| - path.start_with?(actual_target) - }.map { |path| - quote + path - } - when 'require_relative' - result = retrieve_files_to_require_relative_from_current_dir.select { |path| - path.start_with?(actual_target) - }.map { |path| - quote + path - } - end - end - result - } - - CompletionProc = lambda { |target, preposing = nil, postposing = nil| - if preposing && postposing - result = CompletionRequireProc.(target, preposing, postposing) - unless result - result = retrieve_completion_data(target).compact.map{ |i| i.encode(Encoding.default_external) } - end - result - else - retrieve_completion_data(target).compact.map{ |i| i.encode(Encoding.default_external) } - end - } - - def self.retrieve_completion_data(input, bind: IRB.conf[:MAIN_CONTEXT].workspace.binding, doc_namespace: false) - case input - # this regexp only matches the closing character because of irb's Reline.completer_quote_characters setting - # details are described in: https://github.com/ruby/irb/pull/523 - when /^(.*["'`])\.([^.]*)$/ - # String - receiver = $1 - message = $2 - - if doc_namespace - "String.#{message}" - else - candidates = String.instance_methods.collect{|m| m.to_s} - select_message(receiver, message, candidates) - end - - # this regexp only matches the closing character because of irb's Reline.completer_quote_characters setting - # details are described in: https://github.com/ruby/irb/pull/523 - when /^(.*\/)\.([^.]*)$/ - # Regexp - receiver = $1 - message = $2 - - if doc_namespace - "Regexp.#{message}" - else - candidates = Regexp.instance_methods.collect{|m| m.to_s} - select_message(receiver, message, candidates) - end - - when /^([^\]]*\])\.([^.]*)$/ - # Array - receiver = $1 - message = $2 - - if doc_namespace - "Array.#{message}" - else - candidates = Array.instance_methods.collect{|m| m.to_s} - select_message(receiver, message, candidates) - end - - when /^([^\}]*\})\.([^.]*)$/ - # Proc or Hash - receiver = $1 - message = $2 - - if doc_namespace - ["Proc.#{message}", "Hash.#{message}"] - else - proc_candidates = Proc.instance_methods.collect{|m| m.to_s} - hash_candidates = Hash.instance_methods.collect{|m| m.to_s} - select_message(receiver, message, proc_candidates | hash_candidates) - end - - when /^(:[^:.]+)$/ - # Symbol - if doc_namespace - nil - else - sym = $1 - candidates = Symbol.all_symbols.collect do |s| - s.inspect - rescue EncodingError - # ignore - end - candidates.grep(/^#{Regexp.quote(sym)}/) - end - when /^::([A-Z][^:\.\(\)]*)$/ - # Absolute Constant or class methods - receiver = $1 - - candidates = Object.constants.collect{|m| m.to_s} - - if doc_namespace - candidates.find { |i| i == receiver } - else - candidates.grep(/^#{Regexp.quote(receiver)}/).collect{|e| "::" + e} - end - - when /^([A-Z].*)::([^:.]*)$/ - # Constant or class methods - receiver = $1 - message = $2 - - if doc_namespace - "#{receiver}::#{message}" - else - begin - candidates = eval("#{receiver}.constants.collect{|m| m.to_s}", bind) - candidates |= eval("#{receiver}.methods.collect{|m| m.to_s}", bind) - rescue Exception - candidates = [] - end - - select_message(receiver, message, candidates.sort, "::") - end - - when /^(:[^:.]+)(\.|::)([^.]*)$/ - # Symbol - receiver = $1 - sep = $2 - message = $3 - - if doc_namespace - "Symbol.#{message}" - else - candidates = Symbol.instance_methods.collect{|m| m.to_s} - select_message(receiver, message, candidates, sep) - end - - when /^(?-?(?:0[dbo])?[0-9_]+(?:\.[0-9_]+)?(?:(?:[eE][+-]?[0-9]+)?i?|r)?)(?\.|::)(?[^.]*)$/ - # Numeric - receiver = $~[:num] - sep = $~[:sep] - message = $~[:mes] - - begin - instance = eval(receiver, bind) - - if doc_namespace - "#{instance.class.name}.#{message}" - else - candidates = instance.methods.collect{|m| m.to_s} - select_message(receiver, message, candidates, sep) - end - rescue Exception - if doc_namespace - nil - else - [] - end - end - - when /^(-?0x[0-9a-fA-F_]+)(\.|::)([^.]*)$/ - # Numeric(0xFFFF) - receiver = $1 - sep = $2 - message = $3 - - begin - instance = eval(receiver, bind) - if doc_namespace - "#{instance.class.name}.#{message}" - else - candidates = instance.methods.collect{|m| m.to_s} - select_message(receiver, message, candidates, sep) - end - rescue Exception - if doc_namespace - nil - else - [] - end - end - - when /^(\$[^.]*)$/ - # global var - gvar = $1 - all_gvars = global_variables.collect{|m| m.to_s} - - if doc_namespace - all_gvars.find{ |i| i == gvar } - else - all_gvars.grep(Regexp.new(Regexp.quote(gvar))) - end - - when /^([^.:"].*)(\.|::)([^.]*)$/ - # variable.func or func.func - receiver = $1 - sep = $2 - message = $3 - - gv = bind.eval_global_variables.collect{|m| m.to_s}.push("true", "false", "nil") - lv = bind.local_variables.collect{|m| m.to_s} - iv = bind.eval_instance_variables.collect{|m| m.to_s} - cv = bind.eval_class_constants.collect{|m| m.to_s} - - if (gv | lv | iv | cv).include?(receiver) or /^[A-Z]/ =~ receiver && /\./ !~ receiver - # foo.func and foo is var. OR - # foo::func and foo is var. OR - # foo::Const and foo is var. OR - # Foo::Bar.func - begin - candidates = [] - rec = eval(receiver, bind) - if sep == "::" and rec.kind_of?(Module) - candidates = rec.constants.collect{|m| m.to_s} - end - candidates |= rec.methods.collect{|m| m.to_s} - rescue Exception - candidates = [] - end - else - # func1.func2 - candidates = [] - end - - if doc_namespace - rec_class = rec.is_a?(Module) ? rec : rec.class - "#{rec_class.name}#{sep}#{candidates.find{ |i| i == message }}" - else - select_message(receiver, message, candidates, sep) - end - - when /^\.([^.]*)$/ - # unknown(maybe String) - - receiver = "" - message = $1 - - candidates = String.instance_methods(true).collect{|m| m.to_s} - - if doc_namespace - "String.#{candidates.find{ |i| i == message }}" - else - select_message(receiver, message, candidates.sort) - end - - else - if doc_namespace - vars = (bind.local_variables | bind.eval_instance_variables).collect{|m| m.to_s} - perfect_match_var = vars.find{|m| m.to_s == input} - if perfect_match_var - eval("#{perfect_match_var}.class.name", bind) - else - candidates = (bind.eval_methods | bind.eval_private_methods | bind.local_variables | bind.eval_instance_variables | bind.eval_class_constants).collect{|m| m.to_s} - candidates |= ReservedWords - candidates.find{ |i| i == input } - end - else - candidates = (bind.eval_methods | bind.eval_private_methods | bind.local_variables | bind.eval_instance_variables | bind.eval_class_constants).collect{|m| m.to_s} - candidates |= ReservedWords - candidates.grep(/^#{Regexp.quote(input)}/).sort - end - end - end - - PerfectMatchedProc = ->(matched, bind: IRB.conf[:MAIN_CONTEXT].workspace.binding) { - begin - require 'rdoc' - rescue LoadError - return - end - - RDocRIDriver ||= RDoc::RI::Driver.new - - if matched =~ /\A(?:::)?RubyVM/ and not ENV['RUBY_YES_I_AM_NOT_A_NORMAL_USER'] - IRB.__send__(:easter_egg) - return - end - - namespace = retrieve_completion_data(matched, bind: bind, doc_namespace: true) - return unless namespace - - if namespace.is_a?(Array) - out = RDoc::Markup::Document.new - namespace.each do |m| - begin - RDocRIDriver.add_method(out, m) - rescue RDoc::RI::Driver::NotFoundError - end - end - RDocRIDriver.display(out) - else - begin - RDocRIDriver.display_names([namespace]) - rescue RDoc::RI::Driver::NotFoundError - end - end - } - - # Set of available operators in Ruby - Operators = %w[% & * ** + - / < << <= <=> == === =~ > >= >> [] []= ^ ! != !~] - - def self.select_message(receiver, message, candidates, sep = ".") - candidates.grep(/^#{Regexp.quote(message)}/).collect do |e| - case e - when /^[a-zA-Z_]/ - receiver + sep + e - when /^[0-9]/ - when *Operators - #receiver + " " + e - end - end - end - end -end diff --git a/lib/irb/context.rb b/lib/irb/context.rb deleted file mode 100644 index a20510d73c3ee8..00000000000000 --- a/lib/irb/context.rb +++ /dev/null @@ -1,586 +0,0 @@ -# frozen_string_literal: false -# -# irb/context.rb - irb context -# by Keiju ISHITSUKA(keiju@ruby-lang.org) -# - -require_relative "workspace" -require_relative "inspector" -require_relative "input-method" -require_relative "output-method" - -module IRB - # A class that wraps the current state of the irb session, including the - # configuration of IRB.conf. - class Context - # Creates a new IRB context. - # - # The optional +input_method+ argument: - # - # +nil+:: uses stdin or Reline or Readline - # +String+:: uses a File - # +other+:: uses this as InputMethod - def initialize(irb, workspace = nil, input_method = nil) - @irb = irb - if workspace - @workspace = workspace - else - @workspace = WorkSpace.new - end - @thread = Thread.current - - # copy of default configuration - @ap_name = IRB.conf[:AP_NAME] - @rc = IRB.conf[:RC] - @load_modules = IRB.conf[:LOAD_MODULES] - - if IRB.conf.has_key?(:USE_SINGLELINE) - @use_singleline = IRB.conf[:USE_SINGLELINE] - elsif IRB.conf.has_key?(:USE_READLINE) # backward compatibility - @use_singleline = IRB.conf[:USE_READLINE] - else - @use_singleline = nil - end - if IRB.conf.has_key?(:USE_MULTILINE) - @use_multiline = IRB.conf[:USE_MULTILINE] - elsif IRB.conf.has_key?(:USE_RELINE) # backward compatibility - warn <<~MSG.strip - USE_RELINE is deprecated, please use USE_MULTILINE instead. - MSG - @use_multiline = IRB.conf[:USE_RELINE] - elsif IRB.conf.has_key?(:USE_REIDLINE) - warn <<~MSG.strip - USE_REIDLINE is deprecated, please use USE_MULTILINE instead. - MSG - @use_multiline = IRB.conf[:USE_REIDLINE] - else - @use_multiline = nil - end - @use_autocomplete = IRB.conf[:USE_AUTOCOMPLETE] - @verbose = IRB.conf[:VERBOSE] - @io = nil - - self.inspect_mode = IRB.conf[:INSPECT_MODE] - self.use_tracer = IRB.conf[:USE_TRACER] if IRB.conf[:USE_TRACER] - self.use_loader = IRB.conf[:USE_LOADER] if IRB.conf[:USE_LOADER] - self.eval_history = IRB.conf[:EVAL_HISTORY] if IRB.conf[:EVAL_HISTORY] - - @ignore_sigint = IRB.conf[:IGNORE_SIGINT] - @ignore_eof = IRB.conf[:IGNORE_EOF] - - @back_trace_limit = IRB.conf[:BACK_TRACE_LIMIT] - - self.prompt_mode = IRB.conf[:PROMPT_MODE] - - if IRB.conf[:SINGLE_IRB] or !defined?(IRB::JobManager) - @irb_name = IRB.conf[:IRB_NAME] - else - @irb_name = IRB.conf[:IRB_NAME]+"#"+IRB.JobManager.n_jobs.to_s - end - @irb_path = "(" + @irb_name + ")" - - case input_method - when nil - @io = nil - case use_multiline? - when nil - if STDIN.tty? && IRB.conf[:PROMPT_MODE] != :INF_RUBY && !use_singleline? - # Both of multiline mode and singleline mode aren't specified. - @io = RelineInputMethod.new - else - @io = nil - end - when false - @io = nil - when true - @io = RelineInputMethod.new - end - unless @io - case use_singleline? - when nil - if (defined?(ReadlineInputMethod) && STDIN.tty? && - IRB.conf[:PROMPT_MODE] != :INF_RUBY) - @io = ReadlineInputMethod.new - else - @io = nil - end - when false - @io = nil - when true - if defined?(ReadlineInputMethod) - @io = ReadlineInputMethod.new - else - @io = nil - end - else - @io = nil - end - end - @io = StdioInputMethod.new unless @io - - when '-' - @io = FileInputMethod.new($stdin) - @irb_name = '-' - @irb_path = '-' - when String - @io = FileInputMethod.new(input_method) - @irb_name = File.basename(input_method) - @irb_path = input_method - else - @io = input_method - end - @extra_doc_dirs = IRB.conf[:EXTRA_DOC_DIRS] - - @echo = IRB.conf[:ECHO] - if @echo.nil? - @echo = true - end - - @echo_on_assignment = IRB.conf[:ECHO_ON_ASSIGNMENT] - if @echo_on_assignment.nil? - @echo_on_assignment = :truncate - end - - @newline_before_multiline_output = IRB.conf[:NEWLINE_BEFORE_MULTILINE_OUTPUT] - if @newline_before_multiline_output.nil? - @newline_before_multiline_output = true - end - - @command_aliases = IRB.conf[:COMMAND_ALIASES] - end - - def save_history=(val) - IRB.conf[:SAVE_HISTORY] = val - end - - def save_history - IRB.conf[:SAVE_HISTORY] - end - - # A copy of the default IRB.conf[:HISTORY_FILE] - def history_file - IRB.conf[:HISTORY_FILE] - end - - # Set IRB.conf[:HISTORY_FILE] to the given +hist+. - def history_file=(hist) - IRB.conf[:HISTORY_FILE] = hist - end - - # The top-level workspace, see WorkSpace#main - def main - @workspace.main - end - - # The toplevel workspace, see #home_workspace - attr_reader :workspace_home - # WorkSpace in the current context. - attr_accessor :workspace - # The current thread in this context. - attr_reader :thread - # The current input method. - # - # Can be either StdioInputMethod, ReadlineInputMethod, - # RelineInputMethod, FileInputMethod or other specified when the - # context is created. See ::new for more # information on +input_method+. - attr_accessor :io - - # Current irb session. - attr_accessor :irb - # A copy of the default IRB.conf[:AP_NAME] - attr_accessor :ap_name - # A copy of the default IRB.conf[:RC] - attr_accessor :rc - # A copy of the default IRB.conf[:LOAD_MODULES] - attr_accessor :load_modules - # Can be either name from IRB.conf[:IRB_NAME], or the number of - # the current job set by JobManager, such as irb#2 - attr_accessor :irb_name - # Can be either the #irb_name surrounded by parenthesis, or the - # +input_method+ passed to Context.new - attr_accessor :irb_path - - # Whether multiline editor mode is enabled or not. - # - # A copy of the default IRB.conf[:USE_MULTILINE] - attr_reader :use_multiline - # Whether singleline editor mode is enabled or not. - # - # A copy of the default IRB.conf[:USE_SINGLELINE] - attr_reader :use_singleline - # Whether colorization is enabled or not. - # - # A copy of the default IRB.conf[:USE_AUTOCOMPLETE] - attr_reader :use_autocomplete - # A copy of the default IRB.conf[:INSPECT_MODE] - attr_reader :inspect_mode - - # A copy of the default IRB.conf[:PROMPT_MODE] - attr_reader :prompt_mode - # Standard IRB prompt. - # - # See IRB@Customizing+the+IRB+Prompt for more information. - attr_accessor :prompt_i - # IRB prompt for continuated strings. - # - # See IRB@Customizing+the+IRB+Prompt for more information. - attr_accessor :prompt_s - # IRB prompt for continuated statement. (e.g. immediately after an +if+) - # - # See IRB@Customizing+the+IRB+Prompt for more information. - attr_accessor :prompt_c - - # TODO: Remove this when developing v2.0 - def prompt_n - warn "IRB::Context#prompt_n is deprecated and will be removed in the next major release." - "" - end - - # TODO: Remove this when developing v2.0 - def prompt_n=(_) - warn "IRB::Context#prompt_n= is deprecated and will be removed in the next major release." - "" - end - - # Can be either the default IRB.conf[:AUTO_INDENT], or the - # mode set by #prompt_mode= - # - # To disable auto-indentation in irb: - # - # IRB.conf[:AUTO_INDENT] = false - # - # or - # - # irb_context.auto_indent_mode = false - # - # or - # - # IRB.CurrentContext.auto_indent_mode = false - # - # See IRB@Configuration for more information. - attr_accessor :auto_indent_mode - # The format of the return statement, set by #prompt_mode= using the - # +:RETURN+ of the +mode+ passed to set the current #prompt_mode. - attr_accessor :return_format - - # Whether ^C (+control-c+) will be ignored or not. - # - # If set to +false+, ^C will quit irb. - # - # If set to +true+, - # - # * during input: cancel input then return to top level. - # * during execute: abandon current execution. - attr_accessor :ignore_sigint - # Whether ^D (+control-d+) will be ignored or not. - # - # If set to +false+, ^D will quit irb. - attr_accessor :ignore_eof - # Specify the installation locations of the ri file to be displayed in the - # document dialog. - attr_accessor :extra_doc_dirs - # Whether to echo the return value to output or not. - # - # Uses IRB.conf[:ECHO] if available, or defaults to +true+. - # - # puts "hello" - # # hello - # #=> nil - # IRB.CurrentContext.echo = false - # puts "omg" - # # omg - attr_accessor :echo - # Whether to echo for assignment expressions. - # - # If set to +false+, the value of assignment will not be shown. - # - # If set to +true+, the value of assignment will be shown. - # - # If set to +:truncate+, the value of assignment will be shown and truncated. - # - # It defaults to +:truncate+. - # - # a = "omg" - # #=> omg - # - # a = "omg" * 10 - # #=> omgomgomgomgomgomgomg... - # - # IRB.CurrentContext.echo_on_assignment = false - # a = "omg" - # - # IRB.CurrentContext.echo_on_assignment = true - # a = "omg" * 10 - # #=> omgomgomgomgomgomgomgomgomgomg - # - # To set the behaviour of showing on assignment in irb: - # - # IRB.conf[:ECHO_ON_ASSIGNMENT] = :truncate or true or false - # - # or - # - # irb_context.echo_on_assignment = :truncate or true or false - # - # or - # - # IRB.CurrentContext.echo_on_assignment = :truncate or true or false - attr_accessor :echo_on_assignment - # Whether a newline is put before multiline output. - # - # Uses IRB.conf[:NEWLINE_BEFORE_MULTILINE_OUTPUT] if available, - # or defaults to +true+. - # - # "abc\ndef" - # #=> - # abc - # def - # IRB.CurrentContext.newline_before_multiline_output = false - # "abc\ndef" - # #=> abc - # def - attr_accessor :newline_before_multiline_output - # Whether verbose messages are displayed or not. - # - # A copy of the default IRB.conf[:VERBOSE] - attr_accessor :verbose - - # The limit of backtrace lines displayed as top +n+ and tail +n+. - # - # The default value is 16. - # - # Can also be set using the +--back-trace-limit+ command line option. - # - # See IRB@Command+line+options for more command line options. - attr_accessor :back_trace_limit - - # User-defined IRB command aliases - attr_accessor :command_aliases - - attr_accessor :with_debugger - - # Alias for #use_multiline - alias use_multiline? use_multiline - # Alias for #use_singleline - alias use_singleline? use_singleline - # backward compatibility - alias use_reline use_multiline - # backward compatibility - alias use_reline? use_multiline - # backward compatibility - alias use_readline use_singleline - # backward compatibility - alias use_readline? use_singleline - # Alias for #use_autocomplete - alias use_autocomplete? use_autocomplete - # Alias for #rc - alias rc? rc - alias ignore_sigint? ignore_sigint - alias ignore_eof? ignore_eof - alias echo? echo - alias echo_on_assignment? echo_on_assignment - alias newline_before_multiline_output? newline_before_multiline_output - - # Returns whether messages are displayed or not. - def verbose? - if @verbose.nil? - if @io.kind_of?(RelineInputMethod) - false - elsif defined?(ReadlineInputMethod) && @io.kind_of?(ReadlineInputMethod) - false - elsif !STDIN.tty? or @io.kind_of?(FileInputMethod) - true - else - false - end - else - @verbose - end - end - - # Whether #verbose? is +true+, and +input_method+ is either - # StdioInputMethod or RelineInputMethod or ReadlineInputMethod, see #io - # for more information. - def prompting? - verbose? || (STDIN.tty? && @io.kind_of?(StdioInputMethod) || - @io.kind_of?(RelineInputMethod) || - (defined?(ReadlineInputMethod) && @io.kind_of?(ReadlineInputMethod))) - end - - # The return value of the last statement evaluated. - attr_reader :last_value - - # Sets the return value from the last statement evaluated in this context - # to #last_value. - def set_last_value(value) - @last_value = value - @workspace.local_variable_set :_, value - end - - # Sets the +mode+ of the prompt in this context. - # - # See IRB@Customizing+the+IRB+Prompt for more information. - def prompt_mode=(mode) - @prompt_mode = mode - pconf = IRB.conf[:PROMPT][mode] - @prompt_i = pconf[:PROMPT_I] - @prompt_s = pconf[:PROMPT_S] - @prompt_c = pconf[:PROMPT_C] - @return_format = pconf[:RETURN] - @return_format = "%s\n" if @return_format == nil - if ai = pconf.include?(:AUTO_INDENT) - @auto_indent_mode = ai - else - @auto_indent_mode = IRB.conf[:AUTO_INDENT] - end - end - - # Whether #inspect_mode is set or not, see #inspect_mode= for more detail. - def inspect? - @inspect_mode.nil? or @inspect_mode - end - - # Whether #io uses a File for the +input_method+ passed when creating the - # current context, see ::new - def file_input? - @io.class == FileInputMethod - end - - # Specifies the inspect mode with +opt+: - # - # +true+:: display +inspect+ - # +false+:: display +to_s+ - # +nil+:: inspect mode in non-math mode, - # non-inspect mode in math mode - # - # See IRB::Inspector for more information. - # - # Can also be set using the +--inspect+ and +--noinspect+ command line - # options. - # - # See IRB@Command+line+options for more command line options. - def inspect_mode=(opt) - - if i = Inspector::INSPECTORS[opt] - @inspect_mode = opt - @inspect_method = i - i.init - else - case opt - when nil - if Inspector.keys_with_inspector(Inspector::INSPECTORS[true]).include?(@inspect_mode) - self.inspect_mode = false - elsif Inspector.keys_with_inspector(Inspector::INSPECTORS[false]).include?(@inspect_mode) - self.inspect_mode = true - else - puts "Can't switch inspect mode." - return - end - when /^\s*\{.*\}\s*$/ - begin - inspector = eval "proc#{opt}" - rescue Exception - puts "Can't switch inspect mode(#{opt})." - return - end - self.inspect_mode = inspector - when Proc - self.inspect_mode = IRB::Inspector(opt) - when Inspector - prefix = "usr%d" - i = 1 - while Inspector::INSPECTORS[format(prefix, i)]; i += 1; end - @inspect_mode = format(prefix, i) - @inspect_method = opt - Inspector.def_inspector(format(prefix, i), @inspect_method) - else - puts "Can't switch inspect mode(#{opt})." - return - end - end - print "Switch to#{unless @inspect_mode; ' non';end} inspect mode.\n" if verbose? - @inspect_mode - end - - def evaluate(line, line_no) # :nodoc: - @line_no = line_no - result = nil - - if IRB.conf[:MEASURE] && IRB.conf[:MEASURE_CALLBACKS].empty? - IRB.set_measure_callback - end - - if IRB.conf[:MEASURE] && !IRB.conf[:MEASURE_CALLBACKS].empty? - last_proc = proc do - result = @workspace.evaluate(line, irb_path, line_no) - end - IRB.conf[:MEASURE_CALLBACKS].inject(last_proc) do |chain, item| - _name, callback, arg = item - proc do - callback.(self, line, line_no, arg) do - chain.call - end - end - end.call - else - result = @workspace.evaluate(line, irb_path, line_no) - end - - set_last_value(result) - end - - def inspect_last_value # :nodoc: - @inspect_method.inspect_value(@last_value) - end - - alias __exit__ exit - # Exits the current session, see IRB.irb_exit - def exit(ret = 0) - IRB.irb_exit(@irb, ret) - rescue UncaughtThrowError - super - end - - NOPRINTING_IVARS = ["@last_value"] # :nodoc: - NO_INSPECTING_IVARS = ["@irb", "@io"] # :nodoc: - IDNAME_IVARS = ["@prompt_mode"] # :nodoc: - - alias __inspect__ inspect - def inspect # :nodoc: - array = [] - for ivar in instance_variables.sort{|e1, e2| e1 <=> e2} - ivar = ivar.to_s - name = ivar.sub(/^@(.*)$/, '\1') - val = instance_eval(ivar) - case ivar - when *NOPRINTING_IVARS - array.push format("conf.%s=%s", name, "...") - when *NO_INSPECTING_IVARS - array.push format("conf.%s=%s", name, val.to_s) - when *IDNAME_IVARS - array.push format("conf.%s=:%s", name, val.id2name) - else - array.push format("conf.%s=%s", name, val.inspect) - end - end - array.join("\n") - end - alias __to_s__ to_s - alias to_s inspect - - def local_variables # :nodoc: - workspace.binding.local_variables - end - - # Return true if it's aliased from the argument and it's not an identifier. - def symbol_alias?(command) - return nil if command.match?(/\A\w+\z/) - command_aliases.key?(command.to_sym) - end - - # Return true if the command supports transforming args - def transform_args?(command) - command = command_aliases.fetch(command.to_sym, command) - ExtendCommandBundle.load_command(command)&.respond_to?(:transform_args) - end - end -end diff --git a/lib/irb/debug.rb b/lib/irb/debug.rb deleted file mode 100644 index f819f850b10abf..00000000000000 --- a/lib/irb/debug.rb +++ /dev/null @@ -1,115 +0,0 @@ -# frozen_string_literal: true - -module IRB - module Debug - IRB_DIR = File.expand_path('..', __dir__) - - class << self - def insert_debug_break(pre_cmds: nil, do_cmds: nil) - options = { oneshot: true, hook_call: false } - - if pre_cmds || do_cmds - options[:command] = ['irb', pre_cmds, do_cmds] - end - if DEBUGGER__::LineBreakpoint.instance_method(:initialize).parameters.include?([:key, :skip_src]) - options[:skip_src] = true - end - - # To make debugger commands like `next` or `continue` work without asking - # the user to quit IRB after that, we need to exit IRB first and then hit - # a TracePoint on #debug_break. - file, lineno = IRB::Irb.instance_method(:debug_break).source_location - DEBUGGER__::SESSION.add_line_breakpoint(file, lineno + 1, **options) - end - - def setup(irb) - # When debug session is not started at all - unless defined?(DEBUGGER__::SESSION) - begin - require "debug/session" - rescue LoadError # debug.gem is not written in Gemfile - return false unless load_bundled_debug_gem - end - DEBUGGER__::CONFIG.set_config - configure_irb_for_debugger(irb) - thread = Thread.current - - DEBUGGER__.initialize_session{ IRB::Debug::UI.new(thread, irb) } - end - - # When debug session was previously started but not by IRB - if defined?(DEBUGGER__::SESSION) && !irb.context.with_debugger - configure_irb_for_debugger(irb) - thread = Thread.current - - DEBUGGER__::SESSION.reset_ui(IRB::Debug::UI.new(thread, irb)) - end - - # Apply patches to debug gem so it skips IRB frames - unless DEBUGGER__.respond_to?(:capture_frames_without_irb) - DEBUGGER__.singleton_class.send(:alias_method, :capture_frames_without_irb, :capture_frames) - - def DEBUGGER__.capture_frames(*args) - frames = capture_frames_without_irb(*args) - frames.reject! do |frame| - frame.realpath&.start_with?(IRB_DIR) || frame.path == "" - end - frames - end - - DEBUGGER__::ThreadClient.prepend(SkipPathHelperForIRB) - end - - true - end - - private - - def configure_irb_for_debugger(irb) - require 'irb/debug/ui' - IRB.instance_variable_set(:@debugger_irb, irb) - irb.context.with_debugger = true - irb.context.irb_name += ":rdbg" - end - - module SkipPathHelperForIRB - def skip_internal_path?(path) - # The latter can be removed once https://github.com/ruby/debug/issues/866 is resolved - super || path.match?(IRB_DIR) || path.match?('') - end - end - - # This is used when debug.gem is not written in Gemfile. Even if it's not - # installed by `bundle install`, debug.gem is installed by default because - # it's a bundled gem. This method tries to activate and load that. - def load_bundled_debug_gem - # Discover latest debug.gem under GEM_PATH - debug_gem = Gem.paths.path.flat_map { |path| Dir.glob("#{path}/gems/debug-*") }.select do |path| - File.basename(path).match?(/\Adebug-\d+\.\d+\.\d+(\w+)?\z/) - end.sort_by do |path| - Gem::Version.new(File.basename(path).delete_prefix('debug-')) - end.last - return false unless debug_gem - - # Discover debug/debug.so under extensions for Ruby 3.2+ - ext_name = "/debug/debug.#{RbConfig::CONFIG['DLEXT']}" - ext_path = Gem.paths.path.flat_map do |path| - Dir.glob("#{path}/extensions/**/#{File.basename(debug_gem)}#{ext_name}") - end.first - - # Attempt to forcibly load the bundled gem - if ext_path - $LOAD_PATH << ext_path.delete_suffix(ext_name) - end - $LOAD_PATH << "#{debug_gem}/lib" - begin - require "debug/session" - puts "Loaded #{File.basename(debug_gem)}" - true - rescue LoadError - false - end - end - end - end -end diff --git a/lib/irb/debug/ui.rb b/lib/irb/debug/ui.rb deleted file mode 100644 index a4ca4fdf0f2df0..00000000000000 --- a/lib/irb/debug/ui.rb +++ /dev/null @@ -1,104 +0,0 @@ -require 'io/console/size' -require 'debug/console' - -module IRB - module Debug - class UI < DEBUGGER__::UI_Base - def initialize(thread, irb) - @thread = thread - @irb = irb - end - - def remote? - false - end - - def activate session, on_fork: false - end - - def deactivate - end - - def width - if (w = IO.console_size[1]) == 0 # for tests PTY - 80 - else - w - end - end - - def quit n - yield - exit n - end - - def ask prompt - setup_interrupt do - print prompt - ($stdin.gets || '').strip - end - end - - def puts str = nil - case str - when Array - str.each{|line| - $stdout.puts line.chomp - } - when String - str.each_line{|line| - $stdout.puts line.chomp - } - when nil - $stdout.puts - end - end - - def readline _ - setup_interrupt do - tc = DEBUGGER__::SESSION.get_thread_client(@thread) - cmd = @irb.debug_readline(tc.current_frame.binding || TOPLEVEL_BINDING) - - case cmd - when nil # when user types C-d - "continue" - else - cmd - end - end - end - - def setup_interrupt - DEBUGGER__::SESSION.intercept_trap_sigint false do - current_thread = Thread.current # should be session_server thread - - prev_handler = trap(:INT){ - current_thread.raise Interrupt - } - - yield - ensure - trap(:INT, prev_handler) - end - end - - def after_fork_parent - parent_pid = Process.pid - - at_exit{ - DEBUGGER__::SESSION.intercept_trap_sigint_end - trap(:SIGINT, :IGNORE) - - if Process.pid == parent_pid - # only check child process from its parent - begin - # wait for all child processes to keep terminal - Process.waitpid - rescue Errno::ESRCH, Errno::ECHILD - end - end - } - end - end - end -end diff --git a/lib/irb/easter-egg.rb b/lib/irb/easter-egg.rb deleted file mode 100644 index 3e79692de95030..00000000000000 --- a/lib/irb/easter-egg.rb +++ /dev/null @@ -1,138 +0,0 @@ -require "reline" - -module IRB - class << self - class Vec - def initialize(x, y, z) - @x, @y, @z = x, y, z - end - - attr_reader :x, :y, :z - - def sub(other) - Vec.new(@x - other.x, @y - other.y, @z - other.z) - end - - def dot(other) - @x*other.x + @y*other.y + @z*other.z - end - - def cross(other) - ox, oy, oz = other.x, other.y, other.z - Vec.new(@y*oz-@z*oy, @z*ox-@x*oz, @x*oy-@y*ox) - end - - def normalize - r = Math.sqrt(self.dot(self)) - Vec.new(@x / r, @y / r, @z / r) - end - end - - class Canvas - def initialize((h, w)) - @data = (0..h-2).map { [0] * w } - @scale = [w / 2.0, h-2].min - @center = Complex(w / 2, h-2) - end - - def line((x1, y1), (x2, y2)) - p1 = Complex(x1, y1) / 2 * @scale + @center - p2 = Complex(x2, y2) / 2 * @scale + @center - line0(p1, p2) - end - - private def line0(p1, p2) - mid = (p1 + p2) / 2 - if (p1 - p2).abs < 1 - x, y = mid.rect - @data[y / 2][x] |= (y % 2 > 1 ? 2 : 1) - else - line0(p1, mid) - line0(p2, mid) - end - end - - def draw - @data.each {|row| row.fill(0) } - yield - @data.map {|row| row.map {|n| " ',;"[n] }.join }.join("\n") - end - end - - class RubyModel - def initialize - @faces = init_ruby_model - end - - def init_ruby_model - cap_vertices = (0..5).map {|i| Vec.new(*Complex.polar(1, i * Math::PI / 3).rect, 1) } - middle_vertices = (0..5).map {|i| Vec.new(*Complex.polar(2, (i + 0.5) * Math::PI / 3).rect, 0) } - bottom_vertex = Vec.new(0, 0, -2) - - faces = [cap_vertices] - 6.times do |j| - i = j-1 - faces << [cap_vertices[i], middle_vertices[i], cap_vertices[j]] - faces << [cap_vertices[j], middle_vertices[i], middle_vertices[j]] - faces << [middle_vertices[i], bottom_vertex, middle_vertices[j]] - end - - faces - end - - def render_frame(i) - angle = i / 10.0 - dir = Vec.new(*Complex.polar(1, angle).rect, Math.sin(angle)).normalize - dir2 = Vec.new(*Complex.polar(1, angle - Math::PI/2).rect, 0) - up = dir.cross(dir2) - nm = dir.cross(up) - @faces.each do |vertices| - v0, v1, v2, = vertices - if v1.sub(v0).cross(v2.sub(v0)).dot(dir) > 0 - points = vertices.map {|p| [nm.dot(p), up.dot(p)] } - (points + [points[0]]).each_cons(2) do |p1, p2| - yield p1, p2 - end - end - end - end - end - - private def easter_egg(type = nil) - type ||= [:logo, :dancing].sample - case type - when :logo - File.open(File.join(__dir__, 'ruby_logo.aa')) do |f| - require "rdoc" - RDoc::RI::Driver.new.page do |io| - IO.copy_stream(f, io) - end - end - when :dancing - begin - canvas = Canvas.new(Reline.get_screen_size) - Reline::IOGate.set_winch_handler do - canvas = Canvas.new(Reline.get_screen_size) - end - ruby_model = RubyModel.new - print "\e[?1049h" - 0.step do |i| # TODO (0..).each needs Ruby 2.6 or later - buff = canvas.draw do - ruby_model.render_frame(i) do |p1, p2| - canvas.line(p1, p2) - end - end - buff[0, 20] = "\e[0mPress Ctrl+C to stop\e[31m\e[1m" - print "\e[H" + buff - sleep 0.05 - end - rescue Interrupt - ensure - print "\e[0m\e[?1049l" - end - end - end - end -end - -IRB.__send__(:easter_egg, ARGV[0]&.to_sym) if $0 == __FILE__ diff --git a/lib/irb/ext/change-ws.rb b/lib/irb/ext/change-ws.rb deleted file mode 100644 index c0f810a4c80b06..00000000000000 --- a/lib/irb/ext/change-ws.rb +++ /dev/null @@ -1,39 +0,0 @@ -# frozen_string_literal: false -# -# irb/ext/cb.rb - -# by Keiju ISHITSUKA(keiju@ruby-lang.org) -# - -module IRB # :nodoc: - class Context - - # Inherited from +TOPLEVEL_BINDING+. - def home_workspace - if defined? @home_workspace - @home_workspace - else - @home_workspace = @workspace - end - end - - # Changes the current workspace to given object or binding. - # - # If the optional argument is omitted, the workspace will be - # #home_workspace which is inherited from +TOPLEVEL_BINDING+ or the main - # object, IRB.conf[:MAIN_CONTEXT] when irb was initialized. - # - # See IRB::WorkSpace.new for more information. - def change_workspace(*_main) - if _main.empty? - @workspace = home_workspace - return main - end - - @workspace = WorkSpace.new(_main[0]) - - if !(class<IRB.conf[:EVAL_HISTORY] in .irbrc). - attr_reader :eval_history - # Sets command result history limit. Default value is set from - # IRB.conf[:EVAL_HISTORY]. - # - # +no+ is an Integer or +nil+. - # - # Returns +no+ of history items if greater than 0. - # - # If +no+ is 0, the number of history items is unlimited. - # - # If +no+ is +nil+, execution result history isn't used (default). - # - # EvalHistory values are available via __ variable, see - # IRB::EvalHistory. - def eval_history=(no) - if no - if defined?(@eval_history) && @eval_history - @eval_history_values.size(no) - else - @eval_history_values = EvalHistory.new(no) - IRB.conf[:__TMP__EHV__] = @eval_history_values - @workspace.evaluate("__ = IRB.conf[:__TMP__EHV__]") - IRB.conf.delete(:__TMP_EHV__) - end - else - @eval_history_values = nil - end - @eval_history = no - end - end - - # Represents history of results of previously evaluated commands. - # - # Available via __ variable, only if IRB.conf[:EVAL_HISTORY] - # or IRB::CurrentContext().eval_history is non-nil integer value - # (by default it is +nil+). - # - # Example (in `irb`): - # - # # Initialize history - # IRB::CurrentContext().eval_history = 10 - # # => 10 - # - # # Perform some commands... - # 1 + 2 - # # => 3 - # puts 'x' - # # x - # # => nil - # raise RuntimeError - # # ...error raised - # - # # Inspect history (format is " ": - # __ - # # => 1 10 - # # 2 3 - # # 3 nil - # - # __[1] - # # => 10 - # - class EvalHistory - - def initialize(size = 16) # :nodoc: - @size = size - @contents = [] - end - - def size(size) # :nodoc: - if size != 0 && size < @size - @contents = @contents[@size - size .. @size] - end - @size = size - end - - # Get one item of the content (both positive and negative indexes work). - def [](idx) - begin - if idx >= 0 - @contents.find{|no, val| no == idx}[1] - else - @contents[idx][1] - end - rescue NameError - nil - end - end - - def push(no, val) # :nodoc: - @contents.push [no, val] - @contents.shift if @size != 0 && @contents.size > @size - end - - alias real_inspect inspect - - def inspect # :nodoc: - if @contents.empty? - return real_inspect - end - - unless (last = @contents.pop)[1].equal?(self) - @contents.push last - last = nil - end - str = @contents.collect{|no, val| - if val.equal?(self) - "#{no} ...self-history..." - else - "#{no} #{val.inspect}" - end - }.join("\n") - if str == "" - str = "Empty." - end - @contents.push last if last - str - end - end -end diff --git a/lib/irb/ext/loader.rb b/lib/irb/ext/loader.rb deleted file mode 100644 index d65695df3b3146..00000000000000 --- a/lib/irb/ext/loader.rb +++ /dev/null @@ -1,127 +0,0 @@ -# frozen_string_literal: false -# -# loader.rb - -# by Keiju ISHITSUKA(keiju@ruby-lang.org) -# - -module IRB # :nodoc: - # Raised in the event of an exception in a file loaded from an Irb session - class LoadAbort < Exception;end - - # Provides a few commands for loading files within an irb session. - # - # See ExtendCommandBundle for more information. - module IrbLoader - - alias ruby_load load - alias ruby_require require - - # Loads the given file similarly to Kernel#load - def irb_load(fn, priv = nil) - path = search_file_from_ruby_path(fn) - raise LoadError, "No such file to load -- #{fn}" unless path - - load_file(path, priv) - end - - def search_file_from_ruby_path(fn) # :nodoc: - if File.absolute_path?(fn) - return fn if File.exist?(fn) - return nil - end - - for path in $: - if File.exist?(f = File.join(path, fn)) - return f - end - end - return nil - end - - # Loads a given file in the current session and displays the source lines - # - # See Irb#suspend_input_method for more information. - def source_file(path) - irb = irb_context.irb - irb.suspend_name(path, File.basename(path)) do - FileInputMethod.open(path) do |io| - irb.suspend_input_method(io) do - |back_io| - irb.signal_status(:IN_LOAD) do - if back_io.kind_of?(FileInputMethod) - irb.eval_input - else - begin - irb.eval_input - rescue LoadAbort - print "load abort!!\n" - end - end - end - end - end - end - end - - # Loads the given file in the current session's context and evaluates it. - # - # See Irb#suspend_input_method for more information. - def load_file(path, priv = nil) - irb = irb_context.irb - irb.suspend_name(path, File.basename(path)) do - - if priv - ws = WorkSpace.new(Module.new) - else - ws = WorkSpace.new - end - irb.suspend_workspace(ws) do - FileInputMethod.open(path) do |io| - irb.suspend_input_method(io) do - |back_io| - irb.signal_status(:IN_LOAD) do - if back_io.kind_of?(FileInputMethod) - irb.eval_input - else - begin - irb.eval_input - rescue LoadAbort - print "load abort!!\n" - end - end - end - end - end - end - end - end - - def old # :nodoc: - back_io = @io - back_path = @irb_path - back_name = @irb_name - back_scanner = @irb.scanner - begin - @io = FileInputMethod.new(path) - @irb_name = File.basename(path) - @irb_path = path - @irb.signal_status(:IN_LOAD) do - if back_io.kind_of?(FileInputMethod) - @irb.eval_input - else - begin - @irb.eval_input - rescue LoadAbort - print "load abort!!\n" - end - end - end - ensure - @io = back_io - @irb_name = back_name - @irb_path = back_path - @irb.scanner = back_scanner - end - end - end -end diff --git a/lib/irb/ext/multi-irb.rb b/lib/irb/ext/multi-irb.rb deleted file mode 100644 index 1c20489137bd6c..00000000000000 --- a/lib/irb/ext/multi-irb.rb +++ /dev/null @@ -1,258 +0,0 @@ -# frozen_string_literal: false -# -# irb/multi-irb.rb - multiple irb module -# by Keiju ISHITSUKA(keiju@ruby-lang.org) -# - -module IRB - class JobManager - - # Creates a new JobManager object - def initialize - @jobs = [] - @current_job = nil - end - - # The active irb session - attr_accessor :current_job - - # The total number of irb sessions, used to set +irb_name+ of the current - # Context. - def n_jobs - @jobs.size - end - - # Returns the thread for the given +key+ object, see #search for more - # information. - def thread(key) - th, = search(key) - th - end - - # Returns the irb session for the given +key+ object, see #search for more - # information. - def irb(key) - _, irb = search(key) - irb - end - - # Returns the top level thread. - def main_thread - @jobs[0][0] - end - - # Returns the top level irb session. - def main_irb - @jobs[0][1] - end - - # Add the given +irb+ session to the jobs Array. - def insert(irb) - @jobs.push [Thread.current, irb] - end - - # Changes the current active irb session to the given +key+ in the jobs - # Array. - # - # Raises an IrbAlreadyDead exception if the given +key+ is no longer alive. - # - # If the given irb session is already active, an IrbSwitchedToCurrentThread - # exception is raised. - def switch(key) - th, irb = search(key) - fail IrbAlreadyDead unless th.alive? - fail IrbSwitchedToCurrentThread if th == Thread.current - @current_job = irb - th.run - Thread.stop - @current_job = irb(Thread.current) - end - - # Terminates the irb sessions specified by the given +keys+. - # - # Raises an IrbAlreadyDead exception if one of the given +keys+ is already - # terminated. - # - # See Thread#exit for more information. - def kill(*keys) - for key in keys - th, _ = search(key) - fail IrbAlreadyDead unless th.alive? - th.exit - end - end - - # Returns the associated job for the given +key+. - # - # If given an Integer, it will return the +key+ index for the jobs Array. - # - # When an instance of Irb is given, it will return the irb session - # associated with +key+. - # - # If given an instance of Thread, it will return the associated thread - # +key+ using Object#=== on the jobs Array. - # - # Otherwise returns the irb session with the same top-level binding as the - # given +key+. - # - # Raises a NoSuchJob exception if no job can be found with the given +key+. - def search(key) - job = case key - when Integer - @jobs[key] - when Irb - @jobs.find{|k, v| v.equal?(key)} - when Thread - @jobs.assoc(key) - else - @jobs.find{|k, v| v.context.main.equal?(key)} - end - fail NoSuchJob, key if job.nil? - job - end - - # Deletes the job at the given +key+. - def delete(key) - case key - when Integer - fail NoSuchJob, key unless @jobs[key] - @jobs[key] = nil - else - catch(:EXISTS) do - @jobs.each_index do - |i| - if @jobs[i] and (@jobs[i][0] == key || - @jobs[i][1] == key || - @jobs[i][1].context.main.equal?(key)) - @jobs[i] = nil - throw :EXISTS - end - end - fail NoSuchJob, key - end - end - until assoc = @jobs.pop; end unless @jobs.empty? - @jobs.push assoc - end - - # Outputs a list of jobs, see the irb command +irb_jobs+, or +jobs+. - def inspect - ary = [] - @jobs.each_index do - |i| - th, irb = @jobs[i] - next if th.nil? - - if th.alive? - if th.stop? - t_status = "stop" - else - t_status = "running" - end - else - t_status = "exited" - end - ary.push format("#%d->%s on %s (%s: %s)", - i, - irb.context.irb_name, - irb.context.main, - th, - t_status) - end - ary.join("\n") - end - end - - @JobManager = JobManager.new - - # The current JobManager in the session - def IRB.JobManager - @JobManager - end - - # The current Context in this session - def IRB.CurrentContext - IRB.JobManager.irb(Thread.current).context - end - - # Creates a new IRB session, see Irb.new. - # - # The optional +file+ argument is given to Context.new, along with the - # workspace created with the remaining arguments, see WorkSpace.new - def IRB.irb(file = nil, *main) - workspace = WorkSpace.new(*main) - parent_thread = Thread.current - Thread.start do - begin - irb = Irb.new(workspace, file) - rescue - print "Subirb can't start with context(self): ", workspace.main.inspect, "\n" - print "return to main irb\n" - Thread.pass - Thread.main.wakeup - Thread.exit - end - @CONF[:IRB_RC].call(irb.context) if @CONF[:IRB_RC] - @JobManager.insert(irb) - @JobManager.current_job = irb - begin - system_exit = false - catch(:IRB_EXIT) do - irb.eval_input - end - rescue SystemExit - system_exit = true - raise - #fail - ensure - unless system_exit - @JobManager.delete(irb) - if @JobManager.current_job == irb - if parent_thread.alive? - @JobManager.current_job = @JobManager.irb(parent_thread) - parent_thread.run - else - @JobManager.current_job = @JobManager.main_irb - @JobManager.main_thread.run - end - end - end - end - end - Thread.stop - @JobManager.current_job = @JobManager.irb(Thread.current) - end - - @CONF[:SINGLE_IRB_MODE] = false - @JobManager.insert(@CONF[:MAIN_CONTEXT].irb) - @JobManager.current_job = @CONF[:MAIN_CONTEXT].irb - - class Irb - def signal_handle - unless @context.ignore_sigint? - print "\nabort!!\n" if @context.verbose? - exit - end - - case @signal_status - when :IN_INPUT - print "^C\n" - IRB.JobManager.thread(self).raise RubyLex::TerminateLineInput - when :IN_EVAL - IRB.irb_abort(self) - when :IN_LOAD - IRB.irb_abort(self, LoadAbort) - when :IN_IRB - # ignore - else - # ignore other cases as well - end - end - end - - trap("SIGINT") do - @JobManager.current_job.signal_handle - Thread.stop - end - -end diff --git a/lib/irb/ext/tracer.rb b/lib/irb/ext/tracer.rb deleted file mode 100644 index 3eaeb70ef27dd2..00000000000000 --- a/lib/irb/ext/tracer.rb +++ /dev/null @@ -1,78 +0,0 @@ -# frozen_string_literal: false -# -# irb/lib/tracer.rb - -# by Keiju ISHITSUKA(keiju@ruby-lang.org) -# - -begin - require "tracer" -rescue LoadError - $stderr.puts "Tracer extension of IRB is enabled but tracer gem wasn't found." - module IRB - class Context - def use_tracer=(opt) - # do nothing - end - end - end - return # This is about to disable loading below -end - -module IRB - - # initialize tracing function - def IRB.initialize_tracer - Tracer.verbose = false - Tracer.add_filter { - |event, file, line, id, binding, *rests| - /^#{Regexp.quote(@CONF[:IRB_LIB_PATH])}/ !~ file and - File::basename(file) != "irb.rb" - } - end - - class Context - # Whether Tracer is used when evaluating statements in this context. - # - # See +lib/tracer.rb+ for more information. - attr_reader :use_tracer - alias use_tracer? use_tracer - - # Sets whether or not to use the Tracer library when evaluating statements - # in this context. - # - # See +lib/tracer.rb+ for more information. - def use_tracer=(opt) - if opt - Tracer.set_get_line_procs(@irb_path) { - |line_no, *rests| - @io.line(line_no) - } - elsif !opt && @use_tracer - Tracer.off - end - @use_tracer=opt - end - end - - class WorkSpace - alias __evaluate__ evaluate - # Evaluate the context of this workspace and use the Tracer library to - # output the exact lines of code are being executed in chronological order. - # - # See +lib/tracer.rb+ for more information. - def evaluate(context, statements, file = nil, line = nil) - if context.use_tracer? && file != nil && line != nil - Tracer.on - begin - __evaluate__(statements, file, line) - ensure - Tracer.off - end - else - __evaluate__(statements, file || __FILE__, line || __LINE__) - end - end - end - - IRB.initialize_tracer -end diff --git a/lib/irb/ext/use-loader.rb b/lib/irb/ext/use-loader.rb deleted file mode 100644 index d0b8c2d4f487c8..00000000000000 --- a/lib/irb/ext/use-loader.rb +++ /dev/null @@ -1,69 +0,0 @@ -# frozen_string_literal: false -# -# use-loader.rb - -# by Keiju ISHITSUKA(keiju@ruby-lang.org) -# - -require_relative "../cmd/load" -require_relative "loader" - -class Object - alias __original__load__IRB_use_loader__ load - alias __original__require__IRB_use_loader__ require -end - -module IRB - module ExtendCommandBundle - remove_method :irb_load if method_defined?(:irb_load) - # Loads the given file similarly to Kernel#load, see IrbLoader#irb_load - def irb_load(*opts, &b) - ExtendCommand::Load.execute(irb_context, *opts, &b) - end - remove_method :irb_require if method_defined?(:irb_require) - # Loads the given file similarly to Kernel#require - def irb_require(*opts, &b) - ExtendCommand::Require.execute(irb_context, *opts, &b) - end - end - - class Context - - IRB.conf[:USE_LOADER] = false - - # Returns whether +irb+'s own file reader method is used by - # +load+/+require+ or not. - # - # This mode is globally affected (irb-wide). - def use_loader - IRB.conf[:USE_LOADER] - end - - alias use_loader? use_loader - - remove_method :use_loader= if method_defined?(:use_loader=) - # Sets IRB.conf[:USE_LOADER] - # - # See #use_loader for more information. - def use_loader=(opt) - - if IRB.conf[:USE_LOADER] != opt - IRB.conf[:USE_LOADER] = opt - if opt - if !$".include?("irb/cmd/load") - end - (class<<@workspace.main;self;end).instance_eval { - alias_method :load, :irb_load - alias_method :require, :irb_require - } - else - (class<<@workspace.main;self;end).instance_eval { - alias_method :load, :__original__load__IRB_use_loader__ - alias_method :require, :__original__require__IRB_use_loader__ - } - end - end - print "Switch to load/require#{unless use_loader; ' non';end} trace mode.\n" if verbose? - opt - end - end -end diff --git a/lib/irb/ext/workspaces.rb b/lib/irb/ext/workspaces.rb deleted file mode 100644 index 9defc3e17bc530..00000000000000 --- a/lib/irb/ext/workspaces.rb +++ /dev/null @@ -1,60 +0,0 @@ -# frozen_string_literal: false -# -# push-ws.rb - -# by Keiju ISHITSUKA(keiju@ruby-lang.org) -# - -module IRB # :nodoc: - class Context - - # Size of the current WorkSpace stack - def irb_level - workspace_stack.size - end - - # WorkSpaces in the current stack - def workspaces - if defined? @workspaces - @workspaces - else - @workspaces = [] - end - end - - # Creates a new workspace with the given object or binding, and appends it - # onto the current #workspaces stack. - # - # See IRB::Context#change_workspace and IRB::WorkSpace.new for more - # information. - def push_workspace(*_main) - if _main.empty? - if workspaces.empty? - print "No other workspace\n" - return nil - end - ws = workspaces.pop - workspaces.push @workspace - @workspace = ws - return workspaces - end - - workspaces.push @workspace - @workspace = WorkSpace.new(@workspace.binding, _main[0]) - if !(class<IRB.CurrentContext.exit. - def irb_exit(ret = 0) - irb_context.exit(ret) - end - - # Displays current configuration. - # - # Modifying the configuration is achieved by sending a message to IRB.conf. - def irb_context - IRB.CurrentContext - end - - @ALIASES = [ - [:context, :irb_context, NO_OVERRIDE], - [:conf, :irb_context, NO_OVERRIDE], - [:irb_quit, :irb_exit, OVERRIDE_PRIVATE_ONLY], - [:exit, :irb_exit, OVERRIDE_PRIVATE_ONLY], - [:quit, :irb_exit, OVERRIDE_PRIVATE_ONLY], - ] - - - @EXTEND_COMMANDS = [ - [ - :irb_current_working_workspace, :CurrentWorkingWorkspace, "cmd/chws", - [:cwws, NO_OVERRIDE], - [:pwws, NO_OVERRIDE], - [:irb_print_working_workspace, OVERRIDE_ALL], - [:irb_cwws, OVERRIDE_ALL], - [:irb_pwws, OVERRIDE_ALL], - [:irb_current_working_binding, OVERRIDE_ALL], - [:irb_print_working_binding, OVERRIDE_ALL], - [:irb_cwb, OVERRIDE_ALL], - [:irb_pwb, OVERRIDE_ALL], - ], - [ - :irb_change_workspace, :ChangeWorkspace, "cmd/chws", - [:chws, NO_OVERRIDE], - [:cws, NO_OVERRIDE], - [:irb_chws, OVERRIDE_ALL], - [:irb_cws, OVERRIDE_ALL], - [:irb_change_binding, OVERRIDE_ALL], - [:irb_cb, OVERRIDE_ALL], - [:cb, NO_OVERRIDE], - ], - - [ - :irb_workspaces, :Workspaces, "cmd/pushws", - [:workspaces, NO_OVERRIDE], - [:irb_bindings, OVERRIDE_ALL], - [:bindings, NO_OVERRIDE], - ], - [ - :irb_push_workspace, :PushWorkspace, "cmd/pushws", - [:pushws, NO_OVERRIDE], - [:irb_pushws, OVERRIDE_ALL], - [:irb_push_binding, OVERRIDE_ALL], - [:irb_pushb, OVERRIDE_ALL], - [:pushb, NO_OVERRIDE], - ], - [ - :irb_pop_workspace, :PopWorkspace, "cmd/pushws", - [:popws, NO_OVERRIDE], - [:irb_popws, OVERRIDE_ALL], - [:irb_pop_binding, OVERRIDE_ALL], - [:irb_popb, OVERRIDE_ALL], - [:popb, NO_OVERRIDE], - ], - - [ - :irb_load, :Load, "cmd/load"], - [ - :irb_require, :Require, "cmd/load"], - [ - :irb_source, :Source, "cmd/load", - [:source, NO_OVERRIDE], - ], - - [ - :irb, :IrbCommand, "cmd/subirb"], - [ - :irb_jobs, :Jobs, "cmd/subirb", - [:jobs, NO_OVERRIDE], - ], - [ - :irb_fg, :Foreground, "cmd/subirb", - [:fg, NO_OVERRIDE], - ], - [ - :irb_kill, :Kill, "cmd/subirb", - [:kill, OVERRIDE_PRIVATE_ONLY], - ], - - [ - :irb_debug, :Debug, "cmd/debug", - [:debug, NO_OVERRIDE], - ], - [ - :irb_edit, :Edit, "cmd/edit", - [:edit, NO_OVERRIDE], - ], - [ - :irb_break, :Break, "cmd/break", - ], - [ - :irb_catch, :Catch, "cmd/catch", - ], - [ - :irb_next, :Next, "cmd/next" - ], - [ - :irb_delete, :Delete, "cmd/delete", - [:delete, NO_OVERRIDE], - ], - [ - :irb_step, :Step, "cmd/step", - [:step, NO_OVERRIDE], - ], - [ - :irb_continue, :Continue, "cmd/continue", - [:continue, NO_OVERRIDE], - ], - [ - :irb_finish, :Finish, "cmd/finish", - [:finish, NO_OVERRIDE], - ], - [ - :irb_backtrace, :Backtrace, "cmd/backtrace", - [:backtrace, NO_OVERRIDE], - [:bt, NO_OVERRIDE], - ], - [ - :irb_debug_info, :Info, "cmd/info", - [:info, NO_OVERRIDE], - ], - - [ - :irb_help, :Help, "cmd/help", - [:help, NO_OVERRIDE], - ], - - [ - :irb_show_doc, :ShowDoc, "cmd/show_doc", - [:show_doc, NO_OVERRIDE], - ], - - [ - :irb_info, :IrbInfo, "cmd/irb_info" - ], - - [ - :irb_ls, :Ls, "cmd/ls", - [:ls, NO_OVERRIDE], - ], - - [ - :irb_measure, :Measure, "cmd/measure", - [:measure, NO_OVERRIDE], - ], - - [ - :irb_show_source, :ShowSource, "cmd/show_source", - [:show_source, NO_OVERRIDE], - ], - - [ - :irb_whereami, :Whereami, "cmd/whereami", - [:whereami, NO_OVERRIDE], - ], - [ - :irb_show_cmds, :ShowCmds, "cmd/show_cmds", - [:show_cmds, NO_OVERRIDE], - ] - ] - - - @@commands = [] - - def self.all_commands_info - return @@commands unless @@commands.empty? - user_aliases = IRB.CurrentContext.command_aliases.each_with_object({}) do |(alias_name, target), result| - result[target] ||= [] - result[target] << alias_name - end - - @EXTEND_COMMANDS.each do |cmd_name, cmd_class, load_file, *aliases| - if !defined?(ExtendCommand) || !ExtendCommand.const_defined?(cmd_class, false) - require_relative load_file - end - - klass = ExtendCommand.const_get(cmd_class, false) - aliases = aliases.map { |a| a.first } - - if additional_aliases = user_aliases[cmd_name] - aliases += additional_aliases - end - - display_name = aliases.shift || cmd_name - @@commands << { display_name: display_name, description: klass.description, category: klass.category } - end - - @@commands - end - - # Convert a command name to its implementation class if such command exists - def self.load_command(command) - command = command.to_sym - @EXTEND_COMMANDS.each do |cmd_name, cmd_class, load_file, *aliases| - next if cmd_name != command && aliases.all? { |alias_name, _| alias_name != command } - - if !defined?(ExtendCommand) || !ExtendCommand.const_defined?(cmd_class, false) - require_relative load_file - end - return ExtendCommand.const_get(cmd_class, false) - end - nil - end - - # Installs the default irb commands. - def self.install_extend_commands - for args in @EXTEND_COMMANDS - def_extend_command(*args) - end - end - - # Evaluate the given +cmd_name+ on the given +cmd_class+ Class. - # - # Will also define any given +aliases+ for the method. - # - # The optional +load_file+ parameter will be required within the method - # definition. - def self.def_extend_command(cmd_name, cmd_class, load_file, *aliases) - case cmd_class - when Symbol - cmd_class = cmd_class.id2name - when String - when Class - cmd_class = cmd_class.name - end - - line = __LINE__; eval %[ - def #{cmd_name}(*opts, **kwargs, &b) - Kernel.require_relative "#{load_file}" - ::IRB::ExtendCommand::#{cmd_class}.execute(irb_context, *opts, **kwargs, &b) - end - ], nil, __FILE__, line - - for ali, flag in aliases - @ALIASES.push [ali, cmd_name, flag] - end - end - - # Installs alias methods for the default irb commands, see - # ::install_extend_commands. - def install_alias_method(to, from, override = NO_OVERRIDE) - to = to.id2name unless to.kind_of?(String) - from = from.id2name unless from.kind_of?(String) - - if override == OVERRIDE_ALL or - (override == OVERRIDE_PRIVATE_ONLY) && !respond_to?(to) or - (override == NO_OVERRIDE) && !respond_to?(to, true) - target = self - (class << self; self; end).instance_eval{ - if target.respond_to?(to, true) && - !target.respond_to?(EXCB.irb_original_method_name(to), true) - alias_method(EXCB.irb_original_method_name(to), to) - end - alias_method to, from - } - else - Kernel.warn "irb: warn: can't alias #{to} from #{from}.\n" - end - end - - def self.irb_original_method_name(method_name) # :nodoc: - "irb_" + method_name + "_org" - end - - # Installs alias methods for the default irb commands on the given object - # using #install_alias_method. - def self.extend_object(obj) - unless (class << obj; ancestors; end).include?(EXCB) - super - for ali, com, flg in @ALIASES - obj.install_alias_method(ali, com, flg) - end - end - end - - install_extend_commands - end - - # Extends methods for the Context module - module ContextExtender - CE = ContextExtender # :nodoc: - - @EXTEND_COMMANDS = [ - [:eval_history=, "ext/eval_history.rb"], - [:use_tracer=, "ext/tracer.rb"], - [:use_loader=, "ext/use-loader.rb"], - ] - - # Installs the default context extensions as irb commands: - # - # Context#eval_history=:: +irb/ext/history.rb+ - # Context#use_tracer=:: +irb/ext/tracer.rb+ - # Context#use_loader=:: +irb/ext/use-loader.rb+ - def self.install_extend_commands - for args in @EXTEND_COMMANDS - def_extend_command(*args) - end - end - - # Evaluate the given +command+ from the given +load_file+ on the Context - # module. - # - # Will also define any given +aliases+ for the method. - def self.def_extend_command(cmd_name, load_file, *aliases) - line = __LINE__; Context.module_eval %[ - def #{cmd_name}(*opts, &b) - Context.module_eval {remove_method(:#{cmd_name})} - require_relative "#{load_file}" - __send__ :#{cmd_name}, *opts, &b - end - for ali in aliases - alias_method ali, cmd_name - end - ], __FILE__, line - end - - CE.install_extend_commands - end -end diff --git a/lib/irb/frame.rb b/lib/irb/frame.rb deleted file mode 100644 index 14768bd8f6bba5..00000000000000 --- a/lib/irb/frame.rb +++ /dev/null @@ -1,80 +0,0 @@ -# frozen_string_literal: false -# -# frame.rb - -# by Keiju ISHITSUKA(Nihon Rational Software Co.,Ltd) -# - -module IRB - class Frame - class FrameOverflow < StandardError - def initialize - super("frame overflow") - end - end - class FrameUnderflow < StandardError - def initialize - super("frame underflow") - end - end - - # Default number of stack frames - INIT_STACK_TIMES = 3 - # Default number of frames offset - CALL_STACK_OFFSET = 3 - - # Creates a new stack frame - def initialize - @frames = [TOPLEVEL_BINDING] * INIT_STACK_TIMES - end - - # Used by Kernel#set_trace_func to register each event in the call stack - def trace_func(event, file, line, id, binding) - case event - when 'call', 'class' - @frames.push binding - when 'return', 'end' - @frames.pop - end - end - - # Returns the +n+ number of frames on the call stack from the last frame - # initialized. - # - # Raises FrameUnderflow if there are no frames in the given stack range. - def top(n = 0) - bind = @frames[-(n + CALL_STACK_OFFSET)] - fail FrameUnderflow unless bind - bind - end - - # Returns the +n+ number of frames on the call stack from the first frame - # initialized. - # - # Raises FrameOverflow if there are no frames in the given stack range. - def bottom(n = 0) - bind = @frames[n] - fail FrameOverflow unless bind - bind - end - - # Convenience method for Frame#bottom - def Frame.bottom(n = 0) - @backtrace.bottom(n) - end - - # Convenience method for Frame#top - def Frame.top(n = 0) - @backtrace.top(n) - end - - # Returns the binding context of the caller from the last frame initialized - def Frame.sender - eval "self", @backtrace.top - end - - @backtrace = Frame.new - set_trace_func proc{|event, file, line, id, binding, klass| - @backtrace.trace_func(event, file, line, id, binding) - } - end -end diff --git a/lib/irb/help.rb b/lib/irb/help.rb deleted file mode 100644 index ca12810de1f4f2..00000000000000 --- a/lib/irb/help.rb +++ /dev/null @@ -1,28 +0,0 @@ -# frozen_string_literal: false -# -# irb/help.rb - print usage module -# by Keiju ISHITSUKA(keiju@ishitsuka.com) -# - -module IRB - # Outputs the irb help message, see IRB@Command+line+options. - def IRB.print_usage - lc = IRB.conf[:LC_MESSAGES] - path = lc.find("irb/help-message") - space_line = false - File.open(path){|f| - f.each_line do |l| - if /^\s*$/ =~ l - lc.puts l unless space_line - space_line = true - next - end - space_line = false - - l.sub!(/#.*$/, "") - next if /^\s*$/ =~ l - lc.puts l - end - } - end -end diff --git a/lib/irb/history.rb b/lib/irb/history.rb deleted file mode 100644 index ae924d152b096e..00000000000000 --- a/lib/irb/history.rb +++ /dev/null @@ -1,74 +0,0 @@ -module IRB - module HistorySavingAbility # :nodoc: - def support_history_saving? - true - end - - def reset_history_counter - @loaded_history_lines = self.class::HISTORY.size if defined? @loaded_history_lines - end - - def load_history - history = self.class::HISTORY - if history_file = IRB.conf[:HISTORY_FILE] - history_file = File.expand_path(history_file) - end - history_file = IRB.rc_file("_history") unless history_file - if File.exist?(history_file) - File.open(history_file, "r:#{IRB.conf[:LC_MESSAGES].encoding}") do |f| - f.each { |l| - l = l.chomp - if self.class == RelineInputMethod and history.last&.end_with?("\\") - history.last.delete_suffix!("\\") - history.last << "\n" << l - else - history << l - end - } - end - @loaded_history_lines = history.size - @loaded_history_mtime = File.mtime(history_file) - end - end - - def save_history - history = self.class::HISTORY - if num = IRB.conf[:SAVE_HISTORY] and (num = num.to_i) != 0 - if history_file = IRB.conf[:HISTORY_FILE] - history_file = File.expand_path(history_file) - end - history_file = IRB.rc_file("_history") unless history_file - - # Change the permission of a file that already exists[BUG #7694] - begin - if File.stat(history_file).mode & 066 != 0 - File.chmod(0600, history_file) - end - rescue Errno::ENOENT - rescue Errno::EPERM - return - rescue - raise - end - - if File.exist?(history_file) && - File.mtime(history_file) != @loaded_history_mtime - history = history[@loaded_history_lines..-1] if @loaded_history_lines - append_history = true - end - - File.open(history_file, (append_history ? 'a' : 'w'), 0o600, encoding: IRB.conf[:LC_MESSAGES]&.encoding) do |f| - hist = history.map{ |l| l.split("\n").join("\\\n") } - unless append_history - begin - hist = hist.last(num) if hist.size > num and num > 0 - rescue RangeError # bignum too big to convert into `long' - # Do nothing because the bignum should be treated as inifinity - end - end - f.puts(hist) - end - end - end - end -end diff --git a/lib/irb/init.rb b/lib/irb/init.rb deleted file mode 100644 index d1097b573854ef..00000000000000 --- a/lib/irb/init.rb +++ /dev/null @@ -1,436 +0,0 @@ -# frozen_string_literal: false -# -# irb/init.rb - irb initialize module -# by Keiju ISHITSUKA(keiju@ruby-lang.org) -# - -module IRB # :nodoc: - - # initialize config - def IRB.setup(ap_path, argv: ::ARGV) - IRB.init_config(ap_path) - IRB.init_error - IRB.parse_opts(argv: argv) - IRB.run_config - IRB.load_modules - - unless @CONF[:PROMPT][@CONF[:PROMPT_MODE]] - fail UndefinedPromptMode, @CONF[:PROMPT_MODE] - end - end - - # @CONF default setting - def IRB.init_config(ap_path) - # class instance variables - @TRACER_INITIALIZED = false - - # default configurations - unless ap_path and @CONF[:AP_NAME] - ap_path = File.join(File.dirname(File.dirname(__FILE__)), "irb.rb") - end - @CONF[:AP_NAME] = File::basename(ap_path, ".rb") - - @CONF[:IRB_NAME] = "irb" - @CONF[:IRB_LIB_PATH] = File.dirname(__FILE__) - - @CONF[:RC] = true - @CONF[:LOAD_MODULES] = [] - @CONF[:IRB_RC] = nil - - @CONF[:USE_SINGLELINE] = false unless defined?(ReadlineInputMethod) - @CONF[:USE_COLORIZE] = (nc = ENV['NO_COLOR']).nil? || nc.empty? - @CONF[:USE_AUTOCOMPLETE] = ENV.fetch("IRB_USE_AUTOCOMPLETE", "true") != "false" - @CONF[:INSPECT_MODE] = true - @CONF[:USE_TRACER] = false - @CONF[:USE_LOADER] = false - @CONF[:IGNORE_SIGINT] = true - @CONF[:IGNORE_EOF] = false - @CONF[:EXTRA_DOC_DIRS] = [] - @CONF[:ECHO] = nil - @CONF[:ECHO_ON_ASSIGNMENT] = nil - @CONF[:VERBOSE] = nil - - @CONF[:EVAL_HISTORY] = nil - @CONF[:SAVE_HISTORY] = 1000 - - @CONF[:BACK_TRACE_LIMIT] = 16 - - @CONF[:PROMPT] = { - :NULL => { - :PROMPT_I => nil, - :PROMPT_S => nil, - :PROMPT_C => nil, - :RETURN => "%s\n" - }, - :DEFAULT => { - :PROMPT_I => "%N(%m):%03n> ", - :PROMPT_S => "%N(%m):%03n%l ", - :PROMPT_C => "%N(%m):%03n* ", - :RETURN => "=> %s\n" - }, - :CLASSIC => { - :PROMPT_I => "%N(%m):%03n:%i> ", - :PROMPT_S => "%N(%m):%03n:%i%l ", - :PROMPT_C => "%N(%m):%03n:%i* ", - :RETURN => "%s\n" - }, - :SIMPLE => { - :PROMPT_I => ">> ", - :PROMPT_S => "%l> ", - :PROMPT_C => "?> ", - :RETURN => "=> %s\n" - }, - :INF_RUBY => { - :PROMPT_I => "%N(%m):%03n> ", - :PROMPT_S => nil, - :PROMPT_C => nil, - :RETURN => "%s\n", - :AUTO_INDENT => true - }, - :XMP => { - :PROMPT_I => nil, - :PROMPT_S => nil, - :PROMPT_C => nil, - :RETURN => " ==>%s\n" - } - } - - @CONF[:PROMPT_MODE] = (STDIN.tty? ? :DEFAULT : :NULL) - @CONF[:AUTO_INDENT] = true - - @CONF[:CONTEXT_MODE] = 4 # use a copy of TOPLEVEL_BINDING - @CONF[:SINGLE_IRB] = false - - @CONF[:MEASURE] = false - @CONF[:MEASURE_PROC] = {} - @CONF[:MEASURE_PROC][:TIME] = proc { |context, code, line_no, &block| - time = Time.now - result = block.() - now = Time.now - puts 'processing time: %fs' % (now - time) if IRB.conf[:MEASURE] - result - } - # arg can be either a symbol for the mode (:cpu, :wall, ..) or a hash for - # a more complete configuration. - # See https://github.com/tmm1/stackprof#all-options. - @CONF[:MEASURE_PROC][:STACKPROF] = proc { |context, code, line_no, arg, &block| - return block.() unless IRB.conf[:MEASURE] - success = false - begin - require 'stackprof' - success = true - rescue LoadError - puts 'Please run "gem install stackprof" before measuring by StackProf.' - end - if success - result = nil - arg = { mode: arg || :cpu } unless arg.is_a?(Hash) - stackprof_result = StackProf.run(**arg) do - result = block.() - end - case stackprof_result - when File - puts "StackProf report saved to #{stackprof_result.path}" - when Hash - StackProf::Report.new(stackprof_result).print_text - else - puts "Stackprof ran with #{arg.inspect}" - end - result - else - block.() - end - } - @CONF[:MEASURE_CALLBACKS] = [] - - @CONF[:LC_MESSAGES] = Locale.new - - @CONF[:AT_EXIT] = [] - - @CONF[:COMMAND_ALIASES] = { - # Symbol aliases - :'$' => :show_source, - :'@' => :whereami, - # Keyword aliases - :break => :irb_break, - :catch => :irb_catch, - :next => :irb_next, - } - end - - def IRB.set_measure_callback(type = nil, arg = nil, &block) - added = nil - if type - type_sym = type.upcase.to_sym - if IRB.conf[:MEASURE_PROC][type_sym] - added = [type_sym, IRB.conf[:MEASURE_PROC][type_sym], arg] - end - elsif IRB.conf[:MEASURE_PROC][:CUSTOM] - added = [:CUSTOM, IRB.conf[:MEASURE_PROC][:CUSTOM], arg] - elsif block_given? - added = [:BLOCK, block, arg] - found = IRB.conf[:MEASURE_CALLBACKS].find{ |m| m[0] == added[0] && m[2] == added[2] } - if found - found[1] = block - return added - else - IRB.conf[:MEASURE_CALLBACKS] << added - return added - end - else - added = [:TIME, IRB.conf[:MEASURE_PROC][:TIME], arg] - end - if added - found = IRB.conf[:MEASURE_CALLBACKS].find{ |m| m[0] == added[0] && m[2] == added[2] } - if found - # already added - nil - else - IRB.conf[:MEASURE_CALLBACKS] << added if added - added - end - else - nil - end - end - - def IRB.unset_measure_callback(type = nil) - if type.nil? - IRB.conf[:MEASURE_CALLBACKS].clear - else - type_sym = type.upcase.to_sym - IRB.conf[:MEASURE_CALLBACKS].reject!{ |t, | t == type_sym } - end - end - - def IRB.init_error - @CONF[:LC_MESSAGES].load("irb/error.rb") - end - - # option analyzing - def IRB.parse_opts(argv: ::ARGV) - load_path = [] - while opt = argv.shift - case opt - when "-f" - @CONF[:RC] = false - when "-d" - $DEBUG = true - $VERBOSE = true - when "-w" - Warning[:deprecated] = $VERBOSE = true - when /^-W(.+)?/ - opt = $1 || argv.shift - case opt - when "0" - $VERBOSE = nil - when "1" - $VERBOSE = false - else - Warning[:deprecated] = $VERBOSE = true - end - when /^-r(.+)?/ - opt = $1 || argv.shift - @CONF[:LOAD_MODULES].push opt if opt - when /^-I(.+)?/ - opt = $1 || argv.shift - load_path.concat(opt.split(File::PATH_SEPARATOR)) if opt - when '-U' - set_encoding("UTF-8", "UTF-8") - when /^-E(.+)?/, /^--encoding(?:=(.+))?/ - opt = $1 || argv.shift - set_encoding(*opt.split(':', 2)) - when "--inspect" - if /^-/ !~ argv.first - @CONF[:INSPECT_MODE] = argv.shift - else - @CONF[:INSPECT_MODE] = true - end - when "--noinspect" - @CONF[:INSPECT_MODE] = false - when "--singleline", "--readline", "--legacy" - @CONF[:USE_SINGLELINE] = true - when "--nosingleline", "--noreadline" - @CONF[:USE_SINGLELINE] = false - when "--multiline", "--reidline" - if opt == "--reidline" - warn <<~MSG.strip - --reidline is deprecated, please use --multiline instead. - MSG - end - - @CONF[:USE_MULTILINE] = true - when "--nomultiline", "--noreidline" - if opt == "--noreidline" - warn <<~MSG.strip - --noreidline is deprecated, please use --nomultiline instead. - MSG - end - - @CONF[:USE_MULTILINE] = false - when /^--extra-doc-dir(?:=(.+))?/ - opt = $1 || argv.shift - @CONF[:EXTRA_DOC_DIRS] << opt - when "--echo" - @CONF[:ECHO] = true - when "--noecho" - @CONF[:ECHO] = false - when "--echo-on-assignment" - @CONF[:ECHO_ON_ASSIGNMENT] = true - when "--noecho-on-assignment" - @CONF[:ECHO_ON_ASSIGNMENT] = false - when "--truncate-echo-on-assignment" - @CONF[:ECHO_ON_ASSIGNMENT] = :truncate - when "--verbose" - @CONF[:VERBOSE] = true - when "--noverbose" - @CONF[:VERBOSE] = false - when "--colorize" - @CONF[:USE_COLORIZE] = true - when "--nocolorize" - @CONF[:USE_COLORIZE] = false - when "--autocomplete" - @CONF[:USE_AUTOCOMPLETE] = true - when "--noautocomplete" - @CONF[:USE_AUTOCOMPLETE] = false - when /^--prompt-mode(?:=(.+))?/, /^--prompt(?:=(.+))?/ - opt = $1 || argv.shift - prompt_mode = opt.upcase.tr("-", "_").intern - @CONF[:PROMPT_MODE] = prompt_mode - when "--noprompt" - @CONF[:PROMPT_MODE] = :NULL - when "--script" - noscript = false - when "--noscript" - noscript = true - when "--inf-ruby-mode" - @CONF[:PROMPT_MODE] = :INF_RUBY - when "--sample-book-mode", "--simple-prompt" - @CONF[:PROMPT_MODE] = :SIMPLE - when "--tracer" - @CONF[:USE_TRACER] = true - when /^--back-trace-limit(?:=(.+))?/ - @CONF[:BACK_TRACE_LIMIT] = ($1 || argv.shift).to_i - when /^--context-mode(?:=(.+))?/ - @CONF[:CONTEXT_MODE] = ($1 || argv.shift).to_i - when "--single-irb" - @CONF[:SINGLE_IRB] = true - when "-v", "--version" - print IRB.version, "\n" - exit 0 - when "-h", "--help" - require_relative "help" - IRB.print_usage - exit 0 - when "--" - if !noscript && (opt = argv.shift) - @CONF[:SCRIPT] = opt - $0 = opt - end - break - when /^-./ - fail UnrecognizedSwitch, opt - else - if noscript - argv.unshift(opt) - else - @CONF[:SCRIPT] = opt - $0 = opt - end - break - end - end - - load_path.collect! do |path| - /\A\.\// =~ path ? path : File.expand_path(path) - end - $LOAD_PATH.unshift(*load_path) - end - - # running config - def IRB.run_config - if @CONF[:RC] - begin - load rc_file - rescue LoadError, Errno::ENOENT - rescue # StandardError, ScriptError - print "load error: #{rc_file}\n" - print $!.class, ": ", $!, "\n" - for err in $@[0, $@.size - 2] - print "\t", err, "\n" - end - end - end - end - - IRBRC_EXT = "rc" - def IRB.rc_file(ext = IRBRC_EXT) - if !@CONF[:RC_NAME_GENERATOR] - rc_file_generators do |rcgen| - @CONF[:RC_NAME_GENERATOR] ||= rcgen - if File.exist?(rcgen.call(IRBRC_EXT)) - @CONF[:RC_NAME_GENERATOR] = rcgen - break - end - end - end - case rc_file = @CONF[:RC_NAME_GENERATOR].call(ext) - when String - return rc_file - else - fail IllegalRCNameGenerator - end - end - - # enumerate possible rc-file base name generators - def IRB.rc_file_generators - if irbrc = ENV["IRBRC"] - yield proc{|rc| rc == "rc" ? irbrc : irbrc+rc} - end - if xdg_config_home = ENV["XDG_CONFIG_HOME"] - irb_home = File.join(xdg_config_home, "irb") - if File.directory?(irb_home) - yield proc{|rc| irb_home + "/irb#{rc}"} - end - end - if home = ENV["HOME"] - yield proc{|rc| home+"/.irb#{rc}"} - yield proc{|rc| home+"/.config/irb/irb#{rc}"} - end - current_dir = Dir.pwd - yield proc{|rc| current_dir+"/.irb#{rc}"} - yield proc{|rc| current_dir+"/irb#{rc.sub(/\A_?/, '.')}"} - yield proc{|rc| current_dir+"/_irb#{rc}"} - yield proc{|rc| current_dir+"/$irb#{rc}"} - end - - # loading modules - def IRB.load_modules - for m in @CONF[:LOAD_MODULES] - begin - require m - rescue LoadError => err - warn "#{err.class}: #{err}", uplevel: 0 - end - end - end - - class << IRB - private - def set_encoding(extern, intern = nil, override: true) - verbose, $VERBOSE = $VERBOSE, nil - Encoding.default_external = extern unless extern.nil? || extern.empty? - Encoding.default_internal = intern unless intern.nil? || intern.empty? - [$stdin, $stdout, $stderr].each do |io| - io.set_encoding(extern, intern) - end - if override - @CONF[:LC_MESSAGES].instance_variable_set(:@override_encoding, extern) - else - @CONF[:LC_MESSAGES].instance_variable_set(:@encoding, extern) - end - ensure - $VERBOSE = verbose - end - end -end diff --git a/lib/irb/input-method.rb b/lib/irb/input-method.rb deleted file mode 100644 index bd7d4fede4334d..00000000000000 --- a/lib/irb/input-method.rb +++ /dev/null @@ -1,412 +0,0 @@ -# frozen_string_literal: false -# -# irb/input-method.rb - input methods used irb -# by Keiju ISHITSUKA(keiju@ruby-lang.org) -# - -require_relative 'completion' -require_relative "history" -require 'io/console' -require 'reline' - -module IRB - class InputMethod - # The irb prompt associated with this input method - attr_accessor :prompt - - # Reads the next line from this input method. - # - # See IO#gets for more information. - def gets - fail NotImplementedError, "gets" - end - public :gets - - def winsize - if instance_variable_defined?(:@stdout) && @stdout.tty? - @stdout.winsize - else - [24, 80] - end - end - - # Whether this input method is still readable when there is no more data to - # read. - # - # See IO#eof for more information. - def readable_after_eof? - false - end - - def support_history_saving? - false - end - - # For debug message - def inspect - 'Abstract InputMethod' - end - end - - class StdioInputMethod < InputMethod - # Creates a new input method object - def initialize - @line_no = 0 - @line = [] - @stdin = IO.open(STDIN.to_i, :external_encoding => IRB.conf[:LC_MESSAGES].encoding, :internal_encoding => "-") - @stdout = IO.open(STDOUT.to_i, 'w', :external_encoding => IRB.conf[:LC_MESSAGES].encoding, :internal_encoding => "-") - end - - # Reads the next line from this input method. - # - # See IO#gets for more information. - def gets - print @prompt - line = @stdin.gets - @line[@line_no += 1] = line - end - - # Whether the end of this input method has been reached, returns +true+ if - # there is no more data to read. - # - # See IO#eof? for more information. - def eof? - if @stdin.wait_readable(0.00001) - c = @stdin.getc - result = c.nil? ? true : false - @stdin.ungetc(c) unless c.nil? - result - else # buffer is empty - false - end - end - - # Whether this input method is still readable when there is no more data to - # read. - # - # See IO#eof for more information. - def readable_after_eof? - true - end - - # Returns the current line number for #io. - # - # #line counts the number of times #gets is called. - # - # See IO#lineno for more information. - def line(line_no) - @line[line_no] - end - - # The external encoding for standard input. - def encoding - @stdin.external_encoding - end - - # For debug message - def inspect - 'StdioInputMethod' - end - end - - # Use a File for IO with irb, see InputMethod - class FileInputMethod < InputMethod - class << self - def open(file, &block) - begin - io = new(file) - block.call(io) - ensure - io&.close - end - end - end - - # Creates a new input method object - def initialize(file) - @io = file.is_a?(IO) ? file : File.open(file) - @external_encoding = @io.external_encoding - end - - # Whether the end of this input method has been reached, returns +true+ if - # there is no more data to read. - # - # See IO#eof? for more information. - def eof? - @io.closed? || @io.eof? - end - - # Reads the next line from this input method. - # - # See IO#gets for more information. - def gets - print @prompt - @io.gets - end - - # The external encoding for standard input. - def encoding - @external_encoding - end - - # For debug message - def inspect - 'FileInputMethod' - end - - def close - @io.close - end - end - - class ReadlineInputMethod < StdioInputMethod - def self.initialize_readline - require "readline" - rescue LoadError - else - include ::Readline - end - - include HistorySavingAbility - - # Creates a new input method object using Readline - def initialize - self.class.initialize_readline - if Readline.respond_to?(:encoding_system_needs) - IRB.__send__(:set_encoding, Readline.encoding_system_needs.name, override: false) - end - - super - - @eof = false - - if Readline.respond_to?("basic_word_break_characters=") - Readline.basic_word_break_characters = IRB::InputCompletor::BASIC_WORD_BREAK_CHARACTERS - end - Readline.completion_append_character = nil - Readline.completion_proc = IRB::InputCompletor::CompletionProc - end - - # Reads the next line from this input method. - # - # See IO#gets for more information. - def gets - Readline.input = @stdin - Readline.output = @stdout - if l = readline(@prompt, false) - HISTORY.push(l) if !l.empty? - @line[@line_no += 1] = l + "\n" - else - @eof = true - l - end - end - - # Whether the end of this input method has been reached, returns +true+ - # if there is no more data to read. - # - # See IO#eof? for more information. - def eof? - @eof - end - - # For debug message - def inspect - readline_impl = (defined?(Reline) && Readline == Reline) ? 'Reline' : 'ext/readline' - str = "ReadlineInputMethod with #{readline_impl} #{Readline::VERSION}" - inputrc_path = File.expand_path(ENV['INPUTRC'] || '~/.inputrc') - str += " and #{inputrc_path}" if File.exist?(inputrc_path) - str - end - end - - class RelineInputMethod < StdioInputMethod - HISTORY = Reline::HISTORY - include HistorySavingAbility - # Creates a new input method object using Reline - def initialize - IRB.__send__(:set_encoding, Reline.encoding_system_needs.name, override: false) - - super - - @eof = false - - Reline.basic_word_break_characters = IRB::InputCompletor::BASIC_WORD_BREAK_CHARACTERS - Reline.completion_append_character = nil - Reline.completer_quote_characters = '' - Reline.completion_proc = IRB::InputCompletor::CompletionProc - Reline.output_modifier_proc = - if IRB.conf[:USE_COLORIZE] - proc do |output, complete: | - next unless IRB::Color.colorable? - lvars = IRB.CurrentContext&.local_variables || [] - IRB::Color.colorize_code(output, complete: complete, local_variables: lvars) - end - else - proc do |output| - Reline::Unicode.escape_for_print(output) - end - end - Reline.dig_perfect_match_proc = IRB::InputCompletor::PerfectMatchedProc - Reline.autocompletion = IRB.conf[:USE_AUTOCOMPLETE] - - if IRB.conf[:USE_AUTOCOMPLETE] - begin - require 'rdoc' - Reline.add_dialog_proc(:show_doc, SHOW_DOC_DIALOG, Reline::DEFAULT_DIALOG_CONTEXT) - rescue LoadError - end - end - end - - def check_termination(&block) - @check_termination_proc = block - end - - def dynamic_prompt(&block) - @prompt_proc = block - end - - def auto_indent(&block) - @auto_indent_proc = block - end - - SHOW_DOC_DIALOG = ->() { - dialog.trap_key = nil - alt_d = [ - [Reline::Key.new(nil, 0xE4, true)], # Normal Alt+d. - [27, 100], # Normal Alt+d when convert-meta isn't used. - [195, 164], # The "ä" that appears when Alt+d is pressed on xterm. - [226, 136, 130] # The "∂" that appears when Alt+d in pressed on iTerm2. - ] - - if just_cursor_moving and completion_journey_data.nil? - return nil - end - cursor_pos_to_render, result, pointer, autocomplete_dialog = context.pop(4) - return nil if result.nil? or pointer.nil? or pointer < 0 - name = result[pointer] - name = IRB::InputCompletor.retrieve_completion_data(name, doc_namespace: true) - - options = {} - options[:extra_doc_dirs] = IRB.conf[:EXTRA_DOC_DIRS] unless IRB.conf[:EXTRA_DOC_DIRS].empty? - driver = RDoc::RI::Driver.new(options) - - if key.match?(dialog.name) - begin - driver.display_names([name]) - rescue RDoc::RI::Driver::NotFoundError - end - end - - begin - name = driver.expand_name(name) - rescue RDoc::RI::Driver::NotFoundError - return nil - rescue - return nil # unknown error - end - doc = nil - used_for_class = false - if not name =~ /#|\./ - found, klasses, includes, extends = driver.classes_and_includes_and_extends_for(name) - if not found.empty? - doc = driver.class_document(name, found, klasses, includes, extends) - used_for_class = true - end - end - unless used_for_class - doc = RDoc::Markup::Document.new - begin - driver.add_method(doc, name) - rescue RDoc::RI::Driver::NotFoundError - doc = nil - rescue - return nil # unknown error - end - end - return nil if doc.nil? - width = 40 - - right_x = cursor_pos_to_render.x + autocomplete_dialog.width - if right_x + width > screen_width - right_width = screen_width - (right_x + 1) - left_x = autocomplete_dialog.column - width - left_x = 0 if left_x < 0 - left_width = width > autocomplete_dialog.column ? autocomplete_dialog.column : width - if right_width.positive? and left_width.positive? - if right_width >= left_width - width = right_width - x = right_x - else - width = left_width - x = left_x - end - elsif right_width.positive? and left_width <= 0 - width = right_width - x = right_x - elsif right_width <= 0 and left_width.positive? - width = left_width - x = left_x - else # Both are negative width. - return nil - end - else - x = right_x - end - formatter = RDoc::Markup::ToAnsi.new - formatter.width = width - dialog.trap_key = alt_d - mod_key = RUBY_PLATFORM.match?(/darwin/) ? "Option" : "Alt" - message = "Press #{mod_key}+d to read the full document" - contents = [message] + doc.accept(formatter).split("\n") - contents = contents.take(preferred_dialog_height) - - y = cursor_pos_to_render.y - Reline::DialogRenderInfo.new(pos: Reline::CursorPos.new(x, y), contents: contents, width: width, bg_color: '49') - } - - # Reads the next line from this input method. - # - # See IO#gets for more information. - def gets - Reline.input = @stdin - Reline.output = @stdout - Reline.prompt_proc = @prompt_proc - Reline.auto_indent_proc = @auto_indent_proc if @auto_indent_proc - if l = Reline.readmultiline(@prompt, false, &@check_termination_proc) - Reline::HISTORY.push(l) if !l.empty? - @line[@line_no += 1] = l + "\n" - else - @eof = true - l - end - end - - # Whether the end of this input method has been reached, returns +true+ - # if there is no more data to read. - # - # See IO#eof? for more information. - def eof? - @eof - end - - # For debug message - def inspect - config = Reline::Config.new - str = "RelineInputMethod with Reline #{Reline::VERSION}" - inputrc_path = File.expand_path(config.inputrc_path) - str += " and #{inputrc_path}" if File.exist?(inputrc_path) - str - end - end - - class ReidlineInputMethod < RelineInputMethod - def initialize - warn <<~MSG.strip - IRB::ReidlineInputMethod is deprecated, please use IRB::RelineInputMethod instead. - MSG - super - end - end -end diff --git a/lib/irb/inspector.rb b/lib/irb/inspector.rb deleted file mode 100644 index ee3b19efdc503d..00000000000000 --- a/lib/irb/inspector.rb +++ /dev/null @@ -1,130 +0,0 @@ -# frozen_string_literal: false -# -# irb/inspector.rb - inspect methods -# by Keiju ISHITSUKA(keiju@ruby-lang.org) -# - -module IRB # :nodoc: - - - # Convenience method to create a new Inspector, using the given +inspect+ - # proc, and optional +init+ proc and passes them to Inspector.new - # - # irb(main):001:0> ins = IRB::Inspector(proc{ |v| "omg! #{v}" }) - # irb(main):001:0> IRB.CurrentContext.inspect_mode = ins # => omg! # - # irb(main):001:0> "what?" #=> omg! what? - # - def IRB::Inspector(inspect, init = nil) - Inspector.new(inspect, init) - end - - # An irb inspector - # - # In order to create your own custom inspector there are two things you - # should be aware of: - # - # Inspector uses #inspect_value, or +inspect_proc+, for output of return values. - # - # This also allows for an optional #init+, or +init_proc+, which is called - # when the inspector is activated. - # - # Knowing this, you can create a rudimentary inspector as follows: - # - # irb(main):001:0> ins = IRB::Inspector.new(proc{ |v| "omg! #{v}" }) - # irb(main):001:0> IRB.CurrentContext.inspect_mode = ins # => omg! # - # irb(main):001:0> "what?" #=> omg! what? - # - class Inspector - KERNEL_INSPECT = Object.instance_method(:inspect) - # Default inspectors available to irb, this includes: - # - # +:pp+:: Using Kernel#pretty_inspect - # +:yaml+:: Using YAML.dump - # +:marshal+:: Using Marshal.dump - INSPECTORS = {} - - # Determines the inspector to use where +inspector+ is one of the keys passed - # during inspector definition. - def self.keys_with_inspector(inspector) - INSPECTORS.select{|k,v| v == inspector}.collect{|k, v| k} - end - - # Example - # - # Inspector.def_inspector(key, init_p=nil){|v| v.inspect} - # Inspector.def_inspector([key1,..], init_p=nil){|v| v.inspect} - # Inspector.def_inspector(key, inspector) - # Inspector.def_inspector([key1,...], inspector) - def self.def_inspector(key, arg=nil, &block) - if block_given? - inspector = IRB::Inspector(block, arg) - else - inspector = arg - end - - case key - when Array - for k in key - def_inspector(k, inspector) - end - when Symbol - INSPECTORS[key] = inspector - INSPECTORS[key.to_s] = inspector - when String - INSPECTORS[key] = inspector - INSPECTORS[key.intern] = inspector - else - INSPECTORS[key] = inspector - end - end - - # Creates a new inspector object, using the given +inspect_proc+ when - # output return values in irb. - def initialize(inspect_proc, init_proc = nil) - @init = init_proc - @inspect = inspect_proc - end - - # Proc to call when the inspector is activated, good for requiring - # dependent libraries. - def init - @init.call if @init - end - - # Proc to call when the input is evaluated and output in irb. - def inspect_value(v) - @inspect.call(v) - rescue => e - puts "An error occurred when inspecting the object: #{e.inspect}" - - begin - puts "Result of Kernel#inspect: #{KERNEL_INSPECT.bind_call(v)}" - '' - rescue => e - puts "An error occurred when running Kernel#inspect: #{e.inspect}" - puts e.backtrace.join("\n") - '' - end - end - end - - Inspector.def_inspector([false, :to_s, :raw]){|v| v.to_s} - Inspector.def_inspector([:p, :inspect]){|v| - Color.colorize_code(v.inspect, colorable: Color.colorable? && Color.inspect_colorable?(v)) - } - Inspector.def_inspector([true, :pp, :pretty_inspect], proc{require_relative "color_printer"}){|v| - IRB::ColorPrinter.pp(v, '').chomp - } - Inspector.def_inspector([:yaml, :YAML], proc{require "yaml"}){|v| - begin - YAML.dump(v) - rescue - puts "(can't dump yaml. use inspect)" - v.inspect - end - } - - Inspector.def_inspector([:marshal, :Marshal, :MARSHAL, Marshal]){|v| - Marshal.dump(v) - } -end diff --git a/lib/irb/irb.gemspec b/lib/irb/irb.gemspec deleted file mode 100644 index a008a39f9d5d81..00000000000000 --- a/lib/irb/irb.gemspec +++ /dev/null @@ -1,46 +0,0 @@ -begin - require_relative "lib/irb/version" -rescue LoadError - # for Ruby core repository - require_relative "version" -end - -Gem::Specification.new do |spec| - spec.name = "irb" - spec.version = IRB::VERSION - spec.authors = ["aycabta", "Keiju ISHITSUKA"] - spec.email = ["aycabta@gmail.com", "keiju@ruby-lang.org"] - - spec.summary = %q{Interactive Ruby command-line tool for REPL (Read Eval Print Loop).} - spec.description = %q{Interactive Ruby command-line tool for REPL (Read Eval Print Loop).} - spec.homepage = "https://github.com/ruby/irb" - spec.licenses = ["Ruby", "BSD-2-Clause"] - - spec.metadata["homepage_uri"] = spec.homepage - spec.metadata["source_code_uri"] = spec.homepage - spec.metadata["documentation_uri"] = spec.homepage - spec.metadata["changelog_uri"] = "#{spec.homepage}/releases" - - spec.files = [ - ".document", - "Gemfile", - "LICENSE.txt", - "README.md", - "Rakefile", - "bin/console", - "bin/setup", - "doc/irb/irb-tools.rd.ja", - "doc/irb/irb.rd.ja", - "exe/irb", - "irb.gemspec", - "man/irb.1", - ] + Dir.glob("lib/**/*") - spec.bindir = "exe" - spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } - spec.require_paths = ["lib"] - - spec.required_ruby_version = Gem::Requirement.new(">= 2.7") - - spec.add_dependency "reline", ">= 0.3.8" - spec.add_dependency "rdoc" -end diff --git a/lib/irb/lc/error.rb b/lib/irb/lc/error.rb deleted file mode 100644 index a5ec15086595d5..00000000000000 --- a/lib/irb/lc/error.rb +++ /dev/null @@ -1,62 +0,0 @@ -# frozen_string_literal: false -# -# irb/lc/error.rb - -# by Keiju ISHITSUKA(keiju@ruby-lang.org) -# - -module IRB - # :stopdoc: - - class UnrecognizedSwitch < StandardError - def initialize(val) - super("Unrecognized switch: #{val}") - end - end - class NotImplementedError < StandardError - def initialize(val) - super("Need to define `#{val}'") - end - end - class CantReturnToNormalMode < StandardError - def initialize - super("Can't return to normal mode.") - end - end - class IllegalParameter < StandardError - def initialize(val) - super("Invalid parameter(#{val}).") - end - end - class IrbAlreadyDead < StandardError - def initialize - super("Irb is already dead.") - end - end - class IrbSwitchedToCurrentThread < StandardError - def initialize - super("Switched to current thread.") - end - end - class NoSuchJob < StandardError - def initialize(val) - super("No such job(#{val}).") - end - end - class CantChangeBinding < StandardError - def initialize(val) - super("Can't change binding to (#{val}).") - end - end - class UndefinedPromptMode < StandardError - def initialize(val) - super("Undefined prompt mode(#{val}).") - end - end - class IllegalRCGenerator < StandardError - def initialize - super("Define illegal RC_NAME_GENERATOR.") - end - end - - # :startdoc: -end diff --git a/lib/irb/lc/help-message b/lib/irb/lc/help-message deleted file mode 100644 index 7e66100be941d8..00000000000000 --- a/lib/irb/lc/help-message +++ /dev/null @@ -1,51 +0,0 @@ -Usage: irb.rb [options] [programfile] [arguments] - -f Don't initialize from configuration file. - -d Set $DEBUG and $VERBOSE to true (same as 'ruby -d'). - -r load-module Require load-module (same as 'ruby -r'). - -I path Specify $LOAD_PATH directory (same as 'ruby -I'). - -U Set external and internal encodings to UTF-8. - -E ex[:in] Set default external (ex) and internal (in) encodings - (same as 'ruby -E'). - -w Suppress warnings (same as 'ruby -w'). - -W[level=2] Set warning level: 0=silence, 1=medium, 2=verbose - (same as 'ruby -W'). - --context-mode n Set n[0-4] to method to create Binding Object, - when new workspace was created. - --extra-doc-dir Add an extra doc dir for the doc dialog. - --echo Show result (default). - --noecho Don't show result. - --echo-on-assignment - Show result on assignment. - --noecho-on-assignment - Don't show result on assignment. - --truncate-echo-on-assignment - Show truncated result on assignment (default). - --inspect Use 'inspect' for output. - --noinspect Don't use 'inspect' for output. - --multiline Use multiline editor module (default). - --nomultiline Don't use multiline editor module. - --singleline Use single line editor module. - --nosingleline Don't use single line editor module (default). - --colorize Use color-highlighting (default). - --nocolorize Don't use color-highlighting. - --autocomplete Use auto-completion (default). - --noautocomplete Don't use auto-completion. - --prompt prompt-mode, --prompt-mode prompt-mode - Set prompt mode. Pre-defined prompt modes are: - 'default', 'classic', 'simple', 'inf-ruby', 'xmp', 'null'. - --inf-ruby-mode Use prompt appropriate for inf-ruby-mode on emacs. - Suppresses --multiline and --singleline. - --sample-book-mode, --simple-prompt - Set prompt mode to 'simple'. - --noprompt Don't output prompt. - --script Script mode (default, treat first argument as script) - --noscript No script mode (leave arguments in argv) - --single-irb Share self with sub-irb. - --tracer Show stack trace for each command. - --back-trace-limit n[=16] - Display backtrace top n and bottom n. - --verbose Show details. - --noverbose Don't show details. - -v, --version Print the version of irb. - -h, --help Print help. - -- Separate options of irb from the list of command-line args. diff --git a/lib/irb/lc/ja/error.rb b/lib/irb/lc/ja/error.rb deleted file mode 100644 index 50d72c4a10eff6..00000000000000 --- a/lib/irb/lc/ja/error.rb +++ /dev/null @@ -1,63 +0,0 @@ -# frozen_string_literal: false -# -# irb/lc/ja/error.rb - -# by Keiju ISHITSUKA(keiju@ruby-lang.org) -# - -module IRB - # :stopdoc: - - class UnrecognizedSwitch < StandardError - def initialize(val) - super("スイッチ(#{val})が分りません") - end - end - class NotImplementedError < StandardError - def initialize(val) - super("`#{val}'の定義が必要です") - end - end - class CantReturnToNormalMode < StandardError - def initialize - super("Normalモードに戻れません.") - end - end - class IllegalParameter < StandardError - def initialize(val) - super("パラメータ(#{val})が間違っています.") - end - end - class IrbAlreadyDead < StandardError - def initialize - super("Irbは既に死んでいます.") - end - end - class IrbSwitchedToCurrentThread < StandardError - def initialize - super("カレントスレッドに切り替わりました.") - end - end - class NoSuchJob < StandardError - def initialize(val) - super("そのようなジョブ(#{val})はありません.") - end - end - class CantChangeBinding < StandardError - def initialize(val) - super("バインディング(#{val})に変更できません.") - end - end - class UndefinedPromptMode < StandardError - def initialize(val) - super("プロンプトモード(#{val})は定義されていません.") - end - end - class IllegalRCGenerator < StandardError - def initialize - super("RC_NAME_GENERATORが正しく定義されていません.") - end - end - - # :startdoc: -end -# vim:fileencoding=utf-8 diff --git a/lib/irb/lc/ja/help-message b/lib/irb/lc/ja/help-message deleted file mode 100644 index 1c15d331ead25a..00000000000000 --- a/lib/irb/lc/ja/help-message +++ /dev/null @@ -1,45 +0,0 @@ -Usage: irb.rb [options] [programfile] [arguments] - -f ~/.irbrc を読み込まない. - -d $DEBUG をtrueにする(ruby -d と同じ) - -r load-module ruby -r と同じ. - -I path $LOAD_PATH に path を追加する. - -U ruby -U と同じ. - -E enc ruby -E と同じ. - -w ruby -w と同じ. - -W[level=2] ruby -W と同じ. - --context-mode n 新しいワークスペースを作成した時に関連する Binding - オブジェクトの作成方法を 0 から 3 のいずれかに設定する. - --echo 実行結果を表示する(デフォルト). - --noecho 実行結果を表示しない. - --inspect 結果出力にinspectを用いる. - --noinspect 結果出力にinspectを用いない. - --multiline マルチラインエディタを利用する. - --nomultiline マルチラインエディタを利用しない. - --singleline シングルラインエディタを利用する. - --nosingleline シングルラインエディタを利用しない. - --colorize 色付けを利用する. - --nocolorize 色付けを利用しない. - --autocomplete オートコンプリートを利用する. - --noautocomplete オートコンプリートを利用しない. - --prompt prompt-mode/--prompt-mode prompt-mode - プロンプトモードを切替えます. 現在定義されているプ - ロンプトモードは, default, simple, xmp, inf-rubyが - 用意されています. - --inf-ruby-mode emacsのinf-ruby-mode用のプロンプト表示を行なう. 特 - に指定がない限り, シングルラインエディタとマルチラ - インエディタは使わなくなる. - --sample-book-mode/--simple-prompt - 非常にシンプルなプロンプトを用いるモードです. - --noprompt プロンプト表示を行なわない. - --single-irb irb 中で self を実行して得られるオブジェクトをサ - ブ irb と共有する. - --tracer コマンド実行時にトレースを行なう. - --back-trace-limit n - バックトレース表示をバックトレースの頭から n, 後ろ - からnだけ行なう. デフォルトは16 - - --verbose 詳細なメッセージを出力する. - --noverbose 詳細なメッセージを出力しない(デフォルト). - -v, --version irbのバージョンを表示する. - -h, --help irb のヘルプを表示する. - -- 以降のコマンドライン引数をオプションとして扱わない. diff --git a/lib/irb/locale.rb b/lib/irb/locale.rb deleted file mode 100644 index f94aa0f40bb9da..00000000000000 --- a/lib/irb/locale.rb +++ /dev/null @@ -1,153 +0,0 @@ -# frozen_string_literal: false -# -# irb/locale.rb - internationalization module -# by Keiju ISHITSUKA(keiju@ruby-lang.org) -# - -module IRB # :nodoc: - class Locale - - LOCALE_NAME_RE = %r[ - (?[[:alpha:]]{2,3}) - (?:_ (?[[:alpha:]]{2,3}) )? - (?:\. (?[^@]+) )? - (?:@ (?.*) )? - ]x - LOCALE_DIR = "/lc/" - - LEGACY_ENCODING_ALIAS_MAP = { - 'ujis' => Encoding::EUC_JP, - 'euc' => Encoding::EUC_JP - } - - @@loaded = [] - - def initialize(locale = nil) - @override_encoding = nil - @lang = @territory = @encoding_name = @modifier = nil - @locale = locale || ENV["IRB_LANG"] || ENV["LC_MESSAGES"] || ENV["LC_ALL"] || ENV["LANG"] || "C" - if m = LOCALE_NAME_RE.match(@locale) - @lang, @territory, @encoding_name, @modifier = m[:language], m[:territory], m[:codeset], m[:modifier] - - if @encoding_name - if @encoding = LEGACY_ENCODING_ALIAS_MAP[@encoding_name] - warn(("%s is obsolete. use %s" % ["#{@lang}_#{@territory}.#{@encoding_name}", "#{@lang}_#{@territory}.#{@encoding.name}"]), uplevel: 1) - else - @encoding = Encoding.find(@encoding_name) rescue nil - end - end - end - @encoding ||= (Encoding.find('locale') rescue Encoding::ASCII_8BIT) - end - - attr_reader :lang, :territory, :modifier - - def encoding - @override_encoding || @encoding - end - - def String(mes) - mes = super(mes) - if encoding - mes.encode(encoding, undef: :replace) - else - mes - end - end - - def format(*opts) - String(super(*opts)) - end - - def gets(*rs) - String(super(*rs)) - end - - def readline(*rs) - String(super(*rs)) - end - - def print(*opts) - ary = opts.collect{|opt| String(opt)} - super(*ary) - end - - def printf(*opts) - s = format(*opts) - print s - end - - def puts(*opts) - ary = opts.collect{|opt| String(opt)} - super(*ary) - end - - def load(file) - found = find(file) - if found - unless @@loaded.include?(found) - @@loaded << found # cache - Kernel.load(found) - end - else - raise LoadError, "No such file to load -- #{file}" - end - end - - def find(file , paths = $:) - dir = File.dirname(file) - dir = "" if dir == "." - base = File.basename(file) - - if dir.start_with?('/') - return each_localized_path(dir, base).find{|full_path| File.readable? full_path} - else - return search_file(paths, dir, base) - end - end - - # @param paths load paths in which IRB find a localized file. - # @param dir directory - # @param file basename to be localized - # - # typically, for the parameters and a in paths, it searches - # /// - def search_file(lib_paths, dir, file) - each_localized_path(dir, file) do |lc_path| - lib_paths.each do |libpath| - full_path = File.join(libpath, lc_path) - return full_path if File.readable?(full_path) - end - redo if defined?(Gem) and Gem.try_activate(lc_path) - end - nil - end - - def each_localized_path(dir, file) - return enum_for(:each_localized_path) unless block_given? - each_sublocale do |lc| - yield lc.nil? ? File.join(dir, LOCALE_DIR, file) : File.join(dir, LOCALE_DIR, lc, file) - end - end - - def each_sublocale - if @lang - if @territory - if @encoding_name - yield "#{@lang}_#{@territory}.#{@encoding_name}@#{@modifier}" if @modifier - yield "#{@lang}_#{@territory}.#{@encoding_name}" - end - yield "#{@lang}_#{@territory}@#{@modifier}" if @modifier - yield "#{@lang}_#{@territory}" - end - if @encoding_name - yield "#{@lang}.#{@encoding_name}@#{@modifier}" if @modifier - yield "#{@lang}.#{@encoding_name}" - end - yield "#{@lang}@#{@modifier}" if @modifier - yield "#{@lang}" - end - yield nil - end - end -end diff --git a/lib/irb/nesting_parser.rb b/lib/irb/nesting_parser.rb deleted file mode 100644 index 3d4db8244451dd..00000000000000 --- a/lib/irb/nesting_parser.rb +++ /dev/null @@ -1,227 +0,0 @@ -# frozen_string_literal: true -module IRB - module NestingParser - IGNORE_TOKENS = %i[on_sp on_ignored_nl on_comment on_embdoc_beg on_embdoc on_embdoc_end] - - # Scan each token and call the given block with array of token and other information for parsing - def self.scan_opens(tokens) - opens = [] - pending_heredocs = [] - first_token_on_line = true - tokens.each do |t| - skip = false - last_tok, state, args = opens.last - case state - when :in_unquoted_symbol - unless IGNORE_TOKENS.include?(t.event) - opens.pop - skip = true - end - when :in_lambda_head - opens.pop if t.event == :on_tlambeg || (t.event == :on_kw && t.tok == 'do') - when :in_method_head - unless IGNORE_TOKENS.include?(t.event) - next_args = [] - body = nil - if args.include?(:receiver) - case t.event - when :on_lparen, :on_ivar, :on_gvar, :on_cvar - # def (receiver). | def @ivar. | def $gvar. | def @@cvar. - next_args << :dot - when :on_kw - case t.tok - when 'self', 'true', 'false', 'nil' - # def self(arg) | def self. - next_args.push(:arg, :dot) - else - # def if(arg) - skip = true - next_args << :arg - end - when :on_op, :on_backtick - # def +(arg) - skip = true - next_args << :arg - when :on_ident, :on_const - # def a(arg) | def a. - next_args.push(:arg, :dot) - end - end - if args.include?(:dot) - # def receiver.name - next_args << :name if t.event == :on_period || (t.event == :on_op && t.tok == '::') - end - if args.include?(:name) - if %i[on_ident on_const on_op on_kw on_backtick].include?(t.event) - # def name(arg) | def receiver.name(arg) - next_args << :arg - skip = true - end - end - if args.include?(:arg) - case t.event - when :on_nl, :on_semicolon - # def recever.f; - body = :normal - when :on_lparen - # def recever.f() - next_args << :eq - else - if t.event == :on_op && t.tok == '=' - # def receiver.f = - body = :oneliner - else - # def recever.f arg - next_args << :arg_without_paren - end - end - end - if args.include?(:eq) - if t.event == :on_op && t.tok == '=' - body = :oneliner - else - body = :normal - end - end - if args.include?(:arg_without_paren) - if %i[on_semicolon on_nl].include?(t.event) - # def f a; - body = :normal - else - # def f a, b - next_args << :arg_without_paren - end - end - if body == :oneliner - opens.pop - elsif body - opens[-1] = [last_tok, nil] - else - opens[-1] = [last_tok, :in_method_head, next_args] - end - end - when :in_for_while_until_condition - if t.event == :on_semicolon || t.event == :on_nl || (t.event == :on_kw && t.tok == 'do') - skip = true if t.event == :on_kw && t.tok == 'do' - opens[-1] = [last_tok, nil] - end - end - - unless skip - case t.event - when :on_kw - case t.tok - when 'begin', 'class', 'module', 'do', 'case' - opens << [t, nil] - when 'end' - opens.pop - when 'def' - opens << [t, :in_method_head, [:receiver, :name]] - when 'if', 'unless' - unless t.state.allbits?(Ripper::EXPR_LABEL) - opens << [t, nil] - end - when 'while', 'until' - unless t.state.allbits?(Ripper::EXPR_LABEL) - opens << [t, :in_for_while_until_condition] - end - when 'ensure', 'rescue' - unless t.state.allbits?(Ripper::EXPR_LABEL) - opens.pop - opens << [t, nil] - end - when 'elsif', 'else', 'when' - opens.pop - opens << [t, nil] - when 'for' - opens << [t, :in_for_while_until_condition] - when 'in' - if last_tok&.event == :on_kw && %w[case in].include?(last_tok.tok) && first_token_on_line - opens.pop - opens << [t, nil] - end - end - when :on_tlambda - opens << [t, :in_lambda_head] - when :on_lparen, :on_lbracket, :on_lbrace, :on_tlambeg, :on_embexpr_beg, :on_embdoc_beg - opens << [t, nil] - when :on_rparen, :on_rbracket, :on_rbrace, :on_embexpr_end, :on_embdoc_end - opens.pop - when :on_heredoc_beg - pending_heredocs << t - when :on_heredoc_end - opens.pop - when :on_backtick - opens << [t, nil] if t.state.allbits?(Ripper::EXPR_BEG) - when :on_tstring_beg, :on_words_beg, :on_qwords_beg, :on_symbols_beg, :on_qsymbols_beg, :on_regexp_beg - opens << [t, nil] - when :on_tstring_end, :on_regexp_end, :on_label_end - opens.pop - when :on_symbeg - if t.tok == ':' - opens << [t, :in_unquoted_symbol] - else - opens << [t, nil] - end - end - end - if t.event == :on_nl || t.event == :on_semicolon - first_token_on_line = true - elsif t.event != :on_sp - first_token_on_line = false - end - if pending_heredocs.any? && t.tok.include?("\n") - pending_heredocs.reverse_each { |t| opens << [t, nil] } - pending_heredocs = [] - end - yield t, opens if block_given? - end - opens.map(&:first) + pending_heredocs.reverse - end - - def self.open_tokens(tokens) - # scan_opens without block will return a list of open tokens at last token position - scan_opens(tokens) - end - - # Calculates token information [line_tokens, prev_opens, next_opens, min_depth] for each line. - # Example code - # ["hello - # world"+( - # First line - # line_tokens: [[lbracket, '['], [tstring_beg, '"'], [tstring_content("hello\nworld"), "hello\n"]] - # prev_opens: [] - # next_tokens: [lbracket, tstring_beg] - # min_depth: 0 (minimum at beginning of line) - # Second line - # line_tokens: [[tstring_content("hello\nworld"), "world"], [tstring_end, '"'], [op, '+'], [lparen, '(']] - # prev_opens: [lbracket, tstring_beg] - # next_tokens: [lbracket, lparen] - # min_depth: 1 (minimum just after tstring_end) - def self.parse_by_line(tokens) - line_tokens = [] - prev_opens = [] - min_depth = 0 - output = [] - last_opens = scan_opens(tokens) do |t, opens| - depth = t == opens.last&.first ? opens.size - 1 : opens.size - min_depth = depth if depth < min_depth - if t.tok.include?("\n") - t.tok.each_line do |line| - line_tokens << [t, line] - next if line[-1] != "\n" - next_opens = opens.map(&:first) - output << [line_tokens, prev_opens, next_opens, min_depth] - prev_opens = next_opens - min_depth = prev_opens.size - line_tokens = [] - end - else - line_tokens << [t, t.tok] - end - end - output << [line_tokens, prev_opens, last_opens, min_depth] if line_tokens.any? - output - end - end -end diff --git a/lib/irb/notifier.rb b/lib/irb/notifier.rb deleted file mode 100644 index 612de3df168084..00000000000000 --- a/lib/irb/notifier.rb +++ /dev/null @@ -1,230 +0,0 @@ -# frozen_string_literal: false -# -# notifier.rb - output methods used by irb -# by Keiju ISHITSUKA(keiju@ruby-lang.org) -# - -require_relative "output-method" - -module IRB - # An output formatter used internally by the lexer. - module Notifier - class ErrUndefinedNotifier < StandardError - def initialize(val) - super("undefined notifier level: #{val} is specified") - end - end - class ErrUnrecognizedLevel < StandardError - def initialize(val) - super("unrecognized notifier level: #{val} is specified") - end - end - - # Define a new Notifier output source, returning a new CompositeNotifier - # with the given +prefix+ and +output_method+. - # - # The optional +prefix+ will be appended to all objects being inspected - # during output, using the given +output_method+ as the output source. If - # no +output_method+ is given, StdioOutputMethod will be used, and all - # expressions will be sent directly to STDOUT without any additional - # formatting. - def def_notifier(prefix = "", output_method = StdioOutputMethod.new) - CompositeNotifier.new(prefix, output_method) - end - module_function :def_notifier - - # An abstract class, or superclass, for CompositeNotifier and - # LeveledNotifier to inherit. It provides several wrapper methods for the - # OutputMethod object used by the Notifier. - class AbstractNotifier - # Creates a new Notifier object - def initialize(prefix, base_notifier) - @prefix = prefix - @base_notifier = base_notifier - end - - # The +prefix+ for this Notifier, which is appended to all objects being - # inspected during output. - attr_reader :prefix - - # A wrapper method used to determine whether notifications are enabled. - # - # Defaults to +true+. - def notify? - true - end - - # See OutputMethod#print for more detail. - def print(*opts) - @base_notifier.print prefix, *opts if notify? - end - - # See OutputMethod#printn for more detail. - def printn(*opts) - @base_notifier.printn prefix, *opts if notify? - end - - # See OutputMethod#printf for more detail. - def printf(format, *opts) - @base_notifier.printf(prefix + format, *opts) if notify? - end - - # See OutputMethod#puts for more detail. - def puts(*objs) - if notify? - @base_notifier.puts(*objs.collect{|obj| prefix + obj.to_s}) - end - end - - # Same as #ppx, except it uses the #prefix given during object - # initialization. - # See OutputMethod#ppx for more detail. - def pp(*objs) - if notify? - @base_notifier.ppx @prefix, *objs - end - end - - # Same as #pp, except it concatenates the given +prefix+ with the #prefix - # given during object initialization. - # - # See OutputMethod#ppx for more detail. - def ppx(prefix, *objs) - if notify? - @base_notifier.ppx @prefix+prefix, *objs - end - end - - # Execute the given block if notifications are enabled. - def exec_if - yield(@base_notifier) if notify? - end - end - - # A class that can be used to create a group of notifier objects with the - # intent of representing a leveled notification system for irb. - # - # This class will allow you to generate other notifiers, and assign them - # the appropriate level for output. - # - # The Notifier class provides a class-method Notifier.def_notifier to - # create a new composite notifier. Using the first composite notifier - # object you create, sibling notifiers can be initialized with - # #def_notifier. - class CompositeNotifier < AbstractNotifier - # Create a new composite notifier object with the given +prefix+, and - # +base_notifier+ to use for output. - def initialize(prefix, base_notifier) - super - - @notifiers = [D_NOMSG] - @level_notifier = D_NOMSG - end - - # List of notifiers in the group - attr_reader :notifiers - - # Creates a new LeveledNotifier in the composite #notifiers group. - # - # The given +prefix+ will be assigned to the notifier, and +level+ will - # be used as the index of the #notifiers Array. - # - # This method returns the newly created instance. - def def_notifier(level, prefix = "") - notifier = LeveledNotifier.new(self, level, prefix) - @notifiers[level] = notifier - notifier - end - - # Returns the leveled notifier for this object - attr_reader :level_notifier - alias level level_notifier - - # Sets the leveled notifier for this object. - # - # When the given +value+ is an instance of AbstractNotifier, - # #level_notifier is set to the given object. - # - # When an Integer is given, #level_notifier is set to the notifier at the - # index +value+ in the #notifiers Array. - # - # If no notifier exists at the index +value+ in the #notifiers Array, an - # ErrUndefinedNotifier exception is raised. - # - # An ErrUnrecognizedLevel exception is raised if the given +value+ is not - # found in the existing #notifiers Array, or an instance of - # AbstractNotifier - def level_notifier=(value) - case value - when AbstractNotifier - @level_notifier = value - when Integer - l = @notifiers[value] - raise ErrUndefinedNotifier, value unless l - @level_notifier = l - else - raise ErrUnrecognizedLevel, value unless l - end - end - - alias level= level_notifier= - end - - # A leveled notifier is comparable to the composite group from - # CompositeNotifier#notifiers. - class LeveledNotifier < AbstractNotifier - include Comparable - - # Create a new leveled notifier with the given +base+, and +prefix+ to - # send to AbstractNotifier.new - # - # The given +level+ is used to compare other leveled notifiers in the - # CompositeNotifier group to determine whether or not to output - # notifications. - def initialize(base, level, prefix) - super(prefix, base) - - @level = level - end - - # The current level of this notifier object - attr_reader :level - - # Compares the level of this notifier object with the given +other+ - # notifier. - # - # See the Comparable module for more information. - def <=>(other) - @level <=> other.level - end - - # Whether to output messages to the output method, depending on the level - # of this notifier object. - def notify? - @base_notifier.level >= self - end - end - - # NoMsgNotifier is a LeveledNotifier that's used as the default notifier - # when creating a new CompositeNotifier. - # - # This notifier is used as the +zero+ index, or level +0+, for - # CompositeNotifier#notifiers, and will not output messages of any sort. - class NoMsgNotifier < LeveledNotifier - # Creates a new notifier that should not be used to output messages. - def initialize - @base_notifier = nil - @level = 0 - @prefix = "" - end - - # Ensures notifications are ignored, see AbstractNotifier#notify? for - # more information. - def notify? - false - end - end - - D_NOMSG = NoMsgNotifier.new # :nodoc: - end -end diff --git a/lib/irb/output-method.rb b/lib/irb/output-method.rb deleted file mode 100644 index f5ea57111d8dde..00000000000000 --- a/lib/irb/output-method.rb +++ /dev/null @@ -1,86 +0,0 @@ -# frozen_string_literal: false -# -# output-method.rb - output methods used by irb -# by Keiju ISHITSUKA(keiju@ruby-lang.org) -# - -module IRB - # An abstract output class for IO in irb. This is mainly used internally by - # IRB::Notifier. You can define your own output method to use with Irb.new, - # or Context.new - class OutputMethod - class NotImplementedError < StandardError - def initialize(val) - super("Need to define `#{val}'") - end - end - - # Open this method to implement your own output method, raises a - # NotImplementedError if you don't define #print in your own class. - def print(*opts) - raise NotImplementedError, "print" - end - - # Prints the given +opts+, with a newline delimiter. - def printn(*opts) - print opts.join(" "), "\n" - end - - # Extends IO#printf to format the given +opts+ for Kernel#sprintf using - # #parse_printf_format - def printf(format, *opts) - if /(%*)%I/ =~ format - format, opts = parse_printf_format(format, opts) - end - print sprintf(format, *opts) - end - - # Returns an array of the given +format+ and +opts+ to be used by - # Kernel#sprintf, if there was a successful Regexp match in the given - # +format+ from #printf - # - # % - # [#0- +] - # (\*|\*[1-9][0-9]*\$|[1-9][0-9]*) - # .(\*|\*[1-9][0-9]*\$|[1-9][0-9]*|)? - # #(hh|h|l|ll|L|q|j|z|t) - # [diouxXeEfgGcsb%] - def parse_printf_format(format, opts) - return format, opts if $1.size % 2 == 1 - end - - # Calls #print on each element in the given +objs+, followed by a newline - # character. - def puts(*objs) - for obj in objs - print(*obj) - print "\n" - end - end - - # Prints the given +objs+ calling Object#inspect on each. - # - # See #puts for more detail. - def pp(*objs) - puts(*objs.collect{|obj| obj.inspect}) - end - - # Prints the given +objs+ calling Object#inspect on each and appending the - # given +prefix+. - # - # See #puts for more detail. - def ppx(prefix, *objs) - puts(*objs.collect{|obj| prefix+obj.inspect}) - end - - end - - # A standard output printer - class StdioOutputMethod < OutputMethod - # Prints the given +opts+ to standard output, see IO#print for more - # information. - def print(*opts) - STDOUT.print(*opts) - end - end -end diff --git a/lib/irb/pager.rb b/lib/irb/pager.rb deleted file mode 100644 index 1194e41f6f345f..00000000000000 --- a/lib/irb/pager.rb +++ /dev/null @@ -1,86 +0,0 @@ -# frozen_string_literal: true - -module IRB - # The implementation of this class is borrowed from RDoc's lib/rdoc/ri/driver.rb. - # Please do NOT use this class directly outside of IRB. - class Pager - PAGE_COMMANDS = [ENV['RI_PAGER'], ENV['PAGER'], 'less', 'more'].compact.uniq - - class << self - def page_content(content) - if content_exceeds_screen_height?(content) - page do |io| - io.puts content - end - else - $stdout.puts content - end - end - - def page - if STDIN.tty? && pager = setup_pager - begin - pid = pager.pid - yield pager - ensure - pager.close - end - else - yield $stdout - end - # When user presses Ctrl-C, IRB would raise `IRB::Abort` - # But since Pager is implemented by running paging commands like `less` in another process with `IO.popen`, - # the `IRB::Abort` exception only interrupts IRB's execution but doesn't affect the pager - # So to properly terminate the pager with Ctrl-C, we need to catch `IRB::Abort` and kill the pager process - rescue IRB::Abort - Process.kill("TERM", pid) if pid - nil - rescue Errno::EPIPE - end - - private - - def content_exceeds_screen_height?(content) - screen_height, screen_width = begin - Reline.get_screen_size - rescue Errno::EINVAL - [24, 80] - end - - pageable_height = screen_height - 3 # leave some space for previous and the current prompt - - # If the content has more lines than the pageable height - content.lines.count > pageable_height || - # Or if the content is a few long lines - pageable_height * screen_width < Reline::Unicode.calculate_width(content, true) - end - - def setup_pager - require 'shellwords' - - PAGE_COMMANDS.each do |pager| - pager = Shellwords.split(pager) - next if pager.empty? - - if pager.first == 'less' || pager.first == 'more' - pager << '-R' unless pager.include?('-R') - end - - begin - io = IO.popen(pager, 'w') - rescue - next - end - - if $? && $?.pid == io.pid && $?.exited? # pager didn't work - next - end - - return io - end - - nil - end - end - end -end diff --git a/lib/irb/ruby-lex.rb b/lib/irb/ruby-lex.rb deleted file mode 100644 index 502883bd43ca62..00000000000000 --- a/lib/irb/ruby-lex.rb +++ /dev/null @@ -1,501 +0,0 @@ -# frozen_string_literal: false -# -# irb/ruby-lex.rb - ruby lexcal analyzer -# by Keiju ISHITSUKA(keiju@ruby-lang.org) -# - -require "ripper" -require "jruby" if RUBY_ENGINE == "jruby" -require_relative "nesting_parser" - -module IRB - # :stopdoc: - class RubyLex - ASSIGNMENT_NODE_TYPES = [ - # Local, instance, global, class, constant, instance, and index assignment: - # "foo = bar", - # "@foo = bar", - # "$foo = bar", - # "@@foo = bar", - # "::Foo = bar", - # "a::Foo = bar", - # "Foo = bar" - # "foo.bar = 1" - # "foo[1] = bar" - :assign, - - # Operation assignment: - # "foo += bar" - # "foo -= bar" - # "foo ||= bar" - # "foo &&= bar" - :opassign, - - # Multiple assignment: - # "foo, bar = 1, 2 - :massign, - ] - - class TerminateLineInput < StandardError - def initialize - super("Terminate Line Input") - end - end - - attr_reader :line_no - - def initialize(context) - @context = context - @line_no = 1 - @prompt = nil - end - - def self.compile_with_errors_suppressed(code, line_no: 1) - begin - result = yield code, line_no - rescue ArgumentError - # Ruby can issue an error for the code if there is an - # incomplete magic comment for encoding in it. Force an - # expression with a new line before the code in this - # case to prevent magic comment handling. To make sure - # line numbers in the lexed code remain the same, - # decrease the line number by one. - code = ";\n#{code}" - line_no -= 1 - result = yield code, line_no - end - result - end - - def set_prompt(&block) - @prompt = block - end - - ERROR_TOKENS = [ - :on_parse_error, - :compile_error, - :on_assign_error, - :on_alias_error, - :on_class_name_error, - :on_param_error - ] - - def self.generate_local_variables_assign_code(local_variables) - "#{local_variables.join('=')}=nil;" unless local_variables.empty? - end - - # Some part of the code is not included in Ripper's token. - # Example: DATA part, token after heredoc_beg when heredoc has unclosed embexpr. - # With interpolated tokens, tokens.map(&:tok).join will be equal to code. - def self.interpolate_ripper_ignored_tokens(code, tokens) - line_positions = [0] - code.lines.each do |line| - line_positions << line_positions.last + line.bytesize - end - prev_byte_pos = 0 - interpolated = [] - prev_line = 1 - tokens.each do |t| - line, col = t.pos - byte_pos = line_positions[line - 1] + col - if prev_byte_pos < byte_pos - tok = code.byteslice(prev_byte_pos...byte_pos) - pos = [prev_line, prev_byte_pos - line_positions[prev_line - 1]] - interpolated << Ripper::Lexer::Elem.new(pos, :on_ignored_by_ripper, tok, 0) - prev_line += tok.count("\n") - end - interpolated << t - prev_byte_pos = byte_pos + t.tok.bytesize - prev_line += t.tok.count("\n") - end - if prev_byte_pos < code.bytesize - tok = code.byteslice(prev_byte_pos..) - pos = [prev_line, prev_byte_pos - line_positions[prev_line - 1]] - interpolated << Ripper::Lexer::Elem.new(pos, :on_ignored_by_ripper, tok, 0) - end - interpolated - end - - def self.ripper_lex_without_warning(code, context: nil) - verbose, $VERBOSE = $VERBOSE, nil - lvars_code = generate_local_variables_assign_code(context&.local_variables || []) - original_code = code - if lvars_code - code = "#{lvars_code}\n#{code}" - line_no = 0 - else - line_no = 1 - end - - compile_with_errors_suppressed(code, line_no: line_no) do |inner_code, line_no| - lexer = Ripper::Lexer.new(inner_code, '-', line_no) - tokens = [] - lexer.scan.each do |t| - next if t.pos.first == 0 - prev_tk = tokens.last - position_overlapped = prev_tk && t.pos[0] == prev_tk.pos[0] && t.pos[1] < prev_tk.pos[1] + prev_tk.tok.bytesize - if position_overlapped - tokens[-1] = t if ERROR_TOKENS.include?(prev_tk.event) && !ERROR_TOKENS.include?(t.event) - else - tokens << t - end - end - interpolate_ripper_ignored_tokens(original_code, tokens) - end - ensure - $VERBOSE = verbose - end - - def prompt(opens, continue, line_num_offset) - ltype = ltype_from_open_tokens(opens) - indent_level = calc_indent_level(opens) - @prompt&.call(ltype, indent_level, opens.any? || continue, @line_no + line_num_offset) - end - - def check_code_state(code) - tokens = self.class.ripper_lex_without_warning(code, context: @context) - opens = NestingParser.open_tokens(tokens) - [tokens, opens, code_terminated?(code, tokens, opens)] - end - - def code_terminated?(code, tokens, opens) - case check_code_syntax(code) - when :unrecoverable_error - true - when :recoverable_error - false - when :other_error - opens.empty? && !should_continue?(tokens) - when :valid - !should_continue?(tokens) - end - end - - def save_prompt_to_context_io(opens, continue, line_num_offset) - # Implicitly saves prompt string to `@context.io.prompt`. This will be used in the next `@input.call`. - prompt(opens, continue, line_num_offset) - end - - def increase_line_no(addition) - @line_no += addition - end - - def assignment_expression?(code) - # Try to parse the code and check if the last of possibly multiple - # expressions is an assignment type. - - # If the expression is invalid, Ripper.sexp should return nil which will - # result in false being returned. Any valid expression should return an - # s-expression where the second element of the top level array is an - # array of parsed expressions. The first element of each expression is the - # expression's type. - verbose, $VERBOSE = $VERBOSE, nil - code = "#{RubyLex.generate_local_variables_assign_code(@context.local_variables) || 'nil;'}\n#{code}" - # Get the last node_type of the line. drop(1) is to ignore the local_variables_assign_code part. - node_type = Ripper.sexp(code)&.dig(1)&.drop(1)&.dig(-1, 0) - ASSIGNMENT_NODE_TYPES.include?(node_type) - ensure - $VERBOSE = verbose - end - - def should_continue?(tokens) - # Look at the last token and check if IRB need to continue reading next line. - # Example code that should continue: `a\` `a +` `a.` - # Trailing spaces, newline, comments are skipped - return true if tokens.last&.event == :on_sp && tokens.last.tok == "\\\n" - - tokens.reverse_each do |token| - case token.event - when :on_sp, :on_nl, :on_ignored_nl, :on_comment, :on_embdoc_beg, :on_embdoc, :on_embdoc_end - # Skip - when :on_regexp_end, :on_heredoc_end, :on_semicolon - # State is EXPR_BEG but should not continue - return false - else - # Endless range should not continue - return false if token.event == :on_op && token.tok.match?(/\A\.\.\.?\z/) - - # EXPR_DOT and most of the EXPR_BEG should continue - return token.state.anybits?(Ripper::EXPR_BEG | Ripper::EXPR_DOT) - end - end - false - end - - def check_code_syntax(code) - lvars_code = RubyLex.generate_local_variables_assign_code(@context.local_variables) - code = "#{lvars_code}\n#{code}" - - begin # check if parser error are available - verbose, $VERBOSE = $VERBOSE, nil - case RUBY_ENGINE - when 'ruby' - self.class.compile_with_errors_suppressed(code) do |inner_code, line_no| - RubyVM::InstructionSequence.compile(inner_code, nil, nil, line_no) - end - when 'jruby' - JRuby.compile_ir(code) - else - catch(:valid) do - eval("BEGIN { throw :valid, true }\n#{code}") - false - end - end - rescue EncodingError - # This is for a hash with invalid encoding symbol, {"\xAE": 1} - :unrecoverable_error - rescue SyntaxError => e - case e.message - when /unterminated (?:string|regexp) meets end of file/ - # "unterminated regexp meets end of file" - # - # example: - # / - # - # "unterminated string meets end of file" - # - # example: - # ' - return :recoverable_error - when /syntax error, unexpected end-of-input/ - # "syntax error, unexpected end-of-input, expecting keyword_end" - # - # example: - # if true - # hoge - # if false - # fuga - # end - return :recoverable_error - when /syntax error, unexpected keyword_end/ - # "syntax error, unexpected keyword_end" - # - # example: - # if ( - # end - # - # example: - # end - return :unrecoverable_error - when /syntax error, unexpected '\.'/ - # "syntax error, unexpected '.'" - # - # example: - # . - return :unrecoverable_error - when /unexpected tREGEXP_BEG/ - # "syntax error, unexpected tREGEXP_BEG, expecting keyword_do or '{' or '('" - # - # example: - # method / f / - return :unrecoverable_error - else - return :other_error - end - ensure - $VERBOSE = verbose - end - :valid - end - - def calc_indent_level(opens) - indent_level = 0 - opens.each_with_index do |t, index| - case t.event - when :on_heredoc_beg - if opens[index + 1]&.event != :on_heredoc_beg - if t.tok.match?(/^<<[~-]/) - indent_level += 1 - else - indent_level = 0 - end - end - when :on_tstring_beg, :on_regexp_beg, :on_symbeg, :on_backtick - # No indent: "", //, :"", `` - # Indent: %(), %r(), %i(), %x() - indent_level += 1 if t.tok.start_with? '%' - when :on_embdoc_beg - indent_level = 0 - else - indent_level += 1 - end - end - indent_level - end - - FREE_INDENT_TOKENS = %i[on_tstring_beg on_backtick on_regexp_beg on_symbeg] - - def free_indent_token?(token) - FREE_INDENT_TOKENS.include?(token&.event) - end - - # Calculates the difference of pasted code's indent and indent calculated from tokens - def indent_difference(lines, line_results, line_index) - loop do - _tokens, prev_opens, _next_opens, min_depth = line_results[line_index] - open_token = prev_opens.last - if !open_token || (open_token.event != :on_heredoc_beg && !free_indent_token?(open_token)) - # If the leading whitespace is an indent, return the difference - indent_level = calc_indent_level(prev_opens.take(min_depth)) - calculated_indent = 2 * indent_level - actual_indent = lines[line_index][/^ */].size - return actual_indent - calculated_indent - elsif open_token.event == :on_heredoc_beg && open_token.tok.match?(/^<<[^-~]/) - return 0 - end - # If the leading whitespace is not an indent but part of a multiline token - # Calculate base_indent of the multiline token's beginning line - line_index = open_token.pos[0] - 1 - end - end - - def process_indent_level(tokens, lines, line_index, is_newline) - line_results = NestingParser.parse_by_line(tokens) - result = line_results[line_index] - if result - _tokens, prev_opens, next_opens, min_depth = result - else - # When last line is empty - prev_opens = next_opens = line_results.last[2] - min_depth = next_opens.size - end - - # To correctly indent line like `end.map do`, we use shortest open tokens on each line for indent calculation. - # Shortest open tokens can be calculated by `opens.take(min_depth)` - indent = 2 * calc_indent_level(prev_opens.take(min_depth)) - - preserve_indent = lines[line_index - (is_newline ? 1 : 0)][/^ */].size - - prev_open_token = prev_opens.last - next_open_token = next_opens.last - - # Calculates base indent for pasted code on the line where prev_open_token is located - # irb(main):001:1* if a # base_indent is 2, indent calculated from tokens is 0 - # irb(main):002:1* if b # base_indent is 6, indent calculated from tokens is 2 - # irb(main):003:0> c # base_indent is 6, indent calculated from tokens is 4 - if prev_open_token - base_indent = [0, indent_difference(lines, line_results, prev_open_token.pos[0] - 1)].max - else - base_indent = 0 - end - - if free_indent_token?(prev_open_token) - if is_newline && prev_open_token.pos[0] == line_index - # First newline inside free-indent token - base_indent + indent - else - # Accept any number of indent inside free-indent token - preserve_indent - end - elsif prev_open_token&.event == :on_embdoc_beg || next_open_token&.event == :on_embdoc_beg - if prev_open_token&.event == next_open_token&.event - # Accept any number of indent inside embdoc content - preserve_indent - else - # =begin or =end - 0 - end - elsif prev_open_token&.event == :on_heredoc_beg - tok = prev_open_token.tok - if prev_opens.size <= next_opens.size - if is_newline && lines[line_index].empty? && line_results[line_index - 1][1].last != next_open_token - # First line in heredoc - tok.match?(/^<<[-~]/) ? base_indent + indent : indent - elsif tok.match?(/^<<~/) - # Accept extra indent spaces inside `<<~` heredoc - [base_indent + indent, preserve_indent].max - else - # Accept any number of indent inside other heredoc - preserve_indent - end - else - # Heredoc close - prev_line_indent_level = calc_indent_level(prev_opens) - tok.match?(/^<<[~-]/) ? base_indent + 2 * (prev_line_indent_level - 1) : 0 - end - else - base_indent + indent - end - end - - LTYPE_TOKENS = %i[ - on_heredoc_beg on_tstring_beg - on_regexp_beg on_symbeg on_backtick - on_symbols_beg on_qsymbols_beg - on_words_beg on_qwords_beg - ] - - def ltype_from_open_tokens(opens) - start_token = opens.reverse_each.find do |tok| - LTYPE_TOKENS.include?(tok.event) - end - return nil unless start_token - - case start_token&.event - when :on_tstring_beg - case start_token&.tok - when ?" then ?" - when /^%.$/ then ?" - when /^%Q.$/ then ?" - when ?' then ?' - when /^%q.$/ then ?' - end - when :on_regexp_beg then ?/ - when :on_symbeg then ?: - when :on_backtick then ?` - when :on_qwords_beg then ?] - when :on_words_beg then ?] - when :on_qsymbols_beg then ?] - when :on_symbols_beg then ?] - when :on_heredoc_beg - start_token&.tok =~ /<<[-~]?(['"`])\w+\1/ - $1 || ?" - else - nil - end - end - - def check_termination_in_prev_line(code) - tokens = self.class.ripper_lex_without_warning(code, context: @context) - past_first_newline = false - index = tokens.rindex do |t| - # traverse first token before last line - if past_first_newline - if t.tok.include?("\n") - true - end - elsif t.tok.include?("\n") - past_first_newline = true - false - else - false - end - end - - if index - first_token = nil - last_line_tokens = tokens[(index + 1)..(tokens.size - 1)] - last_line_tokens.each do |t| - unless [:on_sp, :on_ignored_sp, :on_comment].include?(t.event) - first_token = t - break - end - end - - if first_token && first_token.state != Ripper::EXPR_DOT - tokens_without_last_line = tokens[0..index] - code_without_last_line = tokens_without_last_line.map(&:tok).join - opens_without_last_line = NestingParser.open_tokens(tokens_without_last_line) - if code_terminated?(code_without_last_line, tokens_without_last_line, opens_without_last_line) - return last_line_tokens.map(&:tok).join - end - end - end - false - end - end - # :startdoc: -end - -RubyLex = IRB::RubyLex -Object.deprecate_constant(:RubyLex) diff --git a/lib/irb/ruby_logo.aa b/lib/irb/ruby_logo.aa deleted file mode 100644 index a34a3e2f2892d4..00000000000000 --- a/lib/irb/ruby_logo.aa +++ /dev/null @@ -1,37 +0,0 @@ - - -+smJYYN?mm- - HB"BBYT TQg NggT - 9Q+g Nm,T 8g NJW - YS+ N2NJ"Sg N? - BQg #( gT Nggggk J - 5j NJ NJ NNge - #Q #JJ NgT N( - @j bj mT J - Bj @/d NJ ( - #q #(( NgT #J - 5d #(t mT $d - #q @(@J NJB; - @( 5d ? HHH H HQmgggggggmN qD - 5d #uN 2QdH E O - 5 5JSd Nd NJH @d j - Fd @J4d s NQH #d ( - #( #o6d Nd NgH #d #d - 4 B&Od v NgT #d F - #( 9JGd NH NgUd F - #d #GJQ d NP $ - #J #U+#Q N Q # j - j /W BQ+ BQ d NJ NJ - - NjJH HBIjTQggPJQgW N W k #J - #J b HYWgggN j s Nag d NN b #d - #J 5- D s Ngg N d Nd F - Fd BKH2 #+ s NNgg J Q J ] - F H @ J N y K(d P I - F4 E N? #d y #Q NJ E j - F W Nd q m Bg NxW N(H- - F d b @ m Hd gW vKJ - NJ d K d s Bg aT FDd - b # d N m BQ mV N> - e5 Nd #d NggggggQWH HHHH NJ - - m7 NW H N HSVO1z=?11- - NgTH bB kH WBHWWHBHWmQgg&gggggNNN - NNggggggNN diff --git a/lib/irb/source_finder.rb b/lib/irb/source_finder.rb deleted file mode 100644 index d196fcddc2a818..00000000000000 --- a/lib/irb/source_finder.rb +++ /dev/null @@ -1,64 +0,0 @@ -# frozen_string_literal: true - -require_relative "ruby-lex" - -module IRB - class SourceFinder - Source = Struct.new( - :file, # @param [String] - file name - :first_line, # @param [String] - first line - :last_line, # @param [String] - last line - keyword_init: true, - ) - private_constant :Source - - def initialize(irb_context) - @irb_context = irb_context - end - - def find_source(signature) - context_binding = @irb_context.workspace.binding - case signature - when /\A[A-Z]\w*(::[A-Z]\w*)*\z/ # Const::Name - eval(signature, context_binding) # trigger autoload - base = context_binding.receiver.yield_self { |r| r.is_a?(Module) ? r : Object } - file, line = base.const_source_location(signature) - when /\A(?[A-Z]\w*(::[A-Z]\w*)*)#(?[^ :.]+)\z/ # Class#method - owner = eval(Regexp.last_match[:owner], context_binding) - method = Regexp.last_match[:method] - if owner.respond_to?(:instance_method) - methods = owner.instance_methods + owner.private_instance_methods - file, line = owner.instance_method(method).source_location if methods.include?(method.to_sym) - end - when /\A((?.+)(\.|::))?(?[^ :.]+)\z/ # method, receiver.method, receiver::method - receiver = eval(Regexp.last_match[:receiver] || 'self', context_binding) - method = Regexp.last_match[:method] - file, line = receiver.method(method).source_location if receiver.respond_to?(method, true) - end - if file && line && File.exist?(file) - Source.new(file: file, first_line: line, last_line: find_end(file, line)) - end - end - - private - - def find_end(file, first_line) - lex = RubyLex.new(@irb_context) - lines = File.read(file).lines[(first_line - 1)..-1] - tokens = RubyLex.ripper_lex_without_warning(lines.join) - prev_tokens = [] - - # chunk with line number - tokens.chunk { |tok| tok.pos[0] }.each do |lnum, chunk| - code = lines[0..lnum].join - prev_tokens.concat chunk - continue = lex.should_continue?(prev_tokens) - syntax = lex.check_code_syntax(code) - if !continue && syntax == :valid - return first_line + lnum - end - end - first_line - end - end -end diff --git a/lib/irb/statement.rb b/lib/irb/statement.rb deleted file mode 100644 index b12110600cc728..00000000000000 --- a/lib/irb/statement.rb +++ /dev/null @@ -1,80 +0,0 @@ -# frozen_string_literal: true - -module IRB - class Statement - attr_reader :code - - def is_assignment? - raise NotImplementedError - end - - def suppresses_echo? - raise NotImplementedError - end - - def should_be_handled_by_debugger? - raise NotImplementedError - end - - def evaluable_code - raise NotImplementedError - end - - class Expression < Statement - def initialize(code, is_assignment) - @code = code - @is_assignment = is_assignment - end - - def suppresses_echo? - @code.match?(/;\s*\z/) - end - - def should_be_handled_by_debugger? - true - end - - def is_assignment? - @is_assignment - end - - def evaluable_code - @code - end - end - - class Command < Statement - def initialize(code, command, arg, command_class) - @code = code - @command = command - @arg = arg - @command_class = command_class - end - - def is_assignment? - false - end - - def suppresses_echo? - false - end - - def should_be_handled_by_debugger? - require_relative 'cmd/help' - require_relative 'cmd/debug' - IRB::ExtendCommand::DebugCommand > @command_class || IRB::ExtendCommand::Help == @command_class - end - - def evaluable_code - # Hook command-specific transformation to return valid Ruby code - if @command_class.respond_to?(:transform_args) - arg = @command_class.transform_args(@arg) - else - arg = @arg - end - - [@command, arg].compact.join(' ') - end - end - end -end diff --git a/lib/irb/version.rb b/lib/irb/version.rb deleted file mode 100644 index 6cb2f1965c5112..00000000000000 --- a/lib/irb/version.rb +++ /dev/null @@ -1,11 +0,0 @@ -# frozen_string_literal: false -# -# irb/version.rb - irb version definition file -# by Keiju ISHITSUKA(keiju@ishitsuka.com) -# - -module IRB # :nodoc: - VERSION = "1.8.1" - @RELEASE_VERSION = VERSION - @LAST_UPDATE_DATE = "2023-09-04" -end diff --git a/lib/irb/workspace.rb b/lib/irb/workspace.rb deleted file mode 100644 index 2bf3d5e0f11f1a..00000000000000 --- a/lib/irb/workspace.rb +++ /dev/null @@ -1,173 +0,0 @@ -# frozen_string_literal: false -# -# irb/workspace-binding.rb - -# by Keiju ISHITSUKA(keiju@ruby-lang.org) -# - -require "delegate" - -IRB::TOPLEVEL_BINDING = binding -module IRB # :nodoc: - class WorkSpace - # Creates a new workspace. - # - # set self to main if specified, otherwise - # inherit main from TOPLEVEL_BINDING. - def initialize(*main) - if main[0].kind_of?(Binding) - @binding = main.shift - elsif IRB.conf[:SINGLE_IRB] - @binding = TOPLEVEL_BINDING - else - case IRB.conf[:CONTEXT_MODE] - when 0 # binding in proc on TOPLEVEL_BINDING - @binding = eval("proc{binding}.call", - TOPLEVEL_BINDING, - __FILE__, - __LINE__) - when 1 # binding in loaded file - require "tempfile" - f = Tempfile.open("irb-binding") - f.print <IRB.conf[:__MAIN__] - attr_reader :main - - def load_commands_to_main - main.extend ExtendCommandBundle - end - - # Evaluate the given +statements+ within the context of this workspace. - def evaluate(statements, file = __FILE__, line = __LINE__) - eval(statements, @binding, file, line) - end - - def local_variable_set(name, value) - @binding.local_variable_set(name, value) - end - - def local_variable_get(name) - @binding.local_variable_get(name) - end - - # error message manipulator - # WARN: Rails patches this method to filter its own backtrace. Be cautious when changing it. - # See: https://github.com/rails/rails/blob/main/railties/lib/rails/commands/console/console_command.rb#L8:~:text=def,filter_backtrace - def filter_backtrace(bt) - return nil if bt =~ /\/irb\/.*\.rb/ - return nil if bt =~ /\/irb\.rb/ - return nil if bt =~ /tool\/lib\/.*\.rb|runner\.rb/ # for tests in Ruby repository - case IRB.conf[:CONTEXT_MODE] - when 1 - return nil if bt =~ %r!/tmp/irb-binding! - when 3 - bt = bt.sub(/:\s*in `irb_binding'/, '') - end - bt - end - - def code_around_binding - file, pos = @binding.source_location - - if defined?(::SCRIPT_LINES__[file]) && lines = ::SCRIPT_LINES__[file] - code = ::SCRIPT_LINES__[file].join('') - else - begin - code = File.read(file) - rescue SystemCallError - return - end - end - - lines = Color.colorize_code(code).lines - pos -= 1 - - start_pos = [pos - 5, 0].max - end_pos = [pos + 5, lines.size - 1].min - - line_number_fmt = Color.colorize("%#{end_pos.to_s.length}d", [:BLUE, :BOLD]) - fmt = " %2s #{line_number_fmt}: %s" - - body = (start_pos..end_pos).map do |current_pos| - sprintf(fmt, pos == current_pos ? '=>' : '', current_pos + 1, lines[current_pos]) - end.join("") - - "\nFrom: #{file} @ line #{pos + 1} :\n\n#{body}#{Color.clear}\n" - end - end -end diff --git a/lib/irb/ws-for-case-2.rb b/lib/irb/ws-for-case-2.rb deleted file mode 100644 index a0f617e4ed0c80..00000000000000 --- a/lib/irb/ws-for-case-2.rb +++ /dev/null @@ -1,9 +0,0 @@ -# frozen_string_literal: false -# -# irb/ws-for-case-2.rb - -# by Keiju ISHITSUKA(keiju@ruby-lang.org) -# - -while true - IRB::BINDING_QUEUE.push _ = binding -end diff --git a/lib/irb/xmp.rb b/lib/irb/xmp.rb deleted file mode 100644 index 94c700b4846f74..00000000000000 --- a/lib/irb/xmp.rb +++ /dev/null @@ -1,164 +0,0 @@ -# frozen_string_literal: false -# -# xmp.rb - irb version of gotoken xmp -# by Keiju ISHITSUKA(Nippon Rational Inc.) -# - -require_relative "../irb" -require_relative "frame" - -# An example printer for irb. -# -# It's much like the standard library PrettyPrint, that shows the value of each -# expression as it runs. -# -# In order to use this library, you must first require it: -# -# require 'irb/xmp' -# -# Now, you can take advantage of the Object#xmp convenience method. -# -# xmp < foo = "bar" -# #==>"bar" -# #=> baz = 42 -# #==>42 -# -# You can also create an XMP object, with an optional binding to print -# expressions in the given binding: -# -# ctx = binding -# x = XMP.new ctx -# x.puts -# #=> today = "a good day" -# #==>"a good day" -# ctx.eval 'today # is what?' -# #=> "a good day" -class XMP - - # Creates a new XMP object. - # - # The top-level binding or, optional +bind+ parameter will be used when - # creating the workspace. See WorkSpace.new for more information. - # - # This uses the +:XMP+ prompt mode, see IRB@Customizing+the+IRB+Prompt for - # full detail. - def initialize(bind = nil) - IRB.init_config(nil) - - IRB.conf[:PROMPT_MODE] = :XMP - - bind = IRB::Frame.top(1) unless bind - ws = IRB::WorkSpace.new(bind) - @io = StringInputMethod.new - @irb = IRB::Irb.new(ws, @io) - @irb.context.ignore_sigint = false - - IRB.conf[:MAIN_CONTEXT] = @irb.context - end - - # Evaluates the given +exps+, for example: - # - # require 'irb/xmp' - # x = XMP.new - # - # x.puts '{:a => 1, :b => 2, :c => 3}' - # #=> {:a => 1, :b => 2, :c => 3} - # # ==>{:a=>1, :b=>2, :c=>3} - # x.puts 'foo = "bar"' - # # => foo = "bar" - # # ==>"bar" - def puts(exps) - @io.puts exps - - if @irb.context.ignore_sigint - begin - trap_proc_b = trap("SIGINT"){@irb.signal_handle} - catch(:IRB_EXIT) do - @irb.eval_input - end - ensure - trap("SIGINT", trap_proc_b) - end - else - catch(:IRB_EXIT) do - @irb.eval_input - end - end - end - - # A custom InputMethod class used by XMP for evaluating string io. - class StringInputMethod < IRB::InputMethod - # Creates a new StringInputMethod object - def initialize - super - @exps = [] - end - - # Whether there are any expressions left in this printer. - def eof? - @exps.empty? - end - - # Reads the next expression from this printer. - # - # See IO#gets for more information. - def gets - while l = @exps.shift - next if /^\s+$/ =~ l - l.concat "\n" - print @prompt, l - break - end - l - end - - # Concatenates all expressions in this printer, separated by newlines. - # - # An Encoding::CompatibilityError is raised of the given +exps+'s encoding - # doesn't match the previous expression evaluated. - def puts(exps) - if @encoding and exps.encoding != @encoding - enc = Encoding.compatible?(@exps.join("\n"), exps) - if enc.nil? - raise Encoding::CompatibilityError, "Encoding in which the passed expression is encoded is not compatible to the preceding's one" - else - @encoding = enc - end - else - @encoding = exps.encoding - end - @exps.concat exps.split(/\n/) - end - - # Returns the encoding of last expression printed by #puts. - attr_reader :encoding - end -end - -# A convenience method that's only available when the you require the IRB::XMP standard library. -# -# Creates a new XMP object, using the given expressions as the +exps+ -# parameter, and optional binding as +bind+ or uses the top-level binding. Then -# evaluates the given expressions using the +:XMP+ prompt mode. -# -# For example: -# -# require 'irb/xmp' -# ctx = binding -# xmp 'foo = "bar"', ctx -# #=> foo = "bar" -# #==>"bar" -# ctx.eval 'foo' -# #=> "bar" -# -# See XMP.new for more information. -def xmp(exps, bind = nil) - bind = IRB::Frame.top(1) unless bind - xmp = XMP.new(bind) - xmp.puts exps - xmp -end diff --git a/lib/logger.rb b/lib/logger.rb deleted file mode 100644 index acc65ac8bb27f8..00000000000000 --- a/lib/logger.rb +++ /dev/null @@ -1,748 +0,0 @@ -# frozen_string_literal: true -# logger.rb - simple logging utility -# Copyright (C) 2000-2003, 2005, 2008, 2011 NAKAMURA, Hiroshi . -# -# Documentation:: NAKAMURA, Hiroshi and Gavin Sinclair -# License:: -# You can redistribute it and/or modify it under the same terms of Ruby's -# license; either the dual license version in 2003, or any later version. -# Revision:: $Id$ -# -# A simple system for logging messages. See Logger for more documentation. - -require 'fiber' -require 'monitor' -require 'rbconfig' - -require_relative 'logger/version' -require_relative 'logger/formatter' -require_relative 'logger/log_device' -require_relative 'logger/severity' -require_relative 'logger/errors' - -# \Class \Logger provides a simple but sophisticated logging utility that -# you can use to create one or more -# {event logs}[https://en.wikipedia.org/wiki/Logging_(software)#Event_logs] -# for your program. -# Each such log contains a chronological sequence of entries -# that provides a record of the program's activities. -# -# == About the Examples -# -# All examples on this page assume that \Logger has been required: -# -# require 'logger' -# -# == Synopsis -# -# Create a log with Logger.new: -# -# # Single log file. -# logger = Logger.new('t.log') -# # Size-based rotated logging: 3 10-megabyte files. -# logger = Logger.new('t.log', 3, 10485760) -# # Period-based rotated logging: daily (also allowed: 'weekly', 'monthly'). -# logger = Logger.new('t.log', 'daily') -# # Log to an IO stream. -# logger = Logger.new($stdout) -# -# Add entries (level, message) with Logger#add: -# -# logger.add(Logger::DEBUG, 'Maximal debugging info') -# logger.add(Logger::INFO, 'Non-error information') -# logger.add(Logger::WARN, 'Non-error warning') -# logger.add(Logger::ERROR, 'Non-fatal error') -# logger.add(Logger::FATAL, 'Fatal error') -# logger.add(Logger::UNKNOWN, 'Most severe') -# -# Close the log with Logger#close: -# -# logger.close -# -# == Entries -# -# You can add entries with method Logger#add: -# -# logger.add(Logger::DEBUG, 'Maximal debugging info') -# logger.add(Logger::INFO, 'Non-error information') -# logger.add(Logger::WARN, 'Non-error warning') -# logger.add(Logger::ERROR, 'Non-fatal error') -# logger.add(Logger::FATAL, 'Fatal error') -# logger.add(Logger::UNKNOWN, 'Most severe') -# -# These shorthand methods also add entries: -# -# logger.debug('Maximal debugging info') -# logger.info('Non-error information') -# logger.warn('Non-error warning') -# logger.error('Non-fatal error') -# logger.fatal('Fatal error') -# logger.unknown('Most severe') -# -# When you call any of these methods, -# the entry may or may not be written to the log, -# depending on the entry's severity and on the log level; -# see {Log Level}[rdoc-ref:Logger@Log+Level] -# -# An entry always has: -# -# - A severity (the required argument to #add). -# - An automatically created timestamp. -# -# And may also have: -# -# - A message. -# - A program name. -# -# Example: -# -# logger = Logger.new($stdout) -# logger.add(Logger::INFO, 'My message.', 'mung') -# # => I, [2022-05-07T17:21:46.536234 #20536] INFO -- mung: My message. -# -# The default format for an entry is: -# -# "%s, [%s #%d] %5s -- %s: %s\n" -# -# where the values to be formatted are: -# -# - \Severity (one letter). -# - Timestamp. -# - Process id. -# - \Severity (word). -# - Program name. -# - Message. -# -# You can use a different entry format by: -# -# - Setting a custom format proc (affects following entries); -# see {formatter=}[Logger.html#attribute-i-formatter]. -# - Calling any of the methods above with a block -# (affects only the one entry). -# Doing so can have two benefits: -# -# - Context: the block can evaluate the entire program context -# and create a context-dependent message. -# - Performance: the block is not evaluated unless the log level -# permits the entry actually to be written: -# -# logger.error { my_slow_message_generator } -# -# Contrast this with the string form, where the string is -# always evaluated, regardless of the log level: -# -# logger.error("#{my_slow_message_generator}") -# -# === \Severity -# -# The severity of a log entry has two effects: -# -# - Determines whether the entry is selected for inclusion in the log; -# see {Log Level}[rdoc-ref:Logger@Log+Level]. -# - Indicates to any log reader (whether a person or a program) -# the relative importance of the entry. -# -# === Timestamp -# -# The timestamp for a log entry is generated automatically -# when the entry is created. -# -# The logged timestamp is formatted by method -# {Time#strftime}[rdoc-ref:Time#strftime] -# using this format string: -# -# '%Y-%m-%dT%H:%M:%S.%6N' -# -# Example: -# -# logger = Logger.new($stdout) -# logger.add(Logger::INFO) -# # => I, [2022-05-07T17:04:32.318331 #20536] INFO -- : nil -# -# You can set a different format using method #datetime_format=. -# -# === Message -# -# The message is an optional argument to an entry method: -# -# logger = Logger.new($stdout) -# logger.add(Logger::INFO, 'My message') -# # => I, [2022-05-07T18:15:37.647581 #20536] INFO -- : My message -# -# For the default entry formatter, Logger::Formatter, -# the message object may be: -# -# - A string: used as-is. -# - An Exception: message.message is used. -# - Anything else: message.inspect is used. -# -# *Note*: Logger::Formatter does not escape or sanitize -# the message passed to it. -# Developers should be aware that malicious data (user input) -# may be in the message, and should explicitly escape untrusted data. -# -# You can use a custom formatter to escape message data; -# see the example at {formatter=}[Logger.html#attribute-i-formatter]. -# -# === Program Name -# -# The program name is an optional argument to an entry method: -# -# logger = Logger.new($stdout) -# logger.add(Logger::INFO, 'My message', 'mung') -# # => I, [2022-05-07T18:17:38.084716 #20536] INFO -- mung: My message -# -# The default program name for a new logger may be set in the call to -# Logger.new via optional keyword argument +progname+: -# -# logger = Logger.new('t.log', progname: 'mung') -# -# The default program name for an existing logger may be set -# by a call to method #progname=: -# -# logger.progname = 'mung' -# -# The current program name may be retrieved with method -# {progname}[Logger.html#attribute-i-progname]: -# -# logger.progname # => "mung" -# -# == Log Level -# -# The log level setting determines whether an entry is actually -# written to the log, based on the entry's severity. -# -# These are the defined severities (least severe to most severe): -# -# logger = Logger.new($stdout) -# logger.add(Logger::DEBUG, 'Maximal debugging info') -# # => D, [2022-05-07T17:57:41.776220 #20536] DEBUG -- : Maximal debugging info -# logger.add(Logger::INFO, 'Non-error information') -# # => I, [2022-05-07T17:59:14.349167 #20536] INFO -- : Non-error information -# logger.add(Logger::WARN, 'Non-error warning') -# # => W, [2022-05-07T18:00:45.337538 #20536] WARN -- : Non-error warning -# logger.add(Logger::ERROR, 'Non-fatal error') -# # => E, [2022-05-07T18:02:41.592912 #20536] ERROR -- : Non-fatal error -# logger.add(Logger::FATAL, 'Fatal error') -# # => F, [2022-05-07T18:05:24.703931 #20536] FATAL -- : Fatal error -# logger.add(Logger::UNKNOWN, 'Most severe') -# # => A, [2022-05-07T18:07:54.657491 #20536] ANY -- : Most severe -# -# The default initial level setting is Logger::DEBUG, the lowest level, -# which means that all entries are to be written, regardless of severity: -# -# logger = Logger.new($stdout) -# logger.level # => 0 -# logger.add(0, "My message") -# # => D, [2022-05-11T15:10:59.773668 #20536] DEBUG -- : My message -# -# You can specify a different setting in a new logger -# using keyword argument +level+ with an appropriate value: -# -# logger = Logger.new($stdout, level: Logger::ERROR) -# logger = Logger.new($stdout, level: 'error') -# logger = Logger.new($stdout, level: :error) -# logger.level # => 3 -# -# With this level, entries with severity Logger::ERROR and higher -# are written, while those with lower severities are not written: -# -# logger = Logger.new($stdout, level: Logger::ERROR) -# logger.add(3) -# # => E, [2022-05-11T15:17:20.933362 #20536] ERROR -- : nil -# logger.add(2) # Silent. -# -# You can set the log level for an existing logger -# with method #level=: -# -# logger.level = Logger::ERROR -# -# These shorthand methods also set the level: -# -# logger.debug! # => 0 -# logger.info! # => 1 -# logger.warn! # => 2 -# logger.error! # => 3 -# logger.fatal! # => 4 -# -# You can retrieve the log level with method -# {level}[Logger.html#attribute-i-level]: -# -# logger.level = Logger::ERROR -# logger.level # => 3 -# -# These methods return whether a given -# level is to be written: -# -# logger.level = Logger::ERROR -# logger.debug? # => false -# logger.info? # => false -# logger.warn? # => false -# logger.error? # => true -# logger.fatal? # => true -# -# == Log File Rotation -# -# By default, a log file is a single file that grows indefinitely -# (until explicitly closed); there is no file rotation. -# -# To keep log files to a manageable size, -# you can use _log_ _file_ _rotation_, which uses multiple log files: -# -# - Each log file has entries for a non-overlapping -# time interval. -# - Only the most recent log file is open and active; -# the others are closed and inactive. -# -# === Size-Based Rotation -# -# For size-based log file rotation, call Logger.new with: -# -# - Argument +logdev+ as a file path. -# - Argument +shift_age+ with a positive integer: -# the number of log files to be in the rotation. -# - Argument +shift_size+ as a positive integer: -# the maximum size (in bytes) of each log file; -# defaults to 1048576 (1 megabyte). -# -# Examples: -# -# logger = Logger.new('t.log', 3) # Three 1-megabyte files. -# logger = Logger.new('t.log', 5, 10485760) # Five 10-megabyte files. -# -# For these examples, suppose: -# -# logger = Logger.new('t.log', 3) -# -# Logging begins in the new log file, +t.log+; -# the log file is "full" and ready for rotation -# when a new entry would cause its size to exceed +shift_size+. -# -# The first time +t.log+ is full: -# -# - +t.log+ is closed and renamed to +t.log.0+. -# - A new file +t.log+ is opened. -# -# The second time +t.log+ is full: -# -# - +t.log.0 is renamed as +t.log.1+. -# - +t.log+ is closed and renamed to +t.log.0+. -# - A new file +t.log+ is opened. -# -# Each subsequent time that +t.log+ is full, -# the log files are rotated: -# -# - +t.log.1+ is removed. -# - +t.log.0 is renamed as +t.log.1+. -# - +t.log+ is closed and renamed to +t.log.0+. -# - A new file +t.log+ is opened. -# -# === Periodic Rotation -# -# For periodic rotation, call Logger.new with: -# -# - Argument +logdev+ as a file path. -# - Argument +shift_age+ as a string period indicator. -# -# Examples: -# -# logger = Logger.new('t.log', 'daily') # Rotate log files daily. -# logger = Logger.new('t.log', 'weekly') # Rotate log files weekly. -# logger = Logger.new('t.log', 'monthly') # Rotate log files monthly. -# -# Example: -# -# logger = Logger.new('t.log', 'daily') -# -# When the given period expires: -# -# - The base log file, +t.log+ is closed and renamed -# with a date-based suffix such as +t.log.20220509+. -# - A new log file +t.log+ is opened. -# - Nothing is removed. -# -# The default format for the suffix is '%Y%m%d', -# which produces a suffix similar to the one above. -# You can set a different format using create-time option -# +shift_period_suffix+; -# see details and suggestions at -# {Time#strftime}[rdoc-ref:Time#strftime]. -# -class Logger - _, name, rev = %w$Id$ - if name - name = name.chomp(",v") - else - name = File.basename(__FILE__) - end - rev ||= "v#{VERSION}" - ProgName = "#{name}/#{rev}" - - include Severity - - # Logging severity threshold (e.g. Logger::INFO). - def level - @level_override[Fiber.current] || @level - end - - # Sets the log level; returns +severity+. - # See {Log Level}[rdoc-ref:Logger@Log+Level]. - # - # Argument +severity+ may be an integer, a string, or a symbol: - # - # logger.level = Logger::ERROR # => 3 - # logger.level = 3 # => 3 - # logger.level = 'error' # => "error" - # logger.level = :error # => :error - # - # Logger#sev_threshold= is an alias for Logger#level=. - # - def level=(severity) - @level = Severity.coerce(severity) - end - - # Adjust the log level during the block execution for the current Fiber only - # - # logger.with_level(:debug) do - # logger.debug { "Hello" } - # end - def with_level(severity) - prev, @level_override[Fiber.current] = level, Severity.coerce(severity) - begin - yield - ensure - if prev - @level_override[Fiber.current] = prev - else - @level_override.delete(Fiber.current) - end - end - end - - # Program name to include in log messages. - attr_accessor :progname - - # Sets the date-time format. - # - # Argument +datetime_format+ should be either of these: - # - # - A string suitable for use as a format for method - # {Time#strftime}[rdoc-ref:Time#strftime]. - # - +nil+: the logger uses '%Y-%m-%dT%H:%M:%S.%6N'. - # - def datetime_format=(datetime_format) - @default_formatter.datetime_format = datetime_format - end - - # Returns the date-time format; see #datetime_format=. - # - def datetime_format - @default_formatter.datetime_format - end - - # Sets or retrieves the logger entry formatter proc. - # - # When +formatter+ is +nil+, the logger uses Logger::Formatter. - # - # When +formatter+ is a proc, a new entry is formatted by the proc, - # which is called with four arguments: - # - # - +severity+: The severity of the entry. - # - +time+: A Time object representing the entry's timestamp. - # - +progname+: The program name for the entry. - # - +msg+: The message for the entry (string or string-convertible object). - # - # The proc should return a string containing the formatted entry. - # - # This custom formatter uses - # {String#dump}[rdoc-ref:String#dump] - # to escape the message string: - # - # logger = Logger.new($stdout, progname: 'mung') - # original_formatter = logger.formatter || Logger::Formatter.new - # logger.formatter = proc { |severity, time, progname, msg| - # original_formatter.call(severity, time, progname, msg.dump) - # } - # logger.add(Logger::INFO, "hello \n ''") - # logger.add(Logger::INFO, "\f\x00\xff\\\"") - # - # Output: - # - # I, [2022-05-13T13:16:29.637488 #8492] INFO -- mung: "hello \n ''" - # I, [2022-05-13T13:16:29.637610 #8492] INFO -- mung: "\f\x00\xFF\\\"" - # - attr_accessor :formatter - - alias sev_threshold level - alias sev_threshold= level= - - # Returns +true+ if the log level allows entries with severity - # Logger::DEBUG to be written, +false+ otherwise. - # See {Log Level}[rdoc-ref:Logger@Log+Level]. - # - def debug?; level <= DEBUG; end - - # Sets the log level to Logger::DEBUG. - # See {Log Level}[rdoc-ref:Logger@Log+Level]. - # - def debug!; self.level = DEBUG; end - - # Returns +true+ if the log level allows entries with severity - # Logger::INFO to be written, +false+ otherwise. - # See {Log Level}[rdoc-ref:Logger@Log+Level]. - # - def info?; level <= INFO; end - - # Sets the log level to Logger::INFO. - # See {Log Level}[rdoc-ref:Logger@Log+Level]. - # - def info!; self.level = INFO; end - - # Returns +true+ if the log level allows entries with severity - # Logger::WARN to be written, +false+ otherwise. - # See {Log Level}[rdoc-ref:Logger@Log+Level]. - # - def warn?; level <= WARN; end - - # Sets the log level to Logger::WARN. - # See {Log Level}[rdoc-ref:Logger@Log+Level]. - # - def warn!; self.level = WARN; end - - # Returns +true+ if the log level allows entries with severity - # Logger::ERROR to be written, +false+ otherwise. - # See {Log Level}[rdoc-ref:Logger@Log+Level]. - # - def error?; level <= ERROR; end - - # Sets the log level to Logger::ERROR. - # See {Log Level}[rdoc-ref:Logger@Log+Level]. - # - def error!; self.level = ERROR; end - - # Returns +true+ if the log level allows entries with severity - # Logger::FATAL to be written, +false+ otherwise. - # See {Log Level}[rdoc-ref:Logger@Log+Level]. - # - def fatal?; level <= FATAL; end - - # Sets the log level to Logger::FATAL. - # See {Log Level}[rdoc-ref:Logger@Log+Level]. - # - def fatal!; self.level = FATAL; end - - # :call-seq: - # Logger.new(logdev, shift_age = 0, shift_size = 1048576, **options) - # - # With the single argument +logdev+, - # returns a new logger with all default options: - # - # Logger.new('t.log') # => # - # - # Argument +logdev+ must be one of: - # - # - A string filepath: entries are to be written - # to the file at that path; if the file at that path exists, - # new entries are appended. - # - An IO stream (typically +$stdout+, +$stderr+. or an open file): - # entries are to be written to the given stream. - # - +nil+ or +File::NULL+: no entries are to be written. - # - # Examples: - # - # Logger.new('t.log') - # Logger.new($stdout) - # - # The keyword options are: - # - # - +level+: sets the log level; default value is Logger::DEBUG. - # See {Log Level}[rdoc-ref:Logger@Log+Level]: - # - # Logger.new('t.log', level: Logger::ERROR) - # - # - +progname+: sets the default program name; default is +nil+. - # See {Program Name}[rdoc-ref:Logger@Program+Name]: - # - # Logger.new('t.log', progname: 'mung') - # - # - +formatter+: sets the entry formatter; default is +nil+. - # See {formatter=}[Logger.html#attribute-i-formatter]. - # - +datetime_format+: sets the format for entry timestamp; - # default is +nil+. - # See #datetime_format=. - # - +binmode+: sets whether the logger writes in binary mode; - # default is +false+. - # - +shift_period_suffix+: sets the format for the filename suffix - # for periodic log file rotation; default is '%Y%m%d'. - # See {Periodic Rotation}[rdoc-ref:Logger@Periodic+Rotation]. - # - def initialize(logdev, shift_age = 0, shift_size = 1048576, level: DEBUG, - progname: nil, formatter: nil, datetime_format: nil, - binmode: false, shift_period_suffix: '%Y%m%d') - self.level = level - self.progname = progname - @default_formatter = Formatter.new - self.datetime_format = datetime_format - self.formatter = formatter - @logdev = nil - @level_override = {} - if logdev && logdev != File::NULL - @logdev = LogDevice.new(logdev, shift_age: shift_age, - shift_size: shift_size, - shift_period_suffix: shift_period_suffix, - binmode: binmode) - end - end - - # Sets the logger's output stream: - # - # - If +logdev+ is +nil+, reopens the current output stream. - # - If +logdev+ is a filepath, opens the indicated file for append. - # - If +logdev+ is an IO stream - # (usually $stdout, $stderr, or an open File object), - # opens the stream for append. - # - # Example: - # - # logger = Logger.new('t.log') - # logger.add(Logger::ERROR, 'one') - # logger.close - # logger.add(Logger::ERROR, 'two') # Prints 'log writing failed. closed stream' - # logger.reopen - # logger.add(Logger::ERROR, 'three') - # logger.close - # File.readlines('t.log') - # # => - # # ["# Logfile created on 2022-05-12 14:21:19 -0500 by logger.rb/v1.5.0\n", - # # "E, [2022-05-12T14:21:27.596726 #22428] ERROR -- : one\n", - # # "E, [2022-05-12T14:23:05.847241 #22428] ERROR -- : three\n"] - # - def reopen(logdev = nil) - @logdev&.reopen(logdev) - self - end - - # Creates a log entry, which may or may not be written to the log, - # depending on the entry's severity and on the log level. - # See {Log Level}[rdoc-ref:Logger@Log+Level] - # and {Entries}[rdoc-ref:Logger@Entries] for details. - # - # Examples: - # - # logger = Logger.new($stdout, progname: 'mung') - # logger.add(Logger::INFO) - # logger.add(Logger::ERROR, 'No good') - # logger.add(Logger::ERROR, 'No good', 'gnum') - # - # Output: - # - # I, [2022-05-12T16:25:31.469726 #36328] INFO -- mung: mung - # E, [2022-05-12T16:25:55.349414 #36328] ERROR -- mung: No good - # E, [2022-05-12T16:26:35.841134 #36328] ERROR -- gnum: No good - # - # These convenience methods have implicit severity: - # - # - #debug. - # - #info. - # - #warn. - # - #error. - # - #fatal. - # - #unknown. - # - def add(severity, message = nil, progname = nil) - severity ||= UNKNOWN - if @logdev.nil? or severity < level - return true - end - if progname.nil? - progname = @progname - end - if message.nil? - if block_given? - message = yield - else - message = progname - progname = @progname - end - end - @logdev.write( - format_message(format_severity(severity), Time.now, progname, message)) - true - end - alias log add - - # Writes the given +msg+ to the log with no formatting; - # returns the number of characters written, - # or +nil+ if no log device exists: - # - # logger = Logger.new($stdout) - # logger << 'My message.' # => 10 - # - # Output: - # - # My message. - # - def <<(msg) - @logdev&.write(msg) - end - - # Equivalent to calling #add with severity Logger::DEBUG. - # - def debug(progname = nil, &block) - add(DEBUG, nil, progname, &block) - end - - # Equivalent to calling #add with severity Logger::INFO. - # - def info(progname = nil, &block) - add(INFO, nil, progname, &block) - end - - # Equivalent to calling #add with severity Logger::WARN. - # - def warn(progname = nil, &block) - add(WARN, nil, progname, &block) - end - - # Equivalent to calling #add with severity Logger::ERROR. - # - def error(progname = nil, &block) - add(ERROR, nil, progname, &block) - end - - # Equivalent to calling #add with severity Logger::FATAL. - # - def fatal(progname = nil, &block) - add(FATAL, nil, progname, &block) - end - - # Equivalent to calling #add with severity Logger::UNKNOWN. - # - def unknown(progname = nil, &block) - add(UNKNOWN, nil, progname, &block) - end - - # Closes the logger; returns +nil+: - # - # logger = Logger.new('t.log') - # logger.close # => nil - # logger.info('foo') # Prints "log writing failed. closed stream" - # - # Related: Logger#reopen. - def close - @logdev&.close - end - -private - - # \Severity label for logging (max 5 chars). - SEV_LABEL = %w(DEBUG INFO WARN ERROR FATAL ANY).freeze - - def format_severity(severity) - SEV_LABEL[severity] || 'ANY' - end - - def format_message(severity, datetime, progname, msg) - (@formatter || @default_formatter).call(severity, datetime, progname, msg) - end -end diff --git a/lib/logger/errors.rb b/lib/logger/errors.rb deleted file mode 100644 index 88581793f0d941..00000000000000 --- a/lib/logger/errors.rb +++ /dev/null @@ -1,9 +0,0 @@ -# frozen_string_literal: true - -class Logger - # not used after 1.2.7. just for compat. - class Error < RuntimeError # :nodoc: - end - class ShiftingError < Error # :nodoc: - end -end diff --git a/lib/logger/formatter.rb b/lib/logger/formatter.rb deleted file mode 100644 index c634dbf34dcb75..00000000000000 --- a/lib/logger/formatter.rb +++ /dev/null @@ -1,36 +0,0 @@ -# frozen_string_literal: true - -class Logger - # Default formatter for log messages. - class Formatter - Format = "%.1s, [%s #%d] %5s -- %s: %s\n" - DatetimeFormat = "%Y-%m-%dT%H:%M:%S.%6N" - - attr_accessor :datetime_format - - def initialize - @datetime_format = nil - end - - def call(severity, time, progname, msg) - sprintf(Format, severity, format_datetime(time), Process.pid, severity, progname, msg2str(msg)) - end - - private - - def format_datetime(time) - time.strftime(@datetime_format || DatetimeFormat) - end - - def msg2str(msg) - case msg - when ::String - msg - when ::Exception - "#{ msg.message } (#{ msg.class })\n#{ msg.backtrace.join("\n") if msg.backtrace }" - else - msg.inspect - end - end - end -end diff --git a/lib/logger/log_device.rb b/lib/logger/log_device.rb deleted file mode 100644 index 84277a2656e607..00000000000000 --- a/lib/logger/log_device.rb +++ /dev/null @@ -1,207 +0,0 @@ -# frozen_string_literal: true - -require_relative 'period' - -class Logger - # Device used for logging messages. - class LogDevice - include Period - - attr_reader :dev - attr_reader :filename - include MonitorMixin - - def initialize(log = nil, shift_age: nil, shift_size: nil, shift_period_suffix: nil, binmode: false) - @dev = @filename = @shift_age = @shift_size = @shift_period_suffix = nil - @binmode = binmode - mon_initialize - set_dev(log) - if @filename - @shift_age = shift_age || 7 - @shift_size = shift_size || 1048576 - @shift_period_suffix = shift_period_suffix || '%Y%m%d' - - unless @shift_age.is_a?(Integer) - base_time = @dev.respond_to?(:stat) ? @dev.stat.mtime : Time.now - @next_rotate_time = next_rotate_time(base_time, @shift_age) - end - end - end - - def write(message) - begin - synchronize do - if @shift_age and @dev.respond_to?(:stat) - begin - check_shift_log - rescue - warn("log shifting failed. #{$!}") - end - end - begin - @dev.write(message) - rescue - warn("log writing failed. #{$!}") - end - end - rescue Exception => ignored - warn("log writing failed. #{ignored}") - end - end - - def close - begin - synchronize do - @dev.close rescue nil - end - rescue Exception - @dev.close rescue nil - end - end - - def reopen(log = nil) - # reopen the same filename if no argument, do nothing for IO - log ||= @filename if @filename - if log - synchronize do - if @filename and @dev - @dev.close rescue nil # close only file opened by Logger - @filename = nil - end - set_dev(log) - end - end - self - end - - private - - def set_dev(log) - if log.respond_to?(:write) and log.respond_to?(:close) - @dev = log - if log.respond_to?(:path) and path = log.path - if File.exist?(path) - @filename = path - end - end - else - @dev = open_logfile(log) - @dev.sync = true - @dev.binmode if @binmode - @filename = log - end - end - - def open_logfile(filename) - begin - File.open(filename, (File::WRONLY | File::APPEND)) - rescue Errno::ENOENT - create_logfile(filename) - end - end - - def create_logfile(filename) - begin - logdev = File.open(filename, (File::WRONLY | File::APPEND | File::CREAT | File::EXCL)) - logdev.flock(File::LOCK_EX) - logdev.sync = true - logdev.binmode if @binmode - add_log_header(logdev) - logdev.flock(File::LOCK_UN) - rescue Errno::EEXIST - # file is created by another process - logdev = open_logfile(filename) - logdev.sync = true - end - logdev - end - - def add_log_header(file) - file.write( - "# Logfile created on %s by %s\n" % [Time.now.to_s, Logger::ProgName] - ) if file.size == 0 - end - - def check_shift_log - if @shift_age.is_a?(Integer) - # Note: always returns false if '0'. - if @filename && (@shift_age > 0) && (@dev.stat.size > @shift_size) - lock_shift_log { shift_log_age } - end - else - now = Time.now - if now >= @next_rotate_time - @next_rotate_time = next_rotate_time(now, @shift_age) - lock_shift_log { shift_log_period(previous_period_end(now, @shift_age)) } - end - end - end - - if /mswin|mingw|cygwin/ =~ RbConfig::CONFIG['host_os'] - def lock_shift_log - yield - end - else - def lock_shift_log - retry_limit = 8 - retry_sleep = 0.1 - begin - File.open(@filename, File::WRONLY | File::APPEND) do |lock| - lock.flock(File::LOCK_EX) # inter-process locking. will be unlocked at closing file - if File.identical?(@filename, lock) and File.identical?(lock, @dev) - yield # log shifting - else - # log shifted by another process (i-node before locking and i-node after locking are different) - @dev.close rescue nil - @dev = open_logfile(@filename) - @dev.sync = true - end - end - rescue Errno::ENOENT - # @filename file would not exist right after #rename and before #create_logfile - if retry_limit <= 0 - warn("log rotation inter-process lock failed. #{$!}") - else - sleep retry_sleep - retry_limit -= 1 - retry_sleep *= 2 - retry - end - end - rescue - warn("log rotation inter-process lock failed. #{$!}") - end - end - - def shift_log_age - (@shift_age-3).downto(0) do |i| - if FileTest.exist?("#{@filename}.#{i}") - File.rename("#{@filename}.#{i}", "#{@filename}.#{i+1}") - end - end - @dev.close rescue nil - File.rename("#{@filename}", "#{@filename}.0") - @dev = create_logfile(@filename) - return true - end - - def shift_log_period(period_end) - suffix = period_end.strftime(@shift_period_suffix) - age_file = "#{@filename}.#{suffix}" - if FileTest.exist?(age_file) - # try to avoid filename crash caused by Timestamp change. - idx = 0 - # .99 can be overridden; avoid too much file search with 'loop do' - while idx < 100 - idx += 1 - age_file = "#{@filename}.#{suffix}.#{idx}" - break unless FileTest.exist?(age_file) - end - end - @dev.close rescue nil - File.rename("#{@filename}", age_file) - @dev = create_logfile(@filename) - return true - end - end -end diff --git a/lib/logger/logger.gemspec b/lib/logger/logger.gemspec deleted file mode 100644 index d12db625d969cf..00000000000000 --- a/lib/logger/logger.gemspec +++ /dev/null @@ -1,26 +0,0 @@ -begin - require_relative "lib/logger/version" -rescue LoadError # Fallback to load version file in ruby core repository - require_relative "version" -end - -Gem::Specification.new do |spec| - spec.name = "logger" - spec.version = Logger::VERSION - spec.authors = ["Naotoshi Seo", "SHIBATA Hiroshi"] - spec.email = ["sonots@gmail.com", "hsbt@ruby-lang.org"] - - spec.summary = %q{Provides a simple logging utility for outputting messages.} - spec.description = %q{Provides a simple logging utility for outputting messages.} - spec.homepage = "https://github.com/ruby/logger" - spec.licenses = ["Ruby", "BSD-2-Clause"] - - spec.files = Dir.glob("lib/**/*.rb") + ["logger.gemspec"] - spec.require_paths = ["lib"] - - spec.required_ruby_version = ">= 2.3.0" - - spec.add_development_dependency "bundler", ">= 0" - spec.add_development_dependency "rake", ">= 12.3.3" - spec.add_development_dependency "test-unit" -end diff --git a/lib/logger/period.rb b/lib/logger/period.rb deleted file mode 100644 index 0a291dbbbe799d..00000000000000 --- a/lib/logger/period.rb +++ /dev/null @@ -1,47 +0,0 @@ -# frozen_string_literal: true - -class Logger - module Period - module_function - - SiD = 24 * 60 * 60 - - def next_rotate_time(now, shift_age) - case shift_age - when 'daily' - t = Time.mktime(now.year, now.month, now.mday) + SiD - when 'weekly' - t = Time.mktime(now.year, now.month, now.mday) + SiD * (7 - now.wday) - when 'monthly' - t = Time.mktime(now.year, now.month, 1) + SiD * 32 - return Time.mktime(t.year, t.month, 1) - when 'now', 'everytime' - return now - else - raise ArgumentError, "invalid :shift_age #{shift_age.inspect}, should be daily, weekly, monthly, or everytime" - end - if t.hour.nonzero? or t.min.nonzero? or t.sec.nonzero? - hour = t.hour - t = Time.mktime(t.year, t.month, t.mday) - t += SiD if hour > 12 - end - t - end - - def previous_period_end(now, shift_age) - case shift_age - when 'daily' - t = Time.mktime(now.year, now.month, now.mday) - SiD / 2 - when 'weekly' - t = Time.mktime(now.year, now.month, now.mday) - (SiD * now.wday + SiD / 2) - when 'monthly' - t = Time.mktime(now.year, now.month, 1) - SiD / 2 - when 'now', 'everytime' - return now - else - raise ArgumentError, "invalid :shift_age #{shift_age.inspect}, should be daily, weekly, monthly, or everytime" - end - Time.mktime(t.year, t.month, t.mday, 23, 59, 59) - end - end -end diff --git a/lib/logger/severity.rb b/lib/logger/severity.rb deleted file mode 100644 index e96fb0d320aa06..00000000000000 --- a/lib/logger/severity.rb +++ /dev/null @@ -1,38 +0,0 @@ -# frozen_string_literal: true - -class Logger - # Logging severity. - module Severity - # Low-level information, mostly for developers. - DEBUG = 0 - # Generic (useful) information about system operation. - INFO = 1 - # A warning. - WARN = 2 - # A handleable error condition. - ERROR = 3 - # An unhandleable error that results in a program crash. - FATAL = 4 - # An unknown message that should always be logged. - UNKNOWN = 5 - - LEVELS = { - "debug" => DEBUG, - "info" => INFO, - "warn" => WARN, - "error" => ERROR, - "fatal" => FATAL, - "unknown" => UNKNOWN, - } - private_constant :LEVELS - - def self.coerce(severity) - if severity.is_a?(Integer) - severity - else - key = severity.to_s.downcase - LEVELS[key] || raise(ArgumentError, "invalid log level: #{severity}") - end - end - end -end diff --git a/lib/logger/version.rb b/lib/logger/version.rb deleted file mode 100644 index f85c72eed35ea7..00000000000000 --- a/lib/logger/version.rb +++ /dev/null @@ -1,5 +0,0 @@ -# frozen_string_literal: true - -class Logger - VERSION = "1.5.3" -end diff --git a/lib/mkmf.rb b/lib/mkmf.rb index 2acff0ddc04ac4..7ac4f916b8ae24 100644 --- a/lib/mkmf.rb +++ b/lib/mkmf.rb @@ -44,6 +44,23 @@ def quote # correctly compile and link the C extension to Ruby and a third-party # library. module MakeMakefile + + target_rbconfig = nil + ARGV.delete_if do |arg| + opt = arg.delete_prefix("--target-rbconfig=") + unless opt == arg + target_rbconfig = opt + end + end + if target_rbconfig + # Load the RbConfig for the target platform into this module. + # Cross-compiling needs the same version of Ruby. + Kernel.load target_rbconfig, self + else + # The RbConfig for the target platform where the built extension runs. + RbConfig = ::RbConfig + end + #### defer until this module become global-state free. # def self.extended(obj) # obj.init_mkmf @@ -59,6 +76,9 @@ module MakeMakefile # The makefile configuration using the defaults from when Ruby was built. CONFIG = RbConfig::MAKEFILE_CONFIG + + ## + # The saved original value of +LIB+ environment variable ORIG_LIBPATH = ENV['LIB'] ## @@ -245,12 +265,16 @@ def map_dir(dir, map = nil) CSRCFLAG = CONFIG['CSRCFLAG'] CPPOUTFILE = config_string('CPPOUTFILE') {|str| str.sub(/\bconftest\b/, CONFTEST)} + # :startdoc: + + # Removes _files_. def rm_f(*files) opt = (Hash === files.last ? [files.pop] : []) FileUtils.rm_f(Dir[*files.flatten], *opt) end module_function :rm_f + # Removes _files_ recursively. def rm_rf(*files) opt = (Hash === files.last ? [files.pop] : []) FileUtils.rm_rf(Dir[*files.flatten], *opt) @@ -265,6 +289,8 @@ def modified?(target, times) t if times.all? {|n| n <= t} end + # :stopdoc: + def split_libs(*strs) sep = $mswin ? /\s+/ : /\s+(?=-|\z)/ strs.flat_map {|s| s.lstrip.split(sep)} @@ -390,6 +416,11 @@ def expand_command(commands, envs = libpath_env) env, *commands = commands if Hash === commands.first envs.merge!(env) if env end + + # disable ASAN leak reporting - conftest programs almost always don't bother + # to free their memory. + envs['ASAN_OPTIONS'] = "detect_leaks=0" unless ENV.key?('ASAN_OPTIONS') + return envs, expand[commands] end @@ -397,11 +428,19 @@ def env_quote(envs) envs.map {|e, v| "#{e}=#{v.quote}"} end - def xsystem command, opts = nil + # :startdoc: + + # call-seq: + # xsystem(command, werror: false) -> true or false + # + # Executes _command_ with expanding variables, and returns the exit + # status like as Kernel#system. If _werror_ is true and the error + # output is not empty, returns +false+. The output will logged. + def xsystem(command, werror: false) env, command = expand_command(command) Logging::open do puts [env_quote(env), command.quote].join(' ') - if opts and opts[:werror] + if werror result = nil Logging.postpone do |log| output = IO.popen(env, command, &:read) @@ -415,6 +454,7 @@ def xsystem command, opts = nil end end + # Executes _command_ similarly to xsystem, but yields opened pipe. def xpopen command, *mode, &block env, commands = expand_command(command) command = [env_quote(env), command].join(' ') @@ -429,6 +469,7 @@ def xpopen command, *mode, &block end end + # Logs _src_ def log_src(src, heading="checked program was") src = src.split(/^/) fmt = "%#{src.size.to_s.size}d: %s" @@ -443,10 +484,15 @@ def log_src(src, heading="checked program was") EOM end + # Returns the language-dependent source file name for configuration + # checks. def conftest_source CONFTEST_C end + # Creats temporary source file from +COMMON_HEADERS+ and _src_. + # Yields the created source string and uses the returned string as + # the source code, if the block is given. def create_tmpsrc(src) src = "#{COMMON_HEADERS}\n#{src}" src = yield(src) if block_given? @@ -467,6 +513,8 @@ def create_tmpsrc(src) src end + # :stopdoc: + def have_devel? unless defined? $have_devel $have_devel = true @@ -475,7 +523,7 @@ def have_devel? $have_devel end - def try_do(src, command, *opts, &b) + def try_do(src, command, **opts, &b) unless have_devel? raise <$CFLAGS and $LDFLAGS are also + # passed to the linker. # # If a block given, it is called with the source before compilation. You can # modify the source in the block. # # [+src+] a String which contains a C source # [+opt+] a String which contains linker options - def try_link(src, opt="", *opts, &b) - exe = try_link0(src, opt, *opts, &b) or return false + def try_link(src, opt = "", **opts, &b) + exe = try_link0(src, opt, **opts, &b) or return false MakeMakefile.rm_f exe true end # Returns whether or not the +src+ can be compiled as a C source. +opt+ is - # passed to the C compiler as options. Note that +$CFLAGS+ is also passed to - # the compiler. + # passed to the C compiler as options. Note that $CFLAGS is also + # passed to the compiler. # # If a block given, it is called with the source before compilation. You can # modify the source in the block. # # [+src+] a String which contains a C source # [+opt+] a String which contains compiler options - def try_compile(src, opt="", *opts, &b) - with_werror(opt, *opts) {|_opt, *| try_do(src, cc_command(_opt), *opts, &b)} and + def try_compile(src, opt = "", werror: nil, **opts, &b) + opt = werror_flag(opt) if werror + try_do(src, cc_command(opt), werror: werror, **opts, &b) and File.file?("#{CONFTEST}.#{$OBJEXT}") ensure MakeMakefile.rm_f "#{CONFTEST}*" @@ -611,15 +660,15 @@ def try_compile(src, opt="", *opts, &b) # Returns whether or not the +src+ can be preprocessed with the C # preprocessor. +opt+ is passed to the preprocessor as options. Note that - # +$CFLAGS+ is also passed to the preprocessor. + # $CFLAGS is also passed to the preprocessor. # # If a block given, it is called with the source before preprocessing. You # can modify the source in the block. # # [+src+] a String which contains a C source # [+opt+] a String which contains preprocessor options - def try_cpp(src, opt="", *opts, &b) - try_do(src, cpp_command(CPPOUTFILE, opt), *opts, &b) and + def try_cpp(src, opt = "", **opts, &b) + try_do(src, cpp_command(CPPOUTFILE, opt), **opts, &b) and File.file?("#{CONFTEST}.i") ensure MakeMakefile.rm_f "#{CONFTEST}*" @@ -636,6 +685,14 @@ def cpp_include(header) end end + # :startdoc: + + # Sets $CPPFLAGS to _flags_ and yields. If the block returns a + # falsy value, $CPPFLAGS is reset to its previous value, remains + # set to _flags_ otherwise. + # + # [+flags+] a C preprocessor flag as a +String+ + # def with_cppflags(flags) cppflags = $CPPFLAGS $CPPFLAGS = flags.dup @@ -644,20 +701,29 @@ def with_cppflags(flags) $CPPFLAGS = cppflags unless ret end - def try_cppflags(flags, opts = {}) - try_header(MAIN_DOES_NOTHING, flags, {:werror => true}.update(opts)) + # :nodoc: + def try_cppflags(flags, werror: true, **opts) + try_header(MAIN_DOES_NOTHING, flags, werror: werror, **opts) end - def append_cppflags(flags, *opts) + # Check whether each given C preprocessor flag is acceptable and append it + # to $CPPFLAGS if so. + # + # [+flags+] a C preprocessor flag as a +String+ or an +Array+ of them + # + def append_cppflags(flags, **opts) Array(flags).each do |flag| if checking_for("whether #{flag} is accepted as CPPFLAGS") { - try_cppflags(flag, *opts) + try_cppflags(flag, **opts) } $CPPFLAGS << " " << flag end end end + # Sets $CFLAGS to _flags_ and yields. If the block returns a falsy + # value, $CFLAGS is reset to its previous value, remains set to + # _flags_ otherwise. def with_cflags(flags) cflags = $CFLAGS $CFLAGS = flags.dup @@ -666,10 +732,14 @@ def with_cflags(flags) $CFLAGS = cflags unless ret end - def try_cflags(flags, opts = {}) - try_compile(MAIN_DOES_NOTHING, flags, {:werror => true}.update(opts)) + # :nodoc: + def try_cflags(flags, werror: true, **opts) + try_compile(MAIN_DOES_NOTHING, flags, werror: werror, **opts) end + # Sets $LDFLAGS to _flags_ and yields. If the block returns a + # falsy value, $LDFLAGS is reset to its previous value, remains set + # to _flags_ otherwise. def with_ldflags(flags) ldflags = $LDFLAGS $LDFLAGS = flags.dup @@ -678,21 +748,30 @@ def with_ldflags(flags) $LDFLAGS = ldflags unless ret end - def try_ldflags(flags, opts = {}) - opts = {:werror => true}.update(opts) if $mswin - try_link(MAIN_DOES_NOTHING, flags, opts) + # :nodoc: + def try_ldflags(flags, werror: $mswin, **opts) + try_link(MAIN_DOES_NOTHING, "", ldflags: flags, werror: werror, **opts) end - def append_ldflags(flags, *opts) + # :startdoc: + + # Check whether each given linker flag is acceptable and append it to + # $LDFLAGS if so. + # + # [+flags+] a linker flag as a +String+ or an +Array+ of them + # + def append_ldflags(flags, **opts) Array(flags).each do |flag| if checking_for("whether #{flag} is accepted as LDFLAGS") { - try_ldflags(flag, *opts) + try_ldflags(flag, **opts) } $LDFLAGS << " " << flag end end end + # :stopdoc: + def try_static_assert(expr, headers = nil, opt = "", &b) headers = cpp_include(headers) try_compile(<$CFLAGS and + # $LDFLAGS are also passed to the linker. # # If a block given, it is called with the source before compilation. You can # modify the source in the block. @@ -958,6 +1041,10 @@ def append_library(libs, lib) # :no-doc: format(LIBARG, lib) + " " + libs end + # Prints messages to $stdout, if verbose mode. + # + # Internal use only. + # def message(*s) unless Logging.quiet and not $VERBOSE printf(*s) @@ -989,6 +1076,10 @@ def checking_for(m, fmt = nil) r end + # Build a message for checking. + # + # Internal use only. + # def checking_message(target, place = nil, opt = nil) [["in", place], ["with", opt]].inject("#{target}") do |msg, (pre, noun)| if noun @@ -1013,10 +1104,10 @@ def checking_message(target, place = nil, opt = nil) # # [+flags+] a C compiler flag as a +String+ or an +Array+ of them # - def append_cflags(flags, *opts) + def append_cflags(flags, **opts) Array(flags).each do |flag| if checking_for("whether #{flag} is accepted as CFLAGS") { - try_cflags(flag, *opts) + try_cflags(flag, **opts) } $CFLAGS << " " << flag end @@ -1250,6 +1341,7 @@ def have_struct_member(type, member, headers = nil, opt = "", &b) end end + # :nodoc: # Returns whether or not the static type +type+ is defined. # # See also +have_type+ @@ -1307,6 +1399,7 @@ def fmt.%(x) end end + # :nodoc: # Returns whether or not the constant +const+ is defined. # # See also +have_const+ @@ -1466,7 +1559,7 @@ def convertible_int(type, headers = nil, opts = nil, &b) u = "unsigned " if signed > 0 prelude << "extern rbcv_typedef_ foo();" compat = UNIVERSAL_INTS.find {|t| - try_compile([prelude, "extern #{u}#{t} foo();"].join("\n"), opts, :werror=>true, &b) + try_compile([prelude, "extern #{u}#{t} foo();"].join("\n"), opts, werror: true, &b) } end if compat @@ -1490,7 +1583,7 @@ def convertible_int(type, headers = nil, opts = nil, &b) # Used internally by the what_type? method to determine if +type+ is a scalar # pointer. def scalar_ptr_type?(type, member = nil, headers = nil, &b) - try_compile(<<"SRC", &b) # pointer + try_compile(<<"SRC", &b) #{cpp_include(headers)} /*top*/ volatile #{type} conftestval; @@ -1503,7 +1596,7 @@ def scalar_ptr_type?(type, member = nil, headers = nil, &b) # Used internally by the what_type? method to determine if +type+ is a scalar # pointer. def scalar_type?(type, member = nil, headers = nil, &b) - try_compile(<<"SRC", &b) # pointer + try_compile(<<"SRC", &b) #{cpp_include(headers)} /*top*/ volatile #{type} conftestval; @@ -1525,6 +1618,10 @@ def have_typeof? end end + # :startdoc: + + # Returns a string represents the type of _type_, or _member_ of + # _type_ if _member_ is not +nil+. def what_type?(type, member = nil, headers = nil, &b) m = "#{type}" var = val = "*rbcv_var_" @@ -1584,6 +1681,8 @@ def fmt.%(x) end end + # :nodoc: + # # This method is used internally by the find_executable method. # # Internal use only. @@ -1622,8 +1721,6 @@ def find_executable0(bin, path = nil) nil end - # :startdoc: - # Searches for the executable +bin+ on +path+. The default path is your # +PATH+ environment variable. If that isn't defined, it will resort to # searching /usr/local/bin, /usr/ucb, /usr/bin and /bin. @@ -1792,7 +1889,8 @@ def create_header(header = "extconf.h") # application. # def dir_config(target, idefault=nil, ldefault=nil) - if conf = $config_dirs[target] + key = [target, idefault, ldefault].compact.join("\0") + if conf = $config_dirs[key] return conf end @@ -1802,9 +1900,13 @@ def dir_config(target, idefault=nil, ldefault=nil) end idir = with_config(target + "-include", idefault) - $arg_config.last[1] ||= "${#{target}-dir}/include" + if conf = $arg_config.assoc("--with-#{target}-include") + conf[1] ||= "${#{target}-dir}/include" + end ldir = with_config(target + "-lib", ldefault) - $arg_config.last[1] ||= "${#{target}-dir}/#{_libdir_basename}" + if conf = $arg_config.assoc("--with-#{target}-lib") + conf[1] ||= "${#{target}-dir}/#{_libdir_basename}" + end idirs = idir ? Array === idir ? idir.dup : idir.split(File::PATH_SEPARATOR) : [] if defaults @@ -1826,7 +1928,7 @@ def dir_config(target, idefault=nil, ldefault=nil) end $LIBPATH = ldirs | $LIBPATH - $config_dirs[target] = [idir, ldir] + $config_dirs[key] = [idir, ldir] end # Returns compile/link information about an installed library in a tuple of [cflags, @@ -1866,7 +1968,7 @@ def fmt.%(x) if pkgconfig = with_config("#{pkg}-config") and find_executable0(pkgconfig) # if and only if package specific config command is given elsif ($PKGCONFIG ||= - (pkgconfig = with_config("pkg-config") {config_string("PKG_CONFIG") || "pkg-config"}) && + (pkgconfig = with_config("pkg-config") {config_string("PKG_CONFIG") || ENV["PKG_CONFIG"] || "pkg-config"}) && find_executable0(pkgconfig) && pkgconfig) and xsystem([*envs, $PKGCONFIG, "--exists", pkg]) # default to pkg-config command @@ -1882,7 +1984,20 @@ def fmt.%(x) opts = Array(opts).map { |o| "--#{o}" } opts = xpopen([*envs, pkgconfig, *opts, *args], err:[:child, :out], &:read) Logging.open {puts opts.each_line.map{|s|"=> #{s.inspect}"}} - opts.strip if $?.success? + if $?.success? + opts = opts.strip + libarg, libpath = LIBARG, LIBPATHFLAG.strip + opts = opts.shellsplit.map { |s| + if s.start_with?('-l') + libarg % s[2..] + elsif s.start_with?('-L') + libpath % s[2..] + else + s + end + }.quote.join(" ") + opts + end } end orig_ldflags = $LDFLAGS @@ -2064,7 +2179,9 @@ def configuration(srcdir) DLDFLAGS = $(ldflags) $(dldflags) $(ARCH_FLAG) LDSHARED = #{CONFIG['LDSHARED']} LDSHAREDXX = #{config_string('LDSHAREDXX') || '$(LDSHARED)'} +POSTLINK = #{config_string('POSTLINK', RbConfig::CONFIG)} AR = #{CONFIG['AR']} +LD = #{CONFIG['LD']} EXEEXT = #{CONFIG['EXEEXT']} } @@ -2264,6 +2381,19 @@ def depend_rules(depend) # directory, i.e. the current directory. It is included as part of the # +VPATH+ and added to the list of +INCFLAGS+. # + # Yields the configuration part of the makefile to be generated, as an array + # of strings, if the block is given. The returned value will be used the + # new configuration part. + # + # create_makefile('foo') {|conf| + # [ + # *conf, + # "MACRO_YOU_NEED = something", + # ] + # } + # + # If "depend" file exist in the source directory, that content will be + # included in the generated makefile, with formatted by depend_rules method. def create_makefile(target, srcprefix = nil) $target = target libpath = $DEFLIBPATH|$LIBPATH @@ -2372,7 +2502,7 @@ def create_makefile(target, srcprefix = nil) DLLIB = #{dllib} EXTSTATIC = #{$static || ""} STATIC_LIB = #{staticlib unless $static.nil?} -#{!$extout && defined?($installed_list) ? "INSTALLED_LIST = #{$installed_list}\n" : ""} +#{!$extout && defined?($installed_list) ? %[INSTALLED_LIST = #{$installed_list}\n] : ""} TIMESTAMP_DIR = #{$extout && $extmk ? '$(extout)/.timestamp' : '.'} " #" # TODO: fixme @@ -2380,16 +2510,19 @@ def create_makefile(target, srcprefix = nil) sodir = $extout ? '$(TARGET_SO_DIR)' : '$(RUBYARCHDIR)' n = '$(TARGET_SO_DIR)$(TARGET)' cleanobjs = ["$(OBJS)"] + cleanlibs = [] if $extmk %w[bc i s].each {|ex| cleanobjs << "$(OBJS:.#{$OBJEXT}=.#{ex})"} end if target config_string('cleanobjs') {|t| cleanobjs << t.gsub(/\$\*/, "$(TARGET)#{deffile ? '-$(arch)': ''}")} + cleanlibs << '$(TARGET_SO)' end + config_string('cleanlibs') {|t| cleanlibs << t.gsub(/\$\*/) {n}} conf << "\ TARGET_SO_DIR =#{$extout ? " $(RUBYARCHDIR)/" : ''} TARGET_SO = $(TARGET_SO_DIR)$(DLLIB) -CLEANLIBS = #{'$(TARGET_SO) ' if target}#{config_string('cleanlibs') {|t| t.gsub(/\$\*/) {n}}} +CLEANLIBS = #{cleanlibs.join(' ')} CLEANOBJS = #{cleanobjs.join(' ')} *.bak TARGET_SO_DIR_TIMESTAMP = #{timestamp_file(sodir, target_prefix)} " #" @@ -2399,7 +2532,7 @@ def create_makefile(target, srcprefix = nil) mfile.puts(conf) mfile.print " all: #{$extout ? "install" : target ? "$(DLLIB)" : "Makefile"} -static: #{$extmk && !$static ? "all" : "$(STATIC_LIB)#{$extout ? " install-rb" : ""}"} +static: #{$extmk && !$static ? "all" : %[$(STATIC_LIB)#{$extout ? " install-rb" : ""}]} .PHONY: all install static install-so install-rb .PHONY: clean clean-so clean-static clean-rb " #" @@ -2430,6 +2563,7 @@ def create_makefile(target, srcprefix = nil) mfile.puts dest mfile.print "clean-so::\n" mfile.print "\t-$(Q)$(RM) #{fseprepl[dest]} #{fseprepl[stamp]}\n" + mfile.print "\t-$(Q)$(RM_RF) #{fseprepl['$(CLEANLIBS)']}\n" mfile.print "\t-$(Q)$(RMDIRS) #{fseprepl[dir]}#{$ignore_error}\n" else mfile.print "#{f} #{stamp}\n" @@ -2460,7 +2594,7 @@ def create_makefile(target, srcprefix = nil) dest = "#{dir}/#{File.basename(f)}" mfile.print("do-install-rb#{sfx}: #{dest}\n") mfile.print("#{dest}: #{f} #{timestamp_file(dir, target_prefix)}\n") - mfile.print("\t$(Q) $(#{$extout ? 'COPY' : 'INSTALL_DATA'}) #{f} $(@D)\n") + mfile.print("\t$(Q) $(#{$extout ? 'COPY' : 'INSTALL_DATA'}) #{f} $@\n") if defined?($installed_list) and !$extout mfile.print("\t@echo #{dest}>>$(INSTALLED_LIST)\n") end @@ -2722,6 +2856,9 @@ def MAIN_DOES_NOTHING(*refs) split = Shellwords.method(:shellwords).to_proc + ## + # The prefix added to exported symbols automatically + EXPORT_PREFIX = config_string('EXPORT_PREFIX') {|s| s.strip} hdr = ['#include "ruby.h"' "\n"] @@ -2751,6 +2888,10 @@ def MAIN_DOES_NOTHING(*refs) # make compile rules COMPILE_RULES = config_string('COMPILE_RULES', &split) || %w[.%s.%s:] + + ## + # Substitution in rules for NMake + RULE_SUBST = config_string('RULE_SUBST') ## @@ -2795,7 +2936,11 @@ def MAIN_DOES_NOTHING(*refs) ## # Argument which will add a library path to the linker - LIBPATHFLAG = config_string('LIBPATHFLAG') || ' -L%s' + LIBPATHFLAG = config_string('LIBPATHFLAG') || '-L%s' + + ## + # Argument which will add a runtime library path to the linker + RPATHFLAG = config_string('RPATHFLAG') || '' ## @@ -2807,6 +2952,10 @@ def MAIN_DOES_NOTHING(*refs) # A C main function which does no work MAIN_DOES_NOTHING = config_string('MAIN_DOES_NOTHING') || "int main(int argc, char **argv)\n{\n return !!argv[argc];\n}" + + ## + # The type names for convertible_int + UNIVERSAL_INTS = config_string('UNIVERSAL_INTS') {|s| Shellwords.shellwords(s)} || %w[int short long long\ long] @@ -2837,18 +2986,32 @@ def MAIN_DOES_NOTHING(*refs) @lang = Hash.new(self) + ## + # Retrieves the module for _name_ language. def self.[](name) @lang.fetch(name) end + ## + # Defines the module for _name_ language. def self.[]=(name, mod) @lang[name] = mod end - self["C++"] = Module.new do + ## + # The language that this module is for + LANGUAGE = -"C" + + self[self::LANGUAGE] = self + + cxx = Module.new do + # Module for C++ + include MakeMakefile extend self + # :stopdoc: + CONFTEST_CXX = "#{CONFTEST}.#{config_string('CXX_EXT') || CXX_EXT[0]}" TRY_LINK_CXX = config_string('TRY_LINK_CXX') || @@ -2878,7 +3041,12 @@ def link_command(ldflags, *opts) conf = link_config(ldflags, *opts) RbConfig::expand(TRY_LINK_CXX.dup, conf) end + + # :startdoc: end + + cxx::LANGUAGE = -"C++" + self[cxx::LANGUAGE] = cxx end # MakeMakefile::Global = # diff --git a/lib/mutex_m.gemspec b/lib/mutex_m.gemspec deleted file mode 100644 index ebbda2606c9fb5..00000000000000 --- a/lib/mutex_m.gemspec +++ /dev/null @@ -1,28 +0,0 @@ -begin - require_relative "lib/mutex_m" -rescue LoadError - # for Ruby core repository - require_relative "mutex_m" -end - -Gem::Specification.new do |spec| - spec.name = "mutex_m" - spec.version = Mutex_m::VERSION - spec.authors = ["Keiju ISHITSUKA"] - spec.email = ["keiju@ruby-lang.org"] - - spec.summary = %q{Mixin to extend objects to be handled like a Mutex.} - spec.description = %q{Mixin to extend objects to be handled like a Mutex.} - spec.homepage = "https://github.com/ruby/mutex_m" - spec.licenses = ["Ruby", "BSD-2-Clause"] - - spec.files = ["Gemfile", "LICENSE.txt", "README.md", "Rakefile", "lib/mutex_m.rb", "mutex_m.gemspec"] - spec.bindir = "exe" - spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } - spec.require_paths = ["lib"] - spec.required_ruby_version = '>= 2.5' - - spec.add_development_dependency "bundler" - spec.add_development_dependency "rake" - spec.add_development_dependency "test-unit" -end diff --git a/lib/mutex_m.rb b/lib/mutex_m.rb deleted file mode 100644 index 4c888d6a1751dc..00000000000000 --- a/lib/mutex_m.rb +++ /dev/null @@ -1,116 +0,0 @@ -# frozen_string_literal: false -# -# mutex_m.rb - -# $Release Version: 3.0$ -# $Revision: 1.7 $ -# Original from mutex.rb -# by Keiju ISHITSUKA(keiju@ishitsuka.com) -# modified by matz -# patched by akira yamada -# -# -- - -# = mutex_m.rb -# -# When 'mutex_m' is required, any object that extends or includes Mutex_m will -# be treated like a Mutex. -# -# Start by requiring the standard library Mutex_m: -# -# require "mutex_m.rb" -# -# From here you can extend an object with Mutex instance methods: -# -# obj = Object.new -# obj.extend Mutex_m -# -# Or mixin Mutex_m into your module to your class inherit Mutex instance -# methods --- remember to call super() in your class initialize method. -# -# class Foo -# include Mutex_m -# def initialize -# # ... -# super() -# end -# # ... -# end -# obj = Foo.new -# # this obj can be handled like Mutex -# -module Mutex_m - - VERSION = "0.1.2" - Ractor.make_shareable(VERSION) if defined?(Ractor) - - def Mutex_m.define_aliases(cl) # :nodoc: - cl.alias_method(:locked?, :mu_locked?) - cl.alias_method(:lock, :mu_lock) - cl.alias_method(:unlock, :mu_unlock) - cl.alias_method(:try_lock, :mu_try_lock) - cl.alias_method(:synchronize, :mu_synchronize) - end - - def Mutex_m.append_features(cl) # :nodoc: - super - define_aliases(cl) unless cl.instance_of?(Module) - end - - def Mutex_m.extend_object(obj) # :nodoc: - super - obj.mu_extended - end - - def mu_extended # :nodoc: - unless (defined? locked? and - defined? lock and - defined? unlock and - defined? try_lock and - defined? synchronize) - Mutex_m.define_aliases(singleton_class) - end - mu_initialize - end - - # See Thread::Mutex#synchronize - def mu_synchronize(&block) - @_mutex.synchronize(&block) - end - - # See Thread::Mutex#locked? - def mu_locked? - @_mutex.locked? - end - - # See Thread::Mutex#try_lock - def mu_try_lock - @_mutex.try_lock - end - - # See Thread::Mutex#lock - def mu_lock - @_mutex.lock - end - - # See Thread::Mutex#unlock - def mu_unlock - @_mutex.unlock - end - - # See Thread::Mutex#sleep - def sleep(timeout = nil) - @_mutex.sleep(timeout) - end - - private - - def mu_initialize # :nodoc: - @_mutex = Thread::Mutex.new - end - - def initialize(*args) # :nodoc: - mu_initialize - super - end - ruby2_keywords(:initialize) if respond_to?(:ruby2_keywords, true) -end diff --git a/lib/net/http.rb b/lib/net/http.rb index ff780b45bd3c2a..85051a44680118 100644 --- a/lib/net/http.rb +++ b/lib/net/http.rb @@ -67,6 +67,8 @@ class HTTPHeaderSyntaxError < StandardError; end # Net::HTTP.post(uri, data) # params = {title: 'foo', body: 'bar', userId: 1} # Net::HTTP.post_form(uri, params) + # data = '{"title": "foo", "body": "bar", "userId": 1}' + # Net::HTTP.put(uri, data) # # - If performance is important, consider using sessions, which lower request overhead. # This {session}[rdoc-ref:Net::HTTP@Sessions] has multiple requests for @@ -456,6 +458,10 @@ class HTTPHeaderSyntaxError < StandardError; end # # == What's Here # + # First, what's elsewhere. Class Net::HTTP: + # + # - Inherits from {class Object}[rdoc-ref:Object@What-27s+Here]. + # # This is a categorized summary of methods and attributes. # # === \Net::HTTP Objects @@ -469,8 +475,7 @@ class HTTPHeaderSyntaxError < StandardError; end # # - {::start}[rdoc-ref:Net::HTTP.start]: # Begins a new session in a new \Net::HTTP object. - # - {#started?}[rdoc-ref:Net::HTTP#started?] - # (aliased as {#active?}[rdoc-ref:Net::HTTP#active?]): + # - {#started?}[rdoc-ref:Net::HTTP#started?]: # Returns whether in a session. # - {#finish}[rdoc-ref:Net::HTTP#finish]: # Ends an active session. @@ -520,6 +525,8 @@ class HTTPHeaderSyntaxError < StandardError; end # Sends a POST request with form data and returns a response object. # - {::post}[rdoc-ref:Net::HTTP.post]: # Sends a POST request with data and returns a response object. + # - {::put}[rdoc-ref:Net::HTTP.put]: + # Sends a PUT request with data and returns a response object. # - {#copy}[rdoc-ref:Net::HTTP#copy]: # Sends a COPY request and returns a response object. # - {#delete}[rdoc-ref:Net::HTTP#delete]: @@ -548,18 +555,15 @@ class HTTPHeaderSyntaxError < StandardError; end # Sends a PUT request and returns a response object. # - {#request}[rdoc-ref:Net::HTTP#request]: # Sends a request and returns a response object. - # - {#request_get}[rdoc-ref:Net::HTTP#request_get] - # (aliased as {#get2}[rdoc-ref:Net::HTTP#get2]): + # - {#request_get}[rdoc-ref:Net::HTTP#request_get]: # Sends a GET request and forms a response object; # if a block given, calls the block with the object, # otherwise returns the object. - # - {#request_head}[rdoc-ref:Net::HTTP#request_head] - # (aliased as {#head2}[rdoc-ref:Net::HTTP#head2]): + # - {#request_head}[rdoc-ref:Net::HTTP#request_head]: # Sends a HEAD request and forms a response object; # if a block given, calls the block with the object, # otherwise returns the object. - # - {#request_post}[rdoc-ref:Net::HTTP#request_post] - # (aliased as {#post2}[rdoc-ref:Net::HTTP#post2]): + # - {#request_post}[rdoc-ref:Net::HTTP#request_post]: # Sends a POST request and forms a response object; # if a block given, calls the block with the object, # otherwise returns the object. @@ -597,8 +601,7 @@ class HTTPHeaderSyntaxError < StandardError; end # Returns whether +self+ is a proxy class. # - {#proxy?}[rdoc-ref:Net::HTTP#proxy?]: # Returns whether +self+ has a proxy. - # - {#proxy_address}[rdoc-ref:Net::HTTP#proxy_address] - # (aliased as {#proxyaddr}[rdoc-ref:Net::HTTP#proxyaddr]): + # - {#proxy_address}[rdoc-ref:Net::HTTP#proxy_address]: # Returns the proxy address. # - {#proxy_from_env?}[rdoc-ref:Net::HTTP#proxy_from_env?]: # Returns whether the proxy is taken from an environment variable. @@ -710,8 +713,7 @@ class HTTPHeaderSyntaxError < StandardError; end # === \HTTP Version # # - {::version_1_2?}[rdoc-ref:Net::HTTP.version_1_2?] - # (aliased as {::is_version_1_2?}[rdoc-ref:Net::HTTP.is_version_1_2?] - # and {::version_1_2}[rdoc-ref:Net::HTTP.version_1_2]): + # (aliased as {::version_1_2}[rdoc-ref:Net::HTTP.version_1_2]): # Returns true; retained for compatibility. # # === Debugging @@ -722,8 +724,7 @@ class HTTPHeaderSyntaxError < StandardError; end class HTTP < Protocol # :stopdoc: - VERSION = "0.3.2" - Revision = %q$Revision$.split[1] + VERSION = "0.6.0" HTTPVersion = '1.1' begin require 'zlib' @@ -890,6 +891,39 @@ def HTTP.post_form(url, params) } end + # Sends a PUT request to the server; returns a Net::HTTPResponse object. + # + # Argument +url+ must be a URL; + # argument +data+ must be a string: + # + # _uri = uri.dup + # _uri.path = '/posts' + # data = '{"title": "foo", "body": "bar", "userId": 1}' + # headers = {'content-type': 'application/json'} + # res = Net::HTTP.put(_uri, data, headers) # => # + # puts res.body + # + # Output: + # + # { + # "title": "foo", + # "body": "bar", + # "userId": 1, + # "id": 101 + # } + # + # Related: + # + # - Net::HTTP::Put: request class for \HTTP method +PUT+. + # - Net::HTTP#put: convenience method for \HTTP method +PUT+. + # + def HTTP.put(url, data, header = nil) + start(url.hostname, url.port, + :use_ssl => url.scheme == 'https' ) {|http| + http.put(url, data, header) + } + end + # # \HTTP session management # @@ -1063,7 +1097,7 @@ class << HTTP # For proxy-defining arguments +p_addr+ through +p_no_proxy+, # see {Proxy Server}[rdoc-ref:Net::HTTP@Proxy+Server]. # - def HTTP.new(address, port = nil, p_addr = :ENV, p_port = nil, p_user = nil, p_pass = nil, p_no_proxy = nil) + def HTTP.new(address, port = nil, p_addr = :ENV, p_port = nil, p_user = nil, p_pass = nil, p_no_proxy = nil, p_use_ssl = nil) http = super address, port if proxy_class? then # from Net::HTTP::Proxy() @@ -1072,10 +1106,11 @@ def HTTP.new(address, port = nil, p_addr = :ENV, p_port = nil, p_user = nil, p_p http.proxy_port = @proxy_port http.proxy_user = @proxy_user http.proxy_pass = @proxy_pass + http.proxy_use_ssl = @proxy_use_ssl elsif p_addr == :ENV then http.proxy_from_env = true else - if p_addr && p_no_proxy && !URI::Generic.use_proxy?(p_addr, p_addr, p_port, p_no_proxy) + if p_addr && p_no_proxy && !URI::Generic.use_proxy?(address, address, port, p_no_proxy) p_addr = nil p_port = nil end @@ -1083,34 +1118,67 @@ def HTTP.new(address, port = nil, p_addr = :ENV, p_port = nil, p_user = nil, p_p http.proxy_port = p_port || default_port http.proxy_user = p_user http.proxy_pass = p_pass + http.proxy_use_ssl = p_use_ssl end http end + class << HTTP + # Allows to set the default configuration that will be used + # when creating a new connection. + # + # Example: + # + # Net::HTTP.default_configuration = { + # read_timeout: 1, + # write_timeout: 1 + # } + # http = Net::HTTP.new(hostname) + # http.open_timeout # => 60 + # http.read_timeout # => 1 + # http.write_timeout # => 1 + # + attr_accessor :default_configuration + end + # Creates a new \Net::HTTP object for the specified server address, # without opening the TCP connection or initializing the \HTTP session. # The +address+ should be a DNS hostname or IP address. def initialize(address, port = nil) # :nodoc: + defaults = { + keep_alive_timeout: 2, + close_on_empty_response: false, + open_timeout: 60, + read_timeout: 60, + write_timeout: 60, + continue_timeout: nil, + max_retries: 1, + debug_output: nil, + response_body_encoding: false, + ignore_eof: true + } + options = defaults.merge(self.class.default_configuration || {}) + @address = address @port = (port || HTTP.default_port) @ipaddr = nil @local_host = nil @local_port = nil @curr_http_version = HTTPVersion - @keep_alive_timeout = 2 + @keep_alive_timeout = options[:keep_alive_timeout] @last_communicated = nil - @close_on_empty_response = false + @close_on_empty_response = options[:close_on_empty_response] @socket = nil @started = false - @open_timeout = 60 - @read_timeout = 60 - @write_timeout = 60 - @continue_timeout = nil - @max_retries = 1 - @debug_output = nil - @response_body_encoding = false - @ignore_eof = true + @open_timeout = options[:open_timeout] + @read_timeout = options[:read_timeout] + @write_timeout = options[:write_timeout] + @continue_timeout = options[:continue_timeout] + @max_retries = options[:max_retries] + @debug_output = options[:debug_output] + @response_body_encoding = options[:response_body_encoding] + @ignore_eof = options[:ignore_eof] @proxy_from_env = false @proxy_uri = nil @@ -1118,6 +1186,7 @@ def initialize(address, port = nil) # :nodoc: @proxy_port = nil @proxy_user = nil @proxy_pass = nil + @proxy_use_ssl = nil @use_ssl = false @ssl_context = nil @@ -1252,6 +1321,7 @@ def response_body_encoding=(value) # Sets the proxy password; # see {Proxy Server}[rdoc-ref:Net::HTTP@Proxy+Server]. attr_writer :proxy_pass + attr_writer :proxy_use_ssl # Returns the IP address for the connection. # @@ -1441,23 +1511,6 @@ def use_ssl=(flag) @use_ssl = flag end - SSL_IVNAMES = [ - :@ca_file, - :@ca_path, - :@cert, - :@cert_store, - :@ciphers, - :@extra_chain_cert, - :@key, - :@ssl_timeout, - :@ssl_version, - :@min_version, - :@max_version, - :@verify_callback, - :@verify_depth, - :@verify_mode, - :@verify_hostname, - ] # :nodoc: SSL_ATTRIBUTES = [ :ca_file, :ca_path, @@ -1476,6 +1529,8 @@ def use_ssl=(flag) :verify_hostname, ] # :nodoc: + SSL_IVNAMES = SSL_ATTRIBUTES.map { |a| "@#{a}".to_sym }.freeze # :nodoc: + # Sets or returns the path to a CA certification file in PEM format. attr_accessor :ca_file @@ -1491,11 +1546,11 @@ def use_ssl=(flag) attr_accessor :cert_store # Sets or returns the available SSL ciphers. - # See {OpenSSL::SSL::SSLContext#ciphers=}[rdoc-ref:OpenSSL::SSL::SSLContext#ciphers-3D]. + # See {OpenSSL::SSL::SSLContext#ciphers=}[OpenSSL::SSL::SSL::Context#ciphers=]. attr_accessor :ciphers # Sets or returns the extra X509 certificates to be added to the certificate chain. - # See {OpenSSL::SSL::SSLContext#add_certificate}[rdoc-ref:OpenSSL::SSL::SSLContext#add_certificate]. + # See {OpenSSL::SSL::SSLContext#add_certificate}[OpenSSL::SSL::SSL::Context#add_certificate]. attr_accessor :extra_chain_cert # Sets or returns the OpenSSL::PKey::RSA or OpenSSL::PKey::DSA object. @@ -1505,15 +1560,15 @@ def use_ssl=(flag) attr_accessor :ssl_timeout # Sets or returns the SSL version. - # See {OpenSSL::SSL::SSLContext#ssl_version=}[rdoc-ref:OpenSSL::SSL::SSLContext#ssl_version-3D]. + # See {OpenSSL::SSL::SSLContext#ssl_version=}[OpenSSL::SSL::SSL::Context#ssl_version=]. attr_accessor :ssl_version # Sets or returns the minimum SSL version. - # See {OpenSSL::SSL::SSLContext#min_version=}[rdoc-ref:OpenSSL::SSL::SSLContext#min_version-3D]. + # See {OpenSSL::SSL::SSLContext#min_version=}[OpenSSL::SSL::SSL::Context#min_version=]. attr_accessor :min_version # Sets or returns the maximum SSL version. - # See {OpenSSL::SSL::SSLContext#max_version=}[rdoc-ref:OpenSSL::SSL::SSLContext#max_version-3D]. + # See {OpenSSL::SSL::SSLContext#max_version=}[OpenSSL::SSL::SSL::Context#max_version=]. attr_accessor :max_version # Sets or returns the callback for the server certification verification. @@ -1529,7 +1584,7 @@ def use_ssl=(flag) # Sets or returns whether to verify that the server certificate is valid # for the hostname. - # See {OpenSSL::SSL::SSLContext#verify_hostname=}[rdoc-ref:OpenSSL::SSL::SSLContext#attribute-i-verify_mode]. + # See {OpenSSL::SSL::SSLContext#verify_hostname=}[OpenSSL::SSL::SSL::Context#verify_hostname=]. attr_accessor :verify_hostname # Returns the X509 certificate chain (an array of strings) @@ -1611,7 +1666,13 @@ def connect debug "opened" if use_ssl? if proxy? - plain_sock = BufferedIO.new(s, read_timeout: @read_timeout, + if @proxy_use_ssl + proxy_sock = OpenSSL::SSL::SSLSocket.new(s) + ssl_socket_connect(proxy_sock, @open_timeout) + else + proxy_sock = s + end + proxy_sock = BufferedIO.new(proxy_sock, read_timeout: @read_timeout, write_timeout: @write_timeout, continue_timeout: @continue_timeout, debug_output: @debug_output) @@ -1622,8 +1683,8 @@ def connect buf << "Proxy-Authorization: Basic #{credential}\r\n" end buf << "\r\n" - plain_sock.write(buf) - HTTPResponse.read_new(plain_sock).value + proxy_sock.write(buf) + HTTPResponse.read_new(proxy_sock).value # assuming nothing left in buffers after successful CONNECT response end @@ -1731,13 +1792,14 @@ def do_finish @proxy_port = nil @proxy_user = nil @proxy_pass = nil + @proxy_use_ssl = nil # Creates an \HTTP proxy class which behaves like \Net::HTTP, but # performs all access via the specified proxy. # # This class is obsolete. You may pass these same parameters directly to # \Net::HTTP.new. See Net::HTTP.new for details of the arguments. - def HTTP.Proxy(p_addr = :ENV, p_port = nil, p_user = nil, p_pass = nil) #:nodoc: + def HTTP.Proxy(p_addr = :ENV, p_port = nil, p_user = nil, p_pass = nil, p_use_ssl = nil) #:nodoc: return self unless p_addr Class.new(self) { @@ -1755,6 +1817,7 @@ def HTTP.Proxy(p_addr = :ENV, p_port = nil, p_user = nil, p_pass = nil) #:nodoc: @proxy_user = p_user @proxy_pass = p_pass + @proxy_use_ssl = p_use_ssl } end @@ -1779,6 +1842,9 @@ def proxy_class? # Returns the password for accessing the proxy, or +nil+ if none; # see Net::HTTP@Proxy+Server. attr_reader :proxy_pass + + # Use SSL when talking to the proxy. If Net::HTTP does not use a proxy, nil. + attr_reader :proxy_use_ssl end # Returns +true+ if a proxy server is defined, +false+ otherwise; @@ -1798,7 +1864,7 @@ def proxy_from_env? def proxy_uri # :nodoc: return if @proxy_uri == false @proxy_uri ||= URI::HTTP.new( - "http".freeze, nil, address, port, nil, nil, nil, nil, nil + "http", nil, address, port, nil, nil, nil, nil, nil ).find_proxy || false @proxy_uri || nil end @@ -1851,7 +1917,8 @@ def proxy_pass private def unescape(value) - require 'cgi/util' + require 'cgi/escape' + require 'cgi/util' unless defined?(CGI::EscapeExt) CGI.unescape(value) end @@ -2013,6 +2080,11 @@ def patch(path, data, initheader = nil, dest = nil, &block) # :yield: +body_segm # http = Net::HTTP.new(hostname) # http.put('/todos/1', data) # => # # + # Related: + # + # - Net::HTTP::Put: request class for \HTTP method PUT. + # - Net::HTTP.put: sends PUT request, returns response body. + # def put(path, data, initheader = nil) request(Put.new(path, initheader), data) end @@ -2351,7 +2423,10 @@ def transport_request(req) res } res.reading_body(@socket, req.response_body_permitted?) { - yield res if block_given? + if block_given? + count = max_retries # Don't restart in the middle of a download + yield res + end } rescue Net::OpenTimeout raise @@ -2479,6 +2554,11 @@ def debug(msg) alias_method :D, :debug end + # for backward compatibility until Ruby 3.5 + # https://bugs.ruby-lang.org/issues/20900 + # https://github.com/bblimke/webmock/pull/1081 + HTTPSession = HTTP + deprecate_constant :HTTPSession end require_relative 'http/exceptions' @@ -2493,5 +2573,3 @@ def debug(msg) require_relative 'http/responses' require_relative 'http/proxy_delta' - -require_relative 'http/backward' diff --git a/lib/net/http/backward.rb b/lib/net/http/backward.rb deleted file mode 100644 index b44577edbd2c6b..00000000000000 --- a/lib/net/http/backward.rb +++ /dev/null @@ -1,40 +0,0 @@ -# frozen_string_literal: true -# for backward compatibility - -# :enddoc: - -class Net::HTTP - ProxyMod = ProxyDelta - deprecate_constant :ProxyMod -end - -module Net::NetPrivate - HTTPRequest = ::Net::HTTPRequest - deprecate_constant :HTTPRequest -end - -module Net - HTTPSession = HTTP - - HTTPInformationCode = HTTPInformation - HTTPSuccessCode = HTTPSuccess - HTTPRedirectionCode = HTTPRedirection - HTTPRetriableCode = HTTPRedirection - HTTPClientErrorCode = HTTPClientError - HTTPFatalErrorCode = HTTPClientError - HTTPServerErrorCode = HTTPServerError - HTTPResponseReceiver = HTTPResponse - - HTTPResponceReceiver = HTTPResponse # Typo since 2001 - - deprecate_constant :HTTPSession, - :HTTPInformationCode, - :HTTPSuccessCode, - :HTTPRedirectionCode, - :HTTPRetriableCode, - :HTTPClientErrorCode, - :HTTPFatalErrorCode, - :HTTPServerErrorCode, - :HTTPResponseReceiver, - :HTTPResponceReceiver -end diff --git a/lib/net/http/generic_request.rb b/lib/net/http/generic_request.rb index 9421535ceb2e45..c92004e5578b38 100644 --- a/lib/net/http/generic_request.rb +++ b/lib/net/http/generic_request.rb @@ -23,7 +23,7 @@ def initialize(m, reqbody, resbody, uri_or_path, initheader = nil) # :nodoc: raise ArgumentError, "no host component for URI" unless (hostname && hostname.length > 0) @uri = uri_or_path.dup host = @uri.hostname.dup - host << ":".freeze << @uri.port.to_s if @uri.port != @uri.default_port + host << ":" << @uri.port.to_s if @uri.port != @uri.default_port @path = uri_or_path.request_uri raise ArgumentError, "no HTTP request path given" unless @path else @@ -102,6 +102,31 @@ def inspect "\#<#{self.class} #{@method}>" end + # Returns a string representation of the request with the details for pp: + # + # require 'pp' + # post = Net::HTTP::Post.new(uri) + # post.inspect # => "#" + # post.pretty_inspect + # # => # ["gzip;q=1.0,deflate;q=0.6,identity;q=0.3"], + # "accept" => ["*/*"], + # "user-agent" => ["Ruby"], + # "host" => ["www.ruby-lang.org"]}> + # + def pretty_print(q) + q.object_group(self) { + q.breakable + q.text @method + q.breakable + q.text "path="; q.pp @path + q.breakable + q.text "headers="; q.pp to_hash + } + end + ## # Don't automatically decode response content-encoding if the user indicates # they want to handle it. @@ -212,15 +237,15 @@ def update_uri(addr, port, ssl) # :nodoc: internal use only return unless @uri if ssl - scheme = 'https'.freeze + scheme = 'https' klass = URI::HTTPS else - scheme = 'http'.freeze + scheme = 'http' klass = URI::HTTP end if host = self['host'] - host.sub!(/:.*/m, ''.freeze) + host.sub!(/:.*/m, '') elsif host = @uri.host else host = addr @@ -260,7 +285,6 @@ def finish def send_request_with_body(sock, ver, path, body) self.content_length = body.bytesize delete 'Transfer-Encoding' - supply_default_content_type write_header sock, ver, path wait_for_continue sock, ver if sock.continue_timeout sock.write body @@ -271,7 +295,6 @@ def send_request_with_body_stream(sock, ver, path, f) raise ArgumentError, "Content-Length not given and Transfer-Encoding is not `chunked'" end - supply_default_content_type write_header sock, ver, path wait_for_continue sock, ver if sock.continue_timeout if chunked? @@ -373,12 +396,6 @@ def flush_buffer(out, buf, chunked_p) buf.clear end - def supply_default_content_type - return if content_type() - warn 'net/http: Content-Type did not set; using application/x-www-form-urlencoded', uplevel: 1 if $VERBOSE - set_content_type 'application/x-www-form-urlencoded' - end - ## # Waits up to the continue timeout for a response from the server provided # we're speaking HTTP 1.1 and are expecting a 100-continue response. @@ -411,4 +428,3 @@ def write_header(sock, ver, path) end end - diff --git a/lib/net/http/header.rb b/lib/net/http/header.rb index 6660c8075a4230..f6c36f1b5e78e7 100644 --- a/lib/net/http/header.rb +++ b/lib/net/http/header.rb @@ -491,7 +491,7 @@ def each_capitalized alias canonical_each each_capitalized def capitalize(name) - name.to_s.split(/-/).map {|s| s.capitalize }.join('-') + name.to_s.split('-'.freeze).map {|s| s.capitalize }.join('-'.freeze) end private :capitalize diff --git a/lib/net/http/net-http.gemspec b/lib/net/http/net-http.gemspec index 0021136793b928..70528d58cb34af 100644 --- a/lib/net/http/net-http.gemspec +++ b/lib/net/http/net-http.gemspec @@ -24,6 +24,7 @@ Gem::Specification.new do |spec| spec.required_ruby_version = Gem::Requirement.new(">= 2.6.0") spec.licenses = ["Ruby", "BSD-2-Clause"] + spec.metadata["changelog_uri"] = spec.homepage + "/releases" spec.metadata["homepage_uri"] = spec.homepage spec.metadata["source_code_uri"] = spec.homepage diff --git a/lib/net/http/requests.rb b/lib/net/http/requests.rb index 5724164205e61b..e58057adf1664c 100644 --- a/lib/net/http/requests.rb +++ b/lib/net/http/requests.rb @@ -124,6 +124,11 @@ class Net::HTTP::Post < Net::HTTPRequest # - {Idempotent}[https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Idempotent_methods]: yes. # - {Cacheable}[https://en.wikipedia.org/wiki/Hypertext_Transfer_Protocol#Cacheable_methods]: no. # +# Related: +# +# - Net::HTTP.put: sends +PUT+ request, returns response object. +# - Net::HTTP#put: sends +PUT+ request, returns response object. +# class Net::HTTP::Put < Net::HTTPRequest METHOD = 'PUT' REQUEST_HAS_BODY = true diff --git a/lib/net/http/response.rb b/lib/net/http/response.rb index 192fa2c749c860..40de96386804f3 100644 --- a/lib/net/http/response.rb +++ b/lib/net/http/response.rb @@ -366,6 +366,7 @@ def read_body(dest = nil, &block) @body = nil end @read = true + return if @body.nil? case enc = @body_encoding when Encoding, false, nil @@ -639,7 +640,7 @@ def read_chunked(dest, chunk_data_io) # :nodoc: end def stream_check - raise IOError, 'attempt to read body out of block' if @socket.closed? + raise IOError, 'attempt to read body out of block' if @socket.nil? || @socket.closed? end def procdest(dest, block) diff --git a/lib/net/http/responses.rb b/lib/net/http/responses.rb index 6f6fb8d0554318..5e2f8ce1aa176a 100644 --- a/lib/net/http/responses.rb +++ b/lib/net/http/responses.rb @@ -1104,7 +1104,7 @@ class Net::HTTPResponse '3' => Net::HTTPRedirection, '4' => Net::HTTPClientError, '5' => Net::HTTPServerError - } + }.freeze CODE_TO_OBJ = { '100' => Net::HTTPContinue, '101' => Net::HTTPSwitchProtocol, @@ -1170,5 +1170,5 @@ class Net::HTTPResponse '508' => Net::HTTPLoopDetected, '510' => Net::HTTPNotExtended, '511' => Net::HTTPNetworkAuthenticationRequired, - } + }.freeze end diff --git a/lib/net/net-protocol.gemspec b/lib/net/net-protocol.gemspec index 29ad2504ebce90..f9fd83f12b05f2 100644 --- a/lib/net/net-protocol.gemspec +++ b/lib/net/net-protocol.gemspec @@ -21,6 +21,7 @@ Gem::Specification.new do |spec| spec.metadata["homepage_uri"] = spec.homepage spec.metadata["source_code_uri"] = spec.homepage + spec.metadata["changelog_uri"] = spec.homepage + "/releases" # Specify which files should be added to the gem when it is released. # The `git ls-files -z` loads the files in the RubyGem that have been added into git. diff --git a/lib/net/protocol.rb b/lib/net/protocol.rb index ea0752a9719364..197ea090890f76 100644 --- a/lib/net/protocol.rb +++ b/lib/net/protocol.rb @@ -26,7 +26,7 @@ module Net # :nodoc: class Protocol #:nodoc: internal use only - VERSION = "0.2.1" + VERSION = "0.2.2" private def Protocol.protocol_param(name, val) diff --git a/lib/observer.gemspec b/lib/observer.gemspec deleted file mode 100644 index 93e61b8c842d07..00000000000000 --- a/lib/observer.gemspec +++ /dev/null @@ -1,32 +0,0 @@ -# frozen_string_literal: true - -name = File.basename(__FILE__, ".gemspec") -version = ["lib", Array.new(name.count("-")+1, ".").join("/")].find do |dir| - break File.foreach(File.join(__dir__, dir, "#{name.tr('-', '/')}.rb")) do |line| - /^\s*VERSION\s*=\s*"(.*)"/ =~ line and break $1 - end rescue nil -end - -Gem::Specification.new do |spec| - spec.name = name - spec.version = version - spec.authors = ["Yukihiro Matsumoto"] - spec.email = ["matz@ruby-lang.org"] - - spec.summary = %q{Implementation of the Observer object-oriented design pattern.} - spec.description = spec.summary - spec.homepage = "https://github.com/ruby/observer" - spec.licenses = ["Ruby", "BSD-2-Clause"] - - spec.metadata["homepage_uri"] = spec.homepage - spec.metadata["source_code_uri"] = spec.homepage - - # Specify which files should be added to the gem when it is released. - # The `git ls-files -z` loads the files in the RubyGem that have been added into git. - spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do - `git ls-files -z 2>#{IO::NULL}`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) } - end - spec.bindir = "exe" - spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } - spec.require_paths = ["lib"] -end diff --git a/lib/observer.rb b/lib/observer.rb deleted file mode 100644 index ef70e39dd823a1..00000000000000 --- a/lib/observer.rb +++ /dev/null @@ -1,229 +0,0 @@ -# frozen_string_literal: true -# -# Implementation of the _Observer_ object-oriented design pattern. The -# following documentation is copied, with modifications, from "Programming -# Ruby", by Hunt and Thomas; http://www.ruby-doc.org/docs/ProgrammingRuby/html/lib_patterns.html. -# -# See Observable for more info. - -# The Observer pattern (also known as publish/subscribe) provides a simple -# mechanism for one object to inform a set of interested third-party objects -# when its state changes. -# -# == Mechanism -# -# The notifying class mixes in the +Observable+ -# module, which provides the methods for managing the associated observer -# objects. -# -# The observable object must: -# * assert that it has +#changed+ -# * call +#notify_observers+ -# -# An observer subscribes to updates using Observable#add_observer, which also -# specifies the method called via #notify_observers. The default method for -# #notify_observers is #update. -# -# === Example -# -# The following example demonstrates this nicely. A +Ticker+, when run, -# continually receives the stock +Price+ for its @symbol. A +Warner+ -# is a general observer of the price, and two warners are demonstrated, a -# +WarnLow+ and a +WarnHigh+, which print a warning if the price is below or -# above their set limits, respectively. -# -# The +update+ callback allows the warners to run without being explicitly -# called. The system is set up with the +Ticker+ and several observers, and the -# observers do their duty without the top-level code having to interfere. -# -# Note that the contract between publisher and subscriber (observable and -# observer) is not declared or enforced. The +Ticker+ publishes a time and a -# price, and the warners receive that. But if you don't ensure that your -# contracts are correct, nothing else can warn you. -# -# require "observer" -# -# class Ticker ### Periodically fetch a stock price. -# include Observable -# -# def initialize(symbol) -# @symbol = symbol -# end -# -# def run -# last_price = nil -# loop do -# price = Price.fetch(@symbol) -# print "Current price: #{price}\n" -# if price != last_price -# changed # notify observers -# last_price = price -# notify_observers(Time.now, price) -# end -# sleep 1 -# end -# end -# end -# -# class Price ### A mock class to fetch a stock price (60 - 140). -# def self.fetch(symbol) -# 60 + rand(80) -# end -# end -# -# class Warner ### An abstract observer of Ticker objects. -# def initialize(ticker, limit) -# @limit = limit -# ticker.add_observer(self) -# end -# end -# -# class WarnLow < Warner -# def update(time, price) # callback for observer -# if price < @limit -# print "--- #{time.to_s}: Price below #@limit: #{price}\n" -# end -# end -# end -# -# class WarnHigh < Warner -# def update(time, price) # callback for observer -# if price > @limit -# print "+++ #{time.to_s}: Price above #@limit: #{price}\n" -# end -# end -# end -# -# ticker = Ticker.new("MSFT") -# WarnLow.new(ticker, 80) -# WarnHigh.new(ticker, 120) -# ticker.run -# -# Produces: -# -# Current price: 83 -# Current price: 75 -# --- Sun Jun 09 00:10:25 CDT 2002: Price below 80: 75 -# Current price: 90 -# Current price: 134 -# +++ Sun Jun 09 00:10:25 CDT 2002: Price above 120: 134 -# Current price: 134 -# Current price: 112 -# Current price: 79 -# --- Sun Jun 09 00:10:25 CDT 2002: Price below 80: 79 -# -# === Usage with procs -# -# The +#notify_observers+ method can also be used with +proc+s by using -# the +:call+ as +func+ parameter. -# -# The following example illustrates the use of a lambda: -# -# require 'observer' -# -# class Ticker -# include Observable -# -# def run -# # logic to retrieve the price (here 77.0) -# changed -# notify_observers(77.0) -# end -# end -# -# ticker = Ticker.new -# warner = ->(price) { puts "New price received: #{price}" } -# ticker.add_observer(warner, :call) -# ticker.run -module Observable - VERSION = "0.1.1" - - # - # Add +observer+ as an observer on this object. So that it will receive - # notifications. - # - # +observer+:: the object that will be notified of changes. - # +func+:: Symbol naming the method that will be called when this Observable - # has changes. - # - # This method must return true for +observer.respond_to?+ and will - # receive *arg when #notify_observers is called, where - # *arg is the value passed to #notify_observers by this - # Observable - def add_observer(observer, func=:update) - @observer_peers = {} unless defined? @observer_peers - unless observer.respond_to? func - raise NoMethodError, "observer does not respond to `#{func}'" - end - @observer_peers[observer] = func - end - - # - # Remove +observer+ as an observer on this object so that it will no longer - # receive notifications. - # - # +observer+:: An observer of this Observable - def delete_observer(observer) - @observer_peers.delete observer if defined? @observer_peers - end - - # - # Remove all observers associated with this object. - # - def delete_observers - @observer_peers.clear if defined? @observer_peers - end - - # - # Return the number of observers associated with this object. - # - def count_observers - if defined? @observer_peers - @observer_peers.size - else - 0 - end - end - - # - # Set the changed state of this object. Notifications will be sent only if - # the changed +state+ is +true+. - # - # +state+:: Boolean indicating the changed state of this Observable. - # - def changed(state=true) - @observer_state = state - end - - # - # Returns true if this object's state has been changed since the last - # #notify_observers call. - # - def changed? - if defined? @observer_state and @observer_state - true - else - false - end - end - - # - # Notify observers of a change in state *if* this object's changed state is - # +true+. - # - # This will invoke the method named in #add_observer, passing *arg. - # The changed state is then set to +false+. - # - # *arg:: Any arguments to pass to the observers. - def notify_observers(*arg) - if defined? @observer_state and @observer_state - if defined? @observer_peers - @observer_peers.each do |k, v| - k.__send__(v, *arg) - end - end - @observer_state = false - end - end - -end diff --git a/lib/open-uri.rb b/lib/open-uri.rb index 11af0f7a121cc4..de710af261eaa9 100644 --- a/lib/open-uri.rb +++ b/lib/open-uri.rb @@ -91,7 +91,7 @@ def self.open(name, *rest, &block) module OpenURI - VERSION = "0.3.0" + VERSION = "0.5.0" Options = { :proxy => true, @@ -108,6 +108,8 @@ module OpenURI :ftp_active_mode => false, :redirect => true, :encoding => nil, + :max_redirects => 64, + :request_specific_fields => nil, } def OpenURI.check_options(options) # :nodoc: @@ -147,7 +149,11 @@ def OpenURI.open_uri(name, *rest) # :nodoc: end encoding = Encoding.find(options[:encoding]) end - + if options.has_key? :request_specific_fields + if !(options[:request_specific_fields].is_a?(Hash) || options[:request_specific_fields].is_a?(Proc)) + raise ArgumentError, "Invalid request_specific_fields option: #{options[:request_specific_fields].inspect}" + end + end unless mode == nil || mode == 'r' || mode == 'rb' || mode == File::RDONLY @@ -211,11 +217,20 @@ def OpenURI.open_loop(uri, options) # :nodoc: end uri_set = {} + max_redirects = options[:max_redirects] || Options.fetch(:max_redirects) buf = nil while true + request_specific_fields = {} + if options.has_key? :request_specific_fields + request_specific_fields = if options[:request_specific_fields].is_a?(Hash) + options[:request_specific_fields] + else options[:request_specific_fields].is_a?(Proc) + options[:request_specific_fields].call(uri) + end + end redirect = catch(:open_uri_redirect) { buf = Buffer.new - uri.buffer_open(buf, find_proxy.call(uri), options) + uri.buffer_open(buf, find_proxy.call(uri), options.merge(request_specific_fields)) nil } if redirect @@ -235,9 +250,14 @@ def OpenURI.open_loop(uri, options) # :nodoc: options = options.dup options.delete :http_basic_authentication end + if options.include?(:request_specific_fields) && options[:request_specific_fields].is_a?(Hash) + # Send request specific headers only for the initial request. + options.delete :request_specific_fields + end uri = redirect raise "HTTP redirection loop: #{uri}" if uri_set.include? uri.to_s uri_set[uri.to_s] = true + raise TooManyRedirects.new("Too many redirects", buf.io) if max_redirects && uri_set.size > max_redirects else break end @@ -392,6 +412,9 @@ def initialize(message, io, uri) attr_reader :uri end + class TooManyRedirects < HTTPError + end + class Buffer # :nodoc: all def initialize @io = StringIO.new @@ -740,6 +763,44 @@ module OpenRead # Using +true+ also means that redirections between http and ftp are # permitted. # + # [:max_redirects] + # Synopsis: + # :max_redirects=>int + # + # Number of HTTP redirects allowed before OpenURI::TooManyRedirects is raised. + # The default is 64. + # + # [:request_specific_fields] + # Synopsis: + # :request_specific_fields => {} + # :request_specific_fields => lambda {|url| ...} + # + # :request_specific_fields option allows specifying custom header fields that + # are sent with the HTTP request. It can be passed as a Hash or a Proc that + # gets evaluated on each request and returns a Hash of header fields. + # + # If a Hash is provided, it specifies the headers only for the initial + # request and these headers will not be sent on redirects. + # + # If a Proc is provided, it will be executed for each request including + # redirects, allowing dynamic header customization based on the request URL. + # It is important that the Proc returns a Hash. And this Hash specifies the + # headers to be sent with the request. + # + # For Example with Hash + # URI.open("http://...", + # request_specific_fields: {"Authorization" => "token dummy"}) {|f| ... } + # + # For Example with Proc: + # URI.open("http://...", + # request_specific_fields: lambda { |uri| + # if uri.host == "example.com" + # {"Authorization" => "token dummy"} + # else + # {} + # end + # }) {|f| ... } + # def open(*rest, &block) OpenURI.open_uri(self, *rest, &block) end diff --git a/lib/open3.rb b/lib/open3.rb index 9652b2719468eb..74d00b86d93f55 100644 --- a/lib/open3.rb +++ b/lib/open3.rb @@ -31,57 +31,189 @@ require 'open3/version' +# \Module \Open3 supports creating child processes +# with access to their $stdin, $stdout, and $stderr streams. +# +# == What's Here +# +# Each of these methods executes a given command in a new process or subshell, +# or multiple commands in new processes and/or subshells: +# +# - Each of these methods executes a single command in a process or subshell, +# accepts a string for input to $stdin, +# and returns string output from $stdout, $stderr, or both: +# +# - Open3.capture2: Executes the command; +# returns the string from $stdout. +# - Open3.capture2e: Executes the command; +# returns the string from merged $stdout and $stderr. +# - Open3.capture3: Executes the command; +# returns strings from $stdout and $stderr. +# +# - Each of these methods executes a single command in a process or subshell, +# and returns pipes for $stdin, $stdout, and/or $stderr: +# +# - Open3.popen2: Executes the command; +# returns pipes for $stdin and $stdout. +# - Open3.popen2e: Executes the command; +# returns pipes for $stdin and merged $stdout and $stderr. +# - Open3.popen3: Executes the command; +# returns pipes for $stdin, $stdout, and $stderr. +# +# - Each of these methods executes one or more commands in processes and/or subshells, +# returns pipes for the first $stdin, the last $stdout, or both: +# +# - Open3.pipeline_r: Returns a pipe for the last $stdout. +# - Open3.pipeline_rw: Returns pipes for the first $stdin and the last $stdout. +# - Open3.pipeline_w: Returns a pipe for the first $stdin. +# - Open3.pipeline_start: Does not wait for processes to complete. +# - Open3.pipeline: Waits for processes to complete. +# +# Each of the methods above accepts: +# +# - An optional hash of environment variable names and values; +# see {Execution Environment}[rdoc-ref:Process@Execution+Environment]. +# - A required string argument that is a +command_line+ or +exe_path+; +# see {Argument command_line or exe_path}[rdoc-ref:Process@Argument+command_line+or+exe_path]. +# - An optional hash of execution options; +# see {Execution Options}[rdoc-ref:Process@Execution+Options]. +# module Open3 - # Open stdin, stdout, and stderr streams and start external executable. - # In addition, a thread to wait for the started process is created. - # The thread has a pid method and a thread variable :pid which is the pid of - # the started process. + # :call-seq: + # Open3.popen3([env, ] command_line, options = {}) -> [stdin, stdout, stderr, wait_thread] + # Open3.popen3([env, ] exe_path, *args, options = {}) -> [stdin, stdout, stderr, wait_thread] + # Open3.popen3([env, ] command_line, options = {}) {|stdin, stdout, stderr, wait_thread| ... } -> object + # Open3.popen3([env, ] exe_path, *args, options = {}) {|stdin, stdout, stderr, wait_thread| ... } -> object + # + # Basically a wrapper for + # {Process.spawn}[rdoc-ref:Process.spawn] + # that: + # + # - Creates a child process, by calling Process.spawn with the given arguments. + # - Creates streams +stdin+, +stdout+, and +stderr+, + # which are the standard input, standard output, and standard error streams + # in the child process. + # - Creates thread +wait_thread+ that waits for the child process to exit; + # the thread has method +pid+, which returns the process ID + # of the child process. + # + # With no block given, returns the array + # [stdin, stdout, stderr, wait_thread]. + # The caller should close each of the three returned streams. + # + # stdin, stdout, stderr, wait_thread = Open3.popen3('echo') + # # => [#, #, #, #] + # stdin.close + # stdout.close + # stderr.close + # wait_thread.pid # => 2210481 + # wait_thread.value # => # + # + # With a block given, calls the block with the four variables + # (three streams and the wait thread) + # and returns the block's return value. + # The caller need not close the streams: + # + # Open3.popen3('echo') do |stdin, stdout, stderr, wait_thread| + # p stdin + # p stdout + # p stderr + # p wait_thread + # p wait_thread.pid + # p wait_thread.value + # end # - # Block form: + # Output: # - # Open3.popen3([env,] cmd... [, opts]) {|stdin, stdout, stderr, wait_thr| - # pid = wait_thr.pid # pid of the started process. - # ... - # exit_status = wait_thr.value # Process::Status object returned. - # } + # # + # # + # # + # # + # 2211047 + # # # - # Non-block form: + # Like Process.spawn, this method has potential security vulnerabilities + # if called with untrusted input; + # see {Command Injection}[rdoc-ref:command_injection.rdoc@Command+Injection]. # - # stdin, stdout, stderr, wait_thr = Open3.popen3([env,] cmd... [, opts]) - # pid = wait_thr[:pid] # pid of the started process - # ... - # stdin.close # stdin, stdout and stderr should be closed explicitly in this form. - # stdout.close - # stderr.close - # exit_status = wait_thr.value # Process::Status object returned. + # Unlike Process.spawn, this method waits for the child process to exit + # before returning, so the caller need not do so. + # + # If the first argument is a hash, it becomes leading argument +env+ + # in the call to Process.spawn; + # see {Execution Environment}[rdoc-ref:Process@Execution+Environment]. + # + # If the last argument is a hash, it becomes trailing argument +options+ + # in the call to Process.spawn; + # see {Execution Options}[rdoc-ref:Process@Execution+Options]. + # + # The single required argument is one of the following: + # + # - +command_line+ if it is a string, + # and if it begins with a shell reserved word or special built-in, + # or if it contains one or more metacharacters. + # - +exe_path+ otherwise. + # + # Argument +command_line+ # - # The parameters env, cmd, and opts are passed to Process.spawn. - # A commandline string and a list of argument strings can be accepted as follows: + # \String argument +command_line+ is a command line to be passed to a shell; + # it must begin with a shell reserved word, begin with a special built-in, + # or contain meta characters: # - # Open3.popen3("echo abc") {|i, o, e, t| ... } - # Open3.popen3("echo", "abc") {|i, o, e, t| ... } - # Open3.popen3(["echo", "argv0"], "abc") {|i, o, e, t| ... } + # Open3.popen3('if true; then echo "Foo"; fi') {|*args| p args } # Shell reserved word. + # Open3.popen3('echo') {|*args| p args } # Built-in. + # Open3.popen3('date > date.tmp') {|*args| p args } # Contains meta character. # - # If the last parameter, opts, is a Hash, it is recognized as an option for Process.spawn. + # Output (similar for each call above): # - # Open3.popen3("pwd", :chdir=>"/") {|i,o,e,t| - # p o.read.chomp #=> "/" - # } + # [#, #, #, #] # - # wait_thr.value waits for the termination of the process. - # The block form also waits for the process when it returns. + # The command line may also contain arguments and options for the command: + # + # Open3.popen3('echo "Foo"') { |i, o, e, t| o.gets } + # "Foo\n" + # + # Argument +exe_path+ + # + # Argument +exe_path+ is one of the following: + # + # - The string path to an executable to be called. + # - A 2-element array containing the path to an executable + # and the string to be used as the name of the executing process. + # + # Example: # - # Closing stdin, stdout and stderr does not wait for the process to complete. + # Open3.popen3('/usr/bin/date') { |i, o, e, t| o.gets } + # # => "Wed Sep 27 02:56:44 PM CDT 2023\n" # - # You should be careful to avoid deadlocks. - # Since pipes are fixed length buffers, - # Open3.popen3("prog") {|i, o, e, t| o.read } deadlocks if - # the program generates too much output on stderr. - # You should read stdout and stderr simultaneously (using threads or IO.select). - # However, if you don't need stderr output, you can use Open3.popen2. - # If merged stdout and stderr output is not a problem, you can use Open3.popen2e. - # If you really need stdout and stderr output as separate strings, you can consider Open3.capture3. + # Ruby invokes the executable directly, with no shell and no shell expansion: + # + # Open3.popen3('doesnt_exist') { |i, o, e, t| o.gets } # Raises Errno::ENOENT + # + # If one or more +args+ is given, each is an argument or option + # to be passed to the executable: + # + # Open3.popen3('echo', 'C #') { |i, o, e, t| o.gets } + # # => "C #\n" + # Open3.popen3('echo', 'hello', 'world') { |i, o, e, t| o.gets } + # # => "hello world\n" + # + # Take care to avoid deadlocks. + # Output streams +stdout+ and +stderr+ have fixed-size buffers, + # so reading extensively from one but not the other can cause a deadlock + # when the unread buffer fills. + # To avoid that, +stdout+ and +stderr+ should be read simultaneously + # (using threads or IO.select). + # + # Related: + # + # - Open3.popen2: Makes the standard input and standard output streams + # of the child process available as separate streams, + # with no access to the standard error stream. + # - Open3.popen2e: Makes the standard input and the merge + # of the standard output and standard error streams + # of the child process available as separate streams. # def popen3(*cmd, &block) if Hash === cmd.last @@ -104,45 +236,131 @@ def popen3(*cmd, &block) end module_function :popen3 - # Open3.popen2 is similar to Open3.popen3 except that it doesn't create a pipe for - # the standard error stream. + # :call-seq: + # Open3.popen2([env, ] command_line, options = {}) -> [stdin, stdout, wait_thread] + # Open3.popen2([env, ] exe_path, *args, options = {}) -> [stdin, stdout, wait_thread] + # Open3.popen2([env, ] command_line, options = {}) {|stdin, stdout, wait_thread| ... } -> object + # Open3.popen2([env, ] exe_path, *args, options = {}) {|stdin, stdout, wait_thread| ... } -> object + # + # Basically a wrapper for + # {Process.spawn}[rdoc-ref:Process.spawn] + # that: + # + # - Creates a child process, by calling Process.spawn with the given arguments. + # - Creates streams +stdin+ and +stdout+, + # which are the standard input and standard output streams + # in the child process. + # - Creates thread +wait_thread+ that waits for the child process to exit; + # the thread has method +pid+, which returns the process ID + # of the child process. + # + # With no block given, returns the array + # [stdin, stdout, wait_thread]. + # The caller should close each of the two returned streams. + # + # stdin, stdout, wait_thread = Open3.popen2('echo') + # # => [#, #, #] + # stdin.close + # stdout.close + # wait_thread.pid # => 2263572 + # wait_thread.value # => # + # + # With a block given, calls the block with the three variables + # (two streams and the wait thread) + # and returns the block's return value. + # The caller need not close the streams: + # + # Open3.popen2('echo') do |stdin, stdout, wait_thread| + # p stdin + # p stdout + # p wait_thread + # p wait_thread.pid + # p wait_thread.value + # end # - # Block form: + # Output: # - # Open3.popen2([env,] cmd... [, opts]) {|stdin, stdout, wait_thr| - # pid = wait_thr.pid # pid of the started process. - # ... - # exit_status = wait_thr.value # Process::Status object returned. - # } + # # + # # + # # + # 2263636 + # # # - # Non-block form: + # Like Process.spawn, this method has potential security vulnerabilities + # if called with untrusted input; + # see {Command Injection}[rdoc-ref:command_injection.rdoc@Command+Injection]. # - # stdin, stdout, wait_thr = Open3.popen2([env,] cmd... [, opts]) - # ... - # stdin.close # stdin and stdout should be closed explicitly in this form. - # stdout.close + # Unlike Process.spawn, this method waits for the child process to exit + # before returning, so the caller need not do so. + # + # If the first argument is a hash, it becomes leading argument +env+ + # in the call to Process.spawn; + # see {Execution Environment}[rdoc-ref:Process@Execution+Environment]. + # + # If the last argument is a hash, it becomes trailing argument +options+ + # in the call to Process.spawn; + # see {Execution Options}[rdoc-ref:Process@Execution+Options]. + # + # The single required argument is one of the following: + # + # - +command_line+ if it is a string, + # and if it begins with a shell reserved word or special built-in, + # or if it contains one or more metacharacters. + # - +exe_path+ otherwise. # - # See Process.spawn for the optional hash arguments _env_ and _opts_. + # Argument +command_line+ + # + # \String argument +command_line+ is a command line to be passed to a shell; + # it must begin with a shell reserved word, begin with a special built-in, + # or contain meta characters: + # + # Open3.popen2('if true; then echo "Foo"; fi') {|*args| p args } # Shell reserved word. + # Open3.popen2('echo') {|*args| p args } # Built-in. + # Open3.popen2('date > date.tmp') {|*args| p args } # Contains meta character. + # + # Output (similar for each call above): + # + # # => [#, #, #] + # + # The command line may also contain arguments and options for the command: + # + # Open3.popen2('echo "Foo"') { |i, o, t| o.gets } + # "Foo\n" + # + # Argument +exe_path+ + # + # Argument +exe_path+ is one of the following: + # + # - The string path to an executable to be called. + # - A 2-element array containing the path to an executable + # and the string to be used as the name of the executing process. # # Example: # - # Open3.popen2("wc -c") {|i,o,t| - # i.print "answer to life the universe and everything" - # i.close - # p o.gets #=> "42\n" - # } + # Open3.popen2('/usr/bin/date') { |i, o, t| o.gets } + # # => "Thu Sep 28 09:41:06 AM CDT 2023\n" + # + # Ruby invokes the executable directly, with no shell and no shell expansion: + # + # Open3.popen2('doesnt_exist') { |i, o, t| o.gets } # Raises Errno::ENOENT + # + # If one or more +args+ is given, each is an argument or option + # to be passed to the executable: + # + # Open3.popen2('echo', 'C #') { |i, o, t| o.gets } + # # => "C #\n" + # Open3.popen2('echo', 'hello', 'world') { |i, o, t| o.gets } + # # => "hello world\n" # - # Open3.popen2("bc -q") {|i,o,t| - # i.puts "obase=13" - # i.puts "6 * 9" - # p o.gets #=> "42\n" - # } # - # Open3.popen2("dc") {|i,o,t| - # i.print "42P" - # i.close - # p o.read #=> "*" - # } + # Related: + # + # - Open3.popen2e: Makes the standard input and the merge + # of the standard output and standard error streams + # of the child process available as separate streams. + # - Open3.popen3: Makes the standard input, standard output, + # and standard error streams + # of the child process available as separate streams. # def popen2(*cmd, &block) if Hash === cmd.last @@ -162,36 +380,130 @@ def popen2(*cmd, &block) end module_function :popen2 - # Open3.popen2e is similar to Open3.popen3 except that it merges - # the standard output stream and the standard error stream. + # :call-seq: + # Open3.popen2e([env, ] command_line, options = {}) -> [stdin, stdout_and_stderr, wait_thread] + # Open3.popen2e([env, ] exe_path, *args, options = {}) -> [stdin, stdout_and_stderr, wait_thread] + # Open3.popen2e([env, ] command_line, options = {}) {|stdin, stdout_and_stderr, wait_thread| ... } -> object + # Open3.popen2e([env, ] exe_path, *args, options = {}) {|stdin, stdout_and_stderr, wait_thread| ... } -> object + # + # Basically a wrapper for + # {Process.spawn}[rdoc-ref:Process.spawn] + # that: + # + # - Creates a child process, by calling Process.spawn with the given arguments. + # - Creates streams +stdin+, +stdout_and_stderr+, + # which are the standard input and the merge of the standard output + # and standard error streams in the child process. + # - Creates thread +wait_thread+ that waits for the child process to exit; + # the thread has method +pid+, which returns the process ID + # of the child process. + # + # With no block given, returns the array + # [stdin, stdout_and_stderr, wait_thread]. + # The caller should close each of the two returned streams. + # + # stdin, stdout_and_stderr, wait_thread = Open3.popen2e('echo') + # # => [#, #, #] + # stdin.close + # stdout_and_stderr.close + # wait_thread.pid # => 2274600 + # wait_thread.value # => # + # + # With a block given, calls the block with the three variables + # (two streams and the wait thread) + # and returns the block's return value. + # The caller need not close the streams: + # + # Open3.popen2e('echo') do |stdin, stdout_and_stderr, wait_thread| + # p stdin + # p stdout_and_stderr + # p wait_thread + # p wait_thread.pid + # p wait_thread.value + # end # - # Block form: + # Output: # - # Open3.popen2e([env,] cmd... [, opts]) {|stdin, stdout_and_stderr, wait_thr| - # pid = wait_thr.pid # pid of the started process. - # ... - # exit_status = wait_thr.value # Process::Status object returned. - # } + # # + # # + # # + # 2274763 + # # # - # Non-block form: + # Like Process.spawn, this method has potential security vulnerabilities + # if called with untrusted input; + # see {Command Injection}[rdoc-ref:command_injection.rdoc@Command+Injection]. # - # stdin, stdout_and_stderr, wait_thr = Open3.popen2e([env,] cmd... [, opts]) - # ... - # stdin.close # stdin and stdout_and_stderr should be closed explicitly in this form. - # stdout_and_stderr.close + # Unlike Process.spawn, this method waits for the child process to exit + # before returning, so the caller need not do so. + # + # If the first argument is a hash, it becomes leading argument +env+ + # in the call to Process.spawn; + # see {Execution Environment}[rdoc-ref:Process@Execution+Environment]. + # + # If the last argument is a hash, it becomes trailing argument +options+ + # in the call to Process.spawn; + # see {Execution Options}[rdoc-ref:Process@Execution+Options]. + # + # The single required argument is one of the following: + # + # - +command_line+ if it is a string, + # and if it begins with a shell reserved word or special built-in, + # or if it contains one or more metacharacters. + # - +exe_path+ otherwise. + # + # Argument +command_line+ + # + # \String argument +command_line+ is a command line to be passed to a shell; + # it must begin with a shell reserved word, begin with a special built-in, + # or contain meta characters: + # + # Open3.popen2e('if true; then echo "Foo"; fi') {|*args| p args } # Shell reserved word. + # Open3.popen2e('echo') {|*args| p args } # Built-in. + # Open3.popen2e('date > date.tmp') {|*args| p args } # Contains meta character. + # + # Output (similar for each call above): + # + # # => [#, #, #] # - # See Process.spawn for the optional hash arguments _env_ and _opts_. + # The command line may also contain arguments and options for the command: + # + # Open3.popen2e('echo "Foo"') { |i, o_and_e, t| o_and_e.gets } + # "Foo\n" + # + # Argument +exe_path+ + # + # Argument +exe_path+ is one of the following: + # + # - The string path to an executable to be called. + # - A 2-element array containing the path to an executable + # and the string to be used as the name of the executing process. # # Example: - # # check gcc warnings - # source = "foo.c" - # Open3.popen2e("gcc", "-Wall", source) {|i,oe,t| - # oe.each {|line| - # if /warning/ =~ line - # ... - # end - # } - # } + # + # Open3.popen2e('/usr/bin/date') { |i, o_and_e, t| o_and_e.gets } + # # => "Thu Sep 28 01:58:45 PM CDT 2023\n" + # + # Ruby invokes the executable directly, with no shell and no shell expansion: + # + # Open3.popen2e('doesnt_exist') { |i, o_and_e, t| o_and_e.gets } # Raises Errno::ENOENT + # + # If one or more +args+ is given, each is an argument or option + # to be passed to the executable: + # + # Open3.popen2e('echo', 'C #') { |i, o_and_e, t| o_and_e.gets } + # # => "C #\n" + # Open3.popen2e('echo', 'hello', 'world') { |i, o_and_e, t| o_and_e.gets } + # # => "hello world\n" + # + # Related: + # + # - Open3.popen2: Makes the standard input and standard output streams + # of the child process available as separate streams, + # with no access to the standard error stream. + # - Open3.popen3: Makes the standard input, standard output, + # and standard error streams + # of the child process available as separate streams. # def popen2e(*cmd, &block) if Hash === cmd.last @@ -238,44 +550,100 @@ class << self private :popen_run end - # Open3.capture3 captures the standard output and the standard error of a command. + # :call-seq: + # Open3.capture3([env, ] command_line, options = {}) -> [stdout_s, stderr_s, status] + # Open3.capture3([env, ] exe_path, *args, options = {}) -> [stdout_s, stderr_s, status] # - # stdout_str, stderr_str, status = Open3.capture3([env,] cmd... [, opts]) + # Basically a wrapper for Open3.popen3 that: # - # The arguments env, cmd and opts are passed to Open3.popen3 except - # opts[:stdin_data] and opts[:binmode]. See Process.spawn. + # - Creates a child process, by calling Open3.popen3 with the given arguments + # (except for certain entries in hash +options+; see below). + # - Returns as strings +stdout_s+ and +stderr_s+ the standard output + # and standard error of the child process. + # - Returns as +status+ a Process::Status object + # that represents the exit status of the child process. # - # If opts[:stdin_data] is specified, it is sent to the command's standard input. + # Returns the array [stdout_s, stderr_s, status]: # - # If opts[:binmode] is true, internal pipes are set to binary mode. + # stdout_s, stderr_s, status = Open3.capture3('echo "Foo"') + # # => ["Foo\n", "", #] # - # Examples: + # Like Process.spawn, this method has potential security vulnerabilities + # if called with untrusted input; + # see {Command Injection}[rdoc-ref:command_injection.rdoc@Command+Injection]. # - # # dot is a command of graphviz. - # graph = <<'End' - # digraph g { - # a -> b - # } - # End - # drawn_graph, dot_log = Open3.capture3("dot -v", :stdin_data=>graph) + # Unlike Process.spawn, this method waits for the child process to exit + # before returning, so the caller need not do so. # - # o, e, s = Open3.capture3("echo abc; sort >&2", :stdin_data=>"foo\nbar\nbaz\n") - # p o #=> "abc\n" - # p e #=> "bar\nbaz\nfoo\n" - # p s #=> # + # If the first argument is a hash, it becomes leading argument +env+ + # in the call to Open3.popen3; + # see {Execution Environment}[rdoc-ref:Process@Execution+Environment]. # - # # generate a thumbnail image using the convert command of ImageMagick. - # # However, if the image is really stored in a file, - # # system("convert", "-thumbnail", "80", "png:#{filename}", "png:-") is better - # # because of reduced memory consumption. - # # But if the image is stored in a DB or generated by the gnuplot Open3.capture2 example, - # # Open3.capture3 should be considered. - # # - # image = File.read("/usr/share/openclipart/png/animals/mammals/sheep-md-v0.1.png", :binmode=>true) - # thumbnail, err, s = Open3.capture3("convert -thumbnail 80 png:- png:-", :stdin_data=>image, :binmode=>true) - # if s.success? - # STDOUT.binmode; print thumbnail - # end + # If the last argument is a hash, it becomes trailing argument +options+ + # in the call to Open3.popen3; + # see {Execution Options}[rdoc-ref:Process@Execution+Options]. + # + # The hash +options+ is given; + # two options have local effect in method Open3.capture3: + # + # - If entry options[:stdin_data] exists, the entry is removed + # and its string value is sent to the command's standard input: + # + # Open3.capture3('tee', stdin_data: 'Foo') + # # => ["Foo", "", #] + # + # - If entry options[:binmode] exists, the entry is removed and + # the internal streams are set to binary mode. + # + # The single required argument is one of the following: + # + # - +command_line+ if it is a string, + # and if it begins with a shell reserved word or special built-in, + # or if it contains one or more metacharacters. + # - +exe_path+ otherwise. + # + # Argument +command_line+ + # + # \String argument +command_line+ is a command line to be passed to a shell; + # it must begin with a shell reserved word, begin with a special built-in, + # or contain meta characters: + # + # Open3.capture3('if true; then echo "Foo"; fi') # Shell reserved word. + # # => ["Foo\n", "", #] + # Open3.capture3('echo') # Built-in. + # # => ["\n", "", #] + # Open3.capture3('date > date.tmp') # Contains meta character. + # # => ["", "", #] + # + # The command line may also contain arguments and options for the command: + # + # Open3.capture3('echo "Foo"') + # # => ["Foo\n", "", #] + # + # Argument +exe_path+ + # + # Argument +exe_path+ is one of the following: + # + # - The string path to an executable to be called. + # - A 2-element array containing the path to an executable + # and the string to be used as the name of the executing process. + # + # Example: + # + # Open3.capture3('/usr/bin/date') + # # => ["Thu Sep 28 05:03:51 PM CDT 2023\n", "", #] + # + # Ruby invokes the executable directly, with no shell and no shell expansion: + # + # Open3.capture3('doesnt_exist') # Raises Errno::ENOENT + # + # If one or more +args+ is given, each is an argument or option + # to be passed to the executable: + # + # Open3.capture3('echo', 'C #') + # # => ["C #\n", "", #] + # Open3.capture3('echo', 'hello', 'world') + # # => ["hello world\n", "", #] # def capture3(*cmd) if Hash === cmd.last @@ -309,34 +677,100 @@ def capture3(*cmd) end module_function :capture3 - # Open3.capture2 captures the standard output of a command. + # :call-seq: + # Open3.capture2([env, ] command_line, options = {}) -> [stdout_s, status] + # Open3.capture2([env, ] exe_path, *args, options = {}) -> [stdout_s, status] + # + # Basically a wrapper for Open3.popen3 that: + # + # - Creates a child process, by calling Open3.popen3 with the given arguments + # (except for certain entries in hash +options+; see below). + # - Returns as string +stdout_s+ the standard output of the child process. + # - Returns as +status+ a Process::Status object + # that represents the exit status of the child process. + # + # Returns the array [stdout_s, status]: + # + # stdout_s, status = Open3.capture2('echo "Foo"') + # # => ["Foo\n", #] + # + # Like Process.spawn, this method has potential security vulnerabilities + # if called with untrusted input; + # see {Command Injection}[rdoc-ref:command_injection.rdoc@Command+Injection]. + # + # Unlike Process.spawn, this method waits for the child process to exit + # before returning, so the caller need not do so. # - # stdout_str, status = Open3.capture2([env,] cmd... [, opts]) + # If the first argument is a hash, it becomes leading argument +env+ + # in the call to Open3.popen3; + # see {Execution Environment}[rdoc-ref:Process@Execution+Environment]. # - # The arguments env, cmd and opts are passed to Open3.popen3 except - # opts[:stdin_data] and opts[:binmode]. See Process.spawn. + # If the last argument is a hash, it becomes trailing argument +options+ + # in the call to Open3.popen3; + # see {Execution Options}[rdoc-ref:Process@Execution+Options]. # - # If opts[:stdin_data] is specified, it is sent to the command's standard input. + # The hash +options+ is given; + # two options have local effect in method Open3.capture2: # - # If opts[:binmode] is true, internal pipes are set to binary mode. + # - If entry options[:stdin_data] exists, the entry is removed + # and its string value is sent to the command's standard input: + # + # Open3.capture2('tee', stdin_data: 'Foo') + # + # # => ["Foo", #] + # + # - If entry options[:binmode] exists, the entry is removed and + # the internal streams are set to binary mode. + # + # The single required argument is one of the following: + # + # - +command_line+ if it is a string, + # and if it begins with a shell reserved word or special built-in, + # or if it contains one or more metacharacters. + # - +exe_path+ otherwise. + # + # Argument +command_line+ + # + # \String argument +command_line+ is a command line to be passed to a shell; + # it must begin with a shell reserved word, begin with a special built-in, + # or contain meta characters: + # + # Open3.capture2('if true; then echo "Foo"; fi') # Shell reserved word. + # # => ["Foo\n", #] + # Open3.capture2('echo') # Built-in. + # # => ["\n", #] + # Open3.capture2('date > date.tmp') # Contains meta character. + # # => ["", #] + # + # The command line may also contain arguments and options for the command: + # + # Open3.capture2('echo "Foo"') + # # => ["Foo\n", #] + # + # Argument +exe_path+ + # + # Argument +exe_path+ is one of the following: + # + # - The string path to an executable to be called. + # - A 2-element array containing the path to an executable + # and the string to be used as the name of the executing process. # # Example: # - # # factor is a command for integer factorization. - # o, s = Open3.capture2("factor", :stdin_data=>"42") - # p o #=> "42: 2 3 7\n" - # - # # generate x**2 graph in png using gnuplot. - # gnuplot_commands = <<"End" - # set terminal png - # plot x**2, "-" with lines - # 1 14 - # 2 1 - # 3 8 - # 4 5 - # e - # End - # image, s = Open3.capture2("gnuplot", :stdin_data=>gnuplot_commands, :binmode=>true) + # Open3.capture2('/usr/bin/date') + # # => ["Fri Sep 29 01:00:39 PM CDT 2023\n", #] + # + # Ruby invokes the executable directly, with no shell and no shell expansion: + # + # Open3.capture2('doesnt_exist') # Raises Errno::ENOENT + # + # If one or more +args+ is given, each is an argument or option + # to be passed to the executable: + # + # Open3.capture2('echo', 'C #') + # # => ["C #\n", #] + # Open3.capture2('echo', 'hello', 'world') + # # => ["hello world\n", #] # def capture2(*cmd) if Hash === cmd.last @@ -370,21 +804,100 @@ def capture2(*cmd) end module_function :capture2 - # Open3.capture2e captures the standard output and the standard error of a command. + # :call-seq: + # Open3.capture2e([env, ] command_line, options = {}) -> [stdout_and_stderr_s, status] + # Open3.capture2e([env, ] exe_path, *args, options = {}) -> [stdout_and_stderr_s, status] + # + # Basically a wrapper for Open3.popen3 that: + # + # - Creates a child process, by calling Open3.popen3 with the given arguments + # (except for certain entries in hash +options+; see below). + # - Returns as string +stdout_and_stderr_s+ the merged standard output + # and standard error of the child process. + # - Returns as +status+ a Process::Status object + # that represents the exit status of the child process. + # + # Returns the array [stdout_and_stderr_s, status]: + # + # stdout_and_stderr_s, status = Open3.capture2e('echo "Foo"') + # # => ["Foo\n", #] + # + # Like Process.spawn, this method has potential security vulnerabilities + # if called with untrusted input; + # see {Command Injection}[rdoc-ref:command_injection.rdoc@Command+Injection]. + # + # Unlike Process.spawn, this method waits for the child process to exit + # before returning, so the caller need not do so. + # + # If the first argument is a hash, it becomes leading argument +env+ + # in the call to Open3.popen3; + # see {Execution Environment}[rdoc-ref:Process@Execution+Environment]. + # + # If the last argument is a hash, it becomes trailing argument +options+ + # in the call to Open3.popen3; + # see {Execution Options}[rdoc-ref:Process@Execution+Options]. + # + # The hash +options+ is given; + # two options have local effect in method Open3.capture2e: + # + # - If entry options[:stdin_data] exists, the entry is removed + # and its string value is sent to the command's standard input: # - # stdout_and_stderr_str, status = Open3.capture2e([env,] cmd... [, opts]) + # Open3.capture2e('tee', stdin_data: 'Foo') + # # => ["Foo", #] # - # The arguments env, cmd and opts are passed to Open3.popen3 except - # opts[:stdin_data] and opts[:binmode]. See Process.spawn. + # - If entry options[:binmode] exists, the entry is removed and + # the internal streams are set to binary mode. # - # If opts[:stdin_data] is specified, it is sent to the command's standard input. + # The single required argument is one of the following: # - # If opts[:binmode] is true, internal pipes are set to binary mode. + # - +command_line+ if it is a string, + # and if it begins with a shell reserved word or special built-in, + # or if it contains one or more metacharacters. + # - +exe_path+ otherwise. + # + # Argument +command_line+ + # + # \String argument +command_line+ is a command line to be passed to a shell; + # it must begin with a shell reserved word, begin with a special built-in, + # or contain meta characters: + # + # Open3.capture2e('if true; then echo "Foo"; fi') # Shell reserved word. + # # => ["Foo\n", #] + # Open3.capture2e('echo') # Built-in. + # # => ["\n", #] + # Open3.capture2e('date > date.tmp') # Contains meta character. + # # => ["", #] + # + # The command line may also contain arguments and options for the command: + # + # Open3.capture2e('echo "Foo"') + # # => ["Foo\n", #] + # + # Argument +exe_path+ + # + # Argument +exe_path+ is one of the following: + # + # - The string path to an executable to be called. + # - A 2-element array containing the path to an executable + # and the string to be used as the name of the executing process. # # Example: # - # # capture make log - # make_log, s = Open3.capture2e("make") + # Open3.capture2e('/usr/bin/date') + # # => ["Sat Sep 30 09:01:46 AM CDT 2023\n", #] + # + # Ruby invokes the executable directly, with no shell and no shell expansion: + # + # Open3.capture2e('doesnt_exist') # Raises Errno::ENOENT + # + # If one or more +args+ is given, each is an argument or option + # to be passed to the executable: + # + # Open3.capture2e('echo', 'C #') + # # => ["C #\n", #] + # Open3.capture2e('echo', 'hello', 'world') + # # => ["hello world\n", #] # def capture2e(*cmd) if Hash === cmd.last @@ -418,48 +931,86 @@ def capture2e(*cmd) end module_function :capture2e - # Open3.pipeline_rw starts a list of commands as a pipeline with pipes - # which connect to stdin of the first command and stdout of the last command. - # - # Open3.pipeline_rw(cmd1, cmd2, ... [, opts]) {|first_stdin, last_stdout, wait_threads| - # ... - # } + # :call-seq: + # Open3.pipeline_rw([env, ] *cmds, options = {}) -> [first_stdin, last_stdout, wait_threads] # - # first_stdin, last_stdout, wait_threads = Open3.pipeline_rw(cmd1, cmd2, ... [, opts]) - # ... - # first_stdin.close - # last_stdout.close + # Basically a wrapper for + # {Process.spawn}[rdoc-ref:Process.spawn] + # that: # - # Each cmd is a string or an array. - # If it is an array, the elements are passed to Process.spawn. + # - Creates a child process for each of the given +cmds+ + # by calling Process.spawn. + # - Pipes the +stdout+ from each child to the +stdin+ of the next child, + # or, for the first child, from the caller's +stdin+, + # or, for the last child, to the caller's +stdout+. # - # cmd: - # commandline command line string which is passed to a shell - # [env, commandline, opts] command line string which is passed to a shell - # [env, cmdname, arg1, ..., opts] command name and one or more arguments (no shell) - # [env, [cmdname, argv0], arg1, ..., opts] command name and arguments including argv[0] (no shell) + # The method does not wait for child processes to exit, + # so the caller must do so. # - # Note that env and opts are optional, as for Process.spawn. + # With no block given, returns a 3-element array containing: # - # The options to pass to Process.spawn are constructed by merging - # +opts+, the last hash element of the array, and - # specifications for the pipes between each of the commands. + # - The +stdin+ stream of the first child process. + # - The +stdout+ stream of the last child process. + # - An array of the wait threads for all of the child processes. # # Example: # - # Open3.pipeline_rw("tr -dc A-Za-z", "wc -c") {|i, o, ts| - # i.puts "All persons more than a mile high to leave the court." - # i.close - # p o.gets #=> "42\n" - # } - # - # Open3.pipeline_rw("sort", "cat -n") {|stdin, stdout, wait_thrs| - # stdin.puts "foo" - # stdin.puts "bar" - # stdin.puts "baz" - # stdin.close # send EOF to sort. - # p stdout.read #=> " 1\tbar\n 2\tbaz\n 3\tfoo\n" - # } + # first_stdin, last_stdout, wait_threads = Open3.pipeline_rw('sort', 'cat -n') + # # => [#, #, [#, #]] + # first_stdin.puts("foo\nbar\nbaz") + # first_stdin.close # Send EOF to sort. + # puts last_stdout.read + # wait_threads.each do |wait_thread| + # wait_thread.join + # end + # + # Output: + # + # 1 bar + # 2 baz + # 3 foo + # + # With a block given, calls the block with the +stdin+ stream of the first child, + # the +stdout+ stream of the last child, + # and an array of the wait processes: + # + # Open3.pipeline_rw('sort', 'cat -n') do |first_stdin, last_stdout, wait_threads| + # first_stdin.puts "foo\nbar\nbaz" + # first_stdin.close # send EOF to sort. + # puts last_stdout.read + # wait_threads.each do |wait_thread| + # wait_thread.join + # end + # end + # + # Output: + # + # 1 bar + # 2 baz + # 3 foo + # + # Like Process.spawn, this method has potential security vulnerabilities + # if called with untrusted input; + # see {Command Injection}[rdoc-ref:command_injection.rdoc@Command+Injection]. + # + # If the first argument is a hash, it becomes leading argument +env+ + # in each call to Process.spawn; + # see {Execution Environment}[rdoc-ref:Process@Execution+Environment]. + # + # If the last argument is a hash, it becomes trailing argument +options+ + # in each call to Process.spawn; + # see {Execution Options}[rdoc-ref:Process@Execution+Options]. + # + # Each remaining argument in +cmds+ is one of: + # + # - A +command_line+: a string that begins with a shell reserved word + # or special built-in, or contains one or more metacharacters. + # - An +exe_path+: the string path to an executable to be called. + # - An array containing a +command_line+ or an +exe_path+, + # along with zero or more string arguments for the command. + # + # See {Argument command_line or exe_path}[rdoc-ref:Process@Argument+command_line+or+exe_path]. + # def pipeline_rw(*cmds, &block) if Hash === cmds.last opts = cmds.pop.dup @@ -478,43 +1029,77 @@ def pipeline_rw(*cmds, &block) end module_function :pipeline_rw - # Open3.pipeline_r starts a list of commands as a pipeline with a pipe - # which connects to stdout of the last command. + # :call-seq: + # Open3.pipeline_r([env, ] *cmds, options = {}) -> [last_stdout, wait_threads] # - # Open3.pipeline_r(cmd1, cmd2, ... [, opts]) {|last_stdout, wait_threads| - # ... - # } + # Basically a wrapper for + # {Process.spawn}[rdoc-ref:Process.spawn] + # that: # - # last_stdout, wait_threads = Open3.pipeline_r(cmd1, cmd2, ... [, opts]) - # ... - # last_stdout.close + # - Creates a child process for each of the given +cmds+ + # by calling Process.spawn. + # - Pipes the +stdout+ from each child to the +stdin+ of the next child, + # or, for the last child, to the caller's +stdout+. # - # Each cmd is a string or an array. - # If it is an array, the elements are passed to Process.spawn. + # The method does not wait for child processes to exit, + # so the caller must do so. # - # cmd: - # commandline command line string which is passed to a shell - # [env, commandline, opts] command line string which is passed to a shell - # [env, cmdname, arg1, ..., opts] command name and one or more arguments (no shell) - # [env, [cmdname, argv0], arg1, ..., opts] command name and arguments including argv[0] (no shell) + # With no block given, returns a 2-element array containing: # - # Note that env and opts are optional, as for Process.spawn. + # - The +stdout+ stream of the last child process. + # - An array of the wait threads for all of the child processes. # # Example: # - # Open3.pipeline_r("zcat /var/log/apache2/access.log.*.gz", - # [{"LANG"=>"C"}, "grep", "GET /favicon.ico"], - # "logresolve") {|o, ts| - # o.each_line {|line| - # ... - # } - # } + # last_stdout, wait_threads = Open3.pipeline_r('ls', 'grep R') + # # => [#, [#, #]] + # puts last_stdout.read + # wait_threads.each do |wait_thread| + # wait_thread.join + # end + # + # Output: + # + # Rakefile + # README.md + # + # With a block given, calls the block with the +stdout+ stream + # of the last child process, + # and an array of the wait processes: + # + # Open3.pipeline_r('ls', 'grep R') do |last_stdout, wait_threads| + # puts last_stdout.read + # wait_threads.each do |wait_thread| + # wait_thread.join + # end + # end + # + # Output: + # + # Rakefile + # README.md + # + # Like Process.spawn, this method has potential security vulnerabilities + # if called with untrusted input; + # see {Command Injection}[rdoc-ref:command_injection.rdoc@Command+Injection]. + # + # If the first argument is a hash, it becomes leading argument +env+ + # in each call to Process.spawn; + # see {Execution Environment}[rdoc-ref:Process@Execution+Environment]. + # + # If the last argument is a hash, it becomes trailing argument +options+ + # in each call to Process.spawn; + # see {Execution Options}[rdoc-ref:Process@Execution+Options]. # - # Open3.pipeline_r("yes", "head -10") {|o, ts| - # p o.read #=> "y\ny\ny\ny\ny\ny\ny\ny\ny\ny\n" - # p ts[0].value #=> # - # p ts[1].value #=> # - # } + # Each remaining argument in +cmds+ is one of: + # + # - A +command_line+: a string that begins with a shell reserved word + # or special built-in, or contains one or more metacharacters. + # - An +exe_path+: the string path to an executable to be called. + # - An array containing a +command_line+ or an +exe_path+, + # along with zero or more string arguments for the command. + # + # See {Argument command_line or exe_path}[rdoc-ref:Process@Argument+command_line+or+exe_path]. # def pipeline_r(*cmds, &block) if Hash === cmds.last @@ -530,33 +1115,82 @@ def pipeline_r(*cmds, &block) end module_function :pipeline_r - # Open3.pipeline_w starts a list of commands as a pipeline with a pipe - # which connects to stdin of the first command. + + # :call-seq: + # Open3.pipeline_w([env, ] *cmds, options = {}) -> [first_stdin, wait_threads] # - # Open3.pipeline_w(cmd1, cmd2, ... [, opts]) {|first_stdin, wait_threads| - # ... - # } + # Basically a wrapper for + # {Process.spawn}[rdoc-ref:Process.spawn] + # that: # - # first_stdin, wait_threads = Open3.pipeline_w(cmd1, cmd2, ... [, opts]) - # ... - # first_stdin.close + # - Creates a child process for each of the given +cmds+ + # by calling Process.spawn. + # - Pipes the +stdout+ from each child to the +stdin+ of the next child, + # or, for the first child, pipes the caller's +stdout+ to the child's +stdin+. # - # Each cmd is a string or an array. - # If it is an array, the elements are passed to Process.spawn. + # The method does not wait for child processes to exit, + # so the caller must do so. # - # cmd: - # commandline command line string which is passed to a shell - # [env, commandline, opts] command line string which is passed to a shell - # [env, cmdname, arg1, ..., opts] command name and one or more arguments (no shell) - # [env, [cmdname, argv0], arg1, ..., opts] command name and arguments including argv[0] (no shell) + # With no block given, returns a 2-element array containing: # - # Note that env and opts are optional, as for Process.spawn. + # - The +stdin+ stream of the first child process. + # - An array of the wait threads for all of the child processes. # # Example: # - # Open3.pipeline_w("bzip2 -c", :out=>"/tmp/hello.bz2") {|i, ts| - # i.puts "hello" - # } + # first_stdin, wait_threads = Open3.pipeline_w('sort', 'cat -n') + # # => [#, [#, #]] + # first_stdin.puts("foo\nbar\nbaz") + # first_stdin.close # Send EOF to sort. + # wait_threads.each do |wait_thread| + # wait_thread.join + # end + # + # Output: + # + # 1 bar + # 2 baz + # 3 foo + # + # With a block given, calls the block with the +stdin+ stream + # of the first child process, + # and an array of the wait processes: + # + # Open3.pipeline_w('sort', 'cat -n') do |first_stdin, wait_threads| + # first_stdin.puts("foo\nbar\nbaz") + # first_stdin.close # Send EOF to sort. + # wait_threads.each do |wait_thread| + # wait_thread.join + # end + # end + # + # Output: + # + # 1 bar + # 2 baz + # 3 foo + # + # Like Process.spawn, this method has potential security vulnerabilities + # if called with untrusted input; + # see {Command Injection}[rdoc-ref:command_injection.rdoc@Command+Injection]. + # + # If the first argument is a hash, it becomes leading argument +env+ + # in each call to Process.spawn; + # see {Execution Environment}[rdoc-ref:Process@Execution+Environment]. + # + # If the last argument is a hash, it becomes trailing argument +options+ + # in each call to Process.spawn; + # see {Execution Options}[rdoc-ref:Process@Execution+Options]. + # + # Each remaining argument in +cmds+ is one of: + # + # - A +command_line+: a string that begins with a shell reserved word + # or special built-in, or contains one or more metacharacters. + # - An +exe_path+: the string path to an executable to be called. + # - An array containing a +command_line+ or an +exe_path+, + # along with zero or more string arguments for the command. + # + # See {Argument command_line or exe_path}[rdoc-ref:Process@Argument+command_line+or+exe_path]. # def pipeline_w(*cmds, &block) if Hash === cmds.last @@ -573,49 +1207,67 @@ def pipeline_w(*cmds, &block) end module_function :pipeline_w - # Open3.pipeline_start starts a list of commands as a pipeline. - # No pipes are created for stdin of the first command and - # stdout of the last command. + # :call-seq: + # Open3.pipeline_start([env, ] *cmds, options = {}) -> [wait_threads] # - # Open3.pipeline_start(cmd1, cmd2, ... [, opts]) {|wait_threads| - # ... - # } + # Basically a wrapper for + # {Process.spawn}[rdoc-ref:Process.spawn] + # that: # - # wait_threads = Open3.pipeline_start(cmd1, cmd2, ... [, opts]) - # ... + # - Creates a child process for each of the given +cmds+ + # by calling Process.spawn. + # - Does not wait for child processes to exit. # - # Each cmd is a string or an array. - # If it is an array, the elements are passed to Process.spawn. + # With no block given, returns an array of the wait threads + # for all of the child processes. # - # cmd: - # commandline command line string which is passed to a shell - # [env, commandline, opts] command line string which is passed to a shell - # [env, cmdname, arg1, ..., opts] command name and one or more arguments (no shell) - # [env, [cmdname, argv0], arg1, ..., opts] command name and arguments including argv[0] (no shell) + # Example: # - # Note that env and opts are optional, as for Process.spawn. + # wait_threads = Open3.pipeline_start('ls', 'grep R') + # # => [#, #] + # wait_threads.each do |wait_thread| + # wait_thread.join + # end # - # Example: + # Output: + # + # Rakefile + # README.md + # + # With a block given, calls the block with an array of the wait processes: + # + # Open3.pipeline_start('ls', 'grep R') do |wait_threads| + # wait_threads.each do |wait_thread| + # wait_thread.join + # end + # end + # + # Output: + # + # Rakefile + # README.md # - # # Run xeyes in 10 seconds. - # Open3.pipeline_start("xeyes") {|ts| - # sleep 10 - # t = ts[0] - # Process.kill("TERM", t.pid) - # p t.value #=> # - # } - # - # # Convert pdf to ps and send it to a printer. - # # Collect error message of pdftops and lpr. - # pdf_file = "paper.pdf" - # printer = "printer-name" - # err_r, err_w = IO.pipe - # Open3.pipeline_start(["pdftops", pdf_file, "-"], - # ["lpr", "-P#{printer}"], - # :err=>err_w) {|ts| - # err_w.close - # p err_r.read # error messages of pdftops and lpr. - # } + # Like Process.spawn, this method has potential security vulnerabilities + # if called with untrusted input; + # see {Command Injection}[rdoc-ref:command_injection.rdoc@Command+Injection]. + # + # If the first argument is a hash, it becomes leading argument +env+ + # in each call to Process.spawn; + # see {Execution Environment}[rdoc-ref:Process@Execution+Environment]. + # + # If the last argument is a hash, it becomes trailing argument +options+ + # in each call to Process.spawn; + # see {Execution Options}[rdoc-ref:Process@Execution+Options]. + # + # Each remaining argument in +cmds+ is one of: + # + # - A +command_line+: a string that begins with a shell reserved word + # or special built-in, or contains one or more metacharacters. + # - An +exe_path+: the string path to an executable to be called. + # - An array containing a +command_line+ or an +exe_path+, + # along with zero or more string arguments for the command. + # + # See {Argument command_line or exe_path}[rdoc-ref:Process@Argument+command_line+or+exe_path]. # def pipeline_start(*cmds, &block) if Hash === cmds.last @@ -633,57 +1285,51 @@ def pipeline_start(*cmds, &block) end module_function :pipeline_start - # Open3.pipeline starts a list of commands as a pipeline. - # It waits for the completion of the commands. - # No pipes are created for stdin of the first command and - # stdout of the last command. + # :call-seq: + # Open3.pipeline([env, ] *cmds, options = {}) -> array_of_statuses # - # status_list = Open3.pipeline(cmd1, cmd2, ... [, opts]) + # Basically a wrapper for + # {Process.spawn}[rdoc-ref:Process.spawn] + # that: # - # Each cmd is a string or an array. - # If it is an array, the elements are passed to Process.spawn. + # - Creates a child process for each of the given +cmds+ + # by calling Process.spawn. + # - Pipes the +stdout+ from each child to the +stdin+ of the next child, + # or, for the last child, to the caller's +stdout+. + # - Waits for the child processes to exit. + # - Returns an array of Process::Status objects (one for each child). # - # cmd: - # commandline command line string which is passed to a shell - # [env, commandline, opts] command line string which is passed to a shell - # [env, cmdname, arg1, ..., opts] command name and one or more arguments (no shell) - # [env, [cmdname, argv0], arg1, ..., opts] command name and arguments including argv[0] (no shell) + # Example: # - # Note that env and opts are optional, as Process.spawn. + # wait_threads = Open3.pipeline('ls', 'grep R') + # # => [#, #] # - # Example: + # Output: + # + # Rakefile + # README.md + # + # Like Process.spawn, this method has potential security vulnerabilities + # if called with untrusted input; + # see {Command Injection}[rdoc-ref:command_injection.rdoc@Command+Injection]. + # + # If the first argument is a hash, it becomes leading argument +env+ + # in each call to Process.spawn; + # see {Execution Environment}[rdoc-ref:Process@Execution+Environment]. + # + # If the last argument is a hash, it becomes trailing argument +options+ + # in each call to Process.spawn' + # see {Execution Options}[rdoc-ref:Process@Execution+Options]. + # + # Each remaining argument in +cmds+ is one of: + # + # - A +command_line+: a string that begins with a shell reserved word + # or special built-in, or contains one or more metacharacters. + # - An +exe_path+: the string path to an executable to be called. + # - An array containing a +command_line+ or an +exe_path+, + # along with zero or more string arguments for the command. # - # fname = "/usr/share/man/man1/ruby.1.gz" - # p Open3.pipeline(["zcat", fname], "nroff -man", "less") - # #=> [#, - # # #, - # # #] - # - # fname = "/usr/share/man/man1/ls.1.gz" - # Open3.pipeline(["zcat", fname], "nroff -man", "colcrt") - # - # # convert PDF to PS and send to a printer by lpr - # pdf_file = "paper.pdf" - # printer = "printer-name" - # Open3.pipeline(["pdftops", pdf_file, "-"], - # ["lpr", "-P#{printer}"]) - # - # # count lines - # Open3.pipeline("sort", "uniq -c", :in=>"names.txt", :out=>"count") - # - # # cyclic pipeline - # r,w = IO.pipe - # w.print "ibase=14\n10\n" - # Open3.pipeline("bc", "tee /dev/tty", :in=>r, :out=>w) - # #=> 14 - # # 18 - # # 22 - # # 30 - # # 42 - # # 58 - # # 78 - # # 106 - # # 202 + # See {Argument command_line or exe_path}[rdoc-ref:Process@Argument+command_line+or+exe_path]. # def pipeline(*cmds) if Hash === cmds.last diff --git a/lib/open3/version.rb b/lib/open3/version.rb index b6b6ee2c9c815a..bfcec44ccc920b 100644 --- a/lib/open3/version.rb +++ b/lib/open3/version.rb @@ -1,3 +1,3 @@ module Open3 - VERSION = "0.1.2" + VERSION = "0.2.1" end diff --git a/lib/optparse.rb b/lib/optparse.rb index 0998251fbf971b..332aea2148f696 100644 --- a/lib/optparse.rb +++ b/lib/optparse.rb @@ -7,7 +7,7 @@ # # See OptionParser for documentation. # - +require 'set' unless defined?(Set) #-- # == Developer Documentation (not for RDoc output) @@ -143,7 +143,7 @@ # Used: # # $ ruby optparse-test.rb -r -# optparse-test.rb:9:in `
': missing argument: -r (OptionParser::MissingArgument) +# optparse-test.rb:9:in '
': missing argument: -r (OptionParser::MissingArgument) # $ ruby optparse-test.rb -r my-library # You required my-library! # @@ -236,7 +236,7 @@ # $ ruby optparse-test.rb --user 2 # # # $ ruby optparse-test.rb --user 3 -# optparse-test.rb:15:in `block in find_user': No User Found for id 3 (RuntimeError) +# optparse-test.rb:15:in 'block in find_user': No User Found for id 3 (RuntimeError) # # === Store options to a Hash # @@ -425,7 +425,8 @@ # If you have any questions, file a ticket at http://bugs.ruby-lang.org. # class OptionParser - OptionParser::Version = "0.4.0.pre.1" + # The version string + OptionParser::Version = "0.7.0.dev.2" # :stopdoc: NoArgument = [NO_ARGUMENT = :NONE, nil].freeze @@ -438,6 +439,8 @@ class OptionParser # and resolved against a list of acceptable values. # module Completion + # :nodoc: + def self.regexp(key, icase) Regexp.new('\A' + Regexp.quote(key).gsub(/\w+\b/, '\&\w*'), icase) end @@ -459,7 +462,11 @@ def self.candidate(key, icase = false, pat = nil, &block) candidates end - def candidate(key, icase = false, pat = nil) + def self.completable?(key) + String.try_convert(key) or defined?(key.id2name) + end + + def candidate(key, icase = false, pat = nil, &_) Completion.candidate(key, icase, pat, &method(:each)) end @@ -494,7 +501,6 @@ def convert(opt = nil, val = nil, *) end end - # # Map from option/keyword string to object with completion. # @@ -502,7 +508,6 @@ class OptionMap < Hash include Completion end - # # Individual switch class. Not important to the user. # @@ -510,6 +515,8 @@ class OptionMap < Hash # RequiredArgument, etc. # class Switch + # :nodoc: + attr_reader :pattern, :conv, :short, :long, :arg, :desc, :block # @@ -542,11 +549,11 @@ def self.pattern def initialize(pattern = nil, conv = nil, short = nil, long = nil, arg = nil, - desc = ([] if short or long), block = nil, &_block) + desc = ([] if short or long), block = nil, values = nil, &_block) raise if Array === pattern block ||= _block - @pattern, @conv, @short, @long, @arg, @desc, @block = - pattern, conv, short, long, arg, desc, block + @pattern, @conv, @short, @long, @arg, @desc, @block, @values = + pattern, conv, short, long, arg, desc, block, values end # @@ -579,11 +586,15 @@ def parse_arg(arg) # :nodoc: # exception. # def conv_arg(arg, val = []) # :nodoc: + v, = *val if conv val = conv.call(*val) else val = proc {|v| v}.call(*val) end + if @values + @values.include?(val) or raise InvalidArgument, v + end return arg, block, val end private :conv_arg @@ -664,7 +675,7 @@ def compsys(sdone, ldone) # :nodoc: (sopts+lopts).each do |opt| # "(-x -c -r)-l[left justify]" - if /^--\[no-\](.+)$/ =~ opt + if /\A--\[no-\](.+)$/ =~ opt o = $1 yield("--#{o}", desc.join("")) yield("--no-#{o}", desc.join("")) @@ -697,6 +708,11 @@ def pretty_print(q) # :nodoc: q.object_group(self) {pretty_print_contents(q)} end + def omitted_argument(val) # :nodoc: + val.pop if val.size == 3 and val.last.nil? + val + end + # # Switch that takes no arguments. # @@ -710,10 +726,10 @@ def parse(arg, argv) conv_arg(arg) end - def self.incompatible_argument_styles(*) + def self.incompatible_argument_styles(*) # :nodoc: end - def self.pattern + def self.pattern # :nodoc: Object end @@ -730,7 +746,7 @@ class RequiredArgument < self # # Raises an exception if argument is not present. # - def parse(arg, argv) + def parse(arg, argv, &_) unless arg raise MissingArgument if argv.empty? arg = argv.shift @@ -755,7 +771,7 @@ def parse(arg, argv, &error) if arg conv_arg(*parse_arg(arg, &error)) else - conv_arg(arg) + omitted_argument conv_arg(arg) end end @@ -774,13 +790,14 @@ class PlacedArgument < self # def parse(arg, argv, &error) if !(val = arg) and (argv.empty? or /\A-./ =~ (val = argv[0])) - return nil, block, nil + return nil, block end opt = (val = parse_arg(val, &error))[1] val = conv_arg(*val) if opt and !arg argv.shift else + omitted_argument val val[0] = nil end val @@ -798,6 +815,8 @@ def pretty_head # :nodoc: # matching pattern and converter pair. Also provides summary feature. # class List + # :nodoc: + # Map from acceptable argument types to pattern and converter pairs. attr_reader :atype @@ -837,7 +856,7 @@ def pretty_print(q) # :nodoc: def accept(t, pat = /.*/m, &block) if pat pat.respond_to?(:match) or - raise TypeError, "has no `match'", ParseError.filter_backtrace(caller(2)) + raise TypeError, "has no 'match'", ParseError.filter_backtrace(caller(2)) else pat = t if t.respond_to?(:match) end @@ -1020,7 +1039,6 @@ def match(key) DefaultList.short['-'] = Switch::NoArgument.new {} DefaultList.long[''] = Switch::NoArgument.new {throw :terminate} - COMPSYS_HEADER = <<'XXX' # :nodoc: typeset -A opt_args @@ -1033,11 +1051,31 @@ def compsys(to, name = File.basename($0)) # :nodoc: to << "#compdef #{name}\n" to << COMPSYS_HEADER visit(:compsys, {}, {}) {|o, d| - to << %Q[ "#{o}[#{d.gsub(/[\"\[\]]/, '\\\\\&')}]" \\\n] + to << %Q[ "#{o}[#{d.gsub(/[\\\"\[\]]/, '\\\\\&')}]" \\\n] } to << " '*:file:_files' && return 0\n" end + def help_exit + if $stdout.tty? && (pager = ENV.values_at(*%w[RUBY_PAGER PAGER]).find {|e| e && !e.empty?}) + less = ENV["LESS"] + args = [{"LESS" => "#{less} -Fe"}, pager, "w"] + print = proc do |f| + f.puts help + rescue Errno::EPIPE + # pager terminated + end + if Process.respond_to?(:fork) and false + IO.popen("-") {|f| f ? Process.exec(*args, in: f) : print.call($stdout)} + # unreachable + end + IO.popen(*args, &print) + else + puts help + end + exit + end + # # Default options for ARGV, which never appear in option summary. # @@ -1049,8 +1087,7 @@ def compsys(to, name = File.basename($0)) # :nodoc: # Officious['help'] = proc do |parser| Switch::NoArgument.new do |arg| - puts parser.help - exit + parser.help_exit end end @@ -1071,7 +1108,7 @@ def compsys(to, name = File.basename($0)) # :nodoc: # Officious['*-completion-zsh'] = proc do |parser| Switch::OptionalArgument.new do |arg| - parser.compsys(STDOUT, arg) + parser.compsys($stdout, arg) exit end end @@ -1084,7 +1121,7 @@ def compsys(to, name = File.basename($0)) # :nodoc: Switch::OptionalArgument.new do |pkg| if pkg begin - require 'optparse/version' + require_relative 'optparse/version' rescue LoadError else show_version(*pkg.split(/,/)) or @@ -1129,6 +1166,10 @@ def self.inc(arg, default = nil) default.to_i + 1 end end + + # + # See self.inc + # def inc(*args) self.class.inc(*args) end @@ -1167,11 +1208,19 @@ def add_officious # :nodoc: def terminate(arg = nil) self.class.terminate(arg) end + # + # See #terminate. + # def self.terminate(arg = nil) throw :terminate, arg end @stack = [DefaultList] + # + # Returns the global top option list. + # + # Do not use directly. + # def self.top() DefaultList end # @@ -1192,9 +1241,9 @@ def self.accept(*args, &blk) top.accept(*args, &blk) end # # Directs to reject specified class argument. # - # +t+:: Argument class specifier, any object including Class. + # +type+:: Argument class specifier, any object including Class. # - # reject(t) + # reject(type) # def reject(*args, &blk) top.reject(*args, &blk) end # @@ -1245,7 +1294,15 @@ def banner # to $0. # def program_name - @program_name || File.basename($0, '.*') + @program_name || strip_ext(File.basename($0)) + end + + private def strip_ext(name) # :nodoc: + exts = /#{ + require "rbconfig" + Regexp.union(*RbConfig::CONFIG["EXECUTABLE_EXTS"]&.split(" ")) + }\z/o + name.sub(exts, "") end # for experimental cascading :-) @@ -1284,10 +1341,24 @@ def ver end end + # + # Shows warning message with the program name + # + # +mesg+:: Message, defaulted to +$!+. + # + # See Kernel#warn. + # def warn(mesg = $!) super("#{program_name}: #{mesg}") end + # + # Shows message with the program name then aborts. + # + # +mesg+:: Message, defaulted to +$!+. + # + # See Kernel#abort. + # def abort(mesg = $!) super("#{program_name}: #{mesg}") end @@ -1309,6 +1380,9 @@ def base # # Pushes a new List. # + # If a block is given, yields +self+ and returns the result of the + # block, otherwise returns +self+. + # def new @stack.push(List.new) if block_given? @@ -1407,6 +1481,7 @@ def make_switch(opts, block = nil) klass = nil q, a = nil has_arg = false + values = nil opts.each do |o| # argument class @@ -1420,7 +1495,7 @@ def make_switch(opts, block = nil) end # directly specified pattern(any object possible to match) - if (!(String === o || Symbol === o)) and o.respond_to?(:match) + if !Completion.completable?(o) and o.respond_to?(:match) pattern = notwice(o, pattern, 'pattern') if pattern.respond_to?(:convert) conv = pattern.method(:convert).to_proc @@ -1434,7 +1509,12 @@ def make_switch(opts, block = nil) case o when Proc, Method block = notwice(o, block, 'block') - when Array, Hash + when Array, Hash, Set + if Array === o + o, v = o.partition {|v,| Completion.completable?(v)} + values = notwice(v, values, 'values') unless v.empty? + next if o.empty? + end case pattern when CompletingHash when nil @@ -1444,11 +1524,13 @@ def make_switch(opts, block = nil) raise ArgumentError, "argument pattern given twice" end o.each {|pat, *v| pattern[pat] = v.fetch(0) {pat}} + when Range + values = notwice(o, values, 'values') when Module raise ArgumentError, "unsupported argument type: #{o}", ParseError.filter_backtrace(caller(4)) when *ArgumentStyle.keys style = notwice(ArgumentStyle[o], style, 'style') - when /^--no-([^\[\]=\s]*)(.+)?/ + when /\A--no-([^\[\]=\s]*)(.+)?/ q, a = $1, $2 o = notwice(a ? Object : TrueClass, klass, 'type') not_pattern, not_conv = search(:atype, o) unless not_style @@ -1459,7 +1541,7 @@ def make_switch(opts, block = nil) (q = q.downcase).tr!('_', '-') long << "no-#{q}" nolong << q - when /^--\[no-\]([^\[\]=\s]*)(.+)?/ + when /\A--\[no-\]([^\[\]=\s]*)(.+)?/ q, a = $1, $2 o = notwice(a ? Object : TrueClass, klass, 'type') if a @@ -1472,7 +1554,7 @@ def make_switch(opts, block = nil) not_pattern, not_conv = search(:atype, FalseClass) unless not_style not_style = Switch::NoArgument nolong << "no-#{o}" - when /^--([^\[\]=\s]*)(.+)?/ + when /\A--([^\[\]=\s]*)(.+)?/ q, a = $1, $2 if a o = notwice(NilClass, klass, 'type') @@ -1482,7 +1564,7 @@ def make_switch(opts, block = nil) ldesc << "--#{q}" (o = q.downcase).tr!('_', '-') long << o - when /^-(\[\^?\]?(?:[^\\\]]|\\.)*\])(.+)?/ + when /\A-(\[\^?\]?(?:[^\\\]]|\\.)*\])(.+)?/ q, a = $1, $2 o = notwice(Object, klass, 'type') if a @@ -1493,7 +1575,7 @@ def make_switch(opts, block = nil) end sdesc << "-#{q}" short << Regexp.new(q) - when /^-(.)(.+)?/ + when /\A-(.)(.+)?/ q, a = $1, $2 if a o = notwice(NilClass, klass, 'type') @@ -1502,7 +1584,7 @@ def make_switch(opts, block = nil) end sdesc << "-#{q}" short << q - when /^=/ + when /\A=/ style = notwice(default_style.guess(arg = o), style, 'style') default_pattern, conv = search(:atype, Object) unless default_pattern else @@ -1511,12 +1593,18 @@ def make_switch(opts, block = nil) end default_pattern, conv = search(:atype, default_style.pattern) unless default_pattern + if Range === values and klass + unless (!values.begin or klass === values.begin) and + (!values.end or klass === values.end) + raise ArgumentError, "range does not match class" + end + end if !(short.empty? and long.empty?) if has_arg and default_style == Switch::NoArgument default_style = Switch::RequiredArgument end s = (style || default_style).new(pattern || default_pattern, - conv, sdesc, ldesc, arg, desc, block) + conv, sdesc, ldesc, arg, desc, block, values) elsif !block if style or pattern raise ArgumentError, "no switch given", ParseError.filter_backtrace(caller) @@ -1525,13 +1613,19 @@ def make_switch(opts, block = nil) else short << pattern s = (style || default_style).new(pattern, - conv, nil, nil, arg, desc, block) + conv, nil, nil, arg, desc, block, values) end return s, short, long, (not_style.new(not_pattern, not_conv, sdesc, ldesc, nil, desc, block) if not_style), nolong end + # ---- + # Option definition phase methods + # + # These methods are used to define options, or to construct an + # OptionParser instance in other words. + # :call-seq: # define(*params, &block) # @@ -1607,6 +1701,13 @@ def separator(string) top.append(string, nil, nil) end + # ---- + # Arguments parse phase methods + # + # These methods parse +argv+, convert, and store the results by + # calling handlers. As these methods do not modify +self+, +self+ + # can be frozen. + # # Parses command line arguments +argv+ in order. When a block is given, # each non-option argument is yielded. When optional +into+ keyword @@ -1616,21 +1717,21 @@ def separator(string) # # Returns the rest of +argv+ left unparsed. # - def order(*argv, into: nil, &nonopt) + def order(*argv, **keywords, &nonopt) argv = argv[0].dup if argv.size == 1 and Array === argv[0] - order!(argv, into: into, &nonopt) + order!(argv, **keywords, &nonopt) end # # Same as #order, but removes switches destructively. # Non-option arguments remain in +argv+. # - def order!(argv = default_argv, into: nil, &nonopt) + def order!(argv = default_argv, into: nil, **keywords, &nonopt) setter = ->(name, val) {into[name.to_sym] = val} if into - parse_in_order(argv, setter, &nonopt) + parse_in_order(argv, setter, **keywords, &nonopt) end - def parse_in_order(argv = default_argv, setter = nil, &nonopt) # :nodoc: + def parse_in_order(argv = default_argv, setter = nil, exact: require_exact, **, &nonopt) # :nodoc: opt, arg, val, rest = nil nonopt ||= proc {|a| throw :terminate, a} argv.unshift(arg) if arg = catch(:terminate) { @@ -1641,19 +1742,24 @@ def parse_in_order(argv = default_argv, setter = nil, &nonopt) # :nodoc: opt, rest = $1, $2 opt.tr!('_', '-') begin - sw, = complete(:long, opt, true) - if require_exact && !sw.long.include?(arg) - throw :terminate, arg unless raise_unknown - raise InvalidOption, arg + if exact + sw, = search(:long, opt) + else + sw, = complete(:long, opt, true) end rescue ParseError throw :terminate, arg unless raise_unknown raise $!.set_option(arg, true) + else + unless sw + throw :terminate, arg unless raise_unknown + raise InvalidOption, arg + end end begin opt, cb, val = sw.parse(rest, argv) {|*exc| raise(*exc)} - val = cb.call(val) if cb - setter.call(sw.switch_name, val) if setter + val = callback!(cb, 1, val) if cb + callback!(setter, 2, sw.switch_name, val) if setter rescue ParseError raise $!.set_option(arg, rest) end @@ -1671,7 +1777,7 @@ def parse_in_order(argv = default_argv, setter = nil, &nonopt) # :nodoc: val = arg.delete_prefix('-') has_arg = true rescue InvalidOption - raise if require_exact + raise if exact # if no short options match, try completion with long # options. sw, = complete(:long, opt) @@ -1691,8 +1797,8 @@ def parse_in_order(argv = default_argv, setter = nil, &nonopt) # :nodoc: end begin argv.unshift(opt) if opt and (!rest or (opt = opt.sub(/\A-*/, '-')) != '-') - val = cb.call(val) if cb - setter.call(sw.switch_name, val) if setter + val = callback!(cb, 1, val) if cb + callback!(setter, 2, sw.switch_name, val) if setter rescue ParseError raise $!.set_option(arg, arg.length > 2) end @@ -1718,6 +1824,19 @@ def parse_in_order(argv = default_argv, setter = nil, &nonopt) # :nodoc: end private :parse_in_order + # Calls callback with _val_. + def callback!(cb, max_arity, *args) # :nodoc: + args.compact! + + if (size = args.size) < max_arity and cb.to_proc.lambda? + (arity = cb.arity) < 0 and arity = (1-arity) + arity = max_arity if arity > max_arity + args[arity - 1] = nil if arity > size + end + cb.call(*args) + end + private :callback! + # # Parses command line arguments +argv+ in permutation mode and returns # list of non-option arguments. When optional +into+ keyword @@ -1725,18 +1844,18 @@ def parse_in_order(argv = default_argv, setter = nil, &nonopt) # :nodoc: # []= method (so it can be Hash, or OpenStruct, or other # similar object). # - def permute(*argv, into: nil) + def permute(*argv, **keywords) argv = argv[0].dup if argv.size == 1 and Array === argv[0] - permute!(argv, into: into) + permute!(argv, **keywords) end # # Same as #permute, but removes switches destructively. # Non-option arguments remain in +argv+. # - def permute!(argv = default_argv, into: nil) + def permute!(argv = default_argv, **keywords) nonopts = [] - order!(argv, into: into, &nonopts.method(:<<)) + order!(argv, **keywords, &nonopts.method(:<<)) argv[0, 0] = nonopts argv end @@ -1748,20 +1867,20 @@ def permute!(argv = default_argv, into: nil) # values are stored there via []= method (so it can be Hash, # or OpenStruct, or other similar object). # - def parse(*argv, into: nil) + def parse(*argv, **keywords) argv = argv[0].dup if argv.size == 1 and Array === argv[0] - parse!(argv, into: into) + parse!(argv, **keywords) end # # Same as #parse, but removes switches destructively. # Non-option arguments remain in +argv+. # - def parse!(argv = default_argv, into: nil) + def parse!(argv = default_argv, **keywords) if ENV.include?('POSIXLY_CORRECT') - order!(argv, into: into) + order!(argv, **keywords) else - permute!(argv, into: into) + permute!(argv, **keywords) end end @@ -1784,7 +1903,7 @@ def parse!(argv = default_argv, into: nil) # # params[:bar] = "x" # --bar x # # params[:zot] = "z" # --zot Z # - def getopts(*args, symbolize_names: false) + def getopts(*args, symbolize_names: false, **keywords) argv = Array === args.first ? args.shift : default_argv single_options, *long_options = *args @@ -1812,7 +1931,7 @@ def getopts(*args, symbolize_names: false) end end - parse_in_order(argv, result.method(:[]=)) + parse_in_order(argv, result.method(:[]=), **keywords) symbolize_names ? result.transform_keys(&:to_sym) : result end @@ -1881,6 +2000,9 @@ def additional_message(typ, opt) DidYouMean.formatter.message_for(all_candidates & checker.correct(opt)) end + # + # Return candidates for +word+. + # def candidate(word) list = [] case word @@ -1922,10 +2044,10 @@ def candidate(word) # The optional +into+ keyword argument works exactly like that accepted in # method #parse. # - def load(filename = nil, into: nil) + def load(filename = nil, **keywords) unless filename basename = File.basename($0, '.*') - return true if load(File.expand_path(basename, '~/.options'), into: into) rescue nil + return true if load(File.expand_path(basename, '~/.options'), **keywords) rescue nil basename << ".options" return [ # XDG @@ -1937,11 +2059,11 @@ def load(filename = nil, into: nil) '~/config/settings', ].any? {|dir| next if !dir or dir.empty? - load(File.expand_path(basename, dir), into: into) rescue nil + load(File.expand_path(basename, dir), **keywords) rescue nil } end begin - parse(*File.readlines(filename, chomp: true), into: into) + parse(*File.readlines(filename, chomp: true), **keywords) true rescue Errno::ENOENT, Errno::ENOTDIR false @@ -1954,10 +2076,10 @@ def load(filename = nil, into: nil) # # +env+ defaults to the basename of the program. # - def environment(env = File.basename($0, '.*')) + def environment(env = File.basename($0, '.*'), **keywords) env = ENV[env] || ENV[env.upcase] or return require 'shellwords' - parse(*Shellwords.shellwords(env)) + parse(*Shellwords.shellwords(env), **keywords) end # @@ -2123,6 +2245,7 @@ class ParseError < RuntimeError # Reason which caused the error. Reason = 'parse error' + # :nodoc: def initialize(*args, additional: nil) @additional = additional @arg0, = args @@ -2273,19 +2396,19 @@ def options # Parses +self+ destructively in order and returns +self+ containing the # rest arguments left unparsed. # - def order!(&blk) options.order!(self, &blk) end + def order!(**keywords, &blk) options.order!(self, **keywords, &blk) end # # Parses +self+ destructively in permutation mode and returns +self+ # containing the rest arguments left unparsed. # - def permute!() options.permute!(self) end + def permute!(**keywords) options.permute!(self, **keywords) end # # Parses +self+ destructively and returns +self+ containing the # rest arguments left unparsed. # - def parse!() options.parse!(self) end + def parse!(**keywords) options.parse!(self, **keywords) end # # Substitution of getopts is possible as follows. Also see @@ -2298,8 +2421,8 @@ def parse!() options.parse!(self) end # rescue OptionParser::ParseError # end # - def getopts(*args, symbolize_names: false) - options.getopts(self, *args, symbolize_names: symbolize_names) + def getopts(*args, symbolize_names: false, **keywords) + options.getopts(self, *args, symbolize_names: symbolize_names, **keywords) end # @@ -2309,7 +2432,8 @@ def self.extend_object(obj) super obj.instance_eval {@optparse = nil} end - def initialize(*args) + + def initialize(*args) # :nodoc: super @optparse = nil end diff --git a/lib/optparse/ac.rb b/lib/optparse/ac.rb index 0953725e46ed8e..23fc740d100300 100644 --- a/lib/optparse/ac.rb +++ b/lib/optparse/ac.rb @@ -1,7 +1,11 @@ # frozen_string_literal: false require_relative '../optparse' +# +# autoconf-like options. +# class OptionParser::AC < OptionParser + # :stopdoc: private def _check_ac_args(name, block) @@ -14,6 +18,7 @@ def _check_ac_args(name, block) end ARG_CONV = proc {|val| val.nil? ? true : val} + private_constant :ARG_CONV def _ac_arg_enable(prefix, name, help_string, block) _check_ac_args(name, block) @@ -29,16 +34,27 @@ def _ac_arg_enable(prefix, name, help_string, block) enable end + # :startdoc: + public + # Define --enable / --disable style option + # + # Appears as --enable-name in help message. def ac_arg_enable(name, help_string, &block) _ac_arg_enable("enable", name, help_string, block) end + # Define --enable / --disable style option + # + # Appears as --disable-name in help message. def ac_arg_disable(name, help_string, &block) _ac_arg_enable("disable", name, help_string, block) end + # Define --with / --without style option + # + # Appears as --with-name in help message. def ac_arg_with(name, help_string, &block) _check_ac_args(name, block) diff --git a/lib/optparse/kwargs.rb b/lib/optparse/kwargs.rb index 992aca467eb870..59a2f61544f9e5 100644 --- a/lib/optparse/kwargs.rb +++ b/lib/optparse/kwargs.rb @@ -7,12 +7,17 @@ class OptionParser # # :include: ../../doc/optparse/creates_option.rdoc # - def define_by_keywords(options, meth, **opts) - meth.parameters.each do |type, name| + # Defines options which set in to _options_ for keyword parameters + # of _method_. + # + # Parameters for each keywords are given as elements of _params_. + # + def define_by_keywords(options, method, **params) + method.parameters.each do |type, name| case type when :key, :keyreq op, cl = *(type == :key ? %w"[ ]" : ["", ""]) - define("--#{name}=#{op}#{name.upcase}#{cl}", *opts[name]) do |o| + define("--#{name}=#{op}#{name.upcase}#{cl}", *params[name]) do |o| options[name] = o end end diff --git a/lib/optparse/optparse.gemspec b/lib/optparse/optparse.gemspec index a4287ddeeed7ed..6ea6b883956dc0 100644 --- a/lib/optparse/optparse.gemspec +++ b/lib/optparse/optparse.gemspec @@ -14,7 +14,10 @@ Gem::Specification.new do |spec| spec.email = ["nobu@ruby-lang.org"] spec.summary = %q{OptionParser is a class for command-line option analysis.} - spec.description = %q{OptionParser is a class for command-line option analysis.} + spec.description = File.open(File.join(__dir__, "README.md")) do |readme| + readme.gets("") # heading + readme.gets("").chomp + end rescue spec.summary spec.homepage = "https://github.com/ruby/optparse" spec.required_ruby_version = Gem::Requirement.new(">= 2.5.0") spec.licenses = ["Ruby", "BSD-2-Clause"] @@ -22,8 +25,9 @@ Gem::Specification.new do |spec| spec.metadata["homepage_uri"] = spec.homepage spec.metadata["source_code_uri"] = spec.homepage - spec.files = Dir["{doc,lib,misc}/**/*"] + %w[README.md ChangeLog COPYING] - spec.rdoc_options = ["--main=README.md", "--op=rdoc", "--page-dir=doc"] + dir, gemspec = File.split(__FILE__) + excludes = %W[#{gemspec} rakelib test/ Gemfile Rakefile .git* .editor*].map {|n| ":^"+n} + spec.files = IO.popen(%w[git ls-files -z --] + excludes, chdir: dir, &:read).split("\x0") spec.bindir = "exe" spec.executables = [] spec.require_paths = ["lib"] diff --git a/lib/optparse/version.rb b/lib/optparse/version.rb index b869d8fe51ed47..b5ed6951460bb1 100644 --- a/lib/optparse/version.rb +++ b/lib/optparse/version.rb @@ -2,6 +2,11 @@ # OptionParser internal utility class << OptionParser + # + # Shows version string in packages if Version is defined. + # + # +pkgs+:: package list + # def show_version(*pkgs) progname = ARGV.options.program_name result = false @@ -47,6 +52,8 @@ def show_version(*pkgs) result end + # :stopdoc: + def each_const(path, base = ::Object) path.split(/::|\//).inject(base) do |klass, name| raise NameError, path unless Module === klass @@ -68,4 +75,6 @@ def search_const(klass, name) end end end + + # :startdoc: end diff --git a/lib/ostruct.gemspec b/lib/ostruct.gemspec deleted file mode 100644 index 21cce182260a65..00000000000000 --- a/lib/ostruct.gemspec +++ /dev/null @@ -1,27 +0,0 @@ -# frozen_string_literal: true - -name = File.basename(__FILE__, ".gemspec") -version = ["lib", Array.new(name.count("-")+1, ".").join("/")].find do |dir| - break File.foreach(File.join(__dir__, dir, "#{name.tr('-', '/')}.rb")) do |line| - /^\s*VERSION\s*=\s*"(.*)"/ =~ line and break $1 - end rescue nil -end - -Gem::Specification.new do |spec| - spec.name = name - spec.version = version - spec.authors = ["Marc-Andre Lafortune"] - spec.email = ["ruby-core@marc-andre.ca"] - - spec.summary = %q{Class to build custom data structures, similar to a Hash.} - spec.description = %q{Class to build custom data structures, similar to a Hash.} - spec.homepage = "https://github.com/ruby/ostruct" - spec.licenses = ["Ruby", "BSD-2-Clause"] - spec.required_ruby_version = ">= 2.5.0" - - spec.files = [".gitignore", "Gemfile", "LICENSE.txt", "README.md", "Rakefile", "bin/console", "bin/setup", "lib/ostruct.rb", "ostruct.gemspec"] - spec.require_paths = ["lib"] - - spec.add_development_dependency "bundler" - spec.add_development_dependency "rake" -end diff --git a/lib/ostruct.rb b/lib/ostruct.rb deleted file mode 100644 index a08561d6c96aca..00000000000000 --- a/lib/ostruct.rb +++ /dev/null @@ -1,477 +0,0 @@ -# frozen_string_literal: true -# -# = ostruct.rb: OpenStruct implementation -# -# Author:: Yukihiro Matsumoto -# Documentation:: Gavin Sinclair -# -# OpenStruct allows the creation of data objects with arbitrary attributes. -# See OpenStruct for an example. -# - -# -# An OpenStruct is a data structure, similar to a Hash, that allows the -# definition of arbitrary attributes with their accompanying values. This is -# accomplished by using Ruby's metaprogramming to define methods on the class -# itself. -# -# == Examples -# -# require "ostruct" -# -# person = OpenStruct.new -# person.name = "John Smith" -# person.age = 70 -# -# person.name # => "John Smith" -# person.age # => 70 -# person.address # => nil -# -# An OpenStruct employs a Hash internally to store the attributes and values -# and can even be initialized with one: -# -# australia = OpenStruct.new(:country => "Australia", :capital => "Canberra") -# # => # -# -# Hash keys with spaces or characters that could normally not be used for -# method calls (e.g. ()[]*) will not be immediately available -# on the OpenStruct object as a method for retrieval or assignment, but can -# still be reached through the Object#send method or using []. -# -# measurements = OpenStruct.new("length (in inches)" => 24) -# measurements[:"length (in inches)"] # => 24 -# measurements.send("length (in inches)") # => 24 -# -# message = OpenStruct.new(:queued? => true) -# message.queued? # => true -# message.send("queued?=", false) -# message.queued? # => false -# -# Removing the presence of an attribute requires the execution of the -# delete_field method as setting the property value to +nil+ will not -# remove the attribute. -# -# first_pet = OpenStruct.new(:name => "Rowdy", :owner => "John Smith") -# second_pet = OpenStruct.new(:name => "Rowdy") -# -# first_pet.owner = nil -# first_pet # => # -# first_pet == second_pet # => false -# -# first_pet.delete_field(:owner) -# first_pet # => # -# first_pet == second_pet # => true -# -# Ractor compatibility: A frozen OpenStruct with shareable values is itself shareable. -# -# == Caveats -# -# An OpenStruct utilizes Ruby's method lookup structure to find and define the -# necessary methods for properties. This is accomplished through the methods -# method_missing and define_singleton_method. -# -# This should be a consideration if there is a concern about the performance of -# the objects that are created, as there is much more overhead in the setting -# of these properties compared to using a Hash or a Struct. -# Creating an open struct from a small Hash and accessing a few of the -# entries can be 200 times slower than accessing the hash directly. -# -# This is a potential security issue; building OpenStruct from untrusted user data -# (e.g. JSON web request) may be susceptible to a "symbol denial of service" attack -# since the keys create methods and names of methods are never garbage collected. -# -# This may also be the source of incompatibilities between Ruby versions: -# -# o = OpenStruct.new -# o.then # => nil in Ruby < 2.6, enumerator for Ruby >= 2.6 -# -# Builtin methods may be overwritten this way, which may be a source of bugs -# or security issues: -# -# o = OpenStruct.new -# o.methods # => [:to_h, :marshal_load, :marshal_dump, :each_pair, ... -# o.methods = [:foo, :bar] -# o.methods # => [:foo, :bar] -# -# To help remedy clashes, OpenStruct uses only protected/private methods ending with ! -# and defines aliases for builtin public methods by adding a !: -# -# o = OpenStruct.new(make: 'Bentley', class: :luxury) -# o.class # => :luxury -# o.class! # => OpenStruct -# -# It is recommended (but not enforced) to not use fields ending in !; -# Note that a subclass' methods may not be overwritten, nor can OpenStruct's own methods -# ending with !. -# -# For all these reasons, consider not using OpenStruct at all. -# -class OpenStruct - VERSION = "0.5.5" - - # - # Creates a new OpenStruct object. By default, the resulting OpenStruct - # object will have no attributes. - # - # The optional +hash+, if given, will generate attributes and values - # (can be a Hash, an OpenStruct or a Struct). - # For example: - # - # require "ostruct" - # hash = { "country" => "Australia", :capital => "Canberra" } - # data = OpenStruct.new(hash) - # - # data # => # - # - def initialize(hash=nil) - if hash - update_to_values!(hash) - else - @table = {} - end - end - - # Duplicates an OpenStruct object's Hash table. - private def initialize_clone(orig) # :nodoc: - super # clones the singleton class for us - @table = @table.dup unless @table.frozen? - end - - private def initialize_dup(orig) # :nodoc: - super - update_to_values!(@table) - end - - private def update_to_values!(hash) # :nodoc: - @table = {} - hash.each_pair do |k, v| - set_ostruct_member_value!(k, v) - end - end - - # - # call-seq: - # ostruct.to_h -> hash - # ostruct.to_h {|name, value| block } -> hash - # - # Converts the OpenStruct to a hash with keys representing - # each attribute (as symbols) and their corresponding values. - # - # If a block is given, the results of the block on each pair of - # the receiver will be used as pairs. - # - # require "ostruct" - # data = OpenStruct.new("country" => "Australia", :capital => "Canberra") - # data.to_h # => {:country => "Australia", :capital => "Canberra" } - # data.to_h {|name, value| [name.to_s, value.upcase] } - # # => {"country" => "AUSTRALIA", "capital" => "CANBERRA" } - # - if {test: :to_h}.to_h{ [:works, true] }[:works] # RUBY_VERSION < 2.6 compatibility - def to_h(&block) - if block - @table.to_h(&block) - else - @table.dup - end - end - else - def to_h(&block) - if block - @table.map(&block).to_h - else - @table.dup - end - end - end - - # - # :call-seq: - # ostruct.each_pair {|name, value| block } -> ostruct - # ostruct.each_pair -> Enumerator - # - # Yields all attributes (as symbols) along with the corresponding values - # or returns an enumerator if no block is given. - # - # require "ostruct" - # data = OpenStruct.new("country" => "Australia", :capital => "Canberra") - # data.each_pair.to_a # => [[:country, "Australia"], [:capital, "Canberra"]] - # - def each_pair - return to_enum(__method__) { @table.size } unless defined?(yield) - @table.each_pair{|p| yield p} - self - end - - # - # Provides marshalling support for use by the Marshal library. - # - def marshal_dump # :nodoc: - @table - end - - # - # Provides marshalling support for use by the Marshal library. - # - alias_method :marshal_load, :update_to_values! # :nodoc: - - # - # Used internally to defined properties on the - # OpenStruct. It does this by using the metaprogramming function - # define_singleton_method for both the getter method and the setter method. - # - def new_ostruct_member!(name) # :nodoc: - unless @table.key?(name) || is_method_protected!(name) - if defined?(::Ractor) - getter_proc = nil.instance_eval{ Proc.new { @table[name] } } - setter_proc = nil.instance_eval{ Proc.new {|x| @table[name] = x} } - ::Ractor.make_shareable(getter_proc) - ::Ractor.make_shareable(setter_proc) - else - getter_proc = Proc.new { @table[name] } - setter_proc = Proc.new {|x| @table[name] = x} - end - define_singleton_method!(name, &getter_proc) - define_singleton_method!("#{name}=", &setter_proc) - end - end - private :new_ostruct_member! - - private def is_method_protected!(name) # :nodoc: - if !respond_to?(name, true) - false - elsif name.match?(/!$/) - true - else - owner = method!(name).owner - if owner.class == ::Class - owner < ::OpenStruct - else - self.class!.ancestors.any? do |mod| - return false if mod == ::OpenStruct - mod == owner - end - end - end - end - - def freeze - @table.freeze - super - end - - private def method_missing(mid, *args) # :nodoc: - len = args.length - if mname = mid[/.*(?==\z)/m] - if len != 1 - raise! ArgumentError, "wrong number of arguments (given #{len}, expected 1)", caller(1) - end - set_ostruct_member_value!(mname, args[0]) - elsif len == 0 - @table[mid] - else - begin - super - rescue NoMethodError => err - err.backtrace.shift - raise! - end - end - end - - # - # :call-seq: - # ostruct[name] -> object - # - # Returns the value of an attribute, or +nil+ if there is no such attribute. - # - # require "ostruct" - # person = OpenStruct.new("name" => "John Smith", "age" => 70) - # person[:age] # => 70, same as person.age - # - def [](name) - @table[name.to_sym] - end - - # - # :call-seq: - # ostruct[name] = obj -> obj - # - # Sets the value of an attribute. - # - # require "ostruct" - # person = OpenStruct.new("name" => "John Smith", "age" => 70) - # person[:age] = 42 # equivalent to person.age = 42 - # person.age # => 42 - # - def []=(name, value) - name = name.to_sym - new_ostruct_member!(name) - @table[name] = value - end - alias_method :set_ostruct_member_value!, :[]= - private :set_ostruct_member_value! - - # :call-seq: - # ostruct.dig(name, *identifiers) -> object - # - # Finds and returns the object in nested objects - # that is specified by +name+ and +identifiers+. - # The nested objects may be instances of various classes. - # See {Dig Methods}[rdoc-ref:dig_methods.rdoc]. - # - # Examples: - # require "ostruct" - # address = OpenStruct.new("city" => "Anytown NC", "zip" => 12345) - # person = OpenStruct.new("name" => "John Smith", "address" => address) - # person.dig(:address, "zip") # => 12345 - # person.dig(:business_address, "zip") # => nil - def dig(name, *names) - begin - name = name.to_sym - rescue NoMethodError - raise! TypeError, "#{name} is not a symbol nor a string" - end - @table.dig(name, *names) - end - - # - # Removes the named field from the object and returns the value the field - # contained if it was defined. You may optionally provide a block. - # If the field is not defined, the result of the block is returned, - # or a NameError is raised if no block was given. - # - # require "ostruct" - # - # person = OpenStruct.new(name: "John", age: 70, pension: 300) - # - # person.delete_field!("age") # => 70 - # person # => # - # - # Setting the value to +nil+ will not remove the attribute: - # - # person.pension = nil - # person # => # - # - # person.delete_field('number') # => NameError - # - # person.delete_field('number') { 8675_309 } # => 8675309 - # - def delete_field(name, &block) - sym = name.to_sym - begin - singleton_class.remove_method(sym, "#{sym}=") - rescue NameError - end - @table.delete(sym) do - return yield if block - raise! NameError.new("no field `#{sym}' in #{self}", sym) - end - end - - InspectKey = :__inspect_key__ # :nodoc: - - # - # Returns a string containing a detailed summary of the keys and values. - # - def inspect - ids = (Thread.current[InspectKey] ||= []) - if ids.include?(object_id) - detail = ' ...' - else - ids << object_id - begin - detail = @table.map do |key, value| - " #{key}=#{value.inspect}" - end.join(',') - ensure - ids.pop - end - end - ['#<', self.class!, detail, '>'].join - end - alias :to_s :inspect - - attr_reader :table # :nodoc: - alias table! table - protected :table! - - # - # Compares this object and +other+ for equality. An OpenStruct is equal to - # +other+ when +other+ is an OpenStruct and the two objects' Hash tables are - # equal. - # - # require "ostruct" - # first_pet = OpenStruct.new("name" => "Rowdy") - # second_pet = OpenStruct.new(:name => "Rowdy") - # third_pet = OpenStruct.new("name" => "Rowdy", :age => nil) - # - # first_pet == second_pet # => true - # first_pet == third_pet # => false - # - def ==(other) - return false unless other.kind_of?(OpenStruct) - @table == other.table! - end - - # - # Compares this object and +other+ for equality. An OpenStruct is eql? to - # +other+ when +other+ is an OpenStruct and the two objects' Hash tables are - # eql?. - # - def eql?(other) - return false unless other.kind_of?(OpenStruct) - @table.eql?(other.table!) - end - - # Computes a hash code for this OpenStruct. - def hash # :nodoc: - @table.hash - end - - # - # Provides marshalling support for use by the YAML library. - # - def encode_with(coder) # :nodoc: - @table.each_pair do |key, value| - coder[key.to_s] = value - end - if @table.size == 1 && @table.key?(:table) # support for legacy format - # in the very unlikely case of a single entry called 'table' - coder['legacy_support!'] = true # add a bogus second entry - end - end - - # - # Provides marshalling support for use by the YAML library. - # - def init_with(coder) # :nodoc: - h = coder.map - if h.size == 1 # support for legacy format - key, val = h.first - if key == 'table' - h = val - end - end - update_to_values!(h) - end - - # Make all public methods (builtin or our own) accessible with !: - give_access = instance_methods - # See https://github.com/ruby/ostruct/issues/30 - give_access -= %i[instance_exec instance_eval eval] if RUBY_ENGINE == 'jruby' - give_access.each do |method| - next if method.match(/\W$/) - - new_name = "#{method}!" - alias_method new_name, method - end - # Other builtin private methods we use: - alias_method :raise!, :raise - private :raise! - - # See https://github.com/ruby/ostruct/issues/40 - if RUBY_ENGINE != 'jruby' - alias_method :block_given!, :block_given? - private :block_given! - end -end diff --git a/lib/pp.gemspec b/lib/pp.gemspec index 27a92a8ce4cb46..15a3b4dc6c94a5 100644 --- a/lib/pp.gemspec +++ b/lib/pp.gemspec @@ -22,7 +22,8 @@ Gem::Specification.new do |spec| spec.metadata["source_code_uri"] = spec.homepage spec.files = %w[ - LICENSE.txt + BSDL + COPYING lib/pp.rb pp.gemspec ] diff --git a/lib/pp.rb b/lib/pp.rb index b81f84cec5b3c8..531839563167cf 100644 --- a/lib/pp.rb +++ b/lib/pp.rb @@ -46,6 +46,7 @@ # # To define a customized pretty printing function for your classes, # redefine method #pretty_print(pp) in the class. +# Note that require 'pp' is needed before redefining #pretty_print(pp). # # #pretty_print takes the +pp+ argument, which is an instance of the PP class. # The method uses #text, #breakable, #nest, #group and #pp to print the @@ -62,7 +63,8 @@ class PP < PrettyPrint - VERSION = "0.4.0" + # The version string + VERSION = "0.6.2" # Returns the usable width for +out+. # As the width of +out+: @@ -92,7 +94,7 @@ def PP.width_for(out) # # PP.pp returns +out+. def PP.pp(obj, out=$>, width=width_for(out)) - q = PP.new(out, width) + q = new(out, width) q.guard_inspect_key {q.pp obj} q.flush #$pp = q @@ -137,6 +139,7 @@ class << self end end + # Module that defines helper methods for pretty_print. module PPMethods # Yields to a block @@ -180,6 +183,24 @@ def pop_inspect_key(id) Thread.current[:__recursive_key__][:inspect].delete id end + private def guard_inspect(object) + recursive_state = Thread.current[:__recursive_key__] + + if recursive_state && recursive_state.key?(:inspect) + begin + push_inspect_key(object) + yield + ensure + pop_inspect_key(object) unless PP.sharing_detection + end + else + guard_inspect_key do + push_inspect_key(object) + yield + end + end + end + # Adds +obj+ to the pretty printing buffer # using Object#pretty_print or Object#pretty_print_cycle. # @@ -188,18 +209,19 @@ def pop_inspect_key(id) def pp(obj) # If obj is a Delegator then use the object being delegated to for cycle # detection - obj = obj.__getobj__ if defined?(::Delegator) and obj.is_a?(::Delegator) + obj = obj.__getobj__ if defined?(::Delegator) and ::Delegator === obj if check_inspect_key(obj) group {obj.pretty_print_cycle self} return end - begin - push_inspect_key(obj) - group {obj.pretty_print self} - ensure - pop_inspect_key(obj) unless PP.sharing_detection + guard_inspect(obj) do + group do + obj.pretty_print self + rescue NoMethodError + text Kernel.instance_method(:inspect).bind_call(obj) + end end end @@ -254,15 +276,20 @@ def comma_breakable def seplist(list, sep=nil, iter_method=:each) # :yield: element sep ||= lambda { comma_breakable } first = true + kwsplat = EMPTY_KWHASH list.__send__(iter_method) {|*v| if first first = false else sep.call end - RUBY_VERSION >= "3.0" ? yield(*v, **{}) : yield(*v) + kwsplat ? yield(*v, **kwsplat) : yield(*v) } end + EMPTY_KWHASH = if RUBY_VERSION >= "3.0" + {}.freeze + end + private_constant :EMPTY_KWHASH # A present standard failsafe for pretty printing any given Object def pp_object(obj) @@ -285,16 +312,42 @@ def pp_hash(obj) group(1, '{', '}') { seplist(obj, nil, :each_pair) {|k, v| group { - pp k - text '=>' - group(1) { - breakable '' - pp v - } + pp_hash_pair k, v } } } end + + if RUBY_VERSION >= '3.4.' + # A pretty print for a pair of Hash + def pp_hash_pair(k, v) + if Symbol === k + sym_s = k.inspect + if sym_s[1].match?(/["$@!]/) || sym_s[-1].match?(/[%&*+\-\/<=>@\]^`|~]/) + text "#{k.to_s.inspect}:" + else + text "#{k}:" + end + else + pp k + text ' ' + text '=>' + end + group(1) { + breakable + pp v + } + end + else + def pp_hash_pair(k, v) + pp k + text '=>' + group(1) { + breakable '' + pp v + } + end + end end include PPMethods @@ -389,6 +442,23 @@ def pretty_print_cycle(q) # :nodoc: end end +class Set # :nodoc: + def pretty_print(pp) # :nodoc: + pp.group(1, '#') { + pp.breakable + pp.group(1, '{', '}') { + pp.seplist(self) { |o| + pp.pp o + } + } + } + end + + def pretty_print_cycle(pp) # :nodoc: + pp.text sprintf('#', empty? ? '' : '...') + end +end + class << ENV # :nodoc: def pretty_print(q) # :nodoc: h = {} @@ -421,14 +491,28 @@ def pretty_print_cycle(q) # :nodoc: class Data # :nodoc: def pretty_print(q) # :nodoc: - q.group(1, sprintf("#') { - q.seplist(PP.mcall(self, Data, :members), lambda { q.text "," }) {|member| + class_name = PP.mcall(self, Kernel, :class).name + class_name = " #{class_name}" if class_name + q.group(1, "#') { + + members = PP.mcall(self, Kernel, :class).members + values = [] + members.select! do |member| + begin + values << __send__(member) + true + rescue NoMethodError + false + end + end + + q.seplist(members.zip(values), lambda { q.text "," }) {|(member, value)| q.breakable q.text member.to_s q.text '=' q.group(1) { q.breakable '' - q.pp public_send(member) + q.pp value } } } @@ -437,15 +521,17 @@ def pretty_print(q) # :nodoc: def pretty_print_cycle(q) # :nodoc: q.text sprintf("#", PP.mcall(self, Kernel, :class).name) end -end if "3.2" <= RUBY_VERSION +end if defined?(Data.define) class Range # :nodoc: def pretty_print(q) # :nodoc: - q.pp self.begin + begin_nil = self.begin == nil + end_nil = self.end == nil + q.pp self.begin if !begin_nil || end_nil q.breakable '' q.text(self.exclude_end? ? '...' : '..') q.breakable '' - q.pp self.end if self.end + q.pp self.end if !end_nil || begin_nil end end @@ -574,7 +660,7 @@ def pretty_print(q) # :nodoc: end if defined?(RubyVM::AbstractSyntaxTree) - class RubyVM::AbstractSyntaxTree::Node + class RubyVM::AbstractSyntaxTree::Node # :nodoc: def pretty_print_children(q, names = []) children.zip(names) do |c, n| if n @@ -632,10 +718,6 @@ def pretty_print(q) module Kernel # Returns a pretty printed object as a string. # - # In order to use this method you must first require the PP module: - # - # require 'pp' - # # See the PP module for more information. def pretty_inspect PP.pp(self, ''.dup) @@ -643,7 +725,7 @@ def pretty_inspect # prints arguments in pretty form. # - # pp returns argument(s). + # +#pp+ returns argument(s). def pp(*objs) objs.each {|obj| PP.pp(obj) diff --git a/lib/prettyprint.rb b/lib/prettyprint.rb index 540b12fb706373..6f50192f5daf29 100644 --- a/lib/prettyprint.rb +++ b/lib/prettyprint.rb @@ -23,17 +23,17 @@ # # == References # Christian Lindig, Strictly Pretty, March 2000, -# http://www.st.cs.uni-sb.de/~lindig/papers/#pretty +# https://lindig.github.io/papers/strictly-pretty-2000.pdf # # Philip Wadler, A prettier printer, March 1998, -# http://homepages.inf.ed.ac.uk/wadler/topics/language-design.html#prettier +# https://homepages.inf.ed.ac.uk/wadler/topics/language-design.html#prettier # # == Author # Tanaka Akira # class PrettyPrint - VERSION = "0.1.1" + VERSION = "0.2.0" # This is a convenience method which is same as follows: # diff --git a/lib/prism.rb b/lib/prism.rb new file mode 100644 index 00000000000000..dceba4b1f5c0a8 --- /dev/null +++ b/lib/prism.rb @@ -0,0 +1,91 @@ +# frozen_string_literal: true +# :markup: markdown + +# The Prism Ruby parser. +# +# "Parsing Ruby is suddenly manageable!" +# - You, hopefully +# +module Prism + # There are many files in prism that are templated to handle every node type, + # which means the files can end up being quite large. We autoload them to make + # our require speed faster since consuming libraries are unlikely to use all + # of these features. + + autoload :BasicVisitor, "prism/visitor" + autoload :Compiler, "prism/compiler" + autoload :DesugarCompiler, "prism/desugar_compiler" + autoload :Dispatcher, "prism/dispatcher" + autoload :DotVisitor, "prism/dot_visitor" + autoload :DSL, "prism/dsl" + autoload :InspectVisitor, "prism/inspect_visitor" + autoload :LexCompat, "prism/lex_compat" + autoload :LexRipper, "prism/lex_compat" + autoload :MutationCompiler, "prism/mutation_compiler" + autoload :Pack, "prism/pack" + autoload :Pattern, "prism/pattern" + autoload :Reflection, "prism/reflection" + autoload :Relocation, "prism/relocation" + autoload :Serialize, "prism/serialize" + autoload :StringQuery, "prism/string_query" + autoload :Translation, "prism/translation" + autoload :Visitor, "prism/visitor" + + # Some of these constants are not meant to be exposed, so marking them as + # private here. + + private_constant :LexCompat + private_constant :LexRipper + + # :call-seq: + # Prism::lex_compat(source, **options) -> LexCompat::Result + # + # Returns a parse result whose value is an array of tokens that closely + # resembles the return value of Ripper::lex. The main difference is that the + # `:on_sp` token is not emitted. + # + # For supported options, see Prism::parse. + def self.lex_compat(source, **options) + LexCompat.new(source, **options).result # steep:ignore + end + + # :call-seq: + # Prism::lex_ripper(source) -> Array + # + # This lexes with the Ripper lex. It drops any space events but otherwise + # returns the same tokens. Raises SyntaxError if the syntax in source is + # invalid. + def self.lex_ripper(source) + LexRipper.new(source).result # steep:ignore + end + + # :call-seq: + # Prism::load(source, serialized, freeze) -> ParseResult + # + # Load the serialized AST using the source as a reference into a tree. + def self.load(source, serialized, freeze = false) + Serialize.load_parse(source, serialized, freeze) + end +end + +require_relative "prism/polyfill/byteindex" +require_relative "prism/polyfill/warn" +require_relative "prism/node" +require_relative "prism/node_ext" +require_relative "prism/parse_result" + +# This is a Ruby implementation of the prism parser. If we're running on CRuby +# and we haven't explicitly set the PRISM_FFI_BACKEND environment variable, then +# it's going to require the built library. Otherwise, it's going to require a +# module that uses FFI to call into the library. +if RUBY_ENGINE == "ruby" and !ENV["PRISM_FFI_BACKEND"] + # The C extension is the default backend on CRuby. + Prism::BACKEND = :CEXT + + require "prism/prism" +else + # The FFI backend is used on other Ruby implementations. + Prism::BACKEND = :FFI + + require_relative "prism/ffi" +end diff --git a/lib/prism/desugar_compiler.rb b/lib/prism/desugar_compiler.rb new file mode 100644 index 00000000000000..5d7d38d84153ce --- /dev/null +++ b/lib/prism/desugar_compiler.rb @@ -0,0 +1,392 @@ +# frozen_string_literal: true +# :markup: markdown + +module Prism + class DesugarAndWriteNode # :nodoc: + include DSL + + attr_reader :node, :default_source, :read_class, :write_class, :arguments + + def initialize(node, default_source, read_class, write_class, **arguments) + @node = node + @default_source = default_source + @read_class = read_class + @write_class = write_class + @arguments = arguments + end + + # Desugar `x &&= y` to `x && x = y` + def compile + and_node( + location: node.location, + left: public_send(read_class, location: node.name_loc, **arguments), + right: public_send( + write_class, + location: node.location, + **arguments, + name_loc: node.name_loc, + value: node.value, + operator_loc: node.operator_loc + ), + operator_loc: node.operator_loc + ) + end + end + + class DesugarOrWriteDefinedNode # :nodoc: + include DSL + + attr_reader :node, :default_source, :read_class, :write_class, :arguments + + def initialize(node, default_source, read_class, write_class, **arguments) + @node = node + @default_source = default_source + @read_class = read_class + @write_class = write_class + @arguments = arguments + end + + # Desugar `x ||= y` to `defined?(x) ? x : x = y` + def compile + if_node( + location: node.location, + if_keyword_loc: node.operator_loc, + predicate: defined_node( + location: node.name_loc, + value: public_send(read_class, location: node.name_loc, **arguments), + keyword_loc: node.operator_loc + ), + then_keyword_loc: node.operator_loc, + statements: statements_node( + location: node.location, + body: [public_send(read_class, location: node.name_loc, **arguments)] + ), + subsequent: else_node( + location: node.location, + else_keyword_loc: node.operator_loc, + statements: statements_node( + location: node.location, + body: [ + public_send( + write_class, + location: node.location, + **arguments, + name_loc: node.name_loc, + value: node.value, + operator_loc: node.operator_loc + ) + ] + ), + end_keyword_loc: node.operator_loc + ), + end_keyword_loc: node.operator_loc + ) + end + end + + class DesugarOperatorWriteNode # :nodoc: + include DSL + + attr_reader :node, :default_source, :read_class, :write_class, :arguments + + def initialize(node, default_source, read_class, write_class, **arguments) + @node = node + @default_source = default_source + @read_class = read_class + @write_class = write_class + @arguments = arguments + end + + # Desugar `x += y` to `x = x + y` + def compile + binary_operator_loc = node.binary_operator_loc.chop + + public_send( + write_class, + location: node.location, + **arguments, + name_loc: node.name_loc, + value: call_node( + location: node.location, + receiver: public_send( + read_class, + location: node.name_loc, + **arguments + ), + name: binary_operator_loc.slice.to_sym, + message_loc: binary_operator_loc, + arguments: arguments_node( + location: node.value.location, + arguments: [node.value] + ) + ), + operator_loc: node.binary_operator_loc.copy( + start_offset: node.binary_operator_loc.end_offset - 1, + length: 1 + ) + ) + end + end + + class DesugarOrWriteNode # :nodoc: + include DSL + + attr_reader :node, :default_source, :read_class, :write_class, :arguments + + def initialize(node, default_source, read_class, write_class, **arguments) + @node = node + @default_source = default_source + @read_class = read_class + @write_class = write_class + @arguments = arguments + end + + # Desugar `x ||= y` to `x || x = y` + def compile + or_node( + location: node.location, + left: public_send(read_class, location: node.name_loc, **arguments), + right: public_send( + write_class, + location: node.location, + **arguments, + name_loc: node.name_loc, + value: node.value, + operator_loc: node.operator_loc + ), + operator_loc: node.operator_loc + ) + end + end + + private_constant :DesugarAndWriteNode, :DesugarOrWriteNode, :DesugarOrWriteDefinedNode, :DesugarOperatorWriteNode + + class ClassVariableAndWriteNode + def desugar # :nodoc: + DesugarAndWriteNode.new(self, source, :class_variable_read_node, :class_variable_write_node, name: name).compile + end + end + + class ClassVariableOrWriteNode + def desugar # :nodoc: + DesugarOrWriteDefinedNode.new(self, source, :class_variable_read_node, :class_variable_write_node, name: name).compile + end + end + + class ClassVariableOperatorWriteNode + def desugar # :nodoc: + DesugarOperatorWriteNode.new(self, source, :class_variable_read_node, :class_variable_write_node, name: name).compile + end + end + + class ConstantAndWriteNode + def desugar # :nodoc: + DesugarAndWriteNode.new(self, source, :constant_read_node, :constant_write_node, name: name).compile + end + end + + class ConstantOrWriteNode + def desugar # :nodoc: + DesugarOrWriteDefinedNode.new(self, source, :constant_read_node, :constant_write_node, name: name).compile + end + end + + class ConstantOperatorWriteNode + def desugar # :nodoc: + DesugarOperatorWriteNode.new(self, source, :constant_read_node, :constant_write_node, name: name).compile + end + end + + class GlobalVariableAndWriteNode + def desugar # :nodoc: + DesugarAndWriteNode.new(self, source, :global_variable_read_node, :global_variable_write_node, name: name).compile + end + end + + class GlobalVariableOrWriteNode + def desugar # :nodoc: + DesugarOrWriteDefinedNode.new(self, source, :global_variable_read_node, :global_variable_write_node, name: name).compile + end + end + + class GlobalVariableOperatorWriteNode + def desugar # :nodoc: + DesugarOperatorWriteNode.new(self, source, :global_variable_read_node, :global_variable_write_node, name: name).compile + end + end + + class InstanceVariableAndWriteNode + def desugar # :nodoc: + DesugarAndWriteNode.new(self, source, :instance_variable_read_node, :instance_variable_write_node, name: name).compile + end + end + + class InstanceVariableOrWriteNode + def desugar # :nodoc: + DesugarOrWriteNode.new(self, source, :instance_variable_read_node, :instance_variable_write_node, name: name).compile + end + end + + class InstanceVariableOperatorWriteNode + def desugar # :nodoc: + DesugarOperatorWriteNode.new(self, source, :instance_variable_read_node, :instance_variable_write_node, name: name).compile + end + end + + class LocalVariableAndWriteNode + def desugar # :nodoc: + DesugarAndWriteNode.new(self, source, :local_variable_read_node, :local_variable_write_node, name: name, depth: depth).compile + end + end + + class LocalVariableOrWriteNode + def desugar # :nodoc: + DesugarOrWriteNode.new(self, source, :local_variable_read_node, :local_variable_write_node, name: name, depth: depth).compile + end + end + + class LocalVariableOperatorWriteNode + def desugar # :nodoc: + DesugarOperatorWriteNode.new(self, source, :local_variable_read_node, :local_variable_write_node, name: name, depth: depth).compile + end + end + + # DesugarCompiler is a compiler that desugars Ruby code into a more primitive + # form. This is useful for consumers that want to deal with fewer node types. + class DesugarCompiler < MutationCompiler + # @@foo &&= bar + # + # becomes + # + # @@foo && @@foo = bar + def visit_class_variable_and_write_node(node) + node.desugar + end + + # @@foo ||= bar + # + # becomes + # + # defined?(@@foo) ? @@foo : @@foo = bar + def visit_class_variable_or_write_node(node) + node.desugar + end + + # @@foo += bar + # + # becomes + # + # @@foo = @@foo + bar + def visit_class_variable_operator_write_node(node) + node.desugar + end + + # Foo &&= bar + # + # becomes + # + # Foo && Foo = bar + def visit_constant_and_write_node(node) + node.desugar + end + + # Foo ||= bar + # + # becomes + # + # defined?(Foo) ? Foo : Foo = bar + def visit_constant_or_write_node(node) + node.desugar + end + + # Foo += bar + # + # becomes + # + # Foo = Foo + bar + def visit_constant_operator_write_node(node) + node.desugar + end + + # $foo &&= bar + # + # becomes + # + # $foo && $foo = bar + def visit_global_variable_and_write_node(node) + node.desugar + end + + # $foo ||= bar + # + # becomes + # + # defined?($foo) ? $foo : $foo = bar + def visit_global_variable_or_write_node(node) + node.desugar + end + + # $foo += bar + # + # becomes + # + # $foo = $foo + bar + def visit_global_variable_operator_write_node(node) + node.desugar + end + + # @foo &&= bar + # + # becomes + # + # @foo && @foo = bar + def visit_instance_variable_and_write_node(node) + node.desugar + end + + # @foo ||= bar + # + # becomes + # + # @foo || @foo = bar + def visit_instance_variable_or_write_node(node) + node.desugar + end + + # @foo += bar + # + # becomes + # + # @foo = @foo + bar + def visit_instance_variable_operator_write_node(node) + node.desugar + end + + # foo &&= bar + # + # becomes + # + # foo && foo = bar + def visit_local_variable_and_write_node(node) + node.desugar + end + + # foo ||= bar + # + # becomes + # + # foo || foo = bar + def visit_local_variable_or_write_node(node) + node.desugar + end + + # foo += bar + # + # becomes + # + # foo = foo + bar + def visit_local_variable_operator_write_node(node) + node.desugar + end + end +end diff --git a/lib/prism/ffi.rb b/lib/prism/ffi.rb new file mode 100644 index 00000000000000..5a4ba09a4fd9a0 --- /dev/null +++ b/lib/prism/ffi.rb @@ -0,0 +1,567 @@ +# frozen_string_literal: true +# :markup: markdown +# typed: ignore + +# This file is responsible for mirroring the API provided by the C extension by +# using FFI to call into the shared library. + +require "rbconfig" +require "ffi" + +# We want to eagerly load this file if there are Ractors so that it does not get +# autoloaded from within a non-main Ractor. +require "prism/serialize" if defined?(Ractor) + +module Prism + module LibRubyParser # :nodoc: + extend FFI::Library + + # Define the library that we will be pulling functions from. Note that this + # must align with the build shared library from make/rake. + libprism_in_build = File.expand_path("../../build/libprism.#{RbConfig::CONFIG["SOEXT"]}", __dir__) + libprism_in_libdir = "#{RbConfig::CONFIG["libdir"]}/prism/libprism.#{RbConfig::CONFIG["SOEXT"]}" + + if File.exist?(libprism_in_build) + INCLUDE_DIR = File.expand_path("../../include", __dir__) + ffi_lib libprism_in_build + else + INCLUDE_DIR = "#{RbConfig::CONFIG["libdir"]}/prism/include" + ffi_lib libprism_in_libdir + end + + # Convert a native C type declaration into a symbol that FFI understands. + # For example: + # + # const char * -> :pointer + # bool -> :bool + # size_t -> :size_t + # void -> :void + # + def self.resolve_type(type, callbacks) + type = type.strip + + if !type.end_with?("*") + type.delete_prefix("const ").to_sym + else + type = type.delete_suffix("*").rstrip + callbacks.include?(type.to_sym) ? type.to_sym : :pointer + end + end + + # Read through the given header file and find the declaration of each of the + # given functions. For each one, define a function with the same name and + # signature as the C function. + def self.load_exported_functions_from(header, *functions, callbacks) + File.foreach("#{INCLUDE_DIR}/#{header}") do |line| + # We only want to attempt to load exported functions. + next unless line.start_with?("PRISM_EXPORTED_FUNCTION ") + + # We only want to load the functions that we are interested in. + next unless functions.any? { |function| line.include?(function) } + + # Parse the function declaration. + unless /^PRISM_EXPORTED_FUNCTION (?.+) (?\w+)\((?.+)\);$/ =~ line + raise "Could not parse #{line}" + end + + # Delete the function from the list of functions we are looking for to + # mark it as having been found. + functions.delete(name) + + # Split up the argument types into an array, ensure we handle the case + # where there are no arguments (by explicit void). + arg_types = arg_types.split(",").map(&:strip) + arg_types = [] if arg_types == %w[void] + + # Resolve the type of the argument by dropping the name of the argument + # first if it is present. + arg_types.map! { |type| resolve_type(type.sub(/\w+$/, ""), callbacks) } + + # Attach the function using the FFI library. + attach_function name, arg_types, resolve_type(return_type, []) + end + + # If we didn't find all of the functions, raise an error. + raise "Could not find functions #{functions.inspect}" unless functions.empty? + end + + callback :pm_parse_stream_fgets_t, [:pointer, :int, :pointer], :pointer + enum :pm_string_init_result_t, %i[PM_STRING_INIT_SUCCESS PM_STRING_INIT_ERROR_GENERIC PM_STRING_INIT_ERROR_DIRECTORY] + enum :pm_string_query_t, [:PM_STRING_QUERY_ERROR, -1, :PM_STRING_QUERY_FALSE, :PM_STRING_QUERY_TRUE] + + load_exported_functions_from( + "prism.h", + "pm_version", + "pm_serialize_parse", + "pm_serialize_parse_stream", + "pm_serialize_parse_comments", + "pm_serialize_lex", + "pm_serialize_parse_lex", + "pm_parse_success_p", + "pm_string_query_local", + "pm_string_query_constant", + "pm_string_query_method_name", + [:pm_parse_stream_fgets_t] + ) + + load_exported_functions_from( + "prism/util/pm_buffer.h", + "pm_buffer_sizeof", + "pm_buffer_init", + "pm_buffer_value", + "pm_buffer_length", + "pm_buffer_free", + [] + ) + + load_exported_functions_from( + "prism/util/pm_string.h", + "pm_string_mapped_init", + "pm_string_free", + "pm_string_source", + "pm_string_length", + "pm_string_sizeof", + [] + ) + + # This object represents a pm_buffer_t. We only use it as an opaque pointer, + # so it doesn't need to know the fields of pm_buffer_t. + class PrismBuffer # :nodoc: + SIZEOF = LibRubyParser.pm_buffer_sizeof + + attr_reader :pointer + + def initialize(pointer) + @pointer = pointer + end + + def value + LibRubyParser.pm_buffer_value(pointer) + end + + def length + LibRubyParser.pm_buffer_length(pointer) + end + + def read + value.read_string(length) + end + + # Initialize a new buffer and yield it to the block. The buffer will be + # automatically freed when the block returns. + def self.with + FFI::MemoryPointer.new(SIZEOF) do |pointer| + raise unless LibRubyParser.pm_buffer_init(pointer) + return yield new(pointer) + ensure + LibRubyParser.pm_buffer_free(pointer) + end + end + end + + # This object represents a pm_string_t. We only use it as an opaque pointer, + # so it doesn't have to be an FFI::Struct. + class PrismString # :nodoc: + SIZEOF = LibRubyParser.pm_string_sizeof + + PLATFORM_EXPECTS_UTF8 = + RbConfig::CONFIG["host_os"].match?(/bccwin|cygwin|djgpp|mingw|mswin|wince|darwin/i) + + attr_reader :pointer, :length + + def initialize(pointer, length, from_string) + @pointer = pointer + @length = length + @from_string = from_string + end + + def read + raise "should use the original String instead" if @from_string + @pointer.read_string(@length) + end + + # Yields a pm_string_t pointer to the given block. + def self.with_string(string) + raise TypeError unless string.is_a?(String) + + length = string.bytesize + # + 1 to never get an address of 0, which pm_parser_init() asserts + FFI::MemoryPointer.new(:char, length + 1, false) do |pointer| + pointer.write_string(string) + # since we have the extra byte we might as well \0-terminate + pointer.put_char(length, 0) + return yield new(pointer, length, true) + end + end + + # Yields a pm_string_t pointer to the given block. + def self.with_file(filepath) + raise TypeError unless filepath.is_a?(String) + + # On Windows and Mac, it's expected that filepaths will be encoded in + # UTF-8. If they are not, we need to convert them to UTF-8 before + # passing them into pm_string_mapped_init. + if PLATFORM_EXPECTS_UTF8 && (encoding = filepath.encoding) != Encoding::ASCII_8BIT && encoding != Encoding::UTF_8 + filepath = filepath.encode(Encoding::UTF_8) + end + + FFI::MemoryPointer.new(SIZEOF) do |pm_string| + case (result = LibRubyParser.pm_string_mapped_init(pm_string, filepath)) + when :PM_STRING_INIT_SUCCESS + pointer = LibRubyParser.pm_string_source(pm_string) + length = LibRubyParser.pm_string_length(pm_string) + return yield new(pointer, length, false) + when :PM_STRING_INIT_ERROR_GENERIC + raise SystemCallError.new(filepath, FFI.errno) + when :PM_STRING_INIT_ERROR_DIRECTORY + raise Errno::EISDIR.new(filepath) + else + raise "Unknown error initializing pm_string_t: #{result.inspect}" + end + ensure + LibRubyParser.pm_string_free(pm_string) + end + end + end + end + + # Mark the LibRubyParser module as private as it should only be called through + # the prism module. + private_constant :LibRubyParser + + # The version constant is set by reading the result of calling pm_version. + VERSION = LibRubyParser.pm_version.read_string.freeze + + class << self + # Mirror the Prism.dump API by using the serialization API. + def dump(source, **options) + LibRubyParser::PrismString.with_string(source) { |string| dump_common(string, options) } + end + + # Mirror the Prism.dump_file API by using the serialization API. + def dump_file(filepath, **options) + options[:filepath] = filepath + LibRubyParser::PrismString.with_file(filepath) { |string| dump_common(string, options) } + end + + # Mirror the Prism.lex API by using the serialization API. + def lex(code, **options) + LibRubyParser::PrismString.with_string(code) { |string| lex_common(string, code, options) } + end + + # Mirror the Prism.lex_file API by using the serialization API. + def lex_file(filepath, **options) + options[:filepath] = filepath + LibRubyParser::PrismString.with_file(filepath) { |string| lex_common(string, string.read, options) } + end + + # Mirror the Prism.parse API by using the serialization API. + def parse(code, **options) + LibRubyParser::PrismString.with_string(code) { |string| parse_common(string, code, options) } + end + + # Mirror the Prism.parse_file API by using the serialization API. This uses + # native strings instead of Ruby strings because it allows us to use mmap + # when it is available. + def parse_file(filepath, **options) + options[:filepath] = filepath + LibRubyParser::PrismString.with_file(filepath) { |string| parse_common(string, string.read, options) } + end + + # Mirror the Prism.parse_stream API by using the serialization API. + def parse_stream(stream, **options) + LibRubyParser::PrismBuffer.with do |buffer| + source = +"" + callback = -> (string, size, _) { + raise "Expected size to be >= 0, got: #{size}" if size <= 0 + + if !(line = stream.gets(size - 1)).nil? + source << line + string.write_string("#{line}\x00", line.bytesize + 1) + end + } + + # In the pm_serialize_parse_stream function it accepts a pointer to the + # IO object as a void* and then passes it through to the callback as the + # third argument, but it never touches it itself. As such, since we have + # access to the IO object already through the closure of the lambda, we + # can pass a null pointer here and not worry. + LibRubyParser.pm_serialize_parse_stream(buffer.pointer, nil, callback, dump_options(options)) + Prism.load(source, buffer.read, options.fetch(:freeze, false)) + end + end + + # Mirror the Prism.parse_comments API by using the serialization API. + def parse_comments(code, **options) + LibRubyParser::PrismString.with_string(code) { |string| parse_comments_common(string, code, options) } + end + + # Mirror the Prism.parse_file_comments API by using the serialization + # API. This uses native strings instead of Ruby strings because it allows us + # to use mmap when it is available. + def parse_file_comments(filepath, **options) + options[:filepath] = filepath + LibRubyParser::PrismString.with_file(filepath) { |string| parse_comments_common(string, string.read, options) } + end + + # Mirror the Prism.parse_lex API by using the serialization API. + def parse_lex(code, **options) + LibRubyParser::PrismString.with_string(code) { |string| parse_lex_common(string, code, options) } + end + + # Mirror the Prism.parse_lex_file API by using the serialization API. + def parse_lex_file(filepath, **options) + options[:filepath] = filepath + LibRubyParser::PrismString.with_file(filepath) { |string| parse_lex_common(string, string.read, options) } + end + + # Mirror the Prism.parse_success? API by using the serialization API. + def parse_success?(code, **options) + LibRubyParser::PrismString.with_string(code) { |string| parse_file_success_common(string, options) } + end + + # Mirror the Prism.parse_failure? API by using the serialization API. + def parse_failure?(code, **options) + !parse_success?(code, **options) + end + + # Mirror the Prism.parse_file_success? API by using the serialization API. + def parse_file_success?(filepath, **options) + options[:filepath] = filepath + LibRubyParser::PrismString.with_file(filepath) { |string| parse_file_success_common(string, options) } + end + + # Mirror the Prism.parse_file_failure? API by using the serialization API. + def parse_file_failure?(filepath, **options) + !parse_file_success?(filepath, **options) + end + + # Mirror the Prism.profile API by using the serialization API. + def profile(source, **options) + LibRubyParser::PrismString.with_string(source) do |string| + LibRubyParser::PrismBuffer.with do |buffer| + LibRubyParser.pm_serialize_parse(buffer.pointer, string.pointer, string.length, dump_options(options)) + nil + end + end + end + + # Mirror the Prism.profile_file API by using the serialization API. + def profile_file(filepath, **options) + LibRubyParser::PrismString.with_file(filepath) do |string| + LibRubyParser::PrismBuffer.with do |buffer| + options[:filepath] = filepath + LibRubyParser.pm_serialize_parse(buffer.pointer, string.pointer, string.length, dump_options(options)) + nil + end + end + end + + private + + def dump_common(string, options) # :nodoc: + LibRubyParser::PrismBuffer.with do |buffer| + LibRubyParser.pm_serialize_parse(buffer.pointer, string.pointer, string.length, dump_options(options)) + + dumped = buffer.read + dumped.freeze if options.fetch(:freeze, false) + + dumped + end + end + + def lex_common(string, code, options) # :nodoc: + LibRubyParser::PrismBuffer.with do |buffer| + LibRubyParser.pm_serialize_lex(buffer.pointer, string.pointer, string.length, dump_options(options)) + Serialize.load_lex(code, buffer.read, options.fetch(:freeze, false)) + end + end + + def parse_common(string, code, options) # :nodoc: + serialized = dump_common(string, options) + Serialize.load_parse(code, serialized, options.fetch(:freeze, false)) + end + + def parse_comments_common(string, code, options) # :nodoc: + LibRubyParser::PrismBuffer.with do |buffer| + LibRubyParser.pm_serialize_parse_comments(buffer.pointer, string.pointer, string.length, dump_options(options)) + Serialize.load_parse_comments(code, buffer.read, options.fetch(:freeze, false)) + end + end + + def parse_lex_common(string, code, options) # :nodoc: + LibRubyParser::PrismBuffer.with do |buffer| + LibRubyParser.pm_serialize_parse_lex(buffer.pointer, string.pointer, string.length, dump_options(options)) + Serialize.load_parse_lex(code, buffer.read, options.fetch(:freeze, false)) + end + end + + def parse_file_success_common(string, options) # :nodoc: + LibRubyParser.pm_parse_success_p(string.pointer, string.length, dump_options(options)) + end + + # Return the value that should be dumped for the command_line option. + def dump_options_command_line(options) + command_line = options.fetch(:command_line, "") + raise ArgumentError, "command_line must be a string" unless command_line.is_a?(String) + + command_line.each_char.inject(0) do |value, char| + case char + when "a" then value | 0b000001 + when "e" then value | 0b000010 + when "l" then value | 0b000100 + when "n" then value | 0b001000 + when "p" then value | 0b010000 + when "x" then value | 0b100000 + else raise ArgumentError, "invalid command_line option: #{char}" + end + end + end + + # Return the value that should be dumped for the version option. + def dump_options_version(version) + case version + when nil, "latest" + 0 + when /\A3\.3(\.\d+)?\z/ + 1 + when /\A3\.4(\.\d+)?\z/ + 2 + when /\A3\.5(\.\d+)?\z/ + 0 + else + raise ArgumentError, "invalid version: #{version}" + end + end + + # Convert the given options into a serialized options string. + def dump_options(options) + template = +"" + values = [] + + template << "L" + if (filepath = options[:filepath]) + values.push(filepath.bytesize, filepath.b) + template << "A*" + else + values << 0 + end + + template << "l" + values << options.fetch(:line, 1) + + template << "L" + if (encoding = options[:encoding]) + name = encoding.is_a?(Encoding) ? encoding.name : encoding + values.push(name.bytesize, name.b) + template << "A*" + else + values << 0 + end + + template << "C" + values << (options.fetch(:frozen_string_literal, false) ? 1 : 0) + + template << "C" + values << dump_options_command_line(options) + + template << "C" + values << dump_options_version(options[:version]) + + template << "C" + values << (options[:encoding] == false ? 1 : 0) + + template << "C" + values << (options.fetch(:main_script, false) ? 1 : 0) + + template << "C" + values << (options.fetch(:partial_script, false) ? 1 : 0) + + template << "C" + values << (options.fetch(:freeze, false) ? 1 : 0) + + template << "L" + if (scopes = options[:scopes]) + values << scopes.length + + scopes.each do |scope| + locals = nil + forwarding = 0 + + case scope + when Array + locals = scope + when Scope + locals = scope.locals + + scope.forwarding.each do |forward| + case forward + when :* then forwarding |= 0x1 + when :** then forwarding |= 0x2 + when :& then forwarding |= 0x4 + when :"..." then forwarding |= 0x8 + else raise ArgumentError, "invalid forwarding value: #{forward}" + end + end + else + raise TypeError, "wrong argument type #{scope.class.inspect} (expected Array or Prism::Scope)" + end + + template << "L" + values << locals.length + + template << "C" + values << forwarding + + locals.each do |local| + name = local.name + template << "L" + values << name.bytesize + + template << "A*" + values << name.b + end + end + else + values << 0 + end + + values.pack(template) + end + end + + # Here we are going to patch StringQuery to put in the class-level methods so + # that it can maintain a consistent interface + class StringQuery + class << self + # Mirrors the C extension's StringQuery::local? method. + def local?(string) + query(LibRubyParser.pm_string_query_local(string, string.bytesize, string.encoding.name)) + end + + # Mirrors the C extension's StringQuery::constant? method. + def constant?(string) + query(LibRubyParser.pm_string_query_constant(string, string.bytesize, string.encoding.name)) + end + + # Mirrors the C extension's StringQuery::method_name? method. + def method_name?(string) + query(LibRubyParser.pm_string_query_method_name(string, string.bytesize, string.encoding.name)) + end + + private + + # Parse the enum result and return an appropriate boolean. + def query(result) + case result + when :PM_STRING_QUERY_ERROR + raise ArgumentError, "Invalid or non ascii-compatible encoding" + when :PM_STRING_QUERY_FALSE + false + when :PM_STRING_QUERY_TRUE + true + end + end + end + end +end diff --git a/lib/yarp/lex_compat.rb b/lib/prism/lex_compat.rb similarity index 80% rename from lib/yarp/lex_compat.rb rename to lib/prism/lex_compat.rb index 37bfecd0bca934..9b3f025ab6a5b4 100644 --- a/lib/yarp/lex_compat.rb +++ b/lib/prism/lex_compat.rb @@ -1,15 +1,34 @@ # frozen_string_literal: true +# :markup: markdown require "delegate" +require "ripper" -module YARP - # This class is responsible for lexing the source using YARP and then +module Prism + # This class is responsible for lexing the source using prism and then # converting those tokens to be compatible with Ripper. In the vast majority # of cases, this is a one-to-one mapping of the token type. Everything else # generally lines up. However, there are a few cases that require special # handling. - class LexCompat - # This is a mapping of YARP token types to Ripper token types. This is a + class LexCompat # :nodoc: + # A result class specialized for holding tokens produced by the lexer. + class Result < Prism::Result + # The list of tokens that were produced by the lexer. + attr_reader :value + + # Create a new lex compat result object with the given values. + def initialize(value, comments, magic_comments, data_loc, errors, warnings, source) + @value = value + super(comments, magic_comments, data_loc, errors, warnings, source) + end + + # Implement the hash pattern matching interface for Result. + def deconstruct_keys(keys) + super.merge!(value: value) + end + end + + # This is a mapping of prism token types to Ripper token types. This is a # many-to-one mapping because we split up our token types, whereas Ripper # tends to group them. RIPPER = { @@ -128,6 +147,7 @@ class LexCompat LESS_EQUAL_GREATER: :on_op, LESS_LESS: :on_op, LESS_LESS_EQUAL: :on_op, + METHOD_NAME: :on_ident, MINUS: :on_op, MINUS_EQUAL: :on_op, MINUS_GREATER: :on_tlambda, @@ -183,18 +203,24 @@ class LexCompat # However, we add a couple of convenience methods onto them to make them a # little easier to work with. We delegate all other methods to the array. class Token < SimpleDelegator + # @dynamic initialize, each, [] + + # The location of the token in the source. def location self[0] end + # The type of the token. def event self[1] end + # The slice of the source that this token represents. def value self[2] end + # The state of the lexer when this token was produced. def state self[3] end @@ -203,7 +229,7 @@ def state # Ripper doesn't include the rest of the token in the event, so we need to # trim it down to just the content on the first line when comparing. class EndContentToken < Token - def ==(other) + def ==(other) # :nodoc: [self[0], self[1], self[2][0..self[2].index("\n")], self[3]] == other end end @@ -211,7 +237,7 @@ def ==(other) # Tokens where state should be ignored # used for :on_comment, :on_heredoc_end, :on_embexpr_end class IgnoreStateToken < Token - def ==(other) + def ==(other) # :nodoc: self[0...-1] == other[0...-1] end end @@ -221,7 +247,7 @@ def ==(other) # through named captures in regular expressions). In that case we don't # compare the state. class IdentToken < Token - def ==(other) + def ==(other) # :nodoc: (self[0...-1] == other[0...-1]) && ( (other[3] == Ripper::EXPR_LABEL | Ripper::EXPR_END) || (other[3] & Ripper::EXPR_ARG_ANY != 0) @@ -232,13 +258,13 @@ def ==(other) # Ignored newlines can occasionally have a LABEL state attached to them, so # we compare the state differently here. class IgnoredNewlineToken < Token - def ==(other) + def ==(other) # :nodoc: return false unless self[0...-1] == other[0...-1] - if self[4] == Ripper::EXPR_ARG | Ripper::EXPR_LABELED - other[4] & Ripper::EXPR_ARG | Ripper::EXPR_LABELED > 0 + if self[3] == Ripper::EXPR_ARG | Ripper::EXPR_LABELED + other[3] & Ripper::EXPR_ARG | Ripper::EXPR_LABELED != 0 else - self[4] == other[4] + self[3] == other[3] end end end @@ -252,7 +278,7 @@ def ==(other) # more accurately, so we need to allow comparing against both END and # END|LABEL. class ParamToken < Token - def ==(other) + def ==(other) # :nodoc: (self[0...-1] == other[0...-1]) && ( (other[3] == Ripper::EXPR_END) || (other[3] == Ripper::EXPR_END | Ripper::EXPR_LABEL) @@ -263,12 +289,12 @@ def ==(other) # A heredoc in this case is a list of tokens that belong to the body of the # heredoc that should be appended onto the list of tokens when the heredoc # closes. - module Heredoc + module Heredoc # :nodoc: # Heredocs that are no dash or tilde heredocs are just a list of tokens. # We need to keep them around so that we can insert them in the correct # order back into the token stream and set the state of the last token to # the state that the heredoc was opened in. - class PlainHeredoc + class PlainHeredoc # :nodoc: attr_reader :tokens def initialize @@ -287,7 +313,7 @@ def to_a # Dash heredocs are a little more complicated. They are a list of tokens # that need to be split on "\\\n" to mimic Ripper's behavior. We also need # to keep track of the state that the heredoc was opened in. - class DashHeredoc + class DashHeredoc # :nodoc: attr_reader :split, :tokens def initialize(split) @@ -302,7 +328,7 @@ def <<(token) def to_a embexpr_balance = 0 - tokens.each_with_object([]) do |token, results| + tokens.each_with_object([]) do |token, results| #$ Array[Token] case token.event when :on_embexpr_beg embexpr_balance += 1 @@ -338,15 +364,15 @@ def to_a # Heredocs that are dedenting heredocs are a little more complicated. # Ripper outputs on_ignored_sp tokens for the whitespace that is being - # removed from the output. YARP only modifies the node itself and keeps - # the token the same. This simplifies YARP, but makes comparing against + # removed from the output. prism only modifies the node itself and keeps + # the token the same. This simplifies prism, but makes comparing against # Ripper much harder because there is a length mismatch. # # Fortunately, we already have to pull out the heredoc tokens in order to # insert them into the stream in the correct order. As such, we can do # some extra manipulation on the tokens to make them match Ripper's # output by mirroring the dedent logic that Ripper uses. - class DedentingHeredoc + class DedentingHeredoc # :nodoc: TAB_WIDTH = 8 attr_reader :tokens, :dedent_next, :dedent, :embexpr_balance @@ -356,6 +382,7 @@ def initialize @dedent_next = true @dedent = nil @embexpr_balance = 0 + @ended_on_newline = false end # As tokens are coming in, we track the minimum amount of common leading @@ -365,14 +392,14 @@ def <<(token) case token.event when :on_embexpr_beg, :on_heredoc_beg @embexpr_balance += 1 + @dedent = 0 if @dedent_next && @ended_on_newline when :on_embexpr_end, :on_heredoc_end @embexpr_balance -= 1 when :on_tstring_content if embexpr_balance == 0 - token.value.split(/(?<=\n)/).each_with_index do |line, index| - next if line.strip.empty? && line.end_with?("\n") - next if !(dedent_next || index > 0) + line = token.value + if dedent_next && !(line.strip.empty? && line.end_with?("\n")) leading = line[/\A(\s*)\n?/, 1] next_dedent = 0 @@ -385,11 +412,16 @@ def <<(token) end @dedent = [dedent, next_dedent].compact.min + @dedent_next = true + @ended_on_newline = line.end_with?("\n") + tokens << token + return end end end @dedent_next = token.event == :on_tstring_content && embexpr_balance == 0 + @ended_on_newline = false tokens << token end @@ -397,7 +429,7 @@ def to_a # If every line in the heredoc is blank, we still need to split up the # string content token into multiple tokens. if dedent.nil? - results = [] + results = [] #: Array[Token] embexpr_balance = 0 tokens.each do |token| @@ -429,11 +461,43 @@ def to_a return results end + # If the minimum common whitespace is 0, then we need to concatenate + # string nodes together that are immediately adjacent. + if dedent == 0 + results = [] #: Array[Token] + embexpr_balance = 0 + + index = 0 + max_index = tokens.length + + while index < max_index + token = tokens[index] + results << token + index += 1 + + case token.event + when :on_embexpr_beg, :on_heredoc_beg + embexpr_balance += 1 + when :on_embexpr_end, :on_heredoc_end + embexpr_balance -= 1 + when :on_tstring_content + if embexpr_balance == 0 + while index < max_index && tokens[index].event == :on_tstring_content && !token.value.match?(/\\\r?\n\z/) + token.value << tokens[index].value + index += 1 + end + end + end + end + + return results + end + # Otherwise, we're going to run through each token in the list and # insert on_ignored_sp tokens for the amount of dedent that we need to # perform. We also need to remove the dedent from the beginning of # each line of plain string content tokens. - results = [] + results = [] #: Array[Token] dedent_next = true embexpr_balance = 0 @@ -482,7 +546,7 @@ def to_a # dedent from the beginning of the line. if (dedent > 0) && (dedent_next || index > 0) deleting = 0 - deleted_chars = [] + deleted_chars = [] #: Array[String] # Gather up all of the characters that we're going to # delete, stopping when you hit a character that would put @@ -490,7 +554,7 @@ def to_a line.each_char.with_index do |char, i| case char when "\r" - if line.chars[i + 1] == "\n" + if line[i + 1] == "\n" break end when "\n" @@ -549,22 +613,25 @@ def self.build(opening) end end - attr_reader :source, :filepath + private_constant :Heredoc - def initialize(source, filepath = "") + attr_reader :source, :options + + def initialize(source, **options) @source = source - @filepath = filepath || "" + @options = options end def result - tokens = [] + tokens = [] #: Array[LexCompat::Token] state = :default - heredoc_stack = [[]] + heredoc_stack = [[]] #: Array[Array[Heredoc::PlainHeredoc | Heredoc::DashHeredoc | Heredoc::DedentingHeredoc]] - result = YARP.lex(source, @filepath) + result = Prism.lex(source, **options) result_value = result.value - previous_state = nil + previous_state = nil #: Ripper::Lexer::State? + last_heredoc_end = nil #: Integer? # In previous versions of Ruby, Ripper wouldn't flush the bom before the # first token, so we had to have a hack in place to account for that. This @@ -619,6 +686,7 @@ def result when :on_heredoc_end # Heredoc end tokens can be emitted in an odd order, so we don't # want to bother comparing the state on them. + last_heredoc_end = token.location.end_offset IgnoreStateToken.new([[lineno, column], event, value, lex_state]) when :on_ident if lex_state == Ripper::EXPR_END @@ -649,7 +717,7 @@ def result IgnoredNewlineToken.new([[lineno, column], event, value, lex_state]) when :on_regexp_end # On regex end, Ripper scans and then sets end state, so the ripper - # lexed output is begin, when it should be end. YARP sets lex state + # lexed output is begin, when it should be end. prism sets lex state # correctly to end state, but we want to be able to compare against # Ripper's lexed state. So here, if it's a regexp end token, we # output the state as the previous state, solely for the sake of @@ -684,16 +752,24 @@ def result # comment and there is still whitespace after the comment, then # Ripper will append a on_nl token (even though there isn't # necessarily a newline). We mirror that here. - start_offset = previous_token.location.end_offset - end_offset = token.location.start_offset + if previous_token.type == :COMMENT + # If the comment is at the start of a heredoc: < tokens.size - raise StandardError, "Lost tokens when performing lex_compat" - end - - ParseResult.new(tokens, result.comments, result.errors, result.warnings, []) + Result.new(tokens, result.comments, result.magic_comments, result.data_loc, result.errors, result.warnings, Source.for(source)) end end - # The constant that wraps the behavior of the lexer to match Ripper's output - # is an implementation detail, so we don't want it to be public. private_constant :LexCompat - # Returns an array of tokens that closely resembles that of the Ripper lexer. - # The only difference is that since we don't keep track of lexer state in the - # same way, it's going to always return the NONE state. - def self.lex_compat(source, filepath = "") - LexCompat.new(source, filepath).result - end + # This is a class that wraps the Ripper lexer to produce almost exactly the + # same tokens. + class LexRipper # :nodoc: + attr_reader :source - # This lexes with the Ripper lex. It drops any space events but otherwise - # returns the same tokens. Raises SyntaxError if the syntax in source is - # invalid. - def self.lex_ripper(source) - previous = [] - results = [] - - Ripper.lex(source, raise_errors: true).each do |token| - case token[1] - when :on_sp - # skip - when :on_tstring_content - if previous[1] == :on_tstring_content && (token[2].start_with?("\#$") || token[2].start_with?("\#@")) - previous[2] << token[2] - else - results << token - previous = token - end - when :on_words_sep - if previous[1] == :on_words_sep - previous[2] << token[2] + def initialize(source) + @source = source + end + + def result + previous = [] #: [[Integer, Integer], Symbol, String, untyped] | [] + results = [] #: Array[[[Integer, Integer], Symbol, String, untyped]] + + lex(source).each do |token| + case token[1] + when :on_sp + # skip + when :on_tstring_content + if previous[1] == :on_tstring_content && (token[2].start_with?("\#$") || token[2].start_with?("\#@")) + previous[2] << token[2] + else + results << token + previous = token + end + when :on_words_sep + if previous[1] == :on_words_sep + previous[2] << token[2] + else + results << token + previous = token + end else results << token previous = token end - else - results << token - previous = token end + + results end - results + private + + if Ripper.method(:lex).parameters.assoc(:keyrest) + def lex(source) + Ripper.lex(source, raise_errors: true) + end + else + def lex(source) + ripper = Ripper::Lexer.new(source) + ripper.lex.tap do |result| + raise SyntaxError, ripper.errors.map(&:message).join(' ;') if ripper.errors.any? + end + end + end end + + private_constant :LexRipper end diff --git a/lib/prism/node_ext.rb b/lib/prism/node_ext.rb new file mode 100644 index 00000000000000..469e54ca0c7def --- /dev/null +++ b/lib/prism/node_ext.rb @@ -0,0 +1,511 @@ +# frozen_string_literal: true +# :markup: markdown + +#-- +# Here we are reopening the prism module to provide methods on nodes that aren't +# templated and are meant as convenience methods. +#++ +module Prism + class Node + def deprecated(*replacements) # :nodoc: + location = caller_locations(1, 1) + location = location[0].label if location + suggest = replacements.map { |replacement| "#{self.class}##{replacement}" } + + warn(<<~MSG, uplevel: 1, category: :deprecated) + [deprecation]: #{self.class}##{location} is deprecated and will be \ + removed in the next major version. Use #{suggest.join("/")} instead. + #{(caller(1, 3) || []).join("\n")} + MSG + end + end + + module RegularExpressionOptions # :nodoc: + # Returns a numeric value that represents the flags that were used to create + # the regular expression. + def options + o = 0 + o |= Regexp::IGNORECASE if flags.anybits?(RegularExpressionFlags::IGNORE_CASE) + o |= Regexp::EXTENDED if flags.anybits?(RegularExpressionFlags::EXTENDED) + o |= Regexp::MULTILINE if flags.anybits?(RegularExpressionFlags::MULTI_LINE) + o |= Regexp::FIXEDENCODING if flags.anybits?(RegularExpressionFlags::EUC_JP | RegularExpressionFlags::WINDOWS_31J | RegularExpressionFlags::UTF_8) + o |= Regexp::NOENCODING if flags.anybits?(RegularExpressionFlags::ASCII_8BIT) + o + end + end + + class InterpolatedMatchLastLineNode < Node + include RegularExpressionOptions + end + + class InterpolatedRegularExpressionNode < Node + include RegularExpressionOptions + end + + class MatchLastLineNode < Node + include RegularExpressionOptions + end + + class RegularExpressionNode < Node + include RegularExpressionOptions + end + + private_constant :RegularExpressionOptions + + module HeredocQuery # :nodoc: + # Returns true if this node was represented as a heredoc in the source code. + def heredoc? + opening&.start_with?("<<") + end + end + + class InterpolatedStringNode < Node + include HeredocQuery + end + + class InterpolatedXStringNode < Node + include HeredocQuery + end + + class StringNode < Node + include HeredocQuery + + # Occasionally it's helpful to treat a string as if it were interpolated so + # that there's a consistent interface for working with strings. + def to_interpolated + InterpolatedStringNode.new( + source, + -1, + location, + frozen? ? InterpolatedStringNodeFlags::FROZEN : 0, + opening_loc, + [copy(location: content_loc, opening_loc: nil, closing_loc: nil)], + closing_loc + ) + end + end + + class XStringNode < Node + include HeredocQuery + + # Occasionally it's helpful to treat a string as if it were interpolated so + # that there's a consistent interface for working with strings. + def to_interpolated + InterpolatedXStringNode.new( + source, + -1, + location, + flags, + opening_loc, + [StringNode.new(source, node_id, content_loc, 0, nil, content_loc, nil, unescaped)], + closing_loc + ) + end + end + + private_constant :HeredocQuery + + class ImaginaryNode < Node + # Returns the value of the node as a Ruby Complex. + def value + Complex(0, numeric.value) + end + end + + class RationalNode < Node + # Returns the value of the node as a Ruby Rational. + def value + Rational(numerator, denominator) + end + + # Returns the value of the node as an IntegerNode or a FloatNode. This + # method is deprecated in favor of #value or #numerator/#denominator. + def numeric + deprecated("value", "numerator", "denominator") + + if denominator == 1 + IntegerNode.new(source, -1, location.chop, flags, numerator) + else + FloatNode.new(source, -1, location.chop, 0, numerator.to_f / denominator) + end + end + end + + class ConstantReadNode < Node + # Returns the list of parts for the full name of this constant. + # For example: [:Foo] + def full_name_parts + [name] + end + + # Returns the full name of this constant. For example: "Foo" + def full_name + name.to_s + end + end + + class ConstantWriteNode < Node + # Returns the list of parts for the full name of this constant. + # For example: [:Foo] + def full_name_parts + [name] + end + + # Returns the full name of this constant. For example: "Foo" + def full_name + name.to_s + end + end + + class ConstantPathNode < Node + # An error class raised when dynamic parts are found while computing a + # constant path's full name. For example: + # Foo::Bar::Baz -> does not raise because all parts of the constant path are + # simple constants + # var::Bar::Baz -> raises because the first part of the constant path is a + # local variable + class DynamicPartsInConstantPathError < StandardError; end + + # An error class raised when missing nodes are found while computing a + # constant path's full name. For example: + # Foo:: -> raises because the constant path is missing the last part + class MissingNodesInConstantPathError < StandardError; end + + # Returns the list of parts for the full name of this constant path. + # For example: [:Foo, :Bar] + def full_name_parts + parts = [] #: Array[Symbol] + current = self #: node? + + while current.is_a?(ConstantPathNode) + name = current.name + if name.nil? + raise MissingNodesInConstantPathError, "Constant path contains missing nodes. Cannot compute full name" + end + + parts.unshift(name) + current = current.parent + end + + if !current.is_a?(ConstantReadNode) && !current.nil? + raise DynamicPartsInConstantPathError, "Constant path contains dynamic parts. Cannot compute full name" + end + + parts.unshift(current&.name || :"") + end + + # Returns the full name of this constant path. For example: "Foo::Bar" + def full_name + full_name_parts.join("::") + end + + # Previously, we had a child node on this class that contained either a + # constant read or a missing node. To not cause a breaking change, we + # continue to supply that API. + def child + deprecated("name", "name_loc") + + if name + ConstantReadNode.new(source, -1, name_loc, 0, name) + else + MissingNode.new(source, -1, location, 0) + end + end + end + + class ConstantPathTargetNode < Node + # Returns the list of parts for the full name of this constant path. + # For example: [:Foo, :Bar] + def full_name_parts + parts = + case parent + when ConstantPathNode, ConstantReadNode + parent.full_name_parts + when nil + [:""] + else + # e.g. self::Foo, (var)::Bar = baz + raise ConstantPathNode::DynamicPartsInConstantPathError, "Constant target path contains dynamic parts. Cannot compute full name" + end + + if name.nil? + raise ConstantPathNode::MissingNodesInConstantPathError, "Constant target path contains missing nodes. Cannot compute full name" + end + + parts.push(name) + end + + # Returns the full name of this constant path. For example: "Foo::Bar" + def full_name + full_name_parts.join("::") + end + + # Previously, we had a child node on this class that contained either a + # constant read or a missing node. To not cause a breaking change, we + # continue to supply that API. + def child + deprecated("name", "name_loc") + + if name + ConstantReadNode.new(source, -1, name_loc, 0, name) + else + MissingNode.new(source, -1, location, 0) + end + end + end + + class ConstantTargetNode < Node + # Returns the list of parts for the full name of this constant. + # For example: [:Foo] + def full_name_parts + [name] + end + + # Returns the full name of this constant. For example: "Foo" + def full_name + name.to_s + end + end + + class ParametersNode < Node + # Mirrors the Method#parameters method. + def signature + names = [] #: Array[[Symbol, Symbol] | [Symbol]] + + requireds.each do |param| + names << (param.is_a?(MultiTargetNode) ? [:req] : [:req, param.name]) + end + + optionals.each { |param| names << [:opt, param.name] } + + if rest && rest.is_a?(RestParameterNode) + names << [:rest, rest.name || :*] + end + + posts.each do |param| + case param + when MultiTargetNode + names << [:req] + when NoKeywordsParameterNode, KeywordRestParameterNode, ForwardingParameterNode + # Invalid syntax, e.g. "def f(**nil, ...)" moves the NoKeywordsParameterNode to posts + raise "Invalid syntax" + else + names << [:req, param.name] + end + end + + # Regardless of the order in which the keywords were defined, the required + # keywords always come first followed by the optional keywords. + keyopt = [] #: Array[OptionalKeywordParameterNode] + keywords.each do |param| + if param.is_a?(OptionalKeywordParameterNode) + keyopt << param + else + names << [:keyreq, param.name] + end + end + + keyopt.each { |param| names << [:key, param.name] } + + case keyword_rest + when ForwardingParameterNode + names.concat([[:rest, :*], [:keyrest, :**], [:block, :&]]) + when KeywordRestParameterNode + names << [:keyrest, keyword_rest.name || :**] + when NoKeywordsParameterNode + names << [:nokey] + end + + names << [:block, block.name || :&] if block + names + end + end + + class CallNode < Node + # When a call node has the attribute_write flag set, it means that the call + # is using the attribute write syntax. This is either a method call to []= + # or a method call to a method that ends with =. Either way, the = sign is + # present in the source. + # + # Prism returns the message_loc _without_ the = sign attached, because there + # can be any amount of space between the message and the = sign. However, + # sometimes you want the location of the full message including the inner + # space and the = sign. This method provides that. + def full_message_loc + attribute_write? ? message_loc&.adjoin("=") : message_loc + end + end + + class CallOperatorWriteNode < Node + # Returns the binary operator used to modify the receiver. This method is + # deprecated in favor of #binary_operator. + def operator + deprecated("binary_operator") + binary_operator + end + + # Returns the location of the binary operator used to modify the receiver. + # This method is deprecated in favor of #binary_operator_loc. + def operator_loc + deprecated("binary_operator_loc") + binary_operator_loc + end + end + + class ClassVariableOperatorWriteNode < Node + # Returns the binary operator used to modify the receiver. This method is + # deprecated in favor of #binary_operator. + def operator + deprecated("binary_operator") + binary_operator + end + + # Returns the location of the binary operator used to modify the receiver. + # This method is deprecated in favor of #binary_operator_loc. + def operator_loc + deprecated("binary_operator_loc") + binary_operator_loc + end + end + + class ConstantOperatorWriteNode < Node + # Returns the binary operator used to modify the receiver. This method is + # deprecated in favor of #binary_operator. + def operator + deprecated("binary_operator") + binary_operator + end + + # Returns the location of the binary operator used to modify the receiver. + # This method is deprecated in favor of #binary_operator_loc. + def operator_loc + deprecated("binary_operator_loc") + binary_operator_loc + end + end + + class ConstantPathOperatorWriteNode < Node + # Returns the binary operator used to modify the receiver. This method is + # deprecated in favor of #binary_operator. + def operator + deprecated("binary_operator") + binary_operator + end + + # Returns the location of the binary operator used to modify the receiver. + # This method is deprecated in favor of #binary_operator_loc. + def operator_loc + deprecated("binary_operator_loc") + binary_operator_loc + end + end + + class GlobalVariableOperatorWriteNode < Node + # Returns the binary operator used to modify the receiver. This method is + # deprecated in favor of #binary_operator. + def operator + deprecated("binary_operator") + binary_operator + end + + # Returns the location of the binary operator used to modify the receiver. + # This method is deprecated in favor of #binary_operator_loc. + def operator_loc + deprecated("binary_operator_loc") + binary_operator_loc + end + end + + class IndexOperatorWriteNode < Node + # Returns the binary operator used to modify the receiver. This method is + # deprecated in favor of #binary_operator. + def operator + deprecated("binary_operator") + binary_operator + end + + # Returns the location of the binary operator used to modify the receiver. + # This method is deprecated in favor of #binary_operator_loc. + def operator_loc + deprecated("binary_operator_loc") + binary_operator_loc + end + end + + class InstanceVariableOperatorWriteNode < Node + # Returns the binary operator used to modify the receiver. This method is + # deprecated in favor of #binary_operator. + def operator + deprecated("binary_operator") + binary_operator + end + + # Returns the location of the binary operator used to modify the receiver. + # This method is deprecated in favor of #binary_operator_loc. + def operator_loc + deprecated("binary_operator_loc") + binary_operator_loc + end + end + + class LocalVariableOperatorWriteNode < Node + # Returns the binary operator used to modify the receiver. This method is + # deprecated in favor of #binary_operator. + def operator + deprecated("binary_operator") + binary_operator + end + + # Returns the location of the binary operator used to modify the receiver. + # This method is deprecated in favor of #binary_operator_loc. + def operator_loc + deprecated("binary_operator_loc") + binary_operator_loc + end + end + + class CaseMatchNode < Node + # Returns the else clause of the case match node. This method is deprecated + # in favor of #else_clause. + def consequent + deprecated("else_clause") + else_clause + end + end + + class CaseNode < Node + # Returns the else clause of the case node. This method is deprecated in + # favor of #else_clause. + def consequent + deprecated("else_clause") + else_clause + end + end + + class IfNode < Node + # Returns the subsequent if/elsif/else clause of the if node. This method is + # deprecated in favor of #subsequent. + def consequent + deprecated("subsequent") + subsequent + end + end + + class RescueNode < Node + # Returns the subsequent rescue clause of the rescue node. This method is + # deprecated in favor of #subsequent. + def consequent + deprecated("subsequent") + subsequent + end + end + + class UnlessNode < Node + # Returns the else clause of the unless node. This method is deprecated in + # favor of #else_clause. + def consequent + deprecated("else_clause") + else_clause + end + end +end diff --git a/lib/prism/pack.rb b/lib/prism/pack.rb new file mode 100644 index 00000000000000..166c04c3c08af5 --- /dev/null +++ b/lib/prism/pack.rb @@ -0,0 +1,230 @@ +# frozen_string_literal: true +# :markup: markdown +# typed: ignore + +# +module Prism + # A parser for the pack template language. + module Pack + %i[ + SPACE + COMMENT + INTEGER + UTF8 + BER + FLOAT + STRING_SPACE_PADDED + STRING_NULL_PADDED + STRING_NULL_TERMINATED + STRING_MSB + STRING_LSB + STRING_HEX_HIGH + STRING_HEX_LOW + STRING_UU + STRING_MIME + STRING_BASE64 + STRING_FIXED + STRING_POINTER + MOVE + BACK + NULL + + UNSIGNED + SIGNED + SIGNED_NA + + AGNOSTIC_ENDIAN + LITTLE_ENDIAN + BIG_ENDIAN + NATIVE_ENDIAN + ENDIAN_NA + + SIZE_SHORT + SIZE_INT + SIZE_LONG + SIZE_LONG_LONG + SIZE_8 + SIZE_16 + SIZE_32 + SIZE_64 + SIZE_P + SIZE_NA + + LENGTH_FIXED + LENGTH_MAX + LENGTH_RELATIVE + LENGTH_NA + ].each do |const| + const_set(const, const) + end + + # A directive in the pack template language. + class Directive + # A symbol representing the version of Ruby. + attr_reader :version + + # A symbol representing whether or not we are packing or unpacking. + attr_reader :variant + + # A byteslice of the source string that this directive represents. + attr_reader :source + + # The type of the directive. + attr_reader :type + + # The type of signedness of the directive. + attr_reader :signed + + # The type of endianness of the directive. + attr_reader :endian + + # The size of the directive. + attr_reader :size + + # The length type of this directive (used for integers). + attr_reader :length_type + + # The length of this directive (used for integers). + attr_reader :length + + # Initialize a new directive with the given values. + def initialize(version, variant, source, type, signed, endian, size, length_type, length) + @version = version + @variant = variant + @source = source + @type = type + @signed = signed + @endian = endian + @size = size + @length_type = length_type + @length = length + end + + # The descriptions of the various types of endianness. + ENDIAN_DESCRIPTIONS = { + AGNOSTIC_ENDIAN: "agnostic", + LITTLE_ENDIAN: "little-endian (VAX)", + BIG_ENDIAN: "big-endian (network)", + NATIVE_ENDIAN: "native-endian", + ENDIAN_NA: "n/a" + } + + # The descriptions of the various types of signedness. + SIGNED_DESCRIPTIONS = { + UNSIGNED: "unsigned", + SIGNED: "signed", + SIGNED_NA: "n/a" + } + + # The descriptions of the various types of sizes. + SIZE_DESCRIPTIONS = { + SIZE_SHORT: "short", + SIZE_INT: "int-width", + SIZE_LONG: "long", + SIZE_LONG_LONG: "long long", + SIZE_8: "8-bit", + SIZE_16: "16-bit", + SIZE_32: "32-bit", + SIZE_64: "64-bit", + SIZE_P: "pointer-width" + } + + # Provide a human-readable description of the directive. + def describe + case type + when SPACE + "whitespace" + when COMMENT + "comment" + when INTEGER + if size == SIZE_8 + base = "#{SIGNED_DESCRIPTIONS[signed]} #{SIZE_DESCRIPTIONS[size]} integer" + else + base = "#{SIGNED_DESCRIPTIONS[signed]} #{SIZE_DESCRIPTIONS[size]} #{ENDIAN_DESCRIPTIONS[endian]} integer" + end + case length_type + when LENGTH_FIXED + if length > 1 + base + ", x#{length}" + else + base + end + when LENGTH_MAX + base + ", as many as possible" + else + raise + end + when UTF8 + "UTF-8 character" + when BER + "BER-compressed integer" + when FLOAT + "#{SIZE_DESCRIPTIONS[size]} #{ENDIAN_DESCRIPTIONS[endian]} float" + when STRING_SPACE_PADDED + "arbitrary binary string (space padded)" + when STRING_NULL_PADDED + "arbitrary binary string (null padded, count is width)" + when STRING_NULL_TERMINATED + "arbitrary binary string (null padded, count is width), except that null is added with *" + when STRING_MSB + "bit string (MSB first)" + when STRING_LSB + "bit string (LSB first)" + when STRING_HEX_HIGH + "hex string (high nibble first)" + when STRING_HEX_LOW + "hex string (low nibble first)" + when STRING_UU + "UU-encoded string" + when STRING_MIME + "quoted printable, MIME encoding" + when STRING_BASE64 + "base64 encoded string" + when STRING_FIXED + "pointer to a structure (fixed-length string)" + when STRING_POINTER + "pointer to a null-terminated string" + when MOVE + "move to absolute position" + when BACK + "back up a byte" + when NULL + "null byte" + else + raise + end + end + end + + # The result of parsing a pack template. + class Format + # A list of the directives in the template. + attr_reader :directives + + # The encoding of the template. + attr_reader :encoding + + # Create a new Format with the given directives and encoding. + def initialize(directives, encoding) + @directives = directives + @encoding = encoding + end + + # Provide a human-readable description of the format. + def describe + source_width = directives.map { |d| d.source.inspect.length }.max + directive_lines = directives.map do |directive| + if directive.type == SPACE + source = directive.source.inspect + else + source = directive.source + end + # @type var source_width: Integer + " #{source.ljust(source_width)} #{directive.describe}" + end + + (["Directives:"] + directive_lines + ["Encoding:", " #{encoding}"]).join("\n") + end + end + end +end diff --git a/lib/prism/parse_result.rb b/lib/prism/parse_result.rb new file mode 100644 index 00000000000000..05c14e33f5c99e --- /dev/null +++ b/lib/prism/parse_result.rb @@ -0,0 +1,911 @@ +# frozen_string_literal: true +# :markup: markdown + +module Prism + # This represents a source of Ruby code that has been parsed. It is used in + # conjunction with locations to allow them to resolve line numbers and source + # ranges. + class Source + # Create a new source object with the given source code. This method should + # be used instead of `new` and it will return either a `Source` or a + # specialized and more performant `ASCIISource` if no multibyte characters + # are present in the source code. + def self.for(source, start_line = 1, offsets = []) + if source.ascii_only? + ASCIISource.new(source, start_line, offsets) + elsif source.encoding == Encoding::BINARY + source.force_encoding(Encoding::UTF_8) + + if source.valid_encoding? + new(source, start_line, offsets) + else + # This is an extremely niche use case where the file is marked as + # binary, contains multi-byte characters, and those characters are not + # valid UTF-8. In this case we'll mark it as binary and fall back to + # treating everything as a single-byte character. This _may_ cause + # problems when asking for code units, but it appears to be the + # cleanest solution at the moment. + source.force_encoding(Encoding::BINARY) + ASCIISource.new(source, start_line, offsets) + end + else + new(source, start_line, offsets) + end + end + + # The source code that this source object represents. + attr_reader :source + + # The line number where this source starts. + attr_reader :start_line + + # The list of newline byte offsets in the source code. + attr_reader :offsets + + # Create a new source object with the given source code. + def initialize(source, start_line = 1, offsets = []) + @source = source + @start_line = start_line # set after parsing is done + @offsets = offsets # set after parsing is done + end + + # Replace the value of start_line with the given value. + def replace_start_line(start_line) + @start_line = start_line + end + + # Replace the value of offsets with the given value. + def replace_offsets(offsets) + @offsets.replace(offsets) + end + + # Returns the encoding of the source code, which is set by parameters to the + # parser or by the encoding magic comment. + def encoding + source.encoding + end + + # Returns the lines of the source code as an array of strings. + def lines + source.lines + end + + # Perform a byteslice on the source code using the given byte offset and + # byte length. + def slice(byte_offset, length) + source.byteslice(byte_offset, length) or raise + end + + # Binary search through the offsets to find the line number for the given + # byte offset. + def line(byte_offset) + start_line + find_line(byte_offset) + end + + # Return the byte offset of the start of the line corresponding to the given + # byte offset. + def line_start(byte_offset) + offsets[find_line(byte_offset)] + end + + # Returns the byte offset of the end of the line corresponding to the given + # byte offset. + def line_end(byte_offset) + offsets[find_line(byte_offset) + 1] || source.bytesize + end + + # Return the column number for the given byte offset. + def column(byte_offset) + byte_offset - line_start(byte_offset) + end + + # Return the character offset for the given byte offset. + def character_offset(byte_offset) + (source.byteslice(0, byte_offset) or raise).length + end + + # Return the column number in characters for the given byte offset. + def character_column(byte_offset) + character_offset(byte_offset) - character_offset(line_start(byte_offset)) + end + + # Returns the offset from the start of the file for the given byte offset + # counting in code units for the given encoding. + # + # This method is tested with UTF-8, UTF-16, and UTF-32. If there is the + # concept of code units that differs from the number of characters in other + # encodings, it is not captured here. + # + # We purposefully replace invalid and undefined characters with replacement + # characters in this conversion. This happens for two reasons. First, it's + # possible that the given byte offset will not occur on a character + # boundary. Second, it's possible that the source code will contain a + # character that has no equivalent in the given encoding. + def code_units_offset(byte_offset, encoding) + byteslice = (source.byteslice(0, byte_offset) or raise).encode(encoding, invalid: :replace, undef: :replace) + + if encoding == Encoding::UTF_16LE || encoding == Encoding::UTF_16BE + byteslice.bytesize / 2 + else + byteslice.length + end + end + + # Generate a cache that targets a specific encoding for calculating code + # unit offsets. + def code_units_cache(encoding) + CodeUnitsCache.new(source, encoding) + end + + # Returns the column number in code units for the given encoding for the + # given byte offset. + def code_units_column(byte_offset, encoding) + code_units_offset(byte_offset, encoding) - code_units_offset(line_start(byte_offset), encoding) + end + + # Freeze this object and the objects it contains. + def deep_freeze + source.freeze + offsets.freeze + freeze + end + + private + + # Binary search through the offsets to find the line number for the given + # byte offset. + def find_line(byte_offset) + left = 0 + right = offsets.length - 1 + + while left <= right + mid = left + (right - left) / 2 + return mid if (offset = offsets[mid]) == byte_offset + + if offset < byte_offset + left = mid + 1 + else + right = mid - 1 + end + end + + left - 1 + end + end + + # A cache that can be used to quickly compute code unit offsets from byte + # offsets. It purposefully provides only a single #[] method to access the + # cache in order to minimize surface area. + # + # Note that there are some known issues here that may or may not be addressed + # in the future: + # + # * The first is that there are issues when the cache computes values that are + # not on character boundaries. This can result in subsequent computations + # being off by one or more code units. + # * The second is that this cache is currently unbounded. In theory we could + # introduce some kind of LRU cache to limit the number of entries, but this + # has not yet been implemented. + # + class CodeUnitsCache + class UTF16Counter # :nodoc: + def initialize(source, encoding) + @source = source + @encoding = encoding + end + + def count(byte_offset, byte_length) + @source.byteslice(byte_offset, byte_length).encode(@encoding, invalid: :replace, undef: :replace).bytesize / 2 + end + end + + class LengthCounter # :nodoc: + def initialize(source, encoding) + @source = source + @encoding = encoding + end + + def count(byte_offset, byte_length) + @source.byteslice(byte_offset, byte_length).encode(@encoding, invalid: :replace, undef: :replace).length + end + end + + private_constant :UTF16Counter, :LengthCounter + + # Initialize a new cache with the given source and encoding. + def initialize(source, encoding) + @source = source + @counter = + if encoding == Encoding::UTF_16LE || encoding == Encoding::UTF_16BE + UTF16Counter.new(source, encoding) + else + LengthCounter.new(source, encoding) + end + + @cache = {} #: Hash[Integer, Integer] + @offsets = [] #: Array[Integer] + end + + # Retrieve the code units offset from the given byte offset. + def [](byte_offset) + @cache[byte_offset] ||= + if (index = @offsets.bsearch_index { |offset| offset > byte_offset }).nil? + @offsets << byte_offset + @counter.count(0, byte_offset) + elsif index == 0 + @offsets.unshift(byte_offset) + @counter.count(0, byte_offset) + else + @offsets.insert(index, byte_offset) + offset = @offsets[index - 1] + @cache[offset] + @counter.count(offset, byte_offset - offset) + end + end + end + + # Specialized version of Prism::Source for source code that includes ASCII + # characters only. This class is used to apply performance optimizations that + # cannot be applied to sources that include multibyte characters. + # + # In the extremely rare case that a source includes multi-byte characters but + # is marked as binary because of a magic encoding comment and it cannot be + # eagerly converted to UTF-8, this class will be used as well. This is because + # at that point we will treat everything as single-byte characters. + class ASCIISource < Source + # Return the character offset for the given byte offset. + def character_offset(byte_offset) + byte_offset + end + + # Return the column number in characters for the given byte offset. + def character_column(byte_offset) + byte_offset - line_start(byte_offset) + end + + # Returns the offset from the start of the file for the given byte offset + # counting in code units for the given encoding. + # + # This method is tested with UTF-8, UTF-16, and UTF-32. If there is the + # concept of code units that differs from the number of characters in other + # encodings, it is not captured here. + def code_units_offset(byte_offset, encoding) + byte_offset + end + + # Returns a cache that is the identity function in order to maintain the + # same interface. We can do this because code units are always equivalent to + # byte offsets for ASCII-only sources. + def code_units_cache(encoding) + ->(byte_offset) { byte_offset } + end + + # Specialized version of `code_units_column` that does not depend on + # `code_units_offset`, which is a more expensive operation. This is + # essentially the same as `Prism::Source#column`. + def code_units_column(byte_offset, encoding) + byte_offset - line_start(byte_offset) + end + end + + # This represents a location in the source. + class Location + # A Source object that is used to determine more information from the given + # offset and length. + attr_reader :source + protected :source + + # The byte offset from the beginning of the source where this location + # starts. + attr_reader :start_offset + + # The length of this location in bytes. + attr_reader :length + + # Create a new location object with the given source, start byte offset, and + # byte length. + def initialize(source, start_offset, length) + @source = source + @start_offset = start_offset + @length = length + + # These are used to store comments that are associated with this location. + # They are initialized to `nil` to save on memory when there are no + # comments to be attached and/or the comment-related APIs are not used. + @leading_comments = nil + @trailing_comments = nil + end + + # These are the comments that are associated with this location that exist + # before the start of this location. + def leading_comments + @leading_comments ||= [] + end + + # Attach a comment to the leading comments of this location. + def leading_comment(comment) + leading_comments << comment + end + + # These are the comments that are associated with this location that exist + # after the end of this location. + def trailing_comments + @trailing_comments ||= [] + end + + # Attach a comment to the trailing comments of this location. + def trailing_comment(comment) + trailing_comments << comment + end + + # Returns all comments that are associated with this location (both leading + # and trailing comments). + def comments + [*@leading_comments, *@trailing_comments] + end + + # Create a new location object with the given options. + def copy(source: self.source, start_offset: self.start_offset, length: self.length) + Location.new(source, start_offset, length) + end + + # Returns a new location that is the result of chopping off the last byte. + def chop + copy(length: length == 0 ? length : length - 1) + end + + # Returns a string representation of this location. + def inspect + "#" + end + + # Returns all of the lines of the source code associated with this location. + def source_lines + source.lines + end + + # The source code that this location represents. + def slice + source.slice(start_offset, length) + end + + # The source code that this location represents starting from the beginning + # of the line that this location starts on to the end of the line that this + # location ends on. + def slice_lines + line_start = source.line_start(start_offset) + line_end = source.line_end(end_offset) + source.slice(line_start, line_end - line_start) + end + + # The character offset from the beginning of the source where this location + # starts. + def start_character_offset + source.character_offset(start_offset) + end + + # The offset from the start of the file in code units of the given encoding. + def start_code_units_offset(encoding = Encoding::UTF_16LE) + source.code_units_offset(start_offset, encoding) + end + + # The start offset from the start of the file in code units using the given + # cache to fetch or calculate the value. + def cached_start_code_units_offset(cache) + cache[start_offset] + end + + # The byte offset from the beginning of the source where this location ends. + def end_offset + start_offset + length + end + + # The character offset from the beginning of the source where this location + # ends. + def end_character_offset + source.character_offset(end_offset) + end + + # The offset from the start of the file in code units of the given encoding. + def end_code_units_offset(encoding = Encoding::UTF_16LE) + source.code_units_offset(end_offset, encoding) + end + + # The end offset from the start of the file in code units using the given + # cache to fetch or calculate the value. + def cached_end_code_units_offset(cache) + cache[end_offset] + end + + # The line number where this location starts. + def start_line + source.line(start_offset) + end + + # The content of the line where this location starts before this location. + def start_line_slice + offset = source.line_start(start_offset) + source.slice(offset, start_offset - offset) + end + + # The line number where this location ends. + def end_line + source.line(end_offset) + end + + # The column number in bytes where this location starts from the start of + # the line. + def start_column + source.column(start_offset) + end + + # The column number in characters where this location ends from the start of + # the line. + def start_character_column + source.character_column(start_offset) + end + + # The column number in code units of the given encoding where this location + # starts from the start of the line. + def start_code_units_column(encoding = Encoding::UTF_16LE) + source.code_units_column(start_offset, encoding) + end + + # The start column in code units using the given cache to fetch or calculate + # the value. + def cached_start_code_units_column(cache) + cache[start_offset] - cache[source.line_start(start_offset)] + end + + # The column number in bytes where this location ends from the start of the + # line. + def end_column + source.column(end_offset) + end + + # The column number in characters where this location ends from the start of + # the line. + def end_character_column + source.character_column(end_offset) + end + + # The column number in code units of the given encoding where this location + # ends from the start of the line. + def end_code_units_column(encoding = Encoding::UTF_16LE) + source.code_units_column(end_offset, encoding) + end + + # The end column in code units using the given cache to fetch or calculate + # the value. + def cached_end_code_units_column(cache) + cache[end_offset] - cache[source.line_start(end_offset)] + end + + # Implement the hash pattern matching interface for Location. + def deconstruct_keys(keys) + { start_offset: start_offset, end_offset: end_offset } + end + + # Implement the pretty print interface for Location. + def pretty_print(q) + q.text("(#{start_line},#{start_column})-(#{end_line},#{end_column})") + end + + # Returns true if the given other location is equal to this location. + def ==(other) + Location === other && + other.start_offset == start_offset && + other.end_offset == end_offset + end + + # Returns a new location that stretches from this location to the given + # other location. Raises an error if this location is not before the other + # location or if they don't share the same source. + def join(other) + raise "Incompatible sources" if source != other.source + raise "Incompatible locations" if start_offset > other.start_offset + + Location.new(source, start_offset, other.end_offset - start_offset) + end + + # Join this location with the first occurrence of the string in the source + # that occurs after this location on the same line, and return the new + # location. This will raise an error if the string does not exist. + def adjoin(string) + line_suffix = source.slice(end_offset, source.line_end(end_offset) - end_offset) + + line_suffix_index = line_suffix.byteindex(string) + raise "Could not find #{string}" if line_suffix_index.nil? + + Location.new(source, start_offset, length + line_suffix_index + string.bytesize) + end + end + + # This represents a comment that was encountered during parsing. It is the + # base class for all comment types. + class Comment + # The location of this comment in the source. + attr_reader :location + + # Create a new comment object with the given location. + def initialize(location) + @location = location + end + + # Implement the hash pattern matching interface for Comment. + def deconstruct_keys(keys) + { location: location } + end + + # Returns the content of the comment by slicing it from the source code. + def slice + location.slice + end + end + + # InlineComment objects are the most common. They correspond to comments in + # the source file like this one that start with #. + class InlineComment < Comment + # Returns true if this comment happens on the same line as other code and + # false if the comment is by itself. + def trailing? + !location.start_line_slice.strip.empty? + end + + # Returns a string representation of this comment. + def inspect + "#" + end + end + + # EmbDocComment objects correspond to comments that are surrounded by =begin + # and =end. + class EmbDocComment < Comment + # This can only be true for inline comments. + def trailing? + false + end + + # Returns a string representation of this comment. + def inspect + "#" + end + end + + # This represents a magic comment that was encountered during parsing. + class MagicComment + # A Location object representing the location of the key in the source. + attr_reader :key_loc + + # A Location object representing the location of the value in the source. + attr_reader :value_loc + + # Create a new magic comment object with the given key and value locations. + def initialize(key_loc, value_loc) + @key_loc = key_loc + @value_loc = value_loc + end + + # Returns the key of the magic comment by slicing it from the source code. + def key + key_loc.slice + end + + # Returns the value of the magic comment by slicing it from the source code. + def value + value_loc.slice + end + + # Implement the hash pattern matching interface for MagicComment. + def deconstruct_keys(keys) + { key_loc: key_loc, value_loc: value_loc } + end + + # Returns a string representation of this magic comment. + def inspect + "#" + end + end + + # This represents an error that was encountered during parsing. + class ParseError + # The type of error. This is an _internal_ symbol that is used for + # communicating with translation layers. It is not meant to be public API. + attr_reader :type + + # The message associated with this error. + attr_reader :message + + # A Location object representing the location of this error in the source. + attr_reader :location + + # The level of this error. + attr_reader :level + + # Create a new error object with the given message and location. + def initialize(type, message, location, level) + @type = type + @message = message + @location = location + @level = level + end + + # Implement the hash pattern matching interface for ParseError. + def deconstruct_keys(keys) + { type: type, message: message, location: location, level: level } + end + + # Returns a string representation of this error. + def inspect + "#" + end + end + + # This represents a warning that was encountered during parsing. + class ParseWarning + # The type of warning. This is an _internal_ symbol that is used for + # communicating with translation layers. It is not meant to be public API. + attr_reader :type + + # The message associated with this warning. + attr_reader :message + + # A Location object representing the location of this warning in the source. + attr_reader :location + + # The level of this warning. + attr_reader :level + + # Create a new warning object with the given message and location. + def initialize(type, message, location, level) + @type = type + @message = message + @location = location + @level = level + end + + # Implement the hash pattern matching interface for ParseWarning. + def deconstruct_keys(keys) + { type: type, message: message, location: location, level: level } + end + + # Returns a string representation of this warning. + def inspect + "#" + end + end + + # This represents the result of a call to ::parse or ::parse_file. It contains + # the requested structure, any comments that were encounters, and any errors + # that were encountered. + class Result + # The list of comments that were encountered during parsing. + attr_reader :comments + + # The list of magic comments that were encountered during parsing. + attr_reader :magic_comments + + # An optional location that represents the location of the __END__ marker + # and the rest of the content of the file. This content is loaded into the + # DATA constant when the file being parsed is the main file being executed. + attr_reader :data_loc + + # The list of errors that were generated during parsing. + attr_reader :errors + + # The list of warnings that were generated during parsing. + attr_reader :warnings + + # A Source instance that represents the source code that was parsed. + attr_reader :source + + # Create a new result object with the given values. + def initialize(comments, magic_comments, data_loc, errors, warnings, source) + @comments = comments + @magic_comments = magic_comments + @data_loc = data_loc + @errors = errors + @warnings = warnings + @source = source + end + + # Implement the hash pattern matching interface for Result. + def deconstruct_keys(keys) + { comments: comments, magic_comments: magic_comments, data_loc: data_loc, errors: errors, warnings: warnings } + end + + # Returns the encoding of the source code that was parsed. + def encoding + source.encoding + end + + # Returns true if there were no errors during parsing and false if there + # were. + def success? + errors.empty? + end + + # Returns true if there were errors during parsing and false if there were + # not. + def failure? + !success? + end + + # Create a code units cache for the given encoding. + def code_units_cache(encoding) + source.code_units_cache(encoding) + end + end + + # This is a result specific to the `parse` and `parse_file` methods. + class ParseResult < Result + autoload :Comments, "prism/parse_result/comments" + autoload :Errors, "prism/parse_result/errors" + autoload :Newlines, "prism/parse_result/newlines" + + private_constant :Comments + private_constant :Errors + private_constant :Newlines + + # The syntax tree that was parsed from the source code. + attr_reader :value + + # Create a new parse result object with the given values. + def initialize(value, comments, magic_comments, data_loc, errors, warnings, source) + @value = value + super(comments, magic_comments, data_loc, errors, warnings, source) + end + + # Implement the hash pattern matching interface for ParseResult. + def deconstruct_keys(keys) + super.merge!(value: value) + end + + # Attach the list of comments to their respective locations in the tree. + def attach_comments! + Comments.new(self).attach! # steep:ignore + end + + # Walk the tree and mark nodes that are on a new line, loosely emulating + # the behavior of CRuby's `:line` tracepoint event. + def mark_newlines! + value.accept(Newlines.new(source.offsets.size)) # steep:ignore + end + + # Returns a string representation of the syntax tree with the errors + # displayed inline. + def errors_format + Errors.new(self).format + end + end + + # This is a result specific to the `lex` and `lex_file` methods. + class LexResult < Result + # The list of tokens that were parsed from the source code. + attr_reader :value + + # Create a new lex result object with the given values. + def initialize(value, comments, magic_comments, data_loc, errors, warnings, source) + @value = value + super(comments, magic_comments, data_loc, errors, warnings, source) + end + + # Implement the hash pattern matching interface for LexResult. + def deconstruct_keys(keys) + super.merge!(value: value) + end + end + + # This is a result specific to the `parse_lex` and `parse_lex_file` methods. + class ParseLexResult < Result + # A tuple of the syntax tree and the list of tokens that were parsed from + # the source code. + attr_reader :value + + # Create a new parse lex result object with the given values. + def initialize(value, comments, magic_comments, data_loc, errors, warnings, source) + @value = value + super(comments, magic_comments, data_loc, errors, warnings, source) + end + + # Implement the hash pattern matching interface for ParseLexResult. + def deconstruct_keys(keys) + super.merge!(value: value) + end + end + + # This represents a token from the Ruby source. + class Token + # The Source object that represents the source this token came from. + attr_reader :source + private :source + + # The type of token that this token is. + attr_reader :type + + # A byteslice of the source that this token represents. + attr_reader :value + + # Create a new token object with the given type, value, and location. + def initialize(source, type, value, location) + @source = source + @type = type + @value = value + @location = location + end + + # Implement the hash pattern matching interface for Token. + def deconstruct_keys(keys) + { type: type, value: value, location: location } + end + + # A Location object representing the location of this token in the source. + def location + location = @location + return location if location.is_a?(Location) + @location = Location.new(source, location >> 32, location & 0xFFFFFFFF) + end + + # Implement the pretty print interface for Token. + def pretty_print(q) + q.group do + q.text(type.to_s) + self.location.pretty_print(q) + q.text("(") + q.nest(2) do + q.breakable("") + q.pp(value) + end + q.breakable("") + q.text(")") + end + end + + # Returns true if the given other token is equal to this token. + def ==(other) + Token === other && + other.type == type && + other.value == value + end + + # Returns a string representation of this token. + def inspect + location + super + end + + # Freeze this object and the objects it contains. + def deep_freeze + value.freeze + location.freeze + freeze + end + end + + # This object is passed to the various Prism.* methods that accept the + # `scopes` option as an element of the list. It defines both the local + # variables visible at that scope as well as the forwarding parameters + # available at that scope. + class Scope + # The list of local variables that are defined in this scope. This should be + # defined as an array of symbols. + attr_reader :locals + + # The list of local variables that are forwarded to the next scope. This + # should by defined as an array of symbols containing the specific values of + # :*, :**, :&, or :"...". + attr_reader :forwarding + + # Create a new scope object with the given locals and forwarding. + def initialize(locals, forwarding) + @locals = locals + @forwarding = forwarding + end + end + + # Create a new scope with the given locals and forwarding options that is + # suitable for passing into one of the Prism.* methods that accepts the + # `scopes` option. + def self.scope(locals: [], forwarding: []) + Scope.new(locals, forwarding) + end +end diff --git a/lib/prism/parse_result/comments.rb b/lib/prism/parse_result/comments.rb new file mode 100644 index 00000000000000..3e93316aff8662 --- /dev/null +++ b/lib/prism/parse_result/comments.rb @@ -0,0 +1,188 @@ +# frozen_string_literal: true +# :markup: markdown + +module Prism + class ParseResult < Result + # When we've parsed the source, we have both the syntax tree and the list of + # comments that we found in the source. This class is responsible for + # walking the tree and finding the nearest location to attach each comment. + # + # It does this by first finding the nearest locations to each comment. + # Locations can either come from nodes directly or from location fields on + # nodes. For example, a `ClassNode` has an overall location encompassing the + # entire class, but it also has a location for the `class` keyword. + # + # Once the nearest locations are found, it determines which one to attach + # to. If it's a trailing comment (a comment on the same line as other source + # code), it will favor attaching to the nearest location that occurs before + # the comment. Otherwise it will favor attaching to the nearest location + # that is after the comment. + class Comments + # A target for attaching comments that is based on a specific node's + # location. + class NodeTarget # :nodoc: + attr_reader :node + + def initialize(node) + @node = node + end + + def start_offset + node.start_offset + end + + def end_offset + node.end_offset + end + + def encloses?(comment) + start_offset <= comment.location.start_offset && + comment.location.end_offset <= end_offset + end + + def leading_comment(comment) + node.location.leading_comment(comment) + end + + def trailing_comment(comment) + node.location.trailing_comment(comment) + end + end + + # A target for attaching comments that is based on a location field on a + # node. For example, the `end` token of a ClassNode. + class LocationTarget # :nodoc: + attr_reader :location + + def initialize(location) + @location = location + end + + def start_offset + location.start_offset + end + + def end_offset + location.end_offset + end + + def encloses?(comment) + false + end + + def leading_comment(comment) + location.leading_comment(comment) + end + + def trailing_comment(comment) + location.trailing_comment(comment) + end + end + + # The parse result that we are attaching comments to. + attr_reader :parse_result + + # Create a new Comments object that will attach comments to the given + # parse result. + def initialize(parse_result) + @parse_result = parse_result + end + + # Attach the comments to their respective locations in the tree by + # mutating the parse result. + def attach! + parse_result.comments.each do |comment| + preceding, enclosing, following = nearest_targets(parse_result.value, comment) + + if comment.trailing? + if preceding + preceding.trailing_comment(comment) + else + (following || enclosing || NodeTarget.new(parse_result.value)).leading_comment(comment) + end + else + # If a comment exists on its own line, prefer a leading comment. + if following + following.leading_comment(comment) + elsif preceding + preceding.trailing_comment(comment) + else + (enclosing || NodeTarget.new(parse_result.value)).leading_comment(comment) + end + end + end + end + + private + + # Responsible for finding the nearest targets to the given comment within + # the context of the given encapsulating node. + def nearest_targets(node, comment) + comment_start = comment.location.start_offset + comment_end = comment.location.end_offset + + targets = [] #: Array[_Target] + node.comment_targets.map do |value| + case value + when StatementsNode + targets.concat(value.body.map { |node| NodeTarget.new(node) }) + when Node + targets << NodeTarget.new(value) + when Location + targets << LocationTarget.new(value) + end + end + + targets.sort_by!(&:start_offset) + preceding = nil #: _Target? + following = nil #: _Target? + + left = 0 + right = targets.length + + # This is a custom binary search that finds the nearest nodes to the + # given comment. When it finds a node that completely encapsulates the + # comment, it recurses downward into the tree. + while left < right + middle = (left + right) / 2 + target = targets[middle] + + target_start = target.start_offset + target_end = target.end_offset + + if target.encloses?(comment) + # @type var target: NodeTarget + # The comment is completely contained by this target. Abandon the + # binary search at this level. + return nearest_targets(target.node, comment) + end + + if target_end <= comment_start + # This target falls completely before the comment. Because we will + # never consider this target or any targets before it again, this + # target must be the closest preceding target we have encountered so + # far. + preceding = target + left = middle + 1 + next + end + + if comment_end <= target_start + # This target falls completely after the comment. Because we will + # never consider this target or any targets after it again, this + # target must be the closest following target we have encountered so + # far. + following = target + right = middle + next + end + + # This should only happen if there is a bug in this parser. + raise "Comment location overlaps with a target location" + end + + [preceding, NodeTarget.new(node), following] + end + end + end +end diff --git a/lib/prism/parse_result/errors.rb b/lib/prism/parse_result/errors.rb new file mode 100644 index 00000000000000..26c376b3ce895f --- /dev/null +++ b/lib/prism/parse_result/errors.rb @@ -0,0 +1,66 @@ +# frozen_string_literal: true +# :markup: markdown + +require "stringio" + +module Prism + class ParseResult < Result + # An object to represent the set of errors on a parse result. This object + # can be used to format the errors in a human-readable way. + class Errors + # The parse result that contains the errors. + attr_reader :parse_result + + # Initialize a new set of errors from the given parse result. + def initialize(parse_result) + @parse_result = parse_result + end + + # Formats the errors in a human-readable way and return them as a string. + def format + error_lines = {} #: Hash[Integer, Array[ParseError]] + parse_result.errors.each do |error| + location = error.location + (location.start_line..location.end_line).each do |line| + error_lines[line] ||= [] + error_lines[line] << error + end + end + + source_lines = parse_result.source.source.lines + source_lines << "" if error_lines.key?(source_lines.size + 1) + + io = StringIO.new + source_lines.each.with_index(1) do |line, line_number| + io.puts(line) + + (error_lines.delete(line_number) || []).each do |error| + location = error.location + + case line_number + when location.start_line + io.print(" " * location.start_column + "^") + + if location.start_line == location.end_line + if location.start_column != location.end_column + io.print("~" * (location.end_column - location.start_column - 1)) + end + + io.puts(" " + error.message) + else + io.puts("~" * (line.bytesize - location.start_column)) + end + when location.end_line + io.puts("~" * location.end_column + " " + error.message) + else + io.puts("~" * line.bytesize) + end + end + end + + io.puts + io.string + end + end + end +end diff --git a/lib/prism/parse_result/newlines.rb b/lib/prism/parse_result/newlines.rb new file mode 100644 index 00000000000000..e7fd62cafedb37 --- /dev/null +++ b/lib/prism/parse_result/newlines.rb @@ -0,0 +1,155 @@ +# frozen_string_literal: true +# :markup: markdown + +module Prism + class ParseResult < Result + # The :line tracepoint event gets fired whenever the Ruby VM encounters an + # expression on a new line. The types of expressions that can trigger this + # event are: + # + # * if statements + # * unless statements + # * nodes that are children of statements lists + # + # In order to keep track of the newlines, we have a list of offsets that + # come back from the parser. We assign these offsets to the first nodes that + # we find in the tree that are on those lines. + # + # Note that the logic in this file should be kept in sync with the Java + # MarkNewlinesVisitor, since that visitor is responsible for marking the + # newlines for JRuby/TruffleRuby. + # + # This file is autoloaded only when `mark_newlines!` is called, so the + # re-opening of the various nodes in this file will only be performed in + # that case. We do that to avoid storing the extra `@newline` instance + # variable on every node if we don't need it. + class Newlines < Visitor + # Create a new Newlines visitor with the given newline offsets. + def initialize(lines) + # @type var lines: Integer + @lines = Array.new(1 + lines, false) + end + + # Permit block/lambda nodes to mark newlines within themselves. + def visit_block_node(node) + old_lines = @lines + @lines = Array.new(old_lines.size, false) + + begin + super(node) + ensure + @lines = old_lines + end + end + + alias_method :visit_lambda_node, :visit_block_node + + # Mark if/unless nodes as newlines. + def visit_if_node(node) + node.newline_flag!(@lines) + super(node) + end + + alias_method :visit_unless_node, :visit_if_node + + # Permit statements lists to mark newlines within themselves. + def visit_statements_node(node) + node.body.each do |child| + child.newline_flag!(@lines) + end + super(node) + end + end + end + + class Node + def newline_flag? # :nodoc: + !!defined?(@newline_flag) + end + + def newline_flag!(lines) # :nodoc: + line = location.start_line + unless lines[line] + lines[line] = true + @newline_flag = true + end + end + end + + class BeginNode < Node + def newline_flag!(lines) # :nodoc: + # Never mark BeginNode with a newline flag, mark children instead. + end + end + + class ParenthesesNode < Node + def newline_flag!(lines) # :nodoc: + # Never mark ParenthesesNode with a newline flag, mark children instead. + end + end + + class IfNode < Node + def newline_flag!(lines) # :nodoc: + predicate.newline_flag!(lines) + end + end + + class UnlessNode < Node + def newline_flag!(lines) # :nodoc: + predicate.newline_flag!(lines) + end + end + + class UntilNode < Node + def newline_flag!(lines) # :nodoc: + predicate.newline_flag!(lines) + end + end + + class WhileNode < Node + def newline_flag!(lines) # :nodoc: + predicate.newline_flag!(lines) + end + end + + class RescueModifierNode < Node + def newline_flag!(lines) # :nodoc: + expression.newline_flag!(lines) + end + end + + class InterpolatedMatchLastLineNode < Node + def newline_flag!(lines) # :nodoc: + first = parts.first + first.newline_flag!(lines) if first + end + end + + class InterpolatedRegularExpressionNode < Node + def newline_flag!(lines) # :nodoc: + first = parts.first + first.newline_flag!(lines) if first + end + end + + class InterpolatedStringNode < Node + def newline_flag!(lines) # :nodoc: + first = parts.first + first.newline_flag!(lines) if first + end + end + + class InterpolatedSymbolNode < Node + def newline_flag!(lines) # :nodoc: + first = parts.first + first.newline_flag!(lines) if first + end + end + + class InterpolatedXStringNode < Node + def newline_flag!(lines) # :nodoc: + first = parts.first + first.newline_flag!(lines) if first + end + end +end diff --git a/lib/prism/pattern.rb b/lib/prism/pattern.rb new file mode 100644 index 00000000000000..6ad2d9e5b9566f --- /dev/null +++ b/lib/prism/pattern.rb @@ -0,0 +1,269 @@ +# frozen_string_literal: true +# :markup: markdown + +module Prism + # A pattern is an object that wraps a Ruby pattern matching expression. The + # expression would normally be passed to an `in` clause within a `case` + # expression or a rightward assignment expression. For example, in the + # following snippet: + # + # case node + # in ConstantPathNode[ConstantReadNode[name: :Prism], ConstantReadNode[name: :Pattern]] + # end + # + # the pattern is the ConstantPathNode[...] expression. + # + # The pattern gets compiled into an object that responds to #call by running + # the #compile method. This method itself will run back through Prism to + # parse the expression into a tree, then walk the tree to generate the + # necessary callable objects. For example, if you wanted to compile the + # expression above into a callable, you would: + # + # callable = Prism::Pattern.new("ConstantPathNode[ConstantReadNode[name: :Prism], ConstantReadNode[name: :Pattern]]").compile + # callable.call(node) + # + # The callable object returned by #compile is guaranteed to respond to #call + # with a single argument, which is the node to match against. It also is + # guaranteed to respond to #===, which means it itself can be used in a `case` + # expression, as in: + # + # case node + # when callable + # end + # + # If the query given to the initializer cannot be compiled into a valid + # matcher (either because of a syntax error or because it is using syntax we + # do not yet support) then a Prism::Pattern::CompilationError will be + # raised. + class Pattern + # Raised when the query given to a pattern is either invalid Ruby syntax or + # is using syntax that we don't yet support. + class CompilationError < StandardError + # Create a new CompilationError with the given representation of the node + # that caused the error. + def initialize(repr) + super(<<~ERROR) + prism was unable to compile the pattern you provided into a usable + expression. It failed on to understand the node represented by: + + #{repr} + + Note that not all syntax supported by Ruby's pattern matching syntax + is also supported by prism's patterns. If you're using some syntax + that you believe should be supported, please open an issue on + GitHub at https://github.com/ruby/prism/issues/new. + ERROR + end + end + + # The query that this pattern was initialized with. + attr_reader :query + + # Create a new pattern with the given query. The query should be a string + # containing a Ruby pattern matching expression. + def initialize(query) + @query = query + @compiled = nil + end + + # Compile the query into a callable object that can be used to match against + # nodes. + def compile + result = Prism.parse("case nil\nin #{query}\nend") + + case_match_node = result.value.statements.body.last + raise CompilationError, case_match_node.inspect unless case_match_node.is_a?(CaseMatchNode) + + in_node = case_match_node.conditions.last + raise CompilationError, in_node.inspect unless in_node.is_a?(InNode) + + compile_node(in_node.pattern) + end + + # Scan the given node and all of its children for nodes that match the + # pattern. If a block is given, it will be called with each node that + # matches the pattern. If no block is given, an enumerator will be returned + # that will yield each node that matches the pattern. + def scan(root) + return to_enum(:scan, root) unless block_given? + + @compiled ||= compile + queue = [root] + + while (node = queue.shift) + yield node if @compiled.call(node) # steep:ignore + queue.concat(node.compact_child_nodes) + end + end + + private + + # Shortcut for combining two procs into one that returns true if both return + # true. + def combine_and(left, right) + ->(other) { left.call(other) && right.call(other) } + end + + # Shortcut for combining two procs into one that returns true if either + # returns true. + def combine_or(left, right) + ->(other) { left.call(other) || right.call(other) } + end + + # Raise an error because the given node is not supported. + def compile_error(node) + raise CompilationError, node.inspect + end + + # in [foo, bar, baz] + def compile_array_pattern_node(node) + compile_error(node) if !node.rest.nil? || node.posts.any? + + constant = node.constant + compiled_constant = compile_node(constant) if constant + + preprocessed = node.requireds.map { |required| compile_node(required) } + + compiled_requireds = ->(other) do + deconstructed = other.deconstruct + + deconstructed.length == preprocessed.length && + preprocessed + .zip(deconstructed) + .all? { |(matcher, value)| matcher.call(value) } + end + + if compiled_constant + combine_and(compiled_constant, compiled_requireds) + else + compiled_requireds + end + end + + # in foo | bar + def compile_alternation_pattern_node(node) + combine_or(compile_node(node.left), compile_node(node.right)) + end + + # in Prism::ConstantReadNode + def compile_constant_path_node(node) + parent = node.parent + + if parent.is_a?(ConstantReadNode) && parent.slice == "Prism" + name = node.name + raise CompilationError, node.inspect if name.nil? + + compile_constant_name(node, name) + else + compile_error(node) + end + end + + # in ConstantReadNode + # in String + def compile_constant_read_node(node) + compile_constant_name(node, node.name) + end + + # Compile a name associated with a constant. + def compile_constant_name(node, name) + if Prism.const_defined?(name, false) + clazz = Prism.const_get(name) + + ->(other) { clazz === other } + elsif Object.const_defined?(name, false) + clazz = Object.const_get(name) + + ->(other) { clazz === other } + else + compile_error(node) + end + end + + # in InstanceVariableReadNode[name: Symbol] + # in { name: Symbol } + def compile_hash_pattern_node(node) + compile_error(node) if node.rest + compiled_constant = compile_node(node.constant) if node.constant + + preprocessed = + node.elements.to_h do |element| + key = element.key + if key.is_a?(SymbolNode) + [key.unescaped.to_sym, compile_node(element.value)] + else + raise CompilationError, element.inspect + end + end + + compiled_keywords = ->(other) do + deconstructed = other.deconstruct_keys(preprocessed.keys) + + preprocessed.all? do |keyword, matcher| + deconstructed.key?(keyword) && matcher.call(deconstructed[keyword]) + end + end + + if compiled_constant + combine_and(compiled_constant, compiled_keywords) + else + compiled_keywords + end + end + + # in nil + def compile_nil_node(node) + ->(attribute) { attribute.nil? } + end + + # in /foo/ + def compile_regular_expression_node(node) + regexp = Regexp.new(node.unescaped, node.closing[1..]) + + ->(attribute) { regexp === attribute } + end + + # in "" + # in "foo" + def compile_string_node(node) + string = node.unescaped + + ->(attribute) { string === attribute } + end + + # in :+ + # in :foo + def compile_symbol_node(node) + symbol = node.unescaped.to_sym + + ->(attribute) { symbol === attribute } + end + + # Compile any kind of node. Dispatch out to the individual compilation + # methods based on the type of node. + def compile_node(node) + case node + when AlternationPatternNode + compile_alternation_pattern_node(node) + when ArrayPatternNode + compile_array_pattern_node(node) + when ConstantPathNode + compile_constant_path_node(node) + when ConstantReadNode + compile_constant_read_node(node) + when HashPatternNode + compile_hash_pattern_node(node) + when NilNode + compile_nil_node(node) + when RegularExpressionNode + compile_regular_expression_node(node) + when StringNode + compile_string_node(node) + when SymbolNode + compile_symbol_node(node) + else + compile_error(node) + end + end + end +end diff --git a/lib/prism/polyfill/append_as_bytes.rb b/lib/prism/polyfill/append_as_bytes.rb new file mode 100644 index 00000000000000..24218bd171aa88 --- /dev/null +++ b/lib/prism/polyfill/append_as_bytes.rb @@ -0,0 +1,15 @@ +# frozen_string_literal: true + +# Polyfill for String#append_as_bytes, which didn't exist until Ruby 3.4. +if !("".respond_to?(:append_as_bytes)) + String.include( + Module.new { + def append_as_bytes(*args) + args.each do |arg| + arg = Integer === arg ? [arg].pack("C") : arg.b + self.<<(arg) # steep:ignore + end + end + } + ) +end diff --git a/lib/prism/polyfill/byteindex.rb b/lib/prism/polyfill/byteindex.rb new file mode 100644 index 00000000000000..98c6089f141ef7 --- /dev/null +++ b/lib/prism/polyfill/byteindex.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true + +# Polyfill for String#byteindex, which didn't exist until Ruby 3.2. +if !("".respond_to?(:byteindex)) + String.include( + Module.new { + def byteindex(needle, offset = 0) + charindex = index(needle, offset) + slice(0...charindex).bytesize if charindex + end + } + ) +end diff --git a/lib/prism/polyfill/scan_byte.rb b/lib/prism/polyfill/scan_byte.rb new file mode 100644 index 00000000000000..2def4572c42870 --- /dev/null +++ b/lib/prism/polyfill/scan_byte.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +require "strscan" + +# Polyfill for StringScanner#scan_byte, which didn't exist until Ruby 3.4. +if !(StringScanner.instance_methods.include?(:scan_byte)) + StringScanner.include( + Module.new { + def scan_byte # :nodoc: + get_byte&.b&.ord + end + } + ) +end diff --git a/lib/prism/polyfill/unpack1.rb b/lib/prism/polyfill/unpack1.rb new file mode 100644 index 00000000000000..3fa9b5a0c56abe --- /dev/null +++ b/lib/prism/polyfill/unpack1.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +# Polyfill for String#unpack1 with the offset parameter. Not all Ruby engines +# have Method#parameters implemented, so we check the arity instead if +# necessary. +if (unpack1 = String.instance_method(:unpack1)).respond_to?(:parameters) ? unpack1.parameters.none? { |_, name| name == :offset } : (unpack1.arity == 1) + String.prepend( + Module.new { + def unpack1(format, offset: 0) # :nodoc: + offset == 0 ? super(format) : self[offset..].unpack1(format) # steep:ignore + end + } + ) +end diff --git a/lib/prism/polyfill/warn.rb b/lib/prism/polyfill/warn.rb new file mode 100644 index 00000000000000..560380d30807e8 --- /dev/null +++ b/lib/prism/polyfill/warn.rb @@ -0,0 +1,42 @@ +# frozen_string_literal: true + +# Polyfill for Kernel#warn with the category parameter. Not all Ruby engines +# have Method#parameters implemented, so we check the arity instead if +# necessary. +if (method = Kernel.instance_method(:warn)).respond_to?(:parameters) ? method.parameters.none? { |_, name| name == :category } : (method.arity == -1) + Kernel.prepend( + Module.new { + def warn(*msgs, uplevel: nil, category: nil) # :nodoc: + uplevel = + case uplevel + when nil + 1 + when Integer + uplevel + 1 + else + uplevel.to_int + 1 + end + + super(*msgs, uplevel: uplevel) + end + } + ) + + Object.prepend( + Module.new { + def warn(*msgs, uplevel: nil, category: nil) # :nodoc: + uplevel = + case uplevel + when nil + 1 + when Integer + uplevel + 1 + else + uplevel.to_int + 1 + end + + super(*msgs, uplevel: uplevel) + end + } + ) +end diff --git a/lib/prism/prism.gemspec b/lib/prism/prism.gemspec new file mode 100644 index 00000000000000..4daa5113007086 --- /dev/null +++ b/lib/prism/prism.gemspec @@ -0,0 +1,174 @@ +# frozen_string_literal: true + +Gem::Specification.new do |spec| + spec.name = "prism" + spec.version = "1.4.0" + spec.authors = ["Shopify"] + spec.email = ["ruby@shopify.com"] + + spec.summary = "Prism Ruby parser" + spec.homepage = "https://github.com/ruby/prism" + spec.license = "MIT" + + spec.required_ruby_version = ">= 2.7.0" + + spec.require_paths = ["lib"] + spec.files = [ + "BSDmakefile", + "CHANGELOG.md", + "CODE_OF_CONDUCT.md", + "CONTRIBUTING.md", + "LICENSE.md", + "Makefile", + "README.md", + "config.yml", + "docs/build_system.md", + "docs/configuration.md", + "docs/cruby_compilation.md", + "docs/design.md", + "docs/encoding.md", + "docs/fuzzing.md", + "docs/heredocs.md", + "docs/javascript.md", + "docs/local_variable_depth.md", + "docs/mapping.md", + "docs/parser_translation.md", + "docs/parsing_rules.md", + "docs/releasing.md", + "docs/relocation.md", + "docs/ripper_translation.md", + "docs/ruby_api.md", + "docs/ruby_parser_translation.md", + "docs/serialization.md", + "docs/testing.md", + "ext/prism/api_node.c", + "ext/prism/api_pack.c", + "ext/prism/extension.c", + "ext/prism/extension.h", + "include/prism.h", + "include/prism/ast.h", + "include/prism/defines.h", + "include/prism/diagnostic.h", + "include/prism/encoding.h", + "include/prism/node.h", + "include/prism/options.h", + "include/prism/pack.h", + "include/prism/parser.h", + "include/prism/prettyprint.h", + "include/prism/regexp.h", + "include/prism/static_literals.h", + "include/prism/util/pm_buffer.h", + "include/prism/util/pm_char.h", + "include/prism/util/pm_constant_pool.h", + "include/prism/util/pm_integer.h", + "include/prism/util/pm_list.h", + "include/prism/util/pm_memchr.h", + "include/prism/util/pm_newline_list.h", + "include/prism/util/pm_strncasecmp.h", + "include/prism/util/pm_string.h", + "include/prism/util/pm_strpbrk.h", + "include/prism/version.h", + "lib/prism.rb", + "lib/prism/compiler.rb", + "lib/prism/desugar_compiler.rb", + "lib/prism/dispatcher.rb", + "lib/prism/dot_visitor.rb", + "lib/prism/dsl.rb", + "lib/prism/ffi.rb", + "lib/prism/inspect_visitor.rb", + "lib/prism/lex_compat.rb", + "lib/prism/mutation_compiler.rb", + "lib/prism/node_ext.rb", + "lib/prism/node.rb", + "lib/prism/pack.rb", + "lib/prism/parse_result.rb", + "lib/prism/parse_result/comments.rb", + "lib/prism/parse_result/errors.rb", + "lib/prism/parse_result/newlines.rb", + "lib/prism/pattern.rb", + "lib/prism/polyfill/append_as_bytes.rb", + "lib/prism/polyfill/byteindex.rb", + "lib/prism/polyfill/scan_byte.rb", + "lib/prism/polyfill/unpack1.rb", + "lib/prism/polyfill/warn.rb", + "lib/prism/reflection.rb", + "lib/prism/relocation.rb", + "lib/prism/serialize.rb", + "lib/prism/string_query.rb", + "lib/prism/translation.rb", + "lib/prism/translation/parser.rb", + "lib/prism/translation/parser_current.rb", + "lib/prism/translation/parser33.rb", + "lib/prism/translation/parser34.rb", + "lib/prism/translation/parser35.rb", + "lib/prism/translation/parser/builder.rb", + "lib/prism/translation/parser/compiler.rb", + "lib/prism/translation/parser/lexer.rb", + "lib/prism/translation/ripper.rb", + "lib/prism/translation/ripper/sexp.rb", + "lib/prism/translation/ripper/shim.rb", + "lib/prism/translation/ruby_parser.rb", + "lib/prism/visitor.rb", + "prism.gemspec", + "rbi/prism.rbi", + "rbi/prism/compiler.rbi", + "rbi/prism/dsl.rbi", + "rbi/prism/inspect_visitor.rbi", + "rbi/prism/node_ext.rbi", + "rbi/prism/node.rbi", + "rbi/prism/parse_result.rbi", + "rbi/prism/reflection.rbi", + "rbi/prism/string_query.rbi", + "rbi/prism/translation/parser.rbi", + "rbi/prism/translation/parser33.rbi", + "rbi/prism/translation/parser34.rbi", + "rbi/prism/translation/parser35.rbi", + "rbi/prism/translation/ripper.rbi", + "rbi/prism/visitor.rbi", + "sig/prism.rbs", + "sig/prism/compiler.rbs", + "sig/prism/dispatcher.rbs", + "sig/prism/dot_visitor.rbs", + "sig/prism/dsl.rbs", + "sig/prism/inspect_visitor.rbs", + "sig/prism/lex_compat.rbs", + "sig/prism/mutation_compiler.rbs", + "sig/prism/node_ext.rbs", + "sig/prism/node.rbs", + "sig/prism/pack.rbs", + "sig/prism/parse_result.rbs", + "sig/prism/parse_result/comments.rbs", + "sig/prism/pattern.rbs", + "sig/prism/reflection.rbs", + "sig/prism/relocation.rbs", + "sig/prism/serialize.rbs", + "sig/prism/string_query.rbs", + "sig/prism/visitor.rbs", + "src/diagnostic.c", + "src/encoding.c", + "src/node.c", + "src/options.c", + "src/pack.c", + "src/prettyprint.c", + "src/prism.c", + "src/regexp.c", + "src/serialize.c", + "src/static_literals.c", + "src/token_type.c", + "src/util/pm_buffer.c", + "src/util/pm_char.c", + "src/util/pm_constant_pool.c", + "src/util/pm_integer.c", + "src/util/pm_list.c", + "src/util/pm_memchr.c", + "src/util/pm_newline_list.c", + "src/util/pm_string.c", + "src/util/pm_strncasecmp.c", + "src/util/pm_strpbrk.c" + ] + + spec.extensions = ["ext/prism/extconf.rb"] + spec.metadata["allowed_push_host"] = "https://rubygems.org" + spec.metadata["source_code_uri"] = "https://github.com/ruby/prism" + spec.metadata["changelog_uri"] = "https://github.com/ruby/prism/blob/main/CHANGELOG.md" +end diff --git a/lib/prism/relocation.rb b/lib/prism/relocation.rb new file mode 100644 index 00000000000000..3e9210a7853431 --- /dev/null +++ b/lib/prism/relocation.rb @@ -0,0 +1,505 @@ +# frozen_string_literal: true +# :markup: markdown + +module Prism + # Prism parses deterministically for the same input. This provides a nice + # property that is exposed through the #node_id API on nodes. Effectively this + # means that for the same input, these values will remain consistent every + # time the source is parsed. This means we can reparse the source same with a + # #node_id value and find the exact same node again. + # + # The Relocation module provides an API around this property. It allows you to + # "save" nodes and locations using a minimal amount of memory (just the + # node_id and a field identifier) and then reify them later. + module Relocation + # An entry in a repository that will lazily reify its values when they are + # first accessed. + class Entry + # Raised if a value that could potentially be on an entry is missing + # because it was either not configured on the repository or it has not yet + # been fetched. + class MissingValueError < StandardError + end + + # Initialize a new entry with the given repository. + def initialize(repository) + @repository = repository + @values = nil + end + + # Fetch the filepath of the value. + def filepath + fetch_value(:filepath) + end + + # Fetch the start line of the value. + def start_line + fetch_value(:start_line) + end + + # Fetch the end line of the value. + def end_line + fetch_value(:end_line) + end + + # Fetch the start byte offset of the value. + def start_offset + fetch_value(:start_offset) + end + + # Fetch the end byte offset of the value. + def end_offset + fetch_value(:end_offset) + end + + # Fetch the start character offset of the value. + def start_character_offset + fetch_value(:start_character_offset) + end + + # Fetch the end character offset of the value. + def end_character_offset + fetch_value(:end_character_offset) + end + + # Fetch the start code units offset of the value, for the encoding that + # was configured on the repository. + def start_code_units_offset + fetch_value(:start_code_units_offset) + end + + # Fetch the end code units offset of the value, for the encoding that was + # configured on the repository. + def end_code_units_offset + fetch_value(:end_code_units_offset) + end + + # Fetch the start byte column of the value. + def start_column + fetch_value(:start_column) + end + + # Fetch the end byte column of the value. + def end_column + fetch_value(:end_column) + end + + # Fetch the start character column of the value. + def start_character_column + fetch_value(:start_character_column) + end + + # Fetch the end character column of the value. + def end_character_column + fetch_value(:end_character_column) + end + + # Fetch the start code units column of the value, for the encoding that + # was configured on the repository. + def start_code_units_column + fetch_value(:start_code_units_column) + end + + # Fetch the end code units column of the value, for the encoding that was + # configured on the repository. + def end_code_units_column + fetch_value(:end_code_units_column) + end + + # Fetch the leading comments of the value. + def leading_comments + fetch_value(:leading_comments) + end + + # Fetch the trailing comments of the value. + def trailing_comments + fetch_value(:trailing_comments) + end + + # Fetch the leading and trailing comments of the value. + def comments + leading_comments.concat(trailing_comments) + end + + # Reify the values on this entry with the given values. This is an + # internal-only API that is called from the repository when it is time to + # reify the values. + def reify!(values) # :nodoc: + @repository = nil + @values = values + end + + private + + # Fetch a value from the entry, raising an error if it is missing. + def fetch_value(name) + values.fetch(name) do + raise MissingValueError, "No value for #{name}, make sure the " \ + "repository has been properly configured" + end + end + + # Return the values from the repository, reifying them if necessary. + def values + @values || (@repository.reify!; @values) + end + end + + # Represents the source of a repository that will be reparsed. + class Source + # The value that will need to be reparsed. + attr_reader :value + + # Initialize the source with the given value. + def initialize(value) + @value = value + end + + # Reparse the value and return the parse result. + def result + raise NotImplementedError, "Subclasses must implement #result" + end + + # Create a code units cache for the given encoding. + def code_units_cache(encoding) + result.code_units_cache(encoding) + end + end + + # A source that is represented by a file path. + class SourceFilepath < Source + # Reparse the file and return the parse result. + def result + Prism.parse_file(value) + end + end + + # A source that is represented by a string. + class SourceString < Source + # Reparse the string and return the parse result. + def result + Prism.parse(value) + end + end + + # A field that represents the file path. + class FilepathField + # The file path that this field represents. + attr_reader :value + + # Initialize a new field with the given file path. + def initialize(value) + @value = value + end + + # Fetch the file path. + def fields(_value) + { filepath: value } + end + end + + # A field representing the start and end lines. + class LinesField + # Fetches the start and end line of a value. + def fields(value) + { start_line: value.start_line, end_line: value.end_line } + end + end + + # A field representing the start and end byte offsets. + class OffsetsField + # Fetches the start and end byte offset of a value. + def fields(value) + { start_offset: value.start_offset, end_offset: value.end_offset } + end + end + + # A field representing the start and end character offsets. + class CharacterOffsetsField + # Fetches the start and end character offset of a value. + def fields(value) + { + start_character_offset: value.start_character_offset, + end_character_offset: value.end_character_offset + } + end + end + + # A field representing the start and end code unit offsets. + class CodeUnitOffsetsField + # A pointer to the repository object that is used for lazily creating a + # code units cache. + attr_reader :repository + + # The associated encoding for the code units. + attr_reader :encoding + + # Initialize a new field with the associated repository and encoding. + def initialize(repository, encoding) + @repository = repository + @encoding = encoding + @cache = nil + end + + # Fetches the start and end code units offset of a value for a particular + # encoding. + def fields(value) + { + start_code_units_offset: value.cached_start_code_units_offset(cache), + end_code_units_offset: value.cached_end_code_units_offset(cache) + } + end + + private + + # Lazily create a code units cache for the associated encoding. + def cache + @cache ||= repository.code_units_cache(encoding) + end + end + + # A field representing the start and end byte columns. + class ColumnsField + # Fetches the start and end byte column of a value. + def fields(value) + { start_column: value.start_column, end_column: value.end_column } + end + end + + # A field representing the start and end character columns. + class CharacterColumnsField + # Fetches the start and end character column of a value. + def fields(value) + { + start_character_column: value.start_character_column, + end_character_column: value.end_character_column + } + end + end + + # A field representing the start and end code unit columns for a specific + # encoding. + class CodeUnitColumnsField + # The repository object that is used for lazily creating a code units + # cache. + attr_reader :repository + + # The associated encoding for the code units. + attr_reader :encoding + + # Initialize a new field with the associated repository and encoding. + def initialize(repository, encoding) + @repository = repository + @encoding = encoding + @cache = nil + end + + # Fetches the start and end code units column of a value for a particular + # encoding. + def fields(value) + { + start_code_units_column: value.cached_start_code_units_column(cache), + end_code_units_column: value.cached_end_code_units_column(cache) + } + end + + private + + # Lazily create a code units cache for the associated encoding. + def cache + @cache ||= repository.code_units_cache(encoding) + end + end + + # An abstract field used as the parent class of the two comments fields. + class CommentsField + # An object that represents a slice of a comment. + class Comment + # The slice of the comment. + attr_reader :slice + + # Initialize a new comment with the given slice. + def initialize(slice) + @slice = slice + end + end + + private + + # Create comment objects from the given values. + def comments(values) + values.map { |value| Comment.new(value.slice) } + end + end + + # A field representing the leading comments. + class LeadingCommentsField < CommentsField + # Fetches the leading comments of a value. + def fields(value) + { leading_comments: comments(value.leading_comments) } + end + end + + # A field representing the trailing comments. + class TrailingCommentsField < CommentsField + # Fetches the trailing comments of a value. + def fields(value) + { trailing_comments: comments(value.trailing_comments) } + end + end + + # A repository is a configured collection of fields and a set of entries + # that knows how to reparse a source and reify the values. + class Repository + # Raised when multiple fields of the same type are configured on the same + # repository. + class ConfigurationError < StandardError + end + + # The source associated with this repository. This will be either a + # SourceFilepath (the most common use case) or a SourceString. + attr_reader :source + + # The fields that have been configured on this repository. + attr_reader :fields + + # The entries that have been saved on this repository. + attr_reader :entries + + # Initialize a new repository with the given source. + def initialize(source) + @source = source + @fields = {} + @entries = Hash.new { |hash, node_id| hash[node_id] = {} } + end + + # Create a code units cache for the given encoding from the source. + def code_units_cache(encoding) + source.code_units_cache(encoding) + end + + # Configure the filepath field for this repository and return self. + def filepath + raise ConfigurationError, "Can only specify filepath for a filepath source" unless source.is_a?(SourceFilepath) + field(:filepath, FilepathField.new(source.value)) + end + + # Configure the lines field for this repository and return self. + def lines + field(:lines, LinesField.new) + end + + # Configure the offsets field for this repository and return self. + def offsets + field(:offsets, OffsetsField.new) + end + + # Configure the character offsets field for this repository and return + # self. + def character_offsets + field(:character_offsets, CharacterOffsetsField.new) + end + + # Configure the code unit offsets field for this repository for a specific + # encoding and return self. + def code_unit_offsets(encoding) + field(:code_unit_offsets, CodeUnitOffsetsField.new(self, encoding)) + end + + # Configure the columns field for this repository and return self. + def columns + field(:columns, ColumnsField.new) + end + + # Configure the character columns field for this repository and return + # self. + def character_columns + field(:character_columns, CharacterColumnsField.new) + end + + # Configure the code unit columns field for this repository for a specific + # encoding and return self. + def code_unit_columns(encoding) + field(:code_unit_columns, CodeUnitColumnsField.new(self, encoding)) + end + + # Configure the leading comments field for this repository and return + # self. + def leading_comments + field(:leading_comments, LeadingCommentsField.new) + end + + # Configure the trailing comments field for this repository and return + # self. + def trailing_comments + field(:trailing_comments, TrailingCommentsField.new) + end + + # Configure both the leading and trailing comment fields for this + # repository and return self. + def comments + leading_comments.trailing_comments + end + + # This method is called from nodes and locations when they want to enter + # themselves into the repository. It it internal-only and meant to be + # called from the #save* APIs. + def enter(node_id, field_name) # :nodoc: + entry = Entry.new(self) + @entries[node_id][field_name] = entry + entry + end + + # This method is called from the entries in the repository when they need + # to reify their values. It is internal-only and meant to be called from + # the various value APIs. + def reify! # :nodoc: + result = source.result + + # Attach the comments if they have been requested as part of the + # configuration of this repository. + if fields.key?(:leading_comments) || fields.key?(:trailing_comments) + result.attach_comments! + end + + queue = [result.value] #: Array[Prism::node] + while (node = queue.shift) + @entries[node.node_id].each do |field_name, entry| + value = node.public_send(field_name) + values = {} #: Hash[Symbol, untyped] + + fields.each_value do |field| + values.merge!(field.fields(value)) + end + + entry.reify!(values) + end + + queue.concat(node.compact_child_nodes) + end + + @entries.clear + end + + private + + # Append the given field to the repository and return the repository so + # that these calls can be chained. + def field(name, value) + raise ConfigurationError, "Cannot specify multiple #{name} fields" if @fields.key?(name) + @fields[name] = value + self + end + end + + # Create a new repository for the given filepath. + def self.filepath(value) + Repository.new(SourceFilepath.new(value)) + end + + # Create a new repository for the given string. + def self.string(value) + Repository.new(SourceString.new(value)) + end + end +end diff --git a/lib/prism/string_query.rb b/lib/prism/string_query.rb new file mode 100644 index 00000000000000..547f58d2fa6c92 --- /dev/null +++ b/lib/prism/string_query.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true +# :markup: markdown + +module Prism + # Query methods that allow categorizing strings based on their context for + # where they could be valid in a Ruby syntax tree. + class StringQuery + # The string that this query is wrapping. + attr_reader :string + + # Initialize a new query with the given string. + def initialize(string) + @string = string + end + + # Whether or not this string is a valid local variable name. + def local? + StringQuery.local?(string) + end + + # Whether or not this string is a valid constant name. + def constant? + StringQuery.constant?(string) + end + + # Whether or not this string is a valid method name. + def method_name? + StringQuery.method_name?(string) + end + end +end diff --git a/lib/prism/translation.rb b/lib/prism/translation.rb new file mode 100644 index 00000000000000..d127f2006c59f2 --- /dev/null +++ b/lib/prism/translation.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true +# :markup: markdown + +module Prism + # This module is responsible for converting the prism syntax tree into other + # syntax trees. + module Translation # steep:ignore + autoload :Parser, "prism/translation/parser" + autoload :ParserCurrent, "prism/translation/parser_current" + autoload :Parser33, "prism/translation/parser33" + autoload :Parser34, "prism/translation/parser34" + autoload :Parser35, "prism/translation/parser35" + autoload :Ripper, "prism/translation/ripper" + autoload :RubyParser, "prism/translation/ruby_parser" + end +end diff --git a/lib/prism/translation/parser.rb b/lib/prism/translation/parser.rb new file mode 100644 index 00000000000000..a7888f77ecced1 --- /dev/null +++ b/lib/prism/translation/parser.rb @@ -0,0 +1,367 @@ +# frozen_string_literal: true +# :markup: markdown + +begin + required_version = ">= 3.3.7.2" + gem "parser", required_version + require "parser" +rescue LoadError + warn(<<~MSG) + Error: Unable to load parser #{required_version}. \ + Add `gem "parser"` to your Gemfile or run `bundle update parser`. + MSG + exit(1) +end + +module Prism + module Translation + # This class is the entry-point for converting a prism syntax tree into the + # whitequark/parser gem's syntax tree. It inherits from the base parser for + # the parser gem, and overrides the parse* methods to parse with prism and + # then translate. + class Parser < ::Parser::Base + Diagnostic = ::Parser::Diagnostic # :nodoc: + private_constant :Diagnostic + + # The parser gem has a list of diagnostics with a hard-coded set of error + # messages. We create our own diagnostic class in order to set our own + # error messages. + class PrismDiagnostic < Diagnostic + # This is the cached message coming from prism. + attr_reader :message + + # Initialize a new diagnostic with the given message and location. + def initialize(message, level, reason, location) + @message = message + super(level, reason, {}, location, []) + end + end + + Racc_debug_parser = false # :nodoc: + + # The `builder` argument is used to create the parser using our custom builder class by default. + # + # By using the `:parser` keyword argument, you can translate in a way that is compatible with + # the Parser gem using any parser. + # + # For example, in RuboCop for Ruby LSP, the following approach can be used to improve performance + # by reusing a pre-parsed `Prism::ParseLexResult`: + # + # class PrismPreparsed + # def initialize(prism_result) + # @prism_result = prism_result + # end + # + # def parse_lex(source, **options) + # @prism_result + # end + # end + # + # prism_preparsed = PrismPreparsed.new(prism_result) + # + # Prism::Translation::Ruby34.new(builder, parser: prism_preparsed) + # + # In an object passed to the `:parser` keyword argument, the `parse` and `parse_lex` methods + # should be implemented as needed. + # + def initialize(builder = Prism::Translation::Parser::Builder.new, parser: Prism) + if !builder.is_a?(Prism::Translation::Parser::Builder) + warn(<<~MSG, uplevel: 1, category: :deprecated) + [deprecation]: The builder passed to `Prism::Translation::Parser.new` is not a \ + `Prism::Translation::Parser::Builder` subclass. This will raise in the next major version. + MSG + end + @parser = parser + + super(builder) + end + + def version # :nodoc: + 34 + end + + # The default encoding for Ruby files is UTF-8. + def default_encoding + Encoding::UTF_8 + end + + def yyerror # :nodoc: + end + + # Parses a source buffer and returns the AST. + def parse(source_buffer) + @source_buffer = source_buffer + source = source_buffer.source + + offset_cache = build_offset_cache(source) + result = unwrap(@parser.parse(source, **prism_options), offset_cache) + + build_ast(result.value, offset_cache) + ensure + @source_buffer = nil + end + + # Parses a source buffer and returns the AST and the source code comments. + def parse_with_comments(source_buffer) + @source_buffer = source_buffer + source = source_buffer.source + + offset_cache = build_offset_cache(source) + result = unwrap(@parser.parse(source, **prism_options), offset_cache) + + [ + build_ast(result.value, offset_cache), + build_comments(result.comments, offset_cache) + ] + ensure + @source_buffer = nil + end + + # Parses a source buffer and returns the AST, the source code comments, + # and the tokens emitted by the lexer. + def tokenize(source_buffer, recover = false) + @source_buffer = source_buffer + source = source_buffer.source + + offset_cache = build_offset_cache(source) + result = + begin + unwrap(@parser.parse_lex(source, **prism_options), offset_cache) + rescue ::Parser::SyntaxError + raise if !recover + end + + program, tokens = result.value + ast = build_ast(program, offset_cache) if result.success? + + [ + ast, + build_comments(result.comments, offset_cache), + build_tokens(tokens, offset_cache) + ] + ensure + @source_buffer = nil + end + + # Since prism resolves num params for us, we don't need to support this + # kind of logic here. + def try_declare_numparam(node) + node.children[0].match?(/\A_[1-9]\z/) + end + + private + + # This is a hook to allow consumers to disable some errors if they don't + # want them to block creating the syntax tree. + def valid_error?(error) + true + end + + # This is a hook to allow consumers to disable some warnings if they don't + # want them to block creating the syntax tree. + def valid_warning?(warning) + true + end + + # Build a diagnostic from the given prism parse error. + def error_diagnostic(error, offset_cache) + location = error.location + diagnostic_location = build_range(location, offset_cache) + + case error.type + when :argument_block_multi + Diagnostic.new(:error, :block_and_blockarg, {}, diagnostic_location, []) + when :argument_formal_constant + Diagnostic.new(:error, :argument_const, {}, diagnostic_location, []) + when :argument_formal_class + Diagnostic.new(:error, :argument_cvar, {}, diagnostic_location, []) + when :argument_formal_global + Diagnostic.new(:error, :argument_gvar, {}, diagnostic_location, []) + when :argument_formal_ivar + Diagnostic.new(:error, :argument_ivar, {}, diagnostic_location, []) + when :argument_no_forwarding_amp + Diagnostic.new(:error, :no_anonymous_blockarg, {}, diagnostic_location, []) + when :argument_no_forwarding_star + Diagnostic.new(:error, :no_anonymous_restarg, {}, diagnostic_location, []) + when :argument_no_forwarding_star_star + Diagnostic.new(:error, :no_anonymous_kwrestarg, {}, diagnostic_location, []) + when :begin_lonely_else + location = location.copy(length: 4) + diagnostic_location = build_range(location, offset_cache) + Diagnostic.new(:error, :useless_else, {}, diagnostic_location, []) + when :class_name, :module_name + Diagnostic.new(:error, :module_name_const, {}, diagnostic_location, []) + when :class_in_method + Diagnostic.new(:error, :class_in_def, {}, diagnostic_location, []) + when :def_endless_setter + Diagnostic.new(:error, :endless_setter, {}, diagnostic_location, []) + when :embdoc_term + Diagnostic.new(:error, :embedded_document, {}, diagnostic_location, []) + when :incomplete_variable_class, :incomplete_variable_class_3_3 + location = location.copy(length: location.length + 1) + diagnostic_location = build_range(location, offset_cache) + + Diagnostic.new(:error, :cvar_name, { name: location.slice }, diagnostic_location, []) + when :incomplete_variable_instance, :incomplete_variable_instance_3_3 + location = location.copy(length: location.length + 1) + diagnostic_location = build_range(location, offset_cache) + + Diagnostic.new(:error, :ivar_name, { name: location.slice }, diagnostic_location, []) + when :invalid_variable_global, :invalid_variable_global_3_3 + Diagnostic.new(:error, :gvar_name, { name: location.slice }, diagnostic_location, []) + when :module_in_method + Diagnostic.new(:error, :module_in_def, {}, diagnostic_location, []) + when :numbered_parameter_ordinary + Diagnostic.new(:error, :ordinary_param_defined, {}, diagnostic_location, []) + when :numbered_parameter_outer_scope + Diagnostic.new(:error, :numparam_used_in_outer_scope, {}, diagnostic_location, []) + when :parameter_circular + Diagnostic.new(:error, :circular_argument_reference, { var_name: location.slice }, diagnostic_location, []) + when :parameter_name_repeat + Diagnostic.new(:error, :duplicate_argument, {}, diagnostic_location, []) + when :parameter_numbered_reserved + Diagnostic.new(:error, :reserved_for_numparam, { name: location.slice }, diagnostic_location, []) + when :regexp_unknown_options + Diagnostic.new(:error, :regexp_options, { options: location.slice[1..] }, diagnostic_location, []) + when :singleton_for_literals + Diagnostic.new(:error, :singleton_literal, {}, diagnostic_location, []) + when :string_literal_eof + Diagnostic.new(:error, :string_eof, {}, diagnostic_location, []) + when :unexpected_token_ignore + Diagnostic.new(:error, :unexpected_token, { token: location.slice }, diagnostic_location, []) + when :write_target_in_method + Diagnostic.new(:error, :dynamic_const, {}, diagnostic_location, []) + else + PrismDiagnostic.new(error.message, :error, error.type, diagnostic_location) + end + end + + # Build a diagnostic from the given prism parse warning. + def warning_diagnostic(warning, offset_cache) + diagnostic_location = build_range(warning.location, offset_cache) + + case warning.type + when :ambiguous_first_argument_plus + Diagnostic.new(:warning, :ambiguous_prefix, { prefix: "+" }, diagnostic_location, []) + when :ambiguous_first_argument_minus + Diagnostic.new(:warning, :ambiguous_prefix, { prefix: "-" }, diagnostic_location, []) + when :ambiguous_prefix_ampersand + Diagnostic.new(:warning, :ambiguous_prefix, { prefix: "&" }, diagnostic_location, []) + when :ambiguous_prefix_star + Diagnostic.new(:warning, :ambiguous_prefix, { prefix: "*" }, diagnostic_location, []) + when :ambiguous_prefix_star_star + Diagnostic.new(:warning, :ambiguous_prefix, { prefix: "**" }, diagnostic_location, []) + when :ambiguous_slash + Diagnostic.new(:warning, :ambiguous_regexp, {}, diagnostic_location, []) + when :dot_dot_dot_eol + Diagnostic.new(:warning, :triple_dot_at_eol, {}, diagnostic_location, []) + when :duplicated_hash_key + # skip, parser does this on its own + else + PrismDiagnostic.new(warning.message, :warning, warning.type, diagnostic_location) + end + end + + # If there was a error generated during the parse, then raise an + # appropriate syntax error. Otherwise return the result. + def unwrap(result, offset_cache) + result.errors.each do |error| + next unless valid_error?(error) + diagnostics.process(error_diagnostic(error, offset_cache)) + end + + result.warnings.each do |warning| + next unless valid_warning?(warning) + diagnostic = warning_diagnostic(warning, offset_cache) + diagnostics.process(diagnostic) if diagnostic + end + + result + end + + # Prism deals with offsets in bytes, while the parser gem deals with + # offsets in characters. We need to handle this conversion in order to + # build the parser gem AST. + # + # If the bytesize of the source is the same as the length, then we can + # just use the offset directly. Otherwise, we build an array where the + # index is the byte offset and the value is the character offset. + def build_offset_cache(source) + if source.bytesize == source.length + -> (offset) { offset } + else + offset_cache = [] + offset = 0 + + source.each_char do |char| + char.bytesize.times { offset_cache << offset } + offset += 1 + end + + offset_cache << offset + end + end + + # Build the parser gem AST from the prism AST. + def build_ast(program, offset_cache) + program.accept(Compiler.new(self, offset_cache)) + end + + # Build the parser gem comments from the prism comments. + def build_comments(comments, offset_cache) + comments.map do |comment| + ::Parser::Source::Comment.new(build_range(comment.location, offset_cache)) + end + end + + # Build the parser gem tokens from the prism tokens. + def build_tokens(tokens, offset_cache) + Lexer.new(source_buffer, tokens, offset_cache).to_a + end + + # Build a range from a prism location. + def build_range(location, offset_cache) + ::Parser::Source::Range.new( + source_buffer, + offset_cache[location.start_offset], + offset_cache[location.end_offset] + ) + end + + # Options for how prism should parse/lex the source. + def prism_options + options = { + filepath: @source_buffer.name, + version: convert_for_prism(version), + partial_script: true, + } + # The parser gem always encodes to UTF-8, unless it is binary. + # https://github.com/whitequark/parser/blob/v3.3.6.0/lib/parser/source/buffer.rb#L80-L107 + options[:encoding] = false if @source_buffer.source.encoding != Encoding::BINARY + + options + end + + # Converts the version format handled by Parser to the format handled by Prism. + def convert_for_prism(version) + case version + when 33 + "3.3.1" + when 34 + "3.4.0" + when 35 + "3.5.0" + else + "latest" + end + end + + require_relative "parser/builder" + require_relative "parser/compiler" + require_relative "parser/lexer" + + private_constant :Compiler + private_constant :Lexer + end + end +end diff --git a/lib/prism/translation/parser/builder.rb b/lib/prism/translation/parser/builder.rb new file mode 100644 index 00000000000000..6b620c25bc9658 --- /dev/null +++ b/lib/prism/translation/parser/builder.rb @@ -0,0 +1,62 @@ +# frozen_string_literal: true +# :markup: markdown + +module Prism + module Translation + class Parser + # A builder that knows how to convert more modern Ruby syntax + # into whitequark/parser gem's syntax tree. + class Builder < ::Parser::Builders::Default + # It represents the `it` block argument, which is not yet implemented in the Parser gem. + def itarg + n(:itarg, [:it], nil) + end + + # The following three lines have been added to support the `it` block parameter syntax in the source code below. + # + # if args.type == :itarg + # block_type = :itblock + # args = :it + # + # https://github.com/whitequark/parser/blob/v3.3.7.1/lib/parser/builders/default.rb#L1122-L1155 + def block(method_call, begin_t, args, body, end_t) + _receiver, _selector, *call_args = *method_call + + if method_call.type == :yield + diagnostic :error, :block_given_to_yield, nil, method_call.loc.keyword, [loc(begin_t)] + end + + last_arg = call_args.last + if last_arg && (last_arg.type == :block_pass || last_arg.type == :forwarded_args) + diagnostic :error, :block_and_blockarg, nil, last_arg.loc.expression, [loc(begin_t)] + end + + if args.type == :itarg + block_type = :itblock + args = :it + elsif args.type == :numargs + block_type = :numblock + args = args.children[0] + else + block_type = :block + end + + if [:send, :csend, :index, :super, :zsuper, :lambda].include?(method_call.type) + n(block_type, [ method_call, args, body ], + block_map(method_call.loc.expression, begin_t, end_t)) + else + # Code like "return foo 1 do end" is reduced in a weird sequence. + # Here, method_call is actually (return). + actual_send, = *method_call + block = + n(block_type, [ actual_send, args, body ], + block_map(actual_send.loc.expression, begin_t, end_t)) + + n(method_call.type, [ block ], + method_call.loc.with_expression(join_exprs(method_call, block))) + end + end + end + end + end +end diff --git a/lib/prism/translation/parser/compiler.rb b/lib/prism/translation/parser/compiler.rb new file mode 100644 index 00000000000000..6e0618890de6a7 --- /dev/null +++ b/lib/prism/translation/parser/compiler.rb @@ -0,0 +1,2234 @@ +# frozen_string_literal: true +# :markup: markdown + +module Prism + module Translation + class Parser + # A visitor that knows how to convert a prism syntax tree into the + # whitequark/parser gem's syntax tree. + class Compiler < ::Prism::Compiler + # Raised when the tree is malformed or there is a bug in the compiler. + class CompilationError < StandardError + end + + # The Parser::Base instance that is being used to build the AST. + attr_reader :parser + + # The Parser::Builders::Default instance that is being used to build the + # AST. + attr_reader :builder + + # The Parser::Source::Buffer instance that is holding a reference to the + # source code. + attr_reader :source_buffer + + # The offset cache that is used to map between byte and character + # offsets in the file. + attr_reader :offset_cache + + # The types of values that can be forwarded in the current scope. + attr_reader :forwarding + + # Whether or not the current node is in a destructure. + attr_reader :in_destructure + + # Whether or not the current node is in a pattern. + attr_reader :in_pattern + + # Initialize a new compiler with the given parser, offset cache, and + # options. + def initialize(parser, offset_cache, forwarding: [], in_destructure: false, in_pattern: false) + @parser = parser + @builder = parser.builder + @source_buffer = parser.source_buffer + @offset_cache = offset_cache + + @forwarding = forwarding + @in_destructure = in_destructure + @in_pattern = in_pattern + end + + # alias foo bar + # ^^^^^^^^^^^^^ + def visit_alias_method_node(node) + builder.alias(token(node.keyword_loc), visit(node.new_name), visit(node.old_name)) + end + + # alias $foo $bar + # ^^^^^^^^^^^^^^^ + def visit_alias_global_variable_node(node) + builder.alias(token(node.keyword_loc), visit(node.new_name), visit(node.old_name)) + end + + # foo => bar | baz + # ^^^^^^^^^ + def visit_alternation_pattern_node(node) + builder.match_alt(visit(node.left), token(node.operator_loc), visit(node.right)) + end + + # a and b + # ^^^^^^^ + def visit_and_node(node) + builder.logical_op(:and, visit(node.left), token(node.operator_loc), visit(node.right)) + end + + # [] + # ^^ + def visit_array_node(node) + if node.opening&.start_with?("%w", "%W", "%i", "%I") + elements = node.elements.flat_map do |element| + if element.is_a?(StringNode) + if element.content.include?("\n") + string_nodes_from_line_continuations(element.unescaped, element.content, element.content_loc.start_offset, node.opening) + else + [builder.string_internal([element.unescaped, srange(element.content_loc)])] + end + elsif element.is_a?(InterpolatedStringNode) + builder.string_compose( + token(element.opening_loc), + string_nodes_from_interpolation(element, node.opening), + token(element.closing_loc) + ) + else + [visit(element)] + end + end + else + elements = visit_all(node.elements) + end + + builder.array(token(node.opening_loc), elements, token(node.closing_loc)) + end + + # foo => [bar] + # ^^^^^ + def visit_array_pattern_node(node) + elements = [*node.requireds] + elements << node.rest if !node.rest.nil? && !node.rest.is_a?(ImplicitRestNode) + elements.concat(node.posts) + visited = visit_all(elements) + + if node.rest.is_a?(ImplicitRestNode) + visited[-1] = builder.match_with_trailing_comma(visited[-1], token(node.rest.location)) + end + + if node.constant + if visited.empty? + builder.const_pattern(visit(node.constant), token(node.opening_loc), builder.array_pattern(token(node.opening_loc), visited, token(node.closing_loc)), token(node.closing_loc)) + else + builder.const_pattern(visit(node.constant), token(node.opening_loc), builder.array_pattern(nil, visited, nil), token(node.closing_loc)) + end + else + builder.array_pattern(token(node.opening_loc), visited, token(node.closing_loc)) + end + end + + # foo(bar) + # ^^^ + def visit_arguments_node(node) + visit_all(node.arguments) + end + + # { a: 1 } + # ^^^^ + def visit_assoc_node(node) + key = node.key + + if node.value.is_a?(ImplicitNode) + if in_pattern + if key.is_a?(SymbolNode) + if key.opening.nil? + builder.match_hash_var([key.unescaped, srange(key.location)]) + else + builder.match_hash_var_from_str(token(key.opening_loc), [builder.string_internal([key.unescaped, srange(key.value_loc)])], token(key.closing_loc)) + end + else + builder.match_hash_var_from_str(token(key.opening_loc), visit_all(key.parts), token(key.closing_loc)) + end + else + value = node.value.value + + implicit_value = if value.is_a?(CallNode) + builder.call_method(nil, nil, [value.name, srange(value.message_loc)]) + elsif value.is_a?(ConstantReadNode) + builder.const([value.name, srange(key.value_loc)]) + else + builder.ident([value.name, srange(key.value_loc)]).updated(:lvar) + end + + builder.pair_keyword([key.unescaped, srange(key)], implicit_value) + end + elsif node.operator_loc + builder.pair(visit(key), token(node.operator_loc), visit(node.value)) + elsif key.is_a?(SymbolNode) && key.opening_loc.nil? + builder.pair_keyword([key.unescaped, srange(key.location)], visit(node.value)) + else + parts = + if key.is_a?(SymbolNode) + [builder.string_internal([key.unescaped, srange(key.value_loc)])] + else + visit_all(key.parts) + end + + builder.pair_quoted(token(key.opening_loc), parts, token(key.closing_loc), visit(node.value)) + end + end + + # def foo(**); bar(**); end + # ^^ + # + # { **foo } + # ^^^^^ + def visit_assoc_splat_node(node) + if in_pattern + builder.match_rest(token(node.operator_loc), token(node.value&.location)) + elsif node.value.nil? && forwarding.include?(:**) + builder.forwarded_kwrestarg(token(node.operator_loc)) + else + builder.kwsplat(token(node.operator_loc), visit(node.value)) + end + end + + # $+ + # ^^ + def visit_back_reference_read_node(node) + builder.back_ref(token(node.location)) + end + + # begin end + # ^^^^^^^^^ + def visit_begin_node(node) + rescue_bodies = [] + + if (rescue_clause = node.rescue_clause) + begin + find_start_offset = (rescue_clause.reference&.location || rescue_clause.exceptions.last&.location || rescue_clause.keyword_loc).end_offset + find_end_offset = ( + rescue_clause.statements&.location&.start_offset || + rescue_clause.subsequent&.location&.start_offset || + node.else_clause&.location&.start_offset || + node.ensure_clause&.location&.start_offset || + node.end_keyword_loc&.start_offset || + find_start_offset + 1 + ) + + rescue_bodies << builder.rescue_body( + token(rescue_clause.keyword_loc), + rescue_clause.exceptions.any? ? builder.array(nil, visit_all(rescue_clause.exceptions), nil) : nil, + token(rescue_clause.operator_loc), + visit(rescue_clause.reference), + srange_find(find_start_offset, find_end_offset, ";"), + visit(rescue_clause.statements) + ) + end until (rescue_clause = rescue_clause.subsequent).nil? + end + + begin_body = + builder.begin_body( + visit(node.statements), + rescue_bodies, + token(node.else_clause&.else_keyword_loc), + visit(node.else_clause), + token(node.ensure_clause&.ensure_keyword_loc), + visit(node.ensure_clause&.statements) + ) + + if node.begin_keyword_loc + builder.begin_keyword(token(node.begin_keyword_loc), begin_body, token(node.end_keyword_loc)) + else + begin_body + end + end + + # foo(&bar) + # ^^^^ + def visit_block_argument_node(node) + builder.block_pass(token(node.operator_loc), visit(node.expression)) + end + + # foo { |; bar| } + # ^^^ + def visit_block_local_variable_node(node) + builder.shadowarg(token(node.location)) + end + + # A block on a keyword or method call. + def visit_block_node(node) + raise CompilationError, "Cannot directly compile block nodes" + end + + # def foo(&bar); end + # ^^^^ + def visit_block_parameter_node(node) + builder.blockarg(token(node.operator_loc), token(node.name_loc)) + end + + # A block's parameters. + def visit_block_parameters_node(node) + [*visit(node.parameters)].concat(visit_all(node.locals)) + end + + # break + # ^^^^^ + # + # break foo + # ^^^^^^^^^ + def visit_break_node(node) + builder.keyword_cmd(:break, token(node.keyword_loc), nil, visit(node.arguments) || [], nil) + end + + # foo + # ^^^ + # + # foo.bar + # ^^^^^^^ + # + # foo.bar() {} + # ^^^^^^^^^^^^ + def visit_call_node(node) + name = node.name + arguments = node.arguments&.arguments || [] + block = node.block + + if block.is_a?(BlockArgumentNode) + arguments = [*arguments, block] + block = nil + end + + if node.call_operator_loc.nil? + case name + when :-@ + case (receiver = node.receiver).type + when :integer_node, :float_node, :rational_node, :imaginary_node + return visit(numeric_negate(node.message_loc, receiver)) + end + when :! + return visit_block(builder.not_op(token(node.message_loc), token(node.opening_loc), visit(node.receiver), token(node.closing_loc)), block) + when :=~ + if (receiver = node.receiver).is_a?(RegularExpressionNode) + return builder.match_op(visit(receiver), token(node.message_loc), visit(node.arguments.arguments.first)) + end + when :[] + return visit_block(builder.index(visit(node.receiver), token(node.opening_loc), visit_all(arguments), token(node.closing_loc)), block) + when :[]= + if node.message != "[]=" && node.arguments && block.nil? && !node.safe_navigation? + arguments = node.arguments.arguments[...-1] + arguments << node.block if node.block + + return visit_block( + builder.assign( + builder.index_asgn( + visit(node.receiver), + token(node.opening_loc), + visit_all(arguments), + token(node.closing_loc), + ), + srange_find(node.message_loc.end_offset, node.arguments.arguments.last.location.start_offset, "="), + visit(node.arguments.arguments.last) + ), + block + ) + end + end + end + + message_loc = node.message_loc + call_operator_loc = node.call_operator_loc + call_operator = [{ "." => :dot, "&." => :anddot, "::" => "::" }.fetch(call_operator_loc.slice), srange(call_operator_loc)] if call_operator_loc + + visit_block( + if name.end_with?("=") && !message_loc.slice.end_with?("=") && node.arguments && block.nil? + builder.assign( + builder.attr_asgn(visit(node.receiver), call_operator, token(message_loc)), + srange_find(message_loc.end_offset, node.arguments.location.start_offset, "="), + visit(node.arguments.arguments.last) + ) + else + builder.call_method( + visit(node.receiver), + call_operator, + message_loc ? [node.name, srange(message_loc)] : nil, + token(node.opening_loc), + visit_all(arguments), + token(node.closing_loc) + ) + end, + block + ) + end + + # foo.bar += baz + # ^^^^^^^^^^^^^^^ + def visit_call_operator_write_node(node) + call_operator_loc = node.call_operator_loc + + builder.op_assign( + builder.call_method( + visit(node.receiver), + call_operator_loc.nil? ? nil : [{ "." => :dot, "&." => :anddot, "::" => "::" }.fetch(call_operator_loc.slice), srange(call_operator_loc)], + node.message_loc ? [node.read_name, srange(node.message_loc)] : nil, + nil, + [], + nil + ), + [node.binary_operator_loc.slice.chomp("="), srange(node.binary_operator_loc)], + visit(node.value) + ) + end + + # foo.bar &&= baz + # ^^^^^^^^^^^^^^^ + def visit_call_and_write_node(node) + call_operator_loc = node.call_operator_loc + + builder.op_assign( + builder.call_method( + visit(node.receiver), + call_operator_loc.nil? ? nil : [{ "." => :dot, "&." => :anddot, "::" => "::" }.fetch(call_operator_loc.slice), srange(call_operator_loc)], + node.message_loc ? [node.read_name, srange(node.message_loc)] : nil, + nil, + [], + nil + ), + [node.operator_loc.slice.chomp("="), srange(node.operator_loc)], + visit(node.value) + ) + end + + # foo.bar ||= baz + # ^^^^^^^^^^^^^^^ + def visit_call_or_write_node(node) + call_operator_loc = node.call_operator_loc + + builder.op_assign( + builder.call_method( + visit(node.receiver), + call_operator_loc.nil? ? nil : [{ "." => :dot, "&." => :anddot, "::" => "::" }.fetch(call_operator_loc.slice), srange(call_operator_loc)], + node.message_loc ? [node.read_name, srange(node.message_loc)] : nil, + nil, + [], + nil + ), + [node.operator_loc.slice.chomp("="), srange(node.operator_loc)], + visit(node.value) + ) + end + + # foo.bar, = 1 + # ^^^^^^^ + def visit_call_target_node(node) + call_operator_loc = node.call_operator_loc + + builder.attr_asgn( + visit(node.receiver), + call_operator_loc.nil? ? nil : [{ "." => :dot, "&." => :anddot, "::" => "::" }.fetch(call_operator_loc.slice), srange(call_operator_loc)], + token(node.message_loc) + ) + end + + # foo => bar => baz + # ^^^^^^^^^^ + def visit_capture_pattern_node(node) + builder.match_as(visit(node.value), token(node.operator_loc), visit(node.target)) + end + + # case foo; when bar; end + # ^^^^^^^^^^^^^^^^^^^^^^^ + def visit_case_node(node) + builder.case( + token(node.case_keyword_loc), + visit(node.predicate), + visit_all(node.conditions), + token(node.else_clause&.else_keyword_loc), + visit(node.else_clause), + token(node.end_keyword_loc) + ) + end + + # case foo; in bar; end + # ^^^^^^^^^^^^^^^^^^^^^ + def visit_case_match_node(node) + builder.case_match( + token(node.case_keyword_loc), + visit(node.predicate), + visit_all(node.conditions), + token(node.else_clause&.else_keyword_loc), + visit(node.else_clause), + token(node.end_keyword_loc) + ) + end + + # class Foo; end + # ^^^^^^^^^^^^^^ + def visit_class_node(node) + builder.def_class( + token(node.class_keyword_loc), + visit(node.constant_path), + token(node.inheritance_operator_loc), + visit(node.superclass), + node.body&.accept(copy_compiler(forwarding: [])), + token(node.end_keyword_loc) + ) + end + + # @@foo + # ^^^^^ + def visit_class_variable_read_node(node) + builder.cvar(token(node.location)) + end + + # @@foo = 1 + # ^^^^^^^^^ + def visit_class_variable_write_node(node) + builder.assign( + builder.assignable(builder.cvar(token(node.name_loc))), + token(node.operator_loc), + visit(node.value) + ) + end + + # @@foo += bar + # ^^^^^^^^^^^^ + def visit_class_variable_operator_write_node(node) + builder.op_assign( + builder.assignable(builder.cvar(token(node.name_loc))), + [node.binary_operator_loc.slice.chomp("="), srange(node.binary_operator_loc)], + visit(node.value) + ) + end + + # @@foo &&= bar + # ^^^^^^^^^^^^^ + def visit_class_variable_and_write_node(node) + builder.op_assign( + builder.assignable(builder.cvar(token(node.name_loc))), + [node.operator_loc.slice.chomp("="), srange(node.operator_loc)], + visit(node.value) + ) + end + + # @@foo ||= bar + # ^^^^^^^^^^^^^ + def visit_class_variable_or_write_node(node) + builder.op_assign( + builder.assignable(builder.cvar(token(node.name_loc))), + [node.operator_loc.slice.chomp("="), srange(node.operator_loc)], + visit(node.value) + ) + end + + # @@foo, = bar + # ^^^^^ + def visit_class_variable_target_node(node) + builder.assignable(builder.cvar(token(node.location))) + end + + # Foo + # ^^^ + def visit_constant_read_node(node) + builder.const([node.name, srange(node.location)]) + end + + # Foo = 1 + # ^^^^^^^ + # + # Foo, Bar = 1 + # ^^^ ^^^ + def visit_constant_write_node(node) + builder.assign(builder.assignable(builder.const([node.name, srange(node.name_loc)])), token(node.operator_loc), visit(node.value)) + end + + # Foo += bar + # ^^^^^^^^^^^ + def visit_constant_operator_write_node(node) + builder.op_assign( + builder.assignable(builder.const([node.name, srange(node.name_loc)])), + [node.binary_operator_loc.slice.chomp("="), srange(node.binary_operator_loc)], + visit(node.value) + ) + end + + # Foo &&= bar + # ^^^^^^^^^^^^ + def visit_constant_and_write_node(node) + builder.op_assign( + builder.assignable(builder.const([node.name, srange(node.name_loc)])), + [node.operator_loc.slice.chomp("="), srange(node.operator_loc)], + visit(node.value) + ) + end + + # Foo ||= bar + # ^^^^^^^^^^^^ + def visit_constant_or_write_node(node) + builder.op_assign( + builder.assignable(builder.const([node.name, srange(node.name_loc)])), + [node.operator_loc.slice.chomp("="), srange(node.operator_loc)], + visit(node.value) + ) + end + + # Foo, = bar + # ^^^ + def visit_constant_target_node(node) + builder.assignable(builder.const([node.name, srange(node.location)])) + end + + # Foo::Bar + # ^^^^^^^^ + def visit_constant_path_node(node) + if node.parent.nil? + builder.const_global( + token(node.delimiter_loc), + [node.name, srange(node.name_loc)] + ) + else + builder.const_fetch( + visit(node.parent), + token(node.delimiter_loc), + [node.name, srange(node.name_loc)] + ) + end + end + + # Foo::Bar = 1 + # ^^^^^^^^^^^^ + # + # Foo::Foo, Bar::Bar = 1 + # ^^^^^^^^ ^^^^^^^^ + def visit_constant_path_write_node(node) + builder.assign( + builder.assignable(visit(node.target)), + token(node.operator_loc), + visit(node.value) + ) + end + + # Foo::Bar += baz + # ^^^^^^^^^^^^^^^ + def visit_constant_path_operator_write_node(node) + builder.op_assign( + builder.assignable(visit(node.target)), + [node.binary_operator_loc.slice.chomp("="), srange(node.binary_operator_loc)], + visit(node.value) + ) + end + + # Foo::Bar &&= baz + # ^^^^^^^^^^^^^^^^ + def visit_constant_path_and_write_node(node) + builder.op_assign( + builder.assignable(visit(node.target)), + [node.operator_loc.slice.chomp("="), srange(node.operator_loc)], + visit(node.value) + ) + end + + # Foo::Bar ||= baz + # ^^^^^^^^^^^^^^^^ + def visit_constant_path_or_write_node(node) + builder.op_assign( + builder.assignable(visit(node.target)), + [node.operator_loc.slice.chomp("="), srange(node.operator_loc)], + visit(node.value) + ) + end + + # Foo::Bar, = baz + # ^^^^^^^^ + def visit_constant_path_target_node(node) + builder.assignable(visit_constant_path_node(node)) + end + + # def foo; end + # ^^^^^^^^^^^^ + # + # def self.foo; end + # ^^^^^^^^^^^^^^^^^ + def visit_def_node(node) + if node.equal_loc + if node.receiver + builder.def_endless_singleton( + token(node.def_keyword_loc), + visit(node.receiver.is_a?(ParenthesesNode) ? node.receiver.body : node.receiver), + token(node.operator_loc), + token(node.name_loc), + builder.args(token(node.lparen_loc), visit(node.parameters) || [], token(node.rparen_loc), false), + token(node.equal_loc), + node.body&.accept(copy_compiler(forwarding: find_forwarding(node.parameters))) + ) + else + builder.def_endless_method( + token(node.def_keyword_loc), + token(node.name_loc), + builder.args(token(node.lparen_loc), visit(node.parameters) || [], token(node.rparen_loc), false), + token(node.equal_loc), + node.body&.accept(copy_compiler(forwarding: find_forwarding(node.parameters))) + ) + end + elsif node.receiver + builder.def_singleton( + token(node.def_keyword_loc), + visit(node.receiver.is_a?(ParenthesesNode) ? node.receiver.body : node.receiver), + token(node.operator_loc), + token(node.name_loc), + builder.args(token(node.lparen_loc), visit(node.parameters) || [], token(node.rparen_loc), false), + node.body&.accept(copy_compiler(forwarding: find_forwarding(node.parameters))), + token(node.end_keyword_loc) + ) + else + builder.def_method( + token(node.def_keyword_loc), + token(node.name_loc), + builder.args(token(node.lparen_loc), visit(node.parameters) || [], token(node.rparen_loc), false), + node.body&.accept(copy_compiler(forwarding: find_forwarding(node.parameters))), + token(node.end_keyword_loc) + ) + end + end + + # defined? a + # ^^^^^^^^^^ + # + # defined?(a) + # ^^^^^^^^^^^ + def visit_defined_node(node) + # Very weird circumstances here where something like: + # + # defined? + # (1) + # + # gets parsed in Ruby as having only the `1` expression but in parser + # it gets parsed as having a begin. In this case we need to synthesize + # that begin to match parser's behavior. + if node.lparen_loc && node.keyword_loc.join(node.lparen_loc).slice.include?("\n") + builder.keyword_cmd( + :defined?, + token(node.keyword_loc), + nil, + [ + builder.begin( + token(node.lparen_loc), + visit(node.value), + token(node.rparen_loc) + ) + ], + nil + ) + else + builder.keyword_cmd( + :defined?, + token(node.keyword_loc), + token(node.lparen_loc), + [visit(node.value)], + token(node.rparen_loc) + ) + end + end + + # if foo then bar else baz end + # ^^^^^^^^^^^^ + def visit_else_node(node) + visit(node.statements) + end + + # "foo #{bar}" + # ^^^^^^ + def visit_embedded_statements_node(node) + builder.begin( + token(node.opening_loc), + visit(node.statements), + token(node.closing_loc) + ) + end + + # "foo #@bar" + # ^^^^^ + def visit_embedded_variable_node(node) + visit(node.variable) + end + + # begin; foo; ensure; bar; end + # ^^^^^^^^^^^^ + def visit_ensure_node(node) + raise CompilationError, "Cannot directly compile ensure nodes" + end + + # false + # ^^^^^ + def visit_false_node(node) + builder.false(token(node.location)) + end + + # foo => [*, bar, *] + # ^^^^^^^^^^^ + def visit_find_pattern_node(node) + elements = [node.left, *node.requireds, node.right] + + if node.constant + builder.const_pattern(visit(node.constant), token(node.opening_loc), builder.find_pattern(nil, visit_all(elements), nil), token(node.closing_loc)) + else + builder.find_pattern(token(node.opening_loc), visit_all(elements), token(node.closing_loc)) + end + end + + # 1.0 + # ^^^ + def visit_float_node(node) + visit_numeric(node, builder.float([node.value, srange(node.location)])) + end + + # for foo in bar do end + # ^^^^^^^^^^^^^^^^^^^^^ + def visit_for_node(node) + builder.for( + token(node.for_keyword_loc), + visit(node.index), + token(node.in_keyword_loc), + visit(node.collection), + if (do_keyword_loc = node.do_keyword_loc) + token(do_keyword_loc) + else + srange_find(node.collection.location.end_offset, (node.statements&.location || node.end_keyword_loc).start_offset, ";") + end, + visit(node.statements), + token(node.end_keyword_loc) + ) + end + + # def foo(...); bar(...); end + # ^^^ + def visit_forwarding_arguments_node(node) + builder.forwarded_args(token(node.location)) + end + + # def foo(...); end + # ^^^ + def visit_forwarding_parameter_node(node) + builder.forward_arg(token(node.location)) + end + + # super + # ^^^^^ + # + # super {} + # ^^^^^^^^ + def visit_forwarding_super_node(node) + visit_block( + builder.keyword_cmd( + :zsuper, + ["super", srange_offsets(node.location.start_offset, node.location.start_offset + 5)] + ), + node.block + ) + end + + # $foo + # ^^^^ + def visit_global_variable_read_node(node) + builder.gvar(token(node.location)) + end + + # $foo = 1 + # ^^^^^^^^ + def visit_global_variable_write_node(node) + builder.assign( + builder.assignable(builder.gvar(token(node.name_loc))), + token(node.operator_loc), + visit(node.value) + ) + end + + # $foo += bar + # ^^^^^^^^^^^ + def visit_global_variable_operator_write_node(node) + builder.op_assign( + builder.assignable(builder.gvar(token(node.name_loc))), + [node.binary_operator_loc.slice.chomp("="), srange(node.binary_operator_loc)], + visit(node.value) + ) + end + + # $foo &&= bar + # ^^^^^^^^^^^^ + def visit_global_variable_and_write_node(node) + builder.op_assign( + builder.assignable(builder.gvar(token(node.name_loc))), + [node.operator_loc.slice.chomp("="), srange(node.operator_loc)], + visit(node.value) + ) + end + + # $foo ||= bar + # ^^^^^^^^^^^^ + def visit_global_variable_or_write_node(node) + builder.op_assign( + builder.assignable(builder.gvar(token(node.name_loc))), + [node.operator_loc.slice.chomp("="), srange(node.operator_loc)], + visit(node.value) + ) + end + + # $foo, = bar + # ^^^^ + def visit_global_variable_target_node(node) + builder.assignable(builder.gvar([node.slice, srange(node.location)])) + end + + # {} + # ^^ + def visit_hash_node(node) + builder.associate( + token(node.opening_loc), + visit_all(node.elements), + token(node.closing_loc) + ) + end + + # foo => {} + # ^^ + def visit_hash_pattern_node(node) + elements = [*node.elements, *node.rest] + + if node.constant + builder.const_pattern(visit(node.constant), token(node.opening_loc), builder.hash_pattern(nil, visit_all(elements), nil), token(node.closing_loc)) + else + builder.hash_pattern(token(node.opening_loc), visit_all(elements), token(node.closing_loc)) + end + end + + # if foo then bar end + # ^^^^^^^^^^^^^^^^^^^ + # + # bar if foo + # ^^^^^^^^^^ + # + # foo ? bar : baz + # ^^^^^^^^^^^^^^^ + def visit_if_node(node) + if !node.if_keyword_loc + builder.ternary( + visit(node.predicate), + token(node.then_keyword_loc), + visit(node.statements), + token(node.subsequent.else_keyword_loc), + visit(node.subsequent) + ) + elsif node.if_keyword_loc.start_offset == node.location.start_offset + builder.condition( + token(node.if_keyword_loc), + visit(node.predicate), + if (then_keyword_loc = node.then_keyword_loc) + token(then_keyword_loc) + else + srange_find(node.predicate.location.end_offset, (node.statements&.location || node.subsequent&.location || node.end_keyword_loc).start_offset, ";") + end, + visit(node.statements), + case node.subsequent + when IfNode + token(node.subsequent.if_keyword_loc) + when ElseNode + token(node.subsequent.else_keyword_loc) + end, + visit(node.subsequent), + if node.if_keyword != "elsif" + token(node.end_keyword_loc) + end + ) + else + builder.condition_mod( + visit(node.statements), + visit(node.subsequent), + token(node.if_keyword_loc), + visit(node.predicate) + ) + end + end + + # 1i + # ^^ + def visit_imaginary_node(node) + visit_numeric(node, builder.complex([Complex(0, node.numeric.value), srange(node.location)])) + end + + # { foo: } + # ^^^^ + def visit_implicit_node(node) + raise CompilationError, "Cannot directly compile implicit nodes" + end + + # foo { |bar,| } + # ^ + def visit_implicit_rest_node(node) + raise CompilationError, "Cannot compile implicit rest nodes" + end + + # case foo; in bar; end + # ^^^^^^^^^^^^^^^^^^^^^ + def visit_in_node(node) + pattern = nil + guard = nil + + case node.pattern + when IfNode + pattern = within_pattern { |compiler| node.pattern.statements.accept(compiler) } + guard = builder.if_guard(token(node.pattern.if_keyword_loc), visit(node.pattern.predicate)) + when UnlessNode + pattern = within_pattern { |compiler| node.pattern.statements.accept(compiler) } + guard = builder.unless_guard(token(node.pattern.keyword_loc), visit(node.pattern.predicate)) + else + pattern = within_pattern { |compiler| node.pattern.accept(compiler) } + end + + builder.in_pattern( + token(node.in_loc), + pattern, + guard, + if (then_loc = node.then_loc) + token(then_loc) + else + srange_find(node.pattern.location.end_offset, node.statements&.location&.start_offset, ";") + end, + visit(node.statements) + ) + end + + # foo[bar] += baz + # ^^^^^^^^^^^^^^^ + def visit_index_operator_write_node(node) + arguments = node.arguments&.arguments || [] + arguments << node.block if node.block + + builder.op_assign( + builder.index( + visit(node.receiver), + token(node.opening_loc), + visit_all(arguments), + token(node.closing_loc) + ), + [node.binary_operator_loc.slice.chomp("="), srange(node.binary_operator_loc)], + visit(node.value) + ) + end + + # foo[bar] &&= baz + # ^^^^^^^^^^^^^^^^ + def visit_index_and_write_node(node) + arguments = node.arguments&.arguments || [] + arguments << node.block if node.block + + builder.op_assign( + builder.index( + visit(node.receiver), + token(node.opening_loc), + visit_all(arguments), + token(node.closing_loc) + ), + [node.operator_loc.slice.chomp("="), srange(node.operator_loc)], + visit(node.value) + ) + end + + # foo[bar] ||= baz + # ^^^^^^^^^^^^^^^^ + def visit_index_or_write_node(node) + arguments = node.arguments&.arguments || [] + arguments << node.block if node.block + + builder.op_assign( + builder.index( + visit(node.receiver), + token(node.opening_loc), + visit_all(arguments), + token(node.closing_loc) + ), + [node.operator_loc.slice.chomp("="), srange(node.operator_loc)], + visit(node.value) + ) + end + + # foo[bar], = 1 + # ^^^^^^^^ + def visit_index_target_node(node) + builder.index_asgn( + visit(node.receiver), + token(node.opening_loc), + visit_all(node.arguments&.arguments || []), + token(node.closing_loc), + ) + end + + # @foo + # ^^^^ + def visit_instance_variable_read_node(node) + builder.ivar(token(node.location)) + end + + # @foo = 1 + # ^^^^^^^^ + def visit_instance_variable_write_node(node) + builder.assign( + builder.assignable(builder.ivar(token(node.name_loc))), + token(node.operator_loc), + visit(node.value) + ) + end + + # @foo += bar + # ^^^^^^^^^^^ + def visit_instance_variable_operator_write_node(node) + builder.op_assign( + builder.assignable(builder.ivar(token(node.name_loc))), + [node.binary_operator_loc.slice.chomp("="), srange(node.binary_operator_loc)], + visit(node.value) + ) + end + + # @foo &&= bar + # ^^^^^^^^^^^^ + def visit_instance_variable_and_write_node(node) + builder.op_assign( + builder.assignable(builder.ivar(token(node.name_loc))), + [node.operator_loc.slice.chomp("="), srange(node.operator_loc)], + visit(node.value) + ) + end + + # @foo ||= bar + # ^^^^^^^^^^^^ + def visit_instance_variable_or_write_node(node) + builder.op_assign( + builder.assignable(builder.ivar(token(node.name_loc))), + [node.operator_loc.slice.chomp("="), srange(node.operator_loc)], + visit(node.value) + ) + end + + # @foo, = bar + # ^^^^ + def visit_instance_variable_target_node(node) + builder.assignable(builder.ivar(token(node.location))) + end + + # 1 + # ^ + def visit_integer_node(node) + visit_numeric(node, builder.integer([node.value, srange(node.location)])) + end + + # /foo #{bar}/ + # ^^^^^^^^^^^^ + def visit_interpolated_regular_expression_node(node) + builder.regexp_compose( + token(node.opening_loc), + string_nodes_from_interpolation(node, node.opening), + [node.closing[0], srange_offsets(node.closing_loc.start_offset, node.closing_loc.start_offset + 1)], + builder.regexp_options([node.closing[1..], srange_offsets(node.closing_loc.start_offset + 1, node.closing_loc.end_offset)]) + ) + end + + # if /foo #{bar}/ then end + # ^^^^^^^^^^^^ + alias visit_interpolated_match_last_line_node visit_interpolated_regular_expression_node + + # "foo #{bar}" + # ^^^^^^^^^^^^ + def visit_interpolated_string_node(node) + if node.heredoc? + return visit_heredoc(node) { |children, closing| builder.string_compose(token(node.opening_loc), children, closing) } + end + + builder.string_compose( + token(node.opening_loc), + string_nodes_from_interpolation(node, node.opening), + token(node.closing_loc) + ) + end + + # :"foo #{bar}" + # ^^^^^^^^^^^^^ + def visit_interpolated_symbol_node(node) + builder.symbol_compose( + token(node.opening_loc), + string_nodes_from_interpolation(node, node.opening), + token(node.closing_loc) + ) + end + + # `foo #{bar}` + # ^^^^^^^^^^^^ + def visit_interpolated_x_string_node(node) + if node.heredoc? + return visit_heredoc(node) { |children, closing| builder.xstring_compose(token(node.opening_loc), children, closing) } + end + + builder.xstring_compose( + token(node.opening_loc), + string_nodes_from_interpolation(node, node.opening), + token(node.closing_loc) + ) + end + + # -> { it } + # ^^ + def visit_it_local_variable_read_node(node) + builder.ident([:it, srange(node.location)]).updated(:lvar) + end + + # -> { it } + # ^^^^^^^^^ + def visit_it_parameters_node(node) + # FIXME: The builder _should_ always be a subclass of the prism builder. + # Currently RuboCop passes in its own builder that always inherits from the + # parser builder (which is lacking the `itarg` method). Once rubocop-ast + # opts in to use the custom prism builder a warning can be emitted when + # it is not the expected class, and eventually raise. + # https://github.com/rubocop/rubocop-ast/pull/354 + if builder.is_a?(Translation::Parser::Builder) + builder.itarg + else + builder.args(nil, [], nil, false) + end + end + + # foo(bar: baz) + # ^^^^^^^^ + def visit_keyword_hash_node(node) + builder.associate(nil, visit_all(node.elements), nil) + end + + # def foo(**bar); end + # ^^^^^ + # + # def foo(**); end + # ^^ + def visit_keyword_rest_parameter_node(node) + builder.kwrestarg( + token(node.operator_loc), + node.name ? [node.name, srange(node.name_loc)] : nil + ) + end + + # -> {} + # ^^^^^ + def visit_lambda_node(node) + parameters = node.parameters + implicit_parameters = parameters.is_a?(NumberedParametersNode) || parameters.is_a?(ItParametersNode) + + builder.block( + builder.call_lambda(token(node.operator_loc)), + [node.opening, srange(node.opening_loc)], + if parameters.nil? + builder.args(nil, [], nil, false) + elsif implicit_parameters + visit(node.parameters) + else + builder.args( + token(node.parameters.opening_loc), + visit(node.parameters), + token(node.parameters.closing_loc), + false + ) + end, + visit(node.body), + [node.closing, srange(node.closing_loc)] + ) + end + + # foo + # ^^^ + def visit_local_variable_read_node(node) + builder.ident([node.name, srange(node.location)]).updated(:lvar) + end + + # foo = 1 + # ^^^^^^^ + def visit_local_variable_write_node(node) + builder.assign( + builder.assignable(builder.ident(token(node.name_loc))), + token(node.operator_loc), + visit(node.value) + ) + end + + # foo += bar + # ^^^^^^^^^^ + def visit_local_variable_operator_write_node(node) + builder.op_assign( + builder.assignable(builder.ident(token(node.name_loc))), + [node.binary_operator_loc.slice.chomp("="), srange(node.binary_operator_loc)], + visit(node.value) + ) + end + + # foo &&= bar + # ^^^^^^^^^^^ + def visit_local_variable_and_write_node(node) + builder.op_assign( + builder.assignable(builder.ident(token(node.name_loc))), + [node.operator_loc.slice.chomp("="), srange(node.operator_loc)], + visit(node.value) + ) + end + + # foo ||= bar + # ^^^^^^^^^^^ + def visit_local_variable_or_write_node(node) + builder.op_assign( + builder.assignable(builder.ident(token(node.name_loc))), + [node.operator_loc.slice.chomp("="), srange(node.operator_loc)], + visit(node.value) + ) + end + + # foo, = bar + # ^^^ + def visit_local_variable_target_node(node) + if in_pattern + builder.assignable(builder.match_var([node.name, srange(node.location)])) + else + builder.assignable(builder.ident(token(node.location))) + end + end + + # foo in bar + # ^^^^^^^^^^ + def visit_match_predicate_node(node) + builder.match_pattern_p( + visit(node.value), + token(node.operator_loc), + within_pattern { |compiler| node.pattern.accept(compiler) } + ) + end + + # foo => bar + # ^^^^^^^^^^ + def visit_match_required_node(node) + builder.match_pattern( + visit(node.value), + token(node.operator_loc), + within_pattern { |compiler| node.pattern.accept(compiler) } + ) + end + + # /(?foo)/ =~ bar + # ^^^^^^^^^^^^^^^^^^^^ + def visit_match_write_node(node) + builder.match_op( + visit(node.call.receiver), + token(node.call.message_loc), + visit(node.call.arguments.arguments.first) + ) + end + + # A node that is missing from the syntax tree. This is only used in the + # case of a syntax error. The parser gem doesn't have such a concept, so + # we invent our own here. + def visit_missing_node(node) + ::AST::Node.new(:missing, [], location: ::Parser::Source::Map.new(srange(node.location))) + end + + # module Foo; end + # ^^^^^^^^^^^^^^^ + def visit_module_node(node) + builder.def_module( + token(node.module_keyword_loc), + visit(node.constant_path), + node.body&.accept(copy_compiler(forwarding: [])), + token(node.end_keyword_loc) + ) + end + + # foo, bar = baz + # ^^^^^^^^ + def visit_multi_target_node(node) + builder.multi_lhs( + token(node.lparen_loc), + visit_all(multi_target_elements(node)), + token(node.rparen_loc) + ) + end + + # foo, bar = baz + # ^^^^^^^^^^^^^^ + def visit_multi_write_node(node) + elements = multi_target_elements(node) + + if elements.length == 1 && elements.first.is_a?(MultiTargetNode) && !node.rest + elements = multi_target_elements(elements.first) + end + + builder.multi_assign( + builder.multi_lhs( + token(node.lparen_loc), + visit_all(elements), + token(node.rparen_loc) + ), + token(node.operator_loc), + visit(node.value) + ) + end + + # next + # ^^^^ + # + # next foo + # ^^^^^^^^ + def visit_next_node(node) + builder.keyword_cmd( + :next, + token(node.keyword_loc), + nil, + visit(node.arguments) || [], + nil + ) + end + + # nil + # ^^^ + def visit_nil_node(node) + builder.nil(token(node.location)) + end + + # def foo(**nil); end + # ^^^^^ + def visit_no_keywords_parameter_node(node) + if in_pattern + builder.match_nil_pattern(token(node.operator_loc), token(node.keyword_loc)) + else + builder.kwnilarg(token(node.operator_loc), token(node.keyword_loc)) + end + end + + # -> { _1 + _2 } + # ^^^^^^^^^^^^^^ + def visit_numbered_parameters_node(node) + builder.numargs(node.maximum) + end + + # $1 + # ^^ + def visit_numbered_reference_read_node(node) + builder.nth_ref([node.number, srange(node.location)]) + end + + # def foo(bar: baz); end + # ^^^^^^^^ + def visit_optional_keyword_parameter_node(node) + builder.kwoptarg([node.name, srange(node.name_loc)], visit(node.value)) + end + + # def foo(bar = 1); end + # ^^^^^^^ + def visit_optional_parameter_node(node) + builder.optarg(token(node.name_loc), token(node.operator_loc), visit(node.value)) + end + + # a or b + # ^^^^^^ + def visit_or_node(node) + builder.logical_op(:or, visit(node.left), token(node.operator_loc), visit(node.right)) + end + + # def foo(bar, *baz); end + # ^^^^^^^^^ + def visit_parameters_node(node) + params = [] + + if node.requireds.any? + node.requireds.each do |required| + params << + if required.is_a?(RequiredParameterNode) + visit(required) + else + required.accept(copy_compiler(in_destructure: true)) + end + end + end + + params.concat(visit_all(node.optionals)) if node.optionals.any? + params << visit(node.rest) if !node.rest.nil? && !node.rest.is_a?(ImplicitRestNode) + + if node.posts.any? + node.posts.each do |post| + params << + if post.is_a?(RequiredParameterNode) + visit(post) + else + post.accept(copy_compiler(in_destructure: true)) + end + end + end + + params.concat(visit_all(node.keywords)) if node.keywords.any? + params << visit(node.keyword_rest) if !node.keyword_rest.nil? + params << visit(node.block) if !node.block.nil? + params + end + + # () + # ^^ + # + # (1) + # ^^^ + def visit_parentheses_node(node) + builder.begin( + token(node.opening_loc), + visit(node.body), + token(node.closing_loc) + ) + end + + # foo => ^(bar) + # ^^^^^^ + def visit_pinned_expression_node(node) + parts = node.expression.accept(copy_compiler(in_pattern: false)) # Don't treat * and similar as match_rest + expression = builder.begin(token(node.lparen_loc), parts, token(node.rparen_loc)) + builder.pin(token(node.operator_loc), expression) + end + + # foo = 1 and bar => ^foo + # ^^^^ + def visit_pinned_variable_node(node) + builder.pin(token(node.operator_loc), visit(node.variable)) + end + + # END {} + def visit_post_execution_node(node) + builder.postexe( + token(node.keyword_loc), + token(node.opening_loc), + visit(node.statements), + token(node.closing_loc) + ) + end + + # BEGIN {} + def visit_pre_execution_node(node) + builder.preexe( + token(node.keyword_loc), + token(node.opening_loc), + visit(node.statements), + token(node.closing_loc) + ) + end + + # The top-level program node. + def visit_program_node(node) + visit(node.statements) + end + + # 0..5 + # ^^^^ + def visit_range_node(node) + if node.exclude_end? + builder.range_exclusive( + visit(node.left), + token(node.operator_loc), + visit(node.right) + ) + else + builder.range_inclusive( + visit(node.left), + token(node.operator_loc), + visit(node.right) + ) + end + end + + # if foo .. bar; end + # ^^^^^^^^^^ + alias visit_flip_flop_node visit_range_node + + # 1r + # ^^ + def visit_rational_node(node) + visit_numeric(node, builder.rational([node.value, srange(node.location)])) + end + + # redo + # ^^^^ + def visit_redo_node(node) + builder.keyword_cmd(:redo, token(node.location)) + end + + # /foo/ + # ^^^^^ + def visit_regular_expression_node(node) + parts = + if node.content == "" + [] + elsif node.content.include?("\n") + string_nodes_from_line_continuations(node.unescaped, node.content, node.content_loc.start_offset, node.opening) + else + [builder.string_internal([node.unescaped, srange(node.content_loc)])] + end + + builder.regexp_compose( + token(node.opening_loc), + parts, + [node.closing[0], srange_offsets(node.closing_loc.start_offset, node.closing_loc.start_offset + 1)], + builder.regexp_options([node.closing[1..], srange_offsets(node.closing_loc.start_offset + 1, node.closing_loc.end_offset)]) + ) + end + + # if /foo/ then end + # ^^^^^ + alias visit_match_last_line_node visit_regular_expression_node + + # def foo(bar:); end + # ^^^^ + def visit_required_keyword_parameter_node(node) + builder.kwarg([node.name, srange(node.name_loc)]) + end + + # def foo(bar); end + # ^^^ + def visit_required_parameter_node(node) + builder.arg(token(node.location)) + end + + # foo rescue bar + # ^^^^^^^^^^^^^^ + def visit_rescue_modifier_node(node) + builder.begin_body( + visit(node.expression), + [ + builder.rescue_body( + token(node.keyword_loc), + nil, + nil, + nil, + nil, + visit(node.rescue_expression) + ) + ] + ) + end + + # begin; rescue; end + # ^^^^^^^ + def visit_rescue_node(node) + raise CompilationError, "Cannot directly compile rescue nodes" + end + + # def foo(*bar); end + # ^^^^ + # + # def foo(*); end + # ^ + def visit_rest_parameter_node(node) + builder.restarg(token(node.operator_loc), token(node.name_loc)) + end + + # retry + # ^^^^^ + def visit_retry_node(node) + builder.keyword_cmd(:retry, token(node.location)) + end + + # return + # ^^^^^^ + # + # return 1 + # ^^^^^^^^ + def visit_return_node(node) + builder.keyword_cmd( + :return, + token(node.keyword_loc), + nil, + visit(node.arguments) || [], + nil + ) + end + + # self + # ^^^^ + def visit_self_node(node) + builder.self(token(node.location)) + end + + # A shareable constant. + def visit_shareable_constant_node(node) + visit(node.write) + end + + # class << self; end + # ^^^^^^^^^^^^^^^^^^ + def visit_singleton_class_node(node) + builder.def_sclass( + token(node.class_keyword_loc), + token(node.operator_loc), + visit(node.expression), + node.body&.accept(copy_compiler(forwarding: [])), + token(node.end_keyword_loc) + ) + end + + # __ENCODING__ + # ^^^^^^^^^^^^ + def visit_source_encoding_node(node) + builder.accessible(builder.__ENCODING__(token(node.location))) + end + + # __FILE__ + # ^^^^^^^^ + def visit_source_file_node(node) + builder.accessible(builder.__FILE__(token(node.location))) + end + + # __LINE__ + # ^^^^^^^^ + def visit_source_line_node(node) + builder.accessible(builder.__LINE__(token(node.location))) + end + + # foo(*bar) + # ^^^^ + # + # def foo((bar, *baz)); end + # ^^^^ + # + # def foo(*); bar(*); end + # ^ + def visit_splat_node(node) + if node.expression.nil? && forwarding.include?(:*) + builder.forwarded_restarg(token(node.operator_loc)) + elsif in_destructure + builder.restarg(token(node.operator_loc), token(node.expression&.location)) + elsif in_pattern + builder.match_rest(token(node.operator_loc), token(node.expression&.location)) + else + builder.splat(token(node.operator_loc), visit(node.expression)) + end + end + + # A list of statements. + def visit_statements_node(node) + builder.compstmt(visit_all(node.body)) + end + + # "foo" + # ^^^^^ + def visit_string_node(node) + if node.heredoc? + visit_heredoc(node.to_interpolated) { |children, closing| builder.string_compose(token(node.opening_loc), children, closing) } + elsif node.opening == "?" + builder.character([node.unescaped, srange(node.location)]) + elsif node.opening&.start_with?("%") && node.unescaped.empty? + builder.string_compose(token(node.opening_loc), [], token(node.closing_loc)) + else + parts = + if node.content.include?("\n") + string_nodes_from_line_continuations(node.unescaped, node.content, node.content_loc.start_offset, node.opening) + else + [builder.string_internal([node.unescaped, srange(node.content_loc)])] + end + + builder.string_compose( + token(node.opening_loc), + parts, + token(node.closing_loc) + ) + end + end + + # super(foo) + # ^^^^^^^^^^ + def visit_super_node(node) + arguments = node.arguments&.arguments || [] + block = node.block + + if block.is_a?(BlockArgumentNode) + arguments = [*arguments, block] + block = nil + end + + visit_block( + builder.keyword_cmd( + :super, + token(node.keyword_loc), + token(node.lparen_loc), + visit_all(arguments), + token(node.rparen_loc) + ), + block + ) + end + + # :foo + # ^^^^ + def visit_symbol_node(node) + if node.closing_loc.nil? + if node.opening_loc.nil? + builder.symbol_internal([node.unescaped, srange(node.location)]) + else + builder.symbol([node.unescaped, srange(node.location)]) + end + else + parts = + if node.value == "" + [] + elsif node.value.include?("\n") + string_nodes_from_line_continuations(node.unescaped, node.value, node.value_loc.start_offset, node.opening) + else + [builder.string_internal([node.unescaped, srange(node.value_loc)])] + end + + builder.symbol_compose( + token(node.opening_loc), + parts, + token(node.closing_loc) + ) + end + end + + # true + # ^^^^ + def visit_true_node(node) + builder.true(token(node.location)) + end + + # undef foo + # ^^^^^^^^^ + def visit_undef_node(node) + builder.undef_method(token(node.keyword_loc), visit_all(node.names)) + end + + # unless foo; bar end + # ^^^^^^^^^^^^^^^^^^^ + # + # bar unless foo + # ^^^^^^^^^^^^^^ + def visit_unless_node(node) + if node.keyword_loc.start_offset == node.location.start_offset + builder.condition( + token(node.keyword_loc), + visit(node.predicate), + if (then_keyword_loc = node.then_keyword_loc) + token(then_keyword_loc) + else + srange_find(node.predicate.location.end_offset, (node.statements&.location || node.else_clause&.location || node.end_keyword_loc).start_offset, ";") + end, + visit(node.else_clause), + token(node.else_clause&.else_keyword_loc), + visit(node.statements), + token(node.end_keyword_loc) + ) + else + builder.condition_mod( + visit(node.else_clause), + visit(node.statements), + token(node.keyword_loc), + visit(node.predicate) + ) + end + end + + # until foo; bar end + # ^^^^^^^^^^^^^^^^^^ + # + # bar until foo + # ^^^^^^^^^^^^^ + def visit_until_node(node) + if node.location.start_offset == node.keyword_loc.start_offset + builder.loop( + :until, + token(node.keyword_loc), + visit(node.predicate), + if (do_keyword_loc = node.do_keyword_loc) + token(do_keyword_loc) + else + srange_find(node.predicate.location.end_offset, (node.statements&.location || node.closing_loc).start_offset, ";") + end, + visit(node.statements), + token(node.closing_loc) + ) + else + builder.loop_mod( + :until, + visit(node.statements), + token(node.keyword_loc), + visit(node.predicate) + ) + end + end + + # case foo; when bar; end + # ^^^^^^^^^^^^^ + def visit_when_node(node) + builder.when( + token(node.keyword_loc), + visit_all(node.conditions), + if (then_keyword_loc = node.then_keyword_loc) + token(then_keyword_loc) + else + srange_find(node.conditions.last.location.end_offset, node.statements&.location&.start_offset, ";") + end, + visit(node.statements) + ) + end + + # while foo; bar end + # ^^^^^^^^^^^^^^^^^^ + # + # bar while foo + # ^^^^^^^^^^^^^ + def visit_while_node(node) + if node.location.start_offset == node.keyword_loc.start_offset + builder.loop( + :while, + token(node.keyword_loc), + visit(node.predicate), + if (do_keyword_loc = node.do_keyword_loc) + token(do_keyword_loc) + else + srange_find(node.predicate.location.end_offset, (node.statements&.location || node.closing_loc).start_offset, ";") + end, + visit(node.statements), + token(node.closing_loc) + ) + else + builder.loop_mod( + :while, + visit(node.statements), + token(node.keyword_loc), + visit(node.predicate) + ) + end + end + + # `foo` + # ^^^^^ + def visit_x_string_node(node) + if node.heredoc? + return visit_heredoc(node.to_interpolated) { |children, closing| builder.xstring_compose(token(node.opening_loc), children, closing) } + end + + parts = + if node.content == "" + [] + elsif node.content.include?("\n") + string_nodes_from_line_continuations(node.unescaped, node.content, node.content_loc.start_offset, node.opening) + else + [builder.string_internal([node.unescaped, srange(node.content_loc)])] + end + + builder.xstring_compose( + token(node.opening_loc), + parts, + token(node.closing_loc) + ) + end + + # yield + # ^^^^^ + # + # yield 1 + # ^^^^^^^ + def visit_yield_node(node) + builder.keyword_cmd( + :yield, + token(node.keyword_loc), + token(node.lparen_loc), + visit(node.arguments) || [], + token(node.rparen_loc) + ) + end + + private + + # Initialize a new compiler with the given option overrides, used to + # visit a subtree with the given options. + def copy_compiler(forwarding: self.forwarding, in_destructure: self.in_destructure, in_pattern: self.in_pattern) + Compiler.new(parser, offset_cache, forwarding: forwarding, in_destructure: in_destructure, in_pattern: in_pattern) + end + + # When *, **, &, or ... are used as an argument in a method call, we + # check if they were allowed by the current context. To determine that + # we build this lookup table. + def find_forwarding(node) + return [] if node.nil? + + forwarding = [] + forwarding << :* if node.rest.is_a?(RestParameterNode) && node.rest.name.nil? + forwarding << :** if node.keyword_rest.is_a?(KeywordRestParameterNode) && node.keyword_rest.name.nil? + forwarding << :& if !node.block.nil? && node.block.name.nil? + forwarding |= [:&, :"..."] if node.keyword_rest.is_a?(ForwardingParameterNode) + + forwarding + end + + # Returns the set of targets for a MultiTargetNode or a MultiWriteNode. + def multi_target_elements(node) + elements = [*node.lefts] + elements << node.rest if !node.rest.nil? && !node.rest.is_a?(ImplicitRestNode) + elements.concat(node.rights) + elements + end + + # Negate the value of a numeric node. This is a special case where you + # have a negative sign on one line and then a number on the next line. + # In normal Ruby, this will always be a method call. The parser gem, + # however, marks this as a numeric literal. We have to massage the tree + # here to get it into the correct form. + def numeric_negate(message_loc, receiver) + case receiver.type + when :integer_node, :float_node + receiver.copy(value: -receiver.value, location: message_loc.join(receiver.location)) + when :rational_node + receiver.copy(numerator: -receiver.numerator, location: message_loc.join(receiver.location)) + when :imaginary_node + receiver.copy(numeric: numeric_negate(message_loc, receiver.numeric), location: message_loc.join(receiver.location)) + end + end + + # Blocks can have a special set of parameters that automatically expand + # when given arrays if they have a single required parameter and no + # other parameters. + def procarg0?(parameters) + parameters && + parameters.requireds.length == 1 && + parameters.optionals.empty? && + parameters.rest.nil? && + parameters.posts.empty? && + parameters.keywords.empty? && + parameters.keyword_rest.nil? && + parameters.block.nil? + end + + # Locations in the parser gem AST are generated using this class. We + # store a reference to its constant to make it slightly faster to look + # up. + Range = ::Parser::Source::Range + + # Constructs a new source range from the given start and end offsets. + def srange(location) + Range.new(source_buffer, offset_cache[location.start_offset], offset_cache[location.end_offset]) if location + end + + # Constructs a new source range from the given start and end offsets. + def srange_offsets(start_offset, end_offset) + Range.new(source_buffer, offset_cache[start_offset], offset_cache[end_offset]) + end + + # Constructs a new source range by finding the given character between + # the given start offset and end offset. If the needle is not found, it + # returns nil. Importantly it does not search past newlines or comments. + # + # Note that end_offset is allowed to be nil, in which case this will + # search until the end of the string. + def srange_find(start_offset, end_offset, character) + if (match = source_buffer.source.byteslice(start_offset...end_offset)[/\A\s*#{character}/]) + final_offset = start_offset + match.bytesize + [character, Range.new(source_buffer, offset_cache[final_offset - character.bytesize], offset_cache[final_offset])] + end + end + + # Transform a location into a token that the parser gem expects. + def token(location) + [location.slice, Range.new(source_buffer, offset_cache[location.start_offset], offset_cache[location.end_offset])] if location + end + + # Visit a block node on a call. + def visit_block(call, block) + if block + parameters = block.parameters + implicit_parameters = parameters.is_a?(NumberedParametersNode) || parameters.is_a?(ItParametersNode) + + builder.block( + call, + token(block.opening_loc), + if parameters.nil? + builder.args(nil, [], nil, false) + elsif implicit_parameters + visit(parameters) + else + builder.args( + token(parameters.opening_loc), + if procarg0?(parameters.parameters) + parameter = parameters.parameters.requireds.first + visited = parameter.is_a?(RequiredParameterNode) ? visit(parameter) : parameter.accept(copy_compiler(in_destructure: true)) + [builder.procarg0(visited)].concat(visit_all(parameters.locals)) + else + visit(parameters) + end, + token(parameters.closing_loc), + false + ) + end, + visit(block.body), + token(block.closing_loc) + ) + else + call + end + end + + # Visit a heredoc that can be either a string or an xstring. + def visit_heredoc(node) + children = Array.new + indented = false + + # If this is a dedenting heredoc, then we need to insert the opening + # content into the children as well. + if node.opening.start_with?("<<~") && node.parts.length > 0 && !node.parts.first.is_a?(StringNode) + location = node.parts.first.location + location = location.copy(start_offset: location.start_offset - location.start_line_slice.bytesize) + children << builder.string_internal(token(location)) + indented = true + end + + node.parts.each do |part| + pushing = + if part.is_a?(StringNode) && part.content.include?("\n") + string_nodes_from_line_continuations(part.unescaped, part.content, part.location.start_offset, node.opening) + else + [visit(part)] + end + + pushing.each do |child| + if child.type == :str && child.children.last == "" + # nothing + elsif child.type == :str && children.last && children.last.type == :str && !children.last.children.first.end_with?("\n") + appendee = children[-1] + + location = appendee.loc + location = location.with_expression(location.expression.join(child.loc.expression)) + + children[-1] = appendee.updated(:str, ["#{appendee.children.first}#{child.children.first}"], location: location) + else + children << child + end + end + end + + closing = node.closing + closing_t = [closing.chomp, srange_offsets(node.closing_loc.start_offset, node.closing_loc.end_offset - (closing[/\s+$/]&.length || 0))] + composed = yield children, closing_t + + composed = composed.updated(nil, children[1..-1]) if indented + composed + end + + # Visit a numeric node and account for the optional sign. + def visit_numeric(node, value) + if (slice = node.slice).match?(/^[+-]/) + builder.unary_num( + [slice[0].to_sym, srange_offsets(node.location.start_offset, node.location.start_offset + 1)], + value + ) + else + value + end + end + + # Within the given block, track that we're within a pattern. + def within_pattern + begin + parser.pattern_variables.push + yield copy_compiler(in_pattern: true) + ensure + parser.pattern_variables.pop + end + end + + # When the content of a string node is split across multiple lines, the + # parser gem creates individual string nodes for each line the content is part of. + def string_nodes_from_interpolation(node, opening) + node.parts.flat_map do |part| + if part.type == :string_node && part.content.include?("\n") && part.opening_loc.nil? + string_nodes_from_line_continuations(part.unescaped, part.content, part.content_loc.start_offset, opening) + else + visit(part) + end + end + end + + # Create parser string nodes from a single prism node. The parser gem + # "glues" strings together when a line continuation is encountered. + def string_nodes_from_line_continuations(unescaped, escaped, start_offset, opening) + unescaped = unescaped.lines + escaped = escaped.lines + percent_array = opening&.start_with?("%w", "%W", "%i", "%I") + regex = opening == "/" || opening&.start_with?("%r") + + # Non-interpolating strings + if opening&.end_with?("'") || opening&.start_with?("%q", "%s", "%w", "%i") + current_length = 0 + current_line = +"" + + escaped.filter_map.with_index do |escaped_line, index| + unescaped_line = unescaped.fetch(index, "") + current_length += escaped_line.bytesize + current_line << unescaped_line + + # Glue line continuations together. Only %w and %i arrays can contain these. + if percent_array && escaped_line[/(\\)*\n$/, 1]&.length&.odd? + next unless index == escaped.count - 1 + end + s = builder.string_internal([current_line, srange_offsets(start_offset, start_offset + current_length)]) + start_offset += escaped_line.bytesize + current_line = +"" + current_length = 0 + s + end + else + escaped_lengths = [] + normalized_lengths = [] + # Keeps track of where an unescaped line should start a new token. An unescaped + # \n would otherwise be indistinguishable from the actual newline at the end of + # of the line. The parser gem only emits a new string node at "real" newlines, + # line continuations don't start a new node as well. + do_next_tokens = [] + + escaped + .chunk_while { |before, after| before[/(\\*)\r?\n$/, 1]&.length&.odd? || false } + .each do |lines| + escaped_lengths << lines.sum(&:bytesize) + + unescaped_lines_count = + if regex + 0 # Will always be preserved as is + else + lines.sum do |line| + count = line.scan(/(\\*)n/).count { |(backslashes)| backslashes&.length&.odd? } + count -= 1 if !line.end_with?("\n") && count > 0 + count + end + end + + extra = 1 + extra = lines.count if percent_array # Account for line continuations in percent arrays + + normalized_lengths.concat(Array.new(unescaped_lines_count + extra, 0)) + normalized_lengths[-1] = lines.sum { |line| line.bytesize } + do_next_tokens.concat(Array.new(unescaped_lines_count + extra, false)) + do_next_tokens[-1] = true + end + + current_line = +"" + current_normalized_length = 0 + + emitted_count = 0 + unescaped.filter_map.with_index do |unescaped_line, index| + current_line << unescaped_line + current_normalized_length += normalized_lengths.fetch(index, 0) + + if do_next_tokens[index] + inner_part = builder.string_internal([current_line, srange_offsets(start_offset, start_offset + current_normalized_length)]) + start_offset += escaped_lengths.fetch(emitted_count, 0) + current_line = +"" + current_normalized_length = 0 + emitted_count += 1 + inner_part + else + nil + end + end + end + end + end + end + end +end diff --git a/lib/prism/translation/parser/lexer.rb b/lib/prism/translation/parser/lexer.rb new file mode 100644 index 00000000000000..dd4867415c5849 --- /dev/null +++ b/lib/prism/translation/parser/lexer.rb @@ -0,0 +1,819 @@ +# frozen_string_literal: true +# :markup: markdown + +require "strscan" +require_relative "../../polyfill/append_as_bytes" +require_relative "../../polyfill/scan_byte" + +module Prism + module Translation + class Parser + # Accepts a list of prism tokens and converts them into the expected + # format for the parser gem. + class Lexer + # These tokens are always skipped + TYPES_ALWAYS_SKIP = Set.new(%i[IGNORED_NEWLINE __END__ EOF]) + private_constant :TYPES_ALWAYS_SKIP + + # The direct translating of types between the two lexers. + TYPES = { + # These tokens should never appear in the output of the lexer. + MISSING: nil, + NOT_PROVIDED: nil, + EMBDOC_END: nil, + EMBDOC_LINE: nil, + + # These tokens have more or less direct mappings. + AMPERSAND: :tAMPER2, + AMPERSAND_AMPERSAND: :tANDOP, + AMPERSAND_AMPERSAND_EQUAL: :tOP_ASGN, + AMPERSAND_DOT: :tANDDOT, + AMPERSAND_EQUAL: :tOP_ASGN, + BACK_REFERENCE: :tBACK_REF, + BACKTICK: :tXSTRING_BEG, + BANG: :tBANG, + BANG_EQUAL: :tNEQ, + BANG_TILDE: :tNMATCH, + BRACE_LEFT: :tLCURLY, + BRACE_RIGHT: :tRCURLY, + BRACKET_LEFT: :tLBRACK2, + BRACKET_LEFT_ARRAY: :tLBRACK, + BRACKET_LEFT_RIGHT: :tAREF, + BRACKET_LEFT_RIGHT_EQUAL: :tASET, + BRACKET_RIGHT: :tRBRACK, + CARET: :tCARET, + CARET_EQUAL: :tOP_ASGN, + CHARACTER_LITERAL: :tCHARACTER, + CLASS_VARIABLE: :tCVAR, + COLON: :tCOLON, + COLON_COLON: :tCOLON2, + COMMA: :tCOMMA, + COMMENT: :tCOMMENT, + CONSTANT: :tCONSTANT, + DOT: :tDOT, + DOT_DOT: :tDOT2, + DOT_DOT_DOT: :tDOT3, + EMBDOC_BEGIN: :tCOMMENT, + EMBEXPR_BEGIN: :tSTRING_DBEG, + EMBEXPR_END: :tSTRING_DEND, + EMBVAR: :tSTRING_DVAR, + EQUAL: :tEQL, + EQUAL_EQUAL: :tEQ, + EQUAL_EQUAL_EQUAL: :tEQQ, + EQUAL_GREATER: :tASSOC, + EQUAL_TILDE: :tMATCH, + FLOAT: :tFLOAT, + FLOAT_IMAGINARY: :tIMAGINARY, + FLOAT_RATIONAL: :tRATIONAL, + FLOAT_RATIONAL_IMAGINARY: :tIMAGINARY, + GLOBAL_VARIABLE: :tGVAR, + GREATER: :tGT, + GREATER_EQUAL: :tGEQ, + GREATER_GREATER: :tRSHFT, + GREATER_GREATER_EQUAL: :tOP_ASGN, + HEREDOC_START: :tSTRING_BEG, + HEREDOC_END: :tSTRING_END, + IDENTIFIER: :tIDENTIFIER, + INSTANCE_VARIABLE: :tIVAR, + INTEGER: :tINTEGER, + INTEGER_IMAGINARY: :tIMAGINARY, + INTEGER_RATIONAL: :tRATIONAL, + INTEGER_RATIONAL_IMAGINARY: :tIMAGINARY, + KEYWORD_ALIAS: :kALIAS, + KEYWORD_AND: :kAND, + KEYWORD_BEGIN: :kBEGIN, + KEYWORD_BEGIN_UPCASE: :klBEGIN, + KEYWORD_BREAK: :kBREAK, + KEYWORD_CASE: :kCASE, + KEYWORD_CLASS: :kCLASS, + KEYWORD_DEF: :kDEF, + KEYWORD_DEFINED: :kDEFINED, + KEYWORD_DO: :kDO, + KEYWORD_DO_LOOP: :kDO_COND, + KEYWORD_END: :kEND, + KEYWORD_END_UPCASE: :klEND, + KEYWORD_ENSURE: :kENSURE, + KEYWORD_ELSE: :kELSE, + KEYWORD_ELSIF: :kELSIF, + KEYWORD_FALSE: :kFALSE, + KEYWORD_FOR: :kFOR, + KEYWORD_IF: :kIF, + KEYWORD_IF_MODIFIER: :kIF_MOD, + KEYWORD_IN: :kIN, + KEYWORD_MODULE: :kMODULE, + KEYWORD_NEXT: :kNEXT, + KEYWORD_NIL: :kNIL, + KEYWORD_NOT: :kNOT, + KEYWORD_OR: :kOR, + KEYWORD_REDO: :kREDO, + KEYWORD_RESCUE: :kRESCUE, + KEYWORD_RESCUE_MODIFIER: :kRESCUE_MOD, + KEYWORD_RETRY: :kRETRY, + KEYWORD_RETURN: :kRETURN, + KEYWORD_SELF: :kSELF, + KEYWORD_SUPER: :kSUPER, + KEYWORD_THEN: :kTHEN, + KEYWORD_TRUE: :kTRUE, + KEYWORD_UNDEF: :kUNDEF, + KEYWORD_UNLESS: :kUNLESS, + KEYWORD_UNLESS_MODIFIER: :kUNLESS_MOD, + KEYWORD_UNTIL: :kUNTIL, + KEYWORD_UNTIL_MODIFIER: :kUNTIL_MOD, + KEYWORD_WHEN: :kWHEN, + KEYWORD_WHILE: :kWHILE, + KEYWORD_WHILE_MODIFIER: :kWHILE_MOD, + KEYWORD_YIELD: :kYIELD, + KEYWORD___ENCODING__: :k__ENCODING__, + KEYWORD___FILE__: :k__FILE__, + KEYWORD___LINE__: :k__LINE__, + LABEL: :tLABEL, + LABEL_END: :tLABEL_END, + LAMBDA_BEGIN: :tLAMBEG, + LESS: :tLT, + LESS_EQUAL: :tLEQ, + LESS_EQUAL_GREATER: :tCMP, + LESS_LESS: :tLSHFT, + LESS_LESS_EQUAL: :tOP_ASGN, + METHOD_NAME: :tFID, + MINUS: :tMINUS, + MINUS_EQUAL: :tOP_ASGN, + MINUS_GREATER: :tLAMBDA, + NEWLINE: :tNL, + NUMBERED_REFERENCE: :tNTH_REF, + PARENTHESIS_LEFT: :tLPAREN2, + PARENTHESIS_LEFT_PARENTHESES: :tLPAREN_ARG, + PARENTHESIS_RIGHT: :tRPAREN, + PERCENT: :tPERCENT, + PERCENT_EQUAL: :tOP_ASGN, + PERCENT_LOWER_I: :tQSYMBOLS_BEG, + PERCENT_LOWER_W: :tQWORDS_BEG, + PERCENT_UPPER_I: :tSYMBOLS_BEG, + PERCENT_UPPER_W: :tWORDS_BEG, + PERCENT_LOWER_X: :tXSTRING_BEG, + PLUS: :tPLUS, + PLUS_EQUAL: :tOP_ASGN, + PIPE_EQUAL: :tOP_ASGN, + PIPE: :tPIPE, + PIPE_PIPE: :tOROP, + PIPE_PIPE_EQUAL: :tOP_ASGN, + QUESTION_MARK: :tEH, + REGEXP_BEGIN: :tREGEXP_BEG, + REGEXP_END: :tSTRING_END, + SEMICOLON: :tSEMI, + SLASH: :tDIVIDE, + SLASH_EQUAL: :tOP_ASGN, + STAR: :tSTAR2, + STAR_EQUAL: :tOP_ASGN, + STAR_STAR: :tPOW, + STAR_STAR_EQUAL: :tOP_ASGN, + STRING_BEGIN: :tSTRING_BEG, + STRING_CONTENT: :tSTRING_CONTENT, + STRING_END: :tSTRING_END, + SYMBOL_BEGIN: :tSYMBEG, + TILDE: :tTILDE, + UAMPERSAND: :tAMPER, + UCOLON_COLON: :tCOLON3, + UDOT_DOT: :tBDOT2, + UDOT_DOT_DOT: :tBDOT3, + UMINUS: :tUMINUS, + UMINUS_NUM: :tUNARY_NUM, + UPLUS: :tUPLUS, + USTAR: :tSTAR, + USTAR_STAR: :tDSTAR, + WORDS_SEP: :tSPACE + } + + # These constants represent flags in our lex state. We really, really + # don't want to be using them and we really, really don't want to be + # exposing them as part of our public API. Unfortunately, we don't have + # another way of matching the exact tokens that the parser gem expects + # without them. We should find another way to do this, but in the + # meantime we'll hide them from the documentation and mark them as + # private constants. + EXPR_BEG = 0x1 # :nodoc: + EXPR_LABEL = 0x400 # :nodoc: + + # It is used to determine whether `do` is of the token type `kDO` or `kDO_LAMBDA`. + # + # NOTE: In edge cases like `-> (foo = -> (bar) {}) do end`, please note that `kDO` is still returned + # instead of `kDO_LAMBDA`, which is expected: https://github.com/ruby/prism/pull/3046 + LAMBDA_TOKEN_TYPES = Set.new([:kDO_LAMBDA, :tLAMBDA, :tLAMBEG]) + + # The `PARENTHESIS_LEFT` token in Prism is classified as either `tLPAREN` or `tLPAREN2` in the Parser gem. + # The following token types are listed as those classified as `tLPAREN`. + LPAREN_CONVERSION_TOKEN_TYPES = Set.new([ + :kBREAK, :tCARET, :kCASE, :tDIVIDE, :kFOR, :kIF, :kNEXT, :kRETURN, :kUNTIL, :kWHILE, :tAMPER, :tANDOP, :tBANG, :tCOMMA, :tDOT2, :tDOT3, + :tEQL, :tLPAREN, :tLPAREN2, :tLPAREN_ARG, :tLSHFT, :tNL, :tOP_ASGN, :tOROP, :tPIPE, :tSEMI, :tSTRING_DBEG, :tUMINUS, :tUPLUS + ]) + + # Types of tokens that are allowed to continue a method call with comments in-between. + # For these, the parser gem doesn't emit a newline token after the last comment. + COMMENT_CONTINUATION_TYPES = Set.new([:COMMENT, :AMPERSAND_DOT, :DOT]) + private_constant :COMMENT_CONTINUATION_TYPES + + # Heredocs are complex and require us to keep track of a bit of info to refer to later + HeredocData = Struct.new(:identifier, :common_whitespace, keyword_init: true) + + private_constant :TYPES, :EXPR_BEG, :EXPR_LABEL, :LAMBDA_TOKEN_TYPES, :LPAREN_CONVERSION_TOKEN_TYPES, :HeredocData + + # The Parser::Source::Buffer that the tokens were lexed from. + attr_reader :source_buffer + + # An array of tuples that contain prism tokens and their associated lex + # state when they were lexed. + attr_reader :lexed + + # A hash that maps offsets in bytes to offsets in characters. + attr_reader :offset_cache + + # Initialize the lexer with the given source buffer, prism tokens, and + # offset cache. + def initialize(source_buffer, lexed, offset_cache) + @source_buffer = source_buffer + @lexed = lexed + @offset_cache = offset_cache + end + + Range = ::Parser::Source::Range # :nodoc: + private_constant :Range + + # Convert the prism tokens into the expected format for the parser gem. + def to_a + tokens = [] + + index = 0 + length = lexed.length + + heredoc_stack = [] + quote_stack = [] + + # The parser gem emits the newline tokens for comments out of order. This saves + # that token location to emit at a later time to properly line everything up. + # https://github.com/whitequark/parser/issues/1025 + comment_newline_location = nil + + while index < length + token, state = lexed[index] + index += 1 + next if TYPES_ALWAYS_SKIP.include?(token.type) + + type = TYPES.fetch(token.type) + value = token.value + location = range(token.location.start_offset, token.location.end_offset) + + case type + when :kDO + nearest_lambda_token = tokens.reverse_each.find do |token| + LAMBDA_TOKEN_TYPES.include?(token.first) + end + + if nearest_lambda_token&.first == :tLAMBDA + type = :kDO_LAMBDA + end + when :tCHARACTER + value.delete_prefix!("?") + # Character literals behave similar to double-quoted strings. We can use the same escaping mechanism. + value = unescape_string(value, "?") + when :tCOMMENT + if token.type == :EMBDOC_BEGIN + + while !((next_token = lexed[index][0]) && next_token.type == :EMBDOC_END) && (index < length - 1) + value += next_token.value + index += 1 + end + + value += next_token.value + location = range(token.location.start_offset, lexed[index][0].location.end_offset) + index += 1 + else + is_at_eol = value.chomp!.nil? + location = range(token.location.start_offset, token.location.end_offset + (is_at_eol ? 0 : -1)) + + prev_token = lexed[index - 2][0] if index - 2 >= 0 + next_token = lexed[index][0] + + is_inline_comment = prev_token&.location&.start_line == token.location.start_line + if is_inline_comment && !is_at_eol && !COMMENT_CONTINUATION_TYPES.include?(next_token&.type) + tokens << [:tCOMMENT, [value, location]] + + nl_location = range(token.location.end_offset - 1, token.location.end_offset) + tokens << [:tNL, [nil, nl_location]] + next + elsif is_inline_comment && next_token&.type == :COMMENT + comment_newline_location = range(token.location.end_offset - 1, token.location.end_offset) + elsif comment_newline_location && !COMMENT_CONTINUATION_TYPES.include?(next_token&.type) + tokens << [:tCOMMENT, [value, location]] + tokens << [:tNL, [nil, comment_newline_location]] + comment_newline_location = nil + next + end + end + when :tNL + next_token = next_token = lexed[index][0] + # Newlines after comments are emitted out of order. + if next_token&.type == :COMMENT + comment_newline_location = location + next + end + + value = nil + when :tFLOAT + value = parse_float(value) + when :tIMAGINARY + value = parse_complex(value) + when :tINTEGER + if value.start_with?("+") + tokens << [:tUNARY_NUM, ["+", range(token.location.start_offset, token.location.start_offset + 1)]] + location = range(token.location.start_offset + 1, token.location.end_offset) + end + + value = parse_integer(value) + when :tLABEL + value.chomp!(":") + when :tLABEL_END + value.chomp!(":") + when :tLCURLY + type = :tLBRACE if state == EXPR_BEG | EXPR_LABEL + when :tLPAREN2 + type = :tLPAREN if tokens.empty? || LPAREN_CONVERSION_TOKEN_TYPES.include?(tokens.dig(-1, 0)) + when :tNTH_REF + value = parse_integer(value.delete_prefix("$")) + when :tOP_ASGN + value.chomp!("=") + when :tRATIONAL + value = parse_rational(value) + when :tSPACE + location = range(token.location.start_offset, token.location.start_offset + percent_array_leading_whitespace(value)) + value = nil + when :tSTRING_BEG + next_token = lexed[index][0] + next_next_token = lexed[index + 1][0] + basic_quotes = value == '"' || value == "'" + + if basic_quotes && next_token&.type == :STRING_END + next_location = token.location.join(next_token.location) + type = :tSTRING + value = "" + location = range(next_location.start_offset, next_location.end_offset) + index += 1 + elsif value.start_with?("'", '"', "%") + if next_token&.type == :STRING_CONTENT && next_next_token&.type == :STRING_END + string_value = next_token.value + if simplify_string?(string_value, value) + next_location = token.location.join(next_next_token.location) + if percent_array?(value) + value = percent_array_unescape(string_value) + else + value = unescape_string(string_value, value) + end + type = :tSTRING + location = range(next_location.start_offset, next_location.end_offset) + index += 2 + tokens << [type, [value, location]] + + next + end + end + + quote_stack.push(value) + elsif token.type == :HEREDOC_START + quote = value[2] == "-" || value[2] == "~" ? value[3] : value[2] + heredoc_type = value[2] == "-" || value[2] == "~" ? value[2] : "" + heredoc = HeredocData.new( + identifier: value.match(/<<[-~]?["'`]?(?.*?)["'`]?\z/)[:heredoc_identifier], + common_whitespace: 0, + ) + + if quote == "`" + type = :tXSTRING_BEG + end + + # The parser gem trims whitespace from squiggly heredocs. We must record + # the most common whitespace to later remove. + if heredoc_type == "~" || heredoc_type == "`" + heredoc.common_whitespace = calculate_heredoc_whitespace(index) + end + + if quote == "'" || quote == '"' || quote == "`" + value = "<<#{quote}" + else + value = '<<"' + end + + heredoc_stack.push(heredoc) + quote_stack.push(value) + end + when :tSTRING_CONTENT + is_percent_array = percent_array?(quote_stack.last) + + if (lines = token.value.lines).one? + # Prism usually emits a single token for strings with line continuations. + # For squiggly heredocs they are not joined so we do that manually here. + current_string = +"" + current_length = 0 + start_offset = token.location.start_offset + while token.type == :STRING_CONTENT + current_length += token.value.bytesize + # Heredoc interpolation can have multiple STRING_CONTENT nodes on the same line. + is_first_token_on_line = lexed[index - 1] && token.location.start_line != lexed[index - 2][0].location&.start_line + # The parser gem only removes indentation when the heredoc is not nested + not_nested = heredoc_stack.size == 1 + if is_percent_array + value = percent_array_unescape(token.value) + elsif is_first_token_on_line && not_nested && (current_heredoc = heredoc_stack.last).common_whitespace > 0 + value = trim_heredoc_whitespace(token.value, current_heredoc) + end + + current_string << unescape_string(value, quote_stack.last) + relevant_backslash_count = if quote_stack.last.start_with?("%W", "%I") + 0 # the last backslash escapes the newline + else + token.value[/(\\{1,})\n/, 1]&.length || 0 + end + if relevant_backslash_count.even? || !interpolation?(quote_stack.last) + tokens << [:tSTRING_CONTENT, [current_string, range(start_offset, start_offset + current_length)]] + break + end + token = lexed[index][0] + index += 1 + end + else + # When the parser gem encounters a line continuation inside of a multiline string, + # it emits a single string node. The backslash (and remaining newline) is removed. + current_line = +"" + adjustment = 0 + start_offset = token.location.start_offset + emit = false + + lines.each.with_index do |line, index| + chomped_line = line.chomp + backslash_count = chomped_line[/\\{1,}\z/]&.length || 0 + is_interpolation = interpolation?(quote_stack.last) + + if backslash_count.odd? && (is_interpolation || is_percent_array) + if is_percent_array + current_line << percent_array_unescape(line) + adjustment += 1 + else + chomped_line.delete_suffix!("\\") + current_line << chomped_line + adjustment += 2 + end + # If the string ends with a line continuation emit the remainder + emit = index == lines.count - 1 + else + current_line << line + emit = true + end + + if emit + end_offset = start_offset + current_line.bytesize + adjustment + tokens << [:tSTRING_CONTENT, [unescape_string(current_line, quote_stack.last), range(start_offset, end_offset)]] + start_offset = end_offset + current_line = +"" + adjustment = 0 + end + end + end + next + when :tSTRING_DVAR + value = nil + when :tSTRING_END + if token.type == :HEREDOC_END && value.end_with?("\n") + newline_length = value.end_with?("\r\n") ? 2 : 1 + value = heredoc_stack.pop.identifier + location = range(token.location.start_offset, token.location.end_offset - newline_length) + elsif token.type == :REGEXP_END + value = value[0] + location = range(token.location.start_offset, token.location.start_offset + 1) + end + + if percent_array?(quote_stack.pop) + prev_token = lexed[index - 2][0] if index - 2 >= 0 + empty = %i[PERCENT_LOWER_I PERCENT_LOWER_W PERCENT_UPPER_I PERCENT_UPPER_W].include?(prev_token&.type) + ends_with_whitespace = prev_token&.type == :WORDS_SEP + # parser always emits a space token after content in a percent array, even if no actual whitespace is present. + if !empty && !ends_with_whitespace + tokens << [:tSPACE, [nil, range(token.location.start_offset, token.location.start_offset)]] + end + end + when :tSYMBEG + if (next_token = lexed[index][0]) && next_token.type != :STRING_CONTENT && next_token.type != :EMBEXPR_BEGIN && next_token.type != :EMBVAR && next_token.type != :STRING_END + next_location = token.location.join(next_token.location) + type = :tSYMBOL + value = next_token.value + value = { "~@" => "~", "!@" => "!" }.fetch(value, value) + location = range(next_location.start_offset, next_location.end_offset) + index += 1 + else + quote_stack.push(value) + end + when :tFID + if !tokens.empty? && tokens.dig(-1, 0) == :kDEF + type = :tIDENTIFIER + end + when :tXSTRING_BEG + if (next_token = lexed[index][0]) && !%i[STRING_CONTENT STRING_END EMBEXPR_BEGIN].include?(next_token.type) + # self.`() + type = :tBACK_REF2 + end + quote_stack.push(value) + when :tSYMBOLS_BEG, :tQSYMBOLS_BEG, :tWORDS_BEG, :tQWORDS_BEG + if (next_token = lexed[index][0]) && next_token.type == :WORDS_SEP + index += 1 + end + + quote_stack.push(value) + when :tREGEXP_BEG + quote_stack.push(value) + end + + tokens << [type, [value, location]] + + if token.type == :REGEXP_END + tokens << [:tREGEXP_OPT, [token.value[1..], range(token.location.start_offset + 1, token.location.end_offset)]] + end + end + + tokens + end + + private + + # Creates a new parser range, taking prisms byte offsets into account + def range(start_offset, end_offset) + Range.new(source_buffer, offset_cache[start_offset], offset_cache[end_offset]) + end + + # Parse an integer from the string representation. + def parse_integer(value) + Integer(value) + rescue ArgumentError + 0 + end + + # Parse a float from the string representation. + def parse_float(value) + Float(value) + rescue ArgumentError + 0.0 + end + + # Parse a complex from the string representation. + def parse_complex(value) + value.chomp!("i") + + if value.end_with?("r") + Complex(0, parse_rational(value)) + elsif value.start_with?(/0[BbOoDdXx]/) + Complex(0, parse_integer(value)) + else + Complex(0, value) + end + rescue ArgumentError + 0i + end + + # Parse a rational from the string representation. + def parse_rational(value) + value.chomp!("r") + + if value.start_with?(/0[BbOoDdXx]/) + Rational(parse_integer(value)) + else + Rational(value) + end + rescue ArgumentError + 0r + end + + # Wonky heredoc tab/spaces rules. + # https://github.com/ruby/prism/blob/v1.3.0/src/prism.c#L10548-L10558 + def calculate_heredoc_whitespace(heredoc_token_index) + next_token_index = heredoc_token_index + nesting_level = 0 + previous_line = -1 + result = Float::MAX + + while (lexed[next_token_index] && next_token = lexed[next_token_index][0]) + next_token_index += 1 + next_next_token = lexed[next_token_index] && lexed[next_token_index][0] + first_token_on_line = next_token.location.start_column == 0 + + # String content inside nested heredocs and interpolation is ignored + if next_token.type == :HEREDOC_START || next_token.type == :EMBEXPR_BEGIN + # When interpolation is the first token of a line there is no string + # content to check against. There will be no common whitespace. + if nesting_level == 0 && first_token_on_line + result = 0 + end + nesting_level += 1 + elsif next_token.type == :HEREDOC_END || next_token.type == :EMBEXPR_END + nesting_level -= 1 + # When we encountered the matching heredoc end, we can exit + break if nesting_level == -1 + elsif next_token.type == :STRING_CONTENT && nesting_level == 0 && first_token_on_line + common_whitespace = 0 + next_token.value[/^\s*/].each_char do |char| + if char == "\t" + common_whitespace = (common_whitespace / 8 + 1) * 8; + else + common_whitespace += 1 + end + end + + is_first_token_on_line = next_token.location.start_line != previous_line + # Whitespace is significant if followed by interpolation + whitespace_only = common_whitespace == next_token.value.length && next_next_token&.location&.start_line != next_token.location.start_line + if is_first_token_on_line && !whitespace_only && common_whitespace < result + result = common_whitespace + previous_line = next_token.location.start_line + end + end + end + result + end + + # Wonky heredoc tab/spaces rules. + # https://github.com/ruby/prism/blob/v1.3.0/src/prism.c#L16528-L16545 + def trim_heredoc_whitespace(string, heredoc) + trimmed_whitespace = 0 + trimmed_characters = 0 + while (string[trimmed_characters] == "\t" || string[trimmed_characters] == " ") && trimmed_whitespace < heredoc.common_whitespace + if string[trimmed_characters] == "\t" + trimmed_whitespace = (trimmed_whitespace / 8 + 1) * 8; + break if trimmed_whitespace > heredoc.common_whitespace + else + trimmed_whitespace += 1 + end + trimmed_characters += 1 + end + + string[trimmed_characters..] + end + + # Escape sequences that have special and should appear unescaped in the resulting string. + ESCAPES = { + "a" => "\a", "b" => "\b", "e" => "\e", "f" => "\f", + "n" => "\n", "r" => "\r", "s" => "\s", "t" => "\t", + "v" => "\v", "\\" => "\\" + }.freeze + private_constant :ESCAPES + + # When one of these delimiters is encountered, then the other + # one is allowed to be escaped as well. + DELIMITER_SYMETRY = { "[" => "]", "(" => ")", "{" => "}", "<" => ">" }.freeze + private_constant :DELIMITER_SYMETRY + + + # https://github.com/whitequark/parser/blob/v3.3.6.0/lib/parser/lexer-strings.rl#L14 + REGEXP_META_CHARACTERS = ["\\", "$", "(", ")", "*", "+", ".", "<", ">", "?", "[", "]", "^", "{", "|", "}"] + private_constant :REGEXP_META_CHARACTERS + + # Apply Ruby string escaping rules + def unescape_string(string, quote) + # In single-quoted heredocs, everything is taken literally. + return string if quote == "<<'" + + # OPTIMIZATION: Assume that few strings need escaping to speed up the common case. + return string unless string.include?("\\") + + # Enclosing character for the string. `"` for `"foo"`, `{` for `%w{foo}`, etc. + delimiter = quote[-1] + + if regexp?(quote) + # Should be escaped handled to single-quoted heredocs. The only character that is + # allowed to be escaped is the delimiter, except when that also has special meaning + # in the regexp. Since all the symetry delimiters have special meaning, they don't need + # to be considered separately. + if REGEXP_META_CHARACTERS.include?(delimiter) + string + else + # There can never be an even amount of backslashes. It would be a syntax error. + string.gsub(/\\(#{Regexp.escape(delimiter)})/, '\1') + end + elsif interpolation?(quote) + # Appending individual escape sequences may force the string out of its intended + # encoding. Start out with binary and force it back later. + result = "".b + + scanner = StringScanner.new(string) + while (skipped = scanner.skip_until(/\\/)) + # Append what was just skipped over, excluding the found backslash. + result.append_as_bytes(string.byteslice(scanner.pos - skipped, skipped - 1)) + escape_read(result, scanner, false, false) + end + + # Add remaining chars + result.append_as_bytes(string.byteslice(scanner.pos..)) + result.force_encoding(source_buffer.source.encoding) + else + delimiters = Regexp.escape("#{delimiter}#{DELIMITER_SYMETRY[delimiter]}") + string.gsub(/\\([\\#{delimiters}])/, '\1') + end + end + + # Certain strings are merged into a single string token. + def simplify_string?(value, quote) + case quote + when "'" + # Only simplify 'foo' + !value.include?("\n") + when '"' + # Simplify when every line ends with a line continuation, or it is the last line + value.lines.all? do |line| + !line.end_with?("\n") || line[/(\\*)$/, 1]&.length&.odd? + end + else + # %q and similar are never simplified + false + end + end + + # Escape a byte value, given the control and meta flags. + def escape_build(value, control, meta) + value &= 0x9f if control + value |= 0x80 if meta + value + end + + # Read an escape out of the string scanner, given the control and meta + # flags, and push the unescaped value into the result. + def escape_read(result, scanner, control, meta) + if scanner.skip("\n") + # Line continuation + elsif (value = ESCAPES[scanner.peek(1)]) + # Simple single-character escape sequences like \n + result.append_as_bytes(value) + scanner.pos += 1 + elsif (value = scanner.scan(/[0-7]{1,3}/)) + # \nnn + result.append_as_bytes(escape_build(value.to_i(8), control, meta)) + elsif (value = scanner.scan(/x[0-9a-fA-F]{1,2}/)) + # \xnn + result.append_as_bytes(escape_build(value[1..].to_i(16), control, meta)) + elsif (value = scanner.scan(/u[0-9a-fA-F]{4}/)) + # \unnnn + result.append_as_bytes(value[1..].hex.chr(Encoding::UTF_8)) + elsif scanner.skip("u{}") + # https://github.com/whitequark/parser/issues/856 + elsif (value = scanner.scan(/u{.*?}/)) + # \u{nnnn ...} + value[2..-2].split.each do |unicode| + result.append_as_bytes(unicode.hex.chr(Encoding::UTF_8)) + end + elsif (value = scanner.scan(/c\\?(?=[[:print:]])|C-\\?(?=[[:print:]])/)) + # \cx or \C-x where x is an ASCII printable character + escape_read(result, scanner, true, meta) + elsif (value = scanner.scan(/M-\\?(?=[[:print:]])/)) + # \M-x where x is an ASCII printable character + escape_read(result, scanner, control, true) + elsif (byte = scanner.scan_byte) + # Something else after an escape. + if control && byte == 0x3f # ASCII '?' + result.append_as_bytes(escape_build(0x7f, false, meta)) + else + result.append_as_bytes(escape_build(byte, control, meta)) + end + end + end + + # In a percent array, certain whitespace can be preceeded with a backslash, + # causing the following characters to be part of the previous element. + def percent_array_unescape(string) + string.gsub(/(\\)+[ \f\n\r\t\v]/) do |full_match| + full_match.delete_prefix!("\\") if Regexp.last_match[1].length.odd? + full_match + end + end + + # For %-arrays whitespace, the parser gem only considers whitespace before the newline. + def percent_array_leading_whitespace(string) + return 1 if string.start_with?("\n") + + leading_whitespace = 0 + string.each_char do |c| + break if c == "\n" + leading_whitespace += 1 + end + leading_whitespace + end + + # Determine if characters preceeded by a backslash should be escaped or not + def interpolation?(quote) + !quote.end_with?("'") && !quote.start_with?("%q", "%w", "%i", "%s") + end + + # Regexp allow interpolation but are handled differently during unescaping + def regexp?(quote) + quote == "/" || quote.start_with?("%r") + end + + # Determine if the string is part of a %-style array. + def percent_array?(quote) + quote.start_with?("%w", "%W", "%i", "%I") + end + end + end + end +end diff --git a/lib/prism/translation/parser33.rb b/lib/prism/translation/parser33.rb new file mode 100644 index 00000000000000..0a596694655a47 --- /dev/null +++ b/lib/prism/translation/parser33.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true +# :markup: markdown + +module Prism + module Translation + # This class is the entry-point for Ruby 3.3 of `Prism::Translation::Parser`. + class Parser33 < Parser + def version # :nodoc: + 33 + end + end + end +end diff --git a/lib/prism/translation/parser34.rb b/lib/prism/translation/parser34.rb new file mode 100644 index 00000000000000..566a23fadbfc6c --- /dev/null +++ b/lib/prism/translation/parser34.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true +# :markup: markdown + +module Prism + module Translation + # This class is the entry-point for Ruby 3.4 of `Prism::Translation::Parser`. + class Parser34 < Parser + def version # :nodoc: + 34 + end + end + end +end diff --git a/lib/prism/translation/parser35.rb b/lib/prism/translation/parser35.rb new file mode 100644 index 00000000000000..79cd59cbd96a8e --- /dev/null +++ b/lib/prism/translation/parser35.rb @@ -0,0 +1,13 @@ +# frozen_string_literal: true +# :markup: markdown + +module Prism + module Translation + # This class is the entry-point for Ruby 3.5 of `Prism::Translation::Parser`. + class Parser35 < Parser + def version # :nodoc: + 35 + end + end + end +end diff --git a/lib/prism/translation/parser_current.rb b/lib/prism/translation/parser_current.rb new file mode 100644 index 00000000000000..1b1794abbe047a --- /dev/null +++ b/lib/prism/translation/parser_current.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true +# :markup: markdown +# typed: ignore + +# +module Prism + module Translation + case RUBY_VERSION + when /^3\.3\./ + ParserCurrent = Parser33 + when /^3\.4\./ + ParserCurrent = Parser34 + when /^3\.5\./ + ParserCurrent = Parser35 + else + # Keep this in sync with released Ruby. + parser = Parser34 + major, minor, _patch = Gem::Version.new(RUBY_VERSION).segments + warn "warning: `Prism::Translation::Current` is loading #{parser.name}, " \ + "but you are running #{major}.#{minor}." + ParserCurrent = parser + end + end +end diff --git a/lib/prism/translation/ripper.rb b/lib/prism/translation/ripper.rb new file mode 100644 index 00000000000000..6ea98fc1eaa598 --- /dev/null +++ b/lib/prism/translation/ripper.rb @@ -0,0 +1,3474 @@ +# frozen_string_literal: true +# :markup: markdown + +require "ripper" + +module Prism + module Translation + # This class provides a compatibility layer between prism and Ripper. It + # functions by parsing the entire tree first and then walking it and + # executing each of the Ripper callbacks as it goes. To use this class, you + # treat `Prism::Translation::Ripper` effectively as you would treat the + # `Ripper` class. + # + # Note that this class will serve the most common use cases, but Ripper's + # API is extensive and undocumented. It relies on reporting the state of the + # parser at any given time. We do our best to replicate that here, but + # because it is a different architecture it is not possible to perfectly + # replicate the behavior of Ripper. + # + # The main known difference is that we may omit dispatching some events in + # some cases. This impacts the following events: + # + # - on_assign_error + # - on_comma + # - on_ignored_nl + # - on_ignored_sp + # - on_kw + # - on_label_end + # - on_lbrace + # - on_lbracket + # - on_lparen + # - on_nl + # - on_op + # - on_operator_ambiguous + # - on_rbrace + # - on_rbracket + # - on_rparen + # - on_semicolon + # - on_sp + # - on_symbeg + # - on_tstring_beg + # - on_tstring_end + # + class Ripper < Compiler + # Parses the given Ruby program read from +src+. + # +src+ must be a String or an IO or a object with a #gets method. + def self.parse(src, filename = "(ripper)", lineno = 1) + new(src, filename, lineno).parse + end + + # Tokenizes the Ruby program and returns an array of an array, + # which is formatted like + # [[lineno, column], type, token, state]. + # The +filename+ argument is mostly ignored. + # By default, this method does not handle syntax errors in +src+, + # use the +raise_errors+ keyword to raise a SyntaxError for an error in +src+. + # + # require "ripper" + # require "pp" + # + # pp Ripper.lex("def m(a) nil end") + # #=> [[[1, 0], :on_kw, "def", FNAME ], + # [[1, 3], :on_sp, " ", FNAME ], + # [[1, 4], :on_ident, "m", ENDFN ], + # [[1, 5], :on_lparen, "(", BEG|LABEL], + # [[1, 6], :on_ident, "a", ARG ], + # [[1, 7], :on_rparen, ")", ENDFN ], + # [[1, 8], :on_sp, " ", BEG ], + # [[1, 9], :on_kw, "nil", END ], + # [[1, 12], :on_sp, " ", END ], + # [[1, 13], :on_kw, "end", END ]] + # + def self.lex(src, filename = "-", lineno = 1, raise_errors: false) + result = Prism.lex_compat(src, filepath: filename, line: lineno) + + if result.failure? && raise_errors + raise SyntaxError, result.errors.first.message + else + result.value + end + end + + # This contains a table of all of the parser events and their + # corresponding arity. + PARSER_EVENT_TABLE = { + BEGIN: 1, + END: 1, + alias: 2, + alias_error: 2, + aref: 2, + aref_field: 2, + arg_ambiguous: 1, + arg_paren: 1, + args_add: 2, + args_add_block: 2, + args_add_star: 2, + args_forward: 0, + args_new: 0, + array: 1, + aryptn: 4, + assign: 2, + assign_error: 2, + assoc_new: 2, + assoc_splat: 1, + assoclist_from_args: 1, + bare_assoc_hash: 1, + begin: 1, + binary: 3, + block_var: 2, + blockarg: 1, + bodystmt: 4, + brace_block: 2, + break: 1, + call: 3, + case: 2, + class: 3, + class_name_error: 2, + command: 2, + command_call: 4, + const_path_field: 2, + const_path_ref: 2, + const_ref: 1, + def: 3, + defined: 1, + defs: 5, + do_block: 2, + dot2: 2, + dot3: 2, + dyna_symbol: 1, + else: 1, + elsif: 3, + ensure: 1, + excessed_comma: 0, + fcall: 1, + field: 3, + fndptn: 4, + for: 3, + hash: 1, + heredoc_dedent: 2, + hshptn: 3, + if: 3, + if_mod: 2, + ifop: 3, + in: 3, + kwrest_param: 1, + lambda: 2, + magic_comment: 2, + massign: 2, + method_add_arg: 2, + method_add_block: 2, + mlhs_add: 2, + mlhs_add_post: 2, + mlhs_add_star: 2, + mlhs_new: 0, + mlhs_paren: 1, + module: 2, + mrhs_add: 2, + mrhs_add_star: 2, + mrhs_new: 0, + mrhs_new_from_args: 1, + next: 1, + nokw_param: 1, + opassign: 3, + operator_ambiguous: 2, + param_error: 2, + params: 7, + paren: 1, + parse_error: 1, + program: 1, + qsymbols_add: 2, + qsymbols_new: 0, + qwords_add: 2, + qwords_new: 0, + redo: 0, + regexp_add: 2, + regexp_literal: 2, + regexp_new: 0, + rescue: 4, + rescue_mod: 2, + rest_param: 1, + retry: 0, + return: 1, + return0: 0, + sclass: 2, + stmts_add: 2, + stmts_new: 0, + string_add: 2, + string_concat: 2, + string_content: 0, + string_dvar: 1, + string_embexpr: 1, + string_literal: 1, + super: 1, + symbol: 1, + symbol_literal: 1, + symbols_add: 2, + symbols_new: 0, + top_const_field: 1, + top_const_ref: 1, + unary: 2, + undef: 1, + unless: 3, + unless_mod: 2, + until: 2, + until_mod: 2, + var_alias: 2, + var_field: 1, + var_ref: 1, + vcall: 1, + void_stmt: 0, + when: 3, + while: 2, + while_mod: 2, + word_add: 2, + word_new: 0, + words_add: 2, + words_new: 0, + xstring_add: 2, + xstring_literal: 1, + xstring_new: 0, + yield: 1, + yield0: 0, + zsuper: 0 + } + + # This contains a table of all of the scanner events and their + # corresponding arity. + SCANNER_EVENT_TABLE = { + CHAR: 1, + __end__: 1, + backref: 1, + backtick: 1, + comma: 1, + comment: 1, + const: 1, + cvar: 1, + embdoc: 1, + embdoc_beg: 1, + embdoc_end: 1, + embexpr_beg: 1, + embexpr_end: 1, + embvar: 1, + float: 1, + gvar: 1, + heredoc_beg: 1, + heredoc_end: 1, + ident: 1, + ignored_nl: 1, + imaginary: 1, + int: 1, + ivar: 1, + kw: 1, + label: 1, + label_end: 1, + lbrace: 1, + lbracket: 1, + lparen: 1, + nl: 1, + op: 1, + period: 1, + qsymbols_beg: 1, + qwords_beg: 1, + rational: 1, + rbrace: 1, + rbracket: 1, + regexp_beg: 1, + regexp_end: 1, + rparen: 1, + semicolon: 1, + sp: 1, + symbeg: 1, + symbols_beg: 1, + tlambda: 1, + tlambeg: 1, + tstring_beg: 1, + tstring_content: 1, + tstring_end: 1, + words_beg: 1, + words_sep: 1, + ignored_sp: 1 + } + + # This array contains name of parser events. + PARSER_EVENTS = PARSER_EVENT_TABLE.keys + + # This array contains name of scanner events. + SCANNER_EVENTS = SCANNER_EVENT_TABLE.keys + + # This array contains name of all ripper events. + EVENTS = PARSER_EVENTS + SCANNER_EVENTS + + # A list of all of the Ruby keywords. + KEYWORDS = [ + "alias", + "and", + "begin", + "BEGIN", + "break", + "case", + "class", + "def", + "defined?", + "do", + "else", + "elsif", + "end", + "END", + "ensure", + "false", + "for", + "if", + "in", + "module", + "next", + "nil", + "not", + "or", + "redo", + "rescue", + "retry", + "return", + "self", + "super", + "then", + "true", + "undef", + "unless", + "until", + "when", + "while", + "yield", + "__ENCODING__", + "__FILE__", + "__LINE__" + ] + + # A list of all of the Ruby binary operators. + BINARY_OPERATORS = [ + :!=, + :!~, + :=~, + :==, + :===, + :<=>, + :>, + :>=, + :<, + :<=, + :&, + :|, + :^, + :>>, + :<<, + :-, + :+, + :%, + :/, + :*, + :** + ] + + private_constant :KEYWORDS, :BINARY_OPERATORS + + # Parses +src+ and create S-exp tree. + # Returns more readable tree rather than Ripper.sexp_raw. + # This method is mainly for developer use. + # The +filename+ argument is mostly ignored. + # By default, this method does not handle syntax errors in +src+, + # returning +nil+ in such cases. Use the +raise_errors+ keyword + # to raise a SyntaxError for an error in +src+. + # + # require "ripper" + # require "pp" + # + # pp Ripper.sexp("def m(a) nil end") + # #=> [:program, + # [[:def, + # [:@ident, "m", [1, 4]], + # [:paren, [:params, [[:@ident, "a", [1, 6]]], nil, nil, nil, nil, nil, nil]], + # [:bodystmt, [[:var_ref, [:@kw, "nil", [1, 9]]]], nil, nil, nil]]]] + # + def self.sexp(src, filename = "-", lineno = 1, raise_errors: false) + builder = SexpBuilderPP.new(src, filename, lineno) + sexp = builder.parse + if builder.error? + if raise_errors + raise SyntaxError, builder.error + end + else + sexp + end + end + + # Parses +src+ and create S-exp tree. + # This method is mainly for developer use. + # The +filename+ argument is mostly ignored. + # By default, this method does not handle syntax errors in +src+, + # returning +nil+ in such cases. Use the +raise_errors+ keyword + # to raise a SyntaxError for an error in +src+. + # + # require "ripper" + # require "pp" + # + # pp Ripper.sexp_raw("def m(a) nil end") + # #=> [:program, + # [:stmts_add, + # [:stmts_new], + # [:def, + # [:@ident, "m", [1, 4]], + # [:paren, [:params, [[:@ident, "a", [1, 6]]], nil, nil, nil]], + # [:bodystmt, + # [:stmts_add, [:stmts_new], [:var_ref, [:@kw, "nil", [1, 9]]]], + # nil, + # nil, + # nil]]]] + # + def self.sexp_raw(src, filename = "-", lineno = 1, raise_errors: false) + builder = SexpBuilder.new(src, filename, lineno) + sexp = builder.parse + if builder.error? + if raise_errors + raise SyntaxError, builder.error + end + else + sexp + end + end + + autoload :SexpBuilder, "prism/translation/ripper/sexp" + autoload :SexpBuilderPP, "prism/translation/ripper/sexp" + + # The source that is being parsed. + attr_reader :source + + # The filename of the source being parsed. + attr_reader :filename + + # The current line number of the parser. + attr_reader :lineno + + # The current column number of the parser. + attr_reader :column + + # Create a new Translation::Ripper object with the given source. + def initialize(source, filename = "(ripper)", lineno = 1) + @source = source + @filename = filename + @lineno = lineno + @column = 0 + @result = nil + end + + ########################################################################## + # Public interface + ########################################################################## + + # True if the parser encountered an error during parsing. + def error? + result.failure? + end + + # Parse the source and return the result. + def parse + result.comments.each do |comment| + location = comment.location + bounds(location) + + if comment.is_a?(InlineComment) + on_comment(comment.slice) + else + offset = location.start_offset + lines = comment.slice.lines + + lines.each_with_index do |line, index| + bounds(location.copy(start_offset: offset)) + + if index == 0 + on_embdoc_beg(line) + elsif index == lines.size - 1 + on_embdoc_end(line) + else + on_embdoc(line) + end + + offset += line.bytesize + end + end + end + + result.magic_comments.each do |magic_comment| + on_magic_comment(magic_comment.key, magic_comment.value) + end + + unless result.data_loc.nil? + on___end__(result.data_loc.slice.each_line.first) + end + + result.warnings.each do |warning| + bounds(warning.location) + + if warning.level == :default + warning(warning.message) + else + case warning.type + when :ambiguous_first_argument_plus + on_arg_ambiguous("+") + when :ambiguous_first_argument_minus + on_arg_ambiguous("-") + when :ambiguous_slash + on_arg_ambiguous("/") + else + warn(warning.message) + end + end + end + + if error? + result.errors.each do |error| + location = error.location + bounds(location) + + case error.type + when :alias_argument + on_alias_error("can't make alias for the number variables", location.slice) + when :argument_formal_class + on_param_error("formal argument cannot be a class variable", location.slice) + when :argument_format_constant + on_param_error("formal argument cannot be a constant", location.slice) + when :argument_formal_global + on_param_error("formal argument cannot be a global variable", location.slice) + when :argument_formal_ivar + on_param_error("formal argument cannot be an instance variable", location.slice) + when :class_name, :module_name + on_class_name_error("class/module name must be CONSTANT", location.slice) + else + on_parse_error(error.message) + end + end + + nil + else + result.value.accept(self) + end + end + + ########################################################################## + # Visitor methods + ########################################################################## + + # alias foo bar + # ^^^^^^^^^^^^^ + def visit_alias_method_node(node) + new_name = visit(node.new_name) + old_name = visit(node.old_name) + + bounds(node.location) + on_alias(new_name, old_name) + end + + # alias $foo $bar + # ^^^^^^^^^^^^^^^ + def visit_alias_global_variable_node(node) + new_name = visit_alias_global_variable_node_value(node.new_name) + old_name = visit_alias_global_variable_node_value(node.old_name) + + bounds(node.location) + on_var_alias(new_name, old_name) + end + + # Visit one side of an alias global variable node. + private def visit_alias_global_variable_node_value(node) + bounds(node.location) + + case node + when BackReferenceReadNode + on_backref(node.slice) + when GlobalVariableReadNode + on_gvar(node.name.to_s) + else + raise + end + end + + # foo => bar | baz + # ^^^^^^^^^ + def visit_alternation_pattern_node(node) + left = visit_pattern_node(node.left) + right = visit_pattern_node(node.right) + + bounds(node.location) + on_binary(left, :|, right) + end + + # Visit a pattern within a pattern match. This is used to bypass the + # parenthesis node that can be used to wrap patterns. + private def visit_pattern_node(node) + if node.is_a?(ParenthesesNode) + visit(node.body) + else + visit(node) + end + end + + # a and b + # ^^^^^^^ + def visit_and_node(node) + left = visit(node.left) + right = visit(node.right) + + bounds(node.location) + on_binary(left, node.operator.to_sym, right) + end + + # [] + # ^^ + def visit_array_node(node) + case (opening = node.opening) + when /^%w/ + opening_loc = node.opening_loc + bounds(opening_loc) + on_qwords_beg(opening) + + elements = on_qwords_new + previous = nil + + node.elements.each do |element| + visit_words_sep(opening_loc, previous, element) + + bounds(element.location) + elements = on_qwords_add(elements, on_tstring_content(element.content)) + + previous = element + end + + bounds(node.closing_loc) + on_tstring_end(node.closing) + when /^%i/ + opening_loc = node.opening_loc + bounds(opening_loc) + on_qsymbols_beg(opening) + + elements = on_qsymbols_new + previous = nil + + node.elements.each do |element| + visit_words_sep(opening_loc, previous, element) + + bounds(element.location) + elements = on_qsymbols_add(elements, on_tstring_content(element.value)) + + previous = element + end + + bounds(node.closing_loc) + on_tstring_end(node.closing) + when /^%W/ + opening_loc = node.opening_loc + bounds(opening_loc) + on_words_beg(opening) + + elements = on_words_new + previous = nil + + node.elements.each do |element| + visit_words_sep(opening_loc, previous, element) + + bounds(element.location) + elements = + on_words_add( + elements, + if element.is_a?(StringNode) + on_word_add(on_word_new, on_tstring_content(element.content)) + else + element.parts.inject(on_word_new) do |word, part| + word_part = + if part.is_a?(StringNode) + bounds(part.location) + on_tstring_content(part.content) + else + visit(part) + end + + on_word_add(word, word_part) + end + end + ) + + previous = element + end + + bounds(node.closing_loc) + on_tstring_end(node.closing) + when /^%I/ + opening_loc = node.opening_loc + bounds(opening_loc) + on_symbols_beg(opening) + + elements = on_symbols_new + previous = nil + + node.elements.each do |element| + visit_words_sep(opening_loc, previous, element) + + bounds(element.location) + elements = + on_symbols_add( + elements, + if element.is_a?(SymbolNode) + on_word_add(on_word_new, on_tstring_content(element.value)) + else + element.parts.inject(on_word_new) do |word, part| + word_part = + if part.is_a?(StringNode) + bounds(part.location) + on_tstring_content(part.content) + else + visit(part) + end + + on_word_add(word, word_part) + end + end + ) + + previous = element + end + + bounds(node.closing_loc) + on_tstring_end(node.closing) + else + bounds(node.opening_loc) + on_lbracket(opening) + + elements = visit_arguments(node.elements) unless node.elements.empty? + + bounds(node.closing_loc) + on_rbracket(node.closing) + end + + bounds(node.location) + on_array(elements) + end + + # Dispatch a words_sep event that contains the space between the elements + # of list literals. + private def visit_words_sep(opening_loc, previous, current) + end_offset = (previous.nil? ? opening_loc : previous.location).end_offset + start_offset = current.location.start_offset + + if end_offset != start_offset + bounds(current.location.copy(start_offset: end_offset)) + on_words_sep(source.byteslice(end_offset...start_offset)) + end + end + + # Visit a list of elements, like the elements of an array or arguments. + private def visit_arguments(elements) + bounds(elements.first.location) + elements.inject(on_args_new) do |args, element| + arg = visit(element) + bounds(element.location) + + case element + when BlockArgumentNode + on_args_add_block(args, arg) + when SplatNode + on_args_add_star(args, arg) + else + on_args_add(args, arg) + end + end + end + + # foo => [bar] + # ^^^^^ + def visit_array_pattern_node(node) + constant = visit(node.constant) + requireds = visit_all(node.requireds) if node.requireds.any? + rest = + if (rest_node = node.rest).is_a?(SplatNode) + if rest_node.expression.nil? + bounds(rest_node.location) + on_var_field(nil) + else + visit(rest_node.expression) + end + end + + posts = visit_all(node.posts) if node.posts.any? + + bounds(node.location) + on_aryptn(constant, requireds, rest, posts) + end + + # foo(bar) + # ^^^ + def visit_arguments_node(node) + arguments, _ = visit_call_node_arguments(node, nil, false) + arguments + end + + # { a: 1 } + # ^^^^ + def visit_assoc_node(node) + key = visit(node.key) + value = visit(node.value) + + bounds(node.location) + on_assoc_new(key, value) + end + + # def foo(**); bar(**); end + # ^^ + # + # { **foo } + # ^^^^^ + def visit_assoc_splat_node(node) + value = visit(node.value) + + bounds(node.location) + on_assoc_splat(value) + end + + # $+ + # ^^ + def visit_back_reference_read_node(node) + bounds(node.location) + on_backref(node.slice) + end + + # begin end + # ^^^^^^^^^ + def visit_begin_node(node) + clauses = visit_begin_node_clauses(node.begin_keyword_loc, node, false) + + bounds(node.location) + on_begin(clauses) + end + + # Visit the clauses of a begin node to form an on_bodystmt call. + private def visit_begin_node_clauses(location, node, allow_newline) + statements = + if node.statements.nil? + on_stmts_add(on_stmts_new, on_void_stmt) + else + body = node.statements.body + body.unshift(nil) if void_stmt?(location, node.statements.body[0].location, allow_newline) + + bounds(node.statements.location) + visit_statements_node_body(body) + end + + rescue_clause = visit(node.rescue_clause) + else_clause = + unless (else_clause_node = node.else_clause).nil? + else_statements = + if else_clause_node.statements.nil? + [nil] + else + body = else_clause_node.statements.body + body.unshift(nil) if void_stmt?(else_clause_node.else_keyword_loc, else_clause_node.statements.body[0].location, allow_newline) + body + end + + bounds(else_clause_node.location) + visit_statements_node_body(else_statements) + end + ensure_clause = visit(node.ensure_clause) + + bounds(node.location) + on_bodystmt(statements, rescue_clause, else_clause, ensure_clause) + end + + # Visit the body of a structure that can have either a set of statements + # or statements wrapped in rescue/else/ensure. + private def visit_body_node(location, node, allow_newline = false) + case node + when nil + bounds(location) + on_bodystmt(visit_statements_node_body([nil]), nil, nil, nil) + when StatementsNode + body = [*node.body] + body.unshift(nil) if void_stmt?(location, body[0].location, allow_newline) + stmts = visit_statements_node_body(body) + + bounds(node.body.first.location) + on_bodystmt(stmts, nil, nil, nil) + when BeginNode + visit_begin_node_clauses(location, node, allow_newline) + else + raise + end + end + + # foo(&bar) + # ^^^^ + def visit_block_argument_node(node) + visit(node.expression) + end + + # foo { |; bar| } + # ^^^ + def visit_block_local_variable_node(node) + bounds(node.location) + on_ident(node.name.to_s) + end + + # Visit a BlockNode. + def visit_block_node(node) + braces = node.opening == "{" + parameters = visit(node.parameters) + + body = + case node.body + when nil + bounds(node.location) + stmts = on_stmts_add(on_stmts_new, on_void_stmt) + + bounds(node.location) + braces ? stmts : on_bodystmt(stmts, nil, nil, nil) + when StatementsNode + stmts = node.body.body + stmts.unshift(nil) if void_stmt?(node.parameters&.location || node.opening_loc, node.body.location, false) + stmts = visit_statements_node_body(stmts) + + bounds(node.body.location) + braces ? stmts : on_bodystmt(stmts, nil, nil, nil) + when BeginNode + visit_body_node(node.parameters&.location || node.opening_loc, node.body) + else + raise + end + + if braces + bounds(node.location) + on_brace_block(parameters, body) + else + bounds(node.location) + on_do_block(parameters, body) + end + end + + # def foo(&bar); end + # ^^^^ + def visit_block_parameter_node(node) + if node.name_loc.nil? + bounds(node.location) + on_blockarg(nil) + else + bounds(node.name_loc) + name = visit_token(node.name.to_s) + + bounds(node.location) + on_blockarg(name) + end + end + + # A block's parameters. + def visit_block_parameters_node(node) + parameters = + if node.parameters.nil? + on_params(nil, nil, nil, nil, nil, nil, nil) + else + visit(node.parameters) + end + + locals = + if node.locals.any? + visit_all(node.locals) + else + false + end + + bounds(node.location) + on_block_var(parameters, locals) + end + + # break + # ^^^^^ + # + # break foo + # ^^^^^^^^^ + def visit_break_node(node) + if node.arguments.nil? + bounds(node.location) + on_break(on_args_new) + else + arguments = visit(node.arguments) + + bounds(node.location) + on_break(arguments) + end + end + + # foo + # ^^^ + # + # foo.bar + # ^^^^^^^ + # + # foo.bar() {} + # ^^^^^^^^^^^^ + def visit_call_node(node) + if node.call_operator_loc.nil? + case node.name + when :[] + receiver = visit(node.receiver) + arguments, block = visit_call_node_arguments(node.arguments, node.block, trailing_comma?(node.arguments&.location || node.location, node.closing_loc)) + + bounds(node.location) + call = on_aref(receiver, arguments) + + if block.nil? + call + else + bounds(node.location) + on_method_add_block(call, block) + end + when :[]= + receiver = visit(node.receiver) + + *arguments, last_argument = node.arguments.arguments + arguments << node.block if !node.block.nil? + + arguments = + if arguments.any? + args = visit_arguments(arguments) + + if !node.block.nil? + args + else + bounds(arguments.first.location) + on_args_add_block(args, false) + end + end + + bounds(node.location) + call = on_aref_field(receiver, arguments) + value = visit_write_value(last_argument) + + bounds(last_argument.location) + on_assign(call, value) + when :-@, :+@, :~ + receiver = visit(node.receiver) + + bounds(node.location) + on_unary(node.name, receiver) + when :! + if node.message == "not" + receiver = + if !node.receiver.is_a?(ParenthesesNode) || !node.receiver.body.nil? + visit(node.receiver) + end + + bounds(node.location) + on_unary(:not, receiver) + else + receiver = visit(node.receiver) + + bounds(node.location) + on_unary(:!, receiver) + end + when *BINARY_OPERATORS + receiver = visit(node.receiver) + value = visit(node.arguments.arguments.first) + + bounds(node.location) + on_binary(receiver, node.name, value) + else + bounds(node.message_loc) + message = visit_token(node.message, false) + + if node.variable_call? + on_vcall(message) + else + arguments, block = visit_call_node_arguments(node.arguments, node.block, trailing_comma?(node.arguments&.location || node.location, node.closing_loc || node.location)) + call = + if node.opening_loc.nil? && arguments&.any? + bounds(node.location) + on_command(message, arguments) + elsif !node.opening_loc.nil? + bounds(node.location) + on_method_add_arg(on_fcall(message), on_arg_paren(arguments)) + else + bounds(node.location) + on_method_add_arg(on_fcall(message), on_args_new) + end + + if block.nil? + call + else + bounds(node.block.location) + on_method_add_block(call, block) + end + end + end + else + receiver = visit(node.receiver) + + bounds(node.call_operator_loc) + call_operator = visit_token(node.call_operator) + + message = + if node.message_loc.nil? + :call + else + bounds(node.message_loc) + visit_token(node.message, false) + end + + if node.name.end_with?("=") && !node.message.end_with?("=") && !node.arguments.nil? && node.block.nil? + value = visit_write_value(node.arguments.arguments.first) + + bounds(node.location) + on_assign(on_field(receiver, call_operator, message), value) + else + arguments, block = visit_call_node_arguments(node.arguments, node.block, trailing_comma?(node.arguments&.location || node.location, node.closing_loc || node.location)) + call = + if node.opening_loc.nil? + bounds(node.location) + + if node.arguments.nil? && !node.block.is_a?(BlockArgumentNode) + on_call(receiver, call_operator, message) + else + on_command_call(receiver, call_operator, message, arguments) + end + else + bounds(node.opening_loc) + arguments = on_arg_paren(arguments) + + bounds(node.location) + on_method_add_arg(on_call(receiver, call_operator, message), arguments) + end + + if block.nil? + call + else + bounds(node.block.location) + on_method_add_block(call, block) + end + end + end + end + + # Visit the arguments and block of a call node and return the arguments + # and block as they should be used. + private def visit_call_node_arguments(arguments_node, block_node, trailing_comma) + arguments = arguments_node&.arguments || [] + block = block_node + + if block.is_a?(BlockArgumentNode) + arguments << block + block = nil + end + + [ + if arguments.length == 1 && arguments.first.is_a?(ForwardingArgumentsNode) + visit(arguments.first) + elsif arguments.any? + args = visit_arguments(arguments) + + if block_node.is_a?(BlockArgumentNode) || arguments.last.is_a?(ForwardingArgumentsNode) || command?(arguments.last) || trailing_comma + args + else + bounds(arguments.first.location) + on_args_add_block(args, false) + end + end, + visit(block) + ] + end + + # Returns true if the given node is a command node. + private def command?(node) + node.is_a?(CallNode) && + node.opening_loc.nil? && + (!node.arguments.nil? || node.block.is_a?(BlockArgumentNode)) && + !BINARY_OPERATORS.include?(node.name) + end + + # foo.bar += baz + # ^^^^^^^^^^^^^^^ + def visit_call_operator_write_node(node) + receiver = visit(node.receiver) + + bounds(node.call_operator_loc) + call_operator = visit_token(node.call_operator) + + bounds(node.message_loc) + message = visit_token(node.message) + + bounds(node.location) + target = on_field(receiver, call_operator, message) + + bounds(node.binary_operator_loc) + operator = on_op("#{node.binary_operator}=") + value = visit_write_value(node.value) + + bounds(node.location) + on_opassign(target, operator, value) + end + + # foo.bar &&= baz + # ^^^^^^^^^^^^^^^ + def visit_call_and_write_node(node) + receiver = visit(node.receiver) + + bounds(node.call_operator_loc) + call_operator = visit_token(node.call_operator) + + bounds(node.message_loc) + message = visit_token(node.message) + + bounds(node.location) + target = on_field(receiver, call_operator, message) + + bounds(node.operator_loc) + operator = on_op("&&=") + value = visit_write_value(node.value) + + bounds(node.location) + on_opassign(target, operator, value) + end + + # foo.bar ||= baz + # ^^^^^^^^^^^^^^^ + def visit_call_or_write_node(node) + receiver = visit(node.receiver) + + bounds(node.call_operator_loc) + call_operator = visit_token(node.call_operator) + + bounds(node.message_loc) + message = visit_token(node.message) + + bounds(node.location) + target = on_field(receiver, call_operator, message) + + bounds(node.operator_loc) + operator = on_op("||=") + value = visit_write_value(node.value) + + bounds(node.location) + on_opassign(target, operator, value) + end + + # foo.bar, = 1 + # ^^^^^^^ + def visit_call_target_node(node) + if node.call_operator == "::" + receiver = visit(node.receiver) + + bounds(node.message_loc) + message = visit_token(node.message) + + bounds(node.location) + on_const_path_field(receiver, message) + else + receiver = visit(node.receiver) + + bounds(node.call_operator_loc) + call_operator = visit_token(node.call_operator) + + bounds(node.message_loc) + message = visit_token(node.message) + + bounds(node.location) + on_field(receiver, call_operator, message) + end + end + + # foo => bar => baz + # ^^^^^^^^^^ + def visit_capture_pattern_node(node) + value = visit(node.value) + target = visit(node.target) + + bounds(node.location) + on_binary(value, :"=>", target) + end + + # case foo; when bar; end + # ^^^^^^^^^^^^^^^^^^^^^^^ + def visit_case_node(node) + predicate = visit(node.predicate) + clauses = + node.conditions.reverse_each.inject(visit(node.else_clause)) do |current, condition| + on_when(*visit(condition), current) + end + + bounds(node.location) + on_case(predicate, clauses) + end + + # case foo; in bar; end + # ^^^^^^^^^^^^^^^^^^^^^ + def visit_case_match_node(node) + predicate = visit(node.predicate) + clauses = + node.conditions.reverse_each.inject(visit(node.else_clause)) do |current, condition| + on_in(*visit(condition), current) + end + + bounds(node.location) + on_case(predicate, clauses) + end + + # class Foo; end + # ^^^^^^^^^^^^^^ + def visit_class_node(node) + constant_path = + if node.constant_path.is_a?(ConstantReadNode) + bounds(node.constant_path.location) + on_const_ref(on_const(node.constant_path.name.to_s)) + else + visit(node.constant_path) + end + + superclass = visit(node.superclass) + bodystmt = visit_body_node(node.superclass&.location || node.constant_path.location, node.body, node.superclass.nil?) + + bounds(node.location) + on_class(constant_path, superclass, bodystmt) + end + + # @@foo + # ^^^^^ + def visit_class_variable_read_node(node) + bounds(node.location) + on_var_ref(on_cvar(node.slice)) + end + + # @@foo = 1 + # ^^^^^^^^^ + # + # @@foo, @@bar = 1 + # ^^^^^ ^^^^^ + def visit_class_variable_write_node(node) + bounds(node.name_loc) + target = on_var_field(on_cvar(node.name.to_s)) + value = visit_write_value(node.value) + + bounds(node.location) + on_assign(target, value) + end + + # @@foo += bar + # ^^^^^^^^^^^^ + def visit_class_variable_operator_write_node(node) + bounds(node.name_loc) + target = on_var_field(on_cvar(node.name.to_s)) + + bounds(node.binary_operator_loc) + operator = on_op("#{node.binary_operator}=") + value = visit_write_value(node.value) + + bounds(node.location) + on_opassign(target, operator, value) + end + + # @@foo &&= bar + # ^^^^^^^^^^^^^ + def visit_class_variable_and_write_node(node) + bounds(node.name_loc) + target = on_var_field(on_cvar(node.name.to_s)) + + bounds(node.operator_loc) + operator = on_op("&&=") + value = visit_write_value(node.value) + + bounds(node.location) + on_opassign(target, operator, value) + end + + # @@foo ||= bar + # ^^^^^^^^^^^^^ + def visit_class_variable_or_write_node(node) + bounds(node.name_loc) + target = on_var_field(on_cvar(node.name.to_s)) + + bounds(node.operator_loc) + operator = on_op("||=") + value = visit_write_value(node.value) + + bounds(node.location) + on_opassign(target, operator, value) + end + + # @@foo, = bar + # ^^^^^ + def visit_class_variable_target_node(node) + bounds(node.location) + on_var_field(on_cvar(node.name.to_s)) + end + + # Foo + # ^^^ + def visit_constant_read_node(node) + bounds(node.location) + on_var_ref(on_const(node.name.to_s)) + end + + # Foo = 1 + # ^^^^^^^ + # + # Foo, Bar = 1 + # ^^^ ^^^ + def visit_constant_write_node(node) + bounds(node.name_loc) + target = on_var_field(on_const(node.name.to_s)) + value = visit_write_value(node.value) + + bounds(node.location) + on_assign(target, value) + end + + # Foo += bar + # ^^^^^^^^^^^ + def visit_constant_operator_write_node(node) + bounds(node.name_loc) + target = on_var_field(on_const(node.name.to_s)) + + bounds(node.binary_operator_loc) + operator = on_op("#{node.binary_operator}=") + value = visit_write_value(node.value) + + bounds(node.location) + on_opassign(target, operator, value) + end + + # Foo &&= bar + # ^^^^^^^^^^^^ + def visit_constant_and_write_node(node) + bounds(node.name_loc) + target = on_var_field(on_const(node.name.to_s)) + + bounds(node.operator_loc) + operator = on_op("&&=") + value = visit_write_value(node.value) + + bounds(node.location) + on_opassign(target, operator, value) + end + + # Foo ||= bar + # ^^^^^^^^^^^^ + def visit_constant_or_write_node(node) + bounds(node.name_loc) + target = on_var_field(on_const(node.name.to_s)) + + bounds(node.operator_loc) + operator = on_op("||=") + value = visit_write_value(node.value) + + bounds(node.location) + on_opassign(target, operator, value) + end + + # Foo, = bar + # ^^^ + def visit_constant_target_node(node) + bounds(node.location) + on_var_field(on_const(node.name.to_s)) + end + + # Foo::Bar + # ^^^^^^^^ + def visit_constant_path_node(node) + if node.parent.nil? + bounds(node.name_loc) + child = on_const(node.name.to_s) + + bounds(node.location) + on_top_const_ref(child) + else + parent = visit(node.parent) + + bounds(node.name_loc) + child = on_const(node.name.to_s) + + bounds(node.location) + on_const_path_ref(parent, child) + end + end + + # Foo::Bar = 1 + # ^^^^^^^^^^^^ + # + # Foo::Foo, Bar::Bar = 1 + # ^^^^^^^^ ^^^^^^^^ + def visit_constant_path_write_node(node) + target = visit_constant_path_write_node_target(node.target) + value = visit_write_value(node.value) + + bounds(node.location) + on_assign(target, value) + end + + # Visit a constant path that is part of a write node. + private def visit_constant_path_write_node_target(node) + if node.parent.nil? + bounds(node.name_loc) + child = on_const(node.name.to_s) + + bounds(node.location) + on_top_const_field(child) + else + parent = visit(node.parent) + + bounds(node.name_loc) + child = on_const(node.name.to_s) + + bounds(node.location) + on_const_path_field(parent, child) + end + end + + # Foo::Bar += baz + # ^^^^^^^^^^^^^^^ + def visit_constant_path_operator_write_node(node) + target = visit_constant_path_write_node_target(node.target) + value = visit(node.value) + + bounds(node.binary_operator_loc) + operator = on_op("#{node.binary_operator}=") + value = visit_write_value(node.value) + + bounds(node.location) + on_opassign(target, operator, value) + end + + # Foo::Bar &&= baz + # ^^^^^^^^^^^^^^^^ + def visit_constant_path_and_write_node(node) + target = visit_constant_path_write_node_target(node.target) + value = visit(node.value) + + bounds(node.operator_loc) + operator = on_op("&&=") + value = visit_write_value(node.value) + + bounds(node.location) + on_opassign(target, operator, value) + end + + # Foo::Bar ||= baz + # ^^^^^^^^^^^^^^^^ + def visit_constant_path_or_write_node(node) + target = visit_constant_path_write_node_target(node.target) + value = visit(node.value) + + bounds(node.operator_loc) + operator = on_op("||=") + value = visit_write_value(node.value) + + bounds(node.location) + on_opassign(target, operator, value) + end + + # Foo::Bar, = baz + # ^^^^^^^^ + def visit_constant_path_target_node(node) + visit_constant_path_write_node_target(node) + end + + # def foo; end + # ^^^^^^^^^^^^ + # + # def self.foo; end + # ^^^^^^^^^^^^^^^^^ + def visit_def_node(node) + receiver = visit(node.receiver) + operator = + if !node.operator_loc.nil? + bounds(node.operator_loc) + visit_token(node.operator) + end + + bounds(node.name_loc) + name = visit_token(node.name_loc.slice) + + parameters = + if node.parameters.nil? + bounds(node.location) + on_params(nil, nil, nil, nil, nil, nil, nil) + else + visit(node.parameters) + end + + if !node.lparen_loc.nil? + bounds(node.lparen_loc) + parameters = on_paren(parameters) + end + + bodystmt = + if node.equal_loc.nil? + visit_body_node(node.rparen_loc || node.end_keyword_loc, node.body) + else + body = visit(node.body.body.first) + + bounds(node.body.location) + on_bodystmt(body, nil, nil, nil) + end + + bounds(node.location) + if receiver.nil? + on_def(name, parameters, bodystmt) + else + on_defs(receiver, operator, name, parameters, bodystmt) + end + end + + # defined? a + # ^^^^^^^^^^ + # + # defined?(a) + # ^^^^^^^^^^^ + def visit_defined_node(node) + expression = visit(node.value) + + # Very weird circumstances here where something like: + # + # defined? + # (1) + # + # gets parsed in Ruby as having only the `1` expression but in Ripper it + # gets parsed as having a parentheses node. In this case we need to + # synthesize that node to match Ripper's behavior. + if node.lparen_loc && node.keyword_loc.join(node.lparen_loc).slice.include?("\n") + bounds(node.lparen_loc.join(node.rparen_loc)) + expression = on_paren(on_stmts_add(on_stmts_new, expression)) + end + + bounds(node.location) + on_defined(expression) + end + + # if foo then bar else baz end + # ^^^^^^^^^^^^ + def visit_else_node(node) + statements = + if node.statements.nil? + [nil] + else + body = node.statements.body + body.unshift(nil) if void_stmt?(node.else_keyword_loc, node.statements.body[0].location, false) + body + end + + bounds(node.location) + on_else(visit_statements_node_body(statements)) + end + + # "foo #{bar}" + # ^^^^^^ + def visit_embedded_statements_node(node) + bounds(node.opening_loc) + on_embexpr_beg(node.opening) + + statements = + if node.statements.nil? + bounds(node.location) + on_stmts_add(on_stmts_new, on_void_stmt) + else + visit(node.statements) + end + + bounds(node.closing_loc) + on_embexpr_end(node.closing) + + bounds(node.location) + on_string_embexpr(statements) + end + + # "foo #@bar" + # ^^^^^ + def visit_embedded_variable_node(node) + bounds(node.operator_loc) + on_embvar(node.operator) + + variable = visit(node.variable) + + bounds(node.location) + on_string_dvar(variable) + end + + # Visit an EnsureNode node. + def visit_ensure_node(node) + statements = + if node.statements.nil? + [nil] + else + body = node.statements.body + body.unshift(nil) if void_stmt?(node.ensure_keyword_loc, body[0].location, false) + body + end + + statements = visit_statements_node_body(statements) + + bounds(node.location) + on_ensure(statements) + end + + # false + # ^^^^^ + def visit_false_node(node) + bounds(node.location) + on_var_ref(on_kw("false")) + end + + # foo => [*, bar, *] + # ^^^^^^^^^^^ + def visit_find_pattern_node(node) + constant = visit(node.constant) + left = + if node.left.expression.nil? + bounds(node.left.location) + on_var_field(nil) + else + visit(node.left.expression) + end + + requireds = visit_all(node.requireds) if node.requireds.any? + right = + if node.right.expression.nil? + bounds(node.right.location) + on_var_field(nil) + else + visit(node.right.expression) + end + + bounds(node.location) + on_fndptn(constant, left, requireds, right) + end + + # if foo .. bar; end + # ^^^^^^^^^^ + def visit_flip_flop_node(node) + left = visit(node.left) + right = visit(node.right) + + bounds(node.location) + if node.exclude_end? + on_dot3(left, right) + else + on_dot2(left, right) + end + end + + # 1.0 + # ^^^ + def visit_float_node(node) + visit_number_node(node) { |text| on_float(text) } + end + + # for foo in bar do end + # ^^^^^^^^^^^^^^^^^^^^^ + def visit_for_node(node) + index = visit(node.index) + collection = visit(node.collection) + statements = + if node.statements.nil? + bounds(node.location) + on_stmts_add(on_stmts_new, on_void_stmt) + else + visit(node.statements) + end + + bounds(node.location) + on_for(index, collection, statements) + end + + # def foo(...); bar(...); end + # ^^^ + def visit_forwarding_arguments_node(node) + bounds(node.location) + on_args_forward + end + + # def foo(...); end + # ^^^ + def visit_forwarding_parameter_node(node) + bounds(node.location) + on_args_forward + end + + # super + # ^^^^^ + # + # super {} + # ^^^^^^^^ + def visit_forwarding_super_node(node) + if node.block.nil? + bounds(node.location) + on_zsuper + else + block = visit(node.block) + + bounds(node.location) + on_method_add_block(on_zsuper, block) + end + end + + # $foo + # ^^^^ + def visit_global_variable_read_node(node) + bounds(node.location) + on_var_ref(on_gvar(node.name.to_s)) + end + + # $foo = 1 + # ^^^^^^^^ + # + # $foo, $bar = 1 + # ^^^^ ^^^^ + def visit_global_variable_write_node(node) + bounds(node.name_loc) + target = on_var_field(on_gvar(node.name.to_s)) + value = visit_write_value(node.value) + + bounds(node.location) + on_assign(target, value) + end + + # $foo += bar + # ^^^^^^^^^^^ + def visit_global_variable_operator_write_node(node) + bounds(node.name_loc) + target = on_var_field(on_gvar(node.name.to_s)) + + bounds(node.binary_operator_loc) + operator = on_op("#{node.binary_operator}=") + value = visit_write_value(node.value) + + bounds(node.location) + on_opassign(target, operator, value) + end + + # $foo &&= bar + # ^^^^^^^^^^^^ + def visit_global_variable_and_write_node(node) + bounds(node.name_loc) + target = on_var_field(on_gvar(node.name.to_s)) + + bounds(node.operator_loc) + operator = on_op("&&=") + value = visit_write_value(node.value) + + bounds(node.location) + on_opassign(target, operator, value) + end + + # $foo ||= bar + # ^^^^^^^^^^^^ + def visit_global_variable_or_write_node(node) + bounds(node.name_loc) + target = on_var_field(on_gvar(node.name.to_s)) + + bounds(node.operator_loc) + operator = on_op("||=") + value = visit_write_value(node.value) + + bounds(node.location) + on_opassign(target, operator, value) + end + + # $foo, = bar + # ^^^^ + def visit_global_variable_target_node(node) + bounds(node.location) + on_var_field(on_gvar(node.name.to_s)) + end + + # {} + # ^^ + def visit_hash_node(node) + elements = + if node.elements.any? + args = visit_all(node.elements) + + bounds(node.elements.first.location) + on_assoclist_from_args(args) + end + + bounds(node.location) + on_hash(elements) + end + + # foo => {} + # ^^ + def visit_hash_pattern_node(node) + constant = visit(node.constant) + elements = + if node.elements.any? || !node.rest.nil? + node.elements.map do |element| + [ + if (key = element.key).opening_loc.nil? + visit(key) + else + bounds(key.value_loc) + if (value = key.value).empty? + on_string_content + else + on_string_add(on_string_content, on_tstring_content(value)) + end + end, + visit(element.value) + ] + end + end + + rest = + case node.rest + when AssocSplatNode + visit(node.rest.value) + when NoKeywordsParameterNode + bounds(node.rest.location) + on_var_field(visit(node.rest)) + end + + bounds(node.location) + on_hshptn(constant, elements, rest) + end + + # if foo then bar end + # ^^^^^^^^^^^^^^^^^^^ + # + # bar if foo + # ^^^^^^^^^^ + # + # foo ? bar : baz + # ^^^^^^^^^^^^^^^ + def visit_if_node(node) + if node.then_keyword == "?" + predicate = visit(node.predicate) + truthy = visit(node.statements.body.first) + falsy = visit(node.subsequent.statements.body.first) + + bounds(node.location) + on_ifop(predicate, truthy, falsy) + elsif node.statements.nil? || (node.predicate.location.start_offset < node.statements.location.start_offset) + predicate = visit(node.predicate) + statements = + if node.statements.nil? + bounds(node.location) + on_stmts_add(on_stmts_new, on_void_stmt) + else + visit(node.statements) + end + subsequent = visit(node.subsequent) + + bounds(node.location) + if node.if_keyword == "if" + on_if(predicate, statements, subsequent) + else + on_elsif(predicate, statements, subsequent) + end + else + statements = visit(node.statements.body.first) + predicate = visit(node.predicate) + + bounds(node.location) + on_if_mod(predicate, statements) + end + end + + # 1i + # ^^ + def visit_imaginary_node(node) + visit_number_node(node) { |text| on_imaginary(text) } + end + + # { foo: } + # ^^^^ + def visit_implicit_node(node) + end + + # foo { |bar,| } + # ^ + def visit_implicit_rest_node(node) + bounds(node.location) + on_excessed_comma + end + + # case foo; in bar; end + # ^^^^^^^^^^^^^^^^^^^^^ + def visit_in_node(node) + # This is a special case where we're not going to call on_in directly + # because we don't have access to the subsequent. Instead, we'll return + # the component parts and let the parent node handle it. + pattern = visit_pattern_node(node.pattern) + statements = + if node.statements.nil? + bounds(node.location) + on_stmts_add(on_stmts_new, on_void_stmt) + else + visit(node.statements) + end + + [pattern, statements] + end + + # foo[bar] += baz + # ^^^^^^^^^^^^^^^ + def visit_index_operator_write_node(node) + receiver = visit(node.receiver) + arguments, _ = visit_call_node_arguments(node.arguments, node.block, trailing_comma?(node.arguments&.location || node.location, node.closing_loc)) + + bounds(node.location) + target = on_aref_field(receiver, arguments) + + bounds(node.binary_operator_loc) + operator = on_op("#{node.binary_operator}=") + value = visit_write_value(node.value) + + bounds(node.location) + on_opassign(target, operator, value) + end + + # foo[bar] &&= baz + # ^^^^^^^^^^^^^^^^ + def visit_index_and_write_node(node) + receiver = visit(node.receiver) + arguments, _ = visit_call_node_arguments(node.arguments, node.block, trailing_comma?(node.arguments&.location || node.location, node.closing_loc)) + + bounds(node.location) + target = on_aref_field(receiver, arguments) + + bounds(node.operator_loc) + operator = on_op("&&=") + value = visit_write_value(node.value) + + bounds(node.location) + on_opassign(target, operator, value) + end + + # foo[bar] ||= baz + # ^^^^^^^^^^^^^^^^ + def visit_index_or_write_node(node) + receiver = visit(node.receiver) + arguments, _ = visit_call_node_arguments(node.arguments, node.block, trailing_comma?(node.arguments&.location || node.location, node.closing_loc)) + + bounds(node.location) + target = on_aref_field(receiver, arguments) + + bounds(node.operator_loc) + operator = on_op("||=") + value = visit_write_value(node.value) + + bounds(node.location) + on_opassign(target, operator, value) + end + + # foo[bar], = 1 + # ^^^^^^^^ + def visit_index_target_node(node) + receiver = visit(node.receiver) + arguments, _ = visit_call_node_arguments(node.arguments, node.block, trailing_comma?(node.arguments&.location || node.location, node.closing_loc)) + + bounds(node.location) + on_aref_field(receiver, arguments) + end + + # @foo + # ^^^^ + def visit_instance_variable_read_node(node) + bounds(node.location) + on_var_ref(on_ivar(node.name.to_s)) + end + + # @foo = 1 + # ^^^^^^^^ + def visit_instance_variable_write_node(node) + bounds(node.name_loc) + target = on_var_field(on_ivar(node.name.to_s)) + value = visit_write_value(node.value) + + bounds(node.location) + on_assign(target, value) + end + + # @foo += bar + # ^^^^^^^^^^^ + def visit_instance_variable_operator_write_node(node) + bounds(node.name_loc) + target = on_var_field(on_ivar(node.name.to_s)) + + bounds(node.binary_operator_loc) + operator = on_op("#{node.binary_operator}=") + value = visit_write_value(node.value) + + bounds(node.location) + on_opassign(target, operator, value) + end + + # @foo &&= bar + # ^^^^^^^^^^^^ + def visit_instance_variable_and_write_node(node) + bounds(node.name_loc) + target = on_var_field(on_ivar(node.name.to_s)) + + bounds(node.operator_loc) + operator = on_op("&&=") + value = visit_write_value(node.value) + + bounds(node.location) + on_opassign(target, operator, value) + end + + # @foo ||= bar + # ^^^^^^^^^^^^ + def visit_instance_variable_or_write_node(node) + bounds(node.name_loc) + target = on_var_field(on_ivar(node.name.to_s)) + + bounds(node.operator_loc) + operator = on_op("||=") + value = visit_write_value(node.value) + + bounds(node.location) + on_opassign(target, operator, value) + end + + # @foo, = bar + # ^^^^ + def visit_instance_variable_target_node(node) + bounds(node.location) + on_var_field(on_ivar(node.name.to_s)) + end + + # 1 + # ^ + def visit_integer_node(node) + visit_number_node(node) { |text| on_int(text) } + end + + # if /foo #{bar}/ then end + # ^^^^^^^^^^^^ + def visit_interpolated_match_last_line_node(node) + bounds(node.opening_loc) + on_regexp_beg(node.opening) + + bounds(node.parts.first.location) + parts = + node.parts.inject(on_regexp_new) do |content, part| + on_regexp_add(content, visit_string_content(part)) + end + + bounds(node.closing_loc) + closing = on_regexp_end(node.closing) + + bounds(node.location) + on_regexp_literal(parts, closing) + end + + # /foo #{bar}/ + # ^^^^^^^^^^^^ + def visit_interpolated_regular_expression_node(node) + bounds(node.opening_loc) + on_regexp_beg(node.opening) + + bounds(node.parts.first.location) + parts = + node.parts.inject(on_regexp_new) do |content, part| + on_regexp_add(content, visit_string_content(part)) + end + + bounds(node.closing_loc) + closing = on_regexp_end(node.closing) + + bounds(node.location) + on_regexp_literal(parts, closing) + end + + # "foo #{bar}" + # ^^^^^^^^^^^^ + def visit_interpolated_string_node(node) + if node.opening&.start_with?("<<~") + heredoc = visit_heredoc_string_node(node) + + bounds(node.location) + on_string_literal(heredoc) + elsif !node.heredoc? && node.parts.length > 1 && node.parts.any? { |part| (part.is_a?(StringNode) || part.is_a?(InterpolatedStringNode)) && !part.opening_loc.nil? } + first, *rest = node.parts + rest.inject(visit(first)) do |content, part| + concat = visit(part) + + bounds(part.location) + on_string_concat(content, concat) + end + else + bounds(node.parts.first.location) + parts = + node.parts.inject(on_string_content) do |content, part| + on_string_add(content, visit_string_content(part)) + end + + bounds(node.location) + on_string_literal(parts) + end + end + + # :"foo #{bar}" + # ^^^^^^^^^^^^^ + def visit_interpolated_symbol_node(node) + bounds(node.parts.first.location) + parts = + node.parts.inject(on_string_content) do |content, part| + on_string_add(content, visit_string_content(part)) + end + + bounds(node.location) + on_dyna_symbol(parts) + end + + # `foo #{bar}` + # ^^^^^^^^^^^^ + def visit_interpolated_x_string_node(node) + if node.opening.start_with?("<<~") + heredoc = visit_heredoc_x_string_node(node) + + bounds(node.location) + on_xstring_literal(heredoc) + else + bounds(node.parts.first.location) + parts = + node.parts.inject(on_xstring_new) do |content, part| + on_xstring_add(content, visit_string_content(part)) + end + + bounds(node.location) + on_xstring_literal(parts) + end + end + + # Visit an individual part of a string-like node. + private def visit_string_content(part) + if part.is_a?(StringNode) + bounds(part.content_loc) + on_tstring_content(part.content) + else + visit(part) + end + end + + # -> { it } + # ^^ + def visit_it_local_variable_read_node(node) + bounds(node.location) + on_vcall(on_ident(node.slice)) + end + + # -> { it } + # ^^^^^^^^^ + def visit_it_parameters_node(node) + end + + # foo(bar: baz) + # ^^^^^^^^ + def visit_keyword_hash_node(node) + elements = visit_all(node.elements) + + bounds(node.location) + on_bare_assoc_hash(elements) + end + + # def foo(**bar); end + # ^^^^^ + # + # def foo(**); end + # ^^ + def visit_keyword_rest_parameter_node(node) + if node.name_loc.nil? + bounds(node.location) + on_kwrest_param(nil) + else + bounds(node.name_loc) + name = on_ident(node.name.to_s) + + bounds(node.location) + on_kwrest_param(name) + end + end + + # -> {} + def visit_lambda_node(node) + bounds(node.operator_loc) + on_tlambda(node.operator) + + parameters = + if node.parameters.is_a?(BlockParametersNode) + # Ripper does not track block-locals within lambdas, so we skip + # directly to the parameters here. + params = + if node.parameters.parameters.nil? + bounds(node.location) + on_params(nil, nil, nil, nil, nil, nil, nil) + else + visit(node.parameters.parameters) + end + + if node.parameters.opening_loc.nil? + params + else + bounds(node.parameters.opening_loc) + on_paren(params) + end + else + bounds(node.location) + on_params(nil, nil, nil, nil, nil, nil, nil) + end + + braces = node.opening == "{" + if braces + bounds(node.opening_loc) + on_tlambeg(node.opening) + end + + body = + case node.body + when nil + bounds(node.location) + stmts = on_stmts_add(on_stmts_new, on_void_stmt) + + bounds(node.location) + braces ? stmts : on_bodystmt(stmts, nil, nil, nil) + when StatementsNode + stmts = node.body.body + stmts.unshift(nil) if void_stmt?(node.parameters&.location || node.opening_loc, node.body.location, false) + stmts = visit_statements_node_body(stmts) + + bounds(node.body.location) + braces ? stmts : on_bodystmt(stmts, nil, nil, nil) + when BeginNode + visit_body_node(node.opening_loc, node.body) + else + raise + end + + bounds(node.location) + on_lambda(parameters, body) + end + + # foo + # ^^^ + def visit_local_variable_read_node(node) + bounds(node.location) + on_var_ref(on_ident(node.slice)) + end + + # foo = 1 + # ^^^^^^^ + def visit_local_variable_write_node(node) + bounds(node.name_loc) + target = on_var_field(on_ident(node.name_loc.slice)) + value = visit_write_value(node.value) + + bounds(node.location) + on_assign(target, value) + end + + # foo += bar + # ^^^^^^^^^^ + def visit_local_variable_operator_write_node(node) + bounds(node.name_loc) + target = on_var_field(on_ident(node.name_loc.slice)) + + bounds(node.binary_operator_loc) + operator = on_op("#{node.binary_operator}=") + value = visit_write_value(node.value) + + bounds(node.location) + on_opassign(target, operator, value) + end + + # foo &&= bar + # ^^^^^^^^^^^ + def visit_local_variable_and_write_node(node) + bounds(node.name_loc) + target = on_var_field(on_ident(node.name_loc.slice)) + + bounds(node.operator_loc) + operator = on_op("&&=") + value = visit_write_value(node.value) + + bounds(node.location) + on_opassign(target, operator, value) + end + + # foo ||= bar + # ^^^^^^^^^^^ + def visit_local_variable_or_write_node(node) + bounds(node.name_loc) + target = on_var_field(on_ident(node.name_loc.slice)) + + bounds(node.operator_loc) + operator = on_op("||=") + value = visit_write_value(node.value) + + bounds(node.location) + on_opassign(target, operator, value) + end + + # foo, = bar + # ^^^ + def visit_local_variable_target_node(node) + bounds(node.location) + on_var_field(on_ident(node.name.to_s)) + end + + # if /foo/ then end + # ^^^^^ + def visit_match_last_line_node(node) + bounds(node.opening_loc) + on_regexp_beg(node.opening) + + bounds(node.content_loc) + tstring_content = on_tstring_content(node.content) + + bounds(node.closing_loc) + closing = on_regexp_end(node.closing) + + on_regexp_literal(on_regexp_add(on_regexp_new, tstring_content), closing) + end + + # foo in bar + # ^^^^^^^^^^ + def visit_match_predicate_node(node) + value = visit(node.value) + pattern = on_in(visit_pattern_node(node.pattern), nil, nil) + + on_case(value, pattern) + end + + # foo => bar + # ^^^^^^^^^^ + def visit_match_required_node(node) + value = visit(node.value) + pattern = on_in(visit_pattern_node(node.pattern), nil, nil) + + on_case(value, pattern) + end + + # /(?foo)/ =~ bar + # ^^^^^^^^^^^^^^^^^^^^ + def visit_match_write_node(node) + visit(node.call) + end + + # A node that is missing from the syntax tree. This is only used in the + # case of a syntax error. + def visit_missing_node(node) + raise "Cannot visit missing nodes directly." + end + + # module Foo; end + # ^^^^^^^^^^^^^^^ + def visit_module_node(node) + constant_path = + if node.constant_path.is_a?(ConstantReadNode) + bounds(node.constant_path.location) + on_const_ref(on_const(node.constant_path.name.to_s)) + else + visit(node.constant_path) + end + + bodystmt = visit_body_node(node.constant_path.location, node.body, true) + + bounds(node.location) + on_module(constant_path, bodystmt) + end + + # (foo, bar), bar = qux + # ^^^^^^^^^^ + def visit_multi_target_node(node) + bounds(node.location) + targets = visit_multi_target_node_targets(node.lefts, node.rest, node.rights, true) + + if node.lparen_loc.nil? + targets + else + bounds(node.lparen_loc) + on_mlhs_paren(targets) + end + end + + # Visit the targets of a multi-target node. + private def visit_multi_target_node_targets(lefts, rest, rights, skippable) + if skippable && lefts.length == 1 && lefts.first.is_a?(MultiTargetNode) && rest.nil? && rights.empty? + return visit(lefts.first) + end + + mlhs = on_mlhs_new + + lefts.each do |left| + bounds(left.location) + mlhs = on_mlhs_add(mlhs, visit(left)) + end + + case rest + when nil + # do nothing + when ImplicitRestNode + # these do not get put into the generated tree + bounds(rest.location) + on_excessed_comma + else + bounds(rest.location) + mlhs = on_mlhs_add_star(mlhs, visit(rest)) + end + + if rights.any? + bounds(rights.first.location) + post = on_mlhs_new + + rights.each do |right| + bounds(right.location) + post = on_mlhs_add(post, visit(right)) + end + + mlhs = on_mlhs_add_post(mlhs, post) + end + + mlhs + end + + # foo, bar = baz + # ^^^^^^^^^^^^^^ + def visit_multi_write_node(node) + bounds(node.location) + targets = visit_multi_target_node_targets(node.lefts, node.rest, node.rights, true) + + unless node.lparen_loc.nil? + bounds(node.lparen_loc) + targets = on_mlhs_paren(targets) + end + + value = visit_write_value(node.value) + + bounds(node.location) + on_massign(targets, value) + end + + # next + # ^^^^ + # + # next foo + # ^^^^^^^^ + def visit_next_node(node) + if node.arguments.nil? + bounds(node.location) + on_next(on_args_new) + else + arguments = visit(node.arguments) + + bounds(node.location) + on_next(arguments) + end + end + + # nil + # ^^^ + def visit_nil_node(node) + bounds(node.location) + on_var_ref(on_kw("nil")) + end + + # def foo(**nil); end + # ^^^^^ + def visit_no_keywords_parameter_node(node) + bounds(node.location) + on_nokw_param(nil) + + :nil + end + + # -> { _1 + _2 } + # ^^^^^^^^^^^^^^ + def visit_numbered_parameters_node(node) + end + + # $1 + # ^^ + def visit_numbered_reference_read_node(node) + bounds(node.location) + on_backref(node.slice) + end + + # def foo(bar: baz); end + # ^^^^^^^^ + def visit_optional_keyword_parameter_node(node) + bounds(node.name_loc) + name = on_label("#{node.name}:") + value = visit(node.value) + + [name, value] + end + + # def foo(bar = 1); end + # ^^^^^^^ + def visit_optional_parameter_node(node) + bounds(node.name_loc) + name = visit_token(node.name.to_s) + value = visit(node.value) + + [name, value] + end + + # a or b + # ^^^^^^ + def visit_or_node(node) + left = visit(node.left) + right = visit(node.right) + + bounds(node.location) + on_binary(left, node.operator.to_sym, right) + end + + # def foo(bar, *baz); end + # ^^^^^^^^^ + def visit_parameters_node(node) + requireds = node.requireds.map { |required| required.is_a?(MultiTargetNode) ? visit_destructured_parameter_node(required) : visit(required) } if node.requireds.any? + optionals = visit_all(node.optionals) if node.optionals.any? + rest = visit(node.rest) + posts = node.posts.map { |post| post.is_a?(MultiTargetNode) ? visit_destructured_parameter_node(post) : visit(post) } if node.posts.any? + keywords = visit_all(node.keywords) if node.keywords.any? + keyword_rest = visit(node.keyword_rest) + block = visit(node.block) + + bounds(node.location) + on_params(requireds, optionals, rest, posts, keywords, keyword_rest, block) + end + + # Visit a destructured positional parameter node. + private def visit_destructured_parameter_node(node) + bounds(node.location) + targets = visit_multi_target_node_targets(node.lefts, node.rest, node.rights, false) + + bounds(node.lparen_loc) + on_mlhs_paren(targets) + end + + # () + # ^^ + # + # (1) + # ^^^ + def visit_parentheses_node(node) + body = + if node.body.nil? + on_stmts_add(on_stmts_new, on_void_stmt) + else + visit(node.body) + end + + bounds(node.location) + on_paren(body) + end + + # foo => ^(bar) + # ^^^^^^ + def visit_pinned_expression_node(node) + expression = visit(node.expression) + + bounds(node.location) + on_begin(expression) + end + + # foo = 1 and bar => ^foo + # ^^^^ + def visit_pinned_variable_node(node) + visit(node.variable) + end + + # END {} + # ^^^^^^ + def visit_post_execution_node(node) + statements = + if node.statements.nil? + bounds(node.location) + on_stmts_add(on_stmts_new, on_void_stmt) + else + visit(node.statements) + end + + bounds(node.location) + on_END(statements) + end + + # BEGIN {} + # ^^^^^^^^ + def visit_pre_execution_node(node) + statements = + if node.statements.nil? + bounds(node.location) + on_stmts_add(on_stmts_new, on_void_stmt) + else + visit(node.statements) + end + + bounds(node.location) + on_BEGIN(statements) + end + + # The top-level program node. + def visit_program_node(node) + body = node.statements.body + body << nil if body.empty? + statements = visit_statements_node_body(body) + + bounds(node.location) + on_program(statements) + end + + # 0..5 + # ^^^^ + def visit_range_node(node) + left = visit(node.left) + right = visit(node.right) + + bounds(node.location) + if node.exclude_end? + on_dot3(left, right) + else + on_dot2(left, right) + end + end + + # 1r + # ^^ + def visit_rational_node(node) + visit_number_node(node) { |text| on_rational(text) } + end + + # redo + # ^^^^ + def visit_redo_node(node) + bounds(node.location) + on_redo + end + + # /foo/ + # ^^^^^ + def visit_regular_expression_node(node) + bounds(node.opening_loc) + on_regexp_beg(node.opening) + + if node.content.empty? + bounds(node.closing_loc) + closing = on_regexp_end(node.closing) + + on_regexp_literal(on_regexp_new, closing) + else + bounds(node.content_loc) + tstring_content = on_tstring_content(node.content) + + bounds(node.closing_loc) + closing = on_regexp_end(node.closing) + + on_regexp_literal(on_regexp_add(on_regexp_new, tstring_content), closing) + end + end + + # def foo(bar:); end + # ^^^^ + def visit_required_keyword_parameter_node(node) + bounds(node.name_loc) + [on_label("#{node.name}:"), false] + end + + # def foo(bar); end + # ^^^ + def visit_required_parameter_node(node) + bounds(node.location) + on_ident(node.name.to_s) + end + + # foo rescue bar + # ^^^^^^^^^^^^^^ + def visit_rescue_modifier_node(node) + expression = visit_write_value(node.expression) + rescue_expression = visit(node.rescue_expression) + + bounds(node.location) + on_rescue_mod(expression, rescue_expression) + end + + # begin; rescue; end + # ^^^^^^^ + def visit_rescue_node(node) + exceptions = + case node.exceptions.length + when 0 + nil + when 1 + if (exception = node.exceptions.first).is_a?(SplatNode) + bounds(exception.location) + on_mrhs_add_star(on_mrhs_new, visit(exception)) + else + [visit(node.exceptions.first)] + end + else + bounds(node.location) + length = node.exceptions.length + + node.exceptions.each_with_index.inject(on_args_new) do |mrhs, (exception, index)| + arg = visit(exception) + + bounds(exception.location) + mrhs = on_mrhs_new_from_args(mrhs) if index == length - 1 + + if exception.is_a?(SplatNode) + if index == length - 1 + on_mrhs_add_star(mrhs, arg) + else + on_args_add_star(mrhs, arg) + end + else + if index == length - 1 + on_mrhs_add(mrhs, arg) + else + on_args_add(mrhs, arg) + end + end + end + end + + reference = visit(node.reference) + statements = + if node.statements.nil? + bounds(node.location) + on_stmts_add(on_stmts_new, on_void_stmt) + else + visit(node.statements) + end + + subsequent = visit(node.subsequent) + + bounds(node.location) + on_rescue(exceptions, reference, statements, subsequent) + end + + # def foo(*bar); end + # ^^^^ + # + # def foo(*); end + # ^ + def visit_rest_parameter_node(node) + if node.name_loc.nil? + bounds(node.location) + on_rest_param(nil) + else + bounds(node.name_loc) + on_rest_param(visit_token(node.name.to_s)) + end + end + + # retry + # ^^^^^ + def visit_retry_node(node) + bounds(node.location) + on_retry + end + + # return + # ^^^^^^ + # + # return 1 + # ^^^^^^^^ + def visit_return_node(node) + if node.arguments.nil? + bounds(node.location) + on_return0 + else + arguments = visit(node.arguments) + + bounds(node.location) + on_return(arguments) + end + end + + # self + # ^^^^ + def visit_self_node(node) + bounds(node.location) + on_var_ref(on_kw("self")) + end + + # A shareable constant. + def visit_shareable_constant_node(node) + visit(node.write) + end + + # class << self; end + # ^^^^^^^^^^^^^^^^^^ + def visit_singleton_class_node(node) + expression = visit(node.expression) + bodystmt = visit_body_node(node.body&.location || node.end_keyword_loc, node.body) + + bounds(node.location) + on_sclass(expression, bodystmt) + end + + # __ENCODING__ + # ^^^^^^^^^^^^ + def visit_source_encoding_node(node) + bounds(node.location) + on_var_ref(on_kw("__ENCODING__")) + end + + # __FILE__ + # ^^^^^^^^ + def visit_source_file_node(node) + bounds(node.location) + on_var_ref(on_kw("__FILE__")) + end + + # __LINE__ + # ^^^^^^^^ + def visit_source_line_node(node) + bounds(node.location) + on_var_ref(on_kw("__LINE__")) + end + + # foo(*bar) + # ^^^^ + # + # def foo((bar, *baz)); end + # ^^^^ + # + # def foo(*); bar(*); end + # ^ + def visit_splat_node(node) + visit(node.expression) + end + + # A list of statements. + def visit_statements_node(node) + bounds(node.location) + visit_statements_node_body(node.body) + end + + # Visit the list of statements of a statements node. We support nil + # statements in the list. This would normally not be allowed by the + # structure of the prism parse tree, but we manually add them here so that + # we can mirror Ripper's void stmt. + private def visit_statements_node_body(body) + body.inject(on_stmts_new) do |stmts, stmt| + on_stmts_add(stmts, stmt.nil? ? on_void_stmt : visit(stmt)) + end + end + + # "foo" + # ^^^^^ + def visit_string_node(node) + if (content = node.content).empty? + bounds(node.location) + on_string_literal(on_string_content) + elsif (opening = node.opening) == "?" + bounds(node.location) + on_CHAR("?#{node.content}") + elsif opening.start_with?("<<~") + heredoc = visit_heredoc_string_node(node.to_interpolated) + + bounds(node.location) + on_string_literal(heredoc) + else + bounds(node.content_loc) + tstring_content = on_tstring_content(content) + + bounds(node.location) + on_string_literal(on_string_add(on_string_content, tstring_content)) + end + end + + # Ripper gives back the escaped string content but strips out the common + # leading whitespace. Prism gives back the unescaped string content and + # a location for the escaped string content. Unfortunately these don't + # work well together, so here we need to re-derive the common leading + # whitespace. + private def visit_heredoc_node_whitespace(parts) + common_whitespace = nil + dedent_next = true + + parts.each do |part| + if part.is_a?(StringNode) + if dedent_next && !(content = part.content).chomp.empty? + common_whitespace = [ + common_whitespace || Float::INFINITY, + content[/\A\s*/].each_char.inject(0) do |part_whitespace, char| + char == "\t" ? ((part_whitespace / 8 + 1) * 8) : (part_whitespace + 1) + end + ].min + end + + dedent_next = true + else + dedent_next = false + end + end + + common_whitespace || 0 + end + + # Visit a string that is expressed using a <<~ heredoc. + private def visit_heredoc_node(parts, base) + common_whitespace = visit_heredoc_node_whitespace(parts) + + if common_whitespace == 0 + bounds(parts.first.location) + + string = [] + result = base + + parts.each do |part| + if part.is_a?(StringNode) + if string.empty? + string = [part] + else + string << part + end + else + unless string.empty? + bounds(string[0].location) + result = yield result, on_tstring_content(string.map(&:content).join) + string = [] + end + + result = yield result, visit(part) + end + end + + unless string.empty? + bounds(string[0].location) + result = yield result, on_tstring_content(string.map(&:content).join) + end + + result + else + bounds(parts.first.location) + result = + parts.inject(base) do |string_content, part| + yield string_content, visit_string_content(part) + end + + bounds(parts.first.location) + on_heredoc_dedent(result, common_whitespace) + end + end + + # Visit a heredoc node that is representing a string. + private def visit_heredoc_string_node(node) + bounds(node.opening_loc) + on_heredoc_beg(node.opening) + + bounds(node.location) + result = + visit_heredoc_node(node.parts, on_string_content) do |parts, part| + on_string_add(parts, part) + end + + bounds(node.closing_loc) + on_heredoc_end(node.closing) + + result + end + + # Visit a heredoc node that is representing an xstring. + private def visit_heredoc_x_string_node(node) + bounds(node.opening_loc) + on_heredoc_beg(node.opening) + + bounds(node.location) + result = + visit_heredoc_node(node.parts, on_xstring_new) do |parts, part| + on_xstring_add(parts, part) + end + + bounds(node.closing_loc) + on_heredoc_end(node.closing) + + result + end + + # super(foo) + # ^^^^^^^^^^ + def visit_super_node(node) + arguments, block = visit_call_node_arguments(node.arguments, node.block, trailing_comma?(node.arguments&.location || node.location, node.rparen_loc || node.location)) + + if !node.lparen_loc.nil? + bounds(node.lparen_loc) + arguments = on_arg_paren(arguments) + end + + bounds(node.location) + call = on_super(arguments) + + if block.nil? + call + else + bounds(node.block.location) + on_method_add_block(call, block) + end + end + + # :foo + # ^^^^ + def visit_symbol_node(node) + if (opening = node.opening)&.match?(/^%s|['"]:?$/) + bounds(node.value_loc) + content = on_string_content + + if !(value = node.value).empty? + content = on_string_add(content, on_tstring_content(value)) + end + + on_dyna_symbol(content) + elsif (closing = node.closing) == ":" + bounds(node.location) + on_label("#{node.value}:") + elsif opening.nil? && node.closing_loc.nil? + bounds(node.value_loc) + on_symbol_literal(visit_token(node.value)) + else + bounds(node.value_loc) + on_symbol_literal(on_symbol(visit_token(node.value))) + end + end + + # true + # ^^^^ + def visit_true_node(node) + bounds(node.location) + on_var_ref(on_kw("true")) + end + + # undef foo + # ^^^^^^^^^ + def visit_undef_node(node) + names = visit_all(node.names) + + bounds(node.location) + on_undef(names) + end + + # unless foo; bar end + # ^^^^^^^^^^^^^^^^^^^ + # + # bar unless foo + # ^^^^^^^^^^^^^^ + def visit_unless_node(node) + if node.statements.nil? || (node.predicate.location.start_offset < node.statements.location.start_offset) + predicate = visit(node.predicate) + statements = + if node.statements.nil? + bounds(node.location) + on_stmts_add(on_stmts_new, on_void_stmt) + else + visit(node.statements) + end + else_clause = visit(node.else_clause) + + bounds(node.location) + on_unless(predicate, statements, else_clause) + else + statements = visit(node.statements.body.first) + predicate = visit(node.predicate) + + bounds(node.location) + on_unless_mod(predicate, statements) + end + end + + # until foo; bar end + # ^^^^^^^^^^^^^^^^^ + # + # bar until foo + # ^^^^^^^^^^^^^ + def visit_until_node(node) + if node.statements.nil? || (node.predicate.location.start_offset < node.statements.location.start_offset) + predicate = visit(node.predicate) + statements = + if node.statements.nil? + bounds(node.location) + on_stmts_add(on_stmts_new, on_void_stmt) + else + visit(node.statements) + end + + bounds(node.location) + on_until(predicate, statements) + else + statements = visit(node.statements.body.first) + predicate = visit(node.predicate) + + bounds(node.location) + on_until_mod(predicate, statements) + end + end + + # case foo; when bar; end + # ^^^^^^^^^^^^^ + def visit_when_node(node) + # This is a special case where we're not going to call on_when directly + # because we don't have access to the subsequent. Instead, we'll return + # the component parts and let the parent node handle it. + conditions = visit_arguments(node.conditions) + statements = + if node.statements.nil? + bounds(node.location) + on_stmts_add(on_stmts_new, on_void_stmt) + else + visit(node.statements) + end + + [conditions, statements] + end + + # while foo; bar end + # ^^^^^^^^^^^^^^^^^^ + # + # bar while foo + # ^^^^^^^^^^^^^ + def visit_while_node(node) + if node.statements.nil? || (node.predicate.location.start_offset < node.statements.location.start_offset) + predicate = visit(node.predicate) + statements = + if node.statements.nil? + bounds(node.location) + on_stmts_add(on_stmts_new, on_void_stmt) + else + visit(node.statements) + end + + bounds(node.location) + on_while(predicate, statements) + else + statements = visit(node.statements.body.first) + predicate = visit(node.predicate) + + bounds(node.location) + on_while_mod(predicate, statements) + end + end + + # `foo` + # ^^^^^ + def visit_x_string_node(node) + if node.unescaped.empty? + bounds(node.location) + on_xstring_literal(on_xstring_new) + elsif node.opening.start_with?("<<~") + heredoc = visit_heredoc_x_string_node(node.to_interpolated) + + bounds(node.location) + on_xstring_literal(heredoc) + else + bounds(node.content_loc) + content = on_tstring_content(node.content) + + bounds(node.location) + on_xstring_literal(on_xstring_add(on_xstring_new, content)) + end + end + + # yield + # ^^^^^ + # + # yield 1 + # ^^^^^^^ + def visit_yield_node(node) + if node.arguments.nil? && node.lparen_loc.nil? + bounds(node.location) + on_yield0 + else + arguments = + if node.arguments.nil? + bounds(node.location) + on_args_new + else + visit(node.arguments) + end + + unless node.lparen_loc.nil? + bounds(node.lparen_loc) + arguments = on_paren(arguments) + end + + bounds(node.location) + on_yield(arguments) + end + end + + private + + # Lazily initialize the parse result. + def result + @result ||= Prism.parse(source, partial_script: true) + end + + ########################################################################## + # Helpers + ########################################################################## + + # Returns true if there is a comma between the two locations. + def trailing_comma?(left, right) + source.byteslice(left.end_offset...right.start_offset).include?(",") + end + + # Returns true if there is a semicolon between the two locations. + def void_stmt?(left, right, allow_newline) + pattern = allow_newline ? /[;\n]/ : /;/ + source.byteslice(left.end_offset...right.start_offset).match?(pattern) + end + + # Visit the string content of a particular node. This method is used to + # split into the various token types. + def visit_token(token, allow_keywords = true) + case token + when "." + on_period(token) + when "`" + on_backtick(token) + when *(allow_keywords ? KEYWORDS : []) + on_kw(token) + when /^_/ + on_ident(token) + when /^[[:upper:]]\w*$/ + on_const(token) + when /^@@/ + on_cvar(token) + when /^@/ + on_ivar(token) + when /^\$/ + on_gvar(token) + when /^[[:punct:]]/ + on_op(token) + else + on_ident(token) + end + end + + # Visit a node that represents a number. We need to explicitly handle the + # unary - operator. + def visit_number_node(node) + slice = node.slice + location = node.location + + if slice[0] == "-" + bounds(location.copy(start_offset: location.start_offset + 1)) + value = yield slice[1..-1] + + bounds(node.location) + on_unary(:-@, value) + else + bounds(location) + yield slice + end + end + + # Visit a node that represents a write value. This is used to handle the + # special case of an implicit array that is generated without brackets. + def visit_write_value(node) + if node.is_a?(ArrayNode) && node.opening_loc.nil? + elements = node.elements + length = elements.length + + bounds(elements.first.location) + elements.each_with_index.inject((elements.first.is_a?(SplatNode) && length == 1) ? on_mrhs_new : on_args_new) do |args, (element, index)| + arg = visit(element) + bounds(element.location) + + if index == length - 1 + if element.is_a?(SplatNode) + mrhs = index == 0 ? args : on_mrhs_new_from_args(args) + on_mrhs_add_star(mrhs, arg) + else + on_mrhs_add(on_mrhs_new_from_args(args), arg) + end + else + case element + when BlockArgumentNode + on_args_add_block(args, arg) + when SplatNode + on_args_add_star(args, arg) + else + on_args_add(args, arg) + end + end + end + else + visit(node) + end + end + + # This method is responsible for updating lineno and column information + # to reflect the current node. + # + # This method could be drastically improved with some caching on the start + # of every line, but for now it's good enough. + def bounds(location) + @lineno = location.start_line + @column = location.start_column + end + + ########################################################################## + # Ripper interface + ########################################################################## + + # :stopdoc: + def _dispatch_0; end + def _dispatch_1(_); end + def _dispatch_2(_, _); end + def _dispatch_3(_, _, _); end + def _dispatch_4(_, _, _, _); end + def _dispatch_5(_, _, _, _, _); end + def _dispatch_7(_, _, _, _, _, _, _); end + # :startdoc: + + # + # Parser Events + # + + PARSER_EVENT_TABLE.each do |id, arity| + alias_method "on_#{id}", "_dispatch_#{arity}" + end + + # This method is called when weak warning is produced by the parser. + # +fmt+ and +args+ is printf style. + def warn(fmt, *args) + end + + # This method is called when strong warning is produced by the parser. + # +fmt+ and +args+ is printf style. + def warning(fmt, *args) + end + + # This method is called when the parser found syntax error. + def compile_error(msg) + end + + # + # Scanner Events + # + + SCANNER_EVENTS.each do |id| + alias_method "on_#{id}", :_dispatch_1 + end + + # This method is provided by the Ripper C extension. It is called when a + # string needs to be dedented because of a tilde heredoc. It is expected + # that it will modify the string in place and return the number of bytes + # that were removed. + def dedent_string(string, width) + whitespace = 0 + cursor = 0 + + while cursor < string.length && string[cursor].match?(/\s/) && whitespace < width + if string[cursor] == "\t" + whitespace = ((whitespace / 8 + 1) * 8) + break if whitespace > width + else + whitespace += 1 + end + + cursor += 1 + end + + string.replace(string[cursor..]) + cursor + end + end + end +end diff --git a/lib/prism/translation/ripper/sexp.rb b/lib/prism/translation/ripper/sexp.rb new file mode 100644 index 00000000000000..8cfefc84723b29 --- /dev/null +++ b/lib/prism/translation/ripper/sexp.rb @@ -0,0 +1,126 @@ +# frozen_string_literal: true +# :markup: markdown + +require_relative "../ripper" + +module Prism + module Translation + class Ripper + # This class mirrors the ::Ripper::SexpBuilder subclass of ::Ripper that + # returns the arrays of [type, *children]. + class SexpBuilder < Ripper + # :stopdoc: + + attr_reader :error + + private + + def dedent_element(e, width) + if (n = dedent_string(e[1], width)) > 0 + e[2][1] += n + end + e + end + + def on_heredoc_dedent(val, width) + sub = proc do |cont| + cont.map! do |e| + if Array === e + case e[0] + when :@tstring_content + e = dedent_element(e, width) + when /_add\z/ + e[1] = sub[e[1]] + end + elsif String === e + dedent_string(e, width) + end + e + end + end + sub[val] + val + end + + events = private_instance_methods(false).grep(/\Aon_/) {$'.to_sym} + (PARSER_EVENTS - events).each do |event| + module_eval(<<-End, __FILE__, __LINE__ + 1) + def on_#{event}(*args) + args.unshift :#{event} + end + End + end + + SCANNER_EVENTS.each do |event| + module_eval(<<-End, __FILE__, __LINE__ + 1) + def on_#{event}(tok) + [:@#{event}, tok, [lineno(), column()]] + end + End + end + + def on_error(mesg) + @error = mesg + end + remove_method :on_parse_error + alias on_parse_error on_error + alias compile_error on_error + + # :startdoc: + end + + # This class mirrors the ::Ripper::SexpBuilderPP subclass of ::Ripper that + # returns the same values as ::Ripper::SexpBuilder except with a couple of + # niceties that flatten linked lists into arrays. + class SexpBuilderPP < SexpBuilder + # :stopdoc: + + private + + def on_heredoc_dedent(val, width) + val.map! do |e| + next e if Symbol === e and /_content\z/ =~ e + if Array === e and e[0] == :@tstring_content + e = dedent_element(e, width) + elsif String === e + dedent_string(e, width) + end + e + end + val + end + + def _dispatch_event_new + [] + end + + def _dispatch_event_push(list, item) + list.push item + list + end + + def on_mlhs_paren(list) + [:mlhs, *list] + end + + def on_mlhs_add_star(list, star) + list.push([:rest_param, star]) + end + + def on_mlhs_add_post(list, post) + list.concat(post) + end + + PARSER_EVENT_TABLE.each do |event, arity| + if /_new\z/ =~ event and arity == 0 + alias_method "on_#{event}", :_dispatch_event_new + elsif /_add\z/ =~ event + alias_method "on_#{event}", :_dispatch_event_push + end + end + + # :startdoc: + end + end + end +end diff --git a/lib/prism/translation/ripper/shim.rb b/lib/prism/translation/ripper/shim.rb new file mode 100644 index 00000000000000..10e21cd16a213f --- /dev/null +++ b/lib/prism/translation/ripper/shim.rb @@ -0,0 +1,5 @@ +# frozen_string_literal: true + +# This writes the prism ripper translation into the Ripper constant so that +# users can transparently use Ripper without any changes. +Ripper = Prism::Translation::Ripper diff --git a/lib/prism/translation/ruby_parser.rb b/lib/prism/translation/ruby_parser.rb new file mode 100644 index 00000000000000..3808cd3130906e --- /dev/null +++ b/lib/prism/translation/ruby_parser.rb @@ -0,0 +1,1929 @@ +# frozen_string_literal: true +# :markup: markdown + +begin + require "ruby_parser" +rescue LoadError + warn(%q{Error: Unable to load ruby_parser. Add `gem "ruby_parser"` to your Gemfile.}) + exit(1) +end + +module Prism + module Translation + # This module is the entry-point for converting a prism syntax tree into the + # seattlerb/ruby_parser gem's syntax tree. + class RubyParser + # A prism visitor that builds Sexp objects. + class Compiler < ::Prism::Compiler + # This is the name of the file that we are compiling. We set it on every + # Sexp object that is generated, and also use it to compile `__FILE__` + # nodes. + attr_reader :file + + # Class variables will change their type based on if they are inside of + # a method definition or not, so we need to track that state. + attr_reader :in_def + + # Some nodes will change their representation if they are inside of a + # pattern, so we need to track that state. + attr_reader :in_pattern + + # Initialize a new compiler with the given file name. + def initialize(file, in_def: false, in_pattern: false) + @file = file + @in_def = in_def + @in_pattern = in_pattern + end + + # ``` + # alias foo bar + # ^^^^^^^^^^^^^ + # ``` + def visit_alias_method_node(node) + s(node, :alias, visit(node.new_name), visit(node.old_name)) + end + + # ``` + # alias $foo $bar + # ^^^^^^^^^^^^^^^ + # ``` + def visit_alias_global_variable_node(node) + s(node, :valias, node.new_name.name, node.old_name.name) + end + + # ``` + # foo => bar | baz + # ^^^^^^^^^ + # ``` + def visit_alternation_pattern_node(node) + s(node, :or, visit(node.left), visit(node.right)) + end + + # ``` + # a and b + # ^^^^^^^ + # ``` + def visit_and_node(node) + left = visit(node.left) + + if left[0] == :and + # ruby_parser has the and keyword as right-associative as opposed to + # prism which has it as left-associative. We reverse that + # associativity here. + nest = left + nest = nest[2] while nest[2][0] == :and + nest[2] = s(node, :and, nest[2], visit(node.right)) + left + else + s(node, :and, left, visit(node.right)) + end + end + + # ``` + # [] + # ^^ + # ``` + def visit_array_node(node) + if in_pattern + s(node, :array_pat, nil).concat(visit_all(node.elements)) + else + s(node, :array).concat(visit_all(node.elements)) + end + end + + # ``` + # foo => [bar] + # ^^^^^ + # ``` + def visit_array_pattern_node(node) + if node.constant.nil? && node.requireds.empty? && node.rest.nil? && node.posts.empty? + s(node, :array_pat) + else + result = s(node, :array_pat, visit_pattern_constant(node.constant)).concat(visit_all(node.requireds)) + + case node.rest + when SplatNode + result << :"*#{node.rest.expression&.name}" + when ImplicitRestNode + result << :* + + # This doesn't make any sense at all, but since we're trying to + # replicate the behavior directly, we'll copy it. + result.line(666) + end + + result.concat(visit_all(node.posts)) + end + end + + # ``` + # foo(bar) + # ^^^ + # ``` + def visit_arguments_node(node) + raise "Cannot visit arguments directly" + end + + # ``` + # { a: 1 } + # ^^^^ + # ``` + def visit_assoc_node(node) + [visit(node.key), visit(node.value)] + end + + # ``` + # def foo(**); bar(**); end + # ^^ + # + # { **foo } + # ^^^^^ + # ``` + def visit_assoc_splat_node(node) + if node.value.nil? + [s(node, :kwsplat)] + else + [s(node, :kwsplat, visit(node.value))] + end + end + + # ``` + # $+ + # ^^ + # ``` + def visit_back_reference_read_node(node) + s(node, :back_ref, node.name.name.delete_prefix("$").to_sym) + end + + # ``` + # begin end + # ^^^^^^^^^ + # ``` + def visit_begin_node(node) + result = node.statements.nil? ? s(node, :nil) : visit(node.statements) + + if !node.rescue_clause.nil? + if !node.statements.nil? + result = s(node.statements, :rescue, result, visit(node.rescue_clause)) + else + result = s(node.rescue_clause, :rescue, visit(node.rescue_clause)) + end + + current = node.rescue_clause + until (current = current.subsequent).nil? + result << visit(current) + end + end + + if !node.else_clause&.statements.nil? + result << visit(node.else_clause) + end + + if !node.ensure_clause.nil? + if !node.statements.nil? || !node.rescue_clause.nil? || !node.else_clause.nil? + result = s(node.statements || node.rescue_clause || node.else_clause || node.ensure_clause, :ensure, result, visit(node.ensure_clause)) + else + result = s(node.ensure_clause, :ensure, visit(node.ensure_clause)) + end + end + + result + end + + # ``` + # foo(&bar) + # ^^^^ + # ``` + def visit_block_argument_node(node) + s(node, :block_pass).tap do |result| + result << visit(node.expression) unless node.expression.nil? + end + end + + # ``` + # foo { |; bar| } + # ^^^ + # ``` + def visit_block_local_variable_node(node) + node.name + end + + # A block on a keyword or method call. + def visit_block_node(node) + s(node, :block_pass, visit(node.expression)) + end + + # ``` + # def foo(&bar); end + # ^^^^ + # ``` + def visit_block_parameter_node(node) + :"&#{node.name}" + end + + # A block's parameters. + def visit_block_parameters_node(node) + # If this block parameters has no parameters and is using pipes, then + # it inherits its location from its shadow locals, even if they're not + # on the same lines as the pipes. + shadow_loc = true + + result = + if node.parameters.nil? + s(node, :args) + else + shadow_loc = false + visit(node.parameters) + end + + if node.opening == "(" + result.line = node.opening_loc.start_line + result.line_max = node.closing_loc.end_line + shadow_loc = false + end + + if node.locals.any? + shadow = s(node, :shadow).concat(visit_all(node.locals)) + shadow.line = node.locals.first.location.start_line + shadow.line_max = node.locals.last.location.end_line + result << shadow + + if shadow_loc + result.line = shadow.line + result.line_max = shadow.line_max + end + end + + result + end + + # ``` + # break + # ^^^^^ + # + # break foo + # ^^^^^^^^^ + # ``` + def visit_break_node(node) + if node.arguments.nil? + s(node, :break) + elsif node.arguments.arguments.length == 1 + s(node, :break, visit(node.arguments.arguments.first)) + else + s(node, :break, s(node.arguments, :array).concat(visit_all(node.arguments.arguments))) + end + end + + # ``` + # foo + # ^^^ + # + # foo.bar + # ^^^^^^^ + # + # foo.bar() {} + # ^^^^^^^^^^^^ + # ``` + def visit_call_node(node) + case node.name + when :!~ + return s(node, :not, visit(node.copy(name: :"=~"))) + when :=~ + if node.arguments&.arguments&.length == 1 && node.block.nil? + case node.receiver + when StringNode + return s(node, :match3, visit(node.arguments.arguments.first), visit(node.receiver)) + when RegularExpressionNode, InterpolatedRegularExpressionNode + return s(node, :match2, visit(node.receiver), visit(node.arguments.arguments.first)) + end + + case node.arguments.arguments.first + when RegularExpressionNode, InterpolatedRegularExpressionNode + return s(node, :match3, visit(node.arguments.arguments.first), visit(node.receiver)) + end + end + end + + type = node.attribute_write? ? :attrasgn : :call + type = :"safe_#{type}" if node.safe_navigation? + + arguments = node.arguments&.arguments || [] + write_value = arguments.pop if type == :attrasgn + block = node.block + + if block.is_a?(BlockArgumentNode) + arguments << block + block = nil + end + + result = s(node, type, visit(node.receiver), node.name).concat(visit_all(arguments)) + result << visit_write_value(write_value) unless write_value.nil? + + visit_block(node, result, block) + end + + # ``` + # foo.bar += baz + # ^^^^^^^^^^^^^^^ + # ``` + def visit_call_operator_write_node(node) + if op_asgn?(node) + s(node, op_asgn_type(node, :op_asgn), visit(node.receiver), visit_write_value(node.value), node.read_name, node.binary_operator) + else + s(node, op_asgn_type(node, :op_asgn2), visit(node.receiver), node.write_name, node.binary_operator, visit_write_value(node.value)) + end + end + + # ``` + # foo.bar &&= baz + # ^^^^^^^^^^^^^^^ + # ``` + def visit_call_and_write_node(node) + if op_asgn?(node) + s(node, op_asgn_type(node, :op_asgn), visit(node.receiver), visit_write_value(node.value), node.read_name, :"&&") + else + s(node, op_asgn_type(node, :op_asgn2), visit(node.receiver), node.write_name, :"&&", visit_write_value(node.value)) + end + end + + # ``` + # foo.bar ||= baz + # ^^^^^^^^^^^^^^^ + # ``` + def visit_call_or_write_node(node) + if op_asgn?(node) + s(node, op_asgn_type(node, :op_asgn), visit(node.receiver), visit_write_value(node.value), node.read_name, :"||") + else + s(node, op_asgn_type(node, :op_asgn2), visit(node.receiver), node.write_name, :"||", visit_write_value(node.value)) + end + end + + # Call nodes with operators following them will either be op_asgn or + # op_asgn2 nodes. That is determined by their call operator and their + # right-hand side. + private def op_asgn?(node) + node.call_operator == "::" || (node.value.is_a?(CallNode) && node.value.opening_loc.nil? && !node.value.arguments.nil?) + end + + # Call nodes with operators following them can use &. as an operator, + # which changes their type by prefixing "safe_". + private def op_asgn_type(node, type) + node.safe_navigation? ? :"safe_#{type}" : type + end + + # ``` + # foo.bar, = 1 + # ^^^^^^^ + # ``` + def visit_call_target_node(node) + s(node, :attrasgn, visit(node.receiver), node.name) + end + + # ``` + # foo => bar => baz + # ^^^^^^^^^^ + # ``` + def visit_capture_pattern_node(node) + visit(node.target) << visit(node.value) + end + + # ``` + # case foo; when bar; end + # ^^^^^^^^^^^^^^^^^^^^^^^ + # ``` + def visit_case_node(node) + s(node, :case, visit(node.predicate)).concat(visit_all(node.conditions)) << visit(node.else_clause) + end + + # ``` + # case foo; in bar; end + # ^^^^^^^^^^^^^^^^^^^^^ + # ``` + def visit_case_match_node(node) + s(node, :case, visit(node.predicate)).concat(visit_all(node.conditions)) << visit(node.else_clause) + end + + # ``` + # class Foo; end + # ^^^^^^^^^^^^^^ + # ``` + def visit_class_node(node) + name = + if node.constant_path.is_a?(ConstantReadNode) + node.name + else + visit(node.constant_path) + end + + if node.body.nil? + s(node, :class, name, visit(node.superclass)) + elsif node.body.is_a?(StatementsNode) + compiler = copy_compiler(in_def: false) + s(node, :class, name, visit(node.superclass)).concat(node.body.body.map { |child| child.accept(compiler) }) + else + s(node, :class, name, visit(node.superclass), node.body.accept(copy_compiler(in_def: false))) + end + end + + # ``` + # @@foo + # ^^^^^ + # ``` + def visit_class_variable_read_node(node) + s(node, :cvar, node.name) + end + + # ``` + # @@foo = 1 + # ^^^^^^^^^ + # + # @@foo, @@bar = 1 + # ^^^^^ ^^^^^ + # ``` + def visit_class_variable_write_node(node) + s(node, class_variable_write_type, node.name, visit_write_value(node.value)) + end + + # ``` + # @@foo += bar + # ^^^^^^^^^^^^ + # ``` + def visit_class_variable_operator_write_node(node) + s(node, class_variable_write_type, node.name, s(node, :call, s(node, :cvar, node.name), node.binary_operator, visit_write_value(node.value))) + end + + # ``` + # @@foo &&= bar + # ^^^^^^^^^^^^^ + # ``` + def visit_class_variable_and_write_node(node) + s(node, :op_asgn_and, s(node, :cvar, node.name), s(node, class_variable_write_type, node.name, visit_write_value(node.value))) + end + + # ``` + # @@foo ||= bar + # ^^^^^^^^^^^^^ + # ``` + def visit_class_variable_or_write_node(node) + s(node, :op_asgn_or, s(node, :cvar, node.name), s(node, class_variable_write_type, node.name, visit_write_value(node.value))) + end + + # ``` + # @@foo, = bar + # ^^^^^ + # ``` + def visit_class_variable_target_node(node) + s(node, class_variable_write_type, node.name) + end + + # If a class variable is written within a method definition, it has a + # different type than everywhere else. + private def class_variable_write_type + in_def ? :cvasgn : :cvdecl + end + + # ``` + # Foo + # ^^^ + # ``` + def visit_constant_read_node(node) + s(node, :const, node.name) + end + + # ``` + # Foo = 1 + # ^^^^^^^ + # + # Foo, Bar = 1 + # ^^^ ^^^ + # ``` + def visit_constant_write_node(node) + s(node, :cdecl, node.name, visit_write_value(node.value)) + end + + # ``` + # Foo += bar + # ^^^^^^^^^^^ + # ``` + def visit_constant_operator_write_node(node) + s(node, :cdecl, node.name, s(node, :call, s(node, :const, node.name), node.binary_operator, visit_write_value(node.value))) + end + + # ``` + # Foo &&= bar + # ^^^^^^^^^^^^ + # ``` + def visit_constant_and_write_node(node) + s(node, :op_asgn_and, s(node, :const, node.name), s(node, :cdecl, node.name, visit(node.value))) + end + + # ``` + # Foo ||= bar + # ^^^^^^^^^^^^ + # ``` + def visit_constant_or_write_node(node) + s(node, :op_asgn_or, s(node, :const, node.name), s(node, :cdecl, node.name, visit(node.value))) + end + + # ``` + # Foo, = bar + # ^^^ + # ``` + def visit_constant_target_node(node) + s(node, :cdecl, node.name) + end + + # ``` + # Foo::Bar + # ^^^^^^^^ + # ``` + def visit_constant_path_node(node) + if node.parent.nil? + s(node, :colon3, node.name) + else + s(node, :colon2, visit(node.parent), node.name) + end + end + + # ``` + # Foo::Bar = 1 + # ^^^^^^^^^^^^ + # + # Foo::Foo, Bar::Bar = 1 + # ^^^^^^^^ ^^^^^^^^ + # ``` + def visit_constant_path_write_node(node) + s(node, :cdecl, visit(node.target), visit_write_value(node.value)) + end + + # ``` + # Foo::Bar += baz + # ^^^^^^^^^^^^^^^ + # ``` + def visit_constant_path_operator_write_node(node) + s(node, :op_asgn, visit(node.target), node.binary_operator, visit_write_value(node.value)) + end + + # ``` + # Foo::Bar &&= baz + # ^^^^^^^^^^^^^^^^ + # ``` + def visit_constant_path_and_write_node(node) + s(node, :op_asgn_and, visit(node.target), visit_write_value(node.value)) + end + + # ``` + # Foo::Bar ||= baz + # ^^^^^^^^^^^^^^^^ + # ``` + def visit_constant_path_or_write_node(node) + s(node, :op_asgn_or, visit(node.target), visit_write_value(node.value)) + end + + # ``` + # Foo::Bar, = baz + # ^^^^^^^^ + # ``` + def visit_constant_path_target_node(node) + inner = + if node.parent.nil? + s(node, :colon3, node.name) + else + s(node, :colon2, visit(node.parent), node.name) + end + + s(node, :const, inner) + end + + # ``` + # def foo; end + # ^^^^^^^^^^^^ + # + # def self.foo; end + # ^^^^^^^^^^^^^^^^^ + # ``` + def visit_def_node(node) + name = node.name_loc.slice.to_sym + result = + if node.receiver.nil? + s(node, :defn, name) + else + s(node, :defs, visit(node.receiver), name) + end + + result.line(node.name_loc.start_line) + if node.parameters.nil? + result << s(node, :args).line(node.name_loc.start_line) + else + result << visit(node.parameters) + end + + if node.body.nil? + result << s(node, :nil) + elsif node.body.is_a?(StatementsNode) + compiler = copy_compiler(in_def: true) + result.concat(node.body.body.map { |child| child.accept(compiler) }) + else + result << node.body.accept(copy_compiler(in_def: true)) + end + end + + # ``` + # defined? a + # ^^^^^^^^^^ + # + # defined?(a) + # ^^^^^^^^^^^ + # ``` + def visit_defined_node(node) + s(node, :defined, visit(node.value)) + end + + # ``` + # if foo then bar else baz end + # ^^^^^^^^^^^^ + # ``` + def visit_else_node(node) + visit(node.statements) + end + + # ``` + # "foo #{bar}" + # ^^^^^^ + # ``` + def visit_embedded_statements_node(node) + result = s(node, :evstr) + result << visit(node.statements) unless node.statements.nil? + result + end + + # ``` + # "foo #@bar" + # ^^^^^ + # ``` + def visit_embedded_variable_node(node) + s(node, :evstr, visit(node.variable)) + end + + # ``` + # begin; foo; ensure; bar; end + # ^^^^^^^^^^^^ + # ``` + def visit_ensure_node(node) + node.statements.nil? ? s(node, :nil) : visit(node.statements) + end + + # ``` + # false + # ^^^^^ + # ``` + def visit_false_node(node) + s(node, :false) + end + + # ``` + # foo => [*, bar, *] + # ^^^^^^^^^^^ + # ``` + def visit_find_pattern_node(node) + s(node, :find_pat, visit_pattern_constant(node.constant), :"*#{node.left.expression&.name}", *visit_all(node.requireds), :"*#{node.right.expression&.name}") + end + + # ``` + # if foo .. bar; end + # ^^^^^^^^^^ + # ``` + def visit_flip_flop_node(node) + if node.left.is_a?(IntegerNode) && node.right.is_a?(IntegerNode) + s(node, :lit, Range.new(node.left.value, node.right.value, node.exclude_end?)) + else + s(node, node.exclude_end? ? :flip3 : :flip2, visit(node.left), visit(node.right)) + end + end + + # ``` + # 1.0 + # ^^^ + # ``` + def visit_float_node(node) + s(node, :lit, node.value) + end + + # ``` + # for foo in bar do end + # ^^^^^^^^^^^^^^^^^^^^^ + # ``` + def visit_for_node(node) + s(node, :for, visit(node.collection), visit(node.index), visit(node.statements)) + end + + # ``` + # def foo(...); bar(...); end + # ^^^ + # ``` + def visit_forwarding_arguments_node(node) + s(node, :forward_args) + end + + # ``` + # def foo(...); end + # ^^^ + # ``` + def visit_forwarding_parameter_node(node) + s(node, :forward_args) + end + + # ``` + # super + # ^^^^^ + # + # super {} + # ^^^^^^^^ + # ``` + def visit_forwarding_super_node(node) + visit_block(node, s(node, :zsuper), node.block) + end + + # ``` + # $foo + # ^^^^ + # ``` + def visit_global_variable_read_node(node) + s(node, :gvar, node.name) + end + + # ``` + # $foo = 1 + # ^^^^^^^^ + # + # $foo, $bar = 1 + # ^^^^ ^^^^ + # ``` + def visit_global_variable_write_node(node) + s(node, :gasgn, node.name, visit_write_value(node.value)) + end + + # ``` + # $foo += bar + # ^^^^^^^^^^^ + # ``` + def visit_global_variable_operator_write_node(node) + s(node, :gasgn, node.name, s(node, :call, s(node, :gvar, node.name), node.binary_operator, visit(node.value))) + end + + # ``` + # $foo &&= bar + # ^^^^^^^^^^^^ + # ``` + def visit_global_variable_and_write_node(node) + s(node, :op_asgn_and, s(node, :gvar, node.name), s(node, :gasgn, node.name, visit_write_value(node.value))) + end + + # ``` + # $foo ||= bar + # ^^^^^^^^^^^^ + # ``` + def visit_global_variable_or_write_node(node) + s(node, :op_asgn_or, s(node, :gvar, node.name), s(node, :gasgn, node.name, visit_write_value(node.value))) + end + + # ``` + # $foo, = bar + # ^^^^ + # ``` + def visit_global_variable_target_node(node) + s(node, :gasgn, node.name) + end + + # ``` + # {} + # ^^ + # ``` + def visit_hash_node(node) + s(node, :hash).concat(node.elements.flat_map { |element| visit(element) }) + end + + # ``` + # foo => {} + # ^^ + # ``` + def visit_hash_pattern_node(node) + result = s(node, :hash_pat, visit_pattern_constant(node.constant)).concat(node.elements.flat_map { |element| visit(element) }) + + case node.rest + when AssocSplatNode + result << s(node.rest, :kwrest, :"**#{node.rest.value&.name}") + when NoKeywordsParameterNode + result << visit(node.rest) + end + + result + end + + # ``` + # if foo then bar end + # ^^^^^^^^^^^^^^^^^^^ + # + # bar if foo + # ^^^^^^^^^^ + # + # foo ? bar : baz + # ^^^^^^^^^^^^^^^ + # ``` + def visit_if_node(node) + s(node, :if, visit(node.predicate), visit(node.statements), visit(node.subsequent)) + end + + # 1i + def visit_imaginary_node(node) + s(node, :lit, node.value) + end + + # ``` + # { foo: } + # ^^^^ + # ``` + def visit_implicit_node(node) + end + + # ``` + # foo { |bar,| } + # ^ + # ``` + def visit_implicit_rest_node(node) + end + + # ``` + # case foo; in bar; end + # ^^^^^^^^^^^^^^^^^^^^^ + # ``` + def visit_in_node(node) + pattern = + if node.pattern.is_a?(ConstantPathNode) + s(node.pattern, :const, visit(node.pattern)) + else + node.pattern.accept(copy_compiler(in_pattern: true)) + end + + s(node, :in, pattern).concat(node.statements.nil? ? [nil] : visit_all(node.statements.body)) + end + + # ``` + # foo[bar] += baz + # ^^^^^^^^^^^^^^^ + # ``` + def visit_index_operator_write_node(node) + arglist = nil + + if !node.arguments.nil? || !node.block.nil? + arglist = s(node, :arglist).concat(visit_all(node.arguments&.arguments || [])) + arglist << visit(node.block) if !node.block.nil? + end + + s(node, :op_asgn1, visit(node.receiver), arglist, node.binary_operator, visit_write_value(node.value)) + end + + # ``` + # foo[bar] &&= baz + # ^^^^^^^^^^^^^^^^ + # ``` + def visit_index_and_write_node(node) + arglist = nil + + if !node.arguments.nil? || !node.block.nil? + arglist = s(node, :arglist).concat(visit_all(node.arguments&.arguments || [])) + arglist << visit(node.block) if !node.block.nil? + end + + s(node, :op_asgn1, visit(node.receiver), arglist, :"&&", visit_write_value(node.value)) + end + + # ``` + # foo[bar] ||= baz + # ^^^^^^^^^^^^^^^^ + # ``` + def visit_index_or_write_node(node) + arglist = nil + + if !node.arguments.nil? || !node.block.nil? + arglist = s(node, :arglist).concat(visit_all(node.arguments&.arguments || [])) + arglist << visit(node.block) if !node.block.nil? + end + + s(node, :op_asgn1, visit(node.receiver), arglist, :"||", visit_write_value(node.value)) + end + + # ``` + # foo[bar], = 1 + # ^^^^^^^^ + # ``` + def visit_index_target_node(node) + arguments = visit_all(node.arguments&.arguments || []) + arguments << visit(node.block) unless node.block.nil? + + s(node, :attrasgn, visit(node.receiver), :[]=).concat(arguments) + end + + # ``` + # @foo + # ^^^^ + # ``` + def visit_instance_variable_read_node(node) + s(node, :ivar, node.name) + end + + # ``` + # @foo = 1 + # ^^^^^^^^ + # + # @foo, @bar = 1 + # ^^^^ ^^^^ + # ``` + def visit_instance_variable_write_node(node) + s(node, :iasgn, node.name, visit_write_value(node.value)) + end + + # ``` + # @foo += bar + # ^^^^^^^^^^^ + # ``` + def visit_instance_variable_operator_write_node(node) + s(node, :iasgn, node.name, s(node, :call, s(node, :ivar, node.name), node.binary_operator, visit_write_value(node.value))) + end + + # ``` + # @foo &&= bar + # ^^^^^^^^^^^^ + # ``` + def visit_instance_variable_and_write_node(node) + s(node, :op_asgn_and, s(node, :ivar, node.name), s(node, :iasgn, node.name, visit(node.value))) + end + + # ``` + # @foo ||= bar + # ^^^^^^^^^^^^ + # ``` + def visit_instance_variable_or_write_node(node) + s(node, :op_asgn_or, s(node, :ivar, node.name), s(node, :iasgn, node.name, visit(node.value))) + end + + # ``` + # @foo, = bar + # ^^^^ + # ``` + def visit_instance_variable_target_node(node) + s(node, :iasgn, node.name) + end + + # ``` + # 1 + # ^ + # ``` + def visit_integer_node(node) + s(node, :lit, node.value) + end + + # ``` + # if /foo #{bar}/ then end + # ^^^^^^^^^^^^ + # ``` + def visit_interpolated_match_last_line_node(node) + parts = visit_interpolated_parts(node.parts) + regexp = + if parts.length == 1 + s(node, :lit, Regexp.new(parts.first, node.options)) + else + s(node, :dregx).concat(parts).tap do |result| + options = node.options + result << options if options != 0 + end + end + + s(node, :match, regexp) + end + + # ``` + # /foo #{bar}/ + # ^^^^^^^^^^^^ + # ``` + def visit_interpolated_regular_expression_node(node) + parts = visit_interpolated_parts(node.parts) + + if parts.length == 1 + s(node, :lit, Regexp.new(parts.first, node.options)) + else + s(node, :dregx).concat(parts).tap do |result| + options = node.options + result << options if options != 0 + end + end + end + + # ``` + # "foo #{bar}" + # ^^^^^^^^^^^^ + # ``` + def visit_interpolated_string_node(node) + parts = visit_interpolated_parts(node.parts) + parts.length == 1 ? s(node, :str, parts.first) : s(node, :dstr).concat(parts) + end + + # ``` + # :"foo #{bar}" + # ^^^^^^^^^^^^^ + # ``` + def visit_interpolated_symbol_node(node) + parts = visit_interpolated_parts(node.parts) + parts.length == 1 ? s(node, :lit, parts.first.to_sym) : s(node, :dsym).concat(parts) + end + + # ``` + # `foo #{bar}` + # ^^^^^^^^^^^^ + # ``` + def visit_interpolated_x_string_node(node) + source = node.heredoc? ? node.parts.first : node + parts = visit_interpolated_parts(node.parts) + parts.length == 1 ? s(source, :xstr, parts.first) : s(source, :dxstr).concat(parts) + end + + # Visit the interpolated content of the string-like node. + private def visit_interpolated_parts(parts) + visited = [] + + parts.each do |part| + result = visit(part) + + if result[0] == :evstr && result[1] + if result[1][0] == :str + visited << result[1] + elsif result[1][0] == :dstr + visited.concat(result[1][1..-1]) + else + visited << result + end + visited << :space + elsif result[0] == :dstr + if !visited.empty? && part.parts[0].is_a?(StringNode) + # If we are in the middle of an implicitly concatenated string, + # we should not have a bare string as the first part. In this + # case we need to visit just that first part and then we can + # push the rest of the parts onto the visited array. + result[1] = visit(part.parts[0]) + end + visited.concat(result[1..-1]) + else + visited << result + end + end + + state = :beginning #: :beginning | :string_content | :interpolated_content + results = [] + + visited.each_with_index do |result, index| + case state + when :beginning + if result.is_a?(String) + results << result + state = :string_content + elsif result.is_a?(Array) && result[0] == :str + results << result[1] + state = :string_content + else + results << "" + results << result + state = :interpolated_content + end + when :string_content + if result == :space + # continue + elsif result.is_a?(String) + results[0] = "#{results[0]}#{result}" + elsif result.is_a?(Array) && result[0] == :str + results[0] = "#{results[0]}#{result[1]}" + else + results << result + state = :interpolated_content + end + when :interpolated_content + if result == :space + # continue + elsif visited[index - 1] != :space && result.is_a?(Array) && result[0] == :str && results[-1][0] == :str && (results[-1].line_max == result.line) + results[-1][1] = "#{results[-1][1]}#{result[1]}" + results[-1].line_max = result.line_max + else + results << result + end + end + end + + results + end + + # ``` + # -> { it } + # ^^ + # ``` + def visit_it_local_variable_read_node(node) + s(node, :call, nil, :it) + end + + # ``` + # foo(bar: baz) + # ^^^^^^^^ + # ``` + def visit_keyword_hash_node(node) + s(node, :hash).concat(node.elements.flat_map { |element| visit(element) }) + end + + # ``` + # def foo(**bar); end + # ^^^^^ + # + # def foo(**); end + # ^^ + # ``` + def visit_keyword_rest_parameter_node(node) + :"**#{node.name}" + end + + # -> {} + def visit_lambda_node(node) + parameters = + case node.parameters + when nil, NumberedParametersNode + s(node, :args) + else + visit(node.parameters) + end + + if node.body.nil? + s(node, :iter, s(node, :lambda), parameters) + else + s(node, :iter, s(node, :lambda), parameters, visit(node.body)) + end + end + + # ``` + # foo + # ^^^ + # ``` + def visit_local_variable_read_node(node) + if node.name.match?(/^_\d$/) + s(node, :call, nil, node.name) + else + s(node, :lvar, node.name) + end + end + + # ``` + # foo = 1 + # ^^^^^^^ + # + # foo, bar = 1 + # ^^^ ^^^ + # ``` + def visit_local_variable_write_node(node) + s(node, :lasgn, node.name, visit_write_value(node.value)) + end + + # ``` + # foo += bar + # ^^^^^^^^^^ + # ``` + def visit_local_variable_operator_write_node(node) + s(node, :lasgn, node.name, s(node, :call, s(node, :lvar, node.name), node.binary_operator, visit_write_value(node.value))) + end + + # ``` + # foo &&= bar + # ^^^^^^^^^^^ + # ``` + def visit_local_variable_and_write_node(node) + s(node, :op_asgn_and, s(node, :lvar, node.name), s(node, :lasgn, node.name, visit_write_value(node.value))) + end + + # ``` + # foo ||= bar + # ^^^^^^^^^^^ + # ``` + def visit_local_variable_or_write_node(node) + s(node, :op_asgn_or, s(node, :lvar, node.name), s(node, :lasgn, node.name, visit_write_value(node.value))) + end + + # ``` + # foo, = bar + # ^^^ + # ``` + def visit_local_variable_target_node(node) + s(node, :lasgn, node.name) + end + + # ``` + # if /foo/ then end + # ^^^^^ + # ``` + def visit_match_last_line_node(node) + s(node, :match, s(node, :lit, Regexp.new(node.unescaped, node.options))) + end + + # ``` + # foo in bar + # ^^^^^^^^^^ + # ``` + def visit_match_predicate_node(node) + s(node, :case, visit(node.value), s(node, :in, node.pattern.accept(copy_compiler(in_pattern: true)), nil), nil) + end + + # ``` + # foo => bar + # ^^^^^^^^^^ + # ``` + def visit_match_required_node(node) + s(node, :case, visit(node.value), s(node, :in, node.pattern.accept(copy_compiler(in_pattern: true)), nil), nil) + end + + # ``` + # /(?foo)/ =~ bar + # ^^^^^^^^^^^^^^^^^^^^ + # ``` + def visit_match_write_node(node) + s(node, :match2, visit(node.call.receiver), visit(node.call.arguments.arguments.first)) + end + + # A node that is missing from the syntax tree. This is only used in the + # case of a syntax error. The parser gem doesn't have such a concept, so + # we invent our own here. + def visit_missing_node(node) + raise "Cannot visit missing node directly" + end + + # ``` + # module Foo; end + # ^^^^^^^^^^^^^^^ + # ``` + def visit_module_node(node) + name = + if node.constant_path.is_a?(ConstantReadNode) + node.name + else + visit(node.constant_path) + end + + if node.body.nil? + s(node, :module, name) + elsif node.body.is_a?(StatementsNode) + compiler = copy_compiler(in_def: false) + s(node, :module, name).concat(node.body.body.map { |child| child.accept(compiler) }) + else + s(node, :module, name, node.body.accept(copy_compiler(in_def: false))) + end + end + + # ``` + # foo, bar = baz + # ^^^^^^^^ + # ``` + def visit_multi_target_node(node) + targets = [*node.lefts] + targets << node.rest if !node.rest.nil? && !node.rest.is_a?(ImplicitRestNode) + targets.concat(node.rights) + + s(node, :masgn, s(node, :array).concat(visit_all(targets))) + end + + # ``` + # foo, bar = baz + # ^^^^^^^^^^^^^^ + # ``` + def visit_multi_write_node(node) + targets = [*node.lefts] + targets << node.rest if !node.rest.nil? && !node.rest.is_a?(ImplicitRestNode) + targets.concat(node.rights) + + value = + if node.value.is_a?(ArrayNode) && node.value.opening_loc.nil? + if node.value.elements.length == 1 && node.value.elements.first.is_a?(SplatNode) + visit(node.value.elements.first) + else + visit(node.value) + end + else + s(node.value, :to_ary, visit(node.value)) + end + + s(node, :masgn, s(node, :array).concat(visit_all(targets)), value) + end + + # ``` + # next + # ^^^^ + # + # next foo + # ^^^^^^^^ + # ``` + def visit_next_node(node) + if node.arguments.nil? + s(node, :next) + elsif node.arguments.arguments.length == 1 + argument = node.arguments.arguments.first + s(node, :next, argument.is_a?(SplatNode) ? s(node, :svalue, visit(argument)) : visit(argument)) + else + s(node, :next, s(node, :array).concat(visit_all(node.arguments.arguments))) + end + end + + # ``` + # nil + # ^^^ + # ``` + def visit_nil_node(node) + s(node, :nil) + end + + # ``` + # def foo(**nil); end + # ^^^^^ + # ``` + def visit_no_keywords_parameter_node(node) + in_pattern ? s(node, :kwrest, :"**nil") : :"**nil" + end + + # ``` + # -> { _1 + _2 } + # ^^^^^^^^^^^^^^ + # ``` + def visit_numbered_parameters_node(node) + raise "Cannot visit numbered parameters directly" + end + + # ``` + # $1 + # ^^ + # ``` + def visit_numbered_reference_read_node(node) + s(node, :nth_ref, node.number) + end + + # ``` + # def foo(bar: baz); end + # ^^^^^^^^ + # ``` + def visit_optional_keyword_parameter_node(node) + s(node, :kwarg, node.name, visit(node.value)) + end + + # ``` + # def foo(bar = 1); end + # ^^^^^^^ + # ``` + def visit_optional_parameter_node(node) + s(node, :lasgn, node.name, visit(node.value)) + end + + # ``` + # a or b + # ^^^^^^ + # ``` + def visit_or_node(node) + left = visit(node.left) + + if left[0] == :or + # ruby_parser has the or keyword as right-associative as opposed to + # prism which has it as left-associative. We reverse that + # associativity here. + nest = left + nest = nest[2] while nest[2][0] == :or + nest[2] = s(node, :or, nest[2], visit(node.right)) + left + else + s(node, :or, left, visit(node.right)) + end + end + + # ``` + # def foo(bar, *baz); end + # ^^^^^^^^^ + # ``` + def visit_parameters_node(node) + children = + node.compact_child_nodes.map do |element| + if element.is_a?(MultiTargetNode) + visit_destructured_parameter(element) + else + visit(element) + end + end + + s(node, :args).concat(children) + end + + # ``` + # def foo((bar, baz)); end + # ^^^^^^^^^^ + # ``` + private def visit_destructured_parameter(node) + children = + [*node.lefts, *node.rest, *node.rights].map do |child| + case child + when RequiredParameterNode + visit(child) + when MultiTargetNode + visit_destructured_parameter(child) + when SplatNode + :"*#{child.expression&.name}" + else + raise + end + end + + s(node, :masgn).concat(children) + end + + # ``` + # () + # ^^ + # + # (1) + # ^^^ + # ``` + def visit_parentheses_node(node) + if node.body.nil? + s(node, :nil) + else + visit(node.body) + end + end + + # ``` + # foo => ^(bar) + # ^^^^^^ + # ``` + def visit_pinned_expression_node(node) + node.expression.accept(copy_compiler(in_pattern: false)) + end + + # ``` + # foo = 1 and bar => ^foo + # ^^^^ + # ``` + def visit_pinned_variable_node(node) + if node.variable.is_a?(LocalVariableReadNode) && node.variable.name.match?(/^_\d$/) + s(node, :lvar, node.variable.name) + else + visit(node.variable) + end + end + + # END {} + def visit_post_execution_node(node) + s(node, :iter, s(node, :postexe), 0, visit(node.statements)) + end + + # BEGIN {} + def visit_pre_execution_node(node) + s(node, :iter, s(node, :preexe), 0, visit(node.statements)) + end + + # The top-level program node. + def visit_program_node(node) + visit(node.statements) + end + + # ``` + # 0..5 + # ^^^^ + # ``` + def visit_range_node(node) + if !in_pattern && !node.left.nil? && !node.right.nil? && ([node.left.type, node.right.type] - %i[nil_node integer_node]).empty? + left = node.left.value if node.left.is_a?(IntegerNode) + right = node.right.value if node.right.is_a?(IntegerNode) + s(node, :lit, Range.new(left, right, node.exclude_end?)) + else + s(node, node.exclude_end? ? :dot3 : :dot2, visit_range_bounds_node(node.left), visit_range_bounds_node(node.right)) + end + end + + # If the bounds of a range node are empty parentheses, then they do not + # get replaced by their usual s(:nil), but instead are s(:begin). + private def visit_range_bounds_node(node) + if node.is_a?(ParenthesesNode) && node.body.nil? + s(node, :begin) + else + visit(node) + end + end + + # ``` + # 1r + # ^^ + # ``` + def visit_rational_node(node) + s(node, :lit, node.value) + end + + # ``` + # redo + # ^^^^ + # ``` + def visit_redo_node(node) + s(node, :redo) + end + + # ``` + # /foo/ + # ^^^^^ + # ``` + def visit_regular_expression_node(node) + s(node, :lit, Regexp.new(node.unescaped, node.options)) + end + + # ``` + # def foo(bar:); end + # ^^^^ + # ``` + def visit_required_keyword_parameter_node(node) + s(node, :kwarg, node.name) + end + + # ``` + # def foo(bar); end + # ^^^ + # ``` + def visit_required_parameter_node(node) + node.name + end + + # ``` + # foo rescue bar + # ^^^^^^^^^^^^^^ + # ``` + def visit_rescue_modifier_node(node) + s(node, :rescue, visit(node.expression), s(node.rescue_expression, :resbody, s(node.rescue_expression, :array), visit(node.rescue_expression))) + end + + # ``` + # begin; rescue; end + # ^^^^^^^ + # ``` + def visit_rescue_node(node) + exceptions = + if node.exceptions.length == 1 && node.exceptions.first.is_a?(SplatNode) + visit(node.exceptions.first) + else + s(node, :array).concat(visit_all(node.exceptions)) + end + + if !node.reference.nil? + exceptions << (visit(node.reference) << s(node.reference, :gvar, :"$!")) + end + + s(node, :resbody, exceptions).concat(node.statements.nil? ? [nil] : visit_all(node.statements.body)) + end + + # ``` + # def foo(*bar); end + # ^^^^ + # + # def foo(*); end + # ^ + # ``` + def visit_rest_parameter_node(node) + :"*#{node.name}" + end + + # ``` + # retry + # ^^^^^ + # ``` + def visit_retry_node(node) + s(node, :retry) + end + + # ``` + # return + # ^^^^^^ + # + # return 1 + # ^^^^^^^^ + # ``` + def visit_return_node(node) + if node.arguments.nil? + s(node, :return) + elsif node.arguments.arguments.length == 1 + argument = node.arguments.arguments.first + s(node, :return, argument.is_a?(SplatNode) ? s(node, :svalue, visit(argument)) : visit(argument)) + else + s(node, :return, s(node, :array).concat(visit_all(node.arguments.arguments))) + end + end + + # ``` + # self + # ^^^^ + # ``` + def visit_self_node(node) + s(node, :self) + end + + # A shareable constant. + def visit_shareable_constant_node(node) + visit(node.write) + end + + # ``` + # class << self; end + # ^^^^^^^^^^^^^^^^^^ + # ``` + def visit_singleton_class_node(node) + s(node, :sclass, visit(node.expression)).tap do |sexp| + sexp << node.body.accept(copy_compiler(in_def: false)) unless node.body.nil? + end + end + + # ``` + # __ENCODING__ + # ^^^^^^^^^^^^ + # ``` + def visit_source_encoding_node(node) + # TODO + s(node, :colon2, s(node, :const, :Encoding), :UTF_8) + end + + # ``` + # __FILE__ + # ^^^^^^^^ + # ``` + def visit_source_file_node(node) + s(node, :str, node.filepath) + end + + # ``` + # __LINE__ + # ^^^^^^^^ + # ``` + def visit_source_line_node(node) + s(node, :lit, node.location.start_line) + end + + # ``` + # foo(*bar) + # ^^^^ + # + # def foo((bar, *baz)); end + # ^^^^ + # + # def foo(*); bar(*); end + # ^ + # ``` + def visit_splat_node(node) + if node.expression.nil? + s(node, :splat) + else + s(node, :splat, visit(node.expression)) + end + end + + # A list of statements. + def visit_statements_node(node) + first, *rest = node.body + + if rest.empty? + visit(first) + else + s(node, :block).concat(visit_all(node.body)) + end + end + + # ``` + # "foo" + # ^^^^^ + # ``` + def visit_string_node(node) + unescaped = node.unescaped + + if node.forced_binary_encoding? + unescaped = unescaped.dup + unescaped.force_encoding(Encoding::BINARY) + end + + s(node, :str, unescaped) + end + + # ``` + # super(foo) + # ^^^^^^^^^^ + # ``` + def visit_super_node(node) + arguments = node.arguments&.arguments || [] + block = node.block + + if block.is_a?(BlockArgumentNode) + arguments << block + block = nil + end + + visit_block(node, s(node, :super).concat(visit_all(arguments)), block) + end + + # ``` + # :foo + # ^^^^ + # ``` + def visit_symbol_node(node) + node.value == "!@" ? s(node, :lit, :"!@") : s(node, :lit, node.unescaped.to_sym) + end + + # ``` + # true + # ^^^^ + # ``` + def visit_true_node(node) + s(node, :true) + end + + # ``` + # undef foo + # ^^^^^^^^^ + # ``` + def visit_undef_node(node) + names = node.names.map { |name| s(node, :undef, visit(name)) } + names.length == 1 ? names.first : s(node, :block).concat(names) + end + + # ``` + # unless foo; bar end + # ^^^^^^^^^^^^^^^^^^^ + # + # bar unless foo + # ^^^^^^^^^^^^^^ + # ``` + def visit_unless_node(node) + s(node, :if, visit(node.predicate), visit(node.else_clause), visit(node.statements)) + end + + # ``` + # until foo; bar end + # ^^^^^^^^^^^^^^^^^ + # + # bar until foo + # ^^^^^^^^^^^^^ + # ``` + def visit_until_node(node) + s(node, :until, visit(node.predicate), visit(node.statements), !node.begin_modifier?) + end + + # ``` + # case foo; when bar; end + # ^^^^^^^^^^^^^ + # ``` + def visit_when_node(node) + s(node, :when, s(node, :array).concat(visit_all(node.conditions))).concat(node.statements.nil? ? [nil] : visit_all(node.statements.body)) + end + + # ``` + # while foo; bar end + # ^^^^^^^^^^^^^^^^^^ + # + # bar while foo + # ^^^^^^^^^^^^^ + # ``` + def visit_while_node(node) + s(node, :while, visit(node.predicate), visit(node.statements), !node.begin_modifier?) + end + + # ``` + # `foo` + # ^^^^^ + # ``` + def visit_x_string_node(node) + result = s(node, :xstr, node.unescaped) + + if node.heredoc? + result.line = node.content_loc.start_line + result.line_max = node.content_loc.end_line + end + + result + end + + # ``` + # yield + # ^^^^^ + # + # yield 1 + # ^^^^^^^ + # ``` + def visit_yield_node(node) + s(node, :yield).concat(visit_all(node.arguments&.arguments || [])) + end + + private + + # Create a new compiler with the given options. + def copy_compiler(in_def: self.in_def, in_pattern: self.in_pattern) + Compiler.new(file, in_def: in_def, in_pattern: in_pattern) + end + + # Create a new Sexp object from the given prism node and arguments. + def s(node, *arguments) + result = Sexp.new(*arguments) + result.file = file + result.line = node.location.start_line + result.line_max = node.location.end_line + result + end + + # Visit a block node, which will modify the AST by wrapping the given + # visited node in an iter node. + def visit_block(node, sexp, block) + if block.nil? + sexp + else + parameters = + case block.parameters + when nil, ItParametersNode, NumberedParametersNode + 0 + else + visit(block.parameters) + end + + if block.body.nil? + s(node, :iter, sexp, parameters) + else + s(node, :iter, sexp, parameters, visit(block.body)) + end + end + end + + # Pattern constants get wrapped in another layer of :const. + def visit_pattern_constant(node) + case node + when nil + # nothing + when ConstantReadNode + visit(node) + else + s(node, :const, visit(node)) + end + end + + # Visit the value of a write, which will be on the right-hand side of + # a write operator. Because implicit arrays can have splats, those could + # potentially be wrapped in an svalue node. + def visit_write_value(node) + if node.is_a?(ArrayNode) && node.opening_loc.nil? + if node.elements.length == 1 && node.elements.first.is_a?(SplatNode) + s(node, :svalue, visit(node.elements.first)) + else + s(node, :svalue, visit(node)) + end + else + visit(node) + end + end + end + + private_constant :Compiler + + # Parse the given source and translate it into the seattlerb/ruby_parser + # gem's Sexp format. + def parse(source, filepath = "(string)") + translate(Prism.parse(source, filepath: filepath, partial_script: true), filepath) + end + + # Parse the given file and translate it into the seattlerb/ruby_parser + # gem's Sexp format. + def parse_file(filepath) + translate(Prism.parse_file(filepath, partial_script: true), filepath) + end + + class << self + # Parse the given source and translate it into the seattlerb/ruby_parser + # gem's Sexp format. + def parse(source, filepath = "(string)") + new.parse(source, filepath) + end + + # Parse the given file and translate it into the seattlerb/ruby_parser + # gem's Sexp format. + def parse_file(filepath) + new.parse_file(filepath) + end + end + + private + + # Translate the given parse result and filepath into the + # seattlerb/ruby_parser gem's Sexp format. + def translate(result, filepath) + if result.failure? + error = result.errors.first + raise ::RubyParser::SyntaxError, "#{filepath}:#{error.location.start_line} :: #{error.message}" + end + + result.value.accept(Compiler.new(filepath)) + end + end + end +end diff --git a/lib/pstore.gemspec b/lib/pstore.gemspec deleted file mode 100644 index 86051d2f438f27..00000000000000 --- a/lib/pstore.gemspec +++ /dev/null @@ -1,32 +0,0 @@ -# frozen_string_literal: true - -name = File.basename(__FILE__, ".gemspec") -version = ["lib", Array.new(name.count("-")+1, ".").join("/")].find do |dir| - break File.foreach(File.join(__dir__, dir, "#{name.tr('-', '/')}.rb")) do |line| - /^\s*VERSION\s*=\s*"(.*)"/ =~ line and break $1 - end rescue nil -end - -Gem::Specification.new do |spec| - spec.name = name - spec.version = version - spec.authors = ["Yukihiro Matsumoto"] - spec.email = ["matz@ruby-lang.org"] - - spec.summary = %q{Transactional File Storage for Ruby Objects} - spec.description = spec.summary - spec.homepage = "https://github.com/ruby/pstore" - spec.licenses = ["Ruby", "BSD-2-Clause"] - - spec.metadata["homepage_uri"] = spec.homepage - spec.metadata["source_code_uri"] = "https://github.com/ruby/pstore" - - # Specify which files should be added to the gem when it is released. - # The `git ls-files -z` loads the files in the RubyGem that have been added into git. - spec.files = Dir.chdir(File.expand_path('..', __FILE__)) do - `git ls-files -z 2>#{IO::NULL}`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) } - end - spec.bindir = "exe" - spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) } - spec.require_paths = ["lib"] -end diff --git a/lib/pstore.rb b/lib/pstore.rb deleted file mode 100644 index 97df3c1509b86b..00000000000000 --- a/lib/pstore.rb +++ /dev/null @@ -1,731 +0,0 @@ -# frozen_string_literal: true -# = PStore -- Transactional File Storage for Ruby Objects -# -# pstore.rb - -# originally by matz -# documentation by Kev Jackson and James Edward Gray II -# improved by Hongli Lai -# -# See PStore for documentation. - -require "digest" - -# \PStore implements a file based persistence mechanism based on a Hash. -# User code can store hierarchies of Ruby objects (values) -# into the data store by name (keys). -# An object hierarchy may be just a single object. -# User code may later read values back from the data store -# or even update data, as needed. -# -# The transactional behavior ensures that any changes succeed or fail together. -# This can be used to ensure that the data store is not left in a transitory state, -# where some values were updated but others were not. -# -# Behind the scenes, Ruby objects are stored to the data store file with Marshal. -# That carries the usual limitations. Proc objects cannot be marshalled, -# for example. -# -# There are three important concepts here (details at the links): -# -# - {Store}[rdoc-ref:PStore@The+Store]: a store is an instance of \PStore. -# - {Entries}[rdoc-ref:PStore@Entries]: the store is hash-like; -# each entry is the key for a stored object. -# - {Transactions}[rdoc-ref:PStore@Transactions]: each transaction is a collection -# of prospective changes to the store; -# a transaction is defined in the block given with a call -# to PStore#transaction. -# -# == About the Examples -# -# Examples on this page need a store that has known properties. -# They can get a new (and populated) store by calling thus: -# -# example_store do |store| -# # Example code using store goes here. -# end -# -# All we really need to know about +example_store+ -# is that it yields a fresh store with a known population of entries; -# its implementation: -# -# require 'pstore' -# require 'tempfile' -# # Yield a pristine store for use in examples. -# def example_store -# # Create the store in a temporary file. -# Tempfile.create do |file| -# store = PStore.new(file) -# # Populate the store. -# store.transaction do -# store[:foo] = 0 -# store[:bar] = 1 -# store[:baz] = 2 -# end -# yield store -# end -# end -# -# == The Store -# -# The contents of the store are maintained in a file whose path is specified -# when the store is created (see PStore.new). -# The objects are stored and retrieved using -# module Marshal, which means that certain objects cannot be added to the store; -# see {Marshal::dump}[rdoc-ref:Marshal.dump]. -# -# == Entries -# -# A store may have any number of entries. -# Each entry has a key and a value, just as in a hash: -# -# - Key: as in a hash, the key can be (almost) any object; -# see {Hash Keys}[rdoc-ref:Hash@Hash+Keys]. -# You may find it convenient to keep it simple by using only -# symbols or strings as keys. -# - Value: the value may be any object that can be marshalled by \Marshal -# (see {Marshal::dump}[rdoc-ref:Marshal.dump]) -# and in fact may be a collection -# (e.g., an array, a hash, a set, a range, etc). -# That collection may in turn contain nested objects, -# including collections, to any depth; -# those objects must also be \Marshal-able. -# See {Hierarchical Values}[rdoc-ref:PStore@Hierarchical+Values]. -# -# == Transactions -# -# === The Transaction Block -# -# The block given with a call to method #transaction# -# contains a _transaction_, -# which consists of calls to \PStore methods that -# read from or write to the store -# (that is, all \PStore methods except #transaction itself, -# #path, and Pstore.new): -# -# example_store do |store| -# store.transaction do -# store.keys # => [:foo, :bar, :baz] -# store[:bat] = 3 -# store.keys # => [:foo, :bar, :baz, :bat] -# end -# end -# -# Execution of the transaction is deferred until the block exits, -# and is executed _atomically_ (all-or-nothing): -# either all transaction calls are executed, or none are. -# This maintains the integrity of the store. -# -# Other code in the block (including even calls to #path and PStore.new) -# is executed immediately, not deferred. -# -# The transaction block: -# -# - May not contain a nested call to #transaction. -# - Is the only context where methods that read from or write to -# the store are allowed. -# -# As seen above, changes in a transaction are made automatically -# when the block exits. -# The block may be exited early by calling method #commit or #abort. -# -# - Method #commit triggers the update to the store and exits the block: -# -# example_store do |store| -# store.transaction do -# store.keys # => [:foo, :bar, :baz] -# store[:bat] = 3 -# store.commit -# fail 'Cannot get here' -# end -# store.transaction do -# # Update was completed. -# store.keys # => [:foo, :bar, :baz, :bat] -# end -# end -# -# - Method #abort discards the update to the store and exits the block: -# -# example_store do |store| -# store.transaction do -# store.keys # => [:foo, :bar, :baz] -# store[:bat] = 3 -# store.abort -# fail 'Cannot get here' -# end -# store.transaction do -# # Update was not completed. -# store.keys # => [:foo, :bar, :baz] -# end -# end -# -# === Read-Only Transactions -# -# By default, a transaction allows both reading from and writing to -# the store: -# -# store.transaction do -# # Read-write transaction. -# # Any code except a call to #transaction is allowed here. -# end -# -# If argument +read_only+ is passed as +true+, -# only reading is allowed: -# -# store.transaction(true) do -# # Read-only transaction: -# # Calls to #transaction, #[]=, and #delete are not allowed here. -# end -# -# == Hierarchical Values -# -# The value for an entry may be a simple object (as seen above). -# It may also be a hierarchy of objects nested to any depth: -# -# deep_store = PStore.new('deep.store') -# deep_store.transaction do -# array_of_hashes = [{}, {}, {}] -# deep_store[:array_of_hashes] = array_of_hashes -# deep_store[:array_of_hashes] # => [{}, {}, {}] -# hash_of_arrays = {foo: [], bar: [], baz: []} -# deep_store[:hash_of_arrays] = hash_of_arrays -# deep_store[:hash_of_arrays] # => {:foo=>[], :bar=>[], :baz=>[]} -# deep_store[:hash_of_arrays][:foo].push(:bat) -# deep_store[:hash_of_arrays] # => {:foo=>[:bat], :bar=>[], :baz=>[]} -# end -# -# And recall that you can use -# {dig methods}[rdoc-ref:dig_methods.rdoc] -# in a returned hierarchy of objects. -# -# == Working with the Store -# -# === Creating a Store -# -# Use method PStore.new to create a store. -# The new store creates or opens its containing file: -# -# store = PStore.new('t.store') -# -# === Modifying the Store -# -# Use method #[]= to update or create an entry: -# -# example_store do |store| -# store.transaction do -# store[:foo] = 1 # Update. -# store[:bam] = 1 # Create. -# end -# end -# -# Use method #delete to remove an entry: -# -# example_store do |store| -# store.transaction do -# store.delete(:foo) -# store[:foo] # => nil -# end -# end -# -# === Retrieving Values -# -# Use method #fetch (allows default) or #[] (defaults to +nil+) -# to retrieve an entry: -# -# example_store do |store| -# store.transaction do -# store[:foo] # => 0 -# store[:nope] # => nil -# store.fetch(:baz) # => 2 -# store.fetch(:nope, nil) # => nil -# store.fetch(:nope) # Raises exception. -# end -# end -# -# === Querying the Store -# -# Use method #key? to determine whether a given key exists: -# -# example_store do |store| -# store.transaction do -# store.key?(:foo) # => true -# end -# end -# -# Use method #keys to retrieve keys: -# -# example_store do |store| -# store.transaction do -# store.keys # => [:foo, :bar, :baz] -# end -# end -# -# Use method #path to retrieve the path to the store's underlying file; -# this method may be called from outside a transaction block: -# -# store = PStore.new('t.store') -# store.path # => "t.store" -# -# == Transaction Safety -# -# For transaction safety, see: -# -# - Optional argument +thread_safe+ at method PStore.new. -# - Attribute #ultra_safe. -# -# Needless to say, if you're storing valuable data with \PStore, then you should -# backup the \PStore file from time to time. -# -# == An Example Store -# -# require "pstore" -# -# # A mock wiki object. -# class WikiPage -# -# attr_reader :page_name -# -# def initialize(page_name, author, contents) -# @page_name = page_name -# @revisions = Array.new -# add_revision(author, contents) -# end -# -# def add_revision(author, contents) -# @revisions << {created: Time.now, -# author: author, -# contents: contents} -# end -# -# def wiki_page_references -# [@page_name] + @revisions.last[:contents].scan(/\b(?:[A-Z]+[a-z]+){2,}/) -# end -# -# end -# -# # Create a new wiki page. -# home_page = WikiPage.new("HomePage", "James Edward Gray II", -# "A page about the JoysOfDocumentation..." ) -# -# wiki = PStore.new("wiki_pages.pstore") -# # Update page data and the index together, or not at all. -# wiki.transaction do -# # Store page. -# wiki[home_page.page_name] = home_page -# # Create page index. -# wiki[:wiki_index] ||= Array.new -# # Update wiki index. -# wiki[:wiki_index].push(*home_page.wiki_page_references) -# end -# -# # Read wiki data, setting argument read_only to true. -# wiki.transaction(true) do -# wiki.keys.each do |key| -# puts key -# puts wiki[key] -# end -# end -# -class PStore - VERSION = "0.1.2" - - RDWR_ACCESS = {mode: IO::RDWR | IO::CREAT | IO::BINARY, encoding: Encoding::ASCII_8BIT}.freeze - RD_ACCESS = {mode: IO::RDONLY | IO::BINARY, encoding: Encoding::ASCII_8BIT}.freeze - WR_ACCESS = {mode: IO::WRONLY | IO::CREAT | IO::TRUNC | IO::BINARY, encoding: Encoding::ASCII_8BIT}.freeze - - # The error type thrown by all PStore methods. - class Error < StandardError - end - - # Whether \PStore should do its best to prevent file corruptions, - # even when an unlikely error (such as memory-error or filesystem error) occurs: - # - # - +true+: changes are posted by creating a temporary file, - # writing the updated data to it, then renaming the file to the given #path. - # File integrity is maintained. - # Note: has effect only if the filesystem has atomic file rename - # (as do POSIX platforms Linux, MacOS, FreeBSD and others). - # - # - +false+ (the default): changes are posted by rewinding the open file - # and writing the updated data. - # File integrity is maintained if the filesystem raises - # no unexpected I/O error; - # if such an error occurs during a write to the store, - # the file may become corrupted. - # - attr_accessor :ultra_safe - - # Returns a new \PStore object. - # - # Argument +file+ is the path to the file in which objects are to be stored; - # if the file exists, it should be one that was written by \PStore. - # - # path = 't.store' - # store = PStore.new(path) - # - # A \PStore object is - # {reentrant}[https://en.wikipedia.org/wiki/Reentrancy_(computing)]. - # If argument +thread_safe+ is given as +true+, - # the object is also thread-safe (at the cost of a small performance penalty): - # - # store = PStore.new(path, true) - # - def initialize(file, thread_safe = false) - dir = File::dirname(file) - unless File::directory? dir - raise PStore::Error, format("directory %s does not exist", dir) - end - if File::exist? file and not File::readable? file - raise PStore::Error, format("file %s not readable", file) - end - @filename = file - @abort = false - @ultra_safe = false - @thread_safe = thread_safe - @lock = Thread::Mutex.new - end - - # Raises PStore::Error if the calling code is not in a PStore#transaction. - def in_transaction - raise PStore::Error, "not in transaction" unless @lock.locked? - end - # - # Raises PStore::Error if the calling code is not in a PStore#transaction or - # if the code is in a read-only PStore#transaction. - # - def in_transaction_wr - in_transaction - raise PStore::Error, "in read-only transaction" if @rdonly - end - private :in_transaction, :in_transaction_wr - - # Returns the value for the given +key+ if the key exists. - # +nil+ otherwise; - # if not +nil+, the returned value is an object or a hierarchy of objects: - # - # example_store do |store| - # store.transaction do - # store[:foo] # => 0 - # store[:nope] # => nil - # end - # end - # - # Returns +nil+ if there is no such key. - # - # See also {Hierarchical Values}[rdoc-ref:PStore@Hierarchical+Values]. - # - # Raises an exception if called outside a transaction block. - def [](key) - in_transaction - @table[key] - end - - # Like #[], except that it accepts a default value for the store. - # If the +key+ does not exist: - # - # - Raises an exception if +default+ is +PStore::Error+. - # - Returns the value of +default+ otherwise: - # - # example_store do |store| - # store.transaction do - # store.fetch(:nope, nil) # => nil - # store.fetch(:nope) # Raises an exception. - # end - # end - # - # Raises an exception if called outside a transaction block. - def fetch(key, default=PStore::Error) - in_transaction - unless @table.key? key - if default == PStore::Error - raise PStore::Error, format("undefined key `%s'", key) - else - return default - end - end - @table[key] - end - - # Creates or replaces the value for the given +key+: - # - # example_store do |store| - # temp.transaction do - # temp[:bat] = 3 - # end - # end - # - # See also {Hierarchical Values}[rdoc-ref:PStore@Hierarchical+Values]. - # - # Raises an exception if called outside a transaction block. - def []=(key, value) - in_transaction_wr - @table[key] = value - end - - # Removes and returns the value at +key+ if it exists: - # - # example_store do |store| - # store.transaction do - # store[:bat] = 3 - # store.delete(:bat) - # end - # end - # - # Returns +nil+ if there is no such key. - # - # Raises an exception if called outside a transaction block. - def delete(key) - in_transaction_wr - @table.delete key - end - - # Returns an array of the existing keys: - # - # example_store do |store| - # store.transaction do - # store.keys # => [:foo, :bar, :baz] - # end - # end - # - # Raises an exception if called outside a transaction block. - def keys - in_transaction - @table.keys - end - alias roots keys - - # Returns +true+ if +key+ exists, +false+ otherwise: - # - # example_store do |store| - # store.transaction do - # store.key?(:foo) # => true - # end - # end - # - # Raises an exception if called outside a transaction block. - def key?(key) - in_transaction - @table.key? key - end - alias root? key? - - # Returns the string file path used to create the store: - # - # store.path # => "flat.store" - # - def path - @filename - end - - # Exits the current transaction block, committing any changes - # specified in the transaction block. - # See {Committing or Aborting}[rdoc-ref:PStore@Committing+or+Aborting]. - # - # Raises an exception if called outside a transaction block. - def commit - in_transaction - @abort = false - throw :pstore_abort_transaction - end - - # Exits the current transaction block, discarding any changes - # specified in the transaction block. - # See {Committing or Aborting}[rdoc-ref:PStore@Committing+or+Aborting]. - # - # Raises an exception if called outside a transaction block. - def abort - in_transaction - @abort = true - throw :pstore_abort_transaction - end - - # Opens a transaction block for the store. - # See {Transactions}[rdoc-ref:PStore@Transactions]. - # - # With argument +read_only+ as +false+, the block may both read from - # and write to the store. - # - # With argument +read_only+ as +true+, the block may not include calls - # to #transaction, #[]=, or #delete. - # - # Raises an exception if called within a transaction block. - def transaction(read_only = false) # :yields: pstore - value = nil - if !@thread_safe - raise PStore::Error, "nested transaction" unless @lock.try_lock - else - begin - @lock.lock - rescue ThreadError - raise PStore::Error, "nested transaction" - end - end - begin - @rdonly = read_only - @abort = false - file = open_and_lock_file(@filename, read_only) - if file - begin - @table, checksum, original_data_size = load_data(file, read_only) - - catch(:pstore_abort_transaction) do - value = yield(self) - end - - if !@abort && !read_only - save_data(checksum, original_data_size, file) - end - ensure - file.close - end - else - # This can only occur if read_only == true. - @table = {} - catch(:pstore_abort_transaction) do - value = yield(self) - end - end - ensure - @lock.unlock - end - value - end - - private - # Constant for relieving Ruby's garbage collector. - CHECKSUM_ALGO = %w[SHA512 SHA384 SHA256 SHA1 RMD160 MD5].each do |algo| - begin - break Digest(algo) - rescue LoadError - end - end - EMPTY_STRING = "" - EMPTY_MARSHAL_DATA = Marshal.dump({}) - EMPTY_MARSHAL_CHECKSUM = CHECKSUM_ALGO.digest(EMPTY_MARSHAL_DATA) - - # - # Open the specified filename (either in read-only mode or in - # read-write mode) and lock it for reading or writing. - # - # The opened File object will be returned. If _read_only_ is true, - # and the file does not exist, then nil will be returned. - # - # All exceptions are propagated. - # - def open_and_lock_file(filename, read_only) - if read_only - begin - file = File.new(filename, **RD_ACCESS) - begin - file.flock(File::LOCK_SH) - return file - rescue - file.close - raise - end - rescue Errno::ENOENT - return nil - end - else - file = File.new(filename, **RDWR_ACCESS) - file.flock(File::LOCK_EX) - return file - end - end - - # Load the given PStore file. - # If +read_only+ is true, the unmarshalled Hash will be returned. - # If +read_only+ is false, a 3-tuple will be returned: the unmarshalled - # Hash, a checksum of the data, and the size of the data. - def load_data(file, read_only) - if read_only - begin - table = load(file) - raise Error, "PStore file seems to be corrupted." unless table.is_a?(Hash) - rescue EOFError - # This seems to be a newly-created file. - table = {} - end - table - else - data = file.read - if data.empty? - # This seems to be a newly-created file. - table = {} - checksum = empty_marshal_checksum - size = empty_marshal_data.bytesize - else - table = load(data) - checksum = CHECKSUM_ALGO.digest(data) - size = data.bytesize - raise Error, "PStore file seems to be corrupted." unless table.is_a?(Hash) - end - data.replace(EMPTY_STRING) - [table, checksum, size] - end - end - - def on_windows? - is_windows = RUBY_PLATFORM =~ /mswin|mingw|bccwin|wince/ - self.class.__send__(:define_method, :on_windows?) do - is_windows - end - is_windows - end - - def save_data(original_checksum, original_file_size, file) - new_data = dump(@table) - - if new_data.bytesize != original_file_size || CHECKSUM_ALGO.digest(new_data) != original_checksum - if @ultra_safe && !on_windows? - # Windows doesn't support atomic file renames. - save_data_with_atomic_file_rename_strategy(new_data, file) - else - save_data_with_fast_strategy(new_data, file) - end - end - - new_data.replace(EMPTY_STRING) - end - - def save_data_with_atomic_file_rename_strategy(data, file) - temp_filename = "#{@filename}.tmp.#{Process.pid}.#{rand 1000000}" - temp_file = File.new(temp_filename, **WR_ACCESS) - begin - temp_file.flock(File::LOCK_EX) - temp_file.write(data) - temp_file.flush - File.rename(temp_filename, @filename) - rescue - File.unlink(temp_file) rescue nil - raise - ensure - temp_file.close - end - end - - def save_data_with_fast_strategy(data, file) - file.rewind - file.write(data) - file.truncate(data.bytesize) - end - - - # This method is just a wrapped around Marshal.dump - # to allow subclass overriding used in YAML::Store. - def dump(table) # :nodoc: - Marshal::dump(table) - end - - # This method is just a wrapped around Marshal.load. - # to allow subclass overriding used in YAML::Store. - def load(content) # :nodoc: - Marshal::load(content) - end - - def empty_marshal_data - EMPTY_MARSHAL_DATA - end - def empty_marshal_checksum - EMPTY_MARSHAL_CHECKSUM - end -end diff --git a/lib/random/formatter.rb b/lib/random/formatter.rb index 45b53a7b6e620e..4ecd6ad027d14a 100644 --- a/lib/random/formatter.rb +++ b/lib/random/formatter.rb @@ -165,15 +165,133 @@ def urlsafe_base64(n=nil, padding=false) # # The result contains 122 random bits (15.25 random bytes). # - # See RFC4122[https://datatracker.ietf.org/doc/html/rfc4122] for details of UUID. + # See RFC9562[https://www.rfc-editor.org/rfc/rfc9562] for details of UUIDv4. # def uuid - ary = random_bytes(16).unpack("NnnnnN") - ary[2] = (ary[2] & 0x0fff) | 0x4000 - ary[3] = (ary[3] & 0x3fff) | 0x8000 - "%08x-%04x-%04x-%04x-%04x%08x" % ary + ary = random_bytes(16) + ary.setbyte(6, (ary.getbyte(6) & 0x0f) | 0x40) + ary.setbyte(8, (ary.getbyte(8) & 0x3f) | 0x80) + ary.unpack("H8H4H4H4H12").join(?-) end + alias uuid_v4 uuid + + # Generate a random v7 UUID (Universally Unique IDentifier). + # + # require 'random/formatter' + # + # Random.uuid_v7 # => "0188d4c3-1311-7f96-85c7-242a7aa58f1e" + # Random.uuid_v7 # => "0188d4c3-16fe-744f-86af-38fa04c62bb5" + # Random.uuid_v7 # => "0188d4c3-1af8-764f-b049-c204ce0afa23" + # Random.uuid_v7 # => "0188d4c3-1e74-7085-b14f-ef6415dc6f31" + # # |<--sorted-->| |<----- random ---->| + # + # # or + # prng = Random.new + # prng.uuid_v7 # => "0188ca51-5e72-7950-a11d-def7ff977c98" + # + # The version 7 UUID starts with the least significant 48 bits of a 64 bit + # Unix timestamp (milliseconds since the epoch) and fills the remaining bits + # with random data, excluding the version and variant bits. + # + # This allows version 7 UUIDs to be sorted by creation time. Time ordered + # UUIDs can be used for better database index locality of newly inserted + # records, which may have a significant performance benefit compared to random + # data inserts. + # + # The result contains 74 random bits (9.25 random bytes). + # + # Note that this method cannot be made reproducible because its output + # includes not only random bits but also timestamp. + # + # See RFC9562[https://www.rfc-editor.org/rfc/rfc9562] for details of UUIDv7. + # + # ==== Monotonicity + # + # UUIDv7 has millisecond precision by default, so multiple UUIDs created + # within the same millisecond are not issued in monotonically increasing + # order. To create UUIDs that are time-ordered with sub-millisecond + # precision, up to 12 bits of additional timestamp may added with + # +extra_timestamp_bits+. The extra timestamp precision comes at the expense + # of random bits. Setting extra_timestamp_bits: 12 provides ~244ns + # of precision, but only 62 random bits (7.75 random bytes). + # + # prng = Random.new + # Array.new(4) { prng.uuid_v7(extra_timestamp_bits: 12) } + # # => + # ["0188d4c7-13da-74f9-8b53-22a786ffdd5a", + # "0188d4c7-13da-753b-83a5-7fb9b2afaeea", + # "0188d4c7-13da-754a-88ea-ac0baeedd8db", + # "0188d4c7-13da-7557-83e1-7cad9cda0d8d"] + # # |<--- sorted --->| |<-- random --->| + # + # Array.new(4) { prng.uuid_v7(extra_timestamp_bits: 8) } + # # => + # ["0188d4c7-3333-7a95-850a-de6edb858f7e", + # "0188d4c7-3333-7ae8-842e-bc3a8b7d0cf9", # <- out of order + # "0188d4c7-3333-7ae2-995a-9f135dc44ead", # <- out of order + # "0188d4c7-3333-7af9-87c3-8f612edac82e"] + # # |<--- sorted -->||<---- random --->| + # + # Any rollbacks of the system clock will break monotonicity. UUIDv7 is based + # on UTC, which excludes leap seconds and can rollback the clock. To avoid + # this, the system clock can synchronize with an NTP server configured to use + # a "leap smear" approach. NTP or PTP will also be needed to synchronize + # across distributed nodes. + # + # Counters and other mechanisms for stronger guarantees of monotonicity are + # not implemented. Applications with stricter requirements should follow + # {Section 6.2}[https://www.rfc-editor.org/rfc/rfc9562.html#name-monotonicity-and-counters] + # of the specification. + # + def uuid_v7(extra_timestamp_bits: 0) + case (extra_timestamp_bits = Integer(extra_timestamp_bits)) + when 0 # min timestamp precision + ms = Process.clock_gettime(Process::CLOCK_REALTIME, :millisecond) + rand = random_bytes(10) + rand.setbyte(0, rand.getbyte(0) & 0x0f | 0x70) # version + rand.setbyte(2, rand.getbyte(2) & 0x3f | 0x80) # variant + "%08x-%04x-%s" % [ + (ms & 0x0000_ffff_ffff_0000) >> 16, + (ms & 0x0000_0000_0000_ffff), + rand.unpack("H4H4H12").join("-") + ] + + when 12 # max timestamp precision + ms, ns = Process.clock_gettime(Process::CLOCK_REALTIME, :nanosecond) + .divmod(1_000_000) + extra_bits = ns * 4096 / 1_000_000 + rand = random_bytes(8) + rand.setbyte(0, rand.getbyte(0) & 0x3f | 0x80) # variant + "%08x-%04x-7%03x-%s" % [ + (ms & 0x0000_ffff_ffff_0000) >> 16, + (ms & 0x0000_0000_0000_ffff), + extra_bits, + rand.unpack("H4H12").join("-") + ] + + when (0..12) # the generic version is slower than the special cases above + rand_a, rand_b1, rand_b2, rand_b3 = random_bytes(10).unpack("nnnN") + rand_mask_bits = 12 - extra_timestamp_bits + ms, ns = Process.clock_gettime(Process::CLOCK_REALTIME, :nanosecond) + .divmod(1_000_000) + "%08x-%04x-%04x-%04x-%04x%08x" % [ + (ms & 0x0000_ffff_ffff_0000) >> 16, + (ms & 0x0000_0000_0000_ffff), + 0x7000 | + ((ns * (1 << extra_timestamp_bits) / 1_000_000) << rand_mask_bits) | + rand_a & ((1 << rand_mask_bits) - 1), + 0x8000 | (rand_b1 & 0x3fff), + rand_b2, + rand_b3 + ] + + else + raise ArgumentError, "extra_timestamp_bits must be in 0..12" + end + end + + # Internal interface to Random; Generate random data _n_ bytes. private def gen_random(n) self.bytes(n) end @@ -221,7 +339,9 @@ def uuid result end - ALPHANUMERIC = [*'A'..'Z', *'a'..'z', *'0'..'9'] + # The default character list for #alphanumeric. + ALPHANUMERIC = [*'A'..'Z', *'a'..'z', *'0'..'9'].map(&:freeze).freeze + # Generate a random alphanumeric string. # # The argument _n_ specifies the length, in characters, of the alphanumeric diff --git a/lib/rdoc.rb b/lib/rdoc.rb deleted file mode 100644 index b62c22576d48a4..00000000000000 --- a/lib/rdoc.rb +++ /dev/null @@ -1,201 +0,0 @@ -# frozen_string_literal: true -$DEBUG_RDOC = nil - -# :main: README.rdoc - -## -# RDoc produces documentation for Ruby source files by parsing the source and -# extracting the definition for classes, modules, methods, includes and -# requires. It associates these with optional documentation contained in an -# immediately preceding comment block then renders the result using an output -# formatter. -# -# For a simple introduction to writing or generating documentation using RDoc -# see the README. -# -# == Roadmap -# -# If you think you found a bug in RDoc see CONTRIBUTING@Bugs -# -# If you want to use RDoc to create documentation for your Ruby source files, -# see RDoc::Markup and refer to rdoc --help for command line usage. -# -# If you want to set the default markup format see -# RDoc::Markup@Supported+Formats -# -# If you want to store rdoc configuration in your gem (such as the default -# markup format) see RDoc::Options@Saved+Options -# -# If you want to write documentation for Ruby files see RDoc::Parser::Ruby -# -# If you want to write documentation for extensions written in C see -# RDoc::Parser::C -# -# If you want to generate documentation using rake see RDoc::Task. -# -# If you want to drive RDoc programmatically, see RDoc::RDoc. -# -# If you want to use the library to format text blocks into HTML or other -# formats, look at RDoc::Markup. -# -# If you want to make an RDoc plugin such as a generator or directive handler -# see RDoc::RDoc. -# -# If you want to write your own output generator see RDoc::Generator. -# -# If you want an overview of how RDoc works see CONTRIBUTING -# -# == Credits -# -# RDoc is currently being maintained by Eric Hodel . -# -# Dave Thomas is the original author of RDoc. -# -# * The Ruby parser in rdoc/parse.rb is based heavily on the outstanding -# work of Keiju ISHITSUKA of Nippon Rational Inc, who produced the Ruby -# parser for irb and the rtags package. - -module RDoc - - ## - # Exception thrown by any rdoc error. - - class Error < RuntimeError; end - - require_relative 'rdoc/version' - - ## - # Method visibilities - - VISIBILITIES = [:public, :protected, :private] - - ## - # Name of the dotfile that contains the description of files to be processed - # in the current directory - - DOT_DOC_FILENAME = ".document" - - ## - # General RDoc modifiers - - GENERAL_MODIFIERS = %w[nodoc].freeze - - ## - # RDoc modifiers for classes - - CLASS_MODIFIERS = GENERAL_MODIFIERS - - ## - # RDoc modifiers for attributes - - ATTR_MODIFIERS = GENERAL_MODIFIERS - - ## - # RDoc modifiers for constants - - CONSTANT_MODIFIERS = GENERAL_MODIFIERS - - ## - # RDoc modifiers for methods - - METHOD_MODIFIERS = GENERAL_MODIFIERS + - %w[arg args yield yields notnew not-new not_new doc] - - ## - # Loads the best available YAML library. - - def self.load_yaml - begin - gem 'psych' - rescue NameError => e # --disable-gems - raise unless e.name == :gem - rescue Gem::LoadError - end - - begin - require 'psych' - rescue ::LoadError - ensure - require 'yaml' - end - end - - def self.home - rdoc_dir = begin - File.expand_path('~/.rdoc') - rescue ArgumentError - end - - if File.directory?(rdoc_dir) - rdoc_dir - else - begin - # XDG - xdg_data_home = ENV["XDG_DATA_HOME"] || File.join(File.expand_path("~"), '.local', 'share') - unless File.exist?(xdg_data_home) - FileUtils.mkdir_p xdg_data_home - end - File.join xdg_data_home, "rdoc" - rescue Errno::EACCES - end - end - end - - autoload :RDoc, "#{__dir__}/rdoc/rdoc" - - autoload :CrossReference, "#{__dir__}/rdoc/cross_reference" - autoload :ERBIO, "#{__dir__}/rdoc/erbio" - autoload :ERBPartial, "#{__dir__}/rdoc/erb_partial" - autoload :Encoding, "#{__dir__}/rdoc/encoding" - autoload :Generator, "#{__dir__}/rdoc/generator" - autoload :Options, "#{__dir__}/rdoc/options" - autoload :Parser, "#{__dir__}/rdoc/parser" - autoload :Servlet, "#{__dir__}/rdoc/servlet" - autoload :RI, "#{__dir__}/rdoc/ri" - autoload :Stats, "#{__dir__}/rdoc/stats" - autoload :Store, "#{__dir__}/rdoc/store" - autoload :Task, "#{__dir__}/rdoc/task" - autoload :Text, "#{__dir__}/rdoc/text" - - autoload :Markdown, "#{__dir__}/rdoc/markdown" - autoload :Markup, "#{__dir__}/rdoc/markup" - autoload :RD, "#{__dir__}/rdoc/rd" - autoload :TomDoc, "#{__dir__}/rdoc/tom_doc" - - autoload :KNOWN_CLASSES, "#{__dir__}/rdoc/known_classes" - - autoload :TokenStream, "#{__dir__}/rdoc/token_stream" - - autoload :Comment, "#{__dir__}/rdoc/comment" - - require_relative 'rdoc/i18n' - - # code objects - # - # We represent the various high-level code constructs that appear in Ruby - # programs: classes, modules, methods, and so on. - autoload :CodeObject, "#{__dir__}/rdoc/code_object" - - autoload :Context, "#{__dir__}/rdoc/context" - autoload :TopLevel, "#{__dir__}/rdoc/top_level" - - autoload :AnonClass, "#{__dir__}/rdoc/anon_class" - autoload :ClassModule, "#{__dir__}/rdoc/class_module" - autoload :NormalClass, "#{__dir__}/rdoc/normal_class" - autoload :NormalModule, "#{__dir__}/rdoc/normal_module" - autoload :SingleClass, "#{__dir__}/rdoc/single_class" - - autoload :Alias, "#{__dir__}/rdoc/alias" - autoload :AnyMethod, "#{__dir__}/rdoc/any_method" - autoload :MethodAttr, "#{__dir__}/rdoc/method_attr" - autoload :GhostMethod, "#{__dir__}/rdoc/ghost_method" - autoload :MetaMethod, "#{__dir__}/rdoc/meta_method" - autoload :Attr, "#{__dir__}/rdoc/attr" - - autoload :Constant, "#{__dir__}/rdoc/constant" - autoload :Mixin, "#{__dir__}/rdoc/mixin" - autoload :Include, "#{__dir__}/rdoc/include" - autoload :Extend, "#{__dir__}/rdoc/extend" - autoload :Require, "#{__dir__}/rdoc/require" - -end diff --git a/lib/rdoc/.document b/lib/rdoc/.document deleted file mode 100644 index 6b5e1b21a569ba..00000000000000 --- a/lib/rdoc/.document +++ /dev/null @@ -1,2 +0,0 @@ -*.rb -parser diff --git a/lib/rdoc/alias.rb b/lib/rdoc/alias.rb deleted file mode 100644 index 446cf9ccb4855f..00000000000000 --- a/lib/rdoc/alias.rb +++ /dev/null @@ -1,111 +0,0 @@ -# frozen_string_literal: true -## -# Represent an alias, which is an old_name/new_name pair associated with a -# particular context -#-- -# TODO implement Alias as a proxy to a method/attribute, inheriting from -# MethodAttr - -class RDoc::Alias < RDoc::CodeObject - - ## - # Aliased method's name - - attr_reader :new_name - - alias name new_name - - ## - # Aliasee method's name - - attr_reader :old_name - - ## - # Is this an alias declared in a singleton context? - - attr_accessor :singleton - - ## - # Source file token stream - - attr_reader :text - - ## - # Creates a new Alias with a token stream of +text+ that aliases +old_name+ - # to +new_name+, has +comment+ and is a +singleton+ context. - - def initialize(text, old_name, new_name, comment, singleton = false) - super() - - @text = text - @singleton = singleton - @old_name = old_name - @new_name = new_name - self.comment = comment - end - - ## - # Order by #singleton then #new_name - - def <=>(other) - [@singleton ? 0 : 1, new_name] <=> [other.singleton ? 0 : 1, other.new_name] - end - - ## - # HTML fragment reference for this alias - - def aref - type = singleton ? 'c' : 'i' - "#alias-#{type}-#{html_name}" - end - - ## - # Full old name including namespace - - def full_old_name - @full_name || "#{parent.name}#{pretty_old_name}" - end - - ## - # HTML id-friendly version of +#new_name+. - - def html_name - CGI.escape(@new_name.gsub('-', '-2D')).gsub('%','-').sub(/^-/, '') - end - - def inspect # :nodoc: - parent_name = parent ? parent.name : '(unknown)' - "#<%s:0x%x %s.alias_method %s, %s>" % [ - self.class, object_id, - parent_name, @old_name, @new_name, - ] - end - - ## - # '::' for the alias of a singleton method/attribute, '#' for instance-level. - - def name_prefix - singleton ? '::' : '#' - end - - ## - # Old name with prefix '::' or '#'. - - def pretty_old_name - "#{singleton ? '::' : '#'}#{@old_name}" - end - - ## - # New name with prefix '::' or '#'. - - def pretty_new_name - "#{singleton ? '::' : '#'}#{@new_name}" - end - - alias pretty_name pretty_new_name - - def to_s # :nodoc: - "alias: #{self.new_name} -> #{self.pretty_old_name} in: #{parent}" - end - -end diff --git a/lib/rdoc/anon_class.rb b/lib/rdoc/anon_class.rb deleted file mode 100644 index 3c2f0e1877dabf..00000000000000 --- a/lib/rdoc/anon_class.rb +++ /dev/null @@ -1,10 +0,0 @@ -# frozen_string_literal: true -## -# An anonymous class like: -# -# c = Class.new do end -# -# AnonClass is currently not used. - -class RDoc::AnonClass < RDoc::ClassModule -end diff --git a/lib/rdoc/any_method.rb b/lib/rdoc/any_method.rb deleted file mode 100644 index 465c4a4fb2d7ef..00000000000000 --- a/lib/rdoc/any_method.rb +++ /dev/null @@ -1,379 +0,0 @@ -# frozen_string_literal: true -## -# AnyMethod is the base class for objects representing methods - -class RDoc::AnyMethod < RDoc::MethodAttr - - ## - # 2:: - # RDoc 4 - # Added calls_super - # Added parent name and class - # Added section title - # 3:: - # RDoc 4.1 - # Added is_alias_for - - MARSHAL_VERSION = 3 # :nodoc: - - ## - # Don't rename \#initialize to \::new - - attr_accessor :dont_rename_initialize - - ## - # The C function that implements this method (if it was defined in a C file) - - attr_accessor :c_function - - # The section title of the method (if defined in a C file via +:category:+) - attr_accessor :section_title - - # Parameters for this method - - attr_accessor :params - - ## - # If true this method uses +super+ to call a superclass version - - attr_accessor :calls_super - - include RDoc::TokenStream - - ## - # Creates a new AnyMethod with a token stream +text+ and +name+ - - def initialize text, name - super - - @c_function = nil - @dont_rename_initialize = false - @token_stream = nil - @calls_super = false - @superclass_method = nil - end - - ## - # Adds +an_alias+ as an alias for this method in +context+. - - def add_alias an_alias, context = nil - method = self.class.new an_alias.text, an_alias.new_name - - method.record_location an_alias.file - method.singleton = self.singleton - method.params = self.params - method.visibility = self.visibility - method.comment = an_alias.comment - method.is_alias_for = self - @aliases << method - context.add_method method if context - method - end - - ## - # Prefix for +aref+ is 'method'. - - def aref_prefix - 'method' - end - - ## - # The call_seq or the param_seq with method name, if there is no call_seq. - # - # Use this for displaying a method's argument lists. - - def arglists - if @call_seq then - @call_seq - elsif @params then - "#{name}#{param_seq}" - end - end - - ## - # Different ways to call this method - - def call_seq - unless call_seq = _call_seq - call_seq = is_alias_for._call_seq if is_alias_for - end - - return unless call_seq - - deduplicate_call_seq(call_seq) - end - - ## - # Sets the different ways you can call this method. If an empty +call_seq+ - # is given nil is assumed. - # - # See also #param_seq - - def call_seq= call_seq - return if call_seq.empty? - - @call_seq = call_seq - end - - ## - # Whether the method has a call-seq. - - def has_call_seq? - !!(@call_seq || is_alias_for&._call_seq) - end - - ## - # Loads is_alias_for from the internal name. Returns nil if the alias - # cannot be found. - - def is_alias_for # :nodoc: - case @is_alias_for - when RDoc::MethodAttr then - @is_alias_for - when Array then - return nil unless @store - - klass_name, singleton, method_name = @is_alias_for - - return nil unless klass = @store.find_class_or_module(klass_name) - - @is_alias_for = klass.find_method method_name, singleton - end - end - - ## - # Dumps this AnyMethod for use by ri. See also #marshal_load - - def marshal_dump - aliases = @aliases.map do |a| - [a.name, parse(a.comment)] - end - - is_alias_for = [ - @is_alias_for.parent.full_name, - @is_alias_for.singleton, - @is_alias_for.name - ] if @is_alias_for - - [ MARSHAL_VERSION, - @name, - full_name, - @singleton, - @visibility, - parse(@comment), - @call_seq, - @block_params, - aliases, - @params, - @file.relative_name, - @calls_super, - @parent.name, - @parent.class, - @section.title, - is_alias_for, - ] - end - - ## - # Loads this AnyMethod from +array+. For a loaded AnyMethod the following - # methods will return cached values: - # - # * #full_name - # * #parent_name - - def marshal_load array - initialize_visibility - - @dont_rename_initialize = nil - @token_stream = nil - @aliases = [] - @parent = nil - @parent_name = nil - @parent_class = nil - @section = nil - @file = nil - - version = array[0] - @name = array[1] - @full_name = array[2] - @singleton = array[3] - @visibility = array[4] - @comment = array[5] - @call_seq = array[6] - @block_params = array[7] - # 8 handled below - @params = array[9] - # 10 handled below - @calls_super = array[11] - @parent_name = array[12] - @parent_title = array[13] - @section_title = array[14] - @is_alias_for = array[15] - - array[8].each do |new_name, comment| - add_alias RDoc::Alias.new(nil, @name, new_name, comment, @singleton) - end - - @parent_name ||= if @full_name =~ /#/ then - $` - else - name = @full_name.split('::') - name.pop - name.join '::' - end - - @file = RDoc::TopLevel.new array[10] if version > 0 - end - - ## - # Method name - # - # If the method has no assigned name, it extracts it from #call_seq. - - def name - return @name if @name - - @name = - @call_seq[/^.*?\.(\w+)/, 1] || - @call_seq[/^.*?(\w+)/, 1] || - @call_seq if @call_seq - end - - ## - # A list of this method's method and yield parameters. +call-seq+ params - # are preferred over parsed method and block params. - - def param_list - if @call_seq then - params = @call_seq.split("\n").last - params = params.sub(/.*?\((.*)\)/, '\1') - params = params.sub(/(\{|do)\s*\|([^|]*)\|.*/, ',\2') - elsif @params then - params = @params.sub(/\((.*)\)/, '\1') - - params << ",#{@block_params}" if @block_params - elsif @block_params then - params = @block_params - else - return [] - end - - if @block_params then - # If this method has explicit block parameters, remove any explicit - # &block - params = params.sub(/,?\s*&\w+/, '') - else - params = params.sub(/\&(\w+)/, '\1') - end - - params = params.gsub(/\s+/, '').split(',').reject(&:empty?) - - params.map { |param| param.sub(/=.*/, '') } - end - - ## - # Pretty parameter list for this method. If the method's parameters were - # given by +call-seq+ it is preferred over the parsed values. - - def param_seq - if @call_seq then - params = @call_seq.split("\n").last - params = params.sub(/[^( ]+/, '') - params = params.sub(/(\|[^|]+\|)\s*\.\.\.\s*(end|\})/, '\1 \2') - elsif @params then - params = @params.gsub(/\s*\#.*/, '') - params = params.tr_s("\n ", " ") - params = "(#{params})" unless params[0] == ?( - else - params = '' - end - - if @block_params then - # If this method has explicit block parameters, remove any explicit - # &block - params = params.sub(/,?\s*&\w+/, '') - - block = @block_params.tr_s("\n ", " ") - if block[0] == ?( - block = block.sub(/^\(/, '').sub(/\)/, '') - end - params << " { |#{block}| ... }" - end - - params - end - - ## - # Whether to skip the method description, true for methods that have - # aliases with a call-seq that doesn't include the method name. - - def skip_description? - has_call_seq? && call_seq.nil? && !!(is_alias_for || !aliases.empty?) - end - - ## - # Sets the store for this method and its referenced code objects. - - def store= store - super - - @file = @store.add_file @file.full_name if @file - end - - ## - # For methods that +super+, find the superclass method that would be called. - - def superclass_method - return unless @calls_super - return @superclass_method if @superclass_method - - parent.each_ancestor do |ancestor| - if method = ancestor.method_list.find { |m| m.name == @name } then - @superclass_method = method - break - end - end - - @superclass_method - end - - protected - - ## - # call_seq without deduplication and alias lookup. - - def _call_seq - @call_seq if defined?(@call_seq) && @call_seq - end - - private - - ## - # call_seq with alias examples information removed, if this - # method is an alias method. - - def deduplicate_call_seq(call_seq) - return call_seq unless is_alias_for || !aliases.empty? - - method_name = self.name - method_name = method_name[0, 1] if method_name =~ /\A\[/ - - entries = call_seq.split "\n" - - ignore = aliases.map(&:name) - if is_alias_for - ignore << is_alias_for.name - ignore.concat is_alias_for.aliases.map(&:name) - end - ignore.map! { |n| n =~ /\A\[/ ? /\[.*\]/ : n} - ignore.delete(method_name) - ignore = Regexp.union(ignore) - - matching = entries.reject do |entry| - entry =~ /^\w*\.?#{ignore}[$\(\s]/ or - entry =~ /\s#{ignore}\s/ - end - - matching.empty? ? nil : matching.join("\n") - end -end diff --git a/lib/rdoc/attr.rb b/lib/rdoc/attr.rb deleted file mode 100644 index a4032359334f31..00000000000000 --- a/lib/rdoc/attr.rb +++ /dev/null @@ -1,175 +0,0 @@ -# frozen_string_literal: true -## -# An attribute created by \#attr, \#attr_reader, \#attr_writer or -# \#attr_accessor - -class RDoc::Attr < RDoc::MethodAttr - - ## - # 3:: - # RDoc 4 - # Added parent name and class - # Added section title - - MARSHAL_VERSION = 3 # :nodoc: - - ## - # Is the attribute readable ('R'), writable ('W') or both ('RW')? - - attr_accessor :rw - - ## - # Creates a new Attr with body +text+, +name+, read/write status +rw+ and - # +comment+. +singleton+ marks this as a class attribute. - - def initialize(text, name, rw, comment, singleton = false) - super text, name - - @rw = rw - @singleton = singleton - self.comment = comment - end - - ## - # Attributes are equal when their names, singleton and rw are identical - - def == other - self.class == other.class and - self.name == other.name and - self.rw == other.rw and - self.singleton == other.singleton - end - - ## - # Add +an_alias+ as an attribute in +context+. - - def add_alias(an_alias, context) - new_attr = self.class.new(self.text, an_alias.new_name, self.rw, - self.comment, self.singleton) - - new_attr.record_location an_alias.file - new_attr.visibility = self.visibility - new_attr.is_alias_for = self - @aliases << new_attr - context.add_attribute new_attr - new_attr - end - - ## - # The #aref prefix for attributes - - def aref_prefix - 'attribute' - end - - ## - # Attributes never call super. See RDoc::AnyMethod#calls_super - # - # An RDoc::Attr can show up in the method list in some situations (see - # Gem::ConfigFile) - - def calls_super # :nodoc: - false - end - - ## - # Returns attr_reader, attr_writer or attr_accessor as appropriate. - - def definition - case @rw - when 'RW' then 'attr_accessor' - when 'R' then 'attr_reader' - when 'W' then 'attr_writer' - end - end - - def inspect # :nodoc: - alias_for = @is_alias_for ? " (alias for #{@is_alias_for.name})" : nil - visibility = self.visibility - visibility = "forced #{visibility}" if force_documentation - "#<%s:0x%x %s %s (%s)%s>" % [ - self.class, object_id, - full_name, - rw, - visibility, - alias_for, - ] - end - - ## - # Dumps this Attr for use by ri. See also #marshal_load - - def marshal_dump - [ MARSHAL_VERSION, - @name, - full_name, - @rw, - @visibility, - parse(@comment), - singleton, - @file.relative_name, - @parent.full_name, - @parent.class, - @section.title - ] - end - - ## - # Loads this Attr from +array+. For a loaded Attr the following - # methods will return cached values: - # - # * #full_name - # * #parent_name - - def marshal_load array - initialize_visibility - - @aliases = [] - @parent = nil - @parent_name = nil - @parent_class = nil - @section = nil - @file = nil - - version = array[0] - @name = array[1] - @full_name = array[2] - @rw = array[3] - @visibility = array[4] - @comment = array[5] - @singleton = array[6] || false # MARSHAL_VERSION == 0 - # 7 handled below - @parent_name = array[8] - @parent_class = array[9] - @section_title = array[10] - - @file = RDoc::TopLevel.new array[7] if version > 1 - - @parent_name ||= @full_name.split('#', 2).first - end - - def pretty_print q # :nodoc: - q.group 2, "[#{self.class.name} #{full_name} #{rw} #{visibility}", "]" do - unless comment.empty? then - q.breakable - q.text "comment:" - q.breakable - q.pp @comment - end - end - end - - def to_s # :nodoc: - "#{definition} #{name} in: #{parent}" - end - - ## - # Attributes do not have token streams. - # - # An RDoc::Attr can show up in the method list in some situations (see - # Gem::ConfigFile) - - def token_stream # :nodoc: - end - -end diff --git a/lib/rdoc/class_module.rb b/lib/rdoc/class_module.rb deleted file mode 100644 index c69e14b5e4ba0b..00000000000000 --- a/lib/rdoc/class_module.rb +++ /dev/null @@ -1,801 +0,0 @@ -# frozen_string_literal: true -## -# ClassModule is the base class for objects representing either a class or a -# module. - -class RDoc::ClassModule < RDoc::Context - - ## - # 1:: - # RDoc 3.7 - # * Added visibility, singleton and file to attributes - # * Added file to constants - # * Added file to includes - # * Added file to methods - # 2:: - # RDoc 3.13 - # * Added extends - # 3:: - # RDoc 4.0 - # * Added sections - # * Added in_files - # * Added parent name - # * Complete Constant dump - - MARSHAL_VERSION = 3 # :nodoc: - - ## - # Constants that are aliases for this class or module - - attr_accessor :constant_aliases - - ## - # Comment and the location it came from. Use #add_comment to add comments - - attr_accessor :comment_location - - attr_accessor :diagram # :nodoc: - - ## - # Class or module this constant is an alias for - - attr_accessor :is_alias_for - - ## - # Return a RDoc::ClassModule of class +class_type+ that is a copy - # of module +module+. Used to promote modules to classes. - #-- - # TODO move to RDoc::NormalClass (I think) - - def self.from_module class_type, mod - klass = class_type.new mod.name - - mod.comment_location.each do |comment, location| - klass.add_comment comment, location - end - - klass.parent = mod.parent - klass.section = mod.section - klass.viewer = mod.viewer - - klass.attributes.concat mod.attributes - klass.method_list.concat mod.method_list - klass.aliases.concat mod.aliases - klass.external_aliases.concat mod.external_aliases - klass.constants.concat mod.constants - klass.includes.concat mod.includes - klass.extends.concat mod.extends - - klass.methods_hash.update mod.methods_hash - klass.constants_hash.update mod.constants_hash - - klass.current_section = mod.current_section - klass.in_files.concat mod.in_files - klass.sections.concat mod.sections - klass.unmatched_alias_lists = mod.unmatched_alias_lists - klass.current_section = mod.current_section - klass.visibility = mod.visibility - - klass.classes_hash.update mod.classes_hash - klass.modules_hash.update mod.modules_hash - klass.metadata.update mod.metadata - - klass.document_self = mod.received_nodoc ? nil : mod.document_self - klass.document_children = mod.document_children - klass.force_documentation = mod.force_documentation - klass.done_documenting = mod.done_documenting - - # update the parent of all children - - (klass.attributes + - klass.method_list + - klass.aliases + - klass.external_aliases + - klass.constants + - klass.includes + - klass.extends + - klass.classes + - klass.modules).each do |obj| - obj.parent = klass - obj.full_name = nil - end - - klass - end - - ## - # Creates a new ClassModule with +name+ with optional +superclass+ - # - # This is a constructor for subclasses, and must never be called directly. - - def initialize(name, superclass = nil) - @constant_aliases = [] - @diagram = nil - @is_alias_for = nil - @name = name - @superclass = superclass - @comment_location = [] # [[comment, location]] - - super() - end - - ## - # Adds +comment+ to this ClassModule's list of comments at +location+. This - # method is preferred over #comment= since it allows ri data to be updated - # across multiple runs. - - def add_comment comment, location - return unless document_self - - original = comment - - comment = case comment - when RDoc::Comment then - comment.normalize - else - normalize_comment comment - end - - if location.parser == RDoc::Parser::C - @comment_location.delete_if { |(_, l)| l == location } - end - - @comment_location << [comment, location] - - self.comment = original - end - - def add_things my_things, other_things # :nodoc: - other_things.each do |group, things| - my_things[group].each { |thing| yield false, thing } if - my_things.include? group - - things.each do |thing| - yield true, thing - end - end - end - - ## - # Ancestors list for this ClassModule: the list of included modules - # (classes will add their superclass if any). - # - # Returns the included classes or modules, not the includes - # themselves. The returned values are either String or - # RDoc::NormalModule instances (see RDoc::Include#module). - # - # The values are returned in reverse order of their inclusion, - # which is the order suitable for searching methods/attributes - # in the ancestors. The superclass, if any, comes last. - - def ancestors - includes.map { |i| i.module }.reverse - end - - def aref_prefix # :nodoc: - raise NotImplementedError, "missing aref_prefix for #{self.class}" - end - - ## - # HTML fragment reference for this module or class. See - # RDoc::NormalClass#aref and RDoc::NormalModule#aref - - def aref - "#{aref_prefix}-#{full_name}" - end - - ## - # Ancestors of this class or module only - - alias direct_ancestors ancestors - - ## - # Clears the comment. Used by the Ruby parser. - - def clear_comment - @comment = '' - end - - ## - # This method is deprecated, use #add_comment instead. - # - # Appends +comment+ to the current comment, but separated by a rule. Works - # more like +=. - - def comment= comment # :nodoc: - comment = case comment - when RDoc::Comment then - comment.normalize - else - normalize_comment comment - end - - comment = "#{@comment.to_s}\n---\n#{comment.to_s}" unless @comment.empty? - - super comment - end - - ## - # Prepares this ClassModule for use by a generator. - # - # See RDoc::Store#complete - - def complete min_visibility - update_aliases - remove_nodoc_children - update_includes - remove_invisible min_visibility - end - - ## - # Does this ClassModule or any of its methods have document_self set? - - def document_self_or_methods - document_self || method_list.any?{ |m| m.document_self } - end - - ## - # Does this class or module have a comment with content or is - # #received_nodoc true? - - def documented? - return true if @received_nodoc - return false if @comment_location.empty? - @comment_location.any? { |comment, _| not comment.empty? } - end - - ## - # Iterates the ancestors of this class or module for which an - # RDoc::ClassModule exists. - - def each_ancestor # :yields: module - return enum_for __method__ unless block_given? - - ancestors.each do |mod| - next if String === mod - next if self == mod - yield mod - end - end - - ## - # Looks for a symbol in the #ancestors. See Context#find_local_symbol. - - def find_ancestor_local_symbol symbol - each_ancestor do |m| - res = m.find_local_symbol(symbol) - return res if res - end - - nil - end - - ## - # Finds a class or module with +name+ in this namespace or its descendants - - def find_class_named name - return self if full_name == name - return self if @name == name - - @classes.values.find do |klass| - next if klass == self - klass.find_class_named name - end - end - - ## - # Return the fully qualified name of this class or module - - def full_name - @full_name ||= if RDoc::ClassModule === parent then - "#{parent.full_name}::#{@name}" - else - @name - end - end - - ## - # TODO: filter included items by #display? - - def marshal_dump # :nodoc: - attrs = attributes.sort.map do |attr| - next unless attr.display? - [ attr.name, attr.rw, - attr.visibility, attr.singleton, attr.file_name, - ] - end.compact - - method_types = methods_by_type.map do |type, visibilities| - visibilities = visibilities.map do |visibility, methods| - method_names = methods.map do |method| - next unless method.display? - [method.name, method.file_name] - end.compact - - [visibility, method_names.uniq] - end - - [type, visibilities] - end - - [ MARSHAL_VERSION, - @name, - full_name, - @superclass, - parse(@comment_location), - attrs, - constants.select { |constant| constant.display? }, - includes.map do |incl| - next unless incl.display? - [incl.name, parse(incl.comment), incl.file_name] - end.compact, - method_types, - extends.map do |ext| - next unless ext.display? - [ext.name, parse(ext.comment), ext.file_name] - end.compact, - @sections.values, - @in_files.map do |tl| - tl.relative_name - end, - parent.full_name, - parent.class, - ] - end - - def marshal_load array # :nodoc: - initialize_visibility - initialize_methods_etc - @current_section = nil - @document_self = true - @done_documenting = false - @parent = nil - @temporary_section = nil - @visibility = nil - @classes = {} - @modules = {} - - @name = array[1] - @full_name = array[2] - @superclass = array[3] - @comment = array[4] - - @comment_location = if RDoc::Markup::Document === @comment.parts.first then - @comment - else - RDoc::Markup::Document.new @comment - end - - array[5].each do |name, rw, visibility, singleton, file| - singleton ||= false - visibility ||= :public - - attr = RDoc::Attr.new nil, name, rw, nil, singleton - - add_attribute attr - attr.visibility = visibility - attr.record_location RDoc::TopLevel.new file - end - - array[6].each do |constant, comment, file| - case constant - when RDoc::Constant then - add_constant constant - else - constant = add_constant RDoc::Constant.new(constant, nil, comment) - constant.record_location RDoc::TopLevel.new file - end - end - - array[7].each do |name, comment, file| - incl = add_include RDoc::Include.new(name, comment) - incl.record_location RDoc::TopLevel.new file - end - - array[8].each do |type, visibilities| - visibilities.each do |visibility, methods| - @visibility = visibility - - methods.each do |name, file| - method = RDoc::AnyMethod.new nil, name - method.singleton = true if type == 'class' - method.record_location RDoc::TopLevel.new file - add_method method - end - end - end - - array[9].each do |name, comment, file| - ext = add_extend RDoc::Extend.new(name, comment) - ext.record_location RDoc::TopLevel.new file - end if array[9] # Support Marshal version 1 - - sections = (array[10] || []).map do |section| - [section.title, section] - end - - @sections = Hash[*sections.flatten] - @current_section = add_section nil - - @in_files = [] - - (array[11] || []).each do |filename| - record_location RDoc::TopLevel.new filename - end - - @parent_name = array[12] - @parent_class = array[13] - end - - ## - # Merges +class_module+ into this ClassModule. - # - # The data in +class_module+ is preferred over the receiver. - - def merge class_module - @parent = class_module.parent - @parent_name = class_module.parent_name - - other_document = parse class_module.comment_location - - if other_document then - document = parse @comment_location - - document = document.merge other_document - - @comment = @comment_location = document - end - - cm = class_module - other_files = cm.in_files - - merge_collections attributes, cm.attributes, other_files do |add, attr| - if add then - add_attribute attr - else - @attributes.delete attr - @methods_hash.delete attr.pretty_name - end - end - - merge_collections constants, cm.constants, other_files do |add, const| - if add then - add_constant const - else - @constants.delete const - @constants_hash.delete const.name - end - end - - merge_collections includes, cm.includes, other_files do |add, incl| - if add then - add_include incl - else - @includes.delete incl - end - end - - @includes.uniq! # clean up - - merge_collections extends, cm.extends, other_files do |add, ext| - if add then - add_extend ext - else - @extends.delete ext - end - end - - @extends.uniq! # clean up - - merge_collections method_list, cm.method_list, other_files do |add, meth| - if add then - add_method meth - else - @method_list.delete meth - @methods_hash.delete meth.pretty_name - end - end - - merge_sections cm - - self - end - - ## - # Merges collection +mine+ with +other+ preferring other. +other_files+ is - # used to help determine which items should be deleted. - # - # Yields whether the item should be added or removed (true or false) and the - # item to be added or removed. - # - # merge_collections things, other.things, other.in_files do |add, thing| - # if add then - # # add the thing - # else - # # remove the thing - # end - # end - - def merge_collections mine, other, other_files, &block # :nodoc: - my_things = mine. group_by { |thing| thing.file } - other_things = other.group_by { |thing| thing.file } - - remove_things my_things, other_files, &block - add_things my_things, other_things, &block - end - - ## - # Merges the comments in this ClassModule with the comments in the other - # ClassModule +cm+. - - def merge_sections cm # :nodoc: - my_sections = sections.group_by { |section| section.title } - other_sections = cm.sections.group_by { |section| section.title } - - other_files = cm.in_files - - remove_things my_sections, other_files do |_, section| - @sections.delete section.title - end - - other_sections.each do |group, sections| - if my_sections.include? group - my_sections[group].each do |my_section| - other_section = cm.sections_hash[group] - - my_comments = my_section.comments - other_comments = other_section.comments - - other_files = other_section.in_files - - merge_collections my_comments, other_comments, other_files do |add, comment| - if add then - my_section.add_comment comment - else - my_section.remove_comment comment - end - end - end - else - sections.each do |section| - add_section group, section.comments - end - end - end - end - - ## - # Does this object represent a module? - - def module? - false - end - - ## - # Allows overriding the initial name. - # - # Used for modules and classes that are constant aliases. - - def name= new_name - @name = new_name - end - - ## - # Parses +comment_location+ into an RDoc::Markup::Document composed of - # multiple RDoc::Markup::Documents with their file set. - - def parse comment_location - case comment_location - when String then - super - when Array then - docs = comment_location.map do |comment, location| - doc = super comment - doc.file = location - doc - end - - RDoc::Markup::Document.new(*docs) - when RDoc::Comment then - doc = super comment_location.text, comment_location.format - doc.file = comment_location.location - doc - when RDoc::Markup::Document then - return comment_location - else - raise ArgumentError, "unknown comment class #{comment_location.class}" - end - end - - ## - # Path to this class or module for use with HTML generator output. - - def path - http_url @store.rdoc.generator.class_dir - end - - ## - # Name to use to generate the url: - # modules and classes that are aliases for another - # module or class return the name of the latter. - - def name_for_path - is_alias_for ? is_alias_for.full_name : full_name - end - - ## - # Returns the classes and modules that are not constants - # aliasing another class or module. For use by formatters - # only (caches its result). - - def non_aliases - @non_aliases ||= classes_and_modules.reject { |cm| cm.is_alias_for } - end - - ## - # Updates the child modules or classes of class/module +parent+ by - # deleting the ones that have been removed from the documentation. - # - # +parent_hash+ is either parent.modules_hash or - # parent.classes_hash and +all_hash+ is ::all_modules_hash or - # ::all_classes_hash. - - def remove_nodoc_children - prefix = self.full_name + '::' - - modules_hash.each_key do |name| - full_name = prefix + name - modules_hash.delete name unless @store.modules_hash[full_name] - end - - classes_hash.each_key do |name| - full_name = prefix + name - classes_hash.delete name unless @store.classes_hash[full_name] - end - end - - def remove_things my_things, other_files # :nodoc: - my_things.delete_if do |file, things| - next false unless other_files.include? file - - things.each do |thing| - yield false, thing - end - - true - end - end - - ## - # Search record used by RDoc::Generator::JsonIndex - - def search_record - [ - name, - full_name, - full_name, - '', - path, - '', - snippet(@comment_location), - ] - end - - ## - # Sets the store for this class or module and its contained code objects. - - def store= store - super - - @attributes .each do |attr| attr.store = store end - @constants .each do |const| const.store = store end - @includes .each do |incl| incl.store = store end - @extends .each do |ext| ext.store = store end - @method_list.each do |meth| meth.store = store end - end - - ## - # Get the superclass of this class. Attempts to retrieve the superclass - # object, returns the name if it is not known. - - def superclass - @store.find_class_named(@superclass) || @superclass - end - - ## - # Set the superclass of this class to +superclass+ - - def superclass=(superclass) - raise NoMethodError, "#{full_name} is a module" if module? - @superclass = superclass - end - - def to_s # :nodoc: - if is_alias_for then - "#{self.class.name} #{self.full_name} -> #{is_alias_for}" - else - super - end - end - - ## - # 'module' or 'class' - - def type - module? ? 'module' : 'class' - end - - ## - # Updates the child modules & classes by replacing the ones that are - # aliases through a constant. - # - # The aliased module/class is replaced in the children and in - # RDoc::Store#modules_hash or RDoc::Store#classes_hash - # by a copy that has RDoc::ClassModule#is_alias_for set to - # the aliased module/class, and this copy is added to #aliases - # of the aliased module/class. - # - # Formatters can use the #non_aliases method to retrieve children that - # are not aliases, for instance to list the namespace content, since - # the aliased modules are included in the constants of the class/module, - # that are listed separately. - - def update_aliases - constants.each do |const| - next unless cm = const.is_alias_for - cm_alias = cm.dup - cm_alias.name = const.name - - # Don't move top-level aliases under Object, they look ugly there - unless RDoc::TopLevel === cm_alias.parent then - cm_alias.parent = self - cm_alias.full_name = nil # force update for new parent - end - - cm_alias.aliases.clear - cm_alias.is_alias_for = cm - - if cm.module? then - @store.modules_hash[cm_alias.full_name] = cm_alias - modules_hash[const.name] = cm_alias - else - @store.classes_hash[cm_alias.full_name] = cm_alias - classes_hash[const.name] = cm_alias - end - - cm.aliases << cm_alias - end - end - - ## - # Deletes from #includes those whose module has been removed from the - # documentation. - #-- - # FIXME: includes are not reliably removed, see _possible_bug test case - - def update_includes - includes.reject! do |include| - mod = include.module - !(String === mod) && @store.modules_hash[mod.full_name].nil? - end - - includes.uniq! - end - - ## - # Deletes from #extends those whose module has been removed from the - # documentation. - #-- - # FIXME: like update_includes, extends are not reliably removed - - def update_extends - extends.reject! do |ext| - mod = ext.module - - !(String === mod) && @store.modules_hash[mod.full_name].nil? - end - - extends.uniq! - end - -end diff --git a/lib/rdoc/code_object.rb b/lib/rdoc/code_object.rb deleted file mode 100644 index aeb4b4762e88da..00000000000000 --- a/lib/rdoc/code_object.rb +++ /dev/null @@ -1,421 +0,0 @@ -# frozen_string_literal: true -## -# Base class for the RDoc code tree. -# -# We contain the common stuff for contexts (which are containers) and other -# elements (methods, attributes and so on) -# -# Here's the tree of the CodeObject subclasses: -# -# * RDoc::Context -# * RDoc::TopLevel -# * RDoc::ClassModule -# * RDoc::AnonClass (never used so far) -# * RDoc::NormalClass -# * RDoc::NormalModule -# * RDoc::SingleClass -# * RDoc::MethodAttr -# * RDoc::Attr -# * RDoc::AnyMethod -# * RDoc::GhostMethod -# * RDoc::MetaMethod -# * RDoc::Alias -# * RDoc::Constant -# * RDoc::Mixin -# * RDoc::Require -# * RDoc::Include - -class RDoc::CodeObject - - include RDoc::Text - - ## - # Our comment - - attr_reader :comment - - ## - # Do we document our children? - - attr_reader :document_children - - ## - # Do we document ourselves? - - attr_reader :document_self - - ## - # Are we done documenting (ie, did we come across a :enddoc:)? - - attr_reader :done_documenting - - ## - # Which file this code object was defined in - - attr_reader :file - - ## - # Force documentation of this CodeObject - - attr_reader :force_documentation - - ## - # Line in #file where this CodeObject was defined - - attr_accessor :line - - ## - # Hash of arbitrary metadata for this CodeObject - - attr_reader :metadata - - ## - # Sets the parent CodeObject - - attr_writer :parent - - ## - # Did we ever receive a +:nodoc:+ directive? - - attr_reader :received_nodoc - - ## - # Set the section this CodeObject is in - - attr_writer :section - - ## - # The RDoc::Store for this object. - - attr_reader :store - - ## - # We are the model of the code, but we know that at some point we will be - # worked on by viewers. By implementing the Viewable protocol, viewers can - # associated themselves with these objects. - - attr_accessor :viewer - - ## - # Creates a new CodeObject that will document itself and its children - - def initialize - @metadata = {} - @comment = '' - @parent = nil - @parent_name = nil # for loading - @parent_class = nil # for loading - @section = nil - @section_title = nil # for loading - @file = nil - @full_name = nil - @store = nil - @track_visibility = true - - initialize_visibility - end - - ## - # Initializes state for visibility of this CodeObject and its children. - - def initialize_visibility # :nodoc: - @document_children = true - @document_self = true - @done_documenting = false - @force_documentation = false - @received_nodoc = false - @ignored = false - @suppressed = false - @track_visibility = true - end - - ## - # Replaces our comment with +comment+, unless it is empty. - - def comment=(comment) - @comment = case comment - when NilClass then '' - when RDoc::Markup::Document then comment - when RDoc::Comment then comment.normalize - else - if comment and not comment.empty? then - normalize_comment comment - else - # HACK correct fix is to have #initialize create @comment - # with the correct encoding - if String === @comment and @comment.empty? then - @comment = RDoc::Encoding.change_encoding @comment, comment.encoding - end - @comment - end - end - end - - ## - # Should this CodeObject be displayed in output? - # - # A code object should be displayed if: - # - # * The item didn't have a nodoc or wasn't in a container that had nodoc - # * The item wasn't ignored - # * The item has documentation and was not suppressed - - def display? - @document_self and not @ignored and - (documented? or not @suppressed) - end - - ## - # Enables or disables documentation of this CodeObject's children unless it - # has been turned off by :enddoc: - - def document_children=(document_children) - return unless @track_visibility - - @document_children = document_children unless @done_documenting - end - - ## - # Enables or disables documentation of this CodeObject unless it has been - # turned off by :enddoc:. If the argument is +nil+ it means the - # documentation is turned off by +:nodoc:+. - - def document_self=(document_self) - return unless @track_visibility - return if @done_documenting - - @document_self = document_self - @received_nodoc = true if document_self.nil? - end - - ## - # Does this object have a comment with content or is #received_nodoc true? - - def documented? - @received_nodoc or !@comment.empty? - end - - ## - # Turns documentation on/off, and turns on/off #document_self - # and #document_children. - # - # Once documentation has been turned off (by +:enddoc:+), - # the object will refuse to turn #document_self or - # #document_children on, so +:doc:+ and +:start_doc:+ directives - # will have no effect in the current file. - - def done_documenting=(value) - return unless @track_visibility - @done_documenting = value - @document_self = !value - @document_children = @document_self - end - - ## - # Yields each parent of this CodeObject. See also - # RDoc::ClassModule#each_ancestor - - def each_parent - code_object = self - - while code_object = code_object.parent do - yield code_object - end - - self - end - - ## - # File name where this CodeObject was found. - # - # See also RDoc::Context#in_files - - def file_name - return unless @file - - @file.absolute_name - end - - ## - # Force the documentation of this object unless documentation - # has been turned off by :enddoc: - #-- - # HACK untested, was assigning to an ivar - - def force_documentation=(value) - @force_documentation = value unless @done_documenting - end - - ## - # Sets the full_name overriding any computed full name. - # - # Set to +nil+ to clear RDoc's cached value - - def full_name= full_name - @full_name = full_name - end - - ## - # Use this to ignore a CodeObject and all its children until found again - # (#record_location is called). An ignored item will not be displayed in - # documentation. - # - # See github issue #55 - # - # The ignored status is temporary in order to allow implementation details - # to be hidden. At the end of processing a file RDoc allows all classes - # and modules to add new documentation to previously created classes. - # - # If a class was ignored (via stopdoc) then reopened later with additional - # documentation it should be displayed. If a class was ignored and never - # reopened it should not be displayed. The ignore flag allows this to - # occur. - - def ignore - return unless @track_visibility - - @ignored = true - - stop_doc - end - - ## - # Has this class been ignored? - # - # See also #ignore - - def ignored? - @ignored - end - - ## - # The options instance from the store this CodeObject is attached to, or a - # default options instance if the CodeObject is not attached. - # - # This is used by Text#snippet - - def options - if @store and @store.rdoc then - @store.rdoc.options - else - RDoc::Options.new - end - end - - ## - # Our parent CodeObject. The parent may be missing for classes loaded from - # legacy RI data stores. - - def parent - return @parent if @parent - return nil unless @parent_name - - if @parent_class == RDoc::TopLevel then - @parent = @store.add_file @parent_name - else - @parent = @store.find_class_or_module @parent_name - - return @parent if @parent - - begin - @parent = @store.load_class @parent_name - rescue RDoc::Store::MissingFileError - nil - end - end - end - - ## - # File name of our parent - - def parent_file_name - @parent ? @parent.base_name : '(unknown)' - end - - ## - # Name of our parent - - def parent_name - @parent ? @parent.full_name : '(unknown)' - end - - ## - # Records the RDoc::TopLevel (file) where this code object was defined - - def record_location top_level - @ignored = false - @suppressed = false - @file = top_level - end - - ## - # The section this CodeObject is in. Sections allow grouping of constants, - # attributes and methods inside a class or module. - - def section - return @section if @section - - @section = parent.add_section @section_title if parent - end - - ## - # Enable capture of documentation unless documentation has been - # turned off by :enddoc: - - def start_doc - return if @done_documenting - - @document_self = true - @document_children = true - @ignored = false - @suppressed = false - end - - ## - # Disable capture of documentation - - def stop_doc - return unless @track_visibility - - @document_self = false - @document_children = false - end - - ## - # Sets the +store+ that contains this CodeObject - - def store= store - @store = store - - return unless @track_visibility - - if :nodoc == options.visibility then - initialize_visibility - @track_visibility = false - end - end - - ## - # Use this to suppress a CodeObject and all its children until the next file - # it is seen in or documentation is discovered. A suppressed item with - # documentation will be displayed while an ignored item with documentation - # may not be displayed. - - def suppress - return unless @track_visibility - - @suppressed = true - - stop_doc - end - - ## - # Has this class been suppressed? - # - # See also #suppress - - def suppressed? - @suppressed - end - -end diff --git a/lib/rdoc/code_objects.rb b/lib/rdoc/code_objects.rb deleted file mode 100644 index d5f2f920ad1402..00000000000000 --- a/lib/rdoc/code_objects.rb +++ /dev/null @@ -1,5 +0,0 @@ -# frozen_string_literal: true -# This file was used to load all the RDoc::CodeObject subclasses at once. Now -# autoload handles this. - -require_relative '../rdoc' diff --git a/lib/rdoc/comment.rb b/lib/rdoc/comment.rb deleted file mode 100644 index fecdcac7820b39..00000000000000 --- a/lib/rdoc/comment.rb +++ /dev/null @@ -1,229 +0,0 @@ -# frozen_string_literal: true -## -# A comment holds the text comment for a RDoc::CodeObject and provides a -# unified way of cleaning it up and parsing it into an RDoc::Markup::Document. -# -# Each comment may have a different markup format set by #format=. By default -# 'rdoc' is used. The :markup: directive tells RDoc which format to use. -# -# See RDoc::Markup@Other+directives for instructions on adding an alternate -# format. - -class RDoc::Comment - - include RDoc::Text - - ## - # The format of this comment. Defaults to RDoc::Markup - - attr_reader :format - - ## - # The RDoc::TopLevel this comment was found in - - attr_accessor :location - - ## - # Line where this Comment was written - - attr_accessor :line - - ## - # For duck-typing when merging classes at load time - - alias file location # :nodoc: - - ## - # The text for this comment - - attr_reader :text - - ## - # Alias for text - - alias to_s text - - ## - # Overrides the content returned by #parse. Use when there is no #text - # source for this comment - - attr_writer :document - - ## - # Creates a new comment with +text+ that is found in the RDoc::TopLevel - # +location+. - - def initialize text = nil, location = nil, language = nil - @location = location - @text = text.nil? ? nil : text.dup - @language = language - - @document = nil - @format = 'rdoc' - @normalized = false - end - - ## - #-- - # TODO deep copy @document - - def initialize_copy copy # :nodoc: - @text = copy.text.dup - end - - def == other # :nodoc: - self.class === other and - other.text == @text and other.location == @location - end - - ## - # Look for a 'call-seq' in the comment to override the normal parameter - # handling. The :call-seq: is indented from the baseline. All lines of the - # same indentation level and prefix are consumed. - # - # For example, all of the following will be used as the :call-seq: - # - # # :call-seq: - # # ARGF.readlines(sep=$/) -> array - # # ARGF.readlines(limit) -> array - # # ARGF.readlines(sep, limit) -> array - # # - # # ARGF.to_a(sep=$/) -> array - # # ARGF.to_a(limit) -> array - # # ARGF.to_a(sep, limit) -> array - - def extract_call_seq method - # we must handle situations like the above followed by an unindented first - # comment. The difficulty is to make sure not to match lines starting - # with ARGF at the same indent, but that are after the first description - # paragraph. - if /^(? ((?!\n)\s)*+ (?# whitespaces except newline)) - :?call-seq: - (? \g(?\n|\z) (?# trailing spaces))? - (? - (\g(?!\w)\S.*\g)* - (?> - (? \g\w+ (?# ' # ARGF' in the example above)) - .*\g)? - (\g\S.*\g (?# other non-blank line))*+ - (\g+(\k.*\g (?# ARGF.to_a lines))++)*+ - ) - (?m:^\s*$|\z) - /x =~ @text - seq = $~[:seq] - - all_start, all_stop = $~.offset(0) - @text.slice! all_start...all_stop - - seq.gsub!(/^\s*/, '') - method.call_seq = seq - end - - method - end - - ## - # A comment is empty if its text String is empty. - - def empty? - @text.empty? - end - - ## - # HACK dubious - - def encode! encoding - @text = String.new @text, encoding: encoding - self - end - - ## - # Sets the format of this comment and resets any parsed document - - def format= format - @format = format - @document = nil - end - - def inspect # :nodoc: - location = @location ? @location.relative_name : '(unknown)' - - "#<%s:%x %s %p>" % [self.class, object_id, location, @text] - end - - ## - # Normalizes the text. See RDoc::Text#normalize_comment for details - - def normalize - return self unless @text - return self if @normalized # TODO eliminate duplicate normalization - - @text = normalize_comment @text - - @normalized = true - - self - end - - ## - # Was this text normalized? - - def normalized? # :nodoc: - @normalized - end - - ## - # Parses the comment into an RDoc::Markup::Document. The parsed document is - # cached until the text is changed. - - def parse - return @document if @document - - @document = super @text, @format - @document.file = @location - @document - end - - ## - # Removes private sections from this comment. Private sections are flush to - # the comment marker and start with -- and end with ++. - # For C-style comments, a private marker may not start at the opening of the - # comment. - # - # /* - # *-- - # * private - # *++ - # * public - # */ - - def remove_private - # Workaround for gsub encoding for Ruby 1.9.2 and earlier - empty = '' - empty = RDoc::Encoding.change_encoding empty, @text.encoding - - @text = @text.gsub(%r%^\s*([#*]?)--.*?^\s*(\1)\+\+\n?%m, empty) - @text = @text.sub(%r%^\s*[#*]?--.*%m, '') - end - - ## - # Replaces this comment's text with +text+ and resets the parsed document. - # - # An error is raised if the comment contains a document but no text. - - def text= text - raise RDoc::Error, 'replacing document-only comment is not allowed' if - @text.nil? and @document - - @document = nil - @text = text.nil? ? nil : text.dup - end - - ## - # Returns true if this comment is in TomDoc format. - - def tomdoc? - @format == 'tomdoc' - end - -end diff --git a/lib/rdoc/constant.rb b/lib/rdoc/constant.rb deleted file mode 100644 index 12b8be775cf6f2..00000000000000 --- a/lib/rdoc/constant.rb +++ /dev/null @@ -1,186 +0,0 @@ -# frozen_string_literal: true -## -# A constant - -class RDoc::Constant < RDoc::CodeObject - - MARSHAL_VERSION = 0 # :nodoc: - - ## - # Sets the module or class this is constant is an alias for. - - attr_writer :is_alias_for - - ## - # The constant's name - - attr_accessor :name - - ## - # The constant's value - - attr_accessor :value - - ## - # The constant's visibility - - attr_accessor :visibility - - ## - # Creates a new constant with +name+, +value+ and +comment+ - - def initialize(name, value, comment) - super() - - @name = name - @value = value - - @is_alias_for = nil - @visibility = :public - - self.comment = comment - end - - ## - # Constants are ordered by name - - def <=> other - return unless self.class === other - - [parent_name, name] <=> [other.parent_name, other.name] - end - - ## - # Constants are equal when their #parent and #name is the same - - def == other - self.class == other.class and - @parent == other.parent and - @name == other.name - end - - ## - # A constant is documented if it has a comment, or is an alias - # for a documented class or module. - - def documented? - return true if super - return false unless @is_alias_for - case @is_alias_for - when String then - found = @store.find_class_or_module @is_alias_for - return false unless found - @is_alias_for = found - end - @is_alias_for.documented? - end - - ## - # Full constant name including namespace - - def full_name - @full_name ||= "#{parent_name}::#{@name}" - end - - ## - # The module or class this constant is an alias for - - def is_alias_for - case @is_alias_for - when String then - found = @store.find_class_or_module @is_alias_for - @is_alias_for = found if found - @is_alias_for - else - @is_alias_for - end - end - - def inspect # :nodoc: - "#<%s:0x%x %s::%s>" % [ - self.class, object_id, - parent_name, @name, - ] - end - - ## - # Dumps this Constant for use by ri. See also #marshal_load - - def marshal_dump - alias_name = case found = is_alias_for - when RDoc::CodeObject then found.full_name - else found - end - - [ MARSHAL_VERSION, - @name, - full_name, - @visibility, - alias_name, - parse(@comment), - @file.relative_name, - parent.name, - parent.class, - section.title, - ] - end - - ## - # Loads this Constant from +array+. For a loaded Constant the following - # methods will return cached values: - # - # * #full_name - # * #parent_name - - def marshal_load array - initialize array[1], nil, array[5] - - @full_name = array[2] - @visibility = array[3] || :public - @is_alias_for = array[4] - # 5 handled above - # 6 handled below - @parent_name = array[7] - @parent_class = array[8] - @section_title = array[9] - - @file = RDoc::TopLevel.new array[6] - end - - ## - # Path to this constant for use with HTML generator output. - - def path - "#{@parent.path}##{@name}" - end - - def pretty_print q # :nodoc: - q.group 2, "[#{self.class.name} #{full_name}", "]" do - unless comment.empty? then - q.breakable - q.text "comment:" - q.breakable - q.pp @comment - end - end - end - - ## - # Sets the store for this class or module and its contained code objects. - - def store= store - super - - @file = @store.add_file @file.full_name if @file - end - - def to_s # :nodoc: - parent_name = parent ? parent.full_name : '(unknown)' - if is_alias_for - "constant #{parent_name}::#@name -> #{is_alias_for}" - else - "constant #{parent_name}::#@name" - end - end - -end diff --git a/lib/rdoc/context.rb b/lib/rdoc/context.rb deleted file mode 100644 index c6edfb473c2d16..00000000000000 --- a/lib/rdoc/context.rb +++ /dev/null @@ -1,1264 +0,0 @@ -# frozen_string_literal: true -## -# A Context is something that can hold modules, classes, methods, attributes, -# aliases, requires, and includes. Classes, modules, and files are all -# Contexts. - -class RDoc::Context < RDoc::CodeObject - - include Comparable - - ## - # Types of methods - - TYPES = %w[class instance] - - ## - # If a context has these titles it will be sorted in this order. - - TOMDOC_TITLES = [nil, 'Public', 'Internal', 'Deprecated'] # :nodoc: - TOMDOC_TITLES_SORT = TOMDOC_TITLES.sort_by { |title| title.to_s } # :nodoc: - - ## - # Class/module aliases - - attr_reader :aliases - - ## - # All attr* methods - - attr_reader :attributes - - ## - # Block params to be used in the next MethodAttr parsed under this context - - attr_accessor :block_params - - ## - # Constants defined - - attr_reader :constants - - ## - # Sets the current documentation section of documentation - - attr_writer :current_section - - ## - # Files this context is found in - - attr_reader :in_files - - ## - # Modules this context includes - - attr_reader :includes - - ## - # Modules this context is extended with - - attr_reader :extends - - ## - # Methods defined in this context - - attr_reader :method_list - - ## - # Name of this class excluding namespace. See also full_name - - attr_reader :name - - ## - # Files this context requires - - attr_reader :requires - - ## - # Use this section for the next method, attribute or constant added. - - attr_accessor :temporary_section - - ## - # Hash old_name => [aliases], for aliases - # that haven't (yet) been resolved to a method/attribute. - # (Not to be confused with the aliases of the context.) - - attr_accessor :unmatched_alias_lists - - ## - # Aliases that could not be resolved. - - attr_reader :external_aliases - - ## - # Current visibility of this context - - attr_accessor :visibility - - ## - # Current visibility of this line - - attr_writer :current_line_visibility - - ## - # Hash of registered methods. Attributes are also registered here, - # twice if they are RW. - - attr_reader :methods_hash - - ## - # Params to be used in the next MethodAttr parsed under this context - - attr_accessor :params - - ## - # Hash of registered constants. - - attr_reader :constants_hash - - ## - # Creates an unnamed empty context with public current visibility - - def initialize - super - - @in_files = [] - - @name ||= "unknown" - @parent = nil - @visibility = :public - - @current_section = Section.new self, nil, nil - @sections = { nil => @current_section } - @temporary_section = nil - - @classes = {} - @modules = {} - - initialize_methods_etc - end - - ## - # Sets the defaults for methods and so-forth - - def initialize_methods_etc - @method_list = [] - @attributes = [] - @aliases = [] - @requires = [] - @includes = [] - @extends = [] - @constants = [] - @external_aliases = [] - @current_line_visibility = nil - - # This Hash maps a method name to a list of unmatched aliases (aliases of - # a method not yet encountered). - @unmatched_alias_lists = {} - - @methods_hash = {} - @constants_hash = {} - - @params = nil - - @store ||= nil - end - - ## - # Contexts are sorted by full_name - - def <=>(other) - return nil unless RDoc::CodeObject === other - - full_name <=> other.full_name - end - - ## - # Adds an item of type +klass+ with the given +name+ and +comment+ to the - # context. - # - # Currently only RDoc::Extend and RDoc::Include are supported. - - def add klass, name, comment - if RDoc::Extend == klass then - ext = RDoc::Extend.new name, comment - add_extend ext - elsif RDoc::Include == klass then - incl = RDoc::Include.new name, comment - add_include incl - else - raise NotImplementedError, "adding a #{klass} is not implemented" - end - end - - ## - # Adds +an_alias+ that is automatically resolved - - def add_alias an_alias - return an_alias unless @document_self - - method_attr = find_method(an_alias.old_name, an_alias.singleton) || - find_attribute(an_alias.old_name, an_alias.singleton) - - if method_attr then - method_attr.add_alias an_alias, self - else - add_to @external_aliases, an_alias - unmatched_alias_list = - @unmatched_alias_lists[an_alias.pretty_old_name] ||= [] - unmatched_alias_list.push an_alias - end - - an_alias - end - - ## - # Adds +attribute+ if not already there. If it is (as method(s) or attribute), - # updates the comment if it was empty. - # - # The attribute is registered only if it defines a new method. - # For instance, attr_reader :foo will not be registered - # if method +foo+ exists, but attr_accessor :foo will be registered - # if method +foo+ exists, but foo= does not. - - def add_attribute attribute - return attribute unless @document_self - - # mainly to check for redefinition of an attribute as a method - # TODO find a policy for 'attr_reader :foo' + 'def foo=()' - register = false - - key = nil - - if attribute.rw.index 'R' then - key = attribute.pretty_name - known = @methods_hash[key] - - if known then - known.comment = attribute.comment if known.comment.empty? - elsif registered = @methods_hash[attribute.pretty_name + '='] and - RDoc::Attr === registered then - registered.rw = 'RW' - else - @methods_hash[key] = attribute - register = true - end - end - - if attribute.rw.index 'W' then - key = attribute.pretty_name + '=' - known = @methods_hash[key] - - if known then - known.comment = attribute.comment if known.comment.empty? - elsif registered = @methods_hash[attribute.pretty_name] and - RDoc::Attr === registered then - registered.rw = 'RW' - else - @methods_hash[key] = attribute - register = true - end - end - - if register then - attribute.visibility = @visibility - add_to @attributes, attribute - resolve_aliases attribute - end - - attribute - end - - ## - # Adds a class named +given_name+ with +superclass+. - # - # Both +given_name+ and +superclass+ may contain '::', and are - # interpreted relative to the +self+ context. This allows handling correctly - # examples like these: - # class RDoc::Gauntlet < Gauntlet - # module Mod - # class Object # implies < ::Object - # class SubObject < Object # this is _not_ ::Object - # - # Given class Container::Item RDoc assumes +Container+ is a module - # unless it later sees class Container. +add_class+ automatically - # upgrades +given_name+ to a class in this case. - - def add_class class_type, given_name, superclass = '::Object' - # superclass +nil+ is passed by the C parser in the following cases: - # - registering Object in 1.8 (correct) - # - registering BasicObject in 1.9 (correct) - # - registering RubyVM in 1.9 in iseq.c (incorrect: < Object in vm.c) - # - # If we later find a superclass for a registered class with a nil - # superclass, we must honor it. - - # find the name & enclosing context - if given_name =~ /^:+(\w+)$/ then - full_name = $1 - enclosing = top_level - name = full_name.split(/:+/).last - else - full_name = child_name given_name - - if full_name =~ /^(.+)::(\w+)$/ then - name = $2 - ename = $1 - enclosing = @store.classes_hash[ename] || @store.modules_hash[ename] - # HACK: crashes in actionpack/lib/action_view/helpers/form_helper.rb (metaprogramming) - unless enclosing then - # try the given name at top level (will work for the above example) - enclosing = @store.classes_hash[given_name] || - @store.modules_hash[given_name] - return enclosing if enclosing - # not found: create the parent(s) - names = ename.split('::') - enclosing = self - names.each do |n| - enclosing = enclosing.classes_hash[n] || - enclosing.modules_hash[n] || - enclosing.add_module(RDoc::NormalModule, n) - end - end - else - name = full_name - enclosing = self - end - end - - # fix up superclass - if full_name == 'BasicObject' then - superclass = nil - elsif full_name == 'Object' then - superclass = '::BasicObject' - end - - # find the superclass full name - if superclass then - if superclass =~ /^:+/ then - superclass = $' #' - else - if superclass =~ /^(\w+):+(.+)$/ then - suffix = $2 - mod = find_module_named($1) - superclass = mod.full_name + '::' + suffix if mod - else - mod = find_module_named(superclass) - superclass = mod.full_name if mod - end - end - - # did we believe it was a module? - mod = @store.modules_hash.delete superclass - - upgrade_to_class mod, RDoc::NormalClass, mod.parent if mod - - # e.g., Object < Object - superclass = nil if superclass == full_name - end - - klass = @store.classes_hash[full_name] - - if klass then - # if TopLevel, it may not be registered in the classes: - enclosing.classes_hash[name] = klass - - # update the superclass if needed - if superclass then - existing = klass.superclass - existing = existing.full_name unless existing.is_a?(String) if existing - if existing.nil? || - (existing == 'Object' && superclass != 'Object') then - klass.superclass = superclass - end - end - else - # this is a new class - mod = @store.modules_hash.delete full_name - - if mod then - klass = upgrade_to_class mod, RDoc::NormalClass, enclosing - - klass.superclass = superclass unless superclass.nil? - else - klass = class_type.new name, superclass - - enclosing.add_class_or_module(klass, enclosing.classes_hash, - @store.classes_hash) - end - end - - klass.parent = self - - klass - end - - ## - # Adds the class or module +mod+ to the modules or - # classes Hash +self_hash+, and to +all_hash+ (either - # TopLevel::modules_hash or TopLevel::classes_hash), - # unless #done_documenting is +true+. Sets the #parent of +mod+ - # to +self+, and its #section to #current_section. Returns +mod+. - - def add_class_or_module mod, self_hash, all_hash - mod.section = current_section # TODO declaring context? something is - # wrong here... - mod.parent = self - mod.full_name = nil - mod.store = @store - - unless @done_documenting then - self_hash[mod.name] = mod - # this must be done AFTER adding mod to its parent, so that the full - # name is correct: - all_hash[mod.full_name] = mod - if @store.unmatched_constant_alias[mod.full_name] then - to, file = @store.unmatched_constant_alias[mod.full_name] - add_module_alias mod, mod.name, to, file - end - end - - mod - end - - ## - # Adds +constant+ if not already there. If it is, updates the comment, - # value and/or is_alias_for of the known constant if they were empty/nil. - - def add_constant constant - return constant unless @document_self - - # HACK: avoid duplicate 'PI' & 'E' in math.c (1.8.7 source code) - # (this is a #ifdef: should be handled by the C parser) - known = @constants_hash[constant.name] - - if known then - known.comment = constant.comment if known.comment.empty? - - known.value = constant.value if - known.value.nil? or known.value.strip.empty? - - known.is_alias_for ||= constant.is_alias_for - else - @constants_hash[constant.name] = constant - add_to @constants, constant - end - - constant - end - - ## - # Adds included module +include+ which should be an RDoc::Include - - def add_include include - add_to @includes, include - - include - end - - ## - # Adds extension module +ext+ which should be an RDoc::Extend - - def add_extend ext - add_to @extends, ext - - ext - end - - ## - # Adds +method+ if not already there. If it is (as method or attribute), - # updates the comment if it was empty. - - def add_method method - return method unless @document_self - - # HACK: avoid duplicate 'new' in io.c & struct.c (1.8.7 source code) - key = method.pretty_name - known = @methods_hash[key] - - if known then - if @store then # otherwise we are loading - known.comment = method.comment if known.comment.empty? - previously = ", previously in #{known.file}" unless - method.file == known.file - @store.rdoc.options.warn \ - "Duplicate method #{known.full_name} in #{method.file}#{previously}" - end - else - @methods_hash[key] = method - if @current_line_visibility - method.visibility, @current_line_visibility = @current_line_visibility, nil - else - method.visibility = @visibility - end - add_to @method_list, method - resolve_aliases method - end - - method - end - - ## - # Adds a module named +name+. If RDoc already knows +name+ is a class then - # that class is returned instead. See also #add_class. - - def add_module(class_type, name) - mod = @classes[name] || @modules[name] - return mod if mod - - full_name = child_name name - mod = @store.modules_hash[full_name] || class_type.new(name) - - add_class_or_module mod, @modules, @store.modules_hash - end - - ## - # Adds a module by +RDoc::NormalModule+ instance. See also #add_module. - - def add_module_by_normal_module(mod) - add_class_or_module mod, @modules, @store.modules_hash - end - - ## - # Adds an alias from +from+ (a class or module) to +name+ which was defined - # in +file+. - - def add_module_alias from, from_name, to, file - return from if @done_documenting - - to_full_name = child_name to.name - - # if we already know this name, don't register an alias: - # see the metaprogramming in lib/active_support/basic_object.rb, - # where we already know BasicObject is a class when we find - # BasicObject = BlankSlate - return from if @store.find_class_or_module to_full_name - - unless from - @store.unmatched_constant_alias[child_name(from_name)] = [to, file] - return to - end - - new_to = from.dup - new_to.name = to.name - new_to.full_name = nil - - if new_to.module? then - @store.modules_hash[to_full_name] = new_to - @modules[to.name] = new_to - else - @store.classes_hash[to_full_name] = new_to - @classes[to.name] = new_to - end - - # Registers a constant for this alias. The constant value and comment - # will be updated later, when the Ruby parser adds the constant - const = RDoc::Constant.new to.name, nil, new_to.comment - const.record_location file - const.is_alias_for = from - add_constant const - - new_to - end - - ## - # Adds +require+ to this context's top level - - def add_require(require) - return require unless @document_self - - if RDoc::TopLevel === self then - add_to @requires, require - else - parent.add_require require - end - end - - ## - # Returns a section with +title+, creating it if it doesn't already exist. - # +comment+ will be appended to the section's comment. - # - # A section with a +title+ of +nil+ will return the default section. - # - # See also RDoc::Context::Section - - def add_section title, comment = nil - if section = @sections[title] then - section.add_comment comment if comment - else - section = Section.new self, title, comment - @sections[title] = section - end - - section - end - - ## - # Adds +thing+ to the collection +array+ - - def add_to array, thing - array << thing if @document_self - - thing.parent = self - thing.store = @store if @store - thing.section = current_section - end - - ## - # Is there any content? - # - # This means any of: comment, aliases, methods, attributes, external - # aliases, require, constant. - # - # Includes and extends are also checked unless includes == false. - - def any_content(includes = true) - @any_content ||= !( - @comment.empty? && - @method_list.empty? && - @attributes.empty? && - @aliases.empty? && - @external_aliases.empty? && - @requires.empty? && - @constants.empty? - ) - @any_content || (includes && !(@includes + @extends).empty? ) - end - - ## - # Creates the full name for a child with +name+ - - def child_name name - if name =~ /^:+/ - $' #' - elsif RDoc::TopLevel === self then - name - else - "#{self.full_name}::#{name}" - end - end - - ## - # Class attributes - - def class_attributes - @class_attributes ||= attributes.select { |a| a.singleton } - end - - ## - # Class methods - - def class_method_list - @class_method_list ||= method_list.select { |a| a.singleton } - end - - ## - # Array of classes in this context - - def classes - @classes.values - end - - ## - # All classes and modules in this namespace - - def classes_and_modules - classes + modules - end - - ## - # Hash of classes keyed by class name - - def classes_hash - @classes - end - - ## - # The current documentation section that new items will be added to. If - # temporary_section is available it will be used. - - def current_section - if section = @temporary_section then - @temporary_section = nil - else - section = @current_section - end - - section - end - - ## - # Is part of this thing was defined in +file+? - - def defined_in?(file) - @in_files.include?(file) - end - - def display(method_attr) # :nodoc: - if method_attr.is_a? RDoc::Attr - "#{method_attr.definition} #{method_attr.pretty_name}" - else - "method #{method_attr.pretty_name}" - end - end - - ## - # Iterator for ancestors for duck-typing. Does nothing. See - # RDoc::ClassModule#each_ancestor. - # - # This method exists to make it easy to work with Context subclasses that - # aren't part of RDoc. - - def each_ancestor # :nodoc: - end - - ## - # Iterator for attributes - - def each_attribute # :yields: attribute - @attributes.each { |a| yield a } - end - - ## - # Iterator for classes and modules - - def each_classmodule(&block) # :yields: module - classes_and_modules.sort.each(&block) - end - - ## - # Iterator for constants - - def each_constant # :yields: constant - @constants.each {|c| yield c} - end - - ## - # Iterator for included modules - - def each_include # :yields: include - @includes.each do |i| yield i end - end - - ## - # Iterator for extension modules - - def each_extend # :yields: extend - @extends.each do |e| yield e end - end - - ## - # Iterator for methods - - def each_method # :yields: method - return enum_for __method__ unless block_given? - - @method_list.sort.each { |m| yield m } - end - - ## - # Iterator for each section's contents sorted by title. The +section+, the - # section's +constants+ and the sections +attributes+ are yielded. The - # +constants+ and +attributes+ collections are sorted. - # - # To retrieve methods in a section use #methods_by_type with the optional - # +section+ parameter. - # - # NOTE: Do not edit collections yielded by this method - - def each_section # :yields: section, constants, attributes - return enum_for __method__ unless block_given? - - constants = @constants.group_by do |constant| constant.section end - attributes = @attributes.group_by do |attribute| attribute.section end - - constants.default = [] - attributes.default = [] - - sort_sections.each do |section| - yield section, constants[section].select(&:display?).sort, attributes[section].select(&:display?).sort - end - end - - ## - # Finds an attribute +name+ with singleton value +singleton+. - - def find_attribute(name, singleton) - name = $1 if name =~ /^(.*)=$/ - @attributes.find { |a| a.name == name && a.singleton == singleton } - end - - ## - # Finds an attribute with +name+ in this context - - def find_attribute_named(name) - case name - when /\A#/ then - find_attribute name[1..-1], false - when /\A::/ then - find_attribute name[2..-1], true - else - @attributes.find { |a| a.name == name } - end - end - - ## - # Finds a class method with +name+ in this context - - def find_class_method_named(name) - @method_list.find { |meth| meth.singleton && meth.name == name } - end - - ## - # Finds a constant with +name+ in this context - - def find_constant_named(name) - @constants.find do |m| - m.name == name || m.full_name == name - end - end - - ## - # Find a module at a higher scope - - def find_enclosing_module_named(name) - parent && parent.find_module_named(name) - end - - ## - # Finds an external alias +name+ with singleton value +singleton+. - - def find_external_alias(name, singleton) - @external_aliases.find { |m| m.name == name && m.singleton == singleton } - end - - ## - # Finds an external alias with +name+ in this context - - def find_external_alias_named(name) - case name - when /\A#/ then - find_external_alias name[1..-1], false - when /\A::/ then - find_external_alias name[2..-1], true - else - @external_aliases.find { |a| a.name == name } - end - end - - ## - # Finds a file with +name+ in this context - - def find_file_named name - @store.find_file_named name - end - - ## - # Finds an instance method with +name+ in this context - - def find_instance_method_named(name) - @method_list.find { |meth| !meth.singleton && meth.name == name } - end - - ## - # Finds a method, constant, attribute, external alias, module or file - # named +symbol+ in this context. - - def find_local_symbol(symbol) - find_method_named(symbol) or - find_constant_named(symbol) or - find_attribute_named(symbol) or - find_external_alias_named(symbol) or - find_module_named(symbol) or - find_file_named(symbol) - end - - ## - # Finds a method named +name+ with singleton value +singleton+. - - def find_method(name, singleton) - @method_list.find { |m| - if m.singleton - m.name == name && m.singleton == singleton - else - m.name == name && !m.singleton && !singleton - end - } - end - - ## - # Finds a instance or module method with +name+ in this context - - def find_method_named(name) - case name - when /\A#/ then - find_method name[1..-1], false - when /\A::/ then - find_method name[2..-1], true - else - @method_list.find { |meth| meth.name == name } - end - end - - ## - # Find a module with +name+ using ruby's scoping rules - - def find_module_named(name) - res = @modules[name] || @classes[name] - return res if res - return self if self.name == name - find_enclosing_module_named name - end - - ## - # Look up +symbol+, first as a module, then as a local symbol. - - def find_symbol(symbol) - find_symbol_module(symbol) || find_local_symbol(symbol) - end - - ## - # Look up a module named +symbol+. - - def find_symbol_module(symbol) - result = nil - - # look for a class or module 'symbol' - case symbol - when /^::/ then - result = @store.find_class_or_module symbol - when /^(\w+):+(.+)$/ - suffix = $2 - top = $1 - searched = self - while searched do - mod = searched.find_module_named(top) - break unless mod - result = @store.find_class_or_module "#{mod.full_name}::#{suffix}" - break if result || searched.is_a?(RDoc::TopLevel) - searched = searched.parent - end - else - searched = self - while searched do - result = searched.find_module_named(symbol) - break if result || searched.is_a?(RDoc::TopLevel) - searched = searched.parent - end - end - - result - end - - ## - # The full name for this context. This method is overridden by subclasses. - - def full_name - '(unknown)' - end - - ## - # Does this context and its methods and constants all have documentation? - # - # (Yes, fully documented doesn't mean everything.) - - def fully_documented? - documented? and - attributes.all? { |a| a.documented? } and - method_list.all? { |m| m.documented? } and - constants.all? { |c| c.documented? } - end - - ## - # URL for this with a +prefix+ - - def http_url(prefix) - path = name_for_path - path = path.gsub(/<<\s*(\w*)/, 'from-\1') if path =~ /<'class' or - # 'instance') and visibility (+:public+, +:protected+, +:private+). - # - # If +section+ is provided only methods in that RDoc::Context::Section will - # be returned. - - def methods_by_type section = nil - methods = {} - - TYPES.each do |type| - visibilities = {} - RDoc::VISIBILITIES.each do |vis| - visibilities[vis] = [] - end - - methods[type] = visibilities - end - - each_method do |method| - next if section and not method.section == section - methods[method.type][method.visibility] << method - end - - methods - end - - ## - # Yields AnyMethod and Attr entries matching the list of names in +methods+. - - def methods_matching(methods, singleton = false, &block) - (@method_list + @attributes).each do |m| - yield m if methods.include?(m.name) and m.singleton == singleton - end - - each_ancestor do |parent| - parent.methods_matching(methods, singleton, &block) - end - end - - ## - # Array of modules in this context - - def modules - @modules.values - end - - ## - # Hash of modules keyed by module name - - def modules_hash - @modules - end - - ## - # Name to use to generate the url. - # #full_name by default. - - def name_for_path - full_name - end - - ## - # Changes the visibility for new methods to +visibility+ - - def ongoing_visibility=(visibility) - @visibility = visibility - end - - ## - # Record +top_level+ as a file +self+ is in. - - def record_location(top_level) - @in_files << top_level unless @in_files.include?(top_level) - end - - ## - # Should we remove this context from the documentation? - # - # The answer is yes if: - # * #received_nodoc is +true+ - # * #any_content is +false+ (not counting includes) - # * All #includes are modules (not a string), and their module has - # #remove_from_documentation? == true - # * All classes and modules have #remove_from_documentation? == true - - def remove_from_documentation? - @remove_from_documentation ||= - @received_nodoc && - !any_content(false) && - @includes.all? { |i| !i.module.is_a?(String) && i.module.remove_from_documentation? } && - classes_and_modules.all? { |cm| cm.remove_from_documentation? } - end - - ## - # Removes methods and attributes with a visibility less than +min_visibility+. - #-- - # TODO mark the visibility of attributes in the template (if not public?) - - def remove_invisible min_visibility - return if [:private, :nodoc].include? min_visibility - remove_invisible_in @method_list, min_visibility - remove_invisible_in @attributes, min_visibility - remove_invisible_in @constants, min_visibility - end - - ## - # Only called when min_visibility == :public or :private - - def remove_invisible_in array, min_visibility # :nodoc: - if min_visibility == :public then - array.reject! { |e| - e.visibility != :public and not e.force_documentation - } - else - array.reject! { |e| - e.visibility == :private and not e.force_documentation - } - end - end - - ## - # Tries to resolve unmatched aliases when a method or attribute has just - # been added. - - def resolve_aliases added - # resolve any pending unmatched aliases - key = added.pretty_name - unmatched_alias_list = @unmatched_alias_lists[key] - return unless unmatched_alias_list - unmatched_alias_list.each do |unmatched_alias| - added.add_alias unmatched_alias, self - @external_aliases.delete unmatched_alias - end - @unmatched_alias_lists.delete key - end - - ## - # Returns RDoc::Context::Section objects referenced in this context for use - # in a table of contents. - - def section_contents - used_sections = {} - - each_method do |method| - next unless method.display? - - used_sections[method.section] = true - end - - # order found sections - sections = sort_sections.select do |section| - used_sections[section] - end - - # only the default section is used - return [] if - sections.length == 1 and not sections.first.title - - sections - end - - ## - # Sections in this context - - def sections - @sections.values - end - - def sections_hash # :nodoc: - @sections - end - - ## - # Sets the current section to a section with +title+. See also #add_section - - def set_current_section title, comment - @current_section = add_section title, comment - end - - ## - # Given an array +methods+ of method names, set the visibility of each to - # +visibility+ - - def set_visibility_for(methods, visibility, singleton = false) - methods_matching methods, singleton do |m| - m.visibility = visibility - end - end - - ## - # Given an array +names+ of constants, set the visibility of each constant to - # +visibility+ - - def set_constant_visibility_for(names, visibility) - names.each do |name| - constant = @constants_hash[name] or next - constant.visibility = visibility - end - end - - ## - # Sorts sections alphabetically (default) or in TomDoc fashion (none, - # Public, Internal, Deprecated) - - def sort_sections - titles = @sections.map { |title, _| title } - - if titles.length > 1 and - TOMDOC_TITLES_SORT == - (titles | TOMDOC_TITLES).sort_by { |title| title.to_s } then - @sections.values_at(*TOMDOC_TITLES).compact - else - @sections.sort_by { |title, _| - title.to_s - }.map { |_, section| - section - } - end - end - - def to_s # :nodoc: - "#{self.class.name} #{self.full_name}" - end - - ## - # Return the TopLevel that owns us - #-- - # FIXME we can be 'owned' by several TopLevel (see #record_location & - # #in_files) - - def top_level - return @top_level if defined? @top_level - @top_level = self - @top_level = @top_level.parent until RDoc::TopLevel === @top_level - @top_level - end - - ## - # Upgrades NormalModule +mod+ in +enclosing+ to a +class_type+ - - def upgrade_to_class mod, class_type, enclosing - enclosing.modules_hash.delete mod.name - - klass = RDoc::ClassModule.from_module class_type, mod - klass.store = @store - - # if it was there, then we keep it even if done_documenting - @store.classes_hash[mod.full_name] = klass - enclosing.classes_hash[mod.name] = klass - - klass - end - - autoload :Section, "#{__dir__}/context/section" - -end diff --git a/lib/rdoc/context/section.rb b/lib/rdoc/context/section.rb deleted file mode 100644 index aecd4e02137bce..00000000000000 --- a/lib/rdoc/context/section.rb +++ /dev/null @@ -1,233 +0,0 @@ -# frozen_string_literal: true -require 'cgi/util' - -## -# A section of documentation like: -# -# # :section: The title -# # The body -# -# Sections can be referenced multiple times and will be collapsed into a -# single section. - -class RDoc::Context::Section - - include RDoc::Text - - MARSHAL_VERSION = 0 # :nodoc: - - ## - # Section comment - - attr_reader :comment - - ## - # Section comments - - attr_reader :comments - - ## - # Context this Section lives in - - attr_reader :parent - - ## - # Section title - - attr_reader :title - - ## - # Creates a new section with +title+ and +comment+ - - def initialize parent, title, comment - @parent = parent - @title = title ? title.strip : title - - @comments = [] - - add_comment comment - end - - ## - # Sections are equal when they have the same #title - - def == other - self.class === other and @title == other.title - end - - alias eql? == - - ## - # Adds +comment+ to this section - - def add_comment comment - comment = extract_comment comment - - return if comment.empty? - - case comment - when RDoc::Comment then - @comments << comment - when RDoc::Markup::Document then - @comments.concat comment.parts - when Array then - @comments.concat comment - else - raise TypeError, "unknown comment type: #{comment.inspect}" - end - end - - ## - # Anchor reference for linking to this section - - def aref - title = @title || '[untitled]' - - CGI.escape(title).gsub('%', '-').sub(/^-/, '') - end - - ## - # Extracts the comment for this section from the original comment block. - # If the first line contains :section:, strip it and use the rest. - # Otherwise remove lines up to the line containing :section:, and look - # for those lines again at the end and remove them. This lets us write - # - # # :section: The title - # # The body - - def extract_comment comment - case comment - when Array then - comment.map do |c| - extract_comment c - end - when nil - RDoc::Comment.new '' - when RDoc::Comment then - if comment.text =~ /^#[ \t]*:section:.*\n/ then - start = $` - rest = $' - - comment.text = if start.empty? then - rest - else - rest.sub(/#{start.chomp}\Z/, '') - end - end - - comment - when RDoc::Markup::Document then - comment - else - raise TypeError, "unknown comment #{comment.inspect}" - end - end - - def inspect # :nodoc: - "#<%s:0x%x %p>" % [self.class, object_id, title] - end - - def hash # :nodoc: - @title.hash - end - - ## - # The files comments in this section come from - - def in_files - return [] if @comments.empty? - - case @comments - when Array then - @comments.map do |comment| - comment.file - end - when RDoc::Markup::Document then - @comment.parts.map do |document| - document.file - end - else - raise RDoc::Error, "BUG: unknown comment class #{@comments.class}" - end - end - - ## - # Serializes this Section. The title and parsed comment are saved, but not - # the section parent which must be restored manually. - - def marshal_dump - [ - MARSHAL_VERSION, - @title, - parse, - ] - end - - ## - # De-serializes this Section. The section parent must be restored manually. - - def marshal_load array - @parent = nil - - @title = array[1] - @comments = array[2] - end - - ## - # Parses +comment_location+ into an RDoc::Markup::Document composed of - # multiple RDoc::Markup::Documents with their file set. - - def parse - case @comments - when String then - super - when Array then - docs = @comments.map do |comment, location| - doc = super comment - doc.file = location if location - doc - end - - RDoc::Markup::Document.new(*docs) - when RDoc::Comment then - doc = super @comments.text, comments.format - doc.file = @comments.location - doc - when RDoc::Markup::Document then - return @comments - else - raise ArgumentError, "unknown comment class #{comments.class}" - end - end - - ## - # The section's title, or 'Top Section' if the title is nil. - # - # This is used by the table of contents template so the name is silly. - - def plain_html - @title || 'Top Section' - end - - ## - # Removes a comment from this section if it is from the same file as - # +comment+ - - def remove_comment comment - return if @comments.empty? - - case @comments - when Array then - @comments.delete_if do |my_comment| - my_comment.file == comment.file - end - when RDoc::Markup::Document then - @comments.parts.delete_if do |document| - document.file == comment.file.name - end - else - raise RDoc::Error, "BUG: unknown comment class #{@comments.class}" - end - end - -end diff --git a/lib/rdoc/cross_reference.rb b/lib/rdoc/cross_reference.rb deleted file mode 100644 index f3b703a5597226..00000000000000 --- a/lib/rdoc/cross_reference.rb +++ /dev/null @@ -1,225 +0,0 @@ -# frozen_string_literal: true - -require_relative 'markup/attribute_manager' # for PROTECT_ATTR - -## -# RDoc::CrossReference is a reusable way to create cross references for names. - -class RDoc::CrossReference - - ## - # Regular expression to match class references - # - # 1. There can be a '\\' in front of text to suppress the cross-reference - # 2. There can be a '::' in front of class names to reference from the - # top-level namespace. - # 3. The method can be followed by parenthesis (not recommended) - - CLASS_REGEXP_STR = '\\\\?((?:\:{2})?[A-Z]\w*(?:\:\:\w+)*)' - - ## - # Regular expression to match a single method argument. - - METHOD_ARG_REGEXP_STR = '[\w.+*/=<>-]+' - - ## - # Regular expression to match method arguments. - - METHOD_ARGS_REGEXP_STR = /(?:\((?:#{METHOD_ARG_REGEXP_STR}(?:,\s*#{METHOD_ARG_REGEXP_STR})*)?\))?/.source - - ## - # Regular expression to match method references. - # - # See CLASS_REGEXP_STR - - METHOD_REGEXP_STR = /( - (?!\d)[\w#{RDoc::Markup::AttributeManager::PROTECT_ATTR}]+[!?=]?| - %|=(?:==?|~)|![=~]|\[\]=?|<(?:<|=>?)?|>[>=]?|[-+!]@?|\*\*?|[\/%\`|&^~] - )#{METHOD_ARGS_REGEXP_STR}/.source.delete("\n ").freeze - - ## - # Regular expressions matching text that should potentially have - # cross-reference links generated are passed to add_regexp_handling. Note - # that these expressions are meant to pick up text for which cross-references - # have been suppressed, since the suppression characters are removed by the - # code that is triggered. - - CROSSREF_REGEXP = /(?:^|[\s()]) - ( - (?: - # A::B::C.meth - #{CLASS_REGEXP_STR}(?:[.#]|::)#{METHOD_REGEXP_STR} - - # A::B::C - # The stuff after CLASS_REGEXP_STR is a - # nasty hack. CLASS_REGEXP_STR unfortunately matches - # words like dog and cat (these are legal "class" - # names in Fortran 95). When a word is flagged as a - # potential cross-reference, limitations in the markup - # engine suppress other processing, such as typesetting. - # This is particularly noticeable for contractions. - # In order that words like "can't" not - # be flagged as potential cross-references, only - # flag potential class cross-references if the character - # after the cross-reference is a space, sentence - # punctuation, tag start character, or attribute - # marker. - | #{CLASS_REGEXP_STR}(?=[@\s).?!,;<\000]|\z) - - # Stand-alone method (preceded by a #) - | \\?\##{METHOD_REGEXP_STR} - - # Stand-alone method (preceded by ::) - | ::#{METHOD_REGEXP_STR} - - # Things that look like filenames - # The key thing is that there must be at least - # one special character (period, slash, or - # underscore). - | (?:\.\.\/)*[-\/\w]+[_\/.][-\w\/.]+ - - # Things that have markup suppressed - # Don't process things like '\<' in \, though. - # TODO: including < is a hack, not very satisfying. - | \\[^\s<] - ) - - # labels for headings - (?:@[\w+%-]+(?:\.[\w|%-]+)?)? - )/x - - ## - # Version of CROSSREF_REGEXP used when --hyperlink-all is specified. - - ALL_CROSSREF_REGEXP = / - (?:^|[\s()]) - ( - (?: - # A::B::C.meth - #{CLASS_REGEXP_STR}(?:[.#]|::)#{METHOD_REGEXP_STR} - - # A::B::C - | #{CLASS_REGEXP_STR}(?=[@\s).?!,;<\000]|\z) - - # Stand-alone method - | \\?#{METHOD_REGEXP_STR} - - # Things that look like filenames - | (?:\.\.\/)*[-\/\w]+[_\/.][-\w\/.]+ - - # Things that have markup suppressed - | \\[^\s<] - ) - - # labels for headings - (?:@[\w+%-]+)? - )/x - - ## - # Hash of references that have been looked-up to their replacements - - attr_accessor :seen - - ## - # Allows cross-references to be created based on the given +context+ - # (RDoc::Context). - - def initialize context - @context = context - @store = context.store - - @seen = {} - end - - def resolve_method name - ref = nil - - if /#{CLASS_REGEXP_STR}([.#]|::)#{METHOD_REGEXP_STR}/o =~ name then - type = $2 - if '.' == type # will find either #method or ::method - method = $3 - else - method = "#{type}#{$3}" - end - container = @context.find_symbol_module($1) - elsif /^([.#]|::)#{METHOD_REGEXP_STR}/o =~ name then - type = $1 - if '.' == type - method = $2 - else - method = "#{type}#{$2}" - end - container = @context - else - type = nil - container = nil - end - - if container then - unless RDoc::TopLevel === container then - if '.' == type then - if 'new' == method then # AnyClassName.new will be class method - ref = container.find_local_symbol method - ref = container.find_ancestor_local_symbol method unless ref - else - ref = container.find_local_symbol "::#{method}" - ref = container.find_ancestor_local_symbol "::#{method}" unless ref - ref = container.find_local_symbol "##{method}" unless ref - ref = container.find_ancestor_local_symbol "##{method}" unless ref - end - else - ref = container.find_local_symbol method - ref = container.find_ancestor_local_symbol method unless ref - end - end - end - - ref - end - - ## - # Returns a reference to +name+. - # - # If the reference is found and +name+ is not documented +text+ will be - # returned. If +name+ is escaped +name+ is returned. If +name+ is not - # found +text+ is returned. - - def resolve name, text - return @seen[name] if @seen.include? name - - ref = case name - when /^\\(#{CLASS_REGEXP_STR})$/o then - @context.find_symbol $1 - else - @context.find_symbol name - end - - ref = resolve_method name unless ref - - # Try a page name - ref = @store.page name if not ref and name =~ /^[\w.]+$/ - - ref = nil if RDoc::Alias === ref # external alias, can't link to it - - out = if name == '\\' then - name - elsif name =~ /^\\/ then - # we remove the \ only in front of what we know: - # other backslashes are treated later, only outside of - ref ? $' : name - elsif ref then - if ref.display? then - ref - else - text - end - else - text - end - - @seen[name] = out - - out - end - -end diff --git a/lib/rdoc/encoding.rb b/lib/rdoc/encoding.rb deleted file mode 100644 index 8a921c7011fa42..00000000000000 --- a/lib/rdoc/encoding.rb +++ /dev/null @@ -1,131 +0,0 @@ -# coding: US-ASCII -# frozen_string_literal: true - -## -# This class is a wrapper around File IO and Encoding that helps RDoc load -# files and convert them to the correct encoding. - -module RDoc::Encoding - - HEADER_REGEXP = /^ - (?: - \A\#!.*\n - | - ^\#\s+frozen[-_]string[-_]literal[=:].+\n - | - ^\#[^\n]+\b(?:en)?coding[=:]\s*(?[^\s;]+).*\n - | - <\?xml[^?]*encoding=(?["'])(?.*?)\k.*\n - )+ - /xi # :nodoc: - - ## - # Reads the contents of +filename+ and handles any encoding directives in - # the file. - # - # The content will be converted to the +encoding+. If the file cannot be - # converted a warning will be printed and nil will be returned. - # - # If +force_transcode+ is true the document will be transcoded and any - # unknown character in the target encoding will be replaced with '?' - - def self.read_file filename, encoding, force_transcode = false - content = File.open filename, "rb" do |f| f.read end - content.gsub!("\r\n", "\n") if RUBY_PLATFORM =~ /mswin|mingw/ - - utf8 = content.sub!(/\A\xef\xbb\xbf/, '') - - enc = RDoc::Encoding.detect_encoding content - content = RDoc::Encoding.change_encoding content, enc if enc - - begin - encoding ||= Encoding.default_external - orig_encoding = content.encoding - - if not orig_encoding.ascii_compatible? then - content = content.encode encoding - elsif utf8 then - content = RDoc::Encoding.change_encoding content, Encoding::UTF_8 - content = content.encode encoding - else - # assume the content is in our output encoding - content = RDoc::Encoding.change_encoding content, encoding - end - - unless content.valid_encoding? then - # revert and try to transcode - content = RDoc::Encoding.change_encoding content, orig_encoding - content = content.encode encoding - end - - unless content.valid_encoding? then - warn "unable to convert #{filename} to #{encoding}, skipping" - content = nil - end - rescue Encoding::InvalidByteSequenceError, - Encoding::UndefinedConversionError => e - if force_transcode then - content = RDoc::Encoding.change_encoding content, orig_encoding - content = content.encode(encoding, - :invalid => :replace, - :undef => :replace, - :replace => '?') - return content - else - warn "unable to convert #{e.message} for #{filename}, skipping" - return nil - end - end - - content - rescue ArgumentError => e - raise unless e.message =~ /unknown encoding name - (.*)/ - warn "unknown encoding name \"#{$1}\" for #{filename}, skipping" - nil - rescue Errno::EISDIR, Errno::ENOENT - nil - end - - def self.remove_frozen_string_literal string - string =~ /\A(?:#!.*\n)?(.*\n)/ - first_line = $1 - - if first_line =~ /\A# +frozen[-_]string[-_]literal[=:].+$/i - string = string.sub first_line, '' - end - - string - end - - ## - # Detects the encoding of +string+ based on the magic comment - - def self.detect_encoding string - result = HEADER_REGEXP.match string - name = result && result[:name] - - name ? Encoding.find(name) : nil - end - - ## - # Removes magic comments and shebang - - def self.remove_magic_comment string - string.sub HEADER_REGEXP do |s| - s.gsub(/[^\n]/, '') - end - end - - ## - # Changes encoding based on +encoding+ without converting and returns new - # string - - def self.change_encoding text, encoding - if text.kind_of? RDoc::Comment - text.encode! encoding - else - String.new text, encoding: encoding - end - end - -end diff --git a/lib/rdoc/erb_partial.rb b/lib/rdoc/erb_partial.rb deleted file mode 100644 index 043d763db1d3da..00000000000000 --- a/lib/rdoc/erb_partial.rb +++ /dev/null @@ -1,18 +0,0 @@ -# frozen_string_literal: true -## -# Allows an ERB template to be rendered in the context (binding) of an -# existing ERB template evaluation. - -class RDoc::ERBPartial < ERB - - ## - # Overrides +compiler+ startup to set the +eoutvar+ to an empty string only - # if it isn't already set. - - def set_eoutvar compiler, eoutvar = '_erbout' - super - - compiler.pre_cmd = ["#{eoutvar} ||= +''"] - end - -end diff --git a/lib/rdoc/erbio.rb b/lib/rdoc/erbio.rb deleted file mode 100644 index 0f98eaedeef313..00000000000000 --- a/lib/rdoc/erbio.rb +++ /dev/null @@ -1,37 +0,0 @@ -# frozen_string_literal: true -require 'erb' - -## -# A subclass of ERB that writes directly to an IO. Credit to Aaron Patterson -# and Masatoshi SEKI. -# -# To use: -# -# erbio = RDoc::ERBIO.new '<%= "hello world" %>', nil, nil -# -# File.open 'hello.txt', 'w' do |io| -# erbio.result binding -# end -# -# Note that binding must enclose the io you wish to output on. - -class RDoc::ERBIO < ERB - - ## - # Defaults +eoutvar+ to 'io', otherwise is identical to ERB's initialize - - def initialize str, trim_mode: nil, eoutvar: 'io' - super(str, trim_mode: trim_mode, eoutvar: eoutvar) - end - - ## - # Instructs +compiler+ how to write to +io_variable+ - - def set_eoutvar compiler, io_variable - compiler.put_cmd = "#{io_variable}.write" - compiler.insert_cmd = "#{io_variable}.write" - compiler.pre_cmd = [] - compiler.post_cmd = [] - end - -end diff --git a/lib/rdoc/extend.rb b/lib/rdoc/extend.rb deleted file mode 100644 index 7d57433de668fb..00000000000000 --- a/lib/rdoc/extend.rb +++ /dev/null @@ -1,9 +0,0 @@ -# frozen_string_literal: true -## -# A Module extension to a class with \#extend -# -# RDoc::Extend.new 'Enumerable', 'comment ...' - -class RDoc::Extend < RDoc::Mixin - -end diff --git a/lib/rdoc/generator.rb b/lib/rdoc/generator.rb deleted file mode 100644 index a769cf8ac0e9cf..00000000000000 --- a/lib/rdoc/generator.rb +++ /dev/null @@ -1,51 +0,0 @@ -# frozen_string_literal: true -## -# RDoc uses generators to turn parsed source code in the form of an -# RDoc::CodeObject tree into some form of output. RDoc comes with the HTML -# generator RDoc::Generator::Darkfish and an ri data generator -# RDoc::Generator::RI. -# -# == Registering a Generator -# -# Generators are registered by calling RDoc::RDoc.add_generator with the class -# of the generator: -# -# class My::Awesome::Generator -# RDoc::RDoc.add_generator self -# end -# -# == Adding Options to +rdoc+ -# -# Before option processing in +rdoc+, RDoc::Options will call ::setup_options -# on the generator class with an RDoc::Options instance. The generator can -# use RDoc::Options#option_parser to add command-line options to the +rdoc+ -# tool. See RDoc::Options@Custom+Options for an example and see OptionParser -# for details on how to add options. -# -# You can extend the RDoc::Options instance with additional accessors for your -# generator. -# -# == Generator Instantiation -# -# After parsing, RDoc::RDoc will instantiate a generator by calling -# #initialize with an RDoc::Store instance and an RDoc::Options instance. -# -# The RDoc::Store instance holds documentation for parsed source code. In -# RDoc 3 and earlier the RDoc::TopLevel class held this data. When upgrading -# a generator from RDoc 3 and earlier you should only need to replace -# RDoc::TopLevel with the store instance. -# -# RDoc will then call #generate on the generator instance. You can use the -# various methods on RDoc::Store and in the RDoc::CodeObject tree to create -# your desired output format. - -module RDoc::Generator - - autoload :Markup, "#{__dir__}/generator/markup" - - autoload :Darkfish, "#{__dir__}/generator/darkfish" - autoload :JsonIndex, "#{__dir__}/generator/json_index" - autoload :RI, "#{__dir__}/generator/ri" - autoload :POT, "#{__dir__}/generator/pot" - -end diff --git a/lib/rdoc/generator/darkfish.rb b/lib/rdoc/generator/darkfish.rb deleted file mode 100644 index 1b408a6f8ee59e..00000000000000 --- a/lib/rdoc/generator/darkfish.rb +++ /dev/null @@ -1,786 +0,0 @@ -# frozen_string_literal: true -# -*- mode: ruby; ruby-indent-level: 2; tab-width: 2 -*- - -require 'erb' -require 'fileutils' -require 'pathname' -require_relative 'markup' - -## -# Darkfish RDoc HTML Generator -# -# $Id: darkfish.rb 52 2009-01-07 02:08:11Z deveiant $ -# -# == Author/s -# * Michael Granger (ged@FaerieMUD.org) -# -# == Contributors -# * Mahlon E. Smith (mahlon@martini.nu) -# * Eric Hodel (drbrain@segment7.net) -# -# == License -# -# Copyright (c) 2007, 2008, Michael Granger. All rights reserved. -# -# 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 author/s, nor the names of the project's -# 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. -# -# == Attributions -# -# Darkfish uses the {Silk Icons}[http://www.famfamfam.com/lab/icons/silk/] set -# by Mark James. - -class RDoc::Generator::Darkfish - - RDoc::RDoc.add_generator self - - include ERB::Util - - ## - # Stylesheets, fonts, etc. that are included in RDoc. - - BUILTIN_STYLE_ITEMS = # :nodoc: - %w[ - css/fonts.css - fonts/Lato-Light.ttf - fonts/Lato-LightItalic.ttf - fonts/Lato-Regular.ttf - fonts/Lato-RegularItalic.ttf - fonts/SourceCodePro-Bold.ttf - fonts/SourceCodePro-Regular.ttf - css/rdoc.css - ] - - ## - # Path to this file's parent directory. Used to find templates and other - # resources. - - GENERATOR_DIR = File.join 'rdoc', 'generator' - - ## - # Release Version - - VERSION = '3' - - ## - # Description of this generator - - DESCRIPTION = 'HTML generator, written by Michael Granger' - - ## - # The relative path to style sheets and javascript. By default this is set - # the same as the rel_prefix. - - attr_accessor :asset_rel_path - - ## - # The path to generate files into, combined with --op from the - # options for a full path. - - attr_reader :base_dir - - ## - # Classes and modules to be used by this generator, not necessarily - # displayed. See also #modsort - - attr_reader :classes - - ## - # No files will be written when dry_run is true. - - attr_accessor :dry_run - - ## - # When false the generate methods return a String instead of writing to a - # file. The default is true. - - attr_accessor :file_output - - ## - # Files to be displayed by this generator - - attr_reader :files - - ## - # The JSON index generator for this Darkfish generator - - attr_reader :json_index - - ## - # Methods to be displayed by this generator - - attr_reader :methods - - ## - # Sorted list of classes and modules to be displayed by this generator - - attr_reader :modsort - - ## - # The RDoc::Store that is the source of the generated content - - attr_reader :store - - ## - # The directory where the template files live - - attr_reader :template_dir # :nodoc: - - ## - # The output directory - - attr_reader :outputdir - - ## - # Initialize a few instance variables before we start - - def initialize store, options - @store = store - @options = options - - @asset_rel_path = '' - @base_dir = Pathname.pwd.expand_path - @dry_run = @options.dry_run - @file_output = true - @template_dir = Pathname.new options.template_dir - @template_cache = {} - - @classes = nil - @context = nil - @files = nil - @methods = nil - @modsort = nil - - @json_index = RDoc::Generator::JsonIndex.new self, options - end - - ## - # Output progress information if debugging is enabled - - def debug_msg *msg - return unless $DEBUG_RDOC - $stderr.puts(*msg) - end - - ## - # Directory where generated class HTML files live relative to the output - # dir. - - def class_dir - nil - end - - ## - # Directory where generated class HTML files live relative to the output - # dir. - - def file_dir - nil - end - - ## - # Create the directories the generated docs will live in if they don't - # already exist. - - def gen_sub_directories - @outputdir.mkpath - end - - ## - # Copy over the stylesheet into the appropriate place in the output - # directory. - - def write_style_sheet - debug_msg "Copying static files" - options = { :verbose => $DEBUG_RDOC, :noop => @dry_run } - - BUILTIN_STYLE_ITEMS.each do |item| - install_rdoc_static_file @template_dir + item, "./#{item}", options - end - - unless @options.template_stylesheets.empty? - FileUtils.cp @options.template_stylesheets, '.', **options - end - - Dir[(@template_dir + "{js,images}/**/*").to_s].each do |path| - next if File.directory? path - next if File.basename(path) =~ /^\./ - - dst = Pathname.new(path).relative_path_from @template_dir - - install_rdoc_static_file @template_dir + path, dst, options - end - end - - ## - # Build the initial indices and output objects based on an array of TopLevel - # objects containing the extracted information. - - def generate - setup - - write_style_sheet - generate_index - generate_class_files - generate_file_files - generate_table_of_contents - @json_index.generate - @json_index.generate_gzipped - - copy_static - - rescue => e - debug_msg "%s: %s\n %s" % [ - e.class.name, e.message, e.backtrace.join("\n ") - ] - - raise - end - - ## - # Copies static files from the static_path into the output directory - - def copy_static - return if @options.static_path.empty? - - fu_options = { :verbose => $DEBUG_RDOC, :noop => @dry_run } - - @options.static_path.each do |path| - unless File.directory? path then - FileUtils.install path, @outputdir, **fu_options.merge(:mode => 0644) - next - end - - Dir.chdir path do - Dir[File.join('**', '*')].each do |entry| - dest_file = @outputdir + entry - - if File.directory? entry then - FileUtils.mkdir_p entry, **fu_options - else - FileUtils.install entry, dest_file, **fu_options.merge(:mode => 0644) - end - end - end - end - end - - ## - # Return a list of the documented modules sorted by salience first, then - # by name. - - def get_sorted_module_list classes - classes.select do |klass| - klass.display? - end.sort - end - - ## - # Generate an index page which lists all the classes which are documented. - - def generate_index - setup - - template_file = @template_dir + 'index.rhtml' - return unless template_file.exist? - - debug_msg "Rendering the index page..." - - out_file = @base_dir + @options.op_dir + 'index.html' - rel_prefix = @outputdir.relative_path_from out_file.dirname - search_index_rel_prefix = rel_prefix - search_index_rel_prefix += @asset_rel_path if @file_output - - asset_rel_prefix = rel_prefix + @asset_rel_path - - @title = @options.title - - render_template template_file, out_file do |io| - here = binding - # suppress 1.9.3 warning - here.local_variable_set(:asset_rel_prefix, asset_rel_prefix) - here - end - rescue => e - error = RDoc::Error.new \ - "error generating index.html: #{e.message} (#{e.class})" - error.set_backtrace e.backtrace - - raise error - end - - ## - # Generates a class file for +klass+ - - def generate_class klass, template_file = nil - setup - - current = klass - - template_file ||= @template_dir + 'class.rhtml' - - debug_msg " working on %s (%s)" % [klass.full_name, klass.path] - out_file = @outputdir + klass.path - rel_prefix = @outputdir.relative_path_from out_file.dirname - search_index_rel_prefix = rel_prefix - search_index_rel_prefix += @asset_rel_path if @file_output - - asset_rel_prefix = rel_prefix + @asset_rel_path - svninfo = get_svninfo(current) - - @title = "#{klass.type} #{klass.full_name} - #{@options.title}" - - debug_msg " rendering #{out_file}" - render_template template_file, out_file do |io| - here = binding - # suppress 1.9.3 warning - here.local_variable_set(:asset_rel_prefix, asset_rel_prefix) - here.local_variable_set(:svninfo, svninfo) - here - end - end - - ## - # Generate a documentation file for each class and module - - def generate_class_files - setup - - template_file = @template_dir + 'class.rhtml' - template_file = @template_dir + 'classpage.rhtml' unless - template_file.exist? - return unless template_file.exist? - debug_msg "Generating class documentation in #{@outputdir}" - - current = nil - - @classes.each do |klass| - current = klass - - generate_class klass, template_file - end - rescue => e - error = RDoc::Error.new \ - "error generating #{current.path}: #{e.message} (#{e.class})" - error.set_backtrace e.backtrace - - raise error - end - - ## - # Generate a documentation file for each file - - def generate_file_files - setup - - page_file = @template_dir + 'page.rhtml' - fileinfo_file = @template_dir + 'fileinfo.rhtml' - - # for legacy templates - filepage_file = @template_dir + 'filepage.rhtml' unless - page_file.exist? or fileinfo_file.exist? - - return unless - page_file.exist? or fileinfo_file.exist? or filepage_file.exist? - - debug_msg "Generating file documentation in #{@outputdir}" - - out_file = nil - current = nil - - @files.each do |file| - current = file - - if file.text? and page_file.exist? then - generate_page file - next - end - - template_file = nil - out_file = @outputdir + file.path - debug_msg " working on %s (%s)" % [file.full_name, out_file] - rel_prefix = @outputdir.relative_path_from out_file.dirname - search_index_rel_prefix = rel_prefix - search_index_rel_prefix += @asset_rel_path if @file_output - - asset_rel_prefix = rel_prefix + @asset_rel_path - - unless filepage_file then - if file.text? then - next unless page_file.exist? - template_file = page_file - @title = file.page_name - else - next unless fileinfo_file.exist? - template_file = fileinfo_file - @title = "File: #{file.base_name}" - end - end - - @title += " - #{@options.title}" - template_file ||= filepage_file - - render_template template_file, out_file do |io| - here = binding - # suppress 1.9.3 warning - here.local_variable_set(:asset_rel_prefix, asset_rel_prefix) - here.local_variable_set(:current, current) - here - end - end - rescue => e - error = - RDoc::Error.new "error generating #{out_file}: #{e.message} (#{e.class})" - error.set_backtrace e.backtrace - - raise error - end - - ## - # Generate a page file for +file+ - - def generate_page file - setup - - template_file = @template_dir + 'page.rhtml' - - out_file = @outputdir + file.path - debug_msg " working on %s (%s)" % [file.full_name, out_file] - rel_prefix = @outputdir.relative_path_from out_file.dirname - search_index_rel_prefix = rel_prefix - search_index_rel_prefix += @asset_rel_path if @file_output - - current = file - asset_rel_prefix = rel_prefix + @asset_rel_path - - @title = "#{file.page_name} - #{@options.title}" - - debug_msg " rendering #{out_file}" - render_template template_file, out_file do |io| - here = binding - # suppress 1.9.3 warning - here.local_variable_set(:current, current) - here.local_variable_set(:asset_rel_prefix, asset_rel_prefix) - here - end - end - - ## - # Generates the 404 page for the RDoc servlet - - def generate_servlet_not_found message - setup - - template_file = @template_dir + 'servlet_not_found.rhtml' - return unless template_file.exist? - - debug_msg "Rendering the servlet 404 Not Found page..." - - rel_prefix = rel_prefix = '' - search_index_rel_prefix = rel_prefix - search_index_rel_prefix += @asset_rel_path if @file_output - - asset_rel_prefix = '' - - @title = 'Not Found' - - render_template template_file do |io| - here = binding - # suppress 1.9.3 warning - here.local_variable_set(:asset_rel_prefix, asset_rel_prefix) - here - end - rescue => e - error = RDoc::Error.new \ - "error generating servlet_not_found: #{e.message} (#{e.class})" - error.set_backtrace e.backtrace - - raise error - end - - ## - # Generates the servlet root page for the RDoc servlet - - def generate_servlet_root installed - setup - - template_file = @template_dir + 'servlet_root.rhtml' - return unless template_file.exist? - - debug_msg 'Rendering the servlet root page...' - - rel_prefix = '.' - asset_rel_prefix = rel_prefix - search_index_rel_prefix = asset_rel_prefix - search_index_rel_prefix += @asset_rel_path if @file_output - - @title = 'Local RDoc Documentation' - - render_template template_file do |io| binding end - rescue => e - error = RDoc::Error.new \ - "error generating servlet_root: #{e.message} (#{e.class})" - error.set_backtrace e.backtrace - - raise error - end - - ## - # Generate an index page which lists all the classes which are documented. - - def generate_table_of_contents - setup - - template_file = @template_dir + 'table_of_contents.rhtml' - return unless template_file.exist? - - debug_msg "Rendering the Table of Contents..." - - out_file = @outputdir + 'table_of_contents.html' - rel_prefix = @outputdir.relative_path_from out_file.dirname - search_index_rel_prefix = rel_prefix - search_index_rel_prefix += @asset_rel_path if @file_output - - asset_rel_prefix = rel_prefix + @asset_rel_path - - @title = "Table of Contents - #{@options.title}" - - render_template template_file, out_file do |io| - here = binding - # suppress 1.9.3 warning - here.local_variable_set(:asset_rel_prefix, asset_rel_prefix) - here - end - rescue => e - error = RDoc::Error.new \ - "error generating table_of_contents.html: #{e.message} (#{e.class})" - error.set_backtrace e.backtrace - - raise error - end - - def install_rdoc_static_file source, destination, options # :nodoc: - return unless source.exist? - - begin - FileUtils.mkdir_p File.dirname(destination), **options - - begin - FileUtils.ln source, destination, **options - rescue Errno::EEXIST - FileUtils.rm destination - retry - end - rescue - FileUtils.cp source, destination, **options - end - end - - ## - # Prepares for generation of output from the current directory - - def setup - return if instance_variable_defined? :@outputdir - - @outputdir = Pathname.new(@options.op_dir).expand_path @base_dir - - return unless @store - - @classes = @store.all_classes_and_modules.sort - @files = @store.all_files.sort - @methods = @classes.flat_map { |m| m.method_list }.sort - @modsort = get_sorted_module_list @classes - end - - ## - # Return a string describing the amount of time in the given number of - # seconds in terms a human can understand easily. - - def time_delta_string seconds - return 'less than a minute' if seconds < 60 - return "#{seconds / 60} minute#{seconds / 60 == 1 ? '' : 's'}" if - seconds < 3000 # 50 minutes - return 'about one hour' if seconds < 5400 # 90 minutes - return "#{seconds / 3600} hours" if seconds < 64800 # 18 hours - return 'one day' if seconds < 86400 # 1 day - return 'about one day' if seconds < 172800 # 2 days - return "#{seconds / 86400} days" if seconds < 604800 # 1 week - return 'about one week' if seconds < 1209600 # 2 week - return "#{seconds / 604800} weeks" if seconds < 7257600 # 3 months - return "#{seconds / 2419200} months" if seconds < 31536000 # 1 year - return "#{seconds / 31536000} years" - end - - # %q$Id: darkfish.rb 52 2009-01-07 02:08:11Z deveiant $" - SVNID_PATTERN = / - \$Id:\s - (\S+)\s # filename - (\d+)\s # rev - (\d{4}-\d{2}-\d{2})\s # Date (YYYY-MM-DD) - (\d{2}:\d{2}:\d{2}Z)\s # Time (HH:MM:SSZ) - (\w+)\s # committer - \$$ - /x - - ## - # Try to extract Subversion information out of the first constant whose - # value looks like a subversion Id tag. If no matching constant is found, - # and empty hash is returned. - - def get_svninfo klass - constants = klass.constants or return {} - - constants.find { |c| c.value =~ SVNID_PATTERN } or return {} - - filename, rev, date, time, committer = $~.captures - commitdate = Time.parse "#{date} #{time}" - - return { - :filename => filename, - :rev => Integer(rev), - :commitdate => commitdate, - :commitdelta => time_delta_string(Time.now - commitdate), - :committer => committer, - } - end - - ## - # Creates a template from its components and the +body_file+. - # - # For backwards compatibility, if +body_file+ contains " - - - -#{head_file.read} - -#{body} - -#{footer_file.read} - TEMPLATE - end - - ## - # Renders the ERb contained in +file_name+ relative to the template - # directory and returns the result based on the current context. - - def render file_name - template_file = @template_dir + file_name - - template = template_for template_file, false, RDoc::ERBPartial - - template.filename = template_file.to_s - - template.result @context - end - - ## - # Load and render the erb template in the given +template_file+ and write - # it out to +out_file+. - # - # Both +template_file+ and +out_file+ should be Pathname-like objects. - # - # An io will be yielded which must be captured by binding in the caller. - - def render_template template_file, out_file = nil # :yield: io - io_output = out_file && !@dry_run && @file_output - erb_klass = io_output ? RDoc::ERBIO : ERB - - template = template_for template_file, true, erb_klass - - if io_output then - debug_msg "Outputting to %s" % [out_file.expand_path] - - out_file.dirname.mkpath - out_file.open 'w', 0644 do |io| - io.set_encoding @options.encoding - - @context = yield io - - template_result template, @context, template_file - end - else - @context = yield nil - - output = template_result template, @context, template_file - - debug_msg " would have written %d characters to %s" % [ - output.length, out_file.expand_path - ] if @dry_run - - output - end - end - - ## - # Creates the result for +template+ with +context+. If an error is raised a - # Pathname +template_file+ will indicate the file where the error occurred. - - def template_result template, context, template_file - template.filename = template_file.to_s - template.result context - rescue NoMethodError => e - raise RDoc::Error, "Error while evaluating %s: %s" % [ - template_file.expand_path, - e.message, - ], e.backtrace - end - - ## - # Retrieves a cache template for +file+, if present, or fills the cache. - - def template_for file, page = true, klass = ERB - template = @template_cache[file] - - return template if template - - if page then - template = assemble_template file - erbout = 'io' - else - template = file.read - template = template.encode @options.encoding - - file_var = File.basename(file).sub(/\..*/, '') - - erbout = "_erbout_#{file_var}" - end - - template = klass.new template, trim_mode: '-', eoutvar: erbout - @template_cache[file] = template - template - end - -end diff --git a/lib/rdoc/generator/json_index.rb b/lib/rdoc/generator/json_index.rb deleted file mode 100644 index c454910d5c94f8..00000000000000 --- a/lib/rdoc/generator/json_index.rb +++ /dev/null @@ -1,300 +0,0 @@ -# frozen_string_literal: true -require 'json' -begin - require 'zlib' -rescue LoadError -end - -## -# The JsonIndex generator is designed to complement an HTML generator and -# produces a JSON search index. This generator is derived from sdoc by -# Vladimir Kolesnikov and contains verbatim code written by him. -# -# This generator is designed to be used with a regular HTML generator: -# -# class RDoc::Generator::Darkfish -# def initialize options -# # ... -# @base_dir = Pathname.pwd.expand_path -# -# @json_index = RDoc::Generator::JsonIndex.new self, options -# end -# -# def generate -# # ... -# @json_index.generate -# end -# end -# -# == Index Format -# -# The index is output as a JSON file assigned to the global variable -# +search_data+. The structure is: -# -# var search_data = { -# "index": { -# "searchIndex": -# ["a", "b", ...], -# "longSearchIndex": -# ["a", "a::b", ...], -# "info": [ -# ["A", "A", "A.html", "", ""], -# ["B", "A::B", "A::B.html", "", ""], -# ... -# ] -# } -# } -# -# The same item is described across the +searchIndex+, +longSearchIndex+ and -# +info+ fields. The +searchIndex+ field contains the item's short name, the -# +longSearchIndex+ field contains the full_name (when appropriate) and the -# +info+ field contains the item's name, full_name, path, parameters and a -# snippet of the item's comment. -# -# == LICENSE -# -# Copyright (c) 2009 Vladimir Kolesnikov -# -# 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. - -class RDoc::Generator::JsonIndex - - include RDoc::Text - - ## - # Where the search index lives in the generated output - - SEARCH_INDEX_FILE = File.join 'js', 'search_index.js' - - attr_reader :index # :nodoc: - - ## - # Creates a new generator. +parent_generator+ is used to determine the - # class_dir and file_dir of links in the output index. - # - # +options+ are the same options passed to the parent generator. - - def initialize parent_generator, options - @parent_generator = parent_generator - @store = parent_generator.store - @options = options - - @template_dir = File.expand_path '../template/json_index', __FILE__ - @base_dir = @parent_generator.base_dir - - @classes = nil - @files = nil - @index = nil - end - - ## - # Builds the JSON index as a Hash. - - def build_index - reset @store.all_files.sort, @store.all_classes_and_modules.sort - - index_classes - index_methods - index_pages - - { :index => @index } - end - - ## - # Output progress information if debugging is enabled - - def debug_msg *msg - return unless $DEBUG_RDOC - $stderr.puts(*msg) - end - - ## - # Writes the JSON index to disk - - def generate - debug_msg "Generating JSON index" - - debug_msg " writing search index to %s" % SEARCH_INDEX_FILE - data = build_index - - return if @options.dry_run - - out_dir = @base_dir + @options.op_dir - index_file = out_dir + SEARCH_INDEX_FILE - - FileUtils.mkdir_p index_file.dirname, :verbose => $DEBUG_RDOC - - index_file.open 'w', 0644 do |io| - io.set_encoding Encoding::UTF_8 - io.write 'var search_data = ' - - JSON.dump data, io, 0 - end - unless ENV['SOURCE_DATE_EPOCH'].nil? - index_file.utime index_file.atime, Time.at(ENV['SOURCE_DATE_EPOCH'].to_i).gmtime - end - - Dir.chdir @template_dir do - Dir['**/*.js'].each do |source| - dest = File.join out_dir, source - - FileUtils.install source, dest, :mode => 0644, :preserve => true, :verbose => $DEBUG_RDOC - end - end - end - - ## - # Compress the search_index.js file using gzip - - def generate_gzipped - return if @options.dry_run or not defined?(Zlib) - - debug_msg "Compressing generated JSON index" - out_dir = @base_dir + @options.op_dir - - search_index_file = out_dir + SEARCH_INDEX_FILE - outfile = out_dir + "#{search_index_file}.gz" - - debug_msg "Reading the JSON index file from %s" % search_index_file - search_index = search_index_file.read(mode: 'r:utf-8') - - debug_msg "Writing gzipped search index to %s" % outfile - - Zlib::GzipWriter.open(outfile) do |gz| - gz.mtime = File.mtime(search_index_file) - gz.orig_name = search_index_file.basename.to_s - gz.write search_index - gz.close - end - - # GZip the rest of the js files - Dir.chdir @template_dir do - Dir['**/*.js'].each do |source| - dest = out_dir + source - outfile = out_dir + "#{dest}.gz" - - debug_msg "Reading the original js file from %s" % dest - data = dest.read - - debug_msg "Writing gzipped file to %s" % outfile - - Zlib::GzipWriter.open(outfile) do |gz| - gz.mtime = File.mtime(dest) - gz.orig_name = dest.basename.to_s - gz.write data - gz.close - end - end - end - end - - ## - # Adds classes and modules to the index - - def index_classes - debug_msg " generating class search index" - - documented = @classes.uniq.select do |klass| - klass.document_self_or_methods - end - - documented.each do |klass| - debug_msg " #{klass.full_name}" - record = klass.search_record - @index[:searchIndex] << search_string(record.shift) - @index[:longSearchIndex] << search_string(record.shift) - @index[:info] << record - end - end - - ## - # Adds methods to the index - - def index_methods - debug_msg " generating method search index" - - list = @classes.uniq.flat_map do |klass| - klass.method_list - end.sort_by do |method| - [method.name, method.parent.full_name] - end - - list.each do |method| - debug_msg " #{method.full_name}" - record = method.search_record - @index[:searchIndex] << "#{search_string record.shift}()" - @index[:longSearchIndex] << "#{search_string record.shift}()" - @index[:info] << record - end - end - - ## - # Adds pages to the index - - def index_pages - debug_msg " generating pages search index" - - pages = @files.select do |file| - file.text? - end - - pages.each do |page| - debug_msg " #{page.page_name}" - record = page.search_record - @index[:searchIndex] << search_string(record.shift) - @index[:longSearchIndex] << '' - record.shift - @index[:info] << record - end - end - - ## - # The directory classes are written to - - def class_dir - @parent_generator.class_dir - end - - ## - # The directory files are written to - - def file_dir - @parent_generator.file_dir - end - - def reset files, classes # :nodoc: - @files = files - @classes = classes - - @index = { - :searchIndex => [], - :longSearchIndex => [], - :info => [] - } - end - - ## - # Removes whitespace and downcases +string+ - - def search_string string - string.downcase.gsub(/\s/, '') - end - -end diff --git a/lib/rdoc/generator/markup.rb b/lib/rdoc/generator/markup.rb deleted file mode 100644 index 76b7d458aa233c..00000000000000 --- a/lib/rdoc/generator/markup.rb +++ /dev/null @@ -1,159 +0,0 @@ -# frozen_string_literal: true -## -# Handle common RDoc::Markup tasks for various CodeObjects -# -# This module is loaded by generators. It allows RDoc's CodeObject tree to -# avoid loading generator code to improve startup time for +ri+. - -module RDoc::Generator::Markup - - ## - # Generates a relative URL from this object's path to +target_path+ - - def aref_to(target_path) - RDoc::Markup::ToHtml.gen_relative_url path, target_path - end - - ## - # Generates a relative URL from +from_path+ to this object's path - - def as_href(from_path) - RDoc::Markup::ToHtml.gen_relative_url from_path, path - end - - ## - # Handy wrapper for marking up this object's comment - - def description - markup @comment - end - - ## - # Creates an RDoc::Markup::ToHtmlCrossref formatter - - def formatter - return @formatter if defined? @formatter - - options = @store.rdoc.options - this = RDoc::Context === self ? self : @parent - - @formatter = RDoc::Markup::ToHtmlCrossref.new options, this.path, this - @formatter.code_object = self - @formatter - end - - ## - # Build a webcvs URL starting for the given +url+ with +full_path+ appended - # as the destination path. If +url+ contains '%s' +full_path+ will be - # will replace the %s using sprintf on the +url+. - - def cvs_url(url, full_path) - if /%s/ =~ url then - sprintf url, full_path - else - url + full_path - end - end - -end - -class RDoc::CodeObject - - include RDoc::Generator::Markup - -end - -class RDoc::MethodAttr - - ## - # Prepend +src+ with line numbers. Relies on the first line of a source - # code listing having: - # - # # File xxxxx, line dddd - # - # If it has this comment then line numbers are added to +src+ and the , - # line dddd portion of the comment is removed. - - def add_line_numbers(src) - return unless src.sub!(/\A(.*)(, line (\d+))/, '\1') - first = $3.to_i - 1 - last = first + src.count("\n") - size = last.to_s.length - - line = first - src.gsub!(/^/) do - res = if line == first then - " " * (size + 1) - else - "%2$*1$d " % [size, line] - end - - line += 1 - res - end - end - - ## - # Turns the method's token stream into HTML. - # - # Prepends line numbers if +options.line_numbers+ is true. - - def markup_code - return '' unless @token_stream - - src = RDoc::TokenStream.to_html @token_stream - - # dedent the source - indent = src.length - lines = src.lines.to_a - lines.shift if src =~ /\A.*#\ *File/i # remove '# File' comment - lines.each do |line| - if line =~ /^ *(?=\S)/ - n = $~.end(0) - indent = n if n < indent - break if n == 0 - end - end - src.gsub!(/^#{' ' * indent}/, '') if indent > 0 - - add_line_numbers(src) if options.line_numbers - - src - end - -end - -class RDoc::ClassModule - - ## - # Handy wrapper for marking up this class or module's comment - - def description - markup @comment_location - end - -end - -class RDoc::Context::Section - - include RDoc::Generator::Markup - -end - -class RDoc::TopLevel - - ## - # Returns a URL for this source file on some web repository. Use the -W - # command line option to set. - - def cvs_url - url = @store.rdoc.options.webcvs - - if /%s/ =~ url then - url % @relative_name - else - url + @relative_name - end - end - -end diff --git a/lib/rdoc/generator/pot.rb b/lib/rdoc/generator/pot.rb deleted file mode 100644 index bee1133b078e4b..00000000000000 --- a/lib/rdoc/generator/pot.rb +++ /dev/null @@ -1,98 +0,0 @@ -# frozen_string_literal: true -## -# Generates a POT file. -# -# Here is a translator work flow with the generator. -# -# == Create .pot -# -# You create .pot file by pot formatter: -# -# % rdoc --format pot -# -# It generates doc/rdoc.pot. -# -# == Create .po -# -# You create .po file from doc/rdoc.pot. This operation is needed only -# the first time. This work flow assumes that you are a translator -# for Japanese. -# -# You create locale/ja/rdoc.po from doc/rdoc.pot. You can use msginit -# provided by GNU gettext or rmsginit provided by gettext gem. This -# work flow uses gettext gem because it is more portable than GNU -# gettext for Rubyists. Gettext gem is implemented by pure Ruby. -# -# % gem install gettext -# % mkdir -p locale/ja -# % rmsginit --input doc/rdoc.pot --output locale/ja/rdoc.po --locale ja -# -# Translate messages in .po -# -# You translate messages in .po by a PO file editor. po-mode.el exists -# for Emacs users. There are some GUI tools such as GTranslator. -# There are some Web services such as POEditor and Tansifex. You can -# edit by your favorite text editor because .po is a text file. -# Generate localized documentation -# -# You can generate localized documentation with locale/ja/rdoc.po: -# -# % rdoc --locale ja -# -# You can find documentation in Japanese in doc/. Yay! -# -# == Update translation -# -# You need to update translation when your application is added or -# modified messages. -# -# You can update .po by the following command lines: -# -# % rdoc --format pot -# % rmsgmerge --update locale/ja/rdoc.po doc/rdoc.pot -# -# You edit locale/ja/rdoc.po to translate new messages. - -class RDoc::Generator::POT - - RDoc::RDoc.add_generator self - - ## - # Description of this generator - - DESCRIPTION = 'creates .pot file' - - ## - # Set up a new .pot generator - - def initialize store, options #:not-new: - @options = options - @store = store - end - - ## - # Writes .pot to disk. - - def generate - po = extract_messages - pot_path = 'rdoc.pot' - File.open(pot_path, "w") do |pot| - pot.print(po.to_s) - end - end - - def class_dir - nil - end - - private - def extract_messages - extractor = MessageExtractor.new(@store) - extractor.extract - end - - require_relative 'pot/message_extractor' - require_relative 'pot/po' - require_relative 'pot/po_entry' - -end diff --git a/lib/rdoc/generator/pot/message_extractor.rb b/lib/rdoc/generator/pot/message_extractor.rb deleted file mode 100644 index 313dfd2dc71393..00000000000000 --- a/lib/rdoc/generator/pot/message_extractor.rb +++ /dev/null @@ -1,68 +0,0 @@ -# frozen_string_literal: true -## -# Extracts message from RDoc::Store - -class RDoc::Generator::POT::MessageExtractor - - ## - # Creates a message extractor for +store+. - - def initialize store - @store = store - @po = RDoc::Generator::POT::PO.new - end - - ## - # Extracts messages from +store+, stores them into - # RDoc::Generator::POT::PO and returns it. - - def extract - @store.all_classes_and_modules.each do |klass| - extract_from_klass(klass) - end - @po - end - - private - - def extract_from_klass klass - extract_text(klass.comment_location, klass.full_name) - - klass.each_section do |section, constants, attributes| - extract_text(section.title ,"#{klass.full_name}: section title") - section.comments.each do |comment| - extract_text(comment, "#{klass.full_name}: #{section.title}") - end - end - - klass.each_constant do |constant| - extract_text(constant.comment, constant.full_name) - end - - klass.each_attribute do |attribute| - extract_text(attribute.comment, attribute.full_name) - end - - klass.each_method do |method| - extract_text(method.comment, method.full_name) - end - end - - def extract_text text, comment, location = nil - return if text.nil? - - options = { - :extracted_comment => comment, - :references => [location].compact, - } - i18n_text = RDoc::I18n::Text.new(text) - i18n_text.extract_messages do |part| - @po.add(entry(part[:paragraph], options)) - end - end - - def entry msgid, options - RDoc::Generator::POT::POEntry.new(msgid, options) - end - -end diff --git a/lib/rdoc/generator/pot/po.rb b/lib/rdoc/generator/pot/po.rb deleted file mode 100644 index 37d45e525889cb..00000000000000 --- a/lib/rdoc/generator/pot/po.rb +++ /dev/null @@ -1,84 +0,0 @@ -# frozen_string_literal: true -## -# Generates a PO format text - -class RDoc::Generator::POT::PO - - ## - # Creates an object that represents PO format. - - def initialize - @entries = {} - add_header - end - - ## - # Adds a PO entry to the PO. - - def add entry - existing_entry = @entries[entry.msgid] - if existing_entry - entry = existing_entry.merge(entry) - end - @entries[entry.msgid] = entry - end - - ## - # Returns PO format text for the PO. - - def to_s - po = '' - sort_entries.each do |entry| - po += "\n" unless po.empty? - po += entry.to_s - end - po - end - - private - - def add_header - add(header_entry) - end - - def header_entry - comment = <<-COMMENT -SOME DESCRIPTIVE TITLE. -Copyright (C) YEAR THE PACKAGE'S COPYRIGHT HOLDER -This file is distributed under the same license as the PACKAGE package. -FIRST AUTHOR , YEAR. - COMMENT - - content = <<-CONTENT -Project-Id-Version: PACKAGE VERSEION -Report-Msgid-Bugs-To: -PO-Revision-Date: YEAR-MO_DA HO:MI+ZONE -Last-Translator: FULL NAME -Language-Team: LANGUAGE -Language: -MIME-Version: 1.0 -Content-Type: text/plain; charset=CHARSET -Content-Transfer-Encoding: 8bit -Plural-Forms: nplurals=INTEGER; plural=EXPRESSION; - CONTENT - - options = { - :msgstr => content, - :translator_comment => comment, - :flags => ['fuzzy'], - } - RDoc::Generator::POT::POEntry.new('', options) - end - - def sort_entries - headers, messages = @entries.values.partition do |entry| - entry.msgid.empty? - end - # TODO: sort by location - sorted_messages = messages.sort_by do |entry| - entry.msgid - end - headers + sorted_messages - end - -end diff --git a/lib/rdoc/generator/pot/po_entry.rb b/lib/rdoc/generator/pot/po_entry.rb deleted file mode 100644 index 3c278826f43905..00000000000000 --- a/lib/rdoc/generator/pot/po_entry.rb +++ /dev/null @@ -1,141 +0,0 @@ -# frozen_string_literal: true -## -# A PO entry in PO - -class RDoc::Generator::POT::POEntry - - # The msgid content - attr_reader :msgid - - # The msgstr content - attr_reader :msgstr - - # The comment content created by translator (PO editor) - attr_reader :translator_comment - - # The comment content extracted from source file - attr_reader :extracted_comment - - # The locations where the PO entry is extracted - attr_reader :references - - # The flags of the PO entry - attr_reader :flags - - ## - # Creates a PO entry for +msgid+. Other valus can be specified by - # +options+. - - def initialize msgid, options = {} - @msgid = msgid - @msgstr = options[:msgstr] || "" - @translator_comment = options[:translator_comment] - @extracted_comment = options[:extracted_comment] - @references = options[:references] || [] - @flags = options[:flags] || [] - end - - ## - # Returns the PO entry in PO format. - - def to_s - entry = '' - entry += format_translator_comment - entry += format_extracted_comment - entry += format_references - entry += format_flags - entry += <<-ENTRY -msgid #{format_message(@msgid)} -msgstr #{format_message(@msgstr)} - ENTRY - end - - ## - # Merges the PO entry with +other_entry+. - - def merge other_entry - options = { - :extracted_comment => merge_string(@extracted_comment, - other_entry.extracted_comment), - :translator_comment => merge_string(@translator_comment, - other_entry.translator_comment), - :references => merge_array(@references, - other_entry.references), - :flags => merge_array(@flags, - other_entry.flags), - } - self.class.new(@msgid, options) - end - - private - - def format_comment mark, comment - return '' unless comment - return '' if comment.empty? - - formatted_comment = '' - comment.each_line do |line| - formatted_comment += "#{mark} #{line}" - end - formatted_comment += "\n" unless formatted_comment.end_with?("\n") - formatted_comment - end - - def format_translator_comment - format_comment('#', @translator_comment) - end - - def format_extracted_comment - format_comment('#.', @extracted_comment) - end - - def format_references - return '' if @references.empty? - - formatted_references = '' - @references.sort.each do |file, line| - formatted_references += "\#: #{file}:#{line}\n" - end - formatted_references - end - - def format_flags - return '' if @flags.empty? - - formatted_flags = flags.join(",") - "\#, #{formatted_flags}\n" - end - - def format_message message - return "\"#{escape(message)}\"" unless message.include?("\n") - - formatted_message = '""' - message.each_line do |line| - formatted_message += "\n" - formatted_message += "\"#{escape(line)}\"" - end - formatted_message - end - - def escape string - string.gsub(/["\\\t\n]/) do |special_character| - case special_character - when "\t" - "\\t" - when "\n" - "\\n" - else - "\\#{special_character}" - end - end - end - - def merge_string string1, string2 - [string1, string2].compact.join("\n") - end - - def merge_array array1, array2 - (array1 + array2).uniq - end - -end diff --git a/lib/rdoc/generator/ri.rb b/lib/rdoc/generator/ri.rb deleted file mode 100644 index 1c2f018f97d15b..00000000000000 --- a/lib/rdoc/generator/ri.rb +++ /dev/null @@ -1,30 +0,0 @@ -# frozen_string_literal: true -## -# Generates ri data files - -class RDoc::Generator::RI - - RDoc::RDoc.add_generator self - - ## - # Description of this generator - - DESCRIPTION = 'creates ri data files' - - ## - # Set up a new ri generator - - def initialize store, options #:not-new: - @options = options - @store = store - @store.path = '.' - end - - ## - # Writes the parsed data store to disk for use by ri. - - def generate - @store.save - end - -end diff --git a/lib/rdoc/generator/template/darkfish/.document b/lib/rdoc/generator/template/darkfish/.document deleted file mode 100644 index e69de29bb2d1d6..00000000000000 diff --git a/lib/rdoc/generator/template/darkfish/_footer.rhtml b/lib/rdoc/generator/template/darkfish/_footer.rhtml deleted file mode 100644 index 9791b42901bf94..00000000000000 --- a/lib/rdoc/generator/template/darkfish/_footer.rhtml +++ /dev/null @@ -1,5 +0,0 @@ - diff --git a/lib/rdoc/generator/template/darkfish/_head.rhtml b/lib/rdoc/generator/template/darkfish/_head.rhtml deleted file mode 100644 index d5aed3e9ef2569..00000000000000 --- a/lib/rdoc/generator/template/darkfish/_head.rhtml +++ /dev/null @@ -1,20 +0,0 @@ - - -<%= h @title %> - - - - - - - - - - - -<%- @options.template_stylesheets.each do |stylesheet| -%> - -<%- end -%> diff --git a/lib/rdoc/generator/template/darkfish/_sidebar_VCS_info.rhtml b/lib/rdoc/generator/template/darkfish/_sidebar_VCS_info.rhtml deleted file mode 100644 index 22a12d9e95a995..00000000000000 --- a/lib/rdoc/generator/template/darkfish/_sidebar_VCS_info.rhtml +++ /dev/null @@ -1,19 +0,0 @@ -<%- if !svninfo.empty? then %> - -<%- end -%> diff --git a/lib/rdoc/generator/template/darkfish/_sidebar_classes.rhtml b/lib/rdoc/generator/template/darkfish/_sidebar_classes.rhtml deleted file mode 100644 index d3d8da4017c3ec..00000000000000 --- a/lib/rdoc/generator/template/darkfish/_sidebar_classes.rhtml +++ /dev/null @@ -1,33 +0,0 @@ - diff --git a/lib/rdoc/generator/template/darkfish/_sidebar_extends.rhtml b/lib/rdoc/generator/template/darkfish/_sidebar_extends.rhtml deleted file mode 100644 index 7602076c966f32..00000000000000 --- a/lib/rdoc/generator/template/darkfish/_sidebar_extends.rhtml +++ /dev/null @@ -1,15 +0,0 @@ -<%- unless klass.extends.empty? then %> - -<%- end -%> diff --git a/lib/rdoc/generator/template/darkfish/_sidebar_in_files.rhtml b/lib/rdoc/generator/template/darkfish/_sidebar_in_files.rhtml deleted file mode 100644 index 74869a4b514032..00000000000000 --- a/lib/rdoc/generator/template/darkfish/_sidebar_in_files.rhtml +++ /dev/null @@ -1,9 +0,0 @@ - diff --git a/lib/rdoc/generator/template/darkfish/_sidebar_includes.rhtml b/lib/rdoc/generator/template/darkfish/_sidebar_includes.rhtml deleted file mode 100644 index 5b600e597592bc..00000000000000 --- a/lib/rdoc/generator/template/darkfish/_sidebar_includes.rhtml +++ /dev/null @@ -1,15 +0,0 @@ -<%- unless klass.includes.empty? then %> - -<%- end -%> diff --git a/lib/rdoc/generator/template/darkfish/_sidebar_installed.rhtml b/lib/rdoc/generator/template/darkfish/_sidebar_installed.rhtml deleted file mode 100644 index faed7e0a9409ba..00000000000000 --- a/lib/rdoc/generator/template/darkfish/_sidebar_installed.rhtml +++ /dev/null @@ -1,15 +0,0 @@ - diff --git a/lib/rdoc/generator/template/darkfish/_sidebar_methods.rhtml b/lib/rdoc/generator/template/darkfish/_sidebar_methods.rhtml deleted file mode 100644 index 5b4c295bed0444..00000000000000 --- a/lib/rdoc/generator/template/darkfish/_sidebar_methods.rhtml +++ /dev/null @@ -1,12 +0,0 @@ -<%- unless klass.method_list.empty? then %> - - -<%- end -%> diff --git a/lib/rdoc/generator/template/darkfish/_sidebar_navigation.rhtml b/lib/rdoc/generator/template/darkfish/_sidebar_navigation.rhtml deleted file mode 100644 index d7f330840a4969..00000000000000 --- a/lib/rdoc/generator/template/darkfish/_sidebar_navigation.rhtml +++ /dev/null @@ -1,11 +0,0 @@ - diff --git a/lib/rdoc/generator/template/darkfish/_sidebar_pages.rhtml b/lib/rdoc/generator/template/darkfish/_sidebar_pages.rhtml deleted file mode 100644 index 3f68f0c0dc8bd3..00000000000000 --- a/lib/rdoc/generator/template/darkfish/_sidebar_pages.rhtml +++ /dev/null @@ -1,32 +0,0 @@ -<%- simple_files = @files.select { |f| f.text? } %> -<%- if defined?(current) -%> - <%- dir = current.full_name[%r{\A[^/]+(?=/)}] || current.page_name -%> -<%- end -%> -<%- unless simple_files.empty? then -%> - -<%- end -%> diff --git a/lib/rdoc/generator/template/darkfish/_sidebar_parent.rhtml b/lib/rdoc/generator/template/darkfish/_sidebar_parent.rhtml deleted file mode 100644 index 1420da3201ceb6..00000000000000 --- a/lib/rdoc/generator/template/darkfish/_sidebar_parent.rhtml +++ /dev/null @@ -1,11 +0,0 @@ -<%- if klass.type == 'class' then %> - -<%- end -%> diff --git a/lib/rdoc/generator/template/darkfish/_sidebar_search.rhtml b/lib/rdoc/generator/template/darkfish/_sidebar_search.rhtml deleted file mode 100644 index afc7f7b88d1d11..00000000000000 --- a/lib/rdoc/generator/template/darkfish/_sidebar_search.rhtml +++ /dev/null @@ -1,14 +0,0 @@ - diff --git a/lib/rdoc/generator/template/darkfish/_sidebar_sections.rhtml b/lib/rdoc/generator/template/darkfish/_sidebar_sections.rhtml deleted file mode 100644 index 6dcd2ae81faf2d..00000000000000 --- a/lib/rdoc/generator/template/darkfish/_sidebar_sections.rhtml +++ /dev/null @@ -1,11 +0,0 @@ -<%- unless klass.sections.length == 1 then %> - -<%- end -%> diff --git a/lib/rdoc/generator/template/darkfish/_sidebar_table_of_contents.rhtml b/lib/rdoc/generator/template/darkfish/_sidebar_table_of_contents.rhtml deleted file mode 100644 index b1e047b5f71b36..00000000000000 --- a/lib/rdoc/generator/template/darkfish/_sidebar_table_of_contents.rhtml +++ /dev/null @@ -1,39 +0,0 @@ -<%- comment = if current.respond_to? :comment_location then - current.comment_location - else - current.comment - end - table = current.parse(comment).table_of_contents.dup - - if table.length > 1 then %> - -<%- end -%> diff --git a/lib/rdoc/generator/template/darkfish/class.rhtml b/lib/rdoc/generator/template/darkfish/class.rhtml deleted file mode 100644 index d6510336dfa110..00000000000000 --- a/lib/rdoc/generator/template/darkfish/class.rhtml +++ /dev/null @@ -1,180 +0,0 @@ - - - -
-

- <%= klass.type %> <%= klass.full_name %> -

- -
- <%= klass.description %> -
- - <%- klass.each_section do |section, constants, attributes| -%> -
- <%- if section.title then -%> -
-

- <%= section.title %> -

- - ↑ top - -
- <%- end -%> - - <%- if section.comment then -%> -
- <%= section.description %> -
- <%- end -%> - - <%- unless constants.empty? then -%> -
-
-

Constants

-
-
- <%- constants.each do |const| -%> -
<%= const.name %> - <%- if const.comment then -%> -
<%= const.description.strip %> - <%- else -%> -
(Not documented) - <%- end -%> - <%- end -%> -
-
- <%- end -%> - - <%- unless attributes.empty? then -%> -
-
-

Attributes

-
- - <%- attributes.each do |attrib| -%> -
-
- <%= h attrib.name %>[<%= attrib.rw %>] -
- -
- <%- if attrib.comment then -%> - <%= attrib.description.strip %> - <%- else -%> -

(Not documented) - <%- end -%> -

-
- <%- end -%> -
- <%- end -%> - - <%- klass.methods_by_type(section).each do |type, visibilities| - next if visibilities.empty? - visibilities.each do |visibility, methods| - next if methods.empty? %> -
-
-

<%= visibility.to_s.capitalize %> <%= type.capitalize %> Methods

-
- - <%- methods.each do |method| -%> -
"> -
- <%- if (call_seq = method.call_seq) then -%> - <%- call_seq.strip.split("\n").each_with_index do |call_seq, i| -%> -
- - <%= h(call_seq.strip. - gsub( /^\w+\./m, '')). - gsub(/(.*)[-=]>/, '\1→') %> - - <%- if i == 0 and method.token_stream then -%> - click to toggle source - <%- end -%> -
- <%- end -%> - <%- elsif method.has_call_seq? then -%> -
- <%= h method.name %> -
- <%- else -%> -
- <%= h method.name %><%= h method.param_seq %> - <%- if method.token_stream then -%> - click to toggle source - <%- end -%> -
- <%- end -%> -
- - <%- unless method.skip_description? then -%> -
- <%- if method.comment then -%> - <%= method.description.strip %> - <%- else -%> -

(Not documented) - <%- end -%> - <%- if method.calls_super then -%> -

- Calls superclass method - <%= - method.superclass_method ? - method.formatter.link(method.superclass_method.full_name, method.superclass_method.full_name) : nil - %> -
- <%- end -%> - - <%- if method.token_stream then -%> -
-
<%= method.markup_code %>
-
- <%- end -%> -
- <%- end -%> - - <%- unless method.aliases.empty? then -%> -
- Also aliased as: <%= method.aliases.map do |aka| - if aka.parent then # HACK lib/rexml/encodings - %{#{h aka.name}} - else - h aka.name - end - end.join ", " %> -
- <%- end -%> - - <%- if method.is_alias_for then -%> - - <%- end -%> -
- - <%- end -%> -
- <%- end - end %> -
-<%- end -%> -
diff --git a/lib/rdoc/generator/template/darkfish/css/fonts.css b/lib/rdoc/generator/template/darkfish/css/fonts.css deleted file mode 100644 index 57302b51837117..00000000000000 --- a/lib/rdoc/generator/template/darkfish/css/fonts.css +++ /dev/null @@ -1,167 +0,0 @@ -/* - * Copyright 2010, 2012 Adobe Systems Incorporated (http://www.adobe.com/), - * with Reserved Font Name "Source". All Rights Reserved. Source is a - * trademark of Adobe Systems Incorporated in the United States and/or other - * countries. - * - * This Font Software is licensed under the SIL Open Font License, Version - * 1.1. - * - * This license is copied below, and is also available with a FAQ at: - * http://scripts.sil.org/OFL - */ - -@font-face { - font-family: "Source Code Pro"; - font-style: normal; - font-weight: 400; - src: local("Source Code Pro"), - local("SourceCodePro-Regular"), - url("../fonts/SourceCodePro-Regular.ttf") format("truetype"); -} - -@font-face { - font-family: "Source Code Pro"; - font-style: normal; - font-weight: 700; - src: local("Source Code Pro Bold"), - local("SourceCodePro-Bold"), - url("../fonts/SourceCodePro-Bold.ttf") format("truetype"); -} - -/* - * Copyright (c) 2010, Łukasz Dziedzic (dziedzic@typoland.com), - * with Reserved Font Name Lato. - * - * This Font Software is licensed under the SIL Open Font License, Version - * 1.1. - * - * This license is copied below, and is also available with a FAQ at: - * http://scripts.sil.org/OFL - */ - -@font-face { - font-family: "Lato"; - font-style: normal; - font-weight: 300; - src: local("Lato Light"), - local("Lato-Light"), - url("../fonts/Lato-Light.ttf") format("truetype"); -} - -@font-face { - font-family: "Lato"; - font-style: italic; - font-weight: 300; - src: local("Lato Light Italic"), - local("Lato-LightItalic"), - url("../fonts/Lato-LightItalic.ttf") format("truetype"); -} - -@font-face { - font-family: "Lato"; - font-style: normal; - font-weight: 700; - src: local("Lato Regular"), - local("Lato-Regular"), - url("../fonts/Lato-Regular.ttf") format("truetype"); -} - -@font-face { - font-family: "Lato"; - font-style: italic; - font-weight: 700; - src: local("Lato Italic"), - local("Lato-Italic"), - url("../fonts/Lato-RegularItalic.ttf") format("truetype"); -} - -/* - * ----------------------------------------------------------- - * SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007 - * ----------------------------------------------------------- - * - * PREAMBLE - * The goals of the Open Font License (OFL) are to stimulate worldwide - * development of collaborative font projects, to support the font creation - * efforts of academic and linguistic communities, and to provide a free and - * open framework in which fonts may be shared and improved in partnership - * with others. - * - * The OFL allows the licensed fonts to be used, studied, modified and - * redistributed freely as long as they are not sold by themselves. The - * fonts, including any derivative works, can be bundled, embedded, - * redistributed and/or sold with any software provided that any reserved - * names are not used by derivative works. The fonts and derivatives, - * however, cannot be released under any other type of license. The - * requirement for fonts to remain under this license does not apply - * to any document created using the fonts or their derivatives. - * - * DEFINITIONS - * "Font Software" refers to the set of files released by the Copyright - * Holder(s) under this license and clearly marked as such. This may - * include source files, build scripts and documentation. - * - * "Reserved Font Name" refers to any names specified as such after the - * copyright statement(s). - * - * "Original Version" refers to the collection of Font Software components as - * distributed by the Copyright Holder(s). - * - * "Modified Version" refers to any derivative made by adding to, deleting, - * or substituting -- in part or in whole -- any of the components of the - * Original Version, by changing formats or by porting the Font Software to a - * new environment. - * - * "Author" refers to any designer, engineer, programmer, technical - * writer or other person who contributed to the Font Software. - * - * PERMISSION & CONDITIONS - * Permission is hereby granted, free of charge, to any person obtaining - * a copy of the Font Software, to use, study, copy, merge, embed, modify, - * redistribute, and sell modified and unmodified copies of the Font - * Software, subject to the following conditions: - * - * 1) Neither the Font Software nor any of its individual components, - * in Original or Modified Versions, may be sold by itself. - * - * 2) Original or Modified Versions of the Font Software may be bundled, - * redistributed and/or sold with any software, provided that each copy - * contains the above copyright notice and this license. These can be - * included either as stand-alone text files, human-readable headers or - * in the appropriate machine-readable metadata fields within text or - * binary files as long as those fields can be easily viewed by the user. - * - * 3) No Modified Version of the Font Software may use the Reserved Font - * Name(s) unless explicit written permission is granted by the corresponding - * Copyright Holder. This restriction only applies to the primary font name as - * presented to the users. - * - * 4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font - * Software shall not be used to promote, endorse or advertise any - * Modified Version, except to acknowledge the contribution(s) of the - * Copyright Holder(s) and the Author(s) or with their explicit written - * permission. - * - * 5) The Font Software, modified or unmodified, in part or in whole, - * must be distributed entirely under this license, and must not be - * distributed under any other license. The requirement for fonts to - * remain under this license does not apply to any document created - * using the Font Software. - * - * TERMINATION - * This license becomes null and void if any of the above conditions are - * not met. - * - * DISCLAIMER - * THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT - * OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE - * COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL - * DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM - * OTHER DEALINGS IN THE FONT SOFTWARE. - */ - diff --git a/lib/rdoc/generator/template/darkfish/css/rdoc.css b/lib/rdoc/generator/template/darkfish/css/rdoc.css deleted file mode 100644 index f845d6cecba0bd..00000000000000 --- a/lib/rdoc/generator/template/darkfish/css/rdoc.css +++ /dev/null @@ -1,676 +0,0 @@ -/* - * "Darkfish" Rdoc CSS - * $Id: rdoc.css 54 2009-01-27 01:09:48Z deveiant $ - * - * Author: Michael Granger - * - */ - -/* vim: ft=css et sw=2 ts=2 sts=2 */ -/* Base Green is: #6C8C22 */ - -.hide { display: none !important; } - -* { padding: 0; margin: 0; } - -body { - background: #fafafa; - font-family: Lato, sans-serif; - font-weight: 300; - - /* Layout */ - display: grid; - grid-template-columns: auto 1fr; -} - -body > :last-child { - grid-column: 1 / 3; -} - -h1 span, -h2 span, -h3 span, -h4 span, -h5 span, -h6 span { - position: relative; - - display: none; - padding-left: 1em; - line-height: 0; - vertical-align: baseline; - font-size: 10px; -} - -h1 span { top: -1.3em; } -h2 span { top: -1.2em; } -h3 span { top: -1.0em; } -h4 span { top: -0.8em; } -h5 span { top: -0.5em; } -h6 span { top: -0.5em; } - -h1:hover span, -h2:hover span, -h3:hover span, -h4:hover span, -h5:hover span, -h6:hover span { - display: inline; -} - -h1:target, -h2:target, -h3:target, -h4:target, -h5:target, -h6:target { - margin-left: -10px; - border-left: 10px solid #f1edba; -} - -:link, -:visited { - color: #6C8C22; - text-decoration: none; -} - -:link:hover, -:visited:hover { - border-bottom: 1px dotted #6C8C22; -} - -code, -pre { - font-family: "Source Code Pro", Monaco, monospace; - background-color: rgba(27,31,35,0.05); - padding: 0em 0.2em; - border-radius: 0.2em; -} - -table { - margin: 0; - border-spacing: 0; - border-collapse: collapse; -} - -table tr th, table tr td { - padding: 0.2em 0.4em; - border: 1px solid #ccc; -} - -table tr th { - background-color: #eceaed; -} - -table tr:nth-child(even) td { - background-color: #f5f4f6; -} - -/* @group Generic Classes */ - -.initially-hidden { - display: none; -} - -#search-field { - width: 98%; - background: white; - border: none; - height: 1.5em; - -webkit-border-radius: 4px; - -moz-border-radius: 4px; - border-radius: 4px; - text-align: left; -} -#search-field:focus { - background: #f1edba; -} -#search-field:-moz-placeholder, -#search-field::-webkit-input-placeholder { - font-weight: bold; - color: #666; -} - -.missing-docs { - font-size: 120%; - background: white url(../images/wrench_orange.png) no-repeat 4px center; - color: #ccc; - line-height: 2em; - border: 1px solid #d00; - opacity: 1; - padding-left: 20px; - text-indent: 24px; - letter-spacing: 3px; - font-weight: bold; - -webkit-border-radius: 5px; - -moz-border-radius: 5px; -} - -.target-section { - border: 2px solid #dcce90; - border-left-width: 8px; - padding: 0 1em; - background: #fff3c2; -} - -/* @end */ - -/* @group Index Page, Standalone file pages */ -.table-of-contents ul { - margin: 1em; - list-style: none; -} - -.table-of-contents ul ul { - margin-top: 0.25em; -} - -.table-of-contents ul :link, -.table-of-contents ul :visited { - font-size: 16px; -} - -.table-of-contents li { - margin-bottom: 0.25em; -} - -.table-of-contents li .toc-toggle { - width: 16px; - height: 16px; - background: url(../images/add.png) no-repeat; -} - -.table-of-contents li .toc-toggle.open { - background: url(../images/delete.png) no-repeat; -} - -/* @end */ - -/* @group Top-Level Structure */ - -nav { - font-family: Helvetica, sans-serif; - font-size: 14px; - border-right: 1px solid #ccc; - position: sticky; - top: 0; - overflow: auto; - - /* Layout */ - width: 260px; /* fallback */ - width: max(50px, 20vw); - min-width: 50px; - max-width: 80vw; - height: calc(100vh - 100px); /* reduce the footer height */ - resize: horizontal; -} - -main { - display: block; - margin: 1em; - min-width: 340px; - font-size: 16px; -} - -main h1, -main h2, -main h3, -main h4, -main h5, -main h6 { - font-family: Helvetica, sans-serif; -} - -.table-of-contents main { - margin-left: 2em; -} - -#validator-badges { - margin: 1em 1em 2em; - font-size: smaller; -} - -/* @end */ - -/* @group navigation */ -nav { - margin-bottom: 1em; -} - -nav .nav-section { - margin-top: 2em; - border-top: 2px solid #aaa; - font-size: 90%; - overflow: hidden; -} - -nav h2 { - margin: 0; - padding: 2px 8px 2px 8px; - background-color: #e8e8e8; - color: #555; - font-size: 125%; - text-align: center; -} - -nav h3, -#table-of-contents-navigation { - margin: 0; - padding: 2px 8px 2px 8px; - text-align: right; - background-color: #e8e8e8; - color: #555; -} - -nav ul, -nav dl, -nav p { - padding: 4px 8px 0; - list-style: none; -} - -#project-navigation .nav-section { - margin: 0; - border-top: 0; -} - -#home-section h2 { - text-align: center; -} - -#table-of-contents-navigation { - font-size: 1.2em; - font-weight: bold; - text-align: center; -} - -#search-section { - margin-top: 0; - border-top: 0; -} - -#search-field-wrapper { - border-top: 1px solid #aaa; - border-bottom: 1px solid #aaa; - padding: 3px 8px; - background-color: #e8e8e8; - color: #555; -} - -ul.link-list li { - white-space: nowrap; - line-height: 1.4em; -} - -ul.link-list .type { - font-size: 8px; - text-transform: uppercase; - color: white; - background: #969696; - padding: 2px 4px; - -webkit-border-radius: 5px; -} - -dl.note-list dt { - float: left; - margin-right: 1em; -} - -.calls-super { - background: url(../images/arrow_up.png) no-repeat right center; -} - -.nav-section details > summary { - display: block; -} - -.nav-section details > summary::-webkit-details-marker { - display: none; -} - -.nav-section details > summary::before { - content: ""; -} - -.nav-section details > summary::after { - content: "\25B6"; /* BLACK RIGHT-POINTING TRIANGLE */ - font-size: 0.8em; - margin-left: 0.4em; -} - -.nav-section details[open] > summary::after { - content: "\25BD"; /* WHITE DOWN-POINTING TRIANGLE */ -} - -/* @end */ - -/* @group Documentation Section */ -main { - color: #333; -} - -main > h1:first-child, -main > h2:first-child, -main > h3:first-child, -main > h4:first-child, -main > h5:first-child, -main > h6:first-child { - margin-top: 0px; -} - -main sup { - vertical-align: super; - font-size: 0.8em; -} - -/* The heading with the class name */ -main h1[class] { - margin-top: 0; - margin-bottom: 1em; - font-size: 2em; - color: #6C8C22; -} - -main h1 { - margin: 2em 0 0.5em; - font-size: 1.7em; -} - -main h2 { - margin: 2em 0 0.5em; - font-size: 1.5em; -} - -main h3 { - margin: 2em 0 0.5em; - font-size: 1.2em; -} - -main h4 { - margin: 2em 0 0.5em; - font-size: 1.1em; -} - -main h5 { - margin: 2em 0 0.5em; - font-size: 1em; -} - -main h6 { - margin: 2em 0 0.5em; - font-size: 1em; -} - -main p { - margin: 0 0 0.5em; - line-height: 1.4em; -} - -main pre { - margin: 1.2em 0.5em; - padding: 1em; - font-size: 0.8em; -} - -main hr { - margin: 1.5em 1em; - border: 2px solid #ddd; -} - -main blockquote { - margin: 0 2em 1.2em 1.2em; - padding-left: 0.5em; - border-left: 2px solid #ddd; -} - -main ol, -main ul { - margin: 1em 2em; -} - -main li > p { - margin-bottom: 0.5em; -} - -main dl { - margin: 1em 0.5em; -} - -main dt { - margin-bottom: 0.5em; - font-weight: bold; -} - -main dd { - margin: 0 1em 1em 0.5em; -} - -main header h2 { - margin-top: 2em; - border-width: 0; - border-top: 4px solid #bbb; - font-size: 130%; -} - -main header h3 { - margin: 2em 0 1.5em; - border-width: 0; - border-top: 3px solid #bbb; - font-size: 120%; -} - -.documentation-section-title { - position: relative; -} -.documentation-section-title .section-click-top { - position: absolute; - top: 6px; - left: 12px; - font-size: 10px; - color: #9b9877; - visibility: hidden; - padding-left: 0.5px; -} - -.documentation-section-title:hover .section-click-top { - visibility: visible; -} - -.constants-list > dl { - margin: 1em 0 2em; - border: 0; -} - -.constants-list > dl dt { - margin-bottom: 0.75em; - padding-left: 0; - font-family: "Source Code Pro", Monaco, monospace; - font-size: 110%; -} - -.constants-list > dl dt a { - color: inherit; -} - -.constants-list > dl dd { - margin: 0 0 2em 0; - padding: 0; - color: #666; -} - -.documentation-section h2 { - position: relative; -} - -.documentation-section h2 a { - position: absolute; - top: 8px; - right: 10px; - font-size: 12px; - color: #9b9877; - visibility: hidden; -} - -.documentation-section h2:hover a { - visibility: visible; -} - -/* @group Method Details */ - -main .method-source-code { - max-height: 0; - overflow: auto; - transition-duration: 200ms; - transition-delay: 0ms; - transition-property: all; - transition-timing-function: ease-in-out; -} - -main .method-source-code.active-menu { - max-height: 100vh; -} - -main .method-description .method-calls-super { - color: #333; - font-weight: bold; -} - -main .method-detail { - margin-bottom: 2.5em; - cursor: pointer; -} - -main .method-detail:target { - margin-left: -10px; - border-left: 10px solid #f1edba; -} - -main .method-heading { - position: relative; - font-family: "Source Code Pro", Monaco, monospace; - font-size: 110%; - font-weight: bold; - color: #333; -} -main .method-heading :link, -main .method-heading :visited { - color: inherit; -} -main .method-click-advice { - position: absolute; - top: 2px; - right: 5px; - font-size: 12px; - color: #9b9877; - visibility: hidden; - padding-right: 20px; - line-height: 20px; - background: url(../images/zoom.png) no-repeat right top; -} -main .method-header:hover .method-click-advice { - visibility: visible; -} - -main .method-alias .method-heading { - color: #666; -} - -main .method-description, -main .aliases { - margin-top: 0.75em; - color: #333; -} - -main .aliases { - padding-top: 4px; - font-style: italic; - cursor: default; -} -main .method-description ul { - margin-left: 1.5em; -} - -main #attribute-method-details .method-detail:hover { - background-color: transparent; - cursor: default; -} -main .attribute-access-type { - text-transform: uppercase; - padding: 0 1em; -} -/* @end */ - -/* @end */ - -/* @group Source Code */ - -pre { - margin: 0.5em 0; - border: 1px dashed #999; - padding: 0.5em; - background: #262626; - color: white; - overflow: auto; -} - -.ruby-constant { color: #7fffd4; background: transparent; } -.ruby-keyword { color: #00ffff; background: transparent; } -.ruby-ivar { color: #eedd82; background: transparent; } -.ruby-operator { color: #00ffee; background: transparent; } -.ruby-identifier { color: #ffdead; background: transparent; } -.ruby-node { color: #ffa07a; background: transparent; } -.ruby-comment { color: #dc0000; background: transparent; } -.ruby-regexp { color: #ffa07a; background: transparent; } -.ruby-value { color: #7fffd4; background: transparent; } - -/* @end */ - - -/* @group search results */ -#search-results { - font-family: Lato, sans-serif; - font-weight: 300; -} - -#search-results .search-match { - font-family: Helvetica, sans-serif; - font-weight: normal; -} - -#search-results .search-selected { - background: #e8e8e8; - border-bottom: 1px solid transparent; -} - -#search-results li { - list-style: none; - border-bottom: 1px solid #aaa; - margin-bottom: 0.5em; -} - -#search-results li:last-child { - border-bottom: none; - margin-bottom: 0; -} - -#search-results li p { - padding: 0; - margin: 0.5em; -} - -#search-results .search-namespace { - font-weight: bold; -} - -#search-results li em { - background: yellow; - font-style: normal; -} - -#search-results pre { - margin: 0.5em; - font-family: "Source Code Pro", Monaco, monospace; -} - -/* @end */ - diff --git a/lib/rdoc/generator/template/darkfish/fonts/Lato-Light.ttf b/lib/rdoc/generator/template/darkfish/fonts/Lato-Light.ttf deleted file mode 100644 index b49dd43729d456..00000000000000 Binary files a/lib/rdoc/generator/template/darkfish/fonts/Lato-Light.ttf and /dev/null differ diff --git a/lib/rdoc/generator/template/darkfish/fonts/Lato-LightItalic.ttf b/lib/rdoc/generator/template/darkfish/fonts/Lato-LightItalic.ttf deleted file mode 100644 index 7959fef0756e90..00000000000000 Binary files a/lib/rdoc/generator/template/darkfish/fonts/Lato-LightItalic.ttf and /dev/null differ diff --git a/lib/rdoc/generator/template/darkfish/fonts/Lato-Regular.ttf b/lib/rdoc/generator/template/darkfish/fonts/Lato-Regular.ttf deleted file mode 100644 index 839cd589dc5eba..00000000000000 Binary files a/lib/rdoc/generator/template/darkfish/fonts/Lato-Regular.ttf and /dev/null differ diff --git a/lib/rdoc/generator/template/darkfish/fonts/Lato-RegularItalic.ttf b/lib/rdoc/generator/template/darkfish/fonts/Lato-RegularItalic.ttf deleted file mode 100644 index bababa09e3fad2..00000000000000 Binary files a/lib/rdoc/generator/template/darkfish/fonts/Lato-RegularItalic.ttf and /dev/null differ diff --git a/lib/rdoc/generator/template/darkfish/fonts/SourceCodePro-Bold.ttf b/lib/rdoc/generator/template/darkfish/fonts/SourceCodePro-Bold.ttf deleted file mode 100644 index dd00982d4952a7..00000000000000 Binary files a/lib/rdoc/generator/template/darkfish/fonts/SourceCodePro-Bold.ttf and /dev/null differ diff --git a/lib/rdoc/generator/template/darkfish/fonts/SourceCodePro-Regular.ttf b/lib/rdoc/generator/template/darkfish/fonts/SourceCodePro-Regular.ttf deleted file mode 100644 index 1decfb95af634f..00000000000000 Binary files a/lib/rdoc/generator/template/darkfish/fonts/SourceCodePro-Regular.ttf and /dev/null differ diff --git a/lib/rdoc/generator/template/darkfish/images/add.png b/lib/rdoc/generator/template/darkfish/images/add.png deleted file mode 100644 index 6332fefea4be19..00000000000000 Binary files a/lib/rdoc/generator/template/darkfish/images/add.png and /dev/null differ diff --git a/lib/rdoc/generator/template/darkfish/images/arrow_up.png b/lib/rdoc/generator/template/darkfish/images/arrow_up.png deleted file mode 100644 index 1ebb193243780b..00000000000000 Binary files a/lib/rdoc/generator/template/darkfish/images/arrow_up.png and /dev/null differ diff --git a/lib/rdoc/generator/template/darkfish/images/brick.png b/lib/rdoc/generator/template/darkfish/images/brick.png deleted file mode 100644 index 7851cf34c946e5..00000000000000 Binary files a/lib/rdoc/generator/template/darkfish/images/brick.png and /dev/null differ diff --git a/lib/rdoc/generator/template/darkfish/images/brick_link.png b/lib/rdoc/generator/template/darkfish/images/brick_link.png deleted file mode 100644 index 9ebf013a23a566..00000000000000 Binary files a/lib/rdoc/generator/template/darkfish/images/brick_link.png and /dev/null differ diff --git a/lib/rdoc/generator/template/darkfish/images/bug.png b/lib/rdoc/generator/template/darkfish/images/bug.png deleted file mode 100644 index 2d5fb90ec6ee08..00000000000000 Binary files a/lib/rdoc/generator/template/darkfish/images/bug.png and /dev/null differ diff --git a/lib/rdoc/generator/template/darkfish/images/bullet_black.png b/lib/rdoc/generator/template/darkfish/images/bullet_black.png deleted file mode 100644 index 57619706d10d97..00000000000000 Binary files a/lib/rdoc/generator/template/darkfish/images/bullet_black.png and /dev/null differ diff --git a/lib/rdoc/generator/template/darkfish/images/bullet_toggle_minus.png b/lib/rdoc/generator/template/darkfish/images/bullet_toggle_minus.png deleted file mode 100644 index b47ce55f685dac..00000000000000 Binary files a/lib/rdoc/generator/template/darkfish/images/bullet_toggle_minus.png and /dev/null differ diff --git a/lib/rdoc/generator/template/darkfish/images/bullet_toggle_plus.png b/lib/rdoc/generator/template/darkfish/images/bullet_toggle_plus.png deleted file mode 100644 index 9ab4a89664eee1..00000000000000 Binary files a/lib/rdoc/generator/template/darkfish/images/bullet_toggle_plus.png and /dev/null differ diff --git a/lib/rdoc/generator/template/darkfish/images/date.png b/lib/rdoc/generator/template/darkfish/images/date.png deleted file mode 100644 index 783c83357fdf90..00000000000000 Binary files a/lib/rdoc/generator/template/darkfish/images/date.png and /dev/null differ diff --git a/lib/rdoc/generator/template/darkfish/images/delete.png b/lib/rdoc/generator/template/darkfish/images/delete.png deleted file mode 100644 index 08f249365afd29..00000000000000 Binary files a/lib/rdoc/generator/template/darkfish/images/delete.png and /dev/null differ diff --git a/lib/rdoc/generator/template/darkfish/images/find.png b/lib/rdoc/generator/template/darkfish/images/find.png deleted file mode 100644 index 1547479646722b..00000000000000 Binary files a/lib/rdoc/generator/template/darkfish/images/find.png and /dev/null differ diff --git a/lib/rdoc/generator/template/darkfish/images/loadingAnimation.gif b/lib/rdoc/generator/template/darkfish/images/loadingAnimation.gif deleted file mode 100644 index 82290f48334c81..00000000000000 Binary files a/lib/rdoc/generator/template/darkfish/images/loadingAnimation.gif and /dev/null differ diff --git a/lib/rdoc/generator/template/darkfish/images/macFFBgHack.png b/lib/rdoc/generator/template/darkfish/images/macFFBgHack.png deleted file mode 100644 index c6473b324ee1da..00000000000000 Binary files a/lib/rdoc/generator/template/darkfish/images/macFFBgHack.png and /dev/null differ diff --git a/lib/rdoc/generator/template/darkfish/images/package.png b/lib/rdoc/generator/template/darkfish/images/package.png deleted file mode 100644 index da3c2a2d74bab1..00000000000000 Binary files a/lib/rdoc/generator/template/darkfish/images/package.png and /dev/null differ diff --git a/lib/rdoc/generator/template/darkfish/images/page_green.png b/lib/rdoc/generator/template/darkfish/images/page_green.png deleted file mode 100644 index de8e003f9fb875..00000000000000 Binary files a/lib/rdoc/generator/template/darkfish/images/page_green.png and /dev/null differ diff --git a/lib/rdoc/generator/template/darkfish/images/page_white_text.png b/lib/rdoc/generator/template/darkfish/images/page_white_text.png deleted file mode 100644 index 813f712f726c93..00000000000000 Binary files a/lib/rdoc/generator/template/darkfish/images/page_white_text.png and /dev/null differ diff --git a/lib/rdoc/generator/template/darkfish/images/page_white_width.png b/lib/rdoc/generator/template/darkfish/images/page_white_width.png deleted file mode 100644 index 1eb880947ddf3e..00000000000000 Binary files a/lib/rdoc/generator/template/darkfish/images/page_white_width.png and /dev/null differ diff --git a/lib/rdoc/generator/template/darkfish/images/plugin.png b/lib/rdoc/generator/template/darkfish/images/plugin.png deleted file mode 100644 index 6187b15aec001b..00000000000000 Binary files a/lib/rdoc/generator/template/darkfish/images/plugin.png and /dev/null differ diff --git a/lib/rdoc/generator/template/darkfish/images/ruby.png b/lib/rdoc/generator/template/darkfish/images/ruby.png deleted file mode 100644 index f763a168807514..00000000000000 Binary files a/lib/rdoc/generator/template/darkfish/images/ruby.png and /dev/null differ diff --git a/lib/rdoc/generator/template/darkfish/images/tag_blue.png b/lib/rdoc/generator/template/darkfish/images/tag_blue.png deleted file mode 100644 index 3f02b5f8f8bf7c..00000000000000 Binary files a/lib/rdoc/generator/template/darkfish/images/tag_blue.png and /dev/null differ diff --git a/lib/rdoc/generator/template/darkfish/images/tag_green.png b/lib/rdoc/generator/template/darkfish/images/tag_green.png deleted file mode 100644 index 83ec984bd73364..00000000000000 Binary files a/lib/rdoc/generator/template/darkfish/images/tag_green.png and /dev/null differ diff --git a/lib/rdoc/generator/template/darkfish/images/transparent.png b/lib/rdoc/generator/template/darkfish/images/transparent.png deleted file mode 100644 index d665e179efd797..00000000000000 Binary files a/lib/rdoc/generator/template/darkfish/images/transparent.png and /dev/null differ diff --git a/lib/rdoc/generator/template/darkfish/images/wrench.png b/lib/rdoc/generator/template/darkfish/images/wrench.png deleted file mode 100644 index 5c8213fef5ab96..00000000000000 Binary files a/lib/rdoc/generator/template/darkfish/images/wrench.png and /dev/null differ diff --git a/lib/rdoc/generator/template/darkfish/images/wrench_orange.png b/lib/rdoc/generator/template/darkfish/images/wrench_orange.png deleted file mode 100644 index 565a9330e0a156..00000000000000 Binary files a/lib/rdoc/generator/template/darkfish/images/wrench_orange.png and /dev/null differ diff --git a/lib/rdoc/generator/template/darkfish/images/zoom.png b/lib/rdoc/generator/template/darkfish/images/zoom.png deleted file mode 100644 index 908612e394525f..00000000000000 Binary files a/lib/rdoc/generator/template/darkfish/images/zoom.png and /dev/null differ diff --git a/lib/rdoc/generator/template/darkfish/index.rhtml b/lib/rdoc/generator/template/darkfish/index.rhtml deleted file mode 100644 index 423e225b683e8b..00000000000000 --- a/lib/rdoc/generator/template/darkfish/index.rhtml +++ /dev/null @@ -1,22 +0,0 @@ - - - -
-<%- if @options.main_page and - main_page = @files.find { |f| f.full_name == @options.main_page } then %> -<%= main_page.description %> -<%- else -%> -

This is the API documentation for <%= h @title %>. -<%- end -%> -

diff --git a/lib/rdoc/generator/template/darkfish/js/darkfish.js b/lib/rdoc/generator/template/darkfish/js/darkfish.js deleted file mode 100644 index 19a85c54e17701..00000000000000 --- a/lib/rdoc/generator/template/darkfish/js/darkfish.js +++ /dev/null @@ -1,97 +0,0 @@ -/** - * - * Darkfish Page Functions - * $Id: darkfish.js 53 2009-01-07 02:52:03Z deveiant $ - * - * Author: Michael Granger - * - */ - -/* Provide console simulation for firebug-less environments */ -/* -if (!("console" in window) || !("firebug" in console)) { - var names = ["log", "debug", "info", "warn", "error", "assert", "dir", "dirxml", - "group", "groupEnd", "time", "timeEnd", "count", "trace", "profile", "profileEnd"]; - - window.console = {}; - for (var i = 0; i < names.length; ++i) - window.console[names[i]] = function() {}; -}; -*/ - - -function showSource( e ) { - var target = e.target; - while (!target.classList.contains('method-detail')) { - target = target.parentNode; - } - if (typeof target !== "undefined" && target !== null) { - target = target.querySelector('.method-source-code'); - } - if (typeof target !== "undefined" && target !== null) { - target.classList.toggle('active-menu') - } -}; - -function hookSourceViews() { - document.querySelectorAll('.method-heading').forEach(function (codeObject) { - codeObject.addEventListener('click', showSource); - }); -}; - -function hookSearch() { - var input = document.querySelector('#search-field'); - var result = document.querySelector('#search-results'); - result.classList.remove("initially-hidden"); - - var search_section = document.querySelector('#search-section'); - search_section.classList.remove("initially-hidden"); - - var search = new Search(search_data, input, result); - - search.renderItem = function(result) { - var li = document.createElement('li'); - var html = ''; - - // TODO add relative path to ',cgi.script) - assert_equal('',cgi.script('bar')) - assert_equal('',cgi.script{'foo'}) - assert_equal('',cgi.script('bar'){'foo'}) - assert_equal('

',cgi.h1) - assert_equal('

',cgi.h1('bar')) - assert_equal('

foo

',cgi.h1{'foo'}) - assert_equal('

foo

',cgi.h1('bar'){'foo'}) - assert_equal('

',cgi.h2) - assert_equal('

',cgi.h2('bar')) - assert_equal('

foo

',cgi.h2{'foo'}) - assert_equal('

foo

',cgi.h2('bar'){'foo'}) - assert_equal('

',cgi.h3) - assert_equal('

',cgi.h3('bar')) - assert_equal('

foo

',cgi.h3{'foo'}) - assert_equal('

foo

',cgi.h3('bar'){'foo'}) - assert_equal('

',cgi.h4) - assert_equal('

',cgi.h4('bar')) - assert_equal('

foo

',cgi.h4{'foo'}) - assert_equal('

foo

',cgi.h4('bar'){'foo'}) - assert_equal('
',cgi.h5) - assert_equal('
',cgi.h5('bar')) - assert_equal('
foo
',cgi.h5{'foo'}) - assert_equal('
foo
',cgi.h5('bar'){'foo'}) - assert_equal('
',cgi.h6) - assert_equal('
',cgi.h6('bar')) - assert_equal('
foo
',cgi.h6{'foo'}) - assert_equal('
foo
',cgi.h6('bar'){'foo'}) - assert_match(/^
Capital Cities